more seperation
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user