From 0473aec335d68c016e241420f5234bd425c3cc0a Mon Sep 17 00:00:00 2001 From: Robert Konrad Date: Sat, 21 Sep 2024 15:35:51 +0200 Subject: [PATCH] Support multiple vertex input structs --- Sources/backends/hlsl.c | 57 +++++++++++++++++++++++++++++++---------- Sources/functions.c | 1 + Sources/functions.h | 1 + Sources/parser.c | 22 +++++++++++++--- 4 files changed, 64 insertions(+), 17 deletions(-) diff --git a/Sources/backends/hlsl.c b/Sources/backends/hlsl.c index 3d55acc..7dd6440 100644 --- a/Sources/backends/hlsl.c +++ b/Sources/backends/hlsl.c @@ -129,8 +129,17 @@ static void write_bytecode(char *hlsl, char *directory, const char *filename, co } } -static void write_types(char *hlsl, size_t *offset, shader_stage stage, type_id input, type_id output, function *main, function **rayshaders, - size_t rayshaders_count) { +static bool is_input(type_id t, type_id inputs[64], size_t inputs_count) { + for (size_t input_index = 0; input_index < inputs_count; ++input_index) { + if (inputs[input_index] == t) { + return true; + } + } + return false; +} + +static void write_types(char *hlsl, size_t *offset, shader_stage stage, type_id inputs[64], size_t inputs_count, type_id output, function *main, + function **rayshaders, size_t rayshaders_count) { type_id types[256]; size_t types_size = 0; if (main != NULL) { @@ -140,15 +149,32 @@ static void write_types(char *hlsl, size_t *offset, shader_stage stage, type_id find_referenced_types(rayshaders[rayshader_index], types, &types_size); } + size_t input_offsets[64]; + input_offsets[0] = 0; + + for (size_t input_index = 0; input_index < inputs_count - 1; ++input_index) { + type *t = get_type(inputs[input_index]); + input_offsets[input_index + 1] = input_offsets[input_index] + t->members.size; + } + for (size_t i = 0; i < types_size; ++i) { type *t = get_type(types[i]); if (!t->built_in && !has_attribute(&t->attributes, add_name("pipe"))) { *offset += sprintf(&hlsl[*offset], "struct %s {\n", get_name(t->name)); - if (stage == SHADER_STAGE_VERTEX && types[i] == input) { + if (stage == SHADER_STAGE_VERTEX && is_input(types[i], inputs, inputs_count)) { + size_t input_offset = 0; + for (size_t input_index = 0; input_index < inputs_count; ++input_index) { + if (types[i] == inputs[input_index]) { + input_offset = input_offsets[input_index]; + break; + } + } + for (size_t j = 0; j < t->members.size; ++j) { - *offset += sprintf(&hlsl[*offset], "\t%s %s : TEXCOORD%zu;\n", type_string(t->members.m[j].type.type), get_name(t->members.m[j].name), j); + *offset += sprintf(&hlsl[*offset], "\t%s %s : TEXCOORD%zu;\n", type_string(t->members.m[j].type.type), get_name(t->members.m[j].name), + j + input_offset); } } else if (stage == SHADER_STAGE_VERTEX && types[i] == output) { @@ -173,7 +199,7 @@ static void write_types(char *hlsl, size_t *offset, shader_stage stage, type_id } } } - else if (stage == SHADER_STAGE_FRAGMENT && types[i] == input) { + else if (stage == SHADER_STAGE_FRAGMENT && types[i] == inputs[0]) { for (size_t j = 0; j < t->members.size; ++j) { if (j == 0) { *offset += sprintf(&hlsl[*offset], "\t%s %s : SV_POSITION;\n", type_string(t->members.m[j].type.type), get_name(t->members.m[j].name)); @@ -554,6 +580,7 @@ static void write_functions(char *hlsl, size_t *offset, shader_stage stage, func for (size_t i = 0; i < functions_size; ++i) { function *f = functions[i]; + assert(f != NULL); debug_context context = {0}; check(f->block != NULL, context, "Function block missing"); @@ -1055,14 +1082,17 @@ static void hlsl_export_vertex(char *directory, api_kind d3d, function *main) { size_t offset = 0; assert(main->parameters_size > 0); - type_id vertex_input = main->parameter_types[0].type; + type_id vertex_inputs[64]; + for (size_t input_index = 0; input_index < main->parameters_size; ++input_index) { + vertex_inputs[input_index] = main->parameter_types[input_index].type; + } type_id vertex_output = main->return_type.type; debug_context context = {0}; - check(vertex_input != NO_TYPE, context, "vertex input missing"); + check(main->parameters_size > 0, context, "vertex input missing"); check(vertex_output != NO_TYPE, context, "vertex output missing"); - write_types(hlsl, &offset, SHADER_STAGE_VERTEX, vertex_input, vertex_output, main, NULL, 0); + write_types(hlsl, &offset, SHADER_STAGE_VERTEX, vertex_inputs, main->parameters_size, vertex_output, main, NULL, 0); write_globals(hlsl, &offset, main, NULL, 0); @@ -1101,7 +1131,7 @@ static void hlsl_export_amplification(char *directory, function *main) { char *hlsl = (char *)calloc(1024 * 1024, 1); size_t offset = 0; - write_types(hlsl, &offset, SHADER_STAGE_AMPLIFICATION, NO_TYPE, NO_TYPE, main, NULL, 0); + write_types(hlsl, &offset, SHADER_STAGE_AMPLIFICATION, NULL, 0, NO_TYPE, main, NULL, 0); write_globals(hlsl, &offset, main, NULL, 0); @@ -1134,9 +1164,10 @@ static void hlsl_export_mesh(char *directory, function *main) { debug_context context = {0}; error(context, "Mesh function requires a vertices attribute with two parameters"); } + assert(vertices_attribute != NULL); type_id vertex_output = (type_id)vertices_attribute->parameters[1]; - write_types(hlsl, &offset, SHADER_STAGE_MESH, NO_TYPE, vertex_output, main, NULL, 0); + write_types(hlsl, &offset, SHADER_STAGE_MESH, NULL, 0, vertex_output, main, NULL, 0); write_globals(hlsl, &offset, main, NULL, 0); @@ -1170,7 +1201,7 @@ static void hlsl_export_fragment(char *directory, api_kind d3d, function *main) debug_context context = {0}; check(pixel_input != NO_TYPE, context, "fragment input missing"); - write_types(hlsl, &offset, SHADER_STAGE_FRAGMENT, pixel_input, NO_TYPE, main, NULL, 0); + write_types(hlsl, &offset, SHADER_STAGE_FRAGMENT, &pixel_input, 1, NO_TYPE, main, NULL, 0); write_globals(hlsl, &offset, main, NULL, 0); @@ -1209,7 +1240,7 @@ static void hlsl_export_compute(char *directory, api_kind d3d, function *main) { char *hlsl = (char *)calloc(1024 * 1024, 1); size_t offset = 0; - write_types(hlsl, &offset, SHADER_STAGE_COMPUTE, NO_TYPE, NO_TYPE, main, NULL, 0); + write_types(hlsl, &offset, SHADER_STAGE_COMPUTE, NULL, 0, NO_TYPE, main, NULL, 0); write_globals(hlsl, &offset, main, NULL, 0); @@ -1298,7 +1329,7 @@ static void hlsl_export_all_ray_shaders(char *directory) { return; } - write_types(hlsl, &offset, SHADER_STAGE_RAY_GENERATION, NO_TYPE, NO_TYPE, NULL, all_rayshaders, all_rayshaders_size); + write_types(hlsl, &offset, SHADER_STAGE_RAY_GENERATION, NULL, 0, NO_TYPE, NULL, all_rayshaders, all_rayshaders_size); write_globals(hlsl, &offset, NULL, all_rayshaders, all_rayshaders_size); diff --git a/Sources/functions.c b/Sources/functions.c index a117170..f18274c 100644 --- a/Sources/functions.c +++ b/Sources/functions.c @@ -660,6 +660,7 @@ function_id add_function(name_id name) { functions[f].attributes.attributes_count = 0; init_type_ref(&functions[f].return_type, NO_NAME); functions[f].parameters_size = 0; + memset(functions[f].parameter_attributes, 0, sizeof(functions[f].parameter_attributes)); functions[f].block = NULL; memset(functions[f].code.o, 0, sizeof(functions[f].code.o)); functions[f].code.size = 0; diff --git a/Sources/functions.h b/Sources/functions.h index 1b48485..f7ff6a8 100644 --- a/Sources/functions.h +++ b/Sources/functions.h @@ -16,6 +16,7 @@ typedef struct function { type_ref return_type; name_id parameter_names[256]; type_ref parameter_types[256]; + name_id parameter_attributes[256]; uint8_t parameters_size; struct statement *block; diff --git a/Sources/parser.c b/Sources/parser.c index a809e8a..f05f236 100644 --- a/Sources/parser.c +++ b/Sources/parser.c @@ -1066,12 +1066,25 @@ static definition parse_function(state_t *state) { advance_state(state); uint8_t parameters_size = 0; - token param_names[256] = {0}; + name_id param_names[256] = {0}; type_ref param_types[256] = {0}; + name_id param_attributes[256] = {0}; while (current(state).kind != TOKEN_RIGHT_PAREN) { + if (current(state).kind == TOKEN_HASH) { + advance_state(state); + match_token(state, TOKEN_LEFT_SQUARE, "Expected an opening square bracket"); + advance_state(state); + match_token(state, TOKEN_IDENTIFIER, "Expected an identifier"); + token attribute_name = current(state); + param_attributes[parameters_size] = attribute_name.identifier; + advance_state(state); + match_token(state, TOKEN_RIGHT_SQUARE, "Expected a closing square bracket"); + advance_state(state); + } + match_token(state, TOKEN_IDENTIFIER, "Expected an identifier"); - param_names[parameters_size] = current(state); + param_names[parameters_size] = current(state).identifier; advance_state(state); match_token(state, TOKEN_COLON, "Expected a colon"); advance_state(state); @@ -1098,8 +1111,9 @@ static definition parse_function(state_t *state) { f->return_type = return_type; f->parameters_size = parameters_size; for (uint8_t parameter_index = 0; parameter_index < parameters_size; ++parameter_index) { - f->parameter_names[parameter_index] = param_names[parameter_index].identifier; + f->parameter_names[parameter_index] = param_names[parameter_index]; f->parameter_types[parameter_index] = param_types[parameter_index]; + f->parameter_attributes[parameter_index] = param_attributes[parameter_index]; } f->block = block; @@ -1136,7 +1150,7 @@ static definition parse_const(state_t *state, attribute_list attributes) { match_token(state, TOKEN_SEMICOLON, "Expected a semicolon"); advance_state(state); - definition d; + definition d = {0}; if (type_name == NO_NAME) { debug_context context = {0};