]> git.tdb.fi Git - libs/gl.git/commitdiff
Improve layout qualifier handling with some more utility functions
authorMikko Rasa <tdb@tdb.fi>
Thu, 11 Nov 2021 10:00:07 +0000 (12:00 +0200)
committerMikko Rasa <tdb@tdb.fi>
Thu, 11 Nov 2021 10:41:24 +0000 (12:41 +0200)
source/glsl/finalize.cpp
source/glsl/finalize.h
source/glsl/reflect.cpp
source/glsl/spirv.cpp
source/glsl/syntax.cpp
source/glsl/syntax.h
source/glsl/validate.cpp
source/glsl/validate.h

index 3bdca5cb7d02dcbf786e69dd60d9f0b3b394d554..7eb0165dc5b82156d6a71caca7953508ad74aa33 100644 (file)
@@ -46,12 +46,7 @@ void StructOrganizer::visit(VariableDeclaration &var)
                if(layout_offset)
                        *layout_offset = offset;
                else
-               {
-                       if(!var.layout)
-                               var.layout = new Layout;
-
-                       var.layout->qualifiers.push_back(Layout::Qualifier("offset", offset));
-               }
+                       add_layout_qualifier(var.layout, Layout::Qualifier("offset", offset));
 
                if(!has_matrix_order)
                {
@@ -59,7 +54,7 @@ void StructOrganizer::visit(VariableDeclaration &var)
                        while(basic && basic->kind==BasicTypeDeclaration::ARRAY)
                                basic = dynamic_cast<const BasicTypeDeclaration *>(basic->base_type);
                        if(basic && basic->kind==BasicTypeDeclaration::MATRIX)
-                               var.layout->qualifiers.push_back(Layout::Qualifier("column_major"));
+                               add_layout_qualifier(var.layout, Layout::Qualifier("column_major"));
                }
 
                offset += mem_reqs.size;
@@ -111,7 +106,7 @@ void LocationAllocator::allocate_locations(const string &iface)
                        auto j = uniforms.find((*i)->name);
                        if(j!=uniforms.end() && j->second.location>=0)
                        {
-                               add_layout_value((*i)->layout, "location", j->second.location);
+                               add_layout_qualifier((*i)->layout, Layout::Qualifier("location", j->second.location));
                                continue;
                        }
                }
@@ -130,7 +125,7 @@ void LocationAllocator::allocate_locations(const string &iface)
                        next = blocking+1;
                }
 
-               add_layout_value((*i)->layout, "location", next);
+               add_layout_qualifier((*i)->layout, Layout::Qualifier("location", next));
                if((*i)->interface=="uniform")
                        uniforms[(*i)->name].location = next;
 
@@ -146,7 +141,7 @@ void LocationAllocator::bind_uniform(RefPtr<Layout> &layout, const string &name,
 {
        auto i = uniforms.find(name);
        if(i!=uniforms.end() && i->second.bind_point>=0)
-               add_layout_value(layout, "binding", i->second.bind_point);
+               add_layout_qualifier(layout, Layout::Qualifier("binding", i->second.bind_point));
        else
        {
                set<unsigned> &used = used_bindings[0];
@@ -155,23 +150,15 @@ void LocationAllocator::bind_uniform(RefPtr<Layout> &layout, const string &name,
                while(used.count(bind_point))
                        bind_point = (bind_point+1)%range;
 
-               add_layout_value(layout, "binding", bind_point);
+               add_layout_qualifier(layout, Layout::Qualifier("binding", bind_point));
                uniforms[name].bind_point = bind_point;
                used.insert(bind_point);
        }
 }
 
-void LocationAllocator::add_layout_value(RefPtr<Layout> &layout, const string &name, unsigned value)
-{
-       if(!layout)
-               layout = new Layout;
-
-       layout->qualifiers.push_back(Layout::Qualifier(name, value));
-}
-
 bool LocationAllocator::visit_uniform(const string &name, RefPtr<Layout> &layout)
 {
-       int bind_point = (layout ? get_layout_value(*layout, "binding") : -1);
+       int bind_point = get_layout_value(layout.get(), "binding");
        if(bind_point>=0)
        {
                used_bindings[0].insert(bind_point);
@@ -187,13 +174,13 @@ void LocationAllocator::visit(VariableDeclaration &var)
 
        if(!var.interface.empty())
        {
-               int location = (var.layout ? get_layout_value(*var.layout, "location") : -1);
+               int location = get_layout_value(var.layout.get(), "location");
 
                if(location<0 && var.linked_declaration && var.linked_declaration->layout)
                {
-                       location = get_layout_value(*var.linked_declaration->layout, "location");
+                       location = get_layout_value(var.linked_declaration->layout.get(), "location");
                        if(location>=0)
-                               add_layout_value(var.layout, "location", location);
+                               add_layout_qualifier(var.layout, Layout::Qualifier("location", location));
                }
 
                if(location>=0)
@@ -223,13 +210,7 @@ void LocationAllocator::visit(InterfaceBlock &iface)
 
        if(iface.interface=="uniform")
        {
-               bool push_constant = false;
-               if(iface.layout)
-               {
-                       auto i = find_member(iface.layout->qualifiers, string("push_constant"), &Layout::Qualifier::name);
-                       push_constant = (i!=iface.layout->qualifiers.end());
-               }
-
+               bool push_constant = has_layout_qualifier(iface.layout.get(), "push_constant");
                if(!push_constant && !visit_uniform(iface.block_name, iface.layout))
                        unbound_blocks.push_back(&iface);
        }
@@ -512,13 +493,7 @@ bool StructuralFeatureConverter::supports_interface_blocks(const string &iface)
 
 void StructuralFeatureConverter::visit(InterfaceBlock &iface)
 {
-       bool push_constant = false;
-       if(iface.layout)
-       {
-               auto i = find_member(iface.layout->qualifiers, string("push_constant"), &Layout::Qualifier::name);
-               push_constant = (i!=iface.layout->qualifiers.end());
-       }
-
+       bool push_constant = has_layout_qualifier(iface.layout.get(), "push_constant");
        if((!supports_interface_blocks(iface.interface) || (push_constant && features.target_api!=VULKAN)) && iface.type_declaration)
        {
                if(!iface.instance_name.empty())
index 1743074849831066a4ff038b093c67b75496395a..bde0618abf2bc3dc5d73f57209486f575fa1e1b6 100644 (file)
@@ -50,7 +50,6 @@ private:
 
        void allocate_locations(const std::string &);
        void bind_uniform(RefPtr<Layout> &, const std::string &, unsigned);
-       void add_layout_value(RefPtr<Layout> &, const std::string &, unsigned);
 
        bool visit_uniform(const std::string &, RefPtr<Layout> &);
        virtual void visit(VariableDeclaration &);
index 811679f3295c320b30d2caaf8bb92d7ac164f992..a2f43a9d18418d1941f5709cbc27fa99cfd35c73 100644 (file)
@@ -311,12 +311,7 @@ void MemoryRequirementsCalculator::visit(StructDeclaration &strct)
 
 void MemoryRequirementsCalculator::visit(VariableDeclaration &var)
 {
-       if(var.layout)
-       {
-               auto i = find_member(var.layout->qualifiers, string("offset"), &Layout::Qualifier::name);
-               if(i!=var.layout->qualifiers.end())
-                       r_offset = i->value;
-       }
+       r_offset = get_layout_value(var.layout.get(), "offset");
 
        if(var.type_declaration)
                var.type_declaration->visit(*this);
index 20345e20ae0760de48e4bbea923e89fea7d9356b..40e731fe63fa9fcfb384dd61baf8429e34be3382 100644 (file)
@@ -1582,16 +1582,6 @@ void SpirVGenerator::visit(StructDeclaration &strct)
 
 void SpirVGenerator::visit(VariableDeclaration &var)
 {
-       const vector<Layout::Qualifier> *layout_ql = (var.layout ? &var.layout->qualifiers : 0);
-
-       int spec_id = -1;
-       if(layout_ql)
-       {
-               auto i = find_member(*layout_ql, string("constant_id"), &Layout::Qualifier::name);
-               if(i!=layout_ql->end())
-                       spec_id = i->value;
-       }
-
        Id type_id = get_variable_type_id(var);
        Id var_id;
 
@@ -1600,6 +1590,8 @@ void SpirVGenerator::visit(VariableDeclaration &var)
                if(!var.init_expression)
                        throw internal_error("const variable without initializer");
 
+               int spec_id = get_layout_value(var.layout.get(), "constant_id");
+
                SetFlag set_const(constant_expression);
                SetFlag set_spec(spec_constant, spec_id>=0);
                r_expression_result_id = 0;
@@ -1650,9 +1642,9 @@ void SpirVGenerator::visit(VariableDeclaration &var)
                        writer.write(init_id);
                writer.end_op(OP_VARIABLE);
 
-               if(layout_ql)
+               if(var.layout)
                {
-                       for(const Layout::Qualifier &q: *layout_ql)
+                       for(const Layout::Qualifier &q: var.layout->qualifiers)
                        {
                                if(q.name=="location")
                                        writer.write_op_decorate(var_id, DECO_LOCATION, q.value);
@@ -1680,14 +1672,7 @@ void SpirVGenerator::visit(VariableDeclaration &var)
 
 void SpirVGenerator::visit(InterfaceBlock &iface)
 {
-       const vector<Layout::Qualifier> *layout_ql = (iface.layout ? &iface.layout->qualifiers : 0);
-
-       bool push_const = false;
-       if(layout_ql)
-       {
-               auto i = find_member(*layout_ql, string("push_constant"), &Layout::Qualifier::name);
-               push_const = (i!=layout_ql->end());
-       }
+       bool push_const = has_layout_qualifier(iface.layout.get(), "push_constant");
 
        StorageClass storage = (push_const ? STORAGE_PUSH_CONSTANT : get_interface_storage(iface.interface, true));
        Id type_id;
@@ -1715,9 +1700,9 @@ void SpirVGenerator::visit(InterfaceBlock &iface)
 
        writer.write_op(content.globals, OP_VARIABLE, ptr_type_id, block_id, storage);
 
-       if(layout_ql)
+       if(iface.layout)
        {
-               for(const Layout::Qualifier &q: *layout_ql)
+               for(const Layout::Qualifier &q: iface.layout->qualifiers)
                {
                        if(q.name=="set")
                                writer.write_op_decorate(block_id, DECO_DESCRIPTOR_SET, q.value);
index 40f6d4f660b24c84dff02a910951c71c87ad6c4e..2ab4d1b61a197b3ccee9ea849d60c990e8b2427b 100644 (file)
@@ -415,10 +415,27 @@ const TypeDeclaration *get_ultimate_base_type(const TypeDeclaration *type)
        return type;
 }
 
-int get_layout_value(const Layout &layout, const string &name, int def_value)
+bool has_layout_qualifier(const Layout *layout, const string &name)
 {
-       auto i = find_member(layout.qualifiers, name, &Layout::Qualifier::name);
-       return (i!=layout.qualifiers.end() ? i->value : def_value);
+       if(!layout)
+               return false;
+       auto i = find_member(layout->qualifiers, name, &Layout::Qualifier::name);
+       return i!=layout->qualifiers.end();
+}
+
+int get_layout_value(const Layout *layout, const string &name, int def_value)
+{
+       if(!layout)
+               return def_value;
+       auto i = find_member(layout->qualifiers, name, &Layout::Qualifier::name);
+       return (i!=layout->qualifiers.end() ? i->value : def_value);
+}
+
+void add_layout_qualifier(RefPtr<Layout> &layout, const Layout::Qualifier &q)
+{
+       if(!layout)
+               layout = new Layout;
+       layout->qualifiers.push_back(q);
 }
 
 void add_to_chain(Assignment::Target &target, Assignment::Target::ChainType type, unsigned index)
index 499779d91faf2e162a2b47ef0b48ca8ab88fed84..a1c62d4b11aa2a97f5ff2b17af1bed66e51a028c 100644 (file)
@@ -553,7 +553,9 @@ struct Module
 
 std::string get_unused_variable_name(const Block &, const std::string &);
 const TypeDeclaration *get_ultimate_base_type(const TypeDeclaration *);
-int get_layout_value(const Layout &, const std::string &, int = -1);
+bool has_layout_qualifier(const Layout *, const std::string &);
+int get_layout_value(const Layout *, const std::string &, int = -1);
+void add_layout_qualifier(RefPtr<Layout> &, const Layout::Qualifier &);
 void add_to_chain(Assignment::Target &, Assignment::Target::ChainType, unsigned);
 bool targets_overlap(const Assignment::Target &, const Assignment::Target &);
 
index df3312e1fa9f6b46f3fdc52f7e305ded14059bab..6a4b8eb0dc0e34ced99b82fcc08d41c22c569bf0 100644 (file)
@@ -526,8 +526,7 @@ void ExpressionValidator::visit(VariableReference &var)
                        error(var, format("Reference to non-constant variable '%s' in a constant expression", var.name));
                else if(var.declaration->layout && constant_expression==FIXED_CONSTANT)
                {
-                       auto i = find_member(var.declaration->layout->qualifiers, string("constant_id"), &Layout::Qualifier::name);
-                       if(i!=var.declaration->layout->qualifiers.end())
+                       if(has_layout_qualifier(var.declaration->layout.get(), "constant_id"))
                                error(var, format("Reference to specialization constant '%s' in a fixed constant expression", var.name));
                }
        }
@@ -662,13 +661,8 @@ void ExpressionValidator::visit(VariableDeclaration &var)
                var.layout->visit(*this);
        if(var.init_expression)
        {
-               ConstantKind const_kind = (var.constant ? SPEC_CONSTANT : NOT_CONSTANT);
-               if(var.layout)
-               {
-                       auto i = find_member(var.layout->qualifiers, string("constant_id"), &Layout::Qualifier::name);
-                       if(i!=var.layout->qualifiers.end())
-                               const_kind = FIXED_CONSTANT;
-               }
+               ConstantKind const_kind = (!var.constant ? NOT_CONSTANT :
+                       has_layout_qualifier(var.layout.get(), "constant_id") ? FIXED_CONSTANT : SPEC_CONSTANT);
 
                SetForScope<ConstantKind> set_const(constant_expression, const_kind);
                TraversingVisitor::visit(var.init_expression);
@@ -770,18 +764,13 @@ void FlowControlValidator::visit(Iteration &iter)
 }
 
 
-int StageInterfaceValidator::get_location(const Layout &layout)
-{
-       return get_layout_value(layout, "location", -1);
-}
-
 void StageInterfaceValidator::visit(VariableDeclaration &var)
 {
-       int location = (var.layout ? get_location(*var.layout) : -1);
+       int location = get_layout_value(var.layout.get(), "location");
        if(var.interface=="in" && var.linked_declaration)
        {
                const Layout *linked_layout = var.linked_declaration->layout.get();
-               int linked_location = (linked_layout ? get_location(*linked_layout) : -1);
+               int linked_location = get_layout_value(linked_layout, "location");
                if(linked_location!=location)
                {
                        error(var, format("Mismatched location %d for 'in %s'", location, var.name));
@@ -910,10 +899,10 @@ void GlobalInterfaceValidator::visit(VariableDeclaration &var)
                uni.name = var.name;
                if(var.layout)
                {
-                       uni.location = get_layout_value(*var.layout, "location");
+                       uni.location = get_layout_value(var.layout.get(), "location");
                        uni.loc_count = LocationCounter().apply(var);
-                       uni.desc_set = get_layout_value(*var.layout, "set", 0);
-                       uni.bind_point = get_layout_value(*var.layout, "binding");
+                       uni.desc_set = get_layout_value(var.layout.get(), "set", 0);
+                       uni.bind_point = get_layout_value(var.layout.get(), "binding");
                }
 
                uniforms.push_back(uni);
@@ -931,8 +920,8 @@ void GlobalInterfaceValidator::visit(InterfaceBlock &iface)
                uni.name = iface.block_name;
                if(iface.layout)
                {
-                       uni.desc_set = get_layout_value(*iface.layout, "set", 0);
-                       uni.bind_point = get_layout_value(*iface.layout, "binding");
+                       uni.desc_set = get_layout_value(iface.layout.get(), "set", 0);
+                       uni.bind_point = get_layout_value(iface.layout.get(), "binding");
                }
 
                uniforms.push_back(uni);
index 558803ff8277b74902f3dcff65d2cdc454526c50..a09f9f643002b11ecae0bfba1237d07d76121cd9 100644 (file)
@@ -175,8 +175,6 @@ public:
        void apply(Stage &s) { stage = &s; s.content.visit(*this); }
 
 private:
-       int get_location(const Layout &);
-
        virtual void visit(VariableDeclaration &);
        virtual void visit(FunctionDeclaration &) { }
 };