Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions GeneralsMD/Code/GameEngine/Include/Common/GameLOD.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ class GameLODManager
Bool isReallyLowMHz() const { return m_cpuFreq < m_reallyLowMHz; }
#if defined(GENERALS_ONLINE_HIGH_FPS_SERVER)
void updateGraphicsQualityState(float averageFPS);
void restoreQualitySettings();
bool isQualityReduced() const { return m_isQualityReduced; }
#endif

StaticGameLODInfo m_staticGameLODInfo[STATIC_GAME_LOD_COUNT];
Expand Down Expand Up @@ -230,14 +232,13 @@ class GameLODManager
Real m_compositeBenchIndex;
Int m_reallyLowMHz;
#if defined(GENERALS_ONLINE_HIGH_FPS_SERVER)
bool m_userGraphSnapshotTaken;
bool m_userShadowVolumesEnabled;
bool m_userShadowDecalsEnabled;
bool m_userHeatEffectsEnabled;
bool m_isQualityReduced;
int m_stableFPSDuration;
int m_lowFPSSecondsCount;
DynamicGameLODLevel m_userDynamicLOD;
int m_stableFPSSecondsCount;
int m_lowFPSSecondsCount;
int m_userMaxParticleCount;
#endif
};

Expand Down
101 changes: 52 additions & 49 deletions GeneralsMD/Code/GameEngine/Source/Common/GameLOD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@

#define DEFINE_PARTICLE_SYSTEM_NAMES
#include "GameClient/ParticleSys.h"
#include "GameClient/Shell.h"
#include "GameLogic/GameLogic.h"


#define PROFILE_ERROR_LIMIT 0.94f //fraction of profiled result needed to get a match. Allows some room for error/fluctuation.
Expand Down Expand Up @@ -232,14 +232,10 @@ GameLODManager::GameLODManager()
m_numBenchProfiles=0;
m_reallyLowMHz = 400;
#if defined(GENERALS_ONLINE_HIGH_FPS_SERVER)
m_userGraphSnapshotTaken = false;
m_userShadowVolumesEnabled = true;
m_userShadowDecalsEnabled = true;
m_userHeatEffectsEnabled = true;
m_isQualityReduced = false;
m_stableFPSDuration = 0;
m_lowFPSSecondsCount = 0;
m_userDynamicLOD = DYNAMIC_GAME_LOD_VERY_HIGH;
m_stableFPSSecondsCount = 0;
m_userMaxParticleCount = 0;
#endif

for (Int i=0; i<STATIC_GAME_LOD_CUSTOM; i++)
Expand Down Expand Up @@ -782,50 +778,41 @@ Bool GameLODManager::didMemPass()
#if defined(GENERALS_ONLINE_HIGH_FPS_SERVER)
void GameLODManager::updateGraphicsQualityState(float averageFPS)
{
if (!m_userGraphSnapshotTaken)
{
m_userShadowVolumesEnabled = TheGlobalData->m_useShadowVolumes;
m_userShadowDecalsEnabled = TheGlobalData->m_useShadowDecals;
m_userHeatEffectsEnabled = TheGlobalData->m_useHeatEffects;
m_userDynamicLOD = m_currentDynamicLOD;
m_userGraphSnapshotTaken = true;
}
if (!TheGameLogic || (TheGameLogic->getFrame() % LOGICFRAMES_PER_SECOND) != 0)
return;

if (m_isQualityReduced && TheGameClient && TheGameClient->getFrame() <= 1)
if (TheGameLogic->isInShellGame() || TheGameLogic->isInReplayGame() || (TheGameLogic->getFrame() < LOGICFRAMES_PER_SECOND))
{
TheWritableGlobalData->m_useShadowVolumes = m_userShadowVolumesEnabled;
TheWritableGlobalData->m_useShadowDecals = m_userShadowDecalsEnabled;
TheWritableGlobalData->m_useHeatEffects = m_userHeatEffectsEnabled;
setDynamicLODLevel(m_userDynamicLOD);
if (TheGameClient)
TheGameClient->allocateShadows();
m_isQualityReduced = false;
m_stableFPSDuration = 0;
if (m_isQualityReduced)
restoreQualitySettings();
return;
}

if (!m_isQualityReduced)
{
m_userShadowVolumesEnabled = TheGlobalData->m_useShadowVolumes;
m_userShadowDecalsEnabled = TheGlobalData->m_useShadowDecals;
m_userHeatEffectsEnabled = TheGlobalData->m_useHeatEffects;
m_userDynamicLOD = m_currentDynamicLOD;
m_userMaxParticleCount = TheGlobalData->m_maxParticleCount;
}

if (averageFPS < 56.0f)
m_lowFPSSecondsCount++, m_stableFPSDuration = 0;
else if (averageFPS > 57.0f)
m_stableFPSDuration++, m_lowFPSSecondsCount = 0;
// Track how many consecutive seconds FPS is below or above threshold.
const float minAcceptedFPS = 58.f;
if (averageFPS < minAcceptedFPS)
{
m_lowFPSSecondsCount++;
m_stableFPSSecondsCount = 0;
}
else
{
m_stableFPSSecondsCount++;
m_lowFPSSecondsCount = 0;
}

bool shouldReduceQuality = (m_lowFPSSecondsCount >= 2 && TheGameClient && TheGameClient->getFrame() > LOGICFRAMES_PER_SECOND * 10 && !TheShell->isShellActive());
bool isInGame = TheGameLogic->isInGame();
bool shouldReduceQuality = (m_lowFPSSecondsCount >= 2 && isInGame);
if (shouldReduceQuality && !m_isQualityReduced)
{
if (averageFPS < 56.0f)
m_dynamicGameLODInfo[DYNAMIC_GAME_LOD_LOW].m_minDynamicParticlePriority = WEAPON_TRAIL;
if (averageFPS < 40.0f)
m_dynamicGameLODInfo[DYNAMIC_GAME_LOD_LOW].m_minDynamicParticlePriority = ALWAYS_RENDER;


setDynamicLODLevel(DYNAMIC_GAME_LOD_LOW);
TheGameClient->releaseShadows();
TheWritableGlobalData->m_useShadowVolumes = false;
TheWritableGlobalData->m_useShadowDecals = false;
Expand All @@ -834,24 +821,40 @@ void GameLODManager::updateGraphicsQualityState(float averageFPS)
m_lowFPSSecondsCount = 0;
}

// Restore to user preferences after sustained good performance
else if (!shouldReduceQuality && m_isQualityReduced)

if (m_isQualityReduced)
{
if (m_stableFPSDuration > 15)
{
TheWritableGlobalData->m_useShadowVolumes = m_userShadowVolumesEnabled;
TheWritableGlobalData->m_useShadowDecals = m_userShadowDecalsEnabled;
TheWritableGlobalData->m_useHeatEffects = m_userHeatEffectsEnabled;
float particleReductionFactor = max(0.f, min(1.f, (minAcceptedFPS - averageFPS) / minAcceptedFPS * 5.f));
int targetCount = max(100, (int)(m_userMaxParticleCount * (1.f - particleReductionFactor)));
int current = TheGlobalData->m_maxParticleCount;

if (TheGameClient)
TheGameClient->allocateShadows();
if (targetCount < current)
TheWritableGlobalData->m_maxParticleCount = max(100, current + (int)((targetCount - current) * 0.5f));

if (!shouldReduceQuality && m_stableFPSSecondsCount > 15)
{
int newCount = current + (int)((m_userMaxParticleCount - current) * 0.3f);
if (newCount >= m_userMaxParticleCount || newCount == current)
restoreQualitySettings();
else
TheWritableGlobalData->m_maxParticleCount = newCount;

DynamicGameLODLevel lod = TheGameLODManager->findDynamicLODLevel(averageFPS);
TheGameLODManager->setDynamicLODLevel(lod);

m_isQualityReduced = false;
m_stableFPSDuration = 0;
}
}
}

void GameLODManager::restoreQualitySettings()
{
TheWritableGlobalData->m_useShadowVolumes = m_userShadowVolumesEnabled;
TheWritableGlobalData->m_useShadowDecals = m_userShadowDecalsEnabled;
TheWritableGlobalData->m_useHeatEffects = m_userHeatEffectsEnabled;
TheWritableGlobalData->m_maxParticleCount = m_userMaxParticleCount;
m_stableFPSSecondsCount = 0;
m_lowFPSSecondsCount = 0;
m_isQualityReduced = false;
if (TheGameClient)
TheGameClient->allocateShadows();
}
#endif // GENERALS_ONLINE_HIGH_FPS_SERVER
Original file line number Diff line number Diff line change
Expand Up @@ -1681,6 +1681,10 @@ void W3DDisplay::draw()
return;

updateAverageFPS();

#if defined(GENERALS_ONLINE_HIGH_FPS_SERVER)
TheGameLODManager->updateGraphicsQualityState(m_averageFPS);
#else
if (TheGlobalData->m_enableDynamicLOD && TheGameLogic->getShowDynamicLOD())
{
DynamicGameLODLevel lod = TheGameLODManager->findDynamicLODLevel(m_averageFPS);
Expand All @@ -1690,7 +1694,7 @@ void W3DDisplay::draw()
{ //if dynamic LOD is turned off, force highest LOD
TheGameLODManager->setDynamicLODLevel(DYNAMIC_GAME_LOD_VERY_HIGH);
}

#endif
if (TheGlobalData->m_terrainLOD == TERRAIN_LOD_AUTOMATIC && TheTerrainRenderObject)
{
calculateTerrainLOD();
Expand Down Expand Up @@ -2060,6 +2064,11 @@ void W3DDisplay::createLightPulse(const Coord3D* pos, const RGBColor* color,
if (innerRadius + attenuationWidth < 2.0 * PATHFIND_CELL_SIZE_F + 1.0f) {
return; // it basically won't make any visual difference. jba.
}
#if defined(GENERALS_ONLINE_HIGH_FPS_SERVER)
if (TheGameLODManager && TheGameLODManager->isQualityReduced())
return;
#endif

W3DDynamicLight* theDynamicLight = m_3DScene->getADynamicLight();
// turn it on.
theDynamicLight->setEnabled(true);
Expand Down
Loading