From 19905aea14e0673454cc7b99fee928999f403a2d Mon Sep 17 00:00:00 2001 From: Ian Elliott Date: Fri, 26 Apr 2019 01:48:31 -0600 Subject: [PATCH] Vulkan: Set the Vulkan scissor to the GLES viewport Some Vulkan drivers are not clipping rendering that is outside of the viewport, and the Vulkan spec has some language that indicates that ANGLE should set the scissor: The application must ensure (using scissor if necessary) that all rendering is contained within the render area. In this case, ANGLE is "the application". Bug: angleproject:3253 Bug: angleproject:3254 Change-Id: I6885a3aa6daed57f6ae1c3d974663d763cad10c9 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1553973 Reviewed-by: Geoff Lang Commit-Queue: Ian Elliott --- include/platform/FeaturesVk.h | 5 +++ src/libANGLE/renderer/vulkan/ContextVk.cpp | 36 ++++++++++++++++--- src/libANGLE/renderer/vulkan/RendererVk.cpp | 5 +++ .../deqp_gles2_test_expectations.txt | 11 ------ 4 files changed, 42 insertions(+), 15 deletions(-) diff --git a/include/platform/FeaturesVk.h b/include/platform/FeaturesVk.h index 183f11489..0a124359b 100644 --- a/include/platform/FeaturesVk.h +++ b/include/platform/FeaturesVk.h @@ -89,6 +89,11 @@ struct FeaturesVk // object within that set. This flag results in empty descriptor sets being bound for any // unused descriptor set to work around this issue. http://anglebug.com/2727 bool bindEmptyForUnusedDescriptorSets = false; + + // When the scissor is (0,0,0,0) on Windows Intel, the driver acts as if the scissor was + // disabled. Work-around this by setting the scissor to just outside of the render area + // (e.g. (renderArea.x, renderArea.y, 1, 1)). http://anglebug.com/3153 + bool forceNonZeroScissor = false; }; inline FeaturesVk::FeaturesVk() = default; diff --git a/src/libANGLE/renderer/vulkan/ContextVk.cpp b/src/libANGLE/renderer/vulkan/ContextVk.cpp index 3e9503f7f..6b77637a1 100644 --- a/src/libANGLE/renderer/vulkan/ContextVk.cpp +++ b/src/libANGLE/renderer/vulkan/ContextVk.cpp @@ -15,6 +15,8 @@ #include "libANGLE/Context.h" #include "libANGLE/Program.h" #include "libANGLE/Surface.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/renderer_utils.h" #include "libANGLE/renderer/vulkan/BufferVk.h" #include "libANGLE/renderer/vulkan/CommandGraph.h" #include "libANGLE/renderer/vulkan/CompilerVk.h" @@ -704,10 +706,34 @@ void ContextVk::updateDepthRange(float nearPlane, float farPlane) void ContextVk::updateScissor(const gl::State &glState) { - FramebufferVk *framebufferVk = vk::GetImpl(glState.getDrawFramebuffer()); - gl::Rectangle scissoredRenderArea = framebufferVk->getScissoredRenderArea(this); - VkRect2D scissor = gl_vk::GetRect(scissoredRenderArea); - mGraphicsPipelineDesc->updateScissor(&mGraphicsPipelineTransition, scissor); + FramebufferVk *framebufferVk = vk::GetImpl(glState.getDrawFramebuffer()); + gl::Rectangle renderArea = framebufferVk->getCompleteRenderArea(); + + // Clip the render area to the viewport. + gl::Rectangle viewportClippedRenderArea; + gl::ClipRectangle(renderArea, glState.getViewport(), &viewportClippedRenderArea); + + gl::Rectangle scissoredArea = ClipRectToScissor(getState(), viewportClippedRenderArea, false); + if (isViewportFlipEnabledForDrawFBO()) + { + scissoredArea.y = renderArea.height - scissoredArea.y - scissoredArea.height; + } + + if (getRenderer()->getFeatures().forceNonZeroScissor && scissoredArea.width == 0 && + scissoredArea.height == 0) + { + // There is no overlap between the app-set viewport and clippedRect. This code works + // around an Intel driver bug that causes the driver to treat a (0,0,0,0) scissor as if + // scissoring is disabled. In this case, set the scissor to be just outside of the + // renderArea. Remove this work-around when driver version 25.20.100.6519 has been + // deployed. http://anglebug.com/3407 + scissoredArea.x = renderArea.x; + scissoredArea.y = renderArea.y; + scissoredArea.width = 1; + scissoredArea.height = 1; + } + mGraphicsPipelineDesc->updateScissor(&mGraphicsPipelineTransition, + gl_vk::GetRect(scissoredArea)); framebufferVk->onScissorChange(this); } @@ -736,6 +762,8 @@ angle::Result ContextVk::syncState(const gl::Context *context, FramebufferVk *framebufferVk = vk::GetImpl(glState.getDrawFramebuffer()); updateViewport(framebufferVk, glState.getViewport(), glState.getNearPlane(), glState.getFarPlane(), isViewportFlipEnabledForDrawFBO()); + // Update the scissor, which will be constrained to the viewport + updateScissor(glState); break; } case gl::State::DIRTY_BIT_DEPTH_RANGE: diff --git a/src/libANGLE/renderer/vulkan/RendererVk.cpp b/src/libANGLE/renderer/vulkan/RendererVk.cpp index 12a54278c..4c964495b 100644 --- a/src/libANGLE/renderer/vulkan/RendererVk.cpp +++ b/src/libANGLE/renderer/vulkan/RendererVk.cpp @@ -1314,6 +1314,11 @@ void RendererVk::initFeatures(const ExtensionNameList &deviceExtensionNames) mFeatures.bindEmptyForUnusedDescriptorSets = true; } + + if (IsWindows() && IsIntel(mPhysicalDeviceProperties.vendorID)) + { + mFeatures.forceNonZeroScissor = true; + } } void RendererVk::initPipelineCacheVkKey() diff --git a/src/tests/deqp_support/deqp_gles2_test_expectations.txt b/src/tests/deqp_support/deqp_gles2_test_expectations.txt index 14aa909c5..adcb83030 100644 --- a/src/tests/deqp_support/deqp_gles2_test_expectations.txt +++ b/src/tests/deqp_support/deqp_gles2_test_expectations.txt @@ -274,14 +274,6 @@ 3253 VULKAN : dEQP-GLES2.functional.clipping.point.wide_point_clip_viewport_center = FAIL 3253 VULKAN : dEQP-GLES2.functional.clipping.point.wide_point_clip_viewport_corner = FAIL -// Other clipping -3254 VULKAN : dEQP-GLES2.functional.clipping.line.line_clip_viewport_center = FAIL -3254 VULKAN : dEQP-GLES2.functional.clipping.line.line_clip_viewport_corner = FAIL - -// Only seems to be an issue on NVIDIA -3254 VULKAN NVIDIA : dEQP-GLES2.functional.clipping.point.point_clip_viewport_center = FAIL -3254 VULKAN NVIDIA : dEQP-GLES2.functional.clipping.point.point_clip_viewport_corner = FAIL - // These seem to fail on both D3D11 and Vulkan 3243 VULKAN : dEQP-GLES2.functional.texture.mipmap.cube.basic.linear_nearest = FAIL 3243 VULKAN : dEQP-GLES2.functional.texture.mipmap.cube.basic.linear_linear = FAIL @@ -334,9 +326,6 @@ // Passes on Pixel XL. Fails on 5x and Pixel 2. Might be fixed in latest driver. 2609 VULKAN ANDROID : dEQP-GLES2.functional.texture.mipmap.cube.generate.* = SKIP -// Fails on Nexus 5x only. TODO(jmadill): Remove suppression when possible. http://anglebug.com/2791 -2791 VULKAN ANDROID : dEQP-GLES2.functional.clipping.* = SKIP - // Failing on the Pixel 2. 2727 VULKAN ANDROID : dEQP-GLES2.functional.shaders.builtin_variable.pointcoord = FAIL 2808 VULKAN ANDROID : dEQP-GLES2.functional.shaders.builtin_variable.fragcoord_w = FAIL