Skip to content

Commit

Permalink
nvapi-gpu: Query variable memory info from DXGI (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
jp7677 committed Aug 15, 2024
1 parent 58477a6 commit b587d3c
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 62 deletions.
48 changes: 27 additions & 21 deletions src/nvapi_gpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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<NV_DISPLAY_DRIVER_MEMORY_INFO_V1*>(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<NV_DISPLAY_DRIVER_MEMORY_INFO_V2*>(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<NV_DISPLAY_DRIVER_MEMORY_INFO_V3*>(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;
Expand Down Expand Up @@ -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<NV_GPU_MEMORY_INFO_EX*>(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;
Expand Down
54 changes: 28 additions & 26 deletions src/sysinfo/nvapi_adapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<IDXGIAdapter3> dxgiAdapter)
: m_vulkan(vulkan), m_nvml(nvml), m_dxgiAdapter(std::move(dxgiAdapter)) {}

NvapiAdapter::~NvapiAdapter() = default;

bool NvapiAdapter::Initialize(Com<IDXGIAdapter1>& dxgiAdapter, uint32_t index, std::vector<NvapiOutput*>& outputs) {
if (FAILED(dxgiAdapter->GetDesc1(&m_dxgiDesc)))
bool NvapiAdapter::Initialize(uint32_t index, std::vector<NvapiOutput*>& 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<IDXGIVkInteropAdapter> 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;
}
Expand Down Expand Up @@ -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

Expand All @@ -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<IDXGIOutput> 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);
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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<LUID> NvapiAdapter::GetLuid() const {
Expand Down
26 changes: 18 additions & 8 deletions src/sysinfo/nvapi_adapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,20 @@ namespace dxvk {
class NvapiAdapter {

public:
explicit NvapiAdapter(Vulkan& vulkan, Nvml& nvml);
explicit NvapiAdapter(Vulkan& vulkan, Nvml& nvml, Com<IDXGIAdapter3> dxgiAdapter);
~NvapiAdapter();

bool Initialize(Com<IDXGIAdapter1>& dxgiAdapter, uint32_t index, std::vector<NvapiOutput*>& 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<NvapiOutput*>& outputs);
[[nodiscard]] std::string GetDeviceName() const;
[[nodiscard]] bool HasNvProprietaryDriver() const;
[[nodiscard]] bool HasNvkDriver() const;
Expand All @@ -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<LUID> 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;
Expand All @@ -50,6 +57,7 @@ namespace dxvk {
private:
Vulkan& m_vulkan;
Nvml& m_nvml;
Com<IDXGIAdapter3> m_dxgiAdapter;

std::set<std::string> m_vkExtensions;
VkPhysicalDeviceProperties m_vkProperties{};
Expand All @@ -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{};

Expand Down
8 changes: 6 additions & 2 deletions src/sysinfo/nvapi_adapter_registry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,12 @@ namespace dxvk {
// Query all D3D11 adapter from DXVK to honor any DXVK device filtering
Com<IDXGIAdapter1> 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<IDXGIAdapter3> 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;
Expand Down
15 changes: 10 additions & 5 deletions tests/nvapi_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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<void*>(&luid));
Expand Down

0 comments on commit b587d3c

Please sign in to comment.