Skip to content

Commit 16d8325

Browse files
i-nazarov-ukraineAngle LUCI CQ
authored andcommitted
Vulkan: Make WindowSurfaceVk::setAutoRefreshEnabled thread safe
Bug: angleproject:379762019 Change-Id: I20feb72c4777a8dbd2058ced8a958d08b6c218ab Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/6175131 Reviewed-by: Amirali Abdolrashidi <abdolrashidi@google.com> Commit-Queue: Igor Nazarov <i.nazarov@samsung.com>
1 parent 23ab7db commit 16d8325

File tree

2 files changed

+57
-37
lines changed

2 files changed

+57
-37
lines changed

src/libANGLE/renderer/vulkan/SurfaceVk.cpp

Lines changed: 50 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1368,8 +1368,7 @@ angle::Result WindowSurfaceVk::initializeImpl(DisplayVk *displayVk, bool *anyMat
13681368
if ((mState.attributes.getAsInt(EGL_RENDER_BUFFER, EGL_BACK_BUFFER) == EGL_SINGLE_BUFFER) &&
13691369
supportsPresentMode(vk::PresentMode::SharedDemandRefreshKHR))
13701370
{
1371-
std::vector<vk::PresentMode> presentModes = {vk::PresentMode::SharedDemandRefreshKHR};
1372-
mDesiredSwapchainPresentMode = GetDesiredPresentMode(presentModes, 0);
1371+
setDesiredSwapchainPresentMode(vk::PresentMode::SharedDemandRefreshKHR);
13731372
}
13741373

13751374
mCompressionFlags = VK_IMAGE_COMPRESSION_DISABLED_EXT;
@@ -1615,6 +1614,10 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::Context *context, const gl::E
16151614
imageUsageFlags |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
16161615
}
16171616

1617+
mSwapchainPresentMode = getDesiredSwapchainPresentMode();
1618+
mWidth = extents.width;
1619+
mHeight = extents.height;
1620+
16181621
VkSwapchainCreateInfoKHR swapchainInfo = {};
16191622
swapchainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
16201623
swapchainInfo.flags = mState.hasProtectedContent() ? VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR : 0;
@@ -1631,8 +1634,8 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::Context *context, const gl::E
16311634
swapchainInfo.pQueueFamilyIndices = nullptr;
16321635
swapchainInfo.preTransform = mPreTransform;
16331636
swapchainInfo.compositeAlpha = mCompositeAlpha;
1634-
swapchainInfo.presentMode = vk::ConvertPresentModeToVkPresentMode(mDesiredSwapchainPresentMode);
1635-
swapchainInfo.clipped = VK_TRUE;
1637+
swapchainInfo.presentMode = vk::ConvertPresentModeToVkPresentMode(mSwapchainPresentMode);
1638+
swapchainInfo.clipped = VK_TRUE;
16361639
swapchainInfo.oldSwapchain = mLastSwapchain;
16371640

16381641
VkImageCompressionControlEXT compressionInfo = {};
@@ -1708,17 +1711,26 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::Context *context, const gl::E
17081711
}
17091712

17101713
// The implementation must always return the given present mode as compatible with itself.
1711-
ASSERT(IsCompatiblePresentMode(mDesiredSwapchainPresentMode, mCompatiblePresentModes.data(),
1714+
ASSERT(IsCompatiblePresentMode(mSwapchainPresentMode, mCompatiblePresentModes.data(),
17121715
mCompatiblePresentModes.size()));
17131716

1717+
// On Android we expect VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR and
1718+
// VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR to be compatible.
1719+
ASSERT(!IsAndroid() || !isSharedPresentMode() ||
1720+
IsCompatiblePresentMode(
1721+
mSwapchainPresentMode == vk::PresentMode::SharedDemandRefreshKHR
1722+
? vk::PresentMode::SharedContinuousRefreshKHR
1723+
: vk::PresentMode::SharedDemandRefreshKHR,
1724+
mCompatiblePresentModes.data(), mCompatiblePresentModes.size()));
1725+
17141726
// Vulkan spec says "The per-present mode image counts may be less-than or greater-than the
17151727
// image counts returned when VkSurfacePresentModeEXT is not provided.". Use the per present
17161728
// mode imageCount here. Otherwise we may get into
17171729
// VUID-VkSwapchainCreateInfoKHR-presentMode-02839.
17181730
mSurfaceCaps = surfaceCaps2.surfaceCapabilities;
17191731
}
17201732

1721-
mMinImageCount = GetMinImageCount(renderer, mSurfaceCaps, mDesiredSwapchainPresentMode);
1733+
mMinImageCount = GetMinImageCount(renderer, mSurfaceCaps, mSwapchainPresentMode);
17221734
swapchainInfo.minImageCount = mMinImageCount;
17231735

17241736
VkSwapchainPresentModesCreateInfoEXT compatibleModesInfo = {};
@@ -1740,7 +1752,7 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::Context *context, const gl::E
17401752
mCompatiblePresentModes[0] = swapchainInfo.presentMode;
17411753
}
17421754

1743-
if (isSharedPresentModeDesired())
1755+
if (isSharedPresentMode())
17441756
{
17451757
swapchainInfo.minImageCount = 1;
17461758

@@ -1760,9 +1772,6 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::Context *context, const gl::E
17601772
VkSwapchainKHR newSwapChain = VK_NULL_HANDLE;
17611773
ANGLE_VK_TRY(context, vkCreateSwapchainKHR(device, &swapchainInfo, nullptr, &newSwapChain));
17621774
mLastSwapchain = newSwapChain;
1763-
mSwapchainPresentMode = mDesiredSwapchainPresentMode;
1764-
mWidth = extents.width;
1765-
mHeight = extents.height;
17661775

17671776
// If frame timestamp was enabled for the surface, [re]enable it when [re]creating the swapchain
17681777
if (renderer->getFeatures().supportsTimestampSurfaceAttribute.enabled &&
@@ -1896,7 +1905,7 @@ angle::Result WindowSurfaceVk::queryAndAdjustSurfaceCaps(ContextVk *contextVk,
18961905
VkSurfacePresentModeEXT surfacePresentMode = {};
18971906
surfacePresentMode.sType = VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT;
18981907
surfacePresentMode.presentMode =
1899-
vk::ConvertPresentModeToVkPresentMode(mDesiredSwapchainPresentMode);
1908+
vk::ConvertPresentModeToVkPresentMode(getDesiredSwapchainPresentMode());
19001909
vk::AddToPNextChain(&surfaceInfo2, &surfacePresentMode);
19011910

19021911
VkSurfaceCapabilities2KHR surfaceCaps2 = {};
@@ -1933,8 +1942,10 @@ angle::Result WindowSurfaceVk::checkForOutOfDateSwapchain(ContextVk *contextVk,
19331942
{
19341943
ASSERT(mAcquireOperation.state != impl::ImageAcquireState::Ready);
19351944

1945+
vk::PresentMode desiredSwapchainPresentMode = getDesiredSwapchainPresentMode();
1946+
19361947
bool presentModeIncompatible =
1937-
!IsCompatiblePresentMode(mDesiredSwapchainPresentMode, mCompatiblePresentModes.data(),
1948+
!IsCompatiblePresentMode(desiredSwapchainPresentMode, mCompatiblePresentModes.data(),
19381949
mCompatiblePresentModes.size());
19391950
bool swapchainMissing = (mSwapchain == VK_NULL_HANDLE);
19401951
bool needRecreate = forceRecreate || presentModeIncompatible || swapchainMissing;
@@ -1969,7 +1980,7 @@ angle::Result WindowSurfaceVk::checkForOutOfDateSwapchain(ContextVk *contextVk,
19691980
mSurfaceCaps.currentExtent.width != swapchainWidth ||
19701981
mSurfaceCaps.currentExtent.height != swapchainHeight ||
19711982
GetMinImageCount(contextVk->getRenderer(), mSurfaceCaps,
1972-
mDesiredSwapchainPresentMode) != mMinImageCount;
1983+
desiredSwapchainPresentMode) != mMinImageCount;
19731984
}
19741985

19751986
// If anything has changed, recreate the swapchain.
@@ -2157,7 +2168,7 @@ egl::Error WindowSurfaceVk::swap(const gl::Context *context)
21572168
//
21582169
// Some apps issue eglSwapBuffers after glFlush unnecessary, causing the CPU throttling logic to
21592170
// effectively wait for the just submitted commands.
2160-
if (isSharedPresentMode() && mSwapchainPresentMode == mDesiredSwapchainPresentMode)
2171+
if (isSharedPresentMode() && mSwapchainPresentMode == getDesiredSwapchainPresentMode())
21612172
{
21622173
const angle::Result result = vk::GetImpl(context)->flush(context);
21632174
return angle::ToEGL(result, EGL_BAD_SURFACE);
@@ -2438,19 +2449,20 @@ angle::Result WindowSurfaceVk::present(ContextVk *contextVk,
24382449
vk::AddToPNextChain(&presentInfo, &presentFenceInfo);
24392450

24402451
// Update the present mode if necessary and possible
2441-
if (mSwapchainPresentMode != mDesiredSwapchainPresentMode &&
2442-
IsCompatiblePresentMode(mDesiredSwapchainPresentMode, mCompatiblePresentModes.data(),
2452+
vk::PresentMode desiredSwapchainPresentMode = getDesiredSwapchainPresentMode();
2453+
if (mSwapchainPresentMode != desiredSwapchainPresentMode &&
2454+
IsCompatiblePresentMode(desiredSwapchainPresentMode, mCompatiblePresentModes.data(),
24432455
mCompatiblePresentModes.size()))
24442456
{
2445-
presentMode = vk::ConvertPresentModeToVkPresentMode(mDesiredSwapchainPresentMode);
2457+
presentMode = vk::ConvertPresentModeToVkPresentMode(desiredSwapchainPresentMode);
24462458

24472459
presentModeInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODE_INFO_EXT;
24482460
presentModeInfo.swapchainCount = 1;
24492461
presentModeInfo.pPresentModes = &presentMode;
24502462

24512463
vk::AddToPNextChain(&presentInfo, &presentModeInfo);
24522464

2453-
mSwapchainPresentMode = mDesiredSwapchainPresentMode;
2465+
mSwapchainPresentMode = desiredSwapchainPresentMode;
24542466
}
24552467
}
24562468

@@ -2882,7 +2894,7 @@ VkResult WindowSurfaceVk::postProcessUnlockedAcquire(vk::Context *context)
28822894
ASSERT(semaphore == acquireImageSemaphore);
28832895
if (primaryCommandBuffer.end() != VK_SUCCESS)
28842896
{
2885-
mDesiredSwapchainPresentMode = vk::PresentMode::FifoKHR;
2897+
setDesiredSwapchainPresentMode(vk::PresentMode::FifoKHR);
28862898
return VK_ERROR_OUT_OF_DATE_KHR;
28872899
}
28882900
QueueSerial queueSerial;
@@ -2891,7 +2903,7 @@ VkResult WindowSurfaceVk::postProcessUnlockedAcquire(vk::Context *context)
28912903
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
28922904
&queueSerial) != angle::Result::Continue)
28932905
{
2894-
mDesiredSwapchainPresentMode = vk::PresentMode::FifoKHR;
2906+
setDesiredSwapchainPresentMode(vk::PresentMode::FifoKHR);
28952907
return VK_ERROR_OUT_OF_DATE_KHR;
28962908
}
28972909
mUse.setQueueSerial(queueSerial);
@@ -2964,6 +2976,16 @@ egl::Error WindowSurfaceVk::getMscRate(EGLint * /*numerator*/, EGLint * /*denomi
29642976
return egl::EglBadAccess();
29652977
}
29662978

2979+
vk::PresentMode WindowSurfaceVk::getDesiredSwapchainPresentMode() const
2980+
{
2981+
return mDesiredSwapchainPresentMode.load(std::memory_order_relaxed);
2982+
}
2983+
2984+
void WindowSurfaceVk::setDesiredSwapchainPresentMode(vk::PresentMode presentMode)
2985+
{
2986+
mDesiredSwapchainPresentMode.store(presentMode, std::memory_order_relaxed);
2987+
}
2988+
29672989
void WindowSurfaceVk::setSwapInterval(DisplayVk *displayVk, EGLint interval)
29682990
{
29692991
// Don't let setSwapInterval change presentation mode if using SHARED present.
@@ -2979,7 +3001,7 @@ void WindowSurfaceVk::setSwapInterval(DisplayVk *displayVk, EGLint interval)
29793001

29803002
interval = gl::clamp(interval, minSwapInterval, maxSwapInterval);
29813003

2982-
mDesiredSwapchainPresentMode = GetDesiredPresentMode(mPresentModes, interval);
3004+
setDesiredSwapchainPresentMode(GetDesiredPresentMode(mPresentModes, interval));
29833005

29843006
// On the next swap, if the desired present mode is different from the current one, the
29853007
// swapchain will be recreated.
@@ -3230,19 +3252,14 @@ egl::Error WindowSurfaceVk::setAutoRefreshEnabled(bool enabled)
32303252
: vk::PresentMode::SharedDemandRefreshKHR;
32313253

32323254
// We only expose EGL_ANDROID_front_buffer_auto_refresh extension on Android with supported
3233-
// VK_EXT_swapchain_maintenance1 extension, where present modes expected to be compatible.
3234-
if (!IsCompatiblePresentMode(newDesiredSwapchainPresentMode, mCompatiblePresentModes.data(),
3235-
mCompatiblePresentModes.size()))
3236-
{
3237-
// This should not happen, unless some specific Android platform requires swapchain
3238-
// recreation for these present modes, in which case EGL_ANDROID_front_buffer_auto_refresh
3239-
// should not be exposed or this code should be updated to support this scenario.
3240-
return egl::EglBadMatch();
3241-
}
3255+
// VK_EXT_swapchain_maintenance1 extension, where current and new present modes expected to be
3256+
// compatible. Can't use |mCompatiblePresentModes| here to check if this is true because it is
3257+
// not thread safe. Instead of the check, ASSERT is added to the |createSwapChain| method where
3258+
// |mCompatiblePresentModes| are queried.
32423259

32433260
// Simply change mDesiredSwapchainPresentMode regardless if we are already in single buffer mode
32443261
// or not, since compatible present modes does not require swapchain recreation.
3245-
mDesiredSwapchainPresentMode = newDesiredSwapchainPresentMode;
3262+
setDesiredSwapchainPresentMode(newDesiredSwapchainPresentMode);
32463263

32473264
return egl::NoError();
32483265
}
@@ -3333,11 +3350,11 @@ egl::Error WindowSurfaceVk::setRenderBuffer(EGLint renderBuffer)
33333350
{
33343351
return egl::EglBadMatch();
33353352
}
3336-
mDesiredSwapchainPresentMode = presentMode;
3353+
setDesiredSwapchainPresentMode(presentMode);
33373354
}
33383355
else // EGL_BACK_BUFFER
33393356
{
3340-
mDesiredSwapchainPresentMode = vk::PresentMode::FifoKHR;
3357+
setDesiredSwapchainPresentMode(vk::PresentMode::FifoKHR);
33413358
}
33423359
return egl::NoError();
33433360
}

src/libANGLE/renderer/vulkan/SurfaceVk.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -346,8 +346,9 @@ class WindowSurfaceVk : public SurfaceVk
346346

347347
bool isSharedPresentModeDesired() const
348348
{
349-
return (mDesiredSwapchainPresentMode == vk::PresentMode::SharedDemandRefreshKHR ||
350-
mDesiredSwapchainPresentMode == vk::PresentMode::SharedContinuousRefreshKHR);
349+
vk::PresentMode desiredSwapchainPresentMode = getDesiredSwapchainPresentMode();
350+
return (desiredSwapchainPresentMode == vk::PresentMode::SharedDemandRefreshKHR ||
351+
desiredSwapchainPresentMode == vk::PresentMode::SharedContinuousRefreshKHR);
351352
}
352353

353354
egl::Error lockSurface(const egl::Display *display,
@@ -398,6 +399,8 @@ class WindowSurfaceVk : public SurfaceVk
398399
virtual angle::Result createSurfaceVk(vk::Context *context, gl::Extents *extentsOut) = 0;
399400
virtual angle::Result getCurrentWindowSize(vk::Context *context, gl::Extents *extentsOut) = 0;
400401

402+
vk::PresentMode getDesiredSwapchainPresentMode() const;
403+
void setDesiredSwapchainPresentMode(vk::PresentMode presentMode);
401404
void setSwapInterval(DisplayVk *displayVk, EGLint interval);
402405

403406
angle::Result initializeImpl(DisplayVk *displayVk, bool *anyMatchesOut);
@@ -463,8 +466,8 @@ class WindowSurfaceVk : public SurfaceVk
463466
VkSwapchainKHR mSwapchain; // Current swapchain (same as last created or NULL)
464467
VkSwapchainKHR mLastSwapchain; // Last created non retired swapchain (or NULL if retired)
465468
// Cached information used to recreate swapchains.
466-
vk::PresentMode mSwapchainPresentMode; // Current swapchain mode
467-
vk::PresentMode mDesiredSwapchainPresentMode; // Desired mode set through setSwapInterval()
469+
vk::PresentMode mSwapchainPresentMode; // Current swapchain mode
470+
std::atomic<vk::PresentMode> mDesiredSwapchainPresentMode; // Desired swapchain mode
468471
uint32_t mMinImageCount;
469472
VkSurfaceTransformFlagBitsKHR mPreTransform;
470473
VkSurfaceTransformFlagBitsKHR mEmulatedPreTransform;

0 commit comments

Comments
 (0)