more seperation

This commit is contained in:
Aiden
2026-05-10 23:53:27 +10:00
parent 7f0f60c0e3
commit 41075bbc61
25 changed files with 733 additions and 1031 deletions

View File

@@ -101,9 +101,10 @@ OpenGLComposite::OpenGLComposite(HWND hWnd, HDC hDC, HGLRC hRC) :
mRuntimeHost = std::make_unique<RuntimeHost>();
mRuntimeStore = std::make_unique<RuntimeStore>(*mRuntimeHost);
mRuntimeSnapshotProvider = std::make_unique<RuntimeSnapshotProvider>(*mRuntimeHost);
mRuntimeCoordinator = std::make_unique<RuntimeCoordinator>(*mRuntimeStore);
mRenderEngine = std::make_unique<RenderEngine>(
*mRuntimeHost,
*mRuntimeSnapshotProvider,
mRuntimeHost->GetHealthTelemetry(),
pMutex,
hGLDC,
hGLRC,
@@ -202,7 +203,11 @@ bool OpenGLComposite::InitVideoIO()
}
if (!mVideoBackend->HasInputDevice() && mRuntimeHost)
{
mRuntimeHost->SetSignalStatus(false, mVideoBackend->InputFrameWidth(), mVideoBackend->InputFrameHeight(), mVideoBackend->InputDisplayModeName());
mRuntimeHost->GetHealthTelemetry().ReportSignalStatus(
false,
mVideoBackend->InputFrameWidth(),
mVideoBackend->InputFrameHeight(),
mVideoBackend->InputDisplayModeName());
}
if (!mVideoBackend->ConfigureOutput(videoModes.output, mRuntimeStore && mRuntimeStore->IsExternalKeyingConfigured(), initFailureReason))
@@ -227,27 +232,15 @@ void OpenGLComposite::paintGL(bool force)
{
if (IsIconic(hGLWnd))
return;
const unsigned previewFps = mRuntimeStore ? mRuntimeStore->GetConfiguredPreviewFps() : 30u;
if (previewFps == 0)
return;
const auto now = std::chrono::steady_clock::now();
const auto minimumInterval = std::chrono::microseconds(1000000 / (previewFps == 0 ? 1u : previewFps));
if (mLastPreviewPresentTime != std::chrono::steady_clock::time_point() &&
now - mLastPreviewPresentTime < minimumInterval)
{
return;
}
}
if (!mRenderEngine->TryPresentToWindow(mVideoBackend->OutputFrameWidth(), mVideoBackend->OutputFrameHeight()))
const unsigned previewFps = mRuntimeStore ? mRuntimeStore->GetConfiguredPreviewFps() : 30u;
if (!mRenderEngine->TryPresentPreview(force, previewFps, mVideoBackend->OutputFrameWidth(), mVideoBackend->OutputFrameHeight()))
{
ValidateRect(hGLWnd, NULL);
return;
}
mLastPreviewPresentTime = std::chrono::steady_clock::now();
ValidateRect(hGLWnd, NULL);
}
@@ -336,7 +329,7 @@ bool OpenGLComposite::InitOpenGLState()
MessageBoxA(NULL, compilerErrorMessage, "OpenGL shader failed to load or compile", MB_OK);
return false;
}
mCachedLayerRenderStates = mRenderEngine->CommittedLayerStates();
mRuntimeStore->SetCompileStatus(true, "Shader layers compiled successfully.");
mUseCommittedLayerStates = false;
mRenderEngine->ResetTemporalHistoryState();
@@ -367,15 +360,8 @@ bool OpenGLComposite::Stop()
bool OpenGLComposite::ReloadShader(bool preserveFeedbackState)
{
mPreserveFeedbackOnNextShaderBuild = preserveFeedbackState;
if (mRuntimeHost)
{
mRuntimeStore->SetCompileStatus(true, "Shader rebuild queued.");
mRuntimeStore->ClearReloadRequest();
}
RequestShaderBuild();
broadcastRuntimeState();
return true;
return mRuntimeCoordinator &&
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->RequestShaderReload(preserveFeedbackState));
}
bool OpenGLComposite::RequestScreenshot(std::string& error)
@@ -442,7 +428,7 @@ void OpenGLComposite::renderEffect()
const auto applyOscOverlays = [&](std::vector<RuntimeRenderState>& states, bool allowCommit)
{
if (states.empty() || mOscOverlayStates.empty() || !mRuntimeHost)
if (states.empty() || mOscOverlayStates.empty())
return;
const double smoothing = ClampOscAlpha(mRuntimeStore ? mRuntimeStore->GetConfiguredOscSmoothing() : 0.0);
@@ -576,66 +562,12 @@ void OpenGLComposite::renderEffect()
const bool hasInputSource = mVideoBackend->HasInputSource();
std::vector<RuntimeRenderState> layerStates;
if (mUseCommittedLayerStates)
{
layerStates = mRenderEngine->CommittedLayerStates();
applyOscOverlays(layerStates, false);
if (mRuntimeSnapshotProvider)
mRuntimeSnapshotProvider->RefreshDynamicRenderStateFields(layerStates);
}
else if (mRuntimeSnapshotProvider)
{
const unsigned renderWidth = mVideoBackend->InputFrameWidth();
const unsigned renderHeight = mVideoBackend->InputFrameHeight();
const RuntimeSnapshotVersions versions = mRuntimeSnapshotProvider->GetVersions();
const bool renderStateCacheValid =
!mCachedLayerRenderStates.empty() &&
mCachedRenderStateVersion == versions.renderStateVersion &&
mCachedRenderStateWidth == renderWidth &&
mCachedRenderStateHeight == renderHeight;
if (renderStateCacheValid)
{
RuntimeRenderStateSnapshot renderSnapshot;
renderSnapshot.outputWidth = renderWidth;
renderSnapshot.outputHeight = renderHeight;
renderSnapshot.versions.renderStateVersion = mCachedRenderStateVersion;
renderSnapshot.versions.parameterStateVersion = mCachedParameterStateVersion;
renderSnapshot.states = mCachedLayerRenderStates;
applyOscOverlays(renderSnapshot.states, true);
if (mCachedParameterStateVersion != versions.parameterStateVersion &&
mRuntimeSnapshotProvider->TryRefreshSnapshotParameters(renderSnapshot))
{
mCachedParameterStateVersion = renderSnapshot.versions.parameterStateVersion;
applyOscOverlays(renderSnapshot.states, true);
}
mCachedLayerRenderStates = renderSnapshot.states;
layerStates = renderSnapshot.states;
mRuntimeSnapshotProvider->RefreshDynamicRenderStateFields(layerStates);
}
else
{
RuntimeRenderStateSnapshot renderSnapshot;
if (mRuntimeSnapshotProvider->TryGetRenderStateSnapshot(renderWidth, renderHeight, renderSnapshot))
{
mCachedLayerRenderStates = renderSnapshot.states;
mCachedRenderStateVersion = renderSnapshot.versions.renderStateVersion;
mCachedParameterStateVersion = renderSnapshot.versions.parameterStateVersion;
mCachedRenderStateWidth = renderSnapshot.outputWidth;
mCachedRenderStateHeight = renderSnapshot.outputHeight;
applyOscOverlays(mCachedLayerRenderStates, true);
layerStates = mCachedLayerRenderStates;
}
else
{
applyOscOverlays(mCachedLayerRenderStates, true);
layerStates = mCachedLayerRenderStates;
mRuntimeSnapshotProvider->RefreshDynamicRenderStateFields(layerStates);
}
}
}
mRenderEngine->ResolveRenderLayerStates(
mUseCommittedLayerStates.load(),
mVideoBackend->InputFrameWidth(),
mVideoBackend->InputFrameHeight(),
applyOscOverlays,
layerStates);
const unsigned historyCap = mRuntimeStore ? mRuntimeStore->GetConfiguredMaxTemporalHistoryFrames() : 0;
mRenderEngine->RenderLayerStack(
hasInputSource,
@@ -657,20 +589,9 @@ void OpenGLComposite::ProcessScreenshotRequest()
if (width == 0 || height == 0)
return;
std::vector<unsigned char> bottomUpPixels;
if (!mRenderEngine->ReadOutputFrameRgba(width, height, bottomUpPixels))
std::vector<unsigned char> topDownPixels;
if (!mRenderEngine->CaptureOutputFrameRgbaTopDown(width, height, topDownPixels))
return;
std::vector<unsigned char> topDownPixels(bottomUpPixels.size());
const std::size_t rowBytes = static_cast<std::size_t>(width) * 4;
for (unsigned y = 0; y < height; ++y)
{
const unsigned sourceY = height - 1 - y;
std::copy(
bottomUpPixels.begin() + static_cast<std::ptrdiff_t>(sourceY * rowBytes),
bottomUpPixels.begin() + static_cast<std::ptrdiff_t>((sourceY + 1) * rowBytes),
topDownPixels.begin() + static_cast<std::ptrdiff_t>(y * rowBytes));
}
try
{
@@ -707,14 +628,13 @@ std::filesystem::path OpenGLComposite::BuildScreenshotPath() const
bool OpenGLComposite::ProcessRuntimePollResults()
{
if (!mRuntimeHost || !mRuntimeServices)
if (!mRuntimeServices)
return true;
const RuntimePollEvents events = mRuntimeServices->ConsumePollEvents();
if (events.failed)
{
mRuntimeStore->SetCompileStatus(false, events.error);
broadcastRuntimeState();
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->HandleRuntimePollFailure(events.error));
return false;
}
@@ -728,29 +648,23 @@ bool OpenGLComposite::ProcessRuntimePollResults()
return true;
char compilerErrorMessage[1024] = {};
if (!mRenderEngine->CommitPreparedLayerPrograms(readyBuild, mVideoBackend->InputFrameWidth(), mVideoBackend->InputFrameHeight(), sizeof(compilerErrorMessage), compilerErrorMessage))
if (!mRenderEngine->ApplyPreparedShaderBuild(
readyBuild,
mVideoBackend->InputFrameWidth(),
mVideoBackend->InputFrameHeight(),
mRuntimeCoordinator && mRuntimeCoordinator->PreserveFeedbackOnNextShaderBuild(),
sizeof(compilerErrorMessage),
compilerErrorMessage))
{
mRuntimeStore->SetCompileStatus(false, compilerErrorMessage);
mUseCommittedLayerStates = true;
mPreserveFeedbackOnNextShaderBuild = false;
broadcastRuntimeState();
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->HandlePreparedShaderBuildFailure(compilerErrorMessage));
return false;
}
mUseCommittedLayerStates = false;
mCachedLayerRenderStates = mRenderEngine->CommittedLayerStates();
mRenderEngine->ResetTemporalHistoryState();
if (!mPreserveFeedbackOnNextShaderBuild)
mRenderEngine->ResetShaderFeedbackState();
mPreserveFeedbackOnNextShaderBuild = false;
broadcastRuntimeState();
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->HandlePreparedShaderBuildSuccess());
return true;
}
mRuntimeStore->SetCompileStatus(true, "Shader rebuild queued.");
mPreserveFeedbackOnNextShaderBuild = false;
RequestShaderBuild();
broadcastRuntimeState();
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->HandleRuntimeReloadRequest());
return true;
}
@@ -759,24 +673,81 @@ void OpenGLComposite::RequestShaderBuild()
if (!mShaderBuildQueue || !mVideoBackend)
return;
mUseCommittedLayerStates = true;
if (mRuntimeHost)
mRuntimeStore->ClearReloadRequest();
mShaderBuildQueue->RequestBuild(mVideoBackend->InputFrameWidth(), mVideoBackend->InputFrameHeight());
}
bool OpenGLComposite::ApplyRuntimeCoordinatorResult(const RuntimeCoordinatorResult& result, std::string* error)
{
if (!result.accepted)
{
if (error)
*error = result.errorMessage;
return false;
}
if (result.compileStatusChanged && mRuntimeStore)
mRuntimeStore->SetCompileStatus(result.compileStatusSucceeded, result.compileStatusMessage);
if (result.clearReloadRequest && mRuntimeStore)
mRuntimeStore->ClearReloadRequest();
switch (result.committedStateMode)
{
case RuntimeCoordinatorCommittedStateMode::UseCommittedStates:
mUseCommittedLayerStates = true;
break;
case RuntimeCoordinatorCommittedStateMode::UseLiveSnapshots:
mUseCommittedLayerStates = false;
break;
case RuntimeCoordinatorCommittedStateMode::Unchanged:
default:
break;
}
if (result.clearTransientOscState)
{
mOscOverlayStates.clear();
if (mRuntimeServices)
mRuntimeServices->ClearOscState();
}
ApplyRuntimeCoordinatorRenderReset(result.renderResetScope);
if (result.shaderBuildRequested)
RequestShaderBuild();
if (result.runtimeStateBroadcastRequired)
broadcastRuntimeState();
return true;
}
void OpenGLComposite::ApplyRuntimeCoordinatorRenderReset(RuntimeCoordinatorRenderResetScope resetScope)
{
if (!mRenderEngine)
return;
switch (resetScope)
{
case RuntimeCoordinatorRenderResetScope::TemporalHistoryOnly:
mRenderEngine->ResetTemporalHistoryState();
break;
case RuntimeCoordinatorRenderResetScope::TemporalHistoryAndFeedback:
mRenderEngine->ResetTemporalHistoryState();
mRenderEngine->ResetShaderFeedbackState();
break;
case RuntimeCoordinatorRenderResetScope::None:
default:
break;
}
}
void OpenGLComposite::broadcastRuntimeState()
{
if (mRuntimeServices)
mRuntimeServices->BroadcastState();
}
void OpenGLComposite::resetTemporalHistoryState()
{
mRenderEngine->ResetTemporalHistoryState();
mRenderEngine->ResetShaderFeedbackState();
}
bool OpenGLComposite::CheckOpenGLExtensions()
{
return true;