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;
|
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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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_
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue