Cocoa Port: Yet another attempt at eliminating microstuttering in Metal display views. While it hasn't been completely eliminated yet, it shouldn't be as bad now.

This commit is contained in:
rogerman 2018-11-28 13:36:02 -08:00
parent 1f9b9e02a4
commit 4f543aa8ca
9 changed files with 210 additions and 148 deletions

View File

@ -1292,7 +1292,7 @@ void ClientDisplayViewInterface::FlushView(void *userData)
this->_viewNeedsFlush = false; this->_viewNeedsFlush = false;
} }
void ClientDisplayViewInterface::FinalizeFlush(void *userData) void ClientDisplayViewInterface::FinalizeFlush(void *userData, uint64_t outputTime)
{ {
// Do nothing. This is implementation dependent. // Do nothing. This is implementation dependent.
} }
@ -1300,7 +1300,7 @@ void ClientDisplayViewInterface::FinalizeFlush(void *userData)
void ClientDisplayViewInterface::FlushAndFinalizeImmediate() void ClientDisplayViewInterface::FlushAndFinalizeImmediate()
{ {
this->FlushView(NULL); this->FlushView(NULL);
this->FinalizeFlush(NULL); this->FinalizeFlush(NULL, 0);
} }
// Touch screen input handling // Touch screen input handling

View File

@ -356,7 +356,7 @@ public:
virtual void SetAllowViewFlushes(bool allowFlushes); virtual void SetAllowViewFlushes(bool allowFlushes);
virtual void FlushView(void *userData); virtual void FlushView(void *userData);
virtual void FinalizeFlush(void *userData); virtual void FinalizeFlush(void *userData, uint64_t outputTime);
virtual void FlushAndFinalizeImmediate(); virtual void FlushAndFinalizeImmediate();
// Touch screen input handling // Touch screen input handling

View File

@ -105,9 +105,8 @@ typedef std::map<CGDirectDisplayID, int64_t> DisplayLinkFlushTimeLimitMap;
- (void) decrementViewsUsingDirectToCPUFiltering; - (void) decrementViewsUsingDirectToCPUFiltering;
- (void) pushVideoDataToAllDisplayViews; - (void) pushVideoDataToAllDisplayViews;
- (void) flushAllDisplaysOnDisplayLink:(CVDisplayLinkRef)displayLink timeStamp:(const CVTimeStamp *)timeStamp; - (void) flushAllDisplaysOnDisplayLink:(CVDisplayLinkRef)displayLink timeStampNow:(const CVTimeStamp *)timeStampNow timeStampOutput:(const CVTimeStamp *)timeStampOutput;
- (void) flushMultipleViews:(const std::vector<ClientDisplay3DView *> &)cdvFlushList; - (void) flushMultipleViews:(const std::vector<ClientDisplay3DView *> &)cdvFlushList timeStampNow:(const CVTimeStamp *)timeStampNow timeStampOutput:(const CVTimeStamp *)timeStampOutput;
- (void) finalizeFlushMultipleViews:(const std::vector<ClientDisplay3DView *> &)cdvFlushList;
- (void) displayLinkStartUsingID:(CGDirectDisplayID)displayID; - (void) displayLinkStartUsingID:(CGDirectDisplayID)displayID;
- (void) displayLinkListUpdate; - (void) displayLinkListUpdate;

View File

@ -1382,7 +1382,7 @@ public:
} }
} }
- (void) flushAllDisplaysOnDisplayLink:(CVDisplayLinkRef)displayLink timeStamp:(const CVTimeStamp *)timeStamp - (void) flushAllDisplaysOnDisplayLink:(CVDisplayLinkRef)displayLink timeStampNow:(const CVTimeStamp *)timeStampNow timeStampOutput:(const CVTimeStamp *)timeStampOutput
{ {
pthread_rwlock_t *currentRWLock = _rwlockOutputList; pthread_rwlock_t *currentRWLock = _rwlockOutputList;
CGDirectDisplayID displayID = CVDisplayLinkGetCurrentCGDisplay(displayLink); CGDirectDisplayID displayID = CVDisplayLinkGetCurrentCGDisplay(displayLink);
@ -1415,8 +1415,7 @@ public:
if (listSize > 0) if (listSize > 0)
{ {
[self flushMultipleViews:cdvFlushList]; [self flushMultipleViews:cdvFlushList timeStampNow:timeStampNow timeStampOutput:timeStampOutput];
[self finalizeFlushMultipleViews:cdvFlushList];
didFlushOccur = true; didFlushOccur = true;
} }
@ -1428,15 +1427,15 @@ public:
if (didFlushOccur) if (didFlushOccur)
{ {
// Set the new time limit to 8 seconds after the current time. // Set the new time limit to 8 seconds after the current time.
_displayLinkFlushTimeList[displayID] = timeStamp->videoTime + (timeStamp->videoTimeScale * VIDEO_FLUSH_TIME_LIMIT_OFFSET); _displayLinkFlushTimeList[displayID] = timeStampNow->videoTime + (timeStampNow->videoTimeScale * VIDEO_FLUSH_TIME_LIMIT_OFFSET);
} }
else if (timeStamp->videoTime > _displayLinkFlushTimeList[displayID]) else if (timeStampNow->videoTime > _displayLinkFlushTimeList[displayID])
{ {
CVDisplayLinkStop(displayLink); CVDisplayLinkStop(displayLink);
} }
} }
- (void) flushMultipleViews:(const std::vector<ClientDisplay3DView *> &)cdvFlushList - (void) flushMultipleViews:(const std::vector<ClientDisplay3DView *> &)cdvFlushList timeStampNow:(const CVTimeStamp *)timeStampNow timeStampOutput:(const CVTimeStamp *)timeStampOutput
{ {
const size_t listSize = cdvFlushList.size(); const size_t listSize = cdvFlushList.size();
@ -1445,16 +1444,11 @@ public:
ClientDisplay3DView *cdv = (ClientDisplay3DView *)cdvFlushList[i]; ClientDisplay3DView *cdv = (ClientDisplay3DView *)cdvFlushList[i];
cdv->FlushView(NULL); cdv->FlushView(NULL);
} }
}
- (void) finalizeFlushMultipleViews:(const std::vector<ClientDisplay3DView *> &)cdvFlushList
{
const size_t listSize = cdvFlushList.size();
for (size_t i = 0; i < listSize; i++) for (size_t i = 0; i < listSize; i++)
{ {
ClientDisplay3DView *cdv = (ClientDisplay3DView *)cdvFlushList[i]; ClientDisplay3DView *cdv = (ClientDisplay3DView *)cdvFlushList[i];
cdv->FinalizeFlush(NULL); cdv->FinalizeFlush(NULL, timeStampOutput->hostTime);
} }
} }
@ -1768,7 +1762,7 @@ CVReturn MacDisplayLinkCallback(CVDisplayLinkRef displayLink,
void *displayLinkContext) void *displayLinkContext)
{ {
MacClientSharedObject *sharedData = (MacClientSharedObject *)displayLinkContext; MacClientSharedObject *sharedData = (MacClientSharedObject *)displayLinkContext;
[sharedData flushAllDisplaysOnDisplayLink:displayLink timeStamp:inNow]; [sharedData flushAllDisplaysOnDisplayLink:displayLink timeStampNow:inNow timeStampOutput:inOutputTime];
return kCVReturnSuccess; return kCVReturnSuccess;
} }

View File

@ -2142,13 +2142,13 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
[self setLayer:localLayer]; [self setLayer:localLayer];
[self setWantsLayer:YES]; [self setWantsLayer:YES];
if (isMetalLayer) if (cdv->GetRenderToCALayer())
{ {
cdv->FlushAndFinalizeImmediate(); [localLayer setNeedsDisplay];
} }
else else
{ {
[localLayer setNeedsDisplay]; cdv->FlushAndFinalizeImmediate();
} }
} }

View File

@ -36,7 +36,7 @@
#endif #endif
#define METAL_FETCH_BUFFER_COUNT 3 #define METAL_FETCH_BUFFER_COUNT 3
#define RENDER_BUFFER_COUNT 6 #define RENDER_BUFFER_COUNT 12
class MacMetalFetchObject; class MacMetalFetchObject;
class MacMetalDisplayPresenter; class MacMetalDisplayPresenter;
@ -166,8 +166,7 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
- (void) fetchNativeDisplayByID:(const NDSDisplayID)displayID bufferIndex:(const u8)bufferIndex blitCommandEncoder:(id<MTLBlitCommandEncoder>)bce; - (void) fetchNativeDisplayByID:(const NDSDisplayID)displayID bufferIndex:(const u8)bufferIndex blitCommandEncoder:(id<MTLBlitCommandEncoder>)bce;
- (void) fetchCustomDisplayByID:(const NDSDisplayID)displayID bufferIndex:(const u8)bufferIndex blitCommandEncoder:(id<MTLBlitCommandEncoder>)bce; - (void) fetchCustomDisplayByID:(const NDSDisplayID)displayID bufferIndex:(const u8)bufferIndex blitCommandEncoder:(id<MTLBlitCommandEncoder>)bce;
- (void) flushMultipleViews:(const std::vector<ClientDisplay3DView *> &)cdvFlushList;; - (void) flushMultipleViews:(const std::vector<ClientDisplay3DView *> &)cdvFlushList timeStampNow:(const CVTimeStamp *)timeStampNow timeStampOutput:(const CVTimeStamp *)timeStampOutput;
- (void) finalizeFlushMultipleViews:(const std::vector<ClientDisplay3DView *> &)cdvFlushList;
@end @end
@ -262,18 +261,23 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
MacDisplayLayeredView *_cdv; MacDisplayLayeredView *_cdv;
MacMetalDisplayPresenterObject *presenterObject; MacMetalDisplayPresenterObject *presenterObject;
dispatch_semaphore_t _semDrawable; dispatch_semaphore_t _semDrawable;
id<CAMetalDrawable> layerDrawable; id<CAMetalDrawable> _currentDrawable;
id<CAMetalDrawable> layerDrawable0;
id<CAMetalDrawable> layerDrawable1;
id<CAMetalDrawable> layerDrawable2;
MetalTexturePair _displayTexturePair; MetalTexturePair _displayTexturePair;
size_t _displaySequenceNumber;
} }
@property (readonly, nonatomic) MacMetalDisplayPresenterObject *presenterObject; @property (readonly, nonatomic) MacMetalDisplayPresenterObject *presenterObject;
@property (retain) id<CAMetalDrawable> layerDrawable; @property (retain) id<CAMetalDrawable> layerDrawable0;
@property (retain) id<CAMetalDrawable> layerDrawable1;
@property (retain) id<CAMetalDrawable> layerDrawable2;
- (id) initWithDisplayPresenterObject:(MacMetalDisplayPresenterObject *)thePresenterObject; - (id) initWithDisplayPresenterObject:(MacMetalDisplayPresenterObject *)thePresenterObject;
- (void) setupLayer; - (void) setupLayer;
- (void) renderToDrawableUsingCommandBuffer:(id<MTLCommandBuffer>)cb; - (void) renderToDrawableUsingCommandBuffer:(id<MTLCommandBuffer>)cb;
- (void) presentDrawableWithCommandBuffer:(id<MTLCommandBuffer>)cb; - (void) presentDrawableWithCommandBuffer:(id<MTLCommandBuffer>)cb outputTime:(uint64_t)outputTime;
- (void) renderAndPresentDrawableImmediate; - (void) renderAndPresentDrawableImmediate;
@end @end
@ -368,7 +372,7 @@ public:
// Client view interface // Client view interface
virtual void FlushView(void *userData); virtual void FlushView(void *userData);
virtual void FinalizeFlush(void *userData); virtual void FinalizeFlush(void *userData, uint64_t outputTime);
virtual void FlushAndFinalizeImmediate(); virtual void FlushAndFinalizeImmediate();
}; };

View File

@ -428,10 +428,10 @@
} }
} }
id<MTLComputeCommandEncoder> cce = [cb computeCommandEncoder];
if (currentDisplayInfo.needApplyMasterBrightness[NDSDisplayID_Main] || currentDisplayInfo.needApplyMasterBrightness[NDSDisplayID_Touch]) if (currentDisplayInfo.needApplyMasterBrightness[NDSDisplayID_Main] || currentDisplayInfo.needApplyMasterBrightness[NDSDisplayID_Touch])
{ {
id<MTLComputeCommandEncoder> cce = [cb computeCommandEncoder];
if (currentDisplayInfo.colorFormat == NDSColorFormat_BGR555_Rev) if (currentDisplayInfo.colorFormat == NDSColorFormat_BGR555_Rev)
{ {
[cce setComputePipelineState:_fetch555Pipeline]; [cce setComputePipelineState:_fetch555Pipeline];
@ -505,9 +505,12 @@
targetTexPair.touch = _texDisplayPostprocessCustom[NDSDisplayID_Touch][index]; targetTexPair.touch = _texDisplayPostprocessCustom[NDSDisplayID_Touch][index];
} }
} }
[cce endEncoding];
} }
else if (currentDisplayInfo.colorFormat != NDSColorFormat_BGR888_Rev) else if (currentDisplayInfo.colorFormat != NDSColorFormat_BGR888_Rev)
{ {
id<MTLComputeCommandEncoder> cce = [cb computeCommandEncoder];
bool isPipelineStateSet = false; bool isPipelineStateSet = false;
if (currentDisplayInfo.colorFormat == NDSColorFormat_BGR555_Rev) if (currentDisplayInfo.colorFormat == NDSColorFormat_BGR555_Rev)
@ -569,9 +572,9 @@
} }
} }
} }
[cce endEncoding];
} }
[cce endEncoding];
} }
return targetTexPair; return targetTexPair;
@ -580,7 +583,6 @@
- (void) fetchFromBufferIndex:(const u8)index - (void) fetchFromBufferIndex:(const u8)index
{ {
id<MTLCommandBuffer> cb = [_fetchCommandQueue commandBufferWithUnretainedReferences]; id<MTLCommandBuffer> cb = [_fetchCommandQueue commandBufferWithUnretainedReferences];
[cb enqueue];
semaphore_wait([self semaphoreFramebufferPageAtIndex:index]); semaphore_wait([self semaphoreFramebufferPageAtIndex:index]);
[self setFramebufferState:ClientDisplayBufferState_Reading index:index]; [self setFramebufferState:ClientDisplayBufferState_Reading index:index];
@ -591,16 +593,6 @@
[self setBceFetch:nil]; [self setBceFetch:nil];
[bce endEncoding]; [bce endEncoding];
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
[self setFramebufferState:ClientDisplayBufferState_Idle index:index];
semaphore_signal([self semaphoreFramebufferPageAtIndex:index]);
}];
[cb commit];
cb = [_fetchCommandQueue commandBufferWithUnretainedReferences];
[cb enqueue];
const MetalTexturePair newTexPair = [self setFetchTextureBindingsAtIndex:index commandBuffer:cb]; const MetalTexturePair newTexPair = [self setFetchTextureBindingsAtIndex:index commandBuffer:cb];
[newTexPair.main retain]; [newTexPair.main retain];
[newTexPair.touch retain]; [newTexPair.touch retain];
@ -610,6 +602,9 @@
[self setTexPairFetch:newTexPair]; [self setTexPairFetch:newTexPair];
[oldTexPair.main release]; [oldTexPair.main release];
[oldTexPair.touch release]; [oldTexPair.touch release];
[self setFramebufferState:ClientDisplayBufferState_Idle index:index];
semaphore_signal([self semaphoreFramebufferPageAtIndex:index]);
}]; }];
[cb commit]; [cb commit];
@ -656,32 +651,37 @@
destinationOrigin:MTLOriginMake(0, 0, 0)]; destinationOrigin:MTLOriginMake(0, 0, 0)];
} }
- (void) flushMultipleViews:(const std::vector<ClientDisplay3DView *> &)cdvFlushList - (void) flushMultipleViews:(const std::vector<ClientDisplay3DView *> &)cdvFlushList timeStampNow:(const CVTimeStamp *)timeStampNow timeStampOutput:(const CVTimeStamp *)timeStampOutput
{ {
const size_t listSize = cdvFlushList.size(); const size_t listSize = cdvFlushList.size();
id<MTLCommandBuffer> cb = [commandQueue commandBufferWithUnretainedReferences];
for (size_t i = 0; i < listSize; i++) @autoreleasepool
{ {
ClientDisplay3DView *cdv = (ClientDisplay3DView *)cdvFlushList[i]; id<MTLCommandBuffer> cbFlush = [commandQueue commandBufferWithUnretainedReferences];
cdv->FlushView(cb); id<MTLCommandBuffer> cbFinalize = [commandQueue commandBufferWithUnretainedReferences];
for (size_t i = 0; i < listSize; i++)
{
ClientDisplay3DView *cdv = (ClientDisplay3DView *)cdvFlushList[i];
cdv->FlushView(cbFlush);
}
for (size_t i = 0; i < listSize; i++)
{
ClientDisplay3DView *cdv = (ClientDisplay3DView *)cdvFlushList[i];
cdv->FinalizeFlush(cbFinalize, timeStampOutput->hostTime);
}
[cbFlush enqueue];
[cbFinalize enqueue];
[cbFlush commit];
[cbFinalize commit];
#ifdef DEBUG
[commandQueue insertDebugCaptureBoundary];
#endif
} }
[cb commit];
}
- (void) finalizeFlushMultipleViews:(const std::vector<ClientDisplay3DView *> &)cdvFlushList
{
const size_t listSize = cdvFlushList.size();
id<MTLCommandBuffer> cb = [commandQueue commandBufferWithUnretainedReferences];
for (size_t i = 0; i < listSize; i++)
{
ClientDisplay3DView *cdv = (ClientDisplay3DView *)cdvFlushList[i];
cdv->FinalizeFlush(cb);
}
[cb commit];
} }
@end @end
@ -2082,7 +2082,9 @@
@synthesize _cdv; @synthesize _cdv;
@synthesize presenterObject; @synthesize presenterObject;
@synthesize layerDrawable; @synthesize layerDrawable0;
@synthesize layerDrawable1;
@synthesize layerDrawable2;
- (id) initWithDisplayPresenterObject:(MacMetalDisplayPresenterObject *)thePresenterObject - (id) initWithDisplayPresenterObject:(MacMetalDisplayPresenterObject *)thePresenterObject
{ {
@ -2094,8 +2096,10 @@
_cdv = NULL; _cdv = NULL;
_semDrawable = dispatch_semaphore_create(3); _semDrawable = dispatch_semaphore_create(3);
layerDrawable = nil; _currentDrawable = nil;
_displaySequenceNumber = 0; layerDrawable0 = nil;
layerDrawable1 = nil;
layerDrawable2 = nil;
_displayTexturePair.bufferIndex = 0; _displayTexturePair.bufferIndex = 0;
_displayTexturePair.fetchSequenceNumber = 0; _displayTexturePair.fetchSequenceNumber = 0;
@ -2116,7 +2120,9 @@
- (void)dealloc - (void)dealloc
{ {
[self setLayerDrawable:nil]; [self setLayerDrawable0:nil];
[self setLayerDrawable1:nil];
[self setLayerDrawable2:nil];
dispatch_release(_semDrawable); dispatch_release(_semDrawable);
[_displayTexturePair.main release]; [_displayTexturePair.main release];
@ -2136,82 +2142,133 @@
- (void) renderToDrawableUsingCommandBuffer:(id<MTLCommandBuffer>)cb - (void) renderToDrawableUsingCommandBuffer:(id<MTLCommandBuffer>)cb
{ {
@autoreleasepool dispatch_semaphore_wait(_semDrawable, DISPATCH_TIME_FOREVER);
{
const MetalTexturePair texProcess = [presenterObject texPairProcess]; id<CAMetalDrawable> drawable = [self nextDrawable];
if (texProcess.fetchSequenceNumber >= _displayTexturePair.fetchSequenceNumber)
{
id<MTLTexture> oldTexMain = _displayTexturePair.main;
id<MTLTexture> oldTexTouch = _displayTexturePair.touch;
_displayTexturePair.bufferIndex = texProcess.bufferIndex;
_displayTexturePair.fetchSequenceNumber = texProcess.fetchSequenceNumber;
_displayTexturePair.main = [texProcess.main retain];
_displayTexturePair.touch = [texProcess.touch retain];
[oldTexMain release];
[oldTexTouch release];
}
// Now that everything is set up, go ahead and draw everything.
dispatch_semaphore_wait(_semDrawable, DISPATCH_TIME_FOREVER);
id<CAMetalDrawable> drawable = [self nextDrawable];
if (drawable != nil)
{
[[presenterObject colorAttachment0Desc] setTexture:[drawable texture]];
const MetalRenderFrameInfo mrfi = [presenterObject renderFrameInfo];
[presenterObject renderForCommandBuffer:cb
outputPipelineState:[presenterObject outputDrawablePipeline]
hudPipelineState:[[presenterObject sharedData] hudPipeline]
texDisplays:_displayTexturePair
mrfi:mrfi
doYFlip:NO];
[cb addScheduledHandler:^(id<MTLCommandBuffer> block) {
[presenterObject setRenderBufferState:ClientDisplayBufferState_Reading index:mrfi.renderIndex];
}];
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
[presenterObject renderFinishAtIndex:mrfi.renderIndex];
}];
[self setLayerDrawable:drawable];
}
else
{
dispatch_semaphore_signal(_semDrawable);
}
}
}
- (void) presentDrawableWithCommandBuffer:(id<MTLCommandBuffer>)cb
{
id<CAMetalDrawable> drawable = [self layerDrawable];
if (drawable == nil) if (drawable == nil)
{ {
_currentDrawable = nil;
dispatch_semaphore_signal(_semDrawable);
return;
}
else
{
if ([self layerDrawable0] == nil)
{
[self setLayerDrawable0:drawable];
}
else if ([self layerDrawable1] == nil)
{
[self setLayerDrawable1:drawable];
}
else if ([self layerDrawable2] == nil)
{
[self setLayerDrawable2:drawable];
}
}
id<MTLTexture> texDrawable = [drawable texture];
[[presenterObject colorAttachment0Desc] setTexture:texDrawable];
const MetalTexturePair texProcess = [presenterObject texPairProcess];
id<MTLTexture> oldTexMain = _displayTexturePair.main;
id<MTLTexture> oldTexTouch = _displayTexturePair.touch;
_displayTexturePair.bufferIndex = texProcess.bufferIndex;
_displayTexturePair.fetchSequenceNumber = texProcess.fetchSequenceNumber;
_displayTexturePair.main = [texProcess.main retain];
_displayTexturePair.touch = [texProcess.touch retain];
[oldTexMain release];
[oldTexTouch release];
const MetalRenderFrameInfo mrfi = [presenterObject renderFrameInfo];
[presenterObject renderForCommandBuffer:cb
outputPipelineState:[presenterObject outputDrawablePipeline]
hudPipelineState:[[presenterObject sharedData] hudPipeline]
texDisplays:_displayTexturePair
mrfi:mrfi
doYFlip:NO];
[cb addScheduledHandler:^(id<MTLCommandBuffer> block) {
[presenterObject setRenderBufferState:ClientDisplayBufferState_Reading index:mrfi.renderIndex];
}];
[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)
{
printf("Metal: No drawable was assigned!\n");
return; return;
} }
[cb presentDrawable:drawable]; // Apple's documentation might seem to suggest that [MTLCommandBuffer presentDrawable:atTime:]
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) { // and [MTLDrawable presentAtTime:] inside of a [MTLCommandBuffer addScheduledHandler:] block
[self setLayerDrawable:nil]; // are equivalent. However, much testing has shown that this is NOT the case.
//
// So rather than using [MTLCommandBuffer presentDrawable:atTime:], which causes Metal to
// present the drawable whenever it pleases, we manually call [MTLDrawable presentAtTime] so
// that we can synchronously force the presentation order of the drawables. If we don't do
// this, then Metal may start presenting the drawables in some random order, causing some
// really nasty microstuttering.
[cb addScheduledHandler:^(id<MTLCommandBuffer> block) {
@autoreleasepool
{
[drawable presentAtTime:(CFTimeInterval)outputTime / 1000000000.0];
if (drawable == [self layerDrawable0])
{
[self setLayerDrawable0:nil];
}
else if (drawable == [self layerDrawable1])
{
[self setLayerDrawable1:nil];
}
else if (drawable == [self layerDrawable2])
{
[self setLayerDrawable2:nil];
}
}
dispatch_semaphore_signal(_semDrawable); dispatch_semaphore_signal(_semDrawable);
}]; }];
} }
- (void) renderAndPresentDrawableImmediate - (void) renderAndPresentDrawableImmediate
{ {
id<MTLCommandBuffer> cb = [presenterObject newCommandBuffer]; @autoreleasepool
_cdv->FlushView(cb); {
[cb commit]; id<MTLCommandBuffer> cbFlush = [presenterObject newCommandBuffer];
id<MTLCommandBuffer> cbFinalize = [presenterObject newCommandBuffer];
cb = [presenterObject newCommandBuffer];
_cdv->FinalizeFlush(cb); _cdv->FlushView(cbFlush);
[cb commit]; _cdv->FinalizeFlush(cbFinalize, 0);
[cbFlush enqueue];
[cbFinalize enqueue];
[cbFlush commit];
[cbFinalize commit];
#ifdef DEBUG
[[[presenterObject sharedData] commandQueue] insertDebugCaptureBoundary];
#endif
}
}
- (void) display
{
[self renderAndPresentDrawableImmediate];
} }
@end @end
@ -2541,15 +2598,23 @@ void MacMetalDisplayView::SetViewNeedsFlush()
return; return;
} }
// For every update, ensure that the CVDisplayLink is started so that the update if (this->GetRenderToCALayer())
// will eventually get flushed. {
this->SetAllowViewFlushes(true); this->_presenter->UpdateLayout();
[this->_caLayer setNeedsDisplay];
this->_presenter->UpdateLayout(); [CATransaction flush];
}
OSSpinLockLock(&this->_spinlockViewNeedsFlush); else
this->_viewNeedsFlush = true; {
OSSpinLockUnlock(&this->_spinlockViewNeedsFlush); // For every update, ensure that the CVDisplayLink is started so that the update
// will eventually get flushed.
this->SetAllowViewFlushes(true);
this->_presenter->UpdateLayout();
OSSpinLockLock(&this->_spinlockViewNeedsFlush);
this->_viewNeedsFlush = true;
OSSpinLockUnlock(&this->_spinlockViewNeedsFlush);
}
} }
void MacMetalDisplayView::SetAllowViewFlushes(bool allowFlushes) void MacMetalDisplayView::SetAllowViewFlushes(bool allowFlushes)
@ -2568,9 +2633,9 @@ void MacMetalDisplayView::FlushView(void *userData)
[(DisplayViewMetalLayer *)this->_caLayer renderToDrawableUsingCommandBuffer:(id<MTLCommandBuffer>)userData]; [(DisplayViewMetalLayer *)this->_caLayer renderToDrawableUsingCommandBuffer:(id<MTLCommandBuffer>)userData];
} }
void MacMetalDisplayView::FinalizeFlush(void *userData) void MacMetalDisplayView::FinalizeFlush(void *userData, uint64_t outputTime)
{ {
[(DisplayViewMetalLayer *)this->_caLayer presentDrawableWithCommandBuffer:(id<MTLCommandBuffer>)userData]; [(DisplayViewMetalLayer *)this->_caLayer presentDrawableWithCommandBuffer:(id<MTLCommandBuffer>)userData outputTime:outputTime];
} }
void MacMetalDisplayView::FlushAndFinalizeImmediate() void MacMetalDisplayView::FlushAndFinalizeImmediate()

View File

@ -134,7 +134,7 @@ public:
// Client view interface // Client view interface
virtual void FlushView(void *userData); virtual void FlushView(void *userData);
virtual void FinalizeFlush(void *userData); virtual void FinalizeFlush(void *userData, uint64_t outputTime);
}; };
#endif // _MAC_OGLDISPLAYOUTPUT_H_ #endif // _MAC_OGLDISPLAYOUTPUT_H_

View File

@ -552,7 +552,7 @@ void MacOGLDisplayView::FlushView(void *userData)
CGLUnlockContext(context); CGLUnlockContext(context);
} }
void MacOGLDisplayView::FinalizeFlush(void *userData) void MacOGLDisplayView::FinalizeFlush(void *userData, uint64_t outputTime)
{ {
CGLContextObj context = ((MacOGLDisplayPresenter *)this->_presenter)->GetContext(); CGLContextObj context = ((MacOGLDisplayPresenter *)this->_presenter)->GetContext();