From bd030db03f03c5bcc6572e7e1441b4b1979d3fb0 Mon Sep 17 00:00:00 2001 From: rogerman Date: Mon, 18 Apr 2022 13:20:41 -0700 Subject: [PATCH] Cocoa Port: Use a std::queue to keep track of Metal drawable ordering. - This is probably super paranoid and completely overkill, but it makes me feel better to do this. Now there is absolute certainty that nothing can disrupt the drawable order in between rendering and presentation. Microstuttering from mis-ordered drawables can no longer happen. --- .../cocoa/userinterface/MacMetalDisplayView.h | 4 +++- .../cocoa/userinterface/MacMetalDisplayView.mm | 15 +++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.h b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.h index 43ea54eab..6e1578031 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.h +++ b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.h @@ -26,6 +26,8 @@ #include #include +#include + #import "DisplayViewCALayer.h" #import "../cocoa_GPU.h" #import "../cocoa_util.h" @@ -269,7 +271,7 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties; MacDisplayLayeredView *_cdv; MacMetalDisplayPresenterObject *presenterObject; dispatch_semaphore_t _semDrawable; - id _currentDrawable; + std::queue< id > *_drawableQueue; id layerDrawable0; id layerDrawable1; id layerDrawable2; diff --git a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm index b871941dc..5f8ea5187 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm +++ b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm @@ -2261,7 +2261,7 @@ _cdv = NULL; _semDrawable = dispatch_semaphore_create(3); - _currentDrawable = nil; + _drawableQueue = new std::queue< id >; layerDrawable0 = nil; layerDrawable1 = nil; layerDrawable2 = nil; @@ -2290,6 +2290,8 @@ [self setLayerDrawable2:nil]; dispatch_release(_semDrawable); + delete _drawableQueue; + [_displayTexturePair.main release]; [_displayTexturePair.touch release]; @@ -2312,7 +2314,6 @@ id drawable = [self nextDrawable]; if (drawable == nil) { - _currentDrawable = nil; dispatch_semaphore_signal(_semDrawable); return; } @@ -2332,6 +2333,8 @@ } } + _drawableQueue->push(drawable); + id texDrawable = [drawable texture]; [[presenterObject colorAttachment0Desc] setTexture:texDrawable]; @@ -2363,19 +2366,19 @@ [cb addCompletedHandler:^(id block) { [presenterObject renderFinishAtIndex:mrfi.renderIndex]; }]; - - _currentDrawable = drawable; } - (void) presentDrawableWithCommandBuffer:(id)cb outputTime:(uint64_t)outputTime { - id drawable = _currentDrawable; - if (drawable == nil) + if (_drawableQueue->empty()) { printf("Metal: No drawable was assigned!\n"); return; } + id drawable = _drawableQueue->front(); + _drawableQueue->pop(); + // Apple's documentation might seem to suggest that [MTLCommandBuffer presentDrawable:atTime:] // and [MTLDrawable presentAtTime:] inside of a [MTLCommandBuffer addScheduledHandler:] block // are equivalent. However, much testing has shown that this is NOT the case.