]> git.tdb.fi Git - libs/gl.git/commitdiff
Use extended alignment in SPIR-V struct layout when necessary
authorMikko Rasa <tdb@tdb.fi>
Sat, 20 Nov 2021 21:59:16 +0000 (23:59 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sat, 20 Nov 2021 22:05:54 +0000 (00:05 +0200)
source/glsl/debug.cpp
source/glsl/reflect.cpp
source/glsl/resolve.cpp
source/glsl/resolve.h
source/glsl/spirv.cpp
source/glsl/spirv.h
source/glsl/syntax.h

index 5ee30e0996c4dfc6ff5331d1c1b200f472c6fcf1..ef7e81f68af289943e7348a81edc8eb407637cf6 100644 (file)
@@ -349,6 +349,8 @@ void DumpTree::visit(BasicTypeDeclaration &type)
                branches.emplace_back(format("Vector: %d", type.size));
        else if(type.kind==BasicTypeDeclaration::MATRIX)
                branches.emplace_back(format("Matrix: %dx%d", type.size&0xFFFF, type.size>>16));
+       if(type.extended_alignment)
+               branches.emplace_back("Extended alignment");
        append_subtree(branches);
 }
 
@@ -370,7 +372,11 @@ void DumpTree::visit(ImageTypeDeclaration &type)
 void DumpTree::visit(StructDeclaration &strct)
 {
        append(strct, format("%s struct %s", get_label(strct), strct.name));
-       append_subtree(strct.members);
+       vector<Branch> branches;
+       if(strct.extended_alignment)
+               branches.emplace_back("Extended alignment");
+       branches.emplace_back(&strct.members);
+       append_subtree(branches);
 }
 
 void DumpTree::visit(VariableDeclaration &var)
index 32c7c7330d0577fde5c156f90d0e3b9925022518..a1ffcd3d449783caf24aa9c79d4c403199972234 100644 (file)
@@ -284,6 +284,9 @@ void MemoryRequirementsCalculator::visit(BasicTypeDeclaration &basic)
        }
        else if(basic.kind==BasicTypeDeclaration::ARRAY)
                basic.base_type->visit(*this);
+
+       if(basic.extended_alignment)
+               r_alignment = (r_alignment+15)&~15U;
 }
 
 void MemoryRequirementsCalculator::visit(StructDeclaration &strct)
@@ -305,6 +308,8 @@ void MemoryRequirementsCalculator::visit(StructDeclaration &strct)
        }
        r_size = total;
        r_alignment = max_align;
+       if(strct.extended_alignment)
+               r_alignment = (r_alignment+15)&~15U;
        r_size += r_alignment-1;
        r_size -= r_size%r_alignment;
 }
index 406d7780e810181ffc8650e9c0ba8c20466d67aa..2f3192d77fa423a2f8fa3fb6587d283eec9da5a0 100644 (file)
@@ -28,7 +28,9 @@ bool TypeResolver::apply(Stage &s)
 
 TypeDeclaration *TypeResolver::get_or_create_array_type(TypeDeclaration &type)
 {
-       auto i = array_types.find(&type);
+       bool extended_alignment = iface_block;
+       auto key = make_pair(&type, extended_alignment);
+       auto i = array_types.find(key);
        if(i!=array_types.end())
                return i->second;
 
@@ -36,10 +38,11 @@ TypeDeclaration *TypeResolver::get_or_create_array_type(TypeDeclaration &type)
        array->source = INTERNAL_SOURCE;
        array->name = type.name+"[]";
        array->kind = BasicTypeDeclaration::ARRAY;
+       array->extended_alignment = extended_alignment;
        array->base = type.name;
        array->base_type = &type;
        stage->content.body.insert(type_insert_point, array);
-       array_types[&type] = array;
+       array_types[key] = array;
        return array;
 }
 
@@ -88,7 +91,7 @@ void TypeResolver::visit(BasicTypeDeclaration &type)
        if(type.kind==BasicTypeDeclaration::ALIAS && type.base_type)
                alias_map[&type] = type.base_type;
        else if(type.kind==BasicTypeDeclaration::ARRAY && type.base_type)
-               array_types[type.base_type] = &type;
+               array_types[make_pair(type.base_type, type.extended_alignment)] = &type;
 
        stage->types.insert(make_pair(type.name, &type));
 }
@@ -102,14 +105,20 @@ 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);
 }
 
 void TypeResolver::visit(VariableDeclaration &var)
 {
        resolve_type(var.type_declaration, var.type, var.array);
-       if(iface_block && var.interface==iface_block->interface)
-               var.interface.clear();
+       if(iface_block)
+       {
+               if(var.interface==iface_block->interface)
+                       var.interface.clear();
+               if(StructDeclaration *strct = dynamic_cast<StructDeclaration *>(var.type_declaration))
+                       strct->extended_alignment = true;
+       }
 }
 
 void TypeResolver::visit(InterfaceBlock &iface)
@@ -123,6 +132,7 @@ void TypeResolver::visit(InterfaceBlock &iface)
                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));
 
index fdbebfe8e3a8e8249407545d5abfef5ca291dda0..92a7c336de71fbbb8a217dd7ece8dd29040c4ea2 100644 (file)
@@ -30,7 +30,7 @@ class TypeResolver: private TraversingVisitor
 private:
        Stage *stage = 0;
        std::map<TypeDeclaration *, TypeDeclaration *> alias_map;
-       std::map<TypeDeclaration *, TypeDeclaration *> array_types;
+       std::map<std::pair<TypeDeclaration *, bool>, TypeDeclaration *> array_types;
        NodeList<Statement>::iterator type_insert_point;
        InterfaceBlock *iface_block = 0;
        bool r_any_resolved = false;
index 7f99ebb3d9ecc61b737739542feed5a72994633f..07d4eb072c0989eb1745405aae0c85ea2ae59fc7 100644 (file)
@@ -338,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++;
@@ -351,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);
        }
 
@@ -383,7 +385,7 @@ SpirVGenerator::Id SpirVGenerator::get_variable_type_id(const VariableDeclaratio
                        }
                        else
                                size_id = get_constant_id(get_standard_type_id(BasicTypeDeclaration::INT, 1), 1);
-                       return get_array_type_id(*basic->base_type, size_id);
+                       return get_array_type_id(*basic->base_type, size_id, true);
                }
 
        return get_id(*var.type_declaration);
@@ -1683,7 +1685,7 @@ void SpirVGenerator::visit(InterfaceBlock &iface)
        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);
+               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);
index addf8970315c5fb68e6d05d31c55c9b467ebf6c5..a83478b0fb6d370d621864aa300ed8fcf4c8f1bd 100644 (file)
@@ -124,7 +124,7 @@ private:
        Id get_vector_constant_id(Id, unsigned, Id);
        Id get_standard_type_id(BasicTypeDeclaration::Kind, unsigned, bool = true);
        bool is_scalar_type(Id, BasicTypeDeclaration::Kind) const;
-       Id get_array_type_id(TypeDeclaration &, unsigned);
+       Id get_array_type_id(TypeDeclaration &, Id, bool);
        Id get_pointer_type_id(Id, StorageClass);
        Id get_variable_type_id(const VariableDeclaration &);
        Id get_load_id(VariableDeclaration &);
index a1c62d4b11aa2a97f5ff2b17af1bed66e51a028c..7a372dc59e2402d5f1872da7aa24415c66c1e783 100644 (file)
@@ -354,6 +354,7 @@ struct BasicTypeDeclaration: TypeDeclaration
        Kind kind = ALIAS;
        unsigned size = 0;
        bool sign = true;
+       bool extended_alignment = false;
        std::string base;
 
        TypeDeclaration *base_type = 0;
@@ -390,6 +391,7 @@ struct ImageTypeDeclaration: TypeDeclaration
 struct StructDeclaration: TypeDeclaration
 {
        Block members;
+       bool extended_alignment = false;
 
        InterfaceBlock *interface_block = 0;