Merge pull request #1660 from KhronosGroup/fix-1658

MSL: Use proper array for quad tess levels.
This commit is contained in:
Hans-Kristian Arntzen 2021-04-23 15:21:00 +02:00 committed by GitHub
commit c624d5387c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 744 additions and 121 deletions

View File

@ -1,8 +1,49 @@
#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]];
@ -17,7 +58,15 @@ struct main0_patchIn
[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], float2 gl_TessCoord [[position_in_patch]])
{
main0_out out = {};
out.gl_Position = float4(((gl_TessCoord.x * patchIn.gl_TessLevelInner.x) * patchIn.gl_TessLevelOuter.x) + (((1.0 - gl_TessCoord.x) * patchIn.gl_TessLevelInner.x) * patchIn.gl_TessLevelOuter.z), ((gl_TessCoord.y * patchIn.gl_TessLevelInner.y) * patchIn.gl_TessLevelOuter.y) + (((1.0 - gl_TessCoord.y) * patchIn.gl_TessLevelInner.y) * patchIn.gl_TessLevelOuter.w), 0.0, 1.0);
spvUnsafeArray<float, 2> gl_TessLevelInner = {};
spvUnsafeArray<float, 4> gl_TessLevelOuter = {};
gl_TessLevelInner[0] = patchIn.gl_TessLevelInner.x;
gl_TessLevelInner[1] = patchIn.gl_TessLevelInner.y;
gl_TessLevelOuter[0] = patchIn.gl_TessLevelOuter.x;
gl_TessLevelOuter[1] = patchIn.gl_TessLevelOuter.y;
gl_TessLevelOuter[2] = patchIn.gl_TessLevelOuter.z;
gl_TessLevelOuter[3] = patchIn.gl_TessLevelOuter.w;
out.gl_Position = float4(((gl_TessCoord.x * gl_TessLevelInner[0]) * gl_TessLevelOuter[0]) + (((1.0 - gl_TessCoord.x) * gl_TessLevelInner[0]) * gl_TessLevelOuter[2]), ((gl_TessCoord.y * gl_TessLevelInner[1]) * gl_TessLevelOuter[1]) + (((1.0 - gl_TessCoord.y) * gl_TessLevelInner[1]) * gl_TessLevelOuter[3]), 0.0, 1.0);
return out;
}

View File

@ -1,8 +1,49 @@
#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]];
@ -17,8 +58,16 @@ struct main0_patchIn
[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], float2 gl_TessCoord [[position_in_patch]])
{
main0_out out = {};
spvUnsafeArray<float, 2> gl_TessLevelInner = {};
spvUnsafeArray<float, 4> gl_TessLevelOuter = {};
gl_TessLevelInner[0] = patchIn.gl_TessLevelInner.x;
gl_TessLevelInner[1] = patchIn.gl_TessLevelInner.y;
gl_TessLevelOuter[0] = patchIn.gl_TessLevelOuter.x;
gl_TessLevelOuter[1] = patchIn.gl_TessLevelOuter.y;
gl_TessLevelOuter[2] = patchIn.gl_TessLevelOuter.z;
gl_TessLevelOuter[3] = patchIn.gl_TessLevelOuter.w;
gl_TessCoord.y = 1.0 - gl_TessCoord.y;
out.gl_Position = float4(((gl_TessCoord.x * patchIn.gl_TessLevelInner.x) * patchIn.gl_TessLevelOuter.x) + (((1.0 - gl_TessCoord.x) * patchIn.gl_TessLevelInner.x) * patchIn.gl_TessLevelOuter.z), ((gl_TessCoord.y * patchIn.gl_TessLevelInner.y) * patchIn.gl_TessLevelOuter.w) + (((1.0 - gl_TessCoord.y) * patchIn.gl_TessLevelInner.y) * patchIn.gl_TessLevelOuter.y), 0.0, 1.0);
out.gl_Position = float4(((gl_TessCoord.x * gl_TessLevelInner[0]) * gl_TessLevelOuter[0]) + (((1.0 - gl_TessCoord.x) * gl_TessLevelInner[0]) * gl_TessLevelOuter[2]), ((gl_TessCoord.y * gl_TessLevelInner[1]) * gl_TessLevelOuter[3]) + (((1.0 - gl_TessCoord.y) * gl_TessLevelInner[1]) * gl_TessLevelOuter[1]), 0.0, 1.0);
return out;
}

View File

@ -1,8 +1,49 @@
#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]];
@ -17,7 +58,15 @@ struct main0_patchIn
[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], float2 gl_TessCoord [[position_in_patch]])
{
main0_out out = {};
out.gl_Position = float4(((gl_TessCoord.x * patchIn.gl_TessLevelInner.x) * patchIn.gl_TessLevelOuter.x) + (((1.0 - gl_TessCoord.x) * patchIn.gl_TessLevelInner.x) * patchIn.gl_TessLevelOuter.z), ((gl_TessCoord.y * patchIn.gl_TessLevelInner.y) * patchIn.gl_TessLevelOuter.y) + (((1.0 - gl_TessCoord.y) * patchIn.gl_TessLevelInner.y) * patchIn.gl_TessLevelOuter.w), 0.0, 1.0);
spvUnsafeArray<float, 2> gl_TessLevelInner = {};
spvUnsafeArray<float, 4> gl_TessLevelOuter = {};
gl_TessLevelInner[0] = patchIn.gl_TessLevelInner.x;
gl_TessLevelInner[1] = patchIn.gl_TessLevelInner.y;
gl_TessLevelOuter[0] = patchIn.gl_TessLevelOuter.x;
gl_TessLevelOuter[1] = patchIn.gl_TessLevelOuter.y;
gl_TessLevelOuter[2] = patchIn.gl_TessLevelOuter.z;
gl_TessLevelOuter[3] = patchIn.gl_TessLevelOuter.w;
out.gl_Position = float4(((gl_TessCoord.x * gl_TessLevelInner[0]) * gl_TessLevelOuter[0]) + (((1.0 - gl_TessCoord.x) * gl_TessLevelInner[0]) * gl_TessLevelOuter[2]), ((gl_TessCoord.y * gl_TessLevelInner[1]) * gl_TessLevelOuter[1]) + (((1.0 - gl_TessCoord.y) * gl_TessLevelInner[1]) * gl_TessLevelOuter[3]), 0.0, 1.0);
return out;
}

View File

@ -0,0 +1,72 @@
#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]];
};
struct main0_patchIn
{
float4 gl_TessLevelOuter [[attribute(0)]];
float2 gl_TessLevelInner [[attribute(1)]];
};
[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]])
{
main0_out out = {};
spvUnsafeArray<float, 4> gl_TessLevelOuter = {};
spvUnsafeArray<float, 2> gl_TessLevelInner = {};
gl_TessLevelOuter[0] = patchIn.gl_TessLevelOuter.x;
gl_TessLevelOuter[1] = patchIn.gl_TessLevelOuter.y;
gl_TessLevelOuter[2] = patchIn.gl_TessLevelOuter.z;
gl_TessLevelOuter[3] = patchIn.gl_TessLevelOuter.w;
gl_TessLevelInner[0] = patchIn.gl_TessLevelInner.x;
gl_TessLevelInner[1] = patchIn.gl_TessLevelInner.y;
out.gl_Position = float4(gl_TessLevelOuter[0], gl_TessLevelOuter[1], gl_TessLevelOuter[2], gl_TessLevelOuter[3]) + float2(gl_TessLevelInner[0], gl_TessLevelInner[1]).xyxy;
return out;
}

View File

@ -58,10 +58,12 @@ struct main0_patchIn
{
main0_out out = {};
spvUnsafeArray<float, 4> gl_TessLevelOuter = {};
spvUnsafeArray<float, 2> gl_TessLevelInner = {};
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]);
gl_TessLevelInner[0] = patchIn.gl_TessLevel.w;
out.gl_Position = float4(gl_TessLevelOuter[0], gl_TessLevelOuter[1], gl_TessLevelOuter[2], gl_TessLevelOuter[3]) + float2(gl_TessLevelInner[0], gl_TessLevelInner[1]).xyxy;
return out;
}

View File

@ -0,0 +1,73 @@
#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 out_var_CUSTOM_VALUE [[user(locn0)]];
float4 gl_Position [[position]];
};
struct main0_patchIn
{
float4 gl_TessLevelOuter [[attribute(0)]];
float2 gl_TessLevelInner [[attribute(1)]];
};
[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]])
{
main0_out out = {};
spvUnsafeArray<float, 4> gl_TessLevelOuter = {};
spvUnsafeArray<float, 2> gl_TessLevelInner = {};
gl_TessLevelOuter[0] = patchIn.gl_TessLevelOuter.x;
gl_TessLevelOuter[1] = patchIn.gl_TessLevelOuter.y;
gl_TessLevelOuter[2] = patchIn.gl_TessLevelOuter.z;
gl_TessLevelOuter[3] = patchIn.gl_TessLevelOuter.w;
gl_TessLevelInner[0] = patchIn.gl_TessLevelInner.x;
gl_TessLevelInner[1] = patchIn.gl_TessLevelInner.y;
out.out_var_CUSTOM_VALUE = float4(gl_TessLevelOuter[0] + gl_TessLevelInner[0], gl_TessLevelOuter[1] + gl_TessLevelInner[1], gl_TessLevelOuter[2], gl_TessLevelOuter[3]);
return out;
}

View File

@ -1,8 +1,49 @@
#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]];
@ -25,7 +66,15 @@ struct main0_patchIn
[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], uint gl_PrimitiveID [[patch_id]])
{
main0_out out = {};
out.gl_Position = (((((float4(1.0) + patchIn.FragColor) + patchIn.gl_in[0].FragColors) + patchIn.gl_in[1].FragColors) + float4(patchIn.gl_TessLevelInner.x)) + float4(patchIn.gl_TessLevelOuter[int(gl_PrimitiveID) & 1])) + patchIn.gl_in[0].gl_Position;
spvUnsafeArray<float, 2> gl_TessLevelInner = {};
spvUnsafeArray<float, 4> gl_TessLevelOuter = {};
gl_TessLevelInner[0] = patchIn.gl_TessLevelInner.x;
gl_TessLevelInner[1] = patchIn.gl_TessLevelInner.y;
gl_TessLevelOuter[0] = patchIn.gl_TessLevelOuter.x;
gl_TessLevelOuter[1] = patchIn.gl_TessLevelOuter.y;
gl_TessLevelOuter[2] = patchIn.gl_TessLevelOuter.z;
gl_TessLevelOuter[3] = patchIn.gl_TessLevelOuter.w;
out.gl_Position = (((((float4(1.0) + patchIn.FragColor) + patchIn.gl_in[0].FragColors) + patchIn.gl_in[1].FragColors) + float4(gl_TessLevelInner[0])) + float4(gl_TessLevelOuter[int(gl_PrimitiveID) & 1])) + patchIn.gl_in[0].gl_Position;
return out;
}

View File

@ -1,8 +1,49 @@
#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]];
@ -17,7 +58,15 @@ struct main0_patchIn
[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], float2 gl_TessCoord [[position_in_patch]])
{
main0_out out = {};
out.gl_Position = float4(((gl_TessCoord.x * patchIn.gl_TessLevelInner.x) * patchIn.gl_TessLevelOuter.x) + (((1.0 - gl_TessCoord.x) * patchIn.gl_TessLevelInner.x) * patchIn.gl_TessLevelOuter.z), ((gl_TessCoord.y * patchIn.gl_TessLevelInner.y) * patchIn.gl_TessLevelOuter.y) + (((1.0 - gl_TessCoord.y) * patchIn.gl_TessLevelInner.y) * patchIn.gl_TessLevelOuter.w), 0.0, 1.0);
spvUnsafeArray<float, 2> gl_TessLevelInner = {};
spvUnsafeArray<float, 4> gl_TessLevelOuter = {};
gl_TessLevelInner[0] = patchIn.gl_TessLevelInner.x;
gl_TessLevelInner[1] = patchIn.gl_TessLevelInner.y;
gl_TessLevelOuter[0] = patchIn.gl_TessLevelOuter.x;
gl_TessLevelOuter[1] = patchIn.gl_TessLevelOuter.y;
gl_TessLevelOuter[2] = patchIn.gl_TessLevelOuter.z;
gl_TessLevelOuter[3] = patchIn.gl_TessLevelOuter.w;
out.gl_Position = float4(((gl_TessCoord.x * gl_TessLevelInner[0]) * gl_TessLevelOuter[0]) + (((1.0 - gl_TessCoord.x) * gl_TessLevelInner[0]) * gl_TessLevelOuter[2]), ((gl_TessCoord.y * gl_TessLevelInner[1]) * gl_TessLevelOuter[1]) + (((1.0 - gl_TessCoord.y) * gl_TessLevelInner[1]) * gl_TessLevelOuter[3]), 0.0, 1.0);
return out;
}

View File

@ -1,8 +1,49 @@
#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]];
@ -17,8 +58,16 @@ struct main0_patchIn
[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], float2 gl_TessCoord [[position_in_patch]])
{
main0_out out = {};
spvUnsafeArray<float, 2> gl_TessLevelInner = {};
spvUnsafeArray<float, 4> gl_TessLevelOuter = {};
gl_TessLevelInner[0] = patchIn.gl_TessLevelInner.x;
gl_TessLevelInner[1] = patchIn.gl_TessLevelInner.y;
gl_TessLevelOuter[0] = patchIn.gl_TessLevelOuter.x;
gl_TessLevelOuter[1] = patchIn.gl_TessLevelOuter.y;
gl_TessLevelOuter[2] = patchIn.gl_TessLevelOuter.z;
gl_TessLevelOuter[3] = patchIn.gl_TessLevelOuter.w;
gl_TessCoord.y = 1.0 - gl_TessCoord.y;
out.gl_Position = float4(((gl_TessCoord.x * patchIn.gl_TessLevelInner.x) * patchIn.gl_TessLevelOuter.x) + (((1.0 - gl_TessCoord.x) * patchIn.gl_TessLevelInner.x) * patchIn.gl_TessLevelOuter.z), ((gl_TessCoord.y * patchIn.gl_TessLevelInner.y) * patchIn.gl_TessLevelOuter.w) + (((1.0 - gl_TessCoord.y) * patchIn.gl_TessLevelInner.y) * patchIn.gl_TessLevelOuter.y), 0.0, 1.0);
out.gl_Position = float4(((gl_TessCoord.x * gl_TessLevelInner[0]) * gl_TessLevelOuter[0]) + (((1.0 - gl_TessCoord.x) * gl_TessLevelInner[0]) * gl_TessLevelOuter[2]), ((gl_TessCoord.y * gl_TessLevelInner[1]) * gl_TessLevelOuter[3]) + (((1.0 - gl_TessCoord.y) * gl_TessLevelInner[1]) * gl_TessLevelOuter[1]), 0.0, 1.0);
return out;
}

View File

@ -1,10 +1,49 @@
#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]];
@ -17,15 +56,23 @@ struct main0_patchIn
};
static inline __attribute__((always_inline))
void set_position(thread float4& gl_Position, thread float2& gl_TessCoord, thread float2& gl_TessLevelInner, thread float4& gl_TessLevelOuter)
void set_position(thread float4& gl_Position, thread float2& gl_TessCoord, thread spvUnsafeArray<float, 2>& gl_TessLevelInner, thread spvUnsafeArray<float, 4>& gl_TessLevelOuter)
{
gl_Position = float4(((gl_TessCoord.x * gl_TessLevelInner.x) * gl_TessLevelOuter.x) + (((1.0 - gl_TessCoord.x) * gl_TessLevelInner.x) * gl_TessLevelOuter.z), ((gl_TessCoord.y * gl_TessLevelInner.y) * gl_TessLevelOuter.y) + (((1.0 - gl_TessCoord.y) * gl_TessLevelInner.y) * gl_TessLevelOuter.w), 0.0, 1.0);
gl_Position = float4(((gl_TessCoord.x * gl_TessLevelInner[0]) * gl_TessLevelOuter[0]) + (((1.0 - gl_TessCoord.x) * gl_TessLevelInner[0]) * gl_TessLevelOuter[2]), ((gl_TessCoord.y * gl_TessLevelInner[1]) * gl_TessLevelOuter[1]) + (((1.0 - gl_TessCoord.y) * gl_TessLevelInner[1]) * gl_TessLevelOuter[3]), 0.0, 1.0);
}
[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], float2 gl_TessCoord [[position_in_patch]])
{
main0_out out = {};
set_position(out.gl_Position, gl_TessCoord, patchIn.gl_TessLevelInner, patchIn.gl_TessLevelOuter);
spvUnsafeArray<float, 2> gl_TessLevelInner = {};
spvUnsafeArray<float, 4> gl_TessLevelOuter = {};
gl_TessLevelInner[0] = patchIn.gl_TessLevelInner.x;
gl_TessLevelInner[1] = patchIn.gl_TessLevelInner.y;
gl_TessLevelOuter[0] = patchIn.gl_TessLevelOuter.x;
gl_TessLevelOuter[1] = patchIn.gl_TessLevelOuter.y;
gl_TessLevelOuter[2] = patchIn.gl_TessLevelOuter.z;
gl_TessLevelOuter[3] = patchIn.gl_TessLevelOuter.w;
set_position(out.gl_Position, gl_TessCoord, gl_TessLevelInner, gl_TessLevelOuter);
return out;
}

View File

@ -0,0 +1,78 @@
#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]];
};
struct main0_patchIn
{
float4 gl_TessLevelOuter [[attribute(0)]];
float2 gl_TessLevelInner [[attribute(1)]];
};
static inline __attribute__((always_inline))
float4 read_tess_levels(thread spvUnsafeArray<float, 4>& gl_TessLevelOuter, thread spvUnsafeArray<float, 2>& gl_TessLevelInner)
{
return float4(gl_TessLevelOuter[0], gl_TessLevelOuter[1], gl_TessLevelOuter[2], gl_TessLevelOuter[3]) + float2(gl_TessLevelInner[0], gl_TessLevelInner[1]).xyxy;
}
[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]])
{
main0_out out = {};
spvUnsafeArray<float, 4> gl_TessLevelOuter = {};
spvUnsafeArray<float, 2> gl_TessLevelInner = {};
gl_TessLevelOuter[0] = patchIn.gl_TessLevelOuter.x;
gl_TessLevelOuter[1] = patchIn.gl_TessLevelOuter.y;
gl_TessLevelOuter[2] = patchIn.gl_TessLevelOuter.z;
gl_TessLevelOuter[3] = patchIn.gl_TessLevelOuter.w;
gl_TessLevelInner[0] = patchIn.gl_TessLevelInner.x;
gl_TessLevelInner[1] = patchIn.gl_TessLevelInner.y;
out.gl_Position = read_tess_levels(gl_TessLevelOuter, gl_TessLevelInner);
return out;
}

View File

@ -55,19 +55,21 @@ struct main0_patchIn
};
static inline __attribute__((always_inline))
float4 read_tess_levels(thread spvUnsafeArray<float, 4>& gl_TessLevelOuter)
float4 read_tess_levels(thread spvUnsafeArray<float, 4>& gl_TessLevelOuter, thread spvUnsafeArray<float, 2>& gl_TessLevelInner)
{
return float4(gl_TessLevelOuter[0], gl_TessLevelOuter[1], gl_TessLevelOuter[2], gl_TessLevelOuter[3]);
return float4(gl_TessLevelOuter[0], gl_TessLevelOuter[1], gl_TessLevelOuter[2], gl_TessLevelOuter[3]) + float2(gl_TessLevelInner[0], gl_TessLevelInner[1]).xyxy;
}
[[ patch(triangle, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]])
{
main0_out out = {};
spvUnsafeArray<float, 4> gl_TessLevelOuter = {};
spvUnsafeArray<float, 2> gl_TessLevelInner = {};
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);
gl_TessLevelInner[0] = patchIn.gl_TessLevel.w;
out.gl_Position = read_tess_levels(gl_TessLevelOuter, gl_TessLevelInner);
return out;
}

View File

@ -0,0 +1,58 @@
; SPIR-V
; Version: 1.0
; Generator: Google spiregg; 0
; Bound: 35
; Schema: 0
OpCapability Tessellation
OpMemoryModel Logical GLSL450
OpEntryPoint TessellationEvaluation %Domain "main" %gl_TessLevelOuter %gl_TessLevelInner %in_var_CUSTOM_VALUE %gl_TessCoord %out_var_CUSTOM_VALUE
OpExecutionMode %Domain Quads
OpSource HLSL 600
OpName %in_var_CUSTOM_VALUE "in.var.CUSTOM_VALUE"
OpName %out_var_CUSTOM_VALUE "out.var.CUSTOM_VALUE"
OpName %Domain "Domain"
OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter
OpDecorate %gl_TessLevelOuter Patch
OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner
OpDecorate %gl_TessLevelInner Patch
OpDecorate %gl_TessCoord BuiltIn TessCoord
OpDecorate %gl_TessCoord Patch
OpDecorate %in_var_CUSTOM_VALUE Location 0
OpDecorate %out_var_CUSTOM_VALUE Location 0
%uint = OpTypeInt 32 0
%uint_4 = OpConstant %uint 4
%float = OpTypeFloat 32
%_arr_float_uint_4 = OpTypeArray %float %uint_4
%_ptr_Input__arr_float_uint_4 = OpTypePointer Input %_arr_float_uint_4
%uint_2 = OpConstant %uint 2
%_arr_float_uint_2 = OpTypeArray %float %uint_2
%_ptr_Input__arr_float_uint_2 = OpTypePointer Input %_arr_float_uint_2
%v4float = OpTypeVector %float 4
%_arr_v4float_uint_4 = OpTypeArray %v4float %uint_4
%_ptr_Input__arr_v4float_uint_4 = OpTypePointer Input %_arr_v4float_uint_4
%v3float = OpTypeVector %float 3
%_ptr_Input_v3float = OpTypePointer Input %v3float
%_ptr_Output_v4float = OpTypePointer Output %v4float
%void = OpTypeVoid
%22 = OpTypeFunction %void
%gl_TessLevelOuter = OpVariable %_ptr_Input__arr_float_uint_4 Input
%gl_TessLevelInner = OpVariable %_ptr_Input__arr_float_uint_2 Input
%in_var_CUSTOM_VALUE = OpVariable %_ptr_Input__arr_v4float_uint_4 Input
%gl_TessCoord = OpVariable %_ptr_Input_v3float Input
%out_var_CUSTOM_VALUE = OpVariable %_ptr_Output_v4float Output
%Domain = OpFunction %void None %22
%23 = OpLabel
%24 = OpLoad %_arr_float_uint_4 %gl_TessLevelOuter
%25 = OpLoad %_arr_float_uint_2 %gl_TessLevelInner
%26 = OpCompositeExtract %float %24 0
%27 = OpCompositeExtract %float %24 1
%28 = OpCompositeExtract %float %24 2
%29 = OpCompositeExtract %float %24 3
%30 = OpCompositeExtract %float %25 0
%31 = OpCompositeExtract %float %25 1
%32 = OpFAdd %float %26 %30
%33 = OpFAdd %float %27 %31
%34 = OpCompositeConstruct %v4float %32 %33 %28 %29
OpStore %out_var_CUSTOM_VALUE %34
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,17 @@
#version 450
layout(quads) in;
vec4 read_tess_levels()
{
return vec4(
gl_TessLevelOuter[0],
gl_TessLevelOuter[1],
gl_TessLevelOuter[2],
gl_TessLevelOuter[3]) +
vec2(gl_TessLevelInner[0], gl_TessLevelInner[1]).xyxy;
}
void main()
{
gl_Position = read_tess_levels();
}

View File

@ -7,7 +7,8 @@ vec4 read_tess_levels()
gl_TessLevelOuter[0],
gl_TessLevelOuter[1],
gl_TessLevelOuter[2],
gl_TessLevelOuter[3]);
gl_TessLevelOuter[3]) +
vec2(gl_TessLevelInner[0], gl_TessLevelInner[1]).xyxy;
}
void main()

View File

@ -2797,100 +2797,19 @@ void CompilerMSL::add_tess_level_input_to_interface_block(const std::string &ib_
BuiltIn builtin = BuiltIn(get_decoration(var.self, DecorationBuiltIn));
// Force the variable to have the proper name.
set_name(var.self, builtin_to_glsl(builtin, StorageClassFunction));
string var_name = builtin_to_glsl(builtin, StorageClassFunction);
set_name(var.self, var_name);
if (get_execution_mode_bitset().get(ExecutionModeTriangles))
{
// Triangles are tricky, because we want only one member in the struct.
// We need to declare the variable early and at entry-point scope.
entry_func.add_local_variable(var.self);
vars_needing_early_declaration.push_back(var.self);
bool triangles = get_execution_mode_bitset().get(ExecutionModeTriangles);
string mbr_name;
// We need to declare the variable early and at entry-point scope.
entry_func.add_local_variable(var.self);
vars_needing_early_declaration.push_back(var.self);
string mbr_name = "gl_TessLevel";
// If we already added the other one, we can skip this step.
if (!added_builtin_tess_level)
{
// Add a reference to the variable type to the interface struct.
uint32_t ib_mbr_idx = uint32_t(ib_type.member_types.size());
uint32_t type_id = build_extended_vector_type(var_type.self, 4);
ib_type.member_types.push_back(type_id);
// Give the member a name
set_member_name(ib_type.self, ib_mbr_idx, mbr_name);
// We cannot decorate both, but the important part is that
// it's marked as builtin so we can get automatic attribute assignment if needed.
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationBuiltIn, builtin);
// There is no qualified alias since we need to flatten the internal array on return.
if (get_decoration_bitset(var.self).get(DecorationLocation))
{
uint32_t locn = get_decoration(var.self, DecorationLocation);
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, locn);
mark_location_as_used_by_shader(locn, var_type, StorageClassInput);
}
else if (inputs_by_builtin.count(builtin))
{
uint32_t locn = inputs_by_builtin[builtin].location;
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, locn);
mark_location_as_used_by_shader(locn, var_type, StorageClassInput);
}
added_builtin_tess_level = true;
}
switch (builtin)
{
case BuiltInTessLevelOuter:
entry_func.fixup_hooks_in.push_back([=, &var]() {
statement(to_name(var.self), "[0] = ", ib_var_ref, ".", mbr_name, ".x;");
statement(to_name(var.self), "[1] = ", ib_var_ref, ".", mbr_name, ".y;");
statement(to_name(var.self), "[2] = ", ib_var_ref, ".", mbr_name, ".z;");
});
break;
case BuiltInTessLevelInner:
entry_func.fixup_hooks_in.push_back(
[=, &var]() { statement(to_name(var.self), "[0] = ", ib_var_ref, ".", mbr_name, ".w;"); });
break;
default:
assert(false);
break;
}
}
else
{
// Add a reference to the variable type to the interface struct.
uint32_t ib_mbr_idx = uint32_t(ib_type.member_types.size());
uint32_t type_id = build_extended_vector_type(var_type.self, builtin == BuiltInTessLevelOuter ? 4 : 2);
// Change the type of the variable, too.
uint32_t ptr_type_id = ir.increase_bound_by(1);
auto &new_var_type = set<SPIRType>(ptr_type_id, get<SPIRType>(type_id));
new_var_type.pointer = true;
new_var_type.pointer_depth++;
new_var_type.storage = StorageClassInput;
new_var_type.parent_type = type_id;
var.basetype = ptr_type_id;
ib_type.member_types.push_back(type_id);
// Give the member a name
string mbr_name = to_expression(var.self);
set_member_name(ib_type.self, ib_mbr_idx, mbr_name);
// Since vectors can be indexed like arrays, there is no need to unpack this. We can
// just refer to the vector directly. So give it a qualified alias.
string qual_var_name = ib_var_ref + "." + mbr_name;
ir.meta[var.self].decoration.qualified_alias = qual_var_name;
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationBuiltIn, builtin);
// Add a reference to the variable type to the interface struct.
uint32_t ib_mbr_idx = uint32_t(ib_type.member_types.size());
const auto mark_locations = [&](const SPIRType &new_var_type) {
if (get_decoration_bitset(var.self).get(DecorationLocation))
{
uint32_t locn = get_decoration(var.self, DecorationLocation);
@ -2903,6 +2822,76 @@ void CompilerMSL::add_tess_level_input_to_interface_block(const std::string &ib_
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, locn);
mark_location_as_used_by_shader(locn, new_var_type, StorageClassInput);
}
};
if (triangles)
{
// Triangles are tricky, because we want only one member in the struct.
mbr_name = "gl_TessLevel";
// If we already added the other one, we can skip this step.
if (!added_builtin_tess_level)
{
uint32_t type_id = build_extended_vector_type(var_type.self, 4);
ib_type.member_types.push_back(type_id);
// Give the member a name
set_member_name(ib_type.self, ib_mbr_idx, mbr_name);
// We cannot decorate both, but the important part is that
// it's marked as builtin so we can get automatic attribute assignment if needed.
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationBuiltIn, builtin);
mark_locations(var_type);
added_builtin_tess_level = true;
}
}
else
{
mbr_name = var_name;
uint32_t type_id = build_extended_vector_type(var_type.self, builtin == BuiltInTessLevelOuter ? 4 : 2);
uint32_t ptr_type_id = ir.increase_bound_by(1);
auto &new_var_type = set<SPIRType>(ptr_type_id, get<SPIRType>(type_id));
new_var_type.pointer = true;
new_var_type.pointer_depth++;
new_var_type.storage = StorageClassInput;
new_var_type.parent_type = type_id;
ib_type.member_types.push_back(type_id);
// Give the member a name
set_member_name(ib_type.self, ib_mbr_idx, mbr_name);
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationBuiltIn, builtin);
mark_locations(new_var_type);
}
if (builtin == BuiltInTessLevelOuter)
{
entry_func.fixup_hooks_in.push_back([=]() {
statement(var_name, "[0] = ", ib_var_ref, ".", mbr_name, ".x;");
statement(var_name, "[1] = ", ib_var_ref, ".", mbr_name, ".y;");
statement(var_name, "[2] = ", ib_var_ref, ".", mbr_name, ".z;");
if (!triangles)
statement(var_name, "[3] = ", ib_var_ref, ".", mbr_name, ".w;");
});
}
else
{
entry_func.fixup_hooks_in.push_back([=]() {
if (triangles)
{
statement(var_name, "[0] = ", ib_var_ref, ".", mbr_name, ".w;");
}
else
{
statement(var_name, "[0] = ", ib_var_ref, ".", mbr_name, ".x;");
statement(var_name, "[1] = ", ib_var_ref, ".", mbr_name, ".y;");
}
});
}
}
@ -13979,31 +13968,21 @@ string CompilerMSL::builtin_to_glsl(BuiltIn builtin, StorageClass storage)
break;
case BuiltInTessLevelOuter:
if (get_execution_model() == ExecutionModelTessellationEvaluation)
if (get_execution_model() == ExecutionModelTessellationControl &&
storage != StorageClassInput && current_function && (current_function->self == ir.default_entry_point))
{
if (storage != StorageClassOutput && !get_entry_point().flags.get(ExecutionModeTriangles) &&
current_function && (current_function->self == ir.default_entry_point))
return join(patch_stage_in_var_name, ".", CompilerGLSL::builtin_to_glsl(builtin, storage));
else
break;
}
if (storage != StorageClassInput && current_function && (current_function->self == ir.default_entry_point))
return join(tess_factor_buffer_var_name, "[", to_expression(builtin_primitive_id_id),
"].edgeTessellationFactor");
}
break;
case BuiltInTessLevelInner:
if (get_execution_model() == ExecutionModelTessellationEvaluation)
if (get_execution_model() == ExecutionModelTessellationControl &&
storage != StorageClassInput && current_function && (current_function->self == ir.default_entry_point))
{
if (storage != StorageClassOutput && !get_entry_point().flags.get(ExecutionModeTriangles) &&
current_function && (current_function->self == ir.default_entry_point))
return join(patch_stage_in_var_name, ".", CompilerGLSL::builtin_to_glsl(builtin, storage));
else
break;
}
if (storage != StorageClassInput && current_function && (current_function->self == ir.default_entry_point))
return join(tess_factor_buffer_var_name, "[", to_expression(builtin_primitive_id_id),
"].insideTessellationFactor");
}
break;
default: