MSL: Account for components when assigning locations to varyings.

Two varyings (vertex outputs/fragment inputs) might have the same
location but be in different components--e.g. the compiler may have
packed what were two different varyings into a single varying vector.
Giving both varyings the same `[[user]]` attribute won't work--it may
yield unexpected results, or flat out fail to link. We could eventually
pack such varyings into a single vector, but that would require us to
handle the case where the varyings are different types--e.g. a `float`
and a `uint` packed into the same vector. For now, it seems most
prudent to give them unique `[[user]]` locations and let Apple's
compiler work out the best way to pack them.
This commit is contained in:
Chip Davis 2018-09-05 17:31:10 -05:00
parent 8c7282bda1
commit 4b99fdd5d0
6 changed files with 66 additions and 12 deletions

View File

@ -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]])

View File

@ -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]])

View File

@ -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;

View File

@ -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;

View File

@ -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<uint32_t> spirv_, vector<MSLVertexAttr> *p_vtx_attrs,
vector<MSLResourceBinding> *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;
}

View File

@ -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);