vblankmanager: Track latent frames
This commit is contained in:
parent
765ddd74b1
commit
7ec498af0a
3 changed files with 44 additions and 25 deletions
|
@ -253,7 +253,7 @@ void steamcompmgr_fpslimit_add_commit( std::shared_ptr<commit_t> commit )
|
||||||
g_FrameLimitCommits.push( commit );
|
g_FrameLimitCommits.push( commit );
|
||||||
}
|
}
|
||||||
|
|
||||||
void steamcompmgr_fpslimit_release_commit( int consecutive_missed_frame_count )
|
bool steamcompmgr_fpslimit_release_commit( int consecutive_missed_frame_count )
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(g_FrameLimitCommitsMutex);
|
std::unique_lock<std::mutex> lock(g_FrameLimitCommitsMutex);
|
||||||
|
|
||||||
|
@ -265,19 +265,23 @@ void steamcompmgr_fpslimit_release_commit( int consecutive_missed_frame_count )
|
||||||
g_FrameLimitCommits = std::queue< std::shared_ptr<commit_t> >();
|
g_FrameLimitCommits = std::queue< std::shared_ptr<commit_t> >();
|
||||||
g_nAppBufferCount = 0;
|
g_nAppBufferCount = 0;
|
||||||
g_nMaxAppBufferCount = 0;
|
g_nMaxAppBufferCount = 0;
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only allow 1 latent buffer -- essentially go to only "double
|
// Only allow 1 latent buffer -- essentially go to only "double
|
||||||
// buffering" when we are falling behind.
|
// buffering" when we are falling behind.
|
||||||
if ( g_nAppBufferCount >= g_nMaxAppBufferCount - 1 )
|
if ( g_nAppBufferCount == g_nMaxAppBufferCount )
|
||||||
{
|
{
|
||||||
if ( !g_FrameLimitCommits.empty() )
|
if ( !g_FrameLimitCommits.empty() )
|
||||||
{
|
{
|
||||||
g_FrameLimitCommits.pop();
|
g_FrameLimitCommits.pop();
|
||||||
g_nAppBufferCount--;
|
g_nAppBufferCount--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -494,13 +498,17 @@ retry:
|
||||||
|
|
||||||
close( entry.fence );
|
close( entry.fence );
|
||||||
|
|
||||||
uint64_t now = get_time_in_nanos();
|
uint64_t frametime;
|
||||||
static uint64_t lastFrameTime = now;
|
if ( entry.fps_nudge || entry.mangoapp_nudge )
|
||||||
uint64_t frametime = now - lastFrameTime;
|
{
|
||||||
lastFrameTime = now;
|
uint64_t now = get_time_in_nanos();
|
||||||
|
static uint64_t lastFrameTime = now;
|
||||||
|
frametime = now - lastFrameTime;
|
||||||
|
lastFrameTime = now;
|
||||||
|
}
|
||||||
|
|
||||||
if ( entry.fps_nudge )
|
if ( entry.fps_nudge )
|
||||||
fpslimit_mark_frame();
|
fpslimit_mark_frame( frametime );
|
||||||
|
|
||||||
{
|
{
|
||||||
std::unique_lock< std::mutex > lock( entry.ctx->listCommitsDoneLock );
|
std::unique_lock< std::mutex > lock( entry.ctx->listCommitsDoneLock );
|
||||||
|
|
|
@ -168,12 +168,12 @@ static std::mutex g_TargetFPSMutex;
|
||||||
static std::condition_variable g_TargetFPSCondition;
|
static std::condition_variable g_TargetFPSCondition;
|
||||||
static int g_nFpsLimitTargetFPS = 0;
|
static int g_nFpsLimitTargetFPS = 0;
|
||||||
|
|
||||||
void steamcompmgr_fpslimit_release_commit( int consecutive_missed_frame_count );
|
bool steamcompmgr_fpslimit_release_commit( int consecutive_missed_frame_count );
|
||||||
void steamcompmgr_fpslimit_release_all();
|
void steamcompmgr_fpslimit_release_all();
|
||||||
void steamcompmgr_send_frame_done_to_focus_window();
|
void steamcompmgr_send_frame_done_to_focus_window();
|
||||||
|
|
||||||
// Dump some stats.
|
// Dump some stats.
|
||||||
//#define FPS_LIMIT_DEBUG
|
#define FPS_LIMIT_DEBUG
|
||||||
|
|
||||||
// 1.80ms for the app's deadzone to account for varying GPU clocks, other variances, etc
|
// 1.80ms for the app's deadzone to account for varying GPU clocks, other variances, etc
|
||||||
uint64_t g_uFPSLimiterRedZoneNS = 1'800'000;
|
uint64_t g_uFPSLimiterRedZoneNS = 1'800'000;
|
||||||
|
@ -187,6 +187,9 @@ bool g_bFPSLimitThreadRun = true;
|
||||||
|
|
||||||
extern bool g_bLowLatency;
|
extern bool g_bLowLatency;
|
||||||
|
|
||||||
|
uint64_t g_uFPSLimitLastFullFrameTime = 0;
|
||||||
|
uint64_t g_uFPSLimitDoneToDoneTime = 0;
|
||||||
|
|
||||||
void fpslimitThreadRun( void )
|
void fpslimitThreadRun( void )
|
||||||
{
|
{
|
||||||
pthread_setname_np( pthread_self(), "gamescope-fps" );
|
pthread_setname_np( pthread_self(), "gamescope-fps" );
|
||||||
|
@ -197,6 +200,10 @@ void fpslimitThreadRun( void )
|
||||||
uint64_t vblank = 0;
|
uint64_t vblank = 0;
|
||||||
int consecutive_missed_frame_count = 0;
|
int consecutive_missed_frame_count = 0;
|
||||||
bool last_frame_was_late = false;
|
bool last_frame_was_late = false;
|
||||||
|
g_uFPSLimitLastFullFrameTime = get_time_in_nanos();
|
||||||
|
uint64_t lastFullFrameTime = 0;
|
||||||
|
uint64_t donetodonetime = 0;
|
||||||
|
bool isLatent = false;
|
||||||
while ( true )
|
while ( true )
|
||||||
{
|
{
|
||||||
int nTargetFPS;
|
int nTargetFPS;
|
||||||
|
@ -228,6 +235,8 @@ void fpslimitThreadRun( void )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nTargetFPS = g_nFpsLimitTargetFPS;
|
nTargetFPS = g_nFpsLimitTargetFPS;
|
||||||
|
lastFullFrameTime = g_uFPSLimitLastFullFrameTime;
|
||||||
|
donetodonetime = g_uFPSLimitDoneToDoneTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int refresh = g_nNestedRefresh ? g_nNestedRefresh : g_nOutputRefresh;
|
const int refresh = g_nNestedRefresh ? g_nNestedRefresh : g_nOutputRefresh;
|
||||||
|
@ -252,7 +261,7 @@ void fpslimitThreadRun( void )
|
||||||
bool useFrameCallbacks = fpslimit_use_frame_callbacks_for_focus_window( nTargetFPS, 0 );
|
bool useFrameCallbacks = fpslimit_use_frame_callbacks_for_focus_window( nTargetFPS, 0 );
|
||||||
|
|
||||||
uint64_t t0 = lastCommitReleased;
|
uint64_t t0 = lastCommitReleased;
|
||||||
uint64_t t1 = get_time_in_nanos();
|
uint64_t t1 = lastFullFrameTime;
|
||||||
|
|
||||||
// Not the actual frame time of the game
|
// Not the actual frame time of the game
|
||||||
// this is the time of the amount of work a 'frame' has done.
|
// this is the time of the amount of work a 'frame' has done.
|
||||||
|
@ -333,7 +342,7 @@ void fpslimitThreadRun( void )
|
||||||
|
|
||||||
if ( !no_frame )
|
if ( !no_frame )
|
||||||
{
|
{
|
||||||
mangoapp_update( targetInterval, frameTime, latency );
|
mangoapp_update( isLatent ? donetodonetime : targetInterval, frameTime, latency );
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FPS_LIMIT_DEBUG
|
#ifdef FPS_LIMIT_DEBUG
|
||||||
|
@ -343,7 +352,7 @@ void fpslimitThreadRun( void )
|
||||||
|
|
||||||
sleep_until_nanos( targetPoint );
|
sleep_until_nanos( targetPoint );
|
||||||
lastCommitReleased = get_time_in_nanos();
|
lastCommitReleased = get_time_in_nanos();
|
||||||
steamcompmgr_fpslimit_release_commit( consecutive_missed_frame_count );
|
isLatent = steamcompmgr_fpslimit_release_commit( consecutive_missed_frame_count );
|
||||||
|
|
||||||
// If we aren't vblank aligned, nudge ourselves to process done commits now.
|
// If we aren't vblank aligned, nudge ourselves to process done commits now.
|
||||||
if ( !useFrameCallbacks )
|
if ( !useFrameCallbacks )
|
||||||
|
@ -357,16 +366,7 @@ void fpslimitThreadRun( void )
|
||||||
{
|
{
|
||||||
if ( nTargetFPS )
|
if ( nTargetFPS )
|
||||||
{
|
{
|
||||||
uint64_t t0 = lastCommitReleased;
|
mangoapp_update( donetodonetime, donetodonetime, uint64_t(~0ull) );
|
||||||
uint64_t t1 = get_time_in_nanos();
|
|
||||||
|
|
||||||
uint64_t frametime = t1 - t0 + targetInterval;
|
|
||||||
|
|
||||||
uint64_t latency = uint64_t(~0ull);
|
|
||||||
if ( refresh % nTargetFPS == 0 )
|
|
||||||
latency = frametime;
|
|
||||||
|
|
||||||
mangoapp_update( frametime, frametime, latency );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,13 +390,23 @@ void fpslimit_shutdown( void )
|
||||||
g_TargetFPSCondition.notify_all();
|
g_TargetFPSCondition.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
void fpslimit_mark_frame( void )
|
void fpslimit_mark_frame( uint64_t frametime )
|
||||||
{
|
{
|
||||||
|
uint64_t now = get_time_in_nanos();
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(g_TargetFPSMutex);
|
||||||
|
g_uFPSLimitLastFullFrameTime = now;
|
||||||
|
g_uFPSLimitDoneToDoneTime = frametime;
|
||||||
|
}
|
||||||
g_TargetFPSCondition.notify_all();
|
g_TargetFPSCondition.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fpslimit_use_frame_callbacks_for_focus_window( int nTargetFPS, int nVBlankCount )
|
bool fpslimit_use_frame_callbacks_for_focus_window( int nTargetFPS, int nVBlankCount )
|
||||||
{
|
{
|
||||||
|
// Avoids a race incase the surface changes
|
||||||
|
// We don't use this anymore since we force no-fifo
|
||||||
|
return true;
|
||||||
|
#if 0
|
||||||
if ( !nTargetFPS )
|
if ( !nTargetFPS )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -412,6 +422,7 @@ bool fpslimit_use_frame_callbacks_for_focus_window( int nTargetFPS, int nVBlankC
|
||||||
// call them from fpslimit
|
// call them from fpslimit
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from steamcompmgr thread
|
// Called from steamcompmgr thread
|
||||||
|
|
|
@ -15,7 +15,7 @@ extern uint64_t g_uVBlankRateOfDecayPercentage;
|
||||||
|
|
||||||
void fpslimit_init( void );
|
void fpslimit_init( void );
|
||||||
|
|
||||||
void fpslimit_mark_frame( void );
|
void fpslimit_mark_frame( uint64_t frametime );
|
||||||
|
|
||||||
bool fpslimit_use_frame_callbacks_for_focus_window( int nTargetFPS, int nVBlankCount );
|
bool fpslimit_use_frame_callbacks_for_focus_window( int nTargetFPS, int nVBlankCount );
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue