#include <metal_stdlib>
using namespace metal;

struct tint_module_vars_struct {
  device uint* prevent_dce;
  texture1d<float, access::sample> arg_0;
};

struct VertexOutput {
  float4 pos;
  uint prevent_dce;
};

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

uint textureDimensions_aac604(tint_module_vars_struct tint_module_vars) {
  uint res = uint(tint_module_vars.arg_0.get_width());
  return res;
}

fragment void fragment_main(device uint* prevent_dce [[buffer(0)]], texture1d<float, access::sample> arg_0 [[texture(0)]]) {
  tint_module_vars_struct const tint_module_vars = tint_module_vars_struct{.prevent_dce=prevent_dce, .arg_0=arg_0};
  (*tint_module_vars.prevent_dce) = textureDimensions_aac604(tint_module_vars);
}

kernel void compute_main(device uint* prevent_dce [[buffer(0)]], texture1d<float, access::sample> arg_0 [[texture(0)]]) {
  tint_module_vars_struct const tint_module_vars = tint_module_vars_struct{.prevent_dce=prevent_dce, .arg_0=arg_0};
  (*tint_module_vars.prevent_dce) = textureDimensions_aac604(tint_module_vars);
}

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

vertex vertex_main_outputs vertex_main(texture1d<float, access::sample> arg_0 [[texture(0)]]) {
  tint_module_vars_struct const tint_module_vars = tint_module_vars_struct{.arg_0=arg_0};
  VertexOutput const v = vertex_main_inner(tint_module_vars);
  return vertex_main_outputs{.VertexOutput_pos=v.pos, .VertexOutput_prevent_dce=v.prevent_dce};
}
