diff --git a/src/dawn/native/Toggles.cpp b/src/dawn/native/Toggles.cpp index e09d41922f..72f59a182b 100644 --- a/src/dawn/native/Toggles.cpp +++ b/src/dawn/native/Toggles.cpp @@ -374,6 +374,12 @@ static constexpr ToggleEnumAndInfoList kToggleNameAndInfoList = {{ "Use a blit to copy from a depth texture to the nonzero subresource of a depth texture. " "Works around an issue where nonzero layers are not written.", "https://crbug.com/dawn/1083", ToggleStage::Device}}, + {Toggle::D3D12ReplaceAddWithMinusWhenDstFactorIsZeroAndSrcFactorIsDstAlpha, + {"d3d12_replace_add_with_minus_when_dst_factor_is_zero_and_src_factor_is_dst_alpha", + "Replace the blending operation 'Add' with 'Minus' when dstBlendFactor is 'Zero' and " + "srcBlendFactor is 'DstAlpha'. Works around an Intel D3D12 driver issue about alpha " + "blending.", + "https://crbug.com/dawn/1579", ToggleStage::Device}}, {Toggle::DisallowDeprecatedAPIs, {"disallow_deprecated_apis", "Disallow all deprecated paths by changing the deprecation warnings to validation error for " @@ -392,10 +398,10 @@ static constexpr ToggleEnumAndInfoList kToggleNameAndInfoList = {{ "MacOS Intel < Gen9 has a bug where indirect base vertex is not applied for " "drawIndexedIndirect. Draws are done as if it is always zero.", "https://crbug.com/dawn/966", ToggleStage::Device}}, - {Toggle::NoWorkaroundDstAlphaBlendDoesNotWork, - {"no_workaround_dst_alpha_blend_does_not_work", - "Using D3D12_BLEND_DEST_ALPHA as blend factor doesn't work correctly on the D3D12 backend " - "using Intel Gen9 or Gen9.5 GPUs.", + {Toggle::NoWorkaroundDstAlphaAsSrcBlendFactorForBothColorAndAlphaDoesNotWork, + {"no_workaround_dst_alpha_as_src_blend_factor_for_both_color_and_alpha_does_not_work", + "Using D3D12_BLEND_DEST_ALPHA as source blend factor for both color and alpha blending " + "doesn't work correctly on the D3D12 backend using Intel Gen9 or Gen9.5 GPUs.", "https://crbug.com/dawn/1579", ToggleStage::Device}}, // Comment to separate the }} so it is clearer what to copy-paste to add a toggle. }}; diff --git a/src/dawn/native/Toggles.h b/src/dawn/native/Toggles.h index 901bb76a93..536a3fb207 100644 --- a/src/dawn/native/Toggles.h +++ b/src/dawn/native/Toggles.h @@ -90,12 +90,13 @@ enum class Toggle { UseBlitForBufferToDepthTextureCopy, UseBlitForBufferToStencilTextureCopy, UseBlitForDepthTextureToTextureCopyToNonzeroSubresource, + D3D12ReplaceAddWithMinusWhenDstFactorIsZeroAndSrcFactorIsDstAlpha, DisallowDeprecatedAPIs, // Unresolved issues. NoWorkaroundSampleMaskBecomesZeroForAllButLastColorTarget, NoWorkaroundIndirectBaseVertexNotApplied, - NoWorkaroundDstAlphaBlendDoesNotWork, + NoWorkaroundDstAlphaAsSrcBlendFactorForBothColorAndAlphaDoesNotWork, EnumCount, InvalidEnum = EnumCount, diff --git a/src/dawn/native/d3d12/AdapterD3D12.cpp b/src/dawn/native/d3d12/AdapterD3D12.cpp index 8676cae10a..4381234ea6 100644 --- a/src/dawn/native/d3d12/AdapterD3D12.cpp +++ b/src/dawn/native/d3d12/AdapterD3D12.cpp @@ -562,7 +562,14 @@ void Adapter::SetupBackendDeviceToggles(TogglesState* deviceToggles) const { // Currently this toggle is only needed on Intel Gen9 and Gen9.5 GPUs. // See http://crbug.com/dawn/1579 for more information. if (gpu_info::IsIntelGen9(vendorId, deviceId)) { - deviceToggles->ForceSet(Toggle::NoWorkaroundDstAlphaBlendDoesNotWork, true); + // We can add workaround when the blending operation is "Add", DstFactor is "Zero" and + // SrcFactor is "DstAlpha". + deviceToggles->ForceSet( + Toggle::D3D12ReplaceAddWithMinusWhenDstFactorIsZeroAndSrcFactorIsDstAlpha, true); + + // Unfortunately we cannot add workaround for other cases. + deviceToggles->ForceSet( + Toggle::NoWorkaroundDstAlphaAsSrcBlendFactorForBothColorAndAlphaDoesNotWork, true); } #if D3D12_SDK_VERSION >= 602 diff --git a/src/dawn/native/d3d12/RenderPipelineD3D12.cpp b/src/dawn/native/d3d12/RenderPipelineD3D12.cpp index d72422ec58..563dab69a5 100644 --- a/src/dawn/native/d3d12/RenderPipelineD3D12.cpp +++ b/src/dawn/native/d3d12/RenderPipelineD3D12.cpp @@ -257,6 +257,18 @@ D3D12_RENDER_TARGET_BLEND_DESC ComputeColorDesc(const DeviceBase* device, blendDesc.SrcBlendAlpha = D3D12AlphaBlend(state->blend->alpha.srcFactor); blendDesc.DestBlendAlpha = D3D12AlphaBlend(state->blend->alpha.dstFactor); blendDesc.BlendOpAlpha = D3D12BlendOperation(state->blend->alpha.operation); + + if (device->IsToggleEnabled( + Toggle::D3D12ReplaceAddWithMinusWhenDstFactorIsZeroAndSrcFactorIsDstAlpha) && + blendDesc.SrcBlend == D3D12_BLEND_DEST_ALPHA && + blendDesc.SrcBlendAlpha == D3D12_BLEND_DEST_ALPHA && + blendDesc.BlendOp == D3D12_BLEND_OP_ADD && + blendDesc.BlendOpAlpha == D3D12_BLEND_OP_ADD && + blendDesc.DestBlend == D3D12_BLEND_ZERO && + blendDesc.DestBlendAlpha == D3D12_BLEND_ZERO) { + blendDesc.BlendOp = D3D12_BLEND_OP_SUBTRACT; + blendDesc.BlendOpAlpha = D3D12_BLEND_OP_SUBTRACT; + } } blendDesc.RenderTargetWriteMask = D3D12RenderTargetWriteMask(state->writeMask); blendDesc.LogicOpEnable = false; diff --git a/src/dawn/tests/end2end/ColorStateTests.cpp b/src/dawn/tests/end2end/ColorStateTests.cpp index b6dd0912e2..0216eaebfb 100644 --- a/src/dawn/tests/end2end/ColorStateTests.cpp +++ b/src/dawn/tests/end2end/ColorStateTests.cpp @@ -1173,6 +1173,21 @@ TEST_P(ColorStateTest, SparseAttachmentsDifferentColorMask) { EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kGreen, attachment3, 0, 0); } +// This is a regression test against an Intel driver issue about using DstAlpha as +// SrcBlendFactor for both color and alpha blend factors. +TEST_P(ColorStateTest, SrcBlendFactorDstAlphaDstBlendFactorZero) { + utils::RGBA8 base(32, 64, 128, 192); + std::vector> tests; + std::transform(kColors.begin(), kColors.end(), std::back_inserter(tests), + [&](const utils::RGBA8& color) { + utils::RGBA8 fac(base.a, base.a, base.a, base.a); + utils::RGBA8 expected = mix(utils::RGBA8(0, 0, 0, 0), color, fac); + return std::make_pair(TriangleSpec({{color}}), expected); + }); + CheckBlendFactor(base, wgpu::BlendFactor::DstAlpha, wgpu::BlendFactor::Zero, + wgpu::BlendFactor::DstAlpha, wgpu::BlendFactor::Zero, tests); +} + DAWN_INSTANTIATE_TEST(ColorStateTest, D3D12Backend(), MetalBackend(),