Fix the FPS counter to show the 'real' framerate, also clean up its mess a bit...
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3920 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
1493c2ba9c
commit
69c0613160
|
@ -71,7 +71,7 @@ namespace Core
|
||||||
// Function forwarding
|
// Function forwarding
|
||||||
//void Callback_VideoRequestWindowSize(int _iWidth, int _iHeight, BOOL _bFullscreen);
|
//void Callback_VideoRequestWindowSize(int _iWidth, int _iHeight, BOOL _bFullscreen);
|
||||||
void Callback_VideoLog(const TCHAR* _szMessage, int _bDoBreak);
|
void Callback_VideoLog(const TCHAR* _szMessage, int _bDoBreak);
|
||||||
void Callback_VideoCopiedToXFB();
|
void Callback_VideoCopiedToXFB(bool video_update);
|
||||||
void Callback_DSPLog(const TCHAR* _szMessage, int _v);
|
void Callback_DSPLog(const TCHAR* _szMessage, int _v);
|
||||||
const char *Callback_ISOName(void);
|
const char *Callback_ISOName(void);
|
||||||
void Callback_DSPInterrupt();
|
void Callback_DSPInterrupt();
|
||||||
|
@ -590,28 +590,32 @@ void Callback_VideoLog(const TCHAR *_szMessage, int _bDoBreak)
|
||||||
// Callback_VideoCopiedToXFB
|
// Callback_VideoCopiedToXFB
|
||||||
// WARNING - THIS IS EXECUTED FROM VIDEO THREAD
|
// WARNING - THIS IS EXECUTED FROM VIDEO THREAD
|
||||||
// We do not write to anything outside this function here
|
// We do not write to anything outside this function here
|
||||||
void Callback_VideoCopiedToXFB()
|
void Callback_VideoCopiedToXFB(bool video_update)
|
||||||
{
|
{
|
||||||
#ifdef RERECORDING
|
#ifdef RERECORDING
|
||||||
FrameUpdate();
|
FrameUpdate();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter;
|
SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter;
|
||||||
//count FPS
|
|
||||||
|
//count FPS and VPS
|
||||||
static Common::Timer Timer;
|
static Common::Timer Timer;
|
||||||
static u32 frames = 0;
|
static u32 frames = 0;
|
||||||
|
static u32 videoupd = 0;
|
||||||
|
|
||||||
|
if (video_update)
|
||||||
|
videoupd++;
|
||||||
|
else
|
||||||
|
frames++;
|
||||||
|
|
||||||
|
// Custom frame limiter
|
||||||
|
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||||
|
|
||||||
u32 targetfps = (SConfig::GetInstance().m_Framelimit)*5;
|
u32 targetfps = (SConfig::GetInstance().m_Framelimit)*5;
|
||||||
static u64 old_frametime=0;
|
static u64 old_frametime=0;
|
||||||
u64 new_frametime;
|
u64 new_frametime;
|
||||||
s16 wait_frametime;
|
s16 wait_frametime;
|
||||||
|
|
||||||
frames++;
|
|
||||||
|
|
||||||
|
|
||||||
// Custom frame limiter
|
|
||||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
|
||||||
if (targetfps > 0)
|
if (targetfps > 0)
|
||||||
{
|
{
|
||||||
new_frametime = Timer.GetTimeDifference() - old_frametime;
|
new_frametime = Timer.GetTimeDifference() - old_frametime;
|
||||||
|
@ -623,20 +627,6 @@ void Callback_VideoCopiedToXFB()
|
||||||
Common::SleepCurrentThread(wait_frametime*2);
|
Common::SleepCurrentThread(wait_frametime*2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Is it possible to calculate the CPU-GPU synced ticks for the dual core mode too?
|
|
||||||
// And possible the idle skipping mode too?
|
|
||||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
|
||||||
static int Diff = 0, DistOld = 0;
|
|
||||||
Diff = CommandProcessor::fifo.CPReadWriteDistance - DistOld;
|
|
||||||
// If the CPReadWriteDistance has increased since the last frame we assume the CPU has raced
|
|
||||||
// ahead of the GPU and we adjust the ticks. Why multiply the difference with 700? I don't know,
|
|
||||||
// please fix it if possible.
|
|
||||||
if (Diff > 0) VideoInterface::SyncTicksProgress -= Diff * 700;
|
|
||||||
DistOld = CommandProcessor::fifo.CPReadWriteDistance;
|
|
||||||
|
|
||||||
|
|
||||||
if (Timer.GetTimeDifference() >= 1000)
|
if (Timer.GetTimeDifference() >= 1000)
|
||||||
{
|
{
|
||||||
// reset timer for framelimiter, placed here so no additional check for 1000ms is required -> don't delete please :)
|
// reset timer for framelimiter, placed here so no additional check for 1000ms is required -> don't delete please :)
|
||||||
|
@ -662,45 +652,11 @@ void Callback_VideoCopiedToXFB()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float FPS = (float)frames / t;
|
float FPS = (float)frames / t;
|
||||||
float FPS_To_VPS_Rate = ((float)FPS / VideoInterface::ActualRefreshRate);
|
// for some reasons "VideoInterface::ActualRefreshRate" gives some odd results :(
|
||||||
|
float VPS = (float)videoupd / t;
|
||||||
|
int TargetVPS = (int)VideoInterface::TargetRefreshRate;
|
||||||
|
|
||||||
// For the sake of the dual core mode calculate an average to somewhat reduce the variations
|
float Speed = (VPS / TargetVPS) * 100.0f;
|
||||||
// in the FPS/VPS rate
|
|
||||||
|
|
||||||
/**/
|
|
||||||
if (_CoreParameter.bUseDualCore)
|
|
||||||
{
|
|
||||||
static std::vector <float> FPSVPSList;
|
|
||||||
static float AverageOver = 5.0;
|
|
||||||
if (FPSVPSList.size() == AverageOver) FPSVPSList.erase(FPSVPSList.begin());
|
|
||||||
FPSVPSList.push_back(FPS_To_VPS_Rate);
|
|
||||||
if (FPSVPSList.size() == AverageOver)
|
|
||||||
FPS_To_VPS_Rate = MathFloatVectorSum(FPSVPSList) / AverageOver;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Correct the FPS/VPS rate for temporary CPU-GPU timing variations. This rate can only be 1/Integer
|
|
||||||
// so we set it to either 0.33, 0.5 or 1.0 depending on which it's closest to.
|
|
||||||
/*
|
|
||||||
1. Notice: This rate can currently not be calculated with any accuracy at all when idle skipping
|
|
||||||
is on (the suggested tick rate in that case is much to high in proportion to the actual FPS)
|
|
||||||
2. When dual core is enabled the CommandProcessor allow some elasticity in the FPS/VPS rate. This
|
|
||||||
is especially noticable in Zelda TP who's FPS/VPS for me varies between 0.25 and 0.6 as a
|
|
||||||
result of this.
|
|
||||||
3. PAL 50Hz games: Are 'patched' so that they still run at the correct speed. So if the NTSC 60Hz
|
|
||||||
version has a FPS/VPS of 0.5 the 50Hz game will run at 0.6.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**/
|
|
||||||
if (FPS_To_VPS_Rate > 0 && FPS_To_VPS_Rate < ((1.0f/3.0f + 1.0f/2.0f)/2)) FPS_To_VPS_Rate = 1.0f/3.0f;
|
|
||||||
else if (FPS_To_VPS_Rate > ((1.0f/3.0f + 1.0f/2.0f)/2) && FPS_To_VPS_Rate < ((1.0f/2.0f + 1.0f/1.0f)/2)) FPS_To_VPS_Rate = 1.0/2.0;
|
|
||||||
else FPS_To_VPS_Rate = 1.0;
|
|
||||||
// PAL patch adjustment
|
|
||||||
if (VideoInterface::TargetRefreshRate == 50) FPS_To_VPS_Rate = FPS_To_VPS_Rate * 1.2f;
|
|
||||||
|
|
||||||
|
|
||||||
float TargetFPS = FPS_To_VPS_Rate * (float)VideoInterface::TargetRefreshRate;
|
|
||||||
float FPSPercentage = (FPS / TargetFPS) * 100.0f;
|
|
||||||
|
|
||||||
// Settings are shown the same for both extended and summary info
|
// Settings are shown the same for both extended and summary info
|
||||||
std::string SSettings = StringFromFormat(" | Core: %s %s",
|
std::string SSettings = StringFromFormat(" | Core: %s %s",
|
||||||
|
@ -718,38 +674,36 @@ void Callback_VideoCopiedToXFB()
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
_CoreParameter.bUseDualCore ? "DC" : "SC");
|
_CoreParameter.bUseDualCore ? "DC" : "SC");
|
||||||
// Show ~ to indicate that the value may be wrong because the ticks are wrong
|
|
||||||
std::string IdleSkipMessage = "";
|
|
||||||
if (_CoreParameter.bSkipIdle || _CoreParameter.bUseDualCore) IdleSkipMessage = "~";
|
|
||||||
#ifdef EXTENDED_INFO
|
#ifdef EXTENDED_INFO
|
||||||
float VPSPercentage = (VideoInterface::ActualRefreshRate / (float)VideoInterface::TargetRefreshRate) * 100.0f;
|
std::string SFPS = StringFromFormat("FPS: %4.1f - VPS: %i/%i (%3.0f%%)",
|
||||||
std::string SFPS = StringFromFormat("FPS: %4.1f/%s%2.0f (%s%3.0f%% | %s%1.2f) VPS:%4.0f/%i (%3.0f%%)",
|
FPS, VPS > 0 ? (int)VPS : (int)VideoInterface::ActualRefreshRate, TargetVPS, Speed);
|
||||||
FPS, IdleSkipMessage.c_str(), TargetFPS,
|
SFPS += StringFromFormat(" | CPU: %s%i MHz [Real: %i + IdleSkip: %i] / %i MHz (%s%3.0f%%)",
|
||||||
IdleSkipMessage.c_str(), FPSPercentage, IdleSkipMessage.c_str(), FPS_To_VPS_Rate,
|
_CoreParameter.bSkipIdle ? "~" : "",
|
||||||
VideoInterface::ActualRefreshRate, VideoInterface::TargetRefreshRate, VPSPercentage);
|
|
||||||
std::string STicks = StringFromFormat(" | CPU: %s%i MHz [Real: %i + IdleSkip: %i] / %i MHz (%s%3.0f%%)",
|
|
||||||
IdleSkipMessage.c_str(),
|
|
||||||
(int)(diff),
|
(int)(diff),
|
||||||
(int)(diff - idleDiff),
|
(int)(diff - idleDiff),
|
||||||
(int)(idleDiff),
|
(int)(idleDiff),
|
||||||
SystemTimers::GetTicksPerSecond() / 1000000,
|
SystemTimers::GetTicksPerSecond() / 1000000,
|
||||||
IdleSkipMessage.c_str(),
|
_CoreParameter.bSkipIdle ? "~" : "",
|
||||||
TicksPercentage);
|
TicksPercentage);
|
||||||
// Summary information
|
|
||||||
#else
|
#else // Summary information
|
||||||
std::string SFPS = StringFromFormat("FPS: %4.1f/%s%2.0f (%s%3.0f%%)",
|
std::string SFPS = StringFromFormat("FPS: %4.1f - VPS: %i/%i (%3.0f%%)",
|
||||||
FPS, IdleSkipMessage.c_str(), TargetFPS, IdleSkipMessage.c_str(), FPSPercentage);
|
FPS, VPS > 0 ? (int)VPS : (int)VideoInterface::ActualRefreshRate, TargetVPS, Speed);
|
||||||
std::string STicks = "";
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::string SMessage = StringFromFormat("%s%s%s", SFPS.c_str(), SSettings.c_str(), STicks.c_str());
|
// This is our final "frame counter" string
|
||||||
|
std::string SMessage = StringFromFormat("%s%s", SFPS.c_str(), SSettings.c_str());
|
||||||
|
|
||||||
// Show message
|
// Show message
|
||||||
if (g_pUpdateFPSDisplay != NULL)
|
if (g_pUpdateFPSDisplay != NULL)
|
||||||
g_pUpdateFPSDisplay(SMessage.c_str());
|
g_pUpdateFPSDisplay(SMessage.c_str());
|
||||||
|
|
||||||
Host_UpdateStatusBar(SMessage.c_str());
|
Host_UpdateStatusBar(SMessage.c_str());
|
||||||
|
|
||||||
// Reset frame counter
|
// Reset frame counter
|
||||||
frames = 0;
|
frames = 0;
|
||||||
|
videoupd = 0;
|
||||||
Timer.Update();
|
Timer.Update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -505,8 +505,8 @@ void Host_UpdateStatusBar(const char* _pText, int Field)
|
||||||
// Update statusbar field
|
// Update statusbar field
|
||||||
event.SetInt(Field);
|
event.SetInt(Field);
|
||||||
// Post message
|
// Post message
|
||||||
// DISABLED - this has been found to cause random hangs.
|
// TODO : this has been said to cause hang (??) how is that even possible ? :d
|
||||||
// wxPostEvent(main_frame, event);
|
wxPostEvent(main_frame, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
// g_VideoInitialize.pSysMessage() goes here
|
// g_VideoInitialize.pSysMessage() goes here
|
||||||
|
|
|
@ -16,7 +16,7 @@ typedef unsigned char* (*TGetMemoryPointer)(const unsigned int _iAddress);
|
||||||
typedef void (*TVideoLog)(const char* _pMessage, int _bBreak);
|
typedef void (*TVideoLog)(const char* _pMessage, int _bBreak);
|
||||||
typedef void (*TSysMessage)(const char *fmt, ...);
|
typedef void (*TSysMessage)(const char *fmt, ...);
|
||||||
typedef void (*TRequestWindowSize)(int _iWidth, int _iHeight, bool _bFullscreen);
|
typedef void (*TRequestWindowSize)(int _iWidth, int _iHeight, bool _bFullscreen);
|
||||||
typedef void (*TCopiedToXFB)(void);
|
typedef void (*TCopiedToXFB)(bool video_update);
|
||||||
typedef unsigned int (*TPeekMessages)(void);
|
typedef unsigned int (*TPeekMessages)(void);
|
||||||
typedef void (*TUpdateInterrupts)(void);
|
typedef void (*TUpdateInterrupts)(void);
|
||||||
typedef void (*TUpdateFPSDisplay)(const char* text); // sets the window title
|
typedef void (*TUpdateFPSDisplay)(const char* text); // sets the window title
|
||||||
|
|
|
@ -227,7 +227,7 @@ void RenderToXFB(const BPCmd &bp, const EFBRectangle &rc, const float &yScale, c
|
||||||
{
|
{
|
||||||
Renderer::SwapBuffers();
|
Renderer::SwapBuffers();
|
||||||
PRIM_LOG("Renderer::SwapBuffers()");
|
PRIM_LOG("Renderer::SwapBuffers()");
|
||||||
g_VideoInitialize.pCopiedToXFB();
|
g_VideoInitialize.pCopiedToXFB(false);
|
||||||
}
|
}
|
||||||
void ClearScreen(const BPCmd &bp, const EFBRectangle &rc)
|
void ClearScreen(const BPCmd &bp, const EFBRectangle &rc)
|
||||||
{
|
{
|
||||||
|
|
|
@ -464,7 +464,7 @@ void VideoFifo_CheckSwapRequest()
|
||||||
Renderer::Swap(s_beginFieldArgs.xfbAddr, s_beginFieldArgs.field, s_beginFieldArgs.fbWidth, s_beginFieldArgs.fbHeight);
|
Renderer::Swap(s_beginFieldArgs.xfbAddr, s_beginFieldArgs.field, s_beginFieldArgs.fbWidth, s_beginFieldArgs.fbHeight);
|
||||||
|
|
||||||
// TODO: Find better name for this because I don't know if it means what it says.
|
// TODO: Find better name for this because I don't know if it means what it says.
|
||||||
g_VideoInitialize.pCopiedToXFB();
|
g_VideoInitialize.pCopiedToXFB(true);
|
||||||
|
|
||||||
Common::AtomicStoreRelease(s_swapRequested, FALSE);
|
Common::AtomicStoreRelease(s_swapRequested, FALSE);
|
||||||
}
|
}
|
||||||
|
@ -478,6 +478,8 @@ inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
|
||||||
// Run from the graphics thread (from Fifo.cpp)
|
// Run from the graphics thread (from Fifo.cpp)
|
||||||
void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
|
void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
|
||||||
{
|
{
|
||||||
|
g_VideoInitialize.pCopiedToXFB(false);
|
||||||
|
|
||||||
if (Common::AtomicLoadAcquire(s_swapRequested))
|
if (Common::AtomicLoadAcquire(s_swapRequested))
|
||||||
{
|
{
|
||||||
u32 aLower = xfbAddr;
|
u32 aLower = xfbAddr;
|
||||||
|
|
Loading…
Reference in New Issue