#include <metal_stdlib>
using namespace metal;

struct tint_GammaTransferParams {
  float G;
  float A;
  float B;
  float C;
  float D;
  float E;
  float F;
  uint padding;
};

struct tint_ExternalTextureParams {
  uint numPlanes;
  uint doYuvToRgbConversionOnly;
  float3x4 yuvToRgbConversionMatrix;
  tint_GammaTransferParams gammaDecodeParams;
  tint_GammaTransferParams gammaEncodeParams;
  float3x3 gamutConversionMatrix;
  float3x2 sampleTransform;
  float3x2 loadTransform;
  float2 samplePlane0RectMin;
  float2 samplePlane0RectMax;
  float2 samplePlane1RectMin;
  float2 samplePlane1RectMax;
  uint2 visibleSize;
  float2 plane1CoordFactor;
};

struct tint_module_vars_struct {
  device float4* prevent_dce;
  texture2d<float, access::sample> arg_0_plane0;
  texture2d<float, access::sample> arg_0_plane1;
  const constant tint_ExternalTextureParams* arg_0_params;
  sampler arg_1;
};

struct VertexOutput {
  float4 pos;
  float4 prevent_dce;
};

struct vertex_main_outputs {
  float4 VertexOutput_pos [[position]];
  float4 VertexOutput_prevent_dce [[user(locn0)]] [[flat]];
};

float3 tint_GammaCorrection(float3 v, tint_GammaTransferParams params) {
  float3 const v_1 = float3(params.G);
  float3 const v_2 = float3(params.D);
  float3 const v_3 = abs(v);
  float3 const v_4 = sign(v);
  return select((v_4 * (powr(((params.A * v_3) + params.B), v_1) + params.E)), (v_4 * ((params.C * v_3) + params.F)), (v_3 < v_2));
}

float4 tint_TextureSampleExternal(texture2d<float, access::sample> plane_0, texture2d<float, access::sample> plane_1, tint_ExternalTextureParams params, sampler sampler, float2 coords) {
  float2 const v_5 = (params.sampleTransform * float3(coords, 1.0f));
  float2 const v_6 = clamp(v_5, params.samplePlane0RectMin, params.samplePlane0RectMax);
  float3 v_7 = 0.0f;
  float v_8 = 0.0f;
  if ((params.numPlanes == 1u)) {
    float4 const v_9 = plane_0.sample(sampler, v_6, level(0.0f));
    v_7 = v_9.xyz;
    v_8 = v_9[3u];
  } else {
    float const v_10 = plane_0.sample(sampler, v_6, level(0.0f))[0u];
    float2 const v_11 = clamp(v_5, params.samplePlane1RectMin, params.samplePlane1RectMax);
    v_7 = (float4(v_10, plane_1.sample(sampler, v_11, level(0.0f)).xy, 1.0f) * params.yuvToRgbConversionMatrix);
    v_8 = 1.0f;
  }
  float3 const v_12 = v_7;
  float3 v_13 = 0.0f;
  if ((params.doYuvToRgbConversionOnly == 0u)) {
    v_13 = tint_GammaCorrection((params.gamutConversionMatrix * tint_GammaCorrection(v_12, params.gammaDecodeParams)), params.gammaEncodeParams);
  } else {
    v_13 = v_12;
  }
  return float4(v_13, v_8);
}

float4 textureSampleBaseClampToEdge_7c04e6(tint_module_vars_struct tint_module_vars) {
  float4 res = tint_TextureSampleExternal(tint_module_vars.arg_0_plane0, tint_module_vars.arg_0_plane1, (*tint_module_vars.arg_0_params), tint_module_vars.arg_1, float2(1.0f));
  return res;
}

fragment void fragment_main(device float4* prevent_dce [[buffer(0)]], texture2d<float, access::sample> arg_0_plane0 [[texture(0)]], texture2d<float, access::sample> arg_0_plane1 [[texture(1)]], const constant tint_ExternalTextureParams* arg_0_params [[buffer(2)]], sampler arg_1 [[sampler(0)]]) {
  tint_module_vars_struct const tint_module_vars = tint_module_vars_struct{.prevent_dce=prevent_dce, .arg_0_plane0=arg_0_plane0, .arg_0_plane1=arg_0_plane1, .arg_0_params=arg_0_params, .arg_1=arg_1};
  (*tint_module_vars.prevent_dce) = textureSampleBaseClampToEdge_7c04e6(tint_module_vars);
}

kernel void compute_main(device float4* prevent_dce [[buffer(0)]], texture2d<float, access::sample> arg_0_plane0 [[texture(0)]], texture2d<float, access::sample> arg_0_plane1 [[texture(1)]], const constant tint_ExternalTextureParams* arg_0_params [[buffer(2)]], sampler arg_1 [[sampler(0)]]) {
  tint_module_vars_struct const tint_module_vars = tint_module_vars_struct{.prevent_dce=prevent_dce, .arg_0_plane0=arg_0_plane0, .arg_0_plane1=arg_0_plane1, .arg_0_params=arg_0_params, .arg_1=arg_1};
  (*tint_module_vars.prevent_dce) = textureSampleBaseClampToEdge_7c04e6(tint_module_vars);
}

VertexOutput vertex_main_inner(tint_module_vars_struct tint_module_vars) {
  VertexOutput out = {};
  out.pos = float4(0.0f);
  out.prevent_dce = textureSampleBaseClampToEdge_7c04e6(tint_module_vars);
  return out;
}

vertex vertex_main_outputs vertex_main(texture2d<float, access::sample> arg_0_plane0 [[texture(0)]], texture2d<float, access::sample> arg_0_plane1 [[texture(1)]], const constant tint_ExternalTextureParams* arg_0_params [[buffer(2)]], sampler arg_1 [[sampler(0)]]) {
  tint_module_vars_struct const tint_module_vars = tint_module_vars_struct{.arg_0_plane0=arg_0_plane0, .arg_0_plane1=arg_0_plane1, .arg_0_params=arg_0_params, .arg_1=arg_1};
  VertexOutput const v_14 = vertex_main_inner(tint_module_vars);
  return vertex_main_outputs{.VertexOutput_pos=v_14.pos, .VertexOutput_prevent_dce=v_14.prevent_dce};
}
