Skip to content

Commit

Permalink
"nriQueryVideoMemoryInfo" improvements:
Browse files Browse the repository at this point in the history
- NRI: removed reservation info because it's not available in VK
- NRI: "QueryVideoMemoryInfo" moved to Helper interface (device specific, validation dependent)
- VK: implemented via "VK_EXT_memory_budget"
  • Loading branch information
dzhdanNV committed Jul 15, 2024
1 parent bc1e896 commit b5a2e90
Show file tree
Hide file tree
Showing 13 changed files with 114 additions and 51 deletions.
16 changes: 7 additions & 9 deletions Include/Extensions/NRIHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ NRI_NAMESPACE_BEGIN

NRI_STRUCT(VideoMemoryInfo)
{
uint64_t budget;
uint64_t currentUsage;
uint64_t availableForReservation;
uint64_t currentReservation;
uint64_t budgetSize; // the OS-provided video memory budget. If "usageSize" > "budgetSize", the application may incur stuttering or performance penalties
uint64_t usageSize; // specifies the application’s current video memory usage
};

NRI_STRUCT(TextureSubresourceUploadDesc)
Expand Down Expand Up @@ -73,18 +71,18 @@ NRI_STRUCT(FormatProps)
NRI_STRUCT(HelperInterface)
{
// Optimized memory allocation for a group of resources
uint32_t (NRI_CALL *CalculateAllocationNumber)(NRI_NAME_REF(Device) device, const NRI_NAME_REF(ResourceGroupDesc) resourceGroupDesc);
uint32_t (NRI_CALL *CalculateAllocationNumber)(const NRI_NAME_REF(Device) device, const NRI_NAME_REF(ResourceGroupDesc) resourceGroupDesc);
NRI_NAME(Result) (NRI_CALL *AllocateAndBindMemory)(NRI_NAME_REF(Device) device, const NRI_NAME_REF(ResourceGroupDesc) resourceGroupDesc, NRI_NAME(Memory)** allocations);

// Populate resources with data (not for streaming data)
// Populate resources with data (not for streaming!)
NRI_NAME(Result) (NRI_CALL *UploadData)(NRI_NAME_REF(CommandQueue) commandQueue, const NRI_NAME(TextureUploadDesc)* textureUploadDescs, uint32_t textureUploadDescNum, const NRI_NAME(BufferUploadDesc)* bufferUploadDescs, uint32_t bufferUploadDescNum);

// WFI
NRI_NAME(Result) (NRI_CALL *WaitForIdle)(NRI_NAME_REF(CommandQueue) commandQueue);
};

// Information about video memory
NRI_API bool NRI_CALL nriQueryVideoMemoryInfo(const NRI_NAME_REF(Device) device, NRI_NAME(MemoryLocation) memoryLocation, NRI_NAME_REF(VideoMemoryInfo) videoMemoryInfo);
// Information about video memory
NRI_NAME(Result) (NRI_CALL *QueryVideoMemoryInfo)(const NRI_NAME_REF(Device) device, NRI_NAME(MemoryLocation) memoryLocation, NRI_NAME_REF(VideoMemoryInfo) videoMemoryInfo);
};

// Format utilities
NRI_API NRI_NAME(Format) NRI_CALL nriConvertDXGIFormatToNRI(uint32_t dxgiFormat);
Expand Down
33 changes: 1 addition & 32 deletions Source/Creation/Creation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Result CreateDeviceD3D12(const DeviceCreationD3D12Desc& deviceCreationDesc, Devi
#if NRI_USE_VULKAN
Result CreateDeviceVK(const DeviceCreationDesc& deviceCreationDesc, DeviceBase*& device);
Result CreateDeviceVK(const DeviceCreationVKDesc& deviceDesc, DeviceBase*& device);
bool QueryVideoMemoryInfoVK(const Device& device, VideoMemoryInfo& videoMemoryInfo);
#endif

DeviceBase* CreateDeviceValidation(const DeviceCreationDesc& deviceCreationDesc, DeviceBase& device);
Expand Down Expand Up @@ -334,29 +335,6 @@ NRI_API Result NRI_CALL nriEnumerateAdapters(AdapterDesc* adapterDescs, uint32_t
return Result::SUCCESS;
}

NRI_API bool NRI_CALL nriQueryVideoMemoryInfo(const Device& device, MemoryLocation memoryLocation, VideoMemoryInfo& videoMemoryInfo) {
uint64_t luid = ((DeviceBase&)device).GetDesc().adapterDesc.luid;

ComPtr<IDXGIFactory4> dxgifactory;
if (FAILED(CreateDXGIFactory2(0, IID_PPV_ARGS(&dxgifactory))))
return false;

ComPtr<IDXGIAdapter3> adapter;
if (FAILED(dxgifactory->EnumAdapterByLuid(*(LUID*)&luid, IID_PPV_ARGS(&adapter))))
return false;

DXGI_QUERY_VIDEO_MEMORY_INFO info = {};
if (FAILED(adapter->QueryVideoMemoryInfo(0,
(memoryLocation == MemoryLocation::DEVICE || memoryLocation == MemoryLocation::DEVICE_UPLOAD) ? DXGI_MEMORY_SEGMENT_GROUP_LOCAL : DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL,
&info)))
return false;

static_assert(sizeof(VideoMemoryInfo) == sizeof(DXGI_QUERY_VIDEO_MEMORY_INFO));
memcpy(&videoMemoryInfo, &info, sizeof(info));

return true;
}

NRI_API void NRI_CALL nriReportLiveObjects() {
ComPtr<IDXGIDebug1> pDebug;
HRESULT hr = DXGIGetDebugInterface1(0, IID_PPV_ARGS(&pDebug));
Expand Down Expand Up @@ -488,15 +466,6 @@ NRI_API Result NRI_CALL nriEnumerateAdapters(AdapterDesc* adapterDescs, uint32_t
return nriResult;
}

NRI_API bool NRI_CALL nriQueryVideoMemoryInfo(const Device& device, MemoryLocation memoryLocation, VideoMemoryInfo& videoMemoryInfo) {
MaybeUnused(device);
MaybeUnused(memoryLocation);
MaybeUnused(videoMemoryInfo);

// TODO: use VK_EXT_memory_budget
return false;
}

NRI_API void NRI_CALL nriReportLiveObjects() {
}

Expand Down
11 changes: 9 additions & 2 deletions Source/D3D11/DeviceD3D11.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,18 +290,25 @@ Result DeviceD3D11::FillFunctionTable(SwapChainInterface& swapChainInterface) co

#pragma region[ Helper ]

static uint32_t NRI_CALL CountAllocationNum(Device& device, const ResourceGroupDesc& resourceGroupDesc) {
static uint32_t NRI_CALL CalculateAllocationNumber(const Device& device, const ResourceGroupDesc& resourceGroupDesc) {
return ((DeviceD3D11&)device).CalculateAllocationNumber(resourceGroupDesc);
}

static Result NRI_CALL AllocateAndBindMemory(Device& device, const ResourceGroupDesc& resourceGroupDesc, Memory** allocations) {
return ((DeviceD3D11&)device).AllocateAndBindMemory(resourceGroupDesc, allocations);
}

static Result NRI_CALL QueryVideoMemoryInfo(const Device& device, MemoryLocation memoryLocation, VideoMemoryInfo& videoMemoryInfo) {
uint64_t luid = ((DeviceD3D11&)device).GetDesc().adapterDesc.luid;

return QueryVideoMemoryInfoDXGI(luid, memoryLocation, videoMemoryInfo);
}

Result DeviceD3D11::FillFunctionTable(HelperInterface& helperInterface) const {
helperInterface = {};
helperInterface.CalculateAllocationNumber = ::CountAllocationNum;
helperInterface.CalculateAllocationNumber = ::CalculateAllocationNumber;
helperInterface.AllocateAndBindMemory = ::AllocateAndBindMemory;
helperInterface.QueryVideoMemoryInfo = ::QueryVideoMemoryInfo;

Helper_CommandQueue_PartiallyFillFunctionTableD3D11(helperInterface);

Expand Down
11 changes: 9 additions & 2 deletions Source/D3D12/DeviceD3D12.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,18 +258,25 @@ Result DeviceD3D12::FillFunctionTable(CoreInterface& coreInterface) const {

#pragma region[ Helper ]

static uint32_t NRI_CALL CountAllocationNum(Device& device, const ResourceGroupDesc& resourceGroupDesc) {
static uint32_t NRI_CALL CalculateAllocationNumber(const Device& device, const ResourceGroupDesc& resourceGroupDesc) {
return ((DeviceD3D12&)device).CalculateAllocationNumber(resourceGroupDesc);
}

static Result NRI_CALL AllocateAndBindMemory(Device& device, const ResourceGroupDesc& resourceGroupDesc, Memory** allocations) {
return ((DeviceD3D12&)device).AllocateAndBindMemory(resourceGroupDesc, allocations);
}

static Result NRI_CALL QueryVideoMemoryInfo(const Device& device, MemoryLocation memoryLocation, VideoMemoryInfo& videoMemoryInfo) {
uint64_t luid = ((DeviceD3D12&)device).GetDesc().adapterDesc.luid;

return QueryVideoMemoryInfoDXGI(luid, memoryLocation, videoMemoryInfo);
}

Result DeviceD3D12::FillFunctionTable(HelperInterface& helperInterface) const {
helperInterface = {};
helperInterface.CalculateAllocationNumber = ::CountAllocationNum;
helperInterface.CalculateAllocationNumber = ::CalculateAllocationNumber;
helperInterface.AllocateAndBindMemory = ::AllocateAndBindMemory;
helperInterface.QueryVideoMemoryInfo = ::QueryVideoMemoryInfo;

Helper_CommandQueue_PartiallyFillFunctionTableD3D12(helperInterface);

Expand Down
23 changes: 23 additions & 0 deletions Source/Shared/SharedExternal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,29 @@ bool HasOutput() {
return false;
}

nri::Result QueryVideoMemoryInfoDXGI(uint64_t luid, nri::MemoryLocation memoryLocation, nri::VideoMemoryInfo& videoMemoryInfo) {
videoMemoryInfo = {};

ComPtr<IDXGIFactory4> dxgifactory;
if (FAILED(CreateDXGIFactory2(0, IID_PPV_ARGS(&dxgifactory))))
return nri::Result::FAILURE;

ComPtr<IDXGIAdapter3> adapter;
if (FAILED(dxgifactory->EnumAdapterByLuid(*(LUID*)&luid, IID_PPV_ARGS(&adapter))))
return nri::Result::FAILURE;

bool isLocal = memoryLocation == nri::MemoryLocation::DEVICE || memoryLocation == nri::MemoryLocation::DEVICE_UPLOAD;

DXGI_QUERY_VIDEO_MEMORY_INFO info = {};
if (FAILED(adapter->QueryVideoMemoryInfo(0, isLocal ? DXGI_MEMORY_SEGMENT_GROUP_LOCAL : DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, &info)))
return nri::Result::FAILURE;

videoMemoryInfo.budgetSize = info.Budget;
videoMemoryInfo.usageSize = info.CurrentUsage;

return nri::Result::SUCCESS;
}

#else

uint32_t NRIFormatToDXGIFormat(nri::Format format) {
Expand Down
1 change: 1 addition & 0 deletions Source/Shared/SharedExternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ struct ComPtr {
};

bool HasOutput();
nri::Result QueryVideoMemoryInfoDXGI(uint64_t luid, nri::MemoryLocation memoryLocation, nri::VideoMemoryInfo& videoMemoryInfo);

struct DisplayDescHelper {
public:
Expand Down
42 changes: 42 additions & 0 deletions Source/VK/DeviceVK.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,9 @@ void DeviceVK::ProcessDeviceExtensions(Vector<const char*>& desiredDeviceExts, b
if (IsExtensionSupported(VK_EXT_SHADER_ATOMIC_FLOAT_2_EXTENSION_NAME, supportedExts))
desiredDeviceExts.push_back(VK_EXT_SHADER_ATOMIC_FLOAT_2_EXTENSION_NAME);

if (IsExtensionSupported(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME, supportedExts))
desiredDeviceExts.push_back(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME);

// Optional
if (IsExtensionSupported(VK_NV_LOW_LATENCY_2_EXTENSION_NAME, supportedExts))
desiredDeviceExts.push_back(VK_NV_LOW_LATENCY_2_EXTENSION_NAME);
Expand Down Expand Up @@ -567,6 +570,9 @@ Result DeviceVK::Create(const DeviceCreationDesc& deviceCreationDesc, const Devi
APPEND_EXT(shaderAtomicFloat2Features);
}

if (IsExtensionSupported(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME, desiredDeviceExts))
m_IsMemoryBudgetSupported = true;

m_VK.GetPhysicalDeviceFeatures2(m_PhysicalDevice, &features);

{ // Create device
Expand Down Expand Up @@ -1269,6 +1275,7 @@ Result DeviceVK::ResolveInstanceDispatchTable(const Vector<const char*>& desired
GET_INSTANCE_PROC(DestroyInstance);
GET_INSTANCE_PROC(DestroyDevice);
GET_INSTANCE_PROC(GetPhysicalDeviceMemoryProperties);
GET_INSTANCE_PROC(GetPhysicalDeviceMemoryProperties2);
GET_INSTANCE_PROC(GetDeviceGroupPeerMemoryFeatures);
GET_INSTANCE_PROC(GetPhysicalDeviceFormatProperties);
GET_INSTANCE_PROC(CreateDevice);
Expand Down Expand Up @@ -1832,4 +1839,39 @@ inline Result DeviceVK::AllocateAndBindMemory(const ResourceGroupDesc& resourceG
return allocator.AllocateAndBindMemory(resourceGroupDesc, allocations);
}

Result DeviceVK::QueryVideoMemoryInfo(MemoryLocation memoryLocation, VideoMemoryInfo& videoMemoryInfo) const {
videoMemoryInfo = {};

if (!m_IsMemoryBudgetSupported)
return Result::UNSUPPORTED;

VkPhysicalDeviceMemoryBudgetPropertiesEXT budgetProps = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT};

VkPhysicalDeviceMemoryProperties2 memoryProps = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2};
memoryProps.pNext = &budgetProps;

const auto& vk = GetDispatchTable();
vk.GetPhysicalDeviceMemoryProperties2(m_PhysicalDevice, &memoryProps);

bool isLocal = memoryLocation == nri::MemoryLocation::DEVICE || memoryLocation == nri::MemoryLocation::DEVICE_UPLOAD;

for (uint32_t i = 0; i < GetCountOf(budgetProps.heapBudget); i++) {
VkDeviceSize size = budgetProps.heapBudget[i];
bool state = m_MemoryProps.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;

if (size && state == isLocal)
videoMemoryInfo.budgetSize += size;
}

for (uint32_t i = 0; i < GetCountOf(budgetProps.heapUsage); i++) {
VkDeviceSize size = budgetProps.heapUsage[i];
bool state = m_MemoryProps.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;

if (size && state == isLocal)
videoMemoryInfo.usageSize += size;
}

return Result::SUCCESS;
}

#include "DeviceVK.hpp"
4 changes: 2 additions & 2 deletions Source/VK/DeviceVK.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

#pragma once

struct IDXGIAdapter;

namespace nri {

struct CommandQueueVK;
Expand Down Expand Up @@ -114,6 +112,7 @@ struct DeviceVK final : public DeviceBase {
FormatSupportBits GetFormatSupport(Format format) const;
uint32_t CalculateAllocationNumber(const ResourceGroupDesc& resourceGroupDesc) const;
Result AllocateAndBindMemory(const ResourceGroupDesc& resourceGroupDesc, Memory** allocations);
Result QueryVideoMemoryInfo(MemoryLocation memoryLocation, VideoMemoryInfo& videoMemoryInfo) const;

//================================================================================================================
// DeviceBase
Expand Down Expand Up @@ -156,6 +155,7 @@ struct DeviceVK final : public DeviceBase {
bool m_IsPresentIdSupported = false;
bool m_IsPresentWaitSupported = false;
bool m_IsLowLatencySupported = false;
bool m_IsMemoryBudgetSupported = false;

private:
Vector<uint32_t> m_ConcurrentSharingModeQueueIndices;
Expand Down
9 changes: 7 additions & 2 deletions Source/VK/DeviceVK.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,18 +415,23 @@ Result DeviceVK::FillFunctionTable(MeshShaderInterface& meshShaderInterface) con

#pragma region[ Helper ]

static uint32_t NRI_CALL CountAllocationNum(Device& device, const ResourceGroupDesc& resourceGroupDesc) {
static uint32_t NRI_CALL CalculateAllocationNumber(const Device& device, const ResourceGroupDesc& resourceGroupDesc) {
return ((DeviceVK&)device).CalculateAllocationNumber(resourceGroupDesc);
}

static Result NRI_CALL AllocateAndBindMemory(Device& device, const ResourceGroupDesc& resourceGroupDesc, Memory** allocations) {
return ((DeviceVK&)device).AllocateAndBindMemory(resourceGroupDesc, allocations);
}

static Result NRI_CALL QueryVideoMemoryInfo(const Device& device, MemoryLocation memoryLocation, VideoMemoryInfo& videoMemoryInfo) {
return ((DeviceVK&)device).QueryVideoMemoryInfo(memoryLocation, videoMemoryInfo);
}

Result DeviceVK::FillFunctionTable(HelperInterface& helperInterface) const {
helperInterface = {};
helperInterface.CalculateAllocationNumber = ::CountAllocationNum;
helperInterface.CalculateAllocationNumber = ::CalculateAllocationNumber;
helperInterface.AllocateAndBindMemory = ::AllocateAndBindMemory;
helperInterface.QueryVideoMemoryInfo = ::QueryVideoMemoryInfo;

Helper_CommandQueue_PartiallyFillFunctionTableVK(helperInterface);

Expand Down
1 change: 1 addition & 0 deletions Source/VK/DispatchTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ struct DispatchTable {
VULKAN_FUNCTION(DestroyInstance);
VULKAN_FUNCTION(DestroyDevice);
VULKAN_FUNCTION(GetPhysicalDeviceMemoryProperties);
VULKAN_FUNCTION(GetPhysicalDeviceMemoryProperties2);
VULKAN_FUNCTION(GetDeviceGroupPeerMemoryFeatures);
VULKAN_FUNCTION(GetPhysicalDeviceFormatProperties);
VULKAN_FUNCTION(CreateDevice);
Expand Down
4 changes: 4 additions & 0 deletions Source/Validation/DeviceVal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1168,6 +1168,10 @@ Result DeviceVal::AllocateAndBindMemory(const ResourceGroupDesc& resourceGroupDe
return result;
}

Result DeviceVal::QueryVideoMemoryInfo(MemoryLocation memoryLocation, VideoMemoryInfo& videoMemoryInfo) const {
return m_HelperAPI.QueryVideoMemoryInfo(m_Device, memoryLocation, videoMemoryInfo);
}

Result DeviceVal::CreateRayTracingPipeline(const RayTracingPipelineDesc& pipelineDesc, Pipeline*& pipeline) {
RETURN_ON_FAILURE(this, pipelineDesc.pipelineLayout != nullptr, Result::INVALID_ARGUMENT, "CreateRayTracingPipeline: 'pipelineDesc.pipelineLayout' is NULL");
RETURN_ON_FAILURE(this, pipelineDesc.shaderLibrary != nullptr, Result::INVALID_ARGUMENT, "CreateRayTracingPipeline: 'pipelineDesc.shaderLibrary' is NULL");
Expand Down
1 change: 1 addition & 0 deletions Source/Validation/DeviceVal.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ struct DeviceVal final : public DeviceBase {

uint32_t CalculateAllocationNumber(const ResourceGroupDesc& resourceGroupDesc) const;
Result AllocateAndBindMemory(const ResourceGroupDesc& resourceGroupDesc, Memory** allocations);
Result QueryVideoMemoryInfo(MemoryLocation memoryLocation, VideoMemoryInfo& videoMemoryInfo) const;

//================================================================================================================
// DeviceBase
Expand Down
9 changes: 7 additions & 2 deletions Source/Validation/DeviceVal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,18 +287,23 @@ Result DeviceVal::FillFunctionTable(WrapperD3D11Interface& wrapperD3D11Interface

#pragma region[ Helper ]

static uint32_t NRI_CALL CountAllocationNum(Device& device, const ResourceGroupDesc& resourceGroupDesc) {
static uint32_t NRI_CALL CalculateAllocationNumber(const Device& device, const ResourceGroupDesc& resourceGroupDesc) {
return ((DeviceVal&)device).CalculateAllocationNumber(resourceGroupDesc);
}

static Result NRI_CALL AllocateAndBindMemory(Device& device, const ResourceGroupDesc& resourceGroupDesc, Memory** allocations) {
return ((DeviceVal&)device).AllocateAndBindMemory(resourceGroupDesc, allocations);
}

static Result NRI_CALL QueryVideoMemoryInfo(const Device& device, MemoryLocation memoryLocation, VideoMemoryInfo& videoMemoryInfo) {
return ((DeviceVal&)device).QueryVideoMemoryInfo(memoryLocation, videoMemoryInfo);
}

Result DeviceVal::FillFunctionTable(HelperInterface& helperInterface) const {
helperInterface = {};
helperInterface.CalculateAllocationNumber = ::CountAllocationNum;
helperInterface.CalculateAllocationNumber = ::CalculateAllocationNumber;
helperInterface.AllocateAndBindMemory = ::AllocateAndBindMemory;
helperInterface.QueryVideoMemoryInfo = ::QueryVideoMemoryInfo;

Helper_CommandQueue_PartiallyFillFunctionTableVal(helperInterface);

Expand Down

0 comments on commit b5a2e90

Please sign in to comment.