diff --git a/src/nvapi_gpu.cpp b/src/nvapi_gpu.cpp index 14f4463c..0a7a6145 100644 --- a/src/nvapi_gpu.cpp +++ b/src/nvapi_gpu.cpp @@ -361,7 +361,7 @@ extern "C" { if (!nvapiAdapterRegistry->IsAdapter(adapter)) return ExpectedPhysicalGpuHandle(n); - *pSize = adapter->GetVRamSize() / 1024; + *pSize = adapter->GetVideoMemoryInfo().DedicatedVideoMemory / 1024; return Ok(n); } @@ -382,7 +382,7 @@ extern "C" { if (!nvapiAdapterRegistry->IsAdapter(adapter)) return ExpectedPhysicalGpuHandle(n); - *pSize = adapter->GetVirtualVRamSize() / 1024; + *pSize = (adapter->GetVideoMemoryInfo().DedicatedVideoMemory + adapter->GetVideoMemoryInfo().DedicatedSystemMemory) / 1024; return Ok(n); } @@ -404,31 +404,34 @@ extern "C" { if (!nvapiAdapterRegistry->IsAdapter(adapter)) return ExpectedPhysicalGpuHandle(n); + auto vidMemInfo = adapter->GetVideoMemoryInfo(); + auto curVidMemInfo = adapter->GetCurrentVideoMemoryInfo(); + switch (pMemoryInfo->version) { case NV_DISPLAY_DRIVER_MEMORY_INFO_VER_1: { auto pMemoryInfoV1 = reinterpret_cast(pMemoryInfo); - pMemoryInfoV1->dedicatedVideoMemory = adapter->GetVRamSize(); - pMemoryInfoV1->availableDedicatedVideoMemory = 0; // Not found in DXVK - pMemoryInfoV1->systemVideoMemory = adapter->GetDedicatedSystemRamSize(); - pMemoryInfoV1->sharedSystemMemory = adapter->GetSharedSystemRamSize(); + pMemoryInfoV1->dedicatedVideoMemory = vidMemInfo.DedicatedVideoMemory; + pMemoryInfoV1->availableDedicatedVideoMemory = curVidMemInfo.Budget; + pMemoryInfoV1->systemVideoMemory = vidMemInfo.DedicatedSystemMemory; + pMemoryInfoV1->sharedSystemMemory = vidMemInfo.SharedSystemMemory; break; } case NV_DISPLAY_DRIVER_MEMORY_INFO_VER_2: { auto pMemoryInfoV2 = reinterpret_cast(pMemoryInfo); - pMemoryInfoV2->dedicatedVideoMemory = adapter->GetVRamSize(); - pMemoryInfoV2->availableDedicatedVideoMemory = 0; // Not found in DXVK - pMemoryInfoV2->systemVideoMemory = adapter->GetDedicatedSystemRamSize(); - pMemoryInfoV2->sharedSystemMemory = adapter->GetSharedSystemRamSize(); - pMemoryInfoV2->curAvailableDedicatedVideoMemory = 0; // Not found in DXVK + pMemoryInfoV2->dedicatedVideoMemory = vidMemInfo.DedicatedVideoMemory; + pMemoryInfoV2->availableDedicatedVideoMemory = curVidMemInfo.Budget; + pMemoryInfoV2->systemVideoMemory = vidMemInfo.DedicatedSystemMemory; + pMemoryInfoV2->sharedSystemMemory = vidMemInfo.SharedSystemMemory; + pMemoryInfoV2->curAvailableDedicatedVideoMemory = curVidMemInfo.Budget - curVidMemInfo.CurrentUsage; break; } case NV_DISPLAY_DRIVER_MEMORY_INFO_VER_3: { auto pMemoryInfoV3 = reinterpret_cast(pMemoryInfo); - pMemoryInfoV3->dedicatedVideoMemory = adapter->GetVRamSize(); - pMemoryInfoV3->availableDedicatedVideoMemory = 0; // Not found in DXVK - pMemoryInfoV3->systemVideoMemory = adapter->GetDedicatedSystemRamSize(); - pMemoryInfoV3->sharedSystemMemory = adapter->GetSharedSystemRamSize(); - pMemoryInfoV3->curAvailableDedicatedVideoMemory = 0; // Not found in DXVK + pMemoryInfoV3->dedicatedVideoMemory = vidMemInfo.DedicatedVideoMemory; + pMemoryInfoV3->availableDedicatedVideoMemory = curVidMemInfo.Budget; + pMemoryInfoV3->systemVideoMemory = vidMemInfo.DedicatedSystemMemory; + pMemoryInfoV3->sharedSystemMemory = vidMemInfo.SharedSystemMemory; + pMemoryInfoV3->curAvailableDedicatedVideoMemory = curVidMemInfo.Budget - curVidMemInfo.CurrentUsage; pMemoryInfoV3->dedicatedVideoMemoryEvictionsSize = 0; pMemoryInfoV3->dedicatedVideoMemoryEvictionCount = 0; break; @@ -457,14 +460,17 @@ extern "C" { if (!nvapiAdapterRegistry->IsAdapter(adapter)) return ExpectedPhysicalGpuHandle(n); + auto vidMemInfo = adapter->GetVideoMemoryInfo(); + auto curVidMemInfo = adapter->GetCurrentVideoMemoryInfo(); + switch (pMemoryInfo->version) { case NV_GPU_MEMORY_INFO_EX_VER: { auto pMemoryInfoV1 = reinterpret_cast(pMemoryInfo); - pMemoryInfoV1->dedicatedVideoMemory = adapter->GetVRamSize(); - pMemoryInfoV1->availableDedicatedVideoMemory = 0; // Not found in DXVK - pMemoryInfoV1->systemVideoMemory = adapter->GetDedicatedSystemRamSize(); - pMemoryInfoV1->sharedSystemMemory = adapter->GetSharedSystemRamSize(); - pMemoryInfoV1->curAvailableDedicatedVideoMemory = 0; // Not found in DXVK + pMemoryInfoV1->dedicatedVideoMemory = vidMemInfo.DedicatedVideoMemory; + pMemoryInfoV1->availableDedicatedVideoMemory = curVidMemInfo.Budget; + pMemoryInfoV1->systemVideoMemory = vidMemInfo.DedicatedSystemMemory; + pMemoryInfoV1->sharedSystemMemory = vidMemInfo.SharedSystemMemory; + pMemoryInfoV1->curAvailableDedicatedVideoMemory = curVidMemInfo.Budget - curVidMemInfo.CurrentUsage; pMemoryInfoV1->dedicatedVideoMemoryEvictionsSize = 0; pMemoryInfoV1->dedicatedVideoMemoryEvictionCount = 0; pMemoryInfoV1->dedicatedVideoMemoryPromotionsSize = 0; diff --git a/src/sysinfo/nvapi_adapter.cpp b/src/sysinfo/nvapi_adapter.cpp index e5de5747..043c27ae 100644 --- a/src/sysinfo/nvapi_adapter.cpp +++ b/src/sysinfo/nvapi_adapter.cpp @@ -6,18 +6,28 @@ #include "../util/util_version.h" namespace dxvk { - NvapiAdapter::NvapiAdapter(Vulkan& vulkan, Nvml& nvml) - : m_vulkan(vulkan), m_nvml(nvml) {} + NvapiAdapter::NvapiAdapter(Vulkan& vulkan, Nvml& nvml, Com dxgiAdapter) + : m_vulkan(vulkan), m_nvml(nvml), m_dxgiAdapter(std::move(dxgiAdapter)) {} NvapiAdapter::~NvapiAdapter() = default; - bool NvapiAdapter::Initialize(Com& dxgiAdapter, uint32_t index, std::vector& outputs) { - if (FAILED(dxgiAdapter->GetDesc1(&m_dxgiDesc))) + bool NvapiAdapter::Initialize(uint32_t index, std::vector& outputs) { + DXGI_ADAPTER_DESC1 dxgiDesc{}; + if (FAILED(m_dxgiAdapter->GetDesc1(&dxgiDesc))) return false; // Should never happen since we already know that we are dealing with a recent DXVK version + // Report vendor / device IDs from DXVK to honor ID overrides + m_dxgiVendorId = dxgiDesc.VendorId; + m_dxgiDeviceId = dxgiDesc.DeviceId; + + // Report VRAM size from DXVK to honor memory overrides + m_videoMemoryInfo.DedicatedSystemMemory = dxgiDesc.DedicatedSystemMemory; + m_videoMemoryInfo.DedicatedVideoMemory = dxgiDesc.DedicatedVideoMemory; + m_videoMemoryInfo.SharedSystemMemory = dxgiDesc.SharedSystemMemory; + // Get the Vulkan handle from the DXGI adapter to get access to Vulkan device properties which has some information we want. Com dxgiVkInteropAdapter; - if (FAILED(dxgiAdapter->QueryInterface(IID_PPV_ARGS(&dxgiVkInteropAdapter)))) { + if (FAILED(m_dxgiAdapter->QueryInterface(IID_PPV_ARGS(&dxgiVkInteropAdapter)))) { log::info("Querying Vulkan handle from DXGI adapter failed, please ensure that DXVK's dxgi.dll is present"); return false; } @@ -84,7 +94,7 @@ namespace dxvk { return false; if ((HasNvProprietaryDriver() || HasNvkDriver()) - && m_dxgiDesc.VendorId != NvidiaPciVendorId + && dxgiDesc.VendorId != NvidiaPciVendorId && env::getEnvVariable("DXVK_ENABLE_NVAPI") != "1") return false; // DXVK NVAPI-hack is enabled, skip this adapter @@ -104,7 +114,7 @@ namespace dxvk { // Query all outputs from DXVK // Mosaic setup is not supported, thus one display output refers to one GPU Com dxgiOutput; - for (auto i = 0U; dxgiAdapter->EnumOutputs(i, &dxgiOutput) != DXGI_ERROR_NOT_FOUND; i++) { + for (auto i = 0U; m_dxgiAdapter->EnumOutputs(i, &dxgiOutput) != DXGI_ERROR_NOT_FOUND; i++) { auto nvapiOutput = new NvapiOutput(this, index, i); nvapiOutput->Initialize(dxgiOutput); outputs.push_back(nvapiOutput); @@ -163,13 +173,11 @@ namespace dxvk { } uint32_t NvapiAdapter::GetDeviceId() const { - // Report vendor / device IDs from DXVK to honor ID overrides - return (m_dxgiDesc.DeviceId << 16) | m_dxgiDesc.VendorId; + return (m_dxgiDeviceId << 16) | m_dxgiVendorId; } uint32_t NvapiAdapter::GetExternalDeviceId() const { - // Report device ID from DXVK to honor ID overrides - return m_dxgiDesc.DeviceId; + return m_dxgiDeviceId; } uint32_t NvapiAdapter::GetSubSystemId() const { @@ -201,24 +209,18 @@ namespace dxvk { | m_vkPciBusProperties.pciDevice; } - uint64_t NvapiAdapter::GetVRamSize() const { - // Report VRAM size from DXVK to honor memory overrides - return m_dxgiDesc.DedicatedVideoMemory; + const NvapiAdapter::VideoMemoryInfo& NvapiAdapter::GetVideoMemoryInfo() const { + return m_videoMemoryInfo; } - uint64_t NvapiAdapter::GetVirtualVRamSize() const { - // Report VRAM size from DXVK to honor memory overrides - return m_dxgiDesc.DedicatedVideoMemory + m_dxgiDesc.DedicatedSystemMemory; - } - - uint64_t NvapiAdapter::GetDedicatedSystemRamSize() const { - // Report dedicated system memory size from DXVK - return m_dxgiDesc.DedicatedSystemMemory; - } + NvapiAdapter::CurrentVideoMemoryInfo NvapiAdapter::GetCurrentVideoMemoryInfo() const { + DXGI_QUERY_VIDEO_MEMORY_INFO dxgiMemInfo{}; + if (FAILED(m_dxgiAdapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &dxgiMemInfo))) + return CurrentVideoMemoryInfo{}; - uint64_t NvapiAdapter::GetSharedSystemRamSize() const { - // Report shared system memory size from DXVK - return m_dxgiDesc.SharedSystemMemory; + return CurrentVideoMemoryInfo{ + dxgiMemInfo.Budget, + dxgiMemInfo.CurrentUsage}; } std::optional NvapiAdapter::GetLuid() const { diff --git a/src/sysinfo/nvapi_adapter.h b/src/sysinfo/nvapi_adapter.h index 6539a9d5..8a83ed9b 100644 --- a/src/sysinfo/nvapi_adapter.h +++ b/src/sysinfo/nvapi_adapter.h @@ -10,10 +10,20 @@ namespace dxvk { class NvapiAdapter { public: - explicit NvapiAdapter(Vulkan& vulkan, Nvml& nvml); + explicit NvapiAdapter(Vulkan& vulkan, Nvml& nvml, Com dxgiAdapter); ~NvapiAdapter(); - bool Initialize(Com& dxgiAdapter, uint32_t index, std::vector& outputs); + struct VideoMemoryInfo { + uint64_t DedicatedVideoMemory; + uint64_t DedicatedSystemMemory; + uint64_t SharedSystemMemory; + }; + struct CurrentVideoMemoryInfo { + uint64_t Budget; + uint64_t CurrentUsage; + }; + + bool Initialize(uint32_t index, std::vector& outputs); [[nodiscard]] std::string GetDeviceName() const; [[nodiscard]] bool HasNvProprietaryDriver() const; [[nodiscard]] bool HasNvkDriver() const; @@ -25,13 +35,10 @@ namespace dxvk { [[nodiscard]] uint32_t GetPciBusId() const; [[nodiscard]] uint32_t GetPciDeviceId() const; [[nodiscard]] uint32_t GetBoardId() const; - [[nodiscard]] uint64_t GetVRamSize() const; - [[nodiscard]] uint64_t GetVirtualVRamSize() const; - [[nodiscard]] uint64_t GetDedicatedSystemRamSize() const; - [[nodiscard]] uint64_t GetSharedSystemRamSize() const; [[nodiscard]] std::optional GetLuid() const; [[nodiscard]] NV_GPU_ARCHITECTURE_ID GetArchitectureId() const; - + [[nodiscard]] const VideoMemoryInfo& GetVideoMemoryInfo() const; + [[nodiscard]] CurrentVideoMemoryInfo GetCurrentVideoMemoryInfo() const; [[nodiscard]] bool HasNvml() const; [[nodiscard]] bool HasNvmlDevice() const; [[nodiscard]] std::string GetNvmlErrorString(nvmlReturn_t result) const; @@ -50,6 +57,7 @@ namespace dxvk { private: Vulkan& m_vulkan; Nvml& m_nvml; + Com m_dxgiAdapter; std::set m_vkExtensions; VkPhysicalDeviceProperties m_vkProperties{}; @@ -60,7 +68,9 @@ namespace dxvk { VkPhysicalDeviceFeatures m_vkFeatures{}; VkPhysicalDeviceDepthClipControlFeaturesEXT m_vkDepthClipControlFeatures{}; uint32_t m_vkDriverVersion{}; - DXGI_ADAPTER_DESC1 m_dxgiDesc{}; + uint32_t m_dxgiVendorId{}; + uint32_t m_dxgiDeviceId{}; + VideoMemoryInfo m_videoMemoryInfo{}; nvmlDevice_t m_nvmlDevice{}; diff --git a/src/sysinfo/nvapi_adapter_registry.cpp b/src/sysinfo/nvapi_adapter_registry.cpp index 8e6e74a4..932943c5 100644 --- a/src/sysinfo/nvapi_adapter_registry.cpp +++ b/src/sysinfo/nvapi_adapter_registry.cpp @@ -44,8 +44,12 @@ namespace dxvk { // Query all D3D11 adapter from DXVK to honor any DXVK device filtering Com dxgiAdapter; for (auto i = 0U; m_dxgiFactory->EnumAdapters1(i, &dxgiAdapter) != DXGI_ERROR_NOT_FOUND; i++) { - auto nvapiAdapter = new NvapiAdapter(*m_vulkan, *m_nvml); - if (nvapiAdapter->Initialize(dxgiAdapter, i, m_nvapiOutputs)) + Com dxgiAdapter3; + if (FAILED(dxgiAdapter->QueryInterface(IID_PPV_ARGS(&dxgiAdapter3)))) + continue; + + auto nvapiAdapter = new NvapiAdapter(*m_vulkan, *m_nvml, dxgiAdapter3); + if (nvapiAdapter->Initialize(i, m_nvapiOutputs)) m_nvapiAdapters.push_back(nvapiAdapter); else delete nvapiAdapter; diff --git a/tests/nvapi_system.cpp b/tests/nvapi_system.cpp index 565b5baf..40f75095 100644 --- a/tests/nvapi_system.cpp +++ b/tests/nvapi_system.cpp @@ -99,7 +99,7 @@ TEST_CASE("Sysinfo methods succeed against local system", "[system]") { GETNVAPIPROCADDR(GPU_GetPCIIdentifiers); GETNVAPIPROCADDR(GPU_GetBusId); GETNVAPIPROCADDR(GPU_GetBusSlotId); - GETNVAPIPROCADDR(GPU_GetPhysicalFrameBufferSize); + GETNVAPIPROCADDR(GPU_GetMemoryInfoEx); GETNVAPIPROCADDR(GPU_GetAdapterIdFromPhysicalGpu); GETNVAPIPROCADDR(GPU_GetArchInfo); GETNVAPIPROCADDR(GPU_GetCurrentPCIEDownstreamWidth); @@ -132,7 +132,7 @@ TEST_CASE("Sysinfo methods succeed against local system", "[system]") { REQUIRE(nvAPI_GPU_GetPCIIdentifiers); REQUIRE(nvAPI_GPU_GetBusId); REQUIRE(nvAPI_GPU_GetBusSlotId); - REQUIRE(nvAPI_GPU_GetPhysicalFrameBufferSize); + REQUIRE(nvAPI_GPU_GetMemoryInfoEx); REQUIRE(nvAPI_GPU_GetAdapterIdFromPhysicalGpu); REQUIRE(nvAPI_GPU_GetArchInfo); REQUIRE(nvAPI_GPU_GetCurrentPCIEDownstreamWidth); @@ -215,9 +215,14 @@ TEST_CASE("Sysinfo methods succeed against local system", "[system]") { REQUIRE(nvAPI_GetGPUIDfromPhysicalGPU(handle, &gpuId) == NVAPI_OK); std::cout << " Board ID: 0x" << std::hex << gpuId << std::endl; - NvU32 size; - REQUIRE(nvAPI_GPU_GetPhysicalFrameBufferSize(handle, &size) == NVAPI_OK); - std::cout << " Physical framebuffer size: " << std::dec << size / 1024 << "MB" << std::endl; + NV_GPU_MEMORY_INFO_EX memoryInfo; + memoryInfo.version = NV_GPU_MEMORY_INFO_EX_VER; + REQUIRE(nvAPI_GPU_GetMemoryInfoEx(handle, &memoryInfo) == NVAPI_OK); + std::cout << " Dedicated video memory: " << std::dec << memoryInfo.dedicatedVideoMemory / 1024 / 1024 << "MB" << std::endl; + std::cout << " Available dedicated v.m.: " << std::dec << memoryInfo.availableDedicatedVideoMemory / 1024 / 1024 << "MB" << std::endl; + std::cout << " System video memory: " << std::dec << memoryInfo.systemVideoMemory / 1024 / 1024 << "MB" << std::endl; + std::cout << " Shared system memory: " << std::dec << memoryInfo.sharedSystemMemory / 1024 / 1024 << "MB" << std::endl; + std::cout << " Cur. avail. dedicated v.m.: " << std::dec << memoryInfo.curAvailableDedicatedVideoMemory / 1024 / 1024 << "MB" << std::endl; LUID luid; result = nvAPI_GPU_GetAdapterIdFromPhysicalGpu(handle, static_cast(&luid));