From 214e794ec4873c527c3e00d734a889c39f280caa Mon Sep 17 00:00:00 2001 From: jacob Date: Mon, 23 Jun 2025 18:54:11 -0500 Subject: [PATCH] blit shader --- res/sh/blit.hlsl | 69 ++++++++++++++++++ res/sh/material.hlsl | 2 +- res/sh/sh_common.h | 12 +++- src/gp.h | 2 - src/gp_dx12.c | 167 +++++++++++++++++++++++++------------------ src/user.c | 3 - 6 files changed, 180 insertions(+), 75 deletions(-) create mode 100644 res/sh/blit.hlsl diff --git a/res/sh/blit.hlsl b/res/sh/blit.hlsl new file mode 100644 index 00000000..0048f4e3 --- /dev/null +++ b/res/sh/blit.hlsl @@ -0,0 +1,69 @@ +#include "sh/common.hlsl" + +/* ========================== * + * Root signature + * ========================== */ + +#define ROOTSIG \ + "RootConstants(num32BitConstants=17, b0), " \ + "DescriptorTable(SRV(t0, 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); +Texture2D g_nuri_textures[] : register(t0); + +SamplerState g_sampler : register(s0); + +/* ========================== * + * Vertex shader + * ========================== */ + +struct vs_input { + DECL(uint, SV_VertexID); +}; + +struct vs_output { + DECL(float4, SV_Position); + DECL(float2, uv); +}; + +SH_ENTRY(ROOTSIG) struct vs_output vs(struct vs_input input) +{ + static const float2 unit_quad_verts[4] = { + float2(-0.5f, -0.5f), + float2(0.5f, -0.5f), + float2(0.5f, 0.5f), + float2(-0.5f, 0.5f) + }; + + float2 vert = unit_quad_verts[input.SV_VertexID]; + + struct vs_output output; + output.SV_Position = mul(g_constants.projection, float4(vert, 0, 1)); + output.uv = vert + 0.5; + return output; +} + +/* ========================== * + * Pixel shader + * ========================== */ + +struct ps_input { + struct vs_output vs; +}; + +struct ps_output { + DECL(float4, SV_Target); +}; + +SH_ENTRY(ROOTSIG) struct ps_output ps(struct ps_input input) +{ + struct ps_output output; + output.SV_Target = g_nuri_textures[g_constants.texture_id].Sample(g_sampler, input.vs.uv); + return output; +} diff --git a/res/sh/material.hlsl b/res/sh/material.hlsl index aa086f93..bc4122e9 100644 --- a/res/sh/material.hlsl +++ b/res/sh/material.hlsl @@ -15,7 +15,7 @@ "addressW = TEXTURE_ADDRESS_CLAMP, " \ "maxAnisotropy = 1)" -cbuffer cb : register(b0) { struct sh_material_constants g_constants; }; +ConstantBuffer g_constants : register(b0); StructuredBuffer g_instances : register(t0); Texture2D g_nuri_textures[] : register(t1); diff --git a/res/sh/sh_common.h b/res/sh/sh_common.h index ca1506ce..2f855122 100644 --- a/res/sh/sh_common.h +++ b/res/sh/sh_common.h @@ -51,7 +51,17 @@ INLINE struct sh_float2x3 sh_float2x3_from_xform(struct xform v) #endif /* ========================== * - * Material shader structs + * Blit shader structures + * ========================== */ + +SH_STRUCT(sh_blit_constants { + SH_DECL(float4x4, projection); + SH_DECL(uint, texture_id); +}); +SH_ASSERT_32BIT(struct sh_blit_constants, 17); /* Expected 32bit root constant size in shader */ + +/* ========================== * + * Material shader structures * ========================== */ SH_STRUCT(sh_material_constants { diff --git a/src/gp.h b/src/gp.h index e4a268ef..e61314be 100644 --- a/src/gp.h +++ b/src/gp.h @@ -57,8 +57,6 @@ enum gp_texture_flag { struct gp_handle gp_texture_alloc(enum gp_texture_format format, u32 flags, struct v2i32 size, void *initial_data); -void gp_texture_clear(struct gp_handle target_texture, u32 clear_color); - struct v2i32 gp_texture_get_size(struct gp_handle texture); /* ========================== * diff --git a/src/gp_dx12.c b/src/gp_dx12.c index e9c03155..353f1344 100644 --- a/src/gp_dx12.c +++ b/src/gp_dx12.c @@ -641,6 +641,12 @@ INTERNAL READONLY struct pipeline_desc g_pipeline_descs[] = { .name = "material", .vs = { "sh/material.hlsl", "vs" }, .ps = { "sh/material.hlsl", "ps" } + }, + /* Blit pipeline */ + { + .name = "blit", + .vs = { "sh/blit.hlsl", "vs" }, + .ps = { "sh/blit.hlsl", "ps" } } }; @@ -1844,7 +1850,7 @@ INTERNAL struct command_buffer *command_list_push_buffer(struct command_list *cl } /* ========================== * - * Command root constant + * Util * ========================== */ INTERNAL void command_list_set_root_constant(struct command_list *cl, void *src, u32 size) @@ -1862,6 +1868,28 @@ INTERNAL void command_list_set_root_constant(struct command_list *cl, void *src, } } +INTERNAL struct D3D12_VIEWPORT viewport_from_rect(struct rect r) +{ + struct D3D12_VIEWPORT viewport = ZI; + viewport.TopLeftX = r.x; + viewport.TopLeftY = r.y; + viewport.Width = r.width; + viewport.Height = r.height; + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + return viewport; +} + +INTERNAL D3D12_RECT scissor_from_rect(struct rect r) +{ + D3D12_RECT scissor = ZI; + scissor.left = r.x; + scissor.top = r.y; + scissor.right = r.x + r.width; + scissor.bottom = r.y + r.height; + return scissor; +} + /* ========================== * * Texture * ========================== */ @@ -2017,12 +2045,6 @@ struct gp_handle gp_texture_alloc(enum gp_texture_format format, u32 flags, stru return handle_alloc(DX12_HANDLE_KIND_RESOURCE, r); } -void gp_texture_clear(struct gp_handle target_resource, u32 clear_color) -{ - (UNUSED)target_resource; - (UNUSED)clear_color; -} - struct v2i32 gp_texture_get_size(struct gp_handle resource) { struct v2i32 res = ZI; @@ -2077,24 +2099,7 @@ void gp_dispatch(struct gp_dispatch_params params) /* 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); + 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 */ @@ -2132,8 +2137,10 @@ void gp_dispatch(struct gp_dispatch_params params) 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); + 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); @@ -2287,52 +2294,76 @@ INTERNAL struct dx12_resource *update_swapchain(struct sys_window *window, struc return G.swapchain_resources[G.swapchain_frame_index]; } - - - - - -/* FIXME: Remove this */ -#include "draw.h" - - - - INTERNAL void present_blit(struct dx12_resource *dst, struct dx12_resource *src, struct xform src_xf) { - /* FIXME: Remove this */ - static struct gp_handle flow = ZI; - if (!flow.gen) { - flow = gp_flow_alloc(); + __prof; + struct pipeline_scope *pipeline_scope = pipeline_scope_begin(); + struct pipeline *blit_pipeline = pipeline_from_name(pipeline_scope, LIT("blit")); + if (blit_pipeline->valid) { + struct command_list *cl = command_list_open(G.cq_direct); + { + /* 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 descriptor heap */ + struct command_descriptor_heap *descriptor_heap = command_list_push_descriptor_heap(cl, G.cbv_srv_uav_heap); + + struct rect viewport_rect = RECT_FROM_V2(V2(0, 0), V2(dst->texture_size.x, dst->texture_size.y)); + D3D12_VIEWPORT viewport = viewport_from_rect(viewport_rect); + D3D12_RECT scissor = scissor_from_rect(viewport_rect); + struct mat4x4 vp_matrix = calculate_vp(src_xf, viewport.Width, viewport.Height); + + /* Transition dst to render target */ + dx12_resource_barrier(cl->cl, dst, D3D12_RESOURCE_STATE_RENDER_TARGET); + ID3D12GraphicsCommandList_OMSetRenderTargets(cl->cl, 1, &dst->rtv_descriptor->handle, false, NULL); + + /* Clear */ + f32 clear_color[] = { 0.0f, 0.0f, 0.0f, 0.0f }; + ID3D12GraphicsCommandList_ClearRenderTargetView(cl->cl, dst->rtv_descriptor->handle, clear_color, 0, NULL); + + /* Bind pipeline */ + ID3D12GraphicsCommandList_SetPipelineState(cl->cl, blit_pipeline->pso); + ID3D12GraphicsCommandList_SetGraphicsRootSignature(cl->cl, blit_pipeline->rootsig); + + /* Set root constants */ + struct sh_blit_constants constants = ZI; + constants.projection = sh_float4x4_from_mat4x4(vp_matrix); + constants.texture_id = sh_uint_from_u32(src->srv_descriptor->index); + 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, 1, descriptor_heap->gp_handle); + + /* Setup Rasterizer State */ + 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, 1, 0, 0, 0); + + /* Set dst to presentable */ + dx12_resource_barrier(cl->cl, dst, D3D12_RESOURCE_STATE_PRESENT); + } + command_list_close(cl); } - struct gp_handle dst_texture_handle = handle_alloc(DX12_HANDLE_KIND_RESOURCE, dst); - struct gp_handle src_texture_handle = handle_alloc(DX12_HANDLE_KIND_RESOURCE, src); - - /* Draw texture to backbuffer texture */ - /* TODO: Specialized blit shader */ - { - struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.xf = src_xf, .texture = src_texture_handle); - draw_texture(flow, params); - } - - /* FIXME: Clear backbuffer */ - - /* Render to backbuffer texture */ - struct gp_dispatch_params params = ZI; - params.flow = flow; - params.draw_target = dst_texture_handle; - params.draw_target_viewport = RECT_FROM_V2(V2(0, 0), V2(dst->texture_size.x, dst->texture_size.y)); - params.draw_target_view = XFORM_IDENT; - params.clear_target = true; - gp_dispatch(params); + pipeline_scope_end(pipeline_scope); } - - - - - - void gp_present(struct sys_window *window, struct v2i32 backbuffer_resolution, struct gp_handle texture, struct xform texture_xf, i32 vsync) { query_memory_info(); diff --git a/src/user.c b/src/user.c index be580b5f..7c486aac 100644 --- a/src/user.c +++ b/src/user.c @@ -2069,9 +2069,6 @@ INTERNAL void user_update(void) G.user_texture = gp_texture_alloc(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM, GP_TEXTURE_FLAG_TARGETABLE, user_resolution, NULL); } - /* Clear textures */ - gp_texture_clear(G.user_texture, 0); - /* Render world to user texture */ { struct gp_dispatch_params params = ZI;