Vulkan: Include minImageCount in swapchain check

The following VVL error has been firing for traces run in
landscape mode:

[ VUID-VkSwapchainCreateInfoKHR-presentMode-02839 ]
vkCreateSwapchainKHR(): pCreateInfo.minImageCount 4, which is outside
the bounds returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR()
(i.e. minImageCount = 5, maxImageCount = 64).

On Android, rotation can cause minImageCount to change.
We need to detect this as an out of date swapchain.

Test: angle_trace_test --gtest_filter=TraceTest.among_us
Bug: b/289274676
Change-Id: Ie75adec5f5318b73c0c27efc134f10f53485692d
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4819790
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
Commit-Queue: Cody Northrop <cnorthrop@google.com>
Reviewed-by: Charlie Lao <cclao@google.com>
This commit is contained in:
Cody Northrop
2023-08-28 16:30:23 -07:00
committed by Angle LUCI CQ
parent 7b0bb0f6e7
commit 00daa45132

View File

@@ -108,6 +108,29 @@ vk::PresentMode GetDesiredPresentMode(const std::vector<vk::PresentMode> &presen
return vk::PresentMode::FifoKHR;
}
uint32_t GetMinImageCount(const VkSurfaceCapabilitiesKHR &surfaceCaps)
{
// - On mailbox, we need at least three images; one is being displayed to the user until the
// next v-sync, and the application alternatingly renders to the other two, one being
// recorded, and the other queued for presentation if v-sync happens in the meantime.
// - On immediate, we need at least two images; the application alternates between the two
// images.
// - On fifo, we use at least three images. Triple-buffering allows us to present an image,
// have one in the queue, and record in another. Note: on certain configurations (windows +
// nvidia + windowed mode), we could get away with a smaller number.
//
// For simplicity, we always allocate at least three images.
uint32_t minImageCount = std::max(3u, surfaceCaps.minImageCount);
// Make sure we don't exceed maxImageCount.
if (surfaceCaps.maxImageCount > 0 && minImageCount > surfaceCaps.maxImageCount)
{
minImageCount = surfaceCaps.maxImageCount;
}
return minImageCount;
}
constexpr VkImageUsageFlags kSurfaceVkImageUsageFlags =
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
constexpr VkImageUsageFlags kSurfaceVkColorImageUsageFlags =
@@ -1788,16 +1811,26 @@ angle::Result WindowSurfaceVk::checkForOutOfDateSwapchain(ContextVk *contextVk,
// Get the latest surface capabilities.
ANGLE_TRY(queryAndAdjustSurfaceCaps(contextVk, &mSurfaceCaps));
if (contextVk->getRenderer()->getFeatures().perFrameWindowSizeQuery.enabled &&
!presentOutOfDate)
if (contextVk->getRenderer()->getFeatures().perFrameWindowSizeQuery.enabled)
{
// This device generates neither VK_ERROR_OUT_OF_DATE_KHR nor VK_SUBOPTIMAL_KHR. Check for
// whether the size and/or rotation have changed since the swapchain was created.
uint32_t swapchainWidth = getWidth();
uint32_t swapchainHeight = getHeight();
presentOutOfDate = mSurfaceCaps.currentTransform != mPreTransform ||
mSurfaceCaps.currentExtent.width != swapchainWidth ||
mSurfaceCaps.currentExtent.height != swapchainHeight;
// On Android, rotation can cause the minImageCount to change
uint32_t minImageCount = GetMinImageCount(mSurfaceCaps);
if (mMinImageCount != minImageCount)
{
presentOutOfDate = true;
mMinImageCount = minImageCount;
}
if (!presentOutOfDate)
{
// This device generates neither VK_ERROR_OUT_OF_DATE_KHR nor VK_SUBOPTIMAL_KHR. Check
// for whether the size and/or rotation have changed since the swapchain was created.
uint32_t swapchainWidth = getWidth();
uint32_t swapchainHeight = getHeight();
presentOutOfDate = mSurfaceCaps.currentTransform != mPreTransform ||
mSurfaceCaps.currentExtent.width != swapchainWidth ||
mSurfaceCaps.currentExtent.height != swapchainHeight;
}
}
// If anything has changed, recreate the swapchain.
@@ -2767,23 +2800,8 @@ void WindowSurfaceVk::setSwapInterval(EGLint interval)
mDesiredSwapchainPresentMode = GetDesiredPresentMode(mPresentModes, interval);
// - On mailbox, we need at least three images; one is being displayed to the user until the
// next v-sync, and the application alternatingly renders to the other two, one being
// recorded, and the other queued for presentation if v-sync happens in the meantime.
// - On immediate, we need at least two images; the application alternates between the two
// images.
// - On fifo, we use at least three images. Triple-buffering allows us to present an image,
// have one in the queue, and record in another. Note: on certain configurations (windows +
// nvidia + windowed mode), we could get away with a smaller number.
//
// For simplicity, we always allocate at least three images.
mMinImageCount = std::max(3u, mSurfaceCaps.minImageCount);
// Make sure we don't exceed maxImageCount.
if (mSurfaceCaps.maxImageCount > 0 && mMinImageCount > mSurfaceCaps.maxImageCount)
{
mMinImageCount = mSurfaceCaps.maxImageCount;
}
// minImageCount may vary based on the Present Mode
mMinImageCount = GetMinImageCount(mSurfaceCaps);
// On the next swap, if the desired present mode is different from the current one, the
// swapchain will be recreated.