Skip to content

Commit ca13977

Browse files
committed
Revert "Revert: Refactor frame rate limiter"
1 parent 61fccbc commit ca13977

File tree

6 files changed

+82
-35
lines changed

6 files changed

+82
-35
lines changed

Client/core/CCore.cpp

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,6 +1718,14 @@ void CCore::UpdateRecentlyPlayed()
17181718
CCore::GetSingleton().SaveConfig();
17191719
}
17201720

1721+
//
1722+
// Called just before GTA calculates frame time deltas
1723+
//
1724+
void CCore::OnGameTimerUpdate()
1725+
{
1726+
ApplyQueuedFrameRateLimit();
1727+
}
1728+
17211729
//
17221730
// Recalculate FPS limit to use
17231731
//
@@ -1793,34 +1801,47 @@ void CCore::ApplyFrameRateLimit(uint uiOverrideRate)
17931801

17941802
uint uiUseRate = uiOverrideRate != -1 ? uiOverrideRate : m_uiFrameRateLimit;
17951803

1796-
TIMING_GRAPH("Limiter");
1797-
1798-
if (uiUseRate < 1)
1799-
return DoReliablePulse();
1800-
1801-
if (m_DiagnosticDebug != EDiagnosticDebug::D3D_6732)
1802-
Sleep(1); // Make frame rate smoother maybe
1803-
1804-
// Calc required time in ms between frames
1805-
const double dTargetTimeToUse = 1000.0 / uiUseRate;
1806-
1807-
while(true)
1804+
if (uiUseRate > 0)
18081805
{
1809-
// See if we need to wait
1810-
double dSpare = dTargetTimeToUse - m_FrameRateTimer.Get();
1811-
if (dSpare <= 0.0)
1812-
break;
1813-
if (dSpare >= 2.0)
1814-
Sleep(1);
1806+
// Apply previous frame rate if is hasn't been done yet
1807+
ApplyQueuedFrameRateLimit();
1808+
1809+
// Limit is usually applied in OnGameTimerUpdate
1810+
m_uiQueuedFrameRate = uiUseRate;
1811+
m_bQueuedFrameRateValid = true;
18151812
}
1816-
m_FrameRateTimer.Reset();
18171813

18181814
DoReliablePulse();
18191815

18201816
TIMING_GRAPH("FrameEnd");
18211817
TIMING_GRAPH("");
18221818
}
18231819

1820+
//
1821+
// Frame rate limit (wait) is done here.
1822+
//
1823+
void CCore::ApplyQueuedFrameRateLimit()
1824+
{
1825+
if (m_bQueuedFrameRateValid)
1826+
{
1827+
m_bQueuedFrameRateValid = false;
1828+
// Calc required time in ms between frames
1829+
const double dTargetTimeToUse = 1000.0 / m_uiQueuedFrameRate;
1830+
1831+
while (true)
1832+
{
1833+
// See if we need to wait
1834+
double dSpare = dTargetTimeToUse - m_FrameRateTimer.Get();
1835+
if (dSpare <= 0.0)
1836+
break;
1837+
if (dSpare >= 2.0)
1838+
Sleep(1);
1839+
}
1840+
m_FrameRateTimer.Reset();
1841+
TIMING_GRAPH("Limiter");
1842+
}
1843+
}
1844+
18241845
//
18251846
// DoReliablePulse
18261847
//

Client/core/CCore.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ class CCore : public CCoreInterface, public CSingleton<CCore>
124124
void EnableChatInput(char* szCommand, DWORD dwColor);
125125
bool IsChatInputEnabled(void);
126126
bool ClearChat();
127+
void OnGameTimerUpdate(void);
127128

128129
// Screenshots
129130
void TakeScreenShot(void);
@@ -213,6 +214,7 @@ class CCore : public CCoreInterface, public CSingleton<CCore>
213214
uint GetFrameRateLimit(void) { return m_uiFrameRateLimit; }
214215
void RecalculateFrameRateLimit(uint uiServerFrameRateLimit = -1, bool bLogToConsole = true);
215216
void ApplyFrameRateLimit(uint uiOverrideRate = -1);
217+
void ApplyQueuedFrameRateLimit(void);
216218
void EnsureFrameRateLimitApplied(void);
217219
void SetClientScriptFrameRateLimit(uint uiClientScriptFrameRateLimit);
218220
void DoReliablePulse(void);
@@ -349,6 +351,8 @@ class CCore : public CCoreInterface, public CSingleton<CCore>
349351
uint m_uiClientScriptFrameRateLimit;
350352
uint m_uiFrameRateLimit;
351353
CElapsedTimeHD m_FrameRateTimer;
354+
uint m_uiQueuedFrameRate;
355+
bool m_bQueuedFrameRateValid;
352356
bool m_bWaitToSetNick;
353357
uint m_uiNewNickWaitFrames;
354358
EDiagnosticDebugType m_DiagnosticDebug;

Client/mods/deathmatch/logic/CClientGame.cpp

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3909,19 +3909,14 @@ void CClientGame::PostWorldProcessHandler(void)
39093909
m_pManager->GetPointLightsManager()->DoPulse();
39103910
m_pManager->GetObjectManager()->DoPulse();
39113911

3912-
// Update frame time slice
3913-
uint uiCurrentTick = GetTickCount32();
3914-
if (m_uiLastFrameTick)
3915-
{
3916-
m_uiFrameTimeSlice = uiCurrentTick - m_uiLastFrameTick;
3917-
m_uiFrameCount++;
3912+
double dTimeSlice = m_TimeSliceTimer.Get();
3913+
m_TimeSliceTimer.Reset();
3914+
m_uiFrameCount++;
39183915

3919-
// Call onClientPreRender LUA event
3920-
CLuaArguments Arguments;
3921-
Arguments.PushNumber(m_uiFrameTimeSlice);
3922-
m_pRootEntity->CallEvent("onClientPreRender", Arguments, false);
3923-
}
3924-
m_uiLastFrameTick = uiCurrentTick;
3916+
// Call onClientPreRender LUA event
3917+
CLuaArguments Arguments;
3918+
Arguments.PushNumber(dTimeSlice);
3919+
m_pRootEntity->CallEvent("onClientPreRender", Arguments, false);
39253920
}
39263921

39273922
void CClientGame::IdleHandler(void)

Client/mods/deathmatch/logic/CClientGame.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,6 @@ class CClientGame
238238
void DoPulses(void);
239239
void DoPulses2(bool bCalledFromIdle);
240240

241-
uint GetFrameTimeSlice(void) { return m_uiFrameTimeSlice; }
242241
uint GetFrameCount(void) { return m_uiFrameCount; }
243242

244243
void HandleException(CExceptionInformation* pExceptionInformation);
@@ -764,9 +763,8 @@ class CClientGame
764763
unsigned long m_ulBigPacketBytesReceivedBase;
765764
CTransferBox* m_pBigPacketTransferBox;
766765

767-
uint m_uiFrameTimeSlice; // how long it took (in ms) to process the current frame
768-
uint m_uiLastFrameTick; // time at which the previous frame was processed
769-
uint m_uiFrameCount; // Frame counter
766+
CElapsedTimeHD m_TimeSliceTimer;
767+
uint m_uiFrameCount;
770768

771769
long long m_llLastTransgressionTime;
772770
SString m_strLastDiagnosticStatus;

Client/multiplayer_sa/CMultiplayerSA_Rendering.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,33 @@ void _declspec(naked) HOOK_WinLoop()
339339
}
340340
}
341341

342+
//////////////////////////////////////////////////////////////////////////////////////////
343+
//
344+
// CTimer::Update
345+
//
346+
// Just before GTA calculates frame time deltas
347+
//
348+
//////////////////////////////////////////////////////////////////////////////////////////
349+
#define HOOKPOS_CTimer_Update 0x561B10
350+
#define HOOKSIZE_CTimer_Update 6
351+
static const DWORD CONTINUE_CTimer_Update = 0x561B16;
352+
static void _declspec(naked) HOOK_CTimer_Update()
353+
{
354+
_asm
355+
{
356+
pushad
357+
}
358+
359+
g_pCore->OnGameTimerUpdate();
360+
361+
_asm
362+
{
363+
popad
364+
mov ecx,dword ptr ds:[0B7CB28h]
365+
jmp CONTINUE_CTimer_Update
366+
}
367+
}
368+
342369
//////////////////////////////////////////////////////////////////////////////////////////
343370
//
344371
// Photograph screen grab in windowed mode
@@ -624,6 +651,7 @@ void CMultiplayerSA::InitHooks_Rendering(void)
624651
EZHookInstall(Check_NoOfVisibleLods);
625652
EZHookInstall(Check_NoOfVisibleEntities);
626653
EZHookInstall(WinLoop);
654+
EZHookInstall(CTimer_Update);
627655
EZHookInstall(psGrabScreen);
628656
EZHookInstallChecked(CClouds_RenderSkyPolys);
629657
EZHookInstallChecked(RwCameraSetNearClipPlane);

Client/sdk/core/CCoreInterface.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ class CCoreInterface
172172
virtual void SetFakeLagCommandEnabled(bool bEnabled) = 0;
173173
virtual SString GetBlueCopyrightString(void) = 0;
174174
virtual bool ClearChat() = 0;
175+
virtual void OnGameTimerUpdate(void) = 0;
175176

176177
virtual bool IsHostSmotraServer() = 0;
177178
};

0 commit comments

Comments
 (0)