Phase 4 step 2a
All checks were successful
CI / React UI Build (push) Successful in 11s
CI / Native Windows Build And Tests (push) Successful in 2m36s
CI / Windows Release Package (push) Successful in 2m42s

This commit is contained in:
Aiden
2026-05-11 17:26:24 +10:00
parent 539fcd3351
commit 0ec5a4cfed
7 changed files with 358 additions and 67 deletions

View File

@@ -0,0 +1,116 @@
#include "RenderCommandQueue.h"
void RenderCommandQueue::RequestPreviewPresent(const RenderPreviewPresentRequest& request)
{
std::lock_guard<std::mutex> lock(mMutex);
if (mHasPreviewPresentRequest)
++mCoalescedCount;
else
++mEnqueuedCount;
mPreviewPresentRequest = request;
mHasPreviewPresentRequest = true;
}
bool RenderCommandQueue::TryTakePreviewPresent(RenderPreviewPresentRequest& request)
{
std::lock_guard<std::mutex> lock(mMutex);
if (!mHasPreviewPresentRequest)
return false;
request = mPreviewPresentRequest;
mPreviewPresentRequest = {};
mHasPreviewPresentRequest = false;
return true;
}
void RenderCommandQueue::RequestScreenshotCapture(const RenderScreenshotCaptureRequest& request)
{
std::lock_guard<std::mutex> lock(mMutex);
if (mHasScreenshotCaptureRequest)
++mCoalescedCount;
else
++mEnqueuedCount;
mScreenshotCaptureRequest = request;
mHasScreenshotCaptureRequest = true;
}
bool RenderCommandQueue::TryTakeScreenshotCapture(RenderScreenshotCaptureRequest& request)
{
std::lock_guard<std::mutex> lock(mMutex);
if (!mHasScreenshotCaptureRequest)
return false;
request = mScreenshotCaptureRequest;
mScreenshotCaptureRequest = {};
mHasScreenshotCaptureRequest = false;
return true;
}
void RenderCommandQueue::RequestRenderReset(RenderCommandResetScope scope)
{
if (scope == RenderCommandResetScope::None)
return;
std::lock_guard<std::mutex> lock(mMutex);
if (mRenderResetScope != RenderCommandResetScope::None)
++mCoalescedCount;
else
++mEnqueuedCount;
mRenderResetScope = MergeResetScopes(mRenderResetScope, scope);
}
bool RenderCommandQueue::TryTakeRenderReset(RenderCommandResetScope& scope)
{
std::lock_guard<std::mutex> lock(mMutex);
if (mRenderResetScope == RenderCommandResetScope::None)
return false;
scope = mRenderResetScope;
mRenderResetScope = RenderCommandResetScope::None;
return true;
}
RenderCommandQueueMetrics RenderCommandQueue::GetMetrics() const
{
std::lock_guard<std::mutex> lock(mMutex);
RenderCommandQueueMetrics metrics;
metrics.depth =
(mHasPreviewPresentRequest ? 1u : 0u) +
(mHasScreenshotCaptureRequest ? 1u : 0u) +
(mRenderResetScope != RenderCommandResetScope::None ? 1u : 0u);
metrics.enqueuedCount = mEnqueuedCount;
metrics.coalescedCount = mCoalescedCount;
return metrics;
}
RenderCommandResetScope RenderCommandQueue::MergeResetScopes(RenderCommandResetScope current, RenderCommandResetScope requested)
{
if (current == RenderCommandResetScope::TemporalHistoryAndFeedback ||
requested == RenderCommandResetScope::TemporalHistoryAndFeedback)
{
return RenderCommandResetScope::TemporalHistoryAndFeedback;
}
if ((current == RenderCommandResetScope::TemporalHistoryOnly && requested == RenderCommandResetScope::ShaderFeedbackOnly) ||
(current == RenderCommandResetScope::ShaderFeedbackOnly && requested == RenderCommandResetScope::TemporalHistoryOnly))
{
return RenderCommandResetScope::TemporalHistoryAndFeedback;
}
if (current == RenderCommandResetScope::TemporalHistoryOnly ||
requested == RenderCommandResetScope::TemporalHistoryOnly)
{
return RenderCommandResetScope::TemporalHistoryOnly;
}
if (current == RenderCommandResetScope::ShaderFeedbackOnly ||
requested == RenderCommandResetScope::ShaderFeedbackOnly)
{
return RenderCommandResetScope::ShaderFeedbackOnly;
}
return RenderCommandResetScope::None;
}

View File

@@ -0,0 +1,59 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include <mutex>
enum class RenderCommandResetScope
{
None,
ShaderFeedbackOnly,
TemporalHistoryOnly,
TemporalHistoryAndFeedback
};
struct RenderPreviewPresentRequest
{
unsigned outputFrameWidth = 0;
unsigned outputFrameHeight = 0;
};
struct RenderScreenshotCaptureRequest
{
unsigned width = 0;
unsigned height = 0;
};
struct RenderCommandQueueMetrics
{
std::size_t depth = 0;
uint64_t enqueuedCount = 0;
uint64_t coalescedCount = 0;
};
class RenderCommandQueue
{
public:
void RequestPreviewPresent(const RenderPreviewPresentRequest& request);
bool TryTakePreviewPresent(RenderPreviewPresentRequest& request);
void RequestScreenshotCapture(const RenderScreenshotCaptureRequest& request);
bool TryTakeScreenshotCapture(RenderScreenshotCaptureRequest& request);
void RequestRenderReset(RenderCommandResetScope scope);
bool TryTakeRenderReset(RenderCommandResetScope& scope);
RenderCommandQueueMetrics GetMetrics() const;
private:
static RenderCommandResetScope MergeResetScopes(RenderCommandResetScope current, RenderCommandResetScope requested);
mutable std::mutex mMutex;
bool mHasPreviewPresentRequest = false;
RenderPreviewPresentRequest mPreviewPresentRequest;
bool mHasScreenshotCaptureRequest = false;
RenderScreenshotCaptureRequest mScreenshotCaptureRequest;
RenderCommandResetScope mRenderResetScope = RenderCommandResetScope::None;
uint64_t mEnqueuedCount = 0;
uint64_t mCoalescedCount = 0;
};

View File

@@ -1,7 +1,5 @@
#include "RenderEngine.h"
#include "ShaderBuildQueue.h"
#include <gl/gl.h>
#include <algorithm>
@@ -88,48 +86,16 @@ bool RenderEngine::ApplyPreparedShaderBuild(
return true;
}
RenderEngine::PreparedShaderBuildApplyResult RenderEngine::TryApplyReadyShaderBuild(
ShaderBuildQueue& shaderBuildQueue,
unsigned inputFrameWidth,
unsigned inputFrameHeight,
bool preserveFeedbackState)
{
PreparedShaderBuildApplyResult result;
PreparedShaderBuild readyBuild;
if (!shaderBuildQueue.TryConsumeReadyBuild(readyBuild))
return result;
result.hadReadyBuild = true;
char compilerErrorMessage[1024] = {};
if (!ApplyPreparedShaderBuild(
readyBuild,
inputFrameWidth,
inputFrameHeight,
preserveFeedbackState,
sizeof(compilerErrorMessage),
compilerErrorMessage))
{
result.errorMessage = compilerErrorMessage;
return result;
}
result.applied = true;
return result;
}
const std::vector<RuntimeRenderState>& RenderEngine::CommittedLayerStates() const
{
return mShaderPrograms.CommittedLayerStates();
}
void RenderEngine::ResetTemporalHistoryState()
{
mShaderPrograms.ResetTemporalHistoryState();
mRenderCommandQueue.RequestRenderReset(RenderCommandResetScope::TemporalHistoryOnly);
ProcessRenderResetCommandsOnRenderThread();
}
void RenderEngine::ResetShaderFeedbackState()
{
mShaderPrograms.ResetShaderFeedbackState();
mRenderCommandQueue.RequestRenderReset(RenderCommandResetScope::ShaderFeedbackOnly);
ProcessRenderResetCommandsOnRenderThread();
}
void RenderEngine::ApplyRuntimeCoordinatorRenderReset(RuntimeCoordinatorRenderResetScope resetScope)
@@ -137,11 +103,12 @@ void RenderEngine::ApplyRuntimeCoordinatorRenderReset(RuntimeCoordinatorRenderRe
switch (resetScope)
{
case RuntimeCoordinatorRenderResetScope::TemporalHistoryOnly:
ResetTemporalHistoryState();
mRenderCommandQueue.RequestRenderReset(RenderCommandResetScope::TemporalHistoryOnly);
ProcessRenderResetCommandsOnRenderThread();
break;
case RuntimeCoordinatorRenderResetScope::TemporalHistoryAndFeedback:
ResetTemporalHistoryState();
ResetShaderFeedbackState();
mRenderCommandQueue.RequestRenderReset(RenderCommandResetScope::TemporalHistoryAndFeedback);
ProcessRenderResetCommandsOnRenderThread();
break;
case RuntimeCoordinatorRenderResetScope::None:
default:
@@ -149,6 +116,43 @@ void RenderEngine::ApplyRuntimeCoordinatorRenderReset(RuntimeCoordinatorRenderRe
}
}
void RenderEngine::ResetTemporalHistoryStateOnRenderThread()
{
mShaderPrograms.ResetTemporalHistoryState();
}
void RenderEngine::ResetShaderFeedbackStateOnRenderThread()
{
mShaderPrograms.ResetShaderFeedbackState();
}
void RenderEngine::ApplyRenderResetOnRenderThread(RenderCommandResetScope resetScope)
{
switch (resetScope)
{
case RenderCommandResetScope::ShaderFeedbackOnly:
ResetShaderFeedbackStateOnRenderThread();
break;
case RenderCommandResetScope::TemporalHistoryOnly:
ResetTemporalHistoryStateOnRenderThread();
break;
case RenderCommandResetScope::TemporalHistoryAndFeedback:
ResetTemporalHistoryStateOnRenderThread();
ResetShaderFeedbackStateOnRenderThread();
break;
case RenderCommandResetScope::None:
default:
break;
}
}
void RenderEngine::ProcessRenderResetCommandsOnRenderThread()
{
RenderCommandResetScope resetScope = RenderCommandResetScope::None;
while (mRenderCommandQueue.TryTakeRenderReset(resetScope))
ApplyRenderResetOnRenderThread(resetScope);
}
void RenderEngine::ClearOscOverlayState()
{
mRuntimeLiveState.Clear();
@@ -195,7 +199,10 @@ bool RenderEngine::TryPresentPreview(bool force, unsigned previewFps, unsigned o
if (!TryEnterCriticalSection(&mMutex))
return false;
const bool presented = PresentPreviewOnRenderThread(outputFrameWidth, outputFrameHeight);
mRenderCommandQueue.RequestPreviewPresent({ outputFrameWidth, outputFrameHeight });
RenderPreviewPresentRequest request;
const bool presented = mRenderCommandQueue.TryTakePreviewPresent(request) &&
PresentPreviewOnRenderThread(request.outputFrameWidth, request.outputFrameHeight);
LeaveCriticalSection(&mMutex);
return presented;
}
@@ -252,6 +259,7 @@ bool RenderEngine::RenderOutputFrame(const RenderPipelineFrameContext& context,
bool RenderEngine::RenderOutputFrameOnRenderThread(const RenderPipelineFrameContext& context, VideoIOOutputFrame& outputFrame)
{
ProcessRenderResetCommandsOnRenderThread();
return mRenderPipeline.RenderFrame(context, outputFrame);
}
@@ -333,7 +341,10 @@ bool RenderEngine::CaptureOutputFrameRgbaTopDown(unsigned width, unsigned height
{
EnterCriticalSection(&mMutex);
wglMakeCurrent(mHdc, mHglrc);
const bool captured = CaptureOutputFrameRgbaTopDownOnRenderThread(width, height, topDownPixels);
mRenderCommandQueue.RequestScreenshotCapture({ width, height });
RenderScreenshotCaptureRequest request;
const bool captured = mRenderCommandQueue.TryTakeScreenshotCapture(request) &&
CaptureOutputFrameRgbaTopDownOnRenderThread(request.width, request.height, topDownPixels);
wglMakeCurrent(NULL, NULL);
LeaveCriticalSection(&mMutex);
return captured;

View File

@@ -4,6 +4,7 @@
#include "OpenGLRenderPipeline.h"
#include "OpenGLRenderer.h"
#include "OpenGLShaderPrograms.h"
#include "RenderCommandQueue.h"
#include "RenderFrameState.h"
#include "RenderFrameStateResolver.h"
#include "HealthTelemetry.h"
@@ -18,8 +19,6 @@
#include <string>
#include <vector>
class ShaderBuildQueue;
class RenderEngine
{
public:
@@ -50,13 +49,6 @@ public:
uint64_t generation = 0;
};
struct PreparedShaderBuildApplyResult
{
bool hadReadyBuild = false;
bool applied = false;
std::string errorMessage;
};
RenderEngine(
RuntimeSnapshotProvider& runtimeSnapshotProvider,
HealthTelemetry& healthTelemetry,
@@ -79,7 +71,6 @@ public:
unsigned outputPackTextureWidth,
std::string& error);
bool CompileLayerPrograms(unsigned inputFrameWidth, unsigned inputFrameHeight, int errorMessageSize, char* errorMessage);
bool CommitPreparedLayerPrograms(const PreparedShaderBuild& preparedBuild, unsigned inputFrameWidth, unsigned inputFrameHeight, int errorMessageSize, char* errorMessage);
bool ApplyPreparedShaderBuild(
const PreparedShaderBuild& preparedBuild,
unsigned inputFrameWidth,
@@ -87,13 +78,7 @@ public:
bool preserveFeedbackState,
int errorMessageSize,
char* errorMessage);
PreparedShaderBuildApplyResult TryApplyReadyShaderBuild(
ShaderBuildQueue& shaderBuildQueue,
unsigned inputFrameWidth,
unsigned inputFrameHeight,
bool preserveFeedbackState);
const std::vector<RuntimeRenderState>& CommittedLayerStates() const;
void ResetTemporalHistoryState();
void ResetShaderFeedbackState();
void ApplyRuntimeCoordinatorRenderReset(RuntimeCoordinatorRenderResetScope resetScope);
@@ -110,6 +95,10 @@ public:
std::vector<OscOverlayCommitRequest>* commitRequests,
RenderFrameState& frameState);
void RenderPreparedFrame(const RenderFrameState& frameState);
bool CaptureOutputFrameRgbaTopDown(unsigned width, unsigned height, std::vector<unsigned char>& topDownPixels);
private:
bool CommitPreparedLayerPrograms(const PreparedShaderBuild& preparedBuild, unsigned inputFrameWidth, unsigned inputFrameHeight, int errorMessageSize, char* errorMessage);
void RenderLayerStack(
bool hasInputSource,
const std::vector<RuntimeRenderState>& layerStates,
@@ -118,9 +107,10 @@ public:
unsigned captureTextureWidth,
VideoIOPixelFormat inputPixelFormat,
unsigned historyCap);
bool CaptureOutputFrameRgbaTopDown(unsigned width, unsigned height, std::vector<unsigned char>& topDownPixels);
private:
void ResetTemporalHistoryStateOnRenderThread();
void ResetShaderFeedbackStateOnRenderThread();
void ApplyRenderResetOnRenderThread(RenderCommandResetScope resetScope);
void ProcessRenderResetCommandsOnRenderThread();
bool PresentPreviewOnRenderThread(unsigned outputFrameWidth, unsigned outputFrameHeight);
bool UploadInputFrameOnRenderThread(const VideoIOFrame& inputFrame, const VideoIOState& videoState);
bool RenderOutputFrameOnRenderThread(const RenderPipelineFrameContext& context, VideoIOOutputFrame& outputFrame);
@@ -136,6 +126,7 @@ private:
HGLRC mHglrc;
std::chrono::steady_clock::time_point mLastPreviewPresentTime;
RenderCommandQueue mRenderCommandQueue;
RenderFrameStateResolver mFrameStateResolver;
RuntimeLiveState mRuntimeLiveState;
};