@@ -10,6 +10,8 @@ namespace nbl::video
10
10
{
11
11
12
12
// The use of this class is supposed to be externally synchronized
13
+ // For this whole thing to work, you CAN ONLY ACQUIRE ONE IMAGE AT A TIME BEFORE CALLING PRESENT!
14
+ // Why? look at the `becomeIrrecoverable` implementation
13
15
class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
14
16
{
15
17
public:
@@ -35,6 +37,15 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
35
37
//
36
38
inline ISurface* getSurface () {return m_surface.get ();}
37
39
inline const ISurface* getSurface () const {return m_surface.get ();}
40
+
41
+ //
42
+ inline uint8_t getMaxFramesInFlight (IPhysicalDevice* physDev) const
43
+ {
44
+ ISurface::SCapabilities caps = {};
45
+ m_surface->getSurfaceCapabilitiesForPhysicalDevice (physDev,caps);
46
+ // vkAcquireNextImageKHR should not be called if the number of images that the application has currently acquired is greater than SwapchainImages-MinimumImages
47
+ return core::min (caps.maxImageCount +1 -caps.minImageCount ,ISwapchain::MaxImages);
48
+ }
38
49
39
50
// A small utility for the boilerplate
40
51
inline uint8_t pickQueueFamily (ILogicalDevice* device) const
@@ -184,8 +195,8 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
184
195
inline ISimpleManagedSurface (core::smart_refctd_ptr<ISurface>&& _surface, ICallback* _cb) : m_surface(std::move(_surface)), m_cb(_cb) {}
185
196
virtual inline ~ISimpleManagedSurface () = default ;
186
197
187
- // RETURNS: Negative on failure, otherwise its the acquired image's index.
188
- inline int8_t acquireNextImage ()
198
+ // RETURNS: `ISwapchain::MaxImages` on failure, otherwise its the acquired image's index.
199
+ inline uint8_t acquireNextImage ()
189
200
{
190
201
// Only check upon an acquire, previously acquired images MUST be presented
191
202
// Window/Surface got closed, but won't actually disappear UNTIL the swapchain gets dropped,
@@ -202,7 +213,7 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
202
213
break ;
203
214
[[fallthrough]];
204
215
case status_t ::IRRECOVERABLE:
205
- return - 1 ;
216
+ return ISwapchain::MaxImages ;
206
217
default :
207
218
break ;
208
219
}
@@ -222,7 +233,7 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
222
233
case ISwapchain::ACQUIRE_IMAGE_RESULT::SUCCESS:
223
234
// the semaphore will only get signalled upon a successful acquire
224
235
m_acquireCount++;
225
- return static_cast <int8_t >(imageIndex);
236
+ return static_cast <uint8_t >(imageIndex);
226
237
case ISwapchain::ACQUIRE_IMAGE_RESULT::TIMEOUT: [[fallthrough]];
227
238
case ISwapchain::ACQUIRE_IMAGE_RESULT::NOT_READY: // don't throw our swapchain away just because of a timeout XD
228
239
assert (false ); // shouldn't happen though cause we use uint64_t::max() as the timeout
@@ -231,20 +242,20 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
231
242
getSwapchainResources ().invalidate ();
232
243
// try again, will re-create swapchain
233
244
{
234
- const int8_t retval = handleOutOfDate ();
235
- if (retval>= 0 )
245
+ const auto retval = handleOutOfDate ();
246
+ if (retval!=ISwapchain::MaxImages )
236
247
return retval;
237
248
}
238
249
default :
239
250
break ;
240
251
}
241
252
}
242
253
getSwapchainResources ().becomeIrrecoverable ();
243
- return - 1 ;
254
+ return ISwapchain::MaxImages ;
244
255
}
245
256
246
257
// Frame Resources are not optional, shouldn't be null!
247
- inline bool present (const uint8_t imageIndex, const std::span<const IQueue::SSubmitInfo::SSemaphoreInfo> waitSemaphores, core::smart_refctd_ptr<core:: IReferenceCounted>&& frameResources)
258
+ inline bool present (const uint8_t imageIndex, const std::span<const IQueue::SSubmitInfo::SSemaphoreInfo> waitSemaphores, core::IReferenceCounted* frameResources)
248
259
{
249
260
if (getSwapchainResources ().getStatus ()!=ISwapchainResources::STATUS::USABLE || !frameResources)
250
261
return false ;
@@ -254,7 +265,7 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
254
265
.imgIndex = imageIndex,
255
266
.waitSemaphores = waitSemaphores
256
267
};
257
- switch (getSwapchainResources ().getSwapchain ()->present (info,std::move (frameResources)))
268
+ switch (getSwapchainResources ().getSwapchain ()->present (info,core::smart_refctd_ptr<core::IReferenceCounted> (frameResources)))
258
269
{
259
270
case ISwapchain::PRESENT_RESULT::SUBOPTIMAL: [[fallthrough]];
260
271
case ISwapchain::PRESENT_RESULT::SUCCESS:
@@ -263,6 +274,14 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
263
274
getSwapchainResources ().invalidate ();
264
275
break ;
265
276
default :
277
+ // because we won't hold onto the `frameResources` we need to block for `waitSemaphores`
278
+ {
279
+ core::vector<ISemaphore::SWaitInfo> waitInfos (waitSemaphores.size ());
280
+ auto outWait = waitInfo.data ();
281
+ for (auto wait : waitSemaphores)
282
+ *(outWait++) = {.semaphore =wait.semaphore ,.value =wait.value };
283
+ const_cast <ILogicalDevice*>(m_queue->getOriginDevice ())->blockForSemaphores (waitInfos);
284
+ }
266
285
getSwapchainResources ().becomeIrrecoverable ();
267
286
break ;
268
287
}
@@ -279,13 +298,16 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
279
298
virtual bool init_impl (CThreadSafeQueueAdapter* queue, const ISwapchain::SSharedCreationParams& sharedParams) = 0;
280
299
281
300
// handlers for acquisition exceptions
282
- virtual bool handleNotReady () = 0;
283
- virtual int8_t handleOutOfDate () = 0;
301
+ // by default we can't do anything
302
+ virtual bool handleNotReady () {return false ;}
303
+ virtual uint8_t handleOutOfDate () {return ISwapchain::MaxImages;}
304
+
305
+ //
306
+ ICallback* const m_cb = nullptr ;
284
307
285
308
private:
286
309
// persistent and constant for whole lifetime of the object
287
310
const core::smart_refctd_ptr<ISurface> m_surface;
288
- ICallback* const m_cb = nullptr ;
289
311
// Use a Threadsafe queue to make sure we can do smooth resize in derived class, might get re-assigned
290
312
CThreadSafeQueueAdapter* m_queue = nullptr ;
291
313
// created and persistent after first initialization
0 commit comments