723 lines
20 KiB
C
723 lines
20 KiB
C
/*
|
|
* Process Hacker Extended Tools -
|
|
* GPU system information section
|
|
*
|
|
* Copyright (C) 2011 wj32
|
|
*
|
|
* This file is part of Process Hacker.
|
|
*
|
|
* Process Hacker is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Process Hacker is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "exttools.h"
|
|
#include "gpusys.h"
|
|
|
|
static PPH_SYSINFO_SECTION GpuSection;
|
|
static HWND GpuDialog;
|
|
static PH_LAYOUT_MANAGER GpuLayoutManager;
|
|
static RECT GpuGraphMargin;
|
|
static HWND GpuGraphHandle;
|
|
static PH_GRAPH_STATE GpuGraphState;
|
|
static HWND DedicatedGraphHandle;
|
|
static PH_GRAPH_STATE DedicatedGraphState;
|
|
static HWND SharedGraphHandle;
|
|
static PH_GRAPH_STATE SharedGraphState;
|
|
static HWND GpuPanel;
|
|
|
|
VOID EtGpuSystemInformationInitializing(
|
|
_In_ PPH_PLUGIN_SYSINFO_POINTERS Pointers
|
|
)
|
|
{
|
|
PH_SYSINFO_SECTION section;
|
|
|
|
memset(§ion, 0, sizeof(PH_SYSINFO_SECTION));
|
|
PhInitializeStringRef(§ion.Name, L"GPU");
|
|
section.Flags = 0;
|
|
section.Callback = EtpGpuSysInfoSectionCallback;
|
|
|
|
GpuSection = Pointers->CreateSection(§ion);
|
|
}
|
|
|
|
BOOLEAN EtpGpuSysInfoSectionCallback(
|
|
_In_ PPH_SYSINFO_SECTION Section,
|
|
_In_ PH_SYSINFO_SECTION_MESSAGE Message,
|
|
_In_opt_ PVOID Parameter1,
|
|
_In_opt_ PVOID Parameter2
|
|
)
|
|
{
|
|
switch (Message)
|
|
{
|
|
case SysInfoDestroy:
|
|
{
|
|
if (GpuDialog)
|
|
{
|
|
EtpUninitializeGpuDialog();
|
|
GpuDialog = NULL;
|
|
}
|
|
}
|
|
return TRUE;
|
|
case SysInfoTick:
|
|
{
|
|
if (GpuDialog)
|
|
{
|
|
EtpTickGpuDialog();
|
|
}
|
|
}
|
|
return TRUE;
|
|
case SysInfoCreateDialog:
|
|
{
|
|
PPH_SYSINFO_CREATE_DIALOG createDialog = Parameter1;
|
|
|
|
createDialog->Instance = PluginInstance->DllBase;
|
|
createDialog->Template = MAKEINTRESOURCE(IDD_SYSINFO_GPU);
|
|
createDialog->DialogProc = EtpGpuDialogProc;
|
|
}
|
|
return TRUE;
|
|
case SysInfoGraphGetDrawInfo:
|
|
{
|
|
PPH_GRAPH_DRAW_INFO drawInfo = Parameter1;
|
|
|
|
drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y;
|
|
Section->Parameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorCpuKernel"), 0);
|
|
PhGetDrawInfoGraphBuffers(&Section->GraphState.Buffers, drawInfo, EtGpuNodeHistory.Count);
|
|
|
|
if (!Section->GraphState.Valid)
|
|
{
|
|
PhCopyCircularBuffer_FLOAT(&EtGpuNodeHistory, Section->GraphState.Data1, drawInfo->LineDataCount);
|
|
Section->GraphState.Valid = TRUE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
case SysInfoGraphGetTooltipText:
|
|
{
|
|
PPH_SYSINFO_GRAPH_GET_TOOLTIP_TEXT getTooltipText = Parameter1;
|
|
FLOAT gpu;
|
|
|
|
gpu = PhGetItemCircularBuffer_FLOAT(&EtGpuNodeHistory, getTooltipText->Index);
|
|
|
|
PhMoveReference(&Section->GraphState.TooltipText, PhFormatString(
|
|
L"%.2f%%%s\n%s",
|
|
gpu * 100,
|
|
PhGetStringOrEmpty(EtpGetMaxNodeString(getTooltipText->Index)),
|
|
((PPH_STRING)PH_AUTO(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer
|
|
));
|
|
getTooltipText->Text = Section->GraphState.TooltipText->sr;
|
|
}
|
|
return TRUE;
|
|
case SysInfoGraphDrawPanel:
|
|
{
|
|
PPH_SYSINFO_DRAW_PANEL drawPanel = Parameter1;
|
|
|
|
drawPanel->Title = PhCreateString(L"GPU");
|
|
drawPanel->SubTitle = PhFormatString(L"%.2f%%", EtGpuNodeUsage * 100);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
VOID EtpInitializeGpuDialog(
|
|
VOID
|
|
)
|
|
{
|
|
PhInitializeGraphState(&GpuGraphState);
|
|
PhInitializeGraphState(&DedicatedGraphState);
|
|
PhInitializeGraphState(&SharedGraphState);
|
|
}
|
|
|
|
VOID EtpUninitializeGpuDialog(
|
|
VOID
|
|
)
|
|
{
|
|
PhDeleteGraphState(&GpuGraphState);
|
|
PhDeleteGraphState(&DedicatedGraphState);
|
|
PhDeleteGraphState(&SharedGraphState);
|
|
}
|
|
|
|
VOID EtpTickGpuDialog(
|
|
VOID
|
|
)
|
|
{
|
|
EtpUpdateGpuGraphs();
|
|
EtpUpdateGpuPanel();
|
|
}
|
|
|
|
INT_PTR CALLBACK EtpGpuDialogProc(
|
|
_In_ HWND hwndDlg,
|
|
_In_ UINT uMsg,
|
|
_In_ WPARAM wParam,
|
|
_In_ LPARAM lParam
|
|
)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
PPH_LAYOUT_ITEM graphItem;
|
|
PPH_LAYOUT_ITEM panelItem;
|
|
|
|
EtpInitializeGpuDialog();
|
|
|
|
GpuDialog = hwndDlg;
|
|
PhInitializeLayoutManager(&GpuLayoutManager, hwndDlg);
|
|
PhAddLayoutItem(&GpuLayoutManager, GetDlgItem(hwndDlg, IDC_GPUNAME), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_TOP | PH_ANCHOR_RIGHT | PH_LAYOUT_FORCE_INVALIDATE);
|
|
graphItem = PhAddLayoutItem(&GpuLayoutManager, GetDlgItem(hwndDlg, IDC_GRAPH_LAYOUT), NULL, PH_ANCHOR_ALL);
|
|
GpuGraphMargin = graphItem->Margin;
|
|
panelItem = PhAddLayoutItem(&GpuLayoutManager, GetDlgItem(hwndDlg, IDC_PANEL_LAYOUT), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM);
|
|
|
|
SendMessage(GetDlgItem(hwndDlg, IDC_TITLE), WM_SETFONT, (WPARAM)GpuSection->Parameters->LargeFont, FALSE);
|
|
SendMessage(GetDlgItem(hwndDlg, IDC_GPUNAME), WM_SETFONT, (WPARAM)GpuSection->Parameters->MediumFont, FALSE);
|
|
|
|
SetDlgItemText(hwndDlg, IDC_GPUNAME, ((PPH_STRING)PH_AUTO(EtpGetGpuNameString()))->Buffer);
|
|
|
|
GpuPanel = CreateDialog(PluginInstance->DllBase, MAKEINTRESOURCE(IDD_SYSINFO_GPUPANEL), hwndDlg, EtpGpuPanelDialogProc);
|
|
ShowWindow(GpuPanel, SW_SHOW);
|
|
PhAddLayoutItemEx(&GpuLayoutManager, GpuPanel, NULL, PH_ANCHOR_LEFT | PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM, panelItem->Margin);
|
|
|
|
EtpCreateGpuGraphs();
|
|
EtpUpdateGpuGraphs();
|
|
EtpUpdateGpuPanel();
|
|
}
|
|
break;
|
|
case WM_DESTROY:
|
|
{
|
|
PhDeleteLayoutManager(&GpuLayoutManager);
|
|
}
|
|
break;
|
|
case WM_SIZE:
|
|
{
|
|
PhLayoutManagerLayout(&GpuLayoutManager);
|
|
EtpLayoutGpuGraphs();
|
|
}
|
|
break;
|
|
case WM_NOTIFY:
|
|
{
|
|
NMHDR *header = (NMHDR *)lParam;
|
|
|
|
if (header->hwndFrom == GpuGraphHandle)
|
|
{
|
|
EtpNotifyGpuGraph(header);
|
|
}
|
|
else if (header->hwndFrom == DedicatedGraphHandle)
|
|
{
|
|
EtpNotifyDedicatedGraph(header);
|
|
}
|
|
else if (header->hwndFrom == SharedGraphHandle)
|
|
{
|
|
EtpNotifySharedGraph(header);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
INT_PTR CALLBACK EtpGpuPanelDialogProc(
|
|
_In_ HWND hwndDlg,
|
|
_In_ UINT uMsg,
|
|
_In_ WPARAM wParam,
|
|
_In_ LPARAM lParam
|
|
)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_COMMAND:
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDC_NODES:
|
|
EtShowGpuNodesDialog(GpuDialog, GpuSection->Parameters);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
VOID EtpCreateGpuGraphs(
|
|
VOID
|
|
)
|
|
{
|
|
GpuGraphHandle = CreateWindow(
|
|
PH_GRAPH_CLASSNAME,
|
|
NULL,
|
|
WS_VISIBLE | WS_CHILD | WS_BORDER,
|
|
0,
|
|
0,
|
|
3,
|
|
3,
|
|
GpuDialog,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
Graph_SetTooltip(GpuGraphHandle, TRUE);
|
|
|
|
DedicatedGraphHandle = CreateWindow(
|
|
PH_GRAPH_CLASSNAME,
|
|
NULL,
|
|
WS_VISIBLE | WS_CHILD | WS_BORDER,
|
|
0,
|
|
0,
|
|
3,
|
|
3,
|
|
GpuDialog,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
Graph_SetTooltip(DedicatedGraphHandle, TRUE);
|
|
|
|
SharedGraphHandle = CreateWindow(
|
|
PH_GRAPH_CLASSNAME,
|
|
NULL,
|
|
WS_VISIBLE | WS_CHILD | WS_BORDER,
|
|
0,
|
|
0,
|
|
3,
|
|
3,
|
|
GpuDialog,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
Graph_SetTooltip(SharedGraphHandle, TRUE);
|
|
}
|
|
|
|
VOID EtpLayoutGpuGraphs(
|
|
VOID
|
|
)
|
|
{
|
|
RECT clientRect;
|
|
RECT labelRect;
|
|
ULONG graphWidth;
|
|
ULONG graphHeight;
|
|
HDWP deferHandle;
|
|
ULONG y;
|
|
|
|
GetClientRect(GpuDialog, &clientRect);
|
|
GetClientRect(GetDlgItem(GpuDialog, IDC_GPU_L), &labelRect);
|
|
graphWidth = clientRect.right - GpuGraphMargin.left - GpuGraphMargin.right;
|
|
graphHeight = (clientRect.bottom - GpuGraphMargin.top - GpuGraphMargin.bottom - labelRect.bottom * 3 - ET_GPU_PADDING * 5) / 3;
|
|
|
|
deferHandle = BeginDeferWindowPos(6);
|
|
y = GpuGraphMargin.top;
|
|
|
|
deferHandle = DeferWindowPos(
|
|
deferHandle,
|
|
GetDlgItem(GpuDialog, IDC_GPU_L),
|
|
NULL,
|
|
GpuGraphMargin.left,
|
|
y,
|
|
0,
|
|
0,
|
|
SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER
|
|
);
|
|
y += labelRect.bottom + ET_GPU_PADDING;
|
|
|
|
deferHandle = DeferWindowPos(
|
|
deferHandle,
|
|
GpuGraphHandle,
|
|
NULL,
|
|
GpuGraphMargin.left,
|
|
y,
|
|
graphWidth,
|
|
graphHeight,
|
|
SWP_NOACTIVATE | SWP_NOZORDER
|
|
);
|
|
y += graphHeight + ET_GPU_PADDING;
|
|
|
|
deferHandle = DeferWindowPos(
|
|
deferHandle,
|
|
GetDlgItem(GpuDialog, IDC_DEDICATED_L),
|
|
NULL,
|
|
GpuGraphMargin.left,
|
|
y,
|
|
0,
|
|
0,
|
|
SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER
|
|
);
|
|
y += labelRect.bottom + ET_GPU_PADDING;
|
|
|
|
deferHandle = DeferWindowPos(
|
|
deferHandle,
|
|
DedicatedGraphHandle,
|
|
NULL,
|
|
GpuGraphMargin.left,
|
|
y,
|
|
graphWidth,
|
|
graphHeight,
|
|
SWP_NOACTIVATE | SWP_NOZORDER
|
|
);
|
|
y += graphHeight + ET_GPU_PADDING;
|
|
|
|
deferHandle = DeferWindowPos(
|
|
deferHandle,
|
|
GetDlgItem(GpuDialog, IDC_SHARED_L),
|
|
NULL,
|
|
GpuGraphMargin.left,
|
|
y,
|
|
0,
|
|
0,
|
|
SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER
|
|
);
|
|
y += labelRect.bottom + ET_GPU_PADDING;
|
|
|
|
deferHandle = DeferWindowPos(
|
|
deferHandle,
|
|
SharedGraphHandle,
|
|
NULL,
|
|
GpuGraphMargin.left,
|
|
y,
|
|
graphWidth,
|
|
clientRect.bottom - GpuGraphMargin.bottom - y,
|
|
SWP_NOACTIVATE | SWP_NOZORDER
|
|
);
|
|
|
|
EndDeferWindowPos(deferHandle);
|
|
}
|
|
|
|
VOID EtpNotifyGpuGraph(
|
|
_In_ NMHDR *Header
|
|
)
|
|
{
|
|
switch (Header->code)
|
|
{
|
|
case GCN_GETDRAWINFO:
|
|
{
|
|
PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)Header;
|
|
PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo;
|
|
|
|
drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y;
|
|
GpuSection->Parameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorCpuKernel"), 0);
|
|
|
|
PhGraphStateGetDrawInfo(
|
|
&GpuGraphState,
|
|
getDrawInfo,
|
|
EtGpuNodeHistory.Count
|
|
);
|
|
|
|
if (!GpuGraphState.Valid)
|
|
{
|
|
PhCopyCircularBuffer_FLOAT(&EtGpuNodeHistory, GpuGraphState.Data1, drawInfo->LineDataCount);
|
|
GpuGraphState.Valid = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
case GCN_GETTOOLTIPTEXT:
|
|
{
|
|
PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)Header;
|
|
|
|
if (getTooltipText->Index < getTooltipText->TotalCount)
|
|
{
|
|
if (GpuGraphState.TooltipIndex != getTooltipText->Index)
|
|
{
|
|
FLOAT gpu;
|
|
|
|
gpu = PhGetItemCircularBuffer_FLOAT(&EtGpuNodeHistory, getTooltipText->Index);
|
|
|
|
PhMoveReference(&GpuGraphState.TooltipText, PhFormatString(
|
|
L"%.2f%%%s\n%s",
|
|
gpu * 100,
|
|
PhGetStringOrEmpty(EtpGetMaxNodeString(getTooltipText->Index)),
|
|
((PPH_STRING)PH_AUTO(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer
|
|
));
|
|
}
|
|
|
|
getTooltipText->Text = GpuGraphState.TooltipText->sr;
|
|
}
|
|
}
|
|
break;
|
|
case GCN_MOUSEEVENT:
|
|
{
|
|
PPH_GRAPH_MOUSEEVENT mouseEvent = (PPH_GRAPH_MOUSEEVENT)Header;
|
|
PPH_PROCESS_RECORD record;
|
|
|
|
record = NULL;
|
|
|
|
if (mouseEvent->Message == WM_LBUTTONDBLCLK && mouseEvent->Index < mouseEvent->TotalCount)
|
|
{
|
|
record = EtpReferenceMaxNodeRecord(mouseEvent->Index);
|
|
}
|
|
|
|
if (record)
|
|
{
|
|
PhShowProcessRecordDialog(GpuDialog, record);
|
|
PhDereferenceProcessRecord(record);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
VOID EtpNotifyDedicatedGraph(
|
|
_In_ NMHDR *Header
|
|
)
|
|
{
|
|
switch (Header->code)
|
|
{
|
|
case GCN_GETDRAWINFO:
|
|
{
|
|
PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)Header;
|
|
PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo;
|
|
ULONG i;
|
|
|
|
drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y;
|
|
GpuSection->Parameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorPrivate"), 0);
|
|
|
|
PhGraphStateGetDrawInfo(
|
|
&DedicatedGraphState,
|
|
getDrawInfo,
|
|
EtGpuDedicatedHistory.Count
|
|
);
|
|
|
|
if (!DedicatedGraphState.Valid)
|
|
{
|
|
for (i = 0; i < drawInfo->LineDataCount; i++)
|
|
{
|
|
DedicatedGraphState.Data1[i] =
|
|
(FLOAT)PhGetItemCircularBuffer_ULONG(&EtGpuDedicatedHistory, i);
|
|
}
|
|
|
|
if (EtGpuDedicatedLimit != 0)
|
|
{
|
|
// Scale the data.
|
|
PhDivideSinglesBySingle(
|
|
DedicatedGraphState.Data1,
|
|
(FLOAT)EtGpuDedicatedLimit / PAGE_SIZE,
|
|
drawInfo->LineDataCount
|
|
);
|
|
}
|
|
|
|
DedicatedGraphState.Valid = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
case GCN_GETTOOLTIPTEXT:
|
|
{
|
|
PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)Header;
|
|
|
|
if (getTooltipText->Index < getTooltipText->TotalCount)
|
|
{
|
|
if (DedicatedGraphState.TooltipIndex != getTooltipText->Index)
|
|
{
|
|
ULONG usedPages;
|
|
|
|
usedPages = PhGetItemCircularBuffer_ULONG(&EtGpuDedicatedHistory, getTooltipText->Index);
|
|
|
|
PhMoveReference(&DedicatedGraphState.TooltipText, PhFormatString(
|
|
L"Dedicated Memory: %s\n%s",
|
|
PhaFormatSize(UInt32x32To64(usedPages, PAGE_SIZE), -1)->Buffer,
|
|
((PPH_STRING)PH_AUTO(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer
|
|
));
|
|
}
|
|
|
|
getTooltipText->Text = DedicatedGraphState.TooltipText->sr;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
VOID EtpNotifySharedGraph(
|
|
_In_ NMHDR *Header
|
|
)
|
|
{
|
|
switch (Header->code)
|
|
{
|
|
case GCN_GETDRAWINFO:
|
|
{
|
|
PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)Header;
|
|
PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo;
|
|
ULONG i;
|
|
|
|
drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y;
|
|
GpuSection->Parameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorPhysical"), 0);
|
|
|
|
PhGraphStateGetDrawInfo(
|
|
&SharedGraphState,
|
|
getDrawInfo,
|
|
EtGpuSharedHistory.Count
|
|
);
|
|
|
|
if (!SharedGraphState.Valid)
|
|
{
|
|
for (i = 0; i < drawInfo->LineDataCount; i++)
|
|
{
|
|
SharedGraphState.Data1[i] =
|
|
(FLOAT)PhGetItemCircularBuffer_ULONG(&EtGpuSharedHistory, i);
|
|
}
|
|
|
|
if (EtGpuSharedLimit != 0)
|
|
{
|
|
// Scale the data.
|
|
PhDivideSinglesBySingle(
|
|
SharedGraphState.Data1,
|
|
(FLOAT)EtGpuSharedLimit / PAGE_SIZE,
|
|
drawInfo->LineDataCount
|
|
);
|
|
}
|
|
|
|
SharedGraphState.Valid = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
case GCN_GETTOOLTIPTEXT:
|
|
{
|
|
PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)Header;
|
|
|
|
if (getTooltipText->Index < getTooltipText->TotalCount)
|
|
{
|
|
if (SharedGraphState.TooltipIndex != getTooltipText->Index)
|
|
{
|
|
ULONG usedPages;
|
|
|
|
usedPages = PhGetItemCircularBuffer_ULONG(&EtGpuSharedHistory, getTooltipText->Index);
|
|
|
|
PhMoveReference(&SharedGraphState.TooltipText, PhFormatString(
|
|
L"Shared Memory: %s\n%s",
|
|
PhaFormatSize(UInt32x32To64(usedPages, PAGE_SIZE), -1)->Buffer,
|
|
((PPH_STRING)PH_AUTO(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer
|
|
));
|
|
}
|
|
|
|
getTooltipText->Text = SharedGraphState.TooltipText->sr;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
VOID EtpUpdateGpuGraphs(
|
|
VOID
|
|
)
|
|
{
|
|
GpuGraphState.Valid = FALSE;
|
|
GpuGraphState.TooltipIndex = -1;
|
|
Graph_MoveGrid(GpuGraphHandle, 1);
|
|
Graph_Draw(GpuGraphHandle);
|
|
Graph_UpdateTooltip(GpuGraphHandle);
|
|
InvalidateRect(GpuGraphHandle, NULL, FALSE);
|
|
|
|
DedicatedGraphState.Valid = FALSE;
|
|
DedicatedGraphState.TooltipIndex = -1;
|
|
Graph_MoveGrid(DedicatedGraphHandle, 1);
|
|
Graph_Draw(DedicatedGraphHandle);
|
|
Graph_UpdateTooltip(DedicatedGraphHandle);
|
|
InvalidateRect(DedicatedGraphHandle, NULL, FALSE);
|
|
|
|
SharedGraphState.Valid = FALSE;
|
|
SharedGraphState.TooltipIndex = -1;
|
|
Graph_MoveGrid(SharedGraphHandle, 1);
|
|
Graph_Draw(SharedGraphHandle);
|
|
Graph_UpdateTooltip(SharedGraphHandle);
|
|
InvalidateRect(SharedGraphHandle, NULL, FALSE);
|
|
}
|
|
|
|
VOID EtpUpdateGpuPanel(
|
|
VOID
|
|
)
|
|
{
|
|
SetDlgItemText(GpuPanel, IDC_ZDEDICATEDCURRENT_V, PhaFormatSize(EtGpuDedicatedUsage, -1)->Buffer);
|
|
SetDlgItemText(GpuPanel, IDC_ZDEDICATEDLIMIT_V, PhaFormatSize(EtGpuDedicatedLimit, -1)->Buffer);
|
|
|
|
SetDlgItemText(GpuPanel, IDC_ZSHAREDCURRENT_V, PhaFormatSize(EtGpuSharedUsage, -1)->Buffer);
|
|
SetDlgItemText(GpuPanel, IDC_ZSHAREDLIMIT_V, PhaFormatSize(EtGpuSharedLimit, -1)->Buffer);
|
|
}
|
|
|
|
PPH_PROCESS_RECORD EtpReferenceMaxNodeRecord(
|
|
_In_ LONG Index
|
|
)
|
|
{
|
|
LARGE_INTEGER time;
|
|
ULONG maxProcessId;
|
|
|
|
maxProcessId = PhGetItemCircularBuffer_ULONG(&EtMaxGpuNodeHistory, Index);
|
|
|
|
if (!maxProcessId)
|
|
return NULL;
|
|
|
|
PhGetStatisticsTime(NULL, Index, &time);
|
|
time.QuadPart += PH_TICKS_PER_SEC - 1;
|
|
|
|
return PhFindProcessRecord(UlongToHandle(maxProcessId), &time);
|
|
}
|
|
|
|
PPH_STRING EtpGetMaxNodeString(
|
|
_In_ LONG Index
|
|
)
|
|
{
|
|
PPH_PROCESS_RECORD maxProcessRecord;
|
|
FLOAT maxGpuUsage;
|
|
PPH_STRING maxUsageString = NULL;
|
|
|
|
if (maxProcessRecord = EtpReferenceMaxNodeRecord(Index))
|
|
{
|
|
maxGpuUsage = PhGetItemCircularBuffer_FLOAT(&EtMaxGpuNodeUsageHistory, Index);
|
|
|
|
maxUsageString = PhaFormatString(
|
|
L"\n%s (%lu): %.2f%%",
|
|
maxProcessRecord->ProcessName->Buffer,
|
|
HandleToUlong(maxProcessRecord->ProcessId),
|
|
maxGpuUsage * 100
|
|
);
|
|
|
|
PhDereferenceProcessRecord(maxProcessRecord);
|
|
}
|
|
|
|
return maxUsageString;
|
|
}
|
|
|
|
PPH_STRING EtpGetGpuNameString(
|
|
VOID
|
|
)
|
|
{
|
|
ULONG i;
|
|
ULONG count;
|
|
PH_STRING_BUILDER sb;
|
|
|
|
count = EtGetGpuAdapterCount();
|
|
PhInitializeStringBuilder(&sb, 100);
|
|
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
PPH_STRING description;
|
|
|
|
description = EtGetGpuAdapterDescription(i);
|
|
|
|
if (!PhIsNullOrEmptyString(description))
|
|
{
|
|
// Ignore "Microsoft Basic Render Driver" unless we don't have any other adapters.
|
|
// This does not take into account localization.
|
|
if (count == 1 || !PhEqualString2(description, L"Microsoft Basic Render Driver", TRUE))
|
|
{
|
|
PhAppendStringBuilder(&sb, &description->sr);
|
|
PhAppendStringBuilder2(&sb, L", ");
|
|
}
|
|
}
|
|
|
|
if (description)
|
|
PhDereferenceObject(description);
|
|
}
|
|
|
|
if (sb.String->Length != 0)
|
|
PhRemoveEndStringBuilder(&sb, 2);
|
|
|
|
return PhFinalStringBuilderString(&sb);
|
|
}
|