MSL: Force builtin arrays for builtin array types.
authorHans-Kristian Arntzen <post@arntzen-software.no>
Tue, 6 Apr 2021 10:25:22 +0000 (12:25 +0200)
committerHans-Kristian Arntzen <post@arntzen-software.no>
Mon, 19 Apr 2021 10:10:49 +0000 (12:10 +0200)
Handles argument_decl() correctly.

reference/opt/shaders-msl/frag/clip-distance-varying.frag
reference/opt/shaders-msl/masking/write-outputs.mask-clip-distance.vert
reference/opt/shaders-msl/tese/read-tess-level-in-func.msl2.tese [new file with mode: 0644]
reference/opt/shaders-msl/tese/triangle-tess-level.tese
reference/shaders-msl/frag/clip-distance-varying.frag
reference/shaders-msl/masking/write-outputs.mask-clip-distance.vert
reference/shaders-msl/tese/read-tess-level-in-func.msl2.tese [new file with mode: 0644]
reference/shaders-msl/tese/triangle-tess-level.tese
shaders-msl/tese/read-tess-level-in-func.msl2.tese [new file with mode: 0644]
spirv_msl.cpp

index 9a72d5b..6c3f173 100644 (file)
@@ -1,49 +1,8 @@
-#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 main0_out
 {
     float4 FragColor [[color(0)]];
@@ -58,7 +17,7 @@ struct main0_in
 fragment main0_out main0(main0_in in [[stage_in]])
 {
     main0_out out = {};
-    spvUnsafeArray<float, 2> gl_ClipDistance = {};
+    float gl_ClipDistance[2] = {};
     gl_ClipDistance[0] = in.gl_ClipDistance_0;
     gl_ClipDistance[1] = in.gl_ClipDistance_1;
     out.FragColor = float4((1.0 - gl_ClipDistance[0]) - gl_ClipDistance[1]);
index 1f56f34..39fd02c 100644 (file)
@@ -1,49 +1,8 @@
-#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 main0_out
 {
     float4 v0 [[user(locn0)]];
@@ -55,7 +14,7 @@ struct main0_out
 vertex main0_out main0()
 {
     main0_out out = {};
-    spvUnsafeArray<float, 2> gl_ClipDistance = {};
+    float gl_ClipDistance[2] = {};
     out.v0 = float4(1.0);
     out.v1 = float4(2.0);
     out.gl_Position = float4(3.0);
diff --git a/reference/opt/shaders-msl/tese/read-tess-level-in-func.msl2.tese b/reference/opt/shaders-msl/tese/read-tess-level-in-func.msl2.tese
new file mode 100644 (file)
index 0000000..b5b7c15
--- /dev/null
@@ -0,0 +1,26 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct main0_out
+{
+    float4 gl_Position [[position]];
+};
+
+struct main0_patchIn
+{
+    float4 gl_TessLevel [[attribute(0)]];
+};
+
+[[ patch(triangle, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]])
+{
+    main0_out out = {};
+    float gl_TessLevelOuter[4] = {};
+    gl_TessLevelOuter[0] = patchIn.gl_TessLevel.x;
+    gl_TessLevelOuter[1] = patchIn.gl_TessLevel.y;
+    gl_TessLevelOuter[2] = patchIn.gl_TessLevel.z;
+    out.gl_Position = float4(gl_TessLevelOuter[0], gl_TessLevelOuter[1], gl_TessLevelOuter[2], gl_TessLevelOuter[3]);
+    return out;
+}
+
index 6930e14..975e629 100644 (file)
@@ -1,49 +1,8 @@
-#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 main0_out
 {
     float4 gl_Position [[position]];
@@ -57,8 +16,8 @@ struct main0_patchIn
 [[ patch(triangle, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], float3 gl_TessCoord [[position_in_patch]])
 {
     main0_out out = {};
-    spvUnsafeArray<float, 2> gl_TessLevelInner = {};
-    spvUnsafeArray<float, 4> gl_TessLevelOuter = {};
+    float gl_TessLevelInner[2] = {};
+    float gl_TessLevelOuter[4] = {};
     gl_TessLevelInner[0] = patchIn.gl_TessLevel.w;
     gl_TessLevelOuter[0] = patchIn.gl_TessLevel.x;
     gl_TessLevelOuter[1] = patchIn.gl_TessLevel.y;
index 9a72d5b..6c3f173 100644 (file)
@@ -1,49 +1,8 @@
-#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 main0_out
 {
     float4 FragColor [[color(0)]];
@@ -58,7 +17,7 @@ struct main0_in
 fragment main0_out main0(main0_in in [[stage_in]])
 {
     main0_out out = {};
-    spvUnsafeArray<float, 2> gl_ClipDistance = {};
+    float gl_ClipDistance[2] = {};
     gl_ClipDistance[0] = in.gl_ClipDistance_0;
     gl_ClipDistance[1] = in.gl_ClipDistance_1;
     out.FragColor = float4((1.0 - gl_ClipDistance[0]) - gl_ClipDistance[1]);
index 6f63fb4..b0fb744 100644 (file)
@@ -1,49 +1,10 @@
 #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 main0_out
 {
     float4 v0 [[user(locn0)]];
@@ -66,7 +27,7 @@ void write_in_func(thread float4& v0, thread float4& v1, thread float4& gl_Posit
 vertex main0_out main0()
 {
     main0_out out = {};
-    spvUnsafeArray<float, 2> gl_ClipDistance = {};
+    float gl_ClipDistance[2] = {};
     write_in_func(out.v0, out.v1, out.gl_Position, out.gl_PointSize, gl_ClipDistance);
     return out;
 }
diff --git a/reference/shaders-msl/tese/read-tess-level-in-func.msl2.tese b/reference/shaders-msl/tese/read-tess-level-in-func.msl2.tese
new file mode 100644 (file)
index 0000000..4bcf22d
--- /dev/null
@@ -0,0 +1,34 @@
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct main0_out
+{
+    float4 gl_Position [[position]];
+};
+
+struct main0_patchIn
+{
+    float4 gl_TessLevel [[attribute(0)]];
+};
+
+static inline __attribute__((always_inline))
+float4 read_tess_levels(thread float (&gl_TessLevelOuter)[4])
+{
+    return float4(gl_TessLevelOuter[0], gl_TessLevelOuter[1], gl_TessLevelOuter[2], gl_TessLevelOuter[3]);
+}
+
+[[ patch(triangle, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]])
+{
+    main0_out out = {};
+    float gl_TessLevelOuter[4] = {};
+    gl_TessLevelOuter[0] = patchIn.gl_TessLevel.x;
+    gl_TessLevelOuter[1] = patchIn.gl_TessLevel.y;
+    gl_TessLevelOuter[2] = patchIn.gl_TessLevel.z;
+    out.gl_Position = read_tess_levels(gl_TessLevelOuter);
+    return out;
+}
+
index 6930e14..975e629 100644 (file)
@@ -1,49 +1,8 @@
-#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 main0_out
 {
     float4 gl_Position [[position]];
@@ -57,8 +16,8 @@ struct main0_patchIn
 [[ patch(triangle, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], float3 gl_TessCoord [[position_in_patch]])
 {
     main0_out out = {};
-    spvUnsafeArray<float, 2> gl_TessLevelInner = {};
-    spvUnsafeArray<float, 4> gl_TessLevelOuter = {};
+    float gl_TessLevelInner[2] = {};
+    float gl_TessLevelOuter[4] = {};
     gl_TessLevelInner[0] = patchIn.gl_TessLevel.w;
     gl_TessLevelOuter[0] = patchIn.gl_TessLevel.x;
     gl_TessLevelOuter[1] = patchIn.gl_TessLevel.y;
diff --git a/shaders-msl/tese/read-tess-level-in-func.msl2.tese b/shaders-msl/tese/read-tess-level-in-func.msl2.tese
new file mode 100644 (file)
index 0000000..f79083f
--- /dev/null
@@ -0,0 +1,16 @@
+#version 450
+layout(triangles) in;
+
+vec4 read_tess_levels()
+{
+       return vec4(
+               gl_TessLevelOuter[0],
+               gl_TessLevelOuter[1],
+               gl_TessLevelOuter[2],
+               gl_TessLevelOuter[3]);
+}
+
+void main()
+{
+       gl_Position = read_tess_levels();
+}
index 3adc98d..8367132 100644 (file)
@@ -12951,12 +12951,17 @@ bool CompilerMSL::variable_decl_is_threadgroup_like(const SPIRVariable &variable
                !is_patch);
 }
 
-// Threadgroup arrays can't have a wrapper type
 std::string CompilerMSL::variable_decl(const SPIRVariable &variable)
 {
        bool old_is_using_builtin_array = is_using_builtin_array;
-       if (variable_decl_is_threadgroup_like(variable))
+
+       // Threadgroup arrays can't have a wrapper type.
+       // More special cases. ClipDistance and CullDistance are emitted as plain arrays in stage out,
+       // so preserve that property when emitting them as masked variables. Avoids lots of extra special casing
+       // in argument_decl(). Similar argument for TessLevels.
+       if (variable_decl_is_threadgroup_like(variable) || has_decoration(variable.self, DecorationBuiltIn))
                is_using_builtin_array = true;
+
        std::string expr = CompilerGLSL::variable_decl(variable);
        is_using_builtin_array = old_is_using_builtin_array;
        return expr;