#pragma clang diagnostic ignored "-Wmissing-prototypes" #include #include using namespace metal; // Returns 2D texture coords corresponding to 1D texel buffer coords uint2 spvTexelBufferCoord(uint tc) { return uint2(tc % 4096, tc / 4096); } enum class spvSwizzle : uint { none = 0, zero, one, red, green, blue, alpha }; template struct spvRemoveReference { typedef T type; }; template struct spvRemoveReference { typedef T type; }; template struct spvRemoveReference { typedef T type; }; template inline constexpr thread T&& spvForward(thread typename spvRemoveReference::type& x) { return static_cast(x); } template inline constexpr thread T&& spvForward(thread typename spvRemoveReference::type&& x) { return static_cast(x); } template inline T spvGetSwizzle(vec x, spvSwizzle s) { switch (s) { case spvSwizzle::zero: return 0; case spvSwizzle::one: return 1; case spvSwizzle::red: return x.r; case spvSwizzle::green: return x.g; case spvSwizzle::blue: return x.b; case spvSwizzle::alpha: return x.a; default: break; } return 0; } // Wrapper function that swizzles texture samples and fetches. template inline vec spvTextureSwizzle(vec x, uint s) { if (!s) return x; return vec(spvGetSwizzle(x, spvSwizzle((s >> 0) & 0xFF)), spvGetSwizzle(x, spvSwizzle((s >> 8) & 0xFF)), spvGetSwizzle(x, spvSwizzle((s >> 16) & 0xFF)), spvGetSwizzle(x, spvSwizzle((s >> 24) & 0xFF))); } template inline T spvTextureSwizzle(T x, uint s) { return spvTextureSwizzle(vec(x, 0, 0, 1), s).x; } // Wrapper function that swizzles texture gathers. template inline vec spvGatherSwizzle(sampler s, thread Tex& t, Ts... params, component c, uint sw) METAL_CONST_ARG(c) { if (sw) { switch (spvSwizzle((sw >> (uint(c) * 8)) & 0xFF)) { case spvSwizzle::none: break; case spvSwizzle::zero: return vec(0, 0, 0, 0); case spvSwizzle::one: return vec(1, 1, 1, 1); case spvSwizzle::red: return t.gather(s, spvForward(params)..., component::x); case spvSwizzle::green: return t.gather(s, spvForward(params)..., component::y); case spvSwizzle::blue: return t.gather(s, spvForward(params)..., component::z); case spvSwizzle::alpha: return t.gather(s, spvForward(params)..., component::w); } } switch (c) { case component::x: return t.gather(s, spvForward(params)..., component::x); case component::y: return t.gather(s, spvForward(params)..., component::y); case component::z: return t.gather(s, spvForward(params)..., component::z); case component::w: return t.gather(s, spvForward(params)..., component::w); } } fragment void main0(constant uint32_t* spvSwizzleConst [[buffer(0)]], texture1d tex1d [[texture(0)]], texture2d tex2d [[texture(1)]], texture3d tex3d [[texture(2)]], texturecube texCube [[texture(3)]], texture2d_array tex2dArray [[texture(4)]], texturecube_array texCubeArray [[texture(5)]], texture2d texBuffer [[texture(6)]], depth2d depth2d [[texture(7)]], depthcube depthCube [[texture(8)]], depth2d_array depth2dArray [[texture(9)]], depthcube_array depthCubeArray [[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(7)]], sampler depthCubeSmplr [[sampler(8)]], sampler depth2dArraySmplr [[sampler(9)]], sampler depthCubeArraySmplr [[sampler(10)]]) { float4 c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), spvSwizzleConst[0]); c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0)), spvSwizzleConst[1]); c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0)), spvSwizzleConst[2]); c = spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0)), spvSwizzleConst[3]); c = spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z))), spvSwizzleConst[4]); c = spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w))), spvSwizzleConst[5]); c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, float3(0.0, 0.0, 1.0).xy, float3(0.0, 0.0, 1.0).z), spvSwizzleConst[7]); c.x = spvTextureSwizzle(depthCube.sample_compare(depthCubeSmplr, float4(0.0, 0.0, 0.0, 1.0).xyz, float4(0.0, 0.0, 0.0, 1.0).w), spvSwizzleConst[8]); 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)), float4(0.0, 0.0, 0.0, 1.0).w), spvSwizzleConst[9]); c.x = spvTextureSwizzle(depthCubeArray.sample_compare(depthCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0), spvSwizzleConst[10]); c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), spvSwizzleConst[0]); c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z), spvSwizzleConst[1]); 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), spvSwizzleConst[2]); float4 _100 = float4(0.0, 0.0, 1.0, 1.0); _100.z = float4(0.0, 0.0, 1.0, 1.0).w; c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, _100.xy / _100.z, float4(0.0, 0.0, 1.0, 1.0).z), spvSwizzleConst[7]); c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, 0.0), spvSwizzleConst[0]); c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float2(0.0), level(0.0)), spvSwizzleConst[1]); c = spvTextureSwizzle(tex3d.sample(tex3dSmplr, float3(0.0), level(0.0)), spvSwizzleConst[2]); c = spvTextureSwizzle(texCube.sample(texCubeSmplr, float3(0.0), level(0.0)), spvSwizzleConst[3]); c = spvTextureSwizzle(tex2dArray.sample(tex2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z)), level(0.0)), spvSwizzleConst[4]); c = spvTextureSwizzle(texCubeArray.sample(texCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), level(0.0)), spvSwizzleConst[5]); c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, float3(0.0, 0.0, 1.0).xy, float3(0.0, 0.0, 1.0).z, level(0.0)), spvSwizzleConst[7]); c = spvTextureSwizzle(tex1d.sample(tex1dSmplr, float2(0.0, 1.0).x / float2(0.0, 1.0).y), spvSwizzleConst[0]); c = spvTextureSwizzle(tex2d.sample(tex2dSmplr, float3(0.0, 0.0, 1.0).xy / float3(0.0, 0.0, 1.0).z, level(0.0)), spvSwizzleConst[1]); 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)), spvSwizzleConst[2]); float4 _128 = float4(0.0, 0.0, 1.0, 1.0); _128.z = float4(0.0, 0.0, 1.0, 1.0).w; c.x = spvTextureSwizzle(depth2d.sample_compare(depth2dSmplr, _128.xy / _128.z, float4(0.0, 0.0, 1.0, 1.0).z, level(0.0)), spvSwizzleConst[7]); c = spvTextureSwizzle(tex1d.read(uint(0)), spvSwizzleConst[0]); c = spvTextureSwizzle(tex2d.read(uint2(int2(0)), 0), spvSwizzleConst[1]); c = spvTextureSwizzle(tex3d.read(uint3(int3(0)), 0), spvSwizzleConst[2]); c = spvTextureSwizzle(tex2dArray.read(uint2(int3(0).xy), uint(int3(0).z), 0), spvSwizzleConst[4]); c = texBuffer.read(spvTexelBufferCoord(0)); c = spvGatherSwizzle, float2, int2>(tex2dSmplr, tex2d, float2(0.0), int2(0), component::x, spvSwizzleConst[1]); c = spvGatherSwizzle, float3>(texCubeSmplr, texCube, float3(0.0), component::y, spvSwizzleConst[3]); c = spvGatherSwizzle, float2, uint, int2>(tex2dArraySmplr, tex2dArray, float3(0.0).xy, uint(round(float3(0.0).z)), int2(0), component::z, spvSwizzleConst[4]); c = spvGatherSwizzle, float3, uint>(texCubeArraySmplr, texCubeArray, float4(0.0).xyz, uint(round(float4(0.0).w)), component::w, spvSwizzleConst[5]); c = depth2d.gather_compare(depth2dSmplr, float2(0.0), 1.0); c = depthCube.gather_compare(depthCubeSmplr, float3(0.0), 1.0); c = depth2dArray.gather_compare(depth2dArraySmplr, float3(0.0).xy, uint(round(float3(0.0).z)), 1.0); c = depthCubeArray.gather_compare(depthCubeArraySmplr, float4(0.0).xyz, uint(round(float4(0.0).w)), 1.0); }