Revert "[tint] Polyfill sample_mask behavior on HLSL (D3D) and MSL (metal)" This reverts commit e39ee4a1edf526099f96dae2c998e2fe68534764. Change-Id: I02f11a1b3db673f5027adb8656beb0a4eb77aea9 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/318595 Auto-Submit: David Neto <dneto@google.com> Reviewed-by: James Price <jrprice@google.com> Commit-Queue: James Price <jrprice@google.com>
diff --git a/src/dawn/native/RenderPipeline.cpp b/src/dawn/native/RenderPipeline.cpp index 67bcb49..9d19fe0 100644 --- a/src/dawn/native/RenderPipeline.cpp +++ b/src/dawn/native/RenderPipeline.cpp
@@ -1069,7 +1069,6 @@ if (HasStage(SingleShaderStage::Fragment)) { mUsesFragDepth = GetStage(SingleShaderStage::Fragment).metadata->usesFragDepth; mUsesFragPosition = GetStage(SingleShaderStage::Fragment).metadata->usesFragPosition; - mUsesSampleMaskInput = GetStage(SingleShaderStage::Fragment).metadata->usesSampleMaskInput; mUsesSampleIndex = GetStage(SingleShaderStage::Fragment).metadata->usesSampleIndex; mUsesFramebufferFetch = GetStage(SingleShaderStage::Fragment).metadata->fragmentInputMask.any(); @@ -1293,11 +1292,6 @@ return mUsesFragDepth; } -bool RenderPipelineBase::UsesSampleMaskInput() const { - DAWN_CHECK(!IsError()); - return mUsesSampleMaskInput; -} - bool RenderPipelineBase::UsesSampleIndex() const { DAWN_CHECK(!IsError()); return mUsesSampleIndex;
diff --git a/src/dawn/native/RenderPipeline.h b/src/dawn/native/RenderPipeline.h index fd01dbc..e39ae40 100644 --- a/src/dawn/native/RenderPipeline.h +++ b/src/dawn/native/RenderPipeline.h
@@ -141,7 +141,6 @@ bool UsesFragDepth() const; bool UsesFragPosition() const; bool UsesSampleIndex() const; - bool UsesSampleMaskInput() const; bool UsesVertexIndex() const; bool UsesInstanceIndex() const; bool UsesFramebufferFetch() const; @@ -190,7 +189,6 @@ bool mUsesFragDepth = false; bool mUsesFragPosition = false; bool mUseSampleRateShading = false; - bool mUsesSampleMaskInput = false; bool mUsesSampleIndex = false; bool mUsesVertexIndex = false; bool mUsesInstanceIndex = false;
diff --git a/src/dawn/native/ShaderModule.cpp b/src/dawn/native/ShaderModule.cpp index 847f584..285f197 100644 --- a/src/dawn/native/ShaderModule.cpp +++ b/src/dawn/native/ShaderModule.cpp
@@ -1008,7 +1008,6 @@ // Other fragment metadata metadata->usesSampleMaskOutput = entryPoint.output_sample_mask_used; - metadata->usesSampleMaskInput = entryPoint.input_sample_mask_used; metadata->usesSampleIndex = entryPoint.sample_index_used; struct BoolName {
diff --git a/src/dawn/native/ShaderModule.h b/src/dawn/native/ShaderModule.h index cdc031b..46dd248 100644 --- a/src/dawn/native/ShaderModule.h +++ b/src/dawn/native/ShaderModule.h
@@ -314,7 +314,6 @@ X(bool, usesInstanceIndex) \ X(bool, usesNumWorkgroups) \ X(bool, usesSampleMaskOutput) \ - X(bool, usesSampleMaskInput) \ X(bool, usesSampleIndex) \ X(bool, usesVertexIndex) \ X(bool, usesGlobalInvocationIndex) \
diff --git a/src/dawn/native/d3d11/ComputePipelineD3D11.cpp b/src/dawn/native/d3d11/ComputePipelineD3D11.cpp index dae0ef3..50a4d58 100644 --- a/src/dawn/native/d3d11/ComputePipelineD3D11.cpp +++ b/src/dawn/native/d3d11/ComputePipelineD3D11.cpp
@@ -82,11 +82,10 @@ } d3d::CompiledShader compiledShader; - const bool kApplySampleMaskPolyfill = false; - DAWN_TRY_ASSIGN(compiledShader, ToBackend(programmableStage.module) - ->Compile(programmableStage, SingleShaderStage::Compute, - ToBackend(GetLayout()), compileFlags, - GetImmediateMask(), kApplySampleMaskPolyfill)); + DAWN_TRY_ASSIGN(compiledShader, + ToBackend(programmableStage.module) + ->Compile(programmableStage, SingleShaderStage::Compute, + ToBackend(GetLayout()), compileFlags, GetImmediateMask())); { TRACE_EVENT0(device->GetPlatform(), General, "ComputePipelineD3D11::CreateComputeShader"); SCOPED_DAWN_HISTOGRAM_TIMER_MICROS(device->GetPlatform(), "D3D11.CreateComputeShaderUs");
diff --git a/src/dawn/native/d3d11/RenderPipelineD3D11.cpp b/src/dawn/native/d3d11/RenderPipelineD3D11.cpp index 034f489..0c5ca9f 100644 --- a/src/dawn/native/d3d11/RenderPipelineD3D11.cpp +++ b/src/dawn/native/d3d11/RenderPipelineD3D11.cpp
@@ -474,13 +474,11 @@ additionalCompileFlags |= D3DCOMPILE_IEEE_STRICTNESS; } - const bool kApplySampleMaskPolyfill = false; - DAWN_TRY_ASSIGN( - compiledShader[SingleShaderStage::Vertex], - ToBackend(programmableStage.module) - ->Compile(programmableStage, SingleShaderStage::Vertex, ToBackend(GetLayout()), - compileFlags | additionalCompileFlags, GetImmediateMask(), - kApplySampleMaskPolyfill, usedInterstageVariables)); + DAWN_TRY_ASSIGN(compiledShader[SingleShaderStage::Vertex], + ToBackend(programmableStage.module) + ->Compile(programmableStage, SingleShaderStage::Vertex, + ToBackend(GetLayout()), compileFlags | additionalCompileFlags, + GetImmediateMask(), usedInterstageVariables)); const Blob& shaderBlob = compiledShader[SingleShaderStage::Vertex].shaderBlob; { TRACE_EVENT0(device->GetPlatform(), General, "RenderPipelineD3D11::CreateVertexShader"); @@ -546,15 +544,12 @@ additionalCompileFlags |= D3DCOMPILE_IEEE_STRICTNESS; } - // This must be accurate in determining when Sample Shading is active. - // It cannot be conservatively correct because the polyfill changes behavior. - bool applySampleMaskPolyfill = UsesSampleMaskInput() && UseSampleRateShading(); DAWN_TRY_ASSIGN( compiledShader[SingleShaderStage::Fragment], ToBackend(programmableStage.module) ->Compile(programmableStage, SingleShaderStage::Fragment, ToBackend(GetLayout()), compileFlags | additionalCompileFlags, GetImmediateMask(), - applySampleMaskPolyfill, usedInterstageVariables, pixelLocalOptions)); + usedInterstageVariables, pixelLocalOptions)); { TRACE_EVENT0(device->GetPlatform(), General, "RenderPipelineD3D11::CreatePixelShader"); SCOPED_DAWN_HISTOGRAM_TIMER_MICROS(device->GetPlatform(), "D3D11.CreatePixelShaderUs");
diff --git a/src/dawn/native/d3d11/ShaderModuleD3D11.cpp b/src/dawn/native/d3d11/ShaderModuleD3D11.cpp index 3641d3b..7712dcf 100644 --- a/src/dawn/native/d3d11/ShaderModuleD3D11.cpp +++ b/src/dawn/native/d3d11/ShaderModuleD3D11.cpp
@@ -73,7 +73,6 @@ const PipelineLayout* layout, uint32_t compileFlags, const ImmediateMask& pipelineImmediateMask, - bool applySampleMaskPolyfill, const std::optional<dawn::native::d3d::InterStageShaderVariablesMask>& usedInterstageVariables, const std::optional<tint::hlsl::writer::PixelLocalOptions>& pixelLocalOptions) { Device* device = ToBackend(GetDevice()); @@ -137,7 +136,6 @@ req.hlsl.tintOptions.disable_integer_range_analysis = !device->IsToggleEnabled(Toggle::EnableIntegerRangeAnalysisInRobustness); - req.hlsl.tintOptions.polyfill_sample_mask = applySampleMaskPolyfill; req.hlsl.tintOptions.immediate_binding_point = tint::BindingPoint{0, PipelineLayout::kReservedConstantBufferSlot}; if (stage == SingleShaderStage::Compute) {
diff --git a/src/dawn/native/d3d11/ShaderModuleD3D11.h b/src/dawn/native/d3d11/ShaderModuleD3D11.h index 0e7b2ab..425e005 100644 --- a/src/dawn/native/d3d11/ShaderModuleD3D11.h +++ b/src/dawn/native/d3d11/ShaderModuleD3D11.h
@@ -61,7 +61,6 @@ const PipelineLayout* layout, uint32_t compileFlags, const ImmediateMask& pipelineImmediateMask, - bool applySampleMaskPolyfill, const std::optional<dawn::native::d3d::InterStageShaderVariablesMask>& usedInterstageVariables = {}, const std::optional<tint::hlsl::writer::PixelLocalOptions>& pixelLocalOptions = {});
diff --git a/src/dawn/native/d3d12/RenderPipelineD3D12.cpp b/src/dawn/native/d3d12/RenderPipelineD3D12.cpp index 6c5594b..121e445 100644 --- a/src/dawn/native/d3d12/RenderPipelineD3D12.cpp +++ b/src/dawn/native/d3d12/RenderPipelineD3D12.cpp
@@ -372,17 +372,11 @@ !device->IsToggleEnabled(Toggle::D3DDisableIEEEStrictness))) { additionalCompileFlags |= D3DCOMPILE_IEEE_STRICTNESS; } - - // This must be accurate in determining when Sample Shading is active. - // It cannot be conservatively correct because the polyfill changes behavior. - bool applySampleMaskPolyfill = (stage == SingleShaderStage::Fragment) && - UsesSampleMaskInput() && UseSampleRateShading(); - - DAWN_TRY_ASSIGN(compiledShader[stage], - ToBackend(programmableStage.module) - ->Compile(programmableStage, stage, ToBackend(GetLayout()), - compileFlags | additionalCompileFlags, - applySampleMaskPolyfill, usedInterstageVariables)); + DAWN_TRY_ASSIGN( + compiledShader[stage], + ToBackend(programmableStage.module) + ->Compile(programmableStage, stage, ToBackend(GetLayout()), + compileFlags | additionalCompileFlags, usedInterstageVariables)); *shaders[stage] = {compiledShader[stage].shaderBlob.DataPtr(), compiledShader[stage].shaderBlob.Size()}; }
diff --git a/src/dawn/native/d3d12/ShaderModuleD3D12.cpp b/src/dawn/native/d3d12/ShaderModuleD3D12.cpp index dcb50ee..6f946bb 100644 --- a/src/dawn/native/d3d12/ShaderModuleD3D12.cpp +++ b/src/dawn/native/d3d12/ShaderModuleD3D12.cpp
@@ -116,7 +116,6 @@ SingleShaderStage stage, const PipelineLayout* layout, uint32_t compileFlags, - bool applySampleMaskPolyfill, const std::optional<dawn::native::d3d::InterStageShaderVariablesMask>& usedInterstageVariables) { Device* device = ToBackend(GetDevice()); @@ -348,7 +347,6 @@ device->IsToggleEnabled(Toggle::PolyFillPacked4x8DotProduct); req.hlsl.tintOptions.extensions.polyfill_pack_unpack_4x8 = device->IsToggleEnabled(Toggle::D3D12PolyFillPackUnpack4x8); - req.hlsl.tintOptions.polyfill_sample_mask = applySampleMaskPolyfill; req.hlsl.limits = LimitsForCompilationRequest::Create(device->GetLimits().v1); req.hlsl.adapterSupportedLimits = UnsafeUnserializedValue(
diff --git a/src/dawn/native/d3d12/ShaderModuleD3D12.h b/src/dawn/native/d3d12/ShaderModuleD3D12.h index 7201718..15df951 100644 --- a/src/dawn/native/d3d12/ShaderModuleD3D12.h +++ b/src/dawn/native/d3d12/ShaderModuleD3D12.h
@@ -60,7 +60,6 @@ SingleShaderStage stage, const PipelineLayout* layout, uint32_t compileFlags, - bool applySampleMaskPolyfill, const std::optional<dawn::native::d3d::InterStageShaderVariablesMask>& usedInterstageVariables = {});
diff --git a/src/dawn/native/metal/RenderPipelineMTL.mm b/src/dawn/native/metal/RenderPipelineMTL.mm index 52a120e..b88b5c5 100644 --- a/src/dawn/native/metal/RenderPipelineMTL.mm +++ b/src/dawn/native/metal/RenderPipelineMTL.mm
@@ -387,12 +387,11 @@ const PerStage<ProgrammableStage>& allStages = GetAllStages(); const ProgrammableStage& vertexStage = allStages[wgpu::ShaderStage::Vertex]; ShaderModule::MetalFunctionData vertexData; - const bool kApplySampleMaskPolyfill = false; - DAWN_TRY_CONTEXT(ToBackend(vertexStage.module.Get()) - ->CreateFunction(SingleShaderStage::Vertex, vertexStage, - ToBackend(GetLayout()), GetImmediateMask(), &vertexData, - 0xFFFFFFFF, this, kApplySampleMaskPolyfill), - " getting vertex MTLFunction for %s", this); + DAWN_TRY_CONTEXT( + ToBackend(vertexStage.module.Get()) + ->CreateFunction(SingleShaderStage::Vertex, vertexStage, ToBackend(GetLayout()), + GetImmediateMask(), &vertexData, 0xFFFFFFFF, this), + " getting vertex MTLFunction for %s", this); descriptorMTL.vertexFunction = vertexData.function.Get(); if (vertexData.needsStorageBufferLength) { @@ -402,14 +401,10 @@ ShaderModule::MetalFunctionData fragmentData; if (GetStageMask() & wgpu::ShaderStage::Fragment) { const ProgrammableStage& fragmentStage = allStages[wgpu::ShaderStage::Fragment]; - // This must be accurate in determining when Sample Shading is active. - // It cannot be conservatively correct because the polyfill changes behavior. - bool applySampleMaskPolyfill = UsesSampleMaskInput() && UseSampleRateShading(); DAWN_TRY_CONTEXT( ToBackend(fragmentStage.module.Get()) ->CreateFunction(SingleShaderStage::Fragment, fragmentStage, ToBackend(GetLayout()), - GetImmediateMask(), &fragmentData, GetSampleMask(), this, - applySampleMaskPolyfill), + GetImmediateMask(), &fragmentData, GetSampleMask(), this), " getting fragment MTLFunction for %s", this); descriptorMTL.fragmentFunction = fragmentData.function.Get();
diff --git a/src/dawn/native/metal/ShaderModuleMTL.h b/src/dawn/native/metal/ShaderModuleMTL.h index 4b5725c..c176c40 100644 --- a/src/dawn/native/metal/ShaderModuleMTL.h +++ b/src/dawn/native/metal/ShaderModuleMTL.h
@@ -69,8 +69,7 @@ const ImmediateMask& pipelineImmediateMask, MetalFunctionData* out, uint32_t sampleMask = 0xFFFFFFFF, - const RenderPipeline* renderPipeline = nullptr, - bool applySampleMaskPolyfill = false); + const RenderPipeline* renderPipeline = nullptr); private: ShaderModule(Device* device,
diff --git a/src/dawn/native/metal/ShaderModuleMTL.mm b/src/dawn/native/metal/ShaderModuleMTL.mm index 605a3fc..a8f09b9 100644 --- a/src/dawn/native/metal/ShaderModuleMTL.mm +++ b/src/dawn/native/metal/ShaderModuleMTL.mm
@@ -220,7 +220,6 @@ SingleShaderStage stage, const PipelineLayout* layout, uint32_t sampleMask, - bool applySampleMaskPolyfill, const RenderPipeline* renderPipeline, const BindingInfoArray& moduleBindingInfo, bool useStrictMath, @@ -322,7 +321,6 @@ req.tintOptions.disable_integer_range_analysis = !device->IsToggleEnabled(Toggle::EnableIntegerRangeAnalysisInRobustness); - req.tintOptions.polyfill_sample_mask = applySampleMaskPolyfill; req.tintOptions.fixed_sample_mask = sampleMask; req.tintOptions.emit_vertex_point_size = stage == SingleShaderStage::Vertex && @@ -472,8 +470,7 @@ const ImmediateMask& pipelineImmediateMask, ShaderModule::MetalFunctionData* out, uint32_t sampleMask, - const RenderPipeline* renderPipeline, - bool applySampleMaskPolyfill) { + const RenderPipeline* renderPipeline) { TRACE_EVENT1(GetDevice()->GetPlatform(), General, "metal::ShaderModule::CreateFunction", "label", utils::GetLabelForTrace(GetLabel())); @@ -490,8 +487,7 @@ CacheResult<MslCompilation> mslCompilation; DAWN_TRY_ASSIGN(mslCompilation, TranslateToMSL(GetDevice(), programmableStage, stage, layout, sampleMask, - applySampleMaskPolyfill, renderPipeline, - GetEntryPoint(entryPointName).bindings, + renderPipeline, GetEntryPoint(entryPointName).bindings, GetStrictMath().value_or(false), pipelineImmediateMask)); out->needsStorageBufferLength = mslCompilation->needsStorageBufferLength;
diff --git a/src/dawn/tests/end2end/MultisampledRenderingTests.cpp b/src/dawn/tests/end2end/MultisampledRenderingTests.cpp index ad89875..1e4874b 100644 --- a/src/dawn/tests/end2end/MultisampledRenderingTests.cpp +++ b/src/dawn/tests/end2end/MultisampledRenderingTests.cpp
@@ -1100,64 +1100,6 @@ VerifyResolveTarget(kGreen, resolveTexture2, 0, 0, kMSAACoverage); } -// Test that the sample_mask input builtin has only the bit for the current sample set -// when per-sample shading is active. -TEST_P(MultisampledRenderingTest, SampleMaskInputWithSampleShading) { - // TODO(crbug.com/522869943): Produces incorrect result on Pixel 10. - DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsImgTec() && IsVulkan()); - - // sample_mask is not supported in compat. - DAWN_TEST_UNSUPPORTED_IF(IsCompatibilityMode()); - - // TODO(crbug.com/dawn/673): Work around or enforce via validation that sample variables are not - // supported on some platforms. - DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("disable_sample_variables")); - - wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder(); - - // The fragment shader uses sample_index, which triggers per-sample shading. - // It verifies that the sample_mask input has only the bit for the current sample set. - const char* fs = R"( - struct U { - color : vec4f - } - @group(0) @binding(0) var<uniform> uBuffer : U; - - struct FragmentOut { - @location(0) color : vec4f, - } - - @fragment fn main(@builtin(sample_index) sampleIndex : u32, - @builtin(sample_mask) mask : u32) -> FragmentOut { - var output : FragmentOut; - if (mask == (1u << sampleIndex)) { - output.color = vec4f(0.0, 1.0, 0.0, 1.0); - } else { - output.color = vec4f(1.0, 0.0, 0.0, 1.0); - } - _ = uBuffer.color; - return output; - })"; - - wgpu::RenderPipeline pipeline = CreateRenderPipelineForTest(fs, 1, false); - - { - utils::ComboRenderPassDescriptor renderPass = - CreateComboRenderPassDescriptorForTest({mMultisampledColorView}, {mResolveView}, - wgpu::LoadOp::Clear, wgpu::LoadOp::Clear, false); - - EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, {0.0, 0.0, 0.0, 0.0}); - } - - wgpu::CommandBuffer commandBuffer = commandEncoder.Finish(); - queue.Submit(1, &commandBuffer); - - // All samples should have passed the check, so the resolved color should be green. - // We check pixel {2, 0} which is fully covered by the triangle. - utils::RGBA8 expectedColor = {0, 255, 0, 255}; - EXPECT_TEXTURE_EQ(&expectedColor, mResolveTexture, {2, 0}, {1, 1}); -} - // Test using one multisampled color attachment with resolve target can render correctly // with alphaToCoverageEnabled. TEST_P(MultisampledRenderingTest, ResolveInto2DTextureWithAlphaToCoverage) {
diff --git a/src/tint/lang/hlsl/writer/common/options.h b/src/tint/lang/hlsl/writer/common/options.h index 5b54124..c829c97 100644 --- a/src/tint/lang/hlsl/writer/common/options.h +++ b/src/tint/lang/hlsl/writer/common/options.h
@@ -256,9 +256,6 @@ /// Offsets of num_workgroups push constant. std::optional<uint32_t> num_workgroups_start_offset; - /// Set to `true` to generate polyfill for `sampleMask` builtin - bool polyfill_sample_mask = false; - /// The bindings Bindings bindings; @@ -295,7 +292,6 @@ first_index_offset, first_instance_offset, num_workgroups_start_offset, - polyfill_sample_mask, bindings, ignored_by_robustness_transform, pixel_local,
diff --git a/src/tint/lang/hlsl/writer/raise/raise.cc b/src/tint/lang/hlsl/writer/raise/raise.cc index 484688b..75a7514 100644 --- a/src/tint/lang/hlsl/writer/raise/raise.cc +++ b/src/tint/lang/hlsl/writer/raise/raise.cc
@@ -285,7 +285,7 @@ .first_index_offset = options.first_index_offset, .first_instance_offset = options.first_instance_offset, .num_workgroups_start_offset = options.num_workgroups_start_offset, - .polyfill_sample_mask = options.polyfill_sample_mask}; + }; TINT_CHECK_RESULT(raise::ShaderIO(module, config)); }
diff --git a/src/tint/lang/hlsl/writer/raise/shader_io.cc b/src/tint/lang/hlsl/writer/raise/shader_io.cc index 5fd7a99..11f31f1 100644 --- a/src/tint/lang/hlsl/writer/raise/shader_io.cc +++ b/src/tint/lang/hlsl/writer/raise/shader_io.cc
@@ -71,8 +71,6 @@ std::optional<uint32_t> subgroup_size_index; std::optional<uint32_t> num_subgroups_index; std::optional<uint32_t> num_workgroups_index; - std::optional<uint32_t> sample_mask_index; - std::optional<uint32_t> sample_index_index; std::optional<uint32_t> local_invocation_index_index; std::optional<uint32_t> first_clip_distance_index; std::optional<uint32_t> second_clip_distance_index; @@ -264,11 +262,6 @@ RequireBuiltinInput(core::BuiltinValue::kGlobalInvocationId, ty.vec3u(), "global_invocation_id"); } - if (config.polyfill_sample_mask && - func->Stage() == core::ir::Function::PipelineStage::kFragment && - HasBuiltinInput(core::BuiltinValue::kSampleMask)) { - RequireBuiltinInput(core::BuiltinValue::kSampleIndex, ty.u32(), "sample_index"); - } Vector<MemberInfo, 4> input_data; bool has_vertex_or_instance_index = false; @@ -287,10 +280,6 @@ num_subgroups_index = i; } else if (*builtin == core::BuiltinValue::kNumWorkgroups) { num_workgroups_index = i; - } else if (*builtin == core::BuiltinValue::kSampleMask) { - sample_mask_index = i; - } else if (*builtin == core::BuiltinValue::kSampleIndex) { - sample_index_index = i; } else if (*builtin == core::BuiltinValue::kLocalInvocationIndex) { local_invocation_index_index = i; } else if (*builtin == core::BuiltinValue::kVertexIndex) { @@ -521,7 +510,7 @@ // // @compute @workgroup_size(...) // fn main(...) { - // // Initialize the counter to zero. + // // Initializer the counter to zero. // atomicStore(&tint_subgroup_id_counter, 0u); // workgroupBarrier(); // @@ -635,17 +624,8 @@ } auto index = input_indices[idx]; - auto* v = builder.Access(inputs[idx].type, input_param, u32(index))->Result(); - if (config.polyfill_sample_mask && sample_mask_index == idx) { - // In Sample Shading mode only the sample for the fragment should be set in the sample - // mask. The behavior of HLSL is to include the full raster sample mask. This is not in - // line with WGSL spec and so we remove this additional information via a bitwise and. - TINT_IR_ASSERT(ir, sample_index_index.has_value()); - auto* sample_index = GetInput(builder, sample_index_index.value()); - auto* mask = builder.ShiftLeft(1_u, sample_index); - return builder.And(v, mask)->Result(); - } + core::ir::Value* v = builder.Access(inputs[idx].type, input_param, u32(index))->Result(); if (inputs[idx].attributes.builtin == core::BuiltinValue::kPosition) { // If this is an input position builtin we need to invert the 'w' component of the @@ -653,45 +633,37 @@ auto* w = builder.Access(ty.f32(), v, 3_u); auto* div = builder.Divide(1.0_f, w); auto* swizzle = builder.Swizzle(ty.vec3f(), v, {0, 1, 2}); - return builder.Construct(ty.vec4f(), swizzle, div)->Result(); - } - - if (config.first_index_offset_binding.has_value() && - inputs[idx].attributes.builtin == core::BuiltinValue::kVertexIndex) { + v = builder.Construct(ty.vec4f(), swizzle, div)->Result(); + } else if (config.first_index_offset_binding.has_value() && + inputs[idx].attributes.builtin == core::BuiltinValue::kVertexIndex) { // Apply vertex_index offset TINT_IR_ASSERT(ir, tint_first_index_offset); auto* vertex_index_offset = builder.Access(ty.ptr<uniform, u32>(), tint_first_index_offset, 0_u); - return builder.Add(v, builder.Load(vertex_index_offset))->Result(); - } - - if (config.first_index_offset_binding.has_value() && - inputs[idx].attributes.builtin == core::BuiltinValue::kInstanceIndex) { + v = builder.Add(v, builder.Load(vertex_index_offset))->Result(); + } else if (config.first_index_offset_binding.has_value() && + inputs[idx].attributes.builtin == core::BuiltinValue::kInstanceIndex) { // Apply instance_index offset TINT_IR_ASSERT(ir, tint_first_index_offset); auto* instance_index_offset = builder.Access(ty.ptr<uniform, u32>(), tint_first_index_offset, 1_u); - return builder.Add(v, builder.Load(instance_index_offset))->Result(); - } - - if (config.first_index_offset.has_value() && - inputs[idx].attributes.builtin == core::BuiltinValue::kVertexIndex) { + v = builder.Add(v, builder.Load(instance_index_offset))->Result(); + } else if (config.first_index_offset.has_value() && + inputs[idx].attributes.builtin == core::BuiltinValue::kVertexIndex) { auto* immediate_data = config.immediate_data_layout.var; auto first_index_offset_idx = u32(config.immediate_data_layout.IndexOf(config.first_index_offset.value())); auto first_index_offset = builder.Access<ptr<immediate, u32>>(immediate_data, first_index_offset_idx); - return builder.Add(v, builder.Load(first_index_offset))->Result(); - } - - if (config.first_instance_offset.has_value() && - inputs[idx].attributes.builtin == core::BuiltinValue::kInstanceIndex) { + v = builder.Add(v, builder.Load(first_index_offset))->Result(); + } else if (config.first_instance_offset.has_value() && + inputs[idx].attributes.builtin == core::BuiltinValue::kInstanceIndex) { auto* immediate_data = config.immediate_data_layout.var; auto first_instance_offset_idx = u32(config.immediate_data_layout.IndexOf(config.first_instance_offset.value())); auto first_instance_offset = builder.Access<ptr<immediate, u32>>(immediate_data, first_instance_offset_idx); - return builder.Add(v, builder.Load(first_instance_offset))->Result(); + v = builder.Add(v, builder.Load(first_instance_offset))->Result(); } return v;
diff --git a/src/tint/lang/hlsl/writer/raise/shader_io.h b/src/tint/lang/hlsl/writer/raise/shader_io.h index 52ca25c..27a4eff 100644 --- a/src/tint/lang/hlsl/writer/raise/shader_io.h +++ b/src/tint/lang/hlsl/writer/raise/shader_io.h
@@ -77,9 +77,6 @@ /// Offsets of num_workgroups push constant. std::optional<uint32_t> num_workgroups_start_offset = std::nullopt; - - /// Set to `true` to generate polyfill for `sample_mask` builtin - bool polyfill_sample_mask = false; }; /// ShaderIO is a transform that prepares entry point inputs and outputs for HLSL codegen.
diff --git a/src/tint/lang/hlsl/writer/raise/shader_io_test.cc b/src/tint/lang/hlsl/writer/raise/shader_io_test.cc index 75ddf25..08725f2 100644 --- a/src/tint/lang/hlsl/writer/raise/shader_io_test.cc +++ b/src/tint/lang/hlsl/writer/raise/shader_io_test.cc
@@ -4737,60 +4737,6 @@ EXPECT_EQ(expect, str()); } -TEST_F(HlslWriterTransformTest, SampleMaskPolyfill) { - auto* sample_mask = b.FunctionParam("sample_mask", ty.u32()); - sample_mask->SetBuiltin(core::BuiltinValue::kSampleMask); - - auto* ep = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment); - ep->SetParams({sample_mask}); - - b.Append(ep->Block(), [&] { - b.Let("mask", sample_mask); - b.Return(ep); - }); - - auto* src = R"( -%foo = @fragment func(%sample_mask:u32 [@sample_mask]):void { - $B1: { - %mask:u32 = let %sample_mask - ret - } -} -)"; - EXPECT_EQ(src, str()); - - auto* expect = R"( -foo_inputs = struct @align(4) { - sample_index:u32 @offset(0), @builtin(sample_index) - sample_mask:u32 @offset(4), @builtin(sample_mask) -} - -%foo_inner = func(%sample_mask:u32):void { - $B1: { - %mask:u32 = let %sample_mask - ret - } -} -%foo = @fragment func(%inputs:foo_inputs):void { - $B2: { - %6:u32 = access %inputs, 1u - %7:u32 = access %inputs, 0u - %8:u32 = shl 1u, %7 - %9:u32 = and %6, %8 - %10:void = call %foo_inner, %9 - ret - } -} -)"; - - core::ir::transform::ImmediateDataLayout immediate_data_2; - ShaderIOConfig config_2{immediate_data_2}; - config_2.polyfill_sample_mask = true; - Run(ShaderIO, config_2); - - EXPECT_EQ(expect, str()); -} - TEST_F(HlslWriterTransformTest, ShaderIOParameters_WorkgroupIndex_AddMissingBuiltins) { auto* workgroup_index = b.FunctionParam("wgindex", ty.u32()); workgroup_index->SetBuiltin(core::BuiltinValue::kWorkgroupIndex); @@ -4993,174 +4939,5 @@ EXPECT_EQ(expect, str()); } -TEST_F(HlslWriterTransformTest, SampleMaskPolyfill_WithExistingSampleIndex) { - auto* sample_mask = b.FunctionParam("sample_mask", ty.u32()); - sample_mask->SetBuiltin(core::BuiltinValue::kSampleMask); - - auto* sample_index = b.FunctionParam("sample_index", ty.u32()); - sample_index->SetBuiltin(core::BuiltinValue::kSampleIndex); - - auto* ep = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment); - ep->SetParams({sample_mask, sample_index}); - - b.Append(ep->Block(), [&] { - b.Let("mask", sample_mask); - b.Let("idx", sample_index); - b.Return(ep); - }); - - auto* src = R"( -%foo = @fragment func(%sample_mask:u32 [@sample_mask], %sample_index:u32 [@sample_index]):void { - $B1: { - %mask:u32 = let %sample_mask - %idx:u32 = let %sample_index - ret - } -} -)"; - EXPECT_EQ(src, str()); - - auto* expect = R"( -foo_inputs = struct @align(4) { - sample_index:u32 @offset(0), @builtin(sample_index) - sample_mask:u32 @offset(4), @builtin(sample_mask) -} - -%foo_inner = func(%sample_mask:u32, %sample_index:u32):void { - $B1: { - %mask:u32 = let %sample_mask - %idx:u32 = let %sample_index - ret - } -} -%foo = @fragment func(%inputs:foo_inputs):void { - $B2: { - %8:u32 = access %inputs, 1u - %9:u32 = access %inputs, 0u - %10:u32 = shl 1u, %9 - %11:u32 = and %8, %10 - %12:u32 = access %inputs, 0u - %13:void = call %foo_inner, %11, %12 - ret - } -} -)"; - - core::ir::transform::ImmediateDataLayout immediate_data; - ShaderIOConfig config{immediate_data}; - config.polyfill_sample_mask = true; - Run(ShaderIO, config); - - EXPECT_EQ(expect, str()); -} - -TEST_F(HlslWriterTransformTest, SampleMaskPolyfill_Disabled) { - auto* sample_mask = b.FunctionParam("sample_mask", ty.u32()); - sample_mask->SetBuiltin(core::BuiltinValue::kSampleMask); - - auto* ep = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment); - ep->SetParams({sample_mask}); - - b.Append(ep->Block(), [&] { - b.Let("mask", sample_mask); - b.Return(ep); - }); - - auto* src = R"( -%foo = @fragment func(%sample_mask:u32 [@sample_mask]):void { - $B1: { - %mask:u32 = let %sample_mask - ret - } -} -)"; - EXPECT_EQ(src, str()); - - auto* expect = R"( -foo_inputs = struct @align(4) { - sample_mask:u32 @offset(0), @builtin(sample_mask) -} - -%foo_inner = func(%sample_mask:u32):void { - $B1: { - %mask:u32 = let %sample_mask - ret - } -} -%foo = @fragment func(%inputs:foo_inputs):void { - $B2: { - %6:u32 = access %inputs, 0u - %7:void = call %foo_inner, %6 - ret - } -} -)"; - - core::ir::transform::ImmediateDataLayout immediate_data; - ShaderIOConfig config{immediate_data}; - config.polyfill_sample_mask = false; - Run(ShaderIO, config); - - EXPECT_EQ(expect, str()); -} - -TEST_F(HlslWriterTransformTest, SampleMaskPolyfill_Disabled_WithExistingSampleIndex) { - auto* sample_mask = b.FunctionParam("sample_mask", ty.u32()); - sample_mask->SetBuiltin(core::BuiltinValue::kSampleMask); - - auto* sample_index = b.FunctionParam("sample_index", ty.u32()); - sample_index->SetBuiltin(core::BuiltinValue::kSampleIndex); - - auto* ep = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment); - ep->SetParams({sample_mask, sample_index}); - - b.Append(ep->Block(), [&] { - b.Let("mask", sample_mask); - b.Let("idx", sample_index); - b.Return(ep); - }); - - auto* src = R"( -%foo = @fragment func(%sample_mask:u32 [@sample_mask], %sample_index:u32 [@sample_index]):void { - $B1: { - %mask:u32 = let %sample_mask - %idx:u32 = let %sample_index - ret - } -} -)"; - EXPECT_EQ(src, str()); - - auto* expect = R"( -foo_inputs = struct @align(4) { - sample_index:u32 @offset(0), @builtin(sample_index) - sample_mask:u32 @offset(4), @builtin(sample_mask) -} - -%foo_inner = func(%sample_mask:u32, %sample_index:u32):void { - $B1: { - %mask:u32 = let %sample_mask - %idx:u32 = let %sample_index - ret - } -} -%foo = @fragment func(%inputs:foo_inputs):void { - $B2: { - %8:u32 = access %inputs, 1u - %9:u32 = access %inputs, 0u - %10:void = call %foo_inner, %8, %9 - ret - } -} -)"; - - core::ir::transform::ImmediateDataLayout immediate_data; - ShaderIOConfig config{immediate_data}; - config.polyfill_sample_mask = false; - Run(ShaderIO, config); - - EXPECT_EQ(expect, str()); -} - } // namespace } // namespace tint::hlsl::writer::raise
diff --git a/src/tint/lang/hlsl/writer/writer_fuzz.cc b/src/tint/lang/hlsl/writer/writer_fuzz.cc index 78b76e5..181e316 100644 --- a/src/tint/lang/hlsl/writer/writer_fuzz.cc +++ b/src/tint/lang/hlsl/writer/writer_fuzz.cc
@@ -65,7 +65,6 @@ std::vector<BindingPoint> ignored_by_robustness_transform; SubstituteOverridesConfig substitute_overrides_config; bool d3d12_decompose_workgroup_access; - bool polyfill_sample_mask; bool collapse_subgroup_min_max; /// Reflect the fields of this class so that it can be used by tint::ForeachField() @@ -89,7 +88,6 @@ ignored_by_robustness_transform, substitute_overrides_config, d3d12_decompose_workgroup_access, - polyfill_sample_mask, collapse_subgroup_min_max); }; @@ -145,7 +143,6 @@ options.first_index_offset = fuzzed_options.first_index_offset; options.first_instance_offset = fuzzed_options.first_instance_offset; options.num_workgroups_start_offset = fuzzed_options.num_workgroups_start_offset; - options.polyfill_sample_mask = fuzzed_options.polyfill_sample_mask; options.ignored_by_robustness_transform = fuzzed_options.ignored_by_robustness_transform; options.substitute_overrides_config = fuzzed_options.substitute_overrides_config;
diff --git a/src/tint/lang/msl/writer/common/options.h b/src/tint/lang/msl/writer/common/options.h index c4c17ee..0d82090 100644 --- a/src/tint/lang/msl/writer/common/options.h +++ b/src/tint/lang/msl/writer/common/options.h
@@ -211,9 +211,6 @@ /// Any used extensions Extensions extensions{}; - /// Set to `true` to generate polyfill for `sample_mask` builtin - bool polyfill_sample_mask = false; - /// The fixed sample mask to combine with fragment shader outputs. /// Defaults to 0xFFFFFFFF. uint32_t fixed_sample_mask = 0xFFFFFFFF; @@ -256,7 +253,6 @@ use_argument_buffers, workarounds, extensions, - polyfill_sample_mask, fixed_sample_mask, pixel_local_attachments, array_length_from_constants,
diff --git a/src/tint/lang/msl/writer/raise/raise.cc b/src/tint/lang/msl/writer/raise/raise.cc index 43e1c29..e340bcf 100644 --- a/src/tint/lang/msl/writer/raise/raise.cc +++ b/src/tint/lang/msl/writer/raise/raise.cc
@@ -227,8 +227,7 @@ TINT_CHECK_RESULT(raise::ShaderIO( module, raise::ShaderIOConfig{immediate_data_layout, options.emit_vertex_point_size, - options.polyfill_sample_mask, options.fixed_sample_mask, - options.depth_range_offsets})); + options.fixed_sample_mask, options.depth_range_offsets})); raise::FixTypeLayoutOptions fix_type_layout_options{ .replace_bool_with_u32 = options.workarounds.replace_workgroup_bool_with_u32,
diff --git a/src/tint/lang/msl/writer/raise/shader_io.cc b/src/tint/lang/msl/writer/raise/shader_io.cc index e075a57..7e6cac0 100644 --- a/src/tint/lang/msl/writer/raise/shader_io.cc +++ b/src/tint/lang/msl/writer/raise/shader_io.cc
@@ -72,8 +72,6 @@ std::optional<uint32_t> workgroup_index_index; std::optional<uint32_t> workgroup_id_index; std::optional<uint32_t> num_workgroups_index; - std::optional<uint32_t> sample_mask_index; - std::optional<uint32_t> sample_index_index; /// Constructor StateImpl(core::ir::Module& mod, core::ir::Function* f, const ShaderIOConfig& cfg) @@ -107,11 +105,6 @@ RequireBuiltinInput(core::BuiltinValue::kGlobalInvocationId, ty.vec3u(), "global_invocation_id"); } - if (config.polyfill_sample_mask && - func->Stage() == core::ir::Function::PipelineStage::kFragment && - HasBuiltinInput(core::BuiltinValue::kSampleMask)) { - RequireBuiltinInput(core::BuiltinValue::kSampleIndex, ty.u32(), "sample_index"); - } Vector<core::type::Manager::StructMemberDesc, 4> input_struct_members; core::ir::FunctionParam* input_struct_param = nullptr; @@ -141,12 +134,6 @@ case core::BuiltinValue::kNumWorkgroups: num_workgroups_index = index; break; - case core::BuiltinValue::kSampleMask: - sample_mask_index = index; - break; - case core::BuiltinValue::kSampleIndex: - sample_index_index = index; - break; default: break; } @@ -230,21 +217,11 @@ auto index = input_indices[idx]; auto* param = input_params[index.param_index]; - core::ir::Value* v = nullptr; if (param->Type()->Is<core::type::Struct>()) { - v = builder.Access(inputs[idx].type, param, u32(index.member_index))->Result(); + return builder.Access(inputs[idx].type, param, u32(index.member_index))->Result(); } else { - v = param; + return param; } - - if (config.polyfill_sample_mask && idx == sample_mask_index) { - TINT_IR_ASSERT(ir, sample_index_index.has_value()); - auto* sample_index = GetInput(builder, sample_index_index.value()); - auto* mask = builder.ShiftLeft(1_u, sample_index); - return builder.And(v, mask)->Result(); - } - - return v; } /// @copydoc ShaderIO::BackendState::SetOutput
diff --git a/src/tint/lang/msl/writer/raise/shader_io.h b/src/tint/lang/msl/writer/raise/shader_io.h index a3d7a6e..2000c36 100644 --- a/src/tint/lang/msl/writer/raise/shader_io.h +++ b/src/tint/lang/msl/writer/raise/shader_io.h
@@ -48,8 +48,6 @@ /// true if a vertex point size builtin output should be added bool emit_vertex_point_size = false; - /// Set to `true` to generate polyfill for `sample_mask` builtin - bool polyfill_sample_mask = false; /// A fixed sample mask to combine into masks produced by fragment shaders. uint32_t fixed_sample_mask = UINT32_MAX;
diff --git a/src/tint/lang/msl/writer/raise/shader_io_test.cc b/src/tint/lang/msl/writer/raise/shader_io_test.cc index b303dac..f5ec594 100644 --- a/src/tint/lang/msl/writer/raise/shader_io_test.cc +++ b/src/tint/lang/msl/writer/raise/shader_io_test.cc
@@ -1619,150 +1619,5 @@ EXPECT_EQ(expect, str()); } -TEST_F(MslWriter_ShaderIOTest, SampleMaskPolyfill) { - auto* sample_mask = b.FunctionParam("sample_mask", ty.u32()); - sample_mask->SetBuiltin(core::BuiltinValue::kSampleMask); - - auto* ep = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment); - ep->SetParams({sample_mask}); - - b.Append(ep->Block(), [&] { - b.Let("mask", sample_mask); - b.Return(ep); - }); - - auto* src = R"( -%foo = @fragment func(%sample_mask:u32 [@sample_mask]):void { - $B1: { - %mask:u32 = let %sample_mask - ret - } -} -)"; - EXPECT_EQ(src, str()); - - auto* expect = R"( -%foo_inner = func(%sample_mask:u32):void { - $B1: { - %mask:u32 = let %sample_mask - ret - } -} -%foo = @fragment func(%sample_mask_1:u32 [@sample_mask], %sample_index:u32 [@sample_index]):void { # %sample_mask_1: 'sample_mask' - $B2: { - %7:u32 = shl 1u, %sample_index - %8:u32 = and %sample_mask_1, %7 - %9:void = call %foo_inner, %8 - ret - } -} -)"; - - core::ir::transform::ImmediateDataLayout immediate_data; - ShaderIOConfig config{immediate_data}; - config.polyfill_sample_mask = true; - Run(ShaderIO, config); - - EXPECT_EQ(expect, str()); -} - -TEST_F(MslWriter_ShaderIOTest, SampleMaskPolyfill_WithExistingSampleIndex) { - auto* sample_mask = b.FunctionParam("sample_mask", ty.u32()); - sample_mask->SetBuiltin(core::BuiltinValue::kSampleMask); - - auto* sample_index = b.FunctionParam("sample_index", ty.u32()); - sample_index->SetBuiltin(core::BuiltinValue::kSampleIndex); - - auto* ep = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment); - ep->SetParams({sample_mask, sample_index}); - - b.Append(ep->Block(), [&] { - b.Let("mask", sample_mask); - b.Let("idx", sample_index); - b.Return(ep); - }); - - auto* src = R"( -%foo = @fragment func(%sample_mask:u32 [@sample_mask], %sample_index:u32 [@sample_index]):void { - $B1: { - %mask:u32 = let %sample_mask - %idx:u32 = let %sample_index - ret - } -} -)"; - EXPECT_EQ(src, str()); - - auto* expect = R"( -%foo_inner = func(%sample_mask:u32, %sample_index:u32):void { - $B1: { - %mask:u32 = let %sample_mask - %idx:u32 = let %sample_index - ret - } -} -%foo = @fragment func(%sample_mask_1:u32 [@sample_mask], %sample_index_1:u32 [@sample_index]):void { # %sample_mask_1: 'sample_mask', %sample_index_1: 'sample_index' - $B2: { - %9:u32 = shl 1u, %sample_index_1 - %10:u32 = and %sample_mask_1, %9 - %11:void = call %foo_inner, %10, %sample_index_1 - ret - } -} -)"; - - core::ir::transform::ImmediateDataLayout immediate_data; - ShaderIOConfig config{immediate_data}; - config.polyfill_sample_mask = true; - Run(ShaderIO, config); - - EXPECT_EQ(expect, str()); -} - -TEST_F(MslWriter_ShaderIOTest, SampleMaskPolyfill_Disabled) { - auto* sample_mask = b.FunctionParam("sample_mask", ty.u32()); - sample_mask->SetBuiltin(core::BuiltinValue::kSampleMask); - - auto* ep = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment); - ep->SetParams({sample_mask}); - - b.Append(ep->Block(), [&] { - b.Let("mask", sample_mask); - b.Return(ep); - }); - - auto* src = R"( -%foo = @fragment func(%sample_mask:u32 [@sample_mask]):void { - $B1: { - %mask:u32 = let %sample_mask - ret - } -} -)"; - EXPECT_EQ(src, str()); - - auto* expect = R"( -%foo_inner = func(%sample_mask:u32):void { - $B1: { - %mask:u32 = let %sample_mask - ret - } -} -%foo = @fragment func(%sample_mask_1:u32 [@sample_mask]):void { # %sample_mask_1: 'sample_mask' - $B2: { - %6:void = call %foo_inner, %sample_mask_1 - ret - } -} -)"; - - core::ir::transform::ImmediateDataLayout immediate_data; - ShaderIOConfig config{immediate_data}; - config.polyfill_sample_mask = false; - Run(ShaderIO, config); - - EXPECT_EQ(expect, str()); -} - } // namespace } // namespace tint::msl::writer::raise
diff --git a/src/tint/lang/msl/writer/writer_fuzz.cc b/src/tint/lang/msl/writer/writer_fuzz.cc index 83b10c2..50fbe5d 100644 --- a/src/tint/lang/msl/writer/writer_fuzz.cc +++ b/src/tint/lang/msl/writer/writer_fuzz.cc
@@ -62,7 +62,6 @@ SubstituteOverridesConfig substitute_overrides_config; bool polyfill_tanh_f16; bool replace_workgroup_bool_with_u32; - bool polyfill_sample_mask; bool collapse_subgroup_min_max; bool fix_u32_div_mod; @@ -87,7 +86,6 @@ substitute_overrides_config, polyfill_tanh_f16, replace_workgroup_bool_with_u32, - polyfill_sample_mask, collapse_subgroup_min_max, fix_u32_div_mod); TINT_REFLECT_HASH_CODE(FuzzedOptions); @@ -142,7 +140,6 @@ options.workarounds.polyfill_tanh_f16 = fuzzed_options.polyfill_tanh_f16; options.workarounds.replace_workgroup_bool_with_u32 = fuzzed_options.replace_workgroup_bool_with_u32; - options.polyfill_sample_mask = fuzzed_options.polyfill_sample_mask; options.workarounds.collapse_subgroup_min_max = fuzzed_options.collapse_subgroup_min_max; options.fixed_sample_mask = fuzzed_options.fixed_sample_mask; options.pixel_local_attachments = fuzzed_options.pixel_local_attachments;
diff --git a/webgpu-cts/expectations.txt b/webgpu-cts/expectations.txt index 624830c..cdeaa18 100644 --- a/webgpu-cts/expectations.txt +++ b/webgpu-cts/expectations.txt
@@ -208,10 +208,10 @@ crbug.com/474820386 webgpu:shader,validation,types,pointer:ptr_not_instantiable:case="workgroupRTArray" [ Skip ] crbug.com/474820386 webgpu:shader,validation,types,pointer:ptr_not_instantiable:case="privateRTArray" [ Skip ] -# Must skip on HLSL backends while we change behavior of CTS +# Must skip on HLSL backends while we change behavior of CTS sample_mask crbug.com/407144390 [ win ] webgpu:shader,execution,shader_io,fragment_builtins:inputs,sample_mask:nearFar=*;sampleCount=4;interpolation={"type":"*","sampling":"sample"} [ Failure ] -# And Must skip on MSL backends while we change behavior of CTS +# And Must skip on MSL backends while we change behavior of CTS sample_mask crbug.com/407144390 [ mac ] webgpu:shader,execution,shader_io,fragment_builtins:inputs,sample_mask:nearFar=*;sampleCount=4;interpolation={"type":"*","sampling":"sample"} [ Failure ] # SharedImage interop failures on Linux