767 lines
26 KiB
C
767 lines
26 KiB
C
/*
|
|
* Process Hacker Extended Tools -
|
|
* GPU process properties page
|
|
*
|
|
* Copyright (C) 2011 wj32
|
|
* Copyright (C) 2015-2016 dmex
|
|
*
|
|
* 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"
|
|
|
|
typedef struct _ET_GPU_CONTEXT
|
|
{
|
|
HWND WindowHandle;
|
|
HWND PanelHandle;
|
|
HWND DetailsHandle;
|
|
PET_PROCESS_BLOCK Block;
|
|
PH_CALLBACK_REGISTRATION ProcessesUpdatedRegistration;
|
|
BOOLEAN Enabled;
|
|
PH_LAYOUT_MANAGER LayoutManager;
|
|
|
|
HWND GpuGroupBox;
|
|
HWND MemGroupBox;
|
|
HWND SharedGroupBox;
|
|
|
|
HWND GpuGraphHandle;
|
|
HWND MemGraphHandle;
|
|
HWND SharedGraphHandle;
|
|
|
|
FLOAT CurrentGpuUsage;
|
|
ULONG CurrentMemUsage;
|
|
ULONG CurrentMemSharedUsage;
|
|
|
|
PH_GRAPH_STATE GpuGraphState;
|
|
PH_GRAPH_STATE MemoryGraphState;
|
|
PH_GRAPH_STATE MemorySharedGraphState;
|
|
|
|
PH_CIRCULAR_BUFFER_FLOAT GpuHistory;
|
|
PH_CIRCULAR_BUFFER_ULONG MemoryHistory;
|
|
PH_CIRCULAR_BUFFER_ULONG MemorySharedHistory;
|
|
} ET_GPU_CONTEXT, *PET_GPU_CONTEXT;
|
|
|
|
static RECT NormalGraphTextMargin = { 5, 5, 5, 5 };
|
|
static RECT NormalGraphTextPadding = { 3, 3, 3, 3 };
|
|
|
|
VOID GpuPropUpdatePanel(
|
|
_Inout_ PET_GPU_CONTEXT Context
|
|
);
|
|
|
|
INT_PTR CALLBACK GpuDetailsDialogProc(
|
|
_In_ HWND hwndDlg,
|
|
_In_ UINT uMsg,
|
|
_In_ WPARAM wParam,
|
|
_In_ LPARAM lParam
|
|
)
|
|
{
|
|
PET_GPU_CONTEXT context = NULL;
|
|
|
|
if (uMsg == WM_INITDIALOG)
|
|
{
|
|
context = (PET_GPU_CONTEXT)lParam;
|
|
SetProp(hwndDlg, L"Context", (HANDLE)context);
|
|
}
|
|
else
|
|
{
|
|
context = (PET_GPU_CONTEXT)GetProp(hwndDlg, L"Context");
|
|
|
|
if (uMsg == WM_DESTROY)
|
|
{
|
|
context->DetailsHandle = NULL;
|
|
RemoveProp(hwndDlg, L"Context");
|
|
}
|
|
}
|
|
|
|
if (context == NULL)
|
|
return FALSE;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
context->DetailsHandle = hwndDlg;
|
|
PhCenterWindow(hwndDlg, GetParent(hwndDlg));
|
|
|
|
GpuPropUpdatePanel(context);
|
|
}
|
|
break;
|
|
case WM_COMMAND:
|
|
{
|
|
switch (GET_WM_COMMAND_ID(wParam, lparam))
|
|
{
|
|
case IDCANCEL:
|
|
EndDialog(hwndDlg, IDCANCEL);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
INT_PTR CALLBACK GpuPanelDialogProc(
|
|
_In_ HWND hwndDlg,
|
|
_In_ UINT uMsg,
|
|
_In_ WPARAM wParam,
|
|
_In_ LPARAM lParam
|
|
)
|
|
{
|
|
PET_GPU_CONTEXT context = NULL;
|
|
|
|
if (uMsg == WM_INITDIALOG)
|
|
{
|
|
context = (PET_GPU_CONTEXT)lParam;
|
|
SetProp(hwndDlg, L"Context", (HANDLE)context);
|
|
}
|
|
else
|
|
{
|
|
context = (PET_GPU_CONTEXT)GetProp(hwndDlg, L"Context");
|
|
|
|
if (uMsg == WM_DESTROY)
|
|
{
|
|
RemoveProp(hwndDlg, L"Context");
|
|
}
|
|
}
|
|
|
|
if (context == NULL)
|
|
return FALSE;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_COMMAND:
|
|
{
|
|
switch (GET_WM_COMMAND_ID(wParam, lparam))
|
|
{
|
|
case IDC_GPUDETAILS:
|
|
{
|
|
DialogBoxParam(
|
|
PluginInstance->DllBase,
|
|
MAKEINTRESOURCE(IDD_PROCGPU_DETAILS),
|
|
hwndDlg,
|
|
GpuDetailsDialogProc,
|
|
(LPARAM)context
|
|
);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
VOID GpuPropCreateGraphs(
|
|
_In_ PET_GPU_CONTEXT Context
|
|
)
|
|
{
|
|
Context->GpuGraphHandle = CreateWindow(
|
|
PH_GRAPH_CLASSNAME,
|
|
NULL,
|
|
WS_VISIBLE | WS_CHILD | WS_BORDER,
|
|
0,
|
|
0,
|
|
3,
|
|
3,
|
|
Context->WindowHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
Graph_SetTooltip(Context->GpuGraphHandle, TRUE);
|
|
|
|
Context->MemGraphHandle = CreateWindow(
|
|
PH_GRAPH_CLASSNAME,
|
|
NULL,
|
|
WS_VISIBLE | WS_CHILD | WS_BORDER,
|
|
0,
|
|
0,
|
|
3,
|
|
3,
|
|
Context->WindowHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
Graph_SetTooltip(Context->MemGraphHandle, TRUE);
|
|
|
|
Context->SharedGraphHandle = CreateWindow(
|
|
PH_GRAPH_CLASSNAME,
|
|
NULL,
|
|
WS_VISIBLE | WS_CHILD | WS_BORDER,
|
|
0,
|
|
0,
|
|
3,
|
|
3,
|
|
Context->WindowHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
Graph_SetTooltip(Context->SharedGraphHandle, TRUE);
|
|
}
|
|
|
|
VOID GpuPropCreatePanel(
|
|
_In_ PET_GPU_CONTEXT Context
|
|
)
|
|
{
|
|
RECT margin;
|
|
|
|
Context->PanelHandle = CreateDialogParam(
|
|
PluginInstance->DllBase,
|
|
MAKEINTRESOURCE(IDD_PROCGPU_PANEL),
|
|
Context->WindowHandle,
|
|
GpuPanelDialogProc,
|
|
(LPARAM)Context
|
|
);
|
|
|
|
SetWindowPos(
|
|
Context->PanelHandle,
|
|
NULL,
|
|
10, 0, 0, 0,
|
|
SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOSIZE | SWP_NOZORDER
|
|
);
|
|
|
|
ShowWindow(Context->PanelHandle, SW_SHOW);
|
|
|
|
margin.left = 0;
|
|
margin.top = 0;
|
|
margin.right = 0;
|
|
margin.bottom = 10;
|
|
MapDialogRect(Context->WindowHandle, &margin);
|
|
|
|
PhAddLayoutItemEx(
|
|
&Context->LayoutManager,
|
|
Context->PanelHandle,
|
|
NULL,
|
|
PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT,
|
|
margin
|
|
);
|
|
|
|
SendMessage(Context->WindowHandle, WM_SIZE, 0, 0);
|
|
}
|
|
|
|
VOID GpuPropLayoutGraphs(
|
|
_In_ PET_GPU_CONTEXT Context
|
|
)
|
|
{
|
|
HDWP deferHandle;
|
|
RECT clientRect;
|
|
RECT panelRect;
|
|
RECT margin = { ET_SCALE_DPI(13), ET_SCALE_DPI(13), ET_SCALE_DPI(13), ET_SCALE_DPI(13) };
|
|
RECT innerMargin = { ET_SCALE_DPI(10), ET_SCALE_DPI(20), ET_SCALE_DPI(10), ET_SCALE_DPI(10) };
|
|
LONG between = ET_SCALE_DPI(3);
|
|
ULONG graphWidth;
|
|
ULONG graphHeight;
|
|
|
|
PhLayoutManagerLayout(&Context->LayoutManager);
|
|
|
|
Context->GpuGraphState.Valid = FALSE;
|
|
Context->MemoryGraphState.Valid = FALSE;
|
|
Context->MemorySharedGraphState.Valid = FALSE;
|
|
|
|
GetClientRect(Context->WindowHandle, &clientRect);
|
|
|
|
// Limit the rectangle bottom to the top of the panel.
|
|
GetWindowRect(Context->PanelHandle, &panelRect);
|
|
MapWindowPoints(NULL, Context->WindowHandle, (PPOINT)&panelRect, 2);
|
|
clientRect.bottom = panelRect.top + 10; // +10 removing extra spacing
|
|
|
|
graphWidth = clientRect.right - margin.left - margin.right;
|
|
graphHeight = (clientRect.bottom - margin.top - margin.bottom - between * 2) / 3;
|
|
|
|
deferHandle = BeginDeferWindowPos(6);
|
|
|
|
deferHandle = DeferWindowPos(deferHandle, Context->GpuGroupBox, NULL, margin.left, margin.top, graphWidth, graphHeight, SWP_NOACTIVATE | SWP_NOZORDER);
|
|
deferHandle = DeferWindowPos(
|
|
deferHandle,
|
|
Context->GpuGraphHandle,
|
|
NULL,
|
|
margin.left + innerMargin.left,
|
|
margin.top + innerMargin.top,
|
|
graphWidth - innerMargin.left - innerMargin.right,
|
|
graphHeight - innerMargin.top - innerMargin.bottom,
|
|
SWP_NOACTIVATE | SWP_NOZORDER
|
|
);
|
|
|
|
deferHandle = DeferWindowPos(deferHandle, Context->MemGroupBox, NULL, margin.left, margin.top + graphHeight + between, graphWidth, graphHeight, SWP_NOACTIVATE | SWP_NOZORDER);
|
|
deferHandle = DeferWindowPos(
|
|
deferHandle,
|
|
Context->MemGraphHandle,
|
|
NULL,
|
|
margin.left + innerMargin.left,
|
|
margin.top + graphHeight + between + innerMargin.top,
|
|
graphWidth - innerMargin.left - innerMargin.right,
|
|
graphHeight - innerMargin.top - innerMargin.bottom,
|
|
SWP_NOACTIVATE | SWP_NOZORDER
|
|
);
|
|
|
|
deferHandle = DeferWindowPos(deferHandle, Context->SharedGroupBox, NULL, margin.left, margin.top + (graphHeight + between) * 2, graphWidth, graphHeight, SWP_NOACTIVATE | SWP_NOZORDER);
|
|
deferHandle = DeferWindowPos(
|
|
deferHandle,
|
|
Context->SharedGraphHandle,
|
|
NULL,
|
|
margin.left + innerMargin.left,
|
|
margin.top + (graphHeight + between) * 2 + innerMargin.top,
|
|
graphWidth - innerMargin.left - innerMargin.right,
|
|
graphHeight - innerMargin.top - innerMargin.bottom,
|
|
SWP_NOACTIVATE | SWP_NOZORDER
|
|
);
|
|
|
|
EndDeferWindowPos(deferHandle);
|
|
}
|
|
|
|
VOID GpuPropUpdateGraphs(
|
|
_In_ PET_GPU_CONTEXT Context
|
|
)
|
|
{
|
|
Context->GpuGraphState.Valid = FALSE;
|
|
Context->GpuGraphState.TooltipIndex = -1;
|
|
Graph_MoveGrid(Context->GpuGraphHandle, 1);
|
|
Graph_Draw(Context->GpuGraphHandle);
|
|
Graph_UpdateTooltip(Context->GpuGraphHandle);
|
|
InvalidateRect(Context->GpuGraphHandle, NULL, FALSE);
|
|
|
|
Context->MemoryGraphState.Valid = FALSE;
|
|
Context->MemoryGraphState.TooltipIndex = -1;
|
|
Graph_MoveGrid(Context->MemGraphHandle, 1);
|
|
Graph_Draw(Context->MemGraphHandle);
|
|
Graph_UpdateTooltip(Context->MemGraphHandle);
|
|
InvalidateRect(Context->MemGraphHandle, NULL, FALSE);
|
|
|
|
Context->MemorySharedGraphState.Valid = FALSE;
|
|
Context->MemorySharedGraphState.TooltipIndex = -1;
|
|
Graph_MoveGrid(Context->SharedGraphHandle, 1);
|
|
Graph_Draw(Context->SharedGraphHandle);
|
|
Graph_UpdateTooltip(Context->SharedGraphHandle);
|
|
InvalidateRect(Context->SharedGraphHandle, NULL, FALSE);
|
|
}
|
|
|
|
VOID GpuPropUpdatePanel(
|
|
_Inout_ PET_GPU_CONTEXT Context
|
|
)
|
|
{
|
|
ET_PROCESS_GPU_STATISTICS statistics;
|
|
WCHAR runningTimeString[PH_TIMESPAN_STR_LEN_1] = L"N/A";
|
|
|
|
if (Context->Block->ProcessItem->QueryHandle)
|
|
EtQueryProcessGpuStatistics(Context->Block->ProcessItem->QueryHandle, &statistics);
|
|
else
|
|
memset(&statistics, 0, sizeof(ET_PROCESS_GPU_STATISTICS));
|
|
|
|
PhPrintTimeSpan(runningTimeString, statistics.RunningTime * 10, PH_TIMESPAN_HMSM);
|
|
|
|
SetDlgItemText(Context->PanelHandle, IDC_ZRUNNINGTIME_V, runningTimeString);
|
|
SetDlgItemText(Context->PanelHandle, IDC_ZCONTEXTSWITCHES_V, PhaFormatUInt64(statistics.ContextSwitches, TRUE)->Buffer);
|
|
SetDlgItemText(Context->PanelHandle, IDC_ZTOTALNODES_V, PhaFormatUInt64(statistics.NodeCount, TRUE)->Buffer);
|
|
SetDlgItemText(Context->PanelHandle, IDC_ZTOTALSEGMENTS_V, PhaFormatUInt64(statistics.SegmentCount, TRUE)->Buffer);
|
|
|
|
if (Context->DetailsHandle)
|
|
{
|
|
// Note: no lock is needed because we only ever update the 'details' dialog text on this same thread.
|
|
SetDlgItemText(Context->DetailsHandle, IDC_ZDEDICATEDCOMMITTED_V, PhaFormatSize(statistics.DedicatedCommitted, -1)->Buffer);
|
|
SetDlgItemText(Context->DetailsHandle, IDC_ZSHAREDCOMMITTED_V, PhaFormatSize(statistics.SharedCommitted, -1)->Buffer);
|
|
SetDlgItemText(Context->DetailsHandle, IDC_ZTOTALALLOCATED_V, PhaFormatSize(statistics.BytesAllocated, -1)->Buffer);
|
|
SetDlgItemText(Context->DetailsHandle, IDC_ZTOTALRESERVED_V, PhaFormatSize(statistics.BytesReserved, -1)->Buffer);
|
|
SetDlgItemText(Context->DetailsHandle, IDC_ZWRITECOMBINEDALLOCATED_V, PhaFormatSize(statistics.WriteCombinedBytesAllocated, -1)->Buffer);
|
|
SetDlgItemText(Context->DetailsHandle, IDC_ZWRITECOMBINEDRESERVED_V, PhaFormatSize(statistics.WriteCombinedBytesReserved, -1)->Buffer);
|
|
SetDlgItemText(Context->DetailsHandle, IDC_ZCACHEDALLOCATED_V, PhaFormatSize(statistics.CachedBytesAllocated, -1)->Buffer);
|
|
SetDlgItemText(Context->DetailsHandle, IDC_ZCACHEDRESERVED_V, PhaFormatSize(statistics.CachedBytesReserved, -1)->Buffer);
|
|
SetDlgItemText(Context->DetailsHandle, IDC_ZSECTIONALLOCATED_V, PhaFormatSize(statistics.SectionBytesAllocated, -1)->Buffer);
|
|
SetDlgItemText(Context->DetailsHandle, IDC_ZSECTIONRESERVED_V, PhaFormatSize(statistics.SectionBytesReserved, -1)->Buffer);
|
|
}
|
|
}
|
|
|
|
VOID GpuPropUpdateInfo(
|
|
_In_ PET_GPU_CONTEXT Context
|
|
)
|
|
{
|
|
PET_PROCESS_BLOCK block = Context->Block;
|
|
|
|
Context->CurrentGpuUsage = block->GpuNodeUsage;
|
|
Context->CurrentMemUsage = (ULONG)(block->GpuDedicatedUsage / PAGE_SIZE);
|
|
Context->CurrentMemSharedUsage = (ULONG)(block->GpuSharedUsage / PAGE_SIZE);
|
|
|
|
PhAddItemCircularBuffer_FLOAT(&Context->GpuHistory, Context->CurrentGpuUsage);
|
|
PhAddItemCircularBuffer_ULONG(&Context->MemoryHistory, Context->CurrentMemUsage);
|
|
PhAddItemCircularBuffer_ULONG(&Context->MemorySharedHistory, Context->CurrentMemSharedUsage);
|
|
}
|
|
|
|
VOID NTAPI ProcessesUpdatedHandler(
|
|
_In_opt_ PVOID Parameter,
|
|
_In_opt_ PVOID Context
|
|
)
|
|
{
|
|
PET_GPU_CONTEXT context = Context;
|
|
|
|
if (!context->Enabled)
|
|
return;
|
|
|
|
if (context->WindowHandle)
|
|
{
|
|
PostMessage(context->WindowHandle, UPDATE_MSG, 0, 0);
|
|
}
|
|
}
|
|
|
|
INT_PTR CALLBACK EtpGpuPageDlgProc(
|
|
_In_ HWND hwndDlg,
|
|
_In_ UINT uMsg,
|
|
_In_ WPARAM wParam,
|
|
_In_ LPARAM lParam
|
|
)
|
|
{
|
|
LPPROPSHEETPAGE propSheetPage;
|
|
PPH_PROCESS_PROPPAGECONTEXT propPageContext;
|
|
PPH_PROCESS_ITEM processItem;
|
|
PET_GPU_CONTEXT context;
|
|
|
|
if (PhPropPageDlgProcHeader(hwndDlg, uMsg, lParam, &propSheetPage, &propPageContext, &processItem))
|
|
{
|
|
context = propPageContext->Context;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
ULONG sampleCount;
|
|
|
|
sampleCount = PhGetIntegerSetting(L"SampleCount");
|
|
|
|
context = PhAllocate(sizeof(ET_GPU_CONTEXT));
|
|
memset(context, 0, sizeof(ET_GPU_CONTEXT));
|
|
|
|
context->WindowHandle = hwndDlg;
|
|
context->Block = EtGetProcessBlock(processItem);
|
|
context->Enabled = TRUE;
|
|
context->GpuGroupBox = GetDlgItem(hwndDlg, IDC_GROUPGPU);
|
|
context->MemGroupBox = GetDlgItem(hwndDlg, IDC_GROUPMEM);
|
|
context->SharedGroupBox = GetDlgItem(hwndDlg, IDC_GROUPSHARED);
|
|
propPageContext->Context = context;
|
|
|
|
PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
|
|
|
|
PhInitializeGraphState(&context->GpuGraphState);
|
|
PhInitializeGraphState(&context->MemoryGraphState);
|
|
PhInitializeGraphState(&context->MemorySharedGraphState);
|
|
|
|
PhInitializeCircularBuffer_FLOAT(&context->GpuHistory, sampleCount);
|
|
PhInitializeCircularBuffer_ULONG(&context->MemoryHistory, sampleCount);
|
|
PhInitializeCircularBuffer_ULONG(&context->MemorySharedHistory, sampleCount);
|
|
|
|
GpuPropCreateGraphs(context);
|
|
GpuPropCreatePanel(context);
|
|
GpuPropUpdateInfo(context);
|
|
GpuPropUpdatePanel(context);
|
|
|
|
PhRegisterCallback(
|
|
&PhProcessesUpdatedEvent,
|
|
ProcessesUpdatedHandler,
|
|
context,
|
|
&context->ProcessesUpdatedRegistration
|
|
);
|
|
}
|
|
break;
|
|
case WM_DESTROY:
|
|
{
|
|
PhDeleteLayoutManager(&context->LayoutManager);
|
|
|
|
PhDeleteGraphState(&context->GpuGraphState);
|
|
PhDeleteGraphState(&context->MemoryGraphState);
|
|
PhDeleteGraphState(&context->MemorySharedGraphState);
|
|
|
|
PhDeleteCircularBuffer_FLOAT(&context->GpuHistory);
|
|
PhDeleteCircularBuffer_ULONG(&context->MemoryHistory);
|
|
PhDeleteCircularBuffer_ULONG(&context->MemorySharedHistory);
|
|
|
|
if (context->GpuGraphHandle)
|
|
DestroyWindow(context->GpuGraphHandle);
|
|
if (context->MemGraphHandle)
|
|
DestroyWindow(context->MemGraphHandle);
|
|
if (context->SharedGraphHandle)
|
|
DestroyWindow(context->SharedGraphHandle);
|
|
if (context->PanelHandle)
|
|
DestroyWindow(context->PanelHandle);
|
|
|
|
PhUnregisterCallback(&PhProcessesUpdatedEvent, &context->ProcessesUpdatedRegistration);
|
|
PhFree(context);
|
|
|
|
PhPropPageDlgProcDestroy(hwndDlg);
|
|
}
|
|
break;
|
|
case WM_SHOWWINDOW:
|
|
{
|
|
if (PhBeginPropPageLayout(hwndDlg, propPageContext))
|
|
PhEndPropPageLayout(hwndDlg, propPageContext);
|
|
}
|
|
break;
|
|
case WM_NOTIFY:
|
|
{
|
|
LPNMHDR header = (LPNMHDR)lParam;
|
|
|
|
switch (header->code)
|
|
{
|
|
case PSN_SETACTIVE:
|
|
context->Enabled = TRUE;
|
|
break;
|
|
case PSN_KILLACTIVE:
|
|
context->Enabled = FALSE;
|
|
break;
|
|
case GCN_GETDRAWINFO:
|
|
{
|
|
PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)header;
|
|
PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo;
|
|
|
|
if (header->hwndFrom == context->GpuGraphHandle)
|
|
{
|
|
if (PhGetIntegerSetting(L"GraphShowText"))
|
|
{
|
|
HDC hdc;
|
|
|
|
PhMoveReference(&context->GpuGraphState.Text, PhFormatString(
|
|
L"%.2f%%",
|
|
context->CurrentGpuUsage * 100
|
|
));
|
|
|
|
hdc = Graph_GetBufferedContext(context->GpuGraphHandle);
|
|
SelectObject(hdc, PhApplicationFont);
|
|
PhSetGraphText(hdc, drawInfo, &context->GpuGraphState.Text->sr,
|
|
&NormalGraphTextMargin, &NormalGraphTextPadding, PH_ALIGN_TOP | PH_ALIGN_LEFT);
|
|
}
|
|
else
|
|
{
|
|
drawInfo->Text.Buffer = NULL;
|
|
}
|
|
|
|
drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y;
|
|
PhSiSetColorsGraphDrawInfo(drawInfo, PhGetIntegerSetting(L"ColorCpuKernel"), 0);
|
|
PhGraphStateGetDrawInfo(&context->GpuGraphState, getDrawInfo, context->GpuHistory.Count);
|
|
|
|
if (!context->GpuGraphState.Valid)
|
|
{
|
|
PhCopyCircularBuffer_FLOAT(&context->GpuHistory, context->GpuGraphState.Data1, drawInfo->LineDataCount);
|
|
context->GpuGraphState.Valid = TRUE;
|
|
}
|
|
}
|
|
else if (header->hwndFrom == context->MemGraphHandle)
|
|
{
|
|
if (PhGetIntegerSetting(L"GraphShowText"))
|
|
{
|
|
HDC hdc;
|
|
|
|
PhMoveReference(&context->MemoryGraphState.Text, PhFormatString(
|
|
L"%s",
|
|
PhaFormatSize(UInt32x32To64(context->CurrentMemUsage, PAGE_SIZE), -1)->Buffer
|
|
));
|
|
|
|
hdc = Graph_GetBufferedContext(context->MemGraphHandle);
|
|
SelectObject(hdc, PhApplicationFont);
|
|
PhSetGraphText(
|
|
hdc,
|
|
drawInfo,
|
|
&context->MemoryGraphState.Text->sr,
|
|
&NormalGraphTextMargin,
|
|
&NormalGraphTextPadding,
|
|
PH_ALIGN_TOP | PH_ALIGN_LEFT
|
|
);
|
|
}
|
|
else
|
|
{
|
|
drawInfo->Text.Buffer = NULL;
|
|
}
|
|
|
|
drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y;
|
|
PhSiSetColorsGraphDrawInfo(drawInfo, PhGetIntegerSetting(L"ColorPhysical"), 0);
|
|
PhGraphStateGetDrawInfo(
|
|
&context->MemoryGraphState,
|
|
getDrawInfo,
|
|
context->MemoryHistory.Count
|
|
);
|
|
|
|
if (!context->MemoryGraphState.Valid)
|
|
{
|
|
ULONG i = 0;
|
|
|
|
for (i = 0; i < drawInfo->LineDataCount; i++)
|
|
{
|
|
context->MemoryGraphState.Data1[i] = (FLOAT)PhGetItemCircularBuffer_ULONG(&context->MemoryHistory, i);
|
|
}
|
|
|
|
if (EtGpuDedicatedLimit != 0)
|
|
{
|
|
PhDivideSinglesBySingle(
|
|
context->MemoryGraphState.Data1,
|
|
(FLOAT)EtGpuDedicatedLimit / PAGE_SIZE,
|
|
drawInfo->LineDataCount
|
|
);
|
|
}
|
|
|
|
context->MemoryGraphState.Valid = TRUE;
|
|
}
|
|
}
|
|
else if (header->hwndFrom == context->SharedGraphHandle)
|
|
{
|
|
if (PhGetIntegerSetting(L"GraphShowText"))
|
|
{
|
|
HDC hdc;
|
|
|
|
PhMoveReference(&context->MemorySharedGraphState.Text, PhFormatString(
|
|
L"%s",
|
|
PhaFormatSize(UInt32x32To64(context->CurrentMemSharedUsage, PAGE_SIZE), -1)->Buffer
|
|
));
|
|
|
|
hdc = Graph_GetBufferedContext(context->SharedGraphHandle);
|
|
SelectObject(hdc, PhApplicationFont);
|
|
PhSetGraphText(hdc, drawInfo, &context->MemorySharedGraphState.Text->sr,
|
|
&NormalGraphTextMargin, &NormalGraphTextPadding, PH_ALIGN_TOP | PH_ALIGN_LEFT);
|
|
}
|
|
else
|
|
{
|
|
drawInfo->Text.Buffer = NULL;
|
|
}
|
|
|
|
drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y;
|
|
PhSiSetColorsGraphDrawInfo(drawInfo, PhGetIntegerSetting(L"ColorPrivate"), 0);
|
|
PhGraphStateGetDrawInfo(
|
|
&context->MemorySharedGraphState,
|
|
getDrawInfo,
|
|
context->MemorySharedHistory.Count
|
|
);
|
|
|
|
if (!context->MemorySharedGraphState.Valid)
|
|
{
|
|
ULONG i = 0;
|
|
|
|
for (i = 0; i < drawInfo->LineDataCount; i++)
|
|
{
|
|
context->MemorySharedGraphState.Data1[i] = (FLOAT)PhGetItemCircularBuffer_ULONG(&context->MemorySharedHistory, i);
|
|
}
|
|
|
|
if (EtGpuSharedLimit != 0)
|
|
{
|
|
PhDivideSinglesBySingle(
|
|
context->MemorySharedGraphState.Data1,
|
|
(FLOAT)EtGpuSharedLimit / PAGE_SIZE,
|
|
drawInfo->LineDataCount
|
|
);
|
|
}
|
|
|
|
context->MemorySharedGraphState.Valid = TRUE;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case GCN_GETTOOLTIPTEXT:
|
|
{
|
|
PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)lParam;
|
|
|
|
if (getTooltipText->Index < getTooltipText->TotalCount)
|
|
{
|
|
if (header->hwndFrom == context->GpuGraphHandle)
|
|
{
|
|
if (context->GpuGraphState.TooltipIndex != getTooltipText->Index)
|
|
{
|
|
FLOAT gpuUsage = PhGetItemCircularBuffer_FLOAT(
|
|
&context->GpuHistory,
|
|
getTooltipText->Index
|
|
);
|
|
|
|
PhMoveReference(&context->GpuGraphState.TooltipText, PhFormatString(
|
|
L"%.2f%%",
|
|
gpuUsage * 100
|
|
));
|
|
}
|
|
|
|
getTooltipText->Text = context->GpuGraphState.TooltipText->sr;
|
|
}
|
|
else if (header->hwndFrom == context->MemGraphHandle)
|
|
{
|
|
if (context->MemoryGraphState.TooltipIndex != getTooltipText->Index)
|
|
{
|
|
ULONG gpuMemory = PhGetItemCircularBuffer_ULONG(
|
|
&context->MemoryHistory,
|
|
getTooltipText->Index
|
|
);
|
|
|
|
PhMoveReference(&context->MemoryGraphState.TooltipText,
|
|
PhFormatSize(UInt32x32To64(gpuMemory, PAGE_SIZE), -1)
|
|
);
|
|
}
|
|
|
|
getTooltipText->Text = context->MemoryGraphState.TooltipText->sr;
|
|
}
|
|
else if (header->hwndFrom == context->SharedGraphHandle)
|
|
{
|
|
if (context->MemorySharedGraphState.TooltipIndex != getTooltipText->Index)
|
|
{
|
|
ULONG gpuSharedMemory = PhGetItemCircularBuffer_ULONG(
|
|
&context->MemorySharedHistory,
|
|
getTooltipText->Index
|
|
);
|
|
|
|
PhMoveReference(&context->MemorySharedGraphState.TooltipText,
|
|
PhFormatSize(UInt32x32To64(gpuSharedMemory, PAGE_SIZE), -1)
|
|
);
|
|
}
|
|
|
|
getTooltipText->Text = context->MemorySharedGraphState.TooltipText->sr;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case UPDATE_MSG:
|
|
{
|
|
if (context->Enabled)
|
|
{
|
|
GpuPropUpdateInfo(context);
|
|
GpuPropUpdateGraphs(context);
|
|
GpuPropUpdatePanel(context);
|
|
}
|
|
}
|
|
break;
|
|
case WM_SIZE:
|
|
{
|
|
GpuPropLayoutGraphs(context);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
VOID EtProcessGpuPropertiesInitializing(
|
|
_In_ PVOID Parameter
|
|
)
|
|
{
|
|
PPH_PLUGIN_PROCESS_PROPCONTEXT propContext = Parameter;
|
|
|
|
if (EtGpuEnabled)
|
|
{
|
|
PhAddProcessPropPage(
|
|
propContext->PropContext,
|
|
PhCreateProcessPropPageContextEx(PluginInstance->DllBase, MAKEINTRESOURCE(IDD_PROCGPU), EtpGpuPageDlgProc, NULL)
|
|
);
|
|
}
|
|
} |