Commit af0301a8 by Shahbaz Youssefi Committed by Commit Bot

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/+/1558681Reviewed-by: 's avatarIan Elliott <ianelliott@google.com> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
parent 3702d8c9
......@@ -559,7 +559,6 @@ angle::Result WindowSurfaceVk::recreateSwapchain(DisplayVk *displayVk,
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 @@ angle::Result WindowSurfaceVk::nextSwapchainImage(DisplayVk *displayVk)
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,
......
......@@ -163,7 +163,6 @@ class WindowSurfaceVk : public SurfaceImpl
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 @@ class WindowSurfaceVk : public SurfaceImpl
// 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 @@ class WindowSurfaceVk : public SurfaceImpl
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;
......
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