Refresh rate driven rendering tick logic (#3375)

* Implement sync interval and refresh rate API for RenderViewportWidget

Signed-off-by: nvsickle <nvsickle@amazon.com>

* Measure actual frame timings in the viewport info overlay.

Takes the median of the sum of (frame end - frame begin) to provide more a more representative view of when frames begin and end.

Note: Until VSync is internally supported by the event loop, this will produce nearly identical frame timings as the frame will spend as much time as needed synchronously waiting on a vblank.

Signed-off-by: nvsickle <nvsickle@amazon.com>

* Make frame timing per-pipeline, wire up refresh rate info to ViewportContext

Signed-off-by: nvsickle <nvsickle@amazon.com>

* POC: Frame limit pipeline rendering

Signed-off-by: nvsickle <nvsickle@amazon.com>

* Switch Editor tick to every 0ms to allow better tick accumulation behavior

Signed-off-by: nvsickle <nvsickle@amazon.com>

* Move RPISystemComponent to the tick bus, remove tick accumulation logic

Signed-off-by: nvsickle <nvsickle@amazon.com>

* Add `AddToRenderTickAtInterval` to RenderPipeline API

This allows a pipeline to update at a set cadence, instead of rendering every frame or being directly told when to tick.

Signed-off-by: nvsickle <nvsickle@amazon.com>

* Make ViewportContext enforce a target framerate

-Adds GetFpsLimit/SetFpsLimit for actively limiting FPS
-Calculates a render tick interval based on vsync and the vps limit and updates the current pipeline

Signed-off-by: nvsickle <nvsickle@amazon.com>

* Add r_fps_limit and ed_inactive_viewport_fps_limit cvars

Signed-off-by: nvsickle <nvsickle@amazon.com>

* Quick null check from a crash I bumped into

Signed-off-by: nvsickle <nvsickle@amazon.com>

* Fix off-by-one on FPS calculation (shouldn't include the not-yet-rendered frame)

Signed-off-by: nvsickle <nvsickle@amazon.com>

* Clarify frame time begin initialization

Signed-off-by: nvsickle <nvsickle@amazon.com>

* Fix TrackView export.

Signed-off-by: nvsickle <nvsickle@amazon.com>

* Address some reviewer feedback, revert RPISystem API change, fix CPU profiler.

Signed-off-by: nvsickle <nvsickle@amazon.com>

* Add g_simulation_tick_rate

Signed-off-by: nvsickle <nvsickle@amazon.com>

* Address review feedback, make frame limit updates event driven

Signed-off-by: nvsickle <nvsickle@amazon.com>

* Remove timestamp update from ComponentApplication::Tick

Signed-off-by: nvsickle <nvsickle@amazon.com>
This commit is contained in:
Nicholas Van Sickle
2021-09-13 17:57:42 -07:00
committed by GitHub
parent b2963f2bc1
commit db63dcbcd9
26 changed files with 633 additions and 124 deletions
@@ -41,7 +41,14 @@
#include <AzCore/Console/IConsole.h>
#include <BootstrapSystemComponent_Traits_Platform.h>
static void OnFrameRateLimitChanged(const float& fpsLimit)
{
AZ::Render::Bootstrap::RequestBus::Broadcast(
&AZ::Render::Bootstrap::RequestBus::Events::SetFrameRateLimit, fpsLimit);
}
AZ_CVAR(AZ::CVarFixedString, r_default_pipeline_name, AZ_TRAIT_BOOTSTRAPSYSTEMCOMPONENT_PIPELINE_NAME, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Default Render pipeline name");
AZ_CVAR(float, r_fps_limit, 0, OnFrameRateLimitChanged, AZ::ConsoleFunctorFlags::Null, "The maximum framerate to render at, or 0 for unlimited");
namespace AZ
{
@@ -342,6 +349,22 @@ namespace AZ
return true;
}
float BootstrapSystemComponent::GetFrameRateLimit() const
{
return r_fps_limit;
}
void BootstrapSystemComponent::SetFrameRateLimit(float fpsLimit)
{
r_fps_limit = fpsLimit;
if (m_viewportContext)
{
m_viewportContext->SetFpsLimit(r_fps_limit);
}
Render::Bootstrap::NotificationBus::Broadcast(
&Render::Bootstrap::NotificationBus::Events::OnFrameRateLimitChanged, fpsLimit);
}
void BootstrapSystemComponent::CreateDefaultRenderPipeline()
{
EnsureDefaultRenderPipelineInstalledForScene(m_defaultScene, m_viewportContext);
@@ -381,23 +404,11 @@ namespace AZ
}
void BootstrapSystemComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] ScriptTimePoint time)
{
// Temp: When running in the launcher without the legacy renderer
// we need to call RenderTick on the viewport context each frame.
if (m_viewportContext)
{
AZ::ApplicationTypeQuery appType;
ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationBus::Events::QueryApplicationType, appType);
if (appType.IsGame())
{
m_viewportContext->RenderTick();
}
}
}
{ }
int BootstrapSystemComponent::GetTickOrder()
{
return TICK_LAST;
return TICK_PRE_RENDER;
}
void BootstrapSystemComponent::OnWindowClosed()