descriptor reuse

This commit is contained in:
jacob 2025-12-13 18:41:01 -06:00
parent f241379dba
commit 6c3c7231ff
4 changed files with 259 additions and 108 deletions

View File

@ -69,8 +69,8 @@
#define FLOOD_DEBUG 0
#define GPU_DEBUG 0
#define GPU_DEBUG_VALIDATION 0
#define GPU_DEBUG 1
#define GPU_DEBUG_VALIDATION 1
#define GPU_SHADER_PRINT 1
#define GPU_SHADER_PRINT_BUFFER_SIZE Kibi(64);

View File

@ -202,6 +202,7 @@ void G_Bootstrap(void)
G_D12_DescriptorHeap *heap = &g->descriptor_heaps[kind];
heap->descriptors_arena = AcquireArena(Gibi(1));
heap->kind = kind;
heap->type = desc.type;
heap->max_count = desc.max;
heap->descriptor_size = ID3D12Device_GetDescriptorHandleIncrementSize(g->device, desc.type);
@ -724,23 +725,25 @@ i64 G_D12_CommitRawCommandList(G_D12_RawCommandList *cl)
}
/* Commit */
i64 completion = 0;
i64 completion_target = 0;
{
Lock lock = LockE(&queue->commit_mutex);
{
completion = ++queue->commit_fence_target;
cl->commit_fence_target = completion;
/* Execute */
ID3D12CommandQueue_ExecuteCommandLists(queue->d3d_queue, 1, (ID3D12CommandList **)&cl->d3d_cl);
ID3D12CommandQueue_Signal(queue->d3d_queue, queue->commit_fence, completion);
Lock lock = LockE(&queue->commit_mutex);
{
completion_target = ++queue->commit_fence_target;
cl->commit_fence_target = completion_target;
ID3D12CommandQueue_Signal(queue->d3d_queue, queue->commit_fence, completion_target);
/* Append */
SllQueuePush(queue->first_committed_cl, queue->last_committed_cl, cl);
}
Unlock(&lock);
}
return completion;
return completion_target;
}
////////////////////////////////////////////////////////////
@ -780,11 +783,64 @@ void G_D12_ResetArena(G_D12_CmdList *cl, G_D12_Arena *gpu_arena)
/* FIXME: Move descriptors into committed lists */
/* FIXME: Release id3d12 resource com object references */
// for (u64 heap_idx = 0; heap_idx < countof(gpu_arena->resource_heaps); ++heap_idx)
// {
// G_D12_ResourceHeap *heap = &gpu_arena->resource_heaps[heap_idx];
// heap->pos = 0;
// if (heap->first_reset_resource)
// {
// heap->last_reset_resource->next = heap->first_resource;
// }
// else
// {
// heap->first_reset_resource = heap->first_resource;
// }
// heap->last_reset_resource = heap->last_resource;
// heap->reset_resources_count += heap->resources_count;
// heap->resources_count = 0;
// heap->first_resource = 0;
// heap->last_resource = 0;
// }
for (u64 heap_idx = 0; heap_idx < countof(gpu_arena->resource_heaps); ++heap_idx)
{
G_D12_ResourceHeap *heap = &gpu_arena->resource_heaps[heap_idx];
heap->pos = 0;
/* FIXME: Free list if this actually works */
for (G_D12_Resource *resource = heap->resources.first; resource; resource = resource->next)
{
ID3D12Resource_Release(resource->d3d_resource);
}
heap->resources.count = 0;
heap->resources.first = 0;
heap->resources.last = 0;
}
/* Push descriptors to cl reset list */
{
if (cl->reset_descriptors.last)
{
cl->reset_descriptors.last->next = gpu_arena->descriptors.first;
}
else
{
cl->reset_descriptors.first = gpu_arena->descriptors.first;
}
cl->reset_descriptors.last = gpu_arena->descriptors.last;
cl->reset_descriptors.count += gpu_arena->descriptors.count;
gpu_arena->descriptors.count = 0;
gpu_arena->descriptors.first = 0;
gpu_arena->descriptors.last = 0;
}
}
////////////////////////////////////////////////////////////
@ -891,7 +947,8 @@ G_ResourceHandle G_PushResource(G_ArenaHandle arena_handle, G_ResourceDesc desc)
Panic(Lit("Gpu heap overflow"));
}
hr = ID3D12Device10_CreatePlacedResource2(g->device,
hr = ID3D12Device10_CreatePlacedResource2(
g->device,
heap->d3d_heap,
0,
&d3d_desc,
@ -900,7 +957,8 @@ G_ResourceHandle G_PushResource(G_ArenaHandle arena_handle, G_ResourceDesc desc)
0,
0,
&IID_ID3D12Resource,
(void **)&heap->d3d_mapped_resource);
(void **)&heap->d3d_mapped_resource
);
}
if (SUCCEEDED(hr))
{
@ -919,7 +977,7 @@ G_ResourceHandle G_PushResource(G_ArenaHandle arena_handle, G_ResourceDesc desc)
}
//////////////////////////////
//- Create buffer / texture
//- Initialize d3d resource desc
D3D12_BARRIER_LAYOUT initial_layout = D3D12_BARRIER_LAYOUT_UNDEFINED;
D3D12_CLEAR_VALUE clear_value = ZI;
@ -964,34 +1022,72 @@ G_ResourceHandle G_PushResource(G_ArenaHandle arena_handle, G_ResourceDesc desc)
}
}
u64 alloc_size = 0;
u64 alloc_align = 0;
u64 align_in_heap = 0;
u64 size_in_heap = 0;
{
D3D12_RESOURCE_ALLOCATION_INFO alloc_info = ZI;
ID3D12Device_GetResourceAllocationInfo(g->device, &alloc_info, 0, 1, (D3D12_RESOURCE_DESC *)&d3d_desc);
alloc_size = alloc_info.SizeInBytes;
alloc_align = alloc_info.Alignment;
align_in_heap = alloc_info.Alignment;
size_in_heap = alloc_info.SizeInBytes;
}
//////////////////////////////
//- Re-use existing resource
// u64 pos_in_heap = 0;
// ID3D12Resource *d3d_resource = 0;
// {
// resource = heap->first_reset_resource;
// if (resource)
// {
// SllQueuePop(heap->first_reset_resource, heap->last_reset_resource);
// --heap->reset_resources_count;
// b32 can_use = 1;
// can_use = can_use && resource->is_texture == is_texture;
// can_use = can_use && resource->size_in_heap >= size_in_heap;
// can_use = can_use && resource->pos_in_heap % align_in_heap == 0;
// if (can_use)
// {
// d3d_resource = resource->d3d_resource;
// pos_in_heap = resource->pos_in_heap;
// size_in_heap = resource->size_in_heap;
// heap->pos = resource->pos_in_heap + resource->size_in_heap;
// }
// else
// {
// /* FIXME: Free d3d resource here? */
// ZeroStruct(resource);
// }
// }
// if (!resource)
// {
// resource = PushStruct(gpu_arena->arena, G_D12_Resource);
// }
// }
u64 pos_in_heap = 0;
ID3D12Resource *d3d_resource = 0;
{
resource = PushStruct(gpu_arena->arena, G_D12_Resource);
}
//////////////////////////////
//- Create new d3d resource
if (!resource->d3d_resource)
{
pos_in_heap = heap->pos;
pos_in_heap = AlignU64(pos_in_heap, alloc_align);
heap->pos = pos_in_heap + alloc_size;
if (pos_in_heap + alloc_size > heap->size)
pos_in_heap = AlignU64(pos_in_heap, align_in_heap);
heap->pos = pos_in_heap + size_in_heap;
if (pos_in_heap + size_in_heap > heap->size)
{
Panic(Lit("Gpu arena overflow"));
}
}
ID3D12Resource *d3d_resource = 0;
{
hr = ID3D12Device10_CreatePlacedResource2(
g->device,
heap->d3d_heap,
pos_in_heap,
&d3d_desc,
D3D12_BARRIER_LAYOUT_UNDEFINED,
initial_layout,
(d3d_desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET) ? &clear_value : 0,
0,
0,
@ -1000,9 +1096,12 @@ G_ResourceHandle G_PushResource(G_ArenaHandle arena_handle, G_ResourceDesc desc)
);
}
resource = PushStruct(gpu_arena->arena, G_D12_Resource);
//////////////////////////////
//- Insert resource
resource->heap = heap;
resource->pos_in_heap = pos_in_heap;
resource->size_in_heap = size_in_heap;
resource->d3d_resource = d3d_resource;
resource->uid = Atomic64FetchAdd(&g->resource_creation_gen.v, 1) + 1;
resource->flags = flags;
@ -1010,6 +1109,7 @@ G_ResourceHandle G_PushResource(G_ArenaHandle arena_handle, G_ResourceDesc desc)
{
resource->buffer_size = desc.buffer.size;
resource->buffer_size_actual = d3d_desc.Width;
/* TODO: Cache this */
resource->buffer_gpu_address = ID3D12Resource_GetGPUVirtualAddress(d3d_resource);
}
if (is_texture)
@ -1020,6 +1120,9 @@ G_ResourceHandle G_PushResource(G_ArenaHandle arena_handle, G_ResourceDesc desc)
resource->texture_mip_levels = desc.texture.mip_levels;
resource->texture_layout = initial_layout;
}
SllQueuePush(heap->resources.first, heap->resources.last, resource);
++heap->resources.count;
}
//////////////////////////////
@ -1052,21 +1155,21 @@ G_D12_Descriptor *G_D12_PushDescriptor(G_D12_Arena *gpu_arena, G_D12_DescriptorH
G_D12_DescriptorHeap *heap = &g->descriptor_heaps[heap_kind];
G_D12_Descriptor *descriptor = 0;
u32 index = 0;
/* Grab completed descriptor from arena */
G_D12_DescriptorList *descriptors_by_queue = gpu_arena->committed_descriptors_by_heap_and_queue[heap_kind];
for (G_QueueKind queue_kind = 0; !descriptor && queue_kind < G_NumQueues; ++queue_kind)
{
G_D12_DescriptorList *descriptors = &descriptors_by_queue[queue_kind];
G_D12_DescriptorList *descriptors = &gpu_arena->reset_descriptors_by_heap[heap_kind];
descriptor = descriptors->first;
if (descriptor)
{
G_D12_Queue *queue = G_D12_QueueFromKind(queue_kind);
u64 queue_commit_completion = ID3D12Fence_GetCompletedValue(queue->commit_fence);
if (queue_commit_completion >= descriptor->queue_commit_target)
G_D12_Queue *queue = G_D12_QueueFromKind(descriptor->completion_queue_kind);
i64 queue_commit_completion = ID3D12Fence_GetCompletedValue(queue->commit_fence);
if (queue_commit_completion >= descriptor->completion_queue_target)
{
/* Descriptor no longer in use by gpu, reuse it */
DllQueueRemove(descriptors->first, descriptors->last, descriptor);
SllQueuePop(descriptors->first, descriptors->last);
--descriptors->count;
index = descriptor->index;
}
else
{
@ -1074,10 +1177,8 @@ G_D12_Descriptor *G_D12_PushDescriptor(G_D12_Arena *gpu_arena, G_D12_DescriptorH
descriptor = 0;
}
}
}
/* Allocate new descriptor from heap */
u32 index = 0;
if (!descriptor)
{
Lock lock = LockE(&heap->mutex);
@ -1085,7 +1186,7 @@ G_D12_Descriptor *G_D12_PushDescriptor(G_D12_Arena *gpu_arena, G_D12_DescriptorH
if (heap->first_free)
{
descriptor = heap->first_free;
DllStackRemove(heap->first_free, descriptor);
SllStackPop(heap->first_free);
index = descriptor->index;
}
else
@ -1104,9 +1205,13 @@ G_D12_Descriptor *G_D12_PushDescriptor(G_D12_Arena *gpu_arena, G_D12_DescriptorH
/* Initialize descriptor handle */
ZeroStruct(descriptor);
descriptor->heap = heap;
descriptor->gpu_arena = gpu_arena;
descriptor->index = index;
descriptor->handle.ptr = heap->start_handle.ptr + (index * heap->descriptor_size);
descriptor->heap = heap;
SllQueuePush(gpu_arena->descriptors.first, gpu_arena->descriptors.last, descriptor);
++gpu_arena->descriptors.count;
return descriptor;
}
@ -1478,14 +1583,16 @@ G_D12_StagingRegionNode *G_D12_PushStagingRegion(G_D12_CmdList *cl, u64 size)
d3d_desc.SampleDesc.Quality = 0;
D3D12_HEAP_PROPERTIES heap_props = { .Type = D3D12_HEAP_TYPE_UPLOAD };
HRESULT hr = ID3D12Device_CreateCommittedResource(g->device,
HRESULT hr = ID3D12Device_CreateCommittedResource(
g->device,
&heap_props,
D3D12_HEAP_FLAG_CREATE_NOT_ZEROED,
&d3d_desc,
D3D12_RESOURCE_STATE_COMMON,
0,
&IID_ID3D12Resource,
(void **)&d3d_resource);
(void **)&d3d_resource
);
if (!SUCCEEDED(hr))
{
/* TODO: Don't panic */
@ -2192,7 +2299,38 @@ i64 G_CommitCommandList(G_CommandListHandle cl_handle)
}
/* End dx12 command list */
i64 completion = G_D12_CommitRawCommandList(rcl);
i64 completion_target = G_D12_CommitRawCommandList(rcl);
/* Attach completion info to descriptors */
for (G_D12_Descriptor *d = cl->reset_descriptors.first; d;)
{
G_D12_Descriptor *next = d->next;
{
G_D12_Arena *gpu_arena = d->gpu_arena;
d->completion_queue_kind = queue_kind;
d->completion_queue_target = completion_target;
G_D12_DescriptorList *gpu_arena_reset_descriptors_list = &gpu_arena->reset_descriptors_by_heap[d->heap->kind];
SllQueuePush(gpu_arena_reset_descriptors_list->first, gpu_arena_reset_descriptors_list->last, d);
++gpu_arena_reset_descriptors_list->count;
}
d = next;
}
// /* Attach completion info to resources */
// for (G_D12_Resource *r = cl->reset_resources.first; r;)
// {
// G_D12_Resource *next = r->next;
// {
// G_D12_ResourceHeap *heap = r->heap;
// G_D12_Arena *gpu_arena = >heap->gpu_arena;
// r->completion_queue_kind = queue->kind;
// r->completion_queue_target = completion_target;
// G_D12_ResourceList *heap_reset_resources_list = &heap->reset_resources;
// SllQueuePush(heap_reset_resources_list->first, heap_reset_resourecs_list->last, r);
// ++heap_reset_resources_list->count;
// }
// r = next;
// }
/* Free command list */
{
@ -2205,7 +2343,7 @@ i64 G_CommitCommandList(G_CommandListHandle cl_handle)
}
EndScratch(scratch);
return completion;
return completion_target;
}
//- Arena

View File

@ -55,6 +55,47 @@ Struct(G_D12_PipelineBin)
G_D12_Pipeline *first;
};
////////////////////////////////////////////////////////////
//~ Resource types
Struct(G_D12_Resource)
{
G_D12_Resource *next;
struct G_D12_ResourceHeap *heap;
u64 pos_in_heap;
u64 size_in_heap;
ID3D12Resource *d3d_resource;
u64 uid;
G_ResourceFlag flags;
/* Buffer info */
u64 buffer_size;
u64 buffer_size_actual;
D3D12_GPU_VIRTUAL_ADDRESS buffer_gpu_address;
/* Texture info */
b32 is_texture;
G_Format texture_format;
Vec3I32 texture_dims;
i32 texture_mip_levels;
D3D12_BARRIER_LAYOUT texture_layout;
/* Sampler info */
G_SamplerDesc sampler_desc;
/* Backbuffer info */
struct G_D12_Swapchain *swapchain;
};
Struct(G_D12_ResourceList)
{
u64 count;
G_D12_Resource *first;
G_D12_Resource *last;
};
////////////////////////////////////////////////////////////
//~ Descriptor types
@ -70,6 +111,7 @@ Enum(G_D12_DescriptorHeapKind)
Struct(G_D12_DescriptorHeap)
{
Arena *descriptors_arena;
G_D12_DescriptorHeapKind kind;
D3D12_DESCRIPTOR_HEAP_TYPE type;
u32 descriptor_size;
@ -84,8 +126,10 @@ Struct(G_D12_DescriptorHeap)
Struct(G_D12_Descriptor)
{
G_D12_Descriptor *next;
G_D12_Descriptor *prev;
u64 queue_commit_target;
struct G_D12_Arena *gpu_arena;
G_QueueKind completion_queue_kind;
i64 completion_queue_target;
G_D12_DescriptorHeap *heap;
D3D12_CPU_DESCRIPTOR_HANDLE handle;
@ -94,6 +138,7 @@ Struct(G_D12_Descriptor)
Struct(G_D12_DescriptorList)
{
u64 count;
G_D12_Descriptor *first;
G_D12_Descriptor *last;
};
@ -120,17 +165,14 @@ Struct(G_D12_ResourceHeap)
{
G_D12_ResourceHeapKind kind;
struct GPU_D12_Arena *gpu_arena;
ID3D12Heap *d3d_heap;
ID3D12Resource *d3d_mapped_resource;
void *mapped;
u64 resources_count;
struct G_D12_Resource *first_resource;
struct G_D12_Resource *last_resource;
u64 reset_resources_count;
struct G_D12_Resource *first_reset_resource;
struct G_D12_Resource *last_reset_resource;
G_D12_ResourceList resources;
G_D12_ResourceList reset_resources;
u64 pos;
u64 size;
@ -139,44 +181,13 @@ Struct(G_D12_ResourceHeap)
Struct(G_D12_Arena)
{
Arena *arena;
G_D12_DescriptorList committed_descriptors_by_heap_and_queue[G_D12_DescriptorHeapKind_Count][G_NumQueues];
G_D12_DescriptorList descriptors;
G_D12_DescriptorList reset_descriptors_by_heap[G_D12_DescriptorHeapKind_Count];
G_D12_ResourceHeap resource_heaps[G_D12_ResourceHeapKind_Count];
};
////////////////////////////////////////////////////////////
//~ Resource types
Struct(G_D12_Resource)
{
G_D12_Resource *next;
G_D12_ResourceHeap *heap;
u64 pos_in_heap;
ID3D12Resource *d3d_resource;
u64 uid;
G_ResourceFlag flags;
/* Buffer info */
u64 buffer_size;
u64 buffer_size_actual;
D3D12_GPU_VIRTUAL_ADDRESS buffer_gpu_address;
/* Texture info */
b32 is_texture;
G_Format texture_format;
Vec3I32 texture_dims;
i32 texture_mip_levels;
D3D12_BARRIER_LAYOUT texture_layout;
/* Sampler info */
G_SamplerDesc sampler_desc;
/* Backbuffer info */
struct G_D12_Swapchain *swapchain;
};
////////////////////////////////////////////////////////////
//~ Staging types
@ -351,8 +362,10 @@ Struct(G_D12_CmdChunk)
Struct(G_D12_CmdList)
{
G_QueueKind queue_kind;
G_D12_CmdList *next;
G_QueueKind queue_kind;
G_D12_DescriptorList reset_descriptors;
G_D12_CmdChunk *first_cmd_chunk;
G_D12_CmdChunk *last_cmd_chunk;

View File

@ -1402,7 +1402,7 @@ void UI_EndFrame(UI_Frame *frame)
//- Clear pass
{
G_ClearRenderTarget(frame->cl, draw_target, VEC4(0, 0, 0, 1));
G_ClearRenderTarget(frame->cl, draw_target, VEC4(0, 0, 0, 0));
}
//- Rect pass