Be more precise in usage of pointer/array mixing.

This commit is contained in:
Hans-Kristian Arntzen 2023-05-11 11:42:32 +02:00
parent cfd1618e31
commit 71fe651e43
4 changed files with 41 additions and 8 deletions

View File

@ -5445,23 +5445,55 @@ void Compiler::analyze_interlocked_resource_usage()
}
bool Compiler::type_is_array_of_pointers(const SPIRType &type) const
{
if (!type_is_top_level_array(type))
return false;
// BDA types must have parent type hierarchy.
if (!type.parent_type)
return false;
// Punch through all array layers.
auto *parent = &get<SPIRType>(type.parent_type);
while (type_is_top_level_array(*parent))
parent = &get<SPIRType>(parent->parent_type);
return type_is_top_level_pointer(*parent);
}
bool Compiler::type_is_top_level_pointer(const SPIRType &type) const
{
if (!type.pointer)
return false;
// If parent type has same pointer depth, we must have an array of pointers.
return type.pointer_depth == get<SPIRType>(type.parent_type).pointer_depth;
// Function pointers, should not be hit by valid SPIR-V.
// Parent type will be SPIRFunction instead.
if (type.basetype == SPIRType::Unknown)
return false;
// Some types are synthesized in-place without complete type hierarchy and might not have parent types,
// but these types are never array-of-pointer or any complicated BDA type, infer reasonable defaults.
if (type.parent_type)
return type.pointer_depth > get<SPIRType>(type.parent_type).pointer_depth;
else
return true;
}
bool Compiler::type_is_top_level_physical_pointer(const SPIRType &type) const
{
return type.pointer && type.storage == StorageClassPhysicalStorageBuffer &&
type.pointer_depth > get<SPIRType>(type.parent_type).pointer_depth;
return type_is_top_level_pointer(type) && type.storage == StorageClassPhysicalStorageBuffer;
}
bool Compiler::type_is_top_level_array(const SPIRType &type) const
{
return !type.array.empty() && type.array.size() > get<SPIRType>(type.parent_type).array.size();
if (type.array.empty())
return false;
// If we have pointer and array, we infer pointer-to-array as it's the only meaningful thing outside BDA.
if (type.parent_type)
return type.array.size() > get<SPIRType>(type.parent_type).array.size();
else
return !type.pointer;
}
bool Compiler::flush_phi_required(BlockID from, BlockID to) const

View File

@ -1145,6 +1145,7 @@ protected:
bool type_is_array_of_pointers(const SPIRType &type) const;
bool type_is_top_level_physical_pointer(const SPIRType &type) const;
bool type_is_top_level_pointer(const SPIRType &type) const;
bool type_is_top_level_array(const SPIRType &type) const;
bool type_is_block_like(const SPIRType &type) const;
bool type_is_opaque_value(const SPIRType &type) const;

View File

@ -14550,7 +14550,7 @@ string CompilerMSL::type_to_glsl(const SPIRType &type, uint32_t id, bool member)
string type_name;
// Pointer?
if (type.pointer)
if (type_is_top_level_pointer(type) || type_is_array_of_pointers(type))
{
assert(type.pointer_depth > 0);
@ -14578,7 +14578,7 @@ string CompilerMSL::type_to_glsl(const SPIRType &type, uint32_t id, bool member)
// the C-style nesting works right.
// FIXME: This is somewhat of a hack.
bool old_is_using_builtin_array = is_using_builtin_array;
if (type.storage == StorageClassPhysicalStorageBuffer)
if (type_is_top_level_physical_pointer(type))
is_using_builtin_array = false;
type_name = join(type_address_space, " ", type_to_glsl(*p_parent_type, id));

View File

@ -292,7 +292,7 @@ bool CompilerReflection::type_is_reference(const SPIRType &type) const
{
// Physical pointers and arrays of physical pointers need to refer to the pointee's type.
return type_is_top_level_physical_pointer(type) ||
(!type.array.empty() && type_is_top_level_physical_pointer(get<SPIRType>(type.parent_type)));
(type_is_array_of_pointers(type) && type.storage == StorageClassPhysicalStorageBuffer);
}
void CompilerReflection::emit_types()