]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/spirv.cpp
Remove Vulkan checks from feature converters
[libs/gl.git] / source / glsl / spirv.cpp
index 13c58a695ab3668d9c0a605ce679f1d00565a997..c6f15614f5c8a56a36c7e7236a1c785f081e0a19 100644 (file)
@@ -135,8 +135,9 @@ SpirVGenerator::SpirVGenerator():
        writer(content)
 { }
 
-void SpirVGenerator::apply(Module &module)
+void SpirVGenerator::apply(Module &module, const Features &f)
 {
+       features = f;
        use_capability(CAP_SHADER);
 
        for(Stage &s: module.stages)
@@ -337,10 +338,10 @@ bool SpirVGenerator::is_scalar_type(Id type_id, BasicTypeDeclaration::Kind kind)
        return (i!=standard_type_ids.end() && i->second==type_id);
 }
 
-SpirVGenerator::Id SpirVGenerator::get_array_type_id(TypeDeclaration &base_type, Id size_id)
+SpirVGenerator::Id SpirVGenerator::get_array_type_id(TypeDeclaration &base_type, Id size_id, bool extended_align)
 {
        Id base_type_id = get_id(base_type);
-       Id &array_type_id = array_type_ids[TypeKey(base_type_id, size_id)];
+       Id &array_type_id = array_type_ids[TypeKey(base_type_id, extended_align*0x400000 | size_id)];
        if(!array_type_id)
        {
                array_type_id = next_id++;
@@ -350,6 +351,8 @@ SpirVGenerator::Id SpirVGenerator::get_array_type_id(TypeDeclaration &base_type,
                        writer.write_op(content.globals, OP_TYPE_RUNTIME_ARRAY, array_type_id, base_type_id);
 
                unsigned stride = MemoryRequirementsCalculator().apply(base_type).stride;
+               if(extended_align)
+                       stride = (stride+15)&~15U;
                writer.write_op_decorate(array_type_id, DECO_ARRAY_STRIDE, stride);
        }
 
@@ -372,17 +375,13 @@ SpirVGenerator::Id SpirVGenerator::get_variable_type_id(const VariableDeclaratio
        if(const BasicTypeDeclaration *basic = dynamic_cast<const BasicTypeDeclaration *>(var.type_declaration))
                if(basic->kind==BasicTypeDeclaration::ARRAY)
                {
-                       Id size_id = 0;
-                       if(var.array_size)
-                       {
-                               SetFlag set_const(constant_expression);
-                               r_expression_result_id = 0;
-                               var.array_size->visit(*this);
-                               size_id = r_expression_result_id;
-                       }
-                       else
-                               size_id = get_constant_id(get_standard_type_id(BasicTypeDeclaration::INT, 1), 1);
-                       return get_array_type_id(*basic->base_type, size_id);
+                       if(!var.array_size)
+                               throw logic_error("array without size");
+
+                       SetFlag set_const(constant_expression);
+                       r_expression_result_id = 0;
+                       var.array_size->visit(*this);
+                       return get_array_type_id(*basic->base_type, r_expression_result_id, basic->extended_alignment);
                }
 
        return get_id(*var.type_declaration);
@@ -538,16 +537,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;
@@ -1032,18 +1021,22 @@ void SpirVGenerator::visit(TernaryExpression &ternary)
        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, condition_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);
        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);
 
+       swap(saved_load_ids, variable_load_ids);
        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);
+       prune_loads(true_label_id);
        r_expression_result_id = begin_expression(OP_PHI, get_id(*ternary.type), 4);
        writer.write(true_result_id);
        writer.write(true_label_id);
@@ -1523,12 +1516,12 @@ void SpirVGenerator::visit(StructDeclaration &strct)
                return;
 
        Id type_id = allocate_id(strct, 0);
-       writer.write_op_name(type_id, strct.name);
+       writer.write_op_name(type_id, (strct.block_name.empty() ? strct.name : strct.block_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)
@@ -1612,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));
@@ -1659,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);
@@ -1672,49 +1674,8 @@ 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);
-       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);
-               }
-       }
+       if(var.name.find(' ')==string::npos)
+               writer.write_op_name(var_id, var.name);
 }
 
 void SpirVGenerator::visit_entry_point(FunctionDeclaration &func, Id func_id)
@@ -1732,22 +1693,22 @@ 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);
 
        if(stage->type==Stage::FRAGMENT)
-               writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_ORIGIN_LOWER_LEFT);
+       {
+               SpirVExecutionMode origin = (features.target_api==VULKAN ? EXEC_ORIGIN_UPPER_LEFT : EXEC_ORIGIN_LOWER_LEFT);
+               writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, origin);
+       }
        else if(stage->type==Stage::GEOMETRY)
+       {
                use_capability(CAP_GEOMETRY);
+               writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_INVOCATIONS, 1);
+       }
 
        for(const InterfaceLayout *i: interface_layouts)
        {
@@ -1823,6 +1784,7 @@ void SpirVGenerator::visit(FunctionDeclaration &func)
        {
                Id param_id = allocate_id(*func.parameters[i], param_type_ids[i]);
                writer.write_op(content.functions, OP_FUNCTION_PARAMETER, param_type_ids[i], param_id);
+               writer.write_op_name(param_id, func.parameters[i]->name);
                // TODO This is probably incorrect if the parameter is assigned to.
                variable_load_ids[func.parameters[i].get()] = param_id;
        }