Vulkan: Workaround oldSwapchin bug on Android

When vkCreateSwapchainKHR is called with a valid oldSwapchain, the
Android framework destroys the images in oldSwapchain.  This is not
correct, as it should be deferred to the actual vkDestroySwapchainKHR
call performed later by ANGLE.  This is because rendering to the
oldSwapchain could still be in progress.

While this issue affects all of Android, currently only ARM shows any
symptoms.  A workaround is added for ARM to vkDeviceWaitIdle before
recreating the swapchain if oldSwapchain is valid.

Bug: angleproject:5061
Change-Id: I308e4798c6418d7891d880218b0ebcfd7a795643
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2416238
Reviewed-by: Sunny Sun <sunny.sun@arm.com>
Reviewed-by: Ian Elliott <ianelliott@google.com>
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
This commit is contained in:
Shahbaz Youssefi 2020-09-17 10:34:07 -04:00 коммит произвёл Commit Bot
Родитель 4043b9d103
Коммит 68c424fe42
3 изменённых файлов: 18 добавлений и 0 удалений

Просмотреть файл

@ -370,6 +370,14 @@ struct FeaturesVk : FeatureSetBase
"defer_flush_until_endrenderpass", FeatureCategory::VulkanWorkarounds, "defer_flush_until_endrenderpass", FeatureCategory::VulkanWorkarounds,
"Allow glFlush to be deferred until renderpass ends", &members, "Allow glFlush to be deferred until renderpass ends", &members,
"https://issuetracker.google.com/issues/166475273"}; "https://issuetracker.google.com/issues/166475273"};
// Android mistakenly destroys oldSwapchain passed to vkCreateSwapchainKHR, causing crashes on
// certain drivers. http://anglebug.com/5061
Feature waitIdleBeforeSwapchainRecreation = {
"wait_idle_before_swapchain_recreation", FeatureCategory::VulkanWorkarounds,
"Before passing an oldSwapchain to VkSwapchainCreateInfoKHR, wait for queue to be idle. "
"Works around a bug on platforms which destroy oldSwapchain in vkCreateSwapchainKHR.",
&members, "http://anglebug.com/5061"};
}; };
inline FeaturesVk::FeaturesVk() = default; inline FeaturesVk::FeaturesVk() = default;

Просмотреть файл

@ -1868,6 +1868,9 @@ void RendererVk::initFeatures(DisplayVk *displayVk, const ExtensionNameList &dev
ANGLE_FEATURE_CONDITION(&mFeatures, deferFlushUntilEndRenderPass, true); ANGLE_FEATURE_CONDITION(&mFeatures, deferFlushUntilEndRenderPass, true);
// Android mistakenly destroys the old swapchain when creating a new one.
ANGLE_FEATURE_CONDITION(&mFeatures, waitIdleBeforeSwapchainRecreation, IsAndroid() && isARM);
angle::PlatformMethods *platform = ANGLEPlatformCurrent(); angle::PlatformMethods *platform = ANGLEPlatformCurrent();
platform->overrideFeaturesVk(platform, &mFeatures); platform->overrideFeaturesVk(platform, &mFeatures);

Просмотреть файл

@ -927,6 +927,13 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::Context *context,
swapchainInfo.clipped = VK_TRUE; swapchainInfo.clipped = VK_TRUE;
swapchainInfo.oldSwapchain = lastSwapchain; swapchainInfo.oldSwapchain = lastSwapchain;
// On Android, vkCreateSwapchainKHR destroys lastSwapchain, which is incorrect. Wait idle in
// that case as a workaround.
if (lastSwapchain && renderer->getFeatures().waitIdleBeforeSwapchainRecreation.enabled)
{
ANGLE_TRY(renderer->deviceWaitIdle(context));
}
// TODO(syoussefi): Once EGL_SWAP_BEHAVIOR_PRESERVED_BIT is supported, the contents of the old // TODO(syoussefi): Once EGL_SWAP_BEHAVIOR_PRESERVED_BIT is supported, the contents of the old
// swapchain need to carry over to the new one. http://anglebug.com/2942 // swapchain need to carry over to the new one. http://anglebug.com/2942
VkSwapchainKHR newSwapChain = VK_NULL_HANDLE; VkSwapchainKHR newSwapChain = VK_NULL_HANDLE;