You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
291 lines
11 KiB
C++
291 lines
11 KiB
C++
/*
|
|
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
|
* its licensors.
|
|
*
|
|
* For complete copyright and license terms please see the LICENSE at the root of this
|
|
* distribution (the "License"). All use of this software is governed by the License,
|
|
* or, if provided, by the license below or the license accompanying this file. Do not
|
|
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
*
|
|
*/
|
|
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
|
|
|
// Description : Manages overload values (eg CPU,GPU etc)
|
|
// 1.0="everything is ok" 0.0="very bad frame rate"
|
|
// various systems can use this information and control what is currently in the scene
|
|
|
|
|
|
#include "CrySystem_precompiled.h"
|
|
#include "OverloadSceneManager.h"
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Name: COverloadSceneManager
|
|
// Desc: Constructor
|
|
//--------------------------------------------------------------------------------------------------
|
|
COverloadSceneManager::COverloadSceneManager()
|
|
{
|
|
InitialiseCVars();
|
|
|
|
m_currentFrameStat = 0;
|
|
|
|
ResetDefaultValues();
|
|
}//-------------------------------------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Desc: static console callback functions
|
|
//--------------------------------------------------------------------------------------------------
|
|
static void OnChange_osm_enabled(ICVar* pCVar)
|
|
{
|
|
if (pCVar->GetIVal() == 0)
|
|
{
|
|
gEnv->pOverloadSceneManager->Reset();
|
|
//gEnv->pRenderer->EnablePipelineProfiler(false); // would need push/pop since something else might have enabled it
|
|
}
|
|
else if (pCVar->GetIVal() == 1)
|
|
{
|
|
gEnv->pRenderer->EnablePipelineProfiler(true);
|
|
}
|
|
}
|
|
|
|
static void cmd_setFBScale(IConsoleCmdArgs* pParams)
|
|
{
|
|
int argCount = pParams->GetArgCount();
|
|
|
|
Vec2 newScale = Vec2(0.0f, 0.0f);
|
|
gEnv->pRenderer->EF_Query(EFQ_GetViewportDownscaleFactor, newScale);
|
|
|
|
if (argCount > 1)
|
|
{
|
|
newScale.x = clamp_tpl((float)atof(pParams->GetArg(1)), 0.0f, 1.0f);
|
|
|
|
if (argCount > 2)
|
|
{
|
|
newScale.y = clamp_tpl((float)atof(pParams->GetArg(2)), 0.0f, 1.0f);
|
|
}
|
|
else
|
|
{
|
|
newScale.y = newScale.x;
|
|
}
|
|
|
|
newScale = gEnv->pRenderer->SetViewportDownscale(newScale.x, newScale.y);
|
|
}
|
|
|
|
int nWidth = gEnv->pRenderer->GetWidth();
|
|
int nHeight = gEnv->pRenderer->GetHeight();
|
|
|
|
gEnv->pLog->LogWithType(ILog::eInputResponse, "Current Viewport Resolution: %dx%d",
|
|
int(nWidth * newScale.x), int(nHeight * newScale.y));
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Name: InitialiseCVars
|
|
// Desc: Initialises CVars
|
|
//--------------------------------------------------------------------------------------------------
|
|
void COverloadSceneManager::InitialiseCVars()
|
|
{
|
|
// depending on final requirements, these could be made into const cvars
|
|
REGISTER_CVAR_CB(osm_enabled, 0, VF_NULL, "Enables/disables overload scene manager", &OnChange_osm_enabled);
|
|
REGISTER_CVAR(osm_historyLength, 5, VF_NULL, "Overload scene manager number of frames to record stats for");
|
|
REGISTER_CVAR(osm_targetFPS, 28.0f, VF_NULL, "Overload scene manager target frame rate");
|
|
REGISTER_CVAR(osm_targetFPSTolerance, 1.0f, VF_NULL, "The overload scene manager will make adjustments if fps is outside targetFPS +/- this value");
|
|
REGISTER_CVAR(osm_fbScaleDeltaDown, 5.0f, VF_NULL, "The speed multiplier for the overload scene manager frame buffer scaling down");
|
|
REGISTER_CVAR(osm_fbScaleDeltaUp, 1.0f, VF_NULL, "The speed multiplier for the overload scene manager frame buffer scaling up");
|
|
REGISTER_CVAR(osm_fbMinScale, 0.66f, VF_NULL, "The minimum scale factor the overload scene manager will drop to");
|
|
|
|
REGISTER_COMMAND("osm_setFBScale", cmd_setFBScale, VF_NULL, "Sets the framebuffer scale to either a single scale on both X and Y, or independent scales.\n"
|
|
"NOTE: Will be overridden immediately if Overload scene manager is still enabled - see osm_enabled");
|
|
}//-------------------------------------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Name: Reset
|
|
// Desc: Resets overload scene manager outputs to sensible defaults
|
|
//--------------------------------------------------------------------------------------------------
|
|
void COverloadSceneManager::Reset()
|
|
{
|
|
ResetDefaultValues();
|
|
|
|
gEnv->pRenderer->SetViewportDownscale(m_fbScale, m_fbScale);
|
|
}
|
|
|
|
void COverloadSceneManager::ResetDefaultValues()
|
|
{
|
|
m_fbScale = 1.0f;
|
|
m_scaleState = FBSCALE_AUTO;
|
|
m_lerpOverride.m_start = m_lerpOverride.m_length = 1.0f;
|
|
m_lerpOverride.m_reversed = false;
|
|
m_lerpAuto.m_start = m_lerpAuto.m_length = 1.0f;
|
|
m_lerpAuto.m_reversed = true;
|
|
m_fbAutoScale = m_fbOverrideDestScale = m_fbOverrideCurScale = 1.0f;
|
|
|
|
// completely reset history
|
|
for (int i = 0; i < osm_historyLength; i++)
|
|
{
|
|
SScenePerformanceStats& stats = m_sceneStats[i];
|
|
stats.frameRate = stats.gpuFrameRate = osm_targetFPS;
|
|
}
|
|
|
|
m_smoothedSceneStats.frameRate = m_smoothedSceneStats.gpuFrameRate = osm_targetFPS;
|
|
}
|
|
//-------------------------------------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Name: Update
|
|
// Desc: Updates overload scene manager
|
|
//--------------------------------------------------------------------------------------------------
|
|
void COverloadSceneManager::Update()
|
|
{
|
|
if (!osm_enabled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
UpdateStats();
|
|
ResizeFB();
|
|
}//-------------------------------------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Name: OverrideScale and ResetScale
|
|
// Desc: sets up appropriate members for lerping between automatic framebuffer scale and manual
|
|
// overrides.
|
|
//--------------------------------------------------------------------------------------------------
|
|
void COverloadSceneManager::OverrideScale(float frameScale, float dt)
|
|
{
|
|
dt = max(dt, 1.0f / 1000.0f);
|
|
|
|
float curTime = gEnv->pTimer->GetCurrTime();
|
|
|
|
frameScale = clamp_tpl(frameScale, osm_fbMinScale, 1.0f);
|
|
|
|
m_fbOverrideDestScale = frameScale;
|
|
|
|
if (m_scaleState == FBSCALE_AUTO)
|
|
{
|
|
// remove any override lerp - we want to lerp straight from auto to the given value.
|
|
m_lerpOverride.m_start = m_lerpOverride.m_length = 1.0f;
|
|
m_lerpOverride.m_reversed = false;
|
|
m_fbOverrideCurScale = frameScale;
|
|
|
|
m_lerpAuto.m_start = curTime;
|
|
m_lerpAuto.m_length = dt;
|
|
m_lerpAuto.m_reversed = false;
|
|
}
|
|
else if (m_scaleState == FBSCALE_OVERRIDE)
|
|
{
|
|
m_lerpOverride.m_start = curTime;
|
|
m_lerpOverride.m_length = dt;
|
|
m_lerpOverride.m_reversed = false;
|
|
|
|
m_fbOverrideCurScale = m_fbScale;
|
|
}
|
|
|
|
m_scaleState = FBSCALE_OVERRIDE;
|
|
}
|
|
|
|
void COverloadSceneManager::ResetScale(float dt)
|
|
{
|
|
dt = max(dt, 1.0f / 1000.0f);
|
|
|
|
float curTime = gEnv->pTimer->GetCurrTime();
|
|
|
|
// remove any override lerp - we want to lerp straight to auto
|
|
m_lerpOverride.m_start = m_lerpOverride.m_length = 1.0f;
|
|
m_lerpOverride.m_reversed = false;
|
|
m_fbOverrideCurScale = m_fbOverrideDestScale = m_fbScale;
|
|
|
|
m_lerpAuto.m_start = curTime;
|
|
m_lerpAuto.m_length = dt;
|
|
m_lerpAuto.m_reversed = true; // want to lerp back to auto mode
|
|
|
|
m_scaleState = FBSCALE_AUTO;
|
|
}//-------------------------------------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Name: UpdateStats
|
|
// Desc: Updates overload stats
|
|
//--------------------------------------------------------------------------------------------------
|
|
void COverloadSceneManager::UpdateStats()
|
|
{
|
|
m_currentFrameStat++;
|
|
|
|
if (m_currentFrameStat >= osm_historyLength)
|
|
{
|
|
m_currentFrameStat = 0;
|
|
}
|
|
|
|
SScenePerformanceStats& currentStats = m_sceneStats[m_currentFrameStat];
|
|
const float frameLength = gEnv->pTimer->GetRealFrameTime() * 1000.0f;
|
|
const float gpuFrameLength = gEnv->pRenderer->GetGPUFrameTime() * 1000.0f;
|
|
|
|
currentStats.frameRate = frameLength > 0.0f ? 1000.0f / frameLength : 0.0f;
|
|
currentStats.gpuFrameRate = gpuFrameLength > 0.0f ? 1000.0f / gpuFrameLength : 0.0f;
|
|
|
|
CalculateSmoothedStats();
|
|
}//-------------------------------------------------------------------------------------------------
|
|
|
|
void COverloadSceneManager::CalculateSmoothedStats()
|
|
{
|
|
m_smoothedSceneStats.Reset();
|
|
|
|
for (int i = 0; i < osm_historyLength; i++)
|
|
{
|
|
SScenePerformanceStats& stats = m_sceneStats[i];
|
|
m_smoothedSceneStats.frameRate += stats.frameRate;
|
|
m_smoothedSceneStats.gpuFrameRate += stats.gpuFrameRate;
|
|
}
|
|
|
|
m_smoothedSceneStats.frameRate /= osm_historyLength;
|
|
m_smoothedSceneStats.gpuFrameRate /= osm_historyLength;
|
|
}
|
|
|
|
float COverloadSceneManager::CalcFBScale()
|
|
{
|
|
float curTime = gEnv->pTimer->GetCurrTime();
|
|
|
|
// first calculate delta of the override lerp
|
|
float delta = clamp_tpl((curTime - m_lerpOverride.m_start) / m_lerpOverride.m_length, 0.0f, 1.0f);
|
|
if (m_lerpOverride.m_reversed)
|
|
{
|
|
delta = 1.0f - delta;
|
|
}
|
|
|
|
// get the current target override
|
|
float curOverrideScale = LERP(m_fbOverrideCurScale, m_fbOverrideDestScale, delta);
|
|
|
|
// calculate the delta from (or two) automatic scaling
|
|
delta = clamp_tpl((curTime - m_lerpAuto.m_start) / m_lerpAuto.m_length, 0.0f, 1.0f);
|
|
if (m_lerpAuto.m_reversed)
|
|
{
|
|
delta = 1.0f - delta;
|
|
}
|
|
|
|
// final lerp from automatic to current override
|
|
return LERP(m_fbAutoScale, curOverrideScale, delta);
|
|
}
|
|
|
|
void COverloadSceneManager::ResizeFB()
|
|
{
|
|
// don't do anything for invalid framerates
|
|
if (m_smoothedSceneStats.gpuFrameRate < 5.0f || m_smoothedSceneStats.gpuFrameRate > 100.0f)
|
|
{
|
|
return;
|
|
}
|
|
|
|
float fpsDiff = fabsf(m_smoothedSceneStats.gpuFrameRate - osm_targetFPS);
|
|
|
|
if (m_smoothedSceneStats.gpuFrameRate < osm_targetFPS - osm_targetFPSTolerance)
|
|
{
|
|
m_fbAutoScale -= osm_fbScaleDeltaDown / 1000.0f * fpsDiff;
|
|
}
|
|
else if (m_smoothedSceneStats.gpuFrameRate > osm_targetFPS + osm_targetFPSTolerance)
|
|
{
|
|
m_fbAutoScale += osm_fbScaleDeltaUp / 1000.0f * fpsDiff;
|
|
}
|
|
|
|
m_fbAutoScale = clamp_tpl(m_fbAutoScale, osm_fbMinScale, 1.0f);
|
|
|
|
m_fbScale = clamp_tpl(CalcFBScale(), osm_fbMinScale, 1.0f);
|
|
|
|
gEnv->pRenderer->SetViewportDownscale(m_fbScale, m_fbScale);
|
|
}
|