Vulkan: fix CPU throttling frames to 2 Previously, the CPU was throttled to be at most N frames ahead, N being the number of swapchain images. N is now fixed to 2, regardless of the number of swapchain images. If N < 2, we would be stalling the CPU unnecessarily, and if N > 2, the CPU could get too far ahead. Effectively, here is how the throttling plays out with this commit: Submit (Fence 1) + Present Submit (Fence 2) + Present Wait Fence 1 Submit (Fence 3) + Present Wait Fence 2 Submit (Fence 4) + Present Wait Fence 3 Submit (Fence 5) + Present Wait Fence 4 ... Bug: angleproject:2942 Change-Id: I3b8c3bb88e52d62231306ec84aad50d2bf472d8c Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1558681 Reviewed-by: Ian Elliott <ianelliott@google.com> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/SurfaceVk.cpp b/src/libANGLE/renderer/vulkan/SurfaceVk.cpp index 8164a91..024111a 100644 --- a/src/libANGLE/renderer/vulkan/SurfaceVk.cpp +++ b/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
@@ -559,7 +559,6 @@ vkGetSwapchainImagesKHR(device, mSwapchain, &imageCount, swapchainImages.data())); mSwapchainImages.resize(imageCount); - ANGLE_TRY(resizeSwapHistory(displayVk, imageCount)); for (uint32_t imageIndex = 0; imageIndex < imageCount; ++imageIndex) { @@ -838,78 +837,6 @@ return angle::Result::Continue; } -angle::Result WindowSurfaceVk::resizeSwapHistory(DisplayVk *displayVk, size_t imageCount) -{ - // The number of swapchain images can change if the present mode is changed. If that number is - // increased, we need to rearrange the history (which is a circular buffer) so it remains - // continuous. If it shrinks, we have to additionally make sure we clean up any old swapchains - // that can no longer fit in the history. - // - // Assume the following history buffer identified with serials: - // - // mCurrentSwapHistoryIndex - // V - // +----+----+----+ - // | 11 | 9 | 10 | - // +----+----+----+ - // - // When shrinking to size 2, we want to clean up 9, and rearrange to the following: - // - // mCurrentSwapHistoryIndex - // V - // +----+----+ - // | 10 | 11 | - // +----+----+ - // - // When expanding back to 3, we want to rearrange to the following: - // - // mCurrentSwapHistoryIndex - // V - // +----+----+----+ - // | 0 | 10 | 11 | - // +----+----+----+ - - if (mSwapHistory.size() == imageCount) - { - return angle::Result::Continue; - } - - RendererVk *renderer = displayVk->getRenderer(); - - // First, clean up anything that won't fit in the resized history. - if (imageCount < mSwapHistory.size()) - { - size_t toClean = mSwapHistory.size() - imageCount; - for (size_t i = 0; i < toClean; ++i) - { - size_t historyIndex = (mCurrentSwapHistoryIndex + i) % mSwapHistory.size(); - SwapHistory &swap = mSwapHistory[historyIndex]; - - ANGLE_TRY(renderer->finishToSerial(displayVk, swap.serial)); - swap.destroy(renderer->getDevice()); - } - } - - // Now, move the history, from most recent to oldest (as much as fits), into a new vector. - std::vector<SwapHistory> resizedHistory(imageCount); - - size_t toCopy = std::min(imageCount, mSwapHistory.size()); - for (size_t i = 0; i < toCopy; ++i) - { - size_t historyIndex = - (mCurrentSwapHistoryIndex + mSwapHistory.size() - i - 1) % mSwapHistory.size(); - size_t resizedHistoryIndex = imageCount - i - 1; - resizedHistory[resizedHistoryIndex] = std::move(mSwapHistory[historyIndex]); - } - - // Set this as the new history. Note that after rearranging in either case, the oldest history - // is at index 0. - mSwapHistory = std::move(resizedHistory); - mCurrentSwapHistoryIndex = 0; - - return angle::Result::Continue; -} - egl::Error WindowSurfaceVk::postSubBuffer(const gl::Context *context, EGLint x, EGLint y,
diff --git a/src/libANGLE/renderer/vulkan/SurfaceVk.h b/src/libANGLE/renderer/vulkan/SurfaceVk.h index 8ea5290..886e902 100644 --- a/src/libANGLE/renderer/vulkan/SurfaceVk.h +++ b/src/libANGLE/renderer/vulkan/SurfaceVk.h
@@ -163,7 +163,6 @@ EGLint n_rects, bool &swapchainOutOfDate); angle::Result swapImpl(DisplayVk *displayVk, EGLint *rects, EGLint n_rects); - angle::Result resizeSwapHistory(DisplayVk *displayVk, size_t imageCount); VkSurfaceCapabilitiesKHR mSurfaceCaps; std::vector<VkPresentModeKHR> mPresentModes; @@ -212,9 +211,9 @@ // results cannot affect the images in a swap chain. std::vector<vk::Semaphore> mFlushSemaphoreChain; - // A circular buffer, with the same size as mSwapchainImages (N), that stores the serial of the - // 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. + // A circular buffer that stores the serial of the renderer on every swap. The CPU is + // throttled by waiting for the 2nd previous serial to finish. Old swapchains are scheduled to + // be destroyed at the same time. struct SwapHistory : angle::NonCopyable { SwapHistory(); @@ -228,7 +227,8 @@ std::vector<vk::Semaphore> semaphores; VkSwapchainKHR swapchain = VK_NULL_HANDLE; }; - std::vector<SwapHistory> mSwapHistory; + static constexpr size_t kSwapHistorySize = 2; + std::array<SwapHistory, kSwapHistorySize> mSwapHistory; size_t mCurrentSwapHistoryIndex; vk::ImageHelper mDepthStencilImage;