Skip to content

Commit 8c0c966

Browse files
better return values on ISimpleManagedSurface::acquireNextImage, make it clear we only acquire consecutive acquire-present pairs, wait on the pre-present wait fences if presentation fails, silence an error in ISurface
1 parent 0d808a2 commit 8c0c966

File tree

2 files changed

+35
-13
lines changed

2 files changed

+35
-13
lines changed

include/nbl/video/surface/ISurface.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ class ISurface : public core::IReferenceCounted
176176
VkExtent2D currentExtent = {0u,0u};
177177
VkExtent2D minImageExtent = {~0u,~0u};
178178
VkExtent2D maxImageExtent = {0u,0u};
179-
uint8_t minImageCount = ~0u;
179+
uint8_t minImageCount = 0xffu;
180180
uint8_t maxImageCount = 0;
181181
uint8_t maxImageArrayLayers = 0;
182182
core::bitflag<E_COMPOSITE_ALPHA> supportedCompositeAlpha = ECA_NONE;

include/nbl/video/utilities/ISimpleManagedSurface.h

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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
1315
class 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

Comments
 (0)