Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/jp7677/dxvk-nvapi.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Peters <jp7677@gmail.com>2022-08-28 11:25:38 +0300
committerJens Peters <jp7677@gmail.com>2022-08-28 14:27:47 +0300
commit42ad10b8418d986f74759e31ffaab34bc1ecabac (patch)
tree0854a01fd4f313bcb1b11dfedf9d31f1d8ac2116
parentfa9a2c4346edaf1cf75165cd3c3ac0d0e2850a8f (diff)
nvapi-gpu: Implement GetCurrentPCIEDownstreamWidth using nvml
-rw-r--r--src/nvapi_gpu.cpp39
-rw-r--r--src/nvapi_interface.cpp1
-rw-r--r--src/sysinfo/nvapi_adapter.cpp4
-rw-r--r--src/sysinfo/nvapi_adapter.h1
-rw-r--r--src/sysinfo/nvml.cpp7
-rw-r--r--src/sysinfo/nvml.h2
-rw-r--r--tests/nvapi_sysinfo.cpp21
-rw-r--r--tests/nvapi_sysinfo_mocks.h1
-rw-r--r--tests/nvapi_system.cpp10
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),