Restore abs() in the rect shader, and validate every shader without a device
`7c50a3e` renamed a length's `abs` component to `px` and took the WGSL `abs()` builtin in the rounded-rect distance with it, so every window failed shader validation on the first frame while `cargo test` stayed green. `naga` is reachable through `wgpu`, so a unit test now composes each shader file with the prelude the way the renderer does and parses and validates it; it reads the shader directory rather than naming primitives, so a new one is covered by adding its file. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
02ff8c7454
commit
f61e8936f1
2 files changed
+38
-2
No files matched your search
+37
-1
@@ -22,6 +22,10 @@ pub use primitive::*;
|
||||
|
||||
const PRELUDE: &str = include_str!("./shader/prelude.wgsl");
|
||||
|
||||
fn module_source(wgsl: &str) -> String {
|
||||
format!("{PRELUDE}\n{wgsl}")
|
||||
}
|
||||
|
||||
pub struct UiRenderNode {
|
||||
shared_layout: BindGroupLayout,
|
||||
shared_group: BindGroup,
|
||||
@@ -222,7 +226,7 @@ impl UiRenderNode {
|
||||
) -> RenderPipeline {
|
||||
let module = device.create_shader_module(ShaderModuleDescriptor {
|
||||
label: Some(label),
|
||||
source: ShaderSource::Wgsl(format!("{PRELUDE}\n{wgsl}").into()),
|
||||
source: ShaderSource::Wgsl(module_source(wgsl).into()),
|
||||
});
|
||||
device.create_render_pipeline(&RenderPipelineDescriptor {
|
||||
label: Some(label),
|
||||
@@ -401,3 +405,35 @@ impl ListBuffers {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::module_source;
|
||||
use wgpu::naga::{
|
||||
front::wgsl,
|
||||
valid::{Capabilities, ValidationFlags, Validator},
|
||||
};
|
||||
|
||||
/// Every shader file, composed as the renderer composes it, parses and
|
||||
/// validates with no device -- so an edit that breaks one fails here and
|
||||
/// not in the first window opened.
|
||||
#[test]
|
||||
fn every_shader_validates() {
|
||||
let dir = concat!(env!("CARGO_MANIFEST_DIR"), "/src/render/shader");
|
||||
let mut checked = 0;
|
||||
for entry in std::fs::read_dir(dir).unwrap() {
|
||||
let path = entry.unwrap().path();
|
||||
if path.extension().is_none_or(|e| e != "wgsl") || path.ends_with("prelude.wgsl") {
|
||||
continue;
|
||||
}
|
||||
let source = module_source(&std::fs::read_to_string(&path).unwrap());
|
||||
let module = wgsl::parse_str(&source)
|
||||
.unwrap_or_else(|e| panic!("{}: {}", path.display(), e.emit_to_string(&source)));
|
||||
Validator::new(ValidationFlags::all(), Capabilities::all())
|
||||
.validate(&module)
|
||||
.unwrap_or_else(|e| panic!("{}: {e:?}", path.display()));
|
||||
checked += 1;
|
||||
}
|
||||
assert!(checked > 0, "no shaders found in {dir}");
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,6 @@ fn distance_from_rect(pixel_pos: vec2<f32>, rect_center: vec2<f32>, rect_corner:
|
||||
// vec from center to pixel
|
||||
let p = pixel_pos - rect_center;
|
||||
// vec from inner rect corner to pixel
|
||||
let q = px(p) - (rect_corner - radius);
|
||||
let q = abs(p) - (rect_corner - radius);
|
||||
return length(max(q, vec2(0.0))) - radius;
|
||||
}
|
||||
Reference in new issue
Block a user