Updated spirv-cross.

This commit is contained in:
Бранимир Караџић 2024-01-12 19:55:13 -08:00
parent 52d0ae58d4
commit a2b4d96c6a
10 changed files with 254 additions and 54 deletions

View File

@ -509,6 +509,8 @@ typedef enum SpvDecoration_ {
SpvDecorationMaxByteOffsetId = 47,
SpvDecorationNoSignedWrap = 4469,
SpvDecorationNoUnsignedWrap = 4470,
SpvDecorationWeightTextureQCOM = 4487,
SpvDecorationBlockMatchTextureQCOM = 4488,
SpvDecorationExplicitInterpAMD = 4999,
SpvDecorationOverrideCoverageNV = 5248,
SpvDecorationPassthroughNV = 5250,
@ -991,6 +993,9 @@ typedef enum SpvCapability_ {
SpvCapabilityRayQueryKHR = 4472,
SpvCapabilityRayTraversalPrimitiveCullingKHR = 4478,
SpvCapabilityRayTracingKHR = 4479,
SpvCapabilityTextureSampleWeightedQCOM = 4484,
SpvCapabilityTextureBoxFilterQCOM = 4485,
SpvCapabilityTextureBlockMatchQCOM = 4486,
SpvCapabilityFloat16ImageAMD = 5008,
SpvCapabilityImageGatherBiasLodAMD = 5009,
SpvCapabilityFragmentMaskAMD = 5010,
@ -1596,6 +1601,10 @@ typedef enum SpvOp_ {
SpvOpRayQueryConfirmIntersectionKHR = 4476,
SpvOpRayQueryProceedKHR = 4477,
SpvOpRayQueryGetIntersectionTypeKHR = 4479,
SpvOpImageSampleWeightedQCOM = 4480,
SpvOpImageBoxFilterQCOM = 4481,
SpvOpImageBlockMatchSSDQCOM = 4482,
SpvOpImageBlockMatchSADQCOM = 4483,
SpvOpGroupIAddNonUniformAMD = 5000,
SpvOpGroupFAddNonUniformAMD = 5001,
SpvOpGroupFMinNonUniformAMD = 5002,
@ -2271,6 +2280,10 @@ inline void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultTy
case SpvOpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break;
case SpvOpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break;
case SpvOpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break;
case SpvOpImageSampleWeightedQCOM: *hasResult = true; *hasResultType = true; break;
case SpvOpImageBoxFilterQCOM: *hasResult = true; *hasResultType = true; break;
case SpvOpImageBlockMatchSSDQCOM: *hasResult = true; *hasResultType = true; break;
case SpvOpImageBlockMatchSADQCOM: *hasResult = true; *hasResultType = true; break;
case SpvOpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break;
case SpvOpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break;
case SpvOpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break;

View File

@ -505,6 +505,8 @@ enum Decoration {
DecorationMaxByteOffsetId = 47,
DecorationNoSignedWrap = 4469,
DecorationNoUnsignedWrap = 4470,
DecorationWeightTextureQCOM = 4487,
DecorationBlockMatchTextureQCOM = 4488,
DecorationExplicitInterpAMD = 4999,
DecorationOverrideCoverageNV = 5248,
DecorationPassthroughNV = 5250,
@ -987,6 +989,9 @@ enum Capability {
CapabilityRayQueryKHR = 4472,
CapabilityRayTraversalPrimitiveCullingKHR = 4478,
CapabilityRayTracingKHR = 4479,
CapabilityTextureSampleWeightedQCOM = 4484,
CapabilityTextureBoxFilterQCOM = 4485,
CapabilityTextureBlockMatchQCOM = 4486,
CapabilityFloat16ImageAMD = 5008,
CapabilityImageGatherBiasLodAMD = 5009,
CapabilityFragmentMaskAMD = 5010,
@ -1592,6 +1597,10 @@ enum Op {
OpRayQueryConfirmIntersectionKHR = 4476,
OpRayQueryProceedKHR = 4477,
OpRayQueryGetIntersectionTypeKHR = 4479,
OpImageSampleWeightedQCOM = 4480,
OpImageBoxFilterQCOM = 4481,
OpImageBlockMatchSSDQCOM = 4482,
OpImageBlockMatchSADQCOM = 4483,
OpGroupIAddNonUniformAMD = 5000,
OpGroupFAddNonUniformAMD = 5001,
OpGroupFMinNonUniformAMD = 5002,
@ -2267,6 +2276,10 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
case OpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break;
case OpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break;
case OpImageSampleWeightedQCOM: *hasResult = true; *hasResultType = true; break;
case OpImageBoxFilterQCOM: *hasResult = true; *hasResultType = true; break;
case OpImageBlockMatchSSDQCOM: *hasResult = true; *hasResultType = true; break;
case OpImageBlockMatchSADQCOM: *hasResult = true; *hasResultType = true; break;
case OpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break;
case OpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break;
case OpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break;

View File

@ -1696,6 +1696,7 @@ struct Meta
uint32_t index = 0;
spv::FPRoundingMode fp_rounding_mode = spv::FPRoundingModeMax;
bool builtin = false;
bool qualified_alias_explicit_override = false;
struct Extended
{

View File

@ -2552,6 +2552,16 @@ int spvc_constant_get_scalar_i32(spvc_constant constant, unsigned column, unsign
return constant->scalar_i32(column, row);
}
unsigned long long spvc_constant_get_scalar_u64(spvc_constant constant, unsigned column, unsigned row)
{
return constant->scalar_u64(column, row);
}
long long spvc_constant_get_scalar_i64(spvc_constant constant, unsigned column, unsigned row)
{
return constant->scalar_i64(column, row);
}
unsigned spvc_constant_get_scalar_u16(spvc_constant constant, unsigned column, unsigned row)
{
return constant->scalar_u16(column, row);
@ -2609,6 +2619,16 @@ void spvc_constant_set_scalar_i32(spvc_constant constant, unsigned column, unsig
constant->m.c[column].r[row].i32 = value;
}
void spvc_constant_set_scalar_u64(spvc_constant constant, unsigned column, unsigned row, unsigned long long value)
{
constant->m.c[column].r[row].u64 = value;
}
void spvc_constant_set_scalar_i64(spvc_constant constant, unsigned column, unsigned row, long long value)
{
constant->m.c[column].r[row].i64 = value;
}
void spvc_constant_set_scalar_u16(spvc_constant constant, unsigned column, unsigned row, unsigned short value)
{
constant->m.c[column].r[row].u32 = uint32_t(value);

View File

@ -40,7 +40,7 @@ extern "C" {
/* Bumped if ABI or API breaks backwards compatibility. */
#define SPVC_C_API_VERSION_MAJOR 0
/* Bumped if APIs or enumerations are added in a backwards compatible way. */
#define SPVC_C_API_VERSION_MINOR 58
#define SPVC_C_API_VERSION_MINOR 59
/* Bumped if internal implementation details change. */
#define SPVC_C_API_VERSION_PATCH 0
@ -1052,6 +1052,8 @@ SPVC_PUBLIC_API int spvc_constant_get_scalar_i16(spvc_constant constant, unsigne
SPVC_PUBLIC_API unsigned spvc_constant_get_scalar_u8(spvc_constant constant, unsigned column, unsigned row);
SPVC_PUBLIC_API int spvc_constant_get_scalar_i8(spvc_constant constant, unsigned column, unsigned row);
SPVC_PUBLIC_API void spvc_constant_get_subconstants(spvc_constant constant, const spvc_constant_id **constituents, size_t *count);
SPVC_PUBLIC_API unsigned long long spvc_constant_get_scalar_u64(spvc_constant constant, unsigned column, unsigned row);
SPVC_PUBLIC_API long long spvc_constant_get_scalar_i64(spvc_constant constant, unsigned column, unsigned row);
SPVC_PUBLIC_API spvc_type_id spvc_constant_get_type(spvc_constant constant);
/*
@ -1062,6 +1064,8 @@ SPVC_PUBLIC_API void spvc_constant_set_scalar_fp32(spvc_constant constant, unsig
SPVC_PUBLIC_API void spvc_constant_set_scalar_fp64(spvc_constant constant, unsigned column, unsigned row, double value);
SPVC_PUBLIC_API void spvc_constant_set_scalar_u32(spvc_constant constant, unsigned column, unsigned row, unsigned value);
SPVC_PUBLIC_API void spvc_constant_set_scalar_i32(spvc_constant constant, unsigned column, unsigned row, int value);
SPVC_PUBLIC_API void spvc_constant_set_scalar_u64(spvc_constant constant, unsigned column, unsigned row, unsigned long long value);
SPVC_PUBLIC_API void spvc_constant_set_scalar_i64(spvc_constant constant, unsigned column, unsigned row, long long value);
SPVC_PUBLIC_API void spvc_constant_set_scalar_u16(spvc_constant constant, unsigned column, unsigned row, unsigned short value);
SPVC_PUBLIC_API void spvc_constant_set_scalar_i16(spvc_constant constant, unsigned column, unsigned row, signed short value);
SPVC_PUBLIC_API void spvc_constant_set_scalar_u8(spvc_constant constant, unsigned column, unsigned row, unsigned char value);

View File

@ -1797,8 +1797,20 @@ bool CompilerGLSL::buffer_is_packing_standard(const SPIRType &type, BufferPackin
if (packing_is_hlsl(packing))
{
// If a member straddles across a vec4 boundary, alignment is actually vec4.
uint32_t begin_word = actual_offset / 16;
uint32_t end_word = (actual_offset + packed_size - 1) / 16;
uint32_t target_offset;
// If we intend to use explicit packing, we must check for improper straddle with that offset.
// In implicit packing, we must check with implicit offset, since the explicit offset
// might have already accounted for the straddle, and we'd miss the alignment promotion to vec4.
// This is important when packing sub-structs that don't support packoffset().
if (packing_has_flexible_offset(packing))
target_offset = actual_offset;
else
target_offset = offset;
uint32_t begin_word = target_offset / 16;
uint32_t end_word = (target_offset + packed_size - 1) / 16;
if (begin_word != end_word)
packed_alignment = max<uint32_t>(packed_alignment, 16u);
}
@ -14136,6 +14148,66 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
break;
}
case OpImageSampleWeightedQCOM:
case OpImageBoxFilterQCOM:
case OpImageBlockMatchSSDQCOM:
case OpImageBlockMatchSADQCOM:
{
require_extension_internal("GL_QCOM_image_processing");
uint32_t result_type_id = ops[0];
uint32_t id = ops[1];
string expr;
switch (opcode)
{
case OpImageSampleWeightedQCOM:
expr = "textureWeightedQCOM";
break;
case OpImageBoxFilterQCOM:
expr = "textureBoxFilterQCOM";
break;
case OpImageBlockMatchSSDQCOM:
expr = "textureBlockMatchSSDQCOM";
break;
case OpImageBlockMatchSADQCOM:
expr = "textureBlockMatchSADQCOM";
break;
default:
SPIRV_CROSS_THROW("Invalid opcode for QCOM_image_processing.");
}
expr += "(";
bool forward = false;
expr += to_expression(ops[2]);
expr += ", " + to_expression(ops[3]);
switch (opcode)
{
case OpImageSampleWeightedQCOM:
expr += ", " + to_non_uniform_aware_expression(ops[4]);
break;
case OpImageBoxFilterQCOM:
expr += ", " + to_expression(ops[4]);
break;
case OpImageBlockMatchSSDQCOM:
case OpImageBlockMatchSADQCOM:
expr += ", " + to_non_uniform_aware_expression(ops[4]);
expr += ", " + to_expression(ops[5]);
expr += ", " + to_expression(ops[6]);
break;
default:
SPIRV_CROSS_THROW("Invalid opcode for QCOM_image_processing.");
}
expr += ")";
emit_op(result_type_id, id, expr, forward);
inherit_expression_dependencies(id, ops[3]);
if (opcode == OpImageBlockMatchSSDQCOM || opcode == OpImageBlockMatchSADQCOM)
inherit_expression_dependencies(id, ops[5]);
break;
}
// Compute
case OpControlBarrier:
case OpMemoryBarrier:
@ -15471,7 +15543,7 @@ string CompilerGLSL::type_to_array_glsl(const SPIRType &type)
}
}
string CompilerGLSL::image_type_glsl(const SPIRType &type, uint32_t id)
string CompilerGLSL::image_type_glsl(const SPIRType &type, uint32_t id, bool /*member*/)
{
auto &imagetype = get<SPIRType>(type.image.type);
string res;

View File

@ -438,7 +438,7 @@ protected:
virtual void emit_struct_member(const SPIRType &type, uint32_t member_type_id, uint32_t index,
const std::string &qualifier = "", uint32_t base_offset = 0);
virtual void emit_struct_padding_target(const SPIRType &type);
virtual std::string image_type_glsl(const SPIRType &type, uint32_t id = 0);
virtual std::string image_type_glsl(const SPIRType &type, uint32_t id = 0, bool member = false);
std::string constant_expression(const SPIRConstant &c,
bool inside_block_like_struct_scope = false,
bool inside_struct_scope = false);

View File

@ -191,13 +191,19 @@ bool CompilerMSL::is_msl_resource_binding_used(ExecutionModel model, uint32_t de
bool CompilerMSL::is_var_runtime_size_array(const SPIRVariable &var) const
{
return is_runtime_size_array(get_variable_data_type(var)) && get_resource_array_size(var.self) == 0;
auto& type = get_variable_data_type(var);
return is_runtime_size_array(type) && get_resource_array_size(type, var.self) == 0;
}
// Returns the size of the array of resources used by the variable with the specified id.
// The returned value is retrieved from the resource binding added using add_msl_resource_binding().
uint32_t CompilerMSL::get_resource_array_size(uint32_t id) const
// Returns the size of the array of resources used by the variable with the specified type and id.
// The size is first retrieved from the type, but in the case of runtime array sizing,
// the size is retrieved from the resource binding added using add_msl_resource_binding().
uint32_t CompilerMSL::get_resource_array_size(const SPIRType &type, uint32_t id) const
{
uint32_t array_size = to_array_size_literal(type);
if (array_size)
return array_size;
StageSetBinding tuple = { get_entry_point().model, get_decoration(id, DecorationDescriptorSet),
get_decoration(id, DecorationBinding) };
auto itr = resource_bindings.find(tuple);
@ -1373,20 +1379,28 @@ void CompilerMSL::emit_entry_point_declarations()
{
SPIRV_CROSS_THROW("Unsized array of descriptors requires argument buffer tier 2");
}
string resource_name;
if (descriptor_set_is_argument_buffer(get_decoration(var.self, DecorationDescriptorSet)))
resource_name = ir.meta[var.self].decoration.qualified_alias;
else
resource_name = name + "_";
switch (type.basetype)
{
case SPIRType::Image:
case SPIRType::Sampler:
case SPIRType::AccelerationStructure:
statement("spvDescriptorArray<", type_to_glsl(buffer_type), "> ", name, " {", name, "_};");
statement("spvDescriptorArray<", type_to_glsl(buffer_type), "> ", name, " {", resource_name, "};");
break;
case SPIRType::SampledImage:
statement("spvDescriptorArray<", type_to_glsl(buffer_type), "> ", name, " {", name, "_};");
statement("spvDescriptorArray<", type_to_glsl(buffer_type), "> ", name, " {", resource_name, "};");
// Unsupported with argument buffer for now.
statement("spvDescriptorArray<sampler> ", name, "Smplr {", name, "Smplr_};");
break;
case SPIRType::Struct:
statement("spvDescriptorArray<", get_argument_address_space(var), " ", type_to_glsl(buffer_type), "*> ",
name, " {", name, "_};");
name, " {", resource_name, "};");
break;
default:
break;
@ -1399,7 +1413,8 @@ void CompilerMSL::emit_entry_point_declarations()
statement(get_argument_address_space(var), " ", type_to_glsl(buffer_type), "* ",
to_restrict(var.self, true), name, "[] =");
begin_scope();
for (uint32_t i = 0; i < to_array_size_literal(type); ++i)
uint32_t array_size = get_resource_array_size(type, var.self);
for (uint32_t i = 0; i < array_size; ++i)
statement(name, "_", i, ",");
end_scope_decl();
statement_no_indent("");
@ -10658,7 +10673,7 @@ void CompilerMSL::emit_function_prototype(SPIRFunction &func, const Bitset &)
{
if (arg_type.array.empty() || (var ? is_var_runtime_size_array(*var) : is_runtime_size_array(arg_type)))
{
decl += join(", ", sampler_type(arg_type, arg.id), " ", to_sampler_expression(name_id));
decl += join(", ", sampler_type(arg_type, arg.id, false), " ", to_sampler_expression(name_id));
}
else
{
@ -10666,7 +10681,7 @@ void CompilerMSL::emit_function_prototype(SPIRFunction &func, const Bitset &)
descriptor_address_space(name_id,
StorageClassUniformConstant,
"thread const");
decl += join(", ", sampler_address_space, " ", sampler_type(arg_type, name_id), "& ",
decl += join(", ", sampler_address_space, " ", sampler_type(arg_type, name_id, false), "& ",
to_sampler_expression(name_id));
}
}
@ -12056,6 +12071,20 @@ string CompilerMSL::to_struct_member(const SPIRType &type, uint32_t member_type_
array_type = type_to_array_glsl(physical_type);
}
if (orig_id)
{
auto *data_type = declared_type;
if (is_pointer(*data_type))
data_type = &get_pointee_type(*data_type);
if (is_array(*data_type) && get_resource_array_size(*data_type, orig_id) == 0)
{
// Hack for declaring unsized array of resources. Need to declare dummy sized array by value inline.
// This can then be wrapped in spvDescriptorArray as usual.
array_type = "[1] /* unsized array hack */";
}
}
string decl_type;
if (declared_type->vecsize > 4)
{
@ -13276,12 +13305,22 @@ void CompilerMSL::entry_point_args_discrete_descriptors(string &ep_args)
!is_hidden_variable(var))
{
auto &type = get_variable_data_type(var);
uint32_t desc_set = get_decoration(var_id, DecorationDescriptorSet);
if (is_supported_argument_buffer_type(type) && var.storage != StorageClassPushConstant)
{
uint32_t desc_set = get_decoration(var_id, DecorationDescriptorSet);
if (descriptor_set_is_argument_buffer(desc_set))
{
if (is_var_runtime_size_array(var))
{
// Runtime arrays need to be wrapped in spvDescriptorArray from argument buffer payload.
entry_point_bindings.push_back(&var);
// We'll wrap this, so to_name() will always use non-qualified name.
// We'll need the qualified name to create temporary variable instead.
ir.meta[var_id].decoration.qualified_alias_explicit_override = true;
}
return;
}
}
// Handle descriptor aliasing. We can handle aliasing of buffers by casting pointers,
@ -13410,11 +13449,6 @@ void CompilerMSL::entry_point_args_discrete_descriptors(string &ep_args)
if (type.array.size() > 1)
SPIRV_CROSS_THROW("Arrays of arrays of buffers are not supported.");
// Metal doesn't directly support this, so we must expand the
// array. We'll declare a local array to hold these elements
// later.
uint32_t array_size = to_array_size_literal(type);
is_using_builtin_array = true;
if (is_var_runtime_size_array(var))
{
@ -13442,6 +13476,7 @@ void CompilerMSL::entry_point_args_discrete_descriptors(string &ep_args)
}
else
{
uint32_t array_size = get_resource_array_size(type, var_id);
for (uint32_t i = 0; i < array_size; ++i)
{
if (!ep_args.empty())
@ -13477,7 +13512,7 @@ void CompilerMSL::entry_point_args_discrete_descriptors(string &ep_args)
case SPIRType::Sampler:
if (!ep_args.empty())
ep_args += ", ";
ep_args += sampler_type(type, var_id) + " " + r.name;
ep_args += sampler_type(type, var_id, false) + " " + r.name;
if (is_var_runtime_size_array(var))
ep_args += "_ [[buffer(" + convert_to_string(r.index) + ")]]";
else
@ -13492,7 +13527,7 @@ void CompilerMSL::entry_point_args_discrete_descriptors(string &ep_args)
const auto &basetype = get<SPIRType>(var.basetype);
if (!type_is_msl_framebuffer_fetch(basetype))
{
ep_args += image_type_glsl(type, var_id) + " " + r.name;
ep_args += image_type_glsl(type, var_id, false) + " " + r.name;
if (r.plane > 0)
ep_args += join(plane_name_suffix, r.plane);
@ -13509,7 +13544,7 @@ void CompilerMSL::entry_point_args_discrete_descriptors(string &ep_args)
{
if (msl_options.is_macos() && !msl_options.supports_msl_version(2, 3))
SPIRV_CROSS_THROW("Framebuffer fetch on Mac is not supported before MSL 2.3.");
ep_args += image_type_glsl(type, var_id) + " " + r.name;
ep_args += image_type_glsl(type, var_id, false) + " " + r.name;
ep_args += " [[color(" + convert_to_string(r.index) + ")]]";
}
@ -14497,11 +14532,15 @@ string CompilerMSL::argument_decl(const SPIRFunction::Parameter &arg)
if (!address_space.empty())
decl = join(address_space, " ", decl);
const char *argument_buffer_space = descriptor_address_space(name_id, type_storage, nullptr);
if (argument_buffer_space)
// spvDescriptorArray absorbs the address space inside the template.
if (!is_var_runtime_size_array(var))
{
decl += " ";
decl += argument_buffer_space;
const char *argument_buffer_space = descriptor_address_space(name_id, type_storage, nullptr);
if (argument_buffer_space)
{
decl += " ";
decl += argument_buffer_space;
}
}
// Special case, need to override the array size here if we're using tess level as an argument.
@ -14623,7 +14662,7 @@ string CompilerMSL::to_name(uint32_t id, bool allow_alias) const
if (current_function && (current_function->self == ir.default_entry_point))
{
auto *m = ir.find_meta(id);
if (m && !m->decoration.qualified_alias.empty())
if (m && !m->decoration.qualified_alias_explicit_override && !m->decoration.qualified_alias.empty())
return m->decoration.qualified_alias;
}
return Compiler::to_name(id, allow_alias);
@ -15046,6 +15085,26 @@ string CompilerMSL::type_to_glsl(const SPIRType &type, uint32_t id, bool member)
auto type_address_space = get_type_address_space(type, id);
const auto *p_parent_type = &get<SPIRType>(type.parent_type);
// If we're wrapping buffer descriptors in a spvDescriptorArray, we'll have to handle it as a special case.
if (member && id)
{
auto &var = get<SPIRVariable>(id);
if (is_var_runtime_size_array(var) && is_runtime_size_array(*p_parent_type))
{
const bool ssbo = has_decoration(p_parent_type->self, DecorationBufferBlock);
bool buffer_desc =
(var.storage == StorageClassStorageBuffer || ssbo) &&
msl_options.runtime_array_rich_descriptor;
const char *wrapper_type = buffer_desc ? "spvBufferDescriptor" : "spvDescriptor";
add_spv_func_and_recompile(SPVFuncImplVariableDescriptorArray);
add_spv_func_and_recompile(buffer_desc ? SPVFuncImplVariableSizedDescriptor : SPVFuncImplVariableDescriptor);
type_name = join(wrapper_type, "<", type_address_space, " ", type_to_glsl(*p_parent_type, id), " *>");
return type_name;
}
}
// Work around C pointer qualifier rules. If glsl_type is a pointer type as well
// we'll need to emit the address space to the right.
// We could always go this route, but it makes the code unnatural.
@ -15104,10 +15163,10 @@ string CompilerMSL::type_to_glsl(const SPIRType &type, uint32_t id, bool member)
case SPIRType::Image:
case SPIRType::SampledImage:
return image_type_glsl(type, id);
return image_type_glsl(type, id, member);
case SPIRType::Sampler:
return sampler_type(type, id);
return sampler_type(type, id, member);
case SPIRType::Void:
return "void";
@ -15323,7 +15382,7 @@ std::string CompilerMSL::variable_decl(const SPIRType &type, const std::string &
return CompilerGLSL::variable_decl(type, name, id);
}
std::string CompilerMSL::sampler_type(const SPIRType &type, uint32_t id)
std::string CompilerMSL::sampler_type(const SPIRType &type, uint32_t id, bool member)
{
auto *var = maybe_get<SPIRVariable>(id);
if (var && var->basevariable)
@ -15342,29 +15401,31 @@ std::string CompilerMSL::sampler_type(const SPIRType &type, uint32_t id)
// Arrays of samplers in MSL must be declared with a special array<T, N> syntax ala C++11 std::array.
// If we have a runtime array, it could be a variable-count descriptor set binding.
uint32_t array_size = to_array_size_literal(type);
if (array_size == 0)
array_size = get_resource_array_size(id);
auto &parent = get<SPIRType>(get_pointee_type(type).parent_type);
uint32_t array_size = get_resource_array_size(type, id);
if (array_size == 0)
{
add_spv_func_and_recompile(SPVFuncImplVariableDescriptor);
add_spv_func_and_recompile(SPVFuncImplVariableDescriptorArray);
auto &parent = get<SPIRType>(get_pointee_type(type).parent_type);
if (processing_entry_point)
return join("const device spvDescriptor<", sampler_type(parent, id), ">*");
return join("const spvDescriptorArray<", sampler_type(parent, id), ">");
}
auto &parent = get<SPIRType>(get_pointee_type(type).parent_type);
return join("array<", sampler_type(parent, id), ", ", array_size, ">");
const char *descriptor_wrapper = processing_entry_point ? "const device spvDescriptor" : "const spvDescriptorArray";
if (member)
descriptor_wrapper = "spvDescriptor";
return join(descriptor_wrapper, "<", sampler_type(parent, id, false), ">",
processing_entry_point ? "*" : "");
}
else
{
return join("array<", sampler_type(parent, id, false), ", ", array_size, ">");
}
}
else
return "sampler";
}
// Returns an MSL string describing the SPIR-V image type
string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id)
string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id, bool member)
{
auto *var = maybe_get<SPIRVariable>(id);
if (var && var->basevariable)
@ -15395,20 +15456,29 @@ string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id)
// Arrays of images in MSL must be declared with a special array<T, N> syntax ala C++11 std::array.
// If we have a runtime array, it could be a variable-count descriptor set binding.
uint32_t array_size = to_array_size_literal(type);
if (array_size == 0)
array_size = get_resource_array_size(id);
auto &parent = get<SPIRType>(get_pointee_type(type).parent_type);
uint32_t array_size = get_resource_array_size(type, id);
if (array_size == 0)
{
add_spv_func_and_recompile(SPVFuncImplVariableDescriptor);
add_spv_func_and_recompile(SPVFuncImplVariableDescriptorArray);
auto &parent = get<SPIRType>(get_pointee_type(type).parent_type);
return join("const device spvDescriptor<", image_type_glsl(parent, id), ">*");
const char *descriptor_wrapper = processing_entry_point ? "const device spvDescriptor" : "const spvDescriptorArray";
if (member)
{
descriptor_wrapper = "spvDescriptor";
// This requires a specialized wrapper type that packs image and sampler side by side.
// It is possible in theory.
if (type.basetype == SPIRType::SampledImage)
SPIRV_CROSS_THROW("Argument buffer runtime array currently not supported for combined image sampler.");
}
return join(descriptor_wrapper, "<", image_type_glsl(parent, id, false), ">",
processing_entry_point ? "*" : "");
}
else
{
return join("array<", image_type_glsl(parent, id, false), ", ", array_size, ">");
}
auto &parent = get<SPIRType>(get_pointee_type(type).parent_type);
return join("array<", image_type_glsl(parent, id), ", ", array_size, ">");
}
string img_type_name;
@ -17845,6 +17915,9 @@ void CompilerMSL::analyze_argument_buffers()
auto &var = *resource.var;
auto &type = get_variable_data_type(var);
if (is_var_runtime_size_array(var) && (argument_buffer_device_storage_mask & (1u << desc_set)) == 0)
SPIRV_CROSS_THROW("Runtime sized variables must be in device storage argument buffers.");
// If needed, synthesize and add padding members.
// member_index and next_arg_buff_index are incremented when padding members are added.
if (msl_options.pad_argument_buffer_resources)

View File

@ -862,8 +862,8 @@ protected:
// GCC workaround of lambdas calling protected functions (for older GCC versions)
std::string variable_decl(const SPIRType &type, const std::string &name, uint32_t id = 0) override;
std::string image_type_glsl(const SPIRType &type, uint32_t id = 0) override;
std::string sampler_type(const SPIRType &type, uint32_t id);
std::string image_type_glsl(const SPIRType &type, uint32_t id, bool member) override;
std::string sampler_type(const SPIRType &type, uint32_t id, bool member);
std::string builtin_to_glsl(spv::BuiltIn builtin, spv::StorageClass storage) override;
std::string to_func_call_arg(const SPIRFunction::Parameter &arg, uint32_t id) override;
std::string to_name(uint32_t id, bool allow_alias = true) const override;
@ -977,7 +977,7 @@ protected:
void emit_interface_block(uint32_t ib_var_id);
bool maybe_emit_array_assignment(uint32_t id_lhs, uint32_t id_rhs);
bool is_var_runtime_size_array(const SPIRVariable &var) const;
uint32_t get_resource_array_size(uint32_t id) const;
uint32_t get_resource_array_size(const SPIRType &type, uint32_t id) const;
void fix_up_shader_inputs_outputs();

View File

@ -633,6 +633,10 @@ void CompilerReflection::emit_resources(const char *tag, const SmallVector<Resou
get_decoration(res.id, DecorationInputAttachmentIndex));
if (mask.get(DecorationOffset))
json_stream->emit_json_key_value("offset", get_decoration(res.id, DecorationOffset));
if (mask.get(DecorationWeightTextureQCOM))
json_stream->emit_json_key_value("WeightTextureQCOM", get_decoration(res.id, DecorationWeightTextureQCOM));
if (mask.get(DecorationBlockMatchTextureQCOM))
json_stream->emit_json_key_value("BlockMatchTextureQCOM", get_decoration(res.id, DecorationBlockMatchTextureQCOM));
// For images, the type itself adds a layout qualifer.
// Only emit the format for storage images.