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
// 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
// (e.g. (renderArea.x, renderArea.y, 1, 1)). http://anglebug.com/3407
Feature forceNonZeroScissor = {
"force_non_zero_scissor", FeatureCategory::VulkanWorkarounds,
"On Windows Intel, when the scissor is (0,0,0,0), the driver acts as if the "
"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
// requires that D16_UNORM support texture filtering
......@@ -174,6 +174,16 @@ struct FeaturesVk : FeatureSetBase
"disable_flipping_blit_with_command", FeatureCategory::VulkanWorkarounds,
"On some android devices, vkCmdBlitImage with flipped coordinates blits incorrectly.",
&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;
......
......@@ -1240,6 +1240,12 @@ void RendererVk::initFeatures(const ExtensionNameList &deviceExtensionNames)
mFeatures.forceNonZeroScissor.enabled = true;
}
if (IsIntel(mPhysicalDeviceProperties.vendorID) ||
(IsWindows() && IsAMD(mPhysicalDeviceProperties.vendorID)))
{
mFeatures.perFrameWindowSizeQuery.enabled = true;
}
if (IsAndroid() && IsQualcomm(mPhysicalDeviceProperties.vendorID))
{
mFeatures.forceD16TexFilter.enabled = true;
......
......@@ -581,6 +581,8 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::Context *context,
const gl::Extents &extents,
VkSwapchainKHR oldSwapchain)
{
ANGLE_TRACE_EVENT0("gpu.angle", "WindowSurfaceVk::createSwapchain");
ASSERT(mSwapchain == VK_NULL_HANDLE);
RendererVk *renderer = context->getRenderer();
......@@ -705,40 +707,45 @@ bool WindowSurfaceVk::isMultiSampled() const
angle::Result WindowSurfaceVk::checkForOutOfDateSwapchain(ContextVk *contextVk,
uint32_t swapHistoryIndex,
bool swapchainOutOfDate)
bool presentOutOfDate)
{
bool swapIntervalChanged = mSwapchainPresentMode != mDesiredSwapchainPresentMode;
// Check for window resize and recreate swapchain if necessary.
gl::Extents currentExtents;
ANGLE_TRY(getCurrentWindowSize(contextVk, &currentExtents));
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)
// If anything has changed, recreate the swapchain.
if (swapIntervalChanged || presentOutOfDate ||
contextVk->getRenderer()->getFeatures().perFrameWindowSizeQuery.enabled)
{
const VkPhysicalDevice &physicalDevice = contextVk->getRenderer()->getPhysicalDevice();
ANGLE_VK_TRY(contextVk, vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, mSurface,
&mSurfaceCaps));
gl::Extents swapchainExtents(getWidth(), getHeight(), 0);
uint32_t width = mSurfaceCaps.currentExtent.width;
uint32_t height = mSurfaceCaps.currentExtent.height;
gl::Extents currentExtents;
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);
currentExtents.width = width;
currentExtents.height = height;
const VkPhysicalDevice &physicalDevice = contextVk->getRenderer()->getPhysicalDevice();
ANGLE_VK_TRY(contextVk, vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
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.
if (swapchainOutOfDate || swapIntervalChanged || currentExtents != swapchainExtents)
{
ANGLE_TRY(recreateSwapchain(contextVk, currentExtents, swapHistoryIndex));
// Check for window resize and recreate swapchain if necessary.
// 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));
}
}
return angle::Result::Continue;
......@@ -864,7 +871,7 @@ egl::Error WindowSurfaceVk::swap(const gl::Context *context)
angle::Result WindowSurfaceVk::present(ContextVk *contextVk,
EGLint *rects,
EGLint n_rects,
bool &swapchainOutOfDate)
bool *presentOutOfDate)
{
ANGLE_TRACE_EVENT0("gpu.angle", "WindowSurfaceVk::present");
......@@ -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
// ignore for now.
// TODO: Check for preRotation: http://anglebug.com/3502
swapchainOutOfDate = result == VK_ERROR_OUT_OF_DATE_KHR;
if (!swapchainOutOfDate && result != VK_SUBOPTIMAL_KHR)
*presentOutOfDate = result == VK_ERROR_OUT_OF_DATE_KHR;
if (!*presentOutOfDate && result != VK_SUBOPTIMAL_KHR)
{
ANGLE_VK_TRY(contextVk, result);
}
......@@ -989,13 +996,13 @@ angle::Result WindowSurfaceVk::swapImpl(const gl::Context *context, EGLint *rect
ContextVk *contextVk = vk::GetImpl(context);
DisplayVk *displayVk = vk::GetImpl(context->getDisplay());
bool swapchainOutOfDate = false;
bool presentOutOfDate = false;
// Save this now, since present() will increment the value.
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:
......
......@@ -171,7 +171,7 @@ class WindowSurfaceVk : public SurfaceVk
angle::Result present(ContextVk *contextVk,
EGLint *rects,
EGLint n_rects,
bool &swapchainOutOfDate);
bool *presentOutOfDate);
angle::Result swapImpl(const gl::Context *context, EGLint *rects, EGLint n_rects);
......
......@@ -302,6 +302,9 @@ TEST_P(EGLSurfaceTest, ResizeWindow)
// TODO(syoussefi): http://anglebug.com/3123
ANGLE_SKIP_TEST_IF(IsAndroid());
// Necessary for a window resizing test
mOSWindow->setVisible(true);
GLenum platform = GetParam().getRenderer();
bool platformSupportsZeroSize = platform == EGL_PLATFORM_ANGLE_TYPE_D3D11_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