Coder Social home page Coder Social logo

include-wgsl-oil's Introduction

Include WGSL-oil

crates.io docs.rs crates.io

Provides a macro for including a wgsl file, using the naga-oil preprocessor at compile time.

Motivation

Running the naga-oil preprocessor at runtime increases startup time for apps, and also leads to shader errors only being reported at runtime. Running it at compile time allows the preprocessor cost to be spent before the user runs the app, and allows the Rust compiler to report shader errors at compile time.

This crate also uses naga-to-tokenstream to expose a bunch of information about the types, constants and globals within a shader to Rust. This allows for de-duplication of code, where a constant from a shader module can be used as a Rust constant, and structs defined in shaders to be used as Rust structs.

Features

  • Shader errors are reported at compile time

  • Bonus syntax added to wgsl by the naga-oil preprocessor like includes and method overriding.

  • Types, constants and globals are exposed to Rust, allowing code to refer to things in the shader without duplicating code.

  • Support for glam and encase with the corresponding feature flags.

  • Support for wgsl minification using the wgsl-minifier crate with the minify feature flag, further reducing startup time.

Getting started

Including a shader module follows similar syntax to the Rust include_str or include_bytes macros, where a path is given relative to the containing folder of the Rust file that the macro is invoked from. However the include_wgsl_oil macro generates a large number of objects, so it is instead invoked as an attribute to a module that you would like it to populate with shader information:

#[include_wgsl_oil::include_wgsl_oil("path/to/shader.wgsl")]
mod my_shader {}

// The preprocessed sourcecode constant string can be found in the `SOURCE` constant at the root of the module:
println!("shader source: {}", my_shader::SOURCE); 

Imports

Shader imports are processed both relative to the importing file, and relative to the root of the crate source folder, and shaders may import any other shaders so long as there is no circular dependency on imports between files.

For example, if your crate directory structure looks like the following:

my-crate/
├─ src/
│  ├─ submodule/
│  │  ├─ subsubmodule/
│  │  │  ├─ extra_special_shader.wgsl
│  │  ├─ special_shader.wgsl
│  │  ├─ mod.rs
│  ├─ general_shader.wgsl
│  ├─ main.rs
├─ Cargo.toml

Then special_shader.wgsl is able to include general_shader.wgsl with either of the following lines:

#import general_shader.wgsl as GeneralShader
#import ../general_shader.wgsl as GeneralShader

GeneralShader::foo();

And extra_special_shader.wgsl is able to include special_shader.wgsl with either of the following lines:

#import ../special_shader.wgsl as SpecialShader
#import submodule/special_shader.wgsl as SpecialShader

SpecialShader::foo();

Exported Types

Structs defined in your shader can be exported as an equivalent Rust struct. To do this, each of the fields of the struct must be representable, for example by enabling the glam feature to represent vectors and matrices, and then your struct definition must be prepended with an @export tag, as follows:

@export struct MyStruct {
    foo: u32,
    bar: i32
}

Then, in your Rust file, you can do the following:

#[include_wgsl_oil::include_wgsl_oil("path/to/shader.wgsl")]
mod my_shader { }

let my_instance = my_shader::types::MyStruct {
    foo: 12,
    bar: -7
};

The encase feature on this crate makes every exported struct derive encase::ShaderType. Note that this may invalidate exported structs, as some types (such as bools) cannot be encoded with encase, however it is assumed that the only structs that you would want to export are structs that your program shares between host and GPU, and so should be encodable.

Definitions

The following definitions are added to pass information from Rust to your shaders:

  • __DEBUG is defined as true iff your project is being built in debug mode.

So in your shaders included by this crate, you can do something like the following:

#if __DEBUG
    do_something_debug();
#endif

Generated Items

For a full list of the items generated when including a module with this macro, see the naga-to-tokenstream documentation.

include-wgsl-oil's People

Contributors

dependabot[bot] avatar joeoc2001 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.