Skip to content

Commit

Permalink
Be more precise in usage of pointer/array mixing.
Browse files Browse the repository at this point in the history
  • Loading branch information
HansKristian-Work committed May 11, 2023
1 parent cfd1618 commit 71fe651
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 8 deletions.
42 changes: 37 additions & 5 deletions spirv_cross.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions spirv_cross.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1145,6 +1145,7 @@ class Compiler

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;
Expand Down
4 changes: 2 additions & 2 deletions spirv_msl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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));
Expand Down
2 changes: 1 addition & 1 deletion spirv_reflect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down

0 comments on commit 71fe651

Please sign in to comment.