blit shader

This commit is contained in:
jacob 2025-06-23 18:54:11 -05:00
parent 01aff521da
commit 214e794ec4
6 changed files with 180 additions and 75 deletions

69
res/sh/blit.hlsl Normal file
View File

@ -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<struct sh_blit_constants> 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;
}

View File

@ -15,7 +15,7 @@
"addressW = TEXTURE_ADDRESS_CLAMP, " \
"maxAnisotropy = 1)"
cbuffer cb : register(b0) { struct sh_material_constants g_constants; };
ConstantBuffer<struct sh_material_constants> g_constants : register(b0);
StructuredBuffer<struct sh_material_instance> g_instances : register(t0);
Texture2D g_nuri_textures[] : register(t1);

View File

@ -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 {

View File

@ -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);
/* ========================== *

View File

@ -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();

View File

@ -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;