Commit ab5acbd5 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: implement swapchain resizing

Vulkan allows a swapchain to be created based off of an older swapchain that's still presenting, to support seamless window resizing. The old swapchain will remain alive (though no image can be acquired from it) and automatically cleaned once no image is being presented from it. The retired swapchain can be destroyed once all operations on its images are completed. We store the old swapchain next to the serial of submission that's used for CPU throttling and defer the destroy call until after `finishToSerial` for that serial is called. Bug: angleproject:2942 Change-Id: Ic62a5a57b712ffa2b087f5fecde0dc8942194075 Reviewed-on: https://chromium-review.googlesource.com/c/1435634 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarYuly Novikov <ynovikov@chromium.org>
parent 088e5217
......@@ -141,12 +141,25 @@ class WindowSurfaceVk : public SurfaceImpl
private:
virtual angle::Result createSurfaceVk(vk::Context *context, gl::Extents *extentsOut) = 0;
virtual angle::Result getCurrentWindowSize(vk::Context *context, gl::Extents *extentsOut) = 0;
angle::Result initializeImpl(DisplayVk *displayVk);
angle::Result recreateSwapchain(DisplayVk *displayVk,
const gl::Extents &extents,
uint32_t swapHistoryIndex);
angle::Result checkForOutOfDateSwapchain(DisplayVk *displayVk,
uint32_t swapHistoryIndex,
bool presentOutOfDate);
void releaseSwapchainImages(RendererVk *renderer);
angle::Result nextSwapchainImage(DisplayVk *displayVk);
angle::Result swapImpl(DisplayVk *displayVk, EGLint *rects, EGLint n_rects);
VkSwapchainKHR mSwapchain;
// Cached information used to recreate swapchains.
VkPresentModeKHR mSwapchainPresentMode;
uint32_t mMinImageCount;
VkSurfaceTransformFlagBitsKHR mPreTransform;
VkCompositeAlphaFlagBitsKHR mCompositeAlpha;
RenderTargetVk mColorRenderTarget;
RenderTargetVk mDepthStencilRenderTarget;
......@@ -167,10 +180,15 @@ class WindowSurfaceVk : public SurfaceImpl
std::vector<SwapchainImage> mSwapchainImages;
// A circular buffer, with the same size as mSwapchainImages (N), that stores the serial of the
// renderer on every swap. In FIFO present modes, the CPU is throttled by waiting for the
// Nth previous serial to finish.
std::vector<Serial> mSwapSerials;
size_t mCurrentSwapSerialIndex;
// renderer on every swap. The CPU is throttled by waiting for the Nth previous serial to
// finish. Old swapchains are scheduled to be destroyed at the same time.
struct SwapHistory
{
Serial serial;
VkSwapchainKHR swapchain = VK_NULL_HANDLE;
};
std::vector<SwapHistory> mSwapHistory;
size_t mCurrentSwapHistoryIndex;
vk::ImageHelper mDepthStencilImage;
vk::ImageView mDepthStencilImageView;
......
......@@ -33,6 +33,12 @@ angle::Result WindowSurfaceVkAndroid::createSurfaceVk(vk::Context *context, gl::
ANGLE_VK_TRY(context, vkCreateAndroidSurfaceKHR(context->getRenderer()->getInstance(),
&createInfo, nullptr, &mSurface));
return getCurrentWindowSize(context, extentsOut);
}
angle::Result WindowSurfaceVkAndroid::getCurrentWindowSize(vk::Context *context,
gl::Extents *extentsOut)
{
int32_t width = ANativeWindow_getWidth(mNativeWindowType);
int32_t height = ANativeWindow_getHeight(mNativeWindowType);
ANGLE_VK_CHECK(context, width > 0 && height > 0, VK_ERROR_INITIALIZATION_FAILED);
......
......@@ -25,6 +25,7 @@ class WindowSurfaceVkAndroid : public WindowSurfaceVk
private:
angle::Result createSurfaceVk(vk::Context *context, gl::Extents *extentsOut) override;
angle::Result getCurrentWindowSize(vk::Context *context, gl::Extents *extentsOut) override;
};
} // namespace rx
......
......@@ -1403,6 +1403,7 @@ void ImageHelper::init2DWeakReference(VkImage handle,
mExtents = extents;
mFormat = &format;
mSamples = samples;
mCurrentLayout = ImageLayout::Undefined;
mLayerCount = 1;
mLevelCount = 1;
......
......@@ -32,6 +32,12 @@ angle::Result WindowSurfaceVkWin32::createSurfaceVk(vk::Context *context, gl::Ex
ANGLE_VK_TRY(context, vkCreateWin32SurfaceKHR(context->getRenderer()->getInstance(),
&createInfo, nullptr, &mSurface));
return getCurrentWindowSize(context, extentsOut);
}
angle::Result WindowSurfaceVkWin32::getCurrentWindowSize(vk::Context *context,
gl::Extents *extentsOut)
{
RECT rect;
ANGLE_VK_CHECK(context, GetClientRect(mNativeWindowType, &rect) == TRUE,
VK_ERROR_INITIALIZATION_FAILED);
......
......@@ -25,6 +25,7 @@ class WindowSurfaceVkWin32 : public WindowSurfaceVk
private:
angle::Result createSurfaceVk(vk::Context *context, gl::Extents *extentsOut) override;
angle::Result getCurrentWindowSize(vk::Context *context, gl::Extents *extentsOut) override;
};
} // namespace rx
......
......@@ -33,6 +33,12 @@ angle::Result WindowSurfaceVkXcb::createSurfaceVk(vk::Context *context, gl::Exte
ANGLE_VK_TRY(context, vkCreateXcbSurfaceKHR(context->getRenderer()->getInstance(), &createInfo,
nullptr, &mSurface));
return getCurrentWindowSize(context, extentsOut);
}
angle::Result WindowSurfaceVkXcb::getCurrentWindowSize(vk::Context *context,
gl::Extents *extentsOut)
{
xcb_get_geometry_cookie_t cookie = xcb_get_geometry(mXcbConnection, mNativeWindowType);
xcb_get_geometry_reply_t *reply = xcb_get_geometry_reply(mXcbConnection, cookie, nullptr);
ASSERT(reply);
......
......@@ -28,6 +28,7 @@ class WindowSurfaceVkXcb : public WindowSurfaceVk
private:
angle::Result createSurfaceVk(vk::Context *context, gl::Extents *extentsOut) override;
angle::Result getCurrentWindowSize(vk::Context *context, gl::Extents *extentsOut) override;
xcb_connection_t *mXcbConnection;
};
......
......@@ -178,7 +178,6 @@
2635 WIN VULKAN : dEQP-EGL.functional.resize.surface_size.stretch_width = FAIL
2635 WIN VULKAN : dEQP-EGL.functional.wide_color.pbuffer_8888_colorspace_default = FAIL
2716 WIN VULKAN : dEQP-EGL.functional.preserve_swap.no_preserve.* = FAIL
2811 WIN VULKAN : dEQP-EGL.functional.swap_buffers_with_damage.resize* = SKIP
// Linux failures
2546 LINUX : dEQP-EGL.functional.color_clears.multi_context.gles1.rgba8888_pixmap = SKIP
......
......@@ -431,7 +431,7 @@ bool X11Window::resize(int width, int height)
// Wait until the window as actually been resized so that the code calling resize
// can assume the window has been resized.
const double kResizeWaitDelay = 0.2;
while (mHeight != height && mWidth != width && timer->getElapsedTime() < kResizeWaitDelay)
while ((mHeight != height || mWidth != width) && timer->getElapsedTime() < kResizeWaitDelay)
{
messageLoop();
angle::Sleep(10);
......@@ -478,6 +478,10 @@ void X11Window::signalTestEvent()
// Hijack StructureNotifyMask as we know we will be listening for it.
XSendEvent(mDisplay, mWindow, False, StructureNotifyMask, &event);
// For test events, the tests want to check that it really did arrive, and they don't wait
// long. XSync here makes sure the event is sent by the time the messageLoop() is called.
XSync(mDisplay, false);
}
void X11Window::processEvent(const XEvent &xEvent)
......
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