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.
This commit is contained in:
Bill Hollings 2021-09-18 18:55:12 -04:00
parent b81334a513
commit 86dfac12c8
2 changed files with 29 additions and 27 deletions

View File

@ -10666,15 +10666,9 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in
return ""; return "";
} }
} }
uint32_t comp; string loc_qual = member_location_attribute_qualifier(type, index);
uint32_t locn = get_member_location(type.self, index, &comp); if (!loc_qual.empty())
if (locn != k_unknown_location) return join(" [[", loc_qual, "]]");
{
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) + ")]]";
}
} }
// Tessellation control function inputs // Tessellation control function inputs
@ -10788,24 +10782,7 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in
} }
} }
else else
{ quals = member_location_attribute_qualifier(type, index);
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) + ")";
}
}
if (builtin == BuiltInBaryCoordNV || builtin == BuiltInBaryCoordNoPerspNV) if (builtin == BuiltInBaryCoordNV || builtin == BuiltInBaryCoordNoPerspNV)
{ {
@ -10937,6 +10914,30 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in
return ""; 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. // 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 // 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 // function assumes the members are ordered in their location order, and simply returns the

View File

@ -867,6 +867,7 @@ protected:
std::string builtin_type_decl(spv::BuiltIn builtin, uint32_t id = 0); 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 built_in_func_arg(spv::BuiltIn builtin, bool prefix_comma);
std::string member_attribute_qualifier(const SPIRType &type, uint32_t index); 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 argument_decl(const SPIRFunction::Parameter &arg);
std::string round_fp_tex_coords(std::string tex_coords, bool coord_is_fp); 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); uint32_t get_metal_resource_index(SPIRVariable &var, SPIRType::BaseType basetype, uint32_t plane = 0);