Fix type aliasing on MSL.
Be careful about who gets to be the alias master, and don't alias types when we have packed types in play.
This commit is contained in:
Родитель
c9516fa917
Коммит
294259e2f1
|
@ -188,7 +188,12 @@ string Compiler::to_name(uint32_t id, bool allow_alias) const
|
|||
// as that can be overridden by the reflection APIs after parse.
|
||||
auto &type = get<SPIRType>(id);
|
||||
if (type.type_alias)
|
||||
return to_name(type.type_alias);
|
||||
{
|
||||
// If the alias master has been specially packed, we will have emitted a clean variant as well,
|
||||
// so skip the name aliasing here.
|
||||
if (!has_decoration(type.type_alias, DecorationCPacked))
|
||||
return to_name(type.type_alias);
|
||||
}
|
||||
}
|
||||
|
||||
if (meta[id].decoration.alias.empty())
|
||||
|
@ -802,6 +807,71 @@ static bool is_valid_spirv_version(uint32_t version)
|
|||
}
|
||||
}
|
||||
|
||||
bool Compiler::type_is_block_like(const SPIRType &type) const
|
||||
{
|
||||
if (type.basetype != SPIRType::Struct)
|
||||
return false;
|
||||
|
||||
if (has_decoration(type.self, DecorationBlock) ||
|
||||
has_decoration(type.self, DecorationBufferBlock))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Block-like types may have Offset decorations.
|
||||
for (uint32_t i = 0; i < uint32_t(type.member_types.size()); i++)
|
||||
if (has_member_decoration(type.self, i, DecorationOffset))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Compiler::fixup_type_alias()
|
||||
{
|
||||
// Due to how some backends work, the "master" type of type_alias must be a block-like type if it exists.
|
||||
// FIXME: Multiple alias types which are both block-like will be awkward, for now, it's best to just drop the type
|
||||
// alias if the slave type is a block type.
|
||||
for (auto &id : ids)
|
||||
{
|
||||
if (id.get_type() != TypeType)
|
||||
continue;
|
||||
|
||||
auto &type = id.get<SPIRType>();
|
||||
|
||||
if (type.type_alias && type_is_block_like(type))
|
||||
{
|
||||
// Become the master.
|
||||
for (auto &other_id : ids)
|
||||
{
|
||||
if (other_id.get_type() != TypeType)
|
||||
continue;
|
||||
if (other_id.get_id() == type.self)
|
||||
continue;
|
||||
|
||||
auto &other_type = other_id.get<SPIRType>();
|
||||
if (other_type.type_alias == type.type_alias)
|
||||
other_type.type_alias = type.self;
|
||||
}
|
||||
|
||||
get<SPIRType>(type.type_alias).type_alias = id.get_id();
|
||||
type.type_alias = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &id : ids)
|
||||
{
|
||||
if (id.get_type() != TypeType)
|
||||
continue;
|
||||
|
||||
auto &type = id.get<SPIRType>();
|
||||
if (type.type_alias && type_is_block_like(type))
|
||||
{
|
||||
// This is not allowed, drop the type_alias.
|
||||
type.type_alias = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Compiler::parse()
|
||||
{
|
||||
auto len = spirv.size();
|
||||
|
@ -853,6 +923,8 @@ void Compiler::parse()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fixup_type_alias();
|
||||
}
|
||||
|
||||
void Compiler::flatten_interface_block(uint32_t id)
|
||||
|
|
|
@ -824,6 +824,9 @@ private:
|
|||
// Used only to implement the old deprecated get_entry_point() interface.
|
||||
const SPIREntryPoint &get_first_entry_point(const std::string &name) const;
|
||||
SPIREntryPoint &get_first_entry_point(const std::string &name);
|
||||
|
||||
void fixup_type_alias();
|
||||
bool type_is_block_like(const SPIRType &type) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -612,7 +612,8 @@ void CompilerGLSL::emit_struct(SPIRType &type)
|
|||
// with just different offsets, matrix layouts, etc ...
|
||||
// Type-punning with these types is legal, which complicates things
|
||||
// when we are storing struct and array types in an SSBO for example.
|
||||
if (type.type_alias != 0)
|
||||
// If the type master is packed however, we can no longer assume that the struct declaration will be redundant.
|
||||
if (type.type_alias != 0 && !has_decoration(type.type_alias, DecorationCPacked))
|
||||
return;
|
||||
|
||||
// Don't declare empty structs in GLSL, this is not allowed.
|
||||
|
|
|
@ -438,6 +438,11 @@ void CompilerMSL::mark_as_packable(SPIRType &type)
|
|||
uint32_t mbr_type_id = type.member_types[mbr_idx];
|
||||
auto &mbr_type = get<SPIRType>(mbr_type_id);
|
||||
mark_as_packable(mbr_type);
|
||||
if (mbr_type.type_alias)
|
||||
{
|
||||
auto &mbr_type_alias = get<SPIRType>(mbr_type.type_alias);
|
||||
mark_as_packable(mbr_type_alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче