From 01aff521daf1156c069a2d87ceabe6f1e4831cf7 Mon Sep 17 00:00:00 2001 From: jacob Date: Mon, 23 Jun 2025 16:38:55 -0500 Subject: [PATCH] use root constants --- res/sh/common.hlsl | 4 +- res/sh/material.hlsl | 2 +- res/sh/sh_common.h | 3 + src/gp_dx12.c | 397 ++++++++++++++++++++++++++----------------- 4 files changed, 251 insertions(+), 155 deletions(-) diff --git a/res/sh/common.hlsl b/res/sh/common.hlsl index 4bbfe07b..7a008d1e 100644 --- a/res/sh/common.hlsl +++ b/res/sh/common.hlsl @@ -6,8 +6,8 @@ #define DECL(t, n) t n : n #define NURI(i) NonUniformResourceIndex(i) -#ifdef INTELLISENSE -# define INLINE +#if !SH_CPU +# define INLINE /* For intellisense */ #endif /* Linear color from normalized sRGB */ diff --git a/res/sh/material.hlsl b/res/sh/material.hlsl index 86b506e4..aa086f93 100644 --- a/res/sh/material.hlsl +++ b/res/sh/material.hlsl @@ -5,7 +5,7 @@ * ========================== */ #define ROOTSIG \ - "CBV(b0), " \ + "RootConstants(num32BitConstants=16, b0), " \ "SRV(t0), " \ "DescriptorTable(SRV(t1, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE)), " \ "StaticSampler(s0, " \ diff --git a/res/sh/sh_common.h b/res/sh/sh_common.h index 9ddbd6dd..ca1506ce 100644 --- a/res/sh/sh_common.h +++ b/res/sh/sh_common.h @@ -3,6 +3,7 @@ #define SH_STRUCT(s) PACK(struct s) #define SH_DECL(t, n) struct CAT(sh_, t) n #define SH_ENTRY(rootsig) static +#define SH_ASSERT_32BIT(s, n) CT_ASSERT((sizeof(s) / 4) == n) struct sh_uint { u32 v; }; INLINE struct sh_uint sh_uint_from_u32(u32 v) @@ -45,6 +46,7 @@ INLINE struct sh_float2x3 sh_float2x3_from_xform(struct xform v) #define SH_STRUCT(s) struct s #define SH_DECL(t, n) t n #define SH_ENTRY(rootsig) [RootSignature(rootsig)] +#define SH_ASSERT_32BIT(s, n) #endif @@ -55,6 +57,7 @@ INLINE struct sh_float2x3 sh_float2x3_from_xform(struct xform v) SH_STRUCT(sh_material_constants { SH_DECL(float4x4, projection); }); +SH_ASSERT_32BIT(struct sh_material_constants, 16); /* Expected 32bit root constant size in shader */ SH_STRUCT(sh_material_instance { SH_DECL(float2x3, xf); diff --git a/src/gp_dx12.c b/src/gp_dx12.c index 9bb5b80f..e9c03155 100644 --- a/src/gp_dx12.c +++ b/src/gp_dx12.c @@ -72,20 +72,24 @@ struct pipeline_desc { }; struct pipeline { + b32 valid; + + struct arena *arena; + struct string name; + + u32 num_errors; + struct pipeline_error *first_error; + struct pipeline_error *last_error; + i64 compilation_time; + struct pipeline_desc desc; ID3D12PipelineState *pso; ID3D12RootSignature *rootsig; }; -struct pipeline_result { - struct pipeline pipeline; - i64 elapsed; - u64 errors_text_len; - u8 errors_text[KILOBYTE(16)]; -}; - struct pipeline_error { struct string msg; + struct pipeline_error *next; }; struct command_queue { @@ -236,22 +240,10 @@ GLOBAL struct { struct arena *resources_arena; struct dx12_resource *first_free_resource; - - - - - - - - /* FIXME: Remove this (testing) */ - struct pipeline test_pipeline; - - - - - - - + /* Pipeline cache */ + struct sys_mutex *pipelines_mutex; + struct arena *pipelines_arena; + struct dict *pipelines_dict; /* Factory */ IDXGIFactory6 *factory; @@ -298,6 +290,10 @@ INTERNAL struct command_queue *command_queue_alloc(enum D3D12_COMMAND_LIST_TYPE INTERNAL void command_queue_release(struct command_queue *cq); INTERNAL void dx12_resource_release(struct dx12_resource *resource); +#if RESOURCE_RELOADING +INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(pipeline_resource_watch_callback, name); +#endif + struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr) { __prof; @@ -319,12 +315,20 @@ struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr) G.resources_mutex = sys_mutex_alloc(); G.resources_arena = arena_alloc(GIGABYTE(64)); + /* Initialize pipeline cache */ + G.pipelines_mutex = sys_mutex_alloc(); + G.pipelines_arena = arena_alloc(GIGABYTE(64)); + G.pipelines_dict = dict_init(G.pipelines_arena, 1024); + /* Initialize dx12 */ dx12_init_device(); dx12_init_objects(); dx12_init_pipelines(); /* Register callbacks */ +#if RESOURCE_RELOADING + resource_register_watch_callback(pipeline_resource_watch_callback); +#endif app_register_exit_callback(gp_shutdown); struct gp_startup_receipt res = ZI; @@ -630,35 +634,35 @@ PACK(struct fx_material_instance { /* ============= */ /* Init pipelines */ -INTERNAL struct pipeline_result *pipeline_alloc_from_descs(struct arena *arena, u64 num_pipelines, struct pipeline_desc *descs); +INTERNAL READONLY struct pipeline g_nil_pipeline = ZI; +INTERNAL READONLY struct pipeline_desc g_pipeline_descs[] = { + /* Material pipeline */ + { + .name = "material", + .vs = { "sh/material.hlsl", "vs" }, + .ps = { "sh/material.hlsl", "ps" } + } +}; + +INTERNAL struct pipeline **pipeline_alloc_from_descs(struct arena *arena, u64 num_pipelines, struct pipeline_desc *descs); INTERNAL void pipeline_release(struct pipeline *pipeline); +INTERNAL void pipeline_register(struct pipeline *pipeline); INTERNAL void dx12_init_pipelines(void) { __prof; struct arena_temp scratch = scratch_begin_no_conflict(); - struct pipeline_desc pipeline_descs[] = { - /* Material pipeline */ - { - .name = "material", - .vs = { "sh/material.hlsl", "vs" }, - .ps = { "sh/material.hlsl", "ps" } - } - }; - - struct 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 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); - pipeline_release(&result->pipeline); + struct pipeline **pipelines = pipeline_alloc_from_descs(scratch.arena, ARRAY_COUNT(g_pipeline_descs), g_pipeline_descs); + for (u64 i = 0; i < ARRAY_COUNT(g_pipeline_descs); ++i) { + struct pipeline *pipeline = pipelines[i]; + if (pipeline->num_errors > 0) { + sys_panic(pipeline->first_error->msg); + pipeline_release(pipeline); } else { - /* FIXME: remove this */ - G.test_pipeline = result->pipeline; + pipeline->valid = true; + pipeline_register(pipeline); } } - scratch_end(scratch); } @@ -838,7 +842,6 @@ INTERNAL WORK_TASK_FUNC_DEF(shader_compile_task, comp_arg_raw) struct pipeline_load_task_arg { struct pipeline *pipeline; - struct pipeline_result *result; }; INTERNAL WORK_TASK_FUNC_DEF(pipeline_load_task, load_arg_raw) @@ -847,12 +850,11 @@ INTERNAL WORK_TASK_FUNC_DEF(pipeline_load_task, load_arg_raw) struct pipeline_load_task_arg *load_arg = (struct pipeline_load_task_arg *)load_arg_raw; struct pipeline *pipeline = load_arg->pipeline; struct pipeline_desc desc = pipeline->desc; - struct pipeline_result *result = load_arg->result; struct arena_temp scratch = scratch_begin_no_conflict(); { i64 start_ns = sys_time_ns(); - struct string pipeline_name = string_from_cstr_no_limit(desc.name); + struct string pipeline_name = pipeline->name; logf_info("Loading pipeline \"%F\"", FMT_STR(pipeline_name)); b32 success = true; HRESULT hr = 0; @@ -1040,13 +1042,20 @@ INTERNAL WORK_TASK_FUNC_DEF(pipeline_load_task, load_arg_raw) error_str = error_blob_str; } } - result->errors_text_len = min_u64(error_str.len, ARRAY_COUNT(result->errors_text)); - MEMCPY(result->errors_text, error_str.text, result->errors_text_len); + struct pipeline_error *error = arena_push(pipeline->arena, struct pipeline_error); + error->msg = string_copy(pipeline->arena, error_str); + if (pipeline->last_error) { + pipeline->last_error->next = error; + } else { + pipeline->first_error = error; + } + pipeline->last_error = error; + ++pipeline->num_errors; } pipeline->pso = pso; pipeline->rootsig = rootsig; - result->elapsed = sys_time_ns() - start_ns; + pipeline->compilation_time = sys_time_ns() - start_ns; resource_close(&vs_res); if (!ps_res_is_shared) { @@ -1071,30 +1080,35 @@ INTERNAL WORK_TASK_FUNC_DEF(pipeline_load_task, load_arg_raw) scratch_end(scratch); } -INTERNAL struct pipeline_result *pipeline_alloc_from_descs(struct arena *arena, u64 num_pipelines, struct pipeline_desc *descs) +INTERNAL struct pipeline **pipeline_alloc_from_descs(struct arena *arena, u64 num_pipelines, struct pipeline_desc *descs) { __prof; - struct pipeline_result *results = arena_push_array(arena, struct pipeline_result, num_pipelines); + struct pipeline **pipelines = arena_push_array(arena, struct pipeline *, num_pipelines); struct pipeline_load_task_arg *task_args = arena_push_array(arena, struct pipeline_load_task_arg, num_pipelines); /* Load pipelines */ struct work_slate ws = work_slate_begin(); for (u64 i = 0; i < num_pipelines; ++i) { - struct pipeline_result *result = &results[i]; - - struct pipeline *pipeline = &results->pipeline; - pipeline->desc = descs[i]; + struct pipeline_desc desc = descs[i]; + struct pipeline *pipeline = NULL; + { + struct arena *pipeline_arena = arena_alloc(MEGABYTE(64)); + pipeline = arena_push(pipeline_arena, struct pipeline); + pipeline->arena = pipeline_arena; + pipelines[i] = pipeline; + } + pipeline->desc = desc; + pipeline->name = string_copy(pipeline->arena, string_from_cstr_no_limit(desc.name)); struct pipeline_load_task_arg *arg = &task_args[i]; arg->pipeline = pipeline; - arg->result = result; work_slate_push_task(&ws, pipeline_load_task, arg); } struct work_handle work = work_slate_end_and_help(&ws, WORK_PRIORITY_HIGH); work_wait(work); - return results; + return pipelines; } INTERNAL void pipeline_release(struct pipeline *pipeline) @@ -1103,8 +1117,66 @@ INTERNAL void pipeline_release(struct pipeline *pipeline) if (pipeline->pso) { ID3D12PipelineState_Release(pipeline->pso); } + arena_release(pipeline->arena); } +/* ========================== * + * Pipeline cache + * ========================== */ + +struct pipeline_scope { + i32 _; +}; + +INTERNAL struct pipeline_scope *pipeline_scope_begin(void) +{ + return NULL; +} + +INTERNAL void pipeline_scope_end(struct pipeline_scope *scope) +{ + (UNUSED)scope; +} + +INTERNAL struct pipeline *pipeline_from_name(struct pipeline_scope *scope, struct string name) +{ + (UNUSED)scope; + + struct pipeline *pipeline = &g_nil_pipeline; + u64 hash = hash_fnv64(HASH_FNV64_BASIS, name); + struct sys_lock lock = sys_mutex_lock_s(G.pipelines_mutex); + { + struct pipeline *res = dict_get(G.pipelines_dict, hash); + if (res) { + pipeline = res; + } + } + sys_mutex_unlock(&lock); + return pipeline; +} + +INTERNAL void pipeline_register(struct pipeline *pipeline) +{ + u64 hash = hash_fnv64(HASH_FNV64_BASIS, pipeline->name); + struct sys_lock lock = sys_mutex_lock_e(G.pipelines_mutex); + { + dict_set(G.pipelines_arena, G.pipelines_dict, hash, pipeline); + } + sys_mutex_unlock(&lock); +} + +#if RESOURCE_RELOADING +INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(pipeline_resource_watch_callback, name) +{ +#if 0 + if (shader_set_dirty(name)) { + logf_debug("Shader source file \"%F\" has changed", FMT_STR(name)); + } +#else + (UNUSED)name; +#endif +} +#endif /* ========================== * * Descriptor @@ -1771,6 +1843,25 @@ INTERNAL struct command_buffer *command_list_push_buffer(struct command_list *cl return cb; } +/* ========================== * + * Command root constant + * ========================== */ + +INTERNAL void command_list_set_root_constant(struct command_list *cl, void *src, u32 size) +{ + if (size % 4 == 0) { + u32 num32bit = size / 4; + for (u32 i = 0; i < num32bit; ++i) { + u32 val = 0; + MEMCPY(&val, (((u32 *)src) + i), 4); + ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstant(cl->cl, 0, val, i); + } + } else { + /* Root constant structs must pad to 32 bits */ + ASSERT(false); + } +} + /* ========================== * * Texture * ========================== */ @@ -1960,110 +2051,111 @@ void gp_dispatch(struct gp_dispatch_params params) struct flow *flow = handle_get_data(params.flow, DX12_HANDLE_KIND_FLOW); - /* Material pass */ - struct command_list *cl = command_list_open(G.cq_direct); - { - struct dx12_resource *target = handle_get_data(params.draw_target, DX12_HANDLE_KIND_RESOURCE); - - /* Upload dummmy vert & index buffer */ - /* TODO: Make these static */ - /* Dummy vertex buffer */ - LOCAL_PERSIST u16 quad_indices[6] = { 0, 1, 2, 0, 2, 3 }; - struct command_buffer *dummy_vertex_buffer = command_list_push_buffer(cl, STRING(0, 0)); - struct command_buffer *quad_index_buffer = command_list_push_buffer(cl, STRING_FROM_ARRAY(quad_indices)); - D3D12_VERTEX_BUFFER_VIEW dummy_vertex_buffer_view = ZI; - dummy_vertex_buffer_view.BufferLocation = dummy_vertex_buffer->resource->gpu_address; - D3D12_INDEX_BUFFER_VIEW quad_index_buffer_view = ZI; - quad_index_buffer_view.BufferLocation = quad_index_buffer->resource->gpu_address; - quad_index_buffer_view.Format = DXGI_FORMAT_R16_UINT; - quad_index_buffer_view.SizeInBytes = sizeof(quad_indices); - - /* Upload instance buffer */ - struct command_buffer *instance_buffer = command_list_push_buffer(cl, STRING_FROM_ARENA(flow->material_instances_arena)); - - /* Upload descriptor heap */ - struct command_descriptor_heap *descriptor_heap = command_list_push_descriptor_heap(cl, G.cbv_srv_uav_heap); - - /* Viewport */ - struct rect viewport = params.draw_target_viewport; - struct D3D12_VIEWPORT d3d12_viewport = ZI; - d3d12_viewport.TopLeftX = viewport.x; - d3d12_viewport.TopLeftY = viewport.y; - d3d12_viewport.Width = viewport.width; - d3d12_viewport.Height = viewport.height; - d3d12_viewport.MinDepth = 0.0f; - d3d12_viewport.MaxDepth = 1.0f; - - /* Scissor */ - D3D12_RECT d3d12_scissor = ZI; - d3d12_scissor.left = viewport.x; - d3d12_scissor.top = viewport.y; - d3d12_scissor.right = viewport.x + viewport.width; - d3d12_scissor.bottom = viewport.y + viewport.height; - - struct mat4x4 vp_matrix = calculate_vp(params.draw_target_view, viewport.width, viewport.height); - - /* Create temporary descriptor heap */ - /* NOTE: This should always occur after buffers are submitted */ - - - /* Transition render target */ - enum D3D12_RESOURCE_STATES target_old_state = dx12_resource_barrier(cl->cl, target, D3D12_RESOURCE_STATE_RENDER_TARGET); + struct pipeline_scope *pipeline_scope = pipeline_scope_begin(); + struct pipeline *material_pipeline = pipeline_from_name(pipeline_scope, LIT("material")); + if (material_pipeline->valid) { + struct command_list *cl = command_list_open(G.cq_direct); { - ID3D12GraphicsCommandList_OMSetRenderTargets(cl->cl, 1, &target->rtv_descriptor->handle, false, NULL); - if (params.clear_target) { - f32 clear_color[] = { 0.0f, 0.0f, 0.0f, 0.0f }; - ID3D12GraphicsCommandList_ClearRenderTargetView(cl->cl, target->rtv_descriptor->handle, clear_color, 0, NULL); + struct dx12_resource *target = handle_get_data(params.draw_target, DX12_HANDLE_KIND_RESOURCE); + + /* Upload dummmy vert & index buffer */ + /* TODO: Make these static */ + /* Dummy vertex buffer */ + LOCAL_PERSIST u16 quad_indices[6] = { 0, 1, 2, 0, 2, 3 }; + struct command_buffer *dummy_vertex_buffer = command_list_push_buffer(cl, STRING(0, 0)); + struct command_buffer *quad_index_buffer = command_list_push_buffer(cl, STRING_FROM_ARRAY(quad_indices)); + D3D12_VERTEX_BUFFER_VIEW dummy_vertex_buffer_view = ZI; + dummy_vertex_buffer_view.BufferLocation = dummy_vertex_buffer->resource->gpu_address; + D3D12_INDEX_BUFFER_VIEW quad_index_buffer_view = ZI; + quad_index_buffer_view.BufferLocation = quad_index_buffer->resource->gpu_address; + quad_index_buffer_view.Format = DXGI_FORMAT_R16_UINT; + quad_index_buffer_view.SizeInBytes = sizeof(quad_indices); + + /* Upload instance buffer */ + struct command_buffer *instance_buffer = command_list_push_buffer(cl, STRING_FROM_ARENA(flow->material_instances_arena)); + + /* Upload descriptor heap */ + struct command_descriptor_heap *descriptor_heap = command_list_push_descriptor_heap(cl, G.cbv_srv_uav_heap); + + /* Viewport */ + struct rect viewport = params.draw_target_viewport; + struct D3D12_VIEWPORT d3d12_viewport = ZI; + d3d12_viewport.TopLeftX = viewport.x; + d3d12_viewport.TopLeftY = viewport.y; + d3d12_viewport.Width = viewport.width; + d3d12_viewport.Height = viewport.height; + d3d12_viewport.MinDepth = 0.0f; + d3d12_viewport.MaxDepth = 1.0f; + + /* Scissor */ + D3D12_RECT d3d12_scissor = ZI; + d3d12_scissor.left = viewport.x; + d3d12_scissor.top = viewport.y; + d3d12_scissor.right = viewport.x + viewport.width; + d3d12_scissor.bottom = viewport.y + viewport.height; + + struct mat4x4 vp_matrix = calculate_vp(params.draw_target_view, viewport.width, viewport.height); + + /* Create temporary descriptor heap */ + /* NOTE: This should always occur after buffers are submitted */ + + + /* Transition render target */ + enum D3D12_RESOURCE_STATES target_old_state = dx12_resource_barrier(cl->cl, target, D3D12_RESOURCE_STATE_RENDER_TARGET); + { + ID3D12GraphicsCommandList_OMSetRenderTargets(cl->cl, 1, &target->rtv_descriptor->handle, false, NULL); + if (params.clear_target) { + f32 clear_color[] = { 0.0f, 0.0f, 0.0f, 0.0f }; + ID3D12GraphicsCommandList_ClearRenderTargetView(cl->cl, target->rtv_descriptor->handle, clear_color, 0, NULL); + } + } + + /* Material pass */ + { + u32 instance_count = instance_buffer->size / sizeof(struct sh_material_instance); + + /* Bind pipeline */ + ID3D12GraphicsCommandList_SetPipelineState(cl->cl, material_pipeline->pso); + ID3D12GraphicsCommandList_SetGraphicsRootSignature(cl->cl, material_pipeline->rootsig); + + /* Set root constants */ + struct sh_material_constants constants = ZI; + constants.projection = sh_float4x4_from_mat4x4(vp_matrix); + command_list_set_root_constant(cl, &constants, sizeof(constants)); + + /* Bind instance buffer */ + ID3D12GraphicsCommandList_SetGraphicsRootShaderResourceView(cl->cl, 1, instance_buffer->resource->gpu_address); + + /* Bind descriptor heap */ + ID3D12DescriptorHeap *heaps[] = { descriptor_heap->heap }; + ID3D12GraphicsCommandList_SetDescriptorHeaps(cl->cl, ARRAY_COUNT(heaps), heaps); + ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(cl->cl, 2, descriptor_heap->gp_handle); + + /* Setup Rasterizer State */ + ID3D12GraphicsCommandList_RSSetViewports(cl->cl, 1, &d3d12_viewport); + ID3D12GraphicsCommandList_RSSetScissorRects(cl->cl, 1, &d3d12_scissor); + + /* Draw */ + ID3D12GraphicsCommandList_IASetPrimitiveTopology(cl->cl, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ID3D12GraphicsCommandList_IASetVertexBuffers(cl->cl, 0, 1, &dummy_vertex_buffer_view); + ID3D12GraphicsCommandList_IASetIndexBuffer(cl->cl, &quad_index_buffer_view); + ID3D12GraphicsCommandList_DrawIndexedInstanced(cl->cl, 6, instance_count, 0, 0, 0); + } + + /* Reset render target */ + { + dx12_resource_barrier(cl->cl, target, target_old_state); } } - - /* Material pass */ - { - //struct pipeline *pipeline = dx12_get_pipeline(pipeline_scope, LIT("material")); - struct pipeline *pipeline = &G.test_pipeline; - u32 instance_count = instance_buffer->size / sizeof(struct sh_material_instance); - - /* Bind pipeline */ - ID3D12GraphicsCommandList_SetPipelineState(cl->cl, pipeline->pso); - ID3D12GraphicsCommandList_SetGraphicsRootSignature(cl->cl, pipeline->rootsig); - - /* Fill & bind constant buffer */ - /* TODO: Move into root constant */ - struct sh_material_constants constants = ZI; - constants.projection = sh_float4x4_from_mat4x4(vp_matrix); - struct command_buffer *constant_buffer = command_list_push_buffer(cl, STRING_FROM_STRUCT(&constants)); - ID3D12GraphicsCommandList_SetGraphicsRootConstantBufferView(cl->cl, 0, constant_buffer->resource->gpu_address); - - /* Bind instance buffer */ - ID3D12GraphicsCommandList_SetGraphicsRootShaderResourceView(cl->cl, 1, instance_buffer->resource->gpu_address); - - /* Bind descriptor heap */ - ID3D12DescriptorHeap *heaps[] = { descriptor_heap->heap }; - ID3D12GraphicsCommandList_SetDescriptorHeaps(cl->cl, ARRAY_COUNT(heaps), heaps); - ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(cl->cl, 2, descriptor_heap->gp_handle); - - /* Setup Rasterizer State */ - ID3D12GraphicsCommandList_RSSetViewports(cl->cl, 1, &d3d12_viewport); - ID3D12GraphicsCommandList_RSSetScissorRects(cl->cl, 1, &d3d12_scissor); - - /* Draw */ - ID3D12GraphicsCommandList_IASetPrimitiveTopology(cl->cl, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - ID3D12GraphicsCommandList_IASetVertexBuffers(cl->cl, 0, 1, &dummy_vertex_buffer_view); - ID3D12GraphicsCommandList_IASetIndexBuffer(cl->cl, &quad_index_buffer_view); - ID3D12GraphicsCommandList_DrawIndexedInstanced(cl->cl, 6, instance_count, 0, 0, 0); - } - - /* Reset render target */ - { - dx12_resource_barrier(cl->cl, target, target_old_state); - } + command_list_close(cl); } - command_list_close(cl); + pipeline_scope_end(pipeline_scope); /* Reset flow */ sprite_scope_end(flow->sprite_scope); flow->sprite_scope = sprite_scope_begin(); arena_reset(flow->material_instances_arena); + } /* ========================== * @@ -2256,6 +2348,7 @@ void gp_present(struct sys_window *window, struct v2i32 backbuffer_resolution, s //sys_sleep(0.1); /* Present */ + /* FIXME: Resource barrier */ HRESULT hr = IDXGISwapChain3_Present(G.swapchain, 0, 0); if (!SUCCEEDED(hr)) { ASSERT(false);