#pragma once #define __STRINGIFY(x) #x #define _STRINGIFY(x) __STRINGIFY(x) constexpr const char* utilityShaderSource = R"V0G0N( #include using namespace metal; #define GET_BUFFER_BINDING(index) (28 + index) #define GET_TEXTURE_BINDING(index) (29 + index) #define GET_SAMPLER_BINDING(index) (14 + index)\n constant float2 positions[] = {float2(-1.0, -3.0), float2(-1.0, 1.0), float2(3.0, 1.0)}; struct VertexOut { float4 position [[position]]; float2 texCoord; }; vertex VertexOut vertexFullscreen(ushort vid [[vertex_id]]) { VertexOut out; out.position = float4(positions[vid], 0.0, 1.0); out.texCoord = positions[vid] * 0.5 + 0.5; out.texCoord.y = 1.0 - out.texCoord.y; return out; } fragment float4 fragmentPresent(VertexOut in [[stage_in]], texture2d tex [[texture(0)]], sampler samplr [[sampler(0)]]) { return tex.sample(samplr, in.texCoord); } /* vertex void vertexCopyTextureToTexture(uint vid [[vertex_id]], texture2d src [[texture(GET_TEXTURE_BINDING(0))]], texture2d dst [[texture(GET_TEXTURE_BINDING(1))]], constant uint32_t& width [[buffer(GET_BUFFER_BINDING(0))]]) { uint2 coord = uint2(vid % width, vid / width); return dst.write(float4(src.read(coord).r, 0.0, 0.0, 0.0), coord); } */ struct RestrideParams { uint oldStride; uint newStride; }; // TODO: use uint32? Since that would require less iterations vertex void vertexRestrideBuffer(uint vid [[vertex_id]], device uint8_t* src [[buffer(GET_BUFFER_BINDING(0))]], device uint8_t* dst [[buffer(GET_BUFFER_BINDING(1))]], constant RestrideParams& params [[buffer(GET_BUFFER_BINDING(2))]]) { for (uint32_t i = 0; i < params.oldStride; i++) { dst[vid * params.newStride + i] = src[vid * params.oldStride + i]; } } )V0G0N";