Merge pull request #1744 from billhollings/location-attribute-fix
MSL: Fix location and component variable matching between shader stages.
diff --git a/spirv_msl.cpp b/spirv_msl.cpp
index 2df3042..9e797f6 100644
--- a/spirv_msl.cpp
+++ b/spirv_msl.cpp
@@ -10672,15 +10672,9 @@
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
@@ -10794,24 +10788,7 @@
}
}
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)
{
@@ -10943,6 +10920,30 @@
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 a34ae32..9dc1a1a 100644
--- a/spirv_msl.hpp
+++ b/spirv_msl.hpp
@@ -867,6 +867,7 @@
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);