Skip to content

Commit f116aa9

Browse files
Jason0214Commit Bot
authored andcommitted
Vulkan: detect swapchain recreation passively
Currently ANGLE vulkan query current window size every frame to detect whether a swapchain recreation is needed, however profiling shows some bottle neck on window size query on X11. So here removing the per frame window size query and only depend the result of vkAcquireImage and VkQueuePresent to detect a need for swapchain recreation. Bug: angleproject:3535 Change-Id: I4ddf70b973d78dfcd5f8fab28e29e802edad1b2d Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1662759 Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Ian Elliott <ianelliott@google.com> Commit-Queue: Ian Elliott <ianelliott@google.com>
1 parent 4237e53 commit f116aa9

5 files changed

Lines changed: 60 additions & 34 deletions

File tree

include/platform/FeaturesVk.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,12 +150,12 @@ struct FeaturesVk : FeatureSetBase
150150

151151
// When the scissor is (0,0,0,0) on Windows Intel, the driver acts as if the scissor was
152152
// disabled. Work-around this by setting the scissor to just outside of the render area
153-
// (e.g. (renderArea.x, renderArea.y, 1, 1)). http://anglebug.com/3153
153+
// (e.g. (renderArea.x, renderArea.y, 1, 1)). http://anglebug.com/3407
154154
Feature forceNonZeroScissor = {
155155
"force_non_zero_scissor", FeatureCategory::VulkanWorkarounds,
156156
"On Windows Intel, when the scissor is (0,0,0,0), the driver acts as if the "
157157
"scissor was disabled",
158-
&members, "http://anglebug.com/3153"};
158+
&members, "http://anglebug.com/3407"};
159159

160160
// OES_depth_texture is a commonly expected feature on Android. However it
161161
// requires that D16_UNORM support texture filtering
@@ -174,6 +174,16 @@ struct FeaturesVk : FeatureSetBase
174174
"disable_flipping_blit_with_command", FeatureCategory::VulkanWorkarounds,
175175
"On some android devices, vkCmdBlitImage with flipped coordinates blits incorrectly.",
176176
&members, "http://anglebug.com/3498"};
177+
178+
// On platform with Intel or AMD GPU, a window resizing would not trigger the vulkan driver to
179+
// return VK_ERROR_OUT_OF_DATE on swapchain present. Work-around by query current window extent
180+
// every frame to detect a window resizing.
181+
// http://anglebug.com/3623, http://anglebug.com/3624, http://anglebug.com/3625
182+
Feature perFrameWindowSizeQuery = {
183+
"per_frame_window_size_query", FeatureCategory::VulkanWorkarounds,
184+
"On platform with Intel or AMD gpu, vulkan swapchain is not returning VK_ERROR_OUT_OF_DATE"
185+
"when window resizing",
186+
&members, "http://anglebug.com/3623, http://anglebug.com/3624, http://anglebug.com/3625"};
177187
};
178188

179189
inline FeaturesVk::FeaturesVk() = default;

src/libANGLE/renderer/vulkan/RendererVk.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,6 +1240,12 @@ void RendererVk::initFeatures(const ExtensionNameList &deviceExtensionNames)
12401240
mFeatures.forceNonZeroScissor.enabled = true;
12411241
}
12421242

1243+
if (IsIntel(mPhysicalDeviceProperties.vendorID) ||
1244+
(IsWindows() && IsAMD(mPhysicalDeviceProperties.vendorID)))
1245+
{
1246+
mFeatures.perFrameWindowSizeQuery.enabled = true;
1247+
}
1248+
12431249
if (IsAndroid() && IsQualcomm(mPhysicalDeviceProperties.vendorID))
12441250
{
12451251
mFeatures.forceD16TexFilter.enabled = true;

src/libANGLE/renderer/vulkan/SurfaceVk.cpp

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,8 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::Context *context,
581581
const gl::Extents &extents,
582582
VkSwapchainKHR oldSwapchain)
583583
{
584+
ANGLE_TRACE_EVENT0("gpu.angle", "WindowSurfaceVk::createSwapchain");
585+
584586
ASSERT(mSwapchain == VK_NULL_HANDLE);
585587

586588
RendererVk *renderer = context->getRenderer();
@@ -705,40 +707,45 @@ bool WindowSurfaceVk::isMultiSampled() const
705707

706708
angle::Result WindowSurfaceVk::checkForOutOfDateSwapchain(ContextVk *contextVk,
707709
uint32_t swapHistoryIndex,
708-
bool swapchainOutOfDate)
710+
bool presentOutOfDate)
709711
{
710712
bool swapIntervalChanged = mSwapchainPresentMode != mDesiredSwapchainPresentMode;
711713

712-
// Check for window resize and recreate swapchain if necessary.
713-
gl::Extents currentExtents;
714-
ANGLE_TRY(getCurrentWindowSize(contextVk, &currentExtents));
715-
716-
gl::Extents swapchainExtents(getWidth(), getHeight(), 0);
717-
718-
// If window size has changed, check with surface capabilities. It has been observed on
719-
// Android that `getCurrentWindowSize()` returns 1920x1080 for example, while surface
720-
// capabilities returns the size the surface was created with.
721-
if (currentExtents != swapchainExtents)
714+
// If anything has changed, recreate the swapchain.
715+
if (swapIntervalChanged || presentOutOfDate ||
716+
contextVk->getRenderer()->getFeatures().perFrameWindowSizeQuery.enabled)
722717
{
723-
const VkPhysicalDevice &physicalDevice = contextVk->getRenderer()->getPhysicalDevice();
724-
ANGLE_VK_TRY(contextVk, vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, mSurface,
725-
&mSurfaceCaps));
718+
gl::Extents swapchainExtents(getWidth(), getHeight(), 0);
726719

727-
uint32_t width = mSurfaceCaps.currentExtent.width;
728-
uint32_t height = mSurfaceCaps.currentExtent.height;
720+
gl::Extents currentExtents;
721+
ANGLE_TRY(getCurrentWindowSize(contextVk, &currentExtents));
729722

730-
if (width != 0xFFFFFFFFu)
723+
// If window size has changed, check with surface capabilities. It has been observed on
724+
// Android that `getCurrentWindowSize()` returns 1920x1080 for example, while surface
725+
// capabilities returns the size the surface was created with.
726+
if (currentExtents != swapchainExtents)
731727
{
732-
ASSERT(height != 0xFFFFFFFFu);
733-
currentExtents.width = width;
734-
currentExtents.height = height;
728+
const VkPhysicalDevice &physicalDevice = contextVk->getRenderer()->getPhysicalDevice();
729+
ANGLE_VK_TRY(contextVk, vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
730+
physicalDevice, mSurface, &mSurfaceCaps));
731+
732+
uint32_t width = mSurfaceCaps.currentExtent.width;
733+
uint32_t height = mSurfaceCaps.currentExtent.height;
734+
735+
if (width != 0xFFFFFFFFu)
736+
{
737+
ASSERT(height != 0xFFFFFFFFu);
738+
currentExtents.width = width;
739+
currentExtents.height = height;
740+
}
735741
}
736-
}
737742

738-
// If anything has changed, recreate the swapchain.
739-
if (swapchainOutOfDate || swapIntervalChanged || currentExtents != swapchainExtents)
740-
{
741-
ANGLE_TRY(recreateSwapchain(contextVk, currentExtents, swapHistoryIndex));
743+
// Check for window resize and recreate swapchain if necessary.
744+
// Work-around for some device which does not return OUT_OF_DATE after window resizing
745+
if (swapIntervalChanged || presentOutOfDate || currentExtents != swapchainExtents)
746+
{
747+
ANGLE_TRY(recreateSwapchain(contextVk, currentExtents, swapHistoryIndex));
748+
}
742749
}
743750

744751
return angle::Result::Continue;
@@ -864,7 +871,7 @@ egl::Error WindowSurfaceVk::swap(const gl::Context *context)
864871
angle::Result WindowSurfaceVk::present(ContextVk *contextVk,
865872
EGLint *rects,
866873
EGLint n_rects,
867-
bool &swapchainOutOfDate)
874+
bool *presentOutOfDate)
868875
{
869876
ANGLE_TRACE_EVENT0("gpu.angle", "WindowSurfaceVk::present");
870877

@@ -973,8 +980,8 @@ angle::Result WindowSurfaceVk::present(ContextVk *contextVk,
973980
// recreate the swapchain with a new window orientation. We aren't quite ready for that so just
974981
// ignore for now.
975982
// TODO: Check for preRotation: http://anglebug.com/3502
976-
swapchainOutOfDate = result == VK_ERROR_OUT_OF_DATE_KHR;
977-
if (!swapchainOutOfDate && result != VK_SUBOPTIMAL_KHR)
983+
*presentOutOfDate = result == VK_ERROR_OUT_OF_DATE_KHR;
984+
if (!*presentOutOfDate && result != VK_SUBOPTIMAL_KHR)
978985
{
979986
ANGLE_VK_TRY(contextVk, result);
980987
}
@@ -989,13 +996,13 @@ angle::Result WindowSurfaceVk::swapImpl(const gl::Context *context, EGLint *rect
989996
ContextVk *contextVk = vk::GetImpl(context);
990997
DisplayVk *displayVk = vk::GetImpl(context->getDisplay());
991998

992-
bool swapchainOutOfDate = false;
999+
bool presentOutOfDate = false;
9931000
// Save this now, since present() will increment the value.
9941001
size_t currentSwapHistoryIndex = mCurrentSwapHistoryIndex;
9951002

996-
ANGLE_TRY(present(contextVk, rects, n_rects, swapchainOutOfDate));
1003+
ANGLE_TRY(present(contextVk, rects, n_rects, &presentOutOfDate));
9971004

998-
ANGLE_TRY(checkForOutOfDateSwapchain(contextVk, currentSwapHistoryIndex, swapchainOutOfDate));
1005+
ANGLE_TRY(checkForOutOfDateSwapchain(contextVk, currentSwapHistoryIndex, presentOutOfDate));
9991006

10001007
{
10011008
// Note: TRACE_EVENT0 is put here instead of inside the function to workaround this issue:

src/libANGLE/renderer/vulkan/SurfaceVk.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ class WindowSurfaceVk : public SurfaceVk
171171
angle::Result present(ContextVk *contextVk,
172172
EGLint *rects,
173173
EGLint n_rects,
174-
bool &swapchainOutOfDate);
174+
bool *presentOutOfDate);
175175

176176
angle::Result swapImpl(const gl::Context *context, EGLint *rects, EGLint n_rects);
177177

src/tests/egl_tests/EGLSurfaceTest.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,9 @@ TEST_P(EGLSurfaceTest, ResizeWindow)
302302
// TODO(syoussefi): http://anglebug.com/3123
303303
ANGLE_SKIP_TEST_IF(IsAndroid());
304304

305+
// Necessary for a window resizing test
306+
mOSWindow->setVisible(true);
307+
305308
GLenum platform = GetParam().getRenderer();
306309
bool platformSupportsZeroSize = platform == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE ||
307310
platform == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE;

0 commit comments

Comments
 (0)