mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-05 01:24:14 +01:00
[dxvk] Rework allocation logic for large resources
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.
This commit is contained in:
parent
15588004b4
commit
f1f8d45fcd
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user