88 lines
3.5 KiB
Rust
88 lines
3.5 KiB
Rust
//! # 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"
|
||
);
|
||
}
|