blob: f31e58cfd244833a274d798724da3af0de7a3031 [file]
/*
* Copyright 2023 Rive
*/
// This header provides GLSL-specific #defines and declarations that enable our shaders to be
// compiled on MSL and GLSL both.
// HLSL warns that it will unroll the loops through r,g,b values in advanced_blend.glsl, but
// unrolling these loops is exactly what we want.
#pragma warning(disable : 3550)
// #define native hlsl 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 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
typedef float3 packed_float3;
#define make_half float
#define make_half2 float2
#define make_half3 float3
#define make_half4 float4
typedef min16int short;
#define make_short min16int
#define make_short2 min16int2
#define make_short3 min16int3
#define make_short4 min16int4
typedef min16uint ushort;
#define make_ushort min16uint
#define make_ushort2 min16uint2
#define make_ushort3 min16uint3
#define make_ushort4 min16uint4
#define make_half3x4 float3x4
#define ATTR_BLOCK_BEGIN(NAME) \
struct NAME \
{
#define ATTR(IDX, TYPE, NAME) TYPE NAME : NAME
#define ATTR_BLOCK_END \
} \
;
#define ATTR_LOAD(T, A, N, I)
#define ATTR_UNPACK(ID, attrs, NAME, TYPE) TYPE NAME = attrs.NAME
#define UNIFORM_BLOCK_BEGIN(NAME) \
cbuffer NAME : register(b0) \
{ \
struct \
{
#define UNIFORM_BLOCK_END(NAME) \
} \
NAME; \
}
#define VARYING_BLOCK_BEGIN(NAME) \
struct NAME \
{
#define NO_PERSPECTIVE noperspective
#define @OPTIONALLY_FLAT nointerpolation
#define FLAT nointerpolation
#define VARYING(IDX, TYPE, NAME) TYPE NAME : TEXCOORD##IDX
#define VARYING_BLOCK_END(_pos) \
float4 _pos : SV_Position; \
} \
;
#define VARYING_INIT(varyings, NAME, TYPE) TYPE NAME
#define VARYING_PACK(varyings, NAME) varyings.NAME = NAME
#define VARYING_UNPACK(varyings, NAME, TYPE) TYPE NAME = varyings.NAME
#ifdef @VERTEX
#define VERTEX_TEXTURE_BLOCK_BEGIN(NAME)
#define VERTEX_TEXTURE_BLOCK_END
#endif
#ifdef @FRAGMENT
#define FRAG_TEXTURE_BLOCK_BEGIN(NAME)
#define FRAG_TEXTURE_BLOCK_END
#endif
#define TEXTURE_RGBA32UI(IDX, NAME) uniform Texture2D<uint4> NAME : register(t##IDX)
#define TEXTURE_RGBA32F(IDX, NAME) uniform Texture2D<float4> NAME : register(t##IDX)
#define TEXTURE_RGBA8(IDX, NAME) uniform Texture2D<unorm float4> NAME : register(t##IDX)
#define TEXEL_FETCH(TEXTURE_BLOCK, NAME, COORD) NAME[COORD]
#define GRADIENT_SAMPLER_DECL(IDX, NAME) SamplerState NAME : register(s##IDX);
#define TEXTURE_SAMPLE(TEXTURE_BLOCK, NAME, SAMPLER_NAME, COORD) NAME.Sample(SAMPLER_NAME, COORD)
#define PLS_INTERLOCK_BEGIN
#define PLS_INTERLOCK_END
#ifdef @DRAW_INTERIOR_TRIANGLES
// The interior triangles don't overlap, so therefore don't need rasterizer ordering.
#define $PLS_TEX2D RWTexture2D
#else
#define $PLS_TEX2D RasterizerOrderedTexture2D
#endif
#define PLS_BLOCK_BEGIN
#define PLS_DECL4F(IDX, NAME) uniform PLS_TEX2D<unorm float4> NAME : register(u##IDX)
#define PLS_DECL2F(IDX, NAME) uniform PLS_TEX2D<uint> NAME : register(u##IDX)
#define PLS_BLOCK_END
#define PLS_LOAD4F(P) P[_plsCoord]
#define PLS_LOAD2F(P) unpackHalf2x16(P[_plsCoord])
#define PLS_STORE4F(P, V) P[_plsCoord] = V
#define PLS_STORE2F(P, X, Y) P[_plsCoord] = packHalf2x16(float2(X, Y))
#define PLS_PRESERVE_VALUE(P)
#ifdef @ENABLE_BASE_INSTANCE_POLYFILL
#define BASE_INSTANCE_POLYFILL_DECL(NAME) \
cbuffer NAME##_cbuff : register(b1) \
{ \
uint NAME; \
uint NAME##_pad0; \
uint NAME##_pad1; \
uint NAME##_pad2; \
}
#endif
#define VERTEX_MAIN(NAME, \
Uniforms, \
uniforms, \
Attrs, \
attrs, \
Varyings, \
varyings, \
VertexTextures, \
textures, \
_vertexID, \
_instanceID, \
_pos) \
Varyings NAME(Attrs attrs, uint _vertexID : SV_VertexID, uint _instanceID : SV_InstanceID) \
{ \
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 NAME(Varyings varyings) : SV_Target \
{
#define EMIT_FRAG_DATA(VALUE) \
return VALUE; \
}
#define PLS_MAIN(NAME, Varyings, varyings, FragmentTextures, textures, _pos) \
[earlydepthstencil] void NAME(Varyings varyings) { \
int2 _plsCoord = int2(floor(varyings._pos.xy));
#define EMIT_PLS }
#define INLINE inline
#define uintBitsToFloat asfloat
#define intBitsToFloat asfloat
#define floatBitsToInt asint
#define floatBitsToUint asuint
#define fract frac
#define mix lerp
#define inversesqrt rsqrt
#define notEqual(A, B) ((A) != (B))
#define lessThanEqual(A, B) ((A) <= (B))
#define greaterThanEqual(A, B) ((A) >= (B))
// HLSL matrices are stored in row-major order, and therefore transposed from their counterparts
// in GLSL and Metal. We can work around this entirely by reversing the arguments to mul().
#define MUL(A, B) mul(B, A)
inline half2 unpackHalf2x16(uint u)
{
uint y = (u >> 16);
uint x = u & 0xffffu;
return make_half2(f16tof32(x), f16tof32(y));
}
inline uint packHalf2x16(float2 v)
{
uint x = f32tof16(v.x);
uint y = f32tof16(v.y);
return (y << 16) | x;
}
inline float atan(float y, float x) { return atan2(y, x); }
inline float2x2 inverse(float2x2 m)
{
float2x2 adjoint = float2x2(m[1][1], -m[0][1], -m[1][0], m[0][0]);
return adjoint * (1. / determinant(m));
}