Cocoa Port: Replace all POSIX named semaphores with Mach semaphores and GCD semaphores, which are both faster than POSIX named semaphores.

This commit is contained in:
rogerman 2017-12-08 11:49:49 -08:00
parent 1e36b36bef
commit cd2f75e43a
7 changed files with 188 additions and 273 deletions

View File

@ -19,12 +19,20 @@
#import <CoreVideo/CoreVideo.h>
#include <pthread.h>
#include <libkern/OSAtomic.h>
#include <semaphore.h>
#include <mach/task.h>
#include <mach/semaphore.h>
#include <mach/sync_policy.h>
#include <map>
#import "cocoa_util.h"
#include "../../GPU.h"
// This symbol only exists in the kernel headers, but not in the user headers.
// Manually define the symbol here, since we will be Mach semaphores in the user-space.
#ifndef SYNC_POLICY_PREPOST
#define SYNC_POLICY_PREPOST 0x4
#endif
#ifdef BOOL
#undef BOOL
#endif
@ -49,7 +57,8 @@ typedef std::map<CGDirectDisplayID, int64_t> DisplayLinkFlushTimeLimitMap;
@interface MacClientSharedObject : NSObject
{
GPUClientFetchObject *GPUFetchObject;
sem_t *_semFramebuffer[2];
task_t _taskEmulationLoop;
semaphore_t _semFramebuffer[2];
pthread_rwlock_t *_rwlockOutputList;
pthread_mutex_t _mutexDisplayLinkLists;
NSMutableArray *_cdsOutputList;
@ -69,7 +78,10 @@ typedef std::map<CGDirectDisplayID, int64_t> DisplayLinkFlushTimeLimitMap;
@property (assign, nonatomic) GPUClientFetchObject *GPUFetchObject;
@property (readonly, nonatomic) volatile int32_t numberViewsUsingDirectToCPUFiltering;
- (sem_t *) semaphoreFramebufferAtIndex:(const u8)bufferIndex;
- (void) semaphoreFramebufferCreate;
- (void) semaphoreFramebufferDestroy;
- (semaphore_t) semaphoreFramebufferAtIndex:(const u8)bufferIndex;
- (void) setOutputList:(NSMutableArray *)theOutputList rwlock:(pthread_rwlock_t *)theRWLock;
- (void) incrementViewsUsingDirectToCPUFiltering;
- (void) decrementViewsUsingDirectToCPUFiltering;

View File

@ -253,16 +253,16 @@ public:
gpuEvent->FramebufferLock();
#ifdef ENABLE_SHARED_FETCH_OBJECT
sem_wait([[self sharedData] semaphoreFramebufferAtIndex:0]);
sem_wait([[self sharedData] semaphoreFramebufferAtIndex:1]);
semaphore_wait([[self sharedData] semaphoreFramebufferAtIndex:0]);
semaphore_wait([[self sharedData] semaphoreFramebufferAtIndex:1]);
#endif
GPU->SetCustomFramebufferSize(w, h);
#ifdef ENABLE_SHARED_FETCH_OBJECT
fetchObject->SetFetchBuffers(GPU->GetDisplayInfo());
sem_post([[self sharedData] semaphoreFramebufferAtIndex:1]);
sem_post([[self sharedData] semaphoreFramebufferAtIndex:0]);
semaphore_signal([[self sharedData] semaphoreFramebufferAtIndex:1]);
semaphore_signal([[self sharedData] semaphoreFramebufferAtIndex:0]);
#endif
gpuEvent->FramebufferUnlock();
@ -314,16 +314,16 @@ public:
if (colorFormat != dispInfo.colorFormat)
{
#ifdef ENABLE_SHARED_FETCH_OBJECT
sem_wait([[self sharedData] semaphoreFramebufferAtIndex:0]);
sem_wait([[self sharedData] semaphoreFramebufferAtIndex:1]);
semaphore_wait([[self sharedData] semaphoreFramebufferAtIndex:0]);
semaphore_wait([[self sharedData] semaphoreFramebufferAtIndex:1]);
#endif
GPU->SetColorFormat((NDSColorFormat)colorFormat);
#ifdef ENABLE_SHARED_FETCH_OBJECT
fetchObject->SetFetchBuffers(GPU->GetDisplayInfo());
sem_post([[self sharedData] semaphoreFramebufferAtIndex:1]);
sem_post([[self sharedData] semaphoreFramebufferAtIndex:0]);
semaphore_signal([[self sharedData] semaphoreFramebufferAtIndex:1]);
semaphore_signal([[self sharedData] semaphoreFramebufferAtIndex:0]);
#endif
}
@ -866,13 +866,13 @@ public:
#ifdef ENABLE_SHARED_FETCH_OBJECT
const u8 bufferIndex = GPU->GetDisplayInfo().bufferIndex;
sem_wait([[self sharedData] semaphoreFramebufferAtIndex:bufferIndex]);
semaphore_wait([[self sharedData] semaphoreFramebufferAtIndex:bufferIndex]);
#endif
GPU->ClearWithColor(colorBGRA5551);
#ifdef ENABLE_SHARED_FETCH_OBJECT
sem_post([[self sharedData] semaphoreFramebufferAtIndex:bufferIndex]);
semaphore_signal([[self sharedData] semaphoreFramebufferAtIndex:bufferIndex]);
#endif
gpuEvent->FramebufferUnlock();
@ -918,28 +918,6 @@ public:
return self;
}
_semFramebuffer[0] = sem_open("desmume_semFramebuffer0", O_CREAT | O_EXCL, 0777, 1);
if (_semFramebuffer[0] == SEM_FAILED)
{
sem_unlink("desmume_semFramebuffer0");
_semFramebuffer[0] = sem_open("desmume_semFramebuffer0", O_CREAT | O_EXCL, 0777, 1);
if (_semFramebuffer[0] == SEM_FAILED)
{
puts("desmume_semFramebuffer0 failed!");
}
}
_semFramebuffer[1] = sem_open("desmume_semFramebuffer1", O_CREAT | O_EXCL, 0777, 1);
if (_semFramebuffer[1] == SEM_FAILED)
{
sem_unlink("desmume_semFramebuffer1");
_semFramebuffer[1] = sem_open("desmume_semFramebuffer1", O_CREAT | O_EXCL, 0777, 1);
if (_semFramebuffer[1] == SEM_FAILED)
{
puts("desmume_semFramebuffer1 failed!");
}
}
pthread_mutex_init(&_mutexDisplayLinkLists, NULL);
GPUFetchObject = nil;
@ -957,6 +935,10 @@ public:
pthread_cond_init(&_condSignalFetch, NULL);
pthread_create(&_threadFetch, NULL, &RunFetchThread, self);
pthread_mutex_init(&_mutexFetchExecute, NULL);
_taskEmulationLoop = 0;
_semFramebuffer[0] = 0;
_semFramebuffer[1] = 0;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(respondToScreenChange:)
@ -1011,15 +993,32 @@ public:
pthread_rwlock_unlock(currentRWLock);
}
sem_close(_semFramebuffer[0]);
sem_close(_semFramebuffer[1]);
sem_unlink("desmume_semFramebuffer0");
sem_unlink("desmume_semFramebuffer1");
[super dealloc];
}
- (sem_t *) semaphoreFramebufferAtIndex:(const u8)bufferIndex
- (void) semaphoreFramebufferCreate
{
_taskEmulationLoop = mach_task_self();
semaphore_create(_taskEmulationLoop, &_semFramebuffer[0], SYNC_POLICY_FIFO, 1);
semaphore_create(_taskEmulationLoop, &_semFramebuffer[1], SYNC_POLICY_FIFO, 1);
}
- (void) semaphoreFramebufferDestroy
{
if (_semFramebuffer[0] != 0)
{
semaphore_destroy(_taskEmulationLoop, _semFramebuffer[0]);
_semFramebuffer[0] = 0;
}
if (_semFramebuffer[1] != 0)
{
semaphore_destroy(_taskEmulationLoop, _semFramebuffer[1]);
_semFramebuffer[1] = 0;
}
}
- (semaphore_t) semaphoreFramebufferAtIndex:(const u8)bufferIndex
{
return _semFramebuffer[bufferIndex];
}
@ -1295,7 +1294,7 @@ void GPUEventHandlerOSX::DidFrameBegin(bool isFrameSkipRequested, const u8 targe
if (!isFrameSkipRequested)
{
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)this->_fetchObject->GetClientData();
sem_wait([sharedViewObject semaphoreFramebufferAtIndex:targetBufferIndex]);
semaphore_wait([sharedViewObject semaphoreFramebufferAtIndex:targetBufferIndex]);
}
#endif
}
@ -1307,7 +1306,7 @@ void GPUEventHandlerOSX::DidFrameEnd(bool isFrameSkipped, const NDSDisplayInfo &
if (!isFrameSkipped)
{
this->_fetchObject->SetFetchDisplayInfo(latestDisplayInfo);
sem_post([sharedViewObject semaphoreFramebufferAtIndex:latestDisplayInfo.bufferIndex]);
semaphore_signal([sharedViewObject semaphoreFramebufferAtIndex:latestDisplayInfo.bufferIndex]);
}
#endif

View File

@ -219,6 +219,8 @@ volatile bool execute = true;
[self removeAllOutputs];
[[cdsGPU sharedData] semaphoreFramebufferDestroy];
[self setCdsController:nil];
[self setCdsFirmware:nil];
[self setCdsGPU:nil];
@ -1129,6 +1131,8 @@ static void* RunCoreThread(void *arg)
ExecutionBehavior behavior = ExecutionBehavior_Pause;
uint64_t frameJumpTarget = 0;
[[[cdsCore cdsGPU] sharedData] semaphoreFramebufferCreate];
do
{
startTime = execControl->GetCurrentAbsoluteTime();

View File

@ -21,7 +21,10 @@
#import <Cocoa/Cocoa.h>
#import <Metal/Metal.h>
#include <libkern/OSAtomic.h>
#include <semaphore.h>
#include <mach/task.h>
#include <mach/semaphore.h>
#include <mach/sync_policy.h>
#import "DisplayViewCALayer.h"
#import "../cocoa_GPU.h"
@ -64,7 +67,6 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
id<MTLComputePipelineState> _fetch888Pipeline;
id<MTLComputePipelineState> _fetch555ConvertOnlyPipeline;
id<MTLComputePipelineState> _fetch666ConvertOnlyPipeline;
id<MTLComputePipelineState> _fetch888PassthroughOnlyPipeline;
id<MTLComputePipelineState> deposterizePipeline;
id<MTLRenderPipelineState> hudPipeline;
id<MTLRenderPipelineState> hudRGBAPipeline;
@ -108,8 +110,6 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
MTLSize _fetchThreadGroupsPerGridCustom;
MTLSize deposterizeThreadsPerGroup;
MTLSize deposterizeThreadGroupsPerGrid;
uint32_t _isUsingFramebufferDirectly[2][2];
}
@property (readonly, nonatomic) id<MTLDevice> device;
@ -138,9 +138,6 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
@property (readonly, nonatomic) MTLSize deposterizeThreadsPerGroup;
@property (readonly, nonatomic) MTLSize deposterizeThreadGroupsPerGrid;
- (void) setUsingFramebufferDirectlyAtIndex:(const u8)index displayID:(NDSDisplayID)displayID state:(bool)theState;
- (bool) isUsingFramebufferDirectlyAtIndex:(const u8)index displayID:(NDSDisplayID)displayID;
- (void) setFetchBuffersWithDisplayInfo:(const NDSDisplayInfo &)dispInfo;
- (void) setFetchTextureBindingsAtIndex:(const u8)index commandBuffer:(id<MTLCommandBuffer>)cb;
- (void) fetchFromBufferIndex:(const u8)index;
@ -185,7 +182,8 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
BOOL needsScreenVerticesUpdate;
BOOL needsHUDVerticesUpdate;
sem_t *_semTexProcessUpdate;
dispatch_semaphore_t _semDisplayLayoutUpdate;
dispatch_semaphore_t _semTexProcessUpdate;
bool _needEncodeViewport;
MTLViewport _newViewport;
bool _willDrawHUD;
@ -199,7 +197,8 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
@property (readonly, nonatomic) ClientDisplay3DPresenter *cdp;
@property (assign, nonatomic) MetalDisplayViewSharedData *sharedData;
@property (readonly, nonatomic) MTLRenderPassColorAttachmentDescriptor *colorAttachment0Desc;
@property (readonly, nonatomic) sem_t *semTexProcessUpdate;
@property (readonly, nonatomic) dispatch_semaphore_t semDisplayLayoutUpdate;
@property (readonly, nonatomic) dispatch_semaphore_t semTexProcessUpdate;
@property (retain) id<MTLComputePipelineState> pixelScalePipeline;
@property (retain) id<MTLRenderPipelineState> outputRGBAPipeline;
@property (retain) id<MTLRenderPipelineState> outputDrawablePipeline;
@ -281,7 +280,7 @@ private:
protected:
MacMetalDisplayPresenterObject *_presenterObject;
pthread_mutex_t _mutexProcessPtr;
sem_t *_semCPUFilter[2][2];
dispatch_semaphore_t _semCPUFilter[2][2];
virtual void _UpdateNormalSize();
virtual void _UpdateOrder();
@ -298,7 +297,7 @@ public:
MacMetalDisplayPresenterObject* GetPresenterObject() const;
pthread_mutex_t* GetMutexProcessPtr();
sem_t* GetCPUFilterSemaphore(const NDSDisplayID displayID, const uint8_t bufferIndex);
dispatch_semaphore_t GetCPUFilterSemaphore(const NDSDisplayID displayID, const uint8_t bufferIndex);
virtual void Init();
virtual void SetSharedData(MacClientSharedObject *sharedObject);
@ -311,6 +310,7 @@ public:
// Client view interface
virtual void ProcessDisplays();
virtual void UpdateLayout();
virtual void CopyFrameToBuffer(uint32_t *dstBuffer);
};

View File

@ -16,12 +16,6 @@
*/
#include "MacMetalDisplayView.h"
#include <stdio.h>
#include <semaphore.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
#include "../cocoa_globals.h"
#include "../../../common.h"
@ -78,7 +72,6 @@
_fetch888Pipeline = [[device newComputePipelineStateWithFunction:[defaultLibrary newFunctionWithName:@"nds_fetch888"] error:nil] retain];
_fetch555ConvertOnlyPipeline = [[device newComputePipelineStateWithFunction:[defaultLibrary newFunctionWithName:@"nds_fetch555ConvertOnly"] error:nil] retain];
_fetch666ConvertOnlyPipeline = [[device newComputePipelineStateWithFunction:[defaultLibrary newFunctionWithName:@"nds_fetch666ConvertOnly"] error:nil] retain];
_fetch888PassthroughOnlyPipeline = [[device newComputePipelineStateWithFunction:[defaultLibrary newFunctionWithName:@"nds_fetch888PassthroughOnly"] error:nil] retain];
deposterizePipeline = [[device newComputePipelineStateWithFunction:[defaultLibrary newFunctionWithName:@"src_filter_deposterize"] error:nil] retain];
if ( IsOSXVersion(10, 13, 0) || IsOSXVersion(10, 13, 1) || IsOSXVersion(10, 13, 2) || IsOSXVersion(10, 13, 3) || IsOSXVersion(10, 13, 4) )
@ -232,11 +225,6 @@
texFetchMain = [_texDisplayPostprocessNative[NDSDisplayID_Main][0] retain];
texFetchTouch = [_texDisplayPostprocessNative[NDSDisplayID_Touch][0] retain];
_isUsingFramebufferDirectly[NDSDisplayID_Main][0] = 1;
_isUsingFramebufferDirectly[NDSDisplayID_Main][1] = 1;
_isUsingFramebufferDirectly[NDSDisplayID_Touch][0] = 1;
_isUsingFramebufferDirectly[NDSDisplayID_Touch][1] = 1;
// Set up the HQnx LUT textures.
SetupHQnxLUTs_Metal(device, commandQueue, texLQ2xLUT, texHQ2xLUT, texHQ3xLUT, texHQ4xLUT);
texCurrentHQnxLUT = nil;
@ -257,7 +245,6 @@
[_fetch888Pipeline release];
[_fetch555ConvertOnlyPipeline release];
[_fetch666ConvertOnlyPipeline release];
[_fetch888PassthroughOnlyPipeline release];
[deposterizePipeline release];
[hudPipeline release];
[hudRGBAPipeline release];
@ -309,23 +296,6 @@
[super dealloc];
}
- (void) setUsingFramebufferDirectlyAtIndex:(const u8)index displayID:(NDSDisplayID)displayID state:(bool)theState
{
if (theState)
{
OSAtomicOr32(1, &_isUsingFramebufferDirectly[displayID][index]);
}
else
{
OSAtomicAnd32(0, &_isUsingFramebufferDirectly[displayID][index]);
}
}
- (bool) isUsingFramebufferDirectlyAtIndex:(const u8)index displayID:(NDSDisplayID)displayID
{
return (OSAtomicAnd32(1, &_isUsingFramebufferDirectly[displayID][index]) == 1);
}
- (void) setFetchBuffersWithDisplayInfo:(const NDSDisplayInfo &)dispInfo
{
const size_t w = dispInfo.customWidth;
@ -483,8 +453,6 @@
const NDSDisplayInfo &currentDisplayInfo = GPUFetchObject->GetFetchDisplayInfoForBufferIndex(index);
const bool isMainEnabled = currentDisplayInfo.isDisplayEnabled[NDSDisplayID_Main];
const bool isTouchEnabled = currentDisplayInfo.isDisplayEnabled[NDSDisplayID_Touch];
bool isUsingFramebufferDirectlyMain = true;
bool isUsingFramebufferDirectlyTouch = true;
if (isMainEnabled || isTouchEnabled)
{
@ -558,8 +526,6 @@
texFetchTargetMain = _texDisplayPostprocessCustom[NDSDisplayID_Main][index];
}
isUsingFramebufferDirectlyMain = false;
}
if (isTouchEnabled)
@ -590,112 +556,105 @@
texFetchTargetTouch = _texDisplayPostprocessCustom[NDSDisplayID_Touch][index];
}
isUsingFramebufferDirectlyTouch = false;
}
}
else
else if (currentDisplayInfo.colorFormat != NDSColorFormat_BGR888_Rev)
{
bool isPipelineStateSet = false;
if (currentDisplayInfo.colorFormat == NDSColorFormat_BGR555_Rev)
{
// 16-bit textures aren't handled natively in Metal for macOS, so we need to explicitly convert to 32-bit here.
[cce setComputePipelineState:_fetch555ConvertOnlyPipeline];
isPipelineStateSet = true;
}
else if ( (currentDisplayInfo.colorFormat == NDSColorFormat_BGR666_Rev) &&
(currentDisplayInfo.needConvertColorFormat[NDSDisplayID_Main] || currentDisplayInfo.needConvertColorFormat[NDSDisplayID_Touch]) )
{
[cce setComputePipelineState:_fetch666ConvertOnlyPipeline];
}
else
{
[cce setComputePipelineState:_fetch888PassthroughOnlyPipeline];
isPipelineStateSet = true;
}
if (isMainEnabled)
if (isPipelineStateSet)
{
if (!currentDisplayInfo.didPerformCustomRender[NDSDisplayID_Main])
if (isMainEnabled)
{
[cce setTexture:_texDisplayFetchNative[NDSDisplayID_Main][index] atIndex:0];
[cce setTexture:_texDisplayPostprocessNative[NDSDisplayID_Main][index] atIndex:1];
[cce dispatchThreadgroups:_fetchThreadGroupsPerGridNative
threadsPerThreadgroup:_fetchThreadsPerGroup];
texFetchTargetMain = _texDisplayPostprocessNative[NDSDisplayID_Main][index];
}
else
{
[cce setTexture:_texDisplayFetchCustom[NDSDisplayID_Main][index] atIndex:0];
[cce setTexture:_texDisplayPostprocessCustom[NDSDisplayID_Main][index] atIndex:1];
[cce dispatchThreadgroups:_fetchThreadGroupsPerGridCustom
threadsPerThreadgroup:_fetchThreadsPerGroup];
texFetchTargetMain = _texDisplayPostprocessCustom[NDSDisplayID_Main][index];
if (!currentDisplayInfo.didPerformCustomRender[NDSDisplayID_Main])
{
[cce setTexture:_texDisplayFetchNative[NDSDisplayID_Main][index] atIndex:0];
[cce setTexture:_texDisplayPostprocessNative[NDSDisplayID_Main][index] atIndex:1];
[cce dispatchThreadgroups:_fetchThreadGroupsPerGridNative
threadsPerThreadgroup:_fetchThreadsPerGroup];
texFetchTargetMain = _texDisplayPostprocessNative[NDSDisplayID_Main][index];
}
else
{
[cce setTexture:_texDisplayFetchCustom[NDSDisplayID_Main][index] atIndex:0];
[cce setTexture:_texDisplayPostprocessCustom[NDSDisplayID_Main][index] atIndex:1];
[cce dispatchThreadgroups:_fetchThreadGroupsPerGridCustom
threadsPerThreadgroup:_fetchThreadsPerGroup];
texFetchTargetMain = _texDisplayPostprocessCustom[NDSDisplayID_Main][index];
}
}
isUsingFramebufferDirectlyMain = false;
}
if (isTouchEnabled)
{
if (!currentDisplayInfo.didPerformCustomRender[NDSDisplayID_Touch])
if (isTouchEnabled)
{
[cce setTexture:_texDisplayFetchNative[NDSDisplayID_Touch][index] atIndex:0];
[cce setTexture:_texDisplayPostprocessNative[NDSDisplayID_Touch][index] atIndex:1];
[cce dispatchThreadgroups:_fetchThreadGroupsPerGridNative
threadsPerThreadgroup:_fetchThreadsPerGroup];
texFetchTargetTouch = _texDisplayPostprocessNative[NDSDisplayID_Touch][index];
if (!currentDisplayInfo.didPerformCustomRender[NDSDisplayID_Touch])
{
[cce setTexture:_texDisplayFetchNative[NDSDisplayID_Touch][index] atIndex:0];
[cce setTexture:_texDisplayPostprocessNative[NDSDisplayID_Touch][index] atIndex:1];
[cce dispatchThreadgroups:_fetchThreadGroupsPerGridNative
threadsPerThreadgroup:_fetchThreadsPerGroup];
texFetchTargetTouch = _texDisplayPostprocessNative[NDSDisplayID_Touch][index];
}
else
{
[cce setTexture:_texDisplayFetchCustom[NDSDisplayID_Touch][index] atIndex:0];
[cce setTexture:_texDisplayPostprocessCustom[NDSDisplayID_Touch][index] atIndex:1];
[cce dispatchThreadgroups:_fetchThreadGroupsPerGridCustom
threadsPerThreadgroup:_fetchThreadsPerGroup];
texFetchTargetTouch = _texDisplayPostprocessCustom[NDSDisplayID_Touch][index];
}
}
else
{
[cce setTexture:_texDisplayFetchCustom[NDSDisplayID_Touch][index] atIndex:0];
[cce setTexture:_texDisplayPostprocessCustom[NDSDisplayID_Touch][index] atIndex:1];
[cce dispatchThreadgroups:_fetchThreadGroupsPerGridCustom
threadsPerThreadgroup:_fetchThreadsPerGroup];
texFetchTargetTouch = _texDisplayPostprocessCustom[NDSDisplayID_Touch][index];
}
isUsingFramebufferDirectlyTouch = false;
}
}
[cce endEncoding];
}
[self setUsingFramebufferDirectlyAtIndex:index displayID:NDSDisplayID_Main state:isUsingFramebufferDirectlyMain];
[self setUsingFramebufferDirectlyAtIndex:index displayID:NDSDisplayID_Touch state:isUsingFramebufferDirectlyTouch];
[self setTexFetchMain:texFetchTargetMain];
[self setTexFetchTouch:texFetchTargetTouch];
}
- (void) fetchFromBufferIndex:(const u8)index
{
sem_wait([self semaphoreFramebufferAtIndex:index]);
id<MTLCommandBuffer> cb = [commandQueue commandBufferWithUnretainedReferences];
_fetchEncoder = [cb blitCommandEncoder];
semaphore_wait([self semaphoreFramebufferAtIndex:index]);
GPUFetchObject->GPUClientFetchObject::FetchFromBufferIndex(index);
[_fetchEncoder endEncoding];
[self setFetchTextureBindingsAtIndex:index commandBuffer:cb];
if (index == 0)
{
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
sem_post([self semaphoreFramebufferAtIndex:0]);
semaphore_signal([self semaphoreFramebufferAtIndex:0]);
}];
}
else
{
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
sem_post([self semaphoreFramebufferAtIndex:1]);
semaphore_signal([self semaphoreFramebufferAtIndex:1]);
}];
}
[cb commit];
cb = [commandQueue commandBufferWithUnretainedReferences];
[self setFetchTextureBindingsAtIndex:index commandBuffer:cb];
[cb commit];
}
@ -750,6 +709,7 @@
@synthesize cdp;
@synthesize sharedData;
@synthesize colorAttachment0Desc;
@dynamic semDisplayLayoutUpdate;
@dynamic semTexProcessUpdate;
@synthesize pixelScalePipeline;
@synthesize outputRGBAPipeline;
@ -830,16 +790,8 @@
_processedFrameInfo.tex[NDSDisplayID_Main] = nil;
_processedFrameInfo.tex[NDSDisplayID_Touch] = nil;
_semTexProcessUpdate = sem_open("desmume_semTexProcessUpdate", O_CREAT | O_EXCL, 0777, 1);
if (_semTexProcessUpdate == SEM_FAILED)
{
sem_unlink("desmume_semTexProcessUpdate");
_semTexProcessUpdate = sem_open("desmume_semTexProcessUpdate", O_CREAT | O_EXCL, 0777, 1);
if (_semTexProcessUpdate == SEM_FAILED)
{
puts("desmume_semTexProcessUpdate failed!");
}
}
_semDisplayLayoutUpdate = dispatch_semaphore_create(1);
_semTexProcessUpdate = dispatch_semaphore_create(1);
return self;
}
@ -878,13 +830,18 @@
[self setSharedData:nil];
sem_close(_semTexProcessUpdate);
sem_unlink("desmume_semTexProcessUpdate");
dispatch_release(_semDisplayLayoutUpdate);
dispatch_release(_semTexProcessUpdate);
[super dealloc];
}
- (sem_t *) semTexProcessUpdate
- (dispatch_semaphore_t) semDisplayLayoutUpdate
{
return _semDisplayLayoutUpdate;
}
- (dispatch_semaphore_t) semTexProcessUpdate
{
return _semTexProcessUpdate;
}
@ -1463,7 +1420,7 @@
if (shouldProcessDisplay[NDSDisplayID_Main] && ([self texDisplayPixelScaleMain] != nil))
{
sem_wait(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Main, bufferIndex));
dispatch_semaphore_wait(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Main, bufferIndex), DISPATCH_TIME_FOREVER);
needsCPUFilterUnlockMain = true;
vfMain->RunFilter();
@ -1471,7 +1428,7 @@
{
[[self bufCPUFilterDstMain] didModifyRange:NSMakeRange(0, vfMain->GetDstWidth() * vfMain->GetDstHeight() * sizeof(uint32_t))];
needsCPUFilterUnlockMain = false;
sem_post(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Main, bufferIndex));
dispatch_semaphore_signal(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Main, bufferIndex));
}
[bce copyFromBuffer:[self bufCPUFilterDstMain]
@ -1498,7 +1455,7 @@
if (shouldProcessDisplay[NDSDisplayID_Touch] && ([self texDisplayPixelScaleTouch] != nil))
{
sem_wait(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Touch, bufferIndex));
dispatch_semaphore_wait(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Touch, bufferIndex), DISPATCH_TIME_FOREVER);
needsCPUFilterUnlockTouch = true;
vfTouch->RunFilter();
@ -1506,7 +1463,7 @@
{
[[self bufCPUFilterDstTouch] didModifyRange:NSMakeRange(0, vfTouch->GetDstWidth() * vfTouch->GetDstHeight() * sizeof(uint32_t))];
needsCPUFilterUnlockTouch = false;
sem_post(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Touch, bufferIndex));
dispatch_semaphore_signal(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Touch, bufferIndex));
}
[bce copyFromBuffer:[self bufCPUFilterDstTouch]
@ -1536,15 +1493,15 @@
if (bufferIndex == 0)
{
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
sem_post(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Main, 0));
sem_post(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Touch, 0));
dispatch_semaphore_signal(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Main, 0));
dispatch_semaphore_signal(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Touch, 0));
}];
}
else
{
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
sem_post(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Main, 1));
sem_post(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Touch, 1));
dispatch_semaphore_signal(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Main, 1));
dispatch_semaphore_signal(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Touch, 1));
}];
}
}
@ -1553,13 +1510,13 @@
if (bufferIndex == 0)
{
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
sem_post(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Main, 0));
dispatch_semaphore_signal(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Main, 0));
}];
}
else
{
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
sem_post(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Main, 1));
dispatch_semaphore_signal(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Main, 1));
}];
}
}
@ -1569,13 +1526,13 @@
if (bufferIndex == 0)
{
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
sem_post(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Touch, 0));
dispatch_semaphore_signal(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Touch, 0));
}];
}
else
{
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
sem_post(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Touch, 1));
dispatch_semaphore_signal(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Touch, 1));
}];
}
}
@ -1584,7 +1541,7 @@
}
// Update the texture coordinates
sem_wait(_semTexProcessUpdate);
dispatch_semaphore_wait(_semTexProcessUpdate, DISPATCH_TIME_FOREVER);
// Update the frame info
id<MTLTexture> oldDisplayProcessedMain = _processedFrameInfo.tex[NDSDisplayID_Main];
@ -1596,10 +1553,10 @@
[self updateTexCoordBuffer];
dispatch_semaphore_signal(_semTexProcessUpdate);
[oldDisplayProcessedMain release];
[oldDisplayProcessedTouch release];
sem_post(_semTexProcessUpdate);
}
- (void) updateTexCoordBuffer
@ -1624,6 +1581,8 @@
newViewport.znear = 0.0;
newViewport.zfar = 1.0;
dispatch_semaphore_wait(_semDisplayLayoutUpdate, DISPATCH_TIME_FOREVER);
if ([self needsViewportUpdate])
{
needEncodeViewport = true;
@ -1722,6 +1681,8 @@
_willDrawHUDInput = cdp->GetHUDShowInput();
_hudStringLength = cdp->GetHUDString().length();
_hudTouchLineLength = hudTouchLineLength;
dispatch_semaphore_signal(_semDisplayLayoutUpdate);
}
- (void) renderForCommandBuffer:(id<MTLCommandBuffer>)cb
@ -1873,16 +1834,9 @@
const size_t clientWidth = cdp->GetPresenterProperties().clientWidth;
const size_t clientHeight = cdp->GetPresenterProperties().clientHeight;
// Create a unique semaphore name based on mach_absolute_time().
char semaphoreName[64];
memset(semaphoreName, '\0', sizeof(semaphoreName));
snprintf(semaphoreName, sizeof(semaphoreName), "desmume_semRenderToBuffer_0x%016llX", (unsigned long long)mach_absolute_time());
sem_t *semRenderToBuffer = sem_open(semaphoreName, O_CREAT, 0777, 1);
if (semRenderToBuffer == SEM_FAILED)
{
puts("desmume_semRenderToBuffer failed!");
}
task_t renderTask = mach_task_self();
semaphore_t semRenderToBuffer = 0;
semaphore_create(renderTask, &semRenderToBuffer, SYNC_POLICY_PREPOST, 0);
@autoreleasepool
{
@ -1897,14 +1851,13 @@
id<MTLTexture> texRender = [[sharedData device] newTextureWithDescriptor:texRenderDesc];
id<MTLBuffer> dstMTLBuffer = [[sharedData device] newBufferWithLength:clientWidth * clientHeight * sizeof(uint32_t) options:MTLResourceStorageModeManaged];
sem_wait(_semTexProcessUpdate);
dispatch_semaphore_wait(_semTexProcessUpdate, DISPATCH_TIME_FOREVER);
dispatch_semaphore_wait(_semDisplayLayoutUpdate, DISPATCH_TIME_FOREVER);
// Now that everything is set up, go ahead and draw everything.
[colorAttachment0Desc setTexture:texRender];
id<MTLCommandBuffer> cb = [self newCommandBuffer];
[self updateRenderBuffers];
[self renderForCommandBuffer:cb
outputPipelineState:[self outputRGBAPipeline]
hudPipelineState:[sharedData hudRGBAPipeline]
@ -1912,12 +1865,11 @@
texDisplayTouch:_processedFrameInfo.tex[NDSDisplayID_Touch]];
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
sem_post(_semTexProcessUpdate);
dispatch_semaphore_signal(_semDisplayLayoutUpdate);
dispatch_semaphore_signal(_semTexProcessUpdate);
}];
[cb commit];
sem_wait(semRenderToBuffer);
cb = [self newCommandBuffer];
id<MTLBlitCommandEncoder> bce = [cb blitCommandEncoder];
@ -1935,13 +1887,12 @@
[bce endEncoding];
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
sem_post(semRenderToBuffer);
semaphore_signal(semRenderToBuffer);
}];
[cb commit];
// Wait on this thread until the GPU completes its task, then continue execution on this thread.
sem_wait(semRenderToBuffer);
sem_post(semRenderToBuffer);
semaphore_wait(semRenderToBuffer);
memcpy(dstBuffer, [dstMTLBuffer contents], clientWidth * clientHeight * sizeof(uint32_t));
@ -1949,8 +1900,7 @@
[dstMTLBuffer release];
}
sem_close(semRenderToBuffer);
sem_unlink(semaphoreName);
semaphore_destroy(renderTask, semRenderToBuffer);
}
@end
@ -1995,7 +1945,8 @@
{
@autoreleasepool
{
sem_wait([presenterObject semTexProcessUpdate]);
dispatch_semaphore_wait([presenterObject semTexProcessUpdate], DISPATCH_TIME_FOREVER);
dispatch_semaphore_wait([presenterObject semDisplayLayoutUpdate], DISPATCH_TIME_FOREVER);
const MetalProcessedFrameInfo &processedInfo = [presenterObject processedFrameInfo];
@ -2004,8 +1955,6 @@
[[presenterObject colorAttachment0Desc] setTexture:[layerDrawable texture]];
id<MTLCommandBuffer> cb = [presenterObject newCommandBuffer];
[presenterObject updateRenderBuffers];
[presenterObject renderForCommandBuffer:cb
outputPipelineState:[presenterObject outputDrawablePipeline]
hudPipelineState:[[presenterObject sharedData] hudPipeline]
@ -2015,7 +1964,8 @@
[cb presentDrawable:layerDrawable];
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
sem_post([presenterObject semTexProcessUpdate]);
dispatch_semaphore_signal([presenterObject semDisplayLayoutUpdate]);
dispatch_semaphore_signal([presenterObject semTexProcessUpdate]);
}];
[cb commit];
@ -2160,14 +2110,10 @@ MacMetalDisplayPresenter::~MacMetalDisplayPresenter()
pthread_mutex_destroy(&this->_mutexProcessPtr);
sem_close(this->_semCPUFilter[NDSDisplayID_Main][0]);
sem_close(this->_semCPUFilter[NDSDisplayID_Main][1]);
sem_close(this->_semCPUFilter[NDSDisplayID_Touch][0]);
sem_close(this->_semCPUFilter[NDSDisplayID_Touch][1]);
sem_unlink("desmume_semCPUFilterMain0");
sem_unlink("desmume_semCPUFilterMain1");
sem_unlink("desmume_semCPUFilterTouch0");
sem_unlink("desmume_semCPUFilterTouch1");
dispatch_release(this->_semCPUFilter[NDSDisplayID_Main][0]);
dispatch_release(this->_semCPUFilter[NDSDisplayID_Main][1]);
dispatch_release(this->_semCPUFilter[NDSDisplayID_Touch][0]);
dispatch_release(this->_semCPUFilter[NDSDisplayID_Touch][1]);
}
void MacMetalDisplayPresenter::__InstanceInit(MacClientSharedObject *sharedObject)
@ -2185,49 +2131,10 @@ void MacMetalDisplayPresenter::__InstanceInit(MacClientSharedObject *sharedObjec
pthread_mutex_init(&_mutexProcessPtr, NULL);
_semCPUFilter[NDSDisplayID_Main][0] = sem_open("desmume_semCPUFilterMain0", O_CREAT | O_EXCL, 0777, 1);
if (_semCPUFilter[NDSDisplayID_Main][0] == SEM_FAILED)
{
sem_unlink("desmume_semCPUFilterMain0");
_semCPUFilter[NDSDisplayID_Main][0] = sem_open("desmume_semCPUFilterMain0", O_CREAT | O_EXCL, 0777, 1);
if (_semCPUFilter[NDSDisplayID_Main][0] == SEM_FAILED)
{
puts("desmume_semCPUFilterMain0 failed!");
}
}
_semCPUFilter[NDSDisplayID_Main][1] = sem_open("desmume_semCPUFilterMain1", O_CREAT | O_EXCL, 0777, 1);
if (_semCPUFilter[NDSDisplayID_Main][1] == SEM_FAILED)
{
sem_unlink("desmume_semCPUFilterMain1");
_semCPUFilter[NDSDisplayID_Main][1] = sem_open("desmume_semCPUFilterMain1", O_CREAT | O_EXCL, 0777, 1);
if (_semCPUFilter[NDSDisplayID_Main][1] == SEM_FAILED)
{
puts("desmume_semCPUFilterMain1 failed!");
}
}
_semCPUFilter[NDSDisplayID_Touch][0] = sem_open("desmume_semCPUFilterTouch0", O_CREAT | O_EXCL, 0777, 1);
if (_semCPUFilter[NDSDisplayID_Touch][0] == SEM_FAILED)
{
sem_unlink("desmume_semCPUFilterTouch0");
_semCPUFilter[NDSDisplayID_Touch][0] = sem_open("desmume_semCPUFilterTouch0", O_CREAT | O_EXCL, 0777, 1);
if (_semCPUFilter[NDSDisplayID_Touch][0] == SEM_FAILED)
{
puts("desmume_semCPUFilterTouch0 failed!");
}
}
_semCPUFilter[NDSDisplayID_Touch][1] = sem_open("desmume_semCPUFilterTouch1", O_CREAT | O_EXCL, 0777, 1);
if (_semCPUFilter[NDSDisplayID_Touch][1] == SEM_FAILED)
{
sem_unlink("desmume_semCPUFilterTouch1");
_semCPUFilter[NDSDisplayID_Touch][1] = sem_open("desmume_semCPUFilterTouch1", O_CREAT | O_EXCL, 0777, 1);
if (_semCPUFilter[NDSDisplayID_Touch][1] == SEM_FAILED)
{
puts("desmume_semCPUFilterTouch1 failed!");
}
}
_semCPUFilter[NDSDisplayID_Main][0] = dispatch_semaphore_create(1);
_semCPUFilter[NDSDisplayID_Main][1] = dispatch_semaphore_create(1);
_semCPUFilter[NDSDisplayID_Touch][0] = dispatch_semaphore_create(1);
_semCPUFilter[NDSDisplayID_Touch][1] = dispatch_semaphore_create(1);
}
void MacMetalDisplayPresenter::_UpdateNormalSize()
@ -2267,9 +2174,9 @@ void MacMetalDisplayPresenter::_LoadNativeDisplayByID(const NDSDisplayID display
const uint8_t bufferIndex = fetchObjMutable.GetLastFetchIndex();
sem_wait(this->_semCPUFilter[displayID][bufferIndex]);
dispatch_semaphore_wait(this->_semCPUFilter[displayID][bufferIndex], DISPATCH_TIME_FOREVER);
fetchObjMutable.CopyFromSrcClone(vf->GetSrcBufferPtr(), displayID, bufferIndex);
sem_post(this->_semCPUFilter[displayID][bufferIndex]);
dispatch_semaphore_signal(this->_semCPUFilter[displayID][bufferIndex]);
}
}
@ -2289,7 +2196,7 @@ pthread_mutex_t* MacMetalDisplayPresenter::GetMutexProcessPtr()
return &this->_mutexProcessPtr;
}
sem_t* MacMetalDisplayPresenter::GetCPUFilterSemaphore(const NDSDisplayID displayID, const uint8_t bufferIndex)
dispatch_semaphore_t MacMetalDisplayPresenter::GetCPUFilterSemaphore(const NDSDisplayID displayID, const uint8_t bufferIndex)
{
return this->_semCPUFilter[displayID][bufferIndex];
}
@ -2344,6 +2251,11 @@ void MacMetalDisplayPresenter::ProcessDisplays()
[this->_presenterObject processDisplays];
}
void MacMetalDisplayPresenter::UpdateLayout()
{
[this->_presenterObject updateRenderBuffers];
}
void MacMetalDisplayPresenter::CopyFrameToBuffer(uint32_t *dstBuffer)
{
[this->_presenterObject renderToBuffer:dstBuffer];

View File

@ -437,7 +437,7 @@ kernel void nds_fetch555(const uint2 position [[thread_position_in_grid]],
const float4 inColor = unpack_unorm1555_to_unorm8888( (ushort)inTexture.read(position).r );
float3 outColor = inColor.rgb;
const uint line = uint(((float)position.y + 0.01f) / ((float)h / 192.0f));
const uint line = uint( (float)position.y / ((float)h / 192.0f) );
outColor = nds_apply_master_brightness(outColor, brightnessMode[line], (float)brightnessIntensity[line] / 16.0f);
outTexture.write(float4(outColor, 1.0f), position);
@ -459,7 +459,7 @@ kernel void nds_fetch666(const uint2 position [[thread_position_in_grid]],
const float4 inColor = inTexture.read(position);
float3 outColor = inColor.rgb * float3(255.0f/63.0f);
const uint line = uint(((float)position.y + 0.01f) / ((float)h / 192.0f));
const uint line = uint( (float)position.y / ((float)h / 192.0f) );
outColor = nds_apply_master_brightness(outColor, brightnessMode[line], (float)brightnessIntensity[line] / 16.0f);
outTexture.write(float4(outColor, 1.0f), position);
@ -481,7 +481,7 @@ kernel void nds_fetch888(const uint2 position [[thread_position_in_grid]],
const float4 inColor = inTexture.read(position);
float3 outColor = inColor.rgb;
const uint line = uint(((float)position.y + 0.01f) / ((float)h / 192.0f));
const uint line = uint( (float)position.y / ((float)h / 192.0f) );
outColor = nds_apply_master_brightness(outColor, brightnessMode[line], (float)brightnessIntensity[line] / 16.0f);
outTexture.write(float4(outColor, 1.0f), position);
@ -513,19 +513,6 @@ kernel void nds_fetch666ConvertOnly(const uint2 position [[thread_position_in_gr
outTexture.write(float4(outColor, 1.0f), position);
}
kernel void nds_fetch888PassthroughOnly(const uint2 position [[thread_position_in_grid]],
const texture2d<float, access::read> inTexture [[texture(0)]],
texture2d<float, access::write> outTexture [[texture(1)]])
{
if ( (position.x > inTexture.get_width() - 1) || (position.y > inTexture.get_height() - 1) )
{
return;
}
const float3 outColor = inTexture.read(position).rgb;
outTexture.write(float4(outColor, 1.0f), position);
}
float3 nds_apply_master_brightness(const float3 inColor, const uchar mode, const float intensity)
{
switch (mode)

View File

@ -16,6 +16,7 @@
*/
#include "MacOGLDisplayView.h"
#include <mach/semaphore.h>
#include "../utilities.h"
@ -194,14 +195,14 @@ void MacOGLClientFetchObject::FetchFromBufferIndex(const u8 index)
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)this->_clientData;
this->_useDirectToCPUFilterPipeline = ([sharedViewObject numberViewsUsingDirectToCPUFiltering] > 0);
sem_wait([sharedViewObject semaphoreFramebufferAtIndex:index]);
semaphore_wait([sharedViewObject semaphoreFramebufferAtIndex:index]);
CGLLockContext(this->_context);
CGLSetCurrentContext(this->_context);
this->OGLClientFetchObject::FetchFromBufferIndex(index);
CGLUnlockContext(this->_context);
sem_post([sharedViewObject semaphoreFramebufferAtIndex:index]);
semaphore_signal([sharedViewObject semaphoreFramebufferAtIndex:index]);
}
GLuint MacOGLClientFetchObject::GetFetchTexture(const NDSDisplayID displayID)
@ -435,7 +436,7 @@ void MacOGLDisplayPresenter::WriteLockEmuFramebuffer(const uint8_t bufferIndex)
const GPUClientFetchObject &fetchObj = this->GetFetchObject();
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)fetchObj.GetClientData();
sem_wait([sharedViewObject semaphoreFramebufferAtIndex:bufferIndex]);
semaphore_wait([sharedViewObject semaphoreFramebufferAtIndex:bufferIndex]);
}
void MacOGLDisplayPresenter::ReadLockEmuFramebuffer(const uint8_t bufferIndex)
@ -443,7 +444,7 @@ void MacOGLDisplayPresenter::ReadLockEmuFramebuffer(const uint8_t bufferIndex)
const GPUClientFetchObject &fetchObj = this->GetFetchObject();
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)fetchObj.GetClientData();
sem_wait([sharedViewObject semaphoreFramebufferAtIndex:bufferIndex]);
semaphore_wait([sharedViewObject semaphoreFramebufferAtIndex:bufferIndex]);
}
void MacOGLDisplayPresenter::UnlockEmuFramebuffer(const uint8_t bufferIndex)
@ -451,7 +452,7 @@ void MacOGLDisplayPresenter::UnlockEmuFramebuffer(const uint8_t bufferIndex)
const GPUClientFetchObject &fetchObj = this->GetFetchObject();
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)fetchObj.GetClientData();
sem_post([sharedViewObject semaphoreFramebufferAtIndex:bufferIndex]);
semaphore_signal([sharedViewObject semaphoreFramebufferAtIndex:bufferIndex]);
}
#pragma mark -