Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/doitsujin/dxvk.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Rebohle <philip.rebohle@tu-dortmund.de>2022-09-22 17:37:41 +0300
committerPhilip Rebohle <philip.rebohle@tu-dortmund.de>2022-09-22 17:37:41 +0300
commit60057d8a5ebbbf7bd4f56661489245fbcd5a3897 (patch)
treeee87eef4dcc1681ba525928a6e29b277d9ff64d8
parentb8bf0b0f8f0780ece5cd27969c99b4ad39192904 (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.cpp34
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;