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.
This commit is contained in:
rogerman 2022-04-18 13:20:41 -07:00
parent 32461006d9
commit bd030db03f
2 changed files with 12 additions and 7 deletions

View File

@ -26,6 +26,8 @@
#include <mach/semaphore.h>
#include <mach/sync_policy.h>
#include <queue>
#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<CAMetalDrawable> _currentDrawable;
std::queue< id<CAMetalDrawable> > *_drawableQueue;
id<CAMetalDrawable> layerDrawable0;
id<CAMetalDrawable> layerDrawable1;
id<CAMetalDrawable> layerDrawable2;

View File

@ -2261,7 +2261,7 @@
_cdv = NULL;
_semDrawable = dispatch_semaphore_create(3);
_currentDrawable = nil;
_drawableQueue = new std::queue< id<CAMetalDrawable> >;
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<CAMetalDrawable> drawable = [self nextDrawable];
if (drawable == nil)
{
_currentDrawable = nil;
dispatch_semaphore_signal(_semDrawable);
return;
}
@ -2332,6 +2333,8 @@
}
}
_drawableQueue->push(drawable);
id<MTLTexture> texDrawable = [drawable texture];
[[presenterObject colorAttachment0Desc] setTexture:texDrawable];
@ -2363,19 +2366,19 @@
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
[presenterObject renderFinishAtIndex:mrfi.renderIndex];
}];
_currentDrawable = drawable;
}
- (void) presentDrawableWithCommandBuffer:(id<MTLCommandBuffer>)cb outputTime:(uint64_t)outputTime
{
id<CAMetalDrawable> drawable = _currentDrawable;
if (drawable == nil)
if (_drawableQueue->empty())
{
printf("Metal: No drawable was assigned!\n");
return;
}
id<CAMetalDrawable> 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.