Group Group Group Group Group Group Group Group Group

Chapter 15 semaphore issue?

First question:
Concerning the Renderer “draw” routine in Chap 15 of Metal Tutorials, beginning with a semaphore.wait. I’m looking more at the sample code than the book. (The only mentions of semaphore in the book are on pages 438 and page 441).

If any error occurs, the “draw” routine exits without a requisite semaphore.signal (as occurs in the completion routine). I believe this effectively hangs the app for good – ie. in the case that any temporary error occurs.

Should not all the early “return” situations from the draw function also signal the semaphore?

Second question:
This same code creates a weak reference to the semaphore just before the completion handler runs (“weak var set = semaphore”). Based on what I see in WWDC2016 Video #603 “Adopting Metal, Part 2” (@31:30) this is not the suggested way to reference a semaphore within a completion handler.

Which is the accepted way of doing things?

Great work, folks!

I am not sure what other errors could happen except those already handled by the guard statements inside the render loop. Can you provide an example of such error? As for the completion handler, that is exactly its purpose: to prevent thread blocking. The command buffer calls a completion handler with a signal command inside and then the command buffer is committed. When the GPU finishes work, the signal is sent and the held resource is freed. Using the weak keyword is the correct way of doing it. If you look at the latest Apple sample code, they are also capturing a reference before the completion handler/block.

Thanks for the kind words and for your feedback! :slightly_smiling_face:

If each of those “bailing” return statements had a semaphore.signal ahead of it, then a subsequent render attempt wouldn’t automatically hang at the semaphore.signal code.

However, the way the code is written, a single error (ever) in this render loop will hang the app for good as that semaphore will now always be waiting.

I am still not sure how that could ever happen. Maybe if you provided an example… are you able to ever get into that situation?

I can’t think of one, but surely there’d be instances where those guard statements will cause the draw function to abort (otherwise, why put them in?) – and if that’s the case, then the app will hang with an unbalanced semaphore.

Did you get a chance to look at the Apple sample code I linked? I believe they do it the same way we did.

Yes I did look at Apple’s code; they do the semaphore.wait at the top of the render and the semaphore.signal in the completion handler. There is no other relevant code; if the completion handler never runs, though, it makes sense to signal the semaphore manually in the event that one ‘bails’ on the render.

I believe the completion handler is guaranteed to run when the command buffer finishes its work.