// Apply sparse residual correction
// Adds residual pixels to final reconstruction
struct Metadata {
width: u32,
height: u32,
levels: u32,
_padding: u32,
}
struct ResidualPixel {
x: u32,
y: u32,
r: i32,
g: i32,
b: i32,
}
@group(0) @binding(0) var<storage, read> residuals: array<ResidualPixel>;
@group(0) @binding(1) var<uniform> metadata: Metadata;
@group(0) @binding(2) var<storage, read_write> output: array<u32>;
@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;
// Read current pixel
let current = output[idx];
var r = i32(current & 0xFFu);
var g = i32((current >> 8u) & 0xFFu);
var b = i32((current >> 16u) & 0xFFu);
// Check if there's a residual for this pixel
let residual_count = arrayLength(&residuals);
for (var i = 0u; i < residual_count; i++) {
let res = residuals[i];
if (res.x == x && res.y == y) {
// Apply residual correction
r += res.r;
g += res.g;
b += res.b;
// Clamp to [0, 255]
r = clamp(r, 0, 255);
g = clamp(g, 0, 255);
b = clamp(b, 0, 255);
break;
}
}
// Pack result
output[idx] = u32(r) | (u32(g) << 8u) | (u32(b) << 16u) | (255u << 24u);
}