#include using namespace metal; struct Vertex { float4 position [[ position ]]; float2 texCoords; }; struct CscParams { half3x3 matrix; half3 offsets; half2 chromaOffset; half bitnessScaleFactor; }; constexpr sampler s(coord::normalized, address::clamp_to_edge, filter::linear); vertex Vertex vs_draw(constant Vertex *vertices [[ buffer(0) ]], uint id [[ vertex_id ]]) { return vertices[id]; } fragment half4 ps_draw_biplanar(Vertex v [[ stage_in ]], constant CscParams &cscParams [[ buffer(0) ]], texture2d luminancePlane [[ texture(0) ]], texture2d chrominancePlane [[ texture(1) ]]) { float2 chromaOffset = float2(cscParams.chromaOffset) / float2(luminancePlane.get_width(), luminancePlane.get_height()); half3 yuv = half3(luminancePlane.sample(s, v.texCoords).r, chrominancePlane.sample(s, v.texCoords + chromaOffset).rg); yuv *= cscParams.bitnessScaleFactor; yuv -= cscParams.offsets; return half4(yuv * cscParams.matrix, 1.0h); } fragment half4 ps_draw_triplanar(Vertex v [[ stage_in ]], constant CscParams &cscParams [[ buffer(0) ]], texture2d luminancePlane [[ texture(0) ]], texture2d chrominancePlaneU [[ texture(1) ]], texture2d chrominancePlaneV [[ texture(2) ]]) { float2 chromaOffset = float2(cscParams.chromaOffset) / float2(luminancePlane.get_width(), luminancePlane.get_height()); half3 yuv = half3(luminancePlane.sample(s, v.texCoords).r, chrominancePlaneU.sample(s, v.texCoords + chromaOffset).r, chrominancePlaneV.sample(s, v.texCoords + chromaOffset).r); yuv *= cscParams.bitnessScaleFactor; yuv -= cscParams.offsets; return half4(yuv * cscParams.matrix, 1.0h); } fragment half4 ps_draw_rgb(Vertex v [[ stage_in ]], texture2d rgbTexture [[ texture(0) ]]) { return rgbTexture.sample(s, v.texCoords); }