wgsl_preprocessor

Crates.iowgsl_preprocessor
lib.rswgsl_preprocessor
version1.1.4
sourcesrc
created_at2022-07-30 09:37:06.678357
updated_at2024-08-19 20:17:40.071078
descriptionAn unofficial preprocessor for WGSL written in Rust for WGPU.
homepage
repositoryhttps://github.com/elyshaffir/wgsl_preprocessor
max_upload_size
id635419
size61,829
Ely Shaffir (elyshaffir)

documentation

README

This crate provides a library for performing similar actions to what is expected from a preprocessor in WGSL. Since WGSL will not have a preprocessor at least for version 1.0, this crate provides solutions to some common problems like including shader files and defining constants from Rust code.

Example: Include Multiple Shader Files

Here are the contents of the three shader files in this example (there are blank lines at the end of each included file): test_shaders/main.wgsl:

//!include test_shaders/included.wgsl test_shaders/included2.wgsl

test_shaders/included.wgsl:

struct TestStruct {
	test_data: vec4<f32>;
};

test_shaders/included2.wgsl:

struct AnotherTestStruct {
	another_test_data: vec3<u32>;
};

With these include statements, main.wgsl, becomes:

struct TestStruct {
	test_data: vec4<f32>;
};
struct AnotherTestStruct {
	another_test_data: vec3<u32>;
};

It is important to note that test_shaders/main.wgsl could also contain:

//!include test_shaders/included.wgsl
//!include test_shaders/included2.wgsl

The result would be the same.

Example: Define Macros

Non-function-like macro definitions are supported, for example:

//!define u3 vec3<u32>
@compute
@workgroup_size(64)
fn main(@builtin(global_invocation_id) id: u3) {
	// ...
}

With this define statement, the source becomes:

@compute
@workgroup_size(64)
fn main(@builtin(global_invocation_id) id: vec3<u32>) {
	// ...
}

Multi-line macros are not yet supported.

Example: Defining a Constant Struct Array

Let's say some color constants are calculated before shader compile time and should be injected into the code for performance reasons. main.wgsl would contain:

struct Struct {
	data: vec4<f32>,
}
//!define STRUCT_ARRAY

In the Rust code, Struct is defined, and given an implementation of [WGSLType] it can be translated to a WGSL struct with a single vec4<f32> member named data. The Rust code building and compiling the shaders will contain:

use wgsl_preprocessor::WGSLType;

struct Struct {
	pub data: [f32; 4],
}

impl WGSLType for Struct {
	fn type_name() -> String {
		"Struct".to_string()
	}

	fn string_definition(&self) -> String {
		format!("{}(vec4<f32>({:?}))", Self::type_name(), self.data)
			.replace(&['[', ']'], "")
	}
}

After building and compiling main.wgsl with the following array definition:

use wgsl_preprocessor::ShaderBuilder;

ShaderBuilder::new("main.wgsl")
	.unwrap()
	.put_array_definition(
		"STRUCT_ARRAY",
		&vec![
			&Struct {
				data: [1.0, 2.0, 3.0, 4.0]
			},
			&Struct {
				data: [1.5, 2.1, 3.7, 4.9]
			}
		]
	)
	.build();

The compiled contents would be identical to:

var<private> STRUCT_ARRAY: array<Struct, 2> = array<Struct, 2>(Struct(vec4<f32>(1.0, 2.0, 3.0, 4.0)),Struct(vec4<f32>(1.5, 2.1, 3.7, 4.9)),);

Crate features

Inserting Arrays of Suitable Lengths as Vectors

By default, none of the following features are enabled.

  • array_vectors - When enabled, implementations of [WGSLType] are compiled for all array types of suitable lengths and scalar types. This feature forces the translation of (for example) [f32; 4] to the WGSL type vec4<f32> in methods like [ShaderBuilder::put_array_definition].
  • cgmath_vectors - This feature is similar to array_vectors but with [cgmath] vector objects like [cgmath::Vector3<u32>] which would be translated to vec3<u32>.
Commit count: 30

cargo fmt