Source code

Revision control

Copy as Markdown

Other Tools

From 64af00a59b7ba856d7e0c76c30831fcbcb020dd1 Mon Sep 17 00:00:00 2001
From: Jeff Muizelaar <jrmuizel@gmail.com>
Date: Wed, 6 May 2020 14:04:42 -0400
Subject: [PATCH] Don't use ClearView if we previously used dual source
blending on Intel gen6. (#22)
Doing a ClearView after a dual source blend seems to cause a TDR on
Intel SandyBridge. Presumeably this is because the ClearView is
implemented as a regular draw and the driver doesn't properly set up the
state.
If we detect that this is going to happen we fall back to the manual
draw call path. This lets us use ClearView most of the time still.
---
.../platform/autogen/FeaturesD3D_autogen.h | 6 +++
include/platform/d3d_features.json | 8 ++++
src/libANGLE/renderer/d3d/d3d11/Clear11.cpp | 43 +++++++++++++++++--
.../renderer/d3d/d3d11/renderer11_utils.cpp | 28 ++++++------
util/autogen/angle_features_autogen.cpp | 1 +
util/autogen/angle_features_autogen.h | 1 +
6 files changed, 71 insertions(+), 16 deletions(-)
diff --git a/include/platform/autogen/FeaturesD3D_autogen.h b/include/platform/autogen/FeaturesD3D_autogen.h
index 5d38b6e..6305080 100644
--- a/include/platform/autogen/FeaturesD3D_autogen.h
+++ b/include/platform/autogen/FeaturesD3D_autogen.h
@@ -98,6 +98,12 @@ struct FeaturesD3D : FeatureSetBase
&members,
};
+ FeatureInfo emulateClearViewAfterDualSourceBlending = {
+ "emulateClearViewAfterDualSourceBlending",
+ FeatureCategory::D3DWorkarounds,
+ &members,
+ };
+
FeatureInfo useSystemMemoryForConstantBuffers = {
"useSystemMemoryForConstantBuffers",
FeatureCategory::D3DWorkarounds,
diff --git a/include/platform/d3d_features.json b/include/platform/d3d_features.json
index 0997289..7eb7385 100644
--- a/include/platform/d3d_features.json
+++ b/include/platform/d3d_features.json
@@ -106,6 +106,14 @@
],
},
+ {
+ "name": "emulate_clear_view_after_dual_source_blending",
+ "category": "Workarounds",
+ "description": [
+ "On Sandybridge, calling ClearView after using dual source blending causes hardware to hang"
+ ],
+ },
{
"name": "use_system_memory_for_constant_buffers",
"category": "Workarounds",
diff --git a/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp b/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
index ff265d9..f3c5ae5 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
@@ -426,10 +426,45 @@ angle::Result Clear11::clearFramebuffer(const gl::Context *context,
const auto &framebufferRTV = renderTarget->getRenderTargetView();
ASSERT(framebufferRTV.valid());
- if ((!(mRenderer->getRenderer11DeviceCaps().supportsClearView) && needScissoredClear) ||
- clearParams.colorType != GL_FLOAT || (formatInfo.redBits > 0 && !r) ||
- (formatInfo.greenBits > 0 && !g) || (formatInfo.blueBits > 0 && !b) ||
- (formatInfo.alphaBits > 0 && !a))
+ bool canClearView = mRenderer->getRenderer11DeviceCaps().supportsClearView;
+ if (canClearView &&
+ mRenderer->getFeatures().emulateClearViewAfterDualSourceBlending.enabled)
+ {
+ // Check the current state to see if we were using dual source blending
+ const auto isDualSource = [](const auto blend) {
+ switch (blend)
+ {
+ case D3D11_BLEND_SRC1_COLOR:
+ case D3D11_BLEND_INV_SRC1_COLOR:
+ case D3D11_BLEND_SRC1_ALPHA:
+ case D3D11_BLEND_INV_SRC1_ALPHA:
+ return true;
+ default:
+ return false;
+ }
+ };
+ FLOAT blendFactor[4];
+ UINT sampleMask;
+ ID3D11BlendState *blendState;
+ deviceContext->OMGetBlendState(&blendState, blendFactor, &sampleMask);
+ if (blendState)
+ {
+ D3D11_BLEND_DESC blendDesc;
+ blendState->GetDesc(&blendDesc);
+ // You can only use dual source blending on slot 0 so only check there
+ if (isDualSource(blendDesc.RenderTarget[0].SrcBlend) ||
+ isDualSource(blendDesc.RenderTarget[0].DestBlend) ||
+ isDualSource(blendDesc.RenderTarget[0].SrcBlendAlpha) ||
+ isDualSource(blendDesc.RenderTarget[0].DestBlendAlpha))
+ {
+ canClearView = false;
+ }
+ }
+ }
+
+ if ((!canClearView && needScissoredClear) || clearParams.colorType != GL_FLOAT ||
+ (formatInfo.redBits > 0 && !r) || (formatInfo.greenBits > 0 && !g) ||
+ (formatInfo.blueBits > 0 && !b) || (formatInfo.alphaBits > 0 && !a))
{
rtvs[numRtvs] = framebufferRTV.get();
rtvMasks[numRtvs] = gl_d3d11::GetColorMask(formatInfo) & colorMask;
diff --git a/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
index d0be62f..6fae418 100644
--- a/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
@@ -2119,24 +2119,26 @@ void InitializeFeatures(const Renderer11DeviceCaps &deviceCaps,
const DXGI_ADAPTER_DESC &adapterDesc,
angle::FeaturesD3D *features)
{
- bool isNvidia = IsNvidia(adapterDesc.VendorId);
- bool isIntel = IsIntel(adapterDesc.VendorId);
- bool isSkylake = false;
- bool isBroadwell = false;
- bool isHaswell = false;
- bool isIvyBridge = false;
- bool isAMD = IsAMD(adapterDesc.VendorId);
- bool isQualcomm = IsQualcomm(adapterDesc.VendorId);
+ bool isNvidia = IsNvidia(adapterDesc.VendorId);
+ bool isIntel = IsIntel(adapterDesc.VendorId);
+ bool isSkylake = false;
+ bool isBroadwell = false;
+ bool isHaswell = false;
+ bool isIvyBridge = false;
+ bool isSandyBridge = false;
+ bool isAMD = IsAMD(adapterDesc.VendorId);
+ bool isQualcomm = IsQualcomm(adapterDesc.VendorId);
angle::VersionTriple capsVersion;
if (isIntel)
{
capsVersion = d3d11_gl::GetIntelDriverVersion(deviceCaps.driverVersion);
- isSkylake = IsSkylake(adapterDesc.DeviceId);
- isBroadwell = IsBroadwell(adapterDesc.DeviceId);
- isHaswell = IsHaswell(adapterDesc.DeviceId);
- isIvyBridge = IsIvyBridge(adapterDesc.DeviceId);
+ isSkylake = IsSkylake(adapterDesc.DeviceId);
+ isBroadwell = IsBroadwell(adapterDesc.DeviceId);
+ isHaswell = IsHaswell(adapterDesc.DeviceId);
+ isIvyBridge = IsIvyBridge(adapterDesc.DeviceId);
+ isSandyBridge = IsSandyBridge(adapterDesc.DeviceId);
}
if (isNvidia)
@@ -2194,6 +2196,8 @@ void InitializeFeatures(const Renderer11DeviceCaps &deviceCaps,
ANGLE_FEATURE_CONDITION(features, setDataFasterThanImageUploadOn128bitFormats,
!(isIvyBridge || isBroadwell || isHaswell));
+ ANGLE_FEATURE_CONDITION(features, emulateClearViewAfterDualSourceBlending, isSandyBridge);
+
ANGLE_FEATURE_CONDITION(features, disableB5G6R5Support,
(isIntel && capsVersion >= angle::VersionTriple(15, 0, 0) &&
capsVersion < angle::VersionTriple(15, 4539, 0)) ||
diff --git a/util/autogen/angle_features_autogen.cpp b/util/autogen/angle_features_autogen.cpp
index 2e0c9e2..e75541b 100644
--- a/util/autogen/angle_features_autogen.cpp
+++ b/util/autogen/angle_features_autogen.cpp
@@ -138,6 +138,7 @@ constexpr PackedEnumMap<Feature, const char *> kFeatureNames = {{
{Feature::EmulateAdvancedBlendEquations, "emulateAdvancedBlendEquations"},
{Feature::EmulateAlphaToCoverage, "emulateAlphaToCoverage"},
{Feature::EmulateAtan2Float, "emulateAtan2Float"},
+ {Feature::EmulateClearViewAfterDualSourceBlending, "emulateClearViewAfterDualSourceBlending"},
{Feature::EmulateClipDistanceState, "emulateClipDistanceState"},
{Feature::EmulateClipOrigin, "emulateClipOrigin"},
{Feature::EmulateCopyTexImage2D, "emulateCopyTexImage2D"},
diff --git a/util/autogen/angle_features_autogen.h b/util/autogen/angle_features_autogen.h
index 68724b7..3ecac9d 100644
--- a/util/autogen/angle_features_autogen.h
+++ b/util/autogen/angle_features_autogen.h
@@ -138,6 +138,7 @@ enum class Feature
EmulateAdvancedBlendEquations,
EmulateAlphaToCoverage,
EmulateAtan2Float,
+ EmulateClearViewAfterDualSourceBlending,
EmulateClipDistanceState,
EmulateClipOrigin,
EmulateCopyTexImage2D,
--
2.43.0