From: Mikko Rasa Date: Thu, 4 Mar 2021 23:06:46 +0000 (+0200) Subject: Give declaration nodes to all GLSL types. X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=4c805f55d89919d6971d600102ab4d6d65d56dc3 Give declaration nodes to all GLSL types. Even the builtin ones. This makes various operations with expressions easier and helps with SPIR-V. --- diff --git a/builtin_data/_builtin.glsl b/builtin_data/_builtin.glsl index f6a3574f..df39bcc0 100644 --- a/builtin_data/_builtin.glsl +++ b/builtin_data/_builtin.glsl @@ -1,3 +1,37 @@ +typedef vector(2) float vec2; +typedef vector(3) float vec3; +typedef vector(4) float vec4; +typedef vector(2) vec2 mat2; +typedef mat2 mat2x2; +typedef vector(3) vec2 mat3x2; +typedef vector(4) vec2 mat4x2; +typedef vector(2) vec3 mat2x3; +typedef vector(3) vec3 mat3; +typedef mat3 mat3x3; +typedef vector(4) vec3 mat4x3; +typedef vector(2) vec4 mat2x4; +typedef vector(3) vec4 mat3x4; +typedef vector(4) vec4 mat4; +typedef mat4 mat4x4; + +typedef vector(2) int ivec2; +typedef vector(3) int ivec3; +typedef vector(4) int ivec4; + +typedef image(dimensions=1, sampled) float sampler1D; +typedef image(dimensions=2, sampled) float sampler2D; +typedef image(dimensions=3, sampled) float sampler3D; +typedef image(dimensions=cube, sampled) float samplerCube; +typedef image(dimensions=1[], sampled) float sampler1DArray; +typedef image(dimensions=2[], sampled) float sampler2DArray; +typedef image(dimensions=cube[], sampled) float samplerCubeArray; +typedef image(dimensions=1, shadow, sampled) float sampler1DShadow; +typedef image(dimensions=2, shadow, sampled) float sampler2DShadow; +typedef image(dimensions=1[], shadow, sampled) float sampler1DArrayShadow; +typedef image(dimensions=2[], shadow, sampled) float sampler2DArrayShadow; +typedef image(dimensions=cube, shadow, sampled) float samplerCubeShadow; +typedef image(dimensions=cube[], shadow, sampled) float samplerCubeArrayShadow; + #pragma MSP stage(vertex) out gl_PerVertex { diff --git a/source/glsl/builtin.cpp b/source/glsl/builtin.cpp index 3800e14b..670cfc2d 100644 --- a/source/glsl/builtin.cpp +++ b/source/glsl/builtin.cpp @@ -1,6 +1,7 @@ #include #include #include "builtin.h" +#include "generate.h" #include "parser.h" using namespace std; @@ -24,6 +25,38 @@ Module *get_builtins_module() Parser parser; Module *module = new Module(parser.parse(*io, "", BUILTIN_SOURCE)); + NodeList &shared_body = module->shared.content.body; + + RefPtr type = new BasicTypeDeclaration; + type->source = BUILTIN_SOURCE; + type->name = "void"; + type->kind = BasicTypeDeclaration::VOID; + shared_body.insert(shared_body.begin(), type); + + type = new BasicTypeDeclaration; + type->source = BUILTIN_SOURCE; + type->name = "bool"; + type->kind = BasicTypeDeclaration::BOOL; + shared_body.insert(shared_body.begin(), type); + + type = new BasicTypeDeclaration; + type->source = BUILTIN_SOURCE; + type->name = "int"; + type->size = 32; + type->kind = BasicTypeDeclaration::INT; + shared_body.insert(shared_body.begin(), type); + + type = new BasicTypeDeclaration; + type->source = BUILTIN_SOURCE; + type->name = "float"; + type->size = 32; + type->kind = BasicTypeDeclaration::FLOAT; + shared_body.insert(shared_body.begin(), type); + + TypeResolver().apply(module->shared); + for(list::iterator i=module->stages.begin(); i!=module->stages.end(); ++i) + TypeResolver().apply(*i); + builtins_module = module; } return builtins_module.get(); diff --git a/source/glsl/compiler.cpp b/source/glsl/compiler.cpp index 8caeba1f..f5540139 100644 --- a/source/glsl/compiler.cpp +++ b/source/glsl/compiler.cpp @@ -241,12 +241,14 @@ void Compiler::generate(Stage &stage, Mode mode) // Initial resolving pass BlockHierarchyResolver().apply(stage); + TypeResolver().apply(stage); FunctionResolver().apply(stage); VariableResolver().apply(stage); /* All variables local to a stage have been resolved. Resolve non-local variables through interfaces. */ InterfaceGenerator().apply(stage); + TypeResolver().apply(stage); VariableResolver().apply(stage); FunctionResolver().apply(stage); @@ -274,6 +276,7 @@ Compiler::OptimizeResult Compiler::optimize(Stage &stage) any_inlined |= ExpressionInliner().apply(stage); if(any_inlined) { + TypeResolver().apply(stage); VariableResolver().apply(stage); FunctionResolver().apply(stage); } diff --git a/source/glsl/debug.cpp b/source/glsl/debug.cpp index 06bf1925..d49b9a5f 100644 --- a/source/glsl/debug.cpp +++ b/source/glsl/debug.cpp @@ -14,7 +14,7 @@ const std::string &DumpTree::apply(Stage &stage) tree.push_back(BRANCH); append(format("Version: %d.%02d", stage.required_features.glsl_version.major, stage.required_features.glsl_version.minor)); - for(std::map::const_iterator i=stage.types.begin(); i!=stage.types.end(); ++i) + for(std::map::const_iterator i=stage.types.begin(); i!=stage.types.end(); ++i) append(format("Type: %%%d %s", get_label(*i->second), i->first)); set seen_interfaces; @@ -236,6 +236,45 @@ void DumpTree::visit(InterfaceLayout &layout) annotated_branch(format("Layout: %s", layout.interface), layout.layout); } +void DumpTree::visit(BasicTypeDeclaration &type) +{ + append(format("%%%d typedef %s", get_label(type), type.name)); + begin_sub(); + if(type.kind!=BasicTypeDeclaration::VECTOR && type.kind!=BasicTypeDeclaration::MATRIX) + last_branch(); + if(type.base_type) + append(format("%s: %%%d %s", (type.kind==BasicTypeDeclaration::ALIAS ? "Alias of" : "Base"), get_label(*type.base_type), type.base_type->name)); + + last_branch(); + if(type.kind==BasicTypeDeclaration::VECTOR) + append(format("Vector: %d", type.size)); + else if(type.kind==BasicTypeDeclaration::MATRIX) + append(format("Matrix: %dx%d", type.size&0xFFFF, type.size>>16)); + end_sub(); +} + +void DumpTree::visit(ImageTypeDeclaration &type) +{ + append(format("%%%d typedef %s", get_label(type), type.name)); + begin_sub(); + + if(!type.shadow && !type.base_type) + last_branch(); + static const char *dims[] = { "1D", "2D", "3D", "Cube" }; + append(format("Dimensions: %s%s", dims[type.dimensions-1], (type.array ? " array" : ""))); + + if(!type.shadow) + last_branch(); + if(type.base_type) + append(format("Element type: %%%d %s", get_label(*type.base_type), type.base_type->name)); + + last_branch(); + if(type.shadow) + append("Shadow"); + + end_sub(); +} + void DumpTree::visit(StructDeclaration &strct) { annotated_branch(format("%%%d struct %s", get_label(strct), strct.name), strct.members); @@ -262,6 +301,11 @@ void DumpTree::visit(VariableDeclaration &var) append(decl); begin_sub(); + if(!var.layout && !var.array && !var.init_expression) + last_branch(); + if(var.type_declaration) + append(format("Type: %%%d %s", get_label(*var.type_declaration), var.type_declaration->name)); + if(!var.array && !var.init_expression) last_branch(); if(var.layout) diff --git a/source/glsl/debug.h b/source/glsl/debug.h index 87ec4734..b377b844 100644 --- a/source/glsl/debug.h +++ b/source/glsl/debug.h @@ -55,6 +55,8 @@ private: virtual void visit(Precision &); virtual void visit(Layout &); virtual void visit(InterfaceLayout &); + virtual void visit(BasicTypeDeclaration &); + virtual void visit(ImageTypeDeclaration &); virtual void visit(StructDeclaration &); virtual void visit(VariableDeclaration &); virtual void visit(InterfaceBlock &); diff --git a/source/glsl/generate.cpp b/source/glsl/generate.cpp index b91c2e26..c4a29110 100644 --- a/source/glsl/generate.cpp +++ b/source/glsl/generate.cpp @@ -114,6 +114,55 @@ void BlockHierarchyResolver::enter(Block &block) } +TypeResolver::TypeResolver(): + stage(0) +{ } + +void TypeResolver::apply(Stage &s) +{ + stage = &s; + s.types.clear(); + s.content.visit(*this); +} + +void TypeResolver::visit(BasicTypeDeclaration &type) +{ + map::iterator i = stage->types.find(type.base); + type.base_type = (i!=stage->types.end() ? i->second : 0); + + if(type.kind==BasicTypeDeclaration::VECTOR && type.base_type) + if(BasicTypeDeclaration *basic_base = dynamic_cast(type.base_type)) + if(basic_base->kind==BasicTypeDeclaration::VECTOR) + { + type.kind = BasicTypeDeclaration::MATRIX; + type.size |= basic_base->size<<16; + } + + stage->types.insert(make_pair(type.name, &type)); +} + +void TypeResolver::visit(ImageTypeDeclaration &type) +{ + map::iterator i = stage->types.find(type.base); + type.base_type = (i!=stage->types.end() ? i->second : 0); + + stage->types.insert(make_pair(type.name, &type)); +} + +void TypeResolver::visit(StructDeclaration &strct) +{ + stage->types.insert(make_pair(strct.name, &strct)); + TraversingVisitor::visit(strct); +} + +void TypeResolver::visit(VariableDeclaration &var) +{ + map::iterator i = stage->types.find(var.type); + if(i!=stage->types.end()) + var.type_declaration = i->second; +} + + VariableResolver::VariableResolver(): stage(0), r_members(0), @@ -125,7 +174,6 @@ VariableResolver::VariableResolver(): void VariableResolver::apply(Stage &s) { stage = &s; - s.types.clear(); s.interface_blocks.clear(); s.content.visit(*this); } @@ -151,8 +199,8 @@ void VariableResolver::visit(VariableReference &var) if(var.declaration) { - if(var.declaration->type_declaration) - r_members = &var.declaration->type_declaration->members.variables; + if(StructDeclaration *strct = dynamic_cast(var.declaration->type_declaration)) + r_members = &strct->members.variables; } else { @@ -228,8 +276,8 @@ void VariableResolver::visit(MemberAccess &memacc) if(i!=r_members->end()) { memacc.declaration = i->second; - if(i->second->type_declaration) - r_members = &i->second->type_declaration->members.variables; + if(StructDeclaration *strct = dynamic_cast(i->second->type_declaration)) + r_members = &strct->members.variables; } else r_members = 0; @@ -292,18 +340,8 @@ void VariableResolver::visit(FunctionCall &call) r_iface_ref = 0; } -void VariableResolver::visit(StructDeclaration &strct) -{ - TraversingVisitor::visit(strct); - stage->types.insert(make_pair(strct.name, &strct)); -} - void VariableResolver::visit(VariableDeclaration &var) { - map::iterator i = stage->types.find(var.type); - if(i!=stage->types.end()) - var.type_declaration = i->second; - if(!block_interface.empty() && var.interface.empty()) var.interface = block_interface; diff --git a/source/glsl/generate.h b/source/glsl/generate.h index 951a672d..d303af36 100644 --- a/source/glsl/generate.h +++ b/source/glsl/generate.h @@ -55,6 +55,24 @@ private: virtual void enter(Block &); }; +/** Resolves types of variables and base types of other types. */ +class TypeResolver: private TraversingVisitor +{ +private: + Stage *stage; + +public: + TypeResolver(); + + void apply(Stage &); + +private: + virtual void visit(BasicTypeDeclaration &); + virtual void visit(ImageTypeDeclaration &); + virtual void visit(StructDeclaration &); + virtual void visit(VariableDeclaration &); +}; + /** Resolves variable references. Variable references which match the name of an interface block are turned into interface block references. */ class VariableResolver: private TraversingVisitor @@ -82,7 +100,6 @@ private: virtual void visit(BinaryExpression &); virtual void visit(Assignment &); virtual void visit(FunctionCall &); - virtual void visit(StructDeclaration &); virtual void visit(VariableDeclaration &); virtual void visit(InterfaceBlock &); }; diff --git a/source/glsl/parser.cpp b/source/glsl/parser.cpp index 0f7122f5..c9a812dd 100644 --- a/source/glsl/parser.cpp +++ b/source/glsl/parser.cpp @@ -2,6 +2,7 @@ #include #include #include +#include "builtin.h" #include "glsl_error.h" #include "parser.h" @@ -53,11 +54,27 @@ void Parser::parse_source(const string &name, int index) { delete module; module = new Module; + cur_stage = &module->shared; base_index = index; source_index = index; if(index>=0) source_reference(1, name); + + // TODO Need to somehow get type names from imports + if(const Stage *builtin = get_builtins(Stage::SHARED)) + { + for(map::const_iterator i=builtin->types.begin(); i!=builtin->types.end(); ++i) + declared_types.insert(i->first); + } + else + { + declared_types.insert("void"); + declared_types.insert("bool"); + declared_types.insert("int"); + declared_types.insert("float"); + } + tokenizer.begin(source, name); allow_stage_change = true; while(!tokenizer.peek_token().empty()) @@ -171,15 +188,9 @@ bool Parser::is_qualifier(const string &token) is_precision_qualifier(token)); } -bool Parser::is_builtin_type(const string &token) -{ - static Regex re("^(void|float|int|bool|[ib]?vec[234]|mat[234](x[234])?|sampler((1D|2D|Cube)(Array)?(Shadow)?|3D))$"); - return re.match(token); -} - bool Parser::is_type(const string &token) { - return is_builtin_type(token) || declared_types.count(token); + return declared_types.count(token); } bool Parser::is_identifier(const string &token) @@ -269,6 +280,8 @@ RefPtr Parser::parse_global_declaration() return var; } } + else if(token=="typedef") + return parse_type_declaration(); else if(token=="struct") return parse_struct_declaration(); else if(is_interface_qualifier(token)) @@ -355,10 +368,8 @@ RefPtr Parser::parse_precision() if(!is_precision_qualifier(precision->precision)) throw parse_error(tokenizer.get_location(), precision->precision, "a precision qualifier"); - precision->type = tokenizer.parse_token(); - // Not entirely accurate; only float, int and sampler types are allowed - if(!is_builtin_type(precision->type)) - throw parse_error(tokenizer.get_location(), precision->type, "a builtin type"); + // TODO Add validation for this + precision->type = expect_type(); tokenizer.expect(";"); @@ -545,6 +556,98 @@ RefPtr Parser::parse_function_call(const VariableReference &var) return call; } +RefPtr Parser::parse_type_declaration() +{ + tokenizer.expect("typedef"); + + RefPtr type; + if(tokenizer.peek_token()=="image") + type = parse_image_type_declaration(); + else + type = parse_basic_type_declaration(); + + tokenizer.expect(";"); + declared_types.insert(type->name); + return type; +} + +RefPtr Parser::parse_basic_type_declaration() +{ + RefPtr type = create_node(); + + if(tokenizer.peek_token()=="vector") + { + type->kind = BasicTypeDeclaration::VECTOR; + + tokenizer.parse_token(); + tokenizer.expect("("); + type->size = expect_integer(); + tokenizer.expect(")"); + } + + type->base = expect_type(); + type->name = expect_identifier(); + + if(type->kind==BasicTypeDeclaration::ALIAS && check("[")) + { + type->kind = BasicTypeDeclaration::ARRAY; + tokenizer.expect("]"); + } + + return type; +} + +RefPtr Parser::parse_image_type_declaration() +{ + tokenizer.expect("image"); + tokenizer.expect("("); + + RefPtr type = create_node(); + while(1) + { + string token = tokenizer.parse_token(); + if(token=="dimensions") + { + tokenizer.expect("="); + token = tokenizer.parse_token(); + if(token=="1") + type->dimensions = ImageTypeDeclaration::ONE; + else if(token=="2") + type->dimensions = ImageTypeDeclaration::TWO; + else if(token=="3") + type->dimensions = ImageTypeDeclaration::THREE; + else if(token=="cube") + type->dimensions = ImageTypeDeclaration::CUBE; + else + throw parse_error(tokenizer.get_location(), token, "dimensions"); + + if(check("[")) + { + type->array = true; + tokenizer.expect("]"); + } + } + else if(token=="sampled") + type->sampled = true; + else if(token=="shadow") + type->shadow = true; + else + throw parse_error(tokenizer.get_location(), token, "image type attribute"); + + token = tokenizer.peek_token(); + if(token==")") + break; + + tokenizer.expect(","); + } + tokenizer.expect(")"); + + type->base = expect_type(); + type->name = expect_identifier(); + + return type; +} + RefPtr Parser::parse_struct_declaration() { tokenizer.expect("struct"); diff --git a/source/glsl/parser.h b/source/glsl/parser.h index 21d86e9d..26867ec4 100644 --- a/source/glsl/parser.h +++ b/source/glsl/parser.h @@ -50,7 +50,6 @@ private: static bool is_interpolation_qualifier(const std::string &); static bool is_precision_qualifier(const std::string &); static bool is_qualifier(const std::string &); - static bool is_builtin_type(const std::string &); bool is_type(const std::string &); bool is_identifier(const std::string &); @@ -74,6 +73,9 @@ private: RefPtr parse_expression(unsigned = 0); RefPtr parse_binary(const RefPtr &, const Operator &); RefPtr parse_function_call(const VariableReference &); + RefPtr parse_type_declaration(); + RefPtr parse_basic_type_declaration(); + RefPtr parse_image_type_declaration(); RefPtr parse_struct_declaration(); RefPtr parse_variable_declaration(); RefPtr parse_variable_declaration_with_layout(); diff --git a/source/glsl/syntax.cpp b/source/glsl/syntax.cpp index 93157864..e20d6c26 100644 --- a/source/glsl/syntax.cpp +++ b/source/glsl/syntax.cpp @@ -237,6 +237,39 @@ void InterfaceLayout::visit(NodeVisitor &visitor) } +BasicTypeDeclaration::BasicTypeDeclaration(): + kind(ALIAS), + size(0), + base_type(0) +{ } + +BasicTypeDeclaration::BasicTypeDeclaration(const BasicTypeDeclaration &other): + TypeDeclaration(other), + kind(other.kind), + size(other.size), + base(other.base), + base_type(0) +{ } + +void BasicTypeDeclaration::visit(NodeVisitor &visitor) +{ + visitor.visit(*this); +} + + +ImageTypeDeclaration::ImageTypeDeclaration(): + dimensions(TWO), + array(false), + sampled(true), + shadow(false) +{ } + +void ImageTypeDeclaration::visit(NodeVisitor &visitor) +{ + visitor.visit(*this); +} + + StructDeclaration::StructDeclaration() { members.use_braces = true; diff --git a/source/glsl/syntax.h b/source/glsl/syntax.h index f275eab8..62c289d9 100644 --- a/source/glsl/syntax.h +++ b/source/glsl/syntax.h @@ -285,9 +285,66 @@ struct InterfaceLayout: Statement virtual void visit(NodeVisitor &); }; -struct StructDeclaration: Statement +struct TypeDeclaration: Statement { std::string name; + + virtual TypeDeclaration *clone() const = 0; +}; + +struct BasicTypeDeclaration: TypeDeclaration +{ + enum Kind + { + ALIAS, + VOID, + BOOL, + INT, + FLOAT, + VECTOR, + MATRIX, + ARRAY + }; + + Kind kind; + unsigned size; + std::string base; + + TypeDeclaration *base_type; + + BasicTypeDeclaration(); + BasicTypeDeclaration(const BasicTypeDeclaration &); + + virtual BasicTypeDeclaration *clone() const { return new BasicTypeDeclaration(*this); } + virtual void visit(NodeVisitor &); +}; + +struct ImageTypeDeclaration: TypeDeclaration +{ + enum Dimensions + { + ONE = 1, + TWO, + THREE, + CUBE + }; + + Dimensions dimensions; + bool array; + bool sampled; + bool shadow; + std::string base; + + TypeDeclaration *base_type; + + ImageTypeDeclaration(); + + virtual ImageTypeDeclaration *clone() const { return new ImageTypeDeclaration(*this); } + virtual void visit(NodeVisitor &); +}; + +struct StructDeclaration: TypeDeclaration +{ Block members; StructDeclaration(); @@ -310,7 +367,7 @@ struct VariableDeclaration: Statement NodePtr array_size; NodePtr init_expression; - StructDeclaration *type_declaration; + TypeDeclaration *type_declaration; VariableDeclaration *linked_declaration; VariableDeclaration(); @@ -413,7 +470,7 @@ struct Stage Type type; Stage *previous; Block content; - std::map types; + std::map types; std::map interface_blocks; std::map functions; std::map locations; diff --git a/source/glsl/validate.cpp b/source/glsl/validate.cpp index 78d3bb4b..6d0f8e51 100644 --- a/source/glsl/validate.cpp +++ b/source/glsl/validate.cpp @@ -60,6 +60,11 @@ void DeclarationValidator::record_definition(const string &name, Statement &stat declarations[current_block->parent].insert(make_pair(name, &statement)); } +void DeclarationValidator::visit(TypeDeclaration &type) +{ + check_definition(type.name, type); +} + void DeclarationValidator::visit(StructDeclaration &strct) { check_definition(strct.name, strct); diff --git a/source/glsl/validate.h b/source/glsl/validate.h index 01f2ba4f..c723b995 100644 --- a/source/glsl/validate.h +++ b/source/glsl/validate.h @@ -41,6 +41,9 @@ private: void check_definition(const std::string &, Statement &); void record_definition(const std::string &, Statement &); + virtual void visit(TypeDeclaration &); + virtual void visit(BasicTypeDeclaration &t) { visit(static_cast(t)); } + virtual void visit(ImageTypeDeclaration &t) { visit(static_cast(t)); } virtual void visit(StructDeclaration &); virtual void visit(VariableDeclaration &); virtual void visit(InterfaceBlock &); diff --git a/source/glsl/visitor.cpp b/source/glsl/visitor.cpp index fa6e614c..bee312fd 100644 --- a/source/glsl/visitor.cpp +++ b/source/glsl/visitor.cpp @@ -154,10 +154,10 @@ void NodeRemover::visit(Block &block) } } -void NodeRemover::visit(StructDeclaration &strct) +void NodeRemover::visit(TypeDeclaration &type) { - if(to_remove->count(&strct)) - remove_from_map(stage->types, strct.name, strct); + if(to_remove->count(&type)) + remove_from_map(stage->types, type.name, type); } void NodeRemover::visit(VariableDeclaration &var) diff --git a/source/glsl/visitor.h b/source/glsl/visitor.h index cd9dafb0..6fe1868c 100644 --- a/source/glsl/visitor.h +++ b/source/glsl/visitor.h @@ -32,6 +32,8 @@ public: virtual void visit(Precision &) { } virtual void visit(Layout &) { } virtual void visit(InterfaceLayout &) { } + virtual void visit(BasicTypeDeclaration &) { } + virtual void visit(ImageTypeDeclaration &) { } virtual void visit(StructDeclaration &) { } virtual void visit(VariableDeclaration &) { } virtual void visit(InterfaceBlock &) { } @@ -104,7 +106,10 @@ private: void remove_from_map(std::map &, const std::string &, T &); virtual void visit(Block &); - virtual void visit(StructDeclaration &); + void visit(TypeDeclaration &); + virtual void visit(BasicTypeDeclaration &t) { visit(static_cast(t)); } + virtual void visit(ImageTypeDeclaration &t) { visit(static_cast(t)); } + virtual void visit(StructDeclaration &t) { visit(static_cast(t)); } virtual void visit(VariableDeclaration &); virtual void visit(InterfaceBlock &); virtual void visit(FunctionDeclaration &);