@@ -233,9 +233,10 @@ static inline MTLTextureUsage getMetalTextureUsage(TextureUsage usage) {
233
233
}
234
234
235
235
void MetalSwapChain::setFrameScheduledCallback (
236
- CallbackHandler* handler, FrameScheduledCallback&& callback) {
236
+ CallbackHandler* handler, FrameScheduledCallback&& callback, uint64_t flags ) {
237
237
frameScheduled.handler = handler;
238
238
frameScheduled.callback = std::make_shared<FrameScheduledCallback>(std::move (callback));
239
+ frameScheduled.flags = flags;
239
240
}
240
241
241
242
void MetalSwapChain::setFrameCompletedCallback (
@@ -264,27 +265,34 @@ static inline MTLTextureUsage getMetalTextureUsage(TextureUsage usage) {
264
265
PresentDrawableData& operator =(const PresentDrawableData&) = delete ;
265
266
266
267
static PresentDrawableData* create (id <CAMetalDrawable > drawable,
267
- std::shared_ptr<std::mutex> drawableMutex, MetalDriver* driver) {
268
+ std::shared_ptr<std::mutex> drawableMutex, MetalDriver* driver, uint64_t flags ) {
268
269
assert_invariant (drawableMutex);
269
270
assert_invariant (driver);
270
- return new PresentDrawableData (drawable, drawableMutex, driver);
271
+ return new PresentDrawableData (drawable, drawableMutex, driver, flags );
271
272
}
272
273
273
274
static void maybePresentAndDestroyAsync (PresentDrawableData* that, bool shouldPresent) {
274
275
if (shouldPresent) {
275
276
[that->mDrawable present ];
276
277
}
277
278
278
- // mDrawable is acquired on the driver thread. Typically, we would release this object on
279
- // the same thread, but after receiving consistent crash reports from within
280
- // [CAMetalDrawable dealloc], we suspect this object requires releasing on the main thread.
281
- dispatch_async (dispatch_get_main_queue (), ^{ cleanupAndDestroy (that); });
279
+ if (that->mFlags & SwapChain::CALLBACK_DEFAULT_USE_METAL_COMPLETION_HANDLER) {
280
+ cleanupAndDestroy (that);
281
+ } else {
282
+ // mDrawable is acquired on the driver thread. Typically, we would release this object
283
+ // on the same thread, but after receiving consistent crash reports from within
284
+ // [CAMetalDrawable dealloc], we suspect this object requires releasing on the main
285
+ // thread.
286
+ dispatch_async (dispatch_get_main_queue (), ^{
287
+ cleanupAndDestroy (that);
288
+ });
289
+ }
282
290
}
283
291
284
292
private:
285
293
PresentDrawableData (id <CAMetalDrawable > drawable, std::shared_ptr<std::mutex> drawableMutex,
286
- MetalDriver* driver)
287
- : mDrawable (drawable), mDrawableMutex (drawableMutex), mDriver (driver) {}
294
+ MetalDriver* driver, uint64_t flags )
295
+ : mDrawable (drawable), mDrawableMutex (drawableMutex), mDriver (driver), mFlags (flags) {}
288
296
289
297
static void cleanupAndDestroy (PresentDrawableData *that) {
290
298
if (that->mDrawable ) {
@@ -299,6 +307,7 @@ static void cleanupAndDestroy(PresentDrawableData *that) {
299
307
id <CAMetalDrawable > mDrawable ;
300
308
std::shared_ptr<std::mutex> mDrawableMutex ;
301
309
MetalDriver* mDriver = nullptr ;
310
+ uint64_t mFlags = 0 ;
302
311
};
303
312
304
313
void presentDrawable (bool presentFrame, void * user) {
@@ -315,8 +324,8 @@ void presentDrawable(bool presentFrame, void* user) {
315
324
316
325
struct Callback {
317
326
Callback (std::shared_ptr<FrameScheduledCallback> callback, id <CAMetalDrawable > drawable,
318
- std::shared_ptr<std::mutex> drawableMutex, MetalDriver* driver)
319
- : f(callback), data(PresentDrawableData::create(drawable, drawableMutex, driver)) {}
327
+ std::shared_ptr<std::mutex> drawableMutex, MetalDriver* driver, uint64_t flags )
328
+ : f(callback), data(PresentDrawableData::create(drawable, drawableMutex, driver, flags )) {}
320
329
std::shared_ptr<FrameScheduledCallback> f;
321
330
// PresentDrawableData* is destroyed by maybePresentAndDestroyAsync() later.
322
331
std::unique_ptr<PresentDrawableData> data;
@@ -331,14 +340,19 @@ static void func(void* user) {
331
340
332
341
// This callback pointer will be captured by the block. Even if the scheduled handler is never
333
342
// called, the unique_ptr will still ensure we don't leak memory.
343
+ uint64_t const flags = frameScheduled.flags ;
334
344
__block auto callback = std::make_unique<Callback>(
335
- frameScheduled.callback , drawable, layerDrawableMutex, context.driver );
345
+ frameScheduled.callback , drawable, layerDrawableMutex, context.driver , flags );
336
346
337
347
backend::CallbackHandler* handler = frameScheduled.handler ;
338
348
MetalDriver* driver = context.driver ;
339
349
[getPendingCommandBuffer (&context) addScheduledHandler: ^(id <MTLCommandBuffer > cb) {
340
350
Callback* user = callback.release ();
341
- driver->scheduleCallback (handler, user, &Callback::func);
351
+ if (flags & SwapChain::CALLBACK_DEFAULT_USE_METAL_COMPLETION_HANDLER) {
352
+ Callback::func (user);
353
+ } else {
354
+ driver->scheduleCallback (handler, user, &Callback::func);
355
+ }
342
356
}];
343
357
}
344
358
0 commit comments