From 7ba2c7814de829083285add561b2e2c3e93ffe23 Mon Sep 17 00:00:00 2001 From: Erich Gubler Date: Fri, 26 Dec 2025 21:33:06 -0700 Subject: [PATCH 1/5] fix(core): compare fragment input indices against `maxInterStageShaderVariables` directly, not `max_fragment_input_variables` --- wgpu-core/src/validation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wgpu-core/src/validation.rs b/wgpu-core/src/validation.rs index 2955f74911..0e0c4578a8 100644 --- a/wgpu-core/src/validation.rs +++ b/wgpu-core/src/validation.rs @@ -1597,7 +1597,7 @@ impl Interface { for output in entry_point.inputs.iter() { match *output { Varying::Local { ref iv, location } => { - if location >= max_fragment_shader_input_variables { + if location >= self.limits.max_inter_stage_shader_variables { return Err(StageError::FragmentInputLocationTooLarge { location, var: iv.clone(), From 67ffaae640353142cf3f902550d04724c27a4755 Mon Sep 17 00:00:00 2001 From: Erich Gubler Date: Fri, 26 Dec 2025 21:33:06 -0700 Subject: [PATCH 2/5] fix(core): do not deduct `Position` built-in from `maxInterStageShaderVariables` --- wgpu-core/src/validation/shader_io_deductions.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wgpu-core/src/validation/shader_io_deductions.rs b/wgpu-core/src/validation/shader_io_deductions.rs index a7a64f8608..6189b15ce3 100644 --- a/wgpu-core/src/validation/shader_io_deductions.rs +++ b/wgpu-core/src/validation/shader_io_deductions.rs @@ -49,7 +49,7 @@ impl MaxFragmentShaderInputDeduction { | InterStageBuiltIn::ViewIndex | InterStageBuiltIn::PointCoord => 1, InterStageBuiltIn::Barycentric => 3, - InterStageBuiltIn::Position => 4, + InterStageBuiltIn::Position => 0, }, } } @@ -58,6 +58,7 @@ impl MaxFragmentShaderInputDeduction { use naga::BuiltIn; Some(Self::InterStageBuiltIn(match builtin { + BuiltIn::Position { .. } => InterStageBuiltIn::Position, BuiltIn::FrontFacing => InterStageBuiltIn::FrontFacing, BuiltIn::SampleIndex => InterStageBuiltIn::SampleIndex, BuiltIn::SampleMask => InterStageBuiltIn::SampleMask, @@ -67,7 +68,6 @@ impl MaxFragmentShaderInputDeduction { BuiltIn::PointCoord => InterStageBuiltIn::PointCoord, BuiltIn::Barycentric => InterStageBuiltIn::Barycentric, - BuiltIn::Position { .. } => InterStageBuiltIn::Position, BuiltIn::ViewIndex => InterStageBuiltIn::ViewIndex, BuiltIn::BaseInstance @@ -107,6 +107,7 @@ impl MaxFragmentShaderInputDeduction { #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum InterStageBuiltIn { // Standard for WebGPU + Position, FrontFacing, SampleIndex, SampleMask, @@ -117,7 +118,6 @@ pub enum InterStageBuiltIn { // Non-standard PointCoord, Barycentric, - Position, ViewIndex, } From a8f484cd37df9bfcccce05822aa517b7c1bde3d4 Mon Sep 17 00:00:00 2001 From: Erich Gubler Date: Fri, 26 Dec 2025 21:33:06 -0700 Subject: [PATCH 3/5] refactor(core): `debug_assert` that we wrote at least one deduction for `maxInterStageShaderVariables` errors --- wgpu-core/src/validation/shader_io_deductions.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/wgpu-core/src/validation/shader_io_deductions.rs b/wgpu-core/src/validation/shader_io_deductions.rs index 6189b15ce3..fbbf17fe06 100644 --- a/wgpu-core/src/validation/shader_io_deductions.rs +++ b/wgpu-core/src/validation/shader_io_deductions.rs @@ -147,9 +147,18 @@ where .filter(|(_, effective_deduction)| *effective_deduction > 0); if relevant_deductions.clone().next().is_some() { writeln!(f, "; note that some deductions apply during validation:")?; + let mut wrote_something = false; for deduction in deductions { - writeln!(f, "\n- {deduction:?}: {}", accessor(deduction))?; + let deducted_amount = accessor(deduction); + if deducted_amount > 0 { + writeln!(f, "\n- {deduction:?}: {}", accessor(deduction))?; + wrote_something = true; + } } + debug_assert!( + wrote_something, + "no substantial deductions found in error display" + ); } Ok(()) }) From 814a415757f8ab50fd3c121f0d4a0d75c7dfcc93 Mon Sep 17 00:00:00 2001 From: Erich Gubler Date: Sat, 27 Dec 2025 17:10:58 -0700 Subject: [PATCH 4/5] docs(CHANGELOG): add #8792 to entry for `maxInterStageShaderVariable` migration --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 880c8cf73a..c7bf265f77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,7 +49,7 @@ Bottom level categories: #### General -- BREAKING: Migrated from the `maxInterStageShaderComponents` limit to `maxInterStageShaderVariables`, which changes validation in a way that should not affect most programs. This follows the latest changes of the WebGPU spec. By @ErichDonGubler in [#8652](https://github.com/gfx-rs/wgpu/pull/8652). +- BREAKING: Migrated from the `maxInterStageShaderComponents` limit to `maxInterStageShaderVariables`, which changes validation in a way that should not affect most programs. This follows the latest changes of the WebGPU spec. By @ErichDonGubler in [#8652](https://github.com/gfx-rs/wgpu/pull/8652), [#8792](https://github.com/gfx-rs/wgpu/pull/8792). - Fixed validation of the texture format in GPUDepthStencilState when neither depth nor stencil is actually enabled. By @andyleiserson in [#8766](https://github.com/gfx-rs/wgpu/pull/8766). #### GLES From 148722838329c211f464c9f28c2ac57b41272f61 Mon Sep 17 00:00:00 2001 From: Erich Gubler Date: Fri, 26 Dec 2025 19:30:18 -0700 Subject: [PATCH 5/5] test(cts): add passing subset of `webgpu:api,validation,render_pipeline,inter_stage:max_variables_count,input:*` --- cts_runner/test.lst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cts_runner/test.lst b/cts_runner/test.lst index e9e338eb7b..0699c5c117 100644 --- a/cts_runner/test.lst +++ b/cts_runner/test.lst @@ -165,6 +165,16 @@ webgpu:api,validation,render_pipeline,depth_stencil_state:stencil_write:* webgpu:api,validation,render_pipeline,inter_stage:max_shader_variable_location:isAsync=false;* //FAIL: webgpu:api,validation,render_pipeline,inter_stage:max_shader_variable_location:isAsync=true;* // https://github.com/gfx-rs/wgpu/pull/8712 +webgpu:api,validation,render_pipeline,inter_stage:max_variables_count,input:isAsync=false;numVariablesDelta=0;useExtraBuiltinInputs=false +webgpu:api,validation,render_pipeline,inter_stage:max_variables_count,input:isAsync=false;numVariablesDelta=0;useExtraBuiltinInputs=true +webgpu:api,validation,render_pipeline,inter_stage:max_variables_count,input:isAsync=false;numVariablesDelta=1;useExtraBuiltinInputs=false +//FAIL: webgpu:api,validation,render_pipeline,inter_stage:max_variables_count,input:isAsync=false;numVariablesDelta=-1;useExtraBuiltinInputs=true +// https://github.com/gpuweb/cts/pull/4546 +webgpu:api,validation,render_pipeline,inter_stage:max_variables_count,input:isAsync=true;numVariablesDelta=0;useExtraBuiltinInputs=false +webgpu:api,validation,render_pipeline,inter_stage:max_variables_count,input:isAsync=true;numVariablesDelta=0;useExtraBuiltinInputs=true +webgpu:api,validation,render_pipeline,inter_stage:max_variables_count,input:isAsync=true;numVariablesDelta=1;useExtraBuiltinInputs=false +//FAIL: webgpu:api,validation,render_pipeline,inter_stage:max_variables_count,input:isAsync=true;numVariablesDelta=-1;useExtraBuiltinInputs=true +// https://github.com/gpuweb/cts/pull/4546 webgpu:api,validation,render_pipeline,inter_stage:max_variables_count,output:* webgpu:api,validation,resource_usages,buffer,in_pass_encoder:* // FAIL: 2 other cases in resource_usages,texture,in_pass_encoder. https://github.com/gfx-rs/wgpu/issues/3126