Cocoa Port: For Metal display views, replace all locks with semaphores, which are the correct synchronization primitive to use here.
- Also change the CocoaDSOutput list lock from a mutex to a rwlock, since testing has shown that there is more thread contention here than I previously thought.
This commit is contained in:
parent
f9109568b8
commit
26ac91edd0
|
@ -19,6 +19,7 @@
|
||||||
#import <CoreVideo/CoreVideo.h>
|
#import <CoreVideo/CoreVideo.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <libkern/OSAtomic.h>
|
#include <libkern/OSAtomic.h>
|
||||||
|
#include <semaphore.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#import "cocoa_util.h"
|
#import "cocoa_util.h"
|
||||||
|
@ -48,8 +49,8 @@ typedef std::map<CGDirectDisplayID, int64_t> DisplayLinkFlushTimeLimitMap;
|
||||||
@interface MacClientSharedObject : NSObject
|
@interface MacClientSharedObject : NSObject
|
||||||
{
|
{
|
||||||
GPUClientFetchObject *GPUFetchObject;
|
GPUClientFetchObject *GPUFetchObject;
|
||||||
pthread_rwlock_t *_rwlockFramebuffer[2];
|
sem_t *_semFramebuffer[2];
|
||||||
pthread_mutex_t *_mutexOutputList;
|
pthread_rwlock_t *_rwlockOutputList;
|
||||||
pthread_mutex_t _mutexDisplayLinkLists;
|
pthread_mutex_t _mutexDisplayLinkLists;
|
||||||
NSMutableArray *_cdsOutputList;
|
NSMutableArray *_cdsOutputList;
|
||||||
volatile int32_t numberViewsUsingDirectToCPUFiltering;
|
volatile int32_t numberViewsUsingDirectToCPUFiltering;
|
||||||
|
@ -58,7 +59,7 @@ typedef std::map<CGDirectDisplayID, int64_t> DisplayLinkFlushTimeLimitMap;
|
||||||
DisplayLinkFlushTimeLimitMap _displayLinkFlushTimeList;
|
DisplayLinkFlushTimeLimitMap _displayLinkFlushTimeList;
|
||||||
|
|
||||||
OSSpinLock spinlockFetchSignal;
|
OSSpinLock spinlockFetchSignal;
|
||||||
BOOL _isFetchSignalled;
|
uint32_t _threadMessageID;
|
||||||
uint8_t _fetchIndex;
|
uint8_t _fetchIndex;
|
||||||
pthread_t _threadFetch;
|
pthread_t _threadFetch;
|
||||||
pthread_cond_t _condSignalFetch;
|
pthread_cond_t _condSignalFetch;
|
||||||
|
@ -68,8 +69,8 @@ typedef std::map<CGDirectDisplayID, int64_t> DisplayLinkFlushTimeLimitMap;
|
||||||
@property (assign, nonatomic) GPUClientFetchObject *GPUFetchObject;
|
@property (assign, nonatomic) GPUClientFetchObject *GPUFetchObject;
|
||||||
@property (readonly, nonatomic) volatile int32_t numberViewsUsingDirectToCPUFiltering;
|
@property (readonly, nonatomic) volatile int32_t numberViewsUsingDirectToCPUFiltering;
|
||||||
|
|
||||||
- (pthread_rwlock_t *) rwlockFramebufferAtIndex:(const u8)bufferIndex;
|
- (sem_t *) semaphoreFramebufferAtIndex:(const u8)bufferIndex;
|
||||||
- (void) setOutputList:(NSMutableArray *)theOutputList mutex:(pthread_mutex_t *)theMutex;
|
- (void) setOutputList:(NSMutableArray *)theOutputList rwlock:(pthread_rwlock_t *)theRWLock;
|
||||||
- (void) incrementViewsUsingDirectToCPUFiltering;
|
- (void) incrementViewsUsingDirectToCPUFiltering;
|
||||||
- (void) decrementViewsUsingDirectToCPUFiltering;
|
- (void) decrementViewsUsingDirectToCPUFiltering;
|
||||||
- (void) pushVideoDataToAllDisplayViews;
|
- (void) pushVideoDataToAllDisplayViews;
|
||||||
|
@ -79,7 +80,7 @@ typedef std::map<CGDirectDisplayID, int64_t> DisplayLinkFlushTimeLimitMap;
|
||||||
- (void) displayLinkListUpdate;
|
- (void) displayLinkListUpdate;
|
||||||
|
|
||||||
- (void) fetchSynchronousAtIndex:(uint8_t)index;
|
- (void) fetchSynchronousAtIndex:(uint8_t)index;
|
||||||
- (void) signalFetchAtIndex:(uint8_t)index;
|
- (void) signalFetchAtIndex:(uint8_t)index message:(int32_t)messageID;
|
||||||
- (void) runFetchLoop;
|
- (void) runFetchLoop;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -135,7 +136,7 @@ typedef std::map<CGDirectDisplayID, int64_t> DisplayLinkFlushTimeLimitMap;
|
||||||
@property (readonly, nonatomic) GPUClientFetchObject *fetchObject;
|
@property (readonly, nonatomic) GPUClientFetchObject *fetchObject;
|
||||||
@property (readonly, nonatomic) MacClientSharedObject *sharedData;
|
@property (readonly, nonatomic) MacClientSharedObject *sharedData;
|
||||||
|
|
||||||
- (void) setOutputList:(NSMutableArray *)theOutputList mutexPtr:(pthread_mutex_t *)theMutex;
|
- (void) setOutputList:(NSMutableArray *)theOutputList rwlock:(pthread_rwlock_t *)theRWLock;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
- (BOOL) gpuStateByBit:(const UInt32)stateBit;
|
- (BOOL) gpuStateByBit:(const UInt32)stateBit;
|
||||||
|
|
|
@ -253,16 +253,16 @@ public:
|
||||||
gpuEvent->FramebufferLock();
|
gpuEvent->FramebufferLock();
|
||||||
|
|
||||||
#ifdef ENABLE_SHARED_FETCH_OBJECT
|
#ifdef ENABLE_SHARED_FETCH_OBJECT
|
||||||
pthread_rwlock_wrlock([[self sharedData] rwlockFramebufferAtIndex:0]);
|
sem_wait([[self sharedData] semaphoreFramebufferAtIndex:0]);
|
||||||
pthread_rwlock_wrlock([[self sharedData] rwlockFramebufferAtIndex:1]);
|
sem_wait([[self sharedData] semaphoreFramebufferAtIndex:1]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GPU->SetCustomFramebufferSize(w, h);
|
GPU->SetCustomFramebufferSize(w, h);
|
||||||
|
|
||||||
#ifdef ENABLE_SHARED_FETCH_OBJECT
|
#ifdef ENABLE_SHARED_FETCH_OBJECT
|
||||||
fetchObject->SetFetchBuffers(GPU->GetDisplayInfo());
|
fetchObject->SetFetchBuffers(GPU->GetDisplayInfo());
|
||||||
pthread_rwlock_unlock([[self sharedData] rwlockFramebufferAtIndex:1]);
|
sem_post([[self sharedData] semaphoreFramebufferAtIndex:1]);
|
||||||
pthread_rwlock_unlock([[self sharedData] rwlockFramebufferAtIndex:0]);
|
sem_post([[self sharedData] semaphoreFramebufferAtIndex:0]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gpuEvent->FramebufferUnlock();
|
gpuEvent->FramebufferUnlock();
|
||||||
|
@ -314,16 +314,16 @@ public:
|
||||||
if (colorFormat != dispInfo.colorFormat)
|
if (colorFormat != dispInfo.colorFormat)
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_SHARED_FETCH_OBJECT
|
#ifdef ENABLE_SHARED_FETCH_OBJECT
|
||||||
pthread_rwlock_wrlock([[self sharedData] rwlockFramebufferAtIndex:0]);
|
sem_wait([[self sharedData] semaphoreFramebufferAtIndex:0]);
|
||||||
pthread_rwlock_wrlock([[self sharedData] rwlockFramebufferAtIndex:1]);
|
sem_wait([[self sharedData] semaphoreFramebufferAtIndex:1]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GPU->SetColorFormat((NDSColorFormat)colorFormat);
|
GPU->SetColorFormat((NDSColorFormat)colorFormat);
|
||||||
|
|
||||||
#ifdef ENABLE_SHARED_FETCH_OBJECT
|
#ifdef ENABLE_SHARED_FETCH_OBJECT
|
||||||
fetchObject->SetFetchBuffers(GPU->GetDisplayInfo());
|
fetchObject->SetFetchBuffers(GPU->GetDisplayInfo());
|
||||||
pthread_rwlock_unlock([[self sharedData] rwlockFramebufferAtIndex:1]);
|
sem_post([[self sharedData] semaphoreFramebufferAtIndex:1]);
|
||||||
pthread_rwlock_unlock([[self sharedData] rwlockFramebufferAtIndex:0]);
|
sem_post([[self sharedData] semaphoreFramebufferAtIndex:0]);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,9 +343,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_SHARED_FETCH_OBJECT
|
#ifdef ENABLE_SHARED_FETCH_OBJECT
|
||||||
- (void) setOutputList:(NSMutableArray *)theOutputList mutexPtr:(pthread_mutex_t *)theMutex
|
- (void) setOutputList:(NSMutableArray *)theOutputList rwlock:(pthread_rwlock_t *)theRWLock
|
||||||
{
|
{
|
||||||
[(MacClientSharedObject *)fetchObject->GetClientData() setOutputList:theOutputList mutex:theMutex];
|
[(MacClientSharedObject *)fetchObject->GetClientData() setOutputList:theOutputList rwlock:theRWLock];
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -866,18 +866,18 @@ public:
|
||||||
|
|
||||||
#ifdef ENABLE_SHARED_FETCH_OBJECT
|
#ifdef ENABLE_SHARED_FETCH_OBJECT
|
||||||
const u8 bufferIndex = GPU->GetDisplayInfo().bufferIndex;
|
const u8 bufferIndex = GPU->GetDisplayInfo().bufferIndex;
|
||||||
pthread_rwlock_wrlock([[self sharedData] rwlockFramebufferAtIndex:bufferIndex]);
|
sem_wait([[self sharedData] semaphoreFramebufferAtIndex:bufferIndex]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GPU->ClearWithColor(colorBGRA5551);
|
GPU->ClearWithColor(colorBGRA5551);
|
||||||
|
|
||||||
#ifdef ENABLE_SHARED_FETCH_OBJECT
|
#ifdef ENABLE_SHARED_FETCH_OBJECT
|
||||||
pthread_rwlock_unlock([[self sharedData] rwlockFramebufferAtIndex:bufferIndex]);
|
sem_post([[self sharedData] semaphoreFramebufferAtIndex:bufferIndex]);
|
||||||
#endif
|
#endif
|
||||||
gpuEvent->FramebufferUnlock();
|
gpuEvent->FramebufferUnlock();
|
||||||
|
|
||||||
#ifdef ENABLE_SHARED_FETCH_OBJECT
|
#ifdef ENABLE_SHARED_FETCH_OBJECT
|
||||||
[[self sharedData] signalFetchAtIndex:bufferIndex];
|
[[self sharedData] signalFetchAtIndex:bufferIndex message:MESSAGE_FETCH_AND_PUSH_VIDEO];
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -918,15 +918,32 @@ public:
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
_rwlockFramebuffer[0] = (pthread_rwlock_t *)malloc(sizeof(pthread_rwlock_t));
|
_semFramebuffer[0] = sem_open("desmume_semFramebuffer0", O_CREAT | O_EXCL, 0777, 1);
|
||||||
_rwlockFramebuffer[1] = (pthread_rwlock_t *)malloc(sizeof(pthread_rwlock_t));
|
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_rwlock_init(_rwlockFramebuffer[0], NULL);
|
|
||||||
pthread_rwlock_init(_rwlockFramebuffer[1], NULL);
|
|
||||||
pthread_mutex_init(&_mutexDisplayLinkLists, NULL);
|
pthread_mutex_init(&_mutexDisplayLinkLists, NULL);
|
||||||
|
|
||||||
GPUFetchObject = nil;
|
GPUFetchObject = nil;
|
||||||
_mutexOutputList = NULL;
|
_rwlockOutputList = NULL;
|
||||||
_cdsOutputList = nil;
|
_cdsOutputList = nil;
|
||||||
numberViewsUsingDirectToCPUFiltering = 0;
|
numberViewsUsingDirectToCPUFiltering = 0;
|
||||||
|
|
||||||
|
@ -935,7 +952,7 @@ public:
|
||||||
[self displayLinkListUpdate];
|
[self displayLinkListUpdate];
|
||||||
|
|
||||||
spinlockFetchSignal = OS_SPINLOCK_INIT;
|
spinlockFetchSignal = OS_SPINLOCK_INIT;
|
||||||
_isFetchSignalled = NO;
|
_threadMessageID = MESSAGE_NONE;
|
||||||
_fetchIndex = 0;
|
_fetchIndex = 0;
|
||||||
pthread_cond_init(&_condSignalFetch, NULL);
|
pthread_cond_init(&_condSignalFetch, NULL);
|
||||||
pthread_create(&_threadFetch, NULL, &RunFetchThread, self);
|
pthread_create(&_threadFetch, NULL, &RunFetchThread, self);
|
||||||
|
@ -980,50 +997,52 @@ public:
|
||||||
pthread_mutex_unlock(&_mutexDisplayLinkLists);
|
pthread_mutex_unlock(&_mutexDisplayLinkLists);
|
||||||
pthread_mutex_destroy(&_mutexDisplayLinkLists);
|
pthread_mutex_destroy(&_mutexDisplayLinkLists);
|
||||||
|
|
||||||
pthread_mutex_t *currentMutex = _mutexOutputList;
|
pthread_rwlock_t *currentRWLock = _rwlockOutputList;
|
||||||
|
|
||||||
if (currentMutex != NULL)
|
if (currentRWLock != NULL)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(currentMutex);
|
pthread_rwlock_wrlock(currentRWLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
[_cdsOutputList release];
|
[_cdsOutputList release];
|
||||||
|
|
||||||
if (currentMutex != NULL)
|
if (currentRWLock != NULL)
|
||||||
{
|
{
|
||||||
pthread_mutex_unlock(currentMutex);
|
pthread_rwlock_unlock(currentRWLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_rwlock_destroy(_rwlockFramebuffer[0]);
|
sem_close(_semFramebuffer[0]);
|
||||||
pthread_rwlock_destroy(_rwlockFramebuffer[1]);
|
sem_close(_semFramebuffer[1]);
|
||||||
|
sem_unlink("desmume_semFramebuffer0");
|
||||||
|
sem_unlink("desmume_semFramebuffer1");
|
||||||
|
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (pthread_rwlock_t *) rwlockFramebufferAtIndex:(const u8)bufferIndex
|
- (sem_t *) semaphoreFramebufferAtIndex:(const u8)bufferIndex
|
||||||
{
|
{
|
||||||
return _rwlockFramebuffer[bufferIndex];
|
return _semFramebuffer[bufferIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) setOutputList:(NSMutableArray *)theOutputList mutex:(pthread_mutex_t *)theMutex
|
- (void) setOutputList:(NSMutableArray *)theOutputList rwlock:(pthread_rwlock_t *)theRWLock
|
||||||
{
|
{
|
||||||
pthread_mutex_t *currentMutex = _mutexOutputList;
|
pthread_rwlock_t *currentRWLock = _rwlockOutputList;
|
||||||
|
|
||||||
if (currentMutex != NULL)
|
if (currentRWLock != NULL)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(currentMutex);
|
pthread_rwlock_wrlock(currentRWLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
[_cdsOutputList release];
|
[_cdsOutputList release];
|
||||||
_cdsOutputList = theOutputList;
|
_cdsOutputList = theOutputList;
|
||||||
[_cdsOutputList retain];
|
[_cdsOutputList retain];
|
||||||
|
|
||||||
if (currentMutex != NULL)
|
if (currentRWLock != NULL)
|
||||||
{
|
{
|
||||||
pthread_mutex_unlock(currentMutex);
|
pthread_rwlock_unlock(currentRWLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
_mutexOutputList = theMutex;
|
_rwlockOutputList = theRWLock;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) incrementViewsUsingDirectToCPUFiltering
|
- (void) incrementViewsUsingDirectToCPUFiltering
|
||||||
|
@ -1038,11 +1057,11 @@ public:
|
||||||
|
|
||||||
- (void) pushVideoDataToAllDisplayViews
|
- (void) pushVideoDataToAllDisplayViews
|
||||||
{
|
{
|
||||||
pthread_mutex_t *currentMutex = _mutexOutputList;
|
pthread_rwlock_t *currentRWLock = _rwlockOutputList;
|
||||||
|
|
||||||
if (currentMutex != NULL)
|
if (currentRWLock != NULL)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(currentMutex);
|
pthread_rwlock_rdlock(currentRWLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (CocoaDSOutput *cdsOutput in _cdsOutputList)
|
for (CocoaDSOutput *cdsOutput in _cdsOutputList)
|
||||||
|
@ -1053,21 +1072,21 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentMutex != NULL)
|
if (currentRWLock != NULL)
|
||||||
{
|
{
|
||||||
pthread_mutex_unlock(currentMutex);
|
pthread_rwlock_unlock(currentRWLock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) flushAllDisplaysOnDisplayLink:(CVDisplayLinkRef)displayLink timeStamp:(const CVTimeStamp *)timeStamp
|
- (void) flushAllDisplaysOnDisplayLink:(CVDisplayLinkRef)displayLink timeStamp:(const CVTimeStamp *)timeStamp
|
||||||
{
|
{
|
||||||
pthread_mutex_t *currentMutex = _mutexOutputList;
|
pthread_rwlock_t *currentRWLock = _rwlockOutputList;
|
||||||
CGDirectDisplayID displayID = CVDisplayLinkGetCurrentCGDisplay(displayLink);
|
CGDirectDisplayID displayID = CVDisplayLinkGetCurrentCGDisplay(displayLink);
|
||||||
bool didFlushOccur = false;
|
bool didFlushOccur = false;
|
||||||
|
|
||||||
if (currentMutex != NULL)
|
if (currentRWLock != NULL)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(currentMutex);
|
pthread_rwlock_rdlock(currentRWLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (CocoaDSOutput *cdsOutput in _cdsOutputList)
|
for (CocoaDSOutput *cdsOutput in _cdsOutputList)
|
||||||
|
@ -1087,9 +1106,9 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentMutex != NULL)
|
if (currentRWLock != NULL)
|
||||||
{
|
{
|
||||||
pthread_mutex_unlock(currentMutex);
|
pthread_rwlock_unlock(currentRWLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (didFlushOccur)
|
if (didFlushOccur)
|
||||||
|
@ -1195,12 +1214,12 @@ public:
|
||||||
GPUFetchObject->FetchFromBufferIndex(index);
|
GPUFetchObject->FetchFromBufferIndex(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) signalFetchAtIndex:(uint8_t)index
|
- (void) signalFetchAtIndex:(uint8_t)index message:(int32_t)messageID
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&_mutexFetchExecute);
|
pthread_mutex_lock(&_mutexFetchExecute);
|
||||||
|
|
||||||
_fetchIndex = index;
|
_fetchIndex = index;
|
||||||
_isFetchSignalled = YES;
|
_threadMessageID = messageID;
|
||||||
pthread_cond_signal(&_condSignalFetch);
|
pthread_cond_signal(&_condSignalFetch);
|
||||||
|
|
||||||
pthread_mutex_unlock(&_mutexFetchExecute);
|
pthread_mutex_unlock(&_mutexFetchExecute);
|
||||||
|
@ -1212,14 +1231,15 @@ public:
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
while (!_isFetchSignalled)
|
while (_threadMessageID == MESSAGE_NONE)
|
||||||
{
|
{
|
||||||
pthread_cond_wait(&_condSignalFetch, &_mutexFetchExecute);
|
pthread_cond_wait(&_condSignalFetch, &_mutexFetchExecute);
|
||||||
}
|
}
|
||||||
_isFetchSignalled = NO;
|
|
||||||
|
|
||||||
GPUFetchObject->FetchFromBufferIndex(_fetchIndex);
|
GPUFetchObject->FetchFromBufferIndex(_fetchIndex);
|
||||||
[self pushVideoDataToAllDisplayViews];
|
[self pushVideoDataToAllDisplayViews];
|
||||||
|
_threadMessageID = MESSAGE_NONE;
|
||||||
|
|
||||||
} while(true);
|
} while(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1275,7 +1295,7 @@ void GPUEventHandlerOSX::DidFrameBegin(bool isFrameSkipRequested, const u8 targe
|
||||||
if (!isFrameSkipRequested)
|
if (!isFrameSkipRequested)
|
||||||
{
|
{
|
||||||
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)this->_fetchObject->GetClientData();
|
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)this->_fetchObject->GetClientData();
|
||||||
pthread_rwlock_wrlock([sharedViewObject rwlockFramebufferAtIndex:targetBufferIndex]);
|
sem_wait([sharedViewObject semaphoreFramebufferAtIndex:targetBufferIndex]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1287,7 +1307,7 @@ void GPUEventHandlerOSX::DidFrameEnd(bool isFrameSkipped, const NDSDisplayInfo &
|
||||||
if (!isFrameSkipped)
|
if (!isFrameSkipped)
|
||||||
{
|
{
|
||||||
this->_fetchObject->SetFetchDisplayInfo(latestDisplayInfo);
|
this->_fetchObject->SetFetchDisplayInfo(latestDisplayInfo);
|
||||||
pthread_rwlock_unlock([sharedViewObject rwlockFramebufferAtIndex:latestDisplayInfo.bufferIndex]);
|
sem_post([sharedViewObject semaphoreFramebufferAtIndex:latestDisplayInfo.bufferIndex]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1296,7 +1316,7 @@ void GPUEventHandlerOSX::DidFrameEnd(bool isFrameSkipped, const NDSDisplayInfo &
|
||||||
#ifdef ENABLE_SHARED_FETCH_OBJECT
|
#ifdef ENABLE_SHARED_FETCH_OBJECT
|
||||||
if (!isFrameSkipped)
|
if (!isFrameSkipped)
|
||||||
{
|
{
|
||||||
[sharedViewObject signalFetchAtIndex:latestDisplayInfo.bufferIndex];
|
[sharedViewObject signalFetchAtIndex:latestDisplayInfo.bufferIndex message:MESSAGE_FETCH_AND_PUSH_VIDEO];
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ typedef void *gdbstub_handle_t;
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
CocoaDSCore *cdsCore;
|
CocoaDSCore *cdsCore;
|
||||||
pthread_mutex_t mutexOutputList;
|
pthread_rwlock_t rwlockOutputList;
|
||||||
pthread_mutex_t mutexThreadExecute;
|
pthread_mutex_t mutexThreadExecute;
|
||||||
pthread_cond_t condThreadExecute;
|
pthread_cond_t condThreadExecute;
|
||||||
pthread_rwlock_t rwlockCoreExecute;
|
pthread_rwlock_t rwlockCoreExecute;
|
||||||
|
|
|
@ -173,7 +173,7 @@ volatile bool execute = true;
|
||||||
|
|
||||||
threadParam.cdsCore = self;
|
threadParam.cdsCore = self;
|
||||||
|
|
||||||
pthread_mutex_init(&threadParam.mutexOutputList, NULL);
|
pthread_rwlock_init(&threadParam.rwlockOutputList, NULL);
|
||||||
pthread_mutex_init(&threadParam.mutexThreadExecute, NULL);
|
pthread_mutex_init(&threadParam.mutexThreadExecute, NULL);
|
||||||
pthread_cond_init(&threadParam.condThreadExecute, NULL);
|
pthread_cond_init(&threadParam.condThreadExecute, NULL);
|
||||||
pthread_rwlock_init(&threadParam.rwlockCoreExecute, NULL);
|
pthread_rwlock_init(&threadParam.rwlockCoreExecute, NULL);
|
||||||
|
@ -198,7 +198,7 @@ volatile bool execute = true;
|
||||||
sp.sched_priority = sched_get_priority_max(thePolicy);
|
sp.sched_priority = sched_get_priority_max(thePolicy);
|
||||||
pthread_setschedparam(coreThread, thePolicy, &sp);
|
pthread_setschedparam(coreThread, thePolicy, &sp);
|
||||||
|
|
||||||
[cdsGPU setOutputList:cdsOutputList mutexPtr:&threadParam.mutexOutputList];
|
[cdsGPU setOutputList:cdsOutputList rwlock:&threadParam.rwlockOutputList];
|
||||||
|
|
||||||
OSXDriver *newDriver = new OSXDriver;
|
OSXDriver *newDriver = new OSXDriver;
|
||||||
newDriver->SetCoreThreadMutexLock(&threadParam.mutexThreadExecute);
|
newDriver->SetCoreThreadMutexLock(&threadParam.mutexThreadExecute);
|
||||||
|
@ -231,7 +231,7 @@ volatile bool execute = true;
|
||||||
|
|
||||||
pthread_mutex_destroy(&threadParam.mutexThreadExecute);
|
pthread_mutex_destroy(&threadParam.mutexThreadExecute);
|
||||||
pthread_cond_destroy(&threadParam.condThreadExecute);
|
pthread_cond_destroy(&threadParam.condThreadExecute);
|
||||||
pthread_mutex_destroy(&threadParam.mutexOutputList);
|
pthread_rwlock_destroy(&threadParam.rwlockOutputList);
|
||||||
pthread_rwlock_destroy(&threadParam.rwlockCoreExecute);
|
pthread_rwlock_destroy(&threadParam.rwlockCoreExecute);
|
||||||
|
|
||||||
[self setIsGdbStubStarted:NO];
|
[self setIsGdbStubStarted:NO];
|
||||||
|
@ -644,7 +644,7 @@ volatile bool execute = true;
|
||||||
|
|
||||||
execControl->SetExecutionBehavior((ExecutionBehavior)coreState);
|
execControl->SetExecutionBehavior((ExecutionBehavior)coreState);
|
||||||
|
|
||||||
pthread_mutex_lock(&threadParam.mutexOutputList);
|
pthread_rwlock_rdlock(&threadParam.rwlockOutputList);
|
||||||
|
|
||||||
switch ((ExecutionBehavior)coreState)
|
switch ((ExecutionBehavior)coreState)
|
||||||
{
|
{
|
||||||
|
@ -718,7 +718,7 @@ volatile bool execute = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&threadParam.mutexOutputList);
|
pthread_rwlock_unlock(&threadParam.rwlockOutputList);
|
||||||
|
|
||||||
pthread_cond_signal(&threadParam.condThreadExecute);
|
pthread_cond_signal(&threadParam.condThreadExecute);
|
||||||
pthread_mutex_unlock(&threadParam.mutexThreadExecute);
|
pthread_mutex_unlock(&threadParam.mutexThreadExecute);
|
||||||
|
@ -878,6 +878,8 @@ volatile bool execute = true;
|
||||||
// count every other instance the timer fires.
|
// count every other instance the timer fires.
|
||||||
_isTimerAtSecond = !_isTimerAtSecond;
|
_isTimerAtSecond = !_isTimerAtSecond;
|
||||||
|
|
||||||
|
pthread_rwlock_rdlock(&threadParam.rwlockOutputList);
|
||||||
|
|
||||||
for (CocoaDSOutput *cdsOutput in cdsOutputList)
|
for (CocoaDSOutput *cdsOutput in cdsOutputList)
|
||||||
{
|
{
|
||||||
if ([cdsOutput isKindOfClass:[CocoaDSDisplay class]])
|
if ([cdsOutput isKindOfClass:[CocoaDSDisplay class]])
|
||||||
|
@ -888,6 +890,8 @@ volatile bool execute = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pthread_rwlock_unlock(&threadParam.rwlockOutputList);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSUInteger) frameNumber
|
- (NSUInteger) frameNumber
|
||||||
|
@ -897,7 +901,7 @@ volatile bool execute = true;
|
||||||
|
|
||||||
- (void) addOutput:(CocoaDSOutput *)theOutput
|
- (void) addOutput:(CocoaDSOutput *)theOutput
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&threadParam.mutexOutputList);
|
pthread_rwlock_wrlock(&threadParam.rwlockOutputList);
|
||||||
|
|
||||||
if ([theOutput isKindOfClass:[CocoaDSDisplay class]])
|
if ([theOutput isKindOfClass:[CocoaDSDisplay class]])
|
||||||
{
|
{
|
||||||
|
@ -909,21 +913,21 @@ volatile bool execute = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[self cdsOutputList] addObject:theOutput];
|
[[self cdsOutputList] addObject:theOutput];
|
||||||
pthread_mutex_unlock(&threadParam.mutexOutputList);
|
pthread_rwlock_unlock(&threadParam.rwlockOutputList);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) removeOutput:(CocoaDSOutput *)theOutput
|
- (void) removeOutput:(CocoaDSOutput *)theOutput
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&threadParam.mutexOutputList);
|
pthread_rwlock_wrlock(&threadParam.rwlockOutputList);
|
||||||
[[self cdsOutputList] removeObject:theOutput];
|
[[self cdsOutputList] removeObject:theOutput];
|
||||||
pthread_mutex_unlock(&threadParam.mutexOutputList);
|
pthread_rwlock_unlock(&threadParam.rwlockOutputList);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) removeAllOutputs
|
- (void) removeAllOutputs
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&threadParam.mutexOutputList);
|
pthread_rwlock_wrlock(&threadParam.rwlockOutputList);
|
||||||
[[self cdsOutputList] removeAllObjects];
|
[[self cdsOutputList] removeAllObjects];
|
||||||
pthread_mutex_unlock(&threadParam.mutexOutputList);
|
pthread_rwlock_unlock(&threadParam.rwlockOutputList);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *) cpuEmulationEngineString
|
- (NSString *) cpuEmulationEngineString
|
||||||
|
@ -1200,7 +1204,7 @@ static void* RunCoreThread(void *arg)
|
||||||
executionSpeedAverageFramesCollected = 0.0;
|
executionSpeedAverageFramesCollected = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(¶m->mutexOutputList);
|
pthread_rwlock_rdlock(¶m->rwlockOutputList);
|
||||||
|
|
||||||
switch (behavior)
|
switch (behavior)
|
||||||
{
|
{
|
||||||
|
@ -1227,7 +1231,7 @@ static void* RunCoreThread(void *arg)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(¶m->mutexOutputList);
|
pthread_rwlock_unlock(¶m->rwlockOutputList);
|
||||||
|
|
||||||
switch (behavior)
|
switch (behavior)
|
||||||
{
|
{
|
||||||
|
|
|
@ -334,6 +334,8 @@ enum
|
||||||
*/
|
*/
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
MESSAGE_NONE = 0,
|
||||||
|
|
||||||
MESSAGE_CHECK_FOR_RESPONSE = 100, // Message to check if a port is responding. Usually sent to make sure that a thread is alive.
|
MESSAGE_CHECK_FOR_RESPONSE = 100, // Message to check if a port is responding. Usually sent to make sure that a thread is alive.
|
||||||
MESSAGE_CHECK_RESPONSE_ECHO, // Response message when another port sends MESSAGE_CHECK_FOR_RESPONSE. Sent to confirm that a thread is indeed alive.
|
MESSAGE_CHECK_RESPONSE_ECHO, // Response message when another port sends MESSAGE_CHECK_FOR_RESPONSE. Sent to confirm that a thread is indeed alive.
|
||||||
MESSAGE_EXIT_THREAD, // Sent whenever there is a need to stop a thread.
|
MESSAGE_EXIT_THREAD, // Sent whenever there is a need to stop a thread.
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
#import <Metal/Metal.h>
|
#import <Metal/Metal.h>
|
||||||
#include <libkern/OSAtomic.h>
|
#include <libkern/OSAtomic.h>
|
||||||
|
#include <semaphore.h>
|
||||||
|
|
||||||
#import "DisplayViewCALayer.h"
|
#import "DisplayViewCALayer.h"
|
||||||
#import "../cocoa_GPU.h"
|
#import "../cocoa_GPU.h"
|
||||||
|
@ -39,8 +40,6 @@ struct MetalProcessedFrameInfo
|
||||||
{
|
{
|
||||||
uint8_t bufferIndex;
|
uint8_t bufferIndex;
|
||||||
id<MTLTexture> tex[2];
|
id<MTLTexture> tex[2];
|
||||||
bool isMainDisplayProcessed;
|
|
||||||
bool isTouchDisplayProcessed;
|
|
||||||
};
|
};
|
||||||
typedef struct MetalProcessedFrameInfo MetalProcessedFrameInfo;
|
typedef struct MetalProcessedFrameInfo MetalProcessedFrameInfo;
|
||||||
|
|
||||||
|
@ -65,6 +64,7 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
|
||||||
id<MTLComputePipelineState> _fetch888Pipeline;
|
id<MTLComputePipelineState> _fetch888Pipeline;
|
||||||
id<MTLComputePipelineState> _fetch555ConvertOnlyPipeline;
|
id<MTLComputePipelineState> _fetch555ConvertOnlyPipeline;
|
||||||
id<MTLComputePipelineState> _fetch666ConvertOnlyPipeline;
|
id<MTLComputePipelineState> _fetch666ConvertOnlyPipeline;
|
||||||
|
id<MTLComputePipelineState> _fetch888PassthroughOnlyPipeline;
|
||||||
id<MTLComputePipelineState> deposterizePipeline;
|
id<MTLComputePipelineState> deposterizePipeline;
|
||||||
id<MTLRenderPipelineState> hudPipeline;
|
id<MTLRenderPipelineState> hudPipeline;
|
||||||
id<MTLRenderPipelineState> hudRGBAPipeline;
|
id<MTLRenderPipelineState> hudRGBAPipeline;
|
||||||
|
@ -185,8 +185,7 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
|
||||||
BOOL needsScreenVerticesUpdate;
|
BOOL needsScreenVerticesUpdate;
|
||||||
BOOL needsHUDVerticesUpdate;
|
BOOL needsHUDVerticesUpdate;
|
||||||
|
|
||||||
pthread_mutex_t _mutexTexProcessUpdate;
|
sem_t *_semTexProcessUpdate;
|
||||||
pthread_mutex_t _mutexBufferUpdate;
|
|
||||||
bool _needEncodeViewport;
|
bool _needEncodeViewport;
|
||||||
MTLViewport _newViewport;
|
MTLViewport _newViewport;
|
||||||
bool _willDrawHUD;
|
bool _willDrawHUD;
|
||||||
|
@ -200,8 +199,7 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
|
||||||
@property (readonly, nonatomic) ClientDisplay3DPresenter *cdp;
|
@property (readonly, nonatomic) ClientDisplay3DPresenter *cdp;
|
||||||
@property (assign, nonatomic) MetalDisplayViewSharedData *sharedData;
|
@property (assign, nonatomic) MetalDisplayViewSharedData *sharedData;
|
||||||
@property (readonly, nonatomic) MTLRenderPassColorAttachmentDescriptor *colorAttachment0Desc;
|
@property (readonly, nonatomic) MTLRenderPassColorAttachmentDescriptor *colorAttachment0Desc;
|
||||||
@property (readonly, nonatomic) pthread_mutex_t *mutexTexProcessUpdate;
|
@property (readonly, nonatomic) sem_t *semTexProcessUpdate;
|
||||||
@property (readonly, nonatomic) pthread_mutex_t *mutexBufferUpdate;
|
|
||||||
@property (retain) id<MTLComputePipelineState> pixelScalePipeline;
|
@property (retain) id<MTLComputePipelineState> pixelScalePipeline;
|
||||||
@property (retain) id<MTLRenderPipelineState> outputRGBAPipeline;
|
@property (retain) id<MTLRenderPipelineState> outputRGBAPipeline;
|
||||||
@property (retain) id<MTLRenderPipelineState> outputDrawablePipeline;
|
@property (retain) id<MTLRenderPipelineState> outputDrawablePipeline;
|
||||||
|
@ -225,6 +223,7 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
|
||||||
- (void) resizeCPUPixelScalerUsingFilterID:(const VideoFilterTypeID)filterID;
|
- (void) resizeCPUPixelScalerUsingFilterID:(const VideoFilterTypeID)filterID;
|
||||||
- (void) copyHUDFontUsingFace:(const FT_Face &)fontFace size:(const size_t)glyphSize tileSize:(const size_t)glyphTileSize info:(GlyphInfo *)glyphInfo;
|
- (void) copyHUDFontUsingFace:(const FT_Face &)fontFace size:(const size_t)glyphSize tileSize:(const size_t)glyphTileSize info:(GlyphInfo *)glyphInfo;
|
||||||
- (void) processDisplays;
|
- (void) processDisplays;
|
||||||
|
- (void) updateTexCoordBuffer;
|
||||||
- (void) updateRenderBuffers;
|
- (void) updateRenderBuffers;
|
||||||
- (void) renderForCommandBuffer:(id<MTLCommandBuffer>)cb
|
- (void) renderForCommandBuffer:(id<MTLCommandBuffer>)cb
|
||||||
outputPipelineState:(id<MTLRenderPipelineState>)outputPipelineState
|
outputPipelineState:(id<MTLRenderPipelineState>)outputPipelineState
|
||||||
|
@ -282,7 +281,7 @@ private:
|
||||||
protected:
|
protected:
|
||||||
MacMetalDisplayPresenterObject *_presenterObject;
|
MacMetalDisplayPresenterObject *_presenterObject;
|
||||||
pthread_mutex_t _mutexProcessPtr;
|
pthread_mutex_t _mutexProcessPtr;
|
||||||
pthread_rwlock_t _cpuFilterRWLock[2][2];
|
sem_t *_semCPUFilter[2][2];
|
||||||
|
|
||||||
virtual void _UpdateNormalSize();
|
virtual void _UpdateNormalSize();
|
||||||
virtual void _UpdateOrder();
|
virtual void _UpdateOrder();
|
||||||
|
@ -299,7 +298,7 @@ public:
|
||||||
|
|
||||||
MacMetalDisplayPresenterObject* GetPresenterObject() const;
|
MacMetalDisplayPresenterObject* GetPresenterObject() const;
|
||||||
pthread_mutex_t* GetMutexProcessPtr();
|
pthread_mutex_t* GetMutexProcessPtr();
|
||||||
pthread_rwlock_t* GetCPUFilterRWLock(const NDSDisplayID displayID, const uint8_t bufferIndex);
|
sem_t* GetCPUFilterSemaphore(const NDSDisplayID displayID, const uint8_t bufferIndex);
|
||||||
|
|
||||||
virtual void Init();
|
virtual void Init();
|
||||||
virtual void SetSharedData(MacClientSharedObject *sharedObject);
|
virtual void SetSharedData(MacClientSharedObject *sharedObject);
|
||||||
|
@ -312,7 +311,6 @@ public:
|
||||||
|
|
||||||
// Client view interface
|
// Client view interface
|
||||||
virtual void ProcessDisplays();
|
virtual void ProcessDisplays();
|
||||||
virtual void UpdateLayout();
|
|
||||||
|
|
||||||
virtual void CopyFrameToBuffer(uint32_t *dstBuffer);
|
virtual void CopyFrameToBuffer(uint32_t *dstBuffer);
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,6 +17,13 @@
|
||||||
|
|
||||||
#include "MacMetalDisplayView.h"
|
#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"
|
#include "../../../common.h"
|
||||||
|
|
||||||
@implementation MetalDisplayViewSharedData
|
@implementation MetalDisplayViewSharedData
|
||||||
|
@ -71,6 +78,7 @@
|
||||||
_fetch888Pipeline = [[device newComputePipelineStateWithFunction:[defaultLibrary newFunctionWithName:@"nds_fetch888"] error:nil] retain];
|
_fetch888Pipeline = [[device newComputePipelineStateWithFunction:[defaultLibrary newFunctionWithName:@"nds_fetch888"] error:nil] retain];
|
||||||
_fetch555ConvertOnlyPipeline = [[device newComputePipelineStateWithFunction:[defaultLibrary newFunctionWithName:@"nds_fetch555ConvertOnly"] error:nil] retain];
|
_fetch555ConvertOnlyPipeline = [[device newComputePipelineStateWithFunction:[defaultLibrary newFunctionWithName:@"nds_fetch555ConvertOnly"] error:nil] retain];
|
||||||
_fetch666ConvertOnlyPipeline = [[device newComputePipelineStateWithFunction:[defaultLibrary newFunctionWithName:@"nds_fetch666ConvertOnly"] 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];
|
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) )
|
if ( IsOSXVersion(10, 13, 0) || IsOSXVersion(10, 13, 1) || IsOSXVersion(10, 13, 2) || IsOSXVersion(10, 13, 3) || IsOSXVersion(10, 13, 4) )
|
||||||
|
@ -249,6 +257,7 @@
|
||||||
[_fetch888Pipeline release];
|
[_fetch888Pipeline release];
|
||||||
[_fetch555ConvertOnlyPipeline release];
|
[_fetch555ConvertOnlyPipeline release];
|
||||||
[_fetch666ConvertOnlyPipeline release];
|
[_fetch666ConvertOnlyPipeline release];
|
||||||
|
[_fetch888PassthroughOnlyPipeline release];
|
||||||
[deposterizePipeline release];
|
[deposterizePipeline release];
|
||||||
[hudPipeline release];
|
[hudPipeline release];
|
||||||
[hudRGBAPipeline release];
|
[hudRGBAPipeline release];
|
||||||
|
@ -585,72 +594,69 @@
|
||||||
isUsingFramebufferDirectlyTouch = false;
|
isUsingFramebufferDirectlyTouch = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (currentDisplayInfo.colorFormat != NDSColorFormat_BGR888_Rev)
|
else
|
||||||
{
|
{
|
||||||
bool isPipelineStateSet = false;
|
|
||||||
|
|
||||||
if (currentDisplayInfo.colorFormat == NDSColorFormat_BGR555_Rev)
|
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.
|
// 16-bit textures aren't handled natively in Metal for macOS, so we need to explicitly convert to 32-bit here.
|
||||||
[cce setComputePipelineState:_fetch555ConvertOnlyPipeline];
|
[cce setComputePipelineState:_fetch555ConvertOnlyPipeline];
|
||||||
isPipelineStateSet = true;
|
|
||||||
}
|
}
|
||||||
else if ( (currentDisplayInfo.colorFormat == NDSColorFormat_BGR666_Rev) &&
|
else if ( (currentDisplayInfo.colorFormat == NDSColorFormat_BGR666_Rev) &&
|
||||||
(currentDisplayInfo.needConvertColorFormat[NDSDisplayID_Main] || currentDisplayInfo.needConvertColorFormat[NDSDisplayID_Touch]) )
|
(currentDisplayInfo.needConvertColorFormat[NDSDisplayID_Main] || currentDisplayInfo.needConvertColorFormat[NDSDisplayID_Touch]) )
|
||||||
{
|
{
|
||||||
[cce setComputePipelineState:_fetch666ConvertOnlyPipeline];
|
[cce setComputePipelineState:_fetch666ConvertOnlyPipeline];
|
||||||
isPipelineStateSet = true;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[cce setComputePipelineState:_fetch888PassthroughOnlyPipeline];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPipelineStateSet)
|
if (isMainEnabled)
|
||||||
{
|
{
|
||||||
if (isMainEnabled)
|
if (!currentDisplayInfo.didPerformCustomRender[NDSDisplayID_Main])
|
||||||
{
|
{
|
||||||
if (!currentDisplayInfo.didPerformCustomRender[NDSDisplayID_Main])
|
[cce setTexture:_texDisplayFetchNative[NDSDisplayID_Main][index] atIndex:0];
|
||||||
{
|
[cce setTexture:_texDisplayPostprocessNative[NDSDisplayID_Main][index] atIndex:1];
|
||||||
[cce setTexture:_texDisplayFetchNative[NDSDisplayID_Main][index] atIndex:0];
|
[cce dispatchThreadgroups:_fetchThreadGroupsPerGridNative
|
||||||
[cce setTexture:_texDisplayPostprocessNative[NDSDisplayID_Main][index] atIndex:1];
|
threadsPerThreadgroup:_fetchThreadsPerGroup];
|
||||||
[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;
|
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 (isTouchEnabled)
|
isUsingFramebufferDirectlyMain = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isTouchEnabled)
|
||||||
|
{
|
||||||
|
if (!currentDisplayInfo.didPerformCustomRender[NDSDisplayID_Touch])
|
||||||
{
|
{
|
||||||
if (!currentDisplayInfo.didPerformCustomRender[NDSDisplayID_Touch])
|
[cce setTexture:_texDisplayFetchNative[NDSDisplayID_Touch][index] atIndex:0];
|
||||||
{
|
[cce setTexture:_texDisplayPostprocessNative[NDSDisplayID_Touch][index] atIndex:1];
|
||||||
[cce setTexture:_texDisplayFetchNative[NDSDisplayID_Touch][index] atIndex:0];
|
[cce dispatchThreadgroups:_fetchThreadGroupsPerGridNative
|
||||||
[cce setTexture:_texDisplayPostprocessNative[NDSDisplayID_Touch][index] atIndex:1];
|
threadsPerThreadgroup:_fetchThreadsPerGroup];
|
||||||
[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];
|
|
||||||
}
|
|
||||||
|
|
||||||
isUsingFramebufferDirectlyTouch = false;
|
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];
|
||||||
|
}
|
||||||
|
|
||||||
|
isUsingFramebufferDirectlyTouch = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -666,7 +672,7 @@
|
||||||
|
|
||||||
- (void) fetchFromBufferIndex:(const u8)index
|
- (void) fetchFromBufferIndex:(const u8)index
|
||||||
{
|
{
|
||||||
pthread_rwlock_rdlock([self rwlockFramebufferAtIndex:index]);
|
sem_wait([self semaphoreFramebufferAtIndex:index]);
|
||||||
|
|
||||||
id<MTLCommandBuffer> cb = [commandQueue commandBufferWithUnretainedReferences];
|
id<MTLCommandBuffer> cb = [commandQueue commandBufferWithUnretainedReferences];
|
||||||
_fetchEncoder = [cb blitCommandEncoder];
|
_fetchEncoder = [cb blitCommandEncoder];
|
||||||
|
@ -680,18 +686,17 @@
|
||||||
if (index == 0)
|
if (index == 0)
|
||||||
{
|
{
|
||||||
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
||||||
pthread_rwlock_unlock([self rwlockFramebufferAtIndex:0]);
|
sem_post([self semaphoreFramebufferAtIndex:0]);
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
||||||
pthread_rwlock_unlock([self rwlockFramebufferAtIndex:1]);
|
sem_post([self semaphoreFramebufferAtIndex:1]);
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
[cb commit];
|
[cb commit];
|
||||||
[cb waitUntilScheduled];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) fetchNativeDisplayByID:(const NDSDisplayID)displayID bufferIndex:(const u8)bufferIndex
|
- (void) fetchNativeDisplayByID:(const NDSDisplayID)displayID bufferIndex:(const u8)bufferIndex
|
||||||
|
@ -745,8 +750,7 @@
|
||||||
@synthesize cdp;
|
@synthesize cdp;
|
||||||
@synthesize sharedData;
|
@synthesize sharedData;
|
||||||
@synthesize colorAttachment0Desc;
|
@synthesize colorAttachment0Desc;
|
||||||
@dynamic mutexTexProcessUpdate;
|
@dynamic semTexProcessUpdate;
|
||||||
@dynamic mutexBufferUpdate;
|
|
||||||
@synthesize pixelScalePipeline;
|
@synthesize pixelScalePipeline;
|
||||||
@synthesize outputRGBAPipeline;
|
@synthesize outputRGBAPipeline;
|
||||||
@synthesize outputDrawablePipeline;
|
@synthesize outputDrawablePipeline;
|
||||||
|
@ -825,11 +829,17 @@
|
||||||
_processedFrameInfo.bufferIndex = 0;
|
_processedFrameInfo.bufferIndex = 0;
|
||||||
_processedFrameInfo.tex[NDSDisplayID_Main] = nil;
|
_processedFrameInfo.tex[NDSDisplayID_Main] = nil;
|
||||||
_processedFrameInfo.tex[NDSDisplayID_Touch] = nil;
|
_processedFrameInfo.tex[NDSDisplayID_Touch] = nil;
|
||||||
_processedFrameInfo.isMainDisplayProcessed = false;
|
|
||||||
_processedFrameInfo.isTouchDisplayProcessed = false;
|
|
||||||
|
|
||||||
pthread_mutex_init(&_mutexTexProcessUpdate, NULL);
|
_semTexProcessUpdate = sem_open("desmume_semTexProcessUpdate", O_CREAT | O_EXCL, 0777, 1);
|
||||||
pthread_mutex_init(&_mutexBufferUpdate, NULL);
|
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!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -868,20 +878,15 @@
|
||||||
|
|
||||||
[self setSharedData:nil];
|
[self setSharedData:nil];
|
||||||
|
|
||||||
pthread_mutex_destroy(&_mutexTexProcessUpdate);
|
sem_close(_semTexProcessUpdate);
|
||||||
pthread_mutex_destroy(&_mutexBufferUpdate);
|
sem_unlink("desmume_semTexProcessUpdate");
|
||||||
|
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (pthread_mutex_t *) mutexTexProcessUpdate
|
- (sem_t *) semTexProcessUpdate
|
||||||
{
|
{
|
||||||
return &_mutexTexProcessUpdate;
|
return _semTexProcessUpdate;
|
||||||
}
|
|
||||||
|
|
||||||
- (pthread_mutex_t *) mutexBufferUpdate
|
|
||||||
{
|
|
||||||
return &_mutexBufferUpdate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (VideoFilterTypeID) pixelScaler
|
- (VideoFilterTypeID) pixelScaler
|
||||||
|
@ -1314,27 +1319,15 @@
|
||||||
id<MTLTexture> texMain = (selectedDisplaySource[NDSDisplayID_Main] == NDSDisplayID_Main) ? [sharedData texFetchMain] : [sharedData texFetchTouch];
|
id<MTLTexture> texMain = (selectedDisplaySource[NDSDisplayID_Main] == NDSDisplayID_Main) ? [sharedData texFetchMain] : [sharedData texFetchTouch];
|
||||||
id<MTLTexture> texTouch = (selectedDisplaySource[NDSDisplayID_Touch] == NDSDisplayID_Touch) ? [sharedData texFetchTouch] : [sharedData texFetchMain];
|
id<MTLTexture> texTouch = (selectedDisplaySource[NDSDisplayID_Touch] == NDSDisplayID_Touch) ? [sharedData texFetchTouch] : [sharedData texFetchMain];
|
||||||
|
|
||||||
bool isDisplayProcessedMain = ![sharedData isUsingFramebufferDirectlyAtIndex:bufferIndex displayID:selectedDisplaySource[NDSDisplayID_Main]];
|
|
||||||
bool isDisplayProcessedTouch = ![sharedData isUsingFramebufferDirectlyAtIndex:bufferIndex displayID:selectedDisplaySource[NDSDisplayID_Touch]];
|
|
||||||
|
|
||||||
if ( (fetchDisplayInfo.pixelBytes != 0) && (useDeposterize || (cdp->GetPixelScaler() != VideoFilterTypeID_None)) )
|
if ( (fetchDisplayInfo.pixelBytes != 0) && (useDeposterize || (cdp->GetPixelScaler() != VideoFilterTypeID_None)) )
|
||||||
{
|
{
|
||||||
const bool willFilterOnGPU = cdp->WillFilterOnGPU();
|
const bool willFilterOnGPU = cdp->WillFilterOnGPU();
|
||||||
const bool shouldProcessDisplay[2] = { (!fetchDisplayInfo.didPerformCustomRender[selectedDisplaySource[NDSDisplayID_Main]] || !fetchDisplayInfo.isCustomSizeRequested) && cdp->IsSelectedDisplayEnabled(NDSDisplayID_Main) && (mode == ClientDisplayMode_Main || mode == ClientDisplayMode_Dual),
|
const bool shouldProcessDisplay[2] = { (!fetchDisplayInfo.didPerformCustomRender[selectedDisplaySource[NDSDisplayID_Main]] || !fetchDisplayInfo.isCustomSizeRequested) && cdp->IsSelectedDisplayEnabled(NDSDisplayID_Main) && (mode == ClientDisplayMode_Main || mode == ClientDisplayMode_Dual),
|
||||||
(!fetchDisplayInfo.didPerformCustomRender[selectedDisplaySource[NDSDisplayID_Touch]] || !fetchDisplayInfo.isCustomSizeRequested) && cdp->IsSelectedDisplayEnabled(NDSDisplayID_Touch) && (mode == ClientDisplayMode_Touch || mode == ClientDisplayMode_Dual) && (selectedDisplaySource[NDSDisplayID_Main] != selectedDisplaySource[NDSDisplayID_Touch]) };
|
(!fetchDisplayInfo.didPerformCustomRender[selectedDisplaySource[NDSDisplayID_Touch]] || !fetchDisplayInfo.isCustomSizeRequested) && cdp->IsSelectedDisplayEnabled(NDSDisplayID_Touch) && (mode == ClientDisplayMode_Touch || mode == ClientDisplayMode_Dual) && (selectedDisplaySource[NDSDisplayID_Main] != selectedDisplaySource[NDSDisplayID_Touch]) };
|
||||||
|
|
||||||
bool texFetchMainNeedsLock = (useDeposterize || ((cdp->GetPixelScaler() != VideoFilterTypeID_None) && willFilterOnGPU)) && shouldProcessDisplay[NDSDisplayID_Main];
|
|
||||||
bool texFetchTouchNeedsLock = (useDeposterize || ((cdp->GetPixelScaler() != VideoFilterTypeID_None) && willFilterOnGPU)) && shouldProcessDisplay[NDSDisplayID_Touch];
|
|
||||||
bool needsFetchBuffersLock = texFetchMainNeedsLock || texFetchTouchNeedsLock;
|
|
||||||
|
|
||||||
id<MTLCommandBuffer> cb = [self newCommandBuffer];
|
id<MTLCommandBuffer> cb = [self newCommandBuffer];
|
||||||
id<MTLComputeCommandEncoder> cce = [cb computeCommandEncoder];
|
id<MTLComputeCommandEncoder> cce = [cb computeCommandEncoder];
|
||||||
|
|
||||||
if (needsFetchBuffersLock)
|
|
||||||
{
|
|
||||||
pthread_rwlock_rdlock([sharedData rwlockFramebufferAtIndex:bufferIndex]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the video source filters and the pixel scalers
|
// Run the video source filters and the pixel scalers
|
||||||
if (useDeposterize)
|
if (useDeposterize)
|
||||||
{
|
{
|
||||||
|
@ -1353,12 +1346,10 @@
|
||||||
threadsPerThreadgroup:[sharedData deposterizeThreadsPerGroup]];
|
threadsPerThreadgroup:[sharedData deposterizeThreadsPerGroup]];
|
||||||
|
|
||||||
texMain = _texDisplaySrcDeposterize[NDSDisplayID_Main][1];
|
texMain = _texDisplaySrcDeposterize[NDSDisplayID_Main][1];
|
||||||
isDisplayProcessedMain = true;
|
|
||||||
|
|
||||||
if (selectedDisplaySource[NDSDisplayID_Main] == selectedDisplaySource[NDSDisplayID_Touch])
|
if (selectedDisplaySource[NDSDisplayID_Main] == selectedDisplaySource[NDSDisplayID_Touch])
|
||||||
{
|
{
|
||||||
texTouch = texMain;
|
texTouch = texMain;
|
||||||
isDisplayProcessedTouch = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1375,35 +1366,6 @@
|
||||||
threadsPerThreadgroup:[sharedData deposterizeThreadsPerGroup]];
|
threadsPerThreadgroup:[sharedData deposterizeThreadsPerGroup]];
|
||||||
|
|
||||||
texTouch = _texDisplaySrcDeposterize[NDSDisplayID_Touch][1];
|
texTouch = _texDisplaySrcDeposterize[NDSDisplayID_Touch][1];
|
||||||
isDisplayProcessedTouch = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needsFetchBuffersLock)
|
|
||||||
{
|
|
||||||
needsFetchBuffersLock = !isDisplayProcessedMain || !isDisplayProcessedTouch;
|
|
||||||
|
|
||||||
[cce endEncoding];
|
|
||||||
|
|
||||||
if (!needsFetchBuffersLock)
|
|
||||||
{
|
|
||||||
if (bufferIndex == 0)
|
|
||||||
{
|
|
||||||
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
|
||||||
pthread_rwlock_unlock([sharedData rwlockFramebufferAtIndex:0]);
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
|
||||||
pthread_rwlock_unlock([sharedData rwlockFramebufferAtIndex:1]);
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[cb commit];
|
|
||||||
|
|
||||||
cb = [self newCommandBuffer];
|
|
||||||
cce = [cb computeCommandEncoder];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1424,14 +1386,12 @@
|
||||||
texMain = [self texDisplayPixelScaleMain];
|
texMain = [self texDisplayPixelScaleMain];
|
||||||
width[NDSDisplayID_Main] = [[self texDisplayPixelScaleMain] width];
|
width[NDSDisplayID_Main] = [[self texDisplayPixelScaleMain] width];
|
||||||
height[NDSDisplayID_Main] = [[self texDisplayPixelScaleMain] height];
|
height[NDSDisplayID_Main] = [[self texDisplayPixelScaleMain] height];
|
||||||
isDisplayProcessedMain = true;
|
|
||||||
|
|
||||||
if (selectedDisplaySource[NDSDisplayID_Main] == selectedDisplaySource[NDSDisplayID_Touch])
|
if (selectedDisplaySource[NDSDisplayID_Main] == selectedDisplaySource[NDSDisplayID_Touch])
|
||||||
{
|
{
|
||||||
texTouch = texMain;
|
texTouch = texMain;
|
||||||
width[NDSDisplayID_Touch] = width[NDSDisplayID_Main];
|
width[NDSDisplayID_Touch] = width[NDSDisplayID_Main];
|
||||||
height[NDSDisplayID_Touch] = height[NDSDisplayID_Main];
|
height[NDSDisplayID_Touch] = height[NDSDisplayID_Main];
|
||||||
isDisplayProcessedTouch = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1445,32 +1405,6 @@
|
||||||
texTouch = [self texDisplayPixelScaleTouch];
|
texTouch = [self texDisplayPixelScaleTouch];
|
||||||
width[NDSDisplayID_Touch] = [[self texDisplayPixelScaleTouch] width];
|
width[NDSDisplayID_Touch] = [[self texDisplayPixelScaleTouch] width];
|
||||||
height[NDSDisplayID_Touch] = [[self texDisplayPixelScaleTouch] height];
|
height[NDSDisplayID_Touch] = [[self texDisplayPixelScaleTouch] height];
|
||||||
isDisplayProcessedTouch = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needsFetchBuffersLock)
|
|
||||||
{
|
|
||||||
needsFetchBuffersLock = false;
|
|
||||||
|
|
||||||
[cce endEncoding];
|
|
||||||
|
|
||||||
if (bufferIndex == 0)
|
|
||||||
{
|
|
||||||
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
|
||||||
pthread_rwlock_unlock([sharedData rwlockFramebufferAtIndex:0]);
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
|
||||||
pthread_rwlock_unlock([sharedData rwlockFramebufferAtIndex:1]);
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
[cb commit];
|
|
||||||
|
|
||||||
cb = [self newCommandBuffer];
|
|
||||||
cce = [cb computeCommandEncoder];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1529,7 +1463,7 @@
|
||||||
|
|
||||||
if (shouldProcessDisplay[NDSDisplayID_Main] && ([self texDisplayPixelScaleMain] != nil))
|
if (shouldProcessDisplay[NDSDisplayID_Main] && ([self texDisplayPixelScaleMain] != nil))
|
||||||
{
|
{
|
||||||
pthread_rwlock_rdlock(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterRWLock(NDSDisplayID_Main, bufferIndex));
|
sem_wait(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Main, bufferIndex));
|
||||||
needsCPUFilterUnlockMain = true;
|
needsCPUFilterUnlockMain = true;
|
||||||
vfMain->RunFilter();
|
vfMain->RunFilter();
|
||||||
|
|
||||||
|
@ -1537,7 +1471,7 @@
|
||||||
{
|
{
|
||||||
[[self bufCPUFilterDstMain] didModifyRange:NSMakeRange(0, vfMain->GetDstWidth() * vfMain->GetDstHeight() * sizeof(uint32_t))];
|
[[self bufCPUFilterDstMain] didModifyRange:NSMakeRange(0, vfMain->GetDstWidth() * vfMain->GetDstHeight() * sizeof(uint32_t))];
|
||||||
needsCPUFilterUnlockMain = false;
|
needsCPUFilterUnlockMain = false;
|
||||||
pthread_rwlock_unlock(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterRWLock(NDSDisplayID_Main, bufferIndex));
|
sem_post(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Main, bufferIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
[bce copyFromBuffer:[self bufCPUFilterDstMain]
|
[bce copyFromBuffer:[self bufCPUFilterDstMain]
|
||||||
|
@ -1553,20 +1487,18 @@
|
||||||
texMain = [self texDisplayPixelScaleMain];
|
texMain = [self texDisplayPixelScaleMain];
|
||||||
width[NDSDisplayID_Main] = [[self texDisplayPixelScaleMain] width];
|
width[NDSDisplayID_Main] = [[self texDisplayPixelScaleMain] width];
|
||||||
height[NDSDisplayID_Main] = [[self texDisplayPixelScaleMain] height];
|
height[NDSDisplayID_Main] = [[self texDisplayPixelScaleMain] height];
|
||||||
isDisplayProcessedMain = true;
|
|
||||||
|
|
||||||
if (selectedDisplaySource[NDSDisplayID_Main] == selectedDisplaySource[NDSDisplayID_Touch])
|
if (selectedDisplaySource[NDSDisplayID_Main] == selectedDisplaySource[NDSDisplayID_Touch])
|
||||||
{
|
{
|
||||||
texTouch = texMain;
|
texTouch = texMain;
|
||||||
width[NDSDisplayID_Touch] = width[NDSDisplayID_Main];
|
width[NDSDisplayID_Touch] = width[NDSDisplayID_Main];
|
||||||
height[NDSDisplayID_Touch] = height[NDSDisplayID_Main];
|
height[NDSDisplayID_Touch] = height[NDSDisplayID_Main];
|
||||||
isDisplayProcessedTouch = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldProcessDisplay[NDSDisplayID_Touch] && ([self texDisplayPixelScaleTouch] != nil))
|
if (shouldProcessDisplay[NDSDisplayID_Touch] && ([self texDisplayPixelScaleTouch] != nil))
|
||||||
{
|
{
|
||||||
pthread_rwlock_rdlock(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterRWLock(NDSDisplayID_Touch, bufferIndex));
|
sem_wait(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Touch, bufferIndex));
|
||||||
needsCPUFilterUnlockTouch = true;
|
needsCPUFilterUnlockTouch = true;
|
||||||
vfTouch->RunFilter();
|
vfTouch->RunFilter();
|
||||||
|
|
||||||
|
@ -1574,7 +1506,7 @@
|
||||||
{
|
{
|
||||||
[[self bufCPUFilterDstTouch] didModifyRange:NSMakeRange(0, vfTouch->GetDstWidth() * vfTouch->GetDstHeight() * sizeof(uint32_t))];
|
[[self bufCPUFilterDstTouch] didModifyRange:NSMakeRange(0, vfTouch->GetDstWidth() * vfTouch->GetDstHeight() * sizeof(uint32_t))];
|
||||||
needsCPUFilterUnlockTouch = false;
|
needsCPUFilterUnlockTouch = false;
|
||||||
pthread_rwlock_unlock(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterRWLock(NDSDisplayID_Touch, bufferIndex));
|
sem_post(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Touch, bufferIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
[bce copyFromBuffer:[self bufCPUFilterDstTouch]
|
[bce copyFromBuffer:[self bufCPUFilterDstTouch]
|
||||||
|
@ -1590,7 +1522,6 @@
|
||||||
texTouch = [self texDisplayPixelScaleTouch];
|
texTouch = [self texDisplayPixelScaleTouch];
|
||||||
width[NDSDisplayID_Touch] = [[self texDisplayPixelScaleTouch] width];
|
width[NDSDisplayID_Touch] = [[self texDisplayPixelScaleTouch] width];
|
||||||
height[NDSDisplayID_Touch] = [[self texDisplayPixelScaleTouch] height];
|
height[NDSDisplayID_Touch] = [[self texDisplayPixelScaleTouch] height];
|
||||||
isDisplayProcessedTouch = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[bce endEncoding];
|
[bce endEncoding];
|
||||||
|
@ -1605,15 +1536,15 @@
|
||||||
if (bufferIndex == 0)
|
if (bufferIndex == 0)
|
||||||
{
|
{
|
||||||
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
||||||
pthread_rwlock_unlock(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterRWLock(NDSDisplayID_Main, 0));
|
sem_post(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Main, 0));
|
||||||
pthread_rwlock_unlock(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterRWLock(NDSDisplayID_Touch, 0));
|
sem_post(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Touch, 0));
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
||||||
pthread_rwlock_unlock(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterRWLock(NDSDisplayID_Main, 1));
|
sem_post(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Main, 1));
|
||||||
pthread_rwlock_unlock(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterRWLock(NDSDisplayID_Touch, 1));
|
sem_post(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Touch, 1));
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1622,13 +1553,13 @@
|
||||||
if (bufferIndex == 0)
|
if (bufferIndex == 0)
|
||||||
{
|
{
|
||||||
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
||||||
pthread_rwlock_unlock(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterRWLock(NDSDisplayID_Main, 0));
|
sem_post(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Main, 0));
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
||||||
pthread_rwlock_unlock(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterRWLock(NDSDisplayID_Main, 1));
|
sem_post(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Main, 1));
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1638,13 +1569,13 @@
|
||||||
if (bufferIndex == 0)
|
if (bufferIndex == 0)
|
||||||
{
|
{
|
||||||
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
||||||
pthread_rwlock_unlock(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterRWLock(NDSDisplayID_Touch, 0));
|
sem_post(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Touch, 0));
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
||||||
pthread_rwlock_unlock(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterRWLock(NDSDisplayID_Touch, 1));
|
sem_post(((MacMetalDisplayPresenter *)cdp)->GetCPUFilterSemaphore(NDSDisplayID_Touch, 1));
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1653,27 +1584,30 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the texture coordinates
|
// Update the texture coordinates
|
||||||
pthread_mutex_lock(&_mutexTexProcessUpdate);
|
sem_wait(_semTexProcessUpdate);
|
||||||
|
|
||||||
cdp->SetScreenTextureCoordinates((float)width[NDSDisplayID_Main], (float)height[NDSDisplayID_Main],
|
|
||||||
(float)width[NDSDisplayID_Touch], (float)height[NDSDisplayID_Touch],
|
|
||||||
(float *)[_displayTexCoordBuffer contents]);
|
|
||||||
[_displayTexCoordBuffer didModifyRange:NSMakeRange(0, sizeof(float) * (4 * 8))];
|
|
||||||
|
|
||||||
// Update the frame info
|
// Update the frame info
|
||||||
id<MTLTexture> oldDisplayProcessedMain = _processedFrameInfo.tex[NDSDisplayID_Main];
|
id<MTLTexture> oldDisplayProcessedMain = _processedFrameInfo.tex[NDSDisplayID_Main];
|
||||||
id<MTLTexture> oldDisplayProcessedTouch = _processedFrameInfo.tex[NDSDisplayID_Touch];
|
id<MTLTexture> oldDisplayProcessedTouch = _processedFrameInfo.tex[NDSDisplayID_Touch];
|
||||||
|
|
||||||
_processedFrameInfo.bufferIndex = bufferIndex;
|
_processedFrameInfo.bufferIndex = bufferIndex;
|
||||||
_processedFrameInfo.isMainDisplayProcessed = isDisplayProcessedMain;
|
|
||||||
_processedFrameInfo.isTouchDisplayProcessed = isDisplayProcessedTouch;
|
|
||||||
_processedFrameInfo.tex[NDSDisplayID_Main] = [texMain retain];
|
_processedFrameInfo.tex[NDSDisplayID_Main] = [texMain retain];
|
||||||
_processedFrameInfo.tex[NDSDisplayID_Touch] = [texTouch retain];
|
_processedFrameInfo.tex[NDSDisplayID_Touch] = [texTouch retain];
|
||||||
|
|
||||||
|
[self updateTexCoordBuffer];
|
||||||
|
|
||||||
[oldDisplayProcessedMain release];
|
[oldDisplayProcessedMain release];
|
||||||
[oldDisplayProcessedTouch release];
|
[oldDisplayProcessedTouch release];
|
||||||
|
|
||||||
pthread_mutex_unlock(&_mutexTexProcessUpdate);
|
sem_post(_semTexProcessUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) updateTexCoordBuffer
|
||||||
|
{
|
||||||
|
cdp->SetScreenTextureCoordinates((float)[_processedFrameInfo.tex[NDSDisplayID_Main] width], (float)[_processedFrameInfo.tex[NDSDisplayID_Main] height],
|
||||||
|
(float)[_processedFrameInfo.tex[NDSDisplayID_Touch] width], (float)[_processedFrameInfo.tex[NDSDisplayID_Touch] height],
|
||||||
|
(float *)[_displayTexCoordBuffer contents]);
|
||||||
|
[_displayTexCoordBuffer didModifyRange:NSMakeRange(0, sizeof(float) * (4 * 8))];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) updateRenderBuffers
|
- (void) updateRenderBuffers
|
||||||
|
@ -1690,8 +1624,6 @@
|
||||||
newViewport.znear = 0.0;
|
newViewport.znear = 0.0;
|
||||||
newViewport.zfar = 1.0;
|
newViewport.zfar = 1.0;
|
||||||
|
|
||||||
pthread_mutex_lock(&_mutexBufferUpdate);
|
|
||||||
|
|
||||||
if ([self needsViewportUpdate])
|
if ([self needsViewportUpdate])
|
||||||
{
|
{
|
||||||
needEncodeViewport = true;
|
needEncodeViewport = true;
|
||||||
|
@ -1790,8 +1722,6 @@
|
||||||
_willDrawHUDInput = cdp->GetHUDShowInput();
|
_willDrawHUDInput = cdp->GetHUDShowInput();
|
||||||
_hudStringLength = cdp->GetHUDString().length();
|
_hudStringLength = cdp->GetHUDString().length();
|
||||||
_hudTouchLineLength = hudTouchLineLength;
|
_hudTouchLineLength = hudTouchLineLength;
|
||||||
|
|
||||||
pthread_mutex_unlock(&_mutexBufferUpdate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) renderForCommandBuffer:(id<MTLCommandBuffer>)cb
|
- (void) renderForCommandBuffer:(id<MTLCommandBuffer>)cb
|
||||||
|
@ -1943,6 +1873,17 @@
|
||||||
const size_t clientWidth = cdp->GetPresenterProperties().clientWidth;
|
const size_t clientWidth = cdp->GetPresenterProperties().clientWidth;
|
||||||
const size_t clientHeight = cdp->GetPresenterProperties().clientHeight;
|
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!");
|
||||||
|
}
|
||||||
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
MTLTextureDescriptor *texRenderDesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm
|
MTLTextureDescriptor *texRenderDesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm
|
||||||
|
@ -1956,19 +1897,13 @@
|
||||||
id<MTLTexture> texRender = [[sharedData device] newTextureWithDescriptor:texRenderDesc];
|
id<MTLTexture> texRender = [[sharedData device] newTextureWithDescriptor:texRenderDesc];
|
||||||
id<MTLBuffer> dstMTLBuffer = [[sharedData device] newBufferWithLength:clientWidth * clientHeight * sizeof(uint32_t) options:MTLResourceStorageModeManaged];
|
id<MTLBuffer> dstMTLBuffer = [[sharedData device] newBufferWithLength:clientWidth * clientHeight * sizeof(uint32_t) options:MTLResourceStorageModeManaged];
|
||||||
|
|
||||||
pthread_mutex_lock(&_mutexTexProcessUpdate);
|
sem_wait(_semTexProcessUpdate);
|
||||||
|
|
||||||
const bool needsFetchBuffersLock = !_processedFrameInfo.isMainDisplayProcessed || !_processedFrameInfo.isTouchDisplayProcessed;
|
|
||||||
if (needsFetchBuffersLock)
|
|
||||||
{
|
|
||||||
pthread_rwlock_rdlock([sharedData rwlockFramebufferAtIndex:_processedFrameInfo.bufferIndex]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now that everything is set up, go ahead and draw everything.
|
// Now that everything is set up, go ahead and draw everything.
|
||||||
[colorAttachment0Desc setTexture:texRender];
|
[colorAttachment0Desc setTexture:texRender];
|
||||||
id<MTLCommandBuffer> cb = [self newCommandBuffer];
|
id<MTLCommandBuffer> cb = [self newCommandBuffer];
|
||||||
|
|
||||||
pthread_mutex_lock(&_mutexBufferUpdate);
|
[self updateRenderBuffers];
|
||||||
|
|
||||||
[self renderForCommandBuffer:cb
|
[self renderForCommandBuffer:cb
|
||||||
outputPipelineState:[self outputRGBAPipeline]
|
outputPipelineState:[self outputRGBAPipeline]
|
||||||
|
@ -1976,35 +1911,13 @@
|
||||||
texDisplayMain:_processedFrameInfo.tex[NDSDisplayID_Main]
|
texDisplayMain:_processedFrameInfo.tex[NDSDisplayID_Main]
|
||||||
texDisplayTouch:_processedFrameInfo.tex[NDSDisplayID_Touch]];
|
texDisplayTouch:_processedFrameInfo.tex[NDSDisplayID_Touch]];
|
||||||
|
|
||||||
if (needsFetchBuffersLock)
|
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
||||||
{
|
sem_post(_semTexProcessUpdate);
|
||||||
if (_processedFrameInfo.bufferIndex == 0)
|
}];
|
||||||
{
|
|
||||||
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
|
||||||
pthread_mutex_unlock(&_mutexBufferUpdate);
|
|
||||||
pthread_rwlock_unlock([sharedData rwlockFramebufferAtIndex:0]);
|
|
||||||
pthread_mutex_unlock(&_mutexTexProcessUpdate);
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
|
||||||
pthread_mutex_unlock(&_mutexBufferUpdate);
|
|
||||||
pthread_rwlock_unlock([sharedData rwlockFramebufferAtIndex:1]);
|
|
||||||
pthread_mutex_unlock(&_mutexTexProcessUpdate);
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
|
||||||
pthread_mutex_unlock(&_mutexBufferUpdate);
|
|
||||||
pthread_mutex_unlock(&_mutexTexProcessUpdate);
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
[cb commit];
|
[cb commit];
|
||||||
|
|
||||||
|
sem_wait(semRenderToBuffer);
|
||||||
|
|
||||||
cb = [self newCommandBuffer];
|
cb = [self newCommandBuffer];
|
||||||
id<MTLBlitCommandEncoder> bce = [cb blitCommandEncoder];
|
id<MTLBlitCommandEncoder> bce = [cb blitCommandEncoder];
|
||||||
|
|
||||||
|
@ -2021,14 +1934,23 @@
|
||||||
[bce synchronizeResource:dstMTLBuffer];
|
[bce synchronizeResource:dstMTLBuffer];
|
||||||
[bce endEncoding];
|
[bce endEncoding];
|
||||||
|
|
||||||
|
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
||||||
|
sem_post(semRenderToBuffer);
|
||||||
|
}];
|
||||||
[cb commit];
|
[cb commit];
|
||||||
[cb waitUntilCompleted];
|
|
||||||
|
// Wait on this thread until the GPU completes its task, then continue execution on this thread.
|
||||||
|
sem_wait(semRenderToBuffer);
|
||||||
|
sem_post(semRenderToBuffer);
|
||||||
|
|
||||||
memcpy(dstBuffer, [dstMTLBuffer contents], clientWidth * clientHeight * sizeof(uint32_t));
|
memcpy(dstBuffer, [dstMTLBuffer contents], clientWidth * clientHeight * sizeof(uint32_t));
|
||||||
|
|
||||||
[texRender release];
|
[texRender release];
|
||||||
[dstMTLBuffer release];
|
[dstMTLBuffer release];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sem_close(semRenderToBuffer);
|
||||||
|
sem_unlink(semaphoreName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -2073,20 +1995,16 @@
|
||||||
{
|
{
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
pthread_mutex_lock([presenterObject mutexTexProcessUpdate]);
|
sem_wait([presenterObject semTexProcessUpdate]);
|
||||||
|
|
||||||
const MetalProcessedFrameInfo &processedInfo = [presenterObject processedFrameInfo];
|
const MetalProcessedFrameInfo &processedInfo = [presenterObject processedFrameInfo];
|
||||||
const bool needsFetchBuffersLock = !processedInfo.isMainDisplayProcessed || !processedInfo.isTouchDisplayProcessed;
|
|
||||||
if (needsFetchBuffersLock)
|
|
||||||
{
|
|
||||||
pthread_rwlock_rdlock([[presenterObject sharedData] rwlockFramebufferAtIndex:processedInfo.bufferIndex]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now that everything is set up, go ahead and draw everything.
|
// Now that everything is set up, go ahead and draw everything.
|
||||||
id<CAMetalDrawable> layerDrawable = [self nextDrawable];
|
id<CAMetalDrawable> layerDrawable = [self nextDrawable];
|
||||||
[[presenterObject colorAttachment0Desc] setTexture:[layerDrawable texture]];
|
[[presenterObject colorAttachment0Desc] setTexture:[layerDrawable texture]];
|
||||||
id<MTLCommandBuffer> cb = [presenterObject newCommandBuffer];
|
id<MTLCommandBuffer> cb = [presenterObject newCommandBuffer];
|
||||||
pthread_mutex_lock([presenterObject mutexBufferUpdate]);
|
|
||||||
|
[presenterObject updateRenderBuffers];
|
||||||
|
|
||||||
[presenterObject renderForCommandBuffer:cb
|
[presenterObject renderForCommandBuffer:cb
|
||||||
outputPipelineState:[presenterObject outputDrawablePipeline]
|
outputPipelineState:[presenterObject outputDrawablePipeline]
|
||||||
|
@ -2096,32 +2014,9 @@
|
||||||
|
|
||||||
[cb presentDrawable:layerDrawable];
|
[cb presentDrawable:layerDrawable];
|
||||||
|
|
||||||
if (needsFetchBuffersLock)
|
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
||||||
{
|
sem_post([presenterObject semTexProcessUpdate]);
|
||||||
if (processedInfo.bufferIndex == 0)
|
}];
|
||||||
{
|
|
||||||
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
|
||||||
pthread_mutex_unlock([presenterObject mutexBufferUpdate]);
|
|
||||||
pthread_rwlock_unlock([[presenterObject sharedData] rwlockFramebufferAtIndex:0]);
|
|
||||||
pthread_mutex_unlock([presenterObject mutexTexProcessUpdate]);
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
|
||||||
pthread_mutex_unlock([presenterObject mutexBufferUpdate]);
|
|
||||||
pthread_rwlock_unlock([[presenterObject sharedData] rwlockFramebufferAtIndex:1]);
|
|
||||||
pthread_mutex_unlock([presenterObject mutexTexProcessUpdate]);
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
|
||||||
pthread_mutex_unlock([presenterObject mutexBufferUpdate]);
|
|
||||||
pthread_mutex_unlock([presenterObject mutexTexProcessUpdate]);
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
[cb commit];
|
[cb commit];
|
||||||
}
|
}
|
||||||
|
@ -2265,10 +2160,14 @@ MacMetalDisplayPresenter::~MacMetalDisplayPresenter()
|
||||||
|
|
||||||
pthread_mutex_destroy(&this->_mutexProcessPtr);
|
pthread_mutex_destroy(&this->_mutexProcessPtr);
|
||||||
|
|
||||||
pthread_rwlock_destroy(&this->_cpuFilterRWLock[NDSDisplayID_Main][0]);
|
sem_close(this->_semCPUFilter[NDSDisplayID_Main][0]);
|
||||||
pthread_rwlock_destroy(&this->_cpuFilterRWLock[NDSDisplayID_Touch][0]);
|
sem_close(this->_semCPUFilter[NDSDisplayID_Main][1]);
|
||||||
pthread_rwlock_destroy(&this->_cpuFilterRWLock[NDSDisplayID_Main][1]);
|
sem_close(this->_semCPUFilter[NDSDisplayID_Touch][0]);
|
||||||
pthread_rwlock_destroy(&this->_cpuFilterRWLock[NDSDisplayID_Touch][1]);
|
sem_close(this->_semCPUFilter[NDSDisplayID_Touch][1]);
|
||||||
|
sem_unlink("desmume_semCPUFilterMain0");
|
||||||
|
sem_unlink("desmume_semCPUFilterMain1");
|
||||||
|
sem_unlink("desmume_semCPUFilterTouch0");
|
||||||
|
sem_unlink("desmume_semCPUFilterTouch1");
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacMetalDisplayPresenter::__InstanceInit(MacClientSharedObject *sharedObject)
|
void MacMetalDisplayPresenter::__InstanceInit(MacClientSharedObject *sharedObject)
|
||||||
|
@ -2286,10 +2185,49 @@ void MacMetalDisplayPresenter::__InstanceInit(MacClientSharedObject *sharedObjec
|
||||||
|
|
||||||
pthread_mutex_init(&_mutexProcessPtr, NULL);
|
pthread_mutex_init(&_mutexProcessPtr, NULL);
|
||||||
|
|
||||||
pthread_rwlock_init(&_cpuFilterRWLock[NDSDisplayID_Main][0], NULL);
|
_semCPUFilter[NDSDisplayID_Main][0] = sem_open("desmume_semCPUFilterMain0", O_CREAT | O_EXCL, 0777, 1);
|
||||||
pthread_rwlock_init(&_cpuFilterRWLock[NDSDisplayID_Touch][0], NULL);
|
if (_semCPUFilter[NDSDisplayID_Main][0] == SEM_FAILED)
|
||||||
pthread_rwlock_init(&_cpuFilterRWLock[NDSDisplayID_Main][1], NULL);
|
{
|
||||||
pthread_rwlock_init(&_cpuFilterRWLock[NDSDisplayID_Touch][1], NULL);
|
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!");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacMetalDisplayPresenter::_UpdateNormalSize()
|
void MacMetalDisplayPresenter::_UpdateNormalSize()
|
||||||
|
@ -2329,9 +2267,9 @@ void MacMetalDisplayPresenter::_LoadNativeDisplayByID(const NDSDisplayID display
|
||||||
|
|
||||||
const uint8_t bufferIndex = fetchObjMutable.GetLastFetchIndex();
|
const uint8_t bufferIndex = fetchObjMutable.GetLastFetchIndex();
|
||||||
|
|
||||||
pthread_rwlock_wrlock(&this->_cpuFilterRWLock[displayID][bufferIndex]);
|
sem_wait(this->_semCPUFilter[displayID][bufferIndex]);
|
||||||
fetchObjMutable.CopyFromSrcClone(vf->GetSrcBufferPtr(), displayID, bufferIndex);
|
fetchObjMutable.CopyFromSrcClone(vf->GetSrcBufferPtr(), displayID, bufferIndex);
|
||||||
pthread_rwlock_unlock(&this->_cpuFilterRWLock[displayID][bufferIndex]);
|
sem_post(this->_semCPUFilter[displayID][bufferIndex]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2351,9 +2289,9 @@ pthread_mutex_t* MacMetalDisplayPresenter::GetMutexProcessPtr()
|
||||||
return &this->_mutexProcessPtr;
|
return &this->_mutexProcessPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_rwlock_t* MacMetalDisplayPresenter::GetCPUFilterRWLock(const NDSDisplayID displayID, const uint8_t bufferIndex)
|
sem_t* MacMetalDisplayPresenter::GetCPUFilterSemaphore(const NDSDisplayID displayID, const uint8_t bufferIndex)
|
||||||
{
|
{
|
||||||
return &this->_cpuFilterRWLock[displayID][bufferIndex];
|
return this->_semCPUFilter[displayID][bufferIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacMetalDisplayPresenter::Init()
|
void MacMetalDisplayPresenter::Init()
|
||||||
|
@ -2406,11 +2344,6 @@ void MacMetalDisplayPresenter::ProcessDisplays()
|
||||||
[this->_presenterObject processDisplays];
|
[this->_presenterObject processDisplays];
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacMetalDisplayPresenter::UpdateLayout()
|
|
||||||
{
|
|
||||||
[this->_presenterObject updateRenderBuffers];
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacMetalDisplayPresenter::CopyFrameToBuffer(uint32_t *dstBuffer)
|
void MacMetalDisplayPresenter::CopyFrameToBuffer(uint32_t *dstBuffer)
|
||||||
{
|
{
|
||||||
[this->_presenterObject renderToBuffer:dstBuffer];
|
[this->_presenterObject renderToBuffer:dstBuffer];
|
||||||
|
|
|
@ -513,6 +513,19 @@ kernel void nds_fetch666ConvertOnly(const uint2 position [[thread_position_in_gr
|
||||||
outTexture.write(float4(outColor, 1.0f), position);
|
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)
|
float3 nds_apply_master_brightness(const float3 inColor, const uchar mode, const float intensity)
|
||||||
{
|
{
|
||||||
switch (mode)
|
switch (mode)
|
||||||
|
|
|
@ -194,14 +194,14 @@ void MacOGLClientFetchObject::FetchFromBufferIndex(const u8 index)
|
||||||
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)this->_clientData;
|
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)this->_clientData;
|
||||||
this->_useDirectToCPUFilterPipeline = ([sharedViewObject numberViewsUsingDirectToCPUFiltering] > 0);
|
this->_useDirectToCPUFilterPipeline = ([sharedViewObject numberViewsUsingDirectToCPUFiltering] > 0);
|
||||||
|
|
||||||
pthread_rwlock_rdlock([sharedViewObject rwlockFramebufferAtIndex:index]);
|
sem_wait([sharedViewObject semaphoreFramebufferAtIndex:index]);
|
||||||
|
|
||||||
CGLLockContext(this->_context);
|
CGLLockContext(this->_context);
|
||||||
CGLSetCurrentContext(this->_context);
|
CGLSetCurrentContext(this->_context);
|
||||||
this->OGLClientFetchObject::FetchFromBufferIndex(index);
|
this->OGLClientFetchObject::FetchFromBufferIndex(index);
|
||||||
CGLUnlockContext(this->_context);
|
CGLUnlockContext(this->_context);
|
||||||
|
|
||||||
pthread_rwlock_unlock([sharedViewObject rwlockFramebufferAtIndex:index]);
|
sem_post([sharedViewObject semaphoreFramebufferAtIndex:index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint MacOGLClientFetchObject::GetFetchTexture(const NDSDisplayID displayID)
|
GLuint MacOGLClientFetchObject::GetFetchTexture(const NDSDisplayID displayID)
|
||||||
|
@ -435,7 +435,7 @@ void MacOGLDisplayPresenter::WriteLockEmuFramebuffer(const uint8_t bufferIndex)
|
||||||
const GPUClientFetchObject &fetchObj = this->GetFetchObject();
|
const GPUClientFetchObject &fetchObj = this->GetFetchObject();
|
||||||
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)fetchObj.GetClientData();
|
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)fetchObj.GetClientData();
|
||||||
|
|
||||||
pthread_rwlock_wrlock([sharedViewObject rwlockFramebufferAtIndex:bufferIndex]);
|
sem_wait([sharedViewObject semaphoreFramebufferAtIndex:bufferIndex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacOGLDisplayPresenter::ReadLockEmuFramebuffer(const uint8_t bufferIndex)
|
void MacOGLDisplayPresenter::ReadLockEmuFramebuffer(const uint8_t bufferIndex)
|
||||||
|
@ -443,7 +443,7 @@ void MacOGLDisplayPresenter::ReadLockEmuFramebuffer(const uint8_t bufferIndex)
|
||||||
const GPUClientFetchObject &fetchObj = this->GetFetchObject();
|
const GPUClientFetchObject &fetchObj = this->GetFetchObject();
|
||||||
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)fetchObj.GetClientData();
|
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)fetchObj.GetClientData();
|
||||||
|
|
||||||
pthread_rwlock_rdlock([sharedViewObject rwlockFramebufferAtIndex:bufferIndex]);
|
sem_wait([sharedViewObject semaphoreFramebufferAtIndex:bufferIndex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacOGLDisplayPresenter::UnlockEmuFramebuffer(const uint8_t bufferIndex)
|
void MacOGLDisplayPresenter::UnlockEmuFramebuffer(const uint8_t bufferIndex)
|
||||||
|
@ -451,7 +451,7 @@ void MacOGLDisplayPresenter::UnlockEmuFramebuffer(const uint8_t bufferIndex)
|
||||||
const GPUClientFetchObject &fetchObj = this->GetFetchObject();
|
const GPUClientFetchObject &fetchObj = this->GetFetchObject();
|
||||||
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)fetchObj.GetClientData();
|
MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)fetchObj.GetClientData();
|
||||||
|
|
||||||
pthread_rwlock_unlock([sharedViewObject rwlockFramebufferAtIndex:bufferIndex]);
|
sem_post([sharedViewObject semaphoreFramebufferAtIndex:bufferIndex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
Loading…
Reference in New Issue