diff --git a/Sources/backends/glsl.c b/Sources/backends/glsl.c index 6d571db..efccb8c 100644 --- a/Sources/backends/glsl.c +++ b/Sources/backends/glsl.c @@ -332,15 +332,15 @@ static void write_functions(char *code, size_t *offset, shader_stage stage, type type *s = get_type(o->op_load_member.member_parent_type); for (size_t i = 0; i < o->op_load_member.member_indices_size; ++i) { if (f == main && o->op_load_member.member_parent_type == input && i == 0) { - *offset += sprintf(&code[*offset], "_%s", get_name(s->members.m[o->op_load_member.member_indices[i]].name)); + *offset += sprintf(&code[*offset], "_%s", get_name(s->members.m[o->op_load_member.static_member_indices[i]].name)); } else if (global_var_index != 0) { - *offset += sprintf(&code[*offset], "_%s", get_name(s->members.m[o->op_load_member.member_indices[i]].name)); + *offset += sprintf(&code[*offset], "_%s", get_name(s->members.m[o->op_load_member.static_member_indices[i]].name)); } else { - *offset += sprintf(&code[*offset], ".%s", get_name(s->members.m[o->op_load_member.member_indices[i]].name)); + *offset += sprintf(&code[*offset], ".%s", get_name(s->members.m[o->op_load_member.static_member_indices[i]].name)); } - s = get_type(s->members.m[o->op_load_member.member_indices[i]].type.type); + s = get_type(s->members.m[o->op_load_member.static_member_indices[i]].type.type); } *offset += sprintf(&code[*offset], ";\n"); break; diff --git a/Sources/backends/hlsl.c b/Sources/backends/hlsl.c index ecb3b40..a40a707 100644 --- a/Sources/backends/hlsl.c +++ b/Sources/backends/hlsl.c @@ -836,13 +836,21 @@ static void write_functions(char *hlsl, size_t *offset, shader_stage stage, func o->op_load_member.from.index); type *s = get_type(o->op_load_member.member_parent_type); for (size_t i = 0; i < o->op_load_member.member_indices_size; ++i) { - if (global_var_index != 0) { - *offset += sprintf(&hlsl[*offset], "_%s", get_name(s->members.m[o->op_load_member.member_indices[i]].name)); + if (o->op_load_member.dynamic_member[i]) { + *offset += sprintf(&hlsl[*offset], "[_%" PRIu64 "]", o->op_load_member.dynamic_member_indices[i].index); + + s = get_type(o->op_load_member.dynamic_member_indices[i].type.type); } else { - *offset += sprintf(&hlsl[*offset], ".%s", get_name(s->members.m[o->op_load_member.member_indices[i]].name)); + if (global_var_index != 0 && i == 0) { + *offset += sprintf(&hlsl[*offset], "_%s", get_name(s->members.m[o->op_load_member.static_member_indices[i]].name)); + } + else { + *offset += sprintf(&hlsl[*offset], ".%s", get_name(s->members.m[o->op_load_member.static_member_indices[i]].name)); + } + + s = get_type(s->members.m[o->op_load_member.static_member_indices[i]].type.type); } - s = get_type(s->members.m[o->op_load_member.member_indices[i]].type.type); } *offset += sprintf(&hlsl[*offset], ";\n"); break; diff --git a/Sources/backends/metal.c b/Sources/backends/metal.c index 3ba6eb6..1ccad7e 100644 --- a/Sources/backends/metal.c +++ b/Sources/backends/metal.c @@ -275,8 +275,8 @@ static void write_functions(char *code, size_t *offset) { o->op_load_member.from.index); type *s = get_type(o->op_load_member.member_parent_type); for (size_t i = 0; i < o->op_load_member.member_indices_size; ++i) { - *offset += sprintf(&code[*offset], ".%s", get_name(s->members.m[o->op_load_member.member_indices[i]].name)); - s = get_type(s->members.m[o->op_load_member.member_indices[i]].type.type); + *offset += sprintf(&code[*offset], ".%s", get_name(s->members.m[o->op_load_member.static_member_indices[i]].name)); + s = get_type(s->members.m[o->op_load_member.static_member_indices[i]].type.type); } *offset += sprintf(&code[*offset], ";\n"); break; diff --git a/Sources/backends/spirv.c b/Sources/backends/spirv.c index e6e181a..4a943b5 100644 --- a/Sources/backends/spirv.c +++ b/Sources/backends/spirv.c @@ -820,7 +820,7 @@ static void write_function(instructions_buffer *instructions, function *f, spirv int indices[256]; uint16_t indices_size = o->op_load_member.member_indices_size; for (size_t i = 0; i < indices_size; ++i) { - indices[i] = (int)o->op_load_member.member_indices[i]; + indices[i] = (int)o->op_load_member.static_member_indices[i]; } storage_class storage; diff --git a/Sources/backends/wgsl.c b/Sources/backends/wgsl.c index b80d420..5656427 100644 --- a/Sources/backends/wgsl.c +++ b/Sources/backends/wgsl.c @@ -344,8 +344,8 @@ static void write_functions(char *code, size_t *offset) { o->op_load_member.from.index); type *s = get_type(o->op_load_member.member_parent_type); for (size_t i = 0; i < o->op_load_member.member_indices_size; ++i) { - *offset += sprintf(&code[*offset], ".%s", get_name(s->members.m[o->op_load_member.member_indices[i]].name)); - s = get_type(s->members.m[o->op_load_member.member_indices[i]].type.type); + *offset += sprintf(&code[*offset], ".%s", get_name(s->members.m[o->op_load_member.static_member_indices[i]].name)); + s = get_type(s->members.m[o->op_load_member.static_member_indices[i]].type.type); } *offset += sprintf(&code[*offset], ";\n"); break; diff --git a/Sources/compiler.c b/Sources/compiler.c index 03ae19a..d6dfe68 100644 --- a/Sources/compiler.c +++ b/Sources/compiler.c @@ -492,7 +492,8 @@ variable emit_expression(opcodes *code, block *parent, expression *e) { return v; } - case EXPRESSION_STATIC_MEMBER: { + case EXPRESSION_STATIC_MEMBER: + case EXPRESSION_DYNAMIC_MEMBER: { variable v = allocate_variable(e->type, VARIABLE_LOCAL); opcode o; @@ -515,41 +516,72 @@ variable emit_expression(opcodes *code, block *parent, expression *e) { type_id prev_struct = e->member.left->type.type; type *prev_s = get_type(prev_struct); o.op_load_member.member_parent_type = prev_struct; + o.op_load_member.member_parent_array = e->member.left->type.array_size > 0 || e->member.left->type.type == tex2d_type_id; - while (right->kind == EXPRESSION_STATIC_MEMBER) { - check(right->type.type != NO_TYPE, context, "Malformed member construct"); - check(right->member.left->kind == EXPRESSION_VARIABLE, context, "Malformed member construct"); + bool parent_dynamic = e->kind == EXPRESSION_DYNAMIC_MEMBER; - bool found = false; - for (size_t i = 0; i < prev_s->members.size; ++i) { - if (prev_s->members.m[i].name == right->member.left->variable) { - o.op_load_member.member_indices[o.op_load_member.member_indices_size] = (uint16_t)i; - ++o.op_load_member.member_indices_size; - found = true; - break; + while (right->kind == EXPRESSION_STATIC_MEMBER || right->kind == EXPRESSION_DYNAMIC_MEMBER) { + debug_context context = {0}; + check(right->type.type != NO_TYPE, context, "Part of the member does not have a type"); + + if (right->member.left->kind == EXPRESSION_VARIABLE && !parent_dynamic) { + bool found = false; + for (size_t i = 0; i < prev_s->members.size; ++i) { + if (prev_s->members.m[i].name == right->member.left->variable) { + o.op_load_member.dynamic_member[o.op_load_member.member_indices_size] = false; + o.op_load_member.static_member_indices[o.op_load_member.member_indices_size] = (uint16_t)i; + ++o.op_load_member.member_indices_size; + found = true; + break; + } } + check(found, context, "Variable for a member not found"); + } + else if (right->member.left->kind == EXPRESSION_INDEX) { + o.op_load_member.dynamic_member[o.op_load_member.member_indices_size] = false; + o.op_load_member.static_member_indices[o.op_load_member.member_indices_size] = (uint16_t)right->member.left->index; + ++o.op_load_member.member_indices_size; + } + else { + variable sub_expression = emit_expression(code, parent, right->member.left); + o.op_load_member.dynamic_member[o.op_load_member.member_indices_size] = true; + o.op_load_member.dynamic_member_indices[o.op_load_member.member_indices_size] = sub_expression; + ++o.op_load_member.member_indices_size; } - check(found, context, "Member not found"); prev_struct = right->member.left->type.type; prev_s = get_type(prev_struct); + parent_dynamic = right->kind == EXPRESSION_DYNAMIC_MEMBER; right = right->member.right; } { - check(right->type.type != NO_TYPE, context, "Malformed member construct"); - check(right->kind == EXPRESSION_VARIABLE, context, "Malformed member construct"); - - bool found = false; - for (size_t i = 0; i < prev_s->members.size; ++i) { - if (prev_s->members.m[i].name == right->variable) { - o.op_load_member.member_indices[o.op_load_member.member_indices_size] = (uint16_t)i; - ++o.op_load_member.member_indices_size; - found = true; - break; + debug_context context = {0}; + check(right->type.type != NO_TYPE, context, "Part of the member does not have a type"); + if (right->kind == EXPRESSION_VARIABLE && !parent_dynamic) { + bool found = false; + for (size_t i = 0; i < prev_s->members.size; ++i) { + if (prev_s->members.m[i].name == right->variable) { + o.op_load_member.dynamic_member[o.op_load_member.member_indices_size] = false; + o.op_load_member.static_member_indices[o.op_load_member.member_indices_size] = (uint16_t)i; + ++o.op_load_member.member_indices_size; + found = true; + break; + } } + check(found, context, "Member not found"); + } + else if (right->kind == EXPRESSION_INDEX) { + o.op_load_member.dynamic_member[o.op_load_member.member_indices_size] = false; + o.op_load_member.static_member_indices[o.op_load_member.member_indices_size] = (uint16_t)right->index; + ++o.op_load_member.member_indices_size; + } + else { + variable sub_expression = emit_expression(code, parent, right); + o.op_load_member.dynamic_member[o.op_load_member.member_indices_size] = true; + o.op_load_member.dynamic_member_indices[o.op_load_member.member_indices_size] = sub_expression; + ++o.op_load_member.member_indices_size; } - check(found, context, "Member not found"); } emit_op(code, &o); diff --git a/Sources/compiler.h b/Sources/compiler.h index 1624796..2baf364 100644 --- a/Sources/compiler.h +++ b/Sources/compiler.h @@ -73,11 +73,14 @@ typedef struct opcode { struct { variable from; variable to; + bool dynamic_member[64]; variable dynamic_member_indices[64]; + uint32_t static_member_indices[64]; type_id member_parent_type; bool member_parent_array; + uint8_t member_indices_size; } op_store_member; struct { @@ -95,8 +98,14 @@ typedef struct opcode { struct { variable from; variable to; - uint16_t member_indices[64]; + + bool dynamic_member[64]; + variable dynamic_member_indices[64]; + + uint32_t static_member_indices[64]; type_id member_parent_type; + bool member_parent_array; + uint8_t member_indices_size; } op_load_member; struct {