fidget-wgpu 0.5.0

WGPU backend for Fidget
Documentation
/// Global render configuration
///
/// Variables are ordered to require no padding
struct Config {
    /// Screen-to-model transform matrix, converting pixels to model space
    mat: mat4x4f,

    /// Mapping from X, Y, Z to input indices
    axes: vec3u,

    /// Next empty position in `tape_data`
    tape_data_offset: atomic<u32>,

    /// Render size, in voxels (always a multiple of 64)
    render_size: vec3u,

    /// Length of the `tape_data` array (in `u32` words)
    tape_data_capacity: u32,

    /// Image size, in voxels
    image_size: vec3u,

    /// Length of the root tape (plus tile tapes after root tile evaluation)
    ///
    /// `tape_data_offset` should be reset to this value between strata
    root_tape_len: atomic<u32>,

    /// Tape data, tightly packed per-tile (flexible array member)
    tape_data: array<TapeWord>,
}

struct TapeWord {
    op: u32,
    imm: u32,
}

/// Dynamic list of tiles, using an atomic bump allocator
struct TileListOutput {
    wg_size: array<atomic<u32>, 3>,
    count: atomic<u32>,

    /// Flexible array member
    active_tiles: array<u32>,
}

/// Read-only version of `TileListOutput`
struct TileListInput {
    wg_size: array<u32, 3>,
    count: u32,
    active_tiles: array<u32>,
}

/// Common render configuration and tape data
@group(0) @binding(0) var<storage, read_write> config: Config;

/// Map from tile to tape index
///
/// See the comment in the computation of `tile_tape_words` for details on how
/// this buffer is packed.
@group(0) @binding(1) var<storage, read_write> tile_tape: array<u32>;

/// Array of values for (non-xyz) variables
@group(1) @binding(0) var<storage, read> var_values: array<f32>;

/// For a given position and recursion level, return the offset into `tile_tape`
fn get_tape_offset_for_level(corner_pos: vec3u, level: u32) -> u32 {
    var offset = 0u; // current position in the buffer

    let size64 = config.render_size / 64;
    if level == 64u {
        // 64^3 root tile tapes are densely packed
        let corner_pos64 = corner_pos / 64;
        let index64 = corner_pos64.x
            + corner_pos64.y * size64.x
            + corner_pos64.z * size64.x * size64.y;
        return index64;
    }
    offset += size64.x * size64.y * size64.z;

    let size16 = config.render_size / 16;
    if level == 16u {
        let corner_pos16 = corner_pos / 16;
        return offset
            + corner_pos16.x
            + corner_pos16.y * size16.x
            + (corner_pos16.z % 4) * size16.x * size16.y;
    }
    offset += size16.x * size16.y * 4;

    let size4 = config.render_size / 4;
    if level == 4u {
        let corner_pos4 = corner_pos / 4;
        return offset
            + corner_pos4.x
            + corner_pos4.y * size4.x
            + (corner_pos4.z % 16) * size4.x * size4.y;
    }

    // invalid level, return the base tape
    return 0;
}