MSL: Support input/output blocks containing nested struct arrays

Fixes numerous CTS tests of types
dEQP-VK.pipeline.interface_matching.vector_length.member_of_*,
passing complex nested structs between stages as stage I/O.

- Make add_composite_member_variable_to_interface_block() recursive to allow
  struct members to contain nested structs, building up member names and access
  chains recursively, and only add the resulting flattened leaf members to the
  synthetic input and output interface blocks.
- Recursively generate individual location numbers for the flattened members
  of the input/output block.
- Replace to_qualified_member_name() with append_member_name().
- Update add_variable_to_interface_block() to support arrays as struct members,
  adding a member to input and output interface blocks for each element of the array.
- Pass name qualifiers to add_plain_member_variable_to_interface_block() to allow
  struct members to be arrays of structs, building up member names and access chains,
  and adding multiple distinct flattened leaf members to the synthetic input and
  output interface blocks.
- Generate individual location numbers for the individual array members
  of the input/output block.
- SPIRVCrossDecorationInterfaceMemberIndex references the index of a member
  of a variable that is a struct type. The value is relative to the variable,
  and for structs nested within that top-level struct, the index value needs
  to take into consideration the members within those nested structs.
- Pass var_mbr_idx to add_plain_member_variable_to_interface_block() and
  add_composite_member_variable_to_interface_block(), start at zero for each
  variable, and increment for each member or nested member within that variable.
- Add unit test shaders-msl/vert/out-block-with-nested-struct-array.vert
- Add unit test shaders-msl/vert/out-block-with-struct-array.vert
- Add unit test shaders-msl/tese/in-block-with-nested-struct.tese
This commit is contained in:
Bill Hollings 2022-02-25 19:58:22 -05:00 committed by Hans-Kristian Arntzen
parent d16183d1d2
commit 3d4daab29d
11 changed files with 709 additions and 125 deletions

View File

@ -0,0 +1,43 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct _RESERVED_IDENTIFIER_FIXUP_35
{
float2 _RESERVED_IDENTIFIER_FIXUP_m0;
float4 _RESERVED_IDENTIFIER_FIXUP_m1;
};
struct _RESERVED_IDENTIFIER_FIXUP_36
{
float2 _RESERVED_IDENTIFIER_FIXUP_m0;
_RESERVED_IDENTIFIER_FIXUP_35 _RESERVED_IDENTIFIER_FIXUP_m1;
};
struct main0_out
{
float _RESERVED_IDENTIFIER_FIXUP_80 [[user(locn0)]];
float4 gl_Position [[position]];
};
struct main0_in
{
float2 _RESERVED_IDENTIFIER_FIXUP_36_RESERVED_IDENTIFIER_FIXUP_m0 [[attribute(0)]];
float2 _RESERVED_IDENTIFIER_FIXUP_36_RESERVED_IDENTIFIER_FIXUP_m1_RESERVED_IDENTIFIER_FIXUP_m0 [[attribute(1)]];
float4 _RESERVED_IDENTIFIER_FIXUP_36_RESERVED_IDENTIFIER_FIXUP_m1_RESERVED_IDENTIFIER_FIXUP_m1 [[attribute(2)]];
};
struct main0_patchIn
{
patch_control_point<main0_in> gl_in;
};
[[ patch(triangle, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], float3 gl_TessCoord [[position_in_patch]])
{
main0_out out = {};
out.gl_Position = float4((gl_TessCoord.xy * 2.0) - float2(1.0), 0.0, 1.0);
out._RESERVED_IDENTIFIER_FIXUP_80 = ((float(abs(patchIn.gl_in[0]._RESERVED_IDENTIFIER_FIXUP_36_RESERVED_IDENTIFIER_FIXUP_m1_RESERVED_IDENTIFIER_FIXUP_m1.x - (-4.0)) < 0.001000000047497451305389404296875) * float(abs(patchIn.gl_in[0]._RESERVED_IDENTIFIER_FIXUP_36_RESERVED_IDENTIFIER_FIXUP_m1_RESERVED_IDENTIFIER_FIXUP_m1.y - (-9.0)) < 0.001000000047497451305389404296875)) * float(abs(patchIn.gl_in[0]._RESERVED_IDENTIFIER_FIXUP_36_RESERVED_IDENTIFIER_FIXUP_m1_RESERVED_IDENTIFIER_FIXUP_m1.z - 3.0) < 0.001000000047497451305389404296875)) * float(abs(patchIn.gl_in[0]._RESERVED_IDENTIFIER_FIXUP_36_RESERVED_IDENTIFIER_FIXUP_m1_RESERVED_IDENTIFIER_FIXUP_m1.w - 7.0) < 0.001000000047497451305389404296875);
return out;
}

View File

@ -0,0 +1,88 @@
#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 _RESERVED_IDENTIFIER_FIXUP_21
{
float4 _RESERVED_IDENTIFIER_FIXUP_m0;
float4 _RESERVED_IDENTIFIER_FIXUP_m1;
};
struct _RESERVED_IDENTIFIER_FIXUP_24
{
spvUnsafeArray<_RESERVED_IDENTIFIER_FIXUP_21, 3> _RESERVED_IDENTIFIER_FIXUP_m0;
};
struct main0_out
{
float4 _RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_0_RESERVED_IDENTIFIER_FIXUP_m0 [[user(locn0)]];
float4 _RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_0_RESERVED_IDENTIFIER_FIXUP_m1 [[user(locn1)]];
float4 _RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_1_RESERVED_IDENTIFIER_FIXUP_m0 [[user(locn2)]];
float4 _RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_1_RESERVED_IDENTIFIER_FIXUP_m1 [[user(locn3)]];
float4 _RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_2_RESERVED_IDENTIFIER_FIXUP_m0 [[user(locn4)]];
float4 _RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_2_RESERVED_IDENTIFIER_FIXUP_m1 [[user(locn5)]];
float4 gl_Position [[position]];
};
struct main0_in
{
float4 _RESERVED_IDENTIFIER_FIXUP_17 [[attribute(0)]];
};
vertex main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
_RESERVED_IDENTIFIER_FIXUP_24 _RESERVED_IDENTIFIER_FIXUP_26 = {};
out.gl_Position = in._RESERVED_IDENTIFIER_FIXUP_17;
_RESERVED_IDENTIFIER_FIXUP_26._RESERVED_IDENTIFIER_FIXUP_m0[1]._RESERVED_IDENTIFIER_FIXUP_m1 = float4(-4.0, -9.0, 3.0, 7.0);
out._RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_0_RESERVED_IDENTIFIER_FIXUP_m0 = _RESERVED_IDENTIFIER_FIXUP_26._RESERVED_IDENTIFIER_FIXUP_m0[0]._RESERVED_IDENTIFIER_FIXUP_m0;
out._RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_0_RESERVED_IDENTIFIER_FIXUP_m1 = _RESERVED_IDENTIFIER_FIXUP_26._RESERVED_IDENTIFIER_FIXUP_m0[0]._RESERVED_IDENTIFIER_FIXUP_m1;
out._RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_1_RESERVED_IDENTIFIER_FIXUP_m0 = _RESERVED_IDENTIFIER_FIXUP_26._RESERVED_IDENTIFIER_FIXUP_m0[1]._RESERVED_IDENTIFIER_FIXUP_m0;
out._RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_1_RESERVED_IDENTIFIER_FIXUP_m1 = _RESERVED_IDENTIFIER_FIXUP_26._RESERVED_IDENTIFIER_FIXUP_m0[1]._RESERVED_IDENTIFIER_FIXUP_m1;
out._RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_2_RESERVED_IDENTIFIER_FIXUP_m0 = _RESERVED_IDENTIFIER_FIXUP_26._RESERVED_IDENTIFIER_FIXUP_m0[2]._RESERVED_IDENTIFIER_FIXUP_m0;
out._RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_2_RESERVED_IDENTIFIER_FIXUP_m1 = _RESERVED_IDENTIFIER_FIXUP_26._RESERVED_IDENTIFIER_FIXUP_m0[2]._RESERVED_IDENTIFIER_FIXUP_m1;
return out;
}

View File

@ -0,0 +1,83 @@
#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 _RESERVED_IDENTIFIER_FIXUP_21
{
float _RESERVED_IDENTIFIER_FIXUP_m0;
float4 _RESERVED_IDENTIFIER_FIXUP_m1;
};
struct main0_out
{
float _RESERVED_IDENTIFIER_FIXUP_21_0_RESERVED_IDENTIFIER_FIXUP_m0 [[user(locn0)]];
float4 _RESERVED_IDENTIFIER_FIXUP_21_0_RESERVED_IDENTIFIER_FIXUP_m1 [[user(locn1)]];
float _RESERVED_IDENTIFIER_FIXUP_21_1_RESERVED_IDENTIFIER_FIXUP_m0 [[user(locn2)]];
float4 _RESERVED_IDENTIFIER_FIXUP_21_1_RESERVED_IDENTIFIER_FIXUP_m1 [[user(locn3)]];
float _RESERVED_IDENTIFIER_FIXUP_21_2_RESERVED_IDENTIFIER_FIXUP_m0 [[user(locn4)]];
float4 _RESERVED_IDENTIFIER_FIXUP_21_2_RESERVED_IDENTIFIER_FIXUP_m1 [[user(locn5)]];
float4 gl_Position [[position]];
};
struct main0_in
{
float4 _RESERVED_IDENTIFIER_FIXUP_17 [[attribute(0)]];
};
vertex main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
spvUnsafeArray<_RESERVED_IDENTIFIER_FIXUP_21, 3> _RESERVED_IDENTIFIER_FIXUP_25 = {};
out.gl_Position = in._RESERVED_IDENTIFIER_FIXUP_17;
_RESERVED_IDENTIFIER_FIXUP_25[2]._RESERVED_IDENTIFIER_FIXUP_m1 = float4(-4.0, -9.0, 3.0, 7.0);
out._RESERVED_IDENTIFIER_FIXUP_21_0_RESERVED_IDENTIFIER_FIXUP_m0 = _RESERVED_IDENTIFIER_FIXUP_25[0]._RESERVED_IDENTIFIER_FIXUP_m0;
out._RESERVED_IDENTIFIER_FIXUP_21_0_RESERVED_IDENTIFIER_FIXUP_m1 = _RESERVED_IDENTIFIER_FIXUP_25[0]._RESERVED_IDENTIFIER_FIXUP_m1;
out._RESERVED_IDENTIFIER_FIXUP_21_1_RESERVED_IDENTIFIER_FIXUP_m0 = _RESERVED_IDENTIFIER_FIXUP_25[1]._RESERVED_IDENTIFIER_FIXUP_m0;
out._RESERVED_IDENTIFIER_FIXUP_21_1_RESERVED_IDENTIFIER_FIXUP_m1 = _RESERVED_IDENTIFIER_FIXUP_25[1]._RESERVED_IDENTIFIER_FIXUP_m1;
out._RESERVED_IDENTIFIER_FIXUP_21_2_RESERVED_IDENTIFIER_FIXUP_m0 = _RESERVED_IDENTIFIER_FIXUP_25[2]._RESERVED_IDENTIFIER_FIXUP_m0;
out._RESERVED_IDENTIFIER_FIXUP_21_2_RESERVED_IDENTIFIER_FIXUP_m1 = _RESERVED_IDENTIFIER_FIXUP_25[2]._RESERVED_IDENTIFIER_FIXUP_m1;
return out;
}

View File

@ -0,0 +1,44 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct _RESERVED_IDENTIFIER_FIXUP_35
{
float2 _RESERVED_IDENTIFIER_FIXUP_m0;
float4 _RESERVED_IDENTIFIER_FIXUP_m1;
};
struct _RESERVED_IDENTIFIER_FIXUP_36
{
float2 _RESERVED_IDENTIFIER_FIXUP_m0;
_RESERVED_IDENTIFIER_FIXUP_35 _RESERVED_IDENTIFIER_FIXUP_m1;
};
struct main0_out
{
float _RESERVED_IDENTIFIER_FIXUP_80 [[user(locn0)]];
float4 gl_Position [[position]];
};
struct main0_in
{
float2 _RESERVED_IDENTIFIER_FIXUP_36_RESERVED_IDENTIFIER_FIXUP_m0 [[attribute(0)]];
float2 _RESERVED_IDENTIFIER_FIXUP_36_RESERVED_IDENTIFIER_FIXUP_m1_RESERVED_IDENTIFIER_FIXUP_m0 [[attribute(1)]];
float4 _RESERVED_IDENTIFIER_FIXUP_36_RESERVED_IDENTIFIER_FIXUP_m1_RESERVED_IDENTIFIER_FIXUP_m1 [[attribute(2)]];
};
struct main0_patchIn
{
patch_control_point<main0_in> gl_in;
};
[[ patch(triangle, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], float3 gl_TessCoord [[position_in_patch]])
{
main0_out out = {};
out.gl_Position = float4((gl_TessCoord.xy * 2.0) - float2(1.0), 0.0, 1.0);
float _RESERVED_IDENTIFIER_FIXUP_34 = ((float(abs(patchIn.gl_in[0]._RESERVED_IDENTIFIER_FIXUP_36_RESERVED_IDENTIFIER_FIXUP_m1_RESERVED_IDENTIFIER_FIXUP_m1.x - (-4.0)) < 0.001000000047497451305389404296875) * float(abs(patchIn.gl_in[0]._RESERVED_IDENTIFIER_FIXUP_36_RESERVED_IDENTIFIER_FIXUP_m1_RESERVED_IDENTIFIER_FIXUP_m1.y - (-9.0)) < 0.001000000047497451305389404296875)) * float(abs(patchIn.gl_in[0]._RESERVED_IDENTIFIER_FIXUP_36_RESERVED_IDENTIFIER_FIXUP_m1_RESERVED_IDENTIFIER_FIXUP_m1.z - 3.0) < 0.001000000047497451305389404296875)) * float(abs(patchIn.gl_in[0]._RESERVED_IDENTIFIER_FIXUP_36_RESERVED_IDENTIFIER_FIXUP_m1_RESERVED_IDENTIFIER_FIXUP_m1.w - 7.0) < 0.001000000047497451305389404296875);
out._RESERVED_IDENTIFIER_FIXUP_80 = _RESERVED_IDENTIFIER_FIXUP_34;
return out;
}

View File

@ -0,0 +1,88 @@
#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 _RESERVED_IDENTIFIER_FIXUP_21
{
float4 _RESERVED_IDENTIFIER_FIXUP_m0;
float4 _RESERVED_IDENTIFIER_FIXUP_m1;
};
struct _RESERVED_IDENTIFIER_FIXUP_24
{
spvUnsafeArray<_RESERVED_IDENTIFIER_FIXUP_21, 3> _RESERVED_IDENTIFIER_FIXUP_m0;
};
struct main0_out
{
float4 _RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_0_RESERVED_IDENTIFIER_FIXUP_m0 [[user(locn0)]];
float4 _RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_0_RESERVED_IDENTIFIER_FIXUP_m1 [[user(locn1)]];
float4 _RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_1_RESERVED_IDENTIFIER_FIXUP_m0 [[user(locn2)]];
float4 _RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_1_RESERVED_IDENTIFIER_FIXUP_m1 [[user(locn3)]];
float4 _RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_2_RESERVED_IDENTIFIER_FIXUP_m0 [[user(locn4)]];
float4 _RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_2_RESERVED_IDENTIFIER_FIXUP_m1 [[user(locn5)]];
float4 gl_Position [[position]];
};
struct main0_in
{
float4 _RESERVED_IDENTIFIER_FIXUP_17 [[attribute(0)]];
};
vertex main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
_RESERVED_IDENTIFIER_FIXUP_24 _RESERVED_IDENTIFIER_FIXUP_26 = {};
out.gl_Position = in._RESERVED_IDENTIFIER_FIXUP_17;
_RESERVED_IDENTIFIER_FIXUP_26._RESERVED_IDENTIFIER_FIXUP_m0[1]._RESERVED_IDENTIFIER_FIXUP_m1 = float4(-4.0, -9.0, 3.0, 7.0);
out._RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_0_RESERVED_IDENTIFIER_FIXUP_m0 = _RESERVED_IDENTIFIER_FIXUP_26._RESERVED_IDENTIFIER_FIXUP_m0[0]._RESERVED_IDENTIFIER_FIXUP_m0;
out._RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_0_RESERVED_IDENTIFIER_FIXUP_m1 = _RESERVED_IDENTIFIER_FIXUP_26._RESERVED_IDENTIFIER_FIXUP_m0[0]._RESERVED_IDENTIFIER_FIXUP_m1;
out._RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_1_RESERVED_IDENTIFIER_FIXUP_m0 = _RESERVED_IDENTIFIER_FIXUP_26._RESERVED_IDENTIFIER_FIXUP_m0[1]._RESERVED_IDENTIFIER_FIXUP_m0;
out._RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_1_RESERVED_IDENTIFIER_FIXUP_m1 = _RESERVED_IDENTIFIER_FIXUP_26._RESERVED_IDENTIFIER_FIXUP_m0[1]._RESERVED_IDENTIFIER_FIXUP_m1;
out._RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_2_RESERVED_IDENTIFIER_FIXUP_m0 = _RESERVED_IDENTIFIER_FIXUP_26._RESERVED_IDENTIFIER_FIXUP_m0[2]._RESERVED_IDENTIFIER_FIXUP_m0;
out._RESERVED_IDENTIFIER_FIXUP_24_RESERVED_IDENTIFIER_FIXUP_m0_2_RESERVED_IDENTIFIER_FIXUP_m1 = _RESERVED_IDENTIFIER_FIXUP_26._RESERVED_IDENTIFIER_FIXUP_m0[2]._RESERVED_IDENTIFIER_FIXUP_m1;
return out;
}

View File

@ -0,0 +1,83 @@
#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 _RESERVED_IDENTIFIER_FIXUP_21
{
float _RESERVED_IDENTIFIER_FIXUP_m0;
float4 _RESERVED_IDENTIFIER_FIXUP_m1;
};
struct main0_out
{
float _RESERVED_IDENTIFIER_FIXUP_21_0_RESERVED_IDENTIFIER_FIXUP_m0 [[user(locn0)]];
float4 _RESERVED_IDENTIFIER_FIXUP_21_0_RESERVED_IDENTIFIER_FIXUP_m1 [[user(locn1)]];
float _RESERVED_IDENTIFIER_FIXUP_21_1_RESERVED_IDENTIFIER_FIXUP_m0 [[user(locn2)]];
float4 _RESERVED_IDENTIFIER_FIXUP_21_1_RESERVED_IDENTIFIER_FIXUP_m1 [[user(locn3)]];
float _RESERVED_IDENTIFIER_FIXUP_21_2_RESERVED_IDENTIFIER_FIXUP_m0 [[user(locn4)]];
float4 _RESERVED_IDENTIFIER_FIXUP_21_2_RESERVED_IDENTIFIER_FIXUP_m1 [[user(locn5)]];
float4 gl_Position [[position]];
};
struct main0_in
{
float4 _RESERVED_IDENTIFIER_FIXUP_17 [[attribute(0)]];
};
vertex main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
spvUnsafeArray<_RESERVED_IDENTIFIER_FIXUP_21, 3> _RESERVED_IDENTIFIER_FIXUP_25 = {};
out.gl_Position = in._RESERVED_IDENTIFIER_FIXUP_17;
_RESERVED_IDENTIFIER_FIXUP_25[2]._RESERVED_IDENTIFIER_FIXUP_m1 = float4(-4.0, -9.0, 3.0, 7.0);
out._RESERVED_IDENTIFIER_FIXUP_21_0_RESERVED_IDENTIFIER_FIXUP_m0 = _RESERVED_IDENTIFIER_FIXUP_25[0]._RESERVED_IDENTIFIER_FIXUP_m0;
out._RESERVED_IDENTIFIER_FIXUP_21_0_RESERVED_IDENTIFIER_FIXUP_m1 = _RESERVED_IDENTIFIER_FIXUP_25[0]._RESERVED_IDENTIFIER_FIXUP_m1;
out._RESERVED_IDENTIFIER_FIXUP_21_1_RESERVED_IDENTIFIER_FIXUP_m0 = _RESERVED_IDENTIFIER_FIXUP_25[1]._RESERVED_IDENTIFIER_FIXUP_m0;
out._RESERVED_IDENTIFIER_FIXUP_21_1_RESERVED_IDENTIFIER_FIXUP_m1 = _RESERVED_IDENTIFIER_FIXUP_25[1]._RESERVED_IDENTIFIER_FIXUP_m1;
out._RESERVED_IDENTIFIER_FIXUP_21_2_RESERVED_IDENTIFIER_FIXUP_m0 = _RESERVED_IDENTIFIER_FIXUP_25[2]._RESERVED_IDENTIFIER_FIXUP_m0;
out._RESERVED_IDENTIFIER_FIXUP_21_2_RESERVED_IDENTIFIER_FIXUP_m1 = _RESERVED_IDENTIFIER_FIXUP_25[2]._RESERVED_IDENTIFIER_FIXUP_m1;
return out;
}

View File

@ -0,0 +1,31 @@
#version 450
layout(triangles, ccw, equal_spacing) in;
out gl_PerVertex
{
vec4 gl_Position;
float gl_PointSize;
float gl_ClipDistance[1];
float gl_CullDistance[1];
};
struct _35
{
vec2 _m0;
vec4 _m1;
};
layout(location = 0) in _36
{
vec2 _m0;
_35 _m1;
} _40[32];
layout(location = 0) out float _80;
void main()
{
gl_Position = vec4((gl_TessCoord.xy * 2.0) - vec2(1.0), 0.0, 1.0);
float _34 = ((float(abs(_40[0]._m1._m1.x - (-4.0)) < 0.001000000047497451305389404296875) * float(abs(_40[0]._m1._m1.y - (-9.0)) < 0.001000000047497451305389404296875)) * float(abs(_40[0]._m1._m1.z - 3.0) < 0.001000000047497451305389404296875)) * float(abs(_40[0]._m1._m1.w - 7.0) < 0.001000000047497451305389404296875);
_80 = _34;
}

View File

@ -0,0 +1,28 @@
#version 450
out gl_PerVertex
{
vec4 gl_Position;
float gl_PointSize;
float gl_ClipDistance[1];
float gl_CullDistance[1];
};
struct _21
{
vec4 _m0;
vec4 _m1;
};
layout(location = 0) in vec4 _17;
layout(location = 0) out _24
{
_21 _m0[3];
} _26;
void main()
{
gl_Position = _17;
_26._m0[1]._m1 = vec4(-4.0, -9.0, 3.0, 7.0);
}

View File

@ -0,0 +1,24 @@
#version 450
out gl_PerVertex
{
vec4 gl_Position;
float gl_PointSize;
float gl_ClipDistance[1];
float gl_CullDistance[1];
};
struct _21
{
float _m0;
vec4 _m1;
};
layout(location = 0) in vec4 _17;
layout(location = 0) out _21 _25[3];
void main()
{
gl_Position = _17;
_25[2]._m1 = vec4(-4.0, -9.0, 3.0, 7.0);
}

View File

@ -2508,12 +2508,15 @@ void CompilerMSL::add_composite_variable_to_interface_block(StorageClass storage
} }
} }
void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass storage, const string &ib_var_ref, void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass storage,
SPIRType &ib_type, SPIRVariable &var, const string &ib_var_ref, SPIRType &ib_type,
uint32_t mbr_idx, InterfaceBlockMeta &meta) SPIRVariable &var, SPIRType &var_type,
uint32_t mbr_idx, InterfaceBlockMeta &meta,
const string &mbr_name_qual,
const string &var_chain_qual,
uint32_t& location, uint32_t& var_mbr_idx)
{ {
auto &entry_func = get<SPIRFunction>(ir.default_entry_point); auto &entry_func = get<SPIRFunction>(ir.default_entry_point);
auto &var_type = meta.strip_array ? get_variable_element_type(var) : get_variable_data_type(var);
BuiltIn builtin = BuiltInMax; BuiltIn builtin = BuiltInMax;
bool is_builtin = is_member_builtin(var_type, mbr_idx, &builtin); bool is_builtin = is_member_builtin(var_type, mbr_idx, &builtin);
@ -2528,8 +2531,8 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass
uint32_t mbr_type_id = var_type.member_types[mbr_idx]; uint32_t mbr_type_id = var_type.member_types[mbr_idx];
auto &mbr_type = get<SPIRType>(mbr_type_id); auto &mbr_type = get<SPIRType>(mbr_type_id);
uint32_t elem_cnt = 0;
uint32_t elem_cnt = 1;
if (is_matrix(mbr_type)) if (is_matrix(mbr_type))
{ {
if (is_array(mbr_type)) if (is_array(mbr_type))
@ -2572,6 +2575,26 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass
return; return;
} }
// Recursively handle nested structures.
if (mbr_type.basetype == SPIRType::Struct)
{
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, "]")));
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++)
{
add_composite_member_variable_to_interface_block(storage, ib_var_ref, ib_type,
var, mbr_type, sub_mbr_idx,
meta, mbr_name, var_chain,
location, var_mbr_idx);
var_mbr_idx++;
}
}
return;
}
for (uint32_t i = 0; i < elem_cnt; i++) for (uint32_t i = 0; i < elem_cnt; i++)
{ {
// Add a reference to the variable type to the interface struct. // Add a reference to the variable type to the interface struct.
@ -2582,26 +2605,38 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass
ib_type.member_types.push_back(usable_type->self); ib_type.member_types.push_back(usable_type->self);
// Give the member a name // Give the member a name
string mbr_name = ensure_valid_name(join(to_qualified_member_name(var_type, mbr_idx), "_", i), "m"); string mbr_name = ensure_valid_name(append_member_name(mbr_name_qual, var_type, mbr_idx) + (elem_cnt == 1 ? "" : join("_", i)), "m");
set_member_name(ib_type.self, ib_mbr_idx, mbr_name); set_member_name(ib_type.self, ib_mbr_idx, mbr_name);
if (has_member_decoration(var_type.self, mbr_idx, DecorationLocation)) // Once we determine the location of the first member within nested structures,
// from a var of the topmost structure, the remaining flattened members of the
// nested structures will have consecutive location values.
if (!is_builtin && location)
{ {
uint32_t locn = get_member_decoration(var_type.self, mbr_idx, DecorationLocation) + i; set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, location);
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, locn); mark_location_as_used_by_shader(location, *usable_type, storage);
mark_location_as_used_by_shader(locn, *usable_type, storage); location++;
}
else if (has_member_decoration(var_type.self, mbr_idx, DecorationLocation))
{
location = get_member_decoration(var_type.self, mbr_idx, DecorationLocation) + i;
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, location);
mark_location_as_used_by_shader(location, *usable_type, storage);
location++;
} }
else if (has_decoration(var.self, DecorationLocation)) else if (has_decoration(var.self, DecorationLocation))
{ {
uint32_t locn = get_accumulated_member_location(var, mbr_idx, meta.strip_array) + i; location = get_accumulated_member_location(var, mbr_idx, meta.strip_array) + i;
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, locn); set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, location);
mark_location_as_used_by_shader(locn, *usable_type, storage); mark_location_as_used_by_shader(location, *usable_type, storage);
location++;
} }
else if (is_builtin && is_tessellation_shader() && storage == StorageClassInput && inputs_by_builtin.count(builtin)) else if (is_builtin && is_tessellation_shader() && storage == StorageClassInput && inputs_by_builtin.count(builtin))
{ {
uint32_t locn = inputs_by_builtin[builtin].location + i; location = inputs_by_builtin[builtin].location + i;
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, locn); set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, location);
mark_location_as_used_by_shader(locn, *usable_type, storage); mark_location_as_used_by_shader(location, *usable_type, storage);
location++;
} }
else if (is_builtin && (builtin == BuiltInClipDistance || builtin == BuiltInCullDistance)) else if (is_builtin && (builtin == BuiltInClipDistance || builtin == BuiltInCullDistance))
{ {
@ -2611,7 +2646,7 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass
} }
if (has_member_decoration(var_type.self, mbr_idx, DecorationComponent)) if (has_member_decoration(var_type.self, mbr_idx, DecorationComponent))
SPIRV_CROSS_THROW("DecorationComponent on matrices and arrays make little sense."); SPIRV_CROSS_THROW("DecorationComponent on matrices and arrays is not supported.");
if (storage != StorageClassInput || !pull_model_inputs.count(var.self)) if (storage != StorageClassInput || !pull_model_inputs.count(var.self))
{ {
@ -2627,47 +2662,36 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass
} }
set_extended_member_decoration(ib_type.self, ib_mbr_idx, SPIRVCrossDecorationInterfaceOrigID, var.self); set_extended_member_decoration(ib_type.self, ib_mbr_idx, SPIRVCrossDecorationInterfaceOrigID, var.self);
set_extended_member_decoration(ib_type.self, ib_mbr_idx, SPIRVCrossDecorationInterfaceMemberIndex, mbr_idx); set_extended_member_decoration(ib_type.self, ib_mbr_idx, SPIRVCrossDecorationInterfaceMemberIndex, var_mbr_idx);
// Unflatten or flatten from [[stage_in]] or [[stage_out]] as appropriate. // Unflatten or flatten from [[stage_in]] or [[stage_out]] as appropriate.
if (!meta.strip_array && meta.allow_local_declaration) 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, "]")));
switch (storage) switch (storage)
{ {
case StorageClassInput: case StorageClassInput:
entry_func.fixup_hooks_in.push_back([=, &var, &var_type]() { entry_func.fixup_hooks_in.push_back([=, &var]() {
string lerp_call;
if (pull_model_inputs.count(var.self)) if (pull_model_inputs.count(var.self))
{ {
string lerp_call;
if (is_centroid) if (is_centroid)
lerp_call = ".interpolate_at_centroid()"; lerp_call = ".interpolate_at_centroid()";
else if (is_sample) else if (is_sample)
lerp_call = join(".interpolate_at_sample(", to_expression(builtin_sample_id_id), ")"); lerp_call = join(".interpolate_at_sample(", to_expression(builtin_sample_id_id), ")");
else else
lerp_call = ".interpolate_at_center()"; lerp_call = ".interpolate_at_center()";
statement(to_name(var.self), ".", to_member_name(var_type, mbr_idx), "[", i, "] = ", ib_var_ref,
".", mbr_name, lerp_call, ";");
}
else
{
statement(to_name(var.self), ".", to_member_name(var_type, mbr_idx), "[", i, "] = ", ib_var_ref,
".", mbr_name, ";");
} }
statement(var_chain, " = ", ib_var_ref, ".", mbr_name, lerp_call, ";");
}); });
break; break;
case StorageClassOutput: case StorageClassOutput:
entry_func.fixup_hooks_out.push_back([=, &var, &var_type]() { entry_func.fixup_hooks_out.push_back([=]() {
if (flatten_from_ib_var) if (flatten_from_ib_var)
{ statement(ib_var_ref, ".", mbr_name, " = ", ib_var_ref, ".", flatten_from_ib_mbr_name, "[", i, "];");
statement(ib_var_ref, ".", mbr_name, " = ", ib_var_ref, ".", flatten_from_ib_mbr_name, "[", i,
"];");
}
else else
{ statement(ib_var_ref, ".", mbr_name, " = ", var_chain, ";");
statement(ib_var_ref, ".", mbr_name, " = ", to_name(var.self), ".",
to_member_name(var_type, mbr_idx), "[", i, "];");
}
}); });
break; break;
@ -2678,11 +2702,14 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass
} }
} }
void CompilerMSL::add_plain_member_variable_to_interface_block(StorageClass storage, const string &ib_var_ref, void CompilerMSL::add_plain_member_variable_to_interface_block(StorageClass storage,
SPIRType &ib_type, SPIRVariable &var, uint32_t mbr_idx, const string &ib_var_ref, SPIRType &ib_type,
InterfaceBlockMeta &meta) SPIRVariable &var, SPIRType &var_type,
uint32_t mbr_idx, InterfaceBlockMeta &meta,
const string &mbr_name_qual,
const string &var_chain_qual,
uint32_t& location, uint32_t& var_mbr_idx)
{ {
auto &var_type = meta.strip_array ? get_variable_element_type(var) : get_variable_data_type(var);
auto &entry_func = get<SPIRFunction>(ir.default_entry_point); auto &entry_func = get<SPIRFunction>(ir.default_entry_point);
BuiltIn builtin = BuiltInMax; BuiltIn builtin = BuiltInMax;
@ -2707,7 +2734,7 @@ void CompilerMSL::add_plain_member_variable_to_interface_block(StorageClass stor
ib_type.member_types.push_back(mbr_type_id); ib_type.member_types.push_back(mbr_type_id);
// Give the member a name // Give the member a name
string mbr_name = ensure_valid_name(to_qualified_member_name(var_type, mbr_idx), "m"); string mbr_name = ensure_valid_name(append_member_name(mbr_name_qual, var_type, mbr_idx), "m");
set_member_name(ib_type.self, ib_mbr_idx, mbr_name); set_member_name(ib_type.self, ib_mbr_idx, mbr_name);
// Update the original variable reference to include the structure reference // Update the original variable reference to include the structure reference
@ -2724,7 +2751,7 @@ void CompilerMSL::add_plain_member_variable_to_interface_block(StorageClass stor
} }
bool flatten_stage_out = false; bool flatten_stage_out = false;
string var_chain = var_chain_qual + "." + to_member_name(var_type, mbr_idx);
if (is_builtin && !meta.strip_array) if (is_builtin && !meta.strip_array)
{ {
// For the builtin gl_PerVertex, we cannot treat it as a block anyways, // For the builtin gl_PerVertex, we cannot treat it as a block anyways,
@ -2737,15 +2764,15 @@ void CompilerMSL::add_plain_member_variable_to_interface_block(StorageClass stor
switch (storage) switch (storage)
{ {
case StorageClassInput: case StorageClassInput:
entry_func.fixup_hooks_in.push_back([=, &var, &var_type]() { entry_func.fixup_hooks_in.push_back([=]() {
statement(to_name(var.self), ".", to_member_name(var_type, mbr_idx), " = ", qual_var_name, ";"); statement(var_chain, " = ", qual_var_name, ";");
}); });
break; break;
case StorageClassOutput: case StorageClassOutput:
flatten_stage_out = true; flatten_stage_out = true;
entry_func.fixup_hooks_out.push_back([=, &var, &var_type]() { entry_func.fixup_hooks_out.push_back([=]() {
statement(qual_var_name, " = ", to_name(var.self), ".", to_member_name(var_type, mbr_idx), ";"); statement(qual_var_name, " = ", var_chain, ";");
}); });
break; break;
@ -2754,48 +2781,54 @@ void CompilerMSL::add_plain_member_variable_to_interface_block(StorageClass stor
} }
} }
// Copy the variable location from the original variable to the member // Once we determine the location of the first member within nested structures,
if (has_member_decoration(var_type.self, mbr_idx, DecorationLocation)) // from a var of the topmost structure, the remaining flattened members of the
// nested structures will have consecutive location values.
if (!is_builtin && location)
{ {
uint32_t locn = get_member_decoration(var_type.self, mbr_idx, DecorationLocation); set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, location);
mark_location_as_used_by_shader(location, get<SPIRType>(mbr_type_id), storage);
location++;
}
else if (has_member_decoration(var_type.self, mbr_idx, DecorationLocation))
{
location = get_member_decoration(var_type.self, mbr_idx, DecorationLocation);
uint32_t comp = get_member_decoration(var_type.self, mbr_idx, DecorationComponent); uint32_t comp = get_member_decoration(var_type.self, mbr_idx, DecorationComponent);
if (storage == StorageClassInput) if (storage == StorageClassInput)
{ {
mbr_type_id = ensure_correct_input_type(mbr_type_id, locn, comp, 0, meta.strip_array); mbr_type_id = ensure_correct_input_type(mbr_type_id, location, comp, 0, meta.strip_array);
var_type.member_types[mbr_idx] = mbr_type_id; var_type.member_types[mbr_idx] = mbr_type_id;
if (storage == StorageClassInput && pull_model_inputs.count(var.self)) if (storage == StorageClassInput && pull_model_inputs.count(var.self))
ib_type.member_types[ib_mbr_idx] = build_msl_interpolant_type(mbr_type_id, is_noperspective); ib_type.member_types[ib_mbr_idx] = build_msl_interpolant_type(mbr_type_id, is_noperspective);
else else
ib_type.member_types[ib_mbr_idx] = mbr_type_id; ib_type.member_types[ib_mbr_idx] = mbr_type_id;
} }
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, locn); set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, location);
mark_location_as_used_by_shader(locn, get<SPIRType>(mbr_type_id), storage); mark_location_as_used_by_shader(location, get<SPIRType>(mbr_type_id), storage);
location++;
} }
else if (has_decoration(var.self, DecorationLocation)) else if (has_decoration(var.self, DecorationLocation))
{ {
// The block itself might have a location and in this case, all members of the block location = get_accumulated_member_location(var, mbr_idx, meta.strip_array);
// receive incrementing locations.
uint32_t locn = get_accumulated_member_location(var, mbr_idx, meta.strip_array);
if (storage == StorageClassInput) if (storage == StorageClassInput)
{ {
mbr_type_id = ensure_correct_input_type(mbr_type_id, locn, 0, 0, meta.strip_array); mbr_type_id = ensure_correct_input_type(mbr_type_id, location, 0, 0, meta.strip_array);
var_type.member_types[mbr_idx] = mbr_type_id; var_type.member_types[mbr_idx] = mbr_type_id;
if (storage == StorageClassInput && pull_model_inputs.count(var.self)) if (storage == StorageClassInput && pull_model_inputs.count(var.self))
ib_type.member_types[ib_mbr_idx] = build_msl_interpolant_type(mbr_type_id, is_noperspective); ib_type.member_types[ib_mbr_idx] = build_msl_interpolant_type(mbr_type_id, is_noperspective);
else else
ib_type.member_types[ib_mbr_idx] = mbr_type_id; ib_type.member_types[ib_mbr_idx] = mbr_type_id;
} }
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, locn); set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, location);
mark_location_as_used_by_shader(locn, get<SPIRType>(mbr_type_id), storage); mark_location_as_used_by_shader(location, get<SPIRType>(mbr_type_id), storage);
location++;
} }
else if (is_builtin && is_tessellation_shader() && storage == StorageClassInput && inputs_by_builtin.count(builtin)) else if (is_builtin && is_tessellation_shader() && storage == StorageClassInput && inputs_by_builtin.count(builtin))
{ {
uint32_t locn = 0; location = inputs_by_builtin[builtin].location;
auto builtin_itr = inputs_by_builtin.find(builtin); set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, location);
if (builtin_itr != end(inputs_by_builtin)) mark_location_as_used_by_shader(location, get<SPIRType>(mbr_type_id), storage);
locn = builtin_itr->second.location; location++;
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, locn);
mark_location_as_used_by_shader(locn, get<SPIRType>(mbr_type_id), storage);
} }
// Copy the component location, if present. // Copy the component location, if present.
@ -2854,7 +2887,7 @@ void CompilerMSL::add_plain_member_variable_to_interface_block(StorageClass stor
} }
set_extended_member_decoration(ib_type.self, ib_mbr_idx, SPIRVCrossDecorationInterfaceOrigID, var.self); set_extended_member_decoration(ib_type.self, ib_mbr_idx, SPIRVCrossDecorationInterfaceOrigID, var.self);
set_extended_member_decoration(ib_type.self, ib_mbr_idx, SPIRVCrossDecorationInterfaceMemberIndex, mbr_idx); set_extended_member_decoration(ib_type.self, ib_mbr_idx, SPIRVCrossDecorationInterfaceMemberIndex, var_mbr_idx);
} }
// In Metal, the tessellation levels are stored as tightly packed half-precision floating point values. // In Metal, the tessellation levels are stored as tightly packed half-precision floating point values.
@ -3114,67 +3147,98 @@ void CompilerMSL::add_variable_to_interface_block(StorageClass storage, const st
else else
{ {
bool masked_block = false; bool masked_block = false;
uint32_t location = 0;
// Flatten the struct members into the interface struct uint32_t var_mbr_idx = 0;
for (uint32_t mbr_idx = 0; mbr_idx < uint32_t(var_type.member_types.size()); mbr_idx++) uint32_t elem_cnt = 1;
if (is_matrix(var_type))
{ {
builtin = BuiltInMax; if (is_array(var_type))
is_builtin = is_member_builtin(var_type, mbr_idx, &builtin); SPIRV_CROSS_THROW("MSL cannot emit arrays-of-matrices in input and output variables.");
auto &mbr_type = get<SPIRType>(var_type.member_types[mbr_idx]);
if (storage == StorageClassOutput && is_stage_output_block_member_masked(var, mbr_idx, meta.strip_array)) elem_cnt = var_type.columns;
}
else if (is_array(var_type))
{
if (var_type.array.size() != 1)
SPIRV_CROSS_THROW("MSL cannot emit arrays-of-arrays in input and output variables.");
elem_cnt = to_array_size_literal(var_type);
}
for (uint32_t elem_idx = 0; elem_idx < elem_cnt; elem_idx++)
{
// Flatten the struct members into the interface struct
for (uint32_t mbr_idx = 0; mbr_idx < uint32_t(var_type.member_types.size()); mbr_idx++)
{ {
if (is_block) builtin = BuiltInMax;
masked_block = true; is_builtin = is_member_builtin(var_type, mbr_idx, &builtin);
auto &mbr_type = get<SPIRType>(var_type.member_types[mbr_idx]);
// Non-builtin block output variables are just ignored, since they will still access if (storage == StorageClassOutput && is_stage_output_block_member_masked(var, mbr_idx, meta.strip_array))
// the block variable as-is. They're just not flattened.
if (is_builtin && !meta.strip_array)
{ {
// Emit a fake variable instead. location++; // Skip this location
uint32_t ids = ir.increase_bound_by(2);
uint32_t ptr_type_id = ids + 0;
uint32_t var_id = ids + 1;
auto ptr_type = mbr_type; if (is_block)
ptr_type.pointer = true; masked_block = true;
ptr_type.pointer_depth++;
ptr_type.parent_type = var_type.member_types[mbr_idx];
ptr_type.storage = StorageClassOutput;
uint32_t initializer = 0; // Non-builtin block output variables are just ignored, since they will still access
if (var.initializer) // the block variable as-is. They're just not flattened.
if (auto *c = maybe_get<SPIRConstant>(var.initializer)) if (is_builtin && !meta.strip_array)
initializer = c->subconstants[mbr_idx]; {
// Emit a fake variable instead.
uint32_t ids = ir.increase_bound_by(2);
uint32_t ptr_type_id = ids + 0;
uint32_t var_id = ids + 1;
set<SPIRType>(ptr_type_id, ptr_type); auto ptr_type = mbr_type;
set<SPIRVariable>(var_id, ptr_type_id, StorageClassOutput, initializer); ptr_type.pointer = true;
entry_func.add_local_variable(var_id); ptr_type.pointer_depth++;
vars_needing_early_declaration.push_back(var_id); ptr_type.parent_type = var_type.member_types[mbr_idx];
set_name(var_id, builtin_to_glsl(builtin, StorageClassOutput)); ptr_type.storage = StorageClassOutput;
set_decoration(var_id, DecorationBuiltIn, builtin);
uint32_t initializer = 0;
if (var.initializer)
if (auto *c = maybe_get<SPIRConstant>(var.initializer))
initializer = c->subconstants[mbr_idx];
set<SPIRType>(ptr_type_id, ptr_type);
set<SPIRVariable>(var_id, ptr_type_id, StorageClassOutput, initializer);
entry_func.add_local_variable(var_id);
vars_needing_early_declaration.push_back(var_id);
set_name(var_id, builtin_to_glsl(builtin, StorageClassOutput));
set_decoration(var_id, DecorationBuiltIn, builtin);
}
} }
} else if (!is_builtin || has_active_builtin(builtin, storage))
else if (!is_builtin || has_active_builtin(builtin, storage))
{
bool is_composite_type = is_matrix(mbr_type) || is_array(mbr_type);
bool attribute_load_store =
storage == StorageClassInput && get_execution_model() != ExecutionModelFragment;
bool storage_is_stage_io = variable_storage_requires_stage_io(storage);
// Clip/CullDistance always need to be declared as user attributes.
if (builtin == BuiltInClipDistance || builtin == BuiltInCullDistance)
is_builtin = false;
if ((!is_builtin || attribute_load_store) && storage_is_stage_io && is_composite_type)
{ {
add_composite_member_variable_to_interface_block(storage, ib_var_ref, ib_type, var, mbr_idx, bool is_composite_type = is_matrix(mbr_type) || is_array(mbr_type) || mbr_type.basetype == SPIRType::Struct;
meta); bool attribute_load_store =
} storage == StorageClassInput && get_execution_model() != ExecutionModelFragment;
else bool storage_is_stage_io = variable_storage_requires_stage_io(storage);
{
add_plain_member_variable_to_interface_block(storage, ib_var_ref, ib_type, var, mbr_idx, meta); // Clip/CullDistance always need to be declared as user attributes.
if (builtin == BuiltInClipDistance || builtin == BuiltInCullDistance)
is_builtin = false;
string mbr_name_qual = to_name(var_type.self) + (elem_cnt == 1 ? "" : join("_", elem_idx));
string var_chain_qual = to_name(var.self) + (elem_cnt == 1 ? "" : join("[", elem_idx, "]"));
if ((!is_builtin || attribute_load_store) && storage_is_stage_io && is_composite_type)
{
add_composite_member_variable_to_interface_block(storage, ib_var_ref, ib_type,
var, var_type, mbr_idx, meta,
mbr_name_qual, var_chain_qual,
location, var_mbr_idx);
}
else
{
add_plain_member_variable_to_interface_block(storage, ib_var_ref, ib_type,
var, var_type, mbr_idx, meta,
mbr_name_qual, var_chain_qual,
location, var_mbr_idx);
}
} }
var_mbr_idx++;
} }
} }
@ -12982,8 +13046,8 @@ string CompilerMSL::to_name(uint32_t id, bool allow_alias) const
return Compiler::to_name(id, allow_alias); return Compiler::to_name(id, allow_alias);
} }
// Returns a name that combines the name of the struct with the name of the member, except for Builtins // Appends the name of the member to the variable qualifier string, except for Builtins.
string CompilerMSL::to_qualified_member_name(const SPIRType &type, uint32_t index) string CompilerMSL::append_member_name(const string qualifier, const SPIRType &type, uint32_t index)
{ {
// Don't qualify Builtin names because they are unique and are treated as such when building expressions // Don't qualify Builtin names because they are unique and are treated as such when building expressions
BuiltIn builtin = BuiltInMax; BuiltIn builtin = BuiltInMax;
@ -12994,7 +13058,7 @@ string CompilerMSL::to_qualified_member_name(const SPIRType &type, uint32_t inde
string mbr_name = to_member_name(type, index); string mbr_name = to_member_name(type, index);
size_t startPos = mbr_name.find_first_not_of("_"); size_t startPos = mbr_name.find_first_not_of("_");
mbr_name = (startPos != string::npos) ? mbr_name.substr(startPos) : ""; mbr_name = (startPos != string::npos) ? mbr_name.substr(startPos) : "";
return join(to_name(type.self), "_", mbr_name); return join(qualifier, "_", mbr_name);
} }
// Ensures that the specified name is permanently usable by prepending a prefix // Ensures that the specified name is permanently usable by prepending a prefix

View File

@ -831,12 +831,20 @@ protected:
bool add_component_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref, bool add_component_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref,
SPIRVariable &var, const SPIRType &type, SPIRVariable &var, const SPIRType &type,
InterfaceBlockMeta &meta); InterfaceBlockMeta &meta);
void add_plain_member_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref, void add_plain_member_variable_to_interface_block(spv::StorageClass storage,
SPIRType &ib_type, SPIRVariable &var, uint32_t index, const std::string &ib_var_ref, SPIRType &ib_type,
InterfaceBlockMeta &meta); SPIRVariable &var, SPIRType &var_type,
void add_composite_member_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref, uint32_t mbr_idx, InterfaceBlockMeta &meta,
SPIRType &ib_type, SPIRVariable &var, uint32_t index, const std::string &mbr_name_qual,
InterfaceBlockMeta &meta); const std::string &var_chain_qual,
uint32_t& location, uint32_t& var_mbr_idx);
void add_composite_member_variable_to_interface_block(spv::StorageClass storage,
const std::string &ib_var_ref, SPIRType &ib_type,
SPIRVariable &var, SPIRType &var_type,
uint32_t mbr_idx, InterfaceBlockMeta &meta,
const std::string &mbr_name_qual,
const std::string &var_chain_qual,
uint32_t& location, uint32_t& var_mbr_idx);
void add_tess_level_input_to_interface_block(const std::string &ib_var_ref, SPIRType &ib_type, SPIRVariable &var); void add_tess_level_input_to_interface_block(const std::string &ib_var_ref, SPIRType &ib_type, SPIRVariable &var);
void fix_up_interface_member_indices(spv::StorageClass storage, uint32_t ib_type_id); void fix_up_interface_member_indices(spv::StorageClass storage, uint32_t ib_type_id);
@ -863,7 +871,7 @@ protected:
std::string entry_point_arg_stage_in(); std::string entry_point_arg_stage_in();
void entry_point_args_builtin(std::string &args); void entry_point_args_builtin(std::string &args);
void entry_point_args_discrete_descriptors(std::string &args); void entry_point_args_discrete_descriptors(std::string &args);
std::string to_qualified_member_name(const SPIRType &type, uint32_t index); std::string append_member_name(const std::string qualifier, const SPIRType &type, uint32_t index);
std::string ensure_valid_name(std::string name, std::string pfx); std::string ensure_valid_name(std::string name, std::string pfx);
std::string to_sampler_expression(uint32_t id); std::string to_sampler_expression(uint32_t id);
std::string to_swizzle_expression(uint32_t id); std::string to_swizzle_expression(uint32_t id);