From b87ef382d4c4b5dfe4bada7138c3c5e940989e83 Mon Sep 17 00:00:00 2001 From: jacob Date: Sun, 8 Jun 2025 14:55:36 -0500 Subject: [PATCH] rename dx12 shader -> pipeline --- src/gpu_dx12.c | 188 ++++++++++++++++++++++++++++--------------------- 1 file changed, 109 insertions(+), 79 deletions(-) diff --git a/src/gpu_dx12.c b/src/gpu_dx12.c index 48663061..11ab90ff 100644 --- a/src/gpu_dx12.c +++ b/src/gpu_dx12.c @@ -43,29 +43,29 @@ # define DX12_SHADER_DEBUG 0 #endif -enum dx12_shader_desc_flags { - DX12_SHADER_DESC_FLAG_NONE = 0, - DX12_SHADER_DESC_FLAG_VS = (1 << 0), - DX12_SHADER_DESC_FLAG_PS = (1 << 1) +enum dx12_pipeline_desc_flags { + DX12_PIPELINE_DESC_FLAG_NONE = 0, + DX12_PIPELINE_DESC_FLAG_VS = (1 << 0), + DX12_PIPELINE_DESC_FLAG_PS = (1 << 1) }; -struct dx12_shader_desc { - char *name; +struct dx12_pipeline_desc { + char *shader; u32 flags; }; -struct dx12_shader { - struct dx12_shader_desc desc; +struct dx12_pipeline { + struct dx12_pipeline_desc desc; ID3D12PipelineState *pso; }; -struct dx12_shader_result { - struct dx12_shader shader; +struct dx12_pipeline_result { + struct dx12_pipeline pipeline; u64 errors_text_len; u8 errors_text[KILOBYTE(16)]; }; -struct dx12_shader_error { +struct dx12_pipeline_error { struct string msg; }; @@ -107,8 +107,11 @@ GLOBAL struct { u32 desc_size_rtv; /* Command queues */ + /* TDOO: Add optional mode to route everything to direct queue */ ID3D12CommandQueue *cq_direct; ID3D12CommandQueue *cq_compute; + ID3D12CommandQueue *cq_copy_critical; + ID3D12CommandQueue *cq_copy_background; /* Swapchain */ u32 swapchain_frame_index; @@ -124,7 +127,7 @@ GLOBAL struct { INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(gpu_shutdown); INTERNAL void dx12_init_base(struct sys_window *window); -INTERNAL void dx12_init_shaders(void); +INTERNAL void dx12_init_pipelines(void); struct gpu_startup_receipt gpu_startup(struct work_startup_receipt *work_sr, struct sys_window *window) { @@ -137,7 +140,7 @@ struct gpu_startup_receipt gpu_startup(struct work_startup_receipt *work_sr, str /* Initialize dx12 */ dx12_init_base(window); - dx12_init_shaders(); + dx12_init_pipelines(); /* Register callbacks */ app_register_exit_callback(gpu_shutdown); @@ -155,10 +158,12 @@ INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(gpu_shutdown) ID3D12Resource_Release(G.swapchain_rtvs[i]); } ID3D12DescriptorHeap_Release(G.swapchain_rtv_heap); - ID3D12CommandQueue_Release(G.swapchain_ca); - ID3D12CommandQueue_Release(G.cq_direct); - ID3D12CommandQueue_Release(G.cq_compute); IDXGISwapChain3_Release(G.swapchain); + ID3D12CommandAllocator_Release(G.swapchain_ca); + ID3D12CommandQueue_Release(G.cq_copy_background); + ID3D12CommandQueue_Release(G.cq_copy_critical); + ID3D12CommandQueue_Release(G.cq_compute); + ID3D12CommandQueue_Release(G.cq_direct); ID3D12Device_Release(G.device); #endif } @@ -375,7 +380,6 @@ INTERNAL void dx12_init_base(struct sys_window *window) D3D12_COMMAND_QUEUE_DESC desc = ZI; desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; - hr = ID3D12Device_CreateCommandQueue(device, &desc, &IID_ID3D12CommandQueue, (void **)&cq_direct); if (FAILED(hr)) { dx12_init_error(LIT("Failed to create direct command queue")); @@ -388,13 +392,37 @@ INTERNAL void dx12_init_base(struct sys_window *window) D3D12_COMMAND_QUEUE_DESC desc = ZI; desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; desc.Type = D3D12_COMMAND_LIST_TYPE_COMPUTE; - hr = ID3D12Device_CreateCommandQueue(device, &desc, &IID_ID3D12CommandQueue, (void **)&cq_compute); if (FAILED(hr)) { dx12_init_error(LIT("Failed to create compute command queue")); } } + /* Create critical copy command queue */ + ID3D12CommandQueue *cq_copy_critical = NULL; + { + D3D12_COMMAND_QUEUE_DESC desc = ZI; + desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + desc.Type = D3D12_COMMAND_LIST_TYPE_COPY; + desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_HIGH; + hr = ID3D12Device_CreateCommandQueue(device, &desc, &IID_ID3D12CommandQueue, (void **)&cq_copy_critical); + if (FAILED(hr)) { + dx12_init_error(LIT("Failed to create critical copy command queue")); + } + } + + /* Create background copy command queue */ + ID3D12CommandQueue *cq_copy_background = NULL; + { + D3D12_COMMAND_QUEUE_DESC desc = ZI; + desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + desc.Type = D3D12_COMMAND_LIST_TYPE_COPY; + hr = ID3D12Device_CreateCommandQueue(device, &desc, &IID_ID3D12CommandQueue, (void **)&cq_copy_background); + if (FAILED(hr)) { + dx12_init_error(LIT("Failed to create background copy command queue")); + } + } + /* Create swapchain command allocator */ ID3D12CommandAllocator *swapchain_ca = NULL; { @@ -476,6 +504,8 @@ INTERNAL void dx12_init_base(struct sys_window *window) G.swapchain_frame_index = swapchain_frame_index; G.cq_direct = cq_direct; G.cq_compute = cq_compute; + G.cq_copy_critical = cq_copy_critical; + G.cq_copy_background = cq_copy_background; G.swapchain_ca = swapchain_ca; G.swapchain = swapchain; G.swapchain_rtv_heap = swapchain_rtv_heap; @@ -486,24 +516,24 @@ INTERNAL void dx12_init_base(struct sys_window *window) } /* ========================== * - * Dx12 shader initialization + * Dx12 pipeline initialization * ========================== */ /* TDOO: Rename 'mesh shader' to 'triangle shader' or something */ /* TODO: Move shader structs into shared file */ /* ============= */ -/* Mesh shader */ +/* Mesh pipeline */ /* ============= */ -/* Texture shader */ +/* Texture pipeline */ -PACK(struct dx12_texture_shader_uniform { +PACK(struct dx12_texture_pipeline_uniform { struct mat4x4 vp; u32 instance_offset; }); -PACK(struct dx12_texture_shader_instance { +PACK(struct dx12_texture_pipeline_instance { struct xform xf; struct v2 uv0; struct v2 uv1; @@ -512,34 +542,34 @@ PACK(struct dx12_texture_shader_instance { }); /* ============= */ -/* Grid shader */ +/* Grid pipeline */ /* ============= */ -/* Init shaders */ +/* Init pipelines */ -INTERNAL struct dx12_shader_result *shader_alloc_from_descs(struct arena *arena, u64 num_shaders, struct dx12_shader_desc *descs); -INTERNAL void dx12_shader_release(struct dx12_shader *shader); +INTERNAL struct dx12_pipeline_result *pipeline_alloc_from_descs(struct arena *arena, u64 num_pipelines, struct dx12_pipeline_desc *descs); +INTERNAL void dx12_pipeline_release(struct dx12_pipeline *pipeline); -INTERNAL void dx12_init_shaders(void) +INTERNAL void dx12_init_pipelines(void) { __prof; struct arena_temp scratch = scratch_begin_no_conflict(); - struct dx12_shader_desc shader_descs[] = { - /* Texture shader */ + struct dx12_pipeline_desc pipeline_descs[] = { + /* Texture pipeline */ { - .name = "shaders/texture.hlsl", - .flags = DX12_SHADER_DESC_FLAG_VS | - DX12_SHADER_DESC_FLAG_PS + .shader = "shaders/texture.hlsl", + .flags = DX12_PIPELINE_DESC_FLAG_VS | + DX12_PIPELINE_DESC_FLAG_PS } }; - struct dx12_shader_result *results = shader_alloc_from_descs(scratch.arena, ARRAY_COUNT(shader_descs), shader_descs); - for (u64 i = 0; i < ARRAY_COUNT(shader_descs); ++i) { - struct dx12_shader_result *result = &results[i]; + struct dx12_pipeline_result *results = pipeline_alloc_from_descs(scratch.arena, ARRAY_COUNT(pipeline_descs), pipeline_descs); + for (u64 i = 0; i < ARRAY_COUNT(pipeline_descs); ++i) { + struct dx12_pipeline_result *result = &results[i]; if (result->errors_text_len > 0) { struct string msg = STRING(result->errors_text_len, result->errors_text); sys_panic(msg); - dx12_shader_release(&result->shader); + dx12_pipeline_release(&result->pipeline); } else { /* TODO */ } @@ -549,13 +579,13 @@ INTERNAL void dx12_init_shaders(void) } /* ========================== * - * Shader include handler + * Shader compilation * ========================== */ struct dx12_include_handler { ID3DInclude d3d_handler; ID3DIncludeVtbl vtbl; - struct dx12_shader *shader; + struct dx12_pipeline *pipeline; b32 has_open_resource; struct resource res; }; @@ -604,13 +634,13 @@ INTERNAL HRESULT dx12_include_close(ID3DInclude *d3d_handler, LPCVOID data) return S_OK; } -INTERNAL struct dx12_include_handler dx12_include_handler_alloc(struct dx12_shader *shader) +INTERNAL struct dx12_include_handler dx12_include_handler_alloc(struct dx12_pipeline *pipeline) { struct dx12_include_handler handler = ZI; handler.d3d_handler.lpVtbl = &handler.vtbl; handler.vtbl.Open = dx12_include_open; handler.vtbl.Close = dx12_include_close; - handler.shader = shader; + handler.pipeline = pipeline; return handler; } @@ -622,10 +652,6 @@ INTERNAL void dx12_include_handler_release(struct dx12_include_handler *handler) } } -/* ========================== * - * Shader compilation - * ========================== */ - /* TODO: Compile shaders offline w/ dxc. * Will also allow for some hlsl language features like static_assert */ @@ -637,7 +663,7 @@ enum shader_compile_task_kind { struct shader_compile_task_arg { /* In */ enum shader_compile_task_kind kind; - struct dx12_shader *shader; + struct dx12_pipeline *pipeline; struct resource *src_res; /* Out */ @@ -646,17 +672,12 @@ struct shader_compile_task_arg { ID3DBlob *error_blob; }; -struct shader_load_task_arg { - struct dx12_shader *shader; - struct dx12_shader_result *result; -}; - INTERNAL WORK_TASK_FUNC_DEF(shader_compile_task, comp_arg_raw) { __prof; struct shader_compile_task_arg *comp_arg = (struct shader_compile_task_arg *)comp_arg_raw; - struct dx12_shader *shader = comp_arg->shader; - struct string shader_name = string_from_cstr_no_limit(shader->desc.name); + struct dx12_pipeline *pipeline = comp_arg->pipeline; + struct string shader_name = string_from_cstr_no_limit(pipeline->desc.shader); enum shader_compile_task_kind kind = comp_arg->kind; struct resource *src_res = comp_arg->src_res; @@ -665,7 +686,7 @@ INTERNAL WORK_TASK_FUNC_DEF(shader_compile_task, comp_arg_raw) b32 success = false; ID3DBlob *blob = NULL; ID3DBlob *error_blob = NULL; - struct dx12_include_handler include_handler = dx12_include_handler_alloc(shader); + struct dx12_include_handler include_handler = dx12_include_handler_alloc(pipeline); if (resource_exists(src_res)) { #if 0 @@ -749,36 +770,45 @@ INTERNAL WORK_TASK_FUNC_DEF(shader_compile_task, comp_arg_raw) scratch_end(scratch); } -INTERNAL WORK_TASK_FUNC_DEF(shader_load_task, load_arg_raw) +/* ========================== * + * Pipeline + * ========================== */ + +struct pipeline_load_task_arg { + struct dx12_pipeline *pipeline; + struct dx12_pipeline_result *result; +}; + +INTERNAL WORK_TASK_FUNC_DEF(pipeline_load_task, load_arg_raw) { __prof; - struct shader_load_task_arg *load_arg = (struct shader_load_task_arg *)load_arg_raw; - struct dx12_shader *shader = load_arg->shader; - struct dx12_shader_desc desc = shader->desc; - struct dx12_shader_result *result = load_arg->result; + struct pipeline_load_task_arg *load_arg = (struct pipeline_load_task_arg *)load_arg_raw; + struct dx12_pipeline *pipeline = load_arg->pipeline; + struct dx12_pipeline_desc desc = pipeline->desc; + struct dx12_pipeline_result *result = load_arg->result; struct arena_temp scratch = scratch_begin_no_conflict(); { - struct string shader_name = string_from_cstr_no_limit(desc.name); - logf_info("Loading shader '%F'", FMT_STR(shader_name)); + struct string shader_name = string_from_cstr_no_limit(desc.shader); + logf_info("Loading pipeline from shader '%F'", FMT_STR(shader_name)); struct resource src_res = resource_open(shader_name); struct string error_str = LIT("Unknown error"); struct shader_compile_task_arg vs = ZI; vs.kind = SHADER_COMPILE_TASK_KIND_VS; vs.src_res = &src_res; - vs.shader = shader; + vs.pipeline = pipeline; struct shader_compile_task_arg ps = ZI; ps.kind = SHADER_COMPILE_TASK_KIND_PS; ps.src_res = &src_res; - ps.shader = shader; + ps.pipeline = pipeline; struct work_slate ws = work_slate_begin(); - if (desc.flags & DX12_SHADER_DESC_FLAG_VS) { + if (desc.flags & DX12_PIPELINE_DESC_FLAG_VS) { work_slate_push_task(&ws, shader_compile_task, &vs); } - if (desc.flags & DX12_SHADER_DESC_FLAG_PS) { + if (desc.flags & DX12_PIPELINE_DESC_FLAG_PS) { work_slate_push_task(&ws, shader_compile_task, &ps); } struct work_handle work = work_slate_end_and_help(&ws, WORK_PRIORITY_NORMAL); @@ -873,7 +903,7 @@ INTERNAL WORK_TASK_FUNC_DEF(shader_load_task, load_arg_raw) MEMCPY(result->errors_text, error_str.text, result->errors_text_len); } - shader->pso = pso; + pipeline->pso = pso; if (vs.blob) { ID3D10Blob_Release(vs.blob); @@ -892,26 +922,26 @@ INTERNAL WORK_TASK_FUNC_DEF(shader_load_task, load_arg_raw) scratch_end(scratch); } -INTERNAL struct dx12_shader_result *shader_alloc_from_descs(struct arena *arena, u64 num_shaders, struct dx12_shader_desc *descs) +INTERNAL struct dx12_pipeline_result *pipeline_alloc_from_descs(struct arena *arena, u64 num_pipelines, struct dx12_pipeline_desc *descs) { __prof; - struct dx12_shader_result *results = arena_push_array(arena, struct dx12_shader_result, num_shaders); - struct shader_load_task_arg *task_args = arena_push_array(arena, struct shader_load_task_arg, num_shaders); + struct dx12_pipeline_result *results = arena_push_array(arena, struct dx12_pipeline_result, num_pipelines); + struct pipeline_load_task_arg *task_args = arena_push_array(arena, struct pipeline_load_task_arg, num_pipelines); struct sys_mutex arena_mutex = sys_mutex_alloc(); /* Create & dispatch work */ struct work_slate ws = work_slate_begin(); - for (u64 i = 0; i < num_shaders; ++i) { - struct dx12_shader_result *result = &results[i]; + for (u64 i = 0; i < num_pipelines; ++i) { + struct dx12_pipeline_result *result = &results[i]; - struct dx12_shader *shader = &results->shader; - shader->desc = descs[i]; + struct dx12_pipeline *pipeline = &results->pipeline; + pipeline->desc = descs[i]; - struct shader_load_task_arg *arg = &task_args[i]; - arg->shader = shader; + struct pipeline_load_task_arg *arg = &task_args[i]; + arg->pipeline = pipeline; arg->result = result; - work_slate_push_task(&ws, shader_load_task, arg); + work_slate_push_task(&ws, pipeline_load_task, arg); } struct work_handle work = work_slate_end_and_help(&ws, WORK_PRIORITY_NORMAL); work_wait(work); @@ -920,11 +950,11 @@ INTERNAL struct dx12_shader_result *shader_alloc_from_descs(struct arena *arena, return results; } -INTERNAL void dx12_shader_release(struct dx12_shader *shader) +INTERNAL void dx12_pipeline_release(struct dx12_pipeline *pipeline) { __prof; - if (shader->pso) { - ID3D12PipelineState_Release(shader->pso); + if (pipeline->pso) { + ID3D12PipelineState_Release(pipeline->pso); } }