Skip to content

Commit

Permalink
v1.139:
Browse files Browse the repository at this point in the history
HIGHLIGHTS:
- Helper: exposed "ResourceGroupDesc::preferredMemorySize" to define desired memory chunk size (256 Mb if 0)
- bug fixes and improvements

DETAILS:
- Helper: added ability to provide preferred memory chunk size
- bug fixes and improvements
- updated Vulkan headers to v1.3.290
- updated comments
  • Loading branch information
dzhdanNV committed Aug 1, 2024
1 parent 6b9ecf8 commit ad030e9
Show file tree
Hide file tree
Showing 19 changed files with 166 additions and 155 deletions.
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[submodule "External/vulkan"]
path = External/vulkan
url = https://github.com/KhronosGroup/Vulkan-Headers.git
branch = origin/vulkan-sdk-1.3.283
branch = origin/vulkan-sdk-1.3.290
update = merge
[submodule "External/nvapi"]
path = External/nvapi
Expand Down
1 change: 1 addition & 0 deletions Include/Extensions/NRIHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ NRI_STRUCT(ResourceGroupDesc)
uint32_t textureNum;
NRI_NAME(Buffer)* const* buffers;
uint32_t bufferNum;
uint64_t preferredMemorySize; // desired chunk size (but can be greater if a resource doesn't fit), 256 Mb if 0
};

NRI_STRUCT(FormatProps)
Expand Down
8 changes: 6 additions & 2 deletions Include/NRI.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ Non-goals:
#include <stddef.h>

#define NRI_VERSION_MAJOR 1
#define NRI_VERSION_MINOR 138
#define NRI_VERSION_DATE "22 July 2024"
#define NRI_VERSION_MINOR 139
#define NRI_VERSION_DATE "31 July 2024"

#ifdef _WIN32
#define NRI_CALL __fastcall
Expand Down Expand Up @@ -90,6 +90,10 @@ NRI_STRUCT(CoreInterface)
void (NRI_CALL *DestroyFence)(NRI_NAME_REF(Fence) fence);

// Memory
// - use "GetBufferMemoryDesc" (or "GetTextureMemoryDesc") to get "MemoryDesc" ("usageBits" and "MemoryLocation" affect returned "MemoryType")
// - (optional) group returned "MemoryDesc"s by "MemoryType", but do not group if "mustBeDedicated = true"
// - call "BindBufferMemory" (or "BindTextureMemory") to bind resources to "Memory" objects
// => "CalculateAllocationNumber" and "AllocateAndBindMemory" simplify this process for static allocations
NRI_NAME(Result) (NRI_CALL *AllocateMemory)(NRI_NAME_REF(Device) device, NRI_NAME(MemoryType) memoryType, uint64_t size, NRI_NAME_REF(Memory*) memory);
NRI_NAME(Result) (NRI_CALL *BindBufferMemory)(NRI_NAME_REF(Device) device, const NRI_NAME(BufferMemoryBindingDesc)* memoryBindingDescs, uint32_t memoryBindingDescNum);
NRI_NAME(Result) (NRI_CALL *BindTextureMemory)(NRI_NAME_REF(Device) device, const NRI_NAME(TextureMemoryBindingDesc)* memoryBindingDescs, uint32_t memoryBindingDescNum);
Expand Down
16 changes: 8 additions & 8 deletions Include/NRIDescs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1212,6 +1212,14 @@ NRI_STRUCT(QueueSubmitDesc)
};

// Memory
NRI_STRUCT(MemoryDesc)
{
uint64_t size;
uint32_t alignment;
NRI_NAME(MemoryType) type;
bool mustBeDedicated;
};

NRI_STRUCT(BufferMemoryBindingDesc)
{
NRI_NAME(Memory)* memory;
Expand All @@ -1226,14 +1234,6 @@ NRI_STRUCT(TextureMemoryBindingDesc)
uint64_t offset;
};

NRI_STRUCT(MemoryDesc)
{
uint64_t size;
uint32_t alignment;
NRI_NAME(MemoryType) type;
bool mustBeDedicated;
};

// Clear storage
NRI_STRUCT(ClearStorageBufferDesc)
{
Expand Down
2 changes: 1 addition & 1 deletion Resources/Version.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#define STR(x) STR_HELPER(x)

#define VERSION_MAJOR 1
#define VERSION_MINOR 138
#define VERSION_MINOR 139
#define VERSION_BUILD 0
#define VERSION_REVISION 0

Expand Down
2 changes: 1 addition & 1 deletion Source/D3D11/PipelineD3D11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ Result PipelineD3D11::Create(const GraphicsPipelineDesc& pipelineDesc) {
m_InputAssemplyStrides[stream.bindingSlot] = stream.stride;
};

assert(vertexShader != nullptr);
CHECK(vertexShader != nullptr, "VS can't be NULL");
hr = m_Device->CreateInputLayout(&inputElements[0], vi.attributeNum, vertexShader->bytecode, (size_t)vertexShader->size, &m_InputLayout);
RETURN_ON_BAD_HRESULT(&m_Device, hr, "ID3D11Device::CreateInputLayout()");
}
Expand Down
6 changes: 3 additions & 3 deletions Source/D3D12/DeviceD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ static uint8_t QueryLatestDevice(ComPtr<ID3D12DeviceBest>& in, ComPtr<ID3D12Devi
}

static inline uint64_t HashRootSignatureAndStride(ID3D12RootSignature* rootSignature, uint32_t stride) {
assert(stride < 4096);
CHECK(stride < 4096, "Only stride < 4096 supported by encoding");
return ((uint64_t)stride << 52ull) | ((uint64_t)rootSignature & ((1ull << 52) - 1));
}

Expand Down Expand Up @@ -686,7 +686,7 @@ void DeviceD3D12::GetMemoryDesc(MemoryLocation memoryLocation, const D3D12_RESOU
D3D12_RESOURCE_ALLOCATION_INFO resourceAllocationInfo = m_Device->GetResourceAllocationInfo(NRI_NODE_MASK, 1, &resourceDesc);
MemoryType memoryType = ConstructMemoryType(heapType, heapFlags);

memoryDesc.size = (uint64_t)resourceAllocationInfo.SizeInBytes;
memoryDesc.size = resourceAllocationInfo.SizeInBytes;
memoryDesc.alignment = (uint32_t)resourceAllocationInfo.Alignment;
memoryDesc.type = memoryType;
memoryDesc.mustBeDedicated = IsDedicated(memoryType);
Expand Down Expand Up @@ -949,7 +949,7 @@ inline void DeviceD3D12::DestroyQueryPool(QueryPool& queryPool) {
Deallocate(GetStdAllocator(), (QueryPoolD3D12*)&queryPool);
}

inline Result DeviceD3D12::AllocateMemory(const MemoryType memoryType, uint64_t size, Memory*& memory) {
inline Result DeviceD3D12::AllocateMemory(MemoryType memoryType, uint64_t size, Memory*& memory) {
return CreateImplementation<MemoryD3D12>(memory, memoryType, size);
}

Expand Down
2 changes: 1 addition & 1 deletion Source/D3D12/DeviceD3D12.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ struct DeviceD3D12 final : public DeviceBase {
void DestroyPipeline(Pipeline& pipeline);
void DestroyFence(Fence& queueSemaphore);
void DestroyQueryPool(QueryPool& queryPool);
Result AllocateMemory(const MemoryType memoryType, uint64_t size, Memory*& memory);
Result AllocateMemory(MemoryType memoryType, uint64_t size, Memory*& memory);
Result BindBufferMemory(const BufferMemoryBindingDesc* memoryBindingDescs, uint32_t memoryBindingDescNum);
Result BindTextureMemory(const TextureMemoryBindingDesc* memoryBindingDescs, uint32_t memoryBindingDescNum);
void FreeMemory(Memory& memory);
Expand Down
2 changes: 1 addition & 1 deletion Source/D3D12/MemoryD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ static inline D3D12_HEAP_TYPE GetHeapType(MemoryType memoryType) {
return (D3D12_HEAP_TYPE)(memoryType >> 16);
}

Result MemoryD3D12::Create(const MemoryType memoryType, uint64_t size) {
Result MemoryD3D12::Create(MemoryType memoryType, uint64_t size) {
D3D12_HEAP_DESC heapDesc = {};
heapDesc.SizeInBytes = size;
heapDesc.Properties.Type = GetHeapType(memoryType);
Expand Down
2 changes: 1 addition & 1 deletion Source/D3D12/MemoryD3D12.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ struct MemoryD3D12 {
return m_Device;
}

Result Create(const MemoryType memoryType, uint64_t size);
Result Create(MemoryType memoryType, uint64_t size);
Result Create(const MemoryD3D12Desc& memoryDesc);

//================================================================================================================
Expand Down
132 changes: 65 additions & 67 deletions Source/Shared/HelperDeviceMemoryAllocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,31 @@

using namespace nri;

HelperDeviceMemoryAllocator::MemoryTypeGroup::MemoryTypeGroup(const StdAllocator<uint8_t>& stdAllocator) :
buffers(stdAllocator), bufferOffsets(stdAllocator), textures(stdAllocator), textureOffsets(stdAllocator), memoryOffset(0) {
HelperDeviceMemoryAllocator::MemoryHeap::MemoryHeap(MemoryType memoryType, const StdAllocator<uint8_t>& stdAllocator) :
buffers(stdAllocator), bufferOffsets(stdAllocator), textures(stdAllocator), textureOffsets(stdAllocator), size(0), type(memoryType) {
}

HelperDeviceMemoryAllocator::HelperDeviceMemoryAllocator(const CoreInterface& NRI, Device& device) :
m_NRI(NRI),
m_Device(device),
m_Map(((DeviceBase&)device).GetStdAllocator()),
m_Heaps(((DeviceBase&)device).GetStdAllocator()),
m_DedicatedBuffers(((DeviceBase&)device).GetStdAllocator()),
m_DedicatedTextures(((DeviceBase&)device).GetStdAllocator()),
m_BufferBindingDescs(((DeviceBase&)device).GetStdAllocator()),
m_TextureBindingDescs(((DeviceBase&)device).GetStdAllocator()) {
}

uint32_t HelperDeviceMemoryAllocator::CalculateAllocationNumber(const ResourceGroupDesc& resourceGroupDesc) {
m_Map.clear();
m_DedicatedBuffers.clear();
m_DedicatedTextures.clear();
GroupByMemoryType(resourceGroupDesc.memoryLocation, resourceGroupDesc);

GroupByMemoryType(resourceGroupDesc.memoryLocation, resourceGroupDesc.buffers, resourceGroupDesc.bufferNum);
GroupByMemoryType(resourceGroupDesc.memoryLocation, resourceGroupDesc.textures, resourceGroupDesc.textureNum);
size_t allocationNum = m_Heaps.size() + m_DedicatedBuffers.size() + m_DedicatedTextures.size();

return uint32_t(m_Map.size()) + uint32_t(m_DedicatedBuffers.size()) + uint32_t(m_DedicatedTextures.size());
return (uint32_t)allocationNum;
}

Result HelperDeviceMemoryAllocator::AllocateAndBindMemory(const ResourceGroupDesc& resourceGroupDesc, Memory** allocations) {
m_Map.clear();
m_DedicatedBuffers.clear();
m_DedicatedTextures.clear();
m_BufferBindingDescs.clear();
m_TextureBindingDescs.clear();

size_t allocationNum = 0;
const Result result = TryToAllocateAndBindMemory(resourceGroupDesc, allocations, allocationNum);
Result result = TryToAllocateAndBindMemory(resourceGroupDesc, allocations, allocationNum);

if (result != Result::SUCCESS) {
for (size_t i = 0; i < allocationNum; i++) {
Expand All @@ -50,24 +41,26 @@ Result HelperDeviceMemoryAllocator::AllocateAndBindMemory(const ResourceGroupDes
}

Result HelperDeviceMemoryAllocator::TryToAllocateAndBindMemory(const ResourceGroupDesc& resourceGroupDesc, Memory** allocations, size_t& allocationNum) {
GroupByMemoryType(resourceGroupDesc.memoryLocation, resourceGroupDesc.buffers, resourceGroupDesc.bufferNum);
GroupByMemoryType(resourceGroupDesc.memoryLocation, resourceGroupDesc.textures, resourceGroupDesc.textureNum);
GroupByMemoryType(resourceGroupDesc.memoryLocation, resourceGroupDesc);

Result result = Result::SUCCESS;
for (MemoryHeap& heap : m_Heaps) {
Memory*& memory = allocations[allocationNum];

for (auto it = m_Map.begin(); it != m_Map.end() && result == Result::SUCCESS; ++it)
result = ProcessMemoryTypeGroup(it->first, it->second, allocations, allocationNum);
Result result = m_NRI.AllocateMemory(m_Device, heap.type, heap.size, memory);
if (result != Result::SUCCESS)
return result;

if (result != Result::SUCCESS)
return result;
FillMemoryBindingDescs(heap.buffers.data(), heap.bufferOffsets.data(), (uint32_t)heap.buffers.size(), *memory);
FillMemoryBindingDescs(heap.textures.data(), heap.textureOffsets.data(), (uint32_t)heap.textures.size(), *memory);

result = ProcessDedicatedResources(resourceGroupDesc.memoryLocation, allocations, allocationNum);
allocationNum++;
}

Result result = ProcessDedicatedResources(resourceGroupDesc.memoryLocation, allocations, allocationNum);
if (result != Result::SUCCESS)
return result;

result = m_NRI.BindBufferMemory(m_Device, m_BufferBindingDescs.data(), (uint32_t)m_BufferBindingDescs.size());

if (result != Result::SUCCESS)
return result;

Expand All @@ -76,22 +69,6 @@ Result HelperDeviceMemoryAllocator::TryToAllocateAndBindMemory(const ResourceGro
return result;
}

Result HelperDeviceMemoryAllocator::ProcessMemoryTypeGroup(MemoryType memoryType, MemoryTypeGroup& group, Memory** allocations, size_t& allocationNum) {
Memory*& memory = allocations[allocationNum];

const uint64_t allocationSize = group.memoryOffset;

const Result result = m_NRI.AllocateMemory(m_Device, memoryType, allocationSize, memory);
if (result != Result::SUCCESS)
return result;

FillMemoryBindingDescs(group.buffers.data(), group.bufferOffsets.data(), (uint32_t)group.buffers.size(), *memory);
FillMemoryBindingDescs(group.textures.data(), group.textureOffsets.data(), (uint32_t)group.textures.size(), *memory);
allocationNum++;

return Result::SUCCESS;
}

Result HelperDeviceMemoryAllocator::ProcessDedicatedResources(MemoryLocation memoryLocation, Memory** allocations, size_t& allocationNum) {
constexpr uint64_t zeroOffset = 0;
MemoryDesc memoryDesc = {};
Expand All @@ -102,11 +79,12 @@ Result HelperDeviceMemoryAllocator::ProcessDedicatedResources(MemoryLocation mem

Memory*& memory = allocations[allocationNum];

const Result result = m_NRI.AllocateMemory(m_Device, memoryDesc.type, memoryDesc.size, memory);
Result result = m_NRI.AllocateMemory(m_Device, memoryDesc.type, memoryDesc.size, memory);
if (result != Result::SUCCESS)
return result;

FillMemoryBindingDescs(m_DedicatedBuffers.data() + i, &zeroOffset, 1, *memory);

allocationNum++;
}

Expand All @@ -116,62 +94,82 @@ Result HelperDeviceMemoryAllocator::ProcessDedicatedResources(MemoryLocation mem

Memory*& memory = allocations[allocationNum];

const Result result = m_NRI.AllocateMemory(m_Device, memoryDesc.type, memoryDesc.size, memory);
Result result = m_NRI.AllocateMemory(m_Device, memoryDesc.type, memoryDesc.size, memory);
if (result != Result::SUCCESS)
return result;

FillMemoryBindingDescs(m_DedicatedTextures.data() + i, &zeroOffset, 1, *memory);

allocationNum++;
}

return Result::SUCCESS;
}

void HelperDeviceMemoryAllocator::GroupByMemoryType(MemoryLocation memoryLocation, Buffer* const* buffers, uint32_t bufferNum) {
MemoryDesc memoryDesc = {};
HelperDeviceMemoryAllocator::MemoryHeap& HelperDeviceMemoryAllocator::FindOrCreateHeap(nri::MemoryDesc& memoryDesc, uint64_t preferredMemorySize) {
if (preferredMemorySize == 0)
preferredMemorySize = 256 * 1024 * 1024;

for (uint32_t i = 0; i < bufferNum; i++) {
Buffer* buffer = buffers[i];
size_t j = 0;
for (; j < m_Heaps.size(); j++) {
const MemoryHeap& heap = m_Heaps[j];

uint64_t offset = Align(heap.size, memoryDesc.alignment);
uint64_t newSize = offset + memoryDesc.size;

if (heap.type == memoryDesc.type && newSize <= preferredMemorySize)
break;
}

if (j == m_Heaps.size())
m_Heaps.push_back(MemoryHeap(memoryDesc.type, ((DeviceBase&)m_Device).GetStdAllocator()));

return m_Heaps[j];
}

void HelperDeviceMemoryAllocator::GroupByMemoryType(MemoryLocation memoryLocation, const nri::ResourceGroupDesc& resourceGroupDesc) {
for (uint32_t i = 0; i < resourceGroupDesc.bufferNum; i++) {
Buffer* buffer = resourceGroupDesc.buffers[i];
const BufferDesc& bufferDesc = m_NRI.GetBufferDesc(*buffer);

MemoryDesc memoryDesc = {};
m_NRI.GetBufferMemoryDesc(m_Device, bufferDesc, memoryLocation, memoryDesc);

if (memoryDesc.mustBeDedicated)
m_DedicatedBuffers.push_back(buffer);
else {
MemoryTypeGroup& group = m_Map.try_emplace(memoryDesc.type, ((DeviceBase&)m_Device).GetStdAllocator()).first->second;
MemoryHeap& heap = FindOrCreateHeap(memoryDesc, resourceGroupDesc.preferredMemorySize);

uint64_t offset = Align(group.memoryOffset, memoryDesc.alignment);
uint64_t offset = Align(heap.size, memoryDesc.alignment);

group.buffers.push_back(buffer);
group.bufferOffsets.push_back(offset);
group.memoryOffset = offset + memoryDesc.size;
heap.buffers.push_back(buffer);
heap.bufferOffsets.push_back(offset);
heap.size = offset + memoryDesc.size;
}
}
}

void HelperDeviceMemoryAllocator::GroupByMemoryType(MemoryLocation memoryLocation, Texture* const* textures, uint32_t textureNum) {
const DeviceDesc& deviceDesc = m_NRI.GetDeviceDesc(m_Device);

MemoryDesc memoryDesc = {};

for (uint32_t i = 0; i < textureNum; i++) {
Texture* texture = textures[i];
for (uint32_t i = 0; i < resourceGroupDesc.textureNum; i++) {
Texture* texture = resourceGroupDesc.textures[i];
const TextureDesc& textureDesc = m_NRI.GetTextureDesc(*texture);

MemoryDesc memoryDesc = {};
m_NRI.GetTextureMemoryDesc(m_Device, textureDesc, memoryLocation, memoryDesc);

if (memoryDesc.mustBeDedicated)
m_DedicatedTextures.push_back(texture);
else {
MemoryTypeGroup& group = m_Map.try_emplace(memoryDesc.type, ((DeviceBase&)m_Device).GetStdAllocator()).first->second;
MemoryHeap& heap = FindOrCreateHeap(memoryDesc, resourceGroupDesc.preferredMemorySize);

if (group.textures.empty() && group.memoryOffset > 0)
group.memoryOffset = Align(group.memoryOffset, deviceDesc.bufferTextureGranularity);
if (heap.textures.empty()) {
const DeviceDesc& deviceDesc = m_NRI.GetDeviceDesc(m_Device);
heap.size = Align(heap.size, deviceDesc.bufferTextureGranularity);
}

uint64_t offset = Align(group.memoryOffset, memoryDesc.alignment);
uint64_t offset = Align(heap.size, memoryDesc.alignment);

group.textures.push_back(texture);
group.textureOffsets.push_back(offset);
group.memoryOffset = offset + memoryDesc.size;
heap.textures.push_back(texture);
heap.textureOffsets.push_back(offset);
heap.size = offset + memoryDesc.size;
}
}
}
Expand Down
Loading

0 comments on commit ad030e9

Please sign in to comment.