/* glsl-block.c GLSL specific block handling Copyright (C) 2024 Bill Currie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to: Free Software Foundation, Inc. 59 Temple Place - Suite 330 Boston, MA 02111-1307, USA */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "QF/alloc.h" #include "QF/hash.h" #include "QF/va.h" #include "tools/qfcc/include/def.h" #include "tools/qfcc/include/diagnostic.h" #include "tools/qfcc/include/glsl-lang.h" #include "tools/qfcc/include/shared.h" #include "tools/qfcc/include/strpool.h" #include "tools/qfcc/include/symtab.h" #include "tools/qfcc/include/type.h" ALLOC_STATE (glsl_block_t, blocks); static hashtab_t *interfaces[glsl_num_interfaces]; static const char * block_get_key (const void *_b, void *) { auto b = (const glsl_block_t *) _b; return b->name; } void glsl_block_clear (void) { if (interfaces[glsl_in]) { for (auto i = glsl_in; i < glsl_num_interfaces; i++) { Hash_FlushTable (interfaces[i]); } } else { for (auto i = glsl_in; i < glsl_num_interfaces; i++) { interfaces[i] = Hash_NewTable (127, block_get_key, 0, 0, 0); } } } static const expr_t * block_sym_ref (symbol_t *sym, void *data) { return new_symbol_expr (data); } void glsl_declare_block (specifier_t spec, symbol_t *block_sym, symbol_t *instance_name) { auto interface = glsl_iftype_from_sc(spec.storage); hashtab_t *block_tab = nullptr; if (interface < glsl_num_interfaces) { block_tab = interfaces[interface]; } if (!block_tab) { error (0, "invalid storage for block: %d", spec.storage); return; } glsl_block_t *block; ALLOC (64, glsl_block_t, blocks, block); *block = (glsl_block_t) { .name = save_string (block_sym->name), .attributes = spec.attributes, .members = block_sym->namespace, .instance_name = instance_name, }; Hash_Add (block_tab, block); for (auto sym = block->members->symbols; sym; sym = sym->next) { auto def = new_def (sym->name, nullptr, nullptr, spec.storage); def->type = sym->type; sym->sy_type = sy_var; sym->def = def; } if (instance_name) { auto type = new_type (); *type = (type_t) { .type = ev_invalid, .name = save_string (block_sym->name), .alignment = 4, .width = 1, .columns = 1, .meta = ty_struct, .symtab = block->members, }; instance_name->type = append_type (instance_name->type, type); instance_name->type = find_type (instance_name->type); auto space = current_symtab->space;// FIXME initialize_def (instance_name, nullptr, space, spec.storage, current_symtab); } else { for (auto sym = block->members->symbols; sym; sym = sym->next) { auto new = new_symbol (sym->name); new->sy_type = sy_convert; new->convert = (symconv_t) { .conv = block_sym_ref, .data = sym, }; symtab_addsymbol (current_symtab, new); } } } glsl_block_t * glsl_get_block (const char *name, glsl_interface_t interface) { if (interface >= glsl_num_interfaces) { internal_error (0, "invalid interface"); } return Hash_Find (interfaces[interface], name); }