Closed ullerrm closed 1 week ago
@bejado can we find a better solution for this? I really don't like having heap allocations for this and I'm not a fan of the mutex in the first place.
Unfortunately CAMetalLayer
is not thread-safe with respect to drawable allocation:
So, the only alternative to using a mutex I imagine would be to always acquire/release drawables on the main thread. But, that has performance implications and potential deadlock hazards I need to think through. For now I think this is the best fix; using shared_ptr
is a pattern we use elsewhere in the backend to ensure certain objects outlast the destruction of a handle.
If a user is using
setFrameScheduledCallback()
, managing the provided PresentCallable during engine shutdown is tricky -- we'll likely get a final frame scheduled when we flush the engine's work queue, but the PresentCallable will schedule the final CAMetalDrawable to be released on main thread afterwards, even if we callpresent(false)
to skip it. If the swap chain is destroyed before that main queue block gets executed, the mutex presenting that drawable will no longer exist, causing a crash.To make things easier, store the std::mutex in a shared_ptr, so that a PresentCallable can safely outlive the FSwapChain instance that created it and clean itself up afterwards.
Alternatives considered, all of which seem unfortunate: