mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-04-11 03:41:08 +00:00
[qfcc] Branch struct and array types for blocks
SPIR-V buffer block members need to be fully decorated with offsets (recursively), which means that any members with struct or array types need their own types in order to support having different offset and stride (arrays) decorations. This breaks struct assignment at the language level, but that is intentional as I want to deal with the member copying needed to implement struct assignment before emitting code. It also removes the need for some of the complication in target_spirv.c, but I'll deal with that later. The recursively built tag for nested structs might be a bit too aggressive, but that too can wait until I have a better idea of what's needed.
This commit is contained in:
parent
d1a13318a3
commit
be576babf9
1 changed files with 46 additions and 0 deletions
|
@ -104,10 +104,56 @@ glsl_parse_declaration (specifier_t spec, symbol_t *sym, const expr_t *init,
|
|||
}
|
||||
}
|
||||
|
||||
static const type_t *
|
||||
glsl_block_type (const type_t *type, const char *pre_tag)
|
||||
{
|
||||
if (is_array (type)) {
|
||||
type = unalias_type (type);
|
||||
auto ele_type = glsl_block_type (type->array.type, pre_tag);
|
||||
int base = type->array.base;
|
||||
int top = base + type->array.count - 1;
|
||||
// calls find_type
|
||||
return based_array_type (ele_type, base, top);
|
||||
}
|
||||
// union not supported
|
||||
if (is_struct (type)) {
|
||||
type = unalias_type (type);
|
||||
auto name = type->name + 4; // skip over "tag "
|
||||
auto tag = save_string (va (0, "%s.%s", pre_tag, name));
|
||||
type_t new = {
|
||||
.type = ev_invalid,
|
||||
.name = tag,
|
||||
.meta = ty_struct,
|
||||
};
|
||||
auto nt = find_type (&new);
|
||||
if (nt->symtab) {
|
||||
// already exists (multiple fields of the same struct in the
|
||||
// block)
|
||||
return nt;
|
||||
}
|
||||
((type_t *)nt)->symtab = new_symtab (type->symtab->parent, stab_struct);
|
||||
for (auto s = type->symtab->symbols; s; s = s->next) {
|
||||
auto ftype = glsl_block_type (s->type, tag);
|
||||
auto sym = new_symbol_type (s->name, ftype);
|
||||
sym->offset = -1;
|
||||
sym->id = s->id;
|
||||
symtab_addsymbol (nt->symtab, sym);
|
||||
}
|
||||
return nt;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
void
|
||||
glsl_declare_field (specifier_t spec, symtab_t *symtab, rua_ctx_t *ctx)
|
||||
{
|
||||
auto attributes = glsl_optimize_attributes (spec.attributes);
|
||||
if (symtab->type == stab_block) {
|
||||
spec = spec_process (spec, ctx);
|
||||
spec.type = find_type (append_type (spec.sym->type, spec.type));
|
||||
spec.type = glsl_block_type (spec.type, symtab->name);
|
||||
spec.sym->type = nullptr;
|
||||
}
|
||||
spec.sym = declare_field (spec, symtab, ctx);
|
||||
spec.sym->offset = -1;
|
||||
glsl_apply_attributes (attributes, spec);
|
||||
|
|
Loading…
Reference in a new issue