From 92fb5cb0c1b5fdf4349b7782644f42e85b8d861c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 27 Mar 2026 10:56:14 +0800 Subject: [PATCH] GPU (WSL): supports VMEM total size query on Windows 10 Also adds debug logs --- src/detection/gpu/d3dkmthk.h | 8 ++ src/detection/gpu/gpu_wsl.c | 157 ++++++++++++++++++++++++++++------- 2 files changed, 137 insertions(+), 28 deletions(-) diff --git a/src/detection/gpu/d3dkmthk.h b/src/detection/gpu/d3dkmthk.h index d2a8cf649..90b10fff8 100644 --- a/src/detection/gpu/d3dkmthk.h +++ b/src/detection/gpu/d3dkmthk.h @@ -96,6 +96,13 @@ typedef struct _D3DKMT_CLOSEADAPTER D3DKMT_HANDLE hAdapter; // in: adapter handle } D3DKMT_CLOSEADAPTER; +typedef struct _D3DKMT_SEGMENTSIZEINFO +{ + D3DKMT_ALIGN64 ULONGLONG DedicatedVideoMemorySize; + D3DKMT_ALIGN64 ULONGLONG DedicatedSystemMemorySize; + D3DKMT_ALIGN64 ULONGLONG SharedSystemMemorySize; +} D3DKMT_SEGMENTSIZEINFO; + typedef struct _D3DKMT_ADAPTERTYPE { union @@ -179,6 +186,7 @@ typedef struct _D3DKMT_QUERY_ADAPTER_UNIQUE_GUID typedef enum _KMTQUERYADAPTERINFOTYPE { + KMTQAITYPE_GETSEGMENTSIZE = 3, KMTQAITYPE_ADAPTERGUID = 4, KMTQAITYPE_ADAPTERADDRESS = 6, KMTQAITYPE_ADAPTERREGISTRYINFO = 8, diff --git a/src/detection/gpu/gpu_wsl.c b/src/detection/gpu/gpu_wsl.c index 466336fd7..ac5a1d659 100644 --- a/src/detection/gpu/gpu_wsl.c +++ b/src/detection/gpu/gpu_wsl.c @@ -3,6 +3,7 @@ #include "detection/gpu/gpu.h" #include "detection/gpu/gpu_driver_specific.h" #include "common/io.h" +#include "common/debug.h" #include "d3dkmthk.h" #include @@ -31,22 +32,36 @@ const char* ffGPUDetectWsl2(const FFGPUOptions* options, FFlist* gpus) if (dxg < 0) { if (errno == ENOENT) + { + FF_DEBUG("/dev/dxg is not available, WSL DXCore GPU driver not detected"); return "No DXCore GPU driver detected (no /dev/dxg)"; + } else + { + FF_DEBUG("Failed to open /dev/dxg: %s", strerror(errno)); return "Failed to open /dev/dxg"; + } } + FF_DEBUG("Opened /dev/dxg successfully"); + D3DKMT_ADAPTERINFO adapters[MAX_ENUM_ADAPTERS]; D3DKMT_ENUMADAPTERS2 enumAdapters = { .NumAdapters = ARRAY_SIZE(adapters), .pAdapters = adapters, }; if (!NT_SUCCESS(D3DKMTEnumAdapters2(dxg, &enumAdapters))) + { + FF_DEBUG("D3DKMTEnumAdapters2 failed: %s", strerror(errno)); return "Failed to enumerate adapters with D3DKMTEnumAdapters2"; + } + + FF_DEBUG("D3DKMTEnumAdapters2 succeeded, adapter count: %u", enumAdapters.NumAdapters); for (uint32_t i = 0; i < enumAdapters.NumAdapters; i++) { const D3DKMT_ADAPTERINFO* adapter = &adapters[i]; + FF_DEBUG("Processing adapter #%u", i); D3DKMT_ADAPTERTYPE adapterType; if (!NT_SUCCESS(D3DKMTQueryAdapterInfo(dxg, &(D3DKMT_QUERYADAPTERINFO) { @@ -54,8 +69,16 @@ const char* ffGPUDetectWsl2(const FFGPUOptions* options, FFlist* gpus) .Type = KMTQAITYPE_ADAPTERTYPE, .pPrivateDriverData = &adapterType, .PrivateDriverDataSize = sizeof(adapterType), - }))) continue; - if (adapterType.SoftwareDevice) continue; + }))) + { + FF_DEBUG("KMTQAITYPE_ADAPTERTYPE query failed for adapter #%u: %s", i, strerror(errno)); + continue; + } + if (adapterType.SoftwareDevice) + { + FF_DEBUG("Skipping software adapter #%u", i); + continue; + } FFGPUResult* gpu = FF_LIST_ADD(FFGPUResult, *gpus); ffStrbufInit(&gpu->vendor); @@ -88,7 +111,10 @@ const char* ffGPUDetectWsl2(const FFGPUOptions* options, FFlist* gpus) { vendorStr = ffGPUGetVendorString(deviceIds.DeviceIds.VendorID); ffStrbufSetStatic(&gpu->vendor, vendorStr); + FF_DEBUG("Adapter #%u vendor/device IDs: vendor=0x%04x device=0x%04x", i, deviceIds.DeviceIds.VendorID, deviceIds.DeviceIds.DeviceID); } + else + FF_DEBUG("KMTQAITYPE_PHYSICALADAPTERDEVICEIDS query failed for adapter #%u: %s", i, strerror(errno)); D3DKMT_ADAPTERADDRESS adapterAddress; if (NT_SUCCESS(D3DKMTQueryAdapterInfo(dxg, &(D3DKMT_QUERYADAPTERINFO) { @@ -97,11 +123,15 @@ const char* ffGPUDetectWsl2(const FFGPUOptions* options, FFlist* gpus) .pPrivateDriverData = &adapterAddress, .PrivateDriverDataSize = sizeof(adapterAddress), }))) + { gpu->deviceId = ffGPUPciAddr2Id(0, adapterAddress.BusNumber, adapterAddress.DeviceNumber, adapterAddress.FunctionNumber); + FF_DEBUG("Adapter #%u PCI address: bus=%u device=%u function=%u", i, adapterAddress.BusNumber, adapterAddress.DeviceNumber, adapterAddress.FunctionNumber); + } else { adapterAddress.BusNumber = -1u; gpu->deviceId = ffGPUGeneral2Id(((uint64_t)adapter->AdapterLuid.HighPart << 32) | (uint64_t)adapter->AdapterLuid.LowPart); + FF_DEBUG("KMTQAITYPE_ADAPTERADDRESS query failed for adapter #%u, fallback to LUID-based deviceId: %s", i, strerror(errno)); } D3DKMT_UMD_DRIVER_VERSION umdDriverVersion; @@ -117,6 +147,11 @@ const char* ffGPUDetectWsl2(const FFGPUOptions* options, FFlist* gpus) umdDriverVersion.DriverVersion.QuadPart >> 32ul & 0xFFFF, umdDriverVersion.DriverVersion.QuadPart >> 16ul & 0xFFFF, umdDriverVersion.DriverVersion.QuadPart >> 0ul & 0xFFFF); + FF_DEBUG("Adapter #%u UMD driver version: %08lX", i, (unsigned long) umdDriverVersion.DriverVersion.QuadPart); + } + else + { + FF_DEBUG("KMTQAITYPE_UMD_DRIVER_VERSION query failed for adapter #%u: %s", i, strerror(errno)); } D3DKMT_DRIVERVERSION wddmVersion = KMT_DRIVERVERSION_WDDM_3_0; @@ -126,9 +161,15 @@ const char* ffGPUDetectWsl2(const FFGPUOptions* options, FFlist* gpus) .pPrivateDriverData = &wddmVersion, .PrivateDriverDataSize = sizeof(wddmVersion), }))) + { ffStrbufSetF(&gpu->platformApi, "WDDM %u.%u", wddmVersion / 1000, (wddmVersion % 1000) / 100); + FF_DEBUG("Adapter #%u WDDM version: %u", i, wddmVersion); + } else + { ffStrbufSetStatic(&gpu->platformApi, "WDDM"); + FF_DEBUG("KMTQAITYPE_DRIVERVERSION query failed for adapter #%u", i); + } if (gpu->name.length == 0) { @@ -139,11 +180,17 @@ const char* ffGPUDetectWsl2(const FFGPUOptions* options, FFlist* gpus) .pPrivateDriverData = ®istryInfo, .PrivateDriverDataSize = sizeof(registryInfo), }))) + { ffStrbufAppendUtf16(&gpu->name, registryInfo.AdapterString); + FF_DEBUG("Adapter #%u adapter string: %s", i, gpu->name.chars); + } + else + FF_DEBUG("KMTQAITYPE_ADAPTERREGISTRYINFO query failed for adapter #%u: %s", i, strerror(errno)); } if (vendorStr == FF_GPU_VENDOR_NAME_NVIDIA && options->driverSpecific) { + FF_DEBUG("Trying NVIDIA driver-specific detection for adapter #%u", i); FFGpuDriverCondition cond = { .type = FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID | (adapterAddress.DeviceNumber != -1u ? FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID : 0), .pciDeviceId = { @@ -159,7 +206,7 @@ const char* ffGPUDetectWsl2(const FFGPUOptions* options, FFlist* gpus) .func = adapterAddress.FunctionNumber, }, }; - ffDetectNvidiaGpuInfo(&cond, (FFGpuDriverResult){ + const char* error = ffDetectNvidiaGpuInfo(&cond, (FFGpuDriverResult){ .index = &gpu->index, .temp = options->temp ? &gpu->temperature : NULL, .memory = options->driverSpecific ? &gpu->dedicated : NULL, @@ -169,35 +216,71 @@ const char* ffGPUDetectWsl2(const FFGPUOptions* options, FFlist* gpus) .frequency = options->driverSpecific ? &gpu->frequency : NULL, .name = &gpu->name, }, "/usr/lib/wsl/lib/libnvidia-ml.so"); + if (error) + FF_DEBUG("NVIDIA driver-specific detection failed for adapter #%u: %s", i, error); + else + FF_DEBUG("NVIDIA driver-specific detection succeeded for adapter #%u", i); } - if (gpu->dedicated.total == FF_GPU_VMEM_SIZE_UNSET && gpu->shared.total == FF_GPU_VMEM_SIZE_UNSET && wddmVersion >= KMT_DRIVERVERSION_WDDM_3_1) + if (gpu->dedicated.total == FF_GPU_VMEM_SIZE_UNSET && gpu->shared.total == FF_GPU_VMEM_SIZE_UNSET) { - D3DKMT_QUERYSTATISTICS queryStatistics = { - .Type = D3DKMT_QUERYSTATISTICS_SEGMENT_GROUP_USAGE, - .AdapterLuid = adapter->AdapterLuid, - .QuerySegmentGroupUsage = { - .PhysicalAdapterIndex = 0, - .SegmentGroup = D3DKMT_MEMORY_SEGMENT_GROUP_LOCAL, - }, - }; - if (NT_SUCCESS(D3DKMTQueryStatistics(dxg, &queryStatistics))) + if (wddmVersion >= KMT_DRIVERVERSION_WDDM_3_1 && options->driverSpecific) { - D3DKMT_QUERYSTATISTICS_MEMORY_USAGE* info = &queryStatistics.QueryResult.SegmentGroupUsageInformation; - uint64_t used = info->AllocatedBytes + info->ModifiedBytes + info->StandbyBytes; - uint64_t total = used + info->FreeBytes + info->ZeroBytes; - gpu->dedicated.used = used; - gpu->dedicated.total = total; - } + // Supports memory usage query; requires Windows 11 (22H2) or later + D3DKMT_QUERYSTATISTICS queryStatistics = { + .Type = D3DKMT_QUERYSTATISTICS_SEGMENT_GROUP_USAGE, + .AdapterLuid = adapter->AdapterLuid, + .QuerySegmentGroupUsage = { + .PhysicalAdapterIndex = 0, + .SegmentGroup = D3DKMT_MEMORY_SEGMENT_GROUP_LOCAL, + }, + }; + if (NT_SUCCESS(D3DKMTQueryStatistics(dxg, &queryStatistics))) + { + D3DKMT_QUERYSTATISTICS_MEMORY_USAGE* info = &queryStatistics.QueryResult.SegmentGroupUsageInformation; + uint64_t used = info->AllocatedBytes + info->ModifiedBytes + info->StandbyBytes; + uint64_t total = used + info->FreeBytes + info->ZeroBytes; + gpu->dedicated.used = used; + gpu->dedicated.total = total; + FF_DEBUG("Adapter #%u local memory usage: used=%lu total=%lu", i, (unsigned long) used, (unsigned long) total); + } + else + FF_DEBUG("D3DKMT_QUERYSTATISTICS_SEGMENT_GROUP_USAGE (LOCAL) failed for adapter #%u: %s", i, strerror(errno)); - queryStatistics.QuerySegmentGroupUsage.SegmentGroup = D3DKMT_MEMORY_SEGMENT_GROUP_NON_LOCAL; - if (NT_SUCCESS(D3DKMTQueryStatistics(dxg, &queryStatistics))) + queryStatistics.QuerySegmentGroupUsage.SegmentGroup = D3DKMT_MEMORY_SEGMENT_GROUP_NON_LOCAL; + if (NT_SUCCESS(D3DKMTQueryStatistics(dxg, &queryStatistics))) + { + D3DKMT_QUERYSTATISTICS_MEMORY_USAGE* info = &queryStatistics.QueryResult.SegmentGroupUsageInformation; + uint64_t used = info->AllocatedBytes + info->ModifiedBytes + info->StandbyBytes; + uint64_t total = used + info->FreeBytes + info->ZeroBytes; + gpu->shared.used = used; + gpu->shared.total = total; + FF_DEBUG("Adapter #%u non-local memory usage: used=%lu total=%lu", i, (unsigned long) used, (unsigned long) total); + } + else + FF_DEBUG("D3DKMT_QUERYSTATISTICS_SEGMENT_GROUP_USAGE (NON_LOCAL) failed for adapter #%u: %s", i, strerror(errno)); + } + else { - D3DKMT_QUERYSTATISTICS_MEMORY_USAGE* info = &queryStatistics.QueryResult.SegmentGroupUsageInformation; - uint64_t used = info->AllocatedBytes + info->ModifiedBytes + info->StandbyBytes; - uint64_t total = used + info->FreeBytes + info->ZeroBytes; - gpu->shared.used = used; - gpu->shared.total = total; + // Supports basic segment (total) size query + D3DKMT_SEGMENTSIZEINFO segmentSizeInfo = {}; + D3DKMT_QUERYADAPTERINFO queryAdapterInfo = { + .hAdapter = adapter->hAdapter, + .Type = KMTQAITYPE_GETSEGMENTSIZE, + .pPrivateDriverData = &segmentSizeInfo, + .PrivateDriverDataSize = sizeof(segmentSizeInfo), + }; + if (NT_SUCCESS(D3DKMTQueryAdapterInfo(dxg, &queryAdapterInfo))) + { + FF_DEBUG("Adapter #%u segment size - DedicatedVideoMemorySize: %lu, DedicatedSystemMemorySize: %lu, SharedSystemMemorySize: %lu", + i, segmentSizeInfo.DedicatedVideoMemorySize, segmentSizeInfo.DedicatedSystemMemorySize, segmentSizeInfo.SharedSystemMemorySize); + gpu->dedicated.total = segmentSizeInfo.DedicatedVideoMemorySize; + gpu->shared.total = segmentSizeInfo.DedicatedSystemMemorySize + segmentSizeInfo.SharedSystemMemorySize; + } + else + { + FF_DEBUG("Failed to query segment size information for adapter #%u: %s", i, strerror(errno)); + } } } @@ -227,8 +310,11 @@ const char* ffGPUDetectWsl2(const FFGPUOptions* options, FFlist* gpus) if (NT_SUCCESS(D3DKMTQueryStatistics(dxg, &queryStatistics))) { gpu->frequency = (uint32_t) (queryStatistics.QueryResult.NodeInformation.NodePerfData.MaxFrequency / 1000 / 1000); + FF_DEBUG("Adapter #%u max graphics frequency: %u MHz", i, gpu->frequency); break; } + else + FF_DEBUG("Failed to query node performance data for adapter #%u node #%u: %s", i, nodeIdx, strerror(errno)); } } @@ -241,12 +327,27 @@ const char* ffGPUDetectWsl2(const FFGPUOptions* options, FFlist* gpus) }; if (NT_SUCCESS(D3DKMTQueryStatistics(dxg, &queryStatistics)) && queryStatistics.QueryResult.PhysAdapterInformation.AdapterPerfData.Temperature != 0) + { gpu->temperature = queryStatistics.QueryResult.PhysAdapterInformation.AdapterPerfData.Temperature / 10.0; + FF_DEBUG("Adapter #%u temperature: %.1f°C", i, gpu->temperature); + } + else + FF_DEBUG("Failed to query temperature for adapter #%u: %s", i, strerror(errno)); } - (void) D3DKMTCloseAdapter(dxg, &(D3DKMT_CLOSEADAPTER) { + FF_DEBUG("Adapter #%u summary: name='%s', vendor='%s', type=%u, deviceId=%lu", + i, + gpu->name.length ? gpu->name.chars : "unknown", + gpu->vendor.length ? gpu->vendor.chars : "unknown", + (unsigned) gpu->type, + (unsigned long) gpu->deviceId); + + if (NT_SUCCESS(D3DKMTCloseAdapter(dxg, &(D3DKMT_CLOSEADAPTER) { .hAdapter = adapter->hAdapter - }); + }))) + FF_DEBUG("Closed adapter #%u successfully", i); + else + FF_DEBUG("Failed to close adapter #%u: %s", i, strerror(errno)); } return NULL;