From 0585e361d8714ac4efc3ae3e1d5c8c9aa8841c34 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 20 Nov 2021 23:59:16 +0200 Subject: [PATCH] Use extended alignment in SPIR-V struct layout when necessary --- source/glsl/debug.cpp | 8 +++++++- source/glsl/reflect.cpp | 5 +++++ source/glsl/resolve.cpp | 20 +++++++++++++++----- source/glsl/resolve.h | 2 +- source/glsl/spirv.cpp | 10 ++++++---- source/glsl/spirv.h | 2 +- source/glsl/syntax.h | 2 ++ 7 files changed, 37 insertions(+), 12 deletions(-) diff --git a/source/glsl/debug.cpp b/source/glsl/debug.cpp index 5ee30e09..ef7e81f6 100644 --- a/source/glsl/debug.cpp +++ b/source/glsl/debug.cpp @@ -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 branches; + if(strct.extended_alignment) + branches.emplace_back("Extended alignment"); + branches.emplace_back(&strct.members); + append_subtree(branches); } void DumpTree::visit(VariableDeclaration &var) diff --git a/source/glsl/reflect.cpp b/source/glsl/reflect.cpp index 32c7c733..a1ffcd3d 100644 --- a/source/glsl/reflect.cpp +++ b/source/glsl/reflect.cpp @@ -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; } diff --git a/source/glsl/resolve.cpp b/source/glsl/resolve.cpp index 406d7780..2f3192d7 100644 --- a/source/glsl/resolve.cpp +++ b/source/glsl/resolve.cpp @@ -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 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(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)); diff --git a/source/glsl/resolve.h b/source/glsl/resolve.h index fdbebfe8..92a7c336 100644 --- a/source/glsl/resolve.h +++ b/source/glsl/resolve.h @@ -30,7 +30,7 @@ class TypeResolver: private TraversingVisitor private: Stage *stage = 0; std::map alias_map; - std::map array_types; + std::map, TypeDeclaration *> array_types; NodeList::iterator type_insert_point; InterfaceBlock *iface_block = 0; bool r_any_resolved = false; diff --git a/source/glsl/spirv.cpp b/source/glsl/spirv.cpp index 7f99ebb3..07d4eb07 100644 --- a/source/glsl/spirv.cpp +++ b/source/glsl/spirv.cpp @@ -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); diff --git a/source/glsl/spirv.h b/source/glsl/spirv.h index addf8970..a83478b0 100644 --- a/source/glsl/spirv.h +++ b/source/glsl/spirv.h @@ -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 &); diff --git a/source/glsl/syntax.h b/source/glsl/syntax.h index a1c62d4b..7a372dc5 100644 --- a/source/glsl/syntax.h +++ b/source/glsl/syntax.h @@ -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; -- 2.43.0