@@ -361,11 +361,10 @@ class ISwapchain : public IBackendObject
361
361
case ACQUIRE_IMAGE_RESULT::SUCCESS: [[fallthrough]];
362
362
case ACQUIRE_IMAGE_RESULT::SUBOPTIMAL:
363
363
m_acquireCounter++;
364
+ // Now hold onto the signal-on-acquire semaphores for this image index till the acquire actually takes place
364
365
{
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 ));
369
368
}
370
369
if (m_oldSwapchain && m_acquireCounter>core::max (m_oldSwapchain->getImageCount (),m_imageCount) && !m_oldSwapchain->acquiredImagesAwaitingPresent ())
371
370
m_oldSwapchain = nullptr ;
@@ -408,19 +407,15 @@ class ISwapchain : public IBackendObject
408
407
threadsafeQ->m .unlock ();
409
408
410
409
// 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
412
411
// - when dropping the swapchain entirely, but need to wait on all previous presents to finish (some manageable UB)
413
412
if (retval!=PRESENT_RESULT::FATAL_ERROR)
414
413
{
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)));
421
416
}
422
- else
423
- m_frameResources[info.imgIndex ] = nullptr ;
417
+ // kill a few frame resources
418
+ m_frameResources[info.imgIndex ]-> poll () ;
424
419
return retval;
425
420
}
426
421
@@ -433,7 +428,7 @@ class ISwapchain : public IBackendObject
433
428
for (uint8_t i=0 ; i<m_imageCount; i++)
434
429
{
435
430
if (unacquired (i))
436
- m_frameResources[i] = nullptr ;
431
+ m_frameResources[i]-> abortAll () ;
437
432
else
438
433
return true ;
439
434
}
@@ -470,7 +465,56 @@ class ISwapchain : public IBackendObject
470
465
471
466
// Vulkan: const VkSwapchainKHR*
472
467
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
+ };
474
518
protected:
475
519
ISwapchain (core::smart_refctd_ptr<const ILogicalDevice>&& dev, SCreationParams&& params, const uint8_t imageCount, core::smart_refctd_ptr<ISwapchain>&& oldSwapchain);
476
520
virtual inline ~ISwapchain ()
@@ -513,8 +557,8 @@ class ISwapchain : public IBackendObject
513
557
std::array<uint8_t ,ILogicalDevice::MaxQueueFamilies> m_queueFamilies;
514
558
const uint8_t m_imageCount;
515
559
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;
518
562
};
519
563
520
564
}
0 commit comments