Commit f116aa9c by Jiacheng Lu Committed by Commit Bot

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/+/1662759Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarIan Elliott <ianelliott@google.com> Commit-Queue: Ian Elliott <ianelliott@google.com>
parent 4237e53e
...@@ -150,12 +150,12 @@ struct FeaturesVk : FeatureSetBase ...@@ -150,12 +150,12 @@ struct FeaturesVk : FeatureSetBase
// When the scissor is (0,0,0,0) on Windows Intel, the driver acts as if the scissor was // 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 // 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 // (e.g. (renderArea.x, renderArea.y, 1, 1)). http://anglebug.com/3407
Feature forceNonZeroScissor = { Feature forceNonZeroScissor = {
"force_non_zero_scissor", FeatureCategory::VulkanWorkarounds, "force_non_zero_scissor", FeatureCategory::VulkanWorkarounds,
"On Windows Intel, when the scissor is (0,0,0,0), the driver acts as if the " "On Windows Intel, when the scissor is (0,0,0,0), the driver acts as if the "
"scissor was disabled", "scissor was disabled",
&members, "http://anglebug.com/3153"}; &members, "http://anglebug.com/3407"};
// OES_depth_texture is a commonly expected feature on Android. However it // OES_depth_texture is a commonly expected feature on Android. However it
// requires that D16_UNORM support texture filtering // requires that D16_UNORM support texture filtering
...@@ -174,6 +174,16 @@ struct FeaturesVk : FeatureSetBase ...@@ -174,6 +174,16 @@ struct FeaturesVk : FeatureSetBase
"disable_flipping_blit_with_command", FeatureCategory::VulkanWorkarounds, "disable_flipping_blit_with_command", FeatureCategory::VulkanWorkarounds,
"On some android devices, vkCmdBlitImage with flipped coordinates blits incorrectly.", "On some android devices, vkCmdBlitImage with flipped coordinates blits incorrectly.",
&members, "http://anglebug.com/3498"}; &members, "http://anglebug.com/3498"};
// On platform with Intel or AMD GPU, a window resizing would not trigger the vulkan driver to
// return VK_ERROR_OUT_OF_DATE on swapchain present. Work-around by query current window extent
// every frame to detect a window resizing.
// http://anglebug.com/3623, http://anglebug.com/3624, http://anglebug.com/3625
Feature perFrameWindowSizeQuery = {
"per_frame_window_size_query", FeatureCategory::VulkanWorkarounds,
"On platform with Intel or AMD gpu, vulkan swapchain is not returning VK_ERROR_OUT_OF_DATE"
"when window resizing",
&members, "http://anglebug.com/3623, http://anglebug.com/3624, http://anglebug.com/3625"};
}; };
inline FeaturesVk::FeaturesVk() = default; inline FeaturesVk::FeaturesVk() = default;
......
...@@ -1240,6 +1240,12 @@ void RendererVk::initFeatures(const ExtensionNameList &deviceExtensionNames) ...@@ -1240,6 +1240,12 @@ void RendererVk::initFeatures(const ExtensionNameList &deviceExtensionNames)
mFeatures.forceNonZeroScissor.enabled = true; mFeatures.forceNonZeroScissor.enabled = true;
} }
if (IsIntel(mPhysicalDeviceProperties.vendorID) ||
(IsWindows() && IsAMD(mPhysicalDeviceProperties.vendorID)))
{
mFeatures.perFrameWindowSizeQuery.enabled = true;
}
if (IsAndroid() && IsQualcomm(mPhysicalDeviceProperties.vendorID)) if (IsAndroid() && IsQualcomm(mPhysicalDeviceProperties.vendorID))
{ {
mFeatures.forceD16TexFilter.enabled = true; mFeatures.forceD16TexFilter.enabled = true;
......
...@@ -581,6 +581,8 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::Context *context, ...@@ -581,6 +581,8 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::Context *context,
const gl::Extents &extents, const gl::Extents &extents,
VkSwapchainKHR oldSwapchain) VkSwapchainKHR oldSwapchain)
{ {
ANGLE_TRACE_EVENT0("gpu.angle", "WindowSurfaceVk::createSwapchain");
ASSERT(mSwapchain == VK_NULL_HANDLE); ASSERT(mSwapchain == VK_NULL_HANDLE);
RendererVk *renderer = context->getRenderer(); RendererVk *renderer = context->getRenderer();
...@@ -705,40 +707,45 @@ bool WindowSurfaceVk::isMultiSampled() const ...@@ -705,40 +707,45 @@ bool WindowSurfaceVk::isMultiSampled() const
angle::Result WindowSurfaceVk::checkForOutOfDateSwapchain(ContextVk *contextVk, angle::Result WindowSurfaceVk::checkForOutOfDateSwapchain(ContextVk *contextVk,
uint32_t swapHistoryIndex, uint32_t swapHistoryIndex,
bool swapchainOutOfDate) bool presentOutOfDate)
{ {
bool swapIntervalChanged = mSwapchainPresentMode != mDesiredSwapchainPresentMode; bool swapIntervalChanged = mSwapchainPresentMode != mDesiredSwapchainPresentMode;
// Check for window resize and recreate swapchain if necessary. // If anything has changed, recreate the swapchain.
gl::Extents currentExtents; if (swapIntervalChanged || presentOutOfDate ||
ANGLE_TRY(getCurrentWindowSize(contextVk, &currentExtents)); contextVk->getRenderer()->getFeatures().perFrameWindowSizeQuery.enabled)
gl::Extents swapchainExtents(getWidth(), getHeight(), 0);
// If window size has changed, check with surface capabilities. It has been observed on
// Android that `getCurrentWindowSize()` returns 1920x1080 for example, while surface
// capabilities returns the size the surface was created with.
if (currentExtents != swapchainExtents)
{ {
const VkPhysicalDevice &physicalDevice = contextVk->getRenderer()->getPhysicalDevice(); gl::Extents swapchainExtents(getWidth(), getHeight(), 0);
ANGLE_VK_TRY(contextVk, vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, mSurface,
&mSurfaceCaps));
uint32_t width = mSurfaceCaps.currentExtent.width; gl::Extents currentExtents;
uint32_t height = mSurfaceCaps.currentExtent.height; ANGLE_TRY(getCurrentWindowSize(contextVk, &currentExtents));
if (width != 0xFFFFFFFFu) // If window size has changed, check with surface capabilities. It has been observed on
// Android that `getCurrentWindowSize()` returns 1920x1080 for example, while surface
// capabilities returns the size the surface was created with.
if (currentExtents != swapchainExtents)
{ {
ASSERT(height != 0xFFFFFFFFu); const VkPhysicalDevice &physicalDevice = contextVk->getRenderer()->getPhysicalDevice();
currentExtents.width = width; ANGLE_VK_TRY(contextVk, vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
currentExtents.height = height; physicalDevice, mSurface, &mSurfaceCaps));
uint32_t width = mSurfaceCaps.currentExtent.width;
uint32_t height = mSurfaceCaps.currentExtent.height;
if (width != 0xFFFFFFFFu)
{
ASSERT(height != 0xFFFFFFFFu);
currentExtents.width = width;
currentExtents.height = height;
}
} }
}
// If anything has changed, recreate the swapchain. // Check for window resize and recreate swapchain if necessary.
if (swapchainOutOfDate || swapIntervalChanged || currentExtents != swapchainExtents) // Work-around for some device which does not return OUT_OF_DATE after window resizing
{ if (swapIntervalChanged || presentOutOfDate || currentExtents != swapchainExtents)
ANGLE_TRY(recreateSwapchain(contextVk, currentExtents, swapHistoryIndex)); {
ANGLE_TRY(recreateSwapchain(contextVk, currentExtents, swapHistoryIndex));
}
} }
return angle::Result::Continue; return angle::Result::Continue;
...@@ -864,7 +871,7 @@ egl::Error WindowSurfaceVk::swap(const gl::Context *context) ...@@ -864,7 +871,7 @@ egl::Error WindowSurfaceVk::swap(const gl::Context *context)
angle::Result WindowSurfaceVk::present(ContextVk *contextVk, angle::Result WindowSurfaceVk::present(ContextVk *contextVk,
EGLint *rects, EGLint *rects,
EGLint n_rects, EGLint n_rects,
bool &swapchainOutOfDate) bool *presentOutOfDate)
{ {
ANGLE_TRACE_EVENT0("gpu.angle", "WindowSurfaceVk::present"); ANGLE_TRACE_EVENT0("gpu.angle", "WindowSurfaceVk::present");
...@@ -973,8 +980,8 @@ angle::Result WindowSurfaceVk::present(ContextVk *contextVk, ...@@ -973,8 +980,8 @@ angle::Result WindowSurfaceVk::present(ContextVk *contextVk,
// recreate the swapchain with a new window orientation. We aren't quite ready for that so just // recreate the swapchain with a new window orientation. We aren't quite ready for that so just
// ignore for now. // ignore for now.
// TODO: Check for preRotation: http://anglebug.com/3502 // TODO: Check for preRotation: http://anglebug.com/3502
swapchainOutOfDate = result == VK_ERROR_OUT_OF_DATE_KHR; *presentOutOfDate = result == VK_ERROR_OUT_OF_DATE_KHR;
if (!swapchainOutOfDate && result != VK_SUBOPTIMAL_KHR) if (!*presentOutOfDate && result != VK_SUBOPTIMAL_KHR)
{ {
ANGLE_VK_TRY(contextVk, result); ANGLE_VK_TRY(contextVk, result);
} }
...@@ -989,13 +996,13 @@ angle::Result WindowSurfaceVk::swapImpl(const gl::Context *context, EGLint *rect ...@@ -989,13 +996,13 @@ angle::Result WindowSurfaceVk::swapImpl(const gl::Context *context, EGLint *rect
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
DisplayVk *displayVk = vk::GetImpl(context->getDisplay()); DisplayVk *displayVk = vk::GetImpl(context->getDisplay());
bool swapchainOutOfDate = false; bool presentOutOfDate = false;
// Save this now, since present() will increment the value. // Save this now, since present() will increment the value.
size_t currentSwapHistoryIndex = mCurrentSwapHistoryIndex; size_t currentSwapHistoryIndex = mCurrentSwapHistoryIndex;
ANGLE_TRY(present(contextVk, rects, n_rects, swapchainOutOfDate)); ANGLE_TRY(present(contextVk, rects, n_rects, &presentOutOfDate));
ANGLE_TRY(checkForOutOfDateSwapchain(contextVk, currentSwapHistoryIndex, swapchainOutOfDate)); ANGLE_TRY(checkForOutOfDateSwapchain(contextVk, currentSwapHistoryIndex, presentOutOfDate));
{ {
// Note: TRACE_EVENT0 is put here instead of inside the function to workaround this issue: // Note: TRACE_EVENT0 is put here instead of inside the function to workaround this issue:
......
...@@ -171,7 +171,7 @@ class WindowSurfaceVk : public SurfaceVk ...@@ -171,7 +171,7 @@ class WindowSurfaceVk : public SurfaceVk
angle::Result present(ContextVk *contextVk, angle::Result present(ContextVk *contextVk,
EGLint *rects, EGLint *rects,
EGLint n_rects, EGLint n_rects,
bool &swapchainOutOfDate); bool *presentOutOfDate);
angle::Result swapImpl(const gl::Context *context, EGLint *rects, EGLint n_rects); angle::Result swapImpl(const gl::Context *context, EGLint *rects, EGLint n_rects);
......
...@@ -302,6 +302,9 @@ TEST_P(EGLSurfaceTest, ResizeWindow) ...@@ -302,6 +302,9 @@ TEST_P(EGLSurfaceTest, ResizeWindow)
// TODO(syoussefi): http://anglebug.com/3123 // TODO(syoussefi): http://anglebug.com/3123
ANGLE_SKIP_TEST_IF(IsAndroid()); ANGLE_SKIP_TEST_IF(IsAndroid());
// Necessary for a window resizing test
mOSWindow->setVisible(true);
GLenum platform = GetParam().getRenderer(); GLenum platform = GetParam().getRenderer();
bool platformSupportsZeroSize = platform == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE || bool platformSupportsZeroSize = platform == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE ||
platform == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE; platform == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE;
......
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