rename dx12 shader -> pipeline

This commit is contained in:
jacob 2025-06-08 14:55:36 -05:00
parent 7229daf49c
commit b87ef382d4

View File

@ -43,29 +43,29 @@
# define DX12_SHADER_DEBUG 0 # define DX12_SHADER_DEBUG 0
#endif #endif
enum dx12_shader_desc_flags { enum dx12_pipeline_desc_flags {
DX12_SHADER_DESC_FLAG_NONE = 0, DX12_PIPELINE_DESC_FLAG_NONE = 0,
DX12_SHADER_DESC_FLAG_VS = (1 << 0), DX12_PIPELINE_DESC_FLAG_VS = (1 << 0),
DX12_SHADER_DESC_FLAG_PS = (1 << 1) DX12_PIPELINE_DESC_FLAG_PS = (1 << 1)
}; };
struct dx12_shader_desc { struct dx12_pipeline_desc {
char *name; char *shader;
u32 flags; u32 flags;
}; };
struct dx12_shader { struct dx12_pipeline {
struct dx12_shader_desc desc; struct dx12_pipeline_desc desc;
ID3D12PipelineState *pso; ID3D12PipelineState *pso;
}; };
struct dx12_shader_result { struct dx12_pipeline_result {
struct dx12_shader shader; struct dx12_pipeline pipeline;
u64 errors_text_len; u64 errors_text_len;
u8 errors_text[KILOBYTE(16)]; u8 errors_text[KILOBYTE(16)];
}; };
struct dx12_shader_error { struct dx12_pipeline_error {
struct string msg; struct string msg;
}; };
@ -107,8 +107,11 @@ GLOBAL struct {
u32 desc_size_rtv; u32 desc_size_rtv;
/* Command queues */ /* Command queues */
/* TDOO: Add optional mode to route everything to direct queue */
ID3D12CommandQueue *cq_direct; ID3D12CommandQueue *cq_direct;
ID3D12CommandQueue *cq_compute; ID3D12CommandQueue *cq_compute;
ID3D12CommandQueue *cq_copy_critical;
ID3D12CommandQueue *cq_copy_background;
/* Swapchain */ /* Swapchain */
u32 swapchain_frame_index; u32 swapchain_frame_index;
@ -124,7 +127,7 @@ GLOBAL struct {
INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(gpu_shutdown); INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(gpu_shutdown);
INTERNAL void dx12_init_base(struct sys_window *window); 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) 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 */ /* Initialize dx12 */
dx12_init_base(window); dx12_init_base(window);
dx12_init_shaders(); dx12_init_pipelines();
/* Register callbacks */ /* Register callbacks */
app_register_exit_callback(gpu_shutdown); app_register_exit_callback(gpu_shutdown);
@ -155,10 +158,12 @@ INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(gpu_shutdown)
ID3D12Resource_Release(G.swapchain_rtvs[i]); ID3D12Resource_Release(G.swapchain_rtvs[i]);
} }
ID3D12DescriptorHeap_Release(G.swapchain_rtv_heap); 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); 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); ID3D12Device_Release(G.device);
#endif #endif
} }
@ -375,7 +380,6 @@ INTERNAL void dx12_init_base(struct sys_window *window)
D3D12_COMMAND_QUEUE_DESC desc = ZI; D3D12_COMMAND_QUEUE_DESC desc = ZI;
desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
hr = ID3D12Device_CreateCommandQueue(device, &desc, &IID_ID3D12CommandQueue, (void **)&cq_direct); hr = ID3D12Device_CreateCommandQueue(device, &desc, &IID_ID3D12CommandQueue, (void **)&cq_direct);
if (FAILED(hr)) { if (FAILED(hr)) {
dx12_init_error(LIT("Failed to create direct command queue")); 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; D3D12_COMMAND_QUEUE_DESC desc = ZI;
desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
desc.Type = D3D12_COMMAND_LIST_TYPE_COMPUTE; desc.Type = D3D12_COMMAND_LIST_TYPE_COMPUTE;
hr = ID3D12Device_CreateCommandQueue(device, &desc, &IID_ID3D12CommandQueue, (void **)&cq_compute); hr = ID3D12Device_CreateCommandQueue(device, &desc, &IID_ID3D12CommandQueue, (void **)&cq_compute);
if (FAILED(hr)) { if (FAILED(hr)) {
dx12_init_error(LIT("Failed to create compute command queue")); 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 */ /* Create swapchain command allocator */
ID3D12CommandAllocator *swapchain_ca = NULL; 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.swapchain_frame_index = swapchain_frame_index;
G.cq_direct = cq_direct; G.cq_direct = cq_direct;
G.cq_compute = cq_compute; 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_ca = swapchain_ca;
G.swapchain = swapchain; G.swapchain = swapchain;
G.swapchain_rtv_heap = swapchain_rtv_heap; 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 */ /* TDOO: Rename 'mesh shader' to 'triangle shader' or something */
/* TODO: Move shader structs into shared file */ /* 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; struct mat4x4 vp;
u32 instance_offset; u32 instance_offset;
}); });
PACK(struct dx12_texture_shader_instance { PACK(struct dx12_texture_pipeline_instance {
struct xform xf; struct xform xf;
struct v2 uv0; struct v2 uv0;
struct v2 uv1; 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 struct dx12_pipeline_result *pipeline_alloc_from_descs(struct arena *arena, u64 num_pipelines, struct dx12_pipeline_desc *descs);
INTERNAL void dx12_shader_release(struct dx12_shader *shader); INTERNAL void dx12_pipeline_release(struct dx12_pipeline *pipeline);
INTERNAL void dx12_init_shaders(void) INTERNAL void dx12_init_pipelines(void)
{ {
__prof; __prof;
struct arena_temp scratch = scratch_begin_no_conflict(); struct arena_temp scratch = scratch_begin_no_conflict();
struct dx12_shader_desc shader_descs[] = { struct dx12_pipeline_desc pipeline_descs[] = {
/* Texture shader */ /* Texture pipeline */
{ {
.name = "shaders/texture.hlsl", .shader = "shaders/texture.hlsl",
.flags = DX12_SHADER_DESC_FLAG_VS | .flags = DX12_PIPELINE_DESC_FLAG_VS |
DX12_SHADER_DESC_FLAG_PS DX12_PIPELINE_DESC_FLAG_PS
} }
}; };
struct dx12_shader_result *results = shader_alloc_from_descs(scratch.arena, ARRAY_COUNT(shader_descs), shader_descs); struct dx12_pipeline_result *results = pipeline_alloc_from_descs(scratch.arena, ARRAY_COUNT(pipeline_descs), pipeline_descs);
for (u64 i = 0; i < ARRAY_COUNT(shader_descs); ++i) { for (u64 i = 0; i < ARRAY_COUNT(pipeline_descs); ++i) {
struct dx12_shader_result *result = &results[i]; struct dx12_pipeline_result *result = &results[i];
if (result->errors_text_len > 0) { if (result->errors_text_len > 0) {
struct string msg = STRING(result->errors_text_len, result->errors_text); struct string msg = STRING(result->errors_text_len, result->errors_text);
sys_panic(msg); sys_panic(msg);
dx12_shader_release(&result->shader); dx12_pipeline_release(&result->pipeline);
} else { } else {
/* TODO */ /* TODO */
} }
@ -549,13 +579,13 @@ INTERNAL void dx12_init_shaders(void)
} }
/* ========================== * /* ========================== *
* Shader include handler * Shader compilation
* ========================== */ * ========================== */
struct dx12_include_handler { struct dx12_include_handler {
ID3DInclude d3d_handler; ID3DInclude d3d_handler;
ID3DIncludeVtbl vtbl; ID3DIncludeVtbl vtbl;
struct dx12_shader *shader; struct dx12_pipeline *pipeline;
b32 has_open_resource; b32 has_open_resource;
struct resource res; struct resource res;
}; };
@ -604,13 +634,13 @@ INTERNAL HRESULT dx12_include_close(ID3DInclude *d3d_handler, LPCVOID data)
return S_OK; 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; struct dx12_include_handler handler = ZI;
handler.d3d_handler.lpVtbl = &handler.vtbl; handler.d3d_handler.lpVtbl = &handler.vtbl;
handler.vtbl.Open = dx12_include_open; handler.vtbl.Open = dx12_include_open;
handler.vtbl.Close = dx12_include_close; handler.vtbl.Close = dx12_include_close;
handler.shader = shader; handler.pipeline = pipeline;
return handler; 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. /* TODO: Compile shaders offline w/ dxc.
* Will also allow for some hlsl language features like static_assert */ * 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 { struct shader_compile_task_arg {
/* In */ /* In */
enum shader_compile_task_kind kind; enum shader_compile_task_kind kind;
struct dx12_shader *shader; struct dx12_pipeline *pipeline;
struct resource *src_res; struct resource *src_res;
/* Out */ /* Out */
@ -646,17 +672,12 @@ struct shader_compile_task_arg {
ID3DBlob *error_blob; 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) INTERNAL WORK_TASK_FUNC_DEF(shader_compile_task, comp_arg_raw)
{ {
__prof; __prof;
struct shader_compile_task_arg *comp_arg = (struct shader_compile_task_arg *)comp_arg_raw; struct shader_compile_task_arg *comp_arg = (struct shader_compile_task_arg *)comp_arg_raw;
struct dx12_shader *shader = comp_arg->shader; struct dx12_pipeline *pipeline = comp_arg->pipeline;
struct string shader_name = string_from_cstr_no_limit(shader->desc.name); struct string shader_name = string_from_cstr_no_limit(pipeline->desc.shader);
enum shader_compile_task_kind kind = comp_arg->kind; enum shader_compile_task_kind kind = comp_arg->kind;
struct resource *src_res = comp_arg->src_res; 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; b32 success = false;
ID3DBlob *blob = NULL; ID3DBlob *blob = NULL;
ID3DBlob *error_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 (resource_exists(src_res)) {
#if 0 #if 0
@ -749,36 +770,45 @@ INTERNAL WORK_TASK_FUNC_DEF(shader_compile_task, comp_arg_raw)
scratch_end(scratch); 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; __prof;
struct shader_load_task_arg *load_arg = (struct shader_load_task_arg *)load_arg_raw; struct pipeline_load_task_arg *load_arg = (struct pipeline_load_task_arg *)load_arg_raw;
struct dx12_shader *shader = load_arg->shader; struct dx12_pipeline *pipeline = load_arg->pipeline;
struct dx12_shader_desc desc = shader->desc; struct dx12_pipeline_desc desc = pipeline->desc;
struct dx12_shader_result *result = load_arg->result; struct dx12_pipeline_result *result = load_arg->result;
struct arena_temp scratch = scratch_begin_no_conflict(); struct arena_temp scratch = scratch_begin_no_conflict();
{ {
struct string shader_name = string_from_cstr_no_limit(desc.name); struct string shader_name = string_from_cstr_no_limit(desc.shader);
logf_info("Loading shader '%F'", FMT_STR(shader_name)); logf_info("Loading pipeline from shader '%F'", FMT_STR(shader_name));
struct resource src_res = resource_open(shader_name); struct resource src_res = resource_open(shader_name);
struct string error_str = LIT("Unknown error"); struct string error_str = LIT("Unknown error");
struct shader_compile_task_arg vs = ZI; struct shader_compile_task_arg vs = ZI;
vs.kind = SHADER_COMPILE_TASK_KIND_VS; vs.kind = SHADER_COMPILE_TASK_KIND_VS;
vs.src_res = &src_res; vs.src_res = &src_res;
vs.shader = shader; vs.pipeline = pipeline;
struct shader_compile_task_arg ps = ZI; struct shader_compile_task_arg ps = ZI;
ps.kind = SHADER_COMPILE_TASK_KIND_PS; ps.kind = SHADER_COMPILE_TASK_KIND_PS;
ps.src_res = &src_res; ps.src_res = &src_res;
ps.shader = shader; ps.pipeline = pipeline;
struct work_slate ws = work_slate_begin(); 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); 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); work_slate_push_task(&ws, shader_compile_task, &ps);
} }
struct work_handle work = work_slate_end_and_help(&ws, WORK_PRIORITY_NORMAL); 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); MEMCPY(result->errors_text, error_str.text, result->errors_text_len);
} }
shader->pso = pso; pipeline->pso = pso;
if (vs.blob) { if (vs.blob) {
ID3D10Blob_Release(vs.blob); ID3D10Blob_Release(vs.blob);
@ -892,26 +922,26 @@ INTERNAL WORK_TASK_FUNC_DEF(shader_load_task, load_arg_raw)
scratch_end(scratch); 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; __prof;
struct dx12_shader_result *results = arena_push_array(arena, struct dx12_shader_result, num_shaders); struct dx12_pipeline_result *results = arena_push_array(arena, struct dx12_pipeline_result, num_pipelines);
struct shader_load_task_arg *task_args = arena_push_array(arena, struct shader_load_task_arg, num_shaders); 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(); struct sys_mutex arena_mutex = sys_mutex_alloc();
/* Create & dispatch work */ /* Create & dispatch work */
struct work_slate ws = work_slate_begin(); struct work_slate ws = work_slate_begin();
for (u64 i = 0; i < num_shaders; ++i) { for (u64 i = 0; i < num_pipelines; ++i) {
struct dx12_shader_result *result = &results[i]; struct dx12_pipeline_result *result = &results[i];
struct dx12_shader *shader = &results->shader; struct dx12_pipeline *pipeline = &results->pipeline;
shader->desc = descs[i]; pipeline->desc = descs[i];
struct shader_load_task_arg *arg = &task_args[i]; struct pipeline_load_task_arg *arg = &task_args[i];
arg->shader = shader; arg->pipeline = pipeline;
arg->result = result; 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); struct work_handle work = work_slate_end_and_help(&ws, WORK_PRIORITY_NORMAL);
work_wait(work); work_wait(work);
@ -920,11 +950,11 @@ INTERNAL struct dx12_shader_result *shader_alloc_from_descs(struct arena *arena,
return results; return results;
} }
INTERNAL void dx12_shader_release(struct dx12_shader *shader) INTERNAL void dx12_pipeline_release(struct dx12_pipeline *pipeline)
{ {
__prof; __prof;
if (shader->pso) { if (pipeline->pso) {
ID3D12PipelineState_Release(shader->pso); ID3D12PipelineState_Release(pipeline->pso);
} }
} }