use root constants
This commit is contained in:
parent
ccf47c03f6
commit
01aff521da
@ -6,8 +6,8 @@
|
||||
#define DECL(t, n) t n : n
|
||||
#define NURI(i) NonUniformResourceIndex(i)
|
||||
|
||||
#ifdef INTELLISENSE
|
||||
# define INLINE
|
||||
#if !SH_CPU
|
||||
# define INLINE /* For intellisense */
|
||||
#endif
|
||||
|
||||
/* Linear color from normalized sRGB */
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
* ========================== */
|
||||
|
||||
#define ROOTSIG \
|
||||
"CBV(b0), " \
|
||||
"RootConstants(num32BitConstants=16, b0), " \
|
||||
"SRV(t0), " \
|
||||
"DescriptorTable(SRV(t1, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE)), " \
|
||||
"StaticSampler(s0, " \
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#define SH_STRUCT(s) PACK(struct s)
|
||||
#define SH_DECL(t, n) struct CAT(sh_, t) n
|
||||
#define SH_ENTRY(rootsig) static
|
||||
#define SH_ASSERT_32BIT(s, n) CT_ASSERT((sizeof(s) / 4) == n)
|
||||
|
||||
struct sh_uint { u32 v; };
|
||||
INLINE struct sh_uint sh_uint_from_u32(u32 v)
|
||||
@ -45,6 +46,7 @@ INLINE struct sh_float2x3 sh_float2x3_from_xform(struct xform v)
|
||||
#define SH_STRUCT(s) struct s
|
||||
#define SH_DECL(t, n) t n
|
||||
#define SH_ENTRY(rootsig) [RootSignature(rootsig)]
|
||||
#define SH_ASSERT_32BIT(s, n)
|
||||
|
||||
#endif
|
||||
|
||||
@ -55,6 +57,7 @@ INLINE struct sh_float2x3 sh_float2x3_from_xform(struct xform v)
|
||||
SH_STRUCT(sh_material_constants {
|
||||
SH_DECL(float4x4, projection);
|
||||
});
|
||||
SH_ASSERT_32BIT(struct sh_material_constants, 16); /* Expected 32bit root constant size in shader */
|
||||
|
||||
SH_STRUCT(sh_material_instance {
|
||||
SH_DECL(float2x3, xf);
|
||||
|
||||
223
src/gp_dx12.c
223
src/gp_dx12.c
@ -72,20 +72,24 @@ struct pipeline_desc {
|
||||
};
|
||||
|
||||
struct pipeline {
|
||||
b32 valid;
|
||||
|
||||
struct arena *arena;
|
||||
struct string name;
|
||||
|
||||
u32 num_errors;
|
||||
struct pipeline_error *first_error;
|
||||
struct pipeline_error *last_error;
|
||||
i64 compilation_time;
|
||||
|
||||
struct pipeline_desc desc;
|
||||
ID3D12PipelineState *pso;
|
||||
ID3D12RootSignature *rootsig;
|
||||
};
|
||||
|
||||
struct pipeline_result {
|
||||
struct pipeline pipeline;
|
||||
i64 elapsed;
|
||||
u64 errors_text_len;
|
||||
u8 errors_text[KILOBYTE(16)];
|
||||
};
|
||||
|
||||
struct pipeline_error {
|
||||
struct string msg;
|
||||
struct pipeline_error *next;
|
||||
};
|
||||
|
||||
struct command_queue {
|
||||
@ -236,22 +240,10 @@ GLOBAL struct {
|
||||
struct arena *resources_arena;
|
||||
struct dx12_resource *first_free_resource;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* FIXME: Remove this (testing) */
|
||||
struct pipeline test_pipeline;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Pipeline cache */
|
||||
struct sys_mutex *pipelines_mutex;
|
||||
struct arena *pipelines_arena;
|
||||
struct dict *pipelines_dict;
|
||||
|
||||
/* Factory */
|
||||
IDXGIFactory6 *factory;
|
||||
@ -298,6 +290,10 @@ INTERNAL struct command_queue *command_queue_alloc(enum D3D12_COMMAND_LIST_TYPE
|
||||
INTERNAL void command_queue_release(struct command_queue *cq);
|
||||
INTERNAL void dx12_resource_release(struct dx12_resource *resource);
|
||||
|
||||
#if RESOURCE_RELOADING
|
||||
INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(pipeline_resource_watch_callback, name);
|
||||
#endif
|
||||
|
||||
struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr)
|
||||
{
|
||||
__prof;
|
||||
@ -319,12 +315,20 @@ struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr)
|
||||
G.resources_mutex = sys_mutex_alloc();
|
||||
G.resources_arena = arena_alloc(GIGABYTE(64));
|
||||
|
||||
/* Initialize pipeline cache */
|
||||
G.pipelines_mutex = sys_mutex_alloc();
|
||||
G.pipelines_arena = arena_alloc(GIGABYTE(64));
|
||||
G.pipelines_dict = dict_init(G.pipelines_arena, 1024);
|
||||
|
||||
/* Initialize dx12 */
|
||||
dx12_init_device();
|
||||
dx12_init_objects();
|
||||
dx12_init_pipelines();
|
||||
|
||||
/* Register callbacks */
|
||||
#if RESOURCE_RELOADING
|
||||
resource_register_watch_callback(pipeline_resource_watch_callback);
|
||||
#endif
|
||||
app_register_exit_callback(gp_shutdown);
|
||||
|
||||
struct gp_startup_receipt res = ZI;
|
||||
@ -630,35 +634,35 @@ PACK(struct fx_material_instance {
|
||||
/* ============= */
|
||||
/* Init pipelines */
|
||||
|
||||
INTERNAL struct pipeline_result *pipeline_alloc_from_descs(struct arena *arena, u64 num_pipelines, struct pipeline_desc *descs);
|
||||
INTERNAL void pipeline_release(struct pipeline *pipeline);
|
||||
|
||||
INTERNAL void dx12_init_pipelines(void)
|
||||
{
|
||||
__prof;
|
||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
||||
struct pipeline_desc pipeline_descs[] = {
|
||||
INTERNAL READONLY struct pipeline g_nil_pipeline = ZI;
|
||||
INTERNAL READONLY struct pipeline_desc g_pipeline_descs[] = {
|
||||
/* Material pipeline */
|
||||
{
|
||||
.name = "material",
|
||||
.vs = { "sh/material.hlsl", "vs" },
|
||||
.ps = { "sh/material.hlsl", "ps" }
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
struct pipeline_result *results = pipeline_alloc_from_descs(scratch.arena, ARRAY_COUNT(pipeline_descs), pipeline_descs);
|
||||
for (u64 i = 0; i < ARRAY_COUNT(pipeline_descs); ++i) {
|
||||
struct pipeline_result *result = &results[i];
|
||||
if (result->errors_text_len > 0) {
|
||||
struct string msg = STRING(result->errors_text_len, result->errors_text);
|
||||
sys_panic(msg);
|
||||
pipeline_release(&result->pipeline);
|
||||
INTERNAL struct pipeline **pipeline_alloc_from_descs(struct arena *arena, u64 num_pipelines, struct pipeline_desc *descs);
|
||||
INTERNAL void pipeline_release(struct pipeline *pipeline);
|
||||
INTERNAL void pipeline_register(struct pipeline *pipeline);
|
||||
|
||||
INTERNAL void dx12_init_pipelines(void)
|
||||
{
|
||||
__prof;
|
||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
||||
struct pipeline **pipelines = pipeline_alloc_from_descs(scratch.arena, ARRAY_COUNT(g_pipeline_descs), g_pipeline_descs);
|
||||
for (u64 i = 0; i < ARRAY_COUNT(g_pipeline_descs); ++i) {
|
||||
struct pipeline *pipeline = pipelines[i];
|
||||
if (pipeline->num_errors > 0) {
|
||||
sys_panic(pipeline->first_error->msg);
|
||||
pipeline_release(pipeline);
|
||||
} else {
|
||||
/* FIXME: remove this */
|
||||
G.test_pipeline = result->pipeline;
|
||||
pipeline->valid = true;
|
||||
pipeline_register(pipeline);
|
||||
}
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
@ -838,7 +842,6 @@ INTERNAL WORK_TASK_FUNC_DEF(shader_compile_task, comp_arg_raw)
|
||||
|
||||
struct pipeline_load_task_arg {
|
||||
struct pipeline *pipeline;
|
||||
struct pipeline_result *result;
|
||||
};
|
||||
|
||||
INTERNAL WORK_TASK_FUNC_DEF(pipeline_load_task, load_arg_raw)
|
||||
@ -847,12 +850,11 @@ INTERNAL WORK_TASK_FUNC_DEF(pipeline_load_task, load_arg_raw)
|
||||
struct pipeline_load_task_arg *load_arg = (struct pipeline_load_task_arg *)load_arg_raw;
|
||||
struct pipeline *pipeline = load_arg->pipeline;
|
||||
struct pipeline_desc desc = pipeline->desc;
|
||||
struct pipeline_result *result = load_arg->result;
|
||||
|
||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
||||
{
|
||||
i64 start_ns = sys_time_ns();
|
||||
struct string pipeline_name = string_from_cstr_no_limit(desc.name);
|
||||
struct string pipeline_name = pipeline->name;
|
||||
logf_info("Loading pipeline \"%F\"", FMT_STR(pipeline_name));
|
||||
b32 success = true;
|
||||
HRESULT hr = 0;
|
||||
@ -1040,13 +1042,20 @@ INTERNAL WORK_TASK_FUNC_DEF(pipeline_load_task, load_arg_raw)
|
||||
error_str = error_blob_str;
|
||||
}
|
||||
}
|
||||
result->errors_text_len = min_u64(error_str.len, ARRAY_COUNT(result->errors_text));
|
||||
MEMCPY(result->errors_text, error_str.text, result->errors_text_len);
|
||||
struct pipeline_error *error = arena_push(pipeline->arena, struct pipeline_error);
|
||||
error->msg = string_copy(pipeline->arena, error_str);
|
||||
if (pipeline->last_error) {
|
||||
pipeline->last_error->next = error;
|
||||
} else {
|
||||
pipeline->first_error = error;
|
||||
}
|
||||
pipeline->last_error = error;
|
||||
++pipeline->num_errors;
|
||||
}
|
||||
|
||||
pipeline->pso = pso;
|
||||
pipeline->rootsig = rootsig;
|
||||
result->elapsed = sys_time_ns() - start_ns;
|
||||
pipeline->compilation_time = sys_time_ns() - start_ns;
|
||||
|
||||
resource_close(&vs_res);
|
||||
if (!ps_res_is_shared) {
|
||||
@ -1071,30 +1080,35 @@ INTERNAL WORK_TASK_FUNC_DEF(pipeline_load_task, load_arg_raw)
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
INTERNAL struct pipeline_result *pipeline_alloc_from_descs(struct arena *arena, u64 num_pipelines, struct pipeline_desc *descs)
|
||||
INTERNAL struct pipeline **pipeline_alloc_from_descs(struct arena *arena, u64 num_pipelines, struct pipeline_desc *descs)
|
||||
{
|
||||
__prof;
|
||||
struct pipeline_result *results = arena_push_array(arena, struct pipeline_result, num_pipelines);
|
||||
struct pipeline **pipelines = arena_push_array(arena, struct pipeline *, num_pipelines);
|
||||
struct pipeline_load_task_arg *task_args = arena_push_array(arena, struct pipeline_load_task_arg, num_pipelines);
|
||||
|
||||
/* Load pipelines */
|
||||
struct work_slate ws = work_slate_begin();
|
||||
for (u64 i = 0; i < num_pipelines; ++i) {
|
||||
struct pipeline_result *result = &results[i];
|
||||
|
||||
struct pipeline *pipeline = &results->pipeline;
|
||||
pipeline->desc = descs[i];
|
||||
struct pipeline_desc desc = descs[i];
|
||||
struct pipeline *pipeline = NULL;
|
||||
{
|
||||
struct arena *pipeline_arena = arena_alloc(MEGABYTE(64));
|
||||
pipeline = arena_push(pipeline_arena, struct pipeline);
|
||||
pipeline->arena = pipeline_arena;
|
||||
pipelines[i] = pipeline;
|
||||
}
|
||||
pipeline->desc = desc;
|
||||
pipeline->name = string_copy(pipeline->arena, string_from_cstr_no_limit(desc.name));
|
||||
|
||||
struct pipeline_load_task_arg *arg = &task_args[i];
|
||||
arg->pipeline = pipeline;
|
||||
arg->result = result;
|
||||
|
||||
work_slate_push_task(&ws, pipeline_load_task, arg);
|
||||
}
|
||||
struct work_handle work = work_slate_end_and_help(&ws, WORK_PRIORITY_HIGH);
|
||||
work_wait(work);
|
||||
|
||||
return results;
|
||||
return pipelines;
|
||||
}
|
||||
|
||||
INTERNAL void pipeline_release(struct pipeline *pipeline)
|
||||
@ -1103,8 +1117,66 @@ INTERNAL void pipeline_release(struct pipeline *pipeline)
|
||||
if (pipeline->pso) {
|
||||
ID3D12PipelineState_Release(pipeline->pso);
|
||||
}
|
||||
arena_release(pipeline->arena);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Pipeline cache
|
||||
* ========================== */
|
||||
|
||||
struct pipeline_scope {
|
||||
i32 _;
|
||||
};
|
||||
|
||||
INTERNAL struct pipeline_scope *pipeline_scope_begin(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INTERNAL void pipeline_scope_end(struct pipeline_scope *scope)
|
||||
{
|
||||
(UNUSED)scope;
|
||||
}
|
||||
|
||||
INTERNAL struct pipeline *pipeline_from_name(struct pipeline_scope *scope, struct string name)
|
||||
{
|
||||
(UNUSED)scope;
|
||||
|
||||
struct pipeline *pipeline = &g_nil_pipeline;
|
||||
u64 hash = hash_fnv64(HASH_FNV64_BASIS, name);
|
||||
struct sys_lock lock = sys_mutex_lock_s(G.pipelines_mutex);
|
||||
{
|
||||
struct pipeline *res = dict_get(G.pipelines_dict, hash);
|
||||
if (res) {
|
||||
pipeline = res;
|
||||
}
|
||||
}
|
||||
sys_mutex_unlock(&lock);
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
INTERNAL void pipeline_register(struct pipeline *pipeline)
|
||||
{
|
||||
u64 hash = hash_fnv64(HASH_FNV64_BASIS, pipeline->name);
|
||||
struct sys_lock lock = sys_mutex_lock_e(G.pipelines_mutex);
|
||||
{
|
||||
dict_set(G.pipelines_arena, G.pipelines_dict, hash, pipeline);
|
||||
}
|
||||
sys_mutex_unlock(&lock);
|
||||
}
|
||||
|
||||
#if RESOURCE_RELOADING
|
||||
INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(pipeline_resource_watch_callback, name)
|
||||
{
|
||||
#if 0
|
||||
if (shader_set_dirty(name)) {
|
||||
logf_debug("Shader source file \"%F\" has changed", FMT_STR(name));
|
||||
}
|
||||
#else
|
||||
(UNUSED)name;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ========================== *
|
||||
* Descriptor
|
||||
@ -1771,6 +1843,25 @@ INTERNAL struct command_buffer *command_list_push_buffer(struct command_list *cl
|
||||
return cb;
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Command root constant
|
||||
* ========================== */
|
||||
|
||||
INTERNAL void command_list_set_root_constant(struct command_list *cl, void *src, u32 size)
|
||||
{
|
||||
if (size % 4 == 0) {
|
||||
u32 num32bit = size / 4;
|
||||
for (u32 i = 0; i < num32bit; ++i) {
|
||||
u32 val = 0;
|
||||
MEMCPY(&val, (((u32 *)src) + i), 4);
|
||||
ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstant(cl->cl, 0, val, i);
|
||||
}
|
||||
} else {
|
||||
/* Root constant structs must pad to 32 bits */
|
||||
ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Texture
|
||||
* ========================== */
|
||||
@ -1960,7 +2051,9 @@ void gp_dispatch(struct gp_dispatch_params params)
|
||||
|
||||
struct flow *flow = handle_get_data(params.flow, DX12_HANDLE_KIND_FLOW);
|
||||
|
||||
/* Material pass */
|
||||
struct pipeline_scope *pipeline_scope = pipeline_scope_begin();
|
||||
struct pipeline *material_pipeline = pipeline_from_name(pipeline_scope, LIT("material"));
|
||||
if (material_pipeline->valid) {
|
||||
struct command_list *cl = command_list_open(G.cq_direct);
|
||||
{
|
||||
struct dx12_resource *target = handle_get_data(params.draw_target, DX12_HANDLE_KIND_RESOURCE);
|
||||
@ -2019,20 +2112,16 @@ void gp_dispatch(struct gp_dispatch_params params)
|
||||
|
||||
/* Material pass */
|
||||
{
|
||||
//struct pipeline *pipeline = dx12_get_pipeline(pipeline_scope, LIT("material"));
|
||||
struct pipeline *pipeline = &G.test_pipeline;
|
||||
u32 instance_count = instance_buffer->size / sizeof(struct sh_material_instance);
|
||||
|
||||
/* Bind pipeline */
|
||||
ID3D12GraphicsCommandList_SetPipelineState(cl->cl, pipeline->pso);
|
||||
ID3D12GraphicsCommandList_SetGraphicsRootSignature(cl->cl, pipeline->rootsig);
|
||||
ID3D12GraphicsCommandList_SetPipelineState(cl->cl, material_pipeline->pso);
|
||||
ID3D12GraphicsCommandList_SetGraphicsRootSignature(cl->cl, material_pipeline->rootsig);
|
||||
|
||||
/* Fill & bind constant buffer */
|
||||
/* TODO: Move into root constant */
|
||||
/* Set root constants */
|
||||
struct sh_material_constants constants = ZI;
|
||||
constants.projection = sh_float4x4_from_mat4x4(vp_matrix);
|
||||
struct command_buffer *constant_buffer = command_list_push_buffer(cl, STRING_FROM_STRUCT(&constants));
|
||||
ID3D12GraphicsCommandList_SetGraphicsRootConstantBufferView(cl->cl, 0, constant_buffer->resource->gpu_address);
|
||||
command_list_set_root_constant(cl, &constants, sizeof(constants));
|
||||
|
||||
/* Bind instance buffer */
|
||||
ID3D12GraphicsCommandList_SetGraphicsRootShaderResourceView(cl->cl, 1, instance_buffer->resource->gpu_address);
|
||||
@ -2059,11 +2148,14 @@ void gp_dispatch(struct gp_dispatch_params params)
|
||||
}
|
||||
}
|
||||
command_list_close(cl);
|
||||
}
|
||||
pipeline_scope_end(pipeline_scope);
|
||||
|
||||
/* Reset flow */
|
||||
sprite_scope_end(flow->sprite_scope);
|
||||
flow->sprite_scope = sprite_scope_begin();
|
||||
arena_reset(flow->material_instances_arena);
|
||||
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
@ -2256,6 +2348,7 @@ void gp_present(struct sys_window *window, struct v2i32 backbuffer_resolution, s
|
||||
//sys_sleep(0.1);
|
||||
|
||||
/* Present */
|
||||
/* FIXME: Resource barrier */
|
||||
HRESULT hr = IDXGISwapChain3_Present(G.swapchain, 0, 0);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
ASSERT(false);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user