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);
}
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)
}
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)
}
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;
}
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;
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;
}
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));
}
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)
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));
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;
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++;
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);
}
}
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);
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);
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 &);
Kind kind = ALIAS;
unsigned size = 0;
bool sign = true;
+ bool extended_alignment = false;
std::string base;
TypeDeclaration *base_type = 0;
struct StructDeclaration: TypeDeclaration
{
Block members;
+ bool extended_alignment = false;
InterfaceBlock *interface_block = 0;