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:
parent
1f9b9e02a4
commit
4f543aa8ca
|
@ -1292,7 +1292,7 @@ void ClientDisplayViewInterface::FlushView(void *userData)
|
|||
this->_viewNeedsFlush = false;
|
||||
}
|
||||
|
||||
void ClientDisplayViewInterface::FinalizeFlush(void *userData)
|
||||
void ClientDisplayViewInterface::FinalizeFlush(void *userData, uint64_t outputTime)
|
||||
{
|
||||
// Do nothing. This is implementation dependent.
|
||||
}
|
||||
|
@ -1300,7 +1300,7 @@ void ClientDisplayViewInterface::FinalizeFlush(void *userData)
|
|||
void ClientDisplayViewInterface::FlushAndFinalizeImmediate()
|
||||
{
|
||||
this->FlushView(NULL);
|
||||
this->FinalizeFlush(NULL);
|
||||
this->FinalizeFlush(NULL, 0);
|
||||
}
|
||||
|
||||
// Touch screen input handling
|
||||
|
|
|
@ -356,7 +356,7 @@ public:
|
|||
virtual void SetAllowViewFlushes(bool allowFlushes);
|
||||
|
||||
virtual void FlushView(void *userData);
|
||||
virtual void FinalizeFlush(void *userData);
|
||||
virtual void FinalizeFlush(void *userData, uint64_t outputTime);
|
||||
virtual void FlushAndFinalizeImmediate();
|
||||
|
||||
// Touch screen input handling
|
||||
|
|
|
@ -105,9 +105,8 @@ typedef std::map<CGDirectDisplayID, int64_t> DisplayLinkFlushTimeLimitMap;
|
|||
- (void) decrementViewsUsingDirectToCPUFiltering;
|
||||
- (void) pushVideoDataToAllDisplayViews;
|
||||
|
||||
- (void) flushAllDisplaysOnDisplayLink:(CVDisplayLinkRef)displayLink timeStamp:(const CVTimeStamp *)timeStamp;
|
||||
- (void) flushMultipleViews:(const std::vector<ClientDisplay3DView *> &)cdvFlushList;
|
||||
- (void) finalizeFlushMultipleViews:(const std::vector<ClientDisplay3DView *> &)cdvFlushList;
|
||||
- (void) flushAllDisplaysOnDisplayLink:(CVDisplayLinkRef)displayLink timeStampNow:(const CVTimeStamp *)timeStampNow timeStampOutput:(const CVTimeStamp *)timeStampOutput;
|
||||
- (void) flushMultipleViews:(const std::vector<ClientDisplay3DView *> &)cdvFlushList timeStampNow:(const CVTimeStamp *)timeStampNow timeStampOutput:(const CVTimeStamp *)timeStampOutput;
|
||||
|
||||
- (void) displayLinkStartUsingID:(CGDirectDisplayID)displayID;
|
||||
- (void) displayLinkListUpdate;
|
||||
|
|
|
@ -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;
|
||||
CGDirectDisplayID displayID = CVDisplayLinkGetCurrentCGDisplay(displayLink);
|
||||
|
@ -1415,8 +1415,7 @@ public:
|
|||
|
||||
if (listSize > 0)
|
||||
{
|
||||
[self flushMultipleViews:cdvFlushList];
|
||||
[self finalizeFlushMultipleViews:cdvFlushList];
|
||||
[self flushMultipleViews:cdvFlushList timeStampNow:timeStampNow timeStampOutput:timeStampOutput];
|
||||
didFlushOccur = true;
|
||||
}
|
||||
|
||||
|
@ -1428,15 +1427,15 @@ public:
|
|||
if (didFlushOccur)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
- (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();
|
||||
|
||||
|
@ -1445,16 +1444,11 @@ public:
|
|||
ClientDisplay3DView *cdv = (ClientDisplay3DView *)cdvFlushList[i];
|
||||
cdv->FlushView(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) finalizeFlushMultipleViews:(const std::vector<ClientDisplay3DView *> &)cdvFlushList
|
||||
{
|
||||
const size_t listSize = cdvFlushList.size();
|
||||
|
||||
for (size_t i = 0; i < listSize; i++)
|
||||
{
|
||||
ClientDisplay3DView *cdv = (ClientDisplay3DView *)cdvFlushList[i];
|
||||
cdv->FinalizeFlush(NULL);
|
||||
cdv->FinalizeFlush(NULL, timeStampOutput->hostTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1768,7 +1762,7 @@ CVReturn MacDisplayLinkCallback(CVDisplayLinkRef displayLink,
|
|||
void *displayLinkContext)
|
||||
{
|
||||
MacClientSharedObject *sharedData = (MacClientSharedObject *)displayLinkContext;
|
||||
[sharedData flushAllDisplaysOnDisplayLink:displayLink timeStamp:inNow];
|
||||
[sharedData flushAllDisplaysOnDisplayLink:displayLink timeStampNow:inNow timeStampOutput:inOutputTime];
|
||||
|
||||
return kCVReturnSuccess;
|
||||
}
|
||||
|
|
|
@ -2142,13 +2142,13 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
|
|||
[self setLayer:localLayer];
|
||||
[self setWantsLayer:YES];
|
||||
|
||||
if (isMetalLayer)
|
||||
if (cdv->GetRenderToCALayer())
|
||||
{
|
||||
cdv->FlushAndFinalizeImmediate();
|
||||
[localLayer setNeedsDisplay];
|
||||
}
|
||||
else
|
||||
{
|
||||
[localLayer setNeedsDisplay];
|
||||
cdv->FlushAndFinalizeImmediate();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#endif
|
||||
|
||||
#define METAL_FETCH_BUFFER_COUNT 3
|
||||
#define RENDER_BUFFER_COUNT 6
|
||||
#define RENDER_BUFFER_COUNT 12
|
||||
|
||||
class MacMetalFetchObject;
|
||||
class MacMetalDisplayPresenter;
|
||||
|
@ -166,8 +166,7 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
|
|||
- (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) flushMultipleViews:(const std::vector<ClientDisplay3DView *> &)cdvFlushList;;
|
||||
- (void) finalizeFlushMultipleViews:(const std::vector<ClientDisplay3DView *> &)cdvFlushList;
|
||||
- (void) flushMultipleViews:(const std::vector<ClientDisplay3DView *> &)cdvFlushList timeStampNow:(const CVTimeStamp *)timeStampNow timeStampOutput:(const CVTimeStamp *)timeStampOutput;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -262,18 +261,23 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
|
|||
MacDisplayLayeredView *_cdv;
|
||||
MacMetalDisplayPresenterObject *presenterObject;
|
||||
dispatch_semaphore_t _semDrawable;
|
||||
id<CAMetalDrawable> layerDrawable;
|
||||
id<CAMetalDrawable> _currentDrawable;
|
||||
id<CAMetalDrawable> layerDrawable0;
|
||||
id<CAMetalDrawable> layerDrawable1;
|
||||
id<CAMetalDrawable> layerDrawable2;
|
||||
|
||||
MetalTexturePair _displayTexturePair;
|
||||
size_t _displaySequenceNumber;
|
||||
}
|
||||
|
||||
@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;
|
||||
- (void) setupLayer;
|
||||
- (void) renderToDrawableUsingCommandBuffer:(id<MTLCommandBuffer>)cb;
|
||||
- (void) presentDrawableWithCommandBuffer:(id<MTLCommandBuffer>)cb;
|
||||
- (void) presentDrawableWithCommandBuffer:(id<MTLCommandBuffer>)cb outputTime:(uint64_t)outputTime;
|
||||
- (void) renderAndPresentDrawableImmediate;
|
||||
|
||||
@end
|
||||
|
@ -368,7 +372,7 @@ public:
|
|||
|
||||
// Client view interface
|
||||
virtual void FlushView(void *userData);
|
||||
virtual void FinalizeFlush(void *userData);
|
||||
virtual void FinalizeFlush(void *userData, uint64_t outputTime);
|
||||
virtual void FlushAndFinalizeImmediate();
|
||||
};
|
||||
|
||||
|
|
|
@ -428,10 +428,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
id<MTLComputeCommandEncoder> cce = [cb computeCommandEncoder];
|
||||
|
||||
if (currentDisplayInfo.needApplyMasterBrightness[NDSDisplayID_Main] || currentDisplayInfo.needApplyMasterBrightness[NDSDisplayID_Touch])
|
||||
{
|
||||
id<MTLComputeCommandEncoder> cce = [cb computeCommandEncoder];
|
||||
|
||||
if (currentDisplayInfo.colorFormat == NDSColorFormat_BGR555_Rev)
|
||||
{
|
||||
[cce setComputePipelineState:_fetch555Pipeline];
|
||||
|
@ -505,9 +505,12 @@
|
|||
targetTexPair.touch = _texDisplayPostprocessCustom[NDSDisplayID_Touch][index];
|
||||
}
|
||||
}
|
||||
|
||||
[cce endEncoding];
|
||||
}
|
||||
else if (currentDisplayInfo.colorFormat != NDSColorFormat_BGR888_Rev)
|
||||
{
|
||||
id<MTLComputeCommandEncoder> cce = [cb computeCommandEncoder];
|
||||
bool isPipelineStateSet = false;
|
||||
|
||||
if (currentDisplayInfo.colorFormat == NDSColorFormat_BGR555_Rev)
|
||||
|
@ -569,9 +572,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[cce endEncoding];
|
||||
[cce endEncoding];
|
||||
}
|
||||
}
|
||||
|
||||
return targetTexPair;
|
||||
|
@ -580,7 +583,6 @@
|
|||
- (void) fetchFromBufferIndex:(const u8)index
|
||||
{
|
||||
id<MTLCommandBuffer> cb = [_fetchCommandQueue commandBufferWithUnretainedReferences];
|
||||
[cb enqueue];
|
||||
|
||||
semaphore_wait([self semaphoreFramebufferPageAtIndex:index]);
|
||||
[self setFramebufferState:ClientDisplayBufferState_Reading index:index];
|
||||
|
@ -591,16 +593,6 @@
|
|||
[self setBceFetch:nil];
|
||||
[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];
|
||||
[newTexPair.main retain];
|
||||
[newTexPair.touch retain];
|
||||
|
@ -610,6 +602,9 @@
|
|||
[self setTexPairFetch:newTexPair];
|
||||
[oldTexPair.main release];
|
||||
[oldTexPair.touch release];
|
||||
|
||||
[self setFramebufferState:ClientDisplayBufferState_Idle index:index];
|
||||
semaphore_signal([self semaphoreFramebufferPageAtIndex:index]);
|
||||
}];
|
||||
|
||||
[cb commit];
|
||||
|
@ -656,32 +651,37 @@
|
|||
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();
|
||||
id<MTLCommandBuffer> cb = [commandQueue commandBufferWithUnretainedReferences];
|
||||
|
||||
for (size_t i = 0; i < listSize; i++)
|
||||
@autoreleasepool
|
||||
{
|
||||
ClientDisplay3DView *cdv = (ClientDisplay3DView *)cdvFlushList[i];
|
||||
cdv->FlushView(cb);
|
||||
id<MTLCommandBuffer> cbFlush = [commandQueue commandBufferWithUnretainedReferences];
|
||||
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
|
||||
|
@ -2082,7 +2082,9 @@
|
|||
|
||||
@synthesize _cdv;
|
||||
@synthesize presenterObject;
|
||||
@synthesize layerDrawable;
|
||||
@synthesize layerDrawable0;
|
||||
@synthesize layerDrawable1;
|
||||
@synthesize layerDrawable2;
|
||||
|
||||
- (id) initWithDisplayPresenterObject:(MacMetalDisplayPresenterObject *)thePresenterObject
|
||||
{
|
||||
|
@ -2094,8 +2096,10 @@
|
|||
|
||||
_cdv = NULL;
|
||||
_semDrawable = dispatch_semaphore_create(3);
|
||||
layerDrawable = nil;
|
||||
_displaySequenceNumber = 0;
|
||||
_currentDrawable = nil;
|
||||
layerDrawable0 = nil;
|
||||
layerDrawable1 = nil;
|
||||
layerDrawable2 = nil;
|
||||
|
||||
_displayTexturePair.bufferIndex = 0;
|
||||
_displayTexturePair.fetchSequenceNumber = 0;
|
||||
|
@ -2116,7 +2120,9 @@
|
|||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self setLayerDrawable:nil];
|
||||
[self setLayerDrawable0:nil];
|
||||
[self setLayerDrawable1:nil];
|
||||
[self setLayerDrawable2:nil];
|
||||
dispatch_release(_semDrawable);
|
||||
|
||||
[_displayTexturePair.main release];
|
||||
|
@ -2136,82 +2142,133 @@
|
|||
|
||||
- (void) renderToDrawableUsingCommandBuffer:(id<MTLCommandBuffer>)cb
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
const MetalTexturePair texProcess = [presenterObject texPairProcess];
|
||||
dispatch_semaphore_wait(_semDrawable, DISPATCH_TIME_FOREVER);
|
||||
|
||||
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];
|
||||
id<CAMetalDrawable> drawable = [self nextDrawable];
|
||||
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;
|
||||
}
|
||||
|
||||
[cb presentDrawable:drawable];
|
||||
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
||||
[self setLayerDrawable:nil];
|
||||
// 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.
|
||||
//
|
||||
// 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);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void) renderAndPresentDrawableImmediate
|
||||
{
|
||||
id<MTLCommandBuffer> cb = [presenterObject newCommandBuffer];
|
||||
_cdv->FlushView(cb);
|
||||
[cb commit];
|
||||
@autoreleasepool
|
||||
{
|
||||
id<MTLCommandBuffer> cbFlush = [presenterObject newCommandBuffer];
|
||||
id<MTLCommandBuffer> cbFinalize = [presenterObject newCommandBuffer];
|
||||
|
||||
cb = [presenterObject newCommandBuffer];
|
||||
_cdv->FinalizeFlush(cb);
|
||||
[cb commit];
|
||||
_cdv->FlushView(cbFlush);
|
||||
_cdv->FinalizeFlush(cbFinalize, 0);
|
||||
|
||||
[cbFlush enqueue];
|
||||
[cbFinalize enqueue];
|
||||
|
||||
[cbFlush commit];
|
||||
[cbFinalize commit];
|
||||
|
||||
#ifdef DEBUG
|
||||
[[[presenterObject sharedData] commandQueue] insertDebugCaptureBoundary];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
- (void) display
|
||||
{
|
||||
[self renderAndPresentDrawableImmediate];
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -2541,15 +2598,23 @@ void MacMetalDisplayView::SetViewNeedsFlush()
|
|||
return;
|
||||
}
|
||||
|
||||
// For every update, ensure that the CVDisplayLink is started so that the update
|
||||
// will eventually get flushed.
|
||||
this->SetAllowViewFlushes(true);
|
||||
if (this->GetRenderToCALayer())
|
||||
{
|
||||
this->_presenter->UpdateLayout();
|
||||
[this->_caLayer setNeedsDisplay];
|
||||
[CATransaction flush];
|
||||
}
|
||||
else
|
||||
{
|
||||
// For every update, ensure that the CVDisplayLink is started so that the update
|
||||
// will eventually get flushed.
|
||||
this->SetAllowViewFlushes(true);
|
||||
this->_presenter->UpdateLayout();
|
||||
|
||||
this->_presenter->UpdateLayout();
|
||||
|
||||
OSSpinLockLock(&this->_spinlockViewNeedsFlush);
|
||||
this->_viewNeedsFlush = true;
|
||||
OSSpinLockUnlock(&this->_spinlockViewNeedsFlush);
|
||||
OSSpinLockLock(&this->_spinlockViewNeedsFlush);
|
||||
this->_viewNeedsFlush = true;
|
||||
OSSpinLockUnlock(&this->_spinlockViewNeedsFlush);
|
||||
}
|
||||
}
|
||||
|
||||
void MacMetalDisplayView::SetAllowViewFlushes(bool allowFlushes)
|
||||
|
@ -2568,9 +2633,9 @@ void MacMetalDisplayView::FlushView(void *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()
|
||||
|
|
|
@ -134,7 +134,7 @@ public:
|
|||
|
||||
// Client view interface
|
||||
virtual void FlushView(void *userData);
|
||||
virtual void FinalizeFlush(void *userData);
|
||||
virtual void FinalizeFlush(void *userData, uint64_t outputTime);
|
||||
};
|
||||
|
||||
#endif // _MAC_OGLDISPLAYOUTPUT_H_
|
||||
|
|
|
@ -552,7 +552,7 @@ void MacOGLDisplayView::FlushView(void *userData)
|
|||
CGLUnlockContext(context);
|
||||
}
|
||||
|
||||
void MacOGLDisplayView::FinalizeFlush(void *userData)
|
||||
void MacOGLDisplayView::FinalizeFlush(void *userData, uint64_t outputTime)
|
||||
{
|
||||
CGLContextObj context = ((MacOGLDisplayPresenter *)this->_presenter)->GetContext();
|
||||
|
||||
|
|
Loading…
Reference in New Issue