Skip to content

Commit 56afa53

Browse files
authored
Merge pull request #440 from MrS-ibra/bugfix/adaptive-fps
bugfix(gamelod): Restore adaptive FPS effects scaling after merge and disable dynamic light pulses when active
2 parents 8f951c5 + d61a796 commit 56afa53

3 files changed

Lines changed: 67 additions & 54 deletions

File tree

GeneralsMD/Code/GameEngine/Include/Common/GameLOD.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,8 @@ class GameLODManager
190190
Bool isReallyLowMHz() const { return m_cpuFreq < m_reallyLowMHz; }
191191
#if defined(GENERALS_ONLINE_HIGH_FPS_SERVER)
192192
void updateGraphicsQualityState(float averageFPS);
193+
void restoreQualitySettings();
194+
bool isQualityReduced() const { return m_isQualityReduced; }
193195
#endif
194196

195197
StaticGameLODInfo m_staticGameLODInfo[STATIC_GAME_LOD_COUNT];
@@ -230,14 +232,13 @@ class GameLODManager
230232
Real m_compositeBenchIndex;
231233
Int m_reallyLowMHz;
232234
#if defined(GENERALS_ONLINE_HIGH_FPS_SERVER)
233-
bool m_userGraphSnapshotTaken;
234235
bool m_userShadowVolumesEnabled;
235236
bool m_userShadowDecalsEnabled;
236237
bool m_userHeatEffectsEnabled;
237238
bool m_isQualityReduced;
238-
int m_stableFPSDuration;
239-
int m_lowFPSSecondsCount;
240-
DynamicGameLODLevel m_userDynamicLOD;
239+
int m_stableFPSSecondsCount;
240+
int m_lowFPSSecondsCount;
241+
int m_userMaxParticleCount;
241242
#endif
242243
};
243244

GeneralsMD/Code/GameEngine/Source/Common/GameLOD.cpp

Lines changed: 52 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040

4141
#define DEFINE_PARTICLE_SYSTEM_NAMES
4242
#include "GameClient/ParticleSys.h"
43-
#include "GameClient/Shell.h"
43+
#include "GameLogic/GameLogic.h"
4444

4545

4646
#define PROFILE_ERROR_LIMIT 0.94f //fraction of profiled result needed to get a match. Allows some room for error/fluctuation.
@@ -232,14 +232,10 @@ GameLODManager::GameLODManager()
232232
m_numBenchProfiles=0;
233233
m_reallyLowMHz = 400;
234234
#if defined(GENERALS_ONLINE_HIGH_FPS_SERVER)
235-
m_userGraphSnapshotTaken = false;
236-
m_userShadowVolumesEnabled = true;
237-
m_userShadowDecalsEnabled = true;
238-
m_userHeatEffectsEnabled = true;
239235
m_isQualityReduced = false;
240-
m_stableFPSDuration = 0;
241236
m_lowFPSSecondsCount = 0;
242-
m_userDynamicLOD = DYNAMIC_GAME_LOD_VERY_HIGH;
237+
m_stableFPSSecondsCount = 0;
238+
m_userMaxParticleCount = 0;
243239
#endif
244240

245241
for (Int i=0; i<STATIC_GAME_LOD_CUSTOM; i++)
@@ -782,50 +778,41 @@ Bool GameLODManager::didMemPass()
782778
#if defined(GENERALS_ONLINE_HIGH_FPS_SERVER)
783779
void GameLODManager::updateGraphicsQualityState(float averageFPS)
784780
{
785-
if (!m_userGraphSnapshotTaken)
786-
{
787-
m_userShadowVolumesEnabled = TheGlobalData->m_useShadowVolumes;
788-
m_userShadowDecalsEnabled = TheGlobalData->m_useShadowDecals;
789-
m_userHeatEffectsEnabled = TheGlobalData->m_useHeatEffects;
790-
m_userDynamicLOD = m_currentDynamicLOD;
791-
m_userGraphSnapshotTaken = true;
792-
}
781+
if (!TheGameLogic || (TheGameLogic->getFrame() % LOGICFRAMES_PER_SECOND) != 0)
782+
return;
793783

794-
if (m_isQualityReduced && TheGameClient && TheGameClient->getFrame() <= 1)
784+
if (TheGameLogic->isInShellGame() || TheGameLogic->isInReplayGame() || (TheGameLogic->getFrame() < LOGICFRAMES_PER_SECOND))
795785
{
796-
TheWritableGlobalData->m_useShadowVolumes = m_userShadowVolumesEnabled;
797-
TheWritableGlobalData->m_useShadowDecals = m_userShadowDecalsEnabled;
798-
TheWritableGlobalData->m_useHeatEffects = m_userHeatEffectsEnabled;
799-
setDynamicLODLevel(m_userDynamicLOD);
800-
if (TheGameClient)
801-
TheGameClient->allocateShadows();
802-
m_isQualityReduced = false;
803-
m_stableFPSDuration = 0;
786+
if (m_isQualityReduced)
787+
restoreQualitySettings();
788+
return;
804789
}
805790

806791
if (!m_isQualityReduced)
807792
{
808793
m_userShadowVolumesEnabled = TheGlobalData->m_useShadowVolumes;
809794
m_userShadowDecalsEnabled = TheGlobalData->m_useShadowDecals;
810795
m_userHeatEffectsEnabled = TheGlobalData->m_useHeatEffects;
811-
m_userDynamicLOD = m_currentDynamicLOD;
796+
m_userMaxParticleCount = TheGlobalData->m_maxParticleCount;
812797
}
813798

814-
if (averageFPS < 56.0f)
815-
m_lowFPSSecondsCount++, m_stableFPSDuration = 0;
816-
else if (averageFPS > 57.0f)
817-
m_stableFPSDuration++, m_lowFPSSecondsCount = 0;
799+
// Track how many consecutive seconds FPS is below or above threshold.
800+
const float minAcceptedFPS = 58.f;
801+
if (averageFPS < minAcceptedFPS)
802+
{
803+
m_lowFPSSecondsCount++;
804+
m_stableFPSSecondsCount = 0;
805+
}
806+
else
807+
{
808+
m_stableFPSSecondsCount++;
809+
m_lowFPSSecondsCount = 0;
810+
}
818811

819-
bool shouldReduceQuality = (m_lowFPSSecondsCount >= 2 && TheGameClient && TheGameClient->getFrame() > LOGICFRAMES_PER_SECOND * 10 && !TheShell->isShellActive());
812+
bool isInGame = TheGameLogic->isInGame();
813+
bool shouldReduceQuality = (m_lowFPSSecondsCount >= 2 && isInGame);
820814
if (shouldReduceQuality && !m_isQualityReduced)
821815
{
822-
if (averageFPS < 56.0f)
823-
m_dynamicGameLODInfo[DYNAMIC_GAME_LOD_LOW].m_minDynamicParticlePriority = WEAPON_TRAIL;
824-
if (averageFPS < 40.0f)
825-
m_dynamicGameLODInfo[DYNAMIC_GAME_LOD_LOW].m_minDynamicParticlePriority = ALWAYS_RENDER;
826-
827-
828-
setDynamicLODLevel(DYNAMIC_GAME_LOD_LOW);
829816
TheGameClient->releaseShadows();
830817
TheWritableGlobalData->m_useShadowVolumes = false;
831818
TheWritableGlobalData->m_useShadowDecals = false;
@@ -834,24 +821,40 @@ void GameLODManager::updateGraphicsQualityState(float averageFPS)
834821
m_lowFPSSecondsCount = 0;
835822
}
836823

837-
// Restore to user preferences after sustained good performance
838-
else if (!shouldReduceQuality && m_isQualityReduced)
824+
825+
if (m_isQualityReduced)
839826
{
840-
if (m_stableFPSDuration > 15)
841-
{
842-
TheWritableGlobalData->m_useShadowVolumes = m_userShadowVolumesEnabled;
843-
TheWritableGlobalData->m_useShadowDecals = m_userShadowDecalsEnabled;
844-
TheWritableGlobalData->m_useHeatEffects = m_userHeatEffectsEnabled;
827+
float particleReductionFactor = max(0.f, min(1.f, (minAcceptedFPS - averageFPS) / minAcceptedFPS * 5.f));
828+
int targetCount = max(100, (int)(m_userMaxParticleCount * (1.f - particleReductionFactor)));
829+
int current = TheGlobalData->m_maxParticleCount;
845830

846-
if (TheGameClient)
847-
TheGameClient->allocateShadows();
831+
if (targetCount < current)
832+
TheWritableGlobalData->m_maxParticleCount = max(100, current + (int)((targetCount - current) * 0.5f));
833+
834+
if (!shouldReduceQuality && m_stableFPSSecondsCount > 15)
835+
{
836+
int newCount = current + (int)((m_userMaxParticleCount - current) * 0.3f);
837+
if (newCount >= m_userMaxParticleCount || newCount == current)
838+
restoreQualitySettings();
839+
else
840+
TheWritableGlobalData->m_maxParticleCount = newCount;
848841

849842
DynamicGameLODLevel lod = TheGameLODManager->findDynamicLODLevel(averageFPS);
850843
TheGameLODManager->setDynamicLODLevel(lod);
851-
852-
m_isQualityReduced = false;
853-
m_stableFPSDuration = 0;
854844
}
855845
}
856846
}
847+
848+
void GameLODManager::restoreQualitySettings()
849+
{
850+
TheWritableGlobalData->m_useShadowVolumes = m_userShadowVolumesEnabled;
851+
TheWritableGlobalData->m_useShadowDecals = m_userShadowDecalsEnabled;
852+
TheWritableGlobalData->m_useHeatEffects = m_userHeatEffectsEnabled;
853+
TheWritableGlobalData->m_maxParticleCount = m_userMaxParticleCount;
854+
m_stableFPSSecondsCount = 0;
855+
m_lowFPSSecondsCount = 0;
856+
m_isQualityReduced = false;
857+
if (TheGameClient)
858+
TheGameClient->allocateShadows();
859+
}
857860
#endif // GENERALS_ONLINE_HIGH_FPS_SERVER

GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1681,6 +1681,10 @@ void W3DDisplay::draw()
16811681
return;
16821682

16831683
updateAverageFPS();
1684+
1685+
#if defined(GENERALS_ONLINE_HIGH_FPS_SERVER)
1686+
TheGameLODManager->updateGraphicsQualityState(m_averageFPS);
1687+
#else
16841688
if (TheGlobalData->m_enableDynamicLOD && TheGameLogic->getShowDynamicLOD())
16851689
{
16861690
DynamicGameLODLevel lod = TheGameLODManager->findDynamicLODLevel(m_averageFPS);
@@ -1690,7 +1694,7 @@ void W3DDisplay::draw()
16901694
{ //if dynamic LOD is turned off, force highest LOD
16911695
TheGameLODManager->setDynamicLODLevel(DYNAMIC_GAME_LOD_VERY_HIGH);
16921696
}
1693-
1697+
#endif
16941698
if (TheGlobalData->m_terrainLOD == TERRAIN_LOD_AUTOMATIC && TheTerrainRenderObject)
16951699
{
16961700
calculateTerrainLOD();
@@ -2060,6 +2064,11 @@ void W3DDisplay::createLightPulse(const Coord3D* pos, const RGBColor* color,
20602064
if (innerRadius + attenuationWidth < 2.0 * PATHFIND_CELL_SIZE_F + 1.0f) {
20612065
return; // it basically won't make any visual difference. jba.
20622066
}
2067+
#if defined(GENERALS_ONLINE_HIGH_FPS_SERVER)
2068+
if (TheGameLODManager && TheGameLODManager->isQualityReduced())
2069+
return;
2070+
#endif
2071+
20632072
W3DDynamicLight* theDynamicLight = m_3DScene->getADynamicLight();
20642073
// turn it on.
20652074
theDynamicLight->setEnabled(true);

0 commit comments

Comments
 (0)