@@ -26,9 +26,7 @@ class NBL_API2 ISmoothResizeSurface : public ISimpleManagedSurface
26
26
27
27
private:
28
28
friend class ISmoothResizeSurface ;
29
- // `recreator` owns the `ISurface`, which refcounts the `IWindow` which refcounts the callback, so fumb pointer to avoid cycles
30
- inline void setSwapchainRecreator (ISmoothResizeSurface* recreator) { m_recreator = recreator; }
31
-
29
+ // `recreator` owns the `ISurface`, which refcounts the `IWindow` which refcounts the callback, so dumb pointer to avoid cycles
32
30
ISmoothResizeSurface* m_recreator = nullptr ;
33
31
};
34
32
@@ -173,20 +171,21 @@ class NBL_API2 ISmoothResizeSurface : public ISimpleManagedSurface
173
171
}
174
172
175
173
protected:
174
+ inline void setSwapchainRecreator () {static_cast <ICallback*>(m_cb)->m_recreator =this ;}
175
+
176
176
using ISimpleManagedSurface::ISimpleManagedSurface;
177
177
virtual inline ~ISmoothResizeSurface ()
178
178
{
179
179
// stop any calls into explicit resizes
180
- std::unique_lock guard (m_swapchainResourcesMutex);
181
- static_cast <ICallback*>(m_cb)->setSwapchainRecreator (nullptr );
180
+ deinit_impl ();
182
181
}
183
182
184
183
//
185
184
inline void deinit_impl () override final
186
185
{
187
186
// stop any calls into explicit resizes
188
187
std::unique_lock guard (m_swapchainResourcesMutex);
189
- static_cast <ICallback*>(m_cb)->setSwapchainRecreator ( nullptr ) ;
188
+ static_cast <ICallback*>(m_cb)->m_recreator = nullptr ;
190
189
191
190
m_lastPresent.source = {};
192
191
m_lastPresentSourceImage = nullptr ;
@@ -208,38 +207,6 @@ class NBL_API2 ISmoothResizeSurface : public ISimpleManagedSurface
208
207
m_presentSemaphore = nullptr ;
209
208
}
210
209
211
- //
212
- inline bool init_impl (const ISwapchain::SSharedCreationParams& sharedParams) override final
213
- {
214
- // swapchain callback already deinitialized, so no mutex needed here
215
-
216
- auto queue = getAssignedQueue ();
217
- auto device = const_cast <ILogicalDevice*>(queue->getOriginDevice ());
218
-
219
- m_sharedParams = sharedParams;
220
- if (!m_sharedParams.deduce (device->getPhysicalDevice (),getSurface ()))
221
- return false ;
222
-
223
- // want to keep using the same semaphore throughout the lifetime to not run into sync issues
224
- if (!m_presentSemaphore)
225
- {
226
- m_presentSemaphore = device->createSemaphore (0u );
227
- if (!m_presentSemaphore)
228
- return false ;
229
- }
230
-
231
- // transient commandbuffer and pool to perform the blits or other copies to SC images
232
- auto pool = device->createCommandPool (queue->getFamilyIndex (),IGPUCommandPool::CREATE_FLAGS::RESET_COMMAND_BUFFER_BIT);
233
- if (!pool || !pool->createCommandBuffers (IGPUCommandPool::BUFFER_LEVEL::PRIMARY,{m_cmdbufs.data (),getMaxFramesInFlight ()}))
234
- return false ;
235
-
236
- if (!createSwapchainResources ())
237
- return false ;
238
-
239
- static_cast <ICallback*>(m_cb)->setSwapchainRecreator (this );
240
- return true ;
241
- }
242
-
243
210
//
244
211
inline bool recreateSwapchain (const uint32_t w=0 , const uint32_t h=0 )
245
212
{
@@ -285,7 +252,7 @@ class NBL_API2 ISmoothResizeSurface : public ISimpleManagedSurface
285
252
if (newSwapchain)
286
253
{
287
254
swapchainResources->invalidate ();
288
- return createSwapchainResources () ->onCreateSwapchain (getAssignedQueue ()->getFamilyIndex (),std::move (newSwapchain));
255
+ return swapchainResources ->onCreateSwapchain (getAssignedQueue ()->getFamilyIndex (),std::move (newSwapchain));
289
256
}
290
257
else
291
258
{
@@ -403,18 +370,16 @@ class NBL_API2 ISmoothResizeSurface : public ISimpleManagedSurface
403
370
return ISimpleManagedSurface::present (imageIx,{waitSemaphores+1 ,1 });
404
371
}
405
372
406
- // Assume it will execute under a mutex
407
- virtual ISwapchainResources* createSwapchainResources () = 0;
408
-
409
373
// Because the surface can start minimized (extent={0,0}) we might not be able to create the swapchain right away, so store creation parameters until we can create it.
410
374
ISwapchain::SSharedCreationParams m_sharedParams = {};
411
375
412
- private :
376
+ protected :
413
377
// Have to use a second semaphore to make acquire-present pairs independent of each other, also because there can be no ordering ensured between present->acquire
414
378
core::smart_refctd_ptr<ISemaphore> m_presentSemaphore;
415
379
// Command Buffers for blitting/copying the Triple Buffers to Swapchain Images
416
380
std::array<core::smart_refctd_ptr<IGPUCommandBuffer>,ISwapchain::MaxImages> m_cmdbufs = {};
417
381
382
+ private:
418
383
// used to protect access to swapchain resources during present and recreateExplicit
419
384
std::mutex m_swapchainResourcesMutex;
420
385
// Why do we delay the swapchain recreate present until the rendering of the most recent present source is done? Couldn't we present whatever latest Triple Buffer is done?
@@ -451,24 +416,51 @@ class CSmoothResizeSurface final : public ISmoothResizeSurface
451
416
return core::smart_refctd_ptr<this_t >(new this_t (std::move (_surface),cb),core::dont_grab);
452
417
}
453
418
419
+ //
420
+ inline bool init (CThreadSafeQueueAdapter* queue, std::unique_ptr<SwapchainResources>&& scResources, const ISwapchain::SSharedCreationParams& sharedParams={})
421
+ {
422
+ // swapchain callback already deinitialized, so no mutex needed here
423
+ if (!scResources || !base_init (queue))
424
+ return init_fail ();
425
+
426
+ auto device = const_cast <ILogicalDevice*>(queue->getOriginDevice ());
427
+
428
+ m_sharedParams = sharedParams;
429
+ if (!m_sharedParams.deduce (device->getPhysicalDevice (),getSurface ()))
430
+ return init_fail ();
431
+
432
+ // want to keep using the same semaphore throughout the lifetime to not run into sync issues
433
+ if (!m_presentSemaphore)
434
+ {
435
+ m_presentSemaphore = device->createSemaphore (0u );
436
+ if (!m_presentSemaphore)
437
+ return init_fail ();
438
+ }
439
+
440
+ // transient commandbuffer and pool to perform the blits or other copies to SC images
441
+ auto pool = device->createCommandPool (queue->getFamilyIndex (),IGPUCommandPool::CREATE_FLAGS::RESET_COMMAND_BUFFER_BIT);
442
+ if (!pool || !pool->createCommandBuffers (IGPUCommandPool::BUFFER_LEVEL::PRIMARY,{m_cmdbufs.data (),getMaxFramesInFlight ()}))
443
+ return init_fail ();
444
+
445
+ m_swapchainResources = std::move (scResources);
446
+
447
+ setSwapchainRecreator ();
448
+ return true ;
449
+ }
450
+
454
451
protected:
455
452
using ISmoothResizeSurface::ISmoothResizeSurface;
456
453
457
454
inline bool checkQueueFamilyProps (const IPhysicalDevice::SQueueFamilyProperties& props) const override {return props.queueFlags .hasFlags (SwapchainResources::RequiredQueueFlags);}
458
455
459
- // All of the below are called under a mutex
460
- inline ISwapchainResources* createSwapchainResources () override
461
- {
462
- m_swapchainResources = core::make_smart_refctd_ptr<SwapchainResources>();
463
- return m_swapchainResources.get ();
464
- }
456
+ // All of the below are called from under a mutex
465
457
inline ISimpleManagedSurface::ISwapchainResources* getSwapchainResources () override {return m_swapchainResources.get ();}
466
458
inline void becomeIrrecoverable () override {m_swapchainResources = nullptr ;}
467
459
468
460
private:
469
461
// As per the above, the swapchain might not be possible to create or recreate right away, so this might be
470
462
// either nullptr before the first successful acquire or the old to-be-retired swapchain.
471
- core::smart_refctd_ptr <SwapchainResources> m_swapchainResources = {};
463
+ std::unique_ptr <SwapchainResources> m_swapchainResources = {};
472
464
};
473
465
474
466
}
0 commit comments