Cocoa Port: Fix a bug in Metal display views where the internal V-sync would cause the total frame rate to be divided amongst multiple visible display views.
This commit is contained in:
parent
5c85bcd732
commit
5d384f9eae
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2017 DeSmuME team
|
||||
Copyright (C) 2017-2018 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -1290,12 +1290,23 @@ void ClientDisplayViewInterface::SetAllowViewFlushes(bool allowFlushes)
|
|||
this->_allowViewFlushes = allowFlushes;
|
||||
}
|
||||
|
||||
void ClientDisplayViewInterface::FlushView()
|
||||
void ClientDisplayViewInterface::FlushView(void *userData)
|
||||
{
|
||||
// Do nothing. This is implementation dependent.
|
||||
this->_viewNeedsFlush = false;
|
||||
}
|
||||
|
||||
void ClientDisplayViewInterface::FinalizeFlush(void *userData)
|
||||
{
|
||||
// Do nothing. This is implementation dependent.
|
||||
}
|
||||
|
||||
void ClientDisplayViewInterface::FlushAndFinalizeImmediate()
|
||||
{
|
||||
this->FlushView(NULL);
|
||||
this->FinalizeFlush(NULL);
|
||||
}
|
||||
|
||||
// Touch screen input handling
|
||||
void ClientDisplayViewInterface::GetNDSPoint(const ClientDisplayPresenterProperties &props,
|
||||
const double logicalClientWidth, const double logicalClientHeight,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2017 DeSmuME team
|
||||
Copyright (C) 2017-2018 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -355,7 +355,9 @@ public:
|
|||
bool GetAllowViewFlushes() const;
|
||||
virtual void SetAllowViewFlushes(bool allowFlushes);
|
||||
|
||||
virtual void FlushView();
|
||||
virtual void FlushView(void *userData);
|
||||
virtual void FinalizeFlush(void *userData);
|
||||
virtual void FlushAndFinalizeImmediate();
|
||||
|
||||
// Touch screen input handling
|
||||
void GetNDSPoint(const ClientDisplayPresenterProperties &props,
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <mach/semaphore.h>
|
||||
#include <mach/sync_policy.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#import "cocoa_util.h"
|
||||
#include "../../GPU.h"
|
||||
|
@ -57,6 +58,7 @@ enum ClientDisplayBufferState
|
|||
};
|
||||
|
||||
class GPUEventHandlerOSX;
|
||||
class ClientDisplay3DView;
|
||||
|
||||
#ifdef ENABLE_SHARED_FETCH_OBJECT
|
||||
|
||||
|
@ -102,7 +104,10 @@ typedef std::map<CGDirectDisplayID, int64_t> DisplayLinkFlushTimeLimitMap;
|
|||
- (void) incrementViewsUsingDirectToCPUFiltering;
|
||||
- (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) displayLinkStartUsingID:(CGDirectDisplayID)displayID;
|
||||
- (void) displayLinkListUpdate;
|
||||
|
|
|
@ -24,16 +24,16 @@
|
|||
#include "../../rasterize.h"
|
||||
|
||||
#ifdef MAC_OS_X_VERSION_10_7
|
||||
#include "../../OGLRender_3_2.h"
|
||||
#include "../../OGLRender_3_2.h"
|
||||
#else
|
||||
#include "../../OGLRender.h"
|
||||
#include "../../OGLRender.h"
|
||||
#endif
|
||||
|
||||
#include <OpenGL/OpenGL.h>
|
||||
#import "userinterface/MacOGLDisplayView.h"
|
||||
|
||||
#ifdef ENABLE_APPLE_METAL
|
||||
#import "userinterface/MacMetalDisplayView.h"
|
||||
#import "userinterface/MacMetalDisplayView.h"
|
||||
#endif
|
||||
|
||||
#ifdef BOOL
|
||||
|
@ -1219,6 +1219,8 @@ public:
|
|||
CGDirectDisplayID displayID = CVDisplayLinkGetCurrentCGDisplay(displayLink);
|
||||
bool didFlushOccur = false;
|
||||
|
||||
std::vector<ClientDisplay3DView *> cdvFlushList;
|
||||
|
||||
if (currentRWLock != NULL)
|
||||
{
|
||||
pthread_rwlock_rdlock(currentRWLock);
|
||||
|
@ -1234,13 +1236,21 @@ public:
|
|||
|
||||
if (cdv->GetViewNeedsFlush())
|
||||
{
|
||||
cdv->FlushView();
|
||||
didFlushOccur = true;
|
||||
cdvFlushList.push_back(cdv);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const size_t listSize = cdvFlushList.size();
|
||||
|
||||
if (listSize > 0)
|
||||
{
|
||||
[self flushMultipleViews:cdvFlushList];
|
||||
[self finalizeFlushMultipleViews:cdvFlushList];
|
||||
didFlushOccur = true;
|
||||
}
|
||||
|
||||
if (currentRWLock != NULL)
|
||||
{
|
||||
pthread_rwlock_unlock(currentRWLock);
|
||||
|
@ -1257,6 +1267,28 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
- (void) flushMultipleViews:(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->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);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) displayLinkStartUsingID:(CGDirectDisplayID)displayID
|
||||
{
|
||||
CVDisplayLinkRef displayLink = NULL;
|
||||
|
|
|
@ -2128,7 +2128,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
|
|||
// If localOGLContext isn't nil, then we will not assign the local layer
|
||||
// directly to the view, since the OpenGL context will already be what
|
||||
// is assigned.
|
||||
cdv->FlushView();
|
||||
cdv->FlushAndFinalizeImmediate();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2144,7 +2144,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
|
|||
|
||||
if (isMetalLayer)
|
||||
{
|
||||
cdv->FlushView();
|
||||
cdv->FlushAndFinalizeImmediate();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2226,12 +2226,12 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
|
|||
|
||||
- (void)updateLayer
|
||||
{
|
||||
[self clientDisplayView]->FlushView();
|
||||
[self clientDisplayView]->FlushAndFinalizeImmediate();
|
||||
}
|
||||
|
||||
- (void)drawRect:(NSRect)dirtyRect
|
||||
{
|
||||
[self clientDisplayView]->FlushView();
|
||||
[self clientDisplayView]->FlushAndFinalizeImmediate();
|
||||
}
|
||||
|
||||
- (void)setFrame:(NSRect)rect
|
||||
|
|
|
@ -168,6 +168,9 @@ 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;
|
||||
|
||||
@end
|
||||
|
||||
@interface MacMetalDisplayPresenterObject : NSObject
|
||||
|
@ -261,13 +264,17 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
|
|||
MacDisplayLayeredView *_cdv;
|
||||
MacMetalDisplayPresenterObject *presenterObject;
|
||||
dispatch_semaphore_t _semDrawable;
|
||||
id<CAMetalDrawable> layerDrawable;
|
||||
}
|
||||
|
||||
@property (readonly, nonatomic) MacMetalDisplayPresenterObject *presenterObject;
|
||||
@property (retain) id<CAMetalDrawable> layerDrawable;
|
||||
|
||||
- (id) initWithDisplayPresenterObject:(MacMetalDisplayPresenterObject *)thePresenterObject;
|
||||
- (void) setupLayer;
|
||||
- (void) renderToDrawable;
|
||||
- (void) renderToDrawableUsingCommandBuffer:(id<MTLCommandBuffer>)cb;
|
||||
- (void) presentDrawableWithCommandBuffer:(id<MTLCommandBuffer>)cb;
|
||||
- (void) renderAndPresentDrawableImmediate;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -360,7 +367,9 @@ public:
|
|||
virtual void SetAllowViewFlushes(bool allowFlushes);
|
||||
|
||||
// Client view interface
|
||||
virtual void FlushView();
|
||||
virtual void FlushView(void *userData);
|
||||
virtual void FinalizeFlush(void *userData);
|
||||
virtual void FlushAndFinalizeImmediate();
|
||||
};
|
||||
|
||||
#pragma mark -
|
||||
|
|
|
@ -150,7 +150,7 @@
|
|||
idxBufferPtr[j+5] = k+0;
|
||||
}
|
||||
|
||||
id<MTLCommandBuffer> cb = [_fetchCommandQueue commandBufferWithUnretainedReferences];;
|
||||
id<MTLCommandBuffer> cb = [_fetchCommandQueue commandBufferWithUnretainedReferences];
|
||||
id<MTLBlitCommandEncoder> bce = [cb blitCommandEncoder];
|
||||
|
||||
[bce copyFromBuffer:tempHUDIndexBuffer
|
||||
|
@ -383,8 +383,11 @@
|
|||
#ifdef MAC_OS_X_VERSION_10_13
|
||||
if (_isSharedBufferTextureSupported)
|
||||
{
|
||||
_texDisplayFetchNative[NDSDisplayID_Main][i] = [_bufDisplayFetchNative[NDSDisplayID_Main][i] newTextureWithDescriptor:newTexDisplayNativeDesc offset:0 bytesPerRow:_nativeLineSize];
|
||||
_texDisplayFetchNative[NDSDisplayID_Touch][i] = [_bufDisplayFetchNative[NDSDisplayID_Touch][i] newTextureWithDescriptor:newTexDisplayNativeDesc offset:0 bytesPerRow:_nativeLineSize];
|
||||
if (@available(macOS 10_13, *))
|
||||
{
|
||||
_texDisplayFetchNative[NDSDisplayID_Main][i] = [_bufDisplayFetchNative[NDSDisplayID_Main][i] newTextureWithDescriptor:newTexDisplayNativeDesc offset:0 bytesPerRow:_nativeLineSize];
|
||||
_texDisplayFetchNative[NDSDisplayID_Touch][i] = [_bufDisplayFetchNative[NDSDisplayID_Touch][i] newTextureWithDescriptor:newTexDisplayNativeDesc offset:0 bytesPerRow:_nativeLineSize];
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -409,8 +412,11 @@
|
|||
#ifdef MAC_OS_X_VERSION_10_13
|
||||
if (_isSharedBufferTextureSupported)
|
||||
{
|
||||
_texDisplayFetchCustom[NDSDisplayID_Main][i] = [_bufDisplayFetchCustom[NDSDisplayID_Main][i] newTextureWithDescriptor:newTexDisplayCustomDesc offset:0 bytesPerRow:_customLineSize];
|
||||
_texDisplayFetchCustom[NDSDisplayID_Touch][i] = [_bufDisplayFetchCustom[NDSDisplayID_Touch][i] newTextureWithDescriptor:newTexDisplayCustomDesc offset:0 bytesPerRow:_customLineSize];
|
||||
if (@available(macOS 10_13, *))
|
||||
{
|
||||
_texDisplayFetchCustom[NDSDisplayID_Main][i] = [_bufDisplayFetchCustom[NDSDisplayID_Main][i] newTextureWithDescriptor:newTexDisplayCustomDesc offset:0 bytesPerRow:_customLineSize];
|
||||
_texDisplayFetchCustom[NDSDisplayID_Touch][i] = [_bufDisplayFetchCustom[NDSDisplayID_Touch][i] newTextureWithDescriptor:newTexDisplayCustomDesc offset:0 bytesPerRow:_customLineSize];
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -731,6 +737,34 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (void) flushMultipleViews:(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->FlushView(cb);
|
||||
}
|
||||
|
||||
[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
|
||||
|
||||
@implementation MacMetalDisplayPresenterObject
|
||||
|
@ -2142,6 +2176,7 @@
|
|||
|
||||
@synthesize _cdv;
|
||||
@synthesize presenterObject;
|
||||
@synthesize layerDrawable;
|
||||
|
||||
- (id) initWithDisplayPresenterObject:(MacMetalDisplayPresenterObject *)thePresenterObject
|
||||
{
|
||||
|
@ -2153,6 +2188,7 @@
|
|||
|
||||
_cdv = NULL;
|
||||
_semDrawable = dispatch_semaphore_create(3);
|
||||
layerDrawable = nil;
|
||||
|
||||
presenterObject = thePresenterObject;
|
||||
if (thePresenterObject != nil)
|
||||
|
@ -2168,6 +2204,7 @@
|
|||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self setLayerDrawable:nil];
|
||||
dispatch_release(_semDrawable);
|
||||
|
||||
[super dealloc];
|
||||
|
@ -2182,46 +2219,37 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (void) renderToDrawable
|
||||
- (void) renderToDrawableUsingCommandBuffer:(id<MTLCommandBuffer>)cb
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
// Now that everything is set up, go ahead and draw everything.
|
||||
dispatch_semaphore_wait(_semDrawable, DISPATCH_TIME_FOREVER);
|
||||
id<CAMetalDrawable> layerDrawable = [[self nextDrawable] retain];
|
||||
id<CAMetalDrawable> drawable = [self nextDrawable];
|
||||
|
||||
if (layerDrawable != nil)
|
||||
if (drawable != nil)
|
||||
{
|
||||
[[presenterObject colorAttachment0Desc] setTexture:[layerDrawable texture]];
|
||||
id<MTLCommandBuffer> cbRender = [presenterObject newCommandBuffer];
|
||||
id<MTLCommandBuffer> cbPresent = [presenterObject newCommandBuffer];
|
||||
[[presenterObject colorAttachment0Desc] setTexture:[drawable texture]];
|
||||
|
||||
const MetalTexturePair texProcess = [presenterObject texPairProcess];
|
||||
const MetalRenderFrameInfo mrfi = [presenterObject renderFrameInfo];
|
||||
|
||||
[presenterObject renderForCommandBuffer:cbRender
|
||||
[presenterObject renderForCommandBuffer:cb
|
||||
outputPipelineState:[presenterObject outputDrawablePipeline]
|
||||
hudPipelineState:[[presenterObject sharedData] hudPipeline]
|
||||
texDisplays:texProcess
|
||||
mrfi:mrfi
|
||||
doYFlip:NO];
|
||||
|
||||
[cbRender addScheduledHandler:^(id<MTLCommandBuffer> block) {
|
||||
[cb addScheduledHandler:^(id<MTLCommandBuffer> block) {
|
||||
[presenterObject setRenderBufferState:ClientDisplayBufferState_Reading index:mrfi.renderIndex];
|
||||
}];
|
||||
|
||||
[cbRender addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
||||
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
||||
[presenterObject renderFinishAtIndex:mrfi.renderIndex];
|
||||
}];
|
||||
|
||||
[cbPresent presentDrawable:layerDrawable];
|
||||
[cbPresent addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
||||
[layerDrawable release];
|
||||
dispatch_semaphore_signal(_semDrawable);
|
||||
}];
|
||||
|
||||
[cbRender commit];
|
||||
[cbPresent commit];
|
||||
[self setLayerDrawable:drawable];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2230,6 +2258,32 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (void) presentDrawableWithCommandBuffer:(id<MTLCommandBuffer>)cb
|
||||
{
|
||||
id<CAMetalDrawable> drawable = [self layerDrawable];
|
||||
if (drawable == nil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
[cb presentDrawable:drawable];
|
||||
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
||||
[self setLayerDrawable:nil];
|
||||
dispatch_semaphore_signal(_semDrawable);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void) renderAndPresentDrawableImmediate
|
||||
{
|
||||
id<MTLCommandBuffer> cb = [presenterObject newCommandBuffer];
|
||||
_cdv->FlushView(cb);
|
||||
[cb commit];
|
||||
|
||||
cb = [presenterObject newCommandBuffer];
|
||||
_cdv->FinalizeFlush(cb);
|
||||
[cb commit];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
@ -2575,13 +2629,23 @@ void MacMetalDisplayView::SetAllowViewFlushes(bool allowFlushes)
|
|||
[sharedData displayLinkStartUsingID:displayID];
|
||||
}
|
||||
|
||||
void MacMetalDisplayView::FlushView()
|
||||
void MacMetalDisplayView::FlushView(void *userData)
|
||||
{
|
||||
OSSpinLockLock(&this->_spinlockViewNeedsFlush);
|
||||
this->_viewNeedsFlush = false;
|
||||
OSSpinLockUnlock(&this->_spinlockViewNeedsFlush);
|
||||
|
||||
[(DisplayViewMetalLayer *)this->_caLayer renderToDrawable];
|
||||
[(DisplayViewMetalLayer *)this->_caLayer renderToDrawableUsingCommandBuffer:(id<MTLCommandBuffer>)userData];
|
||||
}
|
||||
|
||||
void MacMetalDisplayView::FinalizeFlush(void *userData)
|
||||
{
|
||||
[(DisplayViewMetalLayer *)this->_caLayer presentDrawableWithCommandBuffer:(id<MTLCommandBuffer>)userData];
|
||||
}
|
||||
|
||||
void MacMetalDisplayView::FlushAndFinalizeImmediate()
|
||||
{
|
||||
[(DisplayViewMetalLayer *)this->_caLayer renderAndPresentDrawableImmediate];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
|
|
@ -133,7 +133,8 @@ public:
|
|||
virtual void SetUseVerticalSync(const bool useVerticalSync);
|
||||
|
||||
// Client view interface
|
||||
virtual void FlushView();
|
||||
virtual void FlushView(void *userData);
|
||||
virtual void FinalizeFlush(void *userData);
|
||||
};
|
||||
|
||||
#endif // _MAC_OGLDISPLAYOUTPUT_H_
|
||||
|
|
|
@ -538,7 +538,7 @@ void MacOGLDisplayView::SetUseVerticalSync(const bool useVerticalSync)
|
|||
CGLUnlockContext(context);
|
||||
}
|
||||
|
||||
void MacOGLDisplayView::FlushView()
|
||||
void MacOGLDisplayView::FlushView(void *userData)
|
||||
{
|
||||
OSSpinLockLock(&this->_spinlockViewNeedsFlush);
|
||||
this->_viewNeedsFlush = false;
|
||||
|
@ -549,6 +549,15 @@ void MacOGLDisplayView::FlushView()
|
|||
CGLLockContext(context);
|
||||
CGLSetCurrentContext(context);
|
||||
((MacOGLDisplayPresenter *)this->_presenter)->RenderFrameOGL(false);
|
||||
CGLUnlockContext(context);
|
||||
}
|
||||
|
||||
void MacOGLDisplayView::FinalizeFlush(void *userData)
|
||||
{
|
||||
CGLContextObj context = ((MacOGLDisplayPresenter *)this->_presenter)->GetContext();
|
||||
|
||||
CGLLockContext(context);
|
||||
CGLSetCurrentContext(context);
|
||||
CGLFlushDrawable(context);
|
||||
CGLUnlockContext(context);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue