Guard the sharpening kernel against WGSL reserved keywords
The fused-fragment check in lib.rs cannot see a detail pass: it is a separate shader composed at a resolution compose() never knows. The kernel's own test now scans the block the composer wrapped, with comments stripped so prose about the keyword cannot fail a test about the code. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -799,9 +799,8 @@ mod tests {
|
|||||||
// source rather than at the operation that wrote it, and this body
|
// source rather than at the operation that wrote it, and this body
|
||||||
// reaches for exactly that word.
|
// reaches for exactly that word.
|
||||||
//
|
//
|
||||||
// Not the full reserved list; the words a convolution would plausibly
|
// Not the full reserved list; the words a kernel would plausibly pick
|
||||||
// pick for a local.
|
// for a local. The same list `no_fragment_declares_a_wgsl_reserved_keyword` uses,
|
||||||
// The same list `no_fragment_declares_a_wgsl_reserved_keyword` uses,
|
|
||||||
// kept identical on purpose: two lists that drift apart would let a
|
// kept identical on purpose: two lists that drift apart would let a
|
||||||
// word be safe in one stage and not in the other, which is the sort of
|
// word be safe in one stage and not in the other, which is the sort of
|
||||||
// difference nobody discovers until a shader fails to compile.
|
// difference nobody discovers until a shader fails to compile.
|
||||||
@@ -813,18 +812,33 @@ mod tests {
|
|||||||
];
|
];
|
||||||
|
|
||||||
for pass in chain_at(&sharpening(100.0, 2.0), RenderScale::full((512, 512))).passes {
|
for pass in chain_at(&sharpening(100.0, 2.0), RenderScale::full((512, 512))).passes {
|
||||||
// Only what this operation wrote. The composer's own preamble
|
// Only what this operation wrote — the block the composer wraps
|
||||||
// declares `var output` and `let coord`, which naga accepts and
|
// the body in. Its preamble declares `var output` and its tail
|
||||||
// which are not this test's business.
|
// writes through it, and neither is this test's business; scanning
|
||||||
let body = pass
|
// the whole file would fail on generated code nobody here can fix.
|
||||||
|
let block = pass
|
||||||
.source
|
.source
|
||||||
.rsplit_once(" {\n")
|
.rsplit_once(" {\n")
|
||||||
.expect("the operation's block")
|
.expect("the operation's block opens")
|
||||||
.1;
|
.1;
|
||||||
|
let body = block
|
||||||
|
.split_once("\n }\n")
|
||||||
|
.map_or(block, |(inside, _)| inside);
|
||||||
|
|
||||||
|
// Comments are not declarations, and the kernel deliberately names
|
||||||
|
// `target` in one to say why it does not use it. Stripping them
|
||||||
|
// keeps this on the code, so that editing the prose can never fail
|
||||||
|
// a test about what compiles.
|
||||||
|
let code: Vec<&str> = body
|
||||||
|
.lines()
|
||||||
|
.filter(|l| !l.trim_start().starts_with("//"))
|
||||||
|
.collect();
|
||||||
|
let code = code.join("\n");
|
||||||
|
|
||||||
for keyword in RESERVED {
|
for keyword in RESERVED {
|
||||||
for form in [format!("let {keyword} "), format!("var {keyword} ")] {
|
for form in [format!("let {keyword} "), format!("var {keyword} ")] {
|
||||||
assert!(
|
assert!(
|
||||||
!body.contains(&form),
|
!code.contains(&form),
|
||||||
"{} declares `{keyword}`, which is a WGSL reserved keyword",
|
"{} declares `{keyword}`, which is a WGSL reserved keyword",
|
||||||
pass.label
|
pass.label
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user