Cocoa Port:
- Throttle execution speed using mach_wait_until() instead of usleep(). This improves execution timing, and reduces screen tearing when running the video at >= 60FPS. - Improve thread safety when changing the execution speed. - Do some miscellaneous minor optimizations to the execution loop and frame skip.
This commit is contained in:
parent
7ae952f366
commit
f6f1678eca
|
@ -120,5 +120,5 @@ typedef struct
|
|||
|
||||
@end
|
||||
|
||||
void* RunCoreThread(void *arg);
|
||||
void CoreFrameSkip(uint64_t timeBudgetMachAbsoluteTime, uint64_t frameStartMachAbsoluteTime, unsigned int *outFramesToSkip);
|
||||
static void* RunCoreThread(void *arg);
|
||||
static void CoreFrameSkip(uint64_t timeBudgetMachAbsoluteTime, uint64_t frameStartMachAbsoluteTime, unsigned int *outFramesToSkip);
|
||||
|
|
|
@ -642,23 +642,25 @@ static BOOL isCoreStarted = NO;
|
|||
|
||||
@end
|
||||
|
||||
void* RunCoreThread(void *arg)
|
||||
static void* RunCoreThread(void *arg)
|
||||
{
|
||||
CoreThreadParam *param = (CoreThreadParam *)arg;
|
||||
CocoaDSCore *cdsCore = (CocoaDSCore *)param->cdsCore;
|
||||
NSMutableArray *cdsOutputList = [cdsCore cdsOutputList];
|
||||
uint64_t startTime = 0;
|
||||
uint64_t elapsedMachAbsTime;
|
||||
uint64_t timeBudget = 0; // Need local variable to ensure that param->timeBudgetMachAbsTime is thread-safe.
|
||||
|
||||
do
|
||||
{
|
||||
startTime = mach_absolute_time();
|
||||
pthread_mutex_lock(¶m->mutexThreadExecute);
|
||||
timeBudget = param->timeBudgetMachAbsTime;
|
||||
|
||||
while (!(param->state == CORESTATE_EXECUTE && execute && !param->exitThread))
|
||||
{
|
||||
pthread_cond_wait(¶m->condThreadExecute, ¶m->mutexThreadExecute);
|
||||
startTime = mach_absolute_time();
|
||||
timeBudget = param->timeBudgetMachAbsTime;
|
||||
}
|
||||
|
||||
if (param->exitThread)
|
||||
|
@ -708,20 +710,15 @@ void* RunCoreThread(void *arg)
|
|||
// we owe on timeBudget.
|
||||
if (param->isFrameSkipEnabled)
|
||||
{
|
||||
CoreFrameSkip(param->timeBudgetMachAbsTime, startTime, ¶m->framesToSkip);
|
||||
CoreFrameSkip(timeBudget, startTime, ¶m->framesToSkip);
|
||||
}
|
||||
|
||||
// If there is any time left in the loop, go ahead and pad it.
|
||||
elapsedMachAbsTime = mach_absolute_time() - startTime;
|
||||
|
||||
pthread_mutex_unlock(¶m->mutexThreadExecute);
|
||||
|
||||
if(param->timeBudgetMachAbsTime > elapsedMachAbsTime)
|
||||
// If there is any time left in the loop, go ahead and pad it.
|
||||
if(timeBudget > (mach_absolute_time() - startTime))
|
||||
{
|
||||
uint64_t padMachAbsTime = param->timeBudgetMachAbsTime - elapsedMachAbsTime;
|
||||
Nanoseconds padNanoseconds = AbsoluteToNanoseconds(*(AbsoluteTime *)&padMachAbsTime);
|
||||
useconds_t padMicroseconds = (useconds_t)(*(uint64_t *)&padNanoseconds / 1000);
|
||||
usleep(padMicroseconds);
|
||||
mach_wait_until(startTime + timeBudget);
|
||||
}
|
||||
|
||||
} while (!param->exitThread);
|
||||
|
@ -729,10 +726,8 @@ void* RunCoreThread(void *arg)
|
|||
return nil;
|
||||
}
|
||||
|
||||
void CoreFrameSkip(uint64_t timeBudgetMachAbsTime, uint64_t frameStartMachAbsTime, unsigned int *outFramesToSkip)
|
||||
static void CoreFrameSkip(uint64_t timeBudgetMachAbsTime, uint64_t frameStartMachAbsTime, unsigned int *outFramesToSkip)
|
||||
{
|
||||
static unsigned int lastSetFrameSkip = 0;
|
||||
|
||||
if (*outFramesToSkip > 0)
|
||||
{
|
||||
NDS_SkipNextFrame();
|
||||
|
@ -740,13 +735,14 @@ void CoreFrameSkip(uint64_t timeBudgetMachAbsTime, uint64_t frameStartMachAbsTim
|
|||
}
|
||||
else
|
||||
{
|
||||
unsigned int framesToSkip = 0;
|
||||
|
||||
// Calculate the time remaining.
|
||||
uint64_t elapsed = mach_absolute_time() - frameStartMachAbsTime;
|
||||
|
||||
if (elapsed > timeBudgetMachAbsTime)
|
||||
{
|
||||
static unsigned int lastSetFrameSkip = 0;
|
||||
unsigned int framesToSkip = 0;
|
||||
|
||||
if (timeBudgetMachAbsTime > 0)
|
||||
{
|
||||
framesToSkip = (unsigned int)( (((double)(elapsed - timeBudgetMachAbsTime) * FRAME_SKIP_AGGRESSIVENESS) / (double)timeBudgetMachAbsTime) + FRAME_SKIP_BIAS );
|
||||
|
@ -770,8 +766,12 @@ void CoreFrameSkip(uint64_t timeBudgetMachAbsTime, uint64_t frameStartMachAbsTim
|
|||
framesToSkip = (unsigned int)MAX_FRAME_SKIP;
|
||||
lastSetFrameSkip = framesToSkip;
|
||||
}
|
||||
|
||||
*outFramesToSkip = framesToSkip;
|
||||
}
|
||||
else
|
||||
{
|
||||
*outFramesToSkip = 0;
|
||||
}
|
||||
|
||||
*outFramesToSkip = framesToSkip;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue