f3c0942d10
The tessellation levels in Metal are stored as a densely-packed array of half-precision floating point values. But, stage-in attributes in Metal have to have offsets and strides aligned to a multiple of four, so we can't add them individually. Luckily for us, the arrays have lengths less than 4. So, let's use vectors for them! Triangles get a single attribute with a `float4`, where the outer levels are in `.xyz` and the inner levels are in `.w`. The arrays are unpacked as though we had added the elements individually. Quads get two: a `float4` with the outer levels and a `float2` with the inner levels. Further, since vectors can be indexed as arrays, there's no need to unpack them in this case. This also saves on precious vertex attributes. Before, we were using up to 6 of them. Now we need two at most.
29 lines
878 B
GLSL
29 lines
878 B
GLSL
#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]], float3 gl_TessCoord [[position_in_patch]])
|
|
{
|
|
main0_out out = {};
|
|
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;
|
|
gl_TessLevelOuter[2] = patchIn.gl_TessLevel.z;
|
|
out.gl_Position = float4((gl_TessCoord.x * gl_TessLevelInner[0]) * gl_TessLevelOuter[0], (gl_TessCoord.y * gl_TessLevelInner[0]) * gl_TessLevelOuter[1], (gl_TessCoord.z * gl_TessLevelInner[0]) * gl_TessLevelOuter[2], 1.0);
|
|
return out;
|
|
}
|
|
|