MSL: Emit interface block members of array length 1 as arrays instead of scalars.

Test for array presence using is_array() instead of element count.
Add shaders-msl/vert/interface-block-single-element-array.vert regression test.

Fixes a regression error introduced in 3d4daab.
This commit is contained in:
Bill Hollings 2022-04-26 20:39:18 -04:00
parent d7cae5e7cd
commit 3bca246ad2
4 changed files with 182 additions and 4 deletions

View File

@ -0,0 +1,79 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#pragma clang diagnostic ignored "-Wmissing-braces"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
template<typename T, size_t Num>
struct spvUnsafeArray
{
T elements[Num ? Num : 1];
thread T& operator [] (size_t pos) thread
{
return elements[pos];
}
constexpr const thread T& operator [] (size_t pos) const thread
{
return elements[pos];
}
device T& operator [] (size_t pos) device
{
return elements[pos];
}
constexpr const device T& operator [] (size_t pos) const device
{
return elements[pos];
}
constexpr const constant T& operator [] (size_t pos) const constant
{
return elements[pos];
}
threadgroup T& operator [] (size_t pos) threadgroup
{
return elements[pos];
}
constexpr const threadgroup T& operator [] (size_t pos) const threadgroup
{
return elements[pos];
}
};
struct TDPickVertex
{
float4 c;
spvUnsafeArray<float3, 1> uv;
};
struct main0_out
{
float4 oTDVert_c [[user(locn0)]];
float3 oTDVert_uv_0 [[user(locn1)]];
float4 gl_Position [[position]];
};
struct main0_in
{
float3 P [[attribute(0)]];
float3 uv_0 [[attribute(1)]];
};
vertex main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
TDPickVertex oTDVert = {};
spvUnsafeArray<float3, 1> uv = {};
uv[0] = in.uv_0;
out.gl_Position = float4(in.P, 1.0);
oTDVert.uv[0] = uv[0];
oTDVert.c = float4(1.0);
out.oTDVert_c = oTDVert.c;
out.oTDVert_uv_0 = oTDVert.uv[0];
return out;
}

View File

@ -0,0 +1,79 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#pragma clang diagnostic ignored "-Wmissing-braces"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
template<typename T, size_t Num>
struct spvUnsafeArray
{
T elements[Num ? Num : 1];
thread T& operator [] (size_t pos) thread
{
return elements[pos];
}
constexpr const thread T& operator [] (size_t pos) const thread
{
return elements[pos];
}
device T& operator [] (size_t pos) device
{
return elements[pos];
}
constexpr const device T& operator [] (size_t pos) const device
{
return elements[pos];
}
constexpr const constant T& operator [] (size_t pos) const constant
{
return elements[pos];
}
threadgroup T& operator [] (size_t pos) threadgroup
{
return elements[pos];
}
constexpr const threadgroup T& operator [] (size_t pos) const threadgroup
{
return elements[pos];
}
};
struct TDPickVertex
{
float4 c;
spvUnsafeArray<float3, 1> uv;
};
struct main0_out
{
float4 oTDVert_c [[user(locn0)]];
float3 oTDVert_uv_0 [[user(locn1)]];
float4 gl_Position [[position]];
};
struct main0_in
{
float3 P [[attribute(0)]];
float3 uv_0 [[attribute(1)]];
};
vertex main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
TDPickVertex oTDVert = {};
spvUnsafeArray<float3, 1> uv = {};
uv[0] = in.uv_0;
out.gl_Position = float4(in.P, 1.0);
oTDVert.uv[0] = uv[0];
oTDVert.c = float4(1.0);
out.oTDVert_c = oTDVert.c;
out.oTDVert_uv_0 = oTDVert.uv[0];
return out;
}

View File

@ -0,0 +1,17 @@
#version 460
layout(location = 0) out TDPickVertex
{
vec4 c;
vec3 uv[1];
} oTDVert;
layout(location = 0) in vec3 P;
layout(location = 1) in vec3 uv[1];
void main()
{
gl_Position = vec4(P, 1.0);
oTDVert.uv[0] = uv[0];
oTDVert.c = vec4(1.);
}

View File

@ -2580,12 +2580,14 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass
uint32_t mbr_type_id = var_type.member_types[mbr_idx];
auto &mbr_type = get<SPIRType>(mbr_type_id);
bool mbr_is_indexable = false;
uint32_t elem_cnt = 1;
if (is_matrix(mbr_type))
{
if (is_array(mbr_type))
SPIRV_CROSS_THROW("MSL cannot emit arrays-of-matrices in input and output variables.");
mbr_is_indexable = true;
elem_cnt = mbr_type.columns;
}
else if (is_array(mbr_type))
@ -2593,6 +2595,7 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass
if (mbr_type.array.size() != 1)
SPIRV_CROSS_THROW("MSL cannot emit arrays-of-arrays in input and output variables.");
mbr_is_indexable = true;
elem_cnt = to_array_size_literal(mbr_type);
}
@ -2628,8 +2631,8 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass
{
for (uint32_t i = 0; i < elem_cnt; i++)
{
string mbr_name = append_member_name(mbr_name_qual, var_type, mbr_idx) + (elem_cnt == 1 ? "" : join("_", i));
string var_chain = join(var_chain_qual, ".", to_member_name(var_type, mbr_idx), (elem_cnt == 1 ? "" : join("[", i, "]")));
string mbr_name = append_member_name(mbr_name_qual, var_type, mbr_idx) + (mbr_is_indexable ? join("_", i) : "");
string var_chain = join(var_chain_qual, ".", to_member_name(var_type, mbr_idx), (mbr_is_indexable ? join("[", i, "]") : ""));
uint32_t sub_mbr_cnt = uint32_t(mbr_type.member_types.size());
for (uint32_t sub_mbr_idx = 0; sub_mbr_idx < sub_mbr_cnt; sub_mbr_idx++)
{
@ -2654,7 +2657,7 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass
ib_type.member_types.push_back(usable_type->self);
// Give the member a name
string mbr_name = ensure_valid_name(append_member_name(mbr_name_qual, var_type, mbr_idx) + (elem_cnt == 1 ? "" : join("_", i)), "m");
string mbr_name = ensure_valid_name(append_member_name(mbr_name_qual, var_type, mbr_idx) + (mbr_is_indexable ? join("_", i) : ""), "m");
set_member_name(ib_type.self, ib_mbr_idx, mbr_name);
// Once we determine the location of the first member within nested structures,
@ -2718,7 +2721,7 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass
// Unflatten or flatten from [[stage_in]] or [[stage_out]] as appropriate.
if (!meta.strip_array && meta.allow_local_declaration)
{
string var_chain = join(var_chain_qual, ".", to_member_name(var_type, mbr_idx), (elem_cnt == 1 ? "" : join("[", i, "]")));
string var_chain = join(var_chain_qual, ".", to_member_name(var_type, mbr_idx), (mbr_is_indexable ? join("[", i, "]") : ""));
switch (storage)
{
case StorageClassInput: