diff --git a/reference/opt/shaders-msl/asm/frag/locations-components.asm.frag b/reference/opt/shaders-msl/asm/frag/locations-components.asm.frag index 4ff01cb9..07ab82ac 100644 --- a/reference/opt/shaders-msl/asm/frag/locations-components.asm.frag +++ b/reference/opt/shaders-msl/asm/frag/locations-components.asm.frag @@ -11,10 +11,10 @@ struct main0_out struct main0_in { float2 m_2 [[user(locn1)]]; - float m_3 [[user(locn1)]]; + float m_3 [[user(locn1_2)]]; float m_4 [[user(locn2), flat]]; - uint m_5 [[user(locn2)]]; - uint m_6 [[user(locn2)]]; + uint m_5 [[user(locn2_1)]]; + uint m_6 [[user(locn2_2)]]; }; fragment main0_out main0(main0_in in [[stage_in]]) diff --git a/reference/shaders-msl/asm/frag/locations-components.asm.frag b/reference/shaders-msl/asm/frag/locations-components.asm.frag index ecc330db..2cebdec4 100644 --- a/reference/shaders-msl/asm/frag/locations-components.asm.frag +++ b/reference/shaders-msl/asm/frag/locations-components.asm.frag @@ -11,10 +11,10 @@ struct main0_out struct main0_in { float2 m_2 [[user(locn1)]]; - float m_3 [[user(locn1)]]; + float m_3 [[user(locn1_2)]]; float m_4 [[user(locn2), flat]]; - uint m_5 [[user(locn2)]]; - uint m_6 [[user(locn2)]]; + uint m_5 [[user(locn2_1)]]; + uint m_6 [[user(locn2_2)]]; }; fragment main0_out main0(main0_in in [[stage_in]]) diff --git a/spirv_common.hpp b/spirv_common.hpp index 8744d65d..619f2ff2 100644 --- a/spirv_common.hpp +++ b/spirv_common.hpp @@ -1217,6 +1217,7 @@ struct Meta Bitset decoration_flags; spv::BuiltIn builtin_type; uint32_t location = 0; + uint32_t component = 0; uint32_t set = 0; uint32_t binding = 0; uint32_t offset = 0; diff --git a/spirv_cross.cpp b/spirv_cross.cpp index eaddeca5..78e3d02c 100644 --- a/spirv_cross.cpp +++ b/spirv_cross.cpp @@ -1126,6 +1126,10 @@ void Compiler::set_member_decoration(uint32_t id, uint32_t index, Decoration dec dec.location = argument; break; + case DecorationComponent: + dec.component = argument; + break; + case DecorationBinding: dec.binding = argument; break; @@ -1212,6 +1216,8 @@ uint32_t Compiler::get_member_decoration(uint32_t id, uint32_t index, Decoration return dec.builtin_type; case DecorationLocation: return dec.location; + case DecorationComponent: + return dec.component; case DecorationBinding: return dec.binding; case DecorationOffset: @@ -1266,6 +1272,10 @@ void Compiler::unset_member_decoration(uint32_t id, uint32_t index, Decoration d dec.location = 0; break; + case DecorationComponent: + dec.component = 0; + break; + case DecorationOffset: dec.offset = 0; break; @@ -1315,6 +1325,10 @@ void Compiler::set_decoration(uint32_t id, Decoration decoration, uint32_t argum dec.location = argument; break; + case DecorationComponent: + dec.component = argument; + break; + case DecorationOffset: dec.offset = argument; break; @@ -1427,6 +1441,8 @@ uint32_t Compiler::get_decoration(uint32_t id, Decoration decoration) const return dec.builtin_type; case DecorationLocation: return dec.location; + case DecorationComponent: + return dec.component; case DecorationOffset: return dec.offset; case DecorationBinding: @@ -1462,6 +1478,10 @@ void Compiler::unset_decoration(uint32_t id, Decoration decoration) dec.location = 0; break; + case DecorationComponent: + dec.component = 0; + break; + case DecorationOffset: dec.offset = 0; break; diff --git a/spirv_msl.cpp b/spirv_msl.cpp index 1375622d..5d87df69 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -26,6 +26,7 @@ using namespace spirv_cross; using namespace std; static const uint32_t k_unknown_location = ~0u; +static const uint32_t k_unknown_component = ~0u; CompilerMSL::CompilerMSL(vector spirv_, vector *p_vtx_attrs, vector *p_res_bindings) @@ -794,6 +795,13 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage) mark_location_as_used_by_shader(locn, storage); } + // Copy the component location, if present. + if (has_member_decoration(type_id, mbr_idx, DecorationComponent)) + { + uint32_t comp = get_member_decoration(type_id, mbr_idx, DecorationComponent); + set_member_decoration(ib_type_id, ib_mbr_idx, DecorationComponent, comp); + } + // Mark the member as builtin if needed if (is_builtin) { @@ -936,6 +944,12 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage) mark_location_as_used_by_shader(locn, storage); } + if (get_decoration_bitset(p_var->self).get(DecorationComponent)) + { + uint32_t comp = get_decoration(p_var->self, DecorationComponent); + set_member_decoration(ib_type_id, ib_mbr_idx, DecorationComponent, comp); + } + if (get_decoration_bitset(p_var->self).get(DecorationIndex)) { uint32_t index = get_decoration(p_var->self, DecorationIndex); @@ -3129,9 +3143,15 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in return ""; } } - uint32_t locn = get_ordered_member_location(type.self, index); + uint32_t comp; + uint32_t locn = get_ordered_member_location(type.self, index, &comp); if (locn != k_unknown_location) - return string(" [[user(locn") + convert_to_string(locn) + ")]]"; + { + if (comp != k_unknown_component) + return string(" [[user(locn") + convert_to_string(locn) + "_" + convert_to_string(comp) + ")]]"; + else + return string(" [[user(locn") + convert_to_string(locn) + ")]]"; + } } // Fragment function inputs @@ -3156,9 +3176,15 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in } else { - uint32_t locn = get_ordered_member_location(type.self, index); + uint32_t comp; + uint32_t locn = get_ordered_member_location(type.self, index, &comp); if (locn != k_unknown_location) - quals = string("user(locn") + convert_to_string(locn) + ")"; + { + if (comp != k_unknown_component) + quals = string("user(locn") + convert_to_string(locn) + "_" + convert_to_string(comp) + ")"; + else + quals = string("user(locn") + convert_to_string(locn) + ")"; + } } // Don't bother decorating integers with the 'flat' attribute; it's // the default (in fact, the only option). Also don't bother with the @@ -3254,12 +3280,19 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in // If the location of the member has been explicitly set, that location is used. If not, this // function assumes the members are ordered in their location order, and simply returns the // index as the location. -uint32_t CompilerMSL::get_ordered_member_location(uint32_t type_id, uint32_t index) +uint32_t CompilerMSL::get_ordered_member_location(uint32_t type_id, uint32_t index, uint32_t *comp) { auto &m = meta.at(type_id); if (index < m.members.size()) { auto &dec = m.members[index]; + if (comp) + { + if (dec.decoration_flags.get(DecorationComponent)) + *comp = dec.component; + else + *comp = k_unknown_component; + } if (dec.decoration_flags.get(DecorationLocation)) return dec.location; } diff --git a/spirv_msl.hpp b/spirv_msl.hpp index ff53b74c..b100fa54 100644 --- a/spirv_msl.hpp +++ b/spirv_msl.hpp @@ -348,7 +348,7 @@ protected: std::string argument_decl(const SPIRFunction::Parameter &arg); std::string round_fp_tex_coords(std::string tex_coords, bool coord_is_fp); uint32_t get_metal_resource_index(SPIRVariable &var, SPIRType::BaseType basetype); - uint32_t get_ordered_member_location(uint32_t type_id, uint32_t index); + uint32_t get_ordered_member_location(uint32_t type_id, uint32_t index, uint32_t *comp = nullptr); size_t get_declared_struct_member_alignment(const SPIRType &struct_type, uint32_t index) const; std::string to_component_argument(uint32_t id); void align_struct(SPIRType &ib_type);