From 20206b8e66dd9221e92df9e706ee588649511c3c Mon Sep 17 00:00:00 2001 From: Evan Hemsley <2342303+thatcosmonaut@users.noreply.github.com> Date: Mon, 13 Oct 2025 13:00:00 -0700 Subject: [PATCH] GPU: Correctly recycle D3D12 descriptor heaps (#14234) --- src/gpu/d3d12/SDL_gpu_d3d12.c | 54 ++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/src/gpu/d3d12/SDL_gpu_d3d12.c b/src/gpu/d3d12/SDL_gpu_d3d12.c index 85e397a898..b1b2de3605 100644 --- a/src/gpu/d3d12/SDL_gpu_d3d12.c +++ b/src/gpu/d3d12/SDL_gpu_d3d12.c @@ -980,6 +980,10 @@ struct D3D12CommandBuffer // Set at acquire time D3D12DescriptorHeap *gpuDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER + 1]; + D3D12DescriptorHeap **usedDescriptorHeaps; + Uint32 usedDescriptorHeapCount; + Uint32 usedDescriptorHeapCapacity; + D3D12UniformBuffer **usedUniformBuffers; Uint32 usedUniformBufferCount; Uint32 usedUniformBufferCapacity; @@ -1565,6 +1569,7 @@ static void D3D12_INTERNAL_DestroyCommandBuffer(D3D12CommandBuffer *commandBuffe SDL_free(commandBuffer->usedSamplers); SDL_free(commandBuffer->usedGraphicsPipelines); SDL_free(commandBuffer->usedComputePipelines); + SDL_free(commandBuffer->usedDescriptorHeaps); SDL_free(commandBuffer->usedUniformBuffers); SDL_free(commandBuffer->textureDownloads); SDL_free(commandBuffer); @@ -2268,6 +2273,28 @@ static bool D3D12_INTERNAL_ExpandStagingDescriptorPool( return true; } +static void D3D12_INTERNAL_TrackGPUDescriptorHeap( + D3D12CommandBuffer *commandBuffer, + D3D12DescriptorHeap *descriptorHeap) +{ + Uint32 i; + for (i = 0; i < commandBuffer->usedDescriptorHeapCount; i += 1) { + if (commandBuffer->usedDescriptorHeaps[i] == descriptorHeap) { + return; + } + } + + if (commandBuffer->usedDescriptorHeapCount == commandBuffer->usedDescriptorHeapCapacity) { + commandBuffer->usedDescriptorHeapCapacity += 1; + commandBuffer->usedDescriptorHeaps = (D3D12DescriptorHeap **)SDL_realloc( + commandBuffer->usedDescriptorHeaps, + commandBuffer->usedDescriptorHeapCapacity * sizeof(D3D12DescriptorHeap *)); + } + + commandBuffer->usedDescriptorHeaps[commandBuffer->usedDescriptorHeapCount] = descriptorHeap; + commandBuffer->usedDescriptorHeapCount += 1; +} + static D3D12DescriptorHeap *D3D12_INTERNAL_AcquireGPUDescriptorHeapFromPool( D3D12CommandBuffer *commandBuffer, D3D12_DESCRIPTOR_HEAP_TYPE descriptorHeapType) @@ -2289,6 +2316,7 @@ static D3D12DescriptorHeap *D3D12_INTERNAL_AcquireGPUDescriptorHeapFromPool( } SDL_UnlockMutex(pool->lock); + D3D12_INTERNAL_TrackGPUDescriptorHeap(commandBuffer, result); return result; } @@ -4885,14 +4913,7 @@ static void D3D12_INTERNAL_SetGPUDescriptorHeaps(D3D12CommandBuffer *commandBuff viewHeap = D3D12_INTERNAL_AcquireGPUDescriptorHeapFromPool(commandBuffer, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); samplerHeap = D3D12_INTERNAL_AcquireGPUDescriptorHeapFromPool(commandBuffer, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); - if (commandBuffer->gpuDescriptorHeaps[0] != NULL) { - D3D12_INTERNAL_ReturnGPUDescriptorHeapToPool(commandBuffer->renderer, commandBuffer->gpuDescriptorHeaps[0]); - } commandBuffer->gpuDescriptorHeaps[0] = viewHeap; - - if (commandBuffer->gpuDescriptorHeaps[1] != NULL) { - D3D12_INTERNAL_ReturnGPUDescriptorHeapToPool(commandBuffer->renderer, commandBuffer->gpuDescriptorHeaps[1]); - } commandBuffer->gpuDescriptorHeaps[1] = samplerHeap; heaps[0] = viewHeap->handle; @@ -7284,6 +7305,11 @@ static bool D3D12_INTERNAL_AllocateCommandBuffer( commandBuffer->usedComputePipelines = (D3D12ComputePipeline **)SDL_calloc( commandBuffer->usedComputePipelineCapacity, sizeof(D3D12ComputePipeline *)); + commandBuffer->usedDescriptorHeapCapacity = 4; + commandBuffer->usedDescriptorHeapCount = 0; + commandBuffer->usedDescriptorHeaps = (D3D12DescriptorHeap **)SDL_calloc( + commandBuffer->usedDescriptorHeapCapacity, sizeof(D3D12DescriptorHeap *)); + commandBuffer->usedUniformBufferCapacity = 4; commandBuffer->usedUniformBufferCount = 0; commandBuffer->usedUniformBuffers = (D3D12UniformBuffer **)SDL_calloc( @@ -7702,13 +7728,13 @@ static bool D3D12_INTERNAL_CleanCommandBuffer( NULL); CHECK_D3D12_ERROR_AND_RETURN("Could not reset command list", false); - // Return descriptor heaps to pool - D3D12_INTERNAL_ReturnGPUDescriptorHeapToPool( - renderer, - commandBuffer->gpuDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV]); - D3D12_INTERNAL_ReturnGPUDescriptorHeapToPool( - renderer, - commandBuffer->gpuDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER]); + // Return descriptor heaps to pool, pools own their own locks + for (i = 0; i < commandBuffer->usedDescriptorHeapCount; i += 1) { + D3D12_INTERNAL_ReturnGPUDescriptorHeapToPool( + renderer, + commandBuffer->usedDescriptorHeaps[i]); + } + commandBuffer->usedDescriptorHeapCount = 0; commandBuffer->gpuDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV] = NULL; commandBuffer->gpuDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER] = NULL;