blob: 05692331309e41e83817e06e5a2362989163c035 [file]
/*
* Copyright 2023 Rive
*/
// This header provides Metal-specific #defines and declarations that enable our shaders to be
// compiled on MSL and GLSL both.
#define METAL
// #define native metal types if their names are being rewritten.
#define _ARE_TOKEN_NAMES_PRESERVED
#ifndef $_ARE_TOKEN_NAMES_PRESERVED
#define half $half
#define half2 $half2
#define half3 $half3
#define half4 $half4
#define short $short
#define short2 $short2
#define short3 $short3
#define short4 $short4
#define ushort $ushort
#define ushort2 $ushort2
#define ushort3 $ushort3
#define ushort4 $ushort4
#define float2 $float2
#define float3 $float3
#define packed_float3 $packed_float3
#define float4 $float4
#define bool2 $bool2
#define bool3 $bool3
#define bool4 $bool4
#define uint2 $uint2
#define uint3 $uint3
#define uint4 $uint4
#define int2 $int2
#define int3 $int3
#define int4 $int4
#define float4x2 $float4x2
#define ushort $ushort
#define float2x2 $float2x2
#define half3x4 $half3x4
#endif
#define make_half4 half4
#define make_half3 half3
#define make_half2 half2
#define make_half half
#define make_ushort ushort
#define INLINE $inline
#define notEqual(A, B) ((A) != (B))
#define lessThanEqual(A, B) ((A) <= (B))
#define greaterThanEqual(A, B) ((A) >= (B))
#define MUL(A, B) ((A) * (B))
#define atan $atan2
#define inversesqrt $rsqrt
#define UNIFORM_BLOCK_BEGIN(N) \
struct N \
{
#define UNIFORM_BLOCK_END(N) \
} \
;
#define ATTR_BLOCK_BEGIN(N) \
struct N \
{
#define ATTR(IDX, TYPE, NAME) TYPE NAME
#define ATTR_BLOCK_END \
} \
;
#define ATTR_UNPACK(ID, attrs, NAME, TYPE) TYPE NAME = attrs[ID].NAME
#define VARYING_BLOCK_BEGIN(N) \
struct N \
{
#define VARYING(IDX, TYPE, NAME) TYPE NAME
#define FLAT [[flat]]
#define NO_PERSPECTIVE [[$center_no_perspective]]
// No-persective interpolation appears to break the guarantee that a varying == "x" when all
// barycentric values also == "x". Using default (perspective-correct) interpolation is also faster
// than flat on M1.
#define @OPTIONALLY_FLAT
#define VARYING_BLOCK_END(_pos) \
float4 _pos [[$position]]; \
} \
;
#define VARYING_INIT(varyings, NAME, TYPE) $thread TYPE& NAME = varyings.NAME
#define VARYING_PACK(varyings, NAME)
#define VARYING_UNPACK(varyings, NAME, TYPE) TYPE NAME = varyings.NAME
#define VERTEX_TEXTURE_BLOCK_BEGIN(N) \
struct N \
{
#define VERTEX_TEXTURE_BLOCK_END \
} \
;
#define FRAG_TEXTURE_BLOCK_BEGIN(N) \
struct N \
{
#define FRAG_TEXTURE_BLOCK_END \
} \
;
#define TEXTURE_RGBA32UI(IDX, NAME) [[$texture(IDX)]] $texture2d<uint> NAME
#define TEXTURE_RGBA32F(IDX, NAME) [[$texture(IDX)]] $texture2d<float> NAME
#define TEXTURE_RGBA8(IDX, NAME) [[$texture(IDX)]] $texture2d<half> NAME
#define TEXEL_FETCH(TEXTURE_BLOCK, NAME, COORD) TEXTURE_BLOCK.NAME.$read(uint2(COORD))
#define GRADIENT_SAMPLER_DECL(IDX, NAME)
#define TEXTURE_SAMPLE(TEXTURE_BLOCK, NAME, SAMPLER_NAME, COORD) \
TEXTURE_BLOCK.NAME.$sample($sampler($mag_filter::$linear, $min_filter::$linear), COORD)
#define PLS_BLOCK_BEGIN \
struct PLS \
{
#define PLS_DECL4F(IDX, NAME) [[$color(IDX)]] half4 NAME
#define PLS_DECL2F(IDX, NAME) [[$color(IDX)]] half2 NAME
#define PLS_BLOCK_END \
} \
;
#define PLS_LOAD4F(P) _inpls.P
#define PLS_LOAD2F(P) _inpls.P
#define PLS_STORE4F(P, V) _pls.P = (V)
#define PLS_STORE2F(P, X, Y) _pls.P = half2(X, Y)
#define PLS_PRESERVE_VALUE(P) _pls.P = _inpls.P
#define PLS_INTERLOCK_BEGIN
#define PLS_INTERLOCK_END
#define VERTEX_MAIN(NAME, \
Uniforms, \
uniforms, \
Attrs, \
attrs, \
Varyings, \
varyings, \
VertexTextures, \
textures, \
_vertexID, \
_instanceID, \
_pos) \
$__attribute__(($visibility("default"))) Varyings $vertex NAME( \
uint _vertexID [[$vertex_id]], \
uint _instanceID [[$instance_id]], \
$constant Uniforms& uniforms [[$buffer(0)]], \
$constant Attrs* attrs [[$buffer(1)]], \
VertexTextures textures) \
{ \
Varyings varyings; \
float4 _pos;
#define EMIT_VERTEX(varyings, _pos) \
} \
varyings._pos = _pos; \
return varyings;
#define FRAG_DATA_MAIN(DATA_TYPE, NAME, Varyings, varyings) \
DATA_TYPE $__attribute__(($visibility("default"))) $fragment NAME(Varyings varyings \
[[$stage_in]]) \
{
#define EMIT_FRAG_DATA(VALUE) \
return VALUE; \
}
#define PLS_MAIN(NAME, Varyings, varyings, FragmentTextures, textures, _pos) \
$__attribute__(($visibility("default"))) PLS $fragment NAME(PLS _inpls, \
Varyings varyings [[$stage_in]], \
FragmentTextures textures) \
{ \
PLS _pls;
#define EMIT_PLS \
} \
return _pls;
$using $namespace $metal;
$template<int N> INLINE $vec<uint, N> floatBitsToUint($vec<float, N> x)
{
return $as_type<$vec<uint, N>>(x);
}
$template<int N> INLINE $vec<int, N> floatBitsToInt($vec<float, N> x)
{
return $as_type<$vec<int, N>>(x);
}
INLINE uint floatBitsToUint(float x) { return $as_type<uint>(x); }
INLINE int floatBitsToInt(float x) { return $as_type<int>(x); }
$template<int N> INLINE $vec<float, N> uintBitsToFloat($vec<uint, N> x)
{
return $as_type<$vec<float, N>>(x);
}
INLINE float uintBitsToFloat(uint x) { return $as_type<float>(x); }
INLINE half2 unpackHalf2x16(uint x) { return $as_type<half2>(x); }
INLINE uint packHalf2x16(half2 x) { return $as_type<uint>(x); }
INLINE float2x2 inverse(float2x2 m)
{
float2x2 m_ = float2x2(m[1][1], -m[0][1], -m[1][0], m[0][0]);
float det = (m_[0][0] * m[0][0]) + (m_[0][1] * m[1][0]);
return m_ * (1 / det);
}
INLINE half3 mix(half3 a, half3 b, bool3 c)
{
half3 result;
for (int i = 0; i < 3; ++i)
result[i] = c[i] ? b[i] : a[i];
return result;
}
INLINE half3x4 make_half3x4(half3 a, half b, half3 c, half d, half3 e, half f)
{
return half3x4(a.x, a.y, a.z, b, c.x, c.y, c.z, d, e.x, e.y, e.z, f);
}