@@ -10,6 +10,8 @@ namespace nbl::video
1010{
1111
1212// 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
1315class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
1416{
1517 public:
@@ -35,6 +37,15 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
3537 //
3638 inline ISurface* getSurface () {return m_surface.get ();}
3739 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+ }
3849
3950 // A small utility for the boilerplate
4051 inline uint8_t pickQueueFamily (ILogicalDevice* device) const
@@ -184,8 +195,8 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
184195 inline ISimpleManagedSurface (core::smart_refctd_ptr<ISurface>&& _surface, ICallback* _cb) : m_surface(std::move(_surface)), m_cb(_cb) {}
185196 virtual inline ~ISimpleManagedSurface () = default ;
186197
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 ()
189200 {
190201 // Only check upon an acquire, previously acquired images MUST be presented
191202 // 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
202213 break ;
203214 [[fallthrough]];
204215 case status_t ::IRRECOVERABLE:
205- return - 1 ;
216+ return ISwapchain::MaxImages ;
206217 default :
207218 break ;
208219 }
@@ -222,7 +233,7 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
222233 case ISwapchain::ACQUIRE_IMAGE_RESULT::SUCCESS:
223234 // the semaphore will only get signalled upon a successful acquire
224235 m_acquireCount++;
225- return static_cast <int8_t >(imageIndex);
236+ return static_cast <uint8_t >(imageIndex);
226237 case ISwapchain::ACQUIRE_IMAGE_RESULT::TIMEOUT: [[fallthrough]];
227238 case ISwapchain::ACQUIRE_IMAGE_RESULT::NOT_READY: // don't throw our swapchain away just because of a timeout XD
228239 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
231242 getSwapchainResources ().invalidate ();
232243 // try again, will re-create swapchain
233244 {
234- const int8_t retval = handleOutOfDate ();
235- if (retval>= 0 )
245+ const auto retval = handleOutOfDate ();
246+ if (retval!=ISwapchain::MaxImages )
236247 return retval;
237248 }
238249 default :
239250 break ;
240251 }
241252 }
242253 getSwapchainResources ().becomeIrrecoverable ();
243- return - 1 ;
254+ return ISwapchain::MaxImages ;
244255 }
245256
246257 // 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)
248259 {
249260 if (getSwapchainResources ().getStatus ()!=ISwapchainResources::STATUS::USABLE || !frameResources)
250261 return false ;
@@ -254,7 +265,7 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
254265 .imgIndex = imageIndex,
255266 .waitSemaphores = waitSemaphores
256267 };
257- switch (getSwapchainResources ().getSwapchain ()->present (info,std::move (frameResources)))
268+ switch (getSwapchainResources ().getSwapchain ()->present (info,core::smart_refctd_ptr<core::IReferenceCounted> (frameResources)))
258269 {
259270 case ISwapchain::PRESENT_RESULT::SUBOPTIMAL: [[fallthrough]];
260271 case ISwapchain::PRESENT_RESULT::SUCCESS:
@@ -263,6 +274,14 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
263274 getSwapchainResources ().invalidate ();
264275 break ;
265276 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+ }
266285 getSwapchainResources ().becomeIrrecoverable ();
267286 break ;
268287 }
@@ -279,13 +298,16 @@ class NBL_API2 ISimpleManagedSurface : public core::IReferenceCounted
279298 virtual bool init_impl (CThreadSafeQueueAdapter* queue, const ISwapchain::SSharedCreationParams& sharedParams) = 0;
280299
281300 // 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 ;
284307
285308 private:
286309 // persistent and constant for whole lifetime of the object
287310 const core::smart_refctd_ptr<ISurface> m_surface;
288- ICallback* const m_cb = nullptr ;
289311 // Use a Threadsafe queue to make sure we can do smooth resize in derived class, might get re-assigned
290312 CThreadSafeQueueAdapter* m_queue = nullptr ;
291313 // created and persistent after first initialization
0 commit comments