From 7bb5447abf50be5cbbfee1abfff2fdfb2fb6f5ea Mon Sep 17 00:00:00 2001 From: jacob Date: Tue, 2 Dec 2025 22:29:35 -0600 Subject: [PATCH] working buffer copy --- src/gpu/gpu_dx12/gpu_dx12.c | 1143 ++++++++++++++++++++--------------- src/gpu/gpu_dx12/gpu_dx12.h | 15 +- src/proto/proto.c | 1 - src/proto/proto_shaders.gpu | 1 - 4 files changed, 661 insertions(+), 499 deletions(-) diff --git a/src/gpu/gpu_dx12/gpu_dx12.c b/src/gpu/gpu_dx12/gpu_dx12.c index d90e7c23..4e228643 100644 --- a/src/gpu/gpu_dx12/gpu_dx12.c +++ b/src/gpu/gpu_dx12/gpu_dx12.c @@ -1143,7 +1143,7 @@ GPU_ArenaHandle GPU_AcquireArena(void) } gpu_arena->arena = AcquireArena(Gibi(1)); - return GPU_D12_HandleFromPointer(GPU_ArenaHandle, gpu_arena); + return GPU_D12_MakeHandle(GPU_ArenaHandle, gpu_arena); } void GPU_ReleaseArena(GPU_ArenaHandle arena) @@ -1239,10 +1239,86 @@ GPU_D12_Descriptor *GPU_D12_DescriptorFromIndex(GPU_D12_DescriptorHeapKind heap_ //- Resource creation -GPU_ResourceHandle GPU_PushBufferEx(GPU_ArenaHandle arena, GPU_BufferDesc desc) +GPU_ResourceHandle GPU_PushBufferEx(GPU_ArenaHandle arena_handle, GPU_BufferDesc desc) { - /* TODO */ - return GPU_D12_HandleFromPointer(GPU_ResourceHandle, 0); + GPU_D12_SharedState *g = &GPU_D12_shared_state; + GPU_D12_Arena *gpu_arena = GPU_D12_ArenaFromHandle(arena_handle); + + /* Create resource heap */ + if (!gpu_arena->d3d_resource_heap) + { + /* FIXME: Dynamic size */ + D3D12_HEAP_DESC d3d_desc = ZI; + d3d_desc.SizeInBytes = Mebi(64); + d3d_desc.Flags = D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES; /* TODO: Remove this and support tier 1 resource heaps */ + d3d_desc.Properties.Type = D3D12_HEAP_TYPE_DEFAULT; + + ID3D12Heap *heap = 0; + HRESULT hr = ID3D12Device_CreateHeap(g->device, &d3d_desc, &IID_ID3D12Heap, (void **)&heap); + if (!SUCCEEDED(hr)) + { + /* TODO: Don't panic */ + Panic(Lit("Failed to create D3D12 resource heap")); + } + + gpu_arena->d3d_resource_heap = heap; + gpu_arena->heap_size = d3d_desc.SizeInBytes; + } + + /* Create d3d resource */ + ID3D12Resource *d3d_resource = 0; + { + D3D12_RESOURCE_DESC1 d3d_desc = ZI; + d3d_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + d3d_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + d3d_desc.Format = DXGI_FORMAT_UNKNOWN; + d3d_desc.Width = MaxI32(desc.size, 1); + d3d_desc.Height = 1; + d3d_desc.DepthOrArraySize = 1; + d3d_desc.MipLevels = 1; + d3d_desc.SampleDesc.Count = 1; + d3d_desc.SampleDesc.Quality = 0; + d3d_desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS * AnyBit(desc.flags, GPU_ResourceFlag_AllowShaderReadWrite); + + u64 alloc_size = 0; + u64 alloc_align = 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; + } + + u64 alloc_pos = gpu_arena->heap_pos; + alloc_pos = AlignU64(alloc_pos, alloc_align); + gpu_arena->heap_pos = alloc_pos + alloc_size; + + if (alloc_pos + alloc_size > gpu_arena->heap_size) + { + Panic(Lit("Gpu arena overflow")); + } + + HRESULT hr = ID3D12Device10_CreatePlacedResource2(g->device, + gpu_arena->d3d_resource_heap, + alloc_pos, + &d3d_desc, + D3D12_BARRIER_LAYOUT_UNDEFINED, + 0, + 0, + 0, + &IID_ID3D12Resource, + (void **)&d3d_resource); + } + + GPU_D12_Resource *resource = PushStruct(gpu_arena->arena, GPU_D12_Resource); + resource->d3d_resource = d3d_resource; + resource->uid = Atomic64FetchAdd(&g->resource_creation_gen.v, 1) + 1; + resource->flags = desc.flags; + + resource->buffer_size = desc.size; + resource->buffer_gpu_address = ID3D12Resource_GetGPUVirtualAddress(d3d_resource); + + return GPU_D12_MakeHandle(GPU_ResourceHandle, resource); } GPU_ResourceHandle GPU_PushTextureEx(GPU_ArenaHandle arena_handle, GPU_TextureDesc desc) @@ -1272,17 +1348,18 @@ GPU_ResourceHandle GPU_PushTextureEx(GPU_ArenaHandle arena_handle, GPU_TextureDe gpu_arena->heap_size = d3d_desc.SizeInBytes; } + /* Create d3d resource */ ID3D12Resource *d3d_resource = 0; { D3D12_RESOURCE_DESC1 d3d_desc = ZI; d3d_desc.Dimension = desc.kind == GPU_TextureKind_1D ? D3D12_RESOURCE_DIMENSION_TEXTURE1D : GPU_TextureKind_2D ? D3D12_RESOURCE_DIMENSION_TEXTURE2D : D3D12_RESOURCE_DIMENSION_TEXTURE3D; - d3d_desc.Width = MaxI32(desc.dims.x, 1); - d3d_desc.Height = MaxI32(desc.dims.y, 1); - d3d_desc.DepthOrArraySize = MaxI32(desc.dims.z, 1); - d3d_desc.MipLevels = MaxI32(desc.mip_levels, 1); - d3d_desc.Format = GPU_D12_DxgiFormatFromGpuFormat(desc.format); + d3d_desc.Format = GPU_D12_DxgiFormatFromGpuFormat(desc.format); + d3d_desc.Width = MaxI32(desc.dims.x, 1); + d3d_desc.Height = MaxI32(desc.dims.y, 1); + d3d_desc.DepthOrArraySize = MaxI32(desc.dims.z, 1); + d3d_desc.MipLevels = MaxI32(desc.mip_levels, 1); d3d_desc.SampleDesc.Count = 1; d3d_desc.SampleDesc.Quality = 0; d3d_desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS * AnyBit(desc.flags, GPU_ResourceFlag_AllowShaderReadWrite); @@ -1329,22 +1406,28 @@ GPU_ResourceHandle GPU_PushTextureEx(GPU_ArenaHandle arena_handle, GPU_TextureDe GPU_D12_Resource *resource = PushStruct(gpu_arena->arena, GPU_D12_Resource); resource->d3d_resource = d3d_resource; - resource->uid = Atomic64FetchAdd(&g->resource_creation_gen.v, 1) + 1; - resource->flags = desc.flags; + resource->uid = Atomic64FetchAdd(&g->resource_creation_gen.v, 1) + 1; + resource->flags = desc.flags; - resource->is_texture = 1; - resource->texture_format = desc.format; - resource->texture_dims = desc.dims; + resource->is_texture = 1; + resource->texture_format = desc.format; + resource->texture_dims = desc.dims; resource->texture_mip_levels = desc.mip_levels; - resource->texture_layout = initial_layout; + resource->texture_layout = initial_layout; - return GPU_D12_HandleFromPointer(GPU_ResourceHandle, resource); + return GPU_D12_MakeHandle(GPU_ResourceHandle, resource); } -GPU_ResourceHandle GPU_PushSampler(GPU_ArenaHandle arena, GPU_SamplerDesc desc) +GPU_ResourceHandle GPU_PushSampler(GPU_ArenaHandle arena_handle, GPU_SamplerDesc desc) { - /* TODO */ - return GPU_D12_HandleFromPointer(GPU_ResourceHandle, 0); + GPU_D12_SharedState *g = &GPU_D12_shared_state; + GPU_D12_Arena *gpu_arena = GPU_D12_ArenaFromHandle(arena_handle); + + GPU_D12_Resource *resource = PushStruct(gpu_arena->arena, GPU_D12_Resource); + resource->uid = Atomic64FetchAdd(&g->resource_creation_gen.v, 1) + 1; + resource->sampler_desc = desc; + + return GPU_D12_MakeHandle(GPU_ResourceHandle, resource); } b32 GPU_IsResourceNil(GPU_ResourceHandle handle) @@ -1354,34 +1437,64 @@ b32 GPU_IsResourceNil(GPU_ResourceHandle handle) //- Pointer creation -StructuredBufferHandle GPU_PushStructuredBufferHandleEx(GPU_ArenaHandle arena, GPU_ResourceHandle resource, u32 element_size, RngU32 element_range) +StructuredBufferHandle GPU_PushStructuredBufferHandleEx(GPU_ArenaHandle arena_handle, GPU_ResourceHandle resource_handle, u32 element_size, RngU32 element_range) { - /* TODO */ - return GPU_D12_HandleFromPointer(StructuredBufferHandle, 0); + GPU_D12_SharedState *g = &GPU_D12_shared_state; + GPU_D12_Arena *gpu_arena = GPU_D12_ArenaFromHandle(arena_handle); + GPU_D12_Resource *resource = GPU_D12_ResourceFromHandle(resource_handle); + GPU_D12_Descriptor *descriptor = GPU_D12_PushDescriptor(gpu_arena, GPU_D12_DescriptorHeapKind_CbvSrvUav); + { + D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc = ZI; + srv_desc.Format = DXGI_FORMAT_UNKNOWN; + srv_desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; + srv_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + srv_desc.Buffer.FirstElement = element_range.min; + srv_desc.Buffer.NumElements = element_range.max - element_range.min; + srv_desc.Buffer.StructureByteStride = element_size; + srv_desc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE; + ID3D12Device_CreateShaderResourceView(g->device, resource->d3d_resource, &srv_desc, descriptor->handle); + } + return GPU_D12_MakeHandle(StructuredBufferHandle, descriptor->index); } -RWStructuredBufferHandle GPU_PushRWStructuredBufferHandleEx(GPU_ArenaHandle arena, GPU_ResourceHandle resource, u32 element_size, RngU32 element_range) +RWStructuredBufferHandle GPU_PushRWStructuredBufferHandleEx(GPU_ArenaHandle arena_handle, GPU_ResourceHandle resource_handle, u32 element_size, RngU32 element_range) { - /* TODO */ - return GPU_D12_HandleFromPointer(RWStructuredBufferHandle, 0); + GPU_D12_SharedState *g = &GPU_D12_shared_state; + GPU_D12_Arena *gpu_arena = GPU_D12_ArenaFromHandle(arena_handle); + GPU_D12_Resource *resource = GPU_D12_ResourceFromHandle(resource_handle); + GPU_D12_Descriptor *descriptor = GPU_D12_PushDescriptor(gpu_arena, GPU_D12_DescriptorHeapKind_CbvSrvUav); + ID3D12Device_CreateUnorderedAccessView(g->device, resource->d3d_resource, 0, 0, descriptor->handle); + return GPU_D12_MakeHandle(RWStructuredBufferHandle, descriptor->index); } -Texture1DHandle GPU_PushTexture1DHandle(GPU_ArenaHandle arena, GPU_ResourceHandle resource) +Texture1DHandle GPU_PushTexture1DHandle(GPU_ArenaHandle arena_handle, GPU_ResourceHandle resource_handle) { - /* TODO */ - return GPU_D12_HandleFromPointer(Texture1DHandle, 0); + GPU_D12_SharedState *g = &GPU_D12_shared_state; + GPU_D12_Arena *gpu_arena = GPU_D12_ArenaFromHandle(arena_handle); + GPU_D12_Resource *resource = GPU_D12_ResourceFromHandle(resource_handle); + GPU_D12_Descriptor *descriptor = GPU_D12_PushDescriptor(gpu_arena, GPU_D12_DescriptorHeapKind_CbvSrvUav); + ID3D12Device_CreateShaderResourceView(g->device, resource->d3d_resource, 0, descriptor->handle); + return GPU_D12_MakeHandle(Texture1DHandle, descriptor->index); } -RWTexture1DHandle GPU_PushRWTexture1DHandle(GPU_ArenaHandle arena, GPU_ResourceHandle resource) +RWTexture1DHandle GPU_PushRWTexture1DHandle(GPU_ArenaHandle arena_handle, GPU_ResourceHandle resource_handle) { - /* TODO */ - return GPU_D12_HandleFromPointer(RWTexture1DHandle, 0); + GPU_D12_SharedState *g = &GPU_D12_shared_state; + GPU_D12_Arena *gpu_arena = GPU_D12_ArenaFromHandle(arena_handle); + GPU_D12_Resource *resource = GPU_D12_ResourceFromHandle(resource_handle); + GPU_D12_Descriptor *descriptor = GPU_D12_PushDescriptor(gpu_arena, GPU_D12_DescriptorHeapKind_CbvSrvUav); + ID3D12Device_CreateUnorderedAccessView(g->device, resource->d3d_resource, 0, 0, descriptor->handle); + return GPU_D12_MakeHandle(RWTexture1DHandle, descriptor->index); } -Texture2DHandle GPU_PushTexture2DHandle(GPU_ArenaHandle arena, GPU_ResourceHandle resource) +Texture2DHandle GPU_PushTexture2DHandle(GPU_ArenaHandle arena_handle, GPU_ResourceHandle resource_handle) { - /* TODO */ - return GPU_D12_HandleFromPointer(Texture2DHandle, 0); + GPU_D12_SharedState *g = &GPU_D12_shared_state; + GPU_D12_Arena *gpu_arena = GPU_D12_ArenaFromHandle(arena_handle); + GPU_D12_Resource *resource = GPU_D12_ResourceFromHandle(resource_handle); + GPU_D12_Descriptor *descriptor = GPU_D12_PushDescriptor(gpu_arena, GPU_D12_DescriptorHeapKind_CbvSrvUav); + ID3D12Device_CreateShaderResourceView(g->device, resource->d3d_resource, 0, descriptor->handle); + return GPU_D12_MakeHandle(Texture2DHandle, descriptor->index); } RWTexture2DHandle GPU_PushRWTexture2DHandle(GPU_ArenaHandle arena_handle, GPU_ResourceHandle resource_handle) @@ -1391,25 +1504,65 @@ RWTexture2DHandle GPU_PushRWTexture2DHandle(GPU_ArenaHandle arena_handle, GPU_Re GPU_D12_Resource *resource = GPU_D12_ResourceFromHandle(resource_handle); GPU_D12_Descriptor *descriptor = GPU_D12_PushDescriptor(gpu_arena, GPU_D12_DescriptorHeapKind_CbvSrvUav); ID3D12Device_CreateUnorderedAccessView(g->device, resource->d3d_resource, 0, 0, descriptor->handle); - return GPU_D12_HandleFromPointer(RWTexture2DHandle, descriptor->index); + return GPU_D12_MakeHandle(RWTexture2DHandle, descriptor->index); } -Texture3DHandle GPU_PushTexture3DHandle(GPU_ArenaHandle arena, GPU_ResourceHandle resource) +Texture3DHandle GPU_PushTexture3DHandle(GPU_ArenaHandle arena_handle, GPU_ResourceHandle resource_handle) { - /* TODO */ - return GPU_D12_HandleFromPointer(Texture3DHandle, 0); + GPU_D12_SharedState *g = &GPU_D12_shared_state; + GPU_D12_Arena *gpu_arena = GPU_D12_ArenaFromHandle(arena_handle); + GPU_D12_Resource *resource = GPU_D12_ResourceFromHandle(resource_handle); + GPU_D12_Descriptor *descriptor = GPU_D12_PushDescriptor(gpu_arena, GPU_D12_DescriptorHeapKind_CbvSrvUav); + ID3D12Device_CreateShaderResourceView(g->device, resource->d3d_resource, 0, descriptor->handle); + return GPU_D12_MakeHandle(Texture3DHandle, descriptor->index); } -RWTexture3DHandle GPU_PushRWTexture3DHandle(GPU_ArenaHandle arena, GPU_ResourceHandle resource) +RWTexture3DHandle GPU_PushRWTexture3DHandle(GPU_ArenaHandle arena_handle, GPU_ResourceHandle resource_handle) { - /* TODO */ - return GPU_D12_HandleFromPointer(RWTexture3DHandle, 0); + GPU_D12_SharedState *g = &GPU_D12_shared_state; + GPU_D12_Arena *gpu_arena = GPU_D12_ArenaFromHandle(arena_handle); + GPU_D12_Resource *resource = GPU_D12_ResourceFromHandle(resource_handle); + GPU_D12_Descriptor *descriptor = GPU_D12_PushDescriptor(gpu_arena, GPU_D12_DescriptorHeapKind_CbvSrvUav); + ID3D12Device_CreateUnorderedAccessView(g->device, resource->d3d_resource, 0, 0, descriptor->handle); + return GPU_D12_MakeHandle(RWTexture3DHandle, descriptor->index); } -SamplerStateHandle GPU_PushSamplerStateHandle(GPU_ArenaHandle arena, GPU_ResourceHandle resource) +SamplerStateHandle GPU_PushSamplerStateHandle(GPU_ArenaHandle arena_handle, GPU_ResourceHandle resource_handle) { - /* TODO */ - return GPU_D12_HandleFromPointer(SamplerStateHandle, 0); + GPU_D12_SharedState *g = &GPU_D12_shared_state; + GPU_D12_Arena *gpu_arena = GPU_D12_ArenaFromHandle(arena_handle); + GPU_D12_Resource *resource = GPU_D12_ResourceFromHandle(resource_handle); + GPU_D12_Descriptor *descriptor = GPU_D12_PushDescriptor(gpu_arena, GPU_D12_DescriptorHeapKind_Sampler); + { + GPU_SamplerDesc sampler_desc = resource->sampler_desc; + + D3D12_SAMPLER_DESC d3d_desc = ZI; + d3d_desc.Filter = (D3D12_FILTER)sampler_desc.filter; + d3d_desc.AddressU = (D3D12_TEXTURE_ADDRESS_MODE)sampler_desc.x; + d3d_desc.AddressV = (D3D12_TEXTURE_ADDRESS_MODE)sampler_desc.y; + d3d_desc.AddressW = (D3D12_TEXTURE_ADDRESS_MODE)sampler_desc.z; + d3d_desc.MipLODBias = sampler_desc.mip_lod_bias; + d3d_desc.MaxAnisotropy = MaxU32(sampler_desc.max_anisotropy, 1); + d3d_desc.ComparisonFunc = (D3D12_COMPARISON_FUNC)sampler_desc.comparison; + d3d_desc.BorderColor[0] = sampler_desc.border_color.x; + d3d_desc.BorderColor[1] = sampler_desc.border_color.y; + d3d_desc.BorderColor[2] = sampler_desc.border_color.z; + d3d_desc.BorderColor[3] = sampler_desc.border_color.w; + d3d_desc.MinLOD = sampler_desc.min_lod; + d3d_desc.MaxLOD = sampler_desc.max_lod; + + /* Defaults */ + if (d3d_desc.AddressU == 0) d3d_desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + if (d3d_desc.AddressV == 0) d3d_desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + if (d3d_desc.AddressW == 0) d3d_desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + if (d3d_desc.MaxLOD >= F32Infinity) + { + d3d_desc.MaxLOD = D3D12_FLOAT32_MAX; + } + + ID3D12Device_CreateSampler(g->device, &d3d_desc, descriptor->handle); + } + return GPU_D12_MakeHandle(SamplerStateHandle, descriptor->index); } //- Count @@ -1739,7 +1892,7 @@ GPU_CommandListHandle GPU_PrepareCommandList(GPU_QueueKind queue) Unlock(&lock); cl->queue_kind = queue; - return GPU_D12_HandleFromPointer(GPU_CommandListHandle, cl); + return GPU_D12_MakeHandle(GPU_CommandListHandle, cl); } void GPU_CommitCommandListEx(GPU_CommandListHandle cl_handle, u64 fence_ops_count, GPU_FenceOp *fence_ops) @@ -1837,11 +1990,6 @@ void GPU_CommitCommandListEx(GPU_CommandListHandle cl_handle, u64 fence_ops_coun /* This barrier is part of new batch */ prev_barrier_cmd->barrier.is_end_of_batch = 1; } - else - { - /* Barriers can be batched */ - prev_barrier_cmd->skip = 1; - } } cmd->barrier.batch_gen = batch_gen; prev_barrier_cmd = cmd; @@ -1865,494 +2013,499 @@ void GPU_CommitCommandListEx(GPU_CommandListHandle cl_handle, u64 fence_ops_coun while (cmd_idx < cmds_count) { GPU_D12_Cmd *cmd = &cmds[cmd_idx]; - if (cmd->skip) + switch (cmd->kind) { - cmd_idx += 1; - } - else - { - switch (cmd->kind) + default: { - default: - { - cmd_idx += 1; - } break; + cmd_idx += 1; + } break; - //- Constant - case GPU_D12_CmdKind_Constant: + //- Constant + case GPU_D12_CmdKind_Constant: + { + i32 slot = cmd->constant.slot; + u32 value = cmd->constant.value; + if (slot >= 0 && slot < countof(slotted_constants)) { - i32 slot = cmd->constant.slot; - u32 value = cmd->constant.value; - if (slot >= 0 && slot < countof(slotted_constants)) + slotted_constants[slot] = value; + } + cmd_idx += 1; + } break; + + //- Barrier + + case GPU_D12_CmdKind_Barrier: + { + batch_barrier_idx_opl = cmd_idx + 1; + + /* Submit batched barriers */ + if (cmd->barrier.is_end_of_batch) + { + /* Build barriers */ + u64 buffer_barriers_count = 0; + u64 texture_barriers_count = 0; + u64 global_barriers_count = 0; + D3D12_BUFFER_BARRIER *buffer_barriers = PushStructs(scratch.arena, D3D12_BUFFER_BARRIER, (batch_barrier_idx_opl - batch_barrier_idx_start)); + D3D12_TEXTURE_BARRIER *texture_barriers = PushStructs(scratch.arena, D3D12_TEXTURE_BARRIER, (batch_barrier_idx_opl - batch_barrier_idx_start)); + D3D12_GLOBAL_BARRIER *global_barriers = PushStructs(scratch.arena, D3D12_GLOBAL_BARRIER, (batch_barrier_idx_opl - batch_barrier_idx_start)); + for (u64 barrier_cmd_idx = batch_barrier_idx_start; barrier_cmd_idx < batch_barrier_idx_opl; ++barrier_cmd_idx) { - slotted_constants[slot] = value; - } - cmd_idx += 1; - } break; - - //- Barrier - - case GPU_D12_CmdKind_Barrier: - { - batch_barrier_idx_opl = cmd_idx + 1; - - /* Submit batched barriers */ - if (cmd->barrier.is_end_of_batch) - { - /* Build barriers */ - u64 buffer_barriers_count = 0; - u64 texture_barriers_count = 0; - u64 global_barriers_count = 0; - D3D12_BUFFER_BARRIER *buffer_barriers = PushStructs(scratch.arena, D3D12_BUFFER_BARRIER, (batch_barrier_idx_opl - batch_barrier_idx_start)); - D3D12_TEXTURE_BARRIER *texture_barriers = PushStructs(scratch.arena, D3D12_TEXTURE_BARRIER, (batch_barrier_idx_opl - batch_barrier_idx_start)); - D3D12_GLOBAL_BARRIER *global_barriers = PushStructs(scratch.arena, D3D12_GLOBAL_BARRIER, (batch_barrier_idx_opl - batch_barrier_idx_start)); - for (u64 barrier_cmd_idx = batch_barrier_idx_start; barrier_cmd_idx < batch_barrier_idx_opl; ++barrier_cmd_idx) + GPU_D12_Cmd *barrier_cmd = &cmds[barrier_cmd_idx]; + if (barrier_cmd->kind == GPU_D12_CmdKind_Barrier) { - GPU_D12_Cmd *barrier_cmd = &cmds[barrier_cmd_idx]; - if (barrier_cmd->kind == GPU_D12_CmdKind_Barrier && !barrier_cmd->skip) - { - GPU_BarrierDesc desc = barrier_cmd->barrier.desc; - GPU_D12_Resource *resource = GPU_D12_ResourceFromHandle(desc.resource); - D3D12_BARRIER_TYPE barrier_type = resource->is_texture ? D3D12_BARRIER_TYPE_TEXTURE : D3D12_BARRIER_TYPE_BUFFER; + GPU_BarrierDesc desc = barrier_cmd->barrier.desc; + GPU_D12_Resource *resource = GPU_D12_ResourceFromHandle(desc.resource); + D3D12_BARRIER_TYPE barrier_type = resource->is_texture ? D3D12_BARRIER_TYPE_TEXTURE : D3D12_BARRIER_TYPE_BUFFER; - /* Translate gpu barrier kind -> d3d barrier fields */ - D3D12_BARRIER_SYNC sync_before = GPU_D12_BarrierSyncFromStages(desc.sync_prev); - D3D12_BARRIER_SYNC sync_after = GPU_D12_BarrierSyncFromStages(desc.sync_next); - D3D12_BARRIER_ACCESS access_before = GPU_D12_BarrierAccessFromAccesses(desc.access_prev); - D3D12_BARRIER_ACCESS access_after = GPU_D12_BarrierAccessFromAccesses(desc.access_next); - D3D12_BARRIER_LAYOUT layout_before = D3D12_BARRIER_LAYOUT_UNDEFINED; - D3D12_BARRIER_LAYOUT layout_after = D3D12_BARRIER_LAYOUT_UNDEFINED; - if (desc.layout != GPU_Layout_NoChange) + /* Translate gpu barrier kind -> d3d barrier fields */ + D3D12_BARRIER_SYNC sync_before = GPU_D12_BarrierSyncFromStages(desc.sync_prev); + D3D12_BARRIER_SYNC sync_after = GPU_D12_BarrierSyncFromStages(desc.sync_next); + D3D12_BARRIER_ACCESS access_before = GPU_D12_BarrierAccessFromAccesses(desc.access_prev); + D3D12_BARRIER_ACCESS access_after = GPU_D12_BarrierAccessFromAccesses(desc.access_next); + D3D12_BARRIER_LAYOUT layout_before = resource->texture_layout; + D3D12_BARRIER_LAYOUT layout_after = resource->texture_layout; + if (desc.layout != GPU_Layout_NoChange) + { + layout_after = GPU_D12_BarrierLayoutFromLayout(desc.layout); + resource->texture_layout = layout_after; + } + + /* Build barrier */ + switch (barrier_type) + { + case D3D12_BARRIER_TYPE_BUFFER: { - layout_before = resource->texture_layout; - layout_after = GPU_D12_BarrierLayoutFromLayout(desc.layout); - resource->texture_layout = layout_after; - } + D3D12_BUFFER_BARRIER *barrier = &buffer_barriers[buffer_barriers_count++]; + barrier->SyncBefore = sync_before; + barrier->SyncAfter = sync_after; + barrier->AccessBefore = access_before; + barrier->AccessAfter = access_after; + barrier->pResource = resource->d3d_resource; + barrier->Offset = 0; + barrier->Size = U64Max; + } break; - /* Build barrier */ - switch (barrier_type) + case D3D12_BARRIER_TYPE_TEXTURE: { - case D3D12_BARRIER_TYPE_BUFFER: - { - D3D12_BUFFER_BARRIER *barrier = &buffer_barriers[buffer_barriers_count++]; - barrier->SyncBefore = sync_before; - barrier->SyncAfter = sync_after; - barrier->AccessBefore = access_before; - barrier->AccessAfter = access_after; - barrier->pResource = resource->d3d_resource; - barrier->Offset = 0; - barrier->Size = U64Max; - } break; + D3D12_TEXTURE_BARRIER *barrier = &texture_barriers[texture_barriers_count++]; + barrier->SyncBefore = sync_before; + barrier->SyncAfter = sync_after; + barrier->AccessBefore = access_before; + barrier->AccessAfter = access_after; + barrier->LayoutBefore = layout_before; + barrier->LayoutAfter = layout_after; + barrier->pResource = resource->d3d_resource; + barrier->Subresources.IndexOrFirstMipLevel = 0xffffffff; + } break; - case D3D12_BARRIER_TYPE_TEXTURE: - { - D3D12_TEXTURE_BARRIER *barrier = &texture_barriers[texture_barriers_count++]; - barrier->SyncBefore = sync_before; - barrier->SyncAfter = sync_after; - barrier->AccessBefore = access_before; - barrier->AccessAfter = access_after; - barrier->LayoutBefore = layout_before; - barrier->LayoutAfter = layout_after; - barrier->pResource = resource->d3d_resource; - barrier->Subresources.IndexOrFirstMipLevel = 0xffffffff; - } break; - - case D3D12_BARRIER_TYPE_GLOBAL: - { - D3D12_GLOBAL_BARRIER *barrier = &global_barriers[global_barriers_count++]; - barrier->SyncBefore = sync_before; - barrier->SyncAfter = sync_after; - barrier->AccessBefore = access_before; - barrier->AccessAfter = access_after; - } break; - } + case D3D12_BARRIER_TYPE_GLOBAL: + { + D3D12_GLOBAL_BARRIER *barrier = &global_barriers[global_barriers_count++]; + barrier->SyncBefore = sync_before; + barrier->SyncAfter = sync_after; + barrier->AccessBefore = access_before; + barrier->AccessAfter = access_after; + } break; } } - - /* Dispatch barriers */ - { - u32 barrier_groups_count = 0; - D3D12_BARRIER_GROUP barrier_groups[3] = ZI; - if (buffer_barriers_count > 0) - { - D3D12_BARRIER_GROUP *group = &barrier_groups[barrier_groups_count++]; - group->Type = D3D12_BARRIER_TYPE_BUFFER; - group->NumBarriers = buffer_barriers_count; - group->pBufferBarriers = buffer_barriers; - } - if (texture_barriers_count > 0) - { - D3D12_BARRIER_GROUP *group = &barrier_groups[barrier_groups_count++]; - group->Type = D3D12_BARRIER_TYPE_TEXTURE; - group->NumBarriers = texture_barriers_count; - group->pTextureBarriers = texture_barriers; - } - if (global_barriers_count > 0) - { - D3D12_BARRIER_GROUP *group = &barrier_groups[barrier_groups_count++]; - group->Type = D3D12_BARRIER_TYPE_GLOBAL; - group->NumBarriers = global_barriers_count; - group->pGlobalBarriers = global_barriers; - } - if (barrier_groups_count > 0) - { - ID3D12GraphicsCommandList7_Barrier(d3d_cl, barrier_groups_count, barrier_groups); - } - } - - batch_barrier_idx_start = cmd_idx + 1; } - cmd_idx += 1; - } break; + /* Dispatch barriers */ + { + u32 barrier_groups_count = 0; + D3D12_BARRIER_GROUP barrier_groups[3] = ZI; + if (buffer_barriers_count > 0) + { + D3D12_BARRIER_GROUP *group = &barrier_groups[barrier_groups_count++]; + group->Type = D3D12_BARRIER_TYPE_BUFFER; + group->NumBarriers = buffer_barriers_count; + group->pBufferBarriers = buffer_barriers; + } + if (texture_barriers_count > 0) + { + D3D12_BARRIER_GROUP *group = &barrier_groups[barrier_groups_count++]; + group->Type = D3D12_BARRIER_TYPE_TEXTURE; + group->NumBarriers = texture_barriers_count; + group->pTextureBarriers = texture_barriers; + } + if (global_barriers_count > 0) + { + D3D12_BARRIER_GROUP *group = &barrier_groups[barrier_groups_count++]; + group->Type = D3D12_BARRIER_TYPE_GLOBAL; + group->NumBarriers = global_barriers_count; + group->pGlobalBarriers = global_barriers; + } + if (barrier_groups_count > 0) + { + ID3D12GraphicsCommandList7_Barrier(d3d_cl, barrier_groups_count, barrier_groups); + } + } - //- Copy resource + batch_barrier_idx_start = cmd_idx + 1; + } - // case GPU_D12_CmdKind_Copy: - // { - // GPU_D12_Resource *dst = cmd->copy.dst; - // GPU_D12_Resource *src = cmd->copy.src; + cmd_idx += 1; + } break; - // D3D12_RESOURCE_DESC dst_desc = ZI; - // D3D12_RESOURCE_DESC src_desc = ZI; - // ID3D12Resource_GetDesc(dst->d3d_resource, &dst_desc); - // ID3D12Resource_GetDesc(src->d3d_resource, &src_desc); + //- Copy bytes + case GPU_D12_CmdKind_CopyBytes: + { + u64 copy_size = cmd->copy_bytes.src_copy_range.max - cmd->copy_bytes.src_copy_range.min; + ID3D12GraphicsCommandList_CopyBufferRegion(d3d_cl, + cmd->copy_bytes.dst->d3d_resource, + cmd->copy_bytes.dst_offset, + cmd->copy_bytes.src->d3d_resource, + cmd->copy_bytes.src_copy_range.min, + copy_size); + cmd_idx += 1; + } break; - // if (dst_desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && src_desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) - // { /* Copy buffer -> buffer */ - // u64 dst_len = dst->desc.buffer.count * dst->desc.buffer.stride; - // u64 src_len = src->desc.buffer.count * src->desc.buffer.stride; - // u64 cpy_len = MinU64(dst_len, src_len); - // if (cpy_len > 0) - // { - // ID3D12GraphicsCommandList_CopyBufferRegion(d3d_cl, dst->d3d_resource, 0, src->d3d_resource, 0, cpy_len); - // /* Implicit promotion */ - // if (dst->state == D3D12_RESOURCE_STATE_COMMON) dst->state = D3D12_RESOURCE_STATE_COPY_DEST; - // if (src->state == D3D12_RESOURCE_STATE_COMMON) src->state = D3D12_RESOURCE_STATE_COPY_SOURCE; - // } - // } - // else if (src_desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) - // { /* Copy buffer -> texture */ - // D3D12_PLACED_SUBRESOURCE_FOOTPRINT dst_placed_footprint = ZI; - // ID3D12Device_GetCopyableFootprints(g->device, &dst_desc, 0, 1, 0, &dst_placed_footprint, 0, 0, 0); + //- Copy resource - // D3D12_TEXTURE_COPY_LOCATION dst_loc = ZI; - // dst_loc.pResource = dst->d3d_resource; - // dst_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - // dst_loc.SubresourceIndex = 0; + // case GPU_D12_CmdKind_Copy: + // { + // GPU_D12_Resource *dst = cmd->copy.dst; + // GPU_D12_Resource *src = cmd->copy.src; - // D3D12_TEXTURE_COPY_LOCATION src_loc = ZI; - // src_loc.pResource = src->d3d_resource; - // src_loc.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - // src_loc.PlacedFootprint = dst_placed_footprint; + // D3D12_RESOURCE_DESC dst_desc = ZI; + // D3D12_RESOURCE_DESC src_desc = ZI; + // ID3D12Resource_GetDesc(dst->d3d_resource, &dst_desc); + // ID3D12Resource_GetDesc(src->d3d_resource, &src_desc); - // ID3D12GraphicsCommandList_CopyTextureRegion(d3d_cl, &dst_loc, 0, 0, 0, &src_loc, 0); - // /* Implicit promotion */ - // if (dst->state == D3D12_RESOURCE_STATE_COMMON) dst->state = D3D12_RESOURCE_STATE_COPY_DEST; - // if (src->state == D3D12_RESOURCE_STATE_COMMON) src->state = D3D12_RESOURCE_STATE_COPY_SOURCE; - // } - // else if (dst_desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) - // { /* Copy texture -> buffer */ - // /* TODO */ - // Assert(0); - // } - // else if (dst_desc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER && src_desc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER) - // { /* Copy texture -> texture */ - // /* TODO */ - // Assert(0); - // } + // if (dst_desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && src_desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + // { /* Copy buffer -> buffer */ + // u64 dst_len = dst->desc.buffer.count * dst->desc.buffer.stride; + // u64 src_len = src->desc.buffer.count * src->desc.buffer.stride; + // u64 cpy_len = MinU64(dst_len, src_len); + // if (cpy_len > 0) + // { + // ID3D12GraphicsCommandList_CopyBufferRegion(d3d_cl, dst->d3d_resource, 0, src->d3d_resource, 0, cpy_len); + // /* Implicit promotion */ + // if (dst->state == D3D12_RESOURCE_STATE_COMMON) dst->state = D3D12_RESOURCE_STATE_COPY_DEST; + // if (src->state == D3D12_RESOURCE_STATE_COMMON) src->state = D3D12_RESOURCE_STATE_COPY_SOURCE; + // } + // } + // else if (src_desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + // { /* Copy buffer -> texture */ + // D3D12_PLACED_SUBRESOURCE_FOOTPRINT dst_placed_footprint = ZI; + // ID3D12Device_GetCopyableFootprints(g->device, &dst_desc, 0, 1, 0, &dst_placed_footprint, 0, 0, 0); - // cmd_idx += 1; - // } break; + // D3D12_TEXTURE_COPY_LOCATION dst_loc = ZI; + // dst_loc.pResource = dst->d3d_resource; + // dst_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + // dst_loc.SubresourceIndex = 0; - //- Compute + // D3D12_TEXTURE_COPY_LOCATION src_loc = ZI; + // src_loc.pResource = src->d3d_resource; + // src_loc.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + // src_loc.PlacedFootprint = dst_placed_footprint; - case GPU_D12_CmdKind_Compute: + // ID3D12GraphicsCommandList_CopyTextureRegion(d3d_cl, &dst_loc, 0, 0, 0, &src_loc, 0); + // /* Implicit promotion */ + // if (dst->state == D3D12_RESOURCE_STATE_COMMON) dst->state = D3D12_RESOURCE_STATE_COPY_DEST; + // if (src->state == D3D12_RESOURCE_STATE_COMMON) src->state = D3D12_RESOURCE_STATE_COPY_SOURCE; + // } + // else if (dst_desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + // { /* Copy texture -> buffer */ + // /* TODO */ + // Assert(0); + // } + // else if (dst_desc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER && src_desc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER) + // { /* Copy texture -> texture */ + // /* TODO */ + // Assert(0); + // } + + // cmd_idx += 1; + // } break; + + //- Compute + + case GPU_D12_CmdKind_Compute: + { + GPU_D12_Pipeline *pipeline = 0; { - GPU_D12_Pipeline *pipeline = 0; - { - GPU_D12_PipelineDesc pipeline_desc = ZI; - pipeline_desc.cs = cmd->compute.cs; - pipeline = GPU_D12_PipelineFromDesc(pipeline_desc); - } + GPU_D12_PipelineDesc pipeline_desc = ZI; + pipeline_desc.cs = cmd->compute.cs; + pipeline = GPU_D12_PipelineFromDesc(pipeline_desc); + } - if (pipeline) - { - /* Set descriptor heaps */ - if (!descriptor_heaps_set) - { - ID3D12DescriptorHeap *heaps[] = { - g->descriptor_heaps[GPU_D12_DescriptorHeapKind_CbvSrvUav].d3d_heap, - g->descriptor_heaps[GPU_D12_DescriptorHeapKind_Sampler].d3d_heap, - }; - ID3D12GraphicsCommandList_SetDescriptorHeaps(d3d_cl, countof(heaps), heaps); - descriptor_heaps_set = 1; - } - - /* Bind rootsig */ - if (!compute_rootsig_set) - { - ID3D12GraphicsCommandList_SetComputeRootSignature(d3d_cl, g->bindless_rootsig); - compute_rootsig_set = 1; - } - - /* Bind pipeline */ - if (pipeline != bound_pipeline) - { - ID3D12GraphicsCommandList_SetPipelineState(d3d_cl, pipeline->pso); - bound_pipeline = pipeline; - } - - /* Update root constants */ - for (i32 slot = 0; slot < MaxShaderConstants; ++slot) - { - if (bound_compute_constants[slot] != slotted_constants[slot]) - { - ID3D12GraphicsCommandList_SetComputeRoot32BitConstant(d3d_cl, slot, slotted_constants[slot], 0); - bound_compute_constants[slot] = slotted_constants[slot]; - } - } - - /* Dispatch */ - ID3D12GraphicsCommandList_Dispatch(d3d_cl, cmd->compute.groups.x, cmd->compute.groups.y, cmd->compute.groups.z); - } - - cmd_idx += 1; - } break; - - //- Rasterize - - case GPU_D12_CmdKind_Rasterize: + if (pipeline) { - GPU_D12_Pipeline *pipeline = 0; + /* Set descriptor heaps */ + if (!descriptor_heaps_set) { - GPU_D12_PipelineDesc pipeline_desc = ZI; - pipeline_desc.vs = cmd->rasterize.vs; - pipeline_desc.ps = cmd->rasterize.ps; + ID3D12DescriptorHeap *heaps[] = { + g->descriptor_heaps[GPU_D12_DescriptorHeapKind_CbvSrvUav].d3d_heap, + g->descriptor_heaps[GPU_D12_DescriptorHeapKind_Sampler].d3d_heap, + }; + ID3D12GraphicsCommandList_SetDescriptorHeaps(d3d_cl, countof(heaps), heaps); + descriptor_heaps_set = 1; + } + + /* Bind rootsig */ + if (!compute_rootsig_set) + { + ID3D12GraphicsCommandList_SetComputeRootSignature(d3d_cl, g->bindless_rootsig); + compute_rootsig_set = 1; + } + + /* Bind pipeline */ + if (pipeline != bound_pipeline) + { + ID3D12GraphicsCommandList_SetPipelineState(d3d_cl, pipeline->pso); + bound_pipeline = pipeline; + } + + /* Update root constants */ + for (i32 slot = 0; slot < MaxShaderConstants; ++slot) + { + if (bound_compute_constants[slot] != slotted_constants[slot]) { - pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED; - switch (cmd->rasterize.mode) - { - default: Assert(0); break; - case GPU_RasterMode_PointList: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT; break; - case GPU_RasterMode_LineList: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; break; - case GPU_RasterMode_LineStrip: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; break; - case GPU_RasterMode_TriangleList: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; break; - case GPU_RasterMode_TriangleStrip: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; break; - case GPU_RasterMode_WireTriangleList: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; break; - case GPU_RasterMode_WireTriangleStrip: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; break; - } + ID3D12GraphicsCommandList_SetComputeRoot32BitConstant(d3d_cl, slot, slotted_constants[slot], 0); + bound_compute_constants[slot] = slotted_constants[slot]; } - if (cmd->rasterize.mode == GPU_RasterMode_WireTriangleList || cmd->rasterize.mode == GPU_RasterMode_WireTriangleStrip) + } + + /* Dispatch */ + ID3D12GraphicsCommandList_Dispatch(d3d_cl, cmd->compute.groups.x, cmd->compute.groups.y, cmd->compute.groups.z); + } + + cmd_idx += 1; + } break; + + //- Rasterize + + case GPU_D12_CmdKind_Rasterize: + { + GPU_D12_Pipeline *pipeline = 0; + { + GPU_D12_PipelineDesc pipeline_desc = ZI; + pipeline_desc.vs = cmd->rasterize.vs; + pipeline_desc.ps = cmd->rasterize.ps; + { + pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED; + switch (cmd->rasterize.mode) { - pipeline_desc.is_wireframe = 1; + default: Assert(0); break; + case GPU_RasterMode_PointList: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT; break; + case GPU_RasterMode_LineList: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; break; + case GPU_RasterMode_LineStrip: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; break; + case GPU_RasterMode_TriangleList: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; break; + case GPU_RasterMode_TriangleStrip: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; break; + case GPU_RasterMode_WireTriangleList: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; break; + case GPU_RasterMode_WireTriangleStrip: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; break; } + } + if (cmd->rasterize.mode == GPU_RasterMode_WireTriangleList || cmd->rasterize.mode == GPU_RasterMode_WireTriangleStrip) + { + pipeline_desc.is_wireframe = 1; + } + for (u32 i = 0; i < countof(cmd->rasterize.render_targets); ++i) + { + GPU_D12_Resource *rt = cmd->rasterize.render_targets[i]; + if (rt) + { + pipeline_desc.render_target_formats[i] = rt->texture_format; + } + else + { + pipeline_desc.render_target_formats[i] = GPU_Format_Unknown; + } + } + pipeline = GPU_D12_PipelineFromDesc(pipeline_desc); + } + + /* Create ibv */ + u32 indices_count = 0; + D3D12_INDEX_BUFFER_VIEW ibv = ZI; + { + GPU_IndexBufferDesc desc = cmd->rasterize.index_buffer_desc; + if (desc.index_count > 0) + { + GPU_D12_Resource *index_buffer_resource = GPU_D12_ResourceFromHandle(desc.resource); + ibv.BufferLocation = index_buffer_resource->buffer_gpu_address; + ibv.SizeInBytes = desc.index_size * desc.index_count; + if (desc.index_size == 2) + { + ibv.Format = DXGI_FORMAT_R16_UINT; + indices_count = ibv.SizeInBytes / 2; + } + else if (desc.index_size == 4) + { + ibv.Format = DXGI_FORMAT_R32_UINT; + indices_count = ibv.SizeInBytes / 4; + } + else + { + Assert(0); /* Invalid index size */ + } + } + } + + /* Prepare & dispatch */ + if (pipeline && indices_count > 0) + { + /* Set descriptor heaps */ + if (!descriptor_heaps_set) + { + ID3D12DescriptorHeap *heaps[] = { + g->descriptor_heaps[GPU_D12_DescriptorHeapKind_CbvSrvUav].d3d_heap, + g->descriptor_heaps[GPU_D12_DescriptorHeapKind_Sampler].d3d_heap, + }; + ID3D12GraphicsCommandList_SetDescriptorHeaps(d3d_cl, countof(heaps), heaps); + descriptor_heaps_set = 1; + } + + /* Bind rootsig */ + if (!graphics_rootsig_set) + { + ID3D12GraphicsCommandList_SetGraphicsRootSignature(d3d_cl, g->bindless_rootsig); + graphics_rootsig_set = 1; + } + + /* Bind pipeline */ + if (pipeline != bound_pipeline) + { + ID3D12GraphicsCommandList_SetPipelineState(d3d_cl, pipeline->pso); + bound_pipeline = pipeline; + } + + /* Update root constants */ + for (i32 slot = 0; slot < MaxShaderConstants; ++slot) + { + if (bound_graphics_constants[slot] != slotted_constants[slot]) + { + ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstant(d3d_cl, slot, slotted_constants[slot], 0); + bound_graphics_constants[slot] = slotted_constants[slot]; + } + } + + /* Set viewport */ + { + D3D12_VIEWPORT viewport = ZI; + { + Rng3 range = cmd->rasterize.viewport; + viewport.TopLeftX = range.p0.x; + viewport.TopLeftY = range.p0.y; + viewport.Width = range.p1.x - range.p0.x; + viewport.Height = range.p1.y - range.p0.y; + viewport.MinDepth = range.p0.z; + viewport.MaxDepth = range.p1.z; + } + if (!MatchStruct(&viewport, &bound_viewport)) + { + bound_viewport = viewport; + ID3D12GraphicsCommandList_RSSetViewports(d3d_cl, 1, &viewport); + } + } + + /* Set scissor */ + { + D3D12_RECT scissor = ZI; + { + Rng2 range = cmd->rasterize.scissor; + scissor.left = range.p0.x; + scissor.top = range.p0.y; + scissor.right = range.p1.x; + scissor.bottom = range.p1.y; + } + if (!MatchStruct(&scissor, &bound_scissor)) + { + bound_scissor = scissor; + ID3D12GraphicsCommandList_RSSetScissorRects(d3d_cl, 1, &scissor); + } + } + + /* Set topology */ + { + D3D_PRIMITIVE_TOPOLOGY topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + switch (cmd->rasterize.mode) + { + default: Assert(0); break; + case GPU_RasterMode_PointList: topology = D3D_PRIMITIVE_TOPOLOGY_POINTLIST; break; + case GPU_RasterMode_LineList: topology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; break; + case GPU_RasterMode_LineStrip: topology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; break; + case GPU_RasterMode_TriangleList: topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; break; + case GPU_RasterMode_TriangleStrip: topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; break; + case GPU_RasterMode_WireTriangleList: topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; break; + case GPU_RasterMode_WireTriangleStrip: topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; break; + } + if (topology != bound_primitive_topology) + { + ID3D12GraphicsCommandList_IASetPrimitiveTopology(d3d_cl, topology); + } + } + + /* Set index buffer */ + if (!MatchStruct(&ibv, &bound_ibv)) + { + ID3D12GraphicsCommandList_IASetIndexBuffer(d3d_cl, &ibv); + bound_ibv = ibv; + } + + /* Bind render targets */ + { + b32 om_dirty = 0; + u32 rtvs_count = 0; for (u32 i = 0; i < countof(cmd->rasterize.render_targets); ++i) { GPU_D12_Resource *rt = cmd->rasterize.render_targets[i]; if (rt) { - pipeline_desc.render_target_formats[i] = rt->texture_format; + if (bound_render_target_uids[i] != rt->uid) + { + GPU_D12_Descriptor *rtv_descriptor = rcl->rtv_descriptors[i]; + ID3D12Device_CreateRenderTargetView(g->device, rt->d3d_resource, 0, rtv_descriptor->handle); + bound_render_target_uids[i] = rt->uid; + om_dirty = 1; + } + ++rtvs_count; } else { - pipeline_desc.render_target_formats[i] = GPU_Format_Unknown; + break; } } - pipeline = GPU_D12_PipelineFromDesc(pipeline_desc); - } - - /* Create ibv */ - u32 indices_count = 0; - D3D12_INDEX_BUFFER_VIEW ibv = ZI; - { - GPU_IndexBufferDesc desc = cmd->rasterize.index_buffer_desc; - if (desc.index_count > 0) + if (om_dirty) { - GPU_D12_Resource *index_buffer_resource = GPU_D12_ResourceFromHandle(desc.resource); - ibv.BufferLocation = index_buffer_resource->buffer_gpu_address; - ibv.SizeInBytes = desc.index_size * desc.index_count; - if (desc.index_size == 2) + D3D12_CPU_DESCRIPTOR_HANDLE rtv_handles[GPU_MaxRenderTargets] = ZI; + for (u32 i = 0; i < rtvs_count; ++i) { - ibv.Format = DXGI_FORMAT_R16_UINT; - indices_count = ibv.SizeInBytes / 2; - } - else if (desc.index_size == 4) - { - ibv.Format = DXGI_FORMAT_R32_UINT; - indices_count = ibv.SizeInBytes / 4; - } - else - { - Assert(0); /* Invalid index size */ + rtv_handles[i] = rcl->rtv_descriptors[i]->handle; } + ID3D12GraphicsCommandList_OMSetRenderTargets(d3d_cl, rtvs_count, rtv_handles, 0, 0); } } - /* Prepare & dispatch */ - if (pipeline && indices_count > 0) - { - /* Set descriptor heaps */ - if (!descriptor_heaps_set) - { - ID3D12DescriptorHeap *heaps[] = { - g->descriptor_heaps[GPU_D12_DescriptorHeapKind_CbvSrvUav].d3d_heap, - g->descriptor_heaps[GPU_D12_DescriptorHeapKind_Sampler].d3d_heap, - }; - ID3D12GraphicsCommandList_SetDescriptorHeaps(d3d_cl, countof(heaps), heaps); - descriptor_heaps_set = 1; - } + /* Dispatch */ + ID3D12GraphicsCommandList_DrawIndexedInstanced(d3d_cl, indices_count, cmd->rasterize.instances_count, 0, 0, 0); + } - /* Bind rootsig */ - if (!graphics_rootsig_set) - { - ID3D12GraphicsCommandList_SetGraphicsRootSignature(d3d_cl, g->bindless_rootsig); - graphics_rootsig_set = 1; - } + cmd_idx += 1; + } break; - /* Bind pipeline */ - if (pipeline != bound_pipeline) - { - ID3D12GraphicsCommandList_SetPipelineState(d3d_cl, pipeline->pso); - bound_pipeline = pipeline; - } + //- Clear rtv - /* Update root constants */ - for (i32 slot = 0; slot < MaxShaderConstants; ++slot) - { - if (bound_graphics_constants[slot] != slotted_constants[slot]) - { - ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstant(d3d_cl, slot, slotted_constants[slot], 0); - bound_graphics_constants[slot] = slotted_constants[slot]; - } - } - - /* Set viewport */ - { - D3D12_VIEWPORT viewport = ZI; - { - Rng3 range = cmd->rasterize.viewport; - viewport.TopLeftX = range.p0.x; - viewport.TopLeftY = range.p0.y; - viewport.Width = range.p1.x - range.p0.x; - viewport.Height = range.p1.y - range.p0.y; - viewport.MinDepth = range.p0.z; - viewport.MaxDepth = range.p1.z; - } - if (!MatchStruct(&viewport, &bound_viewport)) - { - bound_viewport = viewport; - ID3D12GraphicsCommandList_RSSetViewports(d3d_cl, 1, &viewport); - } - } - - /* Set scissor */ - { - D3D12_RECT scissor = ZI; - { - Rng2 range = cmd->rasterize.scissor; - scissor.left = range.p0.x; - scissor.top = range.p0.y; - scissor.right = range.p1.x; - scissor.bottom = range.p1.y; - } - if (!MatchStruct(&scissor, &bound_scissor)) - { - bound_scissor = scissor; - ID3D12GraphicsCommandList_RSSetScissorRects(d3d_cl, 1, &scissor); - } - } - - /* Set topology */ - { - D3D_PRIMITIVE_TOPOLOGY topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - switch (cmd->rasterize.mode) - { - default: Assert(0); break; - case GPU_RasterMode_PointList: topology = D3D_PRIMITIVE_TOPOLOGY_POINTLIST; break; - case GPU_RasterMode_LineList: topology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; break; - case GPU_RasterMode_LineStrip: topology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; break; - case GPU_RasterMode_TriangleList: topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; break; - case GPU_RasterMode_TriangleStrip: topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; break; - case GPU_RasterMode_WireTriangleList: topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; break; - case GPU_RasterMode_WireTriangleStrip: topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; break; - } - if (topology != bound_primitive_topology) - { - ID3D12GraphicsCommandList_IASetPrimitiveTopology(d3d_cl, topology); - } - } - - /* Set index buffer */ - if (!MatchStruct(&ibv, &bound_ibv)) - { - ID3D12GraphicsCommandList_IASetIndexBuffer(d3d_cl, &ibv); - bound_ibv = ibv; - } - - /* Bind render targets */ - { - b32 om_dirty = 0; - u32 rtvs_count = 0; - for (u32 i = 0; i < countof(cmd->rasterize.render_targets); ++i) - { - GPU_D12_Resource *rt = cmd->rasterize.render_targets[i]; - if (rt) - { - if (bound_render_target_uids[i] != rt->uid) - { - GPU_D12_Descriptor *rtv_descriptor = rcl->rtv_descriptors[i]; - ID3D12Device_CreateRenderTargetView(g->device, rt->d3d_resource, 0, rtv_descriptor->handle); - bound_render_target_uids[i] = rt->uid; - om_dirty = 1; - } - ++rtvs_count; - } - else - { - break; - } - } - if (om_dirty) - { - D3D12_CPU_DESCRIPTOR_HANDLE rtv_handles[GPU_MaxRenderTargets] = ZI; - for (u32 i = 0; i < rtvs_count; ++i) - { - rtv_handles[i] = rcl->rtv_descriptors[i]->handle; - } - ID3D12GraphicsCommandList_OMSetRenderTargets(d3d_cl, rtvs_count, rtv_handles, 0, 0); - } - } - - /* Dispatch */ - ID3D12GraphicsCommandList_DrawIndexedInstanced(d3d_cl, indices_count, cmd->rasterize.instances_count, 0, 0, 0); - } - - cmd_idx += 1; - } break; - - //- Clear rtv - - case GPU_D12_CmdKind_ClearRtv: + case GPU_D12_CmdKind_ClearRtv: + { + GPU_D12_Resource *rt = cmd->clear_rtv.render_target; + f32 clear_color[4] = ZI; { - GPU_D12_Resource *rt = cmd->clear_rtv.render_target; - f32 clear_color[4] = ZI; - { - clear_color[0] = cmd->clear_rtv.color.x; - clear_color[1] = cmd->clear_rtv.color.y; - clear_color[2] = cmd->clear_rtv.color.z; - clear_color[3] = cmd->clear_rtv.color.w; - } - D3D12_CPU_DESCRIPTOR_HANDLE rtv_handle = rcl->rtv_clear_descriptor->handle; - if (bound_render_clear_target_uid != rt->uid) - { - ID3D12Device_CreateRenderTargetView(g->device, rt->d3d_resource, 0, rtv_handle); - bound_render_clear_target_uid = rt->uid; - } - ID3D12GraphicsCommandList_ClearRenderTargetView(d3d_cl, rtv_handle, clear_color, 0, 0); - cmd_idx += 1; - } break; - } + clear_color[0] = cmd->clear_rtv.color.x; + clear_color[1] = cmd->clear_rtv.color.y; + clear_color[2] = cmd->clear_rtv.color.z; + clear_color[3] = cmd->clear_rtv.color.w; + } + D3D12_CPU_DESCRIPTOR_HANDLE rtv_handle = rcl->rtv_clear_descriptor->handle; + if (bound_render_clear_target_uid != rt->uid) + { + ID3D12Device_CreateRenderTargetView(g->device, rt->d3d_resource, 0, rtv_handle); + bound_render_clear_target_uid = rt->uid; + } + ID3D12GraphicsCommandList_ClearRenderTargetView(d3d_cl, rtv_handle, clear_color, 0, 0); + cmd_idx += 1; + } break; } } } @@ -2395,7 +2548,7 @@ void GPU_CopyCpuBytes(GPU_CommandListHandle cl_handle, GPU_ResourceHandle dst_ha u64 size = src_copy_range.max - src_copy_range.min; GPU_D12_StagingRegionNode *region = GPU_D12_PushStagingRegion(cl, size); CopyBytes((u8 *)region->heap->mapped + region->pos, (u8 *)src + src_copy_range.min, size); - GPU_CopyBytes(cl_handle, dst_handle, dst_offset, GPU_D12_HandleFromPointer(GPU_ResourceHandle, ®ion->heap->resource), RNGU64(region->pos, region->pos + size)); + GPU_CopyBytes(cl_handle, dst_handle, dst_offset, GPU_D12_MakeHandle(GPU_ResourceHandle, ®ion->heap->resource), RNGU64(region->pos, region->pos + size)); } void GPU_CopyCpuTexels(GPU_CommandListHandle cl, GPU_ResourceHandle dst_handle, Vec3I32 dst_offset, void *cpu_src, Vec3I32 cpu_src_dims, Rng3I32 cpu_src_copy_range) @@ -2465,12 +2618,18 @@ void GPU_CopyCpuTexels(GPU_CommandListHandle cl, GPU_ResourceHandle dst_handle, //- Gpu <-> Gpu copy -void GPU_CopyBytes(GPU_CommandListHandle cl, GPU_ResourceHandle dst, u64 dst_offset, GPU_ResourceHandle src, RngU64 src_copy_range) +void GPU_CopyBytes(GPU_CommandListHandle cl_handle, GPU_ResourceHandle dst_handle, u64 dst_offset, GPU_ResourceHandle src_handle, RngU64 src_copy_range) { - /* TODO */ + GPU_D12_CmdList *cl = GPU_D12_CmdListFromHandle(cl_handle); + GPU_D12_Cmd *cmd = GPU_D12_PushCmd(cl); + cmd->kind = GPU_D12_CmdKind_CopyBytes; + cmd->copy_bytes.dst = GPU_D12_ResourceFromHandle(dst_handle); + cmd->copy_bytes.src = GPU_D12_ResourceFromHandle(src_handle); + cmd->copy_bytes.dst_offset = dst_offset; + cmd->copy_bytes.src_copy_range = src_copy_range; } -void GPU_CopyTexels(GPU_CommandListHandle cl, GPU_ResourceHandle dst, Vec3I32 dst_offset, GPU_ResourceHandle src, Rng3I32 src_copy_range) +void GPU_CopyTexels(GPU_CommandListHandle cl, GPU_ResourceHandle dst_handle, Vec3I32 dst_offset, GPU_ResourceHandle src_handle, Rng3I32 src_copy_range) { /* TODO */ } @@ -2657,7 +2816,7 @@ GPU_SwapchainHandle GPU_AcquireSwapchain(WND_Handle window) swapchain = PushStruct(perm, GPU_D12_Swapchain); } swapchain->window_hwnd = (HWND)WND_OsHandleFromWindow(window); - return GPU_D12_HandleFromPointer(GPU_SwapchainHandle, swapchain); + return GPU_D12_MakeHandle(GPU_SwapchainHandle, swapchain); } void GPU_ReleaseSwapchain(GPU_SwapchainHandle swapchain_handle) @@ -2796,7 +2955,9 @@ GPU_ResourceHandle GPU_PrepareBackbuffer(GPU_SwapchainHandle swapchain_handle, G backbuffer->d3d_resource = d3d_resource; backbuffer->uid = Atomic64FetchAdd(&g->resource_creation_gen.v, 1) + 1; backbuffer->flags = GPU_ResourceFlag_AllowRenderTarget; + backbuffer->is_texture = 1; + backbuffer->texture_format = format; backbuffer->texture_dims = VEC3I32(size.x, size.y, 1); backbuffer->texture_mip_levels = 1; backbuffer->texture_layout = D3D12_BARRIER_LAYOUT_PRESENT; @@ -2825,7 +2986,7 @@ GPU_ResourceHandle GPU_PrepareBackbuffer(GPU_SwapchainHandle swapchain_handle, G cur_backbuffer = &swapchain->backbuffers[backbuffer_idx]; } - return GPU_D12_HandleFromPointer(GPU_ResourceHandle, cur_backbuffer); + return GPU_D12_MakeHandle(GPU_ResourceHandle, cur_backbuffer); } void GPU_CommitBackbuffer(GPU_ResourceHandle backbuffer_handle, i32 vsync) diff --git a/src/gpu/gpu_dx12/gpu_dx12.h b/src/gpu/gpu_dx12/gpu_dx12.h index af6b92d9..d91c5da4 100644 --- a/src/gpu/gpu_dx12/gpu_dx12.h +++ b/src/gpu/gpu_dx12/gpu_dx12.h @@ -124,6 +124,7 @@ Struct(GPU_D12_Arena) Struct(GPU_D12_Resource) { GPU_D12_Resource *next_free; + ID3D12Resource *d3d_resource; u64 uid; GPU_ResourceFlag flags; @@ -139,6 +140,9 @@ Struct(GPU_D12_Resource) i32 texture_mip_levels; D3D12_BARRIER_LAYOUT texture_layout; + /* Sampler info */ + GPU_SamplerDesc sampler_desc; + /* Backbuffer info */ struct GPU_D12_Swapchain *swapchain; }; @@ -229,7 +233,8 @@ Enum(GPU_D12_CmdKind) GPU_D12_CmdKind_None, GPU_D12_CmdKind_Barrier, GPU_D12_CmdKind_Constant, - GPU_D12_CmdKind_Copy, + GPU_D12_CmdKind_CopyBytes, + GPU_D12_CmdKind_CopyTexels, GPU_D12_CmdKind_Compute, GPU_D12_CmdKind_Rasterize, GPU_D12_CmdKind_ClearRtv, @@ -261,8 +266,7 @@ Struct(GPU_D12_Cmd) GPU_D12_Resource *dst; GPU_D12_Resource *src; u64 dst_offset; - u64 src_offset; - u64 size; + RngU64 src_copy_range; } copy_bytes; struct @@ -270,8 +274,7 @@ Struct(GPU_D12_Cmd) GPU_D12_Resource *dst; GPU_D12_Resource *src; Vec3I32 dst_offset; - Vec3I32 src_offset; - Vec3I32 size; + Rng3I32 src_copy_range; } copy_texels; struct @@ -385,7 +388,7 @@ Struct(GPU_D12_SharedState) //////////////////////////////////////////////////////////// //~ Helpers -#define GPU_D12_HandleFromPointer(type, ptr) (type) { .v = (u64)(ptr) } +#define GPU_D12_MakeHandle(type, ptr) (type) { .v = (u64)(ptr) } GPU_D12_Arena *GPU_D12_ArenaFromHandle(GPU_ArenaHandle handle); GPU_D12_CmdList *GPU_D12_CmdListFromHandle(GPU_CommandListHandle handle); diff --git a/src/proto/proto.c b/src/proto/proto.c index cb3fb713..83fbf722 100644 --- a/src/proto/proto.c +++ b/src/proto/proto.c @@ -68,7 +68,6 @@ JobImpl(PT_RunForever, _sig, _id) PT_BlitVS, PT_BlitPS, 1, GPU_GetCommonQuadIndices(), backbuffer, GPU_RasterMode_TriangleList); - GPU_ClearRenderTarget(cl, backbuffer, VEC4(1, 0, 0, 1)); } /* Finalize backbuffer layout */ diff --git a/src/proto/proto_shaders.gpu b/src/proto/proto_shaders.gpu index 1765df08..b10811ed 100644 --- a/src/proto/proto_shaders.gpu +++ b/src/proto/proto_shaders.gpu @@ -40,7 +40,6 @@ Struct(PT_BlitPSOutput) VertexShader(PT_BlitVS, PT_BlitPSInput) { Vec2 uv = RectUvFromVertexId(SV_VertexID); - PT_BlitPSInput result; result.SV_Position = Vec4(NdcFromUv(uv).xy, 0, 1); result.src_uv = uv;