@@ -160,19 +160,14 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
160160 {
161161 deinit_impl ();
162162
163- if (m_acquireSemaphore)
164- {
165- auto device = const_cast <ILogicalDevice*>(m_acquireSemaphore->getOriginDevice ());
166- const ISemaphore::SWaitInfo info[1 ] = {{
167- .semaphore = m_acquireSemaphore.get (), .value = m_acquireCount
168- }};
169- device->blockForSemaphores (info);
170- }
163+ // I'm going to be lazy and do this instead of blocking on each of `m_acquireSemaphores`
164+ if (m_queue)
165+ m_queue->waitIdle ();
171166
172167 m_queue = nullptr ;
173168 m_maxFramesInFlight = 0 ;
174- m_acquireSemaphore = 0 ;
175169 m_acquireCount = 0 ;
170+ std::fill (m_acquireSemaphores.begin (),m_acquireSemaphores.end (),nullptr );
176171 }
177172
178173 //
@@ -183,7 +178,7 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
183178
184179 // An interesting solution to the "Frames In Flight", our tiny wrapper class will have its own Timeline Semaphore incrementing with each acquire, and thats it.
185180 inline uint64_t getAcquireCount () {return m_acquireCount;}
186- inline ISemaphore* getAcquireSemaphore () {return m_acquireSemaphore .get ();}
181+ inline ISemaphore* getAcquireSemaphore () {return m_acquireSemaphores[m_acquireCount%m_maxFramesInFlight] .get (); }
187182
188183 protected: // some of the methods need to stay protected in this base class because they need to be performed under a Mutex for smooth resize variants
189184 inline ISimpleManagedSurface (core::smart_refctd_ptr<ISurface>&& _surface, ICallback* _cb) : m_surface(std::move(_surface)), m_cb(_cb) {}
@@ -211,15 +206,15 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
211206 m_maxFramesInFlight = core::min (caps.maxImageCount +1 -caps.minImageCount ,ISwapchain::MaxImages);
212207 }
213208
214- if ( m_maxFramesInFlight)
209+ for ( uint8_t i= 0u ; i< m_maxFramesInFlight; i++ )
215210 {
216- m_acquireSemaphore = device->createSemaphore (0u );
217- if (m_acquireSemaphore )
218- return true ;
211+ m_acquireSemaphores[i] = device->createSemaphore (0u );
212+ if (!m_acquireSemaphores[i] )
213+ return init_fail () ;
219214 }
220215 }
221216 }
222- return init_fail () ;
217+ return true ;
223218 }
224219
225220 // just a simple convenience wrapper
@@ -243,10 +238,11 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
243238 if (!swapchainResources || swapchainResources->getStatus ()!=ISwapchainResources::STATUS::USABLE)
244239 return ISwapchain::MaxImages;
245240
241+ const auto nextAcquireSignal = m_acquireCount+1 ;
246242 const IQueue::SSubmitInfo::SSemaphoreInfo signalInfos[1 ] = {
247243 {
248- .semaphore =m_acquireSemaphore .get (),
249- .value =m_acquireCount+ 1
244+ .semaphore =m_acquireSemaphores[nextAcquireSignal%m_maxFramesInFlight] .get (),
245+ .value =nextAcquireSignal
250246 }
251247 };
252248
@@ -257,7 +253,7 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
257253 case ISwapchain::ACQUIRE_IMAGE_RESULT::SUBOPTIMAL: [[fallthrough]];
258254 case ISwapchain::ACQUIRE_IMAGE_RESULT::SUCCESS:
259255 // the semaphore will only get signalled upon a successful acquire
260- m_acquireCount++ ;
256+ m_acquireCount = nextAcquireSignal ;
261257 return static_cast <uint8_t >(imageIndex);
262258 case ISwapchain::ACQUIRE_IMAGE_RESULT::TIMEOUT: [[fallthrough]];
263259 case ISwapchain::ACQUIRE_IMAGE_RESULT::NOT_READY: // don't throw our swapchain away just because of a timeout XD
@@ -327,8 +323,9 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
327323 CThreadSafeQueueAdapter* m_queue = nullptr ;
328324 //
329325 uint8_t m_maxFramesInFlight = 0 ;
330- // created and persistent after first initialization
331- core::smart_refctd_ptr<ISemaphore> m_acquireSemaphore;
326+ // Created and persistent after first initialization, Note that we need one swapchain per Frame In Fligth because Acquires can't wait or synchronize with anything
327+ // The only rule is that you can only have `m_maxFramesInFlight` pending acquires to wait with an infinte timeout, so thats about as far as they synchronize.
328+ std::array<core::smart_refctd_ptr<ISemaphore>,ISwapchain::MaxImages> m_acquireSemaphores;
332329 // You don't want to use `m_swapchainResources.swapchain->getAcquireCount()` because it resets when swapchain gets recreated
333330 uint64_t m_acquireCount = 0 ;
334331};
0 commit comments