override CHUNK_POW: u32 = 10;
const LEN: u32 = REPLACE_LENu;
const ILEN: i32 = i32(LEN);
const LEN2: u32 = LEN * 2;
override WGX: u32 = 8;
override WGY: u32 = 8;

struct View {
    reset: u32,
    level: i32,
    dims: vec2<u32>,
    stretch: vec2<f32>,
    scale: FixedDec,
    corner_x: FixedDec,
    corner_y: FixedDec,
}

@group(0) @binding(0)
var<storage> view: View;
@group(0) @binding(1)
var<storage, read_write> work: array<u32>;
@group(0) @binding(2)
var output: texture_storage_2d<rgba8unorm, write>;

@compute @workgroup_size(WGX, WGY, 1)
fn main(
    @builtin(global_invocation_id) id: vec3<u32>
) {
    if id.x > view.dims.x - 1 || id.y > view.dims.y - 1 {
        return;
    }
    let varwidth = LEN + 2;
    let workwidth = varwidth * 2 + 1;
    let worki = (id.x * view.dims.y + id.y) * workwidth;
    let xidx = worki + 1;
    let yidx = xidx + varwidth;

    let fdims = vec2<f32>(view.dims);
    let fpos = (vec2<f32>(id.xy) / fdims - 0.5) * view.stretch;
    let cx = add(mul(from_f32(fpos.x), view.scale), view.corner_x);
    let cy = add(mul(from_f32(fpos.y), view.scale), view.corner_y);
    var x: FixedDec;
    var y: FixedDec;
    var i = work[worki];
    if bool(view.reset) {
        x = zero();
        y = zero();
        i = 0;
    } else {
        x = FixedDec(work[xidx + 0], bitcast<i32>(work[xidx + 1]), array<u32, LEN>());
        y = FixedDec(work[yidx + 0], bitcast<i32>(work[yidx + 1]), array<u32, LEN>());
        for (var j = 0u; j < LEN; j += 1u) {
            x.parts[j] = work[xidx + 2 + j];
            y.parts[j] = work[yidx + 2 + j];
        }
    }
    let max = i + 1;
    let thresh = from_f32(2.0 * 2.0);
    loop {
        // burning ship
        // x.sign = 0;
        // y.sign = 0;
        let x2 = mul(x, x);
        let y2 = mul(y, y);
        if gt(add(x2, y2), thresh) || i >= max {
            break;
        }
        let xy = mul(x, y);
        y = add(add(xy, xy), cy);
        x = add(sub(x2, y2), cx);
        i += 1u;
    }
    work[worki] = i;
    work[xidx + 0] = x.sign; work[xidx + 1] = bitcast<u32>(x.dec);
    work[yidx + 0] = y.sign; work[yidx + 1] = bitcast<u32>(y.dec);
    for (var j = 0u; j < LEN; j += 1u) {
        work[xidx + 2 + j] = x.parts[j];
        work[yidx + 2 + j] = y.parts[j];
    }
    var color = vec3<f32>(0.0, 0.0, 0.0);
    if i != max {
        let pi = 3.1415;
        let hue = f32(i) / 30.0;
        color.r = cos(hue);
        color.g = cos(hue - 2.0 * pi / 3.0);
        color.b = cos(hue - 4.0 * pi / 3.0);
    }
    textureStore(output, id.xy, vec4(color, 1.0));
}

