WGSL preprocess and composer utilities aligned with naga_oil.
///|
test "README: common package surface" {
let value_defines = @common.default_wgsl_value_defines()
debug_inspect(value_defines.length() > 0, content="true")
}///|
test "README: metadata extraction" {
let metadata : @common.PreprocessorMetaData = @metadata.get_preprocessor_metadata(
"#define_import_path bevy_ui::ui_node\n#define HDR\n#define TONEMAP_MODE 2\n#import bevy_render::{view::View, globals::Globals}\n#import bevy_render::maths as maths\nfn main(view: View, globals: Globals) -> f32 {\n return maths::tone_map(1.0);\n}\n",
) catch {
_ => abort("expected metadata extraction success")
}
debug_inspect(metadata.name, content="Some(\"bevy_ui::ui_node\")")
debug_inspect(metadata.imports.length(), content="3")
debug_inspect(metadata.wgsl_directives.is_empty(), content="true")
}///|
test "README: preprocess single shader" {
let defs : @hashmap.HashMap[String, @common.ShaderDefValue] = @hashmap.HashMap::new()
defs.set("TEXTURE", @common.ShaderDefValue::Bool(true))
let source = "#ifdef TEXTURE\nvar sprite_texture: texture_2d<f32>;\n#else\nvar sprite_texture: texture_2d_array<f32>;\n#endif\n"
let output : @common.PreprocessOutput = @preprocess.Preprocessor::default().preprocess(
source, defs,
) catch {
_ => abort("preprocess failed")
}
debug_inspect(
output.preprocessed_source.contains("texture_2d<f32>"),
content="true",
)
debug_inspect(output.imports.length(), content="0")
}///|
test "README: compose registered modules" {
let composer : @compose.Composer = @compose.Composer::default()
let defines : @hashmap.HashMap[String, Bool] = @hashmap.HashMap::new()
let redirects : Array[@common.WgslSymbolRedirect] = []
composer.clear_sources()
composer.register_source(
"render/maths.wgsl", "#define_import_path bevy_render::maths\nconst PI_2: f32 = 6.28318;\n",
)
composer.register_source(
"sprite_render/mesh2d/mesh2d_functions.wgsl", "#define_import_path bevy_sprite::mesh2d_functions\n#import bevy_render::maths::PI_2\nfn twice_pi() -> f32 {\n return PI_2;\n}\n",
)
composer.register_source(
"sprite_render/mesh2d/mesh2d.wgsl", "#import bevy_sprite::mesh2d_functions as mesh_functions\nfn demo() -> f32 {\n return mesh_functions::twice_pi();\n}\n",
)
let compose_options : @common.WgslComposeOptions = {
defines,
value_defines: @common.default_wgsl_value_defines(),
redirects,
additional_imports: [],
}
let composed : String = composer.compose_wgsl(
"sprite_render/mesh2d/mesh2d.wgsl", compose_options,
) catch {
_ => abort("compose failed")
}
debug_inspect(composed.contains("fn demo"), content="true")
debug_inspect(composed.contains("mesh_functions::"), content="false")
}///|
test "README: bulk registry and relative imports" {
let composer : @compose.Composer = @compose.Composer::default()
let defines : @hashmap.HashMap[String, Bool] = @hashmap.HashMap::new()
let redirects : Array[@common.WgslSymbolRedirect] = []
let files : Array[@common.WgslSourceFile] = [
{
rel_path: "shaders/shared/common.wgsl",
source: "struct SharedValue {\n tint: vec4<f32>,\n}\n",
},
{
rel_path: "shaders/effects/main.wgsl",
source: "#import \"../shared/common.wgsl\" SharedValue\nfn shade(value: SharedValue) -> vec4<f32> {\n return value.tint;\n}\n",
},
]
composer.clear_sources()
composer.register_source_files(files)
debug_inspect(
composer.registered_source("shaders/effects/main.wgsl") is Some(_),
content="true",
)
let compose_options : @common.WgslComposeOptions = {
defines,
value_defines: @common.default_wgsl_value_defines(),
redirects,
additional_imports: [],
}
let composed : String = composer.compose_wgsl(
"shaders/effects/main.wgsl", compose_options,
) catch {
_ => abort("compose failed")
}
debug_inspect(composed.contains("struct SharedValue"), content="true")
}///|
test "README: checked bulk registry" {
let files : Array[@common.WgslSourceFile] = [
{
rel_path: "shaders/demo/a.wgsl",
source: "#define_import_path demo::dup\nfn a() -> f32 { return 1.0; }\n",
},
{
rel_path: "shaders/demo/b.wgsl",
source: "#define_import_path demo::dup\nfn b() -> f32 { return 2.0; }\n",
},
]
let registry = @resolver.WgslSourceRegistry::default()
let diagnostics : Array[@common.WgslDiagnostic] = registry.analyze_source_files(
files,
)
debug_inspect(diagnostics.length(), content="1")
let checked_diagnostics : Array[@common.WgslDiagnostic] = []
registry.register_source_files_checked(files, checked_diagnostics)
debug_inspect(checked_diagnostics.length(), content="1")
}///|
test "README: scan source tree" {
let composer : @compose.Composer = @compose.Composer::default()
let defines : @hashmap.HashMap[String, Bool] = @hashmap.HashMap::new()
let redirects : Array[@common.WgslSymbolRedirect] = []
let scan_options : @common.WgslSourceScanOptions = {
recursive: true,
extensions: [".wgsl"],
exclude_prefixes: ["ignored"],
}
composer.clear_sources()
composer.register_source_tree("testdata/wgsl_scan", scan_options) catch {
_ => abort("failed to scan WGSL shader tree")
}
let compose_options : @common.WgslComposeOptions = {
defines,
value_defines: @common.default_wgsl_value_defines(),
redirects,
additional_imports: [],
}
let composed : String = composer.compose_wgsl(
"effects/main.wgsl", compose_options,
) catch {
_ => abort("compose failed")
}
debug_inspect(composed.contains("fn shade"), content="true")
}///|
test "README: checked tree scan" {
let (files, diagnostics) = @resolver.scan_wgsl_source_files_checked(
"testdata/wgsl_scan_dups",
@common.WgslSourceScanOptions::default(),
) catch {
_ => abort("failed to scan WGSL shader tree")
}
debug_inspect(files.length(), content="2")
debug_inspect(diagnostics.length(), content="1")
}///|
test "README: export single WGSL file" {
let composer : @compose.Composer = @compose.Composer::default()
let defines : @hashmap.HashMap[String, Bool] = @hashmap.HashMap::new()
let redirects : Array[@common.WgslSymbolRedirect] = []
let files : Array[@common.WgslSourceFile] = [
{
rel_path: "shaders/shared/common.wgsl",
source: "struct SharedParams {\n tint: vec4<f32>,\n}\nstruct SharedVertex {\n params: SharedParams,\n}\nfn build_color(vertex: SharedVertex) -> vec4<f32> {\n return vertex.params.tint;\n}\n",
},
{
rel_path: "shaders/effects/main.wgsl",
source: "#import \"../shared/common.wgsl\" SharedVertex, build_color\nfn shade(vertex: SharedVertex) -> vec4<f32> {\n return build_color(vertex);\n}\n",
},
]
composer.clear_sources()
composer.register_source_files(files)
let compose_options : @common.WgslComposeOptions = {
defines,
value_defines: @common.default_wgsl_value_defines(),
redirects,
additional_imports: [],
}
let export_options : @common.WgslExportOptions = { root_items: ["shade"] }
let exported : @common.WgslExportOutput = @export.export_wgsl_with_options(
composer, "shaders/effects/main.wgsl", compose_options, export_options,
) catch {
_ => abort("export failed")
}
debug_inspect(exported.source.contains("#import"), content="false")
debug_inspect(exported.source_catalog.length() > 0, content="true")
debug_inspect(exported.source_map.length() > 0, content="true")
debug_inspect(exported.diagnostics.length(), content="0")
}///|
test "README: build source catalog" {
let composer : @compose.Composer = @compose.Composer::default()
let defines : @hashmap.HashMap[String, Bool] = @hashmap.HashMap::new()
let redirects : Array[@common.WgslSymbolRedirect] = []
let files : Array[@common.WgslSourceFile] = [
{
rel_path: "shaders/shared/common.wgsl",
source: "struct SharedParams {\n tint: vec4<f32>,\n}\nstruct SharedVertex {\n params: SharedParams,\n}\nfn build_color(vertex: SharedVertex) -> vec4<f32> {\n return vertex.params.tint;\n}\n",
},
{
rel_path: "shaders/effects/main.wgsl",
source: "#import \"../shared/common.wgsl\" SharedVertex, build_color\nfn shade(vertex: SharedVertex) -> vec4<f32> {\n return build_color(vertex);\n}\n",
},
]
composer.clear_sources()
composer.register_source_files(files)
let compose_options : @common.WgslComposeOptions = {
defines,
value_defines: @common.default_wgsl_value_defines(),
redirects,
additional_imports: [],
}
let prepared = composer.prepare_wgsl_source(
"shaders/effects/main.wgsl", compose_options,
) catch {
err => abort("expected prepare success: \{err.message()}")
}
let catalog : Array[@common.WgslSourceCatalogEntry] = prepared.source_catalog
debug_inspect(catalog.length() > 0, content="true")
}///|
test "README: source-level redirects" {
let composer : @compose.Composer = @compose.Composer::default()
let defines : @hashmap.HashMap[String, Bool] = @hashmap.HashMap::new()
let redirects : Array[@common.WgslSymbolRedirect] = [
{ from_name: "build_shadow", to_name: "build_color" },
]
let files : Array[@common.WgslSourceFile] = [
{
rel_path: "shaders/shared/common.wgsl",
source: "struct SharedParams {\n tint: vec4<f32>,\n}\nstruct SharedVertex {\n params: SharedParams,\n}\nfn build_color(vertex: SharedVertex) -> vec4<f32> {\n return vertex.params.tint;\n}\nfn build_shadow(vertex: SharedVertex) -> vec4<f32> {\n return vec4<f32>(0.0, 0.0, 0.0, 1.0);\n}\n",
},
{
rel_path: "shaders/effects/redirect.wgsl",
source: "#import \"../shared/common.wgsl\" SharedVertex, build_color, build_shadow\nfn shade(vertex: SharedVertex) -> vec4<f32> {\n return build_shadow(vertex);\n}\n",
},
]
composer.clear_sources()
composer.register_source_files(files)
let compose_options : @common.WgslComposeOptions = {
defines,
value_defines: @common.default_wgsl_value_defines(),
redirects,
additional_imports: [],
}
let export_options : @common.WgslExportOptions = { root_items: ["shade"] }
let exported : @common.WgslExportOutput = @export.export_wgsl_with_options(
composer, "shaders/effects/redirect.wgsl", compose_options, export_options,
) catch {
_ => abort("redirect export failed")
}
debug_inspect(exported.source.contains("build_shadow"), content="false")
debug_inspect(exported.source.contains("build_color"), content="true")
}#import bevy_render::view::View
#import bevy_render::maths as maths
#import bevy_render::{view::View, globals::Globals}
#import bevy_render::{maths::{PI_2, powsafe}}
#import "shaders/skills/shared.wgsl" Vertex, VertexOutput
#import "../shared/common.wgsl" SharedVertex, build_colormoon test