Files
wsg/lib/tests/wgsl_validate.rs
T
Jérôme Bousquié 3a424afe8c GPU culling
2026-09-22 15:48:15 +02:00

88 lines
3.5 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! # Validation WGSL (naga)
//!
//! The `standard_shader.wgsl` shader is not yet loaded by a `RenderPipeline` (see Steps 3–5):
//! this offline validation via `wgpu::naga` is therefore the **only** guarantee of its validity until
//! it is wired in. It protects against future regressions (shader re-edits, layout changes)
//! without requiring a GPU context.
//!
//! No new dependency is introduced: `wgpu` re-exports `naga`, already a `wsg-lib` dependency.
use wgpu::naga;
/// Parses and fully validates the embedded `standard_shader.wgsl` shader via naga.
/// A failure here means the shader would be rejected by `Device::create_shader_module` at Step 3.
#[test]
fn standard_shader_is_valid_wgsl() {
let src = include_str!("../src/shaders/standard_shader.wgsl");
let module = naga::front::wgsl::parse_str(src)
.unwrap_or_else(|e| panic!("standard_shader.wgsl: parsing error: {e:?}"));
let mut validator = naga::valid::Validator::new(
naga::valid::ValidationFlags::all(),
naga::valid::Capabilities::all(),
);
validator
.validate(&module)
.unwrap_or_else(|e| panic!("standard_shader.wgsl: validation failed: {e:?}"));
// Contract: exactly the two expected entry points vs_main / fs_main.
assert!(module.entry_points.len() >= 2, "vs_main + fs_main expected");
}
/// Parses and fully validates the embedded `shadow_shader.wgsl` shader (Step 14, D4) via naga.
/// The "shadow" pipeline is wired directly by `build_shadow_pipeline` (bypassing the
/// PipelineCache), so this offline validation is the guarantee of its validity. The contract
/// expects a single entry point (`vs_main` — pipeline with no fragment stage).
#[test]
fn shadow_shader_is_valid_wgsl() {
let src = include_str!("../src/shaders/shadow_shader.wgsl");
let module = naga::front::wgsl::parse_str(src)
.unwrap_or_else(|e| panic!("shadow_shader.wgsl: parsing error: {e:?}"));
let mut validator = naga::valid::Validator::new(
naga::valid::ValidationFlags::all(),
naga::valid::Capabilities::all(),
);
validator
.validate(&module)
.unwrap_or_else(|e| panic!("shadow_shader.wgsl: validation failed: {e:?}"));
let entry_names: Vec<&str> = module
.entry_points
.iter()
.map(|ep| ep.name.as_str())
.collect();
assert_eq!(entry_names, vec!["vs_main"], "only vs_main expected");
}
/// Parses and fully validates the embedded `gpu_driven.wgsl` compute shader (Phase 3, Step 15)
/// via naga. The renderer compiles it directly into two `ComputePipeline`s (one per entry point),
/// so this offline validation is the guarantee of its validity. The contract expects exactly the
/// two compute entry points: `compute_matrices` and `cull`.
#[test]
fn gpu_driven_shader_is_valid_wgsl() {
let src = include_str!("../src/shaders/gpu_driven.wgsl");
let module = naga::front::wgsl::parse_str(src)
.unwrap_or_else(|e| panic!("gpu_driven.wgsl: parsing error: {e:?}"));
let mut validator = naga::valid::Validator::new(
naga::valid::ValidationFlags::all(),
naga::valid::Capabilities::all(),
);
validator
.validate(&module)
.unwrap_or_else(|e| panic!("gpu_driven.wgsl: validation failed: {e:?}"));
let mut entry_names: Vec<&str> = module
.entry_points
.iter()
.map(|ep| ep.name.as_str())
.collect();
entry_names.sort();
assert_eq!(
entry_names,
vec!["compute_matrices", "cull"],
"the two compute entry points are expected"
);
}