Render timing
This commit is contained in:
@@ -85,6 +85,11 @@ RenderThread::Metrics RenderThread::GetMetrics() const
|
||||
metrics.skippedFrames = mSkippedFrames.load(std::memory_order_relaxed);
|
||||
metrics.shaderBuildsCommitted = mShaderBuildsCommitted.load(std::memory_order_relaxed);
|
||||
metrics.shaderBuildFailures = mShaderBuildFailures.load(std::memory_order_relaxed);
|
||||
metrics.renderFrameMilliseconds = mRenderFrameMilliseconds.load(std::memory_order_relaxed);
|
||||
metrics.renderFrameBudgetUsedPercent = mRenderFrameBudgetUsedPercent.load(std::memory_order_relaxed);
|
||||
metrics.renderFrameMaxMilliseconds = mRenderFrameMaxMilliseconds.load(std::memory_order_relaxed);
|
||||
metrics.readbackQueueMilliseconds = mReadbackQueueMilliseconds.load(std::memory_order_relaxed);
|
||||
metrics.completedReadbackCopyMilliseconds = mCompletedReadbackCopyMilliseconds.load(std::memory_order_relaxed);
|
||||
metrics.inputFramesReceived = mInputFramesReceived.load(std::memory_order_relaxed);
|
||||
metrics.inputFramesDropped = mInputFramesDropped.load(std::memory_order_relaxed);
|
||||
metrics.inputConsumeMisses = mInputConsumeMisses.load(std::memory_order_relaxed);
|
||||
@@ -154,6 +159,7 @@ void RenderThread::ThreadMain()
|
||||
CountAcquireMiss();
|
||||
},
|
||||
[this]() { CountCompleted(); });
|
||||
PublishReadbackMetrics(readback);
|
||||
|
||||
const auto now = RenderCadenceClock::Clock::now();
|
||||
const RenderCadenceClock::Tick tick = clock.Poll(now);
|
||||
@@ -178,6 +184,7 @@ void RenderThread::ThreadMain()
|
||||
{
|
||||
mPboQueueMisses.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
PublishReadbackMetrics(readback);
|
||||
|
||||
CountRendered();
|
||||
++frameIndex;
|
||||
@@ -196,6 +203,7 @@ void RenderThread::ThreadMain()
|
||||
CountAcquireMiss();
|
||||
},
|
||||
[this]() { CountCompleted(); });
|
||||
PublishReadbackMetrics(readback);
|
||||
}
|
||||
|
||||
readback.Shutdown();
|
||||
@@ -237,6 +245,29 @@ void RenderThread::CountAcquireMiss()
|
||||
mAcquireMisses.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void RenderThread::PublishReadbackMetrics(const Bgra8ReadbackPipeline& readback)
|
||||
{
|
||||
const double renderMilliseconds = readback.LastRenderFrameMilliseconds();
|
||||
mRenderFrameMilliseconds.store(renderMilliseconds, std::memory_order_relaxed);
|
||||
if (mConfig.frameDurationMilliseconds > 0.0)
|
||||
{
|
||||
mRenderFrameBudgetUsedPercent.store(
|
||||
(renderMilliseconds / mConfig.frameDurationMilliseconds) * 100.0,
|
||||
std::memory_order_relaxed);
|
||||
}
|
||||
else
|
||||
{
|
||||
mRenderFrameBudgetUsedPercent.store(0.0, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
const double previousMax = mRenderFrameMaxMilliseconds.load(std::memory_order_relaxed);
|
||||
if (renderMilliseconds > previousMax)
|
||||
mRenderFrameMaxMilliseconds.store(renderMilliseconds, std::memory_order_relaxed);
|
||||
|
||||
mReadbackQueueMilliseconds.store(readback.LastReadbackQueueMilliseconds(), std::memory_order_relaxed);
|
||||
mCompletedReadbackCopyMilliseconds.store(readback.LastCompletedReadbackCopyMilliseconds(), std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void RenderThread::PublishInputMetrics(const InputFrameTexture& inputTexture)
|
||||
{
|
||||
if (mInputMailbox != nullptr)
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
class SystemFrameExchange;
|
||||
class InputFrameMailbox;
|
||||
class InputFrameTexture;
|
||||
class Bgra8ReadbackPipeline;
|
||||
|
||||
class RenderThread
|
||||
{
|
||||
@@ -38,6 +39,11 @@ public:
|
||||
uint64_t skippedFrames = 0;
|
||||
uint64_t shaderBuildsCommitted = 0;
|
||||
uint64_t shaderBuildFailures = 0;
|
||||
double renderFrameMilliseconds = 0.0;
|
||||
double renderFrameBudgetUsedPercent = 0.0;
|
||||
double renderFrameMaxMilliseconds = 0.0;
|
||||
double readbackQueueMilliseconds = 0.0;
|
||||
double completedReadbackCopyMilliseconds = 0.0;
|
||||
uint64_t inputFramesReceived = 0;
|
||||
uint64_t inputFramesDropped = 0;
|
||||
uint64_t inputConsumeMisses = 0;
|
||||
@@ -71,6 +77,7 @@ private:
|
||||
void CountRendered();
|
||||
void CountCompleted();
|
||||
void CountAcquireMiss();
|
||||
void PublishReadbackMetrics(const Bgra8ReadbackPipeline& readback);
|
||||
void PublishInputMetrics(const InputFrameTexture& inputTexture);
|
||||
void TryCommitReadyRuntimeShader(RuntimeRenderScene& runtimeRenderScene);
|
||||
bool TryTakePendingRuntimeShaderArtifact(RuntimeShaderArtifact& artifact);
|
||||
@@ -96,6 +103,11 @@ private:
|
||||
std::atomic<uint64_t> mSkippedFrames{ 0 };
|
||||
std::atomic<uint64_t> mShaderBuildsCommitted{ 0 };
|
||||
std::atomic<uint64_t> mShaderBuildFailures{ 0 };
|
||||
std::atomic<double> mRenderFrameMilliseconds{ 0.0 };
|
||||
std::atomic<double> mRenderFrameBudgetUsedPercent{ 0.0 };
|
||||
std::atomic<double> mRenderFrameMaxMilliseconds{ 0.0 };
|
||||
std::atomic<double> mReadbackQueueMilliseconds{ 0.0 };
|
||||
std::atomic<double> mCompletedReadbackCopyMilliseconds{ 0.0 };
|
||||
std::atomic<uint64_t> mInputFramesReceived{ 0 };
|
||||
std::atomic<uint64_t> mInputFramesDropped{ 0 };
|
||||
std::atomic<uint64_t> mInputConsumeMisses{ 0 };
|
||||
|
||||
@@ -2,8 +2,18 @@
|
||||
|
||||
#include "../frames/SystemFrameTypes.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
|
||||
namespace
|
||||
{
|
||||
double MillisecondsSince(std::chrono::steady_clock::time_point start)
|
||||
{
|
||||
return std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(
|
||||
std::chrono::steady_clock::now() - start).count();
|
||||
}
|
||||
}
|
||||
|
||||
Bgra8ReadbackPipeline::~Bgra8ReadbackPipeline()
|
||||
{
|
||||
Shutdown();
|
||||
@@ -50,10 +60,15 @@ bool Bgra8ReadbackPipeline::RenderAndQueue(uint64_t frameIndex, const RenderCall
|
||||
return false;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
|
||||
const auto renderStart = std::chrono::steady_clock::now();
|
||||
renderFrame(frameIndex);
|
||||
mLastRenderFrameMilliseconds = MillisecondsSince(renderStart);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
return mPboRing.QueueReadback(mFramebuffer, mWidth, mHeight, frameIndex);
|
||||
const auto queueStart = std::chrono::steady_clock::now();
|
||||
const bool queued = mPboRing.QueueReadback(mFramebuffer, mWidth, mHeight, frameIndex);
|
||||
mLastReadbackQueueMilliseconds = MillisecondsSince(queueStart);
|
||||
return queued;
|
||||
}
|
||||
|
||||
void Bgra8ReadbackPipeline::ConsumeCompleted(
|
||||
@@ -68,12 +83,14 @@ void Bgra8ReadbackPipeline::ConsumeCompleted(
|
||||
PboReadbackRing::CompletedReadback readback;
|
||||
while (mPboRing.TryAcquireCompleted(readback))
|
||||
{
|
||||
const auto copyStart = std::chrono::steady_clock::now();
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, readback.pbo);
|
||||
void* mapped = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
|
||||
if (!mapped)
|
||||
{
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
mPboRing.ReleaseCompleted(readback);
|
||||
mLastCompletedReadbackCopyMilliseconds = MillisecondsSince(copyStart);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -99,6 +116,7 @@ void Bgra8ReadbackPipeline::ConsumeCompleted(
|
||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
mPboRing.ReleaseCompleted(readback);
|
||||
mLastCompletedReadbackCopyMilliseconds = MillisecondsSince(copyStart);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,9 @@ public:
|
||||
unsigned RowBytes() const { return mRowBytes; }
|
||||
VideoIOPixelFormat PixelFormat() const { return VideoIOPixelFormat::Bgra8; }
|
||||
uint64_t PboQueueMisses() const { return mPboRing.QueueMisses(); }
|
||||
double LastRenderFrameMilliseconds() const { return mLastRenderFrameMilliseconds; }
|
||||
double LastReadbackQueueMilliseconds() const { return mLastReadbackQueueMilliseconds; }
|
||||
double LastCompletedReadbackCopyMilliseconds() const { return mLastCompletedReadbackCopyMilliseconds; }
|
||||
|
||||
private:
|
||||
bool CreateRenderTarget();
|
||||
@@ -48,5 +51,8 @@ private:
|
||||
unsigned mRowBytes = 0;
|
||||
GLuint mFramebuffer = 0;
|
||||
GLuint mTexture = 0;
|
||||
double mLastRenderFrameMilliseconds = 0.0;
|
||||
double mLastReadbackQueueMilliseconds = 0.0;
|
||||
double mLastCompletedReadbackCopyMilliseconds = 0.0;
|
||||
PboReadbackRing mPboRing;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user