Commit c174db3a by Jamie Madill Committed by Commit Bot

D3D11: Apply a non-null blendstate in masked depth clear.

In https://chromium-review.googlesource.com/c/453888/, we changed how blendstates were applied in masked clears. This change would apply a null blendstate when all color channels were disabled, but this seems to have an issue on Intel Cherry View drivers. Work around this issue by restoring the prior functionality of making a simple masked blend state. Also clean up some of the code style in the Clear11 class. BUG=chromium:730126 Change-Id: I9a4044201b2f07e9483525513a59e19bb2a8bcd3 Reviewed-on: https://chromium-review.googlesource.com/533684Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent dbcced8e
...@@ -213,9 +213,9 @@ gl::Error Clear11::ensureResourcesInitialized() ...@@ -213,9 +213,9 @@ gl::Error Clear11::ensureResourcesInitialized()
mDepthStencilStateKey.depthFunc = GL_ALWAYS; mDepthStencilStateKey.depthFunc = GL_ALWAYS;
mDepthStencilStateKey.stencilWritemask = static_cast<GLuint>(-1); mDepthStencilStateKey.stencilWritemask = static_cast<GLuint>(-1);
mDepthStencilStateKey.stencilBackWritemask = static_cast<GLuint>(-1); mDepthStencilStateKey.stencilBackWritemask = static_cast<GLuint>(-1);
mDepthStencilStateKey.stencilBackMask = static_cast<GLuint>(-1); mDepthStencilStateKey.stencilBackMask = 0;
mDepthStencilStateKey.stencilTest = false; mDepthStencilStateKey.stencilTest = false;
mDepthStencilStateKey.stencilMask = static_cast<GLuint>(-1); mDepthStencilStateKey.stencilMask = 0;
mDepthStencilStateKey.stencilFail = GL_REPLACE; mDepthStencilStateKey.stencilFail = GL_REPLACE;
mDepthStencilStateKey.stencilPassDepthFail = GL_REPLACE; mDepthStencilStateKey.stencilPassDepthFail = GL_REPLACE;
mDepthStencilStateKey.stencilPassDepthPass = GL_REPLACE; mDepthStencilStateKey.stencilPassDepthPass = GL_REPLACE;
...@@ -316,19 +316,6 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, ...@@ -316,19 +316,6 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
{ {
ANGLE_TRY(ensureResourcesInitialized()); ANGLE_TRY(ensureResourcesInitialized());
const auto &colorAttachments = fboData.getColorAttachments();
const auto &drawBufferStates = fboData.getDrawBufferStates();
const gl::FramebufferAttachment *depthStencilAttachment = fboData.getDepthOrStencilAttachment();
RenderTarget11 *depthStencilRenderTarget = nullptr;
ASSERT(colorAttachments.size() <= drawBufferStates.size());
if (clearParams.clearDepth || clearParams.clearStencil)
{
ASSERT(depthStencilAttachment != nullptr);
ANGLE_TRY(depthStencilAttachment->getRenderTarget(&depthStencilRenderTarget));
}
// Iterate over the color buffers which require clearing and determine if they can be // Iterate over the color buffers which require clearing and determine if they can be
// cleared with ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView. // cleared with ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView.
// This requires: // This requires:
...@@ -358,6 +345,7 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, ...@@ -358,6 +345,7 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
gl::Extents framebufferSize; gl::Extents framebufferSize;
const auto *depthStencilAttachment = fboData.getDepthOrStencilAttachment();
if (depthStencilAttachment != nullptr) if (depthStencilAttachment != nullptr)
{ {
framebufferSize = depthStencilAttachment->getSize(); framebufferSize = depthStencilAttachment->getSize();
...@@ -399,143 +387,141 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, ...@@ -399,143 +387,141 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported(); ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
std::array<ID3D11RenderTargetView *, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> rtvs; std::array<ID3D11RenderTargetView *, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> rtvs;
std::array<uint8_t, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> rtvMasks; std::array<uint8_t, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> rtvMasks = {};
ID3D11DepthStencilView *dsv = nullptr;
uint32_t numRtvs = 0; uint32_t numRtvs = 0;
const uint8_t colorMask = const uint8_t colorMask =
gl_d3d11::ConvertColorMask(clearParams.colorMaskRed, clearParams.colorMaskGreen, gl_d3d11::ConvertColorMask(clearParams.colorMaskRed, clearParams.colorMaskGreen,
clearParams.colorMaskBlue, clearParams.colorMaskAlpha); clearParams.colorMaskBlue, clearParams.colorMaskAlpha);
for (size_t colorAttachmentIndex = 0; colorAttachmentIndex < colorAttachments.size(); const auto &colorAttachments = fboData.getColorAttachments();
colorAttachmentIndex++) for (auto colorAttachmentIndex : fboData.getEnabledDrawBuffers())
{ {
const gl::FramebufferAttachment &attachment = colorAttachments[colorAttachmentIndex]; const gl::FramebufferAttachment &attachment = colorAttachments[colorAttachmentIndex];
if (clearParams.clearColor[colorAttachmentIndex] && attachment.isAttached() && if (!clearParams.clearColor[colorAttachmentIndex])
drawBufferStates[colorAttachmentIndex] != GL_NONE)
{ {
RenderTarget11 *renderTarget = nullptr; continue;
ANGLE_TRY(attachment.getRenderTarget(&renderTarget)); }
const gl::InternalFormat &formatInfo = *attachment.getFormat().info; RenderTarget11 *renderTarget = nullptr;
ANGLE_TRY(attachment.getRenderTarget(&renderTarget));
if (clearParams.colorType == GL_FLOAT && const gl::InternalFormat &formatInfo = *attachment.getFormat().info;
!(formatInfo.componentType == GL_FLOAT ||
formatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
formatInfo.componentType == GL_SIGNED_NORMALIZED))
{
ERR() << "It is undefined behaviour to clear a render buffer which is not "
"normalized fixed point or floating-point to floating point values (color "
"attachment "
<< colorAttachmentIndex << " has internal format " << attachment.getFormat()
<< ").";
}
if ((formatInfo.redBits == 0 || !clearParams.colorMaskRed) && if (clearParams.colorType == GL_FLOAT &&
(formatInfo.greenBits == 0 || !clearParams.colorMaskGreen) && !(formatInfo.componentType == GL_FLOAT ||
(formatInfo.blueBits == 0 || !clearParams.colorMaskBlue) && formatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
(formatInfo.alphaBits == 0 || !clearParams.colorMaskAlpha)) formatInfo.componentType == GL_SIGNED_NORMALIZED))
{ {
// Every channel either does not exist in the render target or is masked out ERR() << "It is undefined behaviour to clear a render buffer which is not "
continue; "normalized fixed point or floating-point to floating point values (color "
} "attachment "
<< colorAttachmentIndex << " has internal format " << attachment.getFormat()
<< ").";
}
const d3d11::RenderTargetView &framebufferRTV = renderTarget->getRenderTargetView(); if ((formatInfo.redBits == 0 || !clearParams.colorMaskRed) &&
if (!framebufferRTV.valid()) (formatInfo.greenBits == 0 || !clearParams.colorMaskGreen) &&
{ (formatInfo.blueBits == 0 || !clearParams.colorMaskBlue) &&
return gl::OutOfMemory() (formatInfo.alphaBits == 0 || !clearParams.colorMaskAlpha))
<< "Clear11: Render target view pointer unexpectedly null."; {
} // Every channel either does not exist in the render target or is masked out
continue;
}
const auto &framebufferRTV = renderTarget->getRenderTargetView();
ASSERT(framebufferRTV.valid());
if ((!(mRenderer->getRenderer11DeviceCaps().supportsClearView) && needScissoredClear) || if ((!(mRenderer->getRenderer11DeviceCaps().supportsClearView) && needScissoredClear) ||
clearParams.colorType != GL_FLOAT || clearParams.colorType != GL_FLOAT ||
(formatInfo.redBits > 0 && !clearParams.colorMaskRed) || (formatInfo.redBits > 0 && !clearParams.colorMaskRed) ||
(formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) || (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) ||
(formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) || (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) ||
(formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha)) (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha))
{
rtvs[numRtvs] = framebufferRTV.get();
rtvMasks[numRtvs] = gl_d3d11::GetColorMask(formatInfo) & colorMask;
numRtvs++;
}
else
{
// ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView is
// possible
const auto &nativeFormat = renderTarget->getFormatSet().format();
// Check if the actual format has a channel that the internal format does not and
// set them to the default values
float clearValues[4] = {
((formatInfo.redBits == 0 && nativeFormat.redBits > 0) ? 0.0f
: clearParams.colorF.red),
((formatInfo.greenBits == 0 && nativeFormat.greenBits > 0)
? 0.0f
: clearParams.colorF.green),
((formatInfo.blueBits == 0 && nativeFormat.blueBits > 0) ? 0.0f
: clearParams.colorF.blue),
((formatInfo.alphaBits == 0 && nativeFormat.alphaBits > 0)
? 1.0f
: clearParams.colorF.alpha),
};
if (formatInfo.alphaBits == 1)
{ {
rtvs[numRtvs] = framebufferRTV.get(); // Some drivers do not correctly handle calling Clear() on a format with 1-bit
rtvMasks[numRtvs] = gl_d3d11::GetColorMask(&formatInfo) & colorMask; // alpha. They can incorrectly round all non-zero values up to 1.0f. Note that
numRtvs++; // WARP does not do this. We should handle the rounding for them instead.
clearValues[3] = (clearParams.colorF.alpha >= 0.5f) ? 1.0f : 0.0f;
} }
else
{
// ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView is
// possible
const auto &nativeFormat = renderTarget->getFormatSet().format();
// Check if the actual format has a channel that the internal format does not and
// set them to the default values
float clearValues[4] = {
((formatInfo.redBits == 0 && nativeFormat.redBits > 0)
? 0.0f
: clearParams.colorF.red),
((formatInfo.greenBits == 0 && nativeFormat.greenBits > 0)
? 0.0f
: clearParams.colorF.green),
((formatInfo.blueBits == 0 && nativeFormat.blueBits > 0)
? 0.0f
: clearParams.colorF.blue),
((formatInfo.alphaBits == 0 && nativeFormat.alphaBits > 0)
? 1.0f
: clearParams.colorF.alpha),
};
if (formatInfo.alphaBits == 1)
{
// Some drivers do not correctly handle calling Clear() on a format with 1-bit
// alpha. They can incorrectly round all non-zero values up to 1.0f. Note that
// WARP does not do this. We should handle the rounding for them instead.
clearValues[3] = (clearParams.colorF.alpha >= 0.5f) ? 1.0f : 0.0f;
}
if (needScissoredClear) if (needScissoredClear)
{ {
// We shouldn't reach here if deviceContext1 is unavailable. // We shouldn't reach here if deviceContext1 is unavailable.
ASSERT(deviceContext1); ASSERT(deviceContext1);
D3D11_RECT rect; D3D11_RECT rect;
rect.left = clearParams.scissor.x; rect.left = clearParams.scissor.x;
rect.right = clearParams.scissor.x + clearParams.scissor.width; rect.right = clearParams.scissor.x + clearParams.scissor.width;
rect.top = clearParams.scissor.y; rect.top = clearParams.scissor.y;
rect.bottom = clearParams.scissor.y + clearParams.scissor.height; rect.bottom = clearParams.scissor.y + clearParams.scissor.height;
deviceContext1->ClearView(framebufferRTV.get(), clearValues, &rect, 1); deviceContext1->ClearView(framebufferRTV.get(), clearValues, &rect, 1);
if (mRenderer->getWorkarounds().callClearTwiceOnSmallTarget) if (mRenderer->getWorkarounds().callClearTwiceOnSmallTarget)
{
if (clearParams.scissor.width <= 16 || clearParams.scissor.height <= 16)
{ {
if (clearParams.scissor.width <= 16 || clearParams.scissor.height <= 16) deviceContext1->ClearView(framebufferRTV.get(), clearValues, &rect, 1);
{
deviceContext1->ClearView(framebufferRTV.get(), clearValues, &rect, 1);
}
} }
} }
else }
else
{
deviceContext->ClearRenderTargetView(framebufferRTV.get(), clearValues);
if (mRenderer->getWorkarounds().callClearTwiceOnSmallTarget)
{ {
deviceContext->ClearRenderTargetView(framebufferRTV.get(), clearValues); if (framebufferSize.width <= 16 || framebufferSize.height <= 16)
if (mRenderer->getWorkarounds().callClearTwiceOnSmallTarget)
{ {
if (framebufferSize.width <= 16 || framebufferSize.height <= 16) deviceContext->ClearRenderTargetView(framebufferRTV.get(), clearValues);
{
deviceContext->ClearRenderTargetView(framebufferRTV.get(), clearValues);
}
} }
} }
} }
} }
} }
if (depthStencilRenderTarget) ID3D11DepthStencilView *dsv = nullptr;
if (clearParams.clearDepth || clearParams.clearStencil)
{ {
dsv = depthStencilRenderTarget->getDepthStencilView().get(); RenderTarget11 *depthStencilRenderTarget = nullptr;
if (!dsv) ASSERT(depthStencilAttachment != nullptr);
{ ANGLE_TRY(depthStencilAttachment->getRenderTarget(&depthStencilRenderTarget));
return gl::OutOfMemory() << "Clear11: Depth stencil view pointer unexpectedly null.";
} dsv = depthStencilRenderTarget->getDepthStencilView().get();
ASSERT(dsv != nullptr);
const auto &nativeFormat = depthStencilRenderTarget->getFormatSet().format(); const auto &nativeFormat = depthStencilRenderTarget->getFormatSet().format();
const gl::FramebufferAttachment *stencilAttachment = fboData.getStencilAttachment(); const auto *stencilAttachment = fboData.getStencilAttachment();
uint32_t stencilUnmasked = uint32_t stencilUnmasked =
(stencilAttachment != nullptr) ? (1 << nativeFormat.stencilBits) - 1 : 0; (stencilAttachment != nullptr) ? (1 << nativeFormat.stencilBits) - 1 : 0;
...@@ -594,24 +580,18 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, ...@@ -594,24 +580,18 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
ASSERT(numRtvs <= mRenderer->getNativeCaps().maxDrawBuffers); ASSERT(numRtvs <= mRenderer->getNativeCaps().maxDrawBuffers);
const UINT sampleMask = 0xFFFFFFFF; // Setup BlendStateKey parameters
ID3D11BlendState *blendState = nullptr; mBlendStateKey.blendState.colorMaskRed = clearParams.colorMaskRed;
mBlendStateKey.blendState.colorMaskGreen = clearParams.colorMaskGreen;
mBlendStateKey.blendState.colorMaskBlue = clearParams.colorMaskBlue;
mBlendStateKey.blendState.colorMaskAlpha = clearParams.colorMaskAlpha;
mBlendStateKey.mrt = numRtvs > 1;
memcpy(mBlendStateKey.rtvMasks, &rtvMasks[0], sizeof(mBlendStateKey.rtvMasks));
if (numRtvs > 0) // Get BlendState
{ ID3D11BlendState *blendState = nullptr;
// Setup BlendStateKey parameters ANGLE_TRY(mRenderer->getBlendState(mBlendStateKey, &blendState));
mBlendStateKey.blendState.colorMaskRed = clearParams.colorMaskRed;
mBlendStateKey.blendState.colorMaskGreen = clearParams.colorMaskGreen;
mBlendStateKey.blendState.colorMaskBlue = clearParams.colorMaskBlue;
mBlendStateKey.blendState.colorMaskAlpha = clearParams.colorMaskAlpha;
mBlendStateKey.mrt = numRtvs > 1;
memcpy(mBlendStateKey.rtvMasks, &rtvMasks[0], sizeof(mBlendStateKey.rtvMasks));
// Get BlendState
ANGLE_TRY(mRenderer->getBlendState(mBlendStateKey, &blendState));
}
const UINT stencilValue = clearParams.stencilValue & 0xFF;
ID3D11DepthStencilState *dsState = nullptr; ID3D11DepthStencilState *dsState = nullptr;
const float *zValue = nullptr; const float *zValue = nullptr;
...@@ -679,7 +659,9 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, ...@@ -679,7 +659,9 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
deviceContext->RSSetViewports(1, &viewport); deviceContext->RSSetViewports(1, &viewport);
// Apply state // Apply state
deviceContext->OMSetBlendState(blendState, nullptr, sampleMask); deviceContext->OMSetBlendState(blendState, nullptr, 0xFFFFFFFF);
const UINT stencilValue = clearParams.stencilValue & 0xFF;
deviceContext->OMSetDepthStencilState(dsState, stencilValue); deviceContext->OMSetDepthStencilState(dsState, stencilValue);
if (needScissoredClear) if (needScissoredClear)
......
...@@ -69,7 +69,7 @@ d3d11::BlendStateKey RenderStateCache::GetBlendStateKey(const gl::Framebuffer *f ...@@ -69,7 +69,7 @@ d3d11::BlendStateKey RenderStateCache::GetBlendStateKey(const gl::Framebuffer *f
} }
key.rtvMasks[i] = key.rtvMasks[i] =
(gl_d3d11::GetColorMask(attachment->getFormat().info)) & blendStateMask; (gl_d3d11::GetColorMask(*attachment->getFormat().info)) & blendStateMask;
} }
else else
{ {
......
...@@ -1700,26 +1700,10 @@ D3D11_QUERY ConvertQueryType(GLenum queryType) ...@@ -1700,26 +1700,10 @@ D3D11_QUERY ConvertQueryType(GLenum queryType)
} }
// Get the D3D11 write mask covering all color channels of a given format // Get the D3D11 write mask covering all color channels of a given format
UINT8 GetColorMask(const gl::InternalFormat *formatInfo) UINT8 GetColorMask(const gl::InternalFormat &format)
{ {
UINT8 mask = 0; return ConvertColorMask(format.redBits > 0, format.greenBits > 0, format.blueBits > 0,
if (formatInfo->redBits > 0) format.alphaBits > 0);
{
mask |= D3D11_COLOR_WRITE_ENABLE_RED;
}
if (formatInfo->greenBits > 0)
{
mask |= D3D11_COLOR_WRITE_ENABLE_GREEN;
}
if (formatInfo->blueBits > 0)
{
mask |= D3D11_COLOR_WRITE_ENABLE_BLUE;
}
if (formatInfo->alphaBits > 0)
{
mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
}
return mask;
} }
} // namespace gl_d3d11 } // namespace gl_d3d11
......
...@@ -56,7 +56,7 @@ UINT ConvertMaxAnisotropy(float maxAnisotropy, D3D_FEATURE_LEVEL featureLevel); ...@@ -56,7 +56,7 @@ UINT ConvertMaxAnisotropy(float maxAnisotropy, D3D_FEATURE_LEVEL featureLevel);
D3D11_QUERY ConvertQueryType(GLenum queryType); D3D11_QUERY ConvertQueryType(GLenum queryType);
UINT8 GetColorMask(const gl::InternalFormat *formatInfo); UINT8 GetColorMask(const gl::InternalFormat &formatInfo);
} // namespace gl_d3d11 } // namespace gl_d3d11
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment