tenflowers-dataset 0.1.1

Data pipeline and dataset utilities for TenfloweRS
Documentation
// GPU-accelerated Gaussian blur shader
// Applies Gaussian blur filter to image for smoothing effect

struct Uniforms {
    width: u32,
    height: u32,
    channels: u32,
    kernel_size: u32,
    sigma: f32,
    padding1: f32,
    padding2: f32,
    padding3: f32,
};

@group(0) @binding(0) var<storage, read> input_data: array<f32>;
@group(0) @binding(1) var<storage, read_write> output_data: array<f32>;
@group(0) @binding(2) var<uniform> uniforms: Uniforms;

fn get_input_pixel(channel: u32, y: u32, x: u32) -> f32 {
    let idx = channel * uniforms.height * uniforms.width + y * uniforms.width + x;
    if (idx >= arrayLength(&input_data)) {
        return 0.0;
    }
    return input_data[idx];
}

fn set_output_pixel(channel: u32, y: u32, x: u32, value: f32) {
    let idx = channel * uniforms.height * uniforms.width + y * uniforms.width + x;
    if (idx < arrayLength(&output_data)) {
        output_data[idx] = value;
    }
}

fn gaussian_weight(x: f32, sigma: f32) -> f32 {
    let sigma_sq = sigma * sigma;
    return exp(-(x * x) / (2.0 * sigma_sq)) / (sqrt(2.0 * 3.14159265) * sigma);
}

@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;
    let channel = global_id.z;
    
    if (x >= uniforms.width || y >= uniforms.height || channel >= uniforms.channels) {
        return;
    }
    
    let kernel_radius = uniforms.kernel_size / 2u;
    var sum = 0.0;
    var weight_sum = 0.0;
    
    // Apply Gaussian kernel
    for (var ky = 0u; ky < uniforms.kernel_size; ky = ky + 1u) {
        for (var kx = 0u; kx < uniforms.kernel_size; kx = kx + 1u) {
            let offset_x = i32(kx) - i32(kernel_radius);
            let offset_y = i32(ky) - i32(kernel_radius);
            
            let sample_x = i32(x) + offset_x;
            let sample_y = i32(y) + offset_y;
            
            // Clamp to image boundaries
            let clamped_x = max(0, min(sample_x, i32(uniforms.width) - 1));
            let clamped_y = max(0, min(sample_y, i32(uniforms.height) - 1));
            
            // Calculate Gaussian weight
            let distance = sqrt(f32(offset_x * offset_x + offset_y * offset_y));
            let weight = gaussian_weight(distance, uniforms.sigma);
            
            // Sample pixel and accumulate
            let pixel_value = get_input_pixel(channel, u32(clamped_y), u32(clamped_x));
            sum = sum + pixel_value * weight;
            weight_sum = weight_sum + weight;
        }
    }
    
    // Normalize and store result
    let result = sum / weight_sum;
    set_output_pixel(channel, y, x, result);
}