diff options
author | Philip Rebohle <philip.rebohle@tu-dortmund.de> | 2022-09-22 17:37:41 +0300 |
---|---|---|
committer | Philip Rebohle <philip.rebohle@tu-dortmund.de> | 2022-09-22 17:37:41 +0300 |
commit | 60057d8a5ebbbf7bd4f56661489245fbcd5a3897 (patch) | |
tree | ee87eef4dcc1681ba525928a6e29b277d9ff64d8 | |
parent | b8bf0b0f8f0780ece5cd27969c99b4ad39192904 (diff) |
[dxvk] Rework allocation logic for large resourcesmemory-stuff
This may reduce internal fragmentation with very large resources.
We previously changed behaviour to not do this in order to reduce memory
pressure in the average case, however by trying to suballocate from existing
chunks and falling back to a dedicated allocation on failure, rather than
allocating a new chunk, we can mostly avoid that situation.
-rw-r--r-- | src/dxvk/dxvk_memory.cpp | 34 |
1 files changed, 26 insertions, 8 deletions
diff --git a/src/dxvk/dxvk_memory.cpp b/src/dxvk/dxvk_memory.cpp index aca64296..af4760b5 100644 --- a/src/dxvk/dxvk_memory.cpp +++ b/src/dxvk/dxvk_memory.cpp @@ -326,19 +326,25 @@ namespace dxvk { DxvkMemory memory; - if (size >= chunkSize || info.dedicated.buffer || info.dedicated.image) { - if (this->shouldFreeEmptyChunks(type->heap, size)) - this->freeEmptyChunks(type->heap); + // Require dedicated allocations for resources that use the Vulkan dedicated + // allocation bits, or are too large to fit into a single full-sized chunk + bool needsDedicatedAlocation = size >= chunkSize || info.dedicated.buffer || info.dedicated.image; - DxvkDeviceMemory devMem = this->tryAllocDeviceMemory(type, size, info, hints); + // Prefer a dedicated allocation for very large resources in order to + // reduce fragmentation if a large number of those resources are in use + bool wantsDedicatedAllocation = 3 * size >= chunkSize; - if (devMem.memHandle != VK_NULL_HANDLE) - memory = DxvkMemory(this, nullptr, type, devMem.memHandle, 0, size, devMem.memPointer); - } else { + // Try to reuse existing memory as much as possible in case the heap is nearly full + bool heapBudgedExceeded = 5 * type->heap->stats.memoryUsed + size > 4 * type->heap->properties.size; + + if (!needsDedicatedAlocation && (!wantsDedicatedAllocation || heapBudgedExceeded)) { + // Attempt to suballocate from existing chunks first for (uint32_t i = 0; i < type->chunks.size() && !memory; i++) memory = type->chunks[i]->alloc(info.flags, size, align, hints); - if (!memory) { + // If no existing chunk can accomodate the allocation, and if a dedicated + // allocation is not preferred, create a new chunk and suballocate from it + if (!memory && !wantsDedicatedAllocation) { DxvkDeviceMemory devMem; if (this->shouldFreeEmptyChunks(type->heap, chunkSize)) @@ -356,6 +362,18 @@ namespace dxvk { } } + // If a dedicated allocation is required or preferred and we haven't managed + // to suballocate any memory before, try to create a dedicated allocation + if (!memory && (needsDedicatedAlocation || wantsDedicatedAllocation)) { + if (this->shouldFreeEmptyChunks(type->heap, size)) + this->freeEmptyChunks(type->heap); + + DxvkDeviceMemory devMem = this->tryAllocDeviceMemory(type, size, info, hints); + + if (devMem.memHandle != VK_NULL_HANDLE) + memory = DxvkMemory(this, nullptr, type, devMem.memHandle, 0, size, devMem.memPointer); + } + if (memory) type->heap->stats.memoryUsed += memory.m_length; |