VOID EtSaveGpuMonitorSettings( VOID ) { PPH_STRING string; string = PhBufferToHexString((PUCHAR)EtGpuNodeBitMapBuffer, BYTES_NEEDED_FOR_BITS(EtGpuTotalNodeCount)); PhSetStringSetting2(SETTING_NAME_GPU_NODE_BITMAP, &string->sr); PhDereferenceObject(string); }
VOID EtAllocateGpuNodeBitMap( _Out_ PRTL_BITMAP BitMap ) { SIZE_T numberOfBytes; numberOfBytes = BYTES_NEEDED_FOR_BITS(EtGpuTotalNodeCount); BitMap->Buffer = PhAllocate(numberOfBytes); BitMap->SizeOfBitMap = EtGpuTotalNodeCount; memset(BitMap->Buffer, 0, numberOfBytes); }
PETP_GPU_ADAPTER AllocateGpuAdapter( UINT32 NumberOfSegments ) { PETP_GPU_ADAPTER adapter; UINT32 sizeNeeded; sizeNeeded = FIELD_OFFSET(ETP_GPU_ADAPTER, ApertureBitMapBuffer); sizeNeeded += BYTES_NEEDED_FOR_BITS(NumberOfSegments); adapter = (PETP_GPU_ADAPTER) Memory::Allocate(sizeNeeded); Memory::Clear(adapter, sizeNeeded); return adapter; }
PETP_GPU_ADAPTER EtpAllocateGpuAdapter( _In_ ULONG NumberOfSegments ) { PETP_GPU_ADAPTER adapter; SIZE_T sizeNeeded; sizeNeeded = FIELD_OFFSET(ETP_GPU_ADAPTER, ApertureBitMapBuffer); sizeNeeded += BYTES_NEEDED_FOR_BITS(NumberOfSegments); adapter = PhAllocate(sizeNeeded); memset(adapter, 0, sizeNeeded); return adapter; }
VOID D3DKMTInitialize() { VOID *gdi32 = NULL; VOID *deviceInfoSet; UINT32 result; UINT32 memberIndex; UINT32 detailDataSize; SP_DEVICE_INTERFACE_DATA deviceInterfaceData; SP_DEVICE_INTERFACE_DETAIL_DATA_W *detailData; SP_DEVINFO_DATA deviceInfoData; //D3DKMT_OPENADAPTERFROMDEVICENAME openAdapterFromDeviceName; D3DKMT_QUERYSTATISTICS queryStatistics; gdi32 = Module::Load(L"gdi32.dll"); if (!gdi32) { return; } D3DKMTOpenAdapterFromDeviceName = (TYPE_D3DKMTOpenAdapterFromDeviceName) Module::GetProcedureAddress( gdi32, "D3DKMTOpenAdapterFromDeviceName" ); D3DKMTQueryStatistics = (TYPE_D3DKMTQueryStatistics) Module::GetProcedureAddress(gdi32, "D3DKMTQueryStatistics"); if (!D3DKMTOpenAdapterFromDeviceName || !D3DKMTQueryStatistics) { return; } deviceInfoSet = SetupDiGetClassDevsW(&GUID_DISPLAY_DEVICE_ARRIVAL_I, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); if (!deviceInfoSet) { return; } memberIndex = 0; deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); while (SetupDiEnumDeviceInterfaces(deviceInfoSet, NULL, &GUID_DISPLAY_DEVICE_ARRIVAL_I, memberIndex, &deviceInterfaceData)) { detailDataSize = 0x100; detailData = (SP_DEVICE_INTERFACE_DETAIL_DATA_W*) Memory::Allocate(detailDataSize); detailData->cbSize = 6; /*sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)*/ deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); result = SetupDiGetDeviceInterfaceDetailW( deviceInfoSet, &deviceInterfaceData, detailData, detailDataSize, &detailDataSize, &deviceInfoData ); if (result) { openAdapterFromDeviceName.pDeviceName = detailData->DevicePath; if (NT_SUCCESS(D3DKMTOpenAdapterFromDeviceName(&openAdapterFromDeviceName))) { memset(&queryStatistics, 0, sizeof(D3DKMT_QUERYSTATISTICS)); queryStatistics.Type = D3DKMT_QUERYSTATISTICS_ADAPTER; queryStatistics.AdapterLuid = openAdapterFromDeviceName.AdapterLuid; if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics))) { UINT32 i; D3dkmt_GpuAdapter = AllocateGpuAdapter(queryStatistics.QueryResult.AdapterInformation.NbSegments); D3dkmt_GpuAdapter->AdapterLuid = openAdapterFromDeviceName.AdapterLuid; D3dkmt_GpuAdapter->NodeCount = queryStatistics.QueryResult.AdapterInformation.NodeCount; D3dkmt_GpuAdapter->SegmentCount = queryStatistics.QueryResult.AdapterInformation.NbSegments; RtlInitializeBitMap( &D3dkmt_GpuAdapter->ApertureBitMap, D3dkmt_GpuAdapter->ApertureBitMapBuffer, queryStatistics.QueryResult.AdapterInformation.NbSegments ); EtGpuTotalNodeCount += D3dkmt_GpuAdapter->NodeCount; EtGpuTotalSegmentCount += D3dkmt_GpuAdapter->SegmentCount; D3dkmt_GpuAdapter->FirstNodeIndex = EtGpuNextNodeIndex; EtGpuNextNodeIndex += D3dkmt_GpuAdapter->NodeCount; for (i = 0; i < D3dkmt_GpuAdapter->SegmentCount; i++) { memset(&queryStatistics, 0, sizeof(D3DKMT_QUERYSTATISTICS)); queryStatistics.Type = D3DKMT_QUERYSTATISTICS_SEGMENT; queryStatistics.AdapterLuid = D3dkmt_GpuAdapter->AdapterLuid; queryStatistics.QuerySegment.SegmentId = i; if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics))) { UINT64 commitLimit; UINT32 aperature; commitLimit = queryStatistics.QueryResult.SegmentInformationV1.CommitLimit; aperature = queryStatistics.QueryResult.SegmentInformationV1.Aperture; if (aperature) RtlSetBits(&D3dkmt_GpuAdapter->ApertureBitMap, i, 1); else EtGpuDedicatedLimit += commitLimit; } } } } } Memory::Free(detailData); memberIndex++; } SetupDiDestroyDeviceInfoList(deviceInfoSet); EtGpuNodeBitMapBuffer = (UINT32*) Memory::Allocate(BYTES_NEEDED_FOR_BITS(EtGpuTotalNodeCount)); RtlInitializeBitMap(&EtGpuNodeBitMap, EtGpuNodeBitMapBuffer, EtGpuTotalNodeCount); EtGpuNodesTotalRunningTimeDelta = (PPH_UINT64_DELTA) Memory::Allocate(sizeof(PH_UINT64_DELTA) * EtGpuTotalNodeCount); memset(EtGpuNodesTotalRunningTimeDelta, 0, sizeof(PH_UINT64_DELTA) * EtGpuTotalNodeCount); }
BOOLEAN EtpInitializeD3DStatistics( VOID ) { LOGICAL result; HDEVINFO deviceInfoSet; ULONG memberIndex; SP_DEVICE_INTERFACE_DATA deviceInterfaceData; PSP_DEVICE_INTERFACE_DETAIL_DATA detailData; SP_DEVINFO_DATA deviceInfoData; ULONG detailDataSize; D3DKMT_OPENADAPTERFROMDEVICENAME openAdapterFromDeviceName; D3DKMT_QUERYSTATISTICS queryStatistics; deviceInfoSet = SetupDiGetClassDevsW_I(&GUID_DISPLAY_DEVICE_ARRIVAL_I, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); if (!deviceInfoSet) return FALSE; memberIndex = 0; deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); while (SetupDiEnumDeviceInterfaces_I(deviceInfoSet, NULL, &GUID_DISPLAY_DEVICE_ARRIVAL_I, memberIndex, &deviceInterfaceData)) { detailDataSize = 0x100; detailData = PhAllocate(detailDataSize); detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); if (!(result = SetupDiGetDeviceInterfaceDetailW_I(deviceInfoSet, &deviceInterfaceData, detailData, detailDataSize, &detailDataSize, &deviceInfoData)) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { PhFree(detailData); detailData = PhAllocate(detailDataSize); if (detailDataSize >= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA)) detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); result = SetupDiGetDeviceInterfaceDetailW_I(deviceInfoSet, &deviceInterfaceData, detailData, detailDataSize, &detailDataSize, &deviceInfoData); } if (result) { openAdapterFromDeviceName.pDeviceName = detailData->DevicePath; if (NT_SUCCESS(D3DKMTOpenAdapterFromDeviceName_I(&openAdapterFromDeviceName))) { memset(&queryStatistics, 0, sizeof(D3DKMT_QUERYSTATISTICS)); queryStatistics.Type = D3DKMT_QUERYSTATISTICS_ADAPTER; queryStatistics.AdapterLuid = openAdapterFromDeviceName.AdapterLuid; if (NT_SUCCESS(D3DKMTQueryStatistics_I(&queryStatistics))) { PETP_GPU_ADAPTER gpuAdapter; ULONG i; gpuAdapter = EtpAllocateGpuAdapter(queryStatistics.QueryResult.AdapterInformation.NbSegments); gpuAdapter->AdapterLuid = openAdapterFromDeviceName.AdapterLuid; gpuAdapter->Description = EtpQueryDeviceDescription(deviceInfoSet, &deviceInfoData); gpuAdapter->NodeCount = queryStatistics.QueryResult.AdapterInformation.NodeCount; gpuAdapter->SegmentCount = queryStatistics.QueryResult.AdapterInformation.NbSegments; RtlInitializeBitMap(&gpuAdapter->ApertureBitMap, gpuAdapter->ApertureBitMapBuffer, queryStatistics.QueryResult.AdapterInformation.NbSegments); PhAddItemList(EtpGpuAdapterList, gpuAdapter); EtGpuTotalNodeCount += gpuAdapter->NodeCount; EtGpuTotalSegmentCount += gpuAdapter->SegmentCount; gpuAdapter->FirstNodeIndex = EtGpuNextNodeIndex; EtGpuNextNodeIndex += gpuAdapter->NodeCount; for (i = 0; i < gpuAdapter->SegmentCount; i++) { memset(&queryStatistics, 0, sizeof(D3DKMT_QUERYSTATISTICS)); queryStatistics.Type = D3DKMT_QUERYSTATISTICS_SEGMENT; queryStatistics.AdapterLuid = gpuAdapter->AdapterLuid; queryStatistics.QuerySegment.SegmentId = i; if (NT_SUCCESS(D3DKMTQueryStatistics_I(&queryStatistics))) { ULONG64 commitLimit; ULONG aperture; commitLimit = queryStatistics.QueryResult.SegmentInformation.CommitLimit; aperture = queryStatistics.QueryResult.SegmentInformation.Aperture; if (aperture) EtGpuSharedLimit += commitLimit; else EtGpuDedicatedLimit += commitLimit; if (aperture) RtlSetBits(&gpuAdapter->ApertureBitMap, i, 1); } } } } } PhFree(detailData); memberIndex++; } SetupDiDestroyDeviceInfoList_I(deviceInfoSet); EtGpuNodeBitMapBuffer = PhAllocate(BYTES_NEEDED_FOR_BITS(EtGpuTotalNodeCount)); RtlInitializeBitMap(&EtGpuNodeBitMap, EtGpuNodeBitMapBuffer, EtGpuTotalNodeCount); RtlSetBits(&EtGpuNodeBitMap, 0, 1); EtGpuNodeBitMapBitsSet = 1; return TRUE; }
VOID EtGpuMonitorInitialization( VOID ) { if (PhGetIntegerSetting(SETTING_NAME_ENABLE_GPU_MONITOR)) { EtpGpuAdapterList = PhCreateList(4); if (EtpInitializeD3DStatistics()) EtGpuEnabled = TRUE; } if (EtGpuEnabled) { ULONG sampleCount; ULONG i; ULONG j; PPH_STRING bitmapString; D3DKMT_QUERYSTATISTICS queryStatistics; sampleCount = PhGetIntegerSetting(L"SampleCount"); PhInitializeCircularBuffer_FLOAT(&EtGpuNodeHistory, sampleCount); PhInitializeCircularBuffer_ULONG(&EtMaxGpuNodeHistory, sampleCount); PhInitializeCircularBuffer_FLOAT(&EtMaxGpuNodeUsageHistory, sampleCount); PhInitializeCircularBuffer_ULONG(&EtGpuDedicatedHistory, sampleCount); PhInitializeCircularBuffer_ULONG(&EtGpuSharedHistory, sampleCount); EtGpuNodesTotalRunningTimeDelta = PhAllocate(sizeof(PH_UINT64_DELTA) * EtGpuTotalNodeCount); memset(EtGpuNodesTotalRunningTimeDelta, 0, sizeof(PH_UINT64_DELTA) * EtGpuTotalNodeCount); EtGpuNodesHistory = PhAllocate(sizeof(PH_CIRCULAR_BUFFER_FLOAT) * EtGpuTotalNodeCount); for (i = 0; i < EtGpuTotalNodeCount; i++) { PhInitializeCircularBuffer_FLOAT(&EtGpuNodesHistory[i], sampleCount); } PhRegisterCallback( &PhProcessesUpdatedEvent, EtGpuProcessesUpdatedCallback, NULL, &ProcessesUpdatedCallbackRegistration ); // Load the node bitmap. bitmapString = PhGetStringSetting(SETTING_NAME_GPU_NODE_BITMAP); if (!(bitmapString->Length & 3) && bitmapString->Length / 4 <= BYTES_NEEDED_FOR_BITS(EtGpuTotalNodeCount)) { PhHexStringToBuffer(&bitmapString->sr, (PUCHAR)EtGpuNodeBitMapBuffer); EtGpuNodeBitMapBitsSet = RtlNumberOfSetBits(&EtGpuNodeBitMap); } PhDereferenceObject(bitmapString); // Fix up the node bitmap if the current node count differs from what we've seen. if (EtGpuTotalNodeCount != PhGetIntegerSetting(SETTING_NAME_GPU_LAST_NODE_COUNT)) { ULONG maxContextSwitch = 0; ULONG maxContextSwitchNodeIndex = 0; RtlClearAllBits(&EtGpuNodeBitMap); EtGpuNodeBitMapBitsSet = 0; for (i = 0; i < EtpGpuAdapterList->Count; i++) { PETP_GPU_ADAPTER gpuAdapter = EtpGpuAdapterList->Items[i]; for (j = 0; j < gpuAdapter->NodeCount; j++) { memset(&queryStatistics, 0, sizeof(D3DKMT_QUERYSTATISTICS)); queryStatistics.Type = D3DKMT_QUERYSTATISTICS_NODE; queryStatistics.AdapterLuid = gpuAdapter->AdapterLuid; queryStatistics.QueryNode.NodeId = j; if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics))) { // The numbers below are quite arbitrary. if (queryStatistics.QueryResult.NodeInformation.GlobalInformation.RunningTime.QuadPart != 0 && queryStatistics.QueryResult.NodeInformation.GlobalInformation.ContextSwitch > 10000) { RtlSetBits(&EtGpuNodeBitMap, gpuAdapter->FirstNodeIndex + j, 1); EtGpuNodeBitMapBitsSet++; } if (maxContextSwitch < queryStatistics.QueryResult.NodeInformation.GlobalInformation.ContextSwitch) { maxContextSwitch = queryStatistics.QueryResult.NodeInformation.GlobalInformation.ContextSwitch; maxContextSwitchNodeIndex = gpuAdapter->FirstNodeIndex + j; } } } } // Just in case if (EtGpuNodeBitMapBitsSet == 0) { RtlSetBits(&EtGpuNodeBitMap, maxContextSwitchNodeIndex, 1); EtGpuNodeBitMapBitsSet = 1; } PhSetIntegerSetting(SETTING_NAME_GPU_LAST_NODE_COUNT, EtGpuTotalNodeCount); } } }
BOOLEAN EtpInitializeD3DStatistics( VOID ) { PWSTR deviceInterfaceList; ULONG deviceInterfaceListLength = 0; PWSTR deviceInterface; D3DKMT_OPENADAPTERFROMDEVICENAME openAdapterFromDeviceName; D3DKMT_QUERYSTATISTICS queryStatistics; D3DKMT_CLOSEADAPTER closeAdapter; if (CM_Get_Device_Interface_List_Size( &deviceInterfaceListLength, (PGUID)&GUID_DISPLAY_DEVICE_ARRIVAL, NULL, CM_GET_DEVICE_INTERFACE_LIST_PRESENT ) != CR_SUCCESS) { return FALSE; } deviceInterfaceList = PhAllocate(deviceInterfaceListLength * sizeof(WCHAR)); memset(deviceInterfaceList, 0, deviceInterfaceListLength * sizeof(WCHAR)); if (CM_Get_Device_Interface_List( (PGUID)&GUID_DISPLAY_DEVICE_ARRIVAL, NULL, deviceInterfaceList, deviceInterfaceListLength, CM_GET_DEVICE_INTERFACE_LIST_PRESENT ) != CR_SUCCESS) { PhFree(deviceInterfaceList); return FALSE; } for (deviceInterface = deviceInterfaceList; *deviceInterface; deviceInterface += PhCountStringZ(deviceInterface) + 1) { memset(&openAdapterFromDeviceName, 0, sizeof(D3DKMT_OPENADAPTERFROMDEVICENAME)); openAdapterFromDeviceName.pDeviceName = deviceInterface; if (NT_SUCCESS(D3DKMTOpenAdapterFromDeviceName(&openAdapterFromDeviceName))) { memset(&queryStatistics, 0, sizeof(D3DKMT_QUERYSTATISTICS)); queryStatistics.Type = D3DKMT_QUERYSTATISTICS_ADAPTER; queryStatistics.AdapterLuid = openAdapterFromDeviceName.AdapterLuid; if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics))) { PETP_GPU_ADAPTER gpuAdapter; ULONG i; gpuAdapter = EtpAllocateGpuAdapter(queryStatistics.QueryResult.AdapterInformation.NbSegments); gpuAdapter->AdapterLuid = openAdapterFromDeviceName.AdapterLuid; gpuAdapter->Description = EtpQueryDeviceDescription(deviceInterface); gpuAdapter->NodeCount = queryStatistics.QueryResult.AdapterInformation.NodeCount; gpuAdapter->SegmentCount = queryStatistics.QueryResult.AdapterInformation.NbSegments; RtlInitializeBitMap(&gpuAdapter->ApertureBitMap, gpuAdapter->ApertureBitMapBuffer, queryStatistics.QueryResult.AdapterInformation.NbSegments); PhAddItemList(EtpGpuAdapterList, gpuAdapter); EtGpuTotalNodeCount += gpuAdapter->NodeCount; EtGpuTotalSegmentCount += gpuAdapter->SegmentCount; gpuAdapter->FirstNodeIndex = EtGpuNextNodeIndex; EtGpuNextNodeIndex += gpuAdapter->NodeCount; for (i = 0; i < gpuAdapter->SegmentCount; i++) { memset(&queryStatistics, 0, sizeof(D3DKMT_QUERYSTATISTICS)); queryStatistics.Type = D3DKMT_QUERYSTATISTICS_SEGMENT; queryStatistics.AdapterLuid = gpuAdapter->AdapterLuid; queryStatistics.QuerySegment.SegmentId = i; if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics))) { ULONG64 commitLimit; ULONG aperture; if (WindowsVersion >= WINDOWS_8) { commitLimit = queryStatistics.QueryResult.SegmentInformation.CommitLimit; aperture = queryStatistics.QueryResult.SegmentInformation.Aperture; } else { commitLimit = queryStatistics.QueryResult.SegmentInformationV1.CommitLimit; aperture = queryStatistics.QueryResult.SegmentInformationV1.Aperture; } if (aperture) EtGpuSharedLimit += commitLimit; else EtGpuDedicatedLimit += commitLimit; if (aperture) RtlSetBits(&gpuAdapter->ApertureBitMap, i, 1); } } } memset(&closeAdapter, 0, sizeof(D3DKMT_CLOSEADAPTER)); closeAdapter.hAdapter = openAdapterFromDeviceName.hAdapter; D3DKMTCloseAdapter(&closeAdapter); } } PhFree(deviceInterfaceList); EtGpuNodeBitMapBuffer = PhAllocate(BYTES_NEEDED_FOR_BITS(EtGpuTotalNodeCount)); RtlInitializeBitMap(&EtGpuNodeBitMap, EtGpuNodeBitMapBuffer, EtGpuTotalNodeCount); RtlSetBits(&EtGpuNodeBitMap, 0, 1); EtGpuNodeBitMapBitsSet = 1; return TRUE; }