diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index f200b424..40f9e674 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -15483,7 +15483,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/spirv_glsl.hpp b/spirv_glsl.hpp index c04ef88b..4cba0bb6 100644 --- a/spirv_glsl.hpp +++ b/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/spirv_msl.cpp b/spirv_msl.cpp index 200167a2..9560a523 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -10665,7 +10665,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 { @@ -10673,7 +10673,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)); } } @@ -12062,6 +12062,12 @@ string CompilerMSL::to_struct_member(const SPIRType &type, uint32_t member_type_ is_using_builtin_array = true; array_type = type_to_array_glsl(physical_type); } + else if (is_array(*declared_type) && get_resource_array_size(*declared_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) @@ -13480,7 +13486,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 @@ -13495,7 +13501,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); @@ -13512,7 +13518,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) + ")]]"; } @@ -15107,10 +15113,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"; @@ -15326,7 +15332,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) @@ -15345,26 +15351,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. + 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,17 +15406,23 @@ 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. + 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"; + 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; diff --git a/spirv_msl.hpp b/spirv_msl.hpp index 45109d88..06744b87 100644 --- a/spirv_msl.hpp +++ b/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;