diff --git a/CMakeLists.txt b/CMakeLists.txt
index e99203d..e543f7b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -72,6 +72,8 @@ set(APP_SOURCES
"${APP_DIR}/gl/OpenGLShaderPrograms.h"
"${APP_DIR}/gl/ShaderProgramCompiler.cpp"
"${APP_DIR}/gl/ShaderProgramCompiler.h"
+ "${APP_DIR}/gl/ShaderBuildQueue.cpp"
+ "${APP_DIR}/gl/ShaderBuildQueue.h"
"${APP_DIR}/gl/ShaderTextureBindings.cpp"
"${APP_DIR}/gl/ShaderTextureBindings.h"
"${APP_DIR}/gl/Std140Buffer.h"
diff --git a/README.md b/README.md
index da14a24..3cd6252 100644
--- a/README.md
+++ b/README.md
@@ -247,12 +247,10 @@ If neither variable is set, the workflow falls back to the repo-local defaults u
## Still Todo
- Audio.
-- Improve text rendering.
- Genlock.
- Find a better UI library for react.
- Logs.
-- Continue source cleanup/refactoring. Pass 1 done
+- Continue source cleanup/refactoring. Pass 2 done
- Support a separate sound shader `.slang` file in shader packages. (https://www.shadertoy.com/view/XsBXWt)
- Add WebView2
-- move to MSDF, typography rasterisation
-- abritary function/triggers for the shader
\ No newline at end of file
+- move to MSDF, typography rasterisation
\ No newline at end of file
diff --git a/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj b/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj
index bead286..1eb62d8 100644
--- a/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj
+++ b/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj
@@ -198,6 +198,7 @@
+
Create
@@ -218,6 +219,7 @@
+
diff --git a/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj.filters b/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj.filters
index 35ec3e1..d8ae771 100644
--- a/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj.filters
+++ b/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj.filters
@@ -36,6 +36,9 @@
Source Files
+
+ Source Files
+
Source Files
@@ -77,6 +80,9 @@
Header Files
+
+ Header Files
+
Header Files
diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/OpenGLComposite.cpp b/apps/LoopThroughWithOpenGLCompositing/gl/OpenGLComposite.cpp
index 2d10b12..4c37e9c 100644
--- a/apps/LoopThroughWithOpenGLCompositing/gl/OpenGLComposite.cpp
+++ b/apps/LoopThroughWithOpenGLCompositing/gl/OpenGLComposite.cpp
@@ -8,6 +8,7 @@
#include "OpenGLRenderPass.h"
#include "OpenGLShaderPrograms.h"
#include "RuntimeServices.h"
+#include "ShaderBuildQueue.h"
#include
#include
@@ -16,7 +17,8 @@
OpenGLComposite::OpenGLComposite(HWND hWnd, HDC hDC, HGLRC hRC) :
hGLWnd(hWnd), hGLDC(hDC), hGLRC(hRC),
mDeckLink(std::make_unique()),
- mRenderer(std::make_unique())
+ mRenderer(std::make_unique()),
+ mUseCommittedLayerStates(false)
{
InitializeCriticalSection(&pMutex);
mRuntimeHost = std::make_unique();
@@ -31,6 +33,7 @@ OpenGLComposite::OpenGLComposite(HWND hWnd, HDC hDC, HGLRC hRC) :
[this]() { paintGL(); });
mRenderPass = std::make_unique(*mRenderer);
mShaderPrograms = std::make_unique(*mRenderer, *mRuntimeHost);
+ mShaderBuildQueue = std::make_unique(*mRuntimeHost);
mRuntimeServices = std::make_unique();
}
@@ -38,6 +41,8 @@ OpenGLComposite::~OpenGLComposite()
{
if (mRuntimeServices)
mRuntimeServices->Stop();
+ if (mShaderBuildQueue)
+ mShaderBuildQueue->Stop();
mDeckLink->ReleaseResources();
mRenderer->DestroyResources();
@@ -223,6 +228,8 @@ bool OpenGLComposite::InitOpenGLState()
MessageBoxA(NULL, compilerErrorMessage, "OpenGL shader failed to load or compile", MB_OK);
return false;
}
+ mCachedLayerRenderStates = mShaderPrograms->CommittedLayerStates();
+ mUseCommittedLayerStates = false;
mShaderPrograms->ResetTemporalHistoryState();
std::string rendererError;
@@ -268,32 +275,14 @@ bool OpenGLComposite::Stop()
bool OpenGLComposite::ReloadShader()
{
- char compilerErrorMessage[1024];
-
- EnterCriticalSection(&pMutex);
- wglMakeCurrent(hGLDC, hGLRC);
-
- bool success = mShaderPrograms->CompileLayerPrograms(mDeckLink->InputFrameWidth(), mDeckLink->InputFrameHeight(), sizeof(compilerErrorMessage), compilerErrorMessage);
if (mRuntimeHost)
+ {
+ mRuntimeHost->SetCompileStatus(true, "Shader rebuild queued.");
mRuntimeHost->ClearReloadRequest();
-
- wglMakeCurrent(NULL, NULL);
- LeaveCriticalSection(&pMutex);
-
- if (!success)
- {
- if (mRuntimeHost)
- mRuntimeHost->SetCompileStatus(false, compilerErrorMessage);
- MessageBoxA(NULL, compilerErrorMessage, "Slang shader reload failed", MB_OK);
}
- else
- {
- if (mRuntimeHost)
- mRuntimeHost->SetCompileStatus(true, "Shader compiled successfully.");
- broadcastRuntimeState();
- }
-
- return success;
+ RequestShaderBuild();
+ broadcastRuntimeState();
+ return true;
}
void OpenGLComposite::renderEffect()
@@ -302,7 +291,11 @@ void OpenGLComposite::renderEffect()
const bool hasInputSource = mDeckLink->HasInputSource();
std::vector layerStates;
- if (mRuntimeHost)
+ if (mUseCommittedLayerStates)
+ {
+ layerStates = mShaderPrograms->CommittedLayerStates();
+ }
+ else if (mRuntimeHost)
{
if (mRuntimeHost->TryGetLayerRenderStates(mDeckLink->InputFrameWidth(), mDeckLink->InputFrameHeight(), layerStates))
mCachedLayerRenderStates = layerStates;
@@ -341,22 +334,44 @@ bool OpenGLComposite::ProcessRuntimePollResults()
broadcastRuntimeState();
if (!events.reloadRequested)
- return true;
-
- char compilerErrorMessage[1024] = {};
- if (!mShaderPrograms->CompileLayerPrograms(mDeckLink->InputFrameWidth(), mDeckLink->InputFrameHeight(), sizeof(compilerErrorMessage), compilerErrorMessage))
{
- mRuntimeHost->SetCompileStatus(false, compilerErrorMessage);
- mRuntimeHost->ClearReloadRequest();
+ PreparedShaderBuild readyBuild;
+ if (!mShaderBuildQueue || !mShaderBuildQueue->TryConsumeReadyBuild(readyBuild))
+ return true;
+
+ char compilerErrorMessage[1024] = {};
+ if (!mShaderPrograms->CommitPreparedLayerPrograms(readyBuild, mDeckLink->InputFrameWidth(), mDeckLink->InputFrameHeight(), sizeof(compilerErrorMessage), compilerErrorMessage))
+ {
+ mRuntimeHost->SetCompileStatus(false, compilerErrorMessage);
+ mUseCommittedLayerStates = true;
+ broadcastRuntimeState();
+ return false;
+ }
+
+ mUseCommittedLayerStates = false;
+ mCachedLayerRenderStates = mShaderPrograms->CommittedLayerStates();
+ mShaderPrograms->ResetTemporalHistoryState();
broadcastRuntimeState();
- return false;
+ return true;
}
- mShaderPrograms->ResetTemporalHistoryState();
+ mRuntimeHost->SetCompileStatus(true, "Shader rebuild queued.");
+ RequestShaderBuild();
broadcastRuntimeState();
return true;
}
+void OpenGLComposite::RequestShaderBuild()
+{
+ if (!mShaderBuildQueue || !mDeckLink)
+ return;
+
+ mUseCommittedLayerStates = true;
+ if (mRuntimeHost)
+ mRuntimeHost->ClearReloadRequest();
+ mShaderBuildQueue->RequestBuild(mDeckLink->InputFrameWidth(), mDeckLink->InputFrameHeight());
+}
+
void OpenGLComposite::broadcastRuntimeState()
{
if (mRuntimeServices)
diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/OpenGLComposite.h b/apps/LoopThroughWithOpenGLCompositing/gl/OpenGLComposite.h
index 0b9e025..5db2c94 100644
--- a/apps/LoopThroughWithOpenGLCompositing/gl/OpenGLComposite.h
+++ b/apps/LoopThroughWithOpenGLCompositing/gl/OpenGLComposite.h
@@ -17,6 +17,7 @@
#include "RuntimeHost.h"
#include
+#include
#include