]> git.tdb.fi Git - libs/gl.git/commitdiff
Unify handling of variables and interface blocks in the GLSL compiler
authorMikko Rasa <tdb@tdb.fi>
Sat, 27 Nov 2021 19:25:03 +0000 (21:25 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sat, 27 Nov 2021 19:25:03 +0000 (21:25 +0200)
In SPIR-V interface blocks are just variables with a struct type marked
as block.  Treating them this way in the AST reduces duplcation a fair
bit.

24 files changed:
source/glsl/debug.cpp
source/glsl/debug.h
source/glsl/finalize.cpp
source/glsl/finalize.h
source/glsl/generate.cpp
source/glsl/generate.h
source/glsl/optimize.cpp
source/glsl/optimize.h
source/glsl/output.cpp
source/glsl/output.h
source/glsl/parser.cpp
source/glsl/parser.h
source/glsl/reflect.cpp
source/glsl/reflect.h
source/glsl/resolve.cpp
source/glsl/resolve.h
source/glsl/spirv.cpp
source/glsl/spirv.h
source/glsl/syntax.cpp
source/glsl/syntax.h
source/glsl/validate.cpp
source/glsl/validate.h
source/glsl/visitor.cpp
source/glsl/visitor.h

index ef7e81f68af289943e7348a81edc8eb407637cf6..60b7c2477cf093664f4fc2ac8bcfdb52f56fb5b1 100644 (file)
@@ -183,19 +183,10 @@ void DumpTree::visit(VariableReference &var)
        string text;
        if(var.declaration)
                text += format("%s ", get_label(*var.declaration));
-       text += format("%s (var) -> %s", format_name(var.name), format_type(var.type));
+       text += format("%s -> %s", format_name(var.name), format_type(var.type));
        append(var, text);
 }
 
-void DumpTree::visit(InterfaceBlockReference &iface)
-{
-       string text;
-       if(iface.declaration)
-               text += format("%s ", get_label(*iface.declaration));
-       text += format("%s (iface) -> %s", format_name(iface.name), format_type(iface.type));
-       append(iface, text);
-}
-
 void DumpTree::visit(MemberAccess &memacc)
 {
        string text = "Member access:";
@@ -373,6 +364,8 @@ void DumpTree::visit(StructDeclaration &strct)
 {
        append(strct, format("%s struct %s", get_label(strct), strct.name));
        vector<Branch> branches;
+       if(!strct.block_name.empty())
+               branches.emplace_back(format("Interface block: %s", format_name(strct.block_name)));
        if(strct.extended_alignment)
                branches.emplace_back("Extended alignment");
        branches.emplace_back(&strct.members);
@@ -402,6 +395,8 @@ void DumpTree::visit(VariableDeclaration &var)
        vector<Branch> branches;
        if(var.type_declaration)
                branches.emplace_back(format("Type: %s %s", get_label(*var.type_declaration), format_type(var.type_declaration->name)));
+       if(var.block_declaration)
+               branches.emplace_back(format("Interface block: %s", format_name(var.block_declaration->block_name)));
        if(var.layout)
                branches.emplace_back(var.layout.get());
        if(var.array)
@@ -416,29 +411,6 @@ void DumpTree::visit(VariableDeclaration &var)
        append_subtree(branches);
 }
 
-void DumpTree::visit(InterfaceBlock &iface)
-{
-       string head = format("%s %s %s", get_label(iface), iface.interface, format_name(iface.block_name));
-       if(!iface.instance_name.empty())
-               head += format(" %s", format_name(iface.instance_name));
-       if(iface.array)
-               head += "[]";
-       if(iface.source==BUILTIN_SOURCE)
-               head += " (builtin)";
-       else if(iface.linked_block)
-               head += " (linked)";
-       append(iface, head);
-
-       vector<Branch> branches;
-       if(iface.type_declaration)
-               branches.emplace_back(format("Type: %s %s", get_label(*iface.type_declaration), format_type(iface.type_declaration->name)));
-       if(iface.layout)
-               branches.emplace_back(iface.layout.get());
-       if(iface.members)
-               branches.emplace_back(iface.members.get());
-       append_subtree(branches);
-}
-
 void DumpTree::visit(FunctionDeclaration &func)
 {
        string text = format("%s %s %s%s", get_label(func), format_type(func.return_type), format_name(func.name), (func.signature.empty() ? "(?)" : func.signature));
index 5b2a3d96594460459d34783a93545e22dc23cb01..b3682e7b30a98915ff219aaf09a03113beacc9c3 100644 (file)
@@ -76,7 +76,6 @@ private:
        virtual void visit(Block &);
        virtual void visit(Literal &);
        virtual void visit(VariableReference &);
-       virtual void visit(InterfaceBlockReference &);
        virtual void visit(MemberAccess &);
        virtual void visit(Swizzle &);
        virtual void visit(UnaryExpression &);
@@ -93,7 +92,6 @@ private:
        virtual void visit(ImageTypeDeclaration &);
        virtual void visit(StructDeclaration &);
        virtual void visit(VariableDeclaration &);
-       virtual void visit(InterfaceBlock &);
        virtual void visit(FunctionDeclaration &);
        virtual void visit(Conditional &);
        virtual void visit(Iteration &);
index 52cf95804245767ec1e487619313e87d66ee17dc..5307cff93ed1461d1da9c5eab9de770fd6fcd8b0 100644 (file)
@@ -72,8 +72,8 @@ void LocationAllocator::apply(Module &module, const Features &f, bool a)
        if(features.target_api!=VULKAN)
                allocate_locations("uniform");
 
-       for(InterfaceBlock *b: unbound_blocks)
-               bind_uniform(b->layout, b->block_name, features.uniform_binding_range);
+       for(VariableDeclaration *b: unbound_blocks)
+               bind_uniform(b->layout, b->block_declaration->block_name, features.uniform_binding_range);
        for(VariableDeclaration *t: unbound_textures)
                bind_uniform(t->layout, t->name, features.texture_binding_range);
 }
@@ -198,7 +198,7 @@ void LocationAllocator::visit(VariableDeclaration &var)
        if(!var.name.compare(0, 3, "gl_"))
                return;
 
-       if(!var.interface.empty())
+       if(!var.interface.empty() && !var.block_declaration)
        {
                int location = get_layout_value(var.layout.get(), "location");
 
@@ -223,22 +223,18 @@ void LocationAllocator::visit(VariableDeclaration &var)
 
        if(var.interface=="uniform")
        {
-               const TypeDeclaration *base_type = get_ultimate_base_type(var.type_declaration);
-               if(dynamic_cast<const ImageTypeDeclaration *>(base_type) && !visit_uniform(var.name, var.layout))
-                       unbound_textures.push_back(&var);
-       }
-}
-
-void LocationAllocator::visit(InterfaceBlock &iface)
-{
-       if(!iface.instance_name.compare(0, 3, "gl_"))
-               return;
-
-       if(iface.interface=="uniform")
-       {
-               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);
+               if(var.block_declaration)
+               {
+                       bool push_constant = has_layout_qualifier(var.layout.get(), "push_constant");
+                       if(!push_constant && !visit_uniform(var.block_declaration->block_name, var.layout))
+                               unbound_blocks.push_back(&var);
+               }
+               else
+               {
+                       const TypeDeclaration *base_type = get_ultimate_base_type(var.type_declaration);
+                       if(dynamic_cast<const ImageTypeDeclaration *>(base_type) && !visit_uniform(var.name, var.layout))
+                               unbound_textures.push_back(&var);
+               }
        }
 }
 
@@ -413,11 +409,8 @@ void StructuralFeatureConverter::visit(VariableReference &var)
                var.name = "gl_FragColor";
                var.declaration = 0;
        }
-}
 
-void StructuralFeatureConverter::visit(InterfaceBlockReference &iface)
-{
-       r_flattened_interface = nodes_to_remove.count(iface.declaration);
+       r_flattened_interface = nodes_to_remove.count(var.declaration);
 }
 
 void StructuralFeatureConverter::visit(MemberAccess &memacc)
@@ -486,18 +479,6 @@ void StructuralFeatureConverter::visit(FunctionCall &call)
        TraversingVisitor::visit(call);
 }
 
-void StructuralFeatureConverter::visit(VariableDeclaration &var)
-{
-       if((var.interface=="in" || var.interface=="out") && !supports_unified_interface_syntax())
-               if(stage->type==Stage::FRAGMENT && var.interface=="out")
-               {
-                       frag_out = &var;
-                       nodes_to_remove.insert(&var);
-               }
-
-       TraversingVisitor::visit(var);
-}
-
 bool StructuralFeatureConverter::supports_interface_blocks(const string &iface) const
 {
        if(features.target_api==VULKAN)
@@ -517,27 +498,35 @@ bool StructuralFeatureConverter::supports_interface_blocks(const string &iface)
                return false;
 }
 
-void StructuralFeatureConverter::visit(InterfaceBlock &iface)
+void StructuralFeatureConverter::visit(VariableDeclaration &var)
 {
-       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(var.block_declaration)
        {
-               if(!iface.instance_name.empty())
-                       unsupported("ARB_uniform_buffer_object required for interface block instances");
-               else if(iface.struct_declaration)
+               bool push_constant = has_layout_qualifier(var.layout.get(), "push_constant");
+               if(!supports_interface_blocks(var.interface) || (push_constant && features.target_api!=VULKAN))
                {
-                       for(const RefPtr<Statement> &s: iface.struct_declaration->members.body)
-                               if(VariableDeclaration *var = dynamic_cast<VariableDeclaration *>(s.get()))
-                                       var->interface = iface.interface;
-                       stage->content.body.splice(uniform_insert_point, iface.struct_declaration->members.body);
-                       nodes_to_remove.insert(&iface);
-                       nodes_to_remove.insert(iface.struct_declaration);
+                       if(var.name.find(' ')==string::npos)
+                               unsupported("ARB_uniform_buffer_object required for interface block instances");
+                       else
+                       {
+                               for(const RefPtr<Statement> &s: var.block_declaration->members.body)
+                                       if(VariableDeclaration *mem = dynamic_cast<VariableDeclaration *>(s.get()))
+                                               mem->interface = var.interface;
+                               stage->content.body.splice(uniform_insert_point, var.block_declaration->members.body);
+                               nodes_to_remove.insert(&var);
+                               nodes_to_remove.insert(var.block_declaration);
+                       }
                }
-               else
-                       /* If the interface block is an array, it should have an instance
-                       name too, so this should never be reached */
-                       throw logic_error("Unexpected interface block configuration");
        }
+
+       if((var.interface=="in" || var.interface=="out") && !supports_unified_interface_syntax())
+               if(stage->type==Stage::FRAGMENT && var.interface=="out")
+               {
+                       frag_out = &var;
+                       nodes_to_remove.insert(&var);
+               }
+
+       TraversingVisitor::visit(var);
 }
 
 
@@ -618,6 +607,18 @@ bool QualifierConverter::supports_binding() const
                return check_version(Version(4, 20));
 }
 
+bool QualifierConverter::supports_interface_block_location() const
+{
+       if(features.target_api==VULKAN)
+               return true;
+       else if(features.target_api==OPENGL_ES)
+               return check_version(Version(3, 20));
+       else if(check_version(Version(4, 40)))
+               return true;
+       else
+               return check_extension(&Features::arb_enhanced_layouts);
+}
+
 void QualifierConverter::visit(VariableDeclaration &var)
 {
        if(var.layout)
@@ -628,7 +629,9 @@ void QualifierConverter::visit(VariableDeclaration &var)
                        {
                                bool supported = true;
                                bool external = false;
-                               if(var.interface=="in")
+                               if(var.block_declaration)
+                                       supported = supports_interface_block_location();
+                               else if(var.interface=="in")
                                {
                                        external = (stage->type==Stage::VERTEX);
                                        supported = (external ? supports_interface_layouts() : supports_stage_interface_layouts());
@@ -658,7 +661,9 @@ void QualifierConverter::visit(VariableDeclaration &var)
                        }
                        else if(i->name=="binding" && !supports_binding())
                        {
-                               if(dynamic_cast<const ImageTypeDeclaration *>(get_ultimate_base_type(var.type_declaration)))
+                               if(var.block_declaration)
+                                       stage->uniform_block_bindings[var.block_declaration->block_name] = i->value;
+                               else if(dynamic_cast<const ImageTypeDeclaration *>(get_ultimate_base_type(var.type_declaration)))
                                        stage->texture_bindings[var.name] = i->value;
 
                                i = var.layout->qualifiers.erase(i);
@@ -689,40 +694,6 @@ void QualifierConverter::visit(VariableDeclaration &var)
        TraversingVisitor::visit(var);
 }
 
-bool QualifierConverter::supports_interface_block_location() const
-{
-       if(features.target_api==VULKAN)
-               return true;
-       else if(features.target_api==OPENGL_ES)
-               return check_version(Version(3, 20));
-       else if(check_version(Version(4, 40)))
-               return true;
-       else
-               return check_extension(&Features::arb_enhanced_layouts);
-}
-
-void QualifierConverter::visit(InterfaceBlock &iface)
-{
-       if(iface.layout)
-       {
-               for(auto i=iface.layout->qualifiers.begin(); i!=iface.layout->qualifiers.end(); )
-               {
-                       if(i->name=="location" && !supports_interface_block_location())
-                               i = iface.layout->qualifiers.erase(i);
-                       else if(i->name=="binding" && !supports_binding())
-                       {
-                               stage->uniform_block_bindings[iface.block_name] = i->value;
-                               i = iface.layout->qualifiers.erase(i);
-                       }
-                       else
-                               ++i;
-               }
-
-               if(iface.layout->qualifiers.empty())
-                       iface.layout = 0;
-       }
-}
-
 } // namespace SL
 } // namespace GL
 } // namespace Msp
index f9502954f6b1d6ed9983e403c14414870ae63090..79ba54b81b027c8b16743e0f1281b3e961611319 100644 (file)
@@ -41,7 +41,7 @@ private:
        std::map<unsigned, std::set<unsigned> > used_bindings;
        std::vector<VariableDeclaration *> unplaced_variables;
        std::vector<VariableDeclaration *> unbound_textures;
-       std::vector<InterfaceBlock *> unbound_blocks;
+       std::vector<VariableDeclaration *> unbound_blocks;
 
 public:
        void apply(Module &, const Features &, bool = true);
@@ -53,7 +53,6 @@ private:
 
        bool visit_uniform(const std::string &, RefPtr<Layout> &);
        virtual void visit(VariableDeclaration &);
-       virtual void visit(InterfaceBlock &);
        virtual void visit(FunctionDeclaration &) { }
 };
 
@@ -117,14 +116,12 @@ private:
        bool supports_stage(Stage::Type) const;
        bool supports_unified_interface_syntax() const;
        virtual void visit(VariableReference &);
-       virtual void visit(InterfaceBlockReference &);
        virtual void visit(MemberAccess &);
        virtual void visit(Assignment &);
        bool supports_unified_sampling_functions() const;
        virtual void visit(FunctionCall &);
-       virtual void visit(VariableDeclaration &);
        bool supports_interface_blocks(const std::string &) const;
-       virtual void visit(InterfaceBlock &);
+       virtual void visit(VariableDeclaration &);
 };
 
 /** Converts qualifiers on variables and blocksto match a particular set of
@@ -142,9 +139,8 @@ private:
        bool supports_sample_sampling() const;
        bool supports_uniform_location() const;
        bool supports_binding() const;
-       virtual void visit(VariableDeclaration &);
        bool supports_interface_block_location() const;
-       virtual void visit(InterfaceBlock &);
+       virtual void visit(VariableDeclaration &);
 };
 
 } // namespace SL
index 3175c6c9f206fd0c64b4eb130dc461d6979865cb..0a9e8e85a81380977cdf6cbc27f767d61fcf4ebc 100644 (file)
@@ -100,7 +100,7 @@ VariableDeclaration *InterfaceGenerator::generate_interface(VariableDeclaration
        if(stage->content.variables.count(name))
                return 0;
 
-       if(stage->type==Stage::GEOMETRY && !copy_block && var.interface=="out" && var.array)
+       if(stage->type==Stage::GEOMETRY && var.interface=="out" && var.array)
                return 0;
 
        VariableDeclaration* iface_var = new VariableDeclaration;
@@ -108,9 +108,8 @@ VariableDeclaration *InterfaceGenerator::generate_interface(VariableDeclaration
        iface_var->interface = iface;
        iface_var->type = var.type;
        iface_var->name = name;
-       /* Geometry shader inputs are always arrays.  But if we're bringing in an
-       entire block, the array is on the block and not individual variables. */
-       if(stage->type==Stage::GEOMETRY && !copy_block)
+       // Geometry shader inputs are always arrays.
+       if(stage->type==Stage::GEOMETRY)
                iface_var->array = ((var.array && var.interface!="in") || iface=="in");
        else
                iface_var->array = var.array;
@@ -123,6 +122,21 @@ VariableDeclaration *InterfaceGenerator::generate_interface(VariableDeclaration
                var.linked_declaration = iface_var;
        }
 
+       if(var.block_declaration)
+       {
+               StructDeclaration *iface_type = var.block_declaration->clone();
+               iface_type->name = format("_%s_%s", iface, var.block_declaration->block_name);
+               iface_target_block->body.insert(iface_insert_point, iface_type);
+
+               iface_var->type = iface_type->name;
+               if(name.empty())
+                       iface_var->name = format("%s %s", iface, var.block_declaration->block_name);
+
+               stage->interface_blocks.insert(make_pair("in "+var.block_declaration->block_name, iface_var));
+               if(!name.empty())
+                       stage->interface_blocks.insert(make_pair(name, iface_var));
+       }
+
        iface_target_block->body.insert(iface_insert_point, iface_var);
        iface_target_block->variables.insert(make_pair(name, iface_var));
        if(iface_target_block==&stage->content && iface=="in")
@@ -131,51 +145,26 @@ VariableDeclaration *InterfaceGenerator::generate_interface(VariableDeclaration
        return iface_var;
 }
 
-InterfaceBlock *InterfaceGenerator::generate_interface(InterfaceBlock &out_block)
+ExpressionStatement &InterfaceGenerator::insert_assignment(const string &left, Expression *right)
 {
-       if(stage->interface_blocks.count("in "+out_block.block_name))
-               return 0;
+       Assignment *assign = new Assignment;
 
-       InterfaceBlock *in_block = new InterfaceBlock;
-       in_block->interface = "in";
-       in_block->block_name = out_block.block_name;
-       in_block->members = new Block;
-       in_block->instance_name = out_block.instance_name;
-       if(stage->type==Stage::GEOMETRY)
-               in_block->array = true;
-       else
-               in_block->array = out_block.array;
-       in_block->linked_block = &out_block;
-       out_block.linked_block = in_block;
+       string::size_type dot = left.find('.');
+       VariableReference *ref = new VariableReference;
+       ref->name = left.substr(0, dot);
+       assign->left = ref;
 
+       while(dot!=string::npos)
        {
-               SetFlag set_copy(copy_block, true);
-               SetForScope<Block *> set_target(iface_target_block, in_block->members.get());
-               SetForScope<NodeList<Statement>::iterator> set_ins_pt(iface_insert_point, in_block->members->body.end());
-               if(out_block.struct_declaration)
-                       out_block.struct_declaration->members.visit(*this);
-               else if(out_block.members)
-                       out_block.members->visit(*this);
-       }
-
-       iface_target_block->body.insert(iface_insert_point, in_block);
-       stage->interface_blocks.insert(make_pair("in "+in_block->block_name, in_block));
-       if(!in_block->instance_name.empty())
-               stage->interface_blocks.insert(make_pair(in_block->instance_name, in_block));
+               string::size_type start = dot+1;
+               dot = left.find('.', start);
 
-       SetFlag set_scope(function_scope, false);
-       SetForScope<Block *> set_block(current_block, &stage->content);
-       in_block->visit(*this);
-
-       return in_block;
-}
+               MemberAccess *memacc = new MemberAccess;
+               memacc->left = assign->left;
+               memacc->member = left.substr(start, dot-start);
+               assign->left = memacc;
+       }
 
-ExpressionStatement &InterfaceGenerator::insert_assignment(const string &left, Expression *right)
-{
-       Assignment *assign = new Assignment;
-       VariableReference *ref = new VariableReference;
-       ref->name = left;
-       assign->left = ref;
        assign->oper = &Operator::get_operator("=", Operator::BINARY);
        assign->right = right;
 
@@ -213,24 +202,14 @@ void InterfaceGenerator::visit(VariableReference &var)
                return;
        }
 
-       const map<string, InterfaceBlock *> &prev_blocks = stage->previous->interface_blocks;
-       auto j = prev_blocks.find(var.name);
-       if(j!=prev_blocks.end() && j->second->interface=="out")
-       {
-               generate_interface(*j->second);
-               /* Let VariableResolver convert the variable reference into an interface
-               block reference. */
-               return;
-       }
-
-       for(const auto &kvp: prev_blocks)
-               if(kvp.second->instance_name.empty() && kvp.second->struct_declaration)
+       for(const auto &kvp: stage->previous->interface_blocks)
+               if(kvp.first.find(' ')!=string::npos)
                {
-                       const map<string, VariableDeclaration *> &iface_vars = kvp.second->struct_declaration->members.variables;
+                       const map<string, VariableDeclaration *> &iface_vars = kvp.second->block_declaration->members.variables;
                        i = iface_vars.find(var.name);
                        if(i!=iface_vars.end())
                        {
-                               generate_interface(*kvp.second);
+                               generate_interface(*kvp.second, "in", string());
                                return;
                        }
                }
@@ -238,9 +217,7 @@ void InterfaceGenerator::visit(VariableReference &var)
 
 void InterfaceGenerator::visit(VariableDeclaration &var)
 {
-       if(copy_block)
-               generate_interface(var, "in", var.name);
-       else if(var.interface=="out")
+       if(var.interface=="out")
        {
                /* For output variables in function scope, generate a global interface
                and replace the local declaration with an assignment. */
@@ -268,38 +245,30 @@ void InterfaceGenerator::visit(VariableDeclaration &var)
                previous stage. */
                if(!var.linked_declaration && stage->previous)
                {
-                       const map<string, VariableDeclaration *> &prev_vars = stage->previous->content.variables;
-                       auto i = prev_vars.find(var.name);
-                       if(i!=prev_vars.end() && i->second->interface=="out")
+                       const map<string, VariableDeclaration *> *prev_vars;
+                       string name;
+                       // Blocks are linked by their block name, not instance name
+                       if(var.block_declaration)
                        {
-                               var.linked_declaration = i->second;
-                               i->second->linked_declaration = &var;
+                               prev_vars = &stage->previous->interface_blocks;
+                               name = "out "+var.block_declaration->block_name;
+                       }
+                       else
+                       {
+                               prev_vars = &stage->previous->content.variables;
+                               name = var.name;
                        }
-               }
-       }
-
-       TraversingVisitor::visit(var);
-}
 
-void InterfaceGenerator::visit(InterfaceBlock &iface)
-{
-       if(iface.interface=="in")
-       {
-               /* Try to link input blocks with output blocks sharing the same block
-               name from previous stage. */
-               if(!iface.linked_block && stage->previous)
-               {
-                       const map<string, InterfaceBlock *> &prev_blocks = stage->previous->interface_blocks;
-                       auto i = prev_blocks.find("out "+iface.block_name);
-                       if(i!=prev_blocks.end())
+                       auto i = prev_vars->find(name);
+                       if(i!=prev_vars->end() && i->second->interface=="out")
                        {
-                               iface.linked_block = i->second;
-                               i->second->linked_block = &iface;
+                               var.linked_declaration = i->second;
+                               i->second->linked_declaration = &var;
                        }
                }
        }
 
-       TraversingVisitor::visit(iface);
+       TraversingVisitor::visit(var);
 }
 
 void InterfaceGenerator::visit(FunctionDeclaration &func)
@@ -332,7 +301,7 @@ void InterfaceGenerator::visit(Passthrough &pass)
        {
                /* Special case for geometry shader: copy gl_Position from input to
                output. */
-               InterfaceBlockReference *ref = new InterfaceBlockReference;
+               VariableReference *ref = new VariableReference;
                ref->name = "gl_in";
 
                BinaryExpression *subscript = new BinaryExpression;
@@ -344,7 +313,7 @@ void InterfaceGenerator::visit(Passthrough &pass)
                memacc->left = subscript;
                memacc->member = "gl_Position";
 
-               insert_assignment("gl_Position", memacc);
+               insert_assignment("out gl_PerVertex.gl_Position", memacc);
        }
 
        for(VariableDeclaration *v: pass_vars)
index d828daa5172716cb6c173e129cd5c8d6126fb452..73b933bfb63b0f04155c80ab2bb7e484f2529f03 100644 (file)
@@ -56,11 +56,9 @@ private:
        std::string change_prefix(const std::string &, const std::string &) const;
        virtual void visit(Block &);
        VariableDeclaration *generate_interface(VariableDeclaration &, const std::string &, const std::string &);
-       InterfaceBlock *generate_interface(InterfaceBlock &);
        ExpressionStatement &insert_assignment(const std::string &, Expression *);
        virtual void visit(VariableReference &);
        virtual void visit(VariableDeclaration &);
-       virtual void visit(InterfaceBlock &);
        virtual void visit(FunctionDeclaration &);
        virtual void visit(Passthrough &);
 };
index da95158903d2fea799d1aba55c3faca0762f7434..1b9b41de20e07a63ff38cb7e6f984d7311df9664 100644 (file)
@@ -191,12 +191,6 @@ void InlineContentInjector::visit(VariableReference &var)
                referenced_names.insert(var.name);
 }
 
-void InlineContentInjector::visit(InterfaceBlockReference &iface)
-{
-       if(pass==REFERENCED)
-               referenced_names.insert(iface.name);
-}
-
 void InlineContentInjector::visit(FunctionCall &call)
 {
        if(pass==REFERENCED)
@@ -1246,11 +1240,6 @@ void UnusedTypeRemover::visit(VariableDeclaration &var)
        TraversingVisitor::visit(var);
 }
 
-void UnusedTypeRemover::visit(InterfaceBlock &iface)
-{
-       unused_nodes.erase(iface.type_declaration);
-}
-
 void UnusedTypeRemover::visit(FunctionDeclaration &func)
 {
        unused_nodes.erase(func.return_type_declaration);
@@ -1313,14 +1302,6 @@ void UnusedVariableRemover::visit(VariableReference &var)
                referenced(var.declaration, var);
 }
 
-void UnusedVariableRemover::visit(InterfaceBlockReference &iface)
-{
-       if(composite_reference)
-               r_reference.declaration = iface.declaration;
-       else if(iface.declaration)
-               referenced(iface.declaration, iface);
-}
-
 void UnusedVariableRemover::visit_composite(Expression &expr)
 {
        if(!composite_reference)
@@ -1474,7 +1455,8 @@ void UnusedVariableRemover::visit(VariableDeclaration &var)
 
        /* Mark variables as output if they're used by the next stage or the
        graphics API. */
-       var_info.output = (var.interface=="out" && (stage->type==Stage::FRAGMENT || var.linked_declaration || !var.name.compare(0, 3, "gl_")));
+       bool builtin = (!var.name.compare(0, 3, "gl_") || (var.block_declaration && !var.block_declaration->block_name.compare(0, 3, "gl_")));
+       var_info.output = (var.interface=="out" && (stage->type==Stage::FRAGMENT || var.linked_declaration || builtin));
 
        // Linked outputs are automatically referenced.
        if(var_info.output && var.linked_declaration)
@@ -1487,12 +1469,6 @@ void UnusedVariableRemover::visit(VariableDeclaration &var)
        }
 }
 
-void UnusedVariableRemover::visit(InterfaceBlock &iface)
-{
-       VariableInfo &var_info = variables[&iface];
-       var_info.output = (iface.interface=="out" && (iface.linked_block || !iface.block_name.compare(0, 3, "gl_")));
-}
-
 void UnusedVariableRemover::merge_variables(const BlockVariableMap &other_vars)
 {
        for(const auto &kvp: other_vars)
index 75fffa13bb4fcaf6527d56ab676a7b88553cb8c5..33998e5e7408197b696203f1d6143e9f85f759cf 100644 (file)
@@ -71,7 +71,6 @@ public:
 
 private:
        virtual void visit(VariableReference &);
-       virtual void visit(InterfaceBlockReference &);
        virtual void visit(FunctionCall &);
        virtual void visit(VariableDeclaration &);
        virtual void visit(Return &);
@@ -195,7 +194,6 @@ private:
        virtual void visit(BinaryExpression &);
        virtual void visit(StructDeclaration &) { }
        virtual void visit(VariableDeclaration &);
-       virtual void visit(InterfaceBlock &) { }
        virtual void visit(FunctionDeclaration &);
 };
 
@@ -311,7 +309,6 @@ private:
        virtual void visit(ImageTypeDeclaration &);
        virtual void visit(StructDeclaration &);
        virtual void visit(VariableDeclaration &);
-       virtual void visit(InterfaceBlock &);
        virtual void visit(FunctionDeclaration &);
 };
 
@@ -357,7 +354,6 @@ public:
 private:
        void referenced(const Assignment::Target &, Node &);
        virtual void visit(VariableReference &);
-       virtual void visit(InterfaceBlockReference &);
        void visit_composite(Expression &);
        virtual void visit(MemberAccess &);
        virtual void visit(Swizzle &);
@@ -370,7 +366,6 @@ private:
        virtual void visit(ExpressionStatement &);
        virtual void visit(StructDeclaration &);
        virtual void visit(VariableDeclaration &);
-       virtual void visit(InterfaceBlock &);
        void merge_variables(const BlockVariableMap &);
        virtual void visit(FunctionDeclaration &);
        virtual void visit(Conditional &);
index 6b76167468b73d52b16d67e78995dc0961c6c62d..07da64e3ba565cdca64a8bb9f58b5d34f11c11eb 100644 (file)
@@ -144,15 +144,9 @@ void Formatter::visit(Literal &literal)
 
 void Formatter::visit(VariableReference &var)
 {
-       append(var.name);
-       r_empty_name = false;
-}
-
-void Formatter::visit(InterfaceBlockReference &iface)
-{
-       r_empty_name = iface.declaration->instance_name.empty();
+       r_empty_name = var.name.find(' ')!=string::npos;
        if(!r_empty_name)
-               append(iface.declaration->instance_name);
+               append(var.name);
 }
 
 void Formatter::visit(MemberAccess &memacc)
@@ -255,6 +249,9 @@ void Formatter::visit(InterfaceLayout &layout)
 
 void Formatter::visit(StructDeclaration &strct)
 {
+       if(!strct.block_name.empty())
+               return;
+
        append(format("struct %s\n", strct.name));
        strct.members.visit(*this);
        append(';');
@@ -287,10 +284,22 @@ void Formatter::visit(VariableDeclaration &var)
        }
        if(!var.precision.empty())
                append(format("%s ", var.precision));
-       string type_name = var.type_declaration->name;
-       if(var.array)
-               type_name = type_name.substr(0, type_name.find('['));
-       append(format("%s %s", type_name, var.name));
+
+       if(var.block_declaration)
+       {
+               append(format("%s\n", var.block_declaration->block_name));
+               var.block_declaration->members.visit(*this);
+               if(var.name.find(' ')==string::npos)
+                       append(format(" %s", var.name));
+       }
+       else
+       {
+               string type_name = var.type_declaration->name;
+               if(var.array)
+                       type_name = type_name.substr(0, type_name.find('['));
+               append(format("%s %s", type_name, var.name));
+       }
+
        if(var.array)
        {
                append('[');
@@ -307,26 +316,6 @@ void Formatter::visit(VariableDeclaration &var)
                append(';');
 }
 
-void Formatter::visit(InterfaceBlock &iface)
-{
-       if(iface.layout)
-       {
-               iface.layout->visit(*this);
-               append(' ');
-       }
-       append(format("%s %s\n", iface.interface, iface.block_name));
-       if(iface.struct_declaration)
-               iface.struct_declaration->members.visit(*this);
-       if(!iface.instance_name.empty())
-       {
-               append(' ');
-               append(iface.instance_name);
-               if(iface.array)
-                       append("[]");
-       }
-       append(';');
-}
-
 void Formatter::visit(FunctionDeclaration &func)
 {
        append(format("%s %s(", func.return_type_declaration->name, func.name));
index dbdd888e5923aa69355c9fe75923bcadf7e12c61..ec794912adfd55c8d42d49b806bc0ce292be0ecc 100644 (file)
@@ -34,7 +34,6 @@ private:
        void visit_expression(Expression &, const Operator *, bool);
        virtual void visit(Literal &);
        virtual void visit(VariableReference &);
-       virtual void visit(InterfaceBlockReference &);
        virtual void visit(MemberAccess &);
        virtual void visit(Swizzle &);
        virtual void visit(UnaryExpression &);
@@ -49,7 +48,6 @@ private:
        virtual void visit(InterfaceLayout &);
        virtual void visit(StructDeclaration &);
        virtual void visit(VariableDeclaration &);
-       virtual void visit(InterfaceBlock &);
        virtual void visit(FunctionDeclaration &);
        virtual void visit(Conditional &);
        virtual void visit(Iteration &);
index 46bee183f9c061330dc984efd3e88d7ef6773202..8c10c443002e130fa01f42b32ceb18cbe5f4d772 100644 (file)
@@ -66,7 +66,14 @@ void Parser::parse_source(const string &name, int index)
        allow_stage_change = true;
        while(!tokenizer.peek_token().empty())
                if(RefPtr<Statement> statement = parse_with_recovery(&Parser::parse_global_declaration))
+               {
                        cur_stage->content.body.push_back(statement);
+                       if(next_global_declaration)
+                       {
+                               cur_stage->content.body.push_back(next_global_declaration);
+                               next_global_declaration = 0;
+                       }
+               }
 
        if(!errors.empty())
                throw invalid_shader_source(join(errors.begin(), errors.end(), "\n"));
@@ -99,6 +106,11 @@ void Parser::stage_change(Stage::Type stage)
        cur_stage = &module->stages.back();
 
        stage_types.clear();
+       if(const Stage *builtin = get_builtins(stage))
+       {
+               for(const auto &kvp: builtin->types)
+                       stage_types.insert(kvp.first);
+       }
        for(const Module *m: imported_modules)
        {
                auto j = find_member(m->stages, stage, &Stage::type);
@@ -275,9 +287,11 @@ RefPtr<Statement> Parser::parse_global_declaration()
                }
                else if(is_interface_qualifier(token) && tokenizer.peek_token(2)=="{")
                {
-                       RefPtr<InterfaceBlock> iface = parse_interface_block();
-                       iface->layout = layout;
-                       return iface;
+                       RefPtr<StructDeclaration> iface_strct = parse_interface_block();
+                       VariableDeclaration *iface_var = iface_strct->block_declaration;
+                       iface_var->layout = layout;
+                       next_global_declaration = iface_var;
+                       return iface_strct;
                }
                else
                {
@@ -296,7 +310,11 @@ RefPtr<Statement> Parser::parse_global_declaration()
                if(is_type(next) || is_qualifier(next))
                        return parse_variable_declaration();
                else
-                       return parse_interface_block();
+               {
+                       RefPtr<StructDeclaration> iface_strct = parse_interface_block();
+                       next_global_declaration = iface_strct->block_declaration;
+                       return iface_strct;
+               }
        }
        else if(is_qualifier(token))
                return parse_variable_declaration();
@@ -811,29 +829,39 @@ RefPtr<FunctionDeclaration> Parser::parse_function_declaration()
        return func;
 }
 
-RefPtr<InterfaceBlock> Parser::parse_interface_block()
+RefPtr<StructDeclaration> Parser::parse_interface_block()
 {
-       RefPtr<InterfaceBlock> iface = create_node<InterfaceBlock>();
-
-       iface->interface = tokenizer.parse_token();
-       if(!is_interface_qualifier(iface->interface))
-               throw parse_error(tokenizer.get_location(), iface->interface, "an interface qualifier");
+       RefPtr<StructDeclaration> strct = create_node<StructDeclaration>();
+       RefPtr<VariableDeclaration> var = create_node<VariableDeclaration>();
 
-       iface->block_name = expect_identifier();
-       iface->members = new Block;
-       parse_block(*iface->members, true, &Parser::parse_variable_declaration_with_layout);
+       var->interface = tokenizer.parse_token();
+       if(!is_interface_qualifier(var->interface))
+               throw parse_error(tokenizer.get_location(), var->interface, "an interface qualifier");
+
+       strct->block_name = expect_identifier();
+       string name_base = format("_%s_%s", var->interface, strct->block_name);
+       strct->name = name_base;
+       for(unsigned i=1; (stage_types.count(strct->name) || global_types.count(strct->name)); ++i)
+               strct->name = format("%s_%d", name_base, i);
+       var->type = strct->name;
+       parse_block(strct->members, true, &Parser::parse_variable_declaration_with_layout);
        if(!check(";"))
        {
-               iface->instance_name = expect_identifier();
+               var->name = expect_identifier();
                if(check("["))
                {
-                       iface->array = true;
+                       var->array = true;
                        tokenizer.expect("]");
                }
                tokenizer.expect(";");
        }
+       else
+               var->name = format("%s %s", var->interface, strct->block_name);
+
+       strct->block_declaration = var.release();
+       add_type(*strct);
 
-       return iface;
+       return strct;
 }
 
 RefPtr<Conditional> Parser::parse_conditional()
index b35b8bbe084d73b888efbb7431f3e57b82ca660c..51616378c29c947653496ca71be80640081e55f4 100644 (file)
@@ -30,6 +30,7 @@ private:
        std::set<std::string> global_types;
        std::set<std::string> stage_types;
        std::vector<std::string> errors;
+       RefPtr<Statement> next_global_declaration;
 
 public:
        Parser(ModuleCache *);
@@ -87,7 +88,7 @@ private:
        RefPtr<VariableDeclaration> parse_variable_declaration();
        RefPtr<VariableDeclaration> parse_variable_declaration_with_layout();
        RefPtr<FunctionDeclaration> parse_function_declaration();
-       RefPtr<InterfaceBlock> parse_interface_block();
+       RefPtr<StructDeclaration> parse_interface_block();
        RefPtr<Conditional> parse_conditional();
        RefPtr<Iteration> parse_for();
        RefPtr<Iteration> parse_while();
index 21f12d0eb1c57b25491832651d9812aac0beb55b..643c42e79be90f51f07009df7343ce67df80f09e 100644 (file)
@@ -348,15 +348,6 @@ void DependencyCollector::visit(VariableReference &var)
        }
 }
 
-void DependencyCollector::visit(InterfaceBlockReference &iface)
-{
-       if(iface.declaration)
-       {
-               dependencies.insert(iface.declaration);
-               iface.declaration->visit(*this);
-       }
-}
-
 void DependencyCollector::visit(FunctionCall &call)
 {
        if(call.declaration)
@@ -402,12 +393,6 @@ void AssignmentCollector::visit(VariableReference &var)
                assigned_variables.insert(var.declaration);
 }
 
-void AssignmentCollector::visit(InterfaceBlockReference &iface)
-{
-       if(assignment_target)
-               assigned_variables.insert(iface.declaration);
-}
-
 void AssignmentCollector::visit(UnaryExpression &unary)
 {
        SetFlag set_assignment(assignment_target, (unary.oper->token[1]=='+' || unary.oper->token[1]=='-'));
index 7c4d26c47fe6714321d2d50588e877053c3bcb5b..6e6f9d8316bf2c5af1522a03b097bf301c057df6 100644 (file)
@@ -98,7 +98,6 @@ public:
 
 private:
        virtual void visit(VariableReference &);
-       virtual void visit(InterfaceBlockReference &);
        virtual void visit(FunctionCall &);
        virtual void visit(VariableDeclaration &);
        virtual void visit(FunctionDeclaration &);
@@ -115,7 +114,6 @@ public:
 
 private:
        virtual void visit(VariableReference &);
-       virtual void visit(InterfaceBlockReference &);
        virtual void visit(UnaryExpression &);
        virtual void visit(BinaryExpression &);
        virtual void visit(Assignment &);
index 2f3192d77fa423a2f8fa3fb6587d283eec9da5a0..3aeab30bd703711d28909cea07b15adc4fc1318d 100644 (file)
@@ -105,13 +105,32 @@ void TypeResolver::visit(ImageTypeDeclaration &type)
 void TypeResolver::visit(StructDeclaration &strct)
 {
        stage->types.insert(make_pair(strct.name, &strct));
-       SetForScope<InterfaceBlock *> set_iface(iface_block, strct.interface_block);
-       TraversingVisitor::visit(strct);
+       if(strct.block_name.empty())
+       {
+               SetForScope<VariableDeclaration *> set_iface(iface_block, strct.block_declaration);
+               TraversingVisitor::visit(strct);
+       }
+       else
+               block_member_type_ins_pt = type_insert_point;
 }
 
 void TypeResolver::visit(VariableDeclaration &var)
 {
        resolve_type(var.type_declaration, var.type, var.array);
+
+       var.block_declaration = 0;
+       if(StructDeclaration *strct = dynamic_cast<StructDeclaration *>(get_ultimate_base_type(var.type_declaration)))
+               if(!strct->block_name.empty())
+               {
+                       var.block_declaration = strct;
+                       strct->block_declaration = &var;
+                       strct->extended_alignment = true;
+
+                       SetForScope<NodeList<Statement>::iterator> set_ins_pt(type_insert_point, block_member_type_ins_pt);
+                       SetForScope<VariableDeclaration *> set_iface(iface_block, &var);
+                       TraversingVisitor::visit(*strct);
+               }
+
        if(iface_block)
        {
                if(var.interface==iface_block->interface)
@@ -121,33 +140,6 @@ void TypeResolver::visit(VariableDeclaration &var)
        }
 }
 
-void TypeResolver::visit(InterfaceBlock &iface)
-{
-       if(iface.members)
-       {
-               SetForScope<InterfaceBlock *> set_iface(iface_block, &iface);
-               iface.members->visit(*this);
-
-               StructDeclaration *strct = new StructDeclaration;
-               strct->source = INTERNAL_SOURCE;
-               strct->name = format("_%s_%s", iface.interface, iface.block_name);
-               strct->members.body.splice(strct->members.body.begin(), iface.members->body);
-               strct->extended_alignment = true;
-               stage->content.body.insert(type_insert_point, strct);
-               stage->types.insert(make_pair(strct->name, strct));
-
-               iface.members = 0;
-               strct->interface_block = &iface;
-               iface.struct_declaration = strct;
-       }
-
-       TypeDeclaration *type = iface.struct_declaration;
-       if(type && iface.array)
-               type = get_or_create_array_type(*type);
-       r_any_resolved = (type!=iface.type_declaration);
-       iface.type_declaration = type;
-}
-
 void TypeResolver::visit(FunctionDeclaration &func)
 {
        resolve_type(func.return_type_declaration, func.return_type, false);
@@ -222,30 +214,16 @@ void VariableResolver::visit(VariableReference &var)
 
        if(!declaration)
        {
-               const map<string, InterfaceBlock *> &blocks = stage->interface_blocks;
-               auto i = blocks.find(var.name);
-               if(i==blocks.end())
-               {
-                       // Look for the variable in anonymous interface blocks.
-                       for(i=blocks.begin(); i!=blocks.end(); ++i)
-                               if(i->second->instance_name.empty() && i->second->struct_declaration)
-                                       if(i->second->struct_declaration->members.variables.count(var.name))
-                                               break;
-               }
-
-               if(i!=blocks.end())
-               {
-                       /* The name refers to either an interface block with an instance name
-                       or a variable declared inside an anonymous interface block.  Prepare
-                       new syntax tree nodes accordingly. */
-                       InterfaceBlockReference *iface_ref = new InterfaceBlockReference;
-                       iface_ref->source = var.source;
-                       iface_ref->line = var.line;
-                       iface_ref->declaration = i->second;
-
-                       if(i->second->instance_name.empty())
+               for(const auto &kvp: stage->interface_blocks)
+                       if(kvp.second->name.find(' ')!=string::npos && kvp.second->block_declaration->members.variables.count(var.name))
                        {
-                               iface_ref->name = format("%s %s", i->second->interface, i->second->block_name);
+                               /* The name refers a member of an anonymous interface block.  Prepare
+                               new syntax tree nodes accordingly. */
+                               VariableReference *iface_ref = new VariableReference;
+                               iface_ref->name = kvp.first;
+                               iface_ref->source = var.source;
+                               iface_ref->line = var.line;
+                               iface_ref->declaration = kvp.second;
 
                                MemberAccess *memacc = new MemberAccess;
                                memacc->source = var.source;
@@ -254,13 +232,8 @@ void VariableResolver::visit(VariableReference &var)
                                memacc->member = var.name;
 
                                r_replacement_expr = memacc;
+                               break;
                        }
-                       else
-                       {
-                               iface_ref->name = var.name;
-                               r_replacement_expr = iface_ref;
-                       }
-               }
        }
 
        r_any_resolved |= (declaration!=var.declaration);
@@ -269,16 +242,6 @@ void VariableResolver::visit(VariableReference &var)
        check_assignment_target(var.declaration);
 }
 
-void VariableResolver::visit(InterfaceBlockReference &iface)
-{
-       auto i = stage->interface_blocks.find(iface.name);
-       InterfaceBlock *declaration = (i!=stage->interface_blocks.end() ? i->second : 0);
-       r_any_resolved |= (declaration!=iface.declaration);
-       iface.declaration = declaration;
-
-       check_assignment_target(iface.declaration);
-}
-
 void VariableResolver::visit(MemberAccess &memacc)
 {
        TraversingVisitor::visit(memacc);
@@ -421,20 +384,20 @@ void VariableResolver::visit(VariableDeclaration &var)
 
        auto i = current_block->variables.find(var.name);
        VariableDeclaration *existing = 0;
-       InterfaceBlock *block = 0;
+       VariableDeclaration *block = 0;
        if(i!=current_block->variables.end())
                existing = i->second;
        else if(!current_block->parent)
        {
-               const map<string, InterfaceBlock *> &blocks = stage->interface_blocks;
+               const map<string, VariableDeclaration *> &blocks = stage->interface_blocks;
                for(auto j=blocks.begin(); j!=blocks.end(); ++j)
-                       if(j->second->instance_name.empty() && j->second->struct_declaration)
+                       if(j->second->name.find(' ')!=string::npos)
                        {
-                               map<string, VariableDeclaration *> &block_vars = j->second->struct_declaration->members.variables;
-                               i = block_vars.find(var.name);
-                               if(i!=block_vars.end())
+                               const map<string, VariableDeclaration *> &block_vars = j->second->block_declaration->members.variables;
+                               auto k = block_vars.find(var.name);
+                               if(k!=block_vars.end())
                                {
-                                       existing = i->second;
+                                       existing = k->second;
                                        block = j->second;
                                        break;
                                }
@@ -442,24 +405,60 @@ void VariableResolver::visit(VariableDeclaration &var)
        }
 
        if(!existing)
+       {
                current_block->variables.insert(make_pair(var.name, &var));
-       else if(!current_block->parent && (block ? block->interface : existing->interface)==var.interface && existing->type==var.type && existing->array==var.array)
+               if(var.block_declaration)
+               {
+                       stage->interface_blocks.insert(make_pair(format("%s %s", var.interface, var.block_declaration->block_name), &var));
+                       if(var.name.find(' ')==string::npos)
+                               stage->interface_blocks.insert(make_pair(var.name, &var));
+               }
+       }
+       else if(!current_block->parent && (block ? block->interface : existing->interface)==var.interface && existing->array==var.array)
        {
                if(existing->source==BUILTIN_SOURCE)
                {
-                       redeclare_builtin(*existing, var);
-
-                       if(block)
+                       if(var.block_declaration && existing->block_declaration && var.block_declaration->block_name==existing->block_declaration->block_name)
                        {
-                               redeclared_builtins.push_back(block);
-                               for(const auto &kvp: block->struct_declaration->members.variables)
-                                       redeclared_builtins.push_back(kvp.second);
+                               const map<string, VariableDeclaration *> &vars = var.block_declaration->members.variables;
+                               const map<string, VariableDeclaration *> &existing_vars = existing->block_declaration->members.variables;
+
+                               bool found_all = true;
+                               for(const auto &kvp: vars)
+                               {
+                                       auto j = existing_vars.find(kvp.first);
+                                       if(j!=existing_vars.end() && j->second->type==kvp.second->type && j->second->array==kvp.second->array)
+                                               redeclare_builtin(*j->second, *kvp.second);
+                                       else
+                                               found_all = false;
+                               }
+
+                               if(found_all)
+                               {
+                                       redeclared_builtins.push_back(existing);
+                                       nodes_to_remove.insert(&var);
+                                       // The block struct will be removed during unused type removal
+                                       //nodes_to_remove.insert(var.block_declaration);
+                               }
                        }
+                       else if(!var.block_declaration && !existing->block_declaration && var.type==existing->type)
+                       {
+                               redeclare_builtin(*existing, var);
 
-                       nodes_to_remove.insert(&var);
-                       r_any_resolved = true;
+                               if(block)
+                               {
+                                       /* Cause the block and its members to be marked as not builtin
+                                       so it will be emitted in output */
+                                       redeclared_builtins.push_back(block);
+                                       for(const auto &kvp: block->block_declaration->members.variables)
+                                               redeclared_builtins.push_back(kvp.second);
+                               }
+
+                               nodes_to_remove.insert(&var);
+                               r_any_resolved = true;
+                       }
                }
-               else if(existing->array && !existing->array_size && !var.layout && !var.init_expression)
+               else if(existing->array && !existing->array_size && var.type==existing->type && !var.layout && !var.init_expression)
                {
                        existing->array_size = var.array_size;
                        nodes_to_remove.insert(&var);
@@ -468,47 +467,6 @@ void VariableResolver::visit(VariableDeclaration &var)
        }
 }
 
-void VariableResolver::visit(InterfaceBlock &iface)
-{
-       string key = format("%s %s", iface.interface, iface.block_name);
-       auto i = stage->interface_blocks.find(key);
-       if(i!=stage->interface_blocks.end())
-       {
-               if(i->second->source==BUILTIN_SOURCE && iface.struct_declaration && i->second->struct_declaration)
-               {
-                       const map<string, VariableDeclaration *> &vars = iface.struct_declaration->members.variables;
-                       const map<string, VariableDeclaration *> &existing_vars = i->second->struct_declaration->members.variables;
-
-                       bool found_all = true;
-                       for(const auto &kvp: vars)
-                       {
-                               auto j = existing_vars.find(kvp.first);
-                               if(j!=existing_vars.end() && j->second->type==kvp.second->type && j->second->array==kvp.second->array)
-                                       redeclare_builtin(*j->second, *kvp.second);
-                               else
-                                       found_all = false;
-                       }
-
-                       if(found_all)
-                       {
-                               redeclared_builtins.push_back(i->second);
-                               nodes_to_remove.insert(&iface);
-                               nodes_to_remove.insert(iface.struct_declaration);
-                       }
-               }
-       }
-       else
-       {
-               /* Block names can be reused in different interfaces.  Prepend the interface
-               to the name to avoid conflicts. */
-               stage->interface_blocks.insert(make_pair(key, &iface));
-               if(!iface.instance_name.empty())
-                       stage->interface_blocks.insert(make_pair(iface.instance_name, &iface));
-       }
-
-       TraversingVisitor::visit(iface);
-}
-
 
 bool ExpressionResolver::apply(Stage &s)
 {
@@ -630,12 +588,6 @@ void ExpressionResolver::visit(VariableReference &var)
                resolve(var, var.declaration->type_declaration, true);
 }
 
-void ExpressionResolver::visit(InterfaceBlockReference &iface)
-{
-       if(iface.declaration)
-               resolve(iface, iface.declaration->type_declaration, true);
-}
-
 void ExpressionResolver::visit(MemberAccess &memacc)
 {
        TraversingVisitor::visit(memacc);
index 92a7c336de71fbbb8a217dd7ece8dd29040c4ea2..36af54578da987b53fafcdabaffc3d6130b57a55 100644 (file)
@@ -32,7 +32,8 @@ private:
        std::map<TypeDeclaration *, TypeDeclaration *> alias_map;
        std::map<std::pair<TypeDeclaration *, bool>, TypeDeclaration *> array_types;
        NodeList<Statement>::iterator type_insert_point;
-       InterfaceBlock *iface_block = 0;
+       NodeList<Statement>::iterator block_member_type_ins_pt;
+       VariableDeclaration *iface_block = 0;
        bool r_any_resolved = false;
 
 public:
@@ -46,12 +47,10 @@ private:
        virtual void visit(ImageTypeDeclaration &);
        virtual void visit(StructDeclaration &);
        virtual void visit(VariableDeclaration &);
-       virtual void visit(InterfaceBlock &);
        virtual void visit(FunctionDeclaration &);
 };
 
-/** Resolves variable references.  Variable references which match the name
-of an interface block are turned into interface block references. */
+/** Resolves variable references. */
 class VariableResolver: private TraversingVisitor
 {
 private:
@@ -72,7 +71,6 @@ private:
        virtual void visit(RefPtr<Expression> &);
        void check_assignment_target(Statement *);
        virtual void visit(VariableReference &);
-       virtual void visit(InterfaceBlockReference &);
        virtual void visit(MemberAccess &);
        virtual void visit(Swizzle &);
        virtual void visit(BinaryExpression &);
@@ -80,7 +78,6 @@ private:
        void merge_layouts(Layout &, const Layout &);
        void redeclare_builtin(VariableDeclaration &, VariableDeclaration &);
        virtual void visit(VariableDeclaration &);
-       virtual void visit(InterfaceBlock &);
 };
 
 /** Resolves types and lvalueness of expressions. */
@@ -122,7 +119,6 @@ private:
        virtual void visit(Block &);
        virtual void visit(Literal &);
        virtual void visit(VariableReference &);
-       virtual void visit(InterfaceBlockReference &);
        virtual void visit(MemberAccess &);
        virtual void visit(Swizzle &);
        virtual void visit(UnaryExpression &);
index 481f38fb5ae729b3a16b03725ec7c1f7dd9c71cf..4828a00c452ad1e35e54156f97dfaf2ef4a4ffd8 100644 (file)
@@ -541,16 +541,6 @@ void SpirVGenerator::visit(VariableReference &var)
                r_expression_result_id = get_load_id(*var.declaration);
 }
 
-void SpirVGenerator::visit(InterfaceBlockReference &iface)
-{
-       if(!composite_access || !current_function)
-               throw internal_error("invalid interface block reference");
-
-       r_composite_base = iface.declaration;
-       r_expression_result_id = 0;
-       r_constant_result = false;
-}
-
 void SpirVGenerator::generate_composite_access(TypeDeclaration &result_type)
 {
        Opcode opcode;
@@ -1528,10 +1518,10 @@ void SpirVGenerator::visit(StructDeclaration &strct)
        Id type_id = allocate_id(strct, 0);
        writer.write_op_name(type_id, strct.name);
 
-       if(strct.interface_block)
+       if(!strct.block_name.empty())
                writer.write_op_decorate(type_id, DECO_BLOCK);
 
-       bool builtin = (strct.interface_block && !strct.interface_block->block_name.compare(0, 3, "gl_"));
+       bool builtin = !strct.block_name.compare(0, 3, "gl_");
        vector<Id> member_type_ids;
        member_type_ids.reserve(strct.members.body.size());
        for(const RefPtr<Statement> &s: strct.members.body)
@@ -1615,11 +1605,20 @@ void SpirVGenerator::visit(VariableDeclaration &var)
        }
        else
        {
-               StorageClass storage = (current_function ? STORAGE_FUNCTION : get_interface_storage(var.interface, false));
+               bool push_const = has_layout_qualifier(var.layout.get(), "push_constant");
+
+               StorageClass storage;
+               if(current_function)
+                       storage = STORAGE_FUNCTION;
+               else if(push_const)
+                       storage = STORAGE_PUSH_CONSTANT;
+               else
+                       storage = get_interface_storage(var.interface, var.block_declaration);
+
                Id ptr_type_id = get_pointer_type_id(type_id, storage);
                if(var.interface=="uniform")
                {
-                       Id &uni_id = declared_uniform_ids["v"+var.name];
+                       Id &uni_id = declared_uniform_ids[var.block_declaration ? "b"+var.block_declaration->block_name : "v"+var.name];
                        if(uni_id)
                        {
                                insert_unique(declared_ids, &var, Declaration(uni_id, ptr_type_id));
@@ -1662,7 +1661,7 @@ void SpirVGenerator::visit(VariableDeclaration &var)
                                        writer.write_op_decorate(var_id, DECO_BINDING, q.value);
                        }
                }
-               if(!var.name.compare(0, 3, "gl_"))
+               if(!var.block_declaration && !var.name.compare(0, 3, "gl_"))
                {
                        BuiltinSemantic semantic = get_builtin_semantic(var.name);
                        writer.write_op_decorate(var_id, DECO_BUILTIN, semantic);
@@ -1678,48 +1677,6 @@ void SpirVGenerator::visit(VariableDeclaration &var)
        writer.write_op_name(var_id, var.name);
 }
 
-void SpirVGenerator::visit(InterfaceBlock &iface)
-{
-       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;
-       if(iface.array)
-               type_id = get_array_type_id(*iface.struct_declaration, 0, true);
-       else
-               type_id = get_id(*iface.struct_declaration);
-       Id ptr_type_id = get_pointer_type_id(type_id, storage);
-
-       Id block_id;
-       if(iface.interface=="uniform")
-       {
-               Id &uni_id = declared_uniform_ids["b"+iface.block_name];
-               if(uni_id)
-               {
-                       insert_unique(declared_ids, &iface, Declaration(uni_id, ptr_type_id));
-                       return;
-               }
-
-               uni_id = block_id = allocate_id(iface, ptr_type_id);
-       }
-       else
-               block_id = allocate_id(iface, ptr_type_id);
-       writer.write_op_name(block_id, iface.instance_name);
-
-       writer.write_op(content.globals, OP_VARIABLE, ptr_type_id, block_id, storage);
-
-       if(iface.layout)
-       {
-               for(const Layout::Qualifier &q: iface.layout->qualifiers)
-               {
-                       if(q.name=="set")
-                               writer.write_op_decorate(block_id, DECO_DESCRIPTOR_SET, q.value);
-                       else if(q.name=="binding")
-                               writer.write_op_decorate(block_id, DECO_BINDING, q.value);
-               }
-       }
-}
-
 void SpirVGenerator::visit_entry_point(FunctionDeclaration &func, Id func_id)
 {
        writer.begin_op(content.entry_points, OP_ENTRY_POINT);
@@ -1735,15 +1692,9 @@ void SpirVGenerator::visit_entry_point(FunctionDeclaration &func, Id func_id)
 
        set<Node *> dependencies = DependencyCollector().apply(func);
        for(Node *n: dependencies)
-       {
                if(const VariableDeclaration *var = dynamic_cast<const VariableDeclaration *>(n))
-               {
                        if(!var->interface.empty())
                                writer.write(get_id(*n));
-               }
-               else if(dynamic_cast<InterfaceBlock *>(n))
-                       writer.write(get_id(*n));
-       }
 
        writer.end_op(OP_ENTRY_POINT);
 
index a83478b0fb6d370d621864aa300ed8fcf4c8f1bd..23def508d719d6ba23296f4d50da59d730e0d264 100644 (file)
@@ -139,7 +139,6 @@ private:
        virtual void visit(Block &);
        virtual void visit(Literal &);
        virtual void visit(VariableReference &);
-       virtual void visit(InterfaceBlockReference &);
        void generate_composite_access(TypeDeclaration &);
        void visit_composite(Expression &, unsigned, TypeDeclaration &);
        void visit_isolated(Expression &);
@@ -164,7 +163,6 @@ private:
        virtual void visit(ImageTypeDeclaration &);
        virtual void visit(StructDeclaration &);
        virtual void visit(VariableDeclaration &);
-       virtual void visit(InterfaceBlock &);
        void visit_entry_point(FunctionDeclaration &, Id);
        virtual void visit(FunctionDeclaration &);
        virtual void visit(Conditional &);
index d74291bc2840edd89391f6ce04e4fc04275bf5b2..38a7f003be8b239f360df2a143cf214ed50a43b8 100644 (file)
@@ -104,17 +104,6 @@ void VariableReference::visit(NodeVisitor &visitor)
 }
 
 
-InterfaceBlockReference::InterfaceBlockReference(const InterfaceBlockReference &other):
-       Expression(other),
-       name(other.name)
-{ }
-
-void InterfaceBlockReference::visit(NodeVisitor &visitor)
-{
-       visitor.visit(*this);
-}
-
-
 MemberAccess::MemberAccess(const MemberAccess &other):
        Expression(other),
        left(other.left),
@@ -249,16 +238,11 @@ StructDeclaration::StructDeclaration()
 StructDeclaration::StructDeclaration(const StructDeclaration &other):
        TypeDeclaration(other),
        members(other.members),
+       block_name(other.block_name),
        extended_alignment(other.extended_alignment)
-       // Do not copy interface block
+       // Do not copy block declaration
 { }
 
-StructDeclaration::~StructDeclaration()
-{
-       if(interface_block && interface_block->struct_declaration==this)
-               interface_block->struct_declaration = 0;
-}
-
 void StructDeclaration::visit(NodeVisitor &visitor)
 {
        visitor.visit(*this);
@@ -278,7 +262,7 @@ VariableDeclaration::VariableDeclaration(const VariableDeclaration &other):
        array(other.array),
        array_size(other.array_size),
        init_expression(other.init_expression)
-       // Do not copy type and linked declarations
+       // Do not copy pointers to other nodes
 { }
 
 VariableDeclaration::~VariableDeclaration()
@@ -293,31 +277,6 @@ void VariableDeclaration::visit(NodeVisitor &visitor)
 }
 
 
-InterfaceBlock::InterfaceBlock(const InterfaceBlock &other):
-       Statement(other),
-       layout(other.layout),
-       interface(other.interface),
-       block_name(other.block_name),
-       members(other.members),
-       instance_name(other.instance_name),
-       array(other.array)
-       // Do not copy pointers to other nodes
-{ }
-
-InterfaceBlock::~InterfaceBlock()
-{
-       if(linked_block && linked_block->linked_block==this)
-               linked_block->linked_block = 0;
-       if(struct_declaration && struct_declaration->interface_block==this)
-               struct_declaration->interface_block = 0;
-}
-
-void InterfaceBlock::visit(NodeVisitor &visitor)
-{
-       visitor.visit(*this);
-}
-
-
 FunctionDeclaration::FunctionDeclaration(const FunctionDeclaration &other):
        Statement(other),
        return_type(other.return_type),
@@ -403,7 +362,7 @@ string get_unused_variable_name(const Block &block, const string &base)
        }
 }
 
-const TypeDeclaration *get_ultimate_base_type(const TypeDeclaration *type)
+TypeDeclaration *get_ultimate_base_type(TypeDeclaration *type)
 {
        if(!type)
                return 0;
index 7a372dc59e2402d5f1872da7aa24415c66c1e783..95347e1bbb5831deaf9ffceb58cc1e196df25cde 100644 (file)
@@ -111,7 +111,6 @@ class NodeArray: public NodeContainer<std::vector<RefPtr<T> > >
 
 struct TypeDeclaration;
 struct VariableDeclaration;
-struct InterfaceBlock;
 struct FunctionDeclaration;
 
 struct Statement: Node
@@ -166,19 +165,6 @@ struct VariableReference: Expression
        virtual void visit(NodeVisitor &);
 };
 
-struct InterfaceBlockReference: Expression
-{
-       std::string name;
-
-       InterfaceBlock *declaration = 0;
-
-       InterfaceBlockReference() = default;
-       InterfaceBlockReference(const InterfaceBlockReference &);
-
-       virtual InterfaceBlockReference *clone() const { return new InterfaceBlockReference(*this); }
-       virtual void visit(NodeVisitor &);
-};
-
 struct MemberAccess: Expression
 {
        NodePtr<Expression> left;
@@ -391,13 +377,13 @@ struct ImageTypeDeclaration: TypeDeclaration
 struct StructDeclaration: TypeDeclaration
 {
        Block members;
+       std::string block_name;
        bool extended_alignment = false;
 
-       InterfaceBlock *interface_block = 0;
+       VariableDeclaration *block_declaration = 0;
 
        StructDeclaration();
        StructDeclaration(const StructDeclaration &);
-       ~StructDeclaration();
 
        virtual StructDeclaration *clone() const { return new StructDeclaration(*this); }
        virtual void visit(NodeVisitor &);
@@ -418,6 +404,7 @@ struct VariableDeclaration: Statement
        NodePtr<Expression> init_expression;
 
        TypeDeclaration *type_declaration = 0;
+       StructDeclaration *block_declaration = 0;
        VariableDeclaration *linked_declaration = 0;
 
        VariableDeclaration() = default;
@@ -428,29 +415,6 @@ struct VariableDeclaration: Statement
        virtual void visit(NodeVisitor &);
 };
 
-struct InterfaceBlock: Statement
-{
-       NodePtr<Layout> layout;
-       std::string interface;
-       std::string block_name;
-       NodePtr<Block> members;
-       std::string instance_name;
-       bool array = false;
-
-       /* An interface block's ultimate base type is always a struct.  The
-       immediate type may be either that same struct or an array of it. */
-       TypeDeclaration *type_declaration = 0;
-       StructDeclaration *struct_declaration = 0;
-       InterfaceBlock *linked_block = 0;
-
-       InterfaceBlock() = default;
-       InterfaceBlock(const InterfaceBlock &);
-       ~InterfaceBlock();
-
-       virtual InterfaceBlock *clone() const { return new InterfaceBlock(*this); }
-       virtual void visit(NodeVisitor &);
-};
-
 struct FunctionDeclaration: Statement
 {
        std::string return_type;
@@ -530,7 +494,7 @@ struct Stage
        Stage *previous = 0;
        Block content;
        std::map<std::string, TypeDeclaration *> types;
-       std::map<std::string, InterfaceBlock *> interface_blocks;
+       std::map<std::string, VariableDeclaration *> interface_blocks;
        std::map<std::string, FunctionDeclaration *> functions;
        std::map<std::string, unsigned> locations;
        std::map<std::string, unsigned> texture_bindings;
@@ -554,7 +518,7 @@ struct Module
 };
 
 std::string get_unused_variable_name(const Block &, const std::string &);
-const TypeDeclaration *get_ultimate_base_type(const TypeDeclaration *);
+TypeDeclaration *get_ultimate_base_type(TypeDeclaration *);
 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 &);
index 1d0192fea1a44faa0bde09e4888601e5d874c608..f43217ce6314c24a00d1e5885c6f405e129fba38 100644 (file)
@@ -212,13 +212,14 @@ void DeclarationValidator::visit(ImageTypeDeclaration &type)
 
 void DeclarationValidator::visit(StructDeclaration &strct)
 {
-       SetForScope<ScopeType> set_scope(scope, (scope!=INTERFACE_BLOCK ? STRUCT : scope));
+       SetForScope<ScopeType> set_scope(scope, (strct.block_name.empty() ? STRUCT : INTERFACE_BLOCK));
+       SetForScope<VariableDeclaration *> set_iface(iface_block, strct.block_declaration);
        TraversingVisitor::visit(strct);
 }
 
 void DeclarationValidator::visit(VariableDeclaration &var)
 {
-       SetForScope<VariableDeclaration *> set_var(variable, &var);
+       SetForScope<VariableDeclaration *> set_var((var.block_declaration ? iface_block : variable), &var);
 
        const char *descr = describe_variable(scope);
 
@@ -275,6 +276,13 @@ void DeclarationValidator::visit(VariableDeclaration &var)
                else if(scope==GLOBAL && var.interface!="uniform")
                        error(var, format("Type '%s' only allowed with uniform interface", type->name));
        }
+       else if(var.block_declaration)
+       {
+               if(stage->type==Stage::VERTEX && var.interface=="in")
+                       error(var, "Interface block not allowed on vertex shader input");
+               else if(stage->type==Stage::FRAGMENT && var.interface=="out")
+                       error(var, "Interface block not allowed on fragment shader output");
+       }
        else if(kind==BasicTypeDeclaration::VOID)
                error(var, "Type 'void' not allowed on variable");
        else if(kind==BasicTypeDeclaration::BOOL && var.source!=BUILTIN_SOURCE)
@@ -296,21 +304,6 @@ void DeclarationValidator::visit(VariableDeclaration &var)
        }
 }
 
-void DeclarationValidator::visit(InterfaceBlock &iface)
-{
-       SetForScope<ScopeType> set_scope(scope, INTERFACE_BLOCK);
-       SetForScope<InterfaceBlock *> set_iface(iface_block, &iface);
-
-       if(stage->type==Stage::VERTEX && iface.interface=="in")
-               error(iface, "Interface block not allowed on vertex shader input");
-       else if(stage->type==Stage::FRAGMENT && iface.interface=="out")
-               error(iface, "Interface block not allowed on fragment shader output");
-
-       TraversingVisitor::visit(iface);
-       if(iface.struct_declaration)
-               iface.struct_declaration->visit(*this);
-}
-
 void DeclarationValidator::visit(FunctionDeclaration &func)
 {
        SetForScope<ScopeType> set_scope(scope, FUNCTION_PARAM);
@@ -362,42 +355,43 @@ void IdentifierValidator::visit(TypeDeclaration &type)
 
 void IdentifierValidator::visit(StructDeclaration &strct)
 {
-       check_definition(strct.name, strct);
+       if(strct.block_name.empty())
+               check_definition(strct.name, strct);
        TraversingVisitor::visit(strct);
 }
 
 void IdentifierValidator::visit(VariableDeclaration &var)
 {
-       check_definition(var.name, var);
-       TraversingVisitor::visit(var);
-}
+       if(var.block_declaration)
+       {
+               string key = format("%s %s", var.interface, var.block_declaration->block_name);
+               auto i = interface_blocks.find(key);
+               if(i!=interface_blocks.end())
+                       multiple_definition(format("interface block '%s %s'", var.interface, var.block_declaration->block_name), var, *i->second);
+               else
+                       interface_blocks.insert(make_pair(key, &var));
 
-void IdentifierValidator::visit(InterfaceBlock &iface)
-{
-       string key = format("%s %s", iface.interface, iface.block_name);
-       auto i = interface_blocks.find(key);
-       if(i!=interface_blocks.end())
-               multiple_definition(format("interface block '%s %s'", iface.interface, iface.block_name), iface, *i->second);
-       else
-               interface_blocks.insert(make_pair(key, &iface));
+               if(Statement *previous = find_definition(var.block_declaration->block_name))
+               {
+                       const VariableDeclaration *prev_var = dynamic_cast<const VariableDeclaration *>(previous);
+                       if(!prev_var || !prev_var->block_declaration)
+                               multiple_definition(format("'%s'", var.block_declaration->block_name), var, *previous);
+               }
+               else
+                       record_definition(var.block_declaration->block_name, var);
 
-       if(Statement *previous = find_definition(iface.block_name))
-       {
-               if(!dynamic_cast<InterfaceBlock *>(previous))
-                       multiple_definition(format("'%s'", iface.block_name), iface, *previous);
+               if(var.name.find(' ')!=string::npos)
+               {
+                       // Inject anonymous interface block members into the global scope
+                       for(const auto &kvp: var.block_declaration->members.variables)
+                               check_definition(kvp.first, *kvp.second);
+               }
        }
-       else
-               record_definition(iface.block_name, iface);
 
-       if(!iface.instance_name.empty())
-               check_definition(iface.instance_name, iface);
+       if(var.name.find(' ')==string::npos)
+               check_definition(var.name, var);
 
-       if(iface.instance_name.empty() && iface.struct_declaration)
-       {
-               // Inject anonymous interface block members into the global scope
-               for(const auto &kvp: iface.struct_declaration->members.variables)
-                       check_definition(kvp.first, *kvp.second);
-       }
+       TraversingVisitor::visit(var);
 }
 
 void IdentifierValidator::visit(FunctionDeclaration &func)
@@ -445,7 +439,7 @@ void ReferenceValidator::visit(VariableReference &var)
        if(!var.declaration)
                error(var, format("Use of undeclared variable '%s'", var.name));
        else if(stage->type!=Stage::VERTEX && var.declaration->interface=="in" && var.name.compare(0, 3, "gl_") && !var.declaration->linked_declaration)
-               error(var, format("Use of unlinked input variable '%s'", var.name));
+               error(var, format("Use of unlinked input %s '%s'", (var.declaration->block_declaration ? "block" : "variable"), var.name));
 }
 
 void ReferenceValidator::visit(MemberAccess &memacc)
@@ -455,16 +449,6 @@ void ReferenceValidator::visit(MemberAccess &memacc)
        TraversingVisitor::visit(memacc);
 }
 
-void ReferenceValidator::visit(InterfaceBlockReference &iface)
-{
-       /* An interface block reference without a declaration should be impossible
-       since references are generated based on existing declarations. */
-       if(!iface.declaration)
-               error(iface, format("Use of undeclared interface block '%s'", iface.name));
-       else if(stage->type!=Stage::VERTEX && iface.declaration->interface=="in" && !iface.declaration->linked_block)
-               error(iface, format("Use of unlinked input block '%s'", iface.name));
-}
-
 void ReferenceValidator::visit(FunctionCall &call)
 {
        if((!call.constructor && !call.declaration) || (call.constructor && !call.type))
@@ -504,13 +488,6 @@ void ReferenceValidator::visit(VariableDeclaration &var)
        TraversingVisitor::visit(var);
 }
 
-void ReferenceValidator::visit(InterfaceBlock &iface)
-{
-       if(!iface.struct_declaration)
-               error(iface, format("Interface block '%s %s' lacks a struct declaration", iface.interface, iface.block_name));
-       TraversingVisitor::visit(iface);
-}
-
 void ReferenceValidator::visit(FunctionDeclaration &func)
 {
        if(!func.return_type_declaration)
@@ -524,7 +501,10 @@ void ExpressionValidator::visit(VariableReference &var)
        if(var.declaration && constant_expression)
        {
                if(!var.declaration->constant)
-                       error(var, format("Reference to non-constant variable '%s' in a constant expression", var.name));
+               {
+                       const char *kind = (var.declaration->block_declaration ? "interface block" : "non-constant variable");
+                       error(var, format("Reference to %s '%s' in a constant expression", kind, var.name));
+               }
                else if(var.declaration->layout && constant_expression==FIXED_CONSTANT)
                {
                        if(has_layout_qualifier(var.declaration->layout.get(), "constant_id"))
@@ -533,12 +513,6 @@ void ExpressionValidator::visit(VariableReference &var)
        }
 }
 
-void ExpressionValidator::visit(InterfaceBlockReference &iface)
-{
-       if(constant_expression)
-               error(iface, format("Reference to interface block '%s' in a constant expression", iface.name));
-}
-
 void ExpressionValidator::visit(Swizzle &swizzle)
 {
        unsigned size = 0;
@@ -902,11 +876,14 @@ void GlobalInterfaceValidator::visit(VariableDeclaration &var)
                Uniform uni;
                uni.node = &var;
                uni.type = var.type_declaration;
-               uni.name = var.name;
+               uni.name = (var.block_declaration ? var.block_declaration->block_name : var.name);
                if(var.layout)
                {
-                       uni.location = get_layout_value(var.layout.get(), "location");
-                       uni.loc_count = LocationCounter().apply(var);
+                       if(!var.block_declaration)
+                       {
+                               uni.location = get_layout_value(var.layout.get(), "location");
+                               uni.loc_count = LocationCounter().apply(var);
+                       }
                        uni.desc_set = get_layout_value(var.layout.get(), "set", 0);
                        uni.bind_point = get_layout_value(var.layout.get(), "binding");
                }
@@ -916,25 +893,6 @@ void GlobalInterfaceValidator::visit(VariableDeclaration &var)
        }
 }
 
-void GlobalInterfaceValidator::visit(InterfaceBlock &iface)
-{
-       if(iface.interface=="uniform")
-       {
-               Uniform uni;
-               uni.node = &iface;
-               uni.type = iface.struct_declaration;
-               uni.name = iface.block_name;
-               if(iface.layout)
-               {
-                       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);
-               check_uniform(uniforms.back());
-       }
-}
-
 } // namespace SL
 } // namespace GL
 } // namespace Msp
index a09f9f643002b11ecae0bfba1237d07d76121cd9..c9a7b736035519e3d3767062e198cb22e5f8ba6b 100644 (file)
@@ -42,7 +42,7 @@ private:
        Features features;
        ScopeType scope = GLOBAL;
        InterfaceLayout *iface_layout = 0;
-       InterfaceBlock *iface_block = 0;
+       VariableDeclaration *iface_block = 0;
        VariableDeclaration *variable = 0;
 
 public:
@@ -57,7 +57,6 @@ private:
        virtual void visit(ImageTypeDeclaration &);
        virtual void visit(StructDeclaration &);
        virtual void visit(VariableDeclaration &);
-       virtual void visit(InterfaceBlock &);
        virtual void visit(FunctionDeclaration &);
 };
 
@@ -69,7 +68,7 @@ private:
        typedef std::map<std::string, Statement *> BlockDeclarationMap;
 
        std::map<Block *, BlockDeclarationMap> declarations;
-       std::map<std::string, InterfaceBlock *> interface_blocks;
+       std::map<std::string, VariableDeclaration *> interface_blocks;
        std::map<std::string, FunctionDeclaration *> overloaded_functions;
        bool anonymous_block = false;
 
@@ -87,7 +86,6 @@ private:
        virtual void visit(ImageTypeDeclaration &t) { visit(static_cast<TypeDeclaration &>(t)); }
        virtual void visit(StructDeclaration &);
        virtual void visit(VariableDeclaration &);
-       virtual void visit(InterfaceBlock &);
        virtual void visit(FunctionDeclaration &);
 };
 
@@ -102,10 +100,8 @@ private:
        virtual void visit(ImageTypeDeclaration &);
        virtual void visit(VariableReference &);
        virtual void visit(MemberAccess &);
-       virtual void visit(InterfaceBlockReference &);
        virtual void visit(FunctionCall &);
        virtual void visit(VariableDeclaration &);
-       virtual void visit(InterfaceBlock &);
        virtual void visit(FunctionDeclaration &);
 };
 
@@ -130,7 +126,6 @@ public:
 
 private:
        virtual void visit(VariableReference &);
-       virtual void visit(InterfaceBlockReference &);
        virtual void visit(Swizzle &);
        virtual void visit(UnaryExpression &);
        virtual void visit(BinaryExpression &);
@@ -207,7 +202,6 @@ private:
        void check_uniform(const Uniform &);
 
        virtual void visit(VariableDeclaration &);
-       virtual void visit(InterfaceBlock &);
        virtual void visit(FunctionDeclaration &) { }
 };
 
index b0025982fc75255041187ef4d66ce58af5930997..bcd6051a7c4a65b13604a5e75ec63eeed9c8de7b 100644 (file)
@@ -86,14 +86,6 @@ void TraversingVisitor::visit(VariableDeclaration &var)
                visit(var.array_size);
 }
 
-void TraversingVisitor::visit(InterfaceBlock &iface)
-{
-       if(iface.layout)
-               iface.layout->visit(*this);
-       if(iface.members)
-               iface.members->visit(*this);
-}
-
 void TraversingVisitor::visit(FunctionDeclaration &func)
 {
        enter(func.body);
@@ -170,11 +162,32 @@ void NodeRemover::visit(TypeDeclaration &type)
                remove_from_map(stage->types, type.name, type);
 }
 
+void NodeRemover::visit(StructDeclaration &strct)
+{
+       if(to_remove->count(&strct))
+       {
+               remove_from_map<TypeDeclaration>(stage->types, strct.name, strct);
+               if(strct.block_declaration)
+               {
+                       string key = format("%s %s", strct.block_declaration->interface, strct.block_name);
+                       remove_from_map(stage->interface_blocks, key, *strct.block_declaration);
+                       remove_from_map(stage->interface_blocks, strct.block_declaration->name, *strct.block_declaration);
+                       strct.block_declaration->block_declaration = 0;
+               }
+       }
+}
+
 void NodeRemover::visit(VariableDeclaration &var)
 {
-       if(recursive_remove || to_remove->count(&var))
+       if(to_remove->count(&var))
        {
                remove_from_map(current_block->variables, var.name, var);
+               if(var.block_declaration)
+               {
+                       remove_from_map(stage->interface_blocks, format("%s %s", var.interface, var.block_declaration->block_name), var);
+                       remove_from_map(stage->interface_blocks, var.name, var);
+                       var.block_declaration->block_declaration = 0;
+               }
                stage->locations.erase(var.name);
                if(var.linked_declaration)
                        var.linked_declaration->linked_declaration = 0;
@@ -183,18 +196,6 @@ void NodeRemover::visit(VariableDeclaration &var)
                var.init_expression = 0;
 }
 
-void NodeRemover::visit(InterfaceBlock &iface)
-{
-       if(to_remove->count(&iface))
-       {
-               remove_from_map(stage->interface_blocks, format("%s %s", iface.interface, iface.block_name), iface);
-               if(!iface.instance_name.empty())
-                       remove_from_map(stage->interface_blocks, iface.instance_name, iface);
-       }
-       SetFlag set_recursive(recursive_remove, recursive_remove || to_remove->count(&iface));
-       TraversingVisitor::visit(iface);
-}
-
 void NodeRemover::visit(FunctionDeclaration &func)
 {
        if(to_remove->count(&func))
index 622a4834910d9d1f1a1f8e74db8c06af6c29a506..2503a15e79e33c67c233574270b527ecd9a50e26 100644 (file)
@@ -20,7 +20,6 @@ public:
        virtual void visit(Block &) { }
        virtual void visit(Literal &) { }
        virtual void visit(VariableReference &) { }
-       virtual void visit(InterfaceBlockReference &) { }
        virtual void visit(MemberAccess &) { }
        virtual void visit(Swizzle &) { }
        virtual void visit(UnaryExpression &) { }
@@ -37,7 +36,6 @@ public:
        virtual void visit(ImageTypeDeclaration &) { }
        virtual void visit(StructDeclaration &) { }
        virtual void visit(VariableDeclaration &) { }
-       virtual void visit(InterfaceBlock &) { }
        virtual void visit(FunctionDeclaration &) { }
        virtual void visit(Conditional &) { }
        virtual void visit(Iteration &) { }
@@ -69,7 +67,6 @@ public:
        virtual void visit(InterfaceLayout &);
        virtual void visit(StructDeclaration &);
        virtual void visit(VariableDeclaration &);
-       virtual void visit(InterfaceBlock &);
        virtual void visit(FunctionDeclaration &);
        virtual void visit(Conditional &);
        virtual void visit(Iteration &);
@@ -83,7 +80,6 @@ class NodeRemover: private TraversingVisitor
 private:
        Stage *stage = 0;
        const std::set<Node *> *to_remove = 0;
-       bool recursive_remove = false;
 
 public:
        void apply(Stage &, const std::set<Node *> &);
@@ -96,9 +92,8 @@ private:
        void visit(TypeDeclaration &);
        virtual void visit(BasicTypeDeclaration &t) { visit(static_cast<TypeDeclaration &>(t)); }
        virtual void visit(ImageTypeDeclaration &t) { visit(static_cast<TypeDeclaration &>(t)); }
-       virtual void visit(StructDeclaration &t) { visit(static_cast<TypeDeclaration &>(t)); }
+       virtual void visit(StructDeclaration &);
        virtual void visit(VariableDeclaration &);
-       virtual void visit(InterfaceBlock &);
        virtual void visit(FunctionDeclaration &);
        virtual void visit(Iteration &);
 };