]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/spirv.cpp
Fix a name conflict in certain inlining scenarios
[libs/gl.git] / source / glsl / spirv.cpp
index 1da748a64eb297f23f5f135aa3743af92eabbaea..40e731fe63fa9fcfb384dd61baf8429e34be3382 100644 (file)
@@ -132,20 +132,7 @@ const SpirVGenerator::BuiltinFunctionInfo SpirVGenerator::builtin_functions[] =
 };
 
 SpirVGenerator::SpirVGenerator():
-       stage(0),
-       current_function(0),
-       writer(content),
-       next_id(1),
-       r_expression_result_id(0),
-       constant_expression(false),
-       spec_constant(false),
-       reachable(false),
-       composite_access(false),
-       r_composite_base_id(0),
-       r_composite_base(0),
-       assignment_source_id(0),
-       loop_merge_block_id(0),
-       loop_continue_target_id(0)
+       writer(content)
 { }
 
 void SpirVGenerator::apply(Module &module)
@@ -531,8 +518,15 @@ void SpirVGenerator::visit(VariableReference &var)
        r_constant_result = false;
        if(composite_access)
        {
-               r_composite_base = var.declaration;
                r_expression_result_id = 0;
+               if(!assignment_source_id)
+               {
+                       auto i = variable_load_ids.find(var.declaration);
+                       if(i!=variable_load_ids.end())
+                               r_expression_result_id = i->second;
+               }
+               if(!r_expression_result_id)
+                       r_composite_base = var.declaration;
        }
        else if(assignment_source_id)
        {
@@ -583,7 +577,7 @@ void SpirVGenerator::generate_composite_access(TypeDeclaration &result_type)
                throw internal_error("assignment to temporary composite");
        else
        {
-               for(unsigned i: r_composite_chain)
+               for(unsigned &i: r_composite_chain)
                        for(auto j=constant_ids.begin(); (i>=0x400000 && j!=constant_ids.end()); ++j)
                                if(j->second==(i&0x3FFFFF))
                                        i = j->first.int_value;
@@ -696,6 +690,9 @@ void SpirVGenerator::visit(Swizzle &swizzle)
 
 void SpirVGenerator::visit(UnaryExpression &unary)
 {
+       if(composite_access)
+               return visit_isolated(unary);
+
        unary.expression->visit(*this);
 
        char oper = unary.oper->token[0];
@@ -780,6 +777,8 @@ void SpirVGenerator::visit(BinaryExpression &binary)
                visit_isolated(*binary.right);
                return visit_composite(*binary.left, 0x400000|r_expression_result_id, *binary.type);
        }
+       else if(composite_access)
+               return visit_isolated(binary);
 
        if(assignment_source_id)
                throw internal_error("invalid binary expression in assignment target");
@@ -1004,6 +1003,8 @@ void SpirVGenerator::visit(Assignment &assign)
 
 void SpirVGenerator::visit(TernaryExpression &ternary)
 {
+       if(composite_access)
+               return visit_isolated(ternary);
        if(constant_expression)
        {
                ternary.condition->visit(*this);
@@ -1034,11 +1035,13 @@ void SpirVGenerator::visit(TernaryExpression &ternary)
        writer.write_op_label(true_label_id);
        ternary.true_expr->visit(*this);
        Id true_result_id = r_expression_result_id;
+       true_label_id = writer.get_current_block();
        writer.write_op(content.function_body, OP_BRANCH, merge_block_id);
 
        writer.write_op_label(false_label_id);
        ternary.false_expr->visit(*this);
        Id false_result_id = r_expression_result_id;
+       false_label_id = writer.get_current_block();
 
        writer.write_op_label(merge_block_id);
        r_expression_result_id = begin_expression(OP_PHI, get_id(*ternary.type), 4);
@@ -1579,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;
 
@@ -1597,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;
@@ -1647,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);
@@ -1659,6 +1654,11 @@ void SpirVGenerator::visit(VariableDeclaration &var)
                                        writer.write_op_decorate(var_id, DECO_BINDING, q.value);
                        }
                }
+               if(!var.name.compare(0, 3, "gl_"))
+               {
+                       BuiltinSemantic semantic = get_builtin_semantic(var.name);
+                       writer.write_op_decorate(var_id, DECO_BUILTIN, semantic);
+               }
 
                if(init_id && current_function)
                {
@@ -1672,7 +1672,9 @@ void SpirVGenerator::visit(VariableDeclaration &var)
 
 void SpirVGenerator::visit(InterfaceBlock &iface)
 {
-       StorageClass storage = get_interface_storage(iface.interface, true);
+       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);
@@ -1700,9 +1702,13 @@ void SpirVGenerator::visit(InterfaceBlock &iface)
 
        if(iface.layout)
        {
-               auto i = find_member(iface.layout->qualifiers, string("binding"), &Layout::Qualifier::name);
-               if(i!=iface.layout->qualifiers.end())
-                       writer.write_op_decorate(block_id, DECO_BINDING, i->value);
+               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);
+               }
        }
 }
 
@@ -1816,11 +1822,12 @@ void SpirVGenerator::visit(FunctionDeclaration &func)
                variable_load_ids[func.parameters[i].get()] = param_id;
        }
 
+       reachable = true;
        writer.begin_function_body(next_id++);
        SetForScope<FunctionDeclaration *> set_func(current_function, &func);
        func.body.visit(*this);
 
-       if(writer.has_current_block())
+       if(writer.get_current_block())
        {
                if(!reachable)
                        writer.write_op(content.function_body, OP_UNREACHABLE);
@@ -1847,9 +1854,11 @@ void SpirVGenerator::visit(Conditional &cond)
        writer.write_op(content.function_body, OP_SELECTION_MERGE, merge_block_id, 0);  // Selection control (none)
        writer.write_op(content.function_body, OP_BRANCH_CONDITIONAL, r_expression_result_id, true_label_id, false_label_id);
 
+       std::map<const VariableDeclaration *, Id> saved_load_ids = variable_load_ids;
+
        writer.write_op_label(true_label_id);
        cond.body.visit(*this);
-       if(writer.has_current_block())
+       if(writer.get_current_block())
                writer.write_op(content.function_body, OP_BRANCH, merge_block_id);
 
        bool reachable_if_true = reachable;
@@ -1857,6 +1866,7 @@ void SpirVGenerator::visit(Conditional &cond)
        reachable = true;
        if(!cond.else_body.body.empty())
        {
+               swap(saved_load_ids, variable_load_ids);
                writer.write_op_label(false_label_id);
                cond.else_body.visit(*this);
                reachable |= reachable_if_true;
@@ -1871,7 +1881,9 @@ void SpirVGenerator::visit(Iteration &iter)
        if(iter.init_statement)
                iter.init_statement->visit(*this);
 
-       variable_load_ids.clear();
+       for(Node *n: AssignmentCollector().apply(iter))
+               if(VariableDeclaration *var = dynamic_cast<VariableDeclaration *>(n))
+                       variable_load_ids.erase(var);
 
        Id header_id = next_id++;
        Id continue_id = next_id++;