Crate crabslab

source ·
Expand description

Creating and crafting a tasty slab of memory.

slabcraft for crabs

§What

crabslab is a slab implementation focused on marshalling data between CPUs and GPUs.

See the example below.

§But Why?

It’s hard to get data onto GPUs in the form you expect.

To marshall your data correctly you must know about the alignment and sizes of the underlying representation of your data. This will often surprise you!

Working with a slab on the other hand, only requires that your types can be written into an array and read from an array.

§Opinion

Working with shaders is much easier using a slab.

Shader code can be written in Rust with rust-gpu, which will enable you to use this crate on both CPU and GPU code.

§rust-gpu

This crate was made to work with rust-gpu. Specifically, with this crate it is possible to pack your types into a buffer on the CPU and then read your types from the slab on the GPU (in Rust).

§Other no-std platforms

Even though this crate was written with rust-gpu in mind, it should work in other no-std contexts.

§And How

The idea is simple - crabslab helps you manage a heap of contiguous u32s (roughly in the form of Vec<u32>). Types implement the trait SlabItem which writes the type into an index of the slab as contiguous u32s and also reads them out symmetrically.

crabslab includes:

  • a few traits:
    • Slab
    • GrowableSlab
    • SlabItem
  • a derive macro for SlabItem for your types
  • a few new structs for working with slabs
    • Id
    • Array
    • Offset
  • a helper struct CpuSlab which wraps anything implementing GrowableSlab
  • a feature-gated helper for using slabs with wgpu - WgpuBuffer
  • feature for deriving SlabItem for glam types

§Example

use crabslab::{CpuSlab, Slab, GrowableSlab, SlabItem, Id};
use glam::{Vec3, Vec4};

#[derive(Debug, Default, SlabItem, PartialEq)]
struct Light {
    direction: Vec3,
    color: Vec4,
    inner_cutoff: f32,
    outer_cutoff: f32,
    is_on: bool
}

impl Light {
    fn standard() -> Self {
        Light {
            direction: Vec3::NEG_Z, // pointing down
            color: Vec4::ONE, // white
            inner_cutoff: 0.5,
            outer_cutoff: 2.6,
            is_on: true
        }
    }
}

fn cpu_code() -> (Id<Light>, Vec<u32>) {
    // Create a new slab on the CPU-side.
    // NOTE: For simplicity here we use `Vec<u32>` but if we were using `wgpu`
    // we could use `crabslab::WgpuBuffer` instead of `Vec<u32>`.
    // The API is the same.
    let light = Light::standard();
    let mut slab = CpuSlab::new(vec![]);
    let id = slab.append(&light);
    (id, slab.into_inner())
}

fn shader_code(light_id: Id<Light>, slab: &[u32]) {
    let light = slab.read(light_id);
    assert_eq!(Light::standard(), light);
}

let (light_id, slab) = cpu_code();
// marshalling your data depends on which GPU library you are using...
shader_code(light_id, &slab);

Modules§

Structs§

  • A pointer to contiguous T elements in a slab.
  • Iterator over Ids in an Array.
  • A wrapper around a GrowableSlab that provides convenience methods for working with CPU-side slabs.
  • An identifier that can be used to read or write a type from/into the slab.
  • The slab offset of field F within a type T.
  • A slab buffer used by the stage to store heterogeneous objects.

Enums§

Constants§

  • u32 value of an Id that does not point to any item.

Traits§

  • Trait for slabs of u32s that can store many types, and can grow to fit.
  • Trait for slabs of u32s that can store many types.
  • Determines the “size” of a type when stored in a slab of &[u32], and how to read/write it from/to the slab.

Functions§

  • Proxy for u32::saturating_sub.
  • Print the slab’s index, binary representation, integer value, and float value.

Derive Macros§