tx2-iff 0.1.0

PPF-IFF (Involuted Fractal Format) - Image codec using Physics-Prime Factorization, 360-prime quantization, and symplectic warping
Documentation
// Apply warp field with bicubic sampling
// This shader is currently a passthrough since warping is done in warp_field.wgsl

struct Metadata {
    width: u32,
    height: u32,
    levels: u32,
    _padding: u32,
}

@group(0) @binding(0) var<storage, read> warp_data: array<u32>;
@group(0) @binding(1) var<uniform> metadata: Metadata;
@group(0) @binding(2) var<storage, read_write> output: array<u32>;

// Bicubic kernel weight
fn cubic_weight(x: f32) -> f32 {
    let abs_x = abs(x);
    if (abs_x <= 1.0) {
        return 1.5 * abs_x * abs_x * abs_x - 2.5 * abs_x * abs_x + 1.0;
    } else if (abs_x <= 2.0) {
        return -0.5 * abs_x * abs_x * abs_x + 2.5 * abs_x * abs_x - 4.0 * abs_x + 2.0;
    }
    return 0.0;
}

// Bicubic sampling
fn sample_bicubic(img: ptr<storage, array<u32>, read>, x: f32, y: f32, w: u32, h: u32) -> vec3<f32> {
    let x0 = floor(x);
    let y0 = floor(y);
    let dx = x - x0;
    let dy = y - y0;

    var color = vec3<f32>(0.0);
    var weight_sum = 0.0;

    // 4x4 bicubic kernel
    for (var j = -1; j <= 2; j++) {
        for (var i = -1; i <= 2; i++) {
            let sx = u32(clamp(x0 + f32(i), 0.0, f32(w - 1u)));
            let sy = u32(clamp(y0 + f32(j), 0.0, f32(h - 1u)));

            let pixel = img[sy * w + sx];

            let r = f32(pixel & 0xFFu);
            let g = f32((pixel >> 8u) & 0xFFu);
            let b = f32((pixel >> 16u) & 0xFFu);

            let wx = cubic_weight(dx - f32(i));
            let wy = cubic_weight(dy - f32(j));
            let weight = wx * wy;

            color += vec3<f32>(r, g, b) * weight;
            weight_sum += weight;
        }
    }

    if (weight_sum > 0.0) {
        color /= weight_sum;
    }

    return color;
}

@compute @workgroup_size(8, 8, 1)
fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
    let x = global_id.x;
    let y = global_id.y;

    if (x >= metadata.width || y >= metadata.height) {
        return;
    }

    let idx = y * metadata.width + x;

    // Passthrough for now (warping already done in previous pass)
    output[idx] = output[idx];
}