Commit 4e913d34 by Anders Leino Committed by Commit Bot

Vulkan: Work around Nvidia depth clamping bug

In GL ES, depth is always clamped to [0,1]. The same is true in Vulkan, but not for implementations affected by Nvidia bug 3171019. This patch implements a workaround. The workaround introduced test failures on Linux with Nvidia Quadro P400 and driver version 418.56, so it's only applied conditionally, and as a result the test failure expectations are not removed completely. Bug: angleproject:3970 Change-Id: I0d9f855d7f3df72fea4af9f9b134ae3177cf820d Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2514377 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 9c6f7385
...@@ -64,6 +64,13 @@ struct FeaturesVk : FeatureSetBase ...@@ -64,6 +64,13 @@ struct FeaturesVk : FeatureSetBase
"The point size range reported from the API is inconsistent with the actual behavior", "The point size range reported from the API is inconsistent with the actual behavior",
&members, "http://anglebug.com/2970"}; &members, "http://anglebug.com/2970"};
// On some NVIDIA drivers the depth value is not clamped to [0,1] for floating point depth
// buffers. This is NVIDIA bug 3171019, see http://anglebug.com/3970 for details.
Feature depthClamping = {
"depth_clamping", FeatureCategory::VulkanWorkarounds,
"The depth value is not clamped to [0,1] for floating point depth buffers.", &members,
"http://anglebug.com/3970"};
// On some android devices, the memory barrier between the compute shader that converts vertex // On some android devices, the memory barrier between the compute shader that converts vertex
// attributes and the vertex shader that reads from it is ineffective. Only known workaround is // attributes and the vertex shader that reads from it is ineffective. Only known workaround is
// to perform a flush after the conversion. http://anglebug.com/3016 // to perform a flush after the conversion. http://anglebug.com/3016
......
...@@ -602,7 +602,7 @@ angle::Result ContextVk::initialize() ...@@ -602,7 +602,7 @@ angle::Result ContextVk::initialize()
} }
mGraphicsPipelineDesc.reset(new vk::GraphicsPipelineDesc()); mGraphicsPipelineDesc.reset(new vk::GraphicsPipelineDesc());
mGraphicsPipelineDesc->initDefaults(); mGraphicsPipelineDesc->initDefaults(this);
// Initialize current value/default attribute buffers. // Initialize current value/default attribute buffers.
for (vk::DynamicBuffer &buffer : mDefaultAttribBuffers) for (vk::DynamicBuffer &buffer : mDefaultAttribBuffers)
......
...@@ -1166,6 +1166,12 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF ...@@ -1166,6 +1166,12 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
// Initialize features and workarounds. // Initialize features and workarounds.
initFeatures(displayVk, deviceExtensionNames); initFeatures(displayVk, deviceExtensionNames);
// Enable VK_EXT_depth_clip_enable, if supported
if (ExtensionFound(VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME, deviceExtensionNames))
{
enabledDeviceExtensions.push_back(VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME);
}
// Enable VK_KHR_get_memory_requirements2, if supported // Enable VK_KHR_get_memory_requirements2, if supported
if (ExtensionFound(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, deviceExtensionNames)) if (ExtensionFound(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, deviceExtensionNames))
{ {
...@@ -1771,6 +1777,15 @@ void RendererVk::initFeatures(DisplayVk *displayVk, ...@@ -1771,6 +1777,15 @@ void RendererVk::initFeatures(DisplayVk *displayVk,
} }
ANGLE_FEATURE_CONDITION(&mFeatures, clampPointSize, ANGLE_FEATURE_CONDITION(&mFeatures, clampPointSize,
isNvidia && nvidiaVersion.major < uint32_t(IsWindows() ? 430 : 421)); isNvidia && nvidiaVersion.major < uint32_t(IsWindows() ? 430 : 421));
// http://anglebug.com/3970#c25.
// The workaround requires the VK_EXT_depth_clip_enable extension and the 'depthClamp' physical
// device feature. This workaround caused test failures on Quadro P400/driver 418.56/Linux.
// Therefore, on Linux we require a major version > 418.
ANGLE_FEATURE_CONDITION(
&mFeatures, depthClamping,
isNvidia && mPhysicalDeviceFeatures.depthClamp &&
ExtensionFound(VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME, deviceExtensionNames) &&
(!IsLinux() || nvidiaVersion.major > 418u));
// Work around ineffective compute-graphics barriers on Nexus 5X. // Work around ineffective compute-graphics barriers on Nexus 5X.
// TODO(syoussefi): Figure out which other vendors and driver versions are affected. // TODO(syoussefi): Figure out which other vendors and driver versions are affected.
......
...@@ -1517,7 +1517,7 @@ angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk, ...@@ -1517,7 +1517,7 @@ angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
shaderParams.clearDepth = params.depthStencilClearValue.depth; shaderParams.clearDepth = params.depthStencilClearValue.depth;
vk::GraphicsPipelineDesc pipelineDesc; vk::GraphicsPipelineDesc pipelineDesc;
pipelineDesc.initDefaults(); pipelineDesc.initDefaults(contextVk);
pipelineDesc.setCullMode(VK_CULL_MODE_NONE); pipelineDesc.setCullMode(VK_CULL_MODE_NONE);
pipelineDesc.setColorWriteMasks(0, gl::DrawBufferMask(), gl::DrawBufferMask()); pipelineDesc.setColorWriteMasks(0, gl::DrawBufferMask(), gl::DrawBufferMask());
pipelineDesc.setSingleColorWriteMask(params.colorAttachmentIndexGL, params.colorMaskFlags); pipelineDesc.setSingleColorWriteMask(params.colorAttachmentIndexGL, params.colorMaskFlags);
...@@ -1763,7 +1763,7 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk, ...@@ -1763,7 +1763,7 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk,
VK_COLOR_COMPONENT_A_BIT; VK_COLOR_COMPONENT_A_BIT;
vk::GraphicsPipelineDesc pipelineDesc; vk::GraphicsPipelineDesc pipelineDesc;
pipelineDesc.initDefaults(); pipelineDesc.initDefaults(contextVk);
if (blitColor) if (blitColor)
{ {
pipelineDesc.setColorWriteMasks( pipelineDesc.setColorWriteMasks(
...@@ -2204,7 +2204,7 @@ angle::Result UtilsVk::copyImage(ContextVk *contextVk, ...@@ -2204,7 +2204,7 @@ angle::Result UtilsVk::copyImage(ContextVk *contextVk,
ASSERT(src->getSamples() == 1); ASSERT(src->getSamples() == 1);
vk::GraphicsPipelineDesc pipelineDesc; vk::GraphicsPipelineDesc pipelineDesc;
pipelineDesc.initDefaults(); pipelineDesc.initDefaults(contextVk);
pipelineDesc.setCullMode(VK_CULL_MODE_NONE); pipelineDesc.setCullMode(VK_CULL_MODE_NONE);
pipelineDesc.setRenderPassDesc(renderPassDesc); pipelineDesc.setRenderPassDesc(renderPassDesc);
pipelineDesc.setRasterizationSamples(dest->getSamples()); pipelineDesc.setRasterizationSamples(dest->getSamples());
...@@ -2662,7 +2662,7 @@ angle::Result UtilsVk::unresolve(ContextVk *contextVk, ...@@ -2662,7 +2662,7 @@ angle::Result UtilsVk::unresolve(ContextVk *contextVk,
ANGLE_TRY(ensureUnresolveResourcesInitialized(contextVk, function, totalBindingCount)); ANGLE_TRY(ensureUnresolveResourcesInitialized(contextVk, function, totalBindingCount));
vk::GraphicsPipelineDesc pipelineDesc; vk::GraphicsPipelineDesc pipelineDesc;
pipelineDesc.initDefaults(); pipelineDesc.initDefaults(contextVk);
pipelineDesc.setCullMode(VK_CULL_MODE_NONE); pipelineDesc.setCullMode(VK_CULL_MODE_NONE);
pipelineDesc.setRasterizationSamples(framebuffer->getSamples()); pipelineDesc.setRasterizationSamples(framebuffer->getSamples());
pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc()); pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc());
......
...@@ -1490,7 +1490,7 @@ bool GraphicsPipelineDesc::operator==(const GraphicsPipelineDesc &other) const ...@@ -1490,7 +1490,7 @@ bool GraphicsPipelineDesc::operator==(const GraphicsPipelineDesc &other) const
// TODO(jmadill): We should prefer using Packed GLenums. http://anglebug.com/2169 // TODO(jmadill): We should prefer using Packed GLenums. http://anglebug.com/2169
// Initialize PSO states, it is consistent with initial value of gl::State // Initialize PSO states, it is consistent with initial value of gl::State
void GraphicsPipelineDesc::initDefaults() void GraphicsPipelineDesc::initDefaults(const ContextVk *contextVk)
{ {
// Set all vertex input attributes to default, the default format is Float // Set all vertex input attributes to default, the default format is Float
angle::FormatID defaultFormat = GetCurrentValueFormatID(gl::VertexAttribType::Float); angle::FormatID defaultFormat = GetCurrentValueFormatID(gl::VertexAttribType::Float);
...@@ -1503,8 +1503,9 @@ void GraphicsPipelineDesc::initDefaults() ...@@ -1503,8 +1503,9 @@ void GraphicsPipelineDesc::initDefaults()
SetBitField(packedAttrib.offset, 0); SetBitField(packedAttrib.offset, 0);
} }
mRasterizationAndMultisampleStateInfo.bits.subpass = 0; mRasterizationAndMultisampleStateInfo.bits.subpass = 0;
mRasterizationAndMultisampleStateInfo.bits.depthClampEnable = 0; mRasterizationAndMultisampleStateInfo.bits.depthClampEnable =
contextVk->getFeatures().depthClamping.enabled ? VK_TRUE : VK_FALSE;
mRasterizationAndMultisampleStateInfo.bits.rasterizationDiscardEnable = 0; mRasterizationAndMultisampleStateInfo.bits.rasterizationDiscardEnable = 0;
SetBitField(mRasterizationAndMultisampleStateInfo.bits.polygonMode, VK_POLYGON_MODE_FILL); SetBitField(mRasterizationAndMultisampleStateInfo.bits.polygonMode, VK_POLYGON_MODE_FILL);
SetBitField(mRasterizationAndMultisampleStateInfo.bits.cullMode, VK_CULL_MODE_BACK_BIT); SetBitField(mRasterizationAndMultisampleStateInfo.bits.cullMode, VK_CULL_MODE_BACK_BIT);
...@@ -1824,6 +1825,21 @@ angle::Result GraphicsPipelineDesc::initializePipeline( ...@@ -1824,6 +1825,21 @@ angle::Result GraphicsPipelineDesc::initializePipeline(
*pNextPtr = &provokingVertexState; *pNextPtr = &provokingVertexState;
pNextPtr = &provokingVertexState.pNext; pNextPtr = &provokingVertexState.pNext;
} }
// When depth clamping is used, depth clipping is automatically disabled.
// When the 'depthClamping' feature is enabled, we'll be using depth clamping
// to work around a driver issue, not as an alternative to depth clipping. Therefore we need to
// explicitly re-enable depth clipping.
VkPipelineRasterizationDepthClipStateCreateInfoEXT depthClipState = {};
depthClipState.sType =
VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT;
if (contextVk->getFeatures().depthClamping.enabled)
{
depthClipState.depthClipEnable = VK_TRUE;
*pNextPtr = &depthClipState;
pNextPtr = &depthClipState.pNext;
}
VkPipelineRasterizationStateStreamCreateInfoEXT rasterStreamState = {}; VkPipelineRasterizationStateStreamCreateInfoEXT rasterStreamState = {};
rasterStreamState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT; rasterStreamState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT;
if (contextVk->getFeatures().supportsTransformFeedbackExtension.enabled) if (contextVk->getFeatures().supportsTransformFeedbackExtension.enabled)
......
...@@ -574,7 +574,7 @@ class GraphicsPipelineDesc final ...@@ -574,7 +574,7 @@ class GraphicsPipelineDesc final
size_t hash() const; size_t hash() const;
bool operator==(const GraphicsPipelineDesc &other) const; bool operator==(const GraphicsPipelineDesc &other) const;
void initDefaults(); void initDefaults(const ContextVk *contextVk);
// For custom comparisons. // For custom comparisons.
template <typename T> template <typename T>
......
...@@ -533,14 +533,16 @@ ...@@ -533,14 +533,16 @@
3677 VULKAN : dEQP-GLES3.functional.fragment_out.random.* = FAIL 3677 VULKAN : dEQP-GLES3.functional.fragment_out.random.* = FAIL
// NVIDIA Depth/Stencil textures: // NVIDIA Depth/Stencil textures:
3970 VULKAN NVIDIA : dEQP-GLES3.functional.fbo.depth.depth_write_clamp.depth_component32f = FAIL // Fails on Quadro P400, driver 418.56, Linux
3970 VULKAN NVIDIA : dEQP-GLES3.functional.fbo.depth.depth_write_clamp.depth32f_stencil8 = FAIL 3970 VULKAN NVIDIA LINUX : dEQP-GLES3.functional.fbo.depth.depth_write_clamp.depth_component32f = FAIL
3970 VULKAN NVIDIA : dEQP-GLES3.functional.fbo.depth.depth_test_clamp.depth_component32f = FAIL 3970 VULKAN NVIDIA LINUX : dEQP-GLES3.functional.fbo.depth.depth_write_clamp.depth32f_stencil8 = FAIL
3970 VULKAN NVIDIA : dEQP-GLES3.functional.fbo.depth.depth_test_clamp.depth32f_stencil8 = FAIL 3970 VULKAN NVIDIA LINUX : dEQP-GLES3.functional.fbo.depth.depth_test_clamp.depth_component32f = FAIL
3970 VULKAN NVIDIA LINUX : dEQP-GLES3.functional.fbo.depth.depth_test_clamp.depth32f_stencil8 = FAIL
// Polygon offset: // Polygon offset:
3970 VULKAN NVIDIA : dEQP-GLES3.functional.polygon_offset.float32_result_depth_clamp = FAIL // Fails on Quadro P400, driver 418.56, Linux
3970 VULKAN NVIDIA : dEQP-GLES3.functional.polygon_offset.float32_factor_1_slope = FAIL 3970 VULKAN NVIDIA LINUX : dEQP-GLES3.functional.polygon_offset.float32_result_depth_clamp = FAIL
3970 VULKAN NVIDIA LINUX : dEQP-GLES3.functional.polygon_offset.float32_factor_1_slope = FAIL
// Transform Feedback // Transform Feedback
4666 VULKAN NVIDIA : dEQP-GLES3.functional.transform_feedback.array_element.interleaved.* = SKIP 4666 VULKAN NVIDIA : dEQP-GLES3.functional.transform_feedback.array_element.interleaved.* = SKIP
......
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