D3D12: Add workaround for DstAlpha blend factor issue on Intel GPUs

On Intel Gen9 and Gen9.5 GPUs there is a D3D12 driver bug about
using DstAlpha as the source blend factors in both color and alpha
blending.

Although we cannot add workaround for all such cases, we have
confirmed that when the blend operation is 'add', and the
destination blend factors are ‘zero', we can workaround this driver
bug by replacing 'add' to 'minus'. We cannot add workaround when
destination blend factor is another value.

This patch adds such workaround on the affected platforms.

Bug: dawn:1579
Test: dawn_end2end_tests
Change-Id: If7c82b9d559b876e42fb36e2f539f9ff2f71ea91
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/120981
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Jiawei Shao 2023-02-24 01:34:56 +00:00 committed by Dawn LUCI CQ
parent fa5cda877f
commit dd0332ec91
5 changed files with 47 additions and 6 deletions

View File

@ -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.
}};

View File

@ -90,12 +90,13 @@ enum class Toggle {
UseBlitForBufferToDepthTextureCopy,
UseBlitForBufferToStencilTextureCopy,
UseBlitForDepthTextureToTextureCopyToNonzeroSubresource,
D3D12ReplaceAddWithMinusWhenDstFactorIsZeroAndSrcFactorIsDstAlpha,
DisallowDeprecatedAPIs,
// Unresolved issues.
NoWorkaroundSampleMaskBecomesZeroForAllButLastColorTarget,
NoWorkaroundIndirectBaseVertexNotApplied,
NoWorkaroundDstAlphaBlendDoesNotWork,
NoWorkaroundDstAlphaAsSrcBlendFactorForBothColorAndAlphaDoesNotWork,
EnumCount,
InvalidEnum = EnumCount,

View File

@ -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

View File

@ -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;

View File

@ -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<std::pair<TriangleSpec, utils::RGBA8>> 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(),