#proc-macro #shader #wgsl #wgpu #graphics #compile-time #gamedev

naga-to-tokenstream

Creates a TokenStream describing parts of a Naga module

13 unstable releases (6 breaking)

0.7.1 Sep 4, 2024
0.6.0 Jun 22, 2024
0.5.0 Feb 28, 2024
0.4.2 Nov 11, 2023

#267 in Game dev

Download history 156/week @ 2024-07-22 104/week @ 2024-07-29 11/week @ 2024-08-05 122/week @ 2024-08-12 104/week @ 2024-08-19 83/week @ 2024-08-26 223/week @ 2024-09-02 250/week @ 2024-09-09 128/week @ 2024-09-16 251/week @ 2024-09-23 35/week @ 2024-09-30 70/week @ 2024-10-07 59/week @ 2024-10-14 94/week @ 2024-10-21 23/week @ 2024-10-28 17/week @ 2024-11-04

194 downloads per month
Used in 4 crates (2 directly)

MIT license

37KB
657 lines

Naga to TokenStream

crates.io docs.rs crates.io

This library takes a Naga module and produces a proc_macro::TokenStream giving information about the module. It is intended for use in other libraries which process a shader at compile time, for example in a proc macro or build script, to expose a large collection of useful information to the Rust compiler (and hence programmer) about items in the module.

Generated Items

This module generates the following items:

  • A Rust constant for each WGSL const with a type representable in Rust.
    • If glam is enabled, then Glam types will be used to represent vectors and matrices.
  • A Rust struct for each WGSL struct with types representable in Rust.
    • If encase is enabled, these structs will derive from encase::ShaderType.
  • A Rust module for each entry point, containing constants giving their name, workgroup size, etc.
  • A Rust module for each bind group, containing constants giving their name and bindings, and a type redefinition of their generated Rust type if applicable.
    • If naga is enabled, these modules will also contain naga::AddressSpace information.

As an example, take the following shader, written in wgsl:

const ELEMENTS_LENGTH: u32 = 128u;

struct Foo {
    a: i32,
    b: vec4<u32>,
    c: vec4<u32>,
}
struct Bar {
    size: u32,
    elements: array<vec2<bool>, ELEMENTS_LENGTH>,
    foos: array<Foo>
}

@group(0) @binding(0) var<storage> bar: Bar;

@compute
@workgroup_size(256,1,1)
fn main() {
    ...
}

Then this crate would generate something like the following:


/// Equivalent Rust definitions of the constants defined in this module
pub mod constants {
    pub mod ELEMENTS_LENGTH {
        pub const NAME: &'static str = "ELEMENTS_LENGTH";
        pub const VALUE: u32 = 128;
    }
}
/// Equivalent Rust definitions of the types defined in this module
pub mod types {
    // `encase::ShaderType` is only derived if the `encase` feature is enabled.
    #[derive(Debug, PartialEq, Clone, encase::ShaderType)] 
    pub struct Foo {
        a: i32,
        // `glam` objects are only generated if the `glam` feature is enabled.
        b: glam::u32::UVec4, 
        c: glam::u32::UVec4,
    }
    #[derive(Debug, PartialEq, Clone, encase::ShaderType)]
    pub struct Bar {
        size: u32,
        elements: [glam::bool::BVec2; 128],
        #[size(runtime)] // Only added if the `encase` feature is enabled.
        foos: Vec<Foo>,
    }
}
pub mod globals {
    /// Information about the `bar` global variable within the shader module.
    pub mod bar {
        pub const NAME: &'static str = "bar";
        pub type Ty = types::Bar;
        pub const SPACE: naga::AddressSpace = naga::AddressSpace::Storage {
            access: naga::StorageAccess::LOAD,
        }
        pub mod binding {
            pub const GROUP: u32 = 0u32;
            pub const BINDING: u32 = 0u32;
        }
    }
}
/// Information about the entry points within the module.
pub mod entry_points {
    pub mod main {
        pub const NAME: &'static str = "main";

        /// The sourcecode for the shader, as a constant string, excluding any other entry points. 
        /// This is useful when the `minify` feature is enabled for this crate, as it allows more aggressive 
        /// minification to be performed with the knowledge of the specific entry point that will be used.
        pub const EXCLUSIVE_SOURCE: &'static str = "...";
    }
}
/// The sourcecode for the shader, as a constant string.
pub const SOURCE: &'static str = "...";

Dependencies

~6–14MB
~171K SLoC