@@ -160,19 +160,14 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
160
160
{
161
161
deinit_impl ();
162
162
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 ();
171
166
172
167
m_queue = nullptr ;
173
168
m_maxFramesInFlight = 0 ;
174
- m_acquireSemaphore = 0 ;
175
169
m_acquireCount = 0 ;
170
+ std::fill (m_acquireSemaphores.begin (),m_acquireSemaphores.end (),nullptr );
176
171
}
177
172
178
173
//
@@ -183,7 +178,7 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
183
178
184
179
// 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.
185
180
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 (); }
187
182
188
183
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
189
184
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
211
206
m_maxFramesInFlight = core::min (caps.maxImageCount +1 -caps.minImageCount ,ISwapchain::MaxImages);
212
207
}
213
208
214
- if ( m_maxFramesInFlight)
209
+ for ( uint8_t i= 0u ; i< m_maxFramesInFlight; i++ )
215
210
{
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 () ;
219
214
}
220
215
}
221
216
}
222
- return init_fail () ;
217
+ return true ;
223
218
}
224
219
225
220
// just a simple convenience wrapper
@@ -243,10 +238,11 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
243
238
if (!swapchainResources || swapchainResources->getStatus ()!=ISwapchainResources::STATUS::USABLE)
244
239
return ISwapchain::MaxImages;
245
240
241
+ const auto nextAcquireSignal = m_acquireCount+1 ;
246
242
const IQueue::SSubmitInfo::SSemaphoreInfo signalInfos[1 ] = {
247
243
{
248
- .semaphore =m_acquireSemaphore .get (),
249
- .value =m_acquireCount+ 1
244
+ .semaphore =m_acquireSemaphores[nextAcquireSignal%m_maxFramesInFlight] .get (),
245
+ .value =nextAcquireSignal
250
246
}
251
247
};
252
248
@@ -257,7 +253,7 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
257
253
case ISwapchain::ACQUIRE_IMAGE_RESULT::SUBOPTIMAL: [[fallthrough]];
258
254
case ISwapchain::ACQUIRE_IMAGE_RESULT::SUCCESS:
259
255
// the semaphore will only get signalled upon a successful acquire
260
- m_acquireCount++ ;
256
+ m_acquireCount = nextAcquireSignal ;
261
257
return static_cast <uint8_t >(imageIndex);
262
258
case ISwapchain::ACQUIRE_IMAGE_RESULT::TIMEOUT: [[fallthrough]];
263
259
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
327
323
CThreadSafeQueueAdapter* m_queue = nullptr ;
328
324
//
329
325
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;
332
329
// You don't want to use `m_swapchainResources.swapchain->getAcquireCount()` because it resets when swapchain gets recreated
333
330
uint64_t m_acquireCount = 0 ;
334
331
};
0 commit comments