From 5a9d9debbaa9ef3619d721a14e94e5afcc07263c Mon Sep 17 00:00:00 2001 From: jacob Date: Wed, 25 Jun 2025 00:11:05 -0500 Subject: [PATCH] shape shader start --- imgui.ini | 5 + res/sh/blit.hlsl | 10 +- res/sh/common.hlsl | 2 +- res/sh/material.hlsl | 33 ++- res/sh/sh_common.h | 16 ++ res/sh/shape.hlsl | 60 ++++++ src/common.h | 2 +- src/draw.c | 31 +-- src/gp.h | 18 +- src/gp_dx11.c | 502 +++++++++++++++++++------------------------ src/gp_dx12.c | 463 ++++++++++++++++++++++++--------------- src/sprite.c | 1 - src/sys_win32.c | 5 + src/user.c | 13 -- src/work.c | 13 +- 15 files changed, 649 insertions(+), 525 deletions(-) create mode 100644 imgui.ini create mode 100644 res/sh/shape.hlsl diff --git a/imgui.ini b/imgui.ini new file mode 100644 index 00000000..4a5c2014 --- /dev/null +++ b/imgui.ini @@ -0,0 +1,5 @@ +[Window][Debug##Default] +Pos=60,60 +Size=400,400 +Collapsed=0 + diff --git a/res/sh/blit.hlsl b/res/sh/blit.hlsl index 74931b27..ac27669e 100644 --- a/res/sh/blit.hlsl +++ b/res/sh/blit.hlsl @@ -24,12 +24,12 @@ SamplerState g_sampler : register(s0); * ========================== */ struct vs_input { - DECL(uint, SV_VertexID); + DECLS(uint, SV_VertexID); }; struct vs_output { - DECL(float4, SV_Position); - DECL(float2, uv); + DECLS(float4, SV_Position); + DECLS(float2, uv); }; SH_ENTRY(ROOTSIG) struct vs_output vs(struct vs_input input) @@ -58,13 +58,13 @@ struct ps_input { }; struct ps_output { - DECL(float4, SV_Target); + DECLS(float4, SV_Target); }; SH_ENTRY(ROOTSIG) struct ps_output ps(struct ps_input input) { struct ps_output output; const float gamma = g_constants.gamma; - output.SV_Target = pow(g_textures[g_constants.tex_urid].Sample(g_sampler, input.vs.uv), 1/gamma); + output.SV_Target = pow(abs(g_textures[g_constants.tex_urid].Sample(g_sampler, input.vs.uv)), 1/gamma); return output; } diff --git a/res/sh/common.hlsl b/res/sh/common.hlsl index c0a4881d..095f1347 100644 --- a/res/sh/common.hlsl +++ b/res/sh/common.hlsl @@ -3,7 +3,7 @@ #define PI 3.14159265359 #define GOLDEN 1.61803398875 -#define DECL(t, n) t n : n +#define DECLS(t, n) t n : n #define NURID(i) NonUniformResourceIndex(i) #if !SH_CPU diff --git a/res/sh/material.hlsl b/res/sh/material.hlsl index 4732a476..668fdb5c 100644 --- a/res/sh/material.hlsl +++ b/res/sh/material.hlsl @@ -28,17 +28,17 @@ SamplerState g_sampler : register(s0); * ========================== */ struct vs_input { - DECL(uint, SV_InstanceID); - DECL(uint, SV_VertexID); + DECLS(uint, SV_InstanceID); + DECLS(uint, SV_VertexID); }; struct vs_output { - nointerpolation DECL(uint, flags); - nointerpolation DECL(int, tex_nurid); - nointerpolation DECL(int, grid_id); - DECL(float2, uv); - DECL(float4, tint_lin); - DECL(float4, SV_Position); + nointerpolation DECLS(uint, flags); + nointerpolation DECLS(int, tex_nurid); + nointerpolation DECLS(int, grid_id); + DECLS(float2, uv); + DECLS(float4, tint_lin); + DECLS(float4, SV_Position); }; SH_ENTRY(ROOTSIG) struct vs_output vs(struct vs_input input) @@ -73,13 +73,13 @@ struct ps_input { }; struct ps_output { - DECL(float4, SV_Target); + DECLS(float4, SV_Target); }; SH_ENTRY(ROOTSIG) struct ps_output ps(struct ps_input input) { struct ps_output output; - output.SV_Target = float4(1, 1, 1, 1); + output.SV_Target = input.vs.tint_lin; /* Texture */ if (input.vs.tex_nurid >= 0) { @@ -92,15 +92,15 @@ SH_ENTRY(ROOTSIG) struct ps_output ps(struct ps_input input) float2 grid_pos = input.vs.SV_Position.xy + grid.offset; float half_thickness = grid.line_thickness / 2; float spacing = grid.line_spacing; - float4 color = linear_from_srgb32(grid.bg0_srgb); + uint color_srgb = grid.bg0_srgb; float2 v = abs(round(grid_pos / spacing) * spacing - grid_pos); float dist = min(v.x, v.y); if (grid_pos.y <= half_thickness && grid_pos.y >= -half_thickness) { - color = linear_from_srgb32(grid.x_srgb); + color_srgb = grid.x_srgb; } else if (grid_pos.x <= half_thickness && grid_pos.x >= -half_thickness) { - color = linear_from_srgb32(grid.y_srgb); + color_srgb = grid.y_srgb; } else if (dist < half_thickness) { - color = linear_from_srgb32(grid.line_srgb); + color_srgb = grid.line_srgb; } else { bool checker = false; uint cell_x = (uint)(abs(grid_pos.x) / spacing) + (grid_pos.x < 0); @@ -111,12 +111,11 @@ SH_ENTRY(ROOTSIG) struct ps_output ps(struct ps_input input) checker = cell_y % 2 == 1; } if (checker) { - color = linear_from_srgb32(grid.bg1_srgb); + color_srgb = grid.bg1_srgb; } } - output.SV_Target *= color; + output.SV_Target *= linear_from_srgb32(color_srgb); } - output.SV_Target *= input.vs.tint_lin; return output; } diff --git a/res/sh/sh_common.h b/res/sh/sh_common.h index 4cb21bf0..160e5e0f 100644 --- a/res/sh/sh_common.h +++ b/res/sh/sh_common.h @@ -2,6 +2,7 @@ #define SH_STRUCT(s) PACK(struct s) #define SH_DECL(t, n) struct CAT(sh_, t) n +#define SH_DECLS(t, n) SH_DECL(t, n) #define SH_ENTRY(rootsig) static #define SH_ASSERT_32BIT(s, n) CT_ASSERT((sizeof(s) / 4) == n) @@ -51,6 +52,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_DECLS(t, n) t n : n #define SH_ENTRY(rootsig) [RootSignature(rootsig)] #define SH_ASSERT_32BIT(s, n) @@ -99,3 +101,17 @@ SH_STRUCT(sh_material_grid { SH_DECL(uint, x_srgb); SH_DECL(uint, y_srgb); }); + +/* ========================== * + * Shape shader structures + * ========================== */ + +SH_STRUCT(sh_shape_constants { + SH_DECL(float4x4, projection); +}); +SH_ASSERT_32BIT(struct sh_shape_constants, 16); /* Expected 32bit root constant size in shader */ + +SH_STRUCT(sh_shape_vert { + SH_DECLS(float2, pos); + SH_DECLS(uint, color_srgb); +}); diff --git a/res/sh/shape.hlsl b/res/sh/shape.hlsl new file mode 100644 index 00000000..55b041ee --- /dev/null +++ b/res/sh/shape.hlsl @@ -0,0 +1,60 @@ +#include "sh/common.hlsl" + +/* ========================== * + * Root signature + * ========================== */ + +#define ROOTSIG \ + "RootConstants(num32BitConstants=16, b0), " \ + "SRV(t0), " \ + "SRV(t1), " \ + "DescriptorTable(SRV(t2, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE)), " \ + "StaticSampler(s0, " \ + "filter = FILTER_MIN_MAG_MIP_POINT, " \ + "addressU = TEXTURE_ADDRESS_CLAMP, " \ + "addressV = TEXTURE_ADDRESS_CLAMP, " \ + "addressW = TEXTURE_ADDRESS_CLAMP, " \ + "maxAnisotropy = 1)" + +ConstantBuffer g_constants : register(b0); +StructuredBuffer g_instances : register(t0); +StructuredBuffer g_grids : register(t1); +Texture2D g_textures[] : register(t2); + +SamplerState g_sampler : register(s0); + +/* ========================== * + * Vertex shader + * ========================== */ + +struct vs_output { + DECLS(float4, SV_Position); + DECLS(float4, color_lin); +}; + +SH_ENTRY(ROOTSIG) struct vs_output vs(struct sh_shape_vert input) +{ + struct vs_output output; + output.SV_Position = mul(g_constants.projection, float4(input.pos, 0, 1)); + output.color_lin = linear_from_srgb32(input.color_srgb); + return output; +} + +/* ========================== * + * Pixel shader + * ========================== */ + +struct ps_input { + struct vs_output vs; +}; + +struct ps_output { + DECLS(float4, SV_Target); +}; + +SH_ENTRY(ROOTSIG) struct ps_output ps(struct ps_input input) +{ + struct ps_output output; + output.SV_Target = input.vs.color_lin; + return output; +} diff --git a/src/common.h b/src/common.h index bc3be8f9..ef5396f9 100644 --- a/src/common.h +++ b/src/common.h @@ -634,7 +634,7 @@ INLINE f64 clamp_f64(f64 v, f64 min, f64 max) { return v < min ? min : v > max ? #include STRINGIZE(TRACY_INCLUDE_PATH) -#define PROFILING_CAPTURE_FRAME_IMAGE 1 +#define PROFILING_CAPTURE_FRAME_IMAGE 0 /* Clang/GCC cleanup macros */ #if COMPILER_MSVC diff --git a/src/draw.c b/src/draw.c index cb808dd5..43f13be5 100644 --- a/src/draw.c +++ b/src/draw.c @@ -31,13 +31,13 @@ struct draw_startup_receipt draw_startup(struct gp_startup_receipt *gp_sr, void draw_texture(struct gp_handle flow, struct draw_texture_params params) { struct gp_cmd_desc cmd = ZI; - cmd.kind = GP_CMD_KIND_DRAW_TEXTURE; - cmd.texture.xf = params.xf; - cmd.texture.sprite = params.sprite; - cmd.texture.texture = params.texture; - cmd.texture.clip = params.clip; - cmd.texture.tint = params.tint; - cmd.texture.emittance = params.emittance; + cmd.kind = GP_CMD_KIND_DRAW_MATERIAL; + cmd.material.xf = params.xf; + cmd.material.sprite = params.sprite; + cmd.material.texture = params.texture; + cmd.material.clip = params.clip; + cmd.material.tint = params.tint; + cmd.material.emittance = params.emittance; gp_push_cmd(flow, cmd); } @@ -48,10 +48,10 @@ void draw_texture(struct gp_handle flow, struct draw_texture_params params) void draw_poly_ex(struct gp_handle flow, struct v2_array vertices, struct gp_indices indices, u32 color) { struct gp_cmd_desc cmd = ZI; - cmd.kind = GP_CMD_KIND_DRAW_MESH; - cmd.mesh.vertices = vertices; - cmd.mesh.indices = indices; - cmd.mesh.color = color; + cmd.kind = GP_CMD_KIND_DRAW_SHAPE; + cmd.shape.vertices = vertices; + cmd.shape.indices = indices; + cmd.shape.color = color; gp_push_cmd(flow, cmd); } @@ -271,10 +271,10 @@ void draw_grid(struct gp_handle flow, struct xform xf, u32 bg0_color, u32 bg1_co grid.offset = offset; struct gp_cmd_desc cmd = ZI; - cmd.kind = GP_CMD_KIND_DRAW_TEXTURE; - cmd.texture.xf = xf; - cmd.texture.tint = COLOR_WHITE; - cmd.texture.grid = &grid; + cmd.kind = GP_CMD_KIND_DRAW_MATERIAL; + cmd.material.xf = xf; + cmd.material.tint = COLOR_WHITE; + cmd.material.grid = &grid; gp_push_cmd(flow, cmd); } @@ -285,6 +285,7 @@ void draw_grid(struct gp_handle flow, struct xform xf, u32 bg0_color, u32 bg1_co /* Returns the rect of the text area */ struct rect draw_text(struct gp_handle flow, struct draw_text_params params) { + __prof; struct arena_temp scratch = scratch_begin_no_conflict(); f32 inv_font_image_width = 1.0 / (f32)params.font->image_width; diff --git a/src/gp.h b/src/gp.h index 0c6a3372..4d3ddde0 100644 --- a/src/gp.h +++ b/src/gp.h @@ -70,9 +70,8 @@ struct gp_indices { enum gp_cmd_kind { GP_CMD_KIND_NONE, - GP_CMD_KIND_DRAW_MESH, - GP_CMD_KIND_DRAW_TEXTURE, - GP_CMD_KIND_TEST, + GP_CMD_KIND_DRAW_SHAPE, + GP_CMD_KIND_DRAW_MATERIAL, NUM_GP_CMD_KINDS }; @@ -91,11 +90,6 @@ struct gp_grid_desc { struct gp_cmd_desc { enum gp_cmd_kind kind; union { - struct { - struct v2_array vertices; - struct gp_indices indices; - u32 color; - } mesh; struct { struct xform xf; struct sprite_tag sprite; @@ -104,10 +98,12 @@ struct gp_cmd_desc { u32 tint; f32 emittance; struct gp_grid_desc *grid; - } texture; + } material; struct { - struct xform xf; - } test; + struct v2_array vertices; + struct gp_indices indices; + u32 color; + } shape; }; }; diff --git a/src/gp_dx11.c b/src/gp_dx11.c index f3104762..07522aaa 100644 --- a/src/gp_dx11.c +++ b/src/gp_dx11.c @@ -128,6 +128,7 @@ struct dx11_cmd_buffers { struct dx11_cmd { enum gp_cmd_kind kind; + b32 is_grid; union { struct { struct xform xf; @@ -285,7 +286,7 @@ INTERNAL struct dx11_buffer *dx11_buffer_alloc(struct D3D11_BUFFER_DESC desc, D3 INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(shader_resource_watch_callback, name); #endif -struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr, struct sys_window *window) +struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr) { __prof; (UNUSED)work_sr; @@ -314,7 +315,6 @@ struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr, struc HRESULT hr; ID3D11Device *device = NULL; ID3D11DeviceContext *context = NULL; - IDXGISwapChain2 *swapchain = NULL; /* Create D3D11 device & context */ { @@ -361,71 +361,13 @@ struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr, struc } #endif - /* Create swap chain */ - { - __profscope(Create swapchain); - HWND hwnd = (HWND)sys_window_get_internal_handle(window); - - /* Get DXGI device from D3D11 device */ - IDXGIDevice *dxgiDevice; - hr = ID3D11Device_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgiDevice); - ASSERT(SUCCEEDED(hr)); - - /* Get DXGI adapter from DXGI device */ - IDXGIAdapter *dxgiAdapter; - hr = IDXGIDevice_GetAdapter(dxgiDevice, &dxgiAdapter); - ASSERT(SUCCEEDED(hr)); - - /* Get DXGI factory from DXGI adapter */ - IDXGIFactory2 *factory; - hr = IDXGIAdapter_GetParent(dxgiAdapter, &IID_IDXGIFactory2, (void **)&factory); - ASSERT(SUCCEEDED(hr)); - - DXGI_SWAP_CHAIN_DESC1 desc = { - .Format = DX11_SWAPCHAIN_FORMAT, - .SampleDesc = { 1, 0 }, - .BufferUsage = DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT, - .BufferCount = 3, - .Scaling = DXGI_SCALING_NONE, - .Flags = DX11_SWAPCHAIN_FLAGS, - .AlphaMode = DXGI_ALPHA_MODE_IGNORE, - .SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD - }; - - IDXGISwapChain1 *swapchain1 = NULL; - hr = IDXGIFactory2_CreateSwapChainForHwnd(factory, (IUnknown *)device, hwnd, &desc, NULL, NULL, &swapchain1); - ASSERT(SUCCEEDED(hr)); - - if (SUCCEEDED(hr)) { - IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain2, (void **)&swapchain); - } - - /* Disable Alt+Enter changing monitor resolution to match window size */ - IDXGIFactory_MakeWindowAssociation(factory, hwnd, DXGI_MWA_NO_ALT_ENTER); - - IDXGISwapChain1_Release(swapchain1); - IDXGIFactory2_Release(factory); - IDXGIAdapter_Release(dxgiAdapter); - IDXGIDevice_Release(dxgiDevice); - } - - if (!SUCCEEDED(hr) || !device || !context || !swapchain) { + if (!SUCCEEDED(hr) || !device || !context) { /* Gpu initialization failure */ /* TODO: Better message */ sys_panic(LIT("Failed to initialize DirectX 11")); } G.dev = device; G.devcon = context; - G.swapchain = swapchain; - - /* Create the swapchain waitable object */ -#if DX11_WAIT_FRAME_LATENCY - if (G.swapchain != NULL) { - IDXGISwapChain2_SetMaximumFrameLatency(G.swapchain, 1); - G.swapchain_waitable = IDXGISwapChain2_GetFrameLatencyWaitableObject(G.swapchain); - ASSERT(G.swapchain_waitable != NULL); - } -#endif struct string prof_ctx_name = LIT("D3d11 Context"); (UNUSED)prof_ctx_name; @@ -1137,21 +1079,6 @@ struct gp_handle gp_texture_alloc(enum gp_texture_format format, u32 flags, stru return res; } -void gp_texture_clear(struct gp_handle target_texture, u32 clear_color) -{ - __prof; - struct dx11_texture *t = (struct dx11_texture *)target_texture.v; - if (t->rtv) { - __profscope_dx11(G.profiling_ctx, Clear, RGB32_F(0.5, 0.1, 0.1)); - f32 r = (f32)((clear_color >> 0) & 0xFF) / 255.0f; - f32 g = (f32)((clear_color >> 8) & 0xFF) / 255.0f; - f32 b = (f32)((clear_color >> 16) & 0xFF) / 255.0f; - f32 a = (f32)((clear_color >> 24) & 0xFF) / 255.0f; - f32 fill[4] = { r, g, b, a }; - ID3D11DeviceContext_ClearRenderTargetView(G.devcon, t->rtv, fill); - } -} - struct v2i32 gp_texture_get_size(struct gp_handle texture) { return ((struct dx11_texture *)texture.v)->size; @@ -1384,7 +1311,7 @@ void gp_push_cmd(struct gp_handle gp_flow, struct gp_cmd_desc params) ASSERT(false); } break; - case GP_CMD_KIND_DRAW_MESH: + case GP_CMD_KIND_DRAW_SHAPE: { struct dx11_cmd *cmd = flow->cpu_last_cmd; if (cmd && cmd->kind != params.kind) { @@ -1429,75 +1356,76 @@ void gp_push_cmd(struct gp_handle gp_flow, struct gp_cmd_desc params) case GP_CMD_KIND_DRAW_TEXTURE: { - struct dx11_cmd *cmd = flow->cpu_last_cmd; - if (cmd && - ((cmd->kind != params.kind) || - (cmd->texture.sprite.hash != params.texture.sprite.hash) || - (cmd->texture.texture.v != params.texture.texture.v))) { - /* Cannot batch */ - cmd = NULL; - } - - /* Start new cmd */ - if (!cmd) { - /* TODO: Better count method */ - cmd = arena_push(flow->cpu_cmds_arena, struct dx11_cmd); - cmd->kind = params.kind; - cmd->texture.sprite = params.texture.sprite; - cmd->texture.texture = params.texture.texture; - cmd->texture.instance_offset = (flow->cmd_buffers.texture.instance_buffer->cpu_buffer_arena->pos / sizeof(struct dx11_texture_instance)); - if (flow->cpu_last_cmd) { - flow->cpu_last_cmd->next = cmd; - } else { - flow->cpu_first_cmd = cmd; + if (params.texture.grid) { + struct dx11_cmd *cmd = flow->cpu_last_cmd; + if (cmd && (cmd->kind != params.kind || !cmd->is_grid)) { + /* Cannot batch */ + cmd = NULL; } - flow->cpu_last_cmd = cmd; - } - /* Push instance data */ - ++cmd->texture.instance_count; - struct dx11_texture_instance *instance = dx11_buffer_push(flow->cmd_buffers.texture.instance_buffer, sizeof(struct dx11_texture_instance)); - instance->xf = params.texture.xf; - instance->uv0 = params.texture.clip.p0; - instance->uv1 = params.texture.clip.p1; - instance->tint_srgb = params.texture.tint; - instance->emittance = params.texture.emittance; - } break; - - case GP_CMD_KIND_DRAW_GRID: - { - struct dx11_cmd *cmd = flow->cpu_last_cmd; - if (cmd && cmd->kind != params.kind) { - /* Cannot batch */ - cmd = NULL; - } - - /* Start new cmd */ - if (!cmd) { - /* TODO: Better count method */ - cmd = arena_push(flow->cpu_cmds_arena, struct dx11_cmd); - cmd->kind = params.kind; - cmd->grid.instance_offset = (flow->cmd_buffers.grid.instance_buffer->cpu_buffer_arena->pos / sizeof(struct dx11_grid_instance)); - if (flow->cpu_last_cmd) { - flow->cpu_last_cmd->next = cmd; - } else { - flow->cpu_first_cmd = cmd; + /* Start new cmd */ + if (!cmd) { + /* TODO: Better count method */ + cmd = arena_push(flow->cpu_cmds_arena, struct dx11_cmd); + cmd->kind = params.kind; + cmd->is_grid = true; + cmd->grid.instance_offset = (flow->cmd_buffers.grid.instance_buffer->cpu_buffer_arena->pos / sizeof(struct dx11_grid_instance)); + if (flow->cpu_last_cmd) { + flow->cpu_last_cmd->next = cmd; + } else { + flow->cpu_first_cmd = cmd; + } + flow->cpu_last_cmd = cmd; } - flow->cpu_last_cmd = cmd; - } - /* Push instance data */ - ++cmd->grid.instance_count; - struct dx11_grid_instance *instance = dx11_buffer_push(flow->cmd_buffers.grid.instance_buffer, sizeof(struct dx11_grid_instance)); - instance->xf = params.grid.xf; - instance->line_thickness = params.grid.line_thickness; - instance->line_spacing = params.grid.line_spacing; - instance->offset = params.grid.offset; - instance->bg0_srgb = params.grid.bg0_color; - instance->bg1_srgb = params.grid.bg1_color; - instance->line_srgb = params.grid.line_color; - instance->x_srgb = params.grid.x_color; - instance->y_srgb = params.grid.y_color; + /* Push instance data */ + ++cmd->grid.instance_count; + struct dx11_grid_instance *instance = dx11_buffer_push(flow->cmd_buffers.grid.instance_buffer, sizeof(struct dx11_grid_instance)); + instance->xf = params.texture.xf; + instance->line_thickness = params.texture.grid->line_thickness; + instance->line_spacing = params.texture.grid->line_spacing; + instance->offset = params.texture.grid->offset; + instance->bg0_srgb = params.texture.grid->bg0_color; + instance->bg1_srgb = params.texture.grid->bg1_color; + instance->line_srgb = params.texture.grid->line_color; + instance->x_srgb = params.texture.grid->x_color; + instance->y_srgb = params.texture.grid->y_color; + } else { + struct dx11_cmd *cmd = flow->cpu_last_cmd; + if (cmd && + ((cmd->kind != params.kind) || + (cmd->texture.sprite.hash != params.texture.sprite.hash) || + (cmd->texture.texture.v != params.texture.texture.v) || + (cmd->is_grid))) { + /* Cannot batch */ + cmd = NULL; + } + + /* Start new cmd */ + if (!cmd) { + /* TODO: Better count method */ + cmd = arena_push(flow->cpu_cmds_arena, struct dx11_cmd); + cmd->kind = params.kind; + cmd->texture.sprite = params.texture.sprite; + cmd->texture.texture = params.texture.texture; + cmd->texture.instance_offset = (flow->cmd_buffers.texture.instance_buffer->cpu_buffer_arena->pos / sizeof(struct dx11_texture_instance)); + if (flow->cpu_last_cmd) { + flow->cpu_last_cmd->next = cmd; + } else { + flow->cpu_first_cmd = cmd; + } + flow->cpu_last_cmd = cmd; + } + + /* Push instance data */ + ++cmd->texture.instance_count; + struct dx11_texture_instance *instance = dx11_buffer_push(flow->cmd_buffers.texture.instance_buffer, sizeof(struct dx11_texture_instance)); + instance->xf = params.texture.xf; + instance->uv0 = params.texture.clip.p0; + instance->uv1 = params.texture.clip.p1; + instance->tint_srgb = params.texture.tint; + instance->emittance = params.texture.emittance; + } } break; case GP_CMD_KIND_TEST: @@ -1655,6 +1583,20 @@ void gp_dispatch(struct gp_dispatch_params params) flow->constant_buffer = constant_buffer; } + /* Clear target */ + if (params.clear_target) { + u32 clear_color = 0; + if (final_tex->rtv) { + __profscope_dx11(G.profiling_ctx, Clear, RGB32_F(0.5, 0.1, 0.1)); + f32 r = (f32)((clear_color >> 0) & 0xFF) / 255.0f; + f32 g = (f32)((clear_color >> 8) & 0xFF) / 255.0f; + f32 b = (f32)((clear_color >> 16) & 0xFF) / 255.0f; + f32 a = (f32)((clear_color >> 24) & 0xFF) / 255.0f; + f32 fill[4] = { r, g, b, a }; + ID3D11DeviceContext_ClearRenderTargetView(G.devcon, final_tex->rtv, fill); + } + } + /* Regular pass */ struct mat4x4 vp_matrix = calculate_vp(params.draw_target_view, viewport.width, viewport.height); { @@ -1670,7 +1612,7 @@ void gp_dispatch(struct gp_dispatch_params params) ASSERT(false); } break; - case GP_CMD_KIND_DRAW_MESH: + case GP_CMD_KIND_DRAW_SHAPE: { __profscope(Draw mesh); __profscope_dx11(G.profiling_ctx, Draw mesh, RGB32_F(0.5, 0.2, 0.2)); @@ -1718,26 +1660,14 @@ void gp_dispatch(struct gp_dispatch_params params) case GP_CMD_KIND_DRAW_TEXTURE: { - __profscope(Draw texture); - __profscope_dx11(G.profiling_ctx, Draw texture, RGB32_F(0.2, 0.5, 0.2)); - struct dx11_shader *shader = &G.shaders[DX11_SHADER_KIND_TEXTURE]; - if (shader->valid) { - struct dx11_texture *texture = NULL; - if (cmd->texture.texture.v) { - /* Load texture if handle is set */ - texture = (struct dx11_texture *)cmd->texture.texture.v; - } else if (cmd->texture.sprite.hash) { - /* Otherwise load sprite */ - struct sprite_texture *sprite_texture = sprite_texture_from_tag_async(sprite_scope, cmd->texture.sprite); - if (sprite_texture->loaded) { - texture = (struct dx11_texture *)sprite_texture->texture.v; - } - } - - if (texture && texture->srv) { - struct dx11_buffer *instance_buffer = flow->cmd_buffers.texture.instance_buffer; - u32 instance_offset = cmd->texture.instance_offset; - u32 instance_count = cmd->texture.instance_count; + if (cmd->is_grid) { + __profscope(Draw grid); + __profscope_dx11(G.profiling_ctx, Draw grid, RGB32_F(0.2, 0.2, 0.5)); + struct dx11_shader *shader = &G.shaders[DX11_SHADER_KIND_GRID]; + if (shader->valid) { + struct dx11_buffer *instance_buffer = flow->cmd_buffers.grid.instance_buffer; + u32 instance_offset = cmd->grid.instance_offset; + u32 instance_count = cmd->grid.instance_count; /* Bind shader */ ID3D11DeviceContext_VSSetShader(G.devcon, shader->vs, 0, 0); @@ -1745,7 +1675,7 @@ void gp_dispatch(struct gp_dispatch_params params) /* Fill & bind constant buffer */ { - struct dx11_texture_uniform *uniform = dx11_buffer_push(constant_buffer, sizeof(struct dx11_texture_uniform)); + struct dx11_grid_uniform *uniform = dx11_buffer_push(constant_buffer, sizeof(struct dx11_grid_uniform)); uniform->vp = vp_matrix; uniform->instance_offset = instance_offset; dx11_buffer_submit(constant_buffer); @@ -1759,7 +1689,7 @@ void gp_dispatch(struct gp_dispatch_params params) ID3D11DeviceContext_IASetIndexBuffer(G.devcon, G.quad_index_buffer->gpu_buffer, DXGI_FORMAT_R16_UINT, zero); /* Bind SRVs */ - ID3D11ShaderResourceView *srvs[] = { instance_buffer->srv, texture->srv }; + ID3D11ShaderResourceView *srvs[] = { instance_buffer->srv }; ID3D11DeviceContext_VSSetShaderResources(G.devcon, 0, ARRAY_COUNT(srvs), srvs); ID3D11DeviceContext_PSSetShaderResources(G.devcon, 0, ARRAY_COUNT(srvs), srvs); @@ -1774,53 +1704,64 @@ void gp_dispatch(struct gp_dispatch_params params) /* Unbind */ dx11_unbind(DX11_UNBIND_VS | DX11_UNBIND_PS | DX11_UNBIND_CBUFF | DX11_UNBIND_VBUFF | DX11_UNBIND_IBUFF | DX11_UNBIND_SRV | DX11_UNBIND_RTV); } - } - } break; + } else { + __profscope(Draw texture); + __profscope_dx11(G.profiling_ctx, Draw texture, RGB32_F(0.2, 0.5, 0.2)); + struct dx11_shader *shader = &G.shaders[DX11_SHADER_KIND_TEXTURE]; + if (shader->valid) { + struct dx11_texture *texture = NULL; + if (cmd->texture.texture.v) { + /* Load texture if handle is set */ + texture = (struct dx11_texture *)cmd->texture.texture.v; + } else if (cmd->texture.sprite.hash) { + /* Otherwise load sprite */ + struct sprite_texture *sprite_texture = sprite_texture_from_tag_async(sprite_scope, cmd->texture.sprite); + if (sprite_texture->loaded) { + texture = (struct dx11_texture *)sprite_texture->texture.v; + } + } - case GP_CMD_KIND_DRAW_GRID: - { - __profscope(Draw grid); - __profscope_dx11(G.profiling_ctx, Draw grid, RGB32_F(0.2, 0.2, 0.5)); - struct dx11_shader *shader = &G.shaders[DX11_SHADER_KIND_GRID]; - if (shader->valid) { - struct dx11_buffer *instance_buffer = flow->cmd_buffers.grid.instance_buffer; - u32 instance_offset = cmd->grid.instance_offset; - u32 instance_count = cmd->grid.instance_count; + if (texture && texture->srv) { + struct dx11_buffer *instance_buffer = flow->cmd_buffers.texture.instance_buffer; + u32 instance_offset = cmd->texture.instance_offset; + u32 instance_count = cmd->texture.instance_count; - /* Bind shader */ - ID3D11DeviceContext_VSSetShader(G.devcon, shader->vs, 0, 0); - ID3D11DeviceContext_PSSetShader(G.devcon, shader->ps, 0, 0); + /* Bind shader */ + ID3D11DeviceContext_VSSetShader(G.devcon, shader->vs, 0, 0); + ID3D11DeviceContext_PSSetShader(G.devcon, shader->ps, 0, 0); - /* Fill & bind constant buffer */ - { - struct dx11_grid_uniform *uniform = dx11_buffer_push(constant_buffer, sizeof(struct dx11_grid_uniform)); - uniform->vp = vp_matrix; - uniform->instance_offset = instance_offset; - dx11_buffer_submit(constant_buffer); + /* Fill & bind constant buffer */ + { + struct dx11_texture_uniform *uniform = dx11_buffer_push(constant_buffer, sizeof(struct dx11_texture_uniform)); + uniform->vp = vp_matrix; + uniform->instance_offset = instance_offset; + dx11_buffer_submit(constant_buffer); + } + ID3D11DeviceContext_VSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer); + ID3D11DeviceContext_PSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer); + + /* Bind dummy vertex buffer */ + u32 zero = 0; + ID3D11DeviceContext_IASetVertexBuffers(G.devcon, 0, 1, &G.dummy_vertex_buffer->gpu_buffer, &zero, &zero); + ID3D11DeviceContext_IASetIndexBuffer(G.devcon, G.quad_index_buffer->gpu_buffer, DXGI_FORMAT_R16_UINT, zero); + + /* Bind SRVs */ + ID3D11ShaderResourceView *srvs[] = { instance_buffer->srv, texture->srv }; + ID3D11DeviceContext_VSSetShaderResources(G.devcon, 0, ARRAY_COUNT(srvs), srvs); + ID3D11DeviceContext_PSSetShaderResources(G.devcon, 0, ARRAY_COUNT(srvs), srvs); + + /* Bind RTVs */ + ID3D11RenderTargetView *rtvs[] = { final_tex->rtv }; + ID3D11DeviceContext_OMSetRenderTargets(G.devcon, ARRAY_COUNT(rtvs), rtvs, NULL); + + /* Draw */ + ID3D11DeviceContext_IASetPrimitiveTopology(G.devcon, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ID3D11DeviceContext_DrawIndexedInstanced(G.devcon, 6, instance_count, 0, 0, 0); + + /* Unbind */ + dx11_unbind(DX11_UNBIND_VS | DX11_UNBIND_PS | DX11_UNBIND_CBUFF | DX11_UNBIND_VBUFF | DX11_UNBIND_IBUFF | DX11_UNBIND_SRV | DX11_UNBIND_RTV); + } } - ID3D11DeviceContext_VSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer); - ID3D11DeviceContext_PSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer); - - /* Bind dummy vertex buffer */ - u32 zero = 0; - ID3D11DeviceContext_IASetVertexBuffers(G.devcon, 0, 1, &G.dummy_vertex_buffer->gpu_buffer, &zero, &zero); - ID3D11DeviceContext_IASetIndexBuffer(G.devcon, G.quad_index_buffer->gpu_buffer, DXGI_FORMAT_R16_UINT, zero); - - /* Bind SRVs */ - ID3D11ShaderResourceView *srvs[] = { instance_buffer->srv }; - ID3D11DeviceContext_VSSetShaderResources(G.devcon, 0, ARRAY_COUNT(srvs), srvs); - ID3D11DeviceContext_PSSetShaderResources(G.devcon, 0, ARRAY_COUNT(srvs), srvs); - - /* Bind RTVs */ - ID3D11RenderTargetView *rtvs[] = { final_tex->rtv }; - ID3D11DeviceContext_OMSetRenderTargets(G.devcon, ARRAY_COUNT(rtvs), rtvs, NULL); - - /* Draw */ - ID3D11DeviceContext_IASetPrimitiveTopology(G.devcon, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - ID3D11DeviceContext_DrawIndexedInstanced(G.devcon, 6, instance_count, 0, 0, 0); - - /* Unbind */ - dx11_unbind(DX11_UNBIND_VS | DX11_UNBIND_PS | DX11_UNBIND_CBUFF | DX11_UNBIND_VBUFF | DX11_UNBIND_IBUFF | DX11_UNBIND_SRV | DX11_UNBIND_RTV); } } break; @@ -1878,47 +1819,20 @@ void gp_dispatch(struct gp_dispatch_params params) } /* ========================== * - * Backbuffer + * Memory info + * ========================== */ + +struct gp_memory_info gp_query_memory_info(void) +{ + return (struct gp_memory_info) { 0 }; +} + +/* ========================== * + * Present * ========================== */ INTERNAL void capture_image_for_profiler(void); -#if GSTAT_ENABLED || PROFILING -INTERNAL struct DXGI_QUERY_VIDEO_MEMORY_INFO get_memory_info(void) -{ - __prof; - - /* Get DXGI device from D3D11 device */ - IDXGIDevice *dxgiDevice; - HRESULT hr = ID3D11Device_QueryInterface(G.dev, &IID_IDXGIDevice, (void **)&dxgiDevice); - (UNUSED)hr; - ASSERT(SUCCEEDED(hr)); - - /* Get DXGI adapter from DXGI device */ - IDXGIAdapter *dxgiAdapter; - hr = IDXGIDevice_GetAdapter(dxgiDevice, &dxgiAdapter); - ASSERT(SUCCEEDED(hr)); - - IDXGIAdapter3 *dxgiAdapter3 = NULL; - hr = IDXGIAdapter_QueryInterface(dxgiAdapter, &IID_IDXGIAdapter3, (void **)&dxgiAdapter3); - ASSERT(SUCCEEDED(hr)); - - struct DXGI_QUERY_VIDEO_MEMORY_INFO info = ZI; - IDXGIAdapter3_QueryVideoMemoryInfo( - dxgiAdapter3, - 0, - DXGI_MEMORY_SEGMENT_GROUP_LOCAL, - &info - ); - - IDXGIAdapter_Release(dxgiAdapter3); - IDXGIAdapter_Release(dxgiAdapter); - IDXGIDevice_Release(dxgiDevice); - - return info; -} -#endif - INTERNAL void present_resize(struct v2i32 size) { __prof; @@ -1968,19 +1882,78 @@ INTERNAL void present_blit(struct dx11_texture *dst, struct dx11_texture *src, s draw_texture(G.present_blit_flow, params); } - /* Clear texture */ - gp_texture_clear(dst_texture_handle, RGBA32_F(0, 0, 0, 1)); - /* Render to backbuffer texture */ struct gp_dispatch_params params = ZI; params.flow = G.present_blit_flow; params.draw_target = dst_texture_handle; params.draw_target_viewport = RECT_FROM_V2(V2(0, 0), V2(dst->size.x, dst->size.y)); params.draw_target_view = XFORM_IDENT; + params.clear_target = true; gp_dispatch(params); } -void gp_present(struct v2i32 backbuffer_resolution, struct gp_handle texture, struct xform texture_xf, i32 vsync) +INTERNAL void present_init_swapchain(struct sys_window *window) +{ + + /* Create swap chain */ + { + __profscope(Create swapchain); + HWND hwnd = (HWND)sys_window_get_internal_handle(window); + + /* Get DXGI device from D3D11 device */ + IDXGIDevice *dxgiDevice; + HRESULT hr = ID3D11Device_QueryInterface(G.dev, &IID_IDXGIDevice, (void **)&dxgiDevice); + ASSERT(SUCCEEDED(hr)); + + /* Get DXGI adapter from DXGI device */ + IDXGIAdapter *dxgiAdapter; + hr = IDXGIDevice_GetAdapter(dxgiDevice, &dxgiAdapter); + ASSERT(SUCCEEDED(hr)); + + /* Get DXGI factory from DXGI adapter */ + IDXGIFactory2 *factory; + hr = IDXGIAdapter_GetParent(dxgiAdapter, &IID_IDXGIFactory2, (void **)&factory); + ASSERT(SUCCEEDED(hr)); + + DXGI_SWAP_CHAIN_DESC1 desc = { + .Format = DX11_SWAPCHAIN_FORMAT, + .SampleDesc = { 1, 0 }, + .BufferUsage = DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT, + .BufferCount = 3, + .Scaling = DXGI_SCALING_NONE, + .Flags = DX11_SWAPCHAIN_FLAGS, + .AlphaMode = DXGI_ALPHA_MODE_IGNORE, + .SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD + }; + + IDXGISwapChain1 *swapchain1 = NULL; + hr = IDXGIFactory2_CreateSwapChainForHwnd(factory, (IUnknown *)G.dev, hwnd, &desc, NULL, NULL, &swapchain1); + ASSERT(SUCCEEDED(hr)); + + if (SUCCEEDED(hr)) { + IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain2, (void **)&G.swapchain); + } + + /* Disable Alt+Enter changing monitor resolution to match window size */ + IDXGIFactory_MakeWindowAssociation(factory, hwnd, DXGI_MWA_NO_ALT_ENTER); + + IDXGISwapChain1_Release(swapchain1); + IDXGIFactory2_Release(factory); + IDXGIAdapter_Release(dxgiAdapter); + IDXGIDevice_Release(dxgiDevice); + } + + /* Create the swapchain waitable object */ +#if DX11_WAIT_FRAME_LATENCY + if (G.swapchain != NULL) { + IDXGISwapChain2_SetMaximumFrameLatency(G.swapchain, 1); + G.swapchain_waitable = IDXGISwapChain2_GetFrameLatencyWaitableObject(G.swapchain); + ASSERT(G.swapchain_waitable != NULL); + } +#endif +} + +void gp_present(struct sys_window *window, struct v2i32 backbuffer_resolution, struct gp_handle texture, struct xform texture_xf, i32 vsync) { __prof; @@ -1994,36 +1967,9 @@ void gp_present(struct v2i32 backbuffer_resolution, struct gp_handle texture, st } #endif - /* Track vram usage */ -#if GSTAT_ENABLED || PROFILING - { - struct DXGI_QUERY_VIDEO_MEMORY_INFO info = get_memory_info(); - u64 vram = info.CurrentUsage; - u64 budget = info.Budget; - (UNUSED)vram; - (UNUSED)budget; -# if GSTAT_ENABLED - { - gstat_set(GSTAT_VRAM_USAGE, vram); - gstat_set(GSTAT_VRAM_BUDGET, budget); - } -# endif -# if PROFILING - { - LOCAL_PERSIST char *vram_plot_name = NULL; - LOCAL_PERSIST u64 prev_vram = 0; - if (!vram_plot_name) { - vram_plot_name = "Video memory usage"; - __prof_plot_init(vram_plot_name, __prof_plot_type_memory, 1, 1, 0); - } - if (vram != prev_vram) { - __prof_plot_i(vram_plot_name, vram); - } - prev_vram = vram; - } -# endif + if (!G.swapchain) { + present_init_swapchain(window); } -#endif /* Wait */ i32 flags = 0; diff --git a/src/gp_dx12.c b/src/gp_dx12.c index 0f67d664..bbefe7ad 100644 --- a/src/gp_dx12.c +++ b/src/gp_dx12.c @@ -36,6 +36,12 @@ #pragma comment(lib, "dxguid") #pragma comment(lib, "d3dcompiler") +#if PROFILING +/* For RegOpenKeyEx */ +# include +# pragma comment(lib, "advapi32") +#endif + //#define DX12_WAIT_FRAME_LATENCY 1 //#define DX12_SWAPCHAIN_FLAGS ((DX12_ALLOW_TEARING * DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING) | (DX12_WAIT_FRAME_LATENCY * DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT)) @@ -153,8 +159,10 @@ struct command_descriptor_heap { struct command_buffer { struct command_buffer_group *group; - struct dx12_resource *resource; u64 size; + struct dx12_resource *resource; + D3D12_VERTEX_BUFFER_VIEW vbv; + D3D12_INDEX_BUFFER_VIEW Ibv; struct command_buffer *next_in_command_list; @@ -372,6 +380,8 @@ INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(gp_shutdown) command_queue_release(G.cq_compute); command_queue_release(G.cq_direct); ID3D12Device_Release(G.device); +#else + (UNUSED)command_queue_release; #endif } @@ -426,6 +436,7 @@ INTERNAL struct handle_entry *handle_get_entry(struct gp_handle handle, struct s INTERNAL void *handle_get_data(struct gp_handle handle, enum handle_kind kind) { + (UNUSED)kind; void *data = NULL; if (handle.gen) { struct sys_lock lock = sys_mutex_lock_s(G.handle_entries_mutex); @@ -593,6 +604,41 @@ INTERNAL void dx12_init_device(void) } #endif +#if PROFILING + /* Enable stable power state */ + { + b32 success = true; + __profscope(Set stable power state); + HKEY key = 0; + success = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppModelUnlock", 0, KEY_READ, &key) == ERROR_SUCCESS; + if (success) { + DWORD value = ZI; + DWORD dword_size = sizeof(DWORD); + success = RegQueryValueExW(key, L"AllowDevelopmentWithoutDevLicense", 0, NULL, (LPBYTE)&value, &dword_size) == ERROR_SUCCESS; + RegCloseKey(key); + if (success) { + success = value != 0; + } + } + logf_info("D3D12 profiling is enabled, attempting to set stable power state (this will increase GPU timing stability at the cost of performance)"); + if (success) { + logf_info("Machine is in developer mode, calling ID3D12Device::SetStablePowerState"); + hr = ID3D12Device_SetStablePowerState(G.device, 1); + if (SUCCEEDED(hr)) { + logf_info("ID3D12Device::SetStablePowerState succeeded"); + } else { + success = false; + logf_error("ID3D12Device::SetStablePowerState failed"); + } + } else { + logf_warning("Machine is not in developer mode, cannot call ID3D12Device::SetStablePowerState"); + } + if (!success) { + logf_warning("Profiling is enabled, but ID3D12Device::SetStablePowerState could not be called. This means that GPU timing may be unreliable."); + } + } +#endif + scratch_end(scratch); } @@ -648,6 +694,16 @@ INTERNAL void dx12_init_pipelines(void) desc->ps.func = LIT("ps"); dict_set(G.pipelines_arena, G.pipeline_descs, hash_fnv64(HASH_FNV64_BASIS, desc->name), (u64)desc); } + /* Shape pipeline */ + { + struct pipeline_desc *desc = arena_push(G.pipelines_arena, struct pipeline_desc); + desc->name = LIT("shape"); + desc->vs.file = LIT("sh/shape.hlsl"); + desc->ps.file = LIT("sh/shape.hlsl"); + desc->vs.func = LIT("vs"); + desc->ps.func = LIT("ps"); + dict_set(G.pipelines_arena, G.pipeline_descs, hash_fnv64(HASH_FNV64_BASIS, desc->name), (u64)desc); + } /* Blit pipeilne */ { struct pipeline_desc *desc = arena_push(G.pipelines_arena, struct pipeline_desc); @@ -674,7 +730,8 @@ INTERNAL void dx12_init_pipelines(void) struct pipeline *pipeline = pipelines[i]; if (!pipeline->success) { struct string error = pipeline->first_error ? pipeline->first_error->msg : LIT("Unknown error"); - struct string msg = string_format(scratch.arena, LIT("Error creating pipeline \"%F\":\n\n%F"), FMT_STR(pipeline->name), FMT_STR(error)); + struct string msg = string_format(scratch.arena, LIT("Error initializing pipeline \"%F\":\n\n%F"), FMT_STR(pipeline->name), FMT_STR(error)); + log_error(msg); sys_message_box(SYS_MESSAGE_BOX_KIND_WARNING, msg); } } @@ -1142,6 +1199,7 @@ INTERNAL void pipeline_release(struct pipeline *pipeline) INTERNAL struct pipeline_scope *pipeline_scope_begin(void) { + __prof; struct pipeline_scope *scope = NULL; { struct sys_lock lock = sys_mutex_lock_e(G.pipelines_mutex); @@ -1166,6 +1224,7 @@ INTERNAL struct pipeline_scope *pipeline_scope_begin(void) INTERNAL void pipeline_scope_end(struct pipeline_scope *scope) { + __prof; struct sys_lock lock = sys_mutex_lock_e(G.pipelines_mutex); { for (struct dict_entry *entry = scope->refs->first; entry; entry = entry->next) { @@ -1183,6 +1242,7 @@ INTERNAL void pipeline_scope_end(struct pipeline_scope *scope) INTERNAL READONLY struct pipeline g_nil_pipeline = ZI; INTERNAL struct pipeline *pipeline_from_name(struct pipeline_scope *scope, struct string name) { + __prof; struct pipeline *res = &g_nil_pipeline; u64 hash = hash_fnv64(HASH_FNV64_BASIS, name); @@ -1209,6 +1269,7 @@ INTERNAL struct pipeline *pipeline_from_name(struct pipeline_scope *scope, struc INTERNAL void pipeline_register(u64 num_pipelines, struct pipeline **pipelines) { + __prof; struct sys_lock lock = sys_mutex_lock_e(G.pipelines_mutex); { for (u64 i = 0; i < num_pipelines; ++i) { @@ -1240,6 +1301,7 @@ INTERNAL void pipeline_register(u64 num_pipelines, struct pipeline **pipelines) #if RESOURCE_RELOADING INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(pipeline_resource_watch_callback, name) { + __prof; struct arena_temp scratch = scratch_begin_no_conflict(); /* Find dirty pipelines */ @@ -1260,32 +1322,35 @@ INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(pipeline_resource_watch_callback, name } /* Recompile dirty pipelines */ - struct pipeline **pipelines = arena_push_array(scratch.arena, struct pipeline *, num_pipelines); - pipeline_alloc_from_desc(num_pipelines, pipeline_descs, pipelines); - { - struct sys_lock lock = sys_mutex_lock_s(G.pipelines_mutex); - for (u32 i = 0; i < num_pipelines; ++i) { - struct pipeline *pipeline = pipelines[i]; - if (pipeline->success) { - logf_success("Successfully compiled pipeline \"%F\" in %F seconds", FMT_STR(pipeline->name), FMT_FLOAT(SECONDS_FROM_NS(pipeline->compilation_time_ns))); - } else { - struct pipeline *old_pipeline = dict_get(G.top_successful_pipelines, pipeline->hash); - if (old_pipeline) { - struct string error = pipeline->first_error ? pipeline->first_error->msg : LIT("Unknown error"); - struct string msg = string_format(scratch.arena, LIT("Error compiling pipeline \"%F\":\n%F"), FMT_STR(pipeline->name), FMT_STR(error)); - log_error(msg); + if (num_pipelines > 0) { + struct pipeline **pipelines = arena_push_array(scratch.arena, struct pipeline *, num_pipelines); + pipeline_alloc_from_desc(num_pipelines, pipeline_descs, pipelines); + { + struct sys_lock lock = sys_mutex_lock_s(G.pipelines_mutex); + for (u32 i = 0; i < num_pipelines; ++i) { + struct pipeline *pipeline = pipelines[i]; + if (pipeline->success) { + logf_success("Successfully compiled pipeline \"%F\" in %F seconds", FMT_STR(pipeline->name), FMT_FLOAT(SECONDS_FROM_NS(pipeline->compilation_time_ns))); } else { - /* If no previously successful pipeline exists, then show a message box rather than logging since logs may not be visible to user */ - struct string error = pipeline->first_error ? pipeline->first_error->msg : LIT("Unknown error"); - struct string msg = string_format(scratch.arena, LIT("Error compiling pipeline \"%F\":\n\n%F"), FMT_STR(pipeline->name), FMT_STR(error)); - sys_message_box(SYS_MESSAGE_BOX_KIND_WARNING, msg); - } + { + struct string error = pipeline->first_error ? pipeline->first_error->msg : LIT("Unknown error"); + struct string msg = string_format(scratch.arena, LIT("Error compiling pipeline \"%F\":\n%F"), FMT_STR(pipeline->name), FMT_STR(error)); + log_error(msg); + } + struct pipeline *old_pipeline = dict_get(G.top_successful_pipelines, pipeline->hash); + if (!old_pipeline) { + /* If no previously successful pipeline exists, then show a message box rather than logging since logs may not be visible to user */ + struct string error = pipeline->first_error ? pipeline->first_error->msg : LIT("Unknown error"); + struct string msg = string_format(scratch.arena, LIT("Error compiling pipeline \"%F\":\n\n%F"), FMT_STR(pipeline->name), FMT_STR(error)); + sys_message_box(SYS_MESSAGE_BOX_KIND_WARNING, msg); + } + } } + sys_mutex_unlock(&lock); } - sys_mutex_unlock(&lock); + pipeline_register(num_pipelines, pipelines); } - pipeline_register(num_pipelines, pipelines); scratch_end(scratch); } @@ -1297,6 +1362,7 @@ INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(pipeline_resource_watch_callback, name INTERNAL struct descriptor *descriptor_alloc(struct cpu_descriptor_heap *dh) { + __prof; struct descriptor *d = NULL; u32 index = 0; D3D12_CPU_DESCRIPTOR_HANDLE handle = ZI; @@ -1331,6 +1397,7 @@ INTERNAL struct descriptor *descriptor_alloc(struct cpu_descriptor_heap *dh) INTERNAL struct cpu_descriptor_heap *cpu_descriptor_heap_alloc(enum D3D12_DESCRIPTOR_HEAP_TYPE type) { + __prof; struct cpu_descriptor_heap *dh = NULL; { struct arena *arena = arena_alloc(MEGABYTE(64)); @@ -1382,12 +1449,15 @@ struct flow { struct sprite_scope *sprite_scope; struct arena *material_instances_arena; struct arena *material_grids_arena; + struct arena *shape_verts_arena; + struct arena *shape_indices_arena; struct flow *next_free; }; INTERNAL struct flow *flow_alloc(void) { + __prof; struct flow *flow = NULL; { struct arena *arena = arena_alloc(MEGABYTE(64)); @@ -1398,40 +1468,47 @@ INTERNAL struct flow *flow_alloc(void) flow->sprite_scope = sprite_scope_begin(); flow->material_instances_arena = arena_alloc(GIGABYTE(1)); flow->material_grids_arena = arena_alloc(GIGABYTE(1)); + flow->shape_verts_arena = arena_alloc(GIGABYTE(1)); + flow->shape_indices_arena = arena_alloc(GIGABYTE(1)); return flow; } INTERNAL void flow_reset(struct flow *flow) { + __prof; sprite_scope_end(flow->sprite_scope); flow->sprite_scope = sprite_scope_begin(); arena_reset(flow->material_instances_arena); arena_reset(flow->material_grids_arena); + arena_reset(flow->shape_verts_arena); + arena_reset(flow->shape_indices_arena); } struct gp_handle gp_flow_alloc(void) { + __prof; struct flow *flow = flow_alloc(); return handle_alloc(DX12_HANDLE_KIND_FLOW, flow); } void gp_push_cmd(struct gp_handle gp_flow, struct gp_cmd_desc desc) { + __prof; struct flow *flow = handle_get_data(gp_flow, DX12_HANDLE_KIND_FLOW); if (flow) { switch (desc.kind) { default: break; - case GP_CMD_KIND_DRAW_TEXTURE: + case GP_CMD_KIND_DRAW_MATERIAL: { i32 texture_id = -1; { struct dx12_resource *texture = NULL; - if (desc.texture.texture.gen != 0) { - texture = handle_get_data(desc.texture.texture, DX12_HANDLE_KIND_RESOURCE); - } else if (desc.texture.sprite.hash != 0) { - struct sprite_texture *st = sprite_texture_from_tag_async(flow->sprite_scope, desc.texture.sprite); + if (desc.material.texture.gen != 0) { + texture = handle_get_data(desc.material.texture, DX12_HANDLE_KIND_RESOURCE); + } else if (desc.material.sprite.hash != 0) { + struct sprite_texture *st = sprite_texture_from_tag_async(flow->sprite_scope, desc.material.sprite); texture = handle_get_data(st->texture, DX12_HANDLE_KIND_RESOURCE); } if (texture) { @@ -1440,8 +1517,8 @@ void gp_push_cmd(struct gp_handle gp_flow, struct gp_cmd_desc desc) } i32 grid_id = -1; - if (desc.texture.grid) { - struct gp_grid_desc *grid_desc = desc.texture.grid; + if (desc.material.grid) { + struct gp_grid_desc *grid_desc = desc.material.grid; struct sh_material_grid *grid = arena_push(flow->material_grids_arena, struct sh_material_grid); grid->line_thickness = sh_float_from_f32(grid_desc->line_thickness); grid->line_spacing = sh_float_from_f32(grid_desc->line_spacing); @@ -1459,11 +1536,27 @@ void gp_push_cmd(struct gp_handle gp_flow, struct gp_cmd_desc desc) instance->flags = sh_uint_from_u32(SH_MATERIAL_FLAG_NONE); instance->tex_nurid = sh_int_from_i32(texture_id); instance->grid_id = sh_int_from_i32(grid_id); - instance->xf = sh_float2x3_from_xform(desc.texture.xf); - instance->uv0 = sh_float2_from_v2(desc.texture.clip.p0); - instance->uv1 = sh_float2_from_v2(desc.texture.clip.p1); - instance->tint_srgb = sh_uint_from_u32(desc.texture.tint); - instance->emittance = sh_float_from_f32(desc.texture.emittance); + instance->xf = sh_float2x3_from_xform(desc.material.xf); + instance->uv0 = sh_float2_from_v2(desc.material.clip.p0); + instance->uv1 = sh_float2_from_v2(desc.material.clip.p1); + instance->tint_srgb = sh_uint_from_u32(desc.material.tint); + instance->emittance = sh_float_from_f32(desc.material.emittance); + } + } break; + + case GP_CMD_KIND_DRAW_SHAPE: + { + u32 color = desc.shape.color; + u32 vert_offset = flow->shape_verts_arena->pos / sizeof(struct sh_shape_vert); + struct sh_shape_vert *verts = arena_push_array_no_zero(flow->shape_verts_arena, struct sh_shape_vert, desc.shape.vertices.count); + u32 *indices = arena_push_array_no_zero(flow->shape_indices_arena, u32, desc.shape.indices.count); + for (u32 i = 0; i < desc.shape.vertices.count; ++i) { + struct sh_shape_vert *v = &verts[i]; + v->pos = sh_float2_from_v2(desc.shape.vertices.points[i]); + v->color_srgb = sh_uint_from_u32(color); + } + for (u32 i = 0; i < desc.shape.indices.count; ++i) { + indices[i] = desc.shape.indices.indices[i] + vert_offset; } } break; } @@ -1484,6 +1577,7 @@ enum dx12_resource_view_flags { INTERNAL struct dx12_resource *dx12_resource_alloc(D3D12_HEAP_PROPERTIES heap_props, D3D12_HEAP_FLAGS heap_flags, D3D12_RESOURCE_DESC desc, D3D12_RESOURCE_STATES initial_state, enum dx12_resource_view_flags view_flags) { + __prof; struct dx12_resource *r = NULL; { struct sys_lock lock = sys_mutex_lock_e(G.resources_mutex); @@ -1538,6 +1632,7 @@ INTERNAL struct dx12_resource *dx12_resource_alloc(D3D12_HEAP_PROPERTIES heap_pr INTERNAL struct dx12_resource *dx12_resource_alloc_from_swapchain_buffer(ID3D12Resource *buff, struct v2i32 texture_size) { + __prof; struct dx12_resource *r = NULL; { struct sys_lock lock = sys_mutex_lock_e(G.resources_mutex); @@ -1565,16 +1660,19 @@ INTERNAL struct dx12_resource *dx12_resource_alloc_from_swapchain_buffer(ID3D12R INTERNAL void dx12_resource_release(struct dx12_resource *t) { + __prof; (UNUSED)t; } INTERNAL void dx12_resource_release_now(struct dx12_resource *t) { + __prof; (UNUSED)t; } INTERNAL enum D3D12_RESOURCE_STATES dx12_resource_barrier(ID3D12GraphicsCommandList *cl, struct dx12_resource *resource, enum D3D12_RESOURCE_STATES state) { + __prof; enum D3D12_RESOURCE_STATES old_state = resource->state; if (state != resource->state) { struct D3D12_RESOURCE_TRANSITION_BARRIER rtb = ZI; @@ -1601,6 +1699,7 @@ INTERNAL enum D3D12_RESOURCE_STATES dx12_resource_barrier(ID3D12GraphicsCommandL INTERNAL struct command_queue *command_queue_alloc(enum D3D12_COMMAND_LIST_TYPE type, enum D3D12_COMMAND_QUEUE_PRIORITY priority) { + __prof; struct command_queue *cq = NULL; { struct arena *arena = arena_alloc(GIGABYTE(64)); @@ -1629,6 +1728,7 @@ INTERNAL struct command_queue *command_queue_alloc(enum D3D12_COMMAND_LIST_TYPE INTERNAL void command_queue_release(struct command_queue *cq) { + __prof; /* TODO */ (UNUSED)cq; //ID3D12CommandQueue_Release(G.cq_copy_background->cq); @@ -1640,6 +1740,7 @@ INTERNAL void command_queue_release(struct command_queue *cq) INTERNAL struct command_list *command_list_open(struct command_queue *cq) { + __prof; u64 queue_fence_value = ID3D12Fence_GetCompletedValue(cq->fence); struct command_list *cl = NULL; @@ -1717,6 +1818,7 @@ INTERNAL struct command_list *command_list_open(struct command_queue *cq) /* TODO: Allow multiple command list submissions */ INTERNAL u64 command_list_close(struct command_list *cl) { + __prof; struct command_queue *cq = cl->cq; /* Close & execute */ @@ -1786,6 +1888,7 @@ INTERNAL u64 command_list_close(struct command_list *cl) INTERNAL struct command_descriptor_heap *command_list_push_descriptor_heap(struct command_list *cl, struct cpu_descriptor_heap *dh_cpu) { + __prof; ASSERT(dh_cpu->type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); /* Src heap must have expected type */ /* Allocate GPU heap */ @@ -1888,6 +1991,8 @@ INTERNAL u64 align_up_pow2(u64 v) INTERNAL struct command_buffer *command_list_push_buffer(struct command_list *cl, struct string data) { + __prof; + /* Determine size */ u64 size = max_u64(DX12_COMMAND_BUFFER_MIN_SIZE, align_up_pow2(data.len)); @@ -1942,6 +2047,7 @@ INTERNAL struct command_buffer *command_list_push_buffer(struct command_list *cl cb->group = cb_group; cb->size = data.len; + /* Create upload heap */ if (resource) { cb->resource = resource; } else { @@ -1995,6 +2101,7 @@ INTERNAL struct command_buffer *command_list_push_buffer(struct command_list *cl INTERNAL void command_list_set_root_constant(struct command_list *cl, void *src, u32 size) { + __prof; if (size % 4 == 0) { u32 num32bit = size / 4; for (u32 i = 0; i < num32bit; ++i) { @@ -2030,12 +2137,31 @@ INTERNAL D3D12_RECT scissor_from_rect(struct rect r) return scissor; } +INTERNAL D3D12_VERTEX_BUFFER_VIEW vbv_from_command_buffer(struct command_buffer *cb, u32 vertex_size) +{ + D3D12_VERTEX_BUFFER_VIEW vbv = ZI; + vbv.BufferLocation = cb->resource->gpu_address; + vbv.SizeInBytes = cb->size; + vbv.StrideInBytes = vertex_size; + return vbv; +} + +INTERNAL D3D12_INDEX_BUFFER_VIEW ibv_from_command_buffer(struct command_buffer *cb, DXGI_FORMAT format) +{ + D3D12_INDEX_BUFFER_VIEW ibv = ZI; + ibv.BufferLocation = cb->resource->gpu_address; + ibv.Format = format; + ibv.SizeInBytes = cb->size; + return ibv; +} + /* ========================== * * Texture * ========================== */ struct gp_handle gp_texture_alloc(enum gp_texture_format format, u32 flags, struct v2i32 size, void *initial_data) { + __prof; struct dxgi_format_info { DXGI_FORMAT format; u32 size; }; LOCAL_PERSIST const struct dxgi_format_info formats[] = { [GP_TEXTURE_FORMAT_R8G8B8A8_UNORM] = { DXGI_FORMAT_R8G8B8A8_UNORM, 4 }, @@ -2215,91 +2341,123 @@ void gp_dispatch(struct gp_dispatch_params params) struct pipeline_scope *pipeline_scope = pipeline_scope_begin(); struct pipeline *material_pipeline = pipeline_from_name(pipeline_scope, LIT("material")); - if (material_pipeline->success) { - struct command_list *cl = command_list_open(G.cq_direct); + struct pipeline *shape_pipeline = pipeline_from_name(pipeline_scope, LIT("shape")); + 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)); + + /* Upload buffers */ + struct command_buffer *material_instance_buffer = command_list_push_buffer(cl, STRING_FROM_ARENA(flow->material_instances_arena)); + struct command_buffer *material_grid_buffer = command_list_push_buffer(cl, STRING_FROM_ARENA(flow->material_grids_arena)); + struct command_buffer *shape_verts_buffer = command_list_push_buffer(cl, STRING_FROM_ARENA(flow->shape_verts_arena)); + struct command_buffer *shape_indices_buffer = command_list_push_buffer(cl, STRING_FROM_ARENA(flow->shape_indices_arena)); + + + /* Upload descriptor heap */ + struct command_descriptor_heap *descriptor_heap = command_list_push_descriptor_heap(cl, G.cbv_srv_uav_heap); + + struct mat4x4 vp_matrix = calculate_vp(params.draw_target_view, params.draw_target_viewport.width, params.draw_target_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 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 buffers */ - struct command_buffer *instance_buffer = command_list_push_buffer(cl, STRING_FROM_ARENA(flow->material_instances_arena)); - struct command_buffer *grid_buffer = command_list_push_buffer(cl, STRING_FROM_ARENA(flow->material_grids_arena)); - - /* Upload descriptor heap */ - struct command_descriptor_heap *descriptor_heap = command_list_push_descriptor_heap(cl, G.cbv_srv_uav_heap); - - struct mat4x4 vp_matrix = calculate_vp(params.draw_target_view, params.draw_target_viewport.width, params.draw_target_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 grid buffer */ - ID3D12GraphicsCommandList_SetGraphicsRootShaderResourceView(cl->cl, 2, grid_buffer->resource->gpu_address); - - /* Bind descriptor heap */ - ID3D12DescriptorHeap *heaps[] = { descriptor_heap->heap }; - ID3D12GraphicsCommandList_SetDescriptorHeaps(cl->cl, ARRAY_COUNT(heaps), heaps); - ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(cl->cl, 3, descriptor_heap->gp_handle); - - /* Setup Rasterizer State */ - D3D12_VIEWPORT viewport = viewport_from_rect(params.draw_target_viewport); - D3D12_RECT scissor = scissor_from_rect(params.draw_target_viewport); - ID3D12GraphicsCommandList_RSSetViewports(cl->cl, 1, &viewport); - ID3D12GraphicsCommandList_RSSetScissorRects(cl->cl, 1, &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); + 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); } } - command_list_close(cl); + + /* Material pass */ + if (material_pipeline->success) { + __profscope(Material pass); + u32 instance_count = material_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, material_instance_buffer->resource->gpu_address); + + /* Bind grid buffer */ + ID3D12GraphicsCommandList_SetGraphicsRootShaderResourceView(cl->cl, 2, material_grid_buffer->resource->gpu_address); + + /* Bind descriptor heap */ + ID3D12DescriptorHeap *heaps[] = { descriptor_heap->heap }; + ID3D12GraphicsCommandList_SetDescriptorHeaps(cl->cl, ARRAY_COUNT(heaps), heaps); + ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(cl->cl, 3, descriptor_heap->gp_handle); + + /* Setup Rasterizer State */ + D3D12_VIEWPORT viewport = viewport_from_rect(params.draw_target_viewport); + D3D12_RECT scissor = scissor_from_rect(params.draw_target_viewport); + ID3D12GraphicsCommandList_RSSetViewports(cl->cl, 1, &viewport); + ID3D12GraphicsCommandList_RSSetScissorRects(cl->cl, 1, &scissor); + + /* Draw */ + D3D12_VERTEX_BUFFER_VIEW vbv = vbv_from_command_buffer(dummy_vertex_buffer, 0); + D3D12_INDEX_BUFFER_VIEW ibv = ibv_from_command_buffer(quad_index_buffer, DXGI_FORMAT_R16_UINT); + ID3D12GraphicsCommandList_IASetPrimitiveTopology(cl->cl, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ID3D12GraphicsCommandList_IASetVertexBuffers(cl->cl, 0, 1, &vbv); + ID3D12GraphicsCommandList_IASetIndexBuffer(cl->cl, &ibv); + ID3D12GraphicsCommandList_DrawIndexedInstanced(cl->cl, 6, instance_count, 0, 0, 0); + } + + /* Shape pass */ + if (shape_pipeline->success) { + __profscope(Shape pass); + + /* Bind pipeline */ + ID3D12GraphicsCommandList_SetPipelineState(cl->cl, material_pipeline->pso); + ID3D12GraphicsCommandList_SetGraphicsRootSignature(cl->cl, material_pipeline->rootsig); + + /* Set root constants */ + struct sh_shape_constants constants = ZI; + constants.projection = sh_float4x4_from_mat4x4(vp_matrix); + command_list_set_root_constant(cl, &constants, sizeof(constants)); + + /* Bind descriptor heap */ + ID3D12DescriptorHeap *heaps[] = { descriptor_heap->heap }; + ID3D12GraphicsCommandList_SetDescriptorHeaps(cl->cl, ARRAY_COUNT(heaps), heaps); + ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(cl->cl, 3, descriptor_heap->gp_handle); + + /* Setup Rasterizer State */ + D3D12_VIEWPORT viewport = viewport_from_rect(params.draw_target_viewport); + D3D12_RECT scissor = scissor_from_rect(params.draw_target_viewport); + ID3D12GraphicsCommandList_RSSetViewports(cl->cl, 1, &viewport); + ID3D12GraphicsCommandList_RSSetScissorRects(cl->cl, 1, &scissor); + + /* Draw */ + D3D12_VERTEX_BUFFER_VIEW vbv = vbv_from_command_buffer(shape_verts_buffer, sizeof(struct sh_shape_vert)); + D3D12_INDEX_BUFFER_VIEW ibv = ibv_from_command_buffer(shape_indices_buffer, DXGI_FORMAT_R32_UINT); + ID3D12GraphicsCommandList_IASetPrimitiveTopology(cl->cl, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ID3D12GraphicsCommandList_IASetVertexBuffers(cl->cl, 0, 1, &vbv); + ID3D12GraphicsCommandList_IASetIndexBuffer(cl->cl, &ibv); + ID3D12GraphicsCommandList_DrawIndexedInstanced(cl->cl, 6, 1, 0, 0, 0); + } + + /* Reset render target */ + { + dx12_resource_barrier(cl->cl, target, target_old_state); + } } + command_list_close(cl); pipeline_scope_end(pipeline_scope); flow_reset(flow); } @@ -2308,54 +2466,6 @@ void gp_dispatch(struct gp_dispatch_params params) * Memory info * ========================== */ -#if 0 -struct gp_memory_info gp_query_memory_info(void) -{ - struct gp_memory_info res = ZI; - - HRESULT hr = 0; - IDXGIAdapter3 *dxgiAdapter3 = NULL; - struct DXGI_QUERY_VIDEO_MEMORY_INFO info = ZI; - if (SUCCEEDED(hr)) { - hr = IDXGIAdapter_QueryInterface(G.adapter, &IID_IDXGIAdapter3, (void **)&dxgiAdapter3); - ASSERT(SUCCEEDED(hr)); - } - if (SUCCEEDED(hr)) { - IDXGIAdapter3_QueryVideoMemoryInfo(dxgiAdapter3, 0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &info); - { - u64 vram = info.CurrentUsage; - u64 budget = info.Budget; - (UNUSED)vram; - (UNUSED)budget; -#if GSTAT_ENABLED - { - gstat_set(GSTAT_VRAM_USAGE, vram); - gstat_set(GSTAT_VRAM_BUDGET, budget); - } -#endif -#if PROFILING - { - LOCAL_PERSIST char *vram_plot_name = NULL; - LOCAL_PERSIST u64 prev_vram = 0; - if (!vram_plot_name) { - vram_plot_name = "Video memory usage"; - __prof_plot_init(vram_plot_name, __prof_plot_type_memory, 1, 1, 0); - } - if (vram != prev_vram) { - __prof_plot_i(vram_plot_name, vram); - } - prev_vram = vram; - } -#endif - } - } - if (dxgiAdapter3) { - IDXGIAdapter_Release(dxgiAdapter3); - } - - return res; -} -#else struct gp_memory_info gp_query_memory_info(void) { struct gp_memory_info res = ZI; @@ -2383,8 +2493,6 @@ struct gp_memory_info gp_query_memory_info(void) } return res; } -#endif - /* ========================== * * Present @@ -2476,12 +2584,6 @@ INTERNAL void present_blit(struct dx12_resource *dst, struct dx12_resource *src, 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 descriptor heap */ struct command_descriptor_heap *descriptor_heap = command_list_push_descriptor_heap(cl, G.cbv_srv_uav_heap); @@ -2520,9 +2622,11 @@ INTERNAL void present_blit(struct dx12_resource *dst, struct dx12_resource *src, ID3D12GraphicsCommandList_RSSetScissorRects(cl->cl, 1, &scissor); /* Draw */ + D3D12_VERTEX_BUFFER_VIEW vbv = vbv_from_command_buffer(dummy_vertex_buffer, 0); + D3D12_INDEX_BUFFER_VIEW ibv = ibv_from_command_buffer(quad_index_buffer, DXGI_FORMAT_R16_UINT); 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_IASetVertexBuffers(cl->cl, 0, 1, &vbv); + ID3D12GraphicsCommandList_IASetIndexBuffer(cl->cl, &ibv); ID3D12GraphicsCommandList_DrawIndexedInstanced(cl->cl, 6, 1, 0, 0, 0); /* Set dst to presentable */ @@ -2535,6 +2639,7 @@ INTERNAL void present_blit(struct dx12_resource *dst, struct dx12_resource *src, void gp_present(struct sys_window *window, struct v2i32 backbuffer_resolution, struct gp_handle texture, struct xform texture_xf, i32 vsync) { + __prof; //sys_sleep(0.1); struct dx12_resource *backbuffer_resource = update_swapchain(window, backbuffer_resolution); @@ -2547,9 +2652,13 @@ void gp_present(struct sys_window *window, struct v2i32 backbuffer_resolution, s /* Present */ /* FIXME: Resource barrier */ - HRESULT hr = IDXGISwapChain3_Present(G.swapchain, 0, 0); - if (!SUCCEEDED(hr)) { - ASSERT(false); + { + __profscope(Present); + HRESULT hr = IDXGISwapChain3_Present(G.swapchain, 0, 0); + if (!SUCCEEDED(hr)) { + ASSERT(false); + } + __profframe(0); } (UNUSED)backbuffer_resolution; diff --git a/src/sprite.c b/src/sprite.c index a2a79968..5d389799 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -974,7 +974,6 @@ INTERNAL struct sprite_scope_cache_ref *cache_entry_from_tag(struct sprite_scope } } - return scope_ref; } diff --git a/src/sys_win32.c b/src/sys_win32.c index 289e10cd..0abf42e3 100644 --- a/src/sys_win32.c +++ b/src/sys_win32.c @@ -1195,6 +1195,11 @@ INTERNAL void win32_update_window_from_settings(struct win32_window *window, str }; SetWindowPlacement(hwnd, &wp); + /* Make window always on top when debugging */ +#if RTC + SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); +#endif + { struct arena_temp scratch = scratch_begin_no_conflict(); wchar_t *title_wstr = wstr_from_string(scratch.arena, string_from_cstr_no_limit(settings->title)); diff --git a/src/user.c b/src/user.c index 36ca4a9d..d2f19a46 100644 --- a/src/user.c +++ b/src/user.c @@ -1053,19 +1053,6 @@ INTERNAL void user_update(void) draw_grid(G.world_gp_flow, xform_from_rect(RECT_FROM_V2(pos, size)), color0, color1, RGBA32(0x3f, 0x3f, 0x3f, 0xFF), COLOR_RED, COLOR_GREEN, thickness, spacing, offset); } - /* ========================== * - * Draw test - * ========================== */ - - { - struct v2 pos = xform_invert_mul_v2(G.world_to_user_xf, V2(0, 0)); - struct v2 size = xform_basis_invert_mul_v2(G.world_to_user_xf, G.user_size); - struct gp_cmd_desc cmd = ZI; - cmd.kind = GP_CMD_KIND_TEST; - cmd.test.xf = xform_from_rect(RECT_FROM_V2(pos, size)); - gp_push_cmd(G.world_gp_flow, cmd); - } - #if 0 /* ========================== * * Alloc / release tile cache entries diff --git a/src/work.c b/src/work.c index 079774ff..fb248144 100644 --- a/src/work.c +++ b/src/work.c @@ -548,11 +548,12 @@ struct work_handle work_slate_end(struct work_slate *ws, enum work_priority prio struct work_handle work_slate_end_and_help(struct work_slate *ws, enum work_priority priority) { __prof; - - struct sys_lock lock = sys_mutex_lock_e(G.mutex); - struct work_handle handle = work_push_from_slate_locked(&lock, ws, true, priority); - sys_mutex_unlock(&lock); - + struct work_handle handle = ZI; + if (ws->num_tasks > 0) { + struct sys_lock lock = sys_mutex_lock_e(G.mutex); + handle = work_push_from_slate_locked(&lock, ws, true, priority); + sys_mutex_unlock(&lock); + } return handle; } @@ -566,7 +567,7 @@ INTERNAL struct work *work_from_handle_locked(struct sys_lock *lock, struct work (UNUSED)lock; struct work *work = handle.work; - if (work->gen != handle.gen) { + if (work && work->gen != handle.gen) { work = NULL; } return work;