@@ -361,11 +361,10 @@ class ISwapchain : public IBackendObject
361361 case ACQUIRE_IMAGE_RESULT::SUCCESS: [[fallthrough]];
362362 case ACQUIRE_IMAGE_RESULT::SUBOPTIMAL:
363363 m_acquireCounter++;
364+ // Now hold onto the signal-on-acquire semaphores for this image index till the acquire actually takes place
364365 {
365- auto semaphoreArray = core::make_refctd_dynamic_array<core::smart_refctd_dynamic_array<void_refctd_ptr>>(info.signalSemaphores .size ());
366- for (auto i=0ull ; i<info.signalSemaphores .size (); i++)
367- semaphoreArray->operator [](i) = void_refctd_ptr (info.signalSemaphores [i].semaphore );
368- m_frameResources[*out_imgIx] = std::move (semaphoreArray);
366+ const auto & lastSignal = info.signalSemaphores .back ();
367+ m_frameResources[*out_imgIx]->latch ({.semaphore =lastSignal.semaphore ,.value =lastSignal.value },DeferredFrameResourceDrop (info.signalSemaphores ));
369368 }
370369 if (m_oldSwapchain && m_acquireCounter>core::max (m_oldSwapchain->getImageCount (),m_imageCount) && !m_oldSwapchain->acquiredImagesAwaitingPresent ())
371370 m_oldSwapchain = nullptr ;
@@ -408,19 +407,15 @@ class ISwapchain : public IBackendObject
408407 threadsafeQ->m .unlock ();
409408
410409 // If not FATAL_ERROR then semaphore wait will actually occur in the future and resources should be released, either:
411- // - on the next acquire of the same index
410+ // - on the next SIGNALLED acquire of the same index
412411 // - when dropping the swapchain entirely, but need to wait on all previous presents to finish (some manageable UB)
413412 if (retval!=PRESENT_RESULT::FATAL_ERROR)
414413 {
415- auto frameResources = core::make_refctd_dynamic_array<core::smart_refctd_dynamic_array<void_refctd_ptr>>(info.waitSemaphores .size ()+2 );
416- frameResources->operator [](0 ) = std::move (m_frameResources[info.imgIndex ]);
417- frameResources->operator [](1 ) = std::move (_frameResources);
418- for (auto i=0ull ; i<info.waitSemaphores .size (); i++)
419- frameResources->operator [](i+2 ) = void_refctd_ptr (info.waitSemaphores [i].semaphore );
420- m_frameResources[info.imgIndex ] = std::move (frameResources);
414+ auto & lastWait = info.waitSemaphores .back ();
415+ m_frameResources[info.imgIndex ]->latch ({.semaphore =lastWait.semaphore ,.value =lastWait.value },DeferredFrameResourceDrop (info.waitSemaphores ,std::move (_frameResources)));
421416 }
422- else
423- m_frameResources[info.imgIndex ] = nullptr ;
417+ // kill a few frame resources
418+ m_frameResources[info.imgIndex ]-> poll () ;
424419 return retval;
425420 }
426421
@@ -433,7 +428,7 @@ class ISwapchain : public IBackendObject
433428 for (uint8_t i=0 ; i<m_imageCount; i++)
434429 {
435430 if (unacquired (i))
436- m_frameResources[i] = nullptr ;
431+ m_frameResources[i]-> abortAll () ;
437432 else
438433 return true ;
439434 }
@@ -470,7 +465,56 @@ class ISwapchain : public IBackendObject
470465
471466 // Vulkan: const VkSwapchainKHR*
472467 virtual const void * getNativeHandle () const = 0;
473-
468+
469+ // only public because MultiTimelineEventHandlerST needs to know about it
470+ class DeferredFrameResourceDrop final
471+ {
472+ core::smart_refctd_dynamic_array<void_refctd_ptr> m_frameResources;
473+
474+ public:
475+ inline DeferredFrameResourceDrop (const std::span<const IQueue::SSubmitInfo::SSemaphoreInfo> _semaphores, void_refctd_ptr&& _frameResources=nullptr )
476+ {
477+ m_frameResources = core::make_refctd_dynamic_array<decltype (m_frameResources)>(_semaphores.size ()+(_frameResources ? 1 :0 ));
478+ for (auto i=0ull ; i< _semaphores.size (); i++)
479+ m_frameResources->operator [](i) = void_refctd_ptr (_semaphores[i].semaphore );
480+ if (_frameResources)
481+ m_frameResources->back () = std::move (_frameResources);
482+ }
483+ DeferredFrameResourceDrop (const DeferredFrameResourceDrop& other) = delete ;
484+ inline DeferredFrameResourceDrop (DeferredFrameResourceDrop&& other) : m_frameResources(nullptr )
485+ {
486+ this ->operator =(std::move (other));
487+ }
488+
489+ DeferredFrameResourceDrop& operator =(const DeferredFrameResourceDrop& other) = delete ;
490+ inline DeferredFrameResourceDrop& operator =(DeferredFrameResourceDrop&& other)
491+ {
492+ m_frameResources = std::move (other.m_frameResources );
493+ m_frameResources = nullptr ;
494+ return *this ;
495+ }
496+
497+ struct single_poll_t {};
498+ static inline single_poll_t single_poll;
499+ inline bool operator ()(single_poll_t _single_poll)
500+ {
501+ operator ()();
502+ return true ;
503+ }
504+
505+ struct exhaustive_poll_t {};
506+ static inline exhaustive_poll_t exhaustive_poll;
507+ inline bool operator ()(exhaustive_poll_t _exhaustive_poll)
508+ {
509+ operator ()();
510+ return false ;
511+ }
512+
513+ inline void operator ()()
514+ {
515+ m_frameResources = nullptr ;
516+ }
517+ };
474518 protected:
475519 ISwapchain (core::smart_refctd_ptr<const ILogicalDevice>&& dev, SCreationParams&& params, const uint8_t imageCount, core::smart_refctd_ptr<ISwapchain>&& oldSwapchain);
476520 virtual inline ~ISwapchain ()
@@ -513,8 +557,8 @@ class ISwapchain : public IBackendObject
513557 std::array<uint8_t ,ILogicalDevice::MaxQueueFamilies> m_queueFamilies;
514558 const uint8_t m_imageCount;
515559 uint64_t m_acquireCounter = 0 ;
516- // resource to hold onto until a frame is done rendering (between; just before presenting, and next acquire of the same image index)
517- std::array<void_refctd_ptr ,ILogicalDevice::MaxQueueFamilies> m_frameResources = {} ;
560+ // Resources to hold onto until a frame is done rendering (between; just before presenting, and next acquire of the same image index)
561+ std::array<std::unique_ptr<MultiTimelineEventHandlerST<DeferredFrameResourceDrop>> ,ILogicalDevice::MaxQueueFamilies> m_frameResources;
518562};
519563
520564}
0 commit comments