Skip to main content

Crate const_shader_layout

Crate const_shader_layout 

Source
Expand description

§Compile-time checks to ensure structs conform to WGSL’s memory layout rules

Build License Cargo Documentation

The core of this crate is the ShaderLayout, ShaderLayoutCompat derive proc-macros (or declarative macros if derive feature is disabled), and the ShaderLayout, ShaderLayoutCompat traits.

ShaderLayout corresponds to https://www.w3.org/TR/WGSL/#alignment-and-size.

ShaderLayoutCompat is a stricter subset that enforces the uniform address space layout constraints (without the uniform_buffer_standard_layout extension). Every type implementing ShaderLayoutCompat also implements ShaderLayout.

ShaderLayoutArrayElement and ShaderLayoutCompatArrayElement mark whether the type can be used in array<T, N>/array<T>, as some types such as [glam::Vec3; N] isn’t equal to array<vec3f, N> due to different alignment. shader_layout! automatically implements ShaderLayoutArrayElement. ShaderLayoutCompat, however, needs impl_shader_layout_compat_array_element! to manually implement ShaderLayoutCompatArrayElement.

Both macros validate every field’s alignment and the overall struct size at compile time. If a constraint is violated, compilation fails with a clear error message:

shader_layout! {
    pub struct OffsetUnaligned {
        a1: f32,        // align 4
        a4: glam::Vec3, // align 16 — offset 4 is not a multiple of 16!
    }
}
// error[E0080]: evaluation panicked: Failed to implement `ShaderLayout`: field `OffsetUnaligned::a4` (`glam::Vec3`) is not properly aligned. The offset is 4 but required align is 16
use const_shader_layout::{shader_layout, shader_layout_compat, ShaderLayout, ShaderLayoutCompat};
use glam::{Vec2, Vec3, Vec4};

// Use declarative macro
shader_layout! {
    pub struct MyStorage {
        a1: f32,
        a2: [f32; 2],
        a3: [f32; 1],
        a4: Vec3,
        a5: f32,
        a6: Vec3,
        p1: f32, // Padding needed otherwise struct size (44) won't match shader size (48).
    }
}

// Or use proc-macro
#[derive(Clone, Copy, ShaderLayout)]
#[repr(C)]
pub struct Nested {
    a1: [Vec4; 2],
    a2: Vec3,
    a3: f32
}


#[derive(Clone, Copy, ShaderLayout)]
#[repr(C)]
pub struct MyUniform {
    a1: Nested,
    a2: Vec3,
    // Padding is implicit, because struct size is 64 aligned to 16 in `repr(C)` which matches shader size (64).
}

See https://github.com/beicause/const_shader_layout/tree/master/tests for what this supports and checks.

§Features

FeatureDescription
derive(default)Enable ShaderLayout, ShaderLayoutCompat derive macros
glam (default)Implements ShaderLayout/ShaderLayoutCompat for glam types
halfImplements ShaderLayout/ShaderLayoutCompat for half::f16 and array of it
std (default), libm, nostd-libmRe-export glam’s corresponding features

This crate focuses on layout validation only. For safe cast/transmute utilities, pair it with other crates like bytemuck.

Macros§

impl_shader_layout_compat_array_element
Implements ShaderLayoutCompat (also implements ShaderLayout) for [T; N] for types implemented ShaderLayoutCompat.
impl_shader_layout_compat_struct
impl_shader_layout_struct
shader_layout
Checks if all the struct’s fields conform to shader layout then implements ShaderLayout for this struct, or fails at compile-time.
shader_layout_compat
Checks if all the struct’s fields conform to shader layout then implements ShaderLayoutCompat for this struct, or fails at compile-time.

Traits§

ShaderLayout
Marks the type’s alignment requirement in shader.
ShaderLayoutArrayElement
Marks the type can be used as array element.
ShaderLayoutCompat
Marks the type’s uniform-compatible alignment requirement in shader, i.e. with uniform address layout constraints.
ShaderLayoutCompatArrayElement
Marks the type can be used as array element with uniform address layout constraints.

Derive Macros§

ShaderLayoutderive
ShaderLayoutCompatderive
ShaderLayoutCompatArrayElementderive