mirror of https://github.com/bkaradzic/bgfx
Updated spirv-cross.
This commit is contained in:
parent
52d0ae58d4
commit
a2b4d96c6a
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue