diff options
author | Jens Peters <jp7677@gmail.com> | 2022-08-28 11:25:38 +0300 |
---|---|---|
committer | Jens Peters <jp7677@gmail.com> | 2022-08-28 14:27:47 +0300 |
commit | 42ad10b8418d986f74759e31ffaab34bc1ecabac (patch) | |
tree | 0854a01fd4f313bcb1b11dfedf9d31f1d8ac2116 | |
parent | fa9a2c4346edaf1cf75165cd3c3ac0d0e2850a8f (diff) |
nvapi-gpu: Implement GetCurrentPCIEDownstreamWidth using nvml
-rw-r--r-- | src/nvapi_gpu.cpp | 39 | ||||
-rw-r--r-- | src/nvapi_interface.cpp | 1 | ||||
-rw-r--r-- | src/sysinfo/nvapi_adapter.cpp | 4 | ||||
-rw-r--r-- | src/sysinfo/nvapi_adapter.h | 1 | ||||
-rw-r--r-- | src/sysinfo/nvml.cpp | 7 | ||||
-rw-r--r-- | src/sysinfo/nvml.h | 2 | ||||
-rw-r--r-- | tests/nvapi_sysinfo.cpp | 21 | ||||
-rw-r--r-- | tests/nvapi_sysinfo_mocks.h | 1 | ||||
-rw-r--r-- | tests/nvapi_system.cpp | 10 |
9 files changed, 86 insertions, 0 deletions
diff --git a/src/nvapi_gpu.cpp b/src/nvapi_gpu.cpp index 39034a1..c667b73 100644 --- a/src/nvapi_gpu.cpp +++ b/src/nvapi_gpu.cpp @@ -6,6 +6,45 @@ extern "C" { using namespace dxvk; + NvAPI_Status __cdecl NvAPI_GPU_GetCurrentPCIEDownstreamWidth(NvPhysicalGpuHandle hPhysicalGpu, NvU32* pWidth) { + constexpr auto n = __func__; + static bool alreadyLoggedNoNvml = false; + static bool alreadyLoggedHandleInvalidated = false; + static bool alreadyLoggedOk = false; + + if (nvapiAdapterRegistry == nullptr) + return ApiNotInitialized(n); + + if (pWidth == nullptr) + return InvalidArgument(n); + + auto adapter = reinterpret_cast<NvapiAdapter*>(hPhysicalGpu); + if (!nvapiAdapterRegistry->IsAdapter(adapter)) + return ExpectedPhysicalGpuHandle(n); + + if (!adapter->HasNvml()) + return NoImplementation(n, alreadyLoggedNoNvml); + + if (!adapter->HasNvmlDevice()) + return HandleInvalidated(str::format(n, ": NVML available but current adapter is not NVML compatible"), alreadyLoggedHandleInvalidated); + + unsigned int width; + auto result = adapter->GetNvmlDeviceGetCurrPcieLinkWidth(&width); + switch (result) { + case NVML_SUCCESS: + *pWidth = width; + return Ok(n, alreadyLoggedOk); + case NVML_ERROR_FUNCTION_NOT_FOUND: + return NoImplementation(n, alreadyLoggedNoNvml); + case NVML_ERROR_NOT_SUPPORTED: + return NotSupported(n); + case NVML_ERROR_GPU_IS_LOST: + return HandleInvalidated(n); + default: + return Error(str::format(n, ": ", adapter->GetNvmlErrorString(result))); + } + } + NvAPI_Status __cdecl NvAPI_GPU_GetGpuCoreCount(NvPhysicalGpuHandle hPhysicalGpu, NvU32* pCount) { constexpr auto n = __func__; static bool alreadyLoggedNoNvml = false; diff --git a/src/nvapi_interface.cpp b/src/nvapi_interface.cpp index 4dabba1..a62398a 100644 --- a/src/nvapi_interface.cpp +++ b/src/nvapi_interface.cpp @@ -71,6 +71,7 @@ extern "C" { INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D_Sleep) INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D_GetLatency) INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_D3D_SetLatencyMarker) + INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_GPU_GetCurrentPCIEDownstreamWidth) INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_GPU_GetGpuCoreCount) INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_GPU_GetGPUType) INSERT_AND_RETURN_WHEN_EQUALS(NvAPI_GPU_GetPCIIdentifiers) diff --git a/src/sysinfo/nvapi_adapter.cpp b/src/sysinfo/nvapi_adapter.cpp index 569d110..fc56da5 100644 --- a/src/sysinfo/nvapi_adapter.cpp +++ b/src/sysinfo/nvapi_adapter.cpp @@ -274,6 +274,10 @@ namespace dxvk { return m_nvml.DeviceGetVbiosVersion(m_nvmlDevice, version, length); } + nvmlReturn_t NvapiAdapter::GetNvmlDeviceGetCurrPcieLinkWidth(unsigned int* width) const { + return m_nvml.DeviceGetCurrPcieLinkWidth(m_nvmlDevice, width); + } + nvmlReturn_t NvapiAdapter::GetNvmlDeviceNumGpuCores(unsigned int* numCores) const { return m_nvml.DeviceGetNumGpuCores(m_nvmlDevice, numCores); } diff --git a/src/sysinfo/nvapi_adapter.h b/src/sysinfo/nvapi_adapter.h index 0a3075f..364dd01 100644 --- a/src/sysinfo/nvapi_adapter.h +++ b/src/sysinfo/nvapi_adapter.h @@ -37,6 +37,7 @@ namespace dxvk { [[nodiscard]] nvmlReturn_t GetNvmlDevicePerformanceState(nvmlPstates_t* pState) const; [[nodiscard]] nvmlReturn_t GetNvmlDeviceUtilizationRates(nvmlUtilization_t* utilization) const; [[nodiscard]] nvmlReturn_t GetNvmlDeviceVbiosVersion(char* version, unsigned int length) const; + [[nodiscard]] nvmlReturn_t GetNvmlDeviceGetCurrPcieLinkWidth(unsigned int* width) const; [[nodiscard]] nvmlReturn_t GetNvmlDeviceNumGpuCores(unsigned int* numCores) const; [[nodiscard]] nvmlReturn_t GetNvmlDeviceBusType(nvmlBusType_t* type) const; [[nodiscard]] nvmlReturn_t GetNvmlDeviceDynamicPstatesInfo(nvmlGpuDynamicPstatesInfo_t* pDynamicPstatesInfo) const; diff --git a/src/sysinfo/nvml.cpp b/src/sysinfo/nvml.cpp index c4ce9d3..a34fcd3 100644 --- a/src/sysinfo/nvml.cpp +++ b/src/sysinfo/nvml.cpp @@ -27,6 +27,7 @@ namespace dxvk { GETPROCADDR(nvmlDeviceGetPerformanceState); GETPROCADDR(nvmlDeviceGetUtilizationRates); GETPROCADDR(nvmlDeviceGetVbiosVersion); + GETPROCADDR(nvmlDeviceGetCurrPcieLinkWidth); GETPROCADDR(nvmlDeviceGetNumGpuCores); GETPROCADDR(nvmlDeviceGetBusType); GETPROCADDR(nvmlDeviceGetDynamicPstatesInfo); @@ -113,6 +114,12 @@ namespace dxvk { : NVML_ERROR_FUNCTION_NOT_FOUND; } + nvmlReturn_t Nvml::DeviceGetCurrPcieLinkWidth(nvmlDevice_t device, unsigned int* width) const { + return m_nvmlDeviceGetCurrPcieLinkWidth + ? m_nvmlDeviceGetCurrPcieLinkWidth(device, width) + : NVML_ERROR_FUNCTION_NOT_FOUND; + } + nvmlReturn_t Nvml::DeviceGetNumGpuCores(nvmlDevice_t device, unsigned int* numCores) const { return m_nvmlDeviceGetNumGpuCores ? m_nvmlDeviceGetNumGpuCores(device, numCores) diff --git a/src/sysinfo/nvml.h b/src/sysinfo/nvml.h index d8d7a36..5ee8444 100644 --- a/src/sysinfo/nvml.h +++ b/src/sysinfo/nvml.h @@ -19,6 +19,7 @@ namespace dxvk { [[nodiscard]] virtual nvmlReturn_t DeviceGetPerformanceState(nvmlDevice_t device, nvmlPstates_t* pState) const; [[nodiscard]] virtual nvmlReturn_t DeviceGetUtilizationRates(nvmlDevice_t device, nvmlUtilization_t* utilization) const; [[nodiscard]] virtual nvmlReturn_t DeviceGetVbiosVersion(nvmlDevice_t device, char* version, unsigned int length) const; + [[nodiscard]] virtual nvmlReturn_t DeviceGetCurrPcieLinkWidth(nvmlDevice_t device, unsigned int* width) const; [[nodiscard]] virtual nvmlReturn_t DeviceGetNumGpuCores(nvmlDevice_t device, unsigned int* numCores) const; [[nodiscard]] virtual nvmlReturn_t DeviceGetBusType(nvmlDevice_t device, nvmlBusType_t* type) const; [[nodiscard]] virtual nvmlReturn_t DeviceGetDynamicPstatesInfo(nvmlDevice_t device, nvmlGpuDynamicPstatesInfo_t* pDynamicPstatesInfo) const; @@ -44,6 +45,7 @@ namespace dxvk { DECLARE_PFN(nvmlDeviceGetPerformanceState); DECLARE_PFN(nvmlDeviceGetUtilizationRates); DECLARE_PFN(nvmlDeviceGetVbiosVersion); + DECLARE_PFN(nvmlDeviceGetCurrPcieLinkWidth); DECLARE_PFN(nvmlDeviceGetNumGpuCores); DECLARE_PFN(nvmlDeviceGetBusType); DECLARE_PFN(nvmlDeviceGetDynamicPstatesInfo); diff --git a/tests/nvapi_sysinfo.cpp b/tests/nvapi_sysinfo.cpp index fbaad45..69b2aae 100644 --- a/tests/nvapi_sysinfo.cpp +++ b/tests/nvapi_sysinfo.cpp @@ -748,6 +748,23 @@ TEST_CASE("Sysinfo methods succeed", "[.sysinfo]") { .SIDE_EFFECT(*_2 = reinterpret_cast<nvmlDevice_t>(0x1234)) // Just a non-nullptr .RETURN(NVML_SUCCESS); + SECTION("GetCurrentPCIEDownstreamWidth returns OK") { + auto linkWidth = 16U; + ALLOW_CALL(*nvml, DeviceGetCurrPcieLinkWidth(_, _)) // NOLINT(bugprone-use-after-move) + .LR_SIDE_EFFECT(*_2 = linkWidth) + .RETURN(NVML_SUCCESS); + + SetupResourceFactory(std::move(dxgiFactory), std::move(vulkan), std::move(nvml), std::move(lfx)); + REQUIRE(NvAPI_Initialize() == NVAPI_OK); + + NvPhysicalGpuHandle handle; + REQUIRE(NvAPI_SYS_GetPhysicalGpuFromDisplayId(0, &handle) == NVAPI_OK); + + NvU32 width; + REQUIRE(NvAPI_GPU_GetCurrentPCIEDownstreamWidth(handle, &width) == NVAPI_OK); + REQUIRE(width == linkWidth); + } + SECTION("GetGpuCoreCount returns OK") { auto cores = 1536U; ALLOW_CALL(*nvml, DeviceGetNumGpuCores(_, _)) // NOLINT(bugprone-use-after-move) @@ -1159,6 +1176,8 @@ TEST_CASE("Sysinfo methods succeed", "[.sysinfo]") { } SECTION("NVML depending methods return no-implementation when NVML is not available") { + NvU32 width; + REQUIRE(NvAPI_GPU_GetCurrentPCIEDownstreamWidth(handle, &width) == NVAPI_NO_IMPLEMENTATION); NvU32 cores; REQUIRE(NvAPI_GPU_GetGpuCoreCount(handle, &cores) == NVAPI_NO_IMPLEMENTATION); NV_GPU_DYNAMIC_PSTATES_INFO_EX info; @@ -1197,6 +1216,8 @@ TEST_CASE("Sysinfo methods succeed", "[.sysinfo]") { } SECTION("NVML depending methods return handle-invalidated when NVML is available but without suitable adapter") { + NvU32 width; + REQUIRE(NvAPI_GPU_GetCurrentPCIEDownstreamWidth(handle, &width) == NVAPI_HANDLE_INVALIDATED); NvU32 cores; REQUIRE(NvAPI_GPU_GetGpuCoreCount(handle, &cores) == NVAPI_HANDLE_INVALIDATED); NV_GPU_DYNAMIC_PSTATES_INFO_EX info; diff --git a/tests/nvapi_sysinfo_mocks.h b/tests/nvapi_sysinfo_mocks.h index 2c85ee9..efb9bb3 100644 --- a/tests/nvapi_sysinfo_mocks.h +++ b/tests/nvapi_sysinfo_mocks.h @@ -79,6 +79,7 @@ class NvmlMock : public trompeloeil::mock_interface<dxvk::Nvml> { IMPLEMENT_CONST_MOCK2(DeviceGetPerformanceState); IMPLEMENT_CONST_MOCK2(DeviceGetUtilizationRates); IMPLEMENT_CONST_MOCK3(DeviceGetVbiosVersion); + IMPLEMENT_CONST_MOCK2(DeviceGetCurrPcieLinkWidth); IMPLEMENT_CONST_MOCK2(DeviceGetNumGpuCores); IMPLEMENT_CONST_MOCK2(DeviceGetBusType); IMPLEMENT_CONST_MOCK2(DeviceGetDynamicPstatesInfo); diff --git a/tests/nvapi_system.cpp b/tests/nvapi_system.cpp index 1d22964..a8ca983 100644 --- a/tests/nvapi_system.cpp +++ b/tests/nvapi_system.cpp @@ -95,6 +95,7 @@ TEST_CASE("Sysinfo methods succeed against local system", "[system]") { GETNVAPIPROCADDR(GPU_GetPhysicalFrameBufferSize); GETNVAPIPROCADDR(GPU_GetAdapterIdFromPhysicalGpu); GETNVAPIPROCADDR(GPU_GetArchInfo); + GETNVAPIPROCADDR(GPU_GetCurrentPCIEDownstreamWidth); GETNVAPIPROCADDR(GPU_GetGpuCoreCount); GETNVAPIPROCADDR(GPU_CudaEnumComputeCapableGpus); GETNVAPIPROCADDR(GPU_GetVbiosVersionString); @@ -119,6 +120,7 @@ TEST_CASE("Sysinfo methods succeed against local system", "[system]") { REQUIRE(nvAPI_GPU_GetPhysicalFrameBufferSize); REQUIRE(nvAPI_GPU_GetAdapterIdFromPhysicalGpu); REQUIRE(nvAPI_GPU_GetArchInfo); + REQUIRE(nvAPI_GPU_GetCurrentPCIEDownstreamWidth); REQUIRE(nvAPI_GPU_GetGpuCoreCount); REQUIRE(nvAPI_GPU_CudaEnumComputeCapableGpus); REQUIRE(nvAPI_GPU_GetVbiosVersionString); @@ -220,6 +222,14 @@ TEST_CASE("Sysinfo methods succeed against local system", "[system]") { else std::cout << "N/A" << std::endl; + NvU32 gpuPcieWidth; + result = nvAPI_GPU_GetCurrentPCIEDownstreamWidth(handle, &gpuPcieWidth); + std::cout << " Current PCIe link width: "; + if (result == NVAPI_OK) + std::cout << "x" << std::dec << gpuPcieWidth << std::endl; + else + std::cout << "N/A" << std::endl; + auto computeGpusIt = std::find_if( std::begin(computeGpus), std::end(computeGpus), |