1#pragma clang diagnostic ignored "-Wmissing-prototypes" 2 3#include <metal_stdlib> 4#include <simd/simd.h> 5 6using namespace metal; 7 8// Returns 2D texture coords corresponding to 1D texel buffer coords 9static inline __attribute__((always_inline)) 10uint2 spvTexelBufferCoord(uint tc) 11{ 12 return uint2(tc % 4096, tc / 4096); 13} 14 15template<typename T> struct spvRemoveReference { typedef T type; }; 16template<typename T> struct spvRemoveReference<thread T&> { typedef T type; }; 17template<typename T> struct spvRemoveReference<thread T&&> { typedef T type; }; 18template<typename T> inline constexpr thread T&& spvForward(thread typename spvRemoveReference<T>::type& x) 19{ 20 return static_cast<thread T&&>(x); 21} 22template<typename T> inline constexpr thread T&& spvForward(thread typename spvRemoveReference<T>::type&& x) 23{ 24 return static_cast<thread T&&>(x); 25} 26 27enum class spvSwizzle : uint 28{ 29 none = 0, 30 zero, 31 one, 32 red, 33 green, 34 blue, 35 alpha 36}; 37 38template<typename T> 39inline T spvGetSwizzle(vec<T, 4> x, T c, spvSwizzle s) 40{ 41 switch (s) 42 { 43 case spvSwizzle::none: 44 return c; 45 case spvSwizzle::zero: 46 return 0; 47 case spvSwizzle::one: 48 return 1; 49 case spvSwizzle::red: 50 return x.r; 51 case spvSwizzle::green: 52 return x.g; 53 case spvSwizzle::blue: 54 return x.b; 55 case spvSwizzle::alpha: 56 return x.a; 57 } 58} 59 60// Wrapper function that swizzles texture samples and fetches. 61template<typename T> 62inline vec<T, 4> spvTextureSwizzle(vec<T, 4> x, uint s) 63{ 64 if (!s) 65 return x; 66 return vec<T, 4>(spvGetSwizzle(x, x.r, spvSwizzle((s >> 0) & 0xFF)), spvGetSwizzle(x, x.g, spvSwizzle((s >> 8) & 0xFF)), spvGetSwizzle(x, x.b, spvSwizzle((s >> 16) & 0xFF)), spvGetSwizzle(x, x.a, spvSwizzle((s >> 24) & 0xFF))); 67} 68 69template<typename T> 70inline T spvTextureSwizzle(T x, uint s) 71{ 72 return spvTextureSwizzle(vec<T, 4>(x, 0, 0, 1), s).x; 73} 74 75// Wrapper function that swizzles texture gathers. 76template<typename T, template<typename, access = access::sample, typename = void> class Tex, typename... Ts> 77inline vec<T, 4> spvGatherSwizzle(const thread Tex<T>& t, sampler s, uint sw, component c, Ts... params) METAL_CONST_ARG(c) 78{ 79 if (sw) 80 { 81 switch (spvSwizzle((sw >> (uint(c) * 8)) & 0xFF)) 82 { 83 case spvSwizzle::none: 84 break; 85 case spvSwizzle::zero: 86 return vec<T, 4>(0, 0, 0, 0); 87 case spvSwizzle::one: 88 return vec<T, 4>(1, 1, 1, 1); 89 case spvSwizzle::red: 90 return t.gather(s, spvForward<Ts>(params)..., component::x); 91 case spvSwizzle::green: 92 return t.gather(s, spvForward<Ts>(params)..., component::y); 93 case spvSwizzle::blue: 94 return t.gather(s, spvForward<Ts>(params)..., component::z); 95 case spvSwizzle::alpha: 96 return t.gather(s, spvForward<Ts>(params)..., component::w); 97 } 98 } 99 switch (c) 100 { 101 case component::x: 102 return t.gather(s, spvForward<Ts>(params)..., component::x); 103 case component::y: 104 return t.gather(s, spvForward<Ts>(params)..., component::y); 105 case component::z: 106 return t.gather(s, spvForward<Ts>(params)..., component::z); 107 case component::w: 108 return t.gather(s, spvForward<Ts>(params)..., component::w); 109 } 110} 111 112// Wrapper function that swizzles depth texture gathers. 113template<typename T, template<typename, access = access::sample, typename = void> class Tex, typename... Ts> 114inline vec<T, 4> spvGatherCompareSwizzle(const thread Tex<T>& t, sampler s, uint sw, Ts... params) 115{ 116 if (sw) 117 { 118 switch (spvSwizzle(sw & 0xFF)) 119 { 120 case spvSwizzle::none: 121 case spvSwizzle::red: 122 break; 123 case spvSwizzle::zero: 124 case spvSwizzle::green: 125 case spvSwizzle::blue: 126 case spvSwizzle::alpha: 127 return vec<T, 4>(0, 0, 0, 0); 128 case spvSwizzle::one: 129 return vec<T, 4>(1, 1, 1, 1); 130 } 131 } 132 return t.gather_compare(s, spvForward<Ts>(params)...); 133} 134 135static inline __attribute__((always_inline)) 136float4 doSwizzle(thread texture1d<float> tex1d, thread const sampler tex1dSmplr, constant uint& tex1dSwzl, thread texture2d<float> tex2d, thread const sampler tex2dSmplr, constant uint& tex2dSwzl, thread texture3d<float> tex3d, thread const sampler tex3dSmplr, constant uint& tex3dSwzl, thread texturecube<float> texCube, thread const sampler texCubeSmplr, constant uint& texCubeSwzl, thread texture2d_array<float> tex2dArray, thread const sampler tex2dArraySmplr, constant uint& tex2dArraySwzl, thread texturecube_array<float> texCubeArray, thread const sampler texCubeArraySmplr, constant uint& texCubeArraySwzl, thread depth2d<float> depth2d, thread const sampler depth2dSmplr, constant uint& depth2dSwzl, thread depthcube<float> depthCube, thread const sampler depthCubeSmplr, constant uint& depthCubeSwzl, thread depth2d_array<float> depth2dArray, thread const sampler depth2dArraySmplr, constant uint& depth2dArraySwzl, thread depthcube_array<float> depthCubeArray, thread const sampler depthCubeArraySmplr, constant uint& depthCubeArraySwzl, thread texture2d<float> texBuffer) 137{ 138 float4 c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), tex1dSwzl); 139 c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0)), tex2dSwzl); 140 c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0)), tex3dSwzl); 141 c = spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0)), texCubeSwzl); 142 c = spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z))), tex2dArraySwzl); 143 c = spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w))), texCubeArraySwzl); 144 c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, float3(0.0, 0.0, 1.0).xy, 1.0), depth2dSwzl); 145 c.x = spvTextureSwizzle(depthCube.sample_compare(depthCubeSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz, 1.0), depthCubeSwzl); 146 c.x = spvTextureSwizzle(depth2dArray.sample_compare(depth2dArraySmplr, float4(0.0, 0.0, 0.0, 1.0).xy, uint(round(float4(0.0, 0.0, 0.0, 1.0).z)), 1.0), depth2dArraySwzl); 147 c.x = spvTextureSwizzle(depthCubeArray.sample_compare(depthCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0), depthCubeArraySwzl); 148 c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), tex1dSwzl); 149 c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z), tex2dSwzl); 150 c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w), tex3dSwzl); 151 float4 _103 = float4(0.0, 0.0, 1.0, 1.0); 152 _103.z = 1.0; 153 c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, _103.xy / _103.z, 1.0 / _103.z), depth2dSwzl); 154 c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), tex1dSwzl); 155 c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0), level(0.0)), tex2dSwzl); 156 c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0), level(0.0)), tex3dSwzl); 157 c = spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0), level(0.0)), texCubeSwzl); 158 c = spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z)), level(0.0)), tex2dArraySwzl); 159 c = spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), level(0.0)), texCubeArraySwzl); 160 c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, float3(0.0, 0.0, 1.0).xy, 1.0, level(0.0)), depth2dSwzl); 161 c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), tex1dSwzl); 162 c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z, level(0.0)), tex2dSwzl); 163 c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz / float4(0.0, 0.0, 0.0, 1.0).w, level(0.0)), tex3dSwzl); 164 float4 _131 = float4(0.0, 0.0, 1.0, 1.0); 165 _131.z = 1.0; 166 c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, _131.xy / _131.z, 1.0 / _131.z, level(0.0)), depth2dSwzl); 167 c = spvTextureSwizzle(tex1d.read(uint(0)), tex1dSwzl); 168 c = spvTextureSwizzle(tex2d.read(uint2(int2(0)), 0), tex2dSwzl); 169 c = spvTextureSwizzle(tex3d.read(uint3(int3(0)), 0), tex3dSwzl); 170 c = spvTextureSwizzle(tex2dArray.read(uint2(int3(0).xy), uint(int3(0).z), 0), tex2dArraySwzl); 171 c = texBuffer.read(spvTexelBufferCoord(0)); 172 c = spvGatherSwizzle(tex2d, tex2dSmplr, tex2dSwzl, component::x, float2(0.0), int2(0)); 173 c = spvGatherSwizzle(texCube, texCubeSmplr, texCubeSwzl, component::y, float3(0.0)); 174 c = spvGatherSwizzle(tex2dArray, tex2dArraySmplr, tex2dArraySwzl, component::z, float3(0.0).xy, uint(round(float3(0.0).z)), int2(0)); 175 c = spvGatherSwizzle(texCubeArray, texCubeArraySmplr, texCubeArraySwzl, component::w, float4(0.0).xyz, uint(round(float4(0.0).w))); 176 c = spvGatherCompareSwizzle(depth2d, depth2dSmplr, depth2dSwzl, float2(0.0), 1.0); 177 c = spvGatherCompareSwizzle(depthCube, depthCubeSmplr, depthCubeSwzl, float3(0.0), 1.0); 178 c = spvGatherCompareSwizzle(depth2dArray, depth2dArraySmplr, depth2dArraySwzl, float3(0.0).xy, uint(round(float3(0.0).z)), 1.0); 179 c = spvGatherCompareSwizzle(depthCubeArray, depthCubeArraySmplr, depthCubeArraySwzl, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0); 180 return c; 181} 182 183fragment void main0(constant uint* spvSwizzleConstants [[buffer(30)]], texture1d<float> tex1d [[texture(0)]], texture2d<float> tex2d [[texture(1)]], texture3d<float> tex3d [[texture(2)]], texturecube<float> texCube [[texture(3)]], texture2d_array<float> tex2dArray [[texture(4)]], texturecube_array<float> texCubeArray [[texture(5)]], depth2d<float> depth2d [[texture(6)]], depthcube<float> depthCube [[texture(7)]], depth2d_array<float> depth2dArray [[texture(8)]], depthcube_array<float> depthCubeArray [[texture(9)]], texture2d<float> texBuffer [[texture(10)]], sampler tex1dSmplr [[sampler(0)]], sampler tex2dSmplr [[sampler(1)]], sampler tex3dSmplr [[sampler(2)]], sampler texCubeSmplr [[sampler(3)]], sampler tex2dArraySmplr [[sampler(4)]], sampler texCubeArraySmplr [[sampler(5)]], sampler depth2dSmplr [[sampler(6)]], sampler depthCubeSmplr [[sampler(7)]], sampler depth2dArraySmplr [[sampler(8)]], sampler depthCubeArraySmplr [[sampler(9)]]) 184{ 185 constant uint& tex1dSwzl = spvSwizzleConstants[0]; 186 constant uint& tex2dSwzl = spvSwizzleConstants[1]; 187 constant uint& tex3dSwzl = spvSwizzleConstants[2]; 188 constant uint& texCubeSwzl = spvSwizzleConstants[3]; 189 constant uint& tex2dArraySwzl = spvSwizzleConstants[4]; 190 constant uint& texCubeArraySwzl = spvSwizzleConstants[5]; 191 constant uint& depth2dSwzl = spvSwizzleConstants[6]; 192 constant uint& depthCubeSwzl = spvSwizzleConstants[7]; 193 constant uint& depth2dArraySwzl = spvSwizzleConstants[8]; 194 constant uint& depthCubeArraySwzl = spvSwizzleConstants[9]; 195 float4 c = doSwizzle(tex1d, tex1dSmplr, tex1dSwzl, tex2d, tex2dSmplr, tex2dSwzl, tex3d, tex3dSmplr, tex3dSwzl, texCube, texCubeSmplr, texCubeSwzl, tex2dArray, tex2dArraySmplr, tex2dArraySwzl, texCubeArray, texCubeArraySmplr, texCubeArraySwzl, depth2d, depth2dSmplr, depth2dSwzl, depthCube, depthCubeSmplr, depthCubeSwzl, depth2dArray, depth2dArraySmplr, depth2dArraySwzl, depthCubeArray, depthCubeArraySmplr, depthCubeArraySwzl, texBuffer); 196} 197 198