diff --git a/filament/backend/src/vulkan/VulkanDriver.cpp b/filament/backend/src/vulkan/VulkanDriver.cpp index 7a28fce827..b73e41cd33 100644 --- a/filament/backend/src/vulkan/VulkanDriver.cpp +++ b/filament/backend/src/vulkan/VulkanDriver.cpp @@ -206,6 +206,11 @@ VulkanDriver::VulkanDriver(VulkanPlatform* platform, VulkanContext& context, : mPlatform(platform), mResourceManager(driverConfig.handleArenaSize, driverConfig.disableHandleUseAfterFreeCheck, driverConfig.disableHeapHandleTags), + // Note that we always create the default rendertarget before createDefaultRenderTarget(). We + // swap the content later when createDefaultRenderTarget() is called. This frees + // createDefaultRenderTarget() from being ordered with makeCurrent(). + mDefaultRenderTarget( + fvkmemory::resource_ptr::construct(&mResourceManager)), mAllocator(createAllocator(mPlatform->getInstance(), mPlatform->getPhysicalDevice(), mPlatform->getDevice())), mContext(context), @@ -698,8 +703,11 @@ void VulkanDriver::destroyProgram(Handle ph) { } void VulkanDriver::createDefaultRenderTargetR(Handle rth, int) { - assert_invariant(!mDefaultRenderTarget); - auto renderTarget = resource_ptr::make(&mResourceManager, rth); + assert_invariant(mDefaultRenderTarget); // Default render target should already exist. + + auto renderTarget = resource_ptr::make(&mResourceManager, rth, + std::move(std::move(*mDefaultRenderTarget.get()))); + mDefaultRenderTarget = renderTarget; } @@ -775,6 +783,7 @@ void VulkanDriver::destroyRenderTarget(Handle rth) { auto rt = resource_ptr::cast(&mResourceManager, rth); if (UTILS_UNLIKELY(rt == mDefaultRenderTarget)) { + // Note that this should only happen on driver shutdown. mDefaultRenderTarget = {}; } else { rt.dec(); diff --git a/filament/backend/src/vulkan/VulkanHandles.h b/filament/backend/src/vulkan/VulkanHandles.h index 11de2bc3dc..a1d6dc03b8 100644 --- a/filament/backend/src/vulkan/VulkanHandles.h +++ b/filament/backend/src/vulkan/VulkanHandles.h @@ -308,6 +308,15 @@ struct VulkanRenderTarget : private HwRenderTarget, fvkmemory::Resource { // Creates a special "default" render target (i.e. associated with the swap chain) explicit VulkanRenderTarget(); + VulkanRenderTarget(VulkanRenderTarget&& target) { + swap(std::move(target)); + } + + VulkanRenderTarget& operator=(VulkanRenderTarget&& target) { + swap(std::move(target)); + return *this; + } + void transformClientRectToPlatform(VkRect2D* bounds) const; void transformViewportToPlatform(VkViewport* bounds) const; @@ -355,6 +364,12 @@ struct VulkanRenderTarget : private HwRenderTarget, fvkmemory::Resource { void emitBarriersEndRenderPass(VulkanCommandBuffer& commands); private: + void swap(VulkanRenderTarget&& target) { + std::swap(mOffscreen, target.mOffscreen); + std::swap(mProtected, target.mProtected); + std::swap(mInfo, target.mInfo); + } + struct Auxiliary { static constexpr int8_t UNDEFINED_INDEX = -1; @@ -368,7 +383,7 @@ private: int8_t msaaDepthIndex = UNDEFINED_INDEX; int8_t msaaIndex = UNDEFINED_INDEX; }; - bool const mOffscreen; + bool mOffscreen; bool mProtected; std::unique_ptr mInfo;