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:
sl1nk3.s 2009-08-01 18:16:12 +00:00
parent 1493c2ba9c
commit 69c0613160
5 changed files with 52 additions and 96 deletions

View File

@ -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();
} }
} }

View File

@ -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

View File

@ -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

View File

@ -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)
{ {

View File

@ -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;