From 5f2220d6243a020bb1c0665b820f35f0970d8503 Mon Sep 17 00:00:00 2001 From: Robert Konrad <git2016@robdangero.us> Date: Sat, 24 Aug 2024 22:31:30 +0200 Subject: [PATCH] Support const floats --- Sources/backends/hlsl.c | 13 +++++- Sources/compiler.c | 2 +- Sources/functions.c | 55 +++++++++++++++++++++++++ Sources/globals.c | 82 +++++++++++++++++++++++++------------ Sources/globals.h | 24 ++++++++++- Sources/integrations/kinc.c | 14 +++---- Sources/kong.c | 6 +++ Sources/parser.c | 76 +++++++++++++++++++++++++++++++++- Sources/parser.h | 2 +- 9 files changed, 234 insertions(+), 40 deletions(-) diff --git a/Sources/backends/hlsl.c b/Sources/backends/hlsl.c index 2665891..668517b 100644 --- a/Sources/backends/hlsl.c +++ b/Sources/backends/hlsl.c @@ -259,6 +259,18 @@ static void write_globals(char *hlsl, size_t *offset, function *main, function * *offset += sprintf(&hlsl[*offset], "TextureCube<float4> _%" PRIu64 " : register(t%i);\n\n", g.var_index, register_index); } else if (g.type == float_id) { + *offset += sprintf(&hlsl[*offset], "static const float _%" PRIu64 " = %f;\n\n", g.var_index, g.value.value.floats[0]); + } + else if (g.type == float2_id) { + *offset += sprintf(&hlsl[*offset], "static const float2 _%" PRIu64 " = float2(%f, %f);\n\n", g.var_index, g.value.value.floats[0], g.value.value.floats[1]); + } + else if (g.type == float3_id) { + *offset += sprintf(&hlsl[*offset], "static const float3 _%" PRIu64 " = float3(%f, %f, %f);\n\n", g.var_index, g.value.value.floats[0], + g.value.value.floats[1], g.value.value.floats[2]); + } + else if (g.type == float4_id) { + *offset += sprintf(&hlsl[*offset], "static const float4 _%" PRIu64 " = float4(%f, %f, %f, %f);\n\n", g.var_index, g.value.value.floats[0], + g.value.value.floats[1], g.value.value.floats[2], g.value.value.floats[3]); } else { *offset += sprintf(&hlsl[*offset], "cbuffer _%" PRIu64 " : register(b%i) {\n", g.var_index, register_index); @@ -468,7 +480,6 @@ static void write_functions(char *hlsl, size_t *offset, shader_stage stage, func } else if (parameter_index == 1) { *offset += sprintf(&hlsl[*offset], ", BuiltInTriangleIntersectionAttributes _kong_triangle_intersection_attributes"); - //type_string(f->parameter_types[parameter_index].type), parameter_ids[parameter_index]); } else { *offset += sprintf(&hlsl[*offset], ", %s _%" PRIu64, type_string(f->parameter_types[parameter_index].type), parameter_ids[parameter_index]); diff --git a/Sources/compiler.c b/Sources/compiler.c index 58292cb..8ac4817 100644 --- a/Sources/compiler.c +++ b/Sources/compiler.c @@ -429,7 +429,7 @@ variable emit_expression(opcodes *code, block *parent, expression *e) { case EXPRESSION_CALL: { type_ref t; init_type_ref(&t, NO_NAME); - t.type = float4_id; + t.type = e->type.type; variable v = allocate_variable(t, VARIABLE_LOCAL); opcode o; diff --git a/Sources/functions.c b/Sources/functions.c index baf1294..3a98209 100644 --- a/Sources/functions.c +++ b/Sources/functions.c @@ -15,6 +15,52 @@ function_id float2_constructor_id; function_id float3_constructor_id; function_id float4_constructor_id; +static void add_func_int(char *name) { + function_id func = add_function(add_name(name)); + function *f = get_function(func); + init_type_ref(&f->return_type, add_name("int")); + f->return_type.type = find_type_by_ref(&f->return_type); + f->parameters_size = 0; + f->block = NULL; +} + +static void add_func_float3_float_float_float(char *name) { + function_id func = add_function(add_name(name)); + function *f = get_function(func); + init_type_ref(&f->return_type, add_name("float3")); + f->return_type.type = find_type_by_ref(&f->return_type); + f->parameter_names[0] = add_name("a"); + f->parameter_names[1] = add_name("b"); + f->parameter_names[2] = add_name("c"); + for (int i = 0; i < 3; ++i) { + init_type_ref(&f->parameter_types[0], add_name("float")); + f->parameter_types[0].type = find_type_by_ref(&f->parameter_types[0]); + } + f->parameters_size = 3; + f->block = NULL; +} + +static void add_func_float3(char *name) { + function_id func = add_function(add_name(name)); + function *f = get_function(func); + init_type_ref(&f->return_type, add_name("float3")); + f->return_type.type = find_type_by_ref(&f->return_type); + f->parameters_size = 0; + f->block = NULL; +} + +static void add_func_float3_float3(char *name) { + function_id func = add_function(add_name(name)); + function *f = get_function(func); + init_type_ref(&f->return_type, add_name("float3")); + f->return_type.type = find_type_by_ref(&f->return_type); + f->parameter_names[0] = add_name("a"); + init_type_ref(&f->parameter_types[0], add_name("float3")); + f->parameter_types[0].type = find_type_by_ref(&f->parameter_types[0]); + f->parameters_size = 1; + f->block = NULL; +} + void functions_init(void) { function *new_functions = realloc(functions, functions_size * sizeof(function)); debug_context context = {0}; @@ -81,6 +127,15 @@ void functions_init(void) { f->parameters_size = 1; f->block = NULL; } + + add_func_int("group_id"); + add_func_int("group_thread_id"); + add_func_int("dispatch_thread_id"); + add_func_int("group_index"); + + add_func_float3_float_float_float("lerp"); + add_func_float3("world_ray_direction"); + add_func_float3_float3("normalize"); } static void grow_if_needed(uint64_t size) { diff --git a/Sources/globals.c b/Sources/globals.c index 1da30db..dc53c2a 100644 --- a/Sources/globals.c +++ b/Sources/globals.c @@ -8,33 +8,61 @@ static global globals[1024]; static global_id globals_size = 0; void globals_init(void) { - add_global_with_value(float_id, add_name("COMPARE_ALWAYS"), 0); - add_global_with_value(float_id, add_name("COMPARE_NEVER"), 1); - add_global_with_value(float_id, add_name("COMPARE_EQUAL"), 2); - add_global_with_value(float_id, add_name("COMPARE_NOT_EQUAL"), 3); - add_global_with_value(float_id, add_name("COMPARE_LESS"), 4); - add_global_with_value(float_id, add_name("COMPARE_LESS_EQUAL"), 5); - add_global_with_value(float_id, add_name("COMPARE_GREATER"), 6); - add_global_with_value(float_id, add_name("COMPARE_GREATER_EQUAL"), 7); + global_value int_value; + int_value.kind = GLOBAL_VALUE_INT; + + int_value.value.ints[0] = 0; + add_global_with_value(float_id, add_name("COMPARE_ALWAYS"), int_value); + int_value.value.ints[0] = 1; + add_global_with_value(float_id, add_name("COMPARE_NEVER"), int_value); + int_value.value.ints[0] = 2; + add_global_with_value(float_id, add_name("COMPARE_EQUAL"), int_value); + int_value.value.ints[0] = 3; + add_global_with_value(float_id, add_name("COMPARE_NOT_EQUAL"), int_value); + int_value.value.ints[0] = 4; + add_global_with_value(float_id, add_name("COMPARE_LESS"), int_value); + int_value.value.ints[0] = 5; + add_global_with_value(float_id, add_name("COMPARE_LESS_EQUAL"), int_value); + int_value.value.ints[0] = 6; + add_global_with_value(float_id, add_name("COMPARE_GREATER"), int_value); + int_value.value.ints[0] = 7; + add_global_with_value(float_id, add_name("COMPARE_GREATER_EQUAL"), int_value); - add_global_with_value(float_id, add_name("BLEND_ONE"), 0); - add_global_with_value(float_id, add_name("BLEND_ZERO"), 1); - add_global_with_value(float_id, add_name("BLEND_SOURCE_ALPHA"), 2); - add_global_with_value(float_id, add_name("BLEND_DEST_ALPHA"), 3); - add_global_with_value(float_id, add_name("BLEND_INV_SOURCE_ALPHA"), 4); - add_global_with_value(float_id, add_name("BLEND_INV_DEST_ALPHA"), 5); - add_global_with_value(float_id, add_name("BLEND_SOURCE_COLOR"), 6); - add_global_with_value(float_id, add_name("BLEND_DEST_COLOR"), 7); - add_global_with_value(float_id, add_name("BLEND_INV_SOURCE_COLOR"), 8); - add_global_with_value(float_id, add_name("BLEND_INV_DEST_COLOR"), 9); - add_global_with_value(float_id, add_name("BLEND_CONSTANT"), 10); - add_global_with_value(float_id, add_name("BLEND_INV_CONSTANT"), 11); + int_value.value.ints[0] = 0; + add_global_with_value(float_id, add_name("BLEND_ONE"), int_value); + int_value.value.ints[0] = 1; + add_global_with_value(float_id, add_name("BLEND_ZERO"), int_value); + int_value.value.ints[0] = 2; + add_global_with_value(float_id, add_name("BLEND_SOURCE_ALPHA"), int_value); + int_value.value.ints[0] = 3; + add_global_with_value(float_id, add_name("BLEND_DEST_ALPHA"), int_value); + int_value.value.ints[0] = 4; + add_global_with_value(float_id, add_name("BLEND_INV_SOURCE_ALPHA"), int_value); + int_value.value.ints[0] = 5; + add_global_with_value(float_id, add_name("BLEND_INV_DEST_ALPHA"), int_value); + int_value.value.ints[0] = 6; + add_global_with_value(float_id, add_name("BLEND_SOURCE_COLOR"), int_value); + int_value.value.ints[0] = 7; + add_global_with_value(float_id, add_name("BLEND_DEST_COLOR"), int_value); + int_value.value.ints[0] = 8; + add_global_with_value(float_id, add_name("BLEND_INV_SOURCE_COLOR"), int_value); + int_value.value.ints[0] = 9; + add_global_with_value(float_id, add_name("BLEND_INV_DEST_COLOR"), int_value); + int_value.value.ints[0] = 10; + add_global_with_value(float_id, add_name("BLEND_CONSTANT"), int_value); + int_value.value.ints[0] = 11; + add_global_with_value(float_id, add_name("BLEND_INV_CONSTANT"), int_value); - add_global_with_value(float_id, add_name("BLENDOP_ADD"), 0); - add_global_with_value(float_id, add_name("BLENDOP_SUBTRACT"), 1); - add_global_with_value(float_id, add_name("BLENDOP_REVERSE_SUBTRACT"), 2); - add_global_with_value(float_id, add_name("BLENDOP_MIN"), 3); - add_global_with_value(float_id, add_name("BLENDOP_MAX"), 4); + int_value.value.ints[0] = 0; + add_global_with_value(float_id, add_name("BLENDOP_ADD"), int_value); + int_value.value.ints[0] = 1; + add_global_with_value(float_id, add_name("BLENDOP_SUBTRACT"), int_value); + int_value.value.ints[0] = 2; + add_global_with_value(float_id, add_name("BLENDOP_REVERSE_SUBTRACT"), int_value); + int_value.value.ints[0] = 3; + add_global_with_value(float_id, add_name("BLENDOP_MIN"), int_value); + int_value.value.ints[0] = 4; + add_global_with_value(float_id, add_name("BLENDOP_MAX"), int_value); } global_id add_global(type_id type, name_id name) { @@ -42,12 +70,12 @@ global_id add_global(type_id type, name_id name) { globals[index].name = name; globals[index].type = type; globals[index].var_index = 0; - globals[index].value = 0; + globals[index].value.kind = GLOBAL_VALUE_NONE; globals_size += 1; return index; } -global_id add_global_with_value(type_id type, name_id name, float value) { +global_id add_global_with_value(type_id type, name_id name, global_value value) { uint32_t index = globals_size; globals[index].name = name; globals[index].type = type; diff --git a/Sources/globals.h b/Sources/globals.h index 3a3b093..9bf654a 100644 --- a/Sources/globals.h +++ b/Sources/globals.h @@ -5,17 +5,37 @@ typedef uint32_t global_id; +typedef struct global_value { + enum { + GLOBAL_VALUE_FLOAT, + GLOBAL_VALUE_FLOAT2, + GLOBAL_VALUE_FLOAT3, + GLOBAL_VALUE_FLOAT4, + GLOBAL_VALUE_INT, + GLOBAL_VALUE_INT2, + GLOBAL_VALUE_INT3, + GLOBAL_VALUE_INT4, + GLOBAL_VALUE_BOOL, + GLOBAL_VALUE_NONE + } kind; + union { + float floats[4]; + int ints[4]; + bool b; + } value; +} global_value; + typedef struct global { name_id name; type_id type; uint64_t var_index; - float value; + global_value value; } global; void globals_init(void); global_id add_global(type_id type, name_id name); -global_id add_global_with_value(type_id type, name_id name, float value); +global_id add_global_with_value(type_id type, name_id name, global_value value); global find_global(name_id name); diff --git a/Sources/integrations/kinc.c b/Sources/integrations/kinc.c index 574ae75..ac1009b 100644 --- a/Sources/integrations/kinc.c +++ b/Sources/integrations/kinc.c @@ -610,43 +610,43 @@ void kinc_export(char *directory, api_kind api) { debug_context context = {0}; check(t->members.m[j].value.kind == TOKEN_IDENTIFIER, context, "depth_mode expects an identifier"); global g = find_global(t->members.m[j].value.identifier); - fprintf(output, "\t%s.depth_mode = %s;\n\n", get_name(t->name), convert_compare_mode((int)g.value)); + fprintf(output, "\t%s.depth_mode = %s;\n\n", get_name(t->name), convert_compare_mode(g.value.value.ints[0])); } else if (t->members.m[j].name == add_name("blend_source")) { debug_context context = {0}; check(t->members.m[j].value.kind == TOKEN_IDENTIFIER, context, "blend_source expects an identifier"); global g = find_global(t->members.m[j].value.identifier); - fprintf(output, "\t%s.blend_source = %s;\n\n", get_name(t->name), convert_blend_mode((int)g.value)); + fprintf(output, "\t%s.blend_source = %s;\n\n", get_name(t->name), convert_blend_mode(g.value.value.ints[0])); } else if (t->members.m[j].name == add_name("blend_destination")) { debug_context context = {0}; check(t->members.m[j].value.kind == TOKEN_IDENTIFIER, context, "blend_destination expects an identifier"); global g = find_global(t->members.m[j].value.identifier); - fprintf(output, "\t%s.blend_destination = %s;\n\n", get_name(t->name), convert_blend_mode((int)g.value)); + fprintf(output, "\t%s.blend_destination = %s;\n\n", get_name(t->name), convert_blend_mode(g.value.value.ints[0])); } else if (t->members.m[j].name == add_name("blend_operation")) { debug_context context = {0}; check(t->members.m[j].value.kind == TOKEN_IDENTIFIER, context, "blend_operation expects an identifier"); global g = find_global(t->members.m[j].value.identifier); - fprintf(output, "\t%s.blend_operation = %s;\n\n", get_name(t->name), convert_blend_op((int)g.value)); + fprintf(output, "\t%s.blend_operation = %s;\n\n", get_name(t->name), convert_blend_op(g.value.value.ints[0])); } else if (t->members.m[j].name == add_name("alpha_blend_source")) { debug_context context = {0}; check(t->members.m[j].value.kind == TOKEN_IDENTIFIER, context, "alpha_blend_source expects an identifier"); global g = find_global(t->members.m[j].value.identifier); - fprintf(output, "\t%s.alpha_blend_source = %s;\n\n", get_name(t->name), convert_blend_mode((int)g.value)); + fprintf(output, "\t%s.alpha_blend_source = %s;\n\n", get_name(t->name), convert_blend_mode(g.value.value.ints[0])); } else if (t->members.m[j].name == add_name("alpha_blend_destination")) { debug_context context = {0}; check(t->members.m[j].value.kind == TOKEN_IDENTIFIER, context, "alpha_blend_destination expects an identifier"); global g = find_global(t->members.m[j].value.identifier); - fprintf(output, "\t%s.alpha_blend_destination = %s;\n\n", get_name(t->name), convert_blend_mode((int)g.value)); + fprintf(output, "\t%s.alpha_blend_destination = %s;\n\n", get_name(t->name), convert_blend_mode(g.value.value.ints[0])); } else if (t->members.m[j].name == add_name("alpha_blend_operation")) { debug_context context = {0}; check(t->members.m[j].value.kind == TOKEN_IDENTIFIER, context, "alpha_blend_operation expects an identifier"); global g = find_global(t->members.m[j].value.identifier); - fprintf(output, "\t%s.alpha_blend_operation = %s;\n\n", get_name(t->name), convert_blend_op((int)g.value)); + fprintf(output, "\t%s.alpha_blend_operation = %s;\n\n", get_name(t->name), convert_blend_op(g.value.value.ints[0])); } else { debug_context context = {0}; diff --git a/Sources/kong.c b/Sources/kong.c index 5ee896d..142f14a 100644 --- a/Sources/kong.c +++ b/Sources/kong.c @@ -69,6 +69,12 @@ type_ref resolve_member_var_type(statement *parent_block, type_ref parent_type, return left->type; } } + else if (left->kind == EXPRESSION_CALL) { + if (parent_block != NULL) { + resolve_types_in_expression(parent_block, left); + return left->type; + } + } else if (left->kind == EXPRESSION_INDEX) { if (parent_type.type != NO_TYPE) { init_type_ref(&left->type, NO_NAME); diff --git a/Sources/parser.c b/Sources/parser.c index 1317947..2924c48 100644 --- a/Sources/parser.c +++ b/Sources/parser.c @@ -811,6 +811,7 @@ static expressions parse_parameters(state_t *state) { e.size = 0; if (current(state).kind == TOKEN_RIGHT_PAREN) { + advance_state(state); return e; } @@ -1042,6 +1043,12 @@ static definition parse_const(state_t *state) { advance_state(state); } + expression *value = NULL; + if (current(state).kind == TOKEN_OPERATOR && current(state).op == OPERATOR_ASSIGN) { + advance_state(state); + value = parse_expression(state); + } + match_token(state, TOKEN_SEMICOLON, "Expected a semicolon"); advance_state(state); @@ -1049,7 +1056,7 @@ static definition parse_const(state_t *state) { if (type_name == NO_NAME) { debug_context context = {0}; - check(type != NO_TYPE, context, "Const has not type"); + check(type != NO_TYPE, context, "Const has no type"); d.kind = DEFINITION_CONST_CUSTOM; d.global = add_global(type, name.identifier); } @@ -1065,6 +1072,73 @@ static definition parse_const(state_t *state) { d.kind = DEFINITION_SAMPLER; d.global = add_global(sampler_type_id, name.identifier); } + else if (type_name == add_name("float")) { + debug_context context = {0}; + check(value != NULL, context, "const float requires an initialization value"); + check(value->kind == EXPRESSION_NUMBER, context, "const float3 requires a number"); + + global_value float_value; + float_value.kind = GLOBAL_VALUE_FLOAT; + + float_value.value.floats[0] = (float)value->number; + + d.kind = DEFINITION_CONST_BASIC; + d.global = add_global_with_value(float_id, name.identifier, float_value); + } + else if (type_name == add_name("float2")) { + debug_context context = {0}; + check(value != NULL, context, "const float2 requires an initialization value"); + check(value->kind == EXPRESSION_CALL, context, "const float2 requires a constructor call"); + check(value->call.func_name == add_name("float2"), context, "const float2 requires a float2 call"); + check(value->call.parameters.size == 3, context, "const float2 construtor call requires two parameters"); + + global_value float2_value; + float2_value.kind = GLOBAL_VALUE_FLOAT2; + + for (int i = 0; i < 2; ++i) { + check(value->call.parameters.e[i]->kind == EXPRESSION_NUMBER, context, "const float2 construtor parameters have to be numbers"); + float2_value.value.floats[i] = (float)value->call.parameters.e[i]->number; + } + + d.kind = DEFINITION_CONST_BASIC; + d.global = add_global_with_value(float2_id, name.identifier, float2_value); + } + else if (type_name == add_name("float3")) { + debug_context context = {0}; + check(value != NULL, context, "const float3 requires an initialization value"); + check(value->kind == EXPRESSION_CALL, context, "const float3 requires a constructor call"); + check(value->call.func_name == add_name("float3"), context, "const float3 requires a float3 call"); + check(value->call.parameters.size == 3, context, "const float3 construtor call requires three parameters"); + + global_value float3_value; + float3_value.kind = GLOBAL_VALUE_FLOAT3; + + for (int i = 0; i < 3; ++i) { + check(value->call.parameters.e[i]->kind == EXPRESSION_NUMBER, context, "const float3 construtor parameters have to be numbers"); + float3_value.value.floats[i] = (float)value->call.parameters.e[i]->number; + } + + d.kind = DEFINITION_CONST_BASIC; + d.global = add_global_with_value(float3_id, name.identifier, float3_value); + } + else if (type_name == add_name("float4")) { + debug_context context = {0}; + check(value != NULL, context, "const float4 requires an initialization value"); + check(value->kind == EXPRESSION_CALL, context, "const float4 requires a constructor call"); + check(value->call.func_name == add_name("float4"), context, "const float4 requires a float4 call"); + check(value->call.parameters.size == 4, context, "const float4 construtor call requires four parameters"); + + global_value float4_value; + float4_value.kind = GLOBAL_VALUE_FLOAT4; + + for (int i = 0; i < 4; ++i) { + check(value->call.parameters.e[i]->kind == EXPRESSION_NUMBER, context, "const float4 construtor parameters have to be numbers"); + float4_value.value.floats[i] = (float)value->call.parameters.e[i]->number; + } + + d.kind = DEFINITION_CONST_BASIC; + d.global = add_global_with_value(float4_id, name.identifier, float4_value); + } else { debug_context context = {0}; error(context, "Unsupported global"); diff --git a/Sources/parser.h b/Sources/parser.h index 0147ceb..5c4ebe5 100644 --- a/Sources/parser.h +++ b/Sources/parser.h @@ -120,7 +120,7 @@ typedef struct statement { } statement; typedef struct definition { - enum { DEFINITION_FUNCTION, DEFINITION_STRUCT, DEFINITION_TEX2D, DEFINITION_TEXCUBE, DEFINITION_SAMPLER, DEFINITION_CONST_CUSTOM } kind; + enum { DEFINITION_FUNCTION, DEFINITION_STRUCT, DEFINITION_TEX2D, DEFINITION_TEXCUBE, DEFINITION_SAMPLER, DEFINITION_CONST_CUSTOM, DEFINITION_CONST_BASIC } kind; union { function_id function;