From 86dfac12c887ae8622f7370b4f9958250d8f2965 Mon Sep 17 00:00:00 2001 From: Bill Hollings Date: Sat, 18 Sep 2021 18:55:12 -0400 Subject: [PATCH] MSL: Fix location and component variable matching between shader stages. Consolidate derivation of Metal 'user(locnL_C)' output/input location and component attribute qualifier, to establish SVOT across stages. --- spirv_msl.cpp | 55 ++++++++++++++++++++++++++------------------------- spirv_msl.hpp | 1 + 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/spirv_msl.cpp b/spirv_msl.cpp index acd71ace..28b5c2d6 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -10666,15 +10666,9 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in return ""; } } - uint32_t comp; - uint32_t locn = get_member_location(type.self, index, &comp); - if (locn != k_unknown_location) - { - 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) + ")]]"; - } + string loc_qual = member_location_attribute_qualifier(type, index); + if (!loc_qual.empty()) + return join(" [[", loc_qual, "]]"); } // Tessellation control function inputs @@ -10788,24 +10782,7 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in } } else - { - uint32_t comp; - uint32_t locn = get_member_location(type.self, index, &comp); - if (locn != k_unknown_location) - { - // For user-defined attributes, this is fine. From Vulkan spec: - // A user-defined output variable is considered to match an input variable in the subsequent stage if - // the two variables are declared with the same Location and Component decoration and match in type - // and decoration, except that interpolation decorations are not required to match. For the purposes - // of interface matching, variables declared without a Component decoration are considered to have a - // Component decoration of zero. - - if (comp != k_unknown_component && comp != 0) - quals = string("user(locn") + convert_to_string(locn) + "_" + convert_to_string(comp) + ")"; - else - quals = string("user(locn") + convert_to_string(locn) + ")"; - } - } + quals = member_location_attribute_qualifier(type, index); if (builtin == BuiltInBaryCoordNV || builtin == BuiltInBaryCoordNoPerspNV) { @@ -10937,6 +10914,30 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in return ""; } +// A user-defined output variable is considered to match an input variable in the subsequent +// stage if the two variables are declared with the same Location and Component decoration and +// match in type and decoration, except that interpolation decorations are not required to match. +// For the purposes of interface matching, variables declared without a Component decoration are +// considered to have a Component decoration of zero. +string CompilerMSL::member_location_attribute_qualifier(const SPIRType &type, uint32_t index) +{ + string quals; + uint32_t comp; + uint32_t locn = get_member_location(type.self, index, &comp); + if (locn != k_unknown_location) + { + quals += "user(locn"; + quals += convert_to_string(locn); + if (comp != k_unknown_component && comp != 0) + { + quals += "_"; + quals += convert_to_string(comp); + } + quals += ")"; + } + return quals; +} + // Returns the location decoration of the member with the specified index in the specified type. // 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 diff --git a/spirv_msl.hpp b/spirv_msl.hpp index a34ae32e..9dc1a1a0 100644 --- a/spirv_msl.hpp +++ b/spirv_msl.hpp @@ -867,6 +867,7 @@ protected: std::string builtin_type_decl(spv::BuiltIn builtin, uint32_t id = 0); std::string built_in_func_arg(spv::BuiltIn builtin, bool prefix_comma); std::string member_attribute_qualifier(const SPIRType &type, uint32_t index); + std::string member_location_attribute_qualifier(const SPIRType &type, uint32_t index); 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 plane = 0);