add grid to material shader

This commit is contained in:
jacob 2025-06-24 17:25:29 -05:00
parent 520dd6c874
commit 5bdaba67e7
10 changed files with 223 additions and 92 deletions

View File

@ -5,7 +5,7 @@
* ========================== */ * ========================== */
#define ROOTSIG \ #define ROOTSIG \
"RootConstants(num32BitConstants=17, b0), " \ "RootConstants(num32BitConstants=18, b0), " \
"DescriptorTable(SRV(t0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE)), " \ "DescriptorTable(SRV(t0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE)), " \
"StaticSampler(s0, " \ "StaticSampler(s0, " \
"filter = FILTER_MIN_MAG_MIP_POINT, " \ "filter = FILTER_MIN_MAG_MIP_POINT, " \
@ -15,7 +15,7 @@
"maxAnisotropy = 1)" "maxAnisotropy = 1)"
ConstantBuffer<struct sh_blit_constants> g_constants : register(b0); ConstantBuffer<struct sh_blit_constants> g_constants : register(b0);
Texture2D g_nuri_textures[] : register(t0); Texture2D g_textures[] : register(t0);
SamplerState g_sampler : register(s0); SamplerState g_sampler : register(s0);
@ -64,6 +64,7 @@ struct ps_output {
SH_ENTRY(ROOTSIG) struct ps_output ps(struct ps_input input) SH_ENTRY(ROOTSIG) struct ps_output ps(struct ps_input input)
{ {
struct ps_output output; struct ps_output output;
output.SV_Target = g_nuri_textures[g_constants.texture_id].Sample(g_sampler, input.vs.uv); const float gamma = g_constants.gamma;
output.SV_Target = pow(g_textures[g_constants.tex_urid].Sample(g_sampler, input.vs.uv), 1/gamma);
return output; return output;
} }

View File

@ -4,7 +4,7 @@
#define GOLDEN 1.61803398875 #define GOLDEN 1.61803398875
#define DECL(t, n) t n : n #define DECL(t, n) t n : n
#define NURI(i) NonUniformResourceIndex(i) #define NURID(i) NonUniformResourceIndex(i)
#if !SH_CPU #if !SH_CPU
# define INLINE /* For intellisense */ # define INLINE /* For intellisense */

View File

@ -7,7 +7,8 @@
#define ROOTSIG \ #define ROOTSIG \
"RootConstants(num32BitConstants=16, b0), " \ "RootConstants(num32BitConstants=16, b0), " \
"SRV(t0), " \ "SRV(t0), " \
"DescriptorTable(SRV(t1, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE)), " \ "SRV(t1), " \
"DescriptorTable(SRV(t2, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE)), " \
"StaticSampler(s0, " \ "StaticSampler(s0, " \
"filter = FILTER_MIN_MAG_MIP_POINT, " \ "filter = FILTER_MIN_MAG_MIP_POINT, " \
"addressU = TEXTURE_ADDRESS_CLAMP, " \ "addressU = TEXTURE_ADDRESS_CLAMP, " \
@ -17,7 +18,8 @@
ConstantBuffer<struct sh_material_constants> g_constants : register(b0); ConstantBuffer<struct sh_material_constants> g_constants : register(b0);
StructuredBuffer<struct sh_material_instance> g_instances : register(t0); StructuredBuffer<struct sh_material_instance> g_instances : register(t0);
Texture2D g_nuri_textures[] : register(t1); StructuredBuffer<struct sh_material_grid> g_grids : register(t1);
Texture2D g_textures[] : register(t2);
SamplerState g_sampler : register(s0); SamplerState g_sampler : register(s0);
@ -31,10 +33,12 @@ struct vs_input {
}; };
struct vs_output { struct vs_output {
DECL(float4, SV_Position); nointerpolation DECL(uint, flags);
nointerpolation DECL(int, tex_nurid);
nointerpolation DECL(int, grid_id);
DECL(float2, uv); DECL(float2, uv);
DECL(float4, tint_lin); DECL(float4, tint_lin);
DECL(uint, texture_nuri); DECL(float4, SV_Position);
}; };
SH_ENTRY(ROOTSIG) struct vs_output vs(struct vs_input input) SH_ENTRY(ROOTSIG) struct vs_output vs(struct vs_input input)
@ -52,9 +56,11 @@ SH_ENTRY(ROOTSIG) struct vs_output vs(struct vs_input input)
struct vs_output output; struct vs_output output;
output.SV_Position = mul(g_constants.projection, float4(world_pos, 0, 1)); output.SV_Position = mul(g_constants.projection, float4(world_pos, 0, 1));
output.flags = instance.flags;
output.tex_nurid = instance.tex_nurid;
output.grid_id = instance.grid_id;
output.uv = instance.uv0 + ((vert + 0.5) * (instance.uv1 - instance.uv0)); output.uv = instance.uv0 + ((vert + 0.5) * (instance.uv1 - instance.uv0));
output.tint_lin = linear_from_srgb32(instance.tint_srgb); output.tint_lin = linear_from_srgb32(instance.tint_srgb);
output.texture_nuri = instance.texture_nuri;
return output; return output;
} }
@ -73,6 +79,44 @@ struct ps_output {
SH_ENTRY(ROOTSIG) struct ps_output ps(struct ps_input input) SH_ENTRY(ROOTSIG) struct ps_output ps(struct ps_input input)
{ {
struct ps_output output; struct ps_output output;
output.SV_Target = g_nuri_textures[NURI(input.vs.texture_nuri)].Sample(g_sampler, input.vs.uv) * input.vs.tint_lin * 1; output.SV_Target = float4(1, 1, 1, 1);
/* Texture */
if (input.vs.tex_nurid >= 0) {
output.SV_Target *= g_textures[NURID(input.vs.tex_nurid)].Sample(g_sampler, input.vs.uv);
}
/* Grid */
if (input.vs.grid_id >= 0) {
struct sh_material_grid grid = g_grids[input.vs.grid_id];
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);
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);
} else if (grid_pos.x <= half_thickness && grid_pos.x >= -half_thickness) {
color = linear_from_srgb32(grid.y_srgb);
} else if (dist < half_thickness) {
color = linear_from_srgb32(grid.line_srgb);
} else {
bool checker = false;
uint cell_x = (uint)(abs(grid_pos.x) / spacing) + (grid_pos.x < 0);
uint cell_y = (uint)(abs(grid_pos.y) / spacing) + (grid_pos.y < 0);
if (cell_x % 2 == 0) {
checker = cell_y % 2 == 0;
} else {
checker = cell_y % 2 == 1;
}
if (checker) {
color = linear_from_srgb32(grid.bg1_srgb);
}
}
output.SV_Target *= color;
}
output.SV_Target *= input.vs.tint_lin;
return output; return output;
} }

View File

@ -11,6 +11,12 @@ INLINE struct sh_uint sh_uint_from_u32(u32 v)
return (struct sh_uint) { .v = v }; return (struct sh_uint) { .v = v };
} }
struct sh_int { i32 v; };
INLINE struct sh_int sh_int_from_i32(i32 v)
{
return (struct sh_int) { .v = v };
}
struct sh_float { f32 v; }; struct sh_float { f32 v; };
INLINE struct sh_float sh_float_from_f32(f32 v) INLINE struct sh_float sh_float_from_f32(f32 v)
{ {
@ -56,24 +62,40 @@ INLINE struct sh_float2x3 sh_float2x3_from_xform(struct xform v)
SH_STRUCT(sh_blit_constants { SH_STRUCT(sh_blit_constants {
SH_DECL(float4x4, projection); SH_DECL(float4x4, projection);
SH_DECL(uint, texture_id); SH_DECL(uint, tex_urid);
SH_DECL(float, gamma);
}); });
SH_ASSERT_32BIT(struct sh_blit_constants, 17); /* Expected 32bit root constant size in shader */ SH_ASSERT_32BIT(struct sh_blit_constants, 18); /* Expected 32bit root constant size in shader */
/* ========================== * /* ========================== *
* Material shader structures * Material shader structures
* ========================== */ * ========================== */
#define SH_MATERIAL_FLAG_NONE (0)
SH_STRUCT(sh_material_constants { SH_STRUCT(sh_material_constants {
SH_DECL(float4x4, projection); SH_DECL(float4x4, projection);
}); });
SH_ASSERT_32BIT(struct sh_material_constants, 16); /* Expected 32bit root constant size in shader */ SH_ASSERT_32BIT(struct sh_material_constants, 16); /* Expected 32bit root constant size in shader */
SH_STRUCT(sh_material_instance { SH_STRUCT(sh_material_instance {
SH_DECL(uint, flags);
SH_DECL(int, tex_nurid);
SH_DECL(int, grid_id);
SH_DECL(float2x3, xf); SH_DECL(float2x3, xf);
SH_DECL(float2, uv0); SH_DECL(float2, uv0);
SH_DECL(float2, uv1); SH_DECL(float2, uv1);
SH_DECL(uint, texture_nuri);
SH_DECL(uint, tint_srgb); SH_DECL(uint, tint_srgb);
SH_DECL(float, emittance); SH_DECL(float, emittance);
}); });
SH_STRUCT(sh_material_grid {
SH_DECL(float, line_thickness);
SH_DECL(float, line_spacing);
SH_DECL(float2, offset);
SH_DECL(uint, bg0_srgb);
SH_DECL(uint, bg1_srgb);
SH_DECL(uint, line_srgb);
SH_DECL(uint, x_srgb);
SH_DECL(uint, y_srgb);
});

View File

@ -30,7 +30,7 @@ struct draw_startup_receipt draw_startup(struct gp_startup_receipt *gp_sr,
void draw_texture(struct gp_handle flow, struct draw_texture_params params) void draw_texture(struct gp_handle flow, struct draw_texture_params params)
{ {
struct gp_cmd_params cmd = ZI; struct gp_cmd_desc cmd = ZI;
cmd.kind = GP_CMD_KIND_DRAW_TEXTURE; cmd.kind = GP_CMD_KIND_DRAW_TEXTURE;
cmd.texture.xf = params.xf; cmd.texture.xf = params.xf;
cmd.texture.sprite = params.sprite; cmd.texture.sprite = params.sprite;
@ -47,7 +47,7 @@ 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) void draw_poly_ex(struct gp_handle flow, struct v2_array vertices, struct gp_indices indices, u32 color)
{ {
struct gp_cmd_params cmd = ZI; struct gp_cmd_desc cmd = ZI;
cmd.kind = GP_CMD_KIND_DRAW_MESH; cmd.kind = GP_CMD_KIND_DRAW_MESH;
cmd.mesh.vertices = vertices; cmd.mesh.vertices = vertices;
cmd.mesh.indices = indices; cmd.mesh.indices = indices;
@ -260,17 +260,21 @@ void draw_collider_line(struct gp_handle flow, struct collider_shape shape, stru
void draw_grid(struct gp_handle flow, struct xform xf, u32 bg0_color, u32 bg1_color, u32 line_color, u32 x_color, u32 y_color, f32 thickness, f32 spacing, struct v2 offset) void draw_grid(struct gp_handle flow, struct xform xf, u32 bg0_color, u32 bg1_color, u32 line_color, u32 x_color, u32 y_color, f32 thickness, f32 spacing, struct v2 offset)
{ {
struct gp_cmd_params cmd = ZI; struct gp_grid_desc grid = ZI;
cmd.kind = GP_CMD_KIND_DRAW_GRID; grid.bg0_color = bg0_color;
cmd.grid.xf = xf; grid.bg1_color = bg1_color;
cmd.grid.bg0_color = bg0_color; grid.line_color = line_color;
cmd.grid.bg1_color = bg1_color; grid.x_color = x_color;
cmd.grid.line_color = line_color; grid.y_color = y_color;
cmd.grid.x_color = x_color; grid.line_thickness = thickness;
cmd.grid.y_color = y_color; grid.line_spacing = spacing;
cmd.grid.line_thickness = thickness; grid.offset = offset;
cmd.grid.line_spacing = spacing;
cmd.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;
gp_push_cmd(flow, cmd); gp_push_cmd(flow, cmd);
} }

View File

@ -72,13 +72,23 @@ enum gp_cmd_kind {
GP_CMD_KIND_NONE, GP_CMD_KIND_NONE,
GP_CMD_KIND_DRAW_MESH, GP_CMD_KIND_DRAW_MESH,
GP_CMD_KIND_DRAW_TEXTURE, GP_CMD_KIND_DRAW_TEXTURE,
GP_CMD_KIND_DRAW_GRID,
GP_CMD_KIND_TEST, GP_CMD_KIND_TEST,
NUM_GP_CMD_KINDS NUM_GP_CMD_KINDS
}; };
struct gp_cmd_params { struct gp_grid_desc {
f32 line_thickness;
f32 line_spacing;
struct v2 offset;
u32 bg0_color;
u32 bg1_color;
u32 line_color;
u32 x_color;
u32 y_color;
};
struct gp_cmd_desc {
enum gp_cmd_kind kind; enum gp_cmd_kind kind;
union { union {
struct { struct {
@ -93,18 +103,8 @@ struct gp_cmd_params {
struct clip_rect clip; struct clip_rect clip;
u32 tint; u32 tint;
f32 emittance; f32 emittance;
struct gp_grid_desc *grid;
} texture; } texture;
struct {
struct xform xf;
f32 line_thickness;
f32 line_spacing;
struct v2 offset;
u32 bg0_color;
u32 bg1_color;
u32 line_color;
u32 x_color;
u32 y_color;
} grid;
struct { struct {
struct xform xf; struct xform xf;
} test; } test;
@ -121,7 +121,7 @@ struct gp_dispatch_params {
struct gp_handle gp_flow_alloc(void); struct gp_handle gp_flow_alloc(void);
void gp_push_cmd(struct gp_handle gp_flow, struct gp_cmd_params params); void gp_push_cmd(struct gp_handle gp_flow, struct gp_cmd_desc params);
void gp_dispatch(struct gp_dispatch_params params); void gp_dispatch(struct gp_dispatch_params params);

View File

@ -1372,7 +1372,7 @@ struct gp_handle gp_flow_alloc(void)
return res; return res;
} }
void gp_push_cmd(struct gp_handle gp_flow, struct gp_cmd_params params) void gp_push_cmd(struct gp_handle gp_flow, struct gp_cmd_desc params)
{ {
__prof; __prof;
struct dx11_flow *flow = (struct dx11_flow *)gp_flow.v; struct dx11_flow *flow = (struct dx11_flow *)gp_flow.v;

View File

@ -80,10 +80,12 @@ struct pipeline {
struct pipeline_error *first_error; struct pipeline_error *first_error;
struct pipeline_error *last_error; struct pipeline_error *last_error;
i64 compilation_time; i64 compilation_time_ns;
/* Dict with shader source & included file names as keys */
struct dict *dependencies; struct dict *dependencies;
/* Lock global pipelines mutex before accessing */ /* Lock global pipelines mutex when accessing */
i64 refcount; i64 refcount;
struct pipeline_desc desc; struct pipeline_desc desc;
@ -625,9 +627,7 @@ INTERNAL void dx12_init_objects(void)
* Dx12 pipeline initialization * Dx12 pipeline initialization
* ========================== */ * ========================== */
INTERNAL READONLY struct pipeline g_nil_pipeline = ZI; INTERNAL void pipeline_alloc_from_desc(u64 num_pipelines, struct pipeline_desc *descs, struct pipeline **pipelines_out);
INTERNAL void pipeline_alloc_from_descs(u64 num_pipelines, struct pipeline_desc *descs, struct pipeline **pipelines_out);
INTERNAL void pipeline_release(struct pipeline *pipeline); INTERNAL void pipeline_release(struct pipeline *pipeline);
INTERNAL void pipeline_register(u64 num_pipelines, struct pipeline **pipelines); INTERNAL void pipeline_register(u64 num_pipelines, struct pipeline **pipelines);
@ -669,12 +669,13 @@ INTERNAL void dx12_init_pipelines(void)
++num_pipelines; ++num_pipelines;
} }
struct pipeline **pipelines = arena_push_array(scratch.arena, struct pipeline *, num_pipelines); struct pipeline **pipelines = arena_push_array(scratch.arena, struct pipeline *, num_pipelines);
pipeline_alloc_from_descs(num_pipelines, descs, pipelines); pipeline_alloc_from_desc(num_pipelines, descs, pipelines);
for (u32 i = 0; i < num_pipelines; ++i) { for (u32 i = 0; i < num_pipelines; ++i) {
struct pipeline *pipeline = pipelines[i]; struct pipeline *pipeline = pipelines[i];
if (!pipeline->success) { if (!pipeline->success) {
struct string msg = pipeline->first_error ? pipeline->first_error->msg : LIT("Unknown error"); struct string error = pipeline->first_error ? pipeline->first_error->msg : LIT("Unknown error");
sys_panic(msg); struct string msg = string_format(scratch.arena, LIT("Error creating pipeline \"%F\":\n\n%F"), FMT_STR(pipeline->name), FMT_STR(error));
sys_message_box(SYS_MESSAGE_BOX_KIND_WARNING, msg);
} }
} }
pipeline_register(num_pipelines, pipelines); pipeline_register(num_pipelines, pipelines);
@ -1073,7 +1074,7 @@ INTERNAL WORK_TASK_FUNC_DEF(pipeline_load_task, load_arg_raw)
pipeline->pso = pso; pipeline->pso = pso;
pipeline->rootsig = rootsig; pipeline->rootsig = rootsig;
pipeline->compilation_time = sys_time_ns() - start_ns; pipeline->compilation_time_ns = sys_time_ns() - start_ns;
pipeline->success = success; pipeline->success = success;
resource_close(&vs_res); resource_close(&vs_res);
@ -1099,8 +1100,7 @@ INTERNAL WORK_TASK_FUNC_DEF(pipeline_load_task, load_arg_raw)
scratch_end(scratch); scratch_end(scratch);
} }
/* Expects `descs` and `pipelines_out` to be arrays of length `num_pipelines` */ INTERNAL void pipeline_alloc_from_desc(u64 num_pipelines, struct pipeline_desc *descs, struct pipeline **pipelines_out)
INTERNAL void pipeline_alloc_from_descs(u64 num_pipelines, struct pipeline_desc *descs, struct pipeline **pipelines_out)
{ {
__prof; __prof;
struct work_slate ws = work_slate_begin(); struct work_slate ws = work_slate_begin();
@ -1180,28 +1180,31 @@ INTERNAL void pipeline_scope_end(struct pipeline_scope *scope)
sys_mutex_unlock(&lock); sys_mutex_unlock(&lock);
} }
INTERNAL READONLY struct pipeline g_nil_pipeline = ZI;
INTERNAL struct pipeline *pipeline_from_name(struct pipeline_scope *scope, struct string name) INTERNAL struct pipeline *pipeline_from_name(struct pipeline_scope *scope, struct string name)
{ {
struct pipeline *pipeline = NULL; struct pipeline *res = &g_nil_pipeline;
u64 hash = hash_fnv64(HASH_FNV64_BASIS, name); u64 hash = hash_fnv64(HASH_FNV64_BASIS, name);
pipeline = dict_get(scope->refs, hash); struct pipeline *tmp = dict_get(scope->refs, hash);
if (!pipeline) { if (tmp) {
res = tmp;
} else {
{ {
struct sys_lock lock = sys_mutex_lock_e(G.pipelines_mutex); struct sys_lock lock = sys_mutex_lock_e(G.pipelines_mutex);
struct pipeline *res = dict_get(G.top_successful_pipelines, hash); tmp = dict_get(G.top_successful_pipelines, hash);
if (res) { if (tmp) {
pipeline = res; ++tmp->refcount;
++pipeline->refcount;
} }
sys_mutex_unlock(&lock); sys_mutex_unlock(&lock);
} }
if (pipeline) { if (tmp) {
dict_set(scope->arena, scope->refs, hash, (u64)pipeline); dict_set(scope->arena, scope->refs, hash, (u64)tmp);
res = tmp;
} }
} }
return pipeline ? pipeline : &g_nil_pipeline; return res;
} }
INTERNAL void pipeline_register(u64 num_pipelines, struct pipeline **pipelines) INTERNAL void pipeline_register(u64 num_pipelines, struct pipeline **pipelines)
@ -1248,6 +1251,7 @@ INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(pipeline_resource_watch_callback, name
for (struct dict_entry *entry = G.top_pipelines->first; entry; entry = entry->next) { for (struct dict_entry *entry = G.top_pipelines->first; entry; entry = entry->next) {
struct pipeline *pipeline = (struct pipeline *)entry->value; struct pipeline *pipeline = (struct pipeline *)entry->value;
if (dict_get(pipeline->dependencies, hash) == 1) { if (dict_get(pipeline->dependencies, hash) == 1) {
logf_debug("Change detected in shader source file \"%F\", recompiling pipeline \"%F\"", FMT_STR(name), FMT_STR(pipeline->name));
*arena_push(scratch.arena, struct pipeline_desc) = pipeline->desc; *arena_push(scratch.arena, struct pipeline_desc) = pipeline->desc;
++num_pipelines; ++num_pipelines;
} }
@ -1257,12 +1261,35 @@ INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(pipeline_resource_watch_callback, name
/* Recompile dirty pipelines */ /* Recompile dirty pipelines */
struct pipeline **pipelines = arena_push_array(scratch.arena, struct pipeline *, num_pipelines); struct pipeline **pipelines = arena_push_array(scratch.arena, struct pipeline *, num_pipelines);
pipeline_alloc_from_descs(num_pipelines, pipeline_descs, 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);
} 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);
}
}
}
sys_mutex_unlock(&lock);
}
pipeline_register(num_pipelines, pipelines); pipeline_register(num_pipelines, pipelines);
scratch_end(scratch); scratch_end(scratch);
#endif
} }
#endif
/* ========================== * /* ========================== *
* Descriptor * Descriptor
@ -1321,7 +1348,6 @@ INTERNAL struct cpu_descriptor_heap *cpu_descriptor_heap_alloc(enum D3D12_DESCRI
if (num_descriptors == 0 || descriptor_size == 0) { if (num_descriptors == 0 || descriptor_size == 0) {
sys_panic(LIT("Unsupported CPU descriptor type")); sys_panic(LIT("Unsupported CPU descriptor type"));
} }
dh->num_descriptors_capacity = num_descriptors; dh->num_descriptors_capacity = num_descriptors;
dh->descriptor_size = descriptor_size; dh->descriptor_size = descriptor_size;
@ -1355,6 +1381,7 @@ struct flow {
/* Below fields are reset each dispatch */ /* Below fields are reset each dispatch */
struct sprite_scope *sprite_scope; struct sprite_scope *sprite_scope;
struct arena *material_instances_arena; struct arena *material_instances_arena;
struct arena *material_grids_arena;
struct flow *next_free; struct flow *next_free;
}; };
@ -1370,40 +1397,73 @@ INTERNAL struct flow *flow_alloc(void)
flow->sprite_scope = sprite_scope_begin(); flow->sprite_scope = sprite_scope_begin();
flow->material_instances_arena = arena_alloc(GIGABYTE(1)); flow->material_instances_arena = arena_alloc(GIGABYTE(1));
flow->material_grids_arena = arena_alloc(GIGABYTE(1));
return flow; return flow;
} }
INTERNAL void flow_reset(struct flow *flow)
{
sprite_scope_end(flow->sprite_scope);
flow->sprite_scope = sprite_scope_begin();
arena_reset(flow->material_instances_arena);
arena_reset(flow->material_grids_arena);
}
struct gp_handle gp_flow_alloc(void) struct gp_handle gp_flow_alloc(void)
{ {
struct flow *flow = flow_alloc(); struct flow *flow = flow_alloc();
return handle_alloc(DX12_HANDLE_KIND_FLOW, flow); return handle_alloc(DX12_HANDLE_KIND_FLOW, flow);
} }
void gp_push_cmd(struct gp_handle gp_flow, struct gp_cmd_params params) void gp_push_cmd(struct gp_handle gp_flow, struct gp_cmd_desc desc)
{ {
struct flow *flow = handle_get_data(gp_flow, DX12_HANDLE_KIND_FLOW); struct flow *flow = handle_get_data(gp_flow, DX12_HANDLE_KIND_FLOW);
if (flow) { if (flow) {
switch (params.kind) { switch (desc.kind) {
default: break; default: break;
case GP_CMD_KIND_DRAW_TEXTURE: case GP_CMD_KIND_DRAW_TEXTURE:
{
i32 texture_id = -1;
{ {
struct dx12_resource *texture = NULL; struct dx12_resource *texture = NULL;
if (params.texture.texture.gen != 0) { if (desc.texture.texture.gen != 0) {
texture = handle_get_data(params.texture.texture, DX12_HANDLE_KIND_RESOURCE); texture = handle_get_data(desc.texture.texture, DX12_HANDLE_KIND_RESOURCE);
} else if (params.texture.sprite.hash != 0) { } else if (desc.texture.sprite.hash != 0) {
struct sprite_texture *st = sprite_texture_from_tag_async(flow->sprite_scope, params.texture.sprite); struct sprite_texture *st = sprite_texture_from_tag_async(flow->sprite_scope, desc.texture.sprite);
texture = handle_get_data(st->texture, DX12_HANDLE_KIND_RESOURCE); texture = handle_get_data(st->texture, DX12_HANDLE_KIND_RESOURCE);
} }
if (texture) { if (texture) {
texture_id = texture->srv_descriptor->index;
}
}
i32 grid_id = -1;
if (desc.texture.grid) {
struct gp_grid_desc *grid_desc = desc.texture.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);
grid->offset = sh_float2_from_v2(grid_desc->offset);
grid->bg0_srgb = sh_uint_from_u32(grid_desc->bg0_color);
grid->bg1_srgb = sh_uint_from_u32(grid_desc->bg1_color);
grid->line_srgb = sh_uint_from_u32(grid_desc->line_color);
grid->x_srgb = sh_uint_from_u32(grid_desc->x_color);
grid->y_srgb = sh_uint_from_u32(grid_desc->y_color);
grid_id = ((u8 *)grid - arena_base(flow->material_grids_arena)) / sizeof(grid);
}
if (texture_id >= 0 || grid_id >= 0) {
struct sh_material_instance *instance = arena_push(flow->material_instances_arena, struct sh_material_instance); struct sh_material_instance *instance = arena_push(flow->material_instances_arena, struct sh_material_instance);
instance->xf = sh_float2x3_from_xform(params.texture.xf); instance->flags = sh_uint_from_u32(SH_MATERIAL_FLAG_NONE);
instance->uv0 = sh_float2_from_v2(params.texture.clip.p0); instance->tex_nurid = sh_int_from_i32(texture_id);
instance->uv1 = sh_float2_from_v2(params.texture.clip.p1); instance->grid_id = sh_int_from_i32(grid_id);
instance->texture_nuri = sh_uint_from_u32(texture->srv_descriptor->index); instance->xf = sh_float2x3_from_xform(desc.texture.xf);
instance->tint_srgb = sh_uint_from_u32(params.texture.tint); instance->uv0 = sh_float2_from_v2(desc.texture.clip.p0);
instance->emittance = sh_float_from_f32(params.texture.emittance); 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);
} }
} break; } break;
} }
@ -2173,8 +2233,9 @@ void gp_dispatch(struct gp_dispatch_params params)
quad_index_buffer_view.Format = DXGI_FORMAT_R16_UINT; quad_index_buffer_view.Format = DXGI_FORMAT_R16_UINT;
quad_index_buffer_view.SizeInBytes = sizeof(quad_indices); quad_index_buffer_view.SizeInBytes = sizeof(quad_indices);
/* Upload instance buffer */ /* Upload buffers */
struct command_buffer *instance_buffer = command_list_push_buffer(cl, STRING_FROM_ARENA(flow->material_instances_arena)); 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 */ /* Upload descriptor heap */
struct command_descriptor_heap *descriptor_heap = command_list_push_descriptor_heap(cl, G.cbv_srv_uav_heap); struct command_descriptor_heap *descriptor_heap = command_list_push_descriptor_heap(cl, G.cbv_srv_uav_heap);
@ -2211,10 +2272,13 @@ void gp_dispatch(struct gp_dispatch_params params)
/* Bind instance buffer */ /* Bind instance buffer */
ID3D12GraphicsCommandList_SetGraphicsRootShaderResourceView(cl->cl, 1, instance_buffer->resource->gpu_address); 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 */ /* Bind descriptor heap */
ID3D12DescriptorHeap *heaps[] = { descriptor_heap->heap }; ID3D12DescriptorHeap *heaps[] = { descriptor_heap->heap };
ID3D12GraphicsCommandList_SetDescriptorHeaps(cl->cl, ARRAY_COUNT(heaps), heaps); ID3D12GraphicsCommandList_SetDescriptorHeaps(cl->cl, ARRAY_COUNT(heaps), heaps);
ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(cl->cl, 2, descriptor_heap->gp_handle); ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(cl->cl, 3, descriptor_heap->gp_handle);
/* Setup Rasterizer State */ /* Setup Rasterizer State */
D3D12_VIEWPORT viewport = viewport_from_rect(params.draw_target_viewport); D3D12_VIEWPORT viewport = viewport_from_rect(params.draw_target_viewport);
@ -2237,12 +2301,7 @@ void gp_dispatch(struct gp_dispatch_params params)
command_list_close(cl); command_list_close(cl);
} }
pipeline_scope_end(pipeline_scope); pipeline_scope_end(pipeline_scope);
flow_reset(flow);
/* Reset flow */
sprite_scope_end(flow->sprite_scope);
flow->sprite_scope = sprite_scope_begin();
arena_reset(flow->material_instances_arena);
} }
/* ========================== * /* ========================== *
@ -2447,7 +2506,8 @@ INTERNAL void present_blit(struct dx12_resource *dst, struct dx12_resource *src,
/* Set root constants */ /* Set root constants */
struct sh_blit_constants constants = ZI; struct sh_blit_constants constants = ZI;
constants.projection = sh_float4x4_from_mat4x4(vp_matrix); constants.projection = sh_float4x4_from_mat4x4(vp_matrix);
constants.texture_id = sh_uint_from_u32(src->srv_descriptor->index); constants.tex_urid = sh_uint_from_u32(src->srv_descriptor->index);
constants.gamma = sh_float_from_f32(2.2);
command_list_set_root_constant(cl, &constants, sizeof(constants)); command_list_set_root_constant(cl, &constants, sizeof(constants));
/* Bind descriptor heap */ /* Bind descriptor heap */

View File

@ -2088,7 +2088,7 @@ void sys_message_box(enum sys_message_box_kind kind, struct string message)
} break; } break;
} }
//logf_info("Showing message box: \"%F\"", FMT_STR(message)); logf_info("Showing message box kind %F with text \"%F\"", FMT_SINT(kind), FMT_STR(message));
MessageBoxExW(NULL, message_wstr, title, mbox_type, 0); MessageBoxExW(NULL, message_wstr, title, mbox_type, 0);
scratch_end(scratch); scratch_end(scratch);

View File

@ -1060,7 +1060,7 @@ INTERNAL void user_update(void)
{ {
struct v2 pos = xform_invert_mul_v2(G.world_to_user_xf, V2(0, 0)); 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 v2 size = xform_basis_invert_mul_v2(G.world_to_user_xf, G.user_size);
struct gp_cmd_params cmd = ZI; struct gp_cmd_desc cmd = ZI;
cmd.kind = GP_CMD_KIND_TEST; cmd.kind = GP_CMD_KIND_TEST;
cmd.test.xf = xform_from_rect(RECT_FROM_V2(pos, size)); cmd.test.xf = xform_from_rect(RECT_FROM_V2(pos, size));
gp_push_cmd(G.world_gp_flow, cmd); gp_push_cmd(G.world_gp_flow, cmd);