From 6f35da3fa6a3d2e4beef0b2eb512461ffc27d3ed Mon Sep 17 00:00:00 2001 From: jacob Date: Sat, 21 Feb 2026 04:22:23 -0600 Subject: [PATCH] command list spam test --- src/gpu/gpu_dx12/gpu_dx12_core.c | 2021 +++++++++++++++++++----------- src/gpu/gpu_dx12/gpu_dx12_core.h | 2 +- 2 files changed, 1325 insertions(+), 698 deletions(-) diff --git a/src/gpu/gpu_dx12/gpu_dx12_core.c b/src/gpu/gpu_dx12/gpu_dx12_core.c index 4c367df8..63deaeff 100644 --- a/src/gpu/gpu_dx12/gpu_dx12_core.c +++ b/src/gpu/gpu_dx12/gpu_dx12_core.c @@ -58,7 +58,7 @@ void G_Bootstrap(void) { IDXGIAdapter3 *adapter = 0; ID3D12Device1 *device = 0; - String error = Lit("Could not initialize GPU device."); + String error = Lit("Failed to initialize D3D12 device"); String first_gpu_name = Zi; u32 adapter_index = 0; b32 done = 0; @@ -378,6 +378,11 @@ DXGI_FORMAT G_D12_DxgiFormatFromGpuFormat(G_Format format) return (DXGI_FORMAT)format; } +b32 G_D12_IsSimultaneous(G_D12_Resource *resource) +{ + return AnyBit(resource->d3d_desc.Flags, D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS); +} + void G_D12_InitRtv(G_D12_Resource *resource, D3D12_CPU_DESCRIPTOR_HANDLE rtv_handle, i32 mip) { DXGI_FORMAT format = G_D12_DxgiFormatFromGpuFormat(resource->texture_format); @@ -1816,46 +1821,9 @@ i64 G_CommitCommandList(G_CommandListHandle cl_handle) G_D12_Queue *queue = G_D12_QueueFromKind(queue_kind); TempArena scratch = BeginScratchNoConflict(); - // Begin dx12 command list - G_D12_RawCommandList *rcl = G_D12_PrepareRawCommandList(queue_kind); - ID3D12GraphicsCommandList *d3d_cl = rcl->d3d_cl; - - // Pipeline state - b32 graphics_rootsig_set = 0; - b32 compute_rootsig_set = 0; - b32 descriptor_heaps_set = 0; - G_D12_Pipeline *bound_pipeline = 0; - - // Constants state - u64 slotted_constants[G_NumConstants]; - u64 bound_compute_constants[G_NumConstants]; - u64 bound_graphics_constants[G_NumConstants]; - for (i32 i = 0; i < countof(slotted_constants); ++i) { slotted_constants[i] = 0; } // Zero-initialize all slots - for (i32 i = 0; i < countof(bound_compute_constants); ++i) { bound_compute_constants[i] = U64Max; } - for (i32 i = 0; i < countof(bound_graphics_constants); ++i) { bound_graphics_constants[i] = U64Max; } - - // Fill built-in constants - if (!G_IsRefNil(queue->print_buffer_ref)) - { - slotted_constants[G_ShaderConst_PrintBufferRef] = queue->print_buffer_ref.v; - } - { - b32 tweak_b32 = TweakBool("Shader tweak-bool", 1); - f32 tweak_f32 = TweakFloat("Shader tweak-float", 1, 0, 1); - slotted_constants[G_ShaderConst_TweakB32] = tweak_b32; - slotted_constants[G_ShaderConst_TweakF32] = *(u32 *)&tweak_f32; - } - - // Rasterizer state - D3D12_VIEWPORT bound_viewport = Zi; - D3D12_RECT bound_scissor = Zi; - D3D_PRIMITIVE_TOPOLOGY bound_primitive_topology = -1; - D3D12_INDEX_BUFFER_VIEW bound_ibv = Zi; - u64 bound_render_target_uids[G_MaxRenderTargets] = Zi; - u64 bound_render_clear_target_uid = 0; // Flatten command chunks - u64 cmds_count = 0; + i64 cmds_count = 0; G_D12_Cmd *cmds = PushStructsNoZero(scratch.arena, G_D12_Cmd, cl->cmds_count); { // Flatten command chunks @@ -1884,581 +1852,1244 @@ i64 G_CommitCommandList(G_CommandListHandle cl_handle) } } - // Batch barrier cmds - i64 max_barriers = 0; + Struct(Batch) { - u64 cmd_idx = 0; + Batch *next; + i64 first_cmd_idx; + i64 last_cmd_idx; + i64 actionable_cmds_count; + }; + Batch *first_batch = 0; + Batch *last_batch = 0; + + // Batch barrier cmds + { + Batch *batch = PushStruct(scratch.arena, Batch); + u64 batch_gen = 0; G_D12_Cmd *prev_barrier_cmd = 0; - while (cmd_idx < cmds_count) + for (i64 cmd_idx = 0; cmd_idx < cmds_count; ++cmd_idx) { + b32 should_submit_batch = 0; G_D12_Cmd *cmd = &cmds[cmd_idx]; + batch->last_cmd_idx = cmd_idx; switch (cmd->kind) { // Batch-interrupting cmds default: { - cmd_idx += 1; + batch->actionable_cmds_count += 1; batch_gen += 1; } break; // Non-batch-interrupting cmds case G_D12_CmdKind_Constant: { - cmd_idx += 1; } break; case G_D12_CmdKind_Barrier: { // Determine 'before' state from lookup - if (prev_barrier_cmd) + if (!prev_barrier_cmd || prev_barrier_cmd->barrier.batch_gen != batch_gen) { - if (prev_barrier_cmd->barrier.batch_gen != batch_gen) - { - // This barrier is part of new batch - prev_barrier_cmd->barrier.should_commit = 1; - } + // This barrier signals end of batch + should_submit_batch = 1; } + cmd->barrier.batch_gen = batch_gen; prev_barrier_cmd = cmd; - max_barriers += 1; - - cmd_idx += 1; } break; } + if (should_submit_batch && batch->actionable_cmds_count > 0) + { + SllQueuePush(first_batch, last_batch, batch); + batch = PushStruct(scratch.arena, Batch); + batch->first_cmd_idx = cmd_idx + 1; + batch->last_cmd_idx = cmd_idx + 1; + } } - - if (prev_barrier_cmd) + if (batch->actionable_cmds_count > 0) { - prev_barrier_cmd->barrier.should_commit = 1; + SllQueuePush(first_batch, last_batch, batch); } } - // Build d3d commands + + + + + + // FIXME: We need to global lock so barriers don't allow other work to slip in + + + + + + + + + + + + + + u64 slotted_constants[G_NumConstants]; + for (i32 i = 0; i < countof(slotted_constants); ++i) { slotted_constants[i] = 0; } // Zero-initialize all slots + + i64 completion_target = 0; + for (Batch *batch = first_batch; batch; batch = batch->next) { - u64 cmd_idx = 0; - while (cmd_idx < cmds_count) + // Begin dx12 command list + G_D12_RawCommandList *rcl = G_D12_PrepareRawCommandList(queue_kind); + ID3D12GraphicsCommandList *d3d_cl = rcl->d3d_cl; + + // Pipeline state + b32 graphics_rootsig_set = 0; + b32 compute_rootsig_set = 0; + b32 descriptor_heaps_set = 0; + G_D12_Pipeline *bound_pipeline = 0; + + // Constants state + u64 bound_compute_constants[G_NumConstants]; + u64 bound_graphics_constants[G_NumConstants]; + for (i32 i = 0; i < countof(bound_compute_constants); ++i) { bound_compute_constants[i] = U64Max; } + for (i32 i = 0; i < countof(bound_graphics_constants); ++i) { bound_graphics_constants[i] = U64Max; } + + // Fill built-in constants + if (!G_IsRefNil(queue->print_buffer_ref)) { - G_D12_Cmd *cmd = &cmds[cmd_idx]; - switch (cmd->kind) + slotted_constants[G_ShaderConst_PrintBufferRef] = queue->print_buffer_ref.v; + } + { + b32 tweak_b32 = TweakBool("Shader tweak-bool", 1); + f32 tweak_f32 = TweakFloat("Shader tweak-float", 1, 0, 1); + slotted_constants[G_ShaderConst_TweakB32] = tweak_b32; + slotted_constants[G_ShaderConst_TweakF32] = *(u32 *)&tweak_f32; + } + + // Rasterizer state + D3D12_VIEWPORT bound_viewport = Zi; + D3D12_RECT bound_scissor = Zi; + D3D_PRIMITIVE_TOPOLOGY bound_primitive_topology = -1; + D3D12_INDEX_BUFFER_VIEW bound_ibv = Zi; + u64 bound_render_target_uids[G_MaxRenderTargets] = Zi; + u64 bound_render_clear_target_uid = 0; + + // Build d3d commands + { + for (i64 cmd_idx = batch->first_cmd_idx; cmd_idx <= batch->last_cmd_idx; ++cmd_idx) { - default: + G_D12_Cmd *cmd = &cmds[cmd_idx]; + switch (cmd->kind) { - cmd_idx += 1; - } break; - - //- Constant - - case G_D12_CmdKind_Constant: - { - i32 slot = cmd->constant.slot; - u32 value = cmd->constant.value; - if (slot >= 0 && slot < countof(slotted_constants)) + default: { - slotted_constants[slot] = value; - } - cmd_idx += 1; - } break; + } break; - //- Barrier + //- Constant - case G_D12_CmdKind_Barrier: - { - if (cmd->barrier.should_commit) + case G_D12_CmdKind_Constant: { - D3D12_RESOURCE_BARRIER barrier = Zi; - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; - ID3D12GraphicsCommandList_ResourceBarrier(d3d_cl, 1, &barrier); - } - - cmd_idx += 1; - } break; - - //- Copy bytes - - case G_D12_CmdKind_CopyBytes: - { - u64 src_offset = cmd->copy_bytes.src_range.min; - u64 copy_size = cmd->copy_bytes.src_range.max - cmd->copy_bytes.src_range.min; - ID3D12GraphicsCommandList_CopyBufferRegion( - d3d_cl, - cmd->copy_bytes.dst->d3d_resource, - cmd->copy_bytes.dst_offset, - cmd->copy_bytes.src->d3d_resource, - src_offset, - copy_size - ); - cmd_idx += 1; - - - - // FIXME: Remove this (only apply during Barrier command on any implicit resource transitions that occured) - D3D12_RESOURCE_BARRIER barriers[2] = Zi; - { - D3D12_RESOURCE_BARRIER *barrier = &barriers[0]; - barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier->Transition.pResource = cmd->copy_bytes.dst->d3d_resource; - barrier->Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; - barrier->Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; - barrier->Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; - } - { - D3D12_RESOURCE_BARRIER *barrier = &barriers[1]; - barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier->Transition.pResource = cmd->copy_bytes.src->d3d_resource; - barrier->Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; - barrier->Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE; - barrier->Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; - } - ID3D12GraphicsCommandList_ResourceBarrier(d3d_cl, 2, barriers); - - - - - } break; - - //- Copy texels - - case G_D12_CmdKind_CopyTexels: - { - G_D12_Resource *dst = cmd->copy_texels.dst; - G_D12_Resource *src = cmd->copy_texels.src; - D3D12_TEXTURE_COPY_LOCATION dst_loc = cmd->copy_texels.dst_loc; - D3D12_TEXTURE_COPY_LOCATION src_loc = cmd->copy_texels.src_loc; - Vec3I32 dst_offset = cmd->copy_texels.dst_texture_offset; - Rng3I32 src_range = cmd->copy_texels.src_texture_range; - - D3D12_BOX src_box = Zi; - D3D12_BOX *src_box_ptr = 0; - { - src_box.left = src_range.p0.x; - src_box.top = src_range.p0.y; - src_box.front = src_range.p0.z; - src_box.right = src_range.p1.x; - src_box.bottom = src_range.p1.y; - src_box.back = src_range.p1.z; - if (src->is_texture) + i32 slot = cmd->constant.slot; + u32 value = cmd->constant.value; + if (slot >= 0 && slot < countof(slotted_constants)) { - src_box_ptr = &src_box; + slotted_constants[slot] = value; } - } + } break; - if (dst->flags & G_ResourceFlag_AllowDepthStencil) + //- Copy bytes + + case G_D12_CmdKind_CopyBytes: { - // Depth-stencil textures must have src box & dst offset set to 0 - // https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12graphicscommandlist-copytextureregion - ID3D12GraphicsCommandList_CopyTextureRegion(d3d_cl, &dst_loc, 0, 0, 0, &src_loc, 0); - } - else - { - ID3D12GraphicsCommandList_CopyTextureRegion(d3d_cl, &dst_loc, dst_offset.x, dst_offset.y, dst_offset.z, &src_loc, src_box_ptr); - } + u64 src_offset = cmd->copy_bytes.src_range.min; + u64 copy_size = cmd->copy_bytes.src_range.max - cmd->copy_bytes.src_range.min; + ID3D12GraphicsCommandList_CopyBufferRegion( + d3d_cl, + cmd->copy_bytes.dst->d3d_resource, + cmd->copy_bytes.dst_offset, + cmd->copy_bytes.src->d3d_resource, + src_offset, + copy_size + ); - // FIXME: Remove this (only apply during Barrier command on any implicit resource transitions that occured) - D3D12_RESOURCE_BARRIER barriers[2] = Zi; - { - D3D12_RESOURCE_BARRIER *barrier = &barriers[0]; - barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier->Transition.pResource = dst->d3d_resource; - barrier->Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; - barrier->Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; - barrier->Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; - } - { - D3D12_RESOURCE_BARRIER *barrier = &barriers[1]; - barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier->Transition.pResource = src->d3d_resource; - barrier->Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; - barrier->Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE; - barrier->Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; - } - ID3D12GraphicsCommandList_ResourceBarrier(d3d_cl, 2, barriers); - - cmd_idx += 1; - } break; - - //- Compute - - case G_D12_CmdKind_Compute: - { - // Fetch pipeline - G_D12_Pipeline *pipeline = 0; - { - G_D12_PipelineDesc pipeline_desc = Zi; - pipeline_desc.cs = cmd->compute.cs; - pipeline = G_D12_PipelineFromDesc(pipeline_desc); - } - - if (pipeline) - { - // Set descriptor heaps - if (!descriptor_heaps_set) + // FIXME: Remove this (only apply during Barrier command on any implicit resource transitions that occured) + i64 barriers_count = 0; + D3D12_RESOURCE_BARRIER barriers[2] = Zi; + if (G_D12_IsSimultaneous(cmd->copy_bytes.dst)) { - ID3D12DescriptorHeap *heaps[] = { - G_D12.descriptor_heaps[G_D12_DescriptorHeapKind_CbvSrvUav].d3d_heap, - G_D12.descriptor_heaps[G_D12_DescriptorHeapKind_Sampler].d3d_heap, - }; - ID3D12GraphicsCommandList_SetDescriptorHeaps(d3d_cl, countof(heaps), heaps); - descriptor_heaps_set = 1; + D3D12_RESOURCE_BARRIER *barrier = &barriers[barriers_count]; + barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier->Transition.pResource = cmd->copy_bytes.dst->d3d_resource; + barrier->Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier->Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; + barrier->Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; + ++barriers_count; + } + if (G_D12_IsSimultaneous(cmd->copy_bytes.src)) + { + D3D12_RESOURCE_BARRIER *barrier = &barriers[barriers_count]; + barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier->Transition.pResource = cmd->copy_bytes.src->d3d_resource; + barrier->Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier->Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE; + barrier->Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; + ++barriers_count; + } + if (barriers_count > 0) + { + ID3D12GraphicsCommandList_ResourceBarrier(d3d_cl, barriers_count, barriers); } - // Bind rootsig - if (!compute_rootsig_set) - { - ID3D12GraphicsCommandList_SetComputeRootSignature(d3d_cl, G_D12.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 < countof(slotted_constants); ++slot) + + } break; + + //- Copy texels + + case G_D12_CmdKind_CopyTexels: + { + G_D12_Resource *dst = cmd->copy_texels.dst; + G_D12_Resource *src = cmd->copy_texels.src; + D3D12_TEXTURE_COPY_LOCATION dst_loc = cmd->copy_texels.dst_loc; + D3D12_TEXTURE_COPY_LOCATION src_loc = cmd->copy_texels.src_loc; + Vec3I32 dst_offset = cmd->copy_texels.dst_texture_offset; + Rng3I32 src_range = cmd->copy_texels.src_texture_range; + + D3D12_BOX src_box = Zi; + D3D12_BOX *src_box_ptr = 0; { - if (bound_compute_constants[slot] != slotted_constants[slot]) + src_box.left = src_range.p0.x; + src_box.top = src_range.p0.y; + src_box.front = src_range.p0.z; + src_box.right = src_range.p1.x; + src_box.bottom = src_range.p1.y; + src_box.back = src_range.p1.z; + if (src->is_texture) { - ID3D12GraphicsCommandList_SetComputeRoot32BitConstant(d3d_cl, slot, slotted_constants[slot], 0); - bound_compute_constants[slot] = slotted_constants[slot]; + src_box_ptr = &src_box; } } - // Dispatch - ID3D12GraphicsCommandList_Dispatch(d3d_cl, cmd->compute.groups.x, cmd->compute.groups.y, cmd->compute.groups.z); - } + if (dst->flags & G_ResourceFlag_AllowDepthStencil) + { + // Depth-stencil textures must have src box & dst offset set to 0 + // https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12graphicscommandlist-copytextureregion + ID3D12GraphicsCommandList_CopyTextureRegion(d3d_cl, &dst_loc, 0, 0, 0, &src_loc, 0); + } + else + { + ID3D12GraphicsCommandList_CopyTextureRegion(d3d_cl, &dst_loc, dst_offset.x, dst_offset.y, dst_offset.z, &src_loc, src_box_ptr); + } - cmd_idx += 1; - } break; - //- Rasterize - case G_D12_CmdKind_Rasterize: - { - // Fetch pipeline - G_D12_Pipeline *pipeline = 0; + // FIXME: Remove this (only apply during Barrier command on any implicit resource transitions that occured) + i64 barriers_count = 0; + D3D12_RESOURCE_BARRIER barriers[2] = Zi; + if (G_D12_IsSimultaneous(dst)) + { + D3D12_RESOURCE_BARRIER *barrier = &barriers[barriers_count]; + barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier->Transition.pResource = dst->d3d_resource; + barrier->Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier->Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; + barrier->Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; + ++barriers_count; + } + if (G_D12_IsSimultaneous(src)) + { + D3D12_RESOURCE_BARRIER *barrier = &barriers[barriers_count]; + barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier->Transition.pResource = src->d3d_resource; + barrier->Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier->Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE; + barrier->Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; + ++barriers_count; + } + if (barriers_count > 0) + { + ID3D12GraphicsCommandList_ResourceBarrier(d3d_cl, barriers_count, barriers); + } + + } break; + + //- Compute + + case G_D12_CmdKind_Compute: { - G_D12_PipelineDesc pipeline_desc = Zi; - pipeline_desc.vs = cmd->rasterize.vs; - pipeline_desc.ps = cmd->rasterize.ps; + // Fetch pipeline + G_D12_Pipeline *pipeline = 0; { - pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED; - switch (cmd->rasterize.raster_mode) - { - default: Assert(0); break; - case G_RasterMode_PointList: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT; break; - case G_RasterMode_LineList: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; break; - case G_RasterMode_LineStrip: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; break; - case G_RasterMode_TriangleList: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; break; - case G_RasterMode_TriangleStrip: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; break; - case G_RasterMode_WireTriangleList: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; break; - case G_RasterMode_WireTriangleStrip: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; break; - } + G_D12_PipelineDesc pipeline_desc = Zi; + pipeline_desc.cs = cmd->compute.cs; + pipeline = G_D12_PipelineFromDesc(pipeline_desc); } - if (cmd->rasterize.raster_mode == G_RasterMode_WireTriangleList || cmd->rasterize.raster_mode == G_RasterMode_WireTriangleStrip) - { - pipeline_desc.is_wireframe = 1; - } - for (u32 i = 0; i < countof(cmd->rasterize.render_target_descs); ++i) - { - G_RenderTargetDesc desc = cmd->rasterize.render_target_descs[i]; - G_D12_Resource *rt = G_D12_ResourceFromHandle(desc.resource); - if (rt) - { - pipeline_desc.render_target_formats[i] = rt->texture_format; - pipeline_desc.render_target_blend_modes[i] = desc.blend; - } - else - { - pipeline_desc.render_target_formats[i] = G_Format_Unknown; - } - } - pipeline = G_D12_PipelineFromDesc(pipeline_desc); - } - // Create ibv - u32 indices_count = 0; - D3D12_INDEX_BUFFER_VIEW ibv = Zi; + if (pipeline) + { + // Set descriptor heaps + if (!descriptor_heaps_set) + { + ID3D12DescriptorHeap *heaps[] = { + G_D12.descriptor_heaps[G_D12_DescriptorHeapKind_CbvSrvUav].d3d_heap, + G_D12.descriptor_heaps[G_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_D12.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 < countof(slotted_constants); ++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); + } + + } break; + + //- Rasterize + + case G_D12_CmdKind_Rasterize: { - G_IndexBufferDesc desc = cmd->rasterize.index_buffer_desc; - if (desc.index_count > 0) + // Fetch pipeline + G_D12_Pipeline *pipeline = 0; { - G_D12_Resource *index_buffer_resource = G_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) + G_D12_PipelineDesc pipeline_desc = Zi; + pipeline_desc.vs = cmd->rasterize.vs; + pipeline_desc.ps = cmd->rasterize.ps; { - ibv.Format = DXGI_FORMAT_R16_UINT; - indices_count = ibv.SizeInBytes / 2; + pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED; + switch (cmd->rasterize.raster_mode) + { + default: Assert(0); break; + case G_RasterMode_PointList: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT; break; + case G_RasterMode_LineList: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; break; + case G_RasterMode_LineStrip: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; break; + case G_RasterMode_TriangleList: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; break; + case G_RasterMode_TriangleStrip: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; break; + case G_RasterMode_WireTriangleList: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; break; + case G_RasterMode_WireTriangleStrip: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; break; + } } - else if (desc.index_size == 4) + if (cmd->rasterize.raster_mode == G_RasterMode_WireTriangleList || cmd->rasterize.raster_mode == G_RasterMode_WireTriangleStrip) { - ibv.Format = DXGI_FORMAT_R32_UINT; - indices_count = ibv.SizeInBytes / 4; + pipeline_desc.is_wireframe = 1; } - else + for (u32 i = 0; i < countof(cmd->rasterize.render_target_descs); ++i) { - Assert(0); // Invalid index size - } - } - } - - // Prepare & dispatch - if (pipeline && indices_count > 0) - { - // Set descriptor heaps - if (!descriptor_heaps_set) - { - ID3D12DescriptorHeap *heaps[] = { - G_D12.descriptor_heaps[G_D12_DescriptorHeapKind_CbvSrvUav].d3d_heap, - G_D12.descriptor_heaps[G_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_D12.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 < countof(slotted_constants); ++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.raster_mode) - { - default: Assert(0); break; - case G_RasterMode_PointList: topology = D3D_PRIMITIVE_TOPOLOGY_POINTLIST; break; - case G_RasterMode_LineList: topology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; break; - case G_RasterMode_LineStrip: topology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; break; - case G_RasterMode_TriangleList: topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; break; - case G_RasterMode_TriangleStrip: topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; break; - case G_RasterMode_WireTriangleList: topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; break; - case G_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 - u32 barriers_count = 0; - D3D12_RESOURCE_BARRIER barriers[G_MaxRenderTargets] = Zi; - { - u32 rtvs_count = 0; - b32 om_dirty = 0; - for (u32 rtv_idx = 0; rtv_idx < countof(cmd->rasterize.render_target_descs); ++rtv_idx) - { - G_RenderTargetDesc desc = cmd->rasterize.render_target_descs[rtv_idx]; + G_RenderTargetDesc desc = cmd->rasterize.render_target_descs[i]; G_D12_Resource *rt = G_D12_ResourceFromHandle(desc.resource); if (rt) { - { - D3D12_RESOURCE_BARRIER *barrier = &barriers[barriers_count]; - barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier->Transition.pResource = rt->d3d_resource; - barrier->Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; - barrier->Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; - barrier->Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; - ++barriers_count; - } - if (bound_render_target_uids[rtv_idx] != rt->uid + desc.mip) - { - G_D12_Descriptor *rtv_descriptor = rcl->rtv_descriptors[rtv_idx]; - G_D12_InitRtv(rt, rtv_descriptor->handle, desc.mip); - bound_render_target_uids[rtv_idx] = rt->uid + desc.mip; - om_dirty = 1; - } - ++rtvs_count; + pipeline_desc.render_target_formats[i] = rt->texture_format; + pipeline_desc.render_target_blend_modes[i] = desc.blend; } else { - break; + pipeline_desc.render_target_formats[i] = G_Format_Unknown; } } - if (om_dirty) + pipeline = G_D12_PipelineFromDesc(pipeline_desc); + } + + // Create ibv + u32 indices_count = 0; + D3D12_INDEX_BUFFER_VIEW ibv = Zi; + { + G_IndexBufferDesc desc = cmd->rasterize.index_buffer_desc; + if (desc.index_count > 0) { - D3D12_CPU_DESCRIPTOR_HANDLE rtv_handles[G_MaxRenderTargets] = Zi; - for (u32 rtv_idx = 0; rtv_idx < rtvs_count; ++rtv_idx) + G_D12_Resource *index_buffer_resource = G_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) { - rtv_handles[rtv_idx] = rcl->rtv_descriptors[rtv_idx]->handle; + 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 } - ID3D12GraphicsCommandList_OMSetRenderTargets(d3d_cl, rtvs_count, rtv_handles, 0, 0); } } - // Dispatch - ID3D12GraphicsCommandList_DrawIndexedInstanced(d3d_cl, indices_count, cmd->rasterize.instances_count, 0, 0, 0); + // Prepare & dispatch + if (pipeline && indices_count > 0) + { + // Set descriptor heaps + if (!descriptor_heaps_set) + { + ID3D12DescriptorHeap *heaps[] = { + G_D12.descriptor_heaps[G_D12_DescriptorHeapKind_CbvSrvUav].d3d_heap, + G_D12.descriptor_heaps[G_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_D12.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 < countof(slotted_constants); ++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.raster_mode) + { + default: Assert(0); break; + case G_RasterMode_PointList: topology = D3D_PRIMITIVE_TOPOLOGY_POINTLIST; break; + case G_RasterMode_LineList: topology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; break; + case G_RasterMode_LineStrip: topology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; break; + case G_RasterMode_TriangleList: topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; break; + case G_RasterMode_TriangleStrip: topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; break; + case G_RasterMode_WireTriangleList: topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; break; + case G_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 + u32 barriers_count = 0; + D3D12_RESOURCE_BARRIER barriers[G_MaxRenderTargets] = Zi; + { + u32 rtvs_count = 0; + b32 om_dirty = 0; + for (u32 rtv_idx = 0; rtv_idx < countof(cmd->rasterize.render_target_descs); ++rtv_idx) + { + G_RenderTargetDesc desc = cmd->rasterize.render_target_descs[rtv_idx]; + G_D12_Resource *rt = G_D12_ResourceFromHandle(desc.resource); + if (rt) + { + if (G_D12_IsSimultaneous(rt)) + { + D3D12_RESOURCE_BARRIER *barrier = &barriers[barriers_count]; + barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier->Transition.pResource = rt->d3d_resource; + barrier->Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier->Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; + barrier->Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; + ++barriers_count; + } + if (bound_render_target_uids[rtv_idx] != rt->uid + desc.mip) + { + G_D12_Descriptor *rtv_descriptor = rcl->rtv_descriptors[rtv_idx]; + G_D12_InitRtv(rt, rtv_descriptor->handle, desc.mip); + bound_render_target_uids[rtv_idx] = rt->uid + desc.mip; + om_dirty = 1; + } + ++rtvs_count; + } + else + { + break; + } + } + if (om_dirty) + { + D3D12_CPU_DESCRIPTOR_HANDLE rtv_handles[G_MaxRenderTargets] = Zi; + for (u32 rtv_idx = 0; rtv_idx < rtvs_count; ++rtv_idx) + { + rtv_handles[rtv_idx] = rcl->rtv_descriptors[rtv_idx]->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); + + // FIXME: Remove this (only apply during Barrier command on any implicit resource transitions that occured) + // FIXME: Does the implicit promotion happen during Draw? Or during OMSetRenderTargets? + if (barriers_count > 0) + { + ID3D12GraphicsCommandList_ResourceBarrier(d3d_cl, barriers_count, barriers); + } + } + + } break; + + //- Clear rtv + + case G_D12_CmdKind_ClearRtv: + { + G_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 + cmd->clear_rtv.mip) + { + G_D12_InitRtv(rt, rtv_handle, cmd->clear_rtv.mip); + bound_render_clear_target_uid = rt->uid + cmd->clear_rtv.mip; + } + ID3D12GraphicsCommandList_ClearRenderTargetView(d3d_cl, rtv_handle, clear_color, 0, 0); // FIXME: Remove this (only apply during Barrier command on any implicit resource transitions that occured) - // FIXME: Does the implicit promotion happen during Draw? Or during OMSetRenderTargets? - ID3D12GraphicsCommandList_ResourceBarrier(d3d_cl, barriers_count, barriers); - } + i64 barriers_count = 0; + D3D12_RESOURCE_BARRIER barrier = Zi; + if (G_D12_IsSimultaneous(rt)) + { + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Transition.pResource = rt->d3d_resource; + barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; + ++barriers_count; + } + if (barriers_count > 0) + { + ID3D12GraphicsCommandList_ResourceBarrier(d3d_cl, barriers_count, &barrier); + } + } break; - cmd_idx += 1; - } break; + //- Discard rtv - //- Clear rtv - - case G_D12_CmdKind_ClearRtv: - { - G_D12_Resource *rt = cmd->clear_rtv.render_target; - f32 clear_color[4] = Zi; + case G_D12_CmdKind_DiscardRtv: { - 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 + cmd->clear_rtv.mip) + D3D12_DISCARD_REGION region = Zi; + region.FirstSubresource = cmd->discard_rtv.mip; + region.NumSubresources = 1; + G_D12_Resource *resource = cmd->discard_rtv.render_target; + ID3D12GraphicsCommandList_DiscardResource(d3d_cl, resource->d3d_resource, 0); + + // FIXME: Remove this (only apply during Barrier command on any implicit resource transitions that occured) + i64 barriers_count = 0; + D3D12_RESOURCE_BARRIER barrier = Zi; + if (G_D12_IsSimultaneous(resource)) + { + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Transition.pResource = resource->d3d_resource; + barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; + ++barriers_count; + } + if (barriers_count > 0) + { + ID3D12GraphicsCommandList_ResourceBarrier(d3d_cl, barriers_count, &barrier); + } + } break; + + //- Log + + case G_D12_CmdKind_Log: { - G_D12_InitRtv(rt, rtv_handle, cmd->clear_rtv.mip); - bound_render_clear_target_uid = rt->uid + cmd->clear_rtv.mip; - } - ID3D12GraphicsCommandList_ClearRenderTargetView(d3d_cl, rtv_handle, clear_color, 0, 0); - cmd_idx += 1; + // FIXME - // FIXME: Remove this (only apply during Barrier command on any implicit resource transitions that occured) - D3D12_RESOURCE_BARRIER barrier = Zi; - { - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier.Transition.pResource = rt->d3d_resource; - barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; - barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; - barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; - } - ID3D12GraphicsCommandList_ResourceBarrier(d3d_cl, 1, &barrier); - } break; + // G_D12_Resource *resource = cmd->log.resource; + // String resource_name = STRING(resource->name_len, resource->name_text); - //- Discard rtv + // String layouts_str = Zi; + // { + // StringList layout_names = Zi; + // for (i32 mip_idx = 0; mip_idx < resource->texture_mips; ++mip_idx) + // { + // String layout_name = G_D12_NameFromBarrierLayout(resource->cmdlist_texture_layouts[mip_idx]); + // String layout_str = StringF(scratch.arena, "[%F] %F", FmtSint(mip_idx), FmtString(layout_name)); + // PushStringToList(scratch.arena, &layout_names, layout_str); + // } + // layouts_str = StringFromList(scratch.arena, layout_names, Lit(", ")); + // } - case G_D12_CmdKind_DiscardRtv: - { - D3D12_DISCARD_REGION region = Zi; - region.FirstSubresource = cmd->discard_rtv.mip; - region.NumSubresources = 1; - G_D12_Resource *resource = cmd->discard_rtv.render_target; - ID3D12GraphicsCommandList_DiscardResource(d3d_cl, resource->d3d_resource, 0); - cmd_idx += 1; + // String msg = StringF( + // scratch.arena, + // "[Gpu command list resource log] uid: %F, name: \"%F\", layouts: { %F }", + // FmtUint(resource->uid), + // FmtString(resource_name), + // FmtString(layouts_str) + // ); + // LogDebug(msg); - // FIXME: Remove this (only apply during Barrier command on any implicit resource transitions that occured) - D3D12_RESOURCE_BARRIER barrier = Zi; - { - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier.Transition.pResource = resource->d3d_resource; - barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; - barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; - barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; - } - ID3D12GraphicsCommandList_ResourceBarrier(d3d_cl, 1, &barrier); - } break; - - //- Log - - case G_D12_CmdKind_Log: - { - // FIXME - - // G_D12_Resource *resource = cmd->log.resource; - // String resource_name = STRING(resource->name_len, resource->name_text); - - // String layouts_str = Zi; - // { - // StringList layout_names = Zi; - // for (i32 mip_idx = 0; mip_idx < resource->texture_mips; ++mip_idx) - // { - // String layout_name = G_D12_NameFromBarrierLayout(resource->cmdlist_texture_layouts[mip_idx]); - // String layout_str = StringF(scratch.arena, "[%F] %F", FmtSint(mip_idx), FmtString(layout_name)); - // PushStringToList(scratch.arena, &layout_names, layout_str); - // } - // layouts_str = StringFromList(scratch.arena, layout_names, Lit(", ")); - // } - - // String msg = StringF( - // scratch.arena, - // "[Gpu command list resource log] uid: %F, name: \"%F\", layouts: { %F }", - // FmtUint(resource->uid), - // FmtString(resource_name), - // FmtString(layouts_str) - // ); - // LogDebug(msg); - - cmd_idx += 1; - } break; + } break; + } } } + + // End dx12 command list + // FIXME: Only lock & signal fence on final batch + completion_target = G_D12_CommitRawCommandList(rcl); } - // End dx12 command list - i64 completion_target = G_D12_CommitRawCommandList(rcl); + + + + + + + + + + // // Begin dx12 command list + // G_D12_RawCommandList *rcl = G_D12_PrepareRawCommandList(queue_kind); + // ID3D12GraphicsCommandList *d3d_cl = rcl->d3d_cl; + + // // Pipeline state + // b32 graphics_rootsig_set = 0; + // b32 compute_rootsig_set = 0; + // b32 descriptor_heaps_set = 0; + // G_D12_Pipeline *bound_pipeline = 0; + + // // Constants state + // u64 slotted_constants[G_NumConstants]; + // u64 bound_compute_constants[G_NumConstants]; + // u64 bound_graphics_constants[G_NumConstants]; + // for (i32 i = 0; i < countof(slotted_constants); ++i) { slotted_constants[i] = 0; } // Zero-initialize all slots + // for (i32 i = 0; i < countof(bound_compute_constants); ++i) { bound_compute_constants[i] = U64Max; } + // for (i32 i = 0; i < countof(bound_graphics_constants); ++i) { bound_graphics_constants[i] = U64Max; } + + // // Fill built-in constants + // if (!G_IsRefNil(queue->print_buffer_ref)) + // { + // slotted_constants[G_ShaderConst_PrintBufferRef] = queue->print_buffer_ref.v; + // } + // { + // b32 tweak_b32 = TweakBool("Shader tweak-bool", 1); + // f32 tweak_f32 = TweakFloat("Shader tweak-float", 1, 0, 1); + // slotted_constants[G_ShaderConst_TweakB32] = tweak_b32; + // slotted_constants[G_ShaderConst_TweakF32] = *(u32 *)&tweak_f32; + // } + + // // Rasterizer state + // D3D12_VIEWPORT bound_viewport = Zi; + // D3D12_RECT bound_scissor = Zi; + // D3D_PRIMITIVE_TOPOLOGY bound_primitive_topology = -1; + // D3D12_INDEX_BUFFER_VIEW bound_ibv = Zi; + // u64 bound_render_target_uids[G_MaxRenderTargets] = Zi; + // u64 bound_render_clear_target_uid = 0; + + // // Build d3d commands + // { + // u64 cmd_idx = 0; + // while (cmd_idx < cmds_count) + // { + // G_D12_Cmd *cmd = &cmds[cmd_idx]; + // switch (cmd->kind) + // { + // default: + // { + // cmd_idx += 1; + // } break; + + // //- Constant + + // case G_D12_CmdKind_Constant: + // { + // 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 G_D12_CmdKind_Barrier: + // { + // if (cmd->barrier.should_commit) + // { + // D3D12_RESOURCE_BARRIER barrier = Zi; + // barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; + // ID3D12GraphicsCommandList_ResourceBarrier(d3d_cl, 1, &barrier); + // } + + // cmd_idx += 1; + // } break; + + // //- Copy bytes + + // case G_D12_CmdKind_CopyBytes: + // { + // u64 src_offset = cmd->copy_bytes.src_range.min; + // u64 copy_size = cmd->copy_bytes.src_range.max - cmd->copy_bytes.src_range.min; + // ID3D12GraphicsCommandList_CopyBufferRegion( + // d3d_cl, + // cmd->copy_bytes.dst->d3d_resource, + // cmd->copy_bytes.dst_offset, + // cmd->copy_bytes.src->d3d_resource, + // src_offset, + // copy_size + // ); + // cmd_idx += 1; + + + + // // FIXME: Remove this (only apply during Barrier command on any implicit resource transitions that occured) + // D3D12_RESOURCE_BARRIER barriers[2] = Zi; + // { + // D3D12_RESOURCE_BARRIER *barrier = &barriers[0]; + // barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + // barrier->Transition.pResource = cmd->copy_bytes.dst->d3d_resource; + // barrier->Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + // barrier->Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; + // barrier->Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; + // } + // { + // D3D12_RESOURCE_BARRIER *barrier = &barriers[1]; + // barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + // barrier->Transition.pResource = cmd->copy_bytes.src->d3d_resource; + // barrier->Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + // barrier->Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE; + // barrier->Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; + // } + // ID3D12GraphicsCommandList_ResourceBarrier(d3d_cl, 2, barriers); + + + + + // } break; + + // //- Copy texels + + // case G_D12_CmdKind_CopyTexels: + // { + // G_D12_Resource *dst = cmd->copy_texels.dst; + // G_D12_Resource *src = cmd->copy_texels.src; + // D3D12_TEXTURE_COPY_LOCATION dst_loc = cmd->copy_texels.dst_loc; + // D3D12_TEXTURE_COPY_LOCATION src_loc = cmd->copy_texels.src_loc; + // Vec3I32 dst_offset = cmd->copy_texels.dst_texture_offset; + // Rng3I32 src_range = cmd->copy_texels.src_texture_range; + + // D3D12_BOX src_box = Zi; + // D3D12_BOX *src_box_ptr = 0; + // { + // src_box.left = src_range.p0.x; + // src_box.top = src_range.p0.y; + // src_box.front = src_range.p0.z; + // src_box.right = src_range.p1.x; + // src_box.bottom = src_range.p1.y; + // src_box.back = src_range.p1.z; + // if (src->is_texture) + // { + // src_box_ptr = &src_box; + // } + // } + + // if (dst->flags & G_ResourceFlag_AllowDepthStencil) + // { + // // Depth-stencil textures must have src box & dst offset set to 0 + // // https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12graphicscommandlist-copytextureregion + // ID3D12GraphicsCommandList_CopyTextureRegion(d3d_cl, &dst_loc, 0, 0, 0, &src_loc, 0); + // } + // else + // { + // ID3D12GraphicsCommandList_CopyTextureRegion(d3d_cl, &dst_loc, dst_offset.x, dst_offset.y, dst_offset.z, &src_loc, src_box_ptr); + // } + + + + // // FIXME: Remove this (only apply during Barrier command on any implicit resource transitions that occured) + // D3D12_RESOURCE_BARRIER barriers[2] = Zi; + // { + // D3D12_RESOURCE_BARRIER *barrier = &barriers[0]; + // barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + // barrier->Transition.pResource = dst->d3d_resource; + // barrier->Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + // barrier->Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; + // barrier->Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; + // } + // { + // D3D12_RESOURCE_BARRIER *barrier = &barriers[1]; + // barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + // barrier->Transition.pResource = src->d3d_resource; + // barrier->Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + // barrier->Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE; + // barrier->Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; + // } + // ID3D12GraphicsCommandList_ResourceBarrier(d3d_cl, 2, barriers); + + // cmd_idx += 1; + // } break; + + // //- Compute + + // case G_D12_CmdKind_Compute: + // { + // // Fetch pipeline + // G_D12_Pipeline *pipeline = 0; + // { + // G_D12_PipelineDesc pipeline_desc = Zi; + // pipeline_desc.cs = cmd->compute.cs; + // pipeline = G_D12_PipelineFromDesc(pipeline_desc); + // } + + // if (pipeline) + // { + // // Set descriptor heaps + // if (!descriptor_heaps_set) + // { + // ID3D12DescriptorHeap *heaps[] = { + // G_D12.descriptor_heaps[G_D12_DescriptorHeapKind_CbvSrvUav].d3d_heap, + // G_D12.descriptor_heaps[G_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_D12.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 < countof(slotted_constants); ++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 G_D12_CmdKind_Rasterize: + // { + // // Fetch pipeline + // G_D12_Pipeline *pipeline = 0; + // { + // G_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.raster_mode) + // { + // default: Assert(0); break; + // case G_RasterMode_PointList: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT; break; + // case G_RasterMode_LineList: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; break; + // case G_RasterMode_LineStrip: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; break; + // case G_RasterMode_TriangleList: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; break; + // case G_RasterMode_TriangleStrip: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; break; + // case G_RasterMode_WireTriangleList: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; break; + // case G_RasterMode_WireTriangleStrip: pipeline_desc.topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; break; + // } + // } + // if (cmd->rasterize.raster_mode == G_RasterMode_WireTriangleList || cmd->rasterize.raster_mode == G_RasterMode_WireTriangleStrip) + // { + // pipeline_desc.is_wireframe = 1; + // } + // for (u32 i = 0; i < countof(cmd->rasterize.render_target_descs); ++i) + // { + // G_RenderTargetDesc desc = cmd->rasterize.render_target_descs[i]; + // G_D12_Resource *rt = G_D12_ResourceFromHandle(desc.resource); + // if (rt) + // { + // pipeline_desc.render_target_formats[i] = rt->texture_format; + // pipeline_desc.render_target_blend_modes[i] = desc.blend; + // } + // else + // { + // pipeline_desc.render_target_formats[i] = G_Format_Unknown; + // } + // } + // pipeline = G_D12_PipelineFromDesc(pipeline_desc); + // } + + // // Create ibv + // u32 indices_count = 0; + // D3D12_INDEX_BUFFER_VIEW ibv = Zi; + // { + // G_IndexBufferDesc desc = cmd->rasterize.index_buffer_desc; + // if (desc.index_count > 0) + // { + // G_D12_Resource *index_buffer_resource = G_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_D12.descriptor_heaps[G_D12_DescriptorHeapKind_CbvSrvUav].d3d_heap, + // G_D12.descriptor_heaps[G_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_D12.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 < countof(slotted_constants); ++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.raster_mode) + // { + // default: Assert(0); break; + // case G_RasterMode_PointList: topology = D3D_PRIMITIVE_TOPOLOGY_POINTLIST; break; + // case G_RasterMode_LineList: topology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; break; + // case G_RasterMode_LineStrip: topology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; break; + // case G_RasterMode_TriangleList: topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; break; + // case G_RasterMode_TriangleStrip: topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; break; + // case G_RasterMode_WireTriangleList: topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; break; + // case G_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 + // u32 barriers_count = 0; + // D3D12_RESOURCE_BARRIER barriers[G_MaxRenderTargets] = Zi; + // { + // u32 rtvs_count = 0; + // b32 om_dirty = 0; + // for (u32 rtv_idx = 0; rtv_idx < countof(cmd->rasterize.render_target_descs); ++rtv_idx) + // { + // G_RenderTargetDesc desc = cmd->rasterize.render_target_descs[rtv_idx]; + // G_D12_Resource *rt = G_D12_ResourceFromHandle(desc.resource); + // if (rt) + // { + // { + // D3D12_RESOURCE_BARRIER *barrier = &barriers[barriers_count]; + // barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + // barrier->Transition.pResource = rt->d3d_resource; + // barrier->Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + // barrier->Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; + // barrier->Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; + // ++barriers_count; + // } + // if (bound_render_target_uids[rtv_idx] != rt->uid + desc.mip) + // { + // G_D12_Descriptor *rtv_descriptor = rcl->rtv_descriptors[rtv_idx]; + // G_D12_InitRtv(rt, rtv_descriptor->handle, desc.mip); + // bound_render_target_uids[rtv_idx] = rt->uid + desc.mip; + // om_dirty = 1; + // } + // ++rtvs_count; + // } + // else + // { + // break; + // } + // } + // if (om_dirty) + // { + // D3D12_CPU_DESCRIPTOR_HANDLE rtv_handles[G_MaxRenderTargets] = Zi; + // for (u32 rtv_idx = 0; rtv_idx < rtvs_count; ++rtv_idx) + // { + // rtv_handles[rtv_idx] = rcl->rtv_descriptors[rtv_idx]->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); + + // // FIXME: Remove this (only apply during Barrier command on any implicit resource transitions that occured) + // // FIXME: Does the implicit promotion happen during Draw? Or during OMSetRenderTargets? + // ID3D12GraphicsCommandList_ResourceBarrier(d3d_cl, barriers_count, barriers); + // } + + // cmd_idx += 1; + // } break; + + // //- Clear rtv + + // case G_D12_CmdKind_ClearRtv: + // { + // G_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 + cmd->clear_rtv.mip) + // { + // G_D12_InitRtv(rt, rtv_handle, cmd->clear_rtv.mip); + // bound_render_clear_target_uid = rt->uid + cmd->clear_rtv.mip; + // } + // ID3D12GraphicsCommandList_ClearRenderTargetView(d3d_cl, rtv_handle, clear_color, 0, 0); + // cmd_idx += 1; + + // // FIXME: Remove this (only apply during Barrier command on any implicit resource transitions that occured) + // D3D12_RESOURCE_BARRIER barrier = Zi; + // { + // barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + // barrier.Transition.pResource = rt->d3d_resource; + // barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + // barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; + // barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; + // } + // ID3D12GraphicsCommandList_ResourceBarrier(d3d_cl, 1, &barrier); + // } break; + + // //- Discard rtv + + // case G_D12_CmdKind_DiscardRtv: + // { + // D3D12_DISCARD_REGION region = Zi; + // region.FirstSubresource = cmd->discard_rtv.mip; + // region.NumSubresources = 1; + // G_D12_Resource *resource = cmd->discard_rtv.render_target; + // ID3D12GraphicsCommandList_DiscardResource(d3d_cl, resource->d3d_resource, 0); + // cmd_idx += 1; + + // // FIXME: Remove this (only apply during Barrier command on any implicit resource transitions that occured) + // D3D12_RESOURCE_BARRIER barrier = Zi; + // { + // barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + // barrier.Transition.pResource = resource->d3d_resource; + // barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + // barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; + // barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; + // } + // ID3D12GraphicsCommandList_ResourceBarrier(d3d_cl, 1, &barrier); + // } break; + + // //- Log + + // case G_D12_CmdKind_Log: + // { + // // FIXME + + // // G_D12_Resource *resource = cmd->log.resource; + // // String resource_name = STRING(resource->name_len, resource->name_text); + + // // String layouts_str = Zi; + // // { + // // StringList layout_names = Zi; + // // for (i32 mip_idx = 0; mip_idx < resource->texture_mips; ++mip_idx) + // // { + // // String layout_name = G_D12_NameFromBarrierLayout(resource->cmdlist_texture_layouts[mip_idx]); + // // String layout_str = StringF(scratch.arena, "[%F] %F", FmtSint(mip_idx), FmtString(layout_name)); + // // PushStringToList(scratch.arena, &layout_names, layout_str); + // // } + // // layouts_str = StringFromList(scratch.arena, layout_names, Lit(", ")); + // // } + + // // String msg = StringF( + // // scratch.arena, + // // "[Gpu command list resource log] uid: %F, name: \"%F\", layouts: { %F }", + // // FmtUint(resource->uid), + // // FmtString(resource_name), + // // FmtString(layouts_str) + // // ); + // // LogDebug(msg); + + // cmd_idx += 1; + // } break; + // } + // } + // } + + // // End dx12 command list + // i64 completion_target = G_D12_CommitRawCommandList(rcl); + + + + + + + // Attach completion info to staging regions for (G_D12_StagingRegionNode *n = cl->first_staging_region; n;) @@ -2511,10 +3142,6 @@ i64 G_CommitCommandList(G_CommandListHandle cl_handle) Unlock(&lock); } - - - - // // Attach completion info to resources // for (G_D12_Resource *r = cl->reset_resources.first; r;) // { @@ -3230,196 +3857,196 @@ void G_CommitBackbuffer(G_ResourceHandle backbuffer_handle, i32 vsync) void G_D12_CollectionWorkerEntryPoint(WaveLaneCtx *lane) { - for (;;) - { - // FIXME: Remove this - SleepSeconds(0.100); + // for (;;) + // { + // // FIXME: Remove this + // SleepSeconds(0.100); - // Copy print-buffers to readback - for (G_QueueKind queue_kind = 0; queue_kind < G_QueueKind_COUNT; ++queue_kind) - { - G_D12_Queue *queue = G_D12_QueueFromKind(queue_kind); - if (!G_IsResourceNil(queue->print_buffer)) - { - G_CommandListHandle cl = G_PrepareCommandList(queue_kind); - { - // Copy print buffer to readback buffer - G_CopyBufferToBuffer(cl, queue->print_readback_buffer, 0, queue->print_buffer, RNGU64(0, queue->print_buffer_size)); - G_Barrier(cl); - // Reset counters to 0 - u8 zero[12] = Zi; - G_CopyCpuToBuffer(cl, queue->print_buffer, 0, zero, RNGU64(0, sizeof(zero))); - } - G_CommitCommandList(cl); - } - } + // // Copy print-buffers to readback + // for (G_QueueKind queue_kind = 0; queue_kind < G_QueueKind_COUNT; ++queue_kind) + // { + // G_D12_Queue *queue = G_D12_QueueFromKind(queue_kind); + // if (!G_IsResourceNil(queue->print_buffer)) + // { + // G_CommandListHandle cl = G_PrepareCommandList(queue_kind); + // { + // // Copy print buffer to readback buffer + // G_CopyBufferToBuffer(cl, queue->print_readback_buffer, 0, queue->print_buffer, RNGU64(0, queue->print_buffer_size)); + // G_Barrier(cl); + // // Reset counters to 0 + // u8 zero[12] = Zi; + // G_CopyCpuToBuffer(cl, queue->print_buffer, 0, zero, RNGU64(0, sizeof(zero))); + // } + // G_CommitCommandList(cl); + // } + // } - // TODO: Collect asynchronously - G_SyncCpu(G_QueueMask_Direct | G_QueueMask_AsyncCompute); + // // TODO: Collect asynchronously + // G_SyncCpu(G_QueueMask_Direct | G_QueueMask_AsyncCompute); - for (G_QueueKind queue_kind = 0; queue_kind < G_QueueKind_COUNT; ++queue_kind) - { - G_D12_Queue *queue = G_D12_QueueFromKind(queue_kind); - if (!G_IsResourceNil(queue->print_buffer)) - { - u32 attempted_print_bytes_count = *(G_StructFromResource(queue->print_readback_buffer, u32) + 0); // The number of bytes shaders attempted to write - u32 prints_count = *(G_StructFromResource(queue->print_readback_buffer, u32) + 1); // The number of shader prints that are in the buffer - u32 overflows_count = *(G_StructFromResource(queue->print_readback_buffer, u32) + 2); // The number of shader prints that could not fit in the buffer - u8 *start = G_StructFromResource(queue->print_readback_buffer, u8) + 12; + // for (G_QueueKind queue_kind = 0; queue_kind < G_QueueKind_COUNT; ++queue_kind) + // { + // G_D12_Queue *queue = G_D12_QueueFromKind(queue_kind); + // if (!G_IsResourceNil(queue->print_buffer)) + // { + // u32 attempted_print_bytes_count = *(G_StructFromResource(queue->print_readback_buffer, u32) + 0); // The number of bytes shaders attempted to write + // u32 prints_count = *(G_StructFromResource(queue->print_readback_buffer, u32) + 1); // The number of shader prints that are in the buffer + // u32 overflows_count = *(G_StructFromResource(queue->print_readback_buffer, u32) + 2); // The number of shader prints that could not fit in the buffer + // u8 *start = G_StructFromResource(queue->print_readback_buffer, u8) + 12; - // Deserialize - if (GPU_SHADER_PRINT_LOG) - { - if (prints_count > 0) - { - LogDebugF( - "Forwarding logs collected from GPU - Resident prints: %F, Total attempted prints: %F, Total attempted bytes: %F", - FmtUint(prints_count), - FmtUint(prints_count + overflows_count), - FmtUint(attempted_print_bytes_count) - ); - } + // // Deserialize + // if (GPU_SHADER_PRINT_LOG) + // { + // if (prints_count > 0) + // { + // LogDebugF( + // "Forwarding logs collected from GPU - Resident prints: %F, Total attempted prints: %F, Total attempted bytes: %F", + // FmtUint(prints_count), + // FmtUint(prints_count + overflows_count), + // FmtUint(attempted_print_bytes_count) + // ); + // } - // FIXME: Remove this - TempArena scratch = BeginScratchNoConflict(); - u8 *at = start; - { - for (u32 print_idx = 0; print_idx < prints_count; ++print_idx) - { - u32 chars_count = 0; - u32 args_count = 0; - b32 internal_overflow = 0; - { - u32 header = *(u32 *)at; - chars_count = (header & 0x0000FFFF) >> 0; - args_count = (header & 0x7FFF0000) >> 16; - internal_overflow = (header & 0xF0000000) >> 31; - at += 4; - } + // // FIXME: Remove this + // TempArena scratch = BeginScratchNoConflict(); + // u8 *at = start; + // { + // for (u32 print_idx = 0; print_idx < prints_count; ++print_idx) + // { + // u32 chars_count = 0; + // u32 args_count = 0; + // b32 internal_overflow = 0; + // { + // u32 header = *(u32 *)at; + // chars_count = (header & 0x0000FFFF) >> 0; + // args_count = (header & 0x7FFF0000) >> 16; + // internal_overflow = (header & 0xF0000000) >> 31; + // at += 4; + // } - String fmt = Zi; - { - fmt.len = chars_count; - fmt.text = at; - at += chars_count; - } + // String fmt = Zi; + // { + // fmt.len = chars_count; + // fmt.text = at; + // at += chars_count; + // } - FmtArgArray args = Zi; - args.count = args_count; - { - if (args_count > 0) - { - args.args = PushStructs(scratch.arena, FmtArg, args_count); - for (u32 arg_idx = 0; arg_idx < args_count; ++arg_idx) - { - G_FmtArgKind gpu_kind = (G_FmtArgKind)(*at); - at += 1; + // FmtArgArray args = Zi; + // args.count = args_count; + // { + // if (args_count > 0) + // { + // args.args = PushStructs(scratch.arena, FmtArg, args_count); + // for (u32 arg_idx = 0; arg_idx < args_count; ++arg_idx) + // { + // G_FmtArgKind gpu_kind = (G_FmtArgKind)(*at); + // at += 1; - FmtArg *dst = &args.args[arg_idx]; - switch (gpu_kind) - { - // Translate unsigned integer args - case G_FmtArgKind_Uint: - { - u32 gpu_value = *(u32 *)at; - *dst = FmtUint(gpu_value); - at += 4; - } break; - case G_FmtArgKind_Uint2: - { - Vec2U32 gpu_value = *(Vec2U32 *)at; - *dst = FmtUint2(gpu_value); - at += 8; - } break; - case G_FmtArgKind_Uint3: - { - Vec3U32 gpu_value = *(Vec3U32 *)at; - *dst = FmtUint3(gpu_value); - at += 12; - } break; - case G_FmtArgKind_Uint4: - { - Vec4U32 gpu_value = *(Vec4U32 *)at; - *dst = FmtUint4(gpu_value); - at += 16; - } break; + // FmtArg *dst = &args.args[arg_idx]; + // switch (gpu_kind) + // { + // // Translate unsigned integer args + // case G_FmtArgKind_Uint: + // { + // u32 gpu_value = *(u32 *)at; + // *dst = FmtUint(gpu_value); + // at += 4; + // } break; + // case G_FmtArgKind_Uint2: + // { + // Vec2U32 gpu_value = *(Vec2U32 *)at; + // *dst = FmtUint2(gpu_value); + // at += 8; + // } break; + // case G_FmtArgKind_Uint3: + // { + // Vec3U32 gpu_value = *(Vec3U32 *)at; + // *dst = FmtUint3(gpu_value); + // at += 12; + // } break; + // case G_FmtArgKind_Uint4: + // { + // Vec4U32 gpu_value = *(Vec4U32 *)at; + // *dst = FmtUint4(gpu_value); + // at += 16; + // } break; - // Translate signed integer args - case G_FmtArgKind_Sint: - { - i32 gpu_value = *(i32 *)at; - *dst = FmtSint(gpu_value); - at += 4; - } break; - case G_FmtArgKind_Sint2: - { - Vec2I32 gpu_value = *(Vec2I32 *)at; - *dst = FmtSint2(gpu_value); - at += 8; - } break; - case G_FmtArgKind_Sint3: - { - Vec3I32 gpu_value = *(Vec3I32 *)at; - *dst = FmtSint3(gpu_value); - at += 12; - } break; - case G_FmtArgKind_Sint4: - { - Vec4I32 gpu_value = *(Vec4I32 *)at; - *dst = FmtSint4(gpu_value); - at += 16; - } break; + // // Translate signed integer args + // case G_FmtArgKind_Sint: + // { + // i32 gpu_value = *(i32 *)at; + // *dst = FmtSint(gpu_value); + // at += 4; + // } break; + // case G_FmtArgKind_Sint2: + // { + // Vec2I32 gpu_value = *(Vec2I32 *)at; + // *dst = FmtSint2(gpu_value); + // at += 8; + // } break; + // case G_FmtArgKind_Sint3: + // { + // Vec3I32 gpu_value = *(Vec3I32 *)at; + // *dst = FmtSint3(gpu_value); + // at += 12; + // } break; + // case G_FmtArgKind_Sint4: + // { + // Vec4I32 gpu_value = *(Vec4I32 *)at; + // *dst = FmtSint4(gpu_value); + // at += 16; + // } break; - // Translate float args - case G_FmtArgKind_Float: - { - f32 gpu_value = *(f32 *)at; - *dst = FmtFloat(gpu_value); - at += 4; - } break; - case G_FmtArgKind_Float2: - { - Vec2 gpu_value = *(Vec2 *)at; - *dst = FmtFloat2(gpu_value); - at += 8; - } break; - case G_FmtArgKind_Float3: - { - Vec3 gpu_value = *(Vec3 *)at; - *dst = FmtFloat3(gpu_value); - at += 12; - } break; - case G_FmtArgKind_Float4: - { - Vec4 gpu_value = *(Vec4 *)at; - *dst = FmtFloat4(gpu_value); - at += 16; - } break; - } - dst->p = 16; - } - } - } + // // Translate float args + // case G_FmtArgKind_Float: + // { + // f32 gpu_value = *(f32 *)at; + // *dst = FmtFloat(gpu_value); + // at += 4; + // } break; + // case G_FmtArgKind_Float2: + // { + // Vec2 gpu_value = *(Vec2 *)at; + // *dst = FmtFloat2(gpu_value); + // at += 8; + // } break; + // case G_FmtArgKind_Float3: + // { + // Vec3 gpu_value = *(Vec3 *)at; + // *dst = FmtFloat3(gpu_value); + // at += 12; + // } break; + // case G_FmtArgKind_Float4: + // { + // Vec4 gpu_value = *(Vec4 *)at; + // *dst = FmtFloat4(gpu_value); + // at += 16; + // } break; + // } + // dst->p = 16; + // } + // } + // } - String final_str = Zi; - if (internal_overflow) - { - final_str = Lit("[Shader PrintF is too large]"); - } - else - { - final_str = FormatString(scratch.arena, fmt, args); - } - LogDebug(final_str); + // String final_str = Zi; + // if (internal_overflow) + // { + // final_str = Lit("[Shader PrintF is too large]"); + // } + // else + // { + // final_str = FormatString(scratch.arena, fmt, args); + // } + // LogDebug(final_str); - at = (u8 *)AlignU64((u64)at, 4); - } - } - EndScratch(scratch); - } - } - } - } + // at = (u8 *)AlignU64((u64)at, 4); + // } + // } + // EndScratch(scratch); + // } + // } + // } + // } } //////////////////////////////////////////////////////////// diff --git a/src/gpu/gpu_dx12/gpu_dx12_core.h b/src/gpu/gpu_dx12/gpu_dx12_core.h index f5dfaa97..4c4a2871 100644 --- a/src/gpu/gpu_dx12/gpu_dx12_core.h +++ b/src/gpu/gpu_dx12/gpu_dx12_core.h @@ -324,7 +324,6 @@ Struct(G_D12_Cmd) struct { // Post-batch data - b32 should_commit; u64 batch_gen; } barrier; @@ -506,6 +505,7 @@ G_D12_Resource *G_D12_ResourceFromHandle(G_ResourceHandle handle); G_D12_Swapchain *G_D12_SwapchainFromHandle(G_SwapchainHandle handle); DXGI_FORMAT G_D12_DxgiFormatFromGpuFormat(G_Format format); +b32 G_D12_IsSimultaneous(G_D12_Resource *resource); void G_D12_InitRtv(G_D12_Resource *resource, D3D12_CPU_DESCRIPTOR_HANDLE rtv_handle, i32 mip);