Skip to content

Commit f33a779

Browse files
authored
vk: move swapchain acquire() to as late as possible (#9541)
makeCurrent is not meant to acquire the swapchain; we should do so at the momemnt we need it, to shorten the amount of time a swapchain image/buffer needs to be held.
1 parent 1b5916b commit f33a779

File tree

4 files changed

+57
-19
lines changed

4 files changed

+57
-19
lines changed

filament/backend/src/vulkan/VulkanDriver.cpp

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -810,7 +810,7 @@ void VulkanDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, utils:
810810
assert_invariant(mDefaultRenderTarget); // Default render target should already exist.
811811

812812
auto renderTarget = resource_ptr<VulkanRenderTarget>::make(&mResourceManager, rth,
813-
std::move(std::move(*mDefaultRenderTarget.get())));
813+
std::move(*mDefaultRenderTarget.get()));
814814

815815
mDefaultRenderTarget = renderTarget;
816816
mResourceManager.associateHandle(rth.getId(), std::move(tag));
@@ -1808,9 +1808,6 @@ void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
18081808
FVK_SYSTRACE_SCOPE();
18091809

18101810
auto rt = resource_ptr<VulkanRenderTarget>::cast(&mResourceManager, rth);
1811-
VkExtent2D const extent = rt->getExtent();
1812-
1813-
assert_invariant(rt == mDefaultRenderTarget || extent.width > 0 && extent.height > 0);
18141811

18151812
VulkanCommandBuffer* commandBuffer = rt->isProtected() ?
18161813
&mCommands.getProtected() : &mCommands.get();
@@ -1825,9 +1822,16 @@ void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
18251822
if (sc->isFirstRenderPass()) {
18261823
discardStart |= TargetBufferFlags::COLOR;
18271824
sc->markFirstRenderPass();
1825+
acquireNextSwapchainImage();
18281826
}
18291827
}
18301828

1829+
// Note that retrieving the extent must come after the acquireNextSwapchainImage() above;
1830+
// otherwise it might be 0.
1831+
VkExtent2D const extent = rt->getExtent();
1832+
1833+
assert_invariant(rt == mDefaultRenderTarget || extent.width > 0 && extent.height > 0);
1834+
18311835
#if FVK_ENABLED(FVK_DEBUG_TEXTURE)
18321836
if (rt->hasDepth()) {
18331837
auto depth = rt->getDepth();
@@ -2038,20 +2042,13 @@ void VulkanDriver::makeCurrent(Handle<HwSwapChain> drawSch, Handle<HwSwapChain>
20382042
ASSERT_PRECONDITION_NON_FATAL(drawSch == readSch,
20392043
"Vulkan driver does not support distinct draw/read swap chains.");
20402044

2045+
// Before we can render into the new swapchain, we need to make sure the default render target
2046+
// releases its old bound swapchain image.
2047+
mDefaultRenderTarget->releaseSwapchain();
2048+
20412049
resource_ptr<VulkanSwapChain> swapChain =
20422050
resource_ptr<VulkanSwapChain>::cast(&mResourceManager, drawSch);
20432051
mCurrentSwapChain = swapChain;
2044-
2045-
bool resized = false;
2046-
swapChain->acquire(resized);
2047-
2048-
if (resized) {
2049-
mFramebufferCache.resetFramebuffers();
2050-
}
2051-
2052-
if (UTILS_LIKELY(mDefaultRenderTarget)) {
2053-
mDefaultRenderTarget->bindToSwapChain(swapChain);
2054-
}
20552052
}
20562053

20572054
void VulkanDriver::commit(Handle<HwSwapChain> sch) {
@@ -2222,6 +2219,14 @@ void VulkanDriver::blitDEPRECATED(TargetBufferFlags buffers,
22222219
auto dstTarget = resource_ptr<VulkanRenderTarget>::cast(&mResourceManager, dst);
22232220
auto srcTarget = resource_ptr<VulkanRenderTarget>::cast(&mResourceManager, src);
22242221

2222+
// This is a valid use of the api. We need to make sure that the swapchain image has been
2223+
// acquired and associated with the default render target. It's okay to call
2224+
// acquireNextSwapchainImage() even if a swapchain image has already been bound to the default
2225+
// render target.
2226+
if (dstTarget == mDefaultRenderTarget) {
2227+
acquireNextSwapchainImage();
2228+
}
2229+
22252230
VkFilter const vkfilter = (filter == SamplerMagFilter::NEAREST) ?
22262231
VK_FILTER_NEAREST : VK_FILTER_LINEAR;
22272232

@@ -2553,6 +2558,25 @@ void VulkanDriver::endCommandRecording() {
25532558
mDescriptorSetCache.resetCachedState();
25542559
}
25552560

2561+
void VulkanDriver::acquireNextSwapchainImage() {
2562+
assert_invariant(mCurrentSwapChain);
2563+
assert_invariant(mDefaultRenderTarget);
2564+
2565+
// Swapchain has already been bound to the default render target. We just return.
2566+
if (mDefaultRenderTarget->isSwapchainBound()) {
2567+
return;
2568+
}
2569+
2570+
bool resized = false;
2571+
mCurrentSwapChain->acquire(resized);
2572+
if (resized) {
2573+
mFramebufferCache.resetFramebuffers();
2574+
}
2575+
// Note that ordering this after the above lines is necessary since we set the swapchain image
2576+
// to the render target in bindSwapChain().
2577+
mDefaultRenderTarget->bindSwapChain(mCurrentSwapChain);
2578+
}
2579+
25562580
// explicit instantiation of the Dispatcher
25572581
template class ConcreteDispatcher<VulkanDriver>;
25582582

filament/backend/src/vulkan/VulkanDriver.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ class VulkanDriver final : public DriverBase {
132132
// Flush the current command buffer and reset the pipeline state.
133133
void endCommandRecording();
134134

135+
void acquireNextSwapchainImage();
136+
135137
VulkanPlatform* mPlatform = nullptr;
136138
fvkmemory::ResourceManager mResourceManager;
137139

@@ -160,7 +162,6 @@ class VulkanDriver final : public DriverBase {
160162
VulkanExternalImageManager mExternalImageManager;
161163
VulkanStreamedImageManager mStreamedImageManager;
162164

163-
164165
// This maps a VulkanSwapchain to a native swapchain. VulkanSwapchain should have a copy of the
165166
// Platform::Swapchain pointer, but queryFrameTimestamps() and queryCompositorTiming() are
166167
// synchronous calls, making access to VulkanSwapchain unsafe (this difference vs other backends

filament/backend/src/vulkan/VulkanHandles.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -387,16 +387,18 @@ VulkanRenderTarget::VulkanRenderTarget()
387387

388388
VulkanRenderTarget::~VulkanRenderTarget() = default;
389389

390-
void VulkanRenderTarget::bindToSwapChain(fvkmemory::resource_ptr<VulkanSwapChain> swapchain) {
390+
void VulkanRenderTarget::bindSwapChain(fvkmemory::resource_ptr<VulkanSwapChain> swapchain) {
391391
assert_invariant(!mOffscreen);
392+
assert_invariant(!mInfo->colors[0]);
392393

393394
VkExtent2D const extent = swapchain->getExtent();
394395
width = extent.width;
395396
height = extent.height;
396397
mProtected = swapchain->isProtected();
397398

398399
VulkanAttachment color = createSwapchainAttachment(swapchain->getCurrentColor());
399-
mInfo->attachments = {color};
400+
assert_invariant(mInfo->attachments.size() == 0);
401+
mInfo->attachments.push_back(color);
400402

401403
auto& fbkey = mInfo->fbkey;
402404
auto& rpkey = mInfo->rpkey;
@@ -422,6 +424,11 @@ void VulkanRenderTarget::bindToSwapChain(fvkmemory::resource_ptr<VulkanSwapChain
422424
mInfo->colors.set(0);
423425
}
424426

427+
void VulkanRenderTarget::releaseSwapchain() {
428+
mInfo->colors = {};
429+
mInfo->attachments.clear();
430+
}
431+
425432
VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physicalDevice,
426433
VulkanContext const& context, fvkmemory::ResourceManager* resourceManager,
427434
VmaAllocator allocator, VulkanCommands* commands, uint32_t width, uint32_t height,

filament/backend/src/vulkan/VulkanHandles.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,13 @@ struct VulkanRenderTarget : private HwRenderTarget, fvkmemory::Resource {
366366
inline bool isSwapChain() const { return !mOffscreen; }
367367
inline bool isProtected() const { return mProtected; }
368368

369-
void bindToSwapChain(fvkmemory::resource_ptr<VulkanSwapChain> swapchain);
369+
void bindSwapChain(fvkmemory::resource_ptr<VulkanSwapChain> swapchain);
370+
371+
void releaseSwapchain();
372+
373+
bool isSwapchainBound() const {
374+
return isSwapChain() && mInfo->colors[0];
375+
}
370376

371377
void emitBarriersBeginRenderPass(VulkanCommandBuffer& commands);
372378

0 commit comments

Comments
 (0)