69 lines
2.1 KiB
C++
69 lines
2.1 KiB
C++
#pragma once
|
|
|
|
#include <chrono>
|
|
#include <cstdint>
|
|
|
|
enum class RenderCadenceAction
|
|
{
|
|
Wait,
|
|
Render
|
|
};
|
|
|
|
struct RenderCadencePolicy
|
|
{
|
|
bool skipLateTicks = true;
|
|
uint64_t maxSkippedTicksPerDecision = 4;
|
|
double skipThresholdFrames = 2.0;
|
|
};
|
|
|
|
struct RenderCadenceDecision
|
|
{
|
|
RenderCadenceAction action = RenderCadenceAction::Wait;
|
|
uint64_t frameIndex = 0;
|
|
uint64_t skippedTicks = 0;
|
|
std::chrono::steady_clock::time_point renderTargetTime;
|
|
std::chrono::steady_clock::time_point nextRenderTime;
|
|
std::chrono::steady_clock::duration waitDuration = std::chrono::steady_clock::duration::zero();
|
|
std::chrono::steady_clock::duration lateness = std::chrono::steady_clock::duration::zero();
|
|
const char* reason = "waiting-for-next-render-tick";
|
|
};
|
|
|
|
struct RenderCadenceMetrics
|
|
{
|
|
uint64_t nextFrameIndex = 0;
|
|
uint64_t renderedFrameCount = 0;
|
|
uint64_t skippedTickCount = 0;
|
|
uint64_t lateFrameCount = 0;
|
|
std::chrono::steady_clock::duration lastLateness = std::chrono::steady_clock::duration::zero();
|
|
std::chrono::steady_clock::duration maxLateness = std::chrono::steady_clock::duration::zero();
|
|
};
|
|
|
|
class RenderCadenceController
|
|
{
|
|
public:
|
|
using Clock = std::chrono::steady_clock;
|
|
using TimePoint = Clock::time_point;
|
|
using Duration = Clock::duration;
|
|
|
|
void Configure(Duration targetFrameDuration, TimePoint firstRenderTime, const RenderCadencePolicy& policy = RenderCadencePolicy());
|
|
void Reset(TimePoint firstRenderTime);
|
|
RenderCadenceDecision Tick(TimePoint now);
|
|
|
|
Duration TargetFrameDuration() const { return mTargetFrameDuration; }
|
|
TimePoint NextRenderTime() const { return mNextRenderTime; }
|
|
uint64_t NextFrameIndex() const { return mNextFrameIndex; }
|
|
const RenderCadenceMetrics& Metrics() const { return mMetrics; }
|
|
|
|
private:
|
|
uint64_t SkippedTicksForLateness(Duration lateness) const;
|
|
static bool IsPositive(Duration duration);
|
|
|
|
Duration mTargetFrameDuration = std::chrono::milliseconds(16);
|
|
TimePoint mNextRenderTime;
|
|
uint64_t mNextFrameIndex = 0;
|
|
RenderCadencePolicy mPolicy;
|
|
RenderCadenceMetrics mMetrics;
|
|
};
|
|
|
|
const char* RenderCadenceActionName(RenderCadenceAction action);
|