Skip to content

Commit

Permalink
Updated spirv-cross.
Browse files Browse the repository at this point in the history
  • Loading branch information
bkaradzic committed Feb 10, 2024
1 parent 3ac2dda commit 7067b37
Show file tree
Hide file tree
Showing 9 changed files with 312 additions and 79 deletions.
4 changes: 2 additions & 2 deletions 3rdparty/spirv-cross/spirv_common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ static inline std::string convert_to_string(int32_t value)
// INT_MIN is ... special on some backends. If we use a decimal literal, and negate it, we
// could accidentally promote the literal to long first, then negate.
// To workaround it, emit int(0x80000000) instead.
if (value == std::numeric_limits<int32_t>::min())
if (value == (std::numeric_limits<int32_t>::min)())
return "int(0x80000000)";
else
return std::to_string(value);
Expand All @@ -231,7 +231,7 @@ static inline std::string convert_to_string(int64_t value, const std::string &in
// INT64_MIN is ... special on some backends.
// If we use a decimal literal, and negate it, we might overflow the representable numbers.
// To workaround it, emit int(0x80000000) instead.
if (value == std::numeric_limits<int64_t>::min())
if (value == (std::numeric_limits<int64_t>::min)())
return join(int64_type, "(0x8000000000000000u", (long_long_literal_suffix ? "ll" : "l"), ")");
else
return std::to_string(value) + (long_long_literal_suffix ? "ll" : "l");
Expand Down
34 changes: 21 additions & 13 deletions 3rdparty/spirv-cross/spirv_cross.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,13 @@ bool Compiler::is_physical_pointer(const SPIRType &type) const
return type.op == OpTypePointer && type.storage == StorageClassPhysicalStorageBuffer;
}

bool Compiler::is_physical_pointer_to_buffer_block(const SPIRType &type) const
{
return is_physical_pointer(type) && get_pointee_type(type).self == type.parent_type &&
(has_decoration(type.self, DecorationBlock) ||
has_decoration(type.self, DecorationBufferBlock));
}

bool Compiler::is_runtime_size_array(const SPIRType &type)
{
return type.op == OpTypeRuntimeArray;
Expand Down Expand Up @@ -5024,8 +5031,7 @@ void Compiler::PhysicalStorageBufferPointerHandler::mark_aligned_access(uint32_t
bool Compiler::PhysicalStorageBufferPointerHandler::type_is_bda_block_entry(uint32_t type_id) const
{
auto &type = compiler.get<SPIRType>(type_id);
return type.storage == StorageClassPhysicalStorageBufferEXT && type.pointer &&
type.pointer_depth == 1 && !compiler.type_is_array_of_pointers(type);
return compiler.is_physical_pointer(type);
}

uint32_t Compiler::PhysicalStorageBufferPointerHandler::get_minimum_scalar_alignment(const SPIRType &type) const
Expand Down Expand Up @@ -5055,7 +5061,8 @@ void Compiler::PhysicalStorageBufferPointerHandler::setup_meta_chain(uint32_t ty
access_chain_to_physical_block[var_id] = &meta;

auto &type = compiler.get<SPIRType>(type_id);
if (type.basetype != SPIRType::Struct)

if (!compiler.is_physical_pointer_to_buffer_block(type))
non_block_types.insert(type_id);

if (meta.alignment == 0)
Expand Down Expand Up @@ -5114,9 +5121,7 @@ bool Compiler::PhysicalStorageBufferPointerHandler::handle(Op op, const uint32_t
uint32_t Compiler::PhysicalStorageBufferPointerHandler::get_base_non_block_type_id(uint32_t type_id) const
{
auto *type = &compiler.get<SPIRType>(type_id);
while (type->pointer &&
type->storage == StorageClassPhysicalStorageBufferEXT &&
!type_is_bda_block_entry(type_id))
while (compiler.is_physical_pointer(*type) && !type_is_bda_block_entry(type_id))
{
type_id = type->parent_type;
type = &compiler.get<SPIRType>(type_id);
Expand All @@ -5131,12 +5136,10 @@ void Compiler::PhysicalStorageBufferPointerHandler::analyze_non_block_types_from
for (auto &member : type.member_types)
{
auto &subtype = compiler.get<SPIRType>(member);
if (subtype.basetype != SPIRType::Struct && subtype.pointer &&
subtype.storage == spv::StorageClassPhysicalStorageBufferEXT)
{

if (compiler.is_physical_pointer(subtype) && !compiler.is_physical_pointer_to_buffer_block(subtype))
non_block_types.insert(get_base_non_block_type_id(member));
}
else if (subtype.basetype == SPIRType::Struct && !subtype.pointer)
else if (subtype.basetype == SPIRType::Struct && !compiler.is_pointer(subtype))
analyze_non_block_types_from_block(subtype);
}
}
Expand All @@ -5149,9 +5152,14 @@ void Compiler::analyze_non_block_pointer_types()
// Analyze any block declaration we have to make. It might contain
// physical pointers to POD types which we never used, and thus never added to the list.
// We'll need to add those pointer types to the set of types we declare.
ir.for_each_typed_id<SPIRType>([&](uint32_t, SPIRType &type) {
if (has_decoration(type.self, DecorationBlock) || has_decoration(type.self, DecorationBufferBlock))
ir.for_each_typed_id<SPIRType>([&](uint32_t id, SPIRType &type) {
// Only analyze the raw block struct, not any pointer-to-struct, since that's just redundant.
if (type.self == id &&
(has_decoration(type.self, DecorationBlock) ||
has_decoration(type.self, DecorationBufferBlock)))
{
handler.analyze_non_block_types_from_block(type);
}
});

physical_storage_non_block_pointer_types.reserve(handler.non_block_types.size());
Expand Down
1 change: 1 addition & 0 deletions 3rdparty/spirv-cross/spirv_cross.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,7 @@ class Compiler
bool is_array(const SPIRType &type) const;
bool is_pointer(const SPIRType &type) const;
bool is_physical_pointer(const SPIRType &type) const;
bool is_physical_pointer_to_buffer_block(const SPIRType &type) const;
static bool is_runtime_size_array(const SPIRType &type);
uint32_t expression_type_id(uint32_t id) const;
const SPIRType &expression_type(uint32_t id) const;
Expand Down
1 change: 1 addition & 0 deletions 3rdparty/spirv-cross/spirv_cross_containers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,7 @@ class ObjectPool : public ObjectPoolBase
if (!ptr)
return nullptr;

vacants.reserve(num_objects);
for (unsigned i = 0; i < num_objects; i++)
vacants.push_back(&ptr[i]);

Expand Down
5 changes: 5 additions & 0 deletions 3rdparty/spirv-cross/spirv_cross_error_handling.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ class CompilerError : public std::runtime_error
: std::runtime_error(str)
{
}

explicit CompilerError(const char *str)
: std::runtime_error(str)
{
}
};

#define SPIRV_CROSS_THROW(x) throw CompilerError(x)
Expand Down
125 changes: 82 additions & 43 deletions 3rdparty/spirv-cross/spirv_glsl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1768,7 +1768,9 @@ bool CompilerGLSL::buffer_is_packing_standard(const SPIRType &type, BufferPackin
for (uint32_t i = 0; i < type.member_types.size(); i++)
{
auto &memb_type = get<SPIRType>(type.member_types[i]);
auto member_flags = ir.meta[type.self].members[i].decoration_flags;

auto *type_meta = ir.find_meta(type.self);
auto member_flags = type_meta ? type_meta->members[i].decoration_flags : Bitset{};

// Verify alignment rules.
uint32_t packed_alignment = type_to_packed_alignment(memb_type, member_flags, packing);
Expand Down Expand Up @@ -2145,11 +2147,11 @@ string CompilerGLSL::layout_for_variable(const SPIRVariable &var)
// If SPIR-V does not comply with either layout, we cannot really work around it.
if (can_use_buffer_blocks && (ubo_block || emulated_ubo))
{
attr.push_back(buffer_to_packing_standard(type, false));
attr.push_back(buffer_to_packing_standard(type, false, true));
}
else if (can_use_buffer_blocks && (push_constant_block || ssbo_block))
{
attr.push_back(buffer_to_packing_standard(type, true));
attr.push_back(buffer_to_packing_standard(type, true, true));
}

// For images, the type itself adds a layout qualifer.
Expand All @@ -2170,7 +2172,9 @@ string CompilerGLSL::layout_for_variable(const SPIRVariable &var)
return res;
}

string CompilerGLSL::buffer_to_packing_standard(const SPIRType &type, bool support_std430_without_scalar_layout)
string CompilerGLSL::buffer_to_packing_standard(const SPIRType &type,
bool support_std430_without_scalar_layout,
bool support_enhanced_layouts)
{
if (support_std430_without_scalar_layout && buffer_is_packing_standard(type, BufferPackingStd430))
return "std430";
Expand All @@ -2182,6 +2186,7 @@ string CompilerGLSL::buffer_to_packing_standard(const SPIRType &type, bool suppo
return "scalar";
}
else if (support_std430_without_scalar_layout &&
support_enhanced_layouts &&
buffer_is_packing_standard(type, BufferPackingStd430EnhancedLayout))
{
if (options.es && !options.vulkan_semantics)
Expand All @@ -2193,7 +2198,8 @@ string CompilerGLSL::buffer_to_packing_standard(const SPIRType &type, bool suppo
set_extended_decoration(type.self, SPIRVCrossDecorationExplicitOffset);
return "std430";
}
else if (buffer_is_packing_standard(type, BufferPackingStd140EnhancedLayout))
else if (support_enhanced_layouts &&
buffer_is_packing_standard(type, BufferPackingStd140EnhancedLayout))
{
// Fallback time. We might be able to use the ARB_enhanced_layouts to deal with this difference,
// however, we can only use layout(offset) on the block itself, not any substructs, so the substructs better be the appropriate layout.
Expand All @@ -2207,7 +2213,9 @@ string CompilerGLSL::buffer_to_packing_standard(const SPIRType &type, bool suppo
set_extended_decoration(type.self, SPIRVCrossDecorationExplicitOffset);
return "std140";
}
else if (options.vulkan_semantics && buffer_is_packing_standard(type, BufferPackingScalarEnhancedLayout))
else if (options.vulkan_semantics &&
support_enhanced_layouts &&
buffer_is_packing_standard(type, BufferPackingScalarEnhancedLayout))
{
set_extended_decoration(type.self, SPIRVCrossDecorationExplicitOffset);
require_extension_internal("GL_EXT_scalar_block_layout");
Expand All @@ -2221,6 +2229,7 @@ string CompilerGLSL::buffer_to_packing_standard(const SPIRType &type, bool suppo
return "std430";
}
else if (!support_std430_without_scalar_layout && options.vulkan_semantics &&
support_enhanced_layouts &&
buffer_is_packing_standard(type, BufferPackingStd430EnhancedLayout))
{
// UBOs can support std430 with GL_EXT_scalar_block_layout.
Expand Down Expand Up @@ -2319,7 +2328,7 @@ void CompilerGLSL::emit_buffer_reference_block(uint32_t type_id, bool forward_de
auto &type = get<SPIRType>(type_id);
string buffer_name;

if (forward_declaration)
if (forward_declaration && is_physical_pointer_to_buffer_block(type))
{
// Block names should never alias, but from HLSL input they kind of can because block types are reused for UAVs ...
// Allow aliased name since we might be declaring the block twice. Once with buffer reference (forward declared) and one proper declaration.
Expand Down Expand Up @@ -2352,10 +2361,10 @@ void CompilerGLSL::emit_buffer_reference_block(uint32_t type_id, bool forward_de
// Ensure we emit the correct name when emitting non-forward pointer type.
ir.meta[type.self].decoration.alias = buffer_name;
}
else if (type.basetype != SPIRType::Struct)
buffer_name = type_to_glsl(type);
else
buffer_name = to_name(type.self, false);
{
buffer_name = type_to_glsl(type);
}

if (!forward_declaration)
{
Expand All @@ -2364,13 +2373,13 @@ void CompilerGLSL::emit_buffer_reference_block(uint32_t type_id, bool forward_de
if (itr != physical_storage_type_to_alignment.end())
alignment = itr->second.alignment;

if (type.basetype == SPIRType::Struct)
if (is_physical_pointer_to_buffer_block(type))
{
SmallVector<std::string> attributes;
attributes.push_back("buffer_reference");
if (alignment)
attributes.push_back(join("buffer_reference_align = ", alignment));
attributes.push_back(buffer_to_packing_standard(type, true));
attributes.push_back(buffer_to_packing_standard(type, true, true));

auto flags = ir.get_buffer_block_type_flags(type);
string decorations;
Expand All @@ -2385,14 +2394,32 @@ void CompilerGLSL::emit_buffer_reference_block(uint32_t type_id, bool forward_de

statement("layout(", merge(attributes), ")", decorations, " buffer ", buffer_name);
}
else if (alignment)
statement("layout(buffer_reference, buffer_reference_align = ", alignment, ") buffer ", buffer_name);
else
statement("layout(buffer_reference) buffer ", buffer_name);
{
string packing_standard;
if (type.basetype == SPIRType::Struct)
{
// The non-block type is embedded in a block, so we cannot use enhanced layouts :(
packing_standard = buffer_to_packing_standard(type, true, false) + ", ";
}
else if (is_array(get_pointee_type(type)))
{
SPIRType wrap_type{OpTypeStruct};
wrap_type.self = ir.increase_bound_by(1);
wrap_type.member_types.push_back(get_pointee_type_id(type_id));
ir.set_member_decoration(wrap_type.self, 0, DecorationOffset, 0);
packing_standard = buffer_to_packing_standard(wrap_type, true, false) + ", ";
}

if (alignment)
statement("layout(", packing_standard, "buffer_reference, buffer_reference_align = ", alignment, ") buffer ", buffer_name);
else
statement("layout(", packing_standard, "buffer_reference) buffer ", buffer_name);
}

begin_scope();

if (type.basetype == SPIRType::Struct)
if (is_physical_pointer_to_buffer_block(type))
{
type.member_name_cache.clear();

Expand Down Expand Up @@ -3705,31 +3732,34 @@ void CompilerGLSL::emit_resources()

if (ir.addressing_model == AddressingModelPhysicalStorageBuffer64EXT)
{
for (auto type : physical_storage_non_block_pointer_types)
{
emit_buffer_reference_block(type, false);
}

// Output buffer reference blocks.
// Do this in two stages, one with forward declaration,
// and one without. Buffer reference blocks can reference themselves
// to support things like linked lists.
ir.for_each_typed_id<SPIRType>([&](uint32_t self, SPIRType &type) {
if (type.basetype == SPIRType::Struct && type.pointer &&
type.pointer_depth == 1 && !type_is_array_of_pointers(type) &&
type.storage == StorageClassPhysicalStorageBufferEXT)
ir.for_each_typed_id<SPIRType>([&](uint32_t id, SPIRType &type) {
if (is_physical_pointer(type))
{
emit_buffer_reference_block(self, true);
bool emit_type = true;
if (!is_physical_pointer_to_buffer_block(type))
{
// Only forward-declare if we intend to emit it in the non_block_pointer types.
// Otherwise, these are just "benign" pointer types that exist as a result of access chains.
emit_type = std::find(physical_storage_non_block_pointer_types.begin(),
physical_storage_non_block_pointer_types.end(),
id) != physical_storage_non_block_pointer_types.end();
}

if (emit_type)
emit_buffer_reference_block(id, true);
}
});

ir.for_each_typed_id<SPIRType>([&](uint32_t self, SPIRType &type) {
if (type.basetype == SPIRType::Struct &&
type.pointer && type.pointer_depth == 1 && !type_is_array_of_pointers(type) &&
type.storage == StorageClassPhysicalStorageBufferEXT)
{
emit_buffer_reference_block(self, false);
}
for (auto type : physical_storage_non_block_pointer_types)
emit_buffer_reference_block(type, false);

ir.for_each_typed_id<SPIRType>([&](uint32_t id, SPIRType &type) {
if (is_physical_pointer_to_buffer_block(type))
emit_buffer_reference_block(id, false);
});
}

Expand Down Expand Up @@ -5011,11 +5041,8 @@ string CompilerGLSL::dereference_expression(const SPIRType &expr_type, const std
return expr.substr(1);
else if (backend.native_pointers)
return join('*', expr);
else if (expr_type.storage == StorageClassPhysicalStorageBufferEXT && expr_type.basetype != SPIRType::Struct &&
expr_type.pointer_depth == 1)
{
else if (is_physical_pointer(expr_type) && !is_physical_pointer_to_buffer_block(expr_type))
return join(enclose_expression(expr), ".value");
}
else
return expr;
}
Expand Down Expand Up @@ -15695,17 +15722,29 @@ string CompilerGLSL::type_to_glsl_constructor(const SPIRType &type)
// depend on a specific object's use of that type.
string CompilerGLSL::type_to_glsl(const SPIRType &type, uint32_t id)
{
if (type.pointer && type.storage == StorageClassPhysicalStorageBufferEXT && type.basetype != SPIRType::Struct)
if (is_physical_pointer(type) && !is_physical_pointer_to_buffer_block(type))
{
// Need to create a magic type name which compacts the entire type information.
string name = type_to_glsl(get_pointee_type(type));
for (size_t i = 0; i < type.array.size(); i++)
auto *parent = &get_pointee_type(type);
string name = type_to_glsl(*parent);

uint32_t array_stride = get_decoration(type.parent_type, DecorationArrayStride);

// Resolve all array dimensions in one go since once we lose the pointer type,
// array information is left to to_array_type_glsl. The base type loses array information.
while (is_array(*parent))
{
if (type.array_size_literal[i])
name += join(type.array[i], "_");
if (parent->array_size_literal.back())
name += join(type.array.back(), "_");
else
name += join("id", type.array[i], "_");
name += join("id", type.array.back(), "_");

name += "stride_" + std::to_string(array_stride);

array_stride = get_decoration(parent->parent_type, DecorationArrayStride);
parent = &get<SPIRType>(parent->parent_type);
}

name += "Pointer";
return name;
}
Expand Down
4 changes: 3 additions & 1 deletion 3rdparty/spirv-cross/spirv_glsl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -833,7 +833,9 @@ class CompilerGLSL : public Compiler
bool buffer_is_packing_standard(const SPIRType &type, BufferPackingStandard packing,
uint32_t *failed_index = nullptr, uint32_t start_offset = 0,
uint32_t end_offset = ~(0u));
std::string buffer_to_packing_standard(const SPIRType &type, bool support_std430_without_scalar_layout);
std::string buffer_to_packing_standard(const SPIRType &type,
bool support_std430_without_scalar_layout,
bool support_enhanced_layouts);

uint32_t type_to_packed_base_size(const SPIRType &type, BufferPackingStandard packing);
uint32_t type_to_packed_alignment(const SPIRType &type, const Bitset &flags, BufferPackingStandard packing);
Expand Down
Loading

0 comments on commit 7067b37

Please sign in to comment.