Updated spirv-cross.

This commit is contained in:
Бранимир Караџић 2022-03-12 13:23:36 -08:00
parent 837eecfa16
commit 12e3ad2970
5 changed files with 72 additions and 9 deletions

View File

@ -349,7 +349,7 @@ void ParsedIR::set_name(ID id, const string &name)
void ParsedIR::set_member_name(TypeID id, uint32_t index, const string &name) void ParsedIR::set_member_name(TypeID id, uint32_t index, const string &name)
{ {
auto &m = meta[id]; auto &m = meta[id];
m.members.resize(max(meta[id].members.size(), size_t(index) + 1)); m.members.resize(max(m.members.size(), size_t(index) + 1));
m.members[index].alias = name; m.members[index].alias = name;
if (!is_valid_identifier(name) || is_reserved_identifier(name, true, false)) if (!is_valid_identifier(name) || is_reserved_identifier(name, true, false))
meta_needing_name_fixup.insert(id); meta_needing_name_fixup.insert(id);
@ -451,8 +451,9 @@ void ParsedIR::set_decoration(ID id, Decoration decoration, uint32_t argument)
void ParsedIR::set_member_decoration(TypeID id, uint32_t index, Decoration decoration, uint32_t argument) void ParsedIR::set_member_decoration(TypeID id, uint32_t index, Decoration decoration, uint32_t argument)
{ {
meta[id].members.resize(max(meta[id].members.size(), size_t(index) + 1)); auto &m = meta[id];
auto &dec = meta[id].members[index]; m.members.resize(max(m.members.size(), size_t(index) + 1));
auto &dec = m.members[index];
dec.decoration_flags.set(decoration); dec.decoration_flags.set(decoration);
switch (decoration) switch (decoration)
@ -792,7 +793,8 @@ const Bitset &ParsedIR::get_decoration_bitset(ID id) const
void ParsedIR::set_member_decoration_string(TypeID id, uint32_t index, Decoration decoration, const string &argument) void ParsedIR::set_member_decoration_string(TypeID id, uint32_t index, Decoration decoration, const string &argument)
{ {
meta[id].members.resize(max(meta[id].members.size(), size_t(index) + 1)); auto &m = meta[id];
m.members.resize(max(m.members.size(), size_t(index) + 1));
auto &dec = meta[id].members[index]; auto &dec = meta[id].members[index];
dec.decoration_flags.set(decoration); dec.decoration_flags.set(decoration);

View File

@ -656,6 +656,7 @@ string CompilerGLSL::compile()
backend.support_case_fallthrough = false; backend.support_case_fallthrough = false;
// Scan the SPIR-V to find trivial uses of extensions. // Scan the SPIR-V to find trivial uses of extensions.
fixup_anonymous_struct_names();
fixup_type_alias(); fixup_type_alias();
reorder_type_alias(); reorder_type_alias();
build_function_control_flow_graphs_and_analyze(); build_function_control_flow_graphs_and_analyze();
@ -15791,6 +15792,52 @@ void CompilerGLSL::reset_name_caches()
function_overloads.clear(); function_overloads.clear();
} }
void CompilerGLSL::fixup_anonymous_struct_names(std::unordered_set<uint32_t> &visited, const SPIRType &type)
{
if (visited.count(type.self))
return;
visited.insert(type.self);
for (uint32_t i = 0; i < uint32_t(type.member_types.size()); i++)
{
auto &mbr_type = get<SPIRType>(type.member_types[i]);
if (mbr_type.basetype == SPIRType::Struct)
{
// If there are multiple aliases, the output might be somewhat unpredictable,
// but the only real alternative in that case is to do nothing, which isn't any better.
// This check should be fine in practice.
if (get_name(mbr_type.self).empty() && !get_member_name(type.self, i).empty())
{
auto anon_name = join("anon_", get_member_name(type.self, i));
ParsedIR::sanitize_underscores(anon_name);
set_name(mbr_type.self, anon_name);
}
fixup_anonymous_struct_names(visited, mbr_type);
}
}
}
void CompilerGLSL::fixup_anonymous_struct_names()
{
// HLSL codegen can often end up emitting anonymous structs inside blocks, which
// breaks GL linking since all names must match ...
// Try to emit sensible code, so attempt to find such structs and emit anon_$member.
// Breaks exponential explosion with weird type trees.
std::unordered_set<uint32_t> visited;
ir.for_each_typed_id<SPIRType>([&](uint32_t, SPIRType &type) {
if (type.basetype == SPIRType::Struct &&
(has_decoration(type.self, DecorationBlock) ||
has_decoration(type.self, DecorationBufferBlock)))
{
fixup_anonymous_struct_names(visited, type);
}
});
}
void CompilerGLSL::fixup_type_alias() void CompilerGLSL::fixup_type_alias()
{ {
// Due to how some backends work, the "master" type of type_alias must be a block-like type if it exists. // Due to how some backends work, the "master" type of type_alias must be a block-like type if it exists.

View File

@ -946,6 +946,8 @@ protected:
void fixup_type_alias(); void fixup_type_alias();
void reorder_type_alias(); void reorder_type_alias();
void fixup_anonymous_struct_names();
void fixup_anonymous_struct_names(std::unordered_set<uint32_t> &visited, const SPIRType &type);
static const char *vector_swizzle(int vecsize, int index); static const char *vector_swizzle(int vecsize, int index);

View File

@ -5820,6 +5820,7 @@ string CompilerHLSL::compile()
// SM 4.1 does not support precise for some reason. // SM 4.1 does not support precise for some reason.
backend.support_precise_qualifier = hlsl_options.shader_model >= 50 || hlsl_options.shader_model == 40; backend.support_precise_qualifier = hlsl_options.shader_model >= 50 || hlsl_options.shader_model == 40;
fixup_anonymous_struct_names();
fixup_type_alias(); fixup_type_alias();
reorder_type_alias(); reorder_type_alias();
build_function_control_flow_graphs_and_analyze(); build_function_control_flow_graphs_and_analyze();

View File

@ -1371,6 +1371,7 @@ string CompilerMSL::compile()
for (auto &id : next_metal_resource_ids) for (auto &id : next_metal_resource_ids)
id = 0; id = 0;
fixup_anonymous_struct_names();
fixup_type_alias(); fixup_type_alias();
replace_illegal_names(); replace_illegal_names();
sync_entry_point_aliases_and_names(); sync_entry_point_aliases_and_names();
@ -3132,6 +3133,14 @@ void CompilerMSL::add_variable_to_interface_block(StorageClass storage, const st
return; return;
} }
// If variable names alias, they will end up with wrong names in the interface struct, because
// there might be aliases in the member name cache and there would be a mismatch in fixup_in code.
// Make sure to register the variables as unique resource names ahead of time.
// This would normally conflict with the name cache when emitting local variables,
// but this happens in the setup stage, before we hit compilation loops.
// The name cache is cleared before we actually emit code, so this is safe.
add_resource_name(var.self);
if (var_type.basetype == SPIRType::Struct) if (var_type.basetype == SPIRType::Struct)
{ {
bool block_requires_flattening = variable_storage_requires_stage_io(storage) || is_block; bool block_requires_flattening = variable_storage_requires_stage_io(storage) || is_block;
@ -3189,7 +3198,7 @@ void CompilerMSL::add_variable_to_interface_block(StorageClass storage, const st
if (storage == StorageClassOutput && is_stage_output_block_member_masked(var, mbr_idx, meta.strip_array)) if (storage == StorageClassOutput && is_stage_output_block_member_masked(var, mbr_idx, meta.strip_array))
{ {
location = UINT32_MAX; // Skip this member and resolve location again on next var member location = UINT32_MAX; // Skip this member and resolve location again on next var member
if (is_block) if (is_block)
masked_block = true; masked_block = true;
@ -3226,16 +3235,18 @@ void CompilerMSL::add_variable_to_interface_block(StorageClass storage, const st
{ {
bool is_composite_type = is_matrix(mbr_type) || is_array(mbr_type) || mbr_type.basetype == SPIRType::Struct; bool is_composite_type = is_matrix(mbr_type) || is_array(mbr_type) || mbr_type.basetype == SPIRType::Struct;
bool attribute_load_store = bool attribute_load_store =
storage == StorageClassInput && get_execution_model() != ExecutionModelFragment; storage == StorageClassInput && get_execution_model() != ExecutionModelFragment;
bool storage_is_stage_io = variable_storage_requires_stage_io(storage); bool storage_is_stage_io = variable_storage_requires_stage_io(storage);
// Clip/CullDistance always need to be declared as user attributes. // Clip/CullDistance always need to be declared as user attributes.
if (builtin == BuiltInClipDistance || builtin == BuiltInCullDistance) if (builtin == BuiltInClipDistance || builtin == BuiltInCullDistance)
is_builtin = false; is_builtin = false;
string mbr_name_qual = to_name(var_type.self); const string var_name = to_name(var.self);
string var_chain_qual = to_name(var.self); string mbr_name_qual = var_name;
if (elem_cnt > 1) { string var_chain_qual = var_name;
if (elem_cnt > 1)
{
mbr_name_qual += join("_", elem_idx); mbr_name_qual += join("_", elem_idx);
var_chain_qual += join("[", elem_idx, "]"); var_chain_qual += join("[", elem_idx, "]");
} }