From a2b4d96c6ab67bc1b20cdd4e6295a12a24085745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D1=80=D0=B0=D0=BD=D0=B8=D0=BC=D0=B8=D1=80=20=D0=9A?= =?UTF-8?q?=D0=B0=D1=80=D0=B0=D1=9F=D0=B8=D1=9B?= Date: Fri, 12 Jan 2024 19:55:13 -0800 Subject: [PATCH] Updated spirv-cross. --- 3rdparty/spirv-cross/spirv.h | 13 ++ 3rdparty/spirv-cross/spirv.hpp | 13 ++ 3rdparty/spirv-cross/spirv_common.hpp | 1 + 3rdparty/spirv-cross/spirv_cross_c.cpp | 20 +++ 3rdparty/spirv-cross/spirv_cross_c.h | 6 +- 3rdparty/spirv-cross/spirv_glsl.cpp | 78 +++++++++++- 3rdparty/spirv-cross/spirv_glsl.hpp | 2 +- 3rdparty/spirv-cross/spirv_msl.cpp | 165 ++++++++++++++++++------- 3rdparty/spirv-cross/spirv_msl.hpp | 6 +- 3rdparty/spirv-cross/spirv_reflect.cpp | 4 + 10 files changed, 254 insertions(+), 54 deletions(-) diff --git a/3rdparty/spirv-cross/spirv.h b/3rdparty/spirv-cross/spirv.h index 5b6e8aaf4..2d6e215de 100644 --- a/3rdparty/spirv-cross/spirv.h +++ b/3rdparty/spirv-cross/spirv.h @@ -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; diff --git a/3rdparty/spirv-cross/spirv.hpp b/3rdparty/spirv-cross/spirv.hpp index e25264af2..f2ee9096b 100644 --- a/3rdparty/spirv-cross/spirv.hpp +++ b/3rdparty/spirv-cross/spirv.hpp @@ -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; diff --git a/3rdparty/spirv-cross/spirv_common.hpp b/3rdparty/spirv-cross/spirv_common.hpp index 7fce7ae7e..0cdbda23d 100644 --- a/3rdparty/spirv-cross/spirv_common.hpp +++ b/3rdparty/spirv-cross/spirv_common.hpp @@ -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 { diff --git a/3rdparty/spirv-cross/spirv_cross_c.cpp b/3rdparty/spirv-cross/spirv_cross_c.cpp index dc2e5ea81..679333dac 100644 --- a/3rdparty/spirv-cross/spirv_cross_c.cpp +++ b/3rdparty/spirv-cross/spirv_cross_c.cpp @@ -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); diff --git a/3rdparty/spirv-cross/spirv_cross_c.h b/3rdparty/spirv-cross/spirv_cross_c.h index dd9884f5d..47369964a 100644 --- a/3rdparty/spirv-cross/spirv_cross_c.h +++ b/3rdparty/spirv-cross/spirv_cross_c.h @@ -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); diff --git a/3rdparty/spirv-cross/spirv_glsl.cpp b/3rdparty/spirv-cross/spirv_glsl.cpp index 9b8c7d792..0efc44aee 100644 --- a/3rdparty/spirv-cross/spirv_glsl.cpp +++ b/3rdparty/spirv-cross/spirv_glsl.cpp @@ -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(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(type.image.type); string res; diff --git a/3rdparty/spirv-cross/spirv_glsl.hpp b/3rdparty/spirv-cross/spirv_glsl.hpp index c04ef88bf..4cba0bb63 100644 --- a/3rdparty/spirv-cross/spirv_glsl.hpp +++ b/3rdparty/spirv-cross/spirv_glsl.hpp @@ -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); diff --git a/3rdparty/spirv-cross/spirv_msl.cpp b/3rdparty/spirv-cross/spirv_msl.cpp index 1167e26c0..de81738e7 100644 --- a/3rdparty/spirv-cross/spirv_msl.cpp +++ b/3rdparty/spirv-cross/spirv_msl.cpp @@ -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 ", 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(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(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(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(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 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(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(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(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(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 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(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(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(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) diff --git a/3rdparty/spirv-cross/spirv_msl.hpp b/3rdparty/spirv-cross/spirv_msl.hpp index 05c09fde5..06744b873 100644 --- a/3rdparty/spirv-cross/spirv_msl.hpp +++ b/3rdparty/spirv-cross/spirv_msl.hpp @@ -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(); diff --git a/3rdparty/spirv-cross/spirv_reflect.cpp b/3rdparty/spirv-cross/spirv_reflect.cpp index b02773722..633983bd3 100644 --- a/3rdparty/spirv-cross/spirv_reflect.cpp +++ b/3rdparty/spirv-cross/spirv_reflect.cpp @@ -633,6 +633,10 @@ void CompilerReflection::emit_resources(const char *tag, const SmallVectoremit_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.