From 87cb55b80b2ecd8775368a636284044549438d3d Mon Sep 17 00:00:00 2001 From: Aiden Date: Fri, 8 May 2026 17:10:29 +1000 Subject: [PATCH] Layer program split --- .../gl/pipeline/OpenGLRenderPass.cpp | 15 ++-- .../gl/pipeline/OpenGLRenderPass.h | 3 +- .../gl/pipeline/RenderPassDescriptor.h | 1 + .../gl/renderer/OpenGLRenderer.cpp | 70 ++++++++++--------- .../gl/renderer/OpenGLRenderer.h | 19 +++-- .../gl/shader/ShaderProgramCompiler.cpp | 19 +++-- .../gl/shader/ShaderProgramCompiler.h | 1 + .../gl/shader/ShaderTextureBindings.cpp | 26 +++---- .../gl/shader/ShaderTextureBindings.h | 5 +- 9 files changed, 91 insertions(+), 68 deletions(-) diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/OpenGLRenderPass.cpp b/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/OpenGLRenderPass.cpp index 4c40fec..810e6fc 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/OpenGLRenderPass.cpp +++ b/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/OpenGLRenderPass.cpp @@ -101,6 +101,8 @@ std::vector OpenGLRenderPass::BuildLayerPassDescriptors( { const RuntimeRenderState& state = layerStates[index]; LayerProgram& layerProgram = layerPrograms[index]; + if (layerProgram.passes.empty()) + continue; const std::size_t remaining = layerStates.size() - index; const bool writeToMain = (remaining % 2) == 1; @@ -115,6 +117,7 @@ std::vector OpenGLRenderPass::BuildLayerPassDescriptors( pass.sourceFramebuffer = sourceFramebuffer; pass.destinationFramebuffer = writeToMain ? mRenderer.CompositeFramebuffer() : mRenderer.LayerTempFramebuffer(); pass.layerProgram = &layerProgram; + pass.passProgram = &layerProgram.passes.front(); pass.layerState = &state; pass.capturePreLayerHistory = state.temporalHistorySource == TemporalHistorySource::PreLayerInput; passes.push_back(pass); @@ -134,13 +137,13 @@ void OpenGLRenderPass::RenderLayerPass( const TextBindingUpdater& updateTextBinding, const GlobalParamsUpdater& updateGlobalParams) { - if (pass.layerProgram == nullptr || pass.layerState == nullptr) + if (pass.passProgram == nullptr || pass.layerState == nullptr) return; RenderShaderProgram( pass.sourceTexture, pass.destinationFramebuffer, - *pass.layerProgram, + *pass.passProgram, *pass.layerState, inputFrameWidth, inputFrameHeight, @@ -155,7 +158,7 @@ void OpenGLRenderPass::RenderLayerPass( void OpenGLRenderPass::RenderShaderProgram( GLuint sourceTexture, GLuint destinationFrameBuffer, - LayerProgram& layerProgram, + PassProgram& passProgram, const RuntimeRenderState& state, unsigned inputFrameWidth, unsigned inputFrameHeight, @@ -163,7 +166,7 @@ void OpenGLRenderPass::RenderShaderProgram( const TextBindingUpdater& updateTextBinding, const GlobalParamsUpdater& updateGlobalParams) { - for (LayerProgram::TextBinding& textBinding : layerProgram.textBindings) + for (LayerProgram::TextBinding& textBinding : passProgram.textBindings) { std::string textError; if (!updateTextBinding(state, textBinding, textError)) @@ -176,10 +179,10 @@ void OpenGLRenderPass::RenderShaderProgram( const std::vector sourceHistoryTextures = mRenderer.TemporalHistory().ResolveSourceHistoryTextures(sourceTexture, state.isTemporal ? historyCap : 0); const std::vector temporalHistoryTextures = mRenderer.TemporalHistory().ResolveTemporalHistoryTextures(state, sourceTexture, state.isTemporal ? historyCap : 0); const ShaderTextureBindings::RuntimeTextureBindingPlan texturePlan = - mTextureBindings.BuildLayerRuntimeBindingPlan(layerProgram, sourceTexture, sourceHistoryTextures, temporalHistoryTextures); + mTextureBindings.BuildLayerRuntimeBindingPlan(passProgram, sourceTexture, sourceHistoryTextures, temporalHistoryTextures); mTextureBindings.BindRuntimeTexturePlan(texturePlan); glBindVertexArray(mRenderer.FullscreenVertexArray()); - glUseProgram(layerProgram.program); + glUseProgram(passProgram.program); updateGlobalParams(state, mRenderer.TemporalHistory().SourceAvailableCount(), mRenderer.TemporalHistory().AvailableCountForLayer(state.layerId)); glDrawArrays(GL_TRIANGLES, 0, 3); glUseProgram(0); diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/OpenGLRenderPass.h b/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/OpenGLRenderPass.h index 7262acc..9e3cf65 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/OpenGLRenderPass.h +++ b/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/OpenGLRenderPass.h @@ -14,6 +14,7 @@ class OpenGLRenderPass { public: using LayerProgram = OpenGLRenderer::LayerProgram; + using PassProgram = OpenGLRenderer::LayerProgram::PassProgram; using TextBindingUpdater = std::function; using GlobalParamsUpdater = std::function; @@ -45,7 +46,7 @@ private: void RenderShaderProgram( GLuint sourceTexture, GLuint destinationFrameBuffer, - LayerProgram& layerProgram, + PassProgram& passProgram, const RuntimeRenderState& state, unsigned inputFrameWidth, unsigned inputFrameHeight, diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/RenderPassDescriptor.h b/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/RenderPassDescriptor.h index 3e108bf..3f53fc9 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/RenderPassDescriptor.h +++ b/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/RenderPassDescriptor.h @@ -31,6 +31,7 @@ struct RenderPassDescriptor GLuint sourceFramebuffer = 0; GLuint destinationFramebuffer = 0; OpenGLRenderer::LayerProgram* layerProgram = nullptr; + OpenGLRenderer::LayerProgram::PassProgram* passProgram = nullptr; const RuntimeRenderState* layerState = nullptr; bool capturePreLayerHistory = false; }; diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.cpp b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.cpp index 1f1f8b0..08e2c26 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.cpp +++ b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.cpp @@ -155,43 +155,47 @@ void OpenGLRenderer::DestroyResources() void OpenGLRenderer::DestroySingleLayerProgram(LayerProgram& layerProgram) { - for (LayerProgram::TextureBinding& binding : layerProgram.textureBindings) + for (LayerProgram::PassProgram& passProgram : layerProgram.passes) { - if (binding.texture != 0) + for (LayerProgram::TextureBinding& binding : passProgram.textureBindings) { - glDeleteTextures(1, &binding.texture); - binding.texture = 0; + if (binding.texture != 0) + { + glDeleteTextures(1, &binding.texture); + binding.texture = 0; + } + } + passProgram.textureBindings.clear(); + + for (LayerProgram::TextBinding& binding : passProgram.textBindings) + { + if (binding.texture != 0) + { + glDeleteTextures(1, &binding.texture); + binding.texture = 0; + } + } + passProgram.textBindings.clear(); + + if (passProgram.program != 0) + { + glDeleteProgram(passProgram.program); + passProgram.program = 0; + } + + if (passProgram.fragmentShader != 0) + { + glDeleteShader(passProgram.fragmentShader); + passProgram.fragmentShader = 0; + } + + if (passProgram.vertexShader != 0) + { + glDeleteShader(passProgram.vertexShader); + passProgram.vertexShader = 0; } } - layerProgram.textureBindings.clear(); - - for (LayerProgram::TextBinding& binding : layerProgram.textBindings) - { - if (binding.texture != 0) - { - glDeleteTextures(1, &binding.texture); - binding.texture = 0; - } - } - layerProgram.textBindings.clear(); - - if (layerProgram.program != 0) - { - glDeleteProgram(layerProgram.program); - layerProgram.program = 0; - } - - if (layerProgram.fragmentShader != 0) - { - glDeleteShader(layerProgram.fragmentShader); - layerProgram.fragmentShader = 0; - } - - if (layerProgram.vertexShader != 0) - { - glDeleteShader(layerProgram.vertexShader); - layerProgram.vertexShader = 0; - } + layerProgram.passes.clear(); } void OpenGLRenderer::DestroyLayerPrograms() diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.h b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.h index dac49bc..b4c9989 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.h +++ b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.h @@ -37,12 +37,19 @@ public: std::string layerId; std::string shaderId; - GLuint shaderTextureBase = 0; - GLuint program = 0; - GLuint vertexShader = 0; - GLuint fragmentShader = 0; - std::vector textureBindings; - std::vector textBindings; + + struct PassProgram + { + std::string passId; + GLuint shaderTextureBase = 0; + GLuint program = 0; + GLuint vertexShader = 0; + GLuint fragmentShader = 0; + std::vector textureBindings; + std::vector textBindings; + }; + + std::vector passes; }; GLuint CaptureTexture() const { return mCaptureTexture; } diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderProgramCompiler.cpp b/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderProgramCompiler.cpp index 21ef418..42002f3 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderProgramCompiler.cpp +++ b/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderProgramCompiler.cpp @@ -5,6 +5,7 @@ #include "GlShaderSources.h" #include +#include #include namespace @@ -103,9 +104,12 @@ bool ShaderProgramCompiler::CompilePreparedLayerProgram(const RuntimeRenderState layerProgram.layerId = state.layerId; layerProgram.shaderId = state.shaderId; - layerProgram.shaderTextureBase = mTextureBindings.ResolveShaderTextureBase(state, mRuntimeHost.GetMaxTemporalHistoryFrames()); - layerProgram.textureBindings.swap(textureBindings); - layerProgram.textBindings.swap(textBindings); + + PassProgram passProgram; + passProgram.passId = "main"; + passProgram.shaderTextureBase = mTextureBindings.ResolveShaderTextureBase(state, mRuntimeHost.GetMaxTemporalHistoryFrames()); + passProgram.textureBindings.swap(textureBindings); + passProgram.textBindings.swap(textBindings); const GLuint globalParamsIndex = glGetUniformBlockIndex(newProgram.get(), "GlobalParams"); if (globalParamsIndex != GL_INVALID_INDEX) @@ -113,12 +117,13 @@ bool ShaderProgramCompiler::CompilePreparedLayerProgram(const RuntimeRenderState const unsigned historyCap = mRuntimeHost.GetMaxTemporalHistoryFrames(); glUseProgram(newProgram.get()); - mTextureBindings.AssignLayerSamplerUniforms(newProgram.get(), state, layerProgram, historyCap); + mTextureBindings.AssignLayerSamplerUniforms(newProgram.get(), state, passProgram, historyCap); glUseProgram(0); - layerProgram.program = newProgram.release(); - layerProgram.vertexShader = newVertexShader.release(); - layerProgram.fragmentShader = newFragmentShader.release(); + passProgram.program = newProgram.release(); + passProgram.vertexShader = newVertexShader.release(); + passProgram.fragmentShader = newFragmentShader.release(); + layerProgram.passes.push_back(std::move(passProgram)); return true; } diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderProgramCompiler.h b/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderProgramCompiler.h index 1ed388b..4e4b622 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderProgramCompiler.h +++ b/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderProgramCompiler.h @@ -10,6 +10,7 @@ class ShaderProgramCompiler { public: using LayerProgram = OpenGLRenderer::LayerProgram; + using PassProgram = OpenGLRenderer::LayerProgram::PassProgram; ShaderProgramCompiler(OpenGLRenderer& renderer, RuntimeHost& runtimeHost, ShaderTextureBindings& textureBindings); diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderTextureBindings.cpp b/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderTextureBindings.cpp index f326ed0..2031ab8 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderTextureBindings.cpp +++ b/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderTextureBindings.cpp @@ -108,7 +108,7 @@ GLuint ShaderTextureBindings::ResolveShaderTextureBase(const RuntimeRenderState& return state.isTemporal ? kSourceHistoryTextureUnitBase + historyCap + historyCap : kSourceHistoryTextureUnitBase; } -void ShaderTextureBindings::AssignLayerSamplerUniforms(GLuint program, const RuntimeRenderState& state, const LayerProgram& layerProgram, unsigned historyCap) const +void ShaderTextureBindings::AssignLayerSamplerUniforms(GLuint program, const RuntimeRenderState& state, const PassProgram& passProgram, unsigned historyCap) const { const GLuint shaderTextureBase = ResolveShaderTextureBase(state, historyCap); @@ -129,24 +129,24 @@ void ShaderTextureBindings::AssignLayerSamplerUniforms(GLuint program, const Run glUniform1i(temporalSamplerLocation, static_cast(kSourceHistoryTextureUnitBase + historyCap + index)); } - for (std::size_t index = 0; index < layerProgram.textureBindings.size(); ++index) + for (std::size_t index = 0; index < passProgram.textureBindings.size(); ++index) { - const GLint textureSamplerLocation = FindSamplerUniformLocation(program, layerProgram.textureBindings[index].samplerName); + const GLint textureSamplerLocation = FindSamplerUniformLocation(program, passProgram.textureBindings[index].samplerName); if (textureSamplerLocation >= 0) glUniform1i(textureSamplerLocation, static_cast(shaderTextureBase + static_cast(index))); } - const GLuint textTextureBase = shaderTextureBase + static_cast(layerProgram.textureBindings.size()); - for (std::size_t index = 0; index < layerProgram.textBindings.size(); ++index) + const GLuint textTextureBase = shaderTextureBase + static_cast(passProgram.textureBindings.size()); + for (std::size_t index = 0; index < passProgram.textBindings.size(); ++index) { - const GLint textSamplerLocation = FindSamplerUniformLocation(program, layerProgram.textBindings[index].samplerName); + const GLint textSamplerLocation = FindSamplerUniformLocation(program, passProgram.textBindings[index].samplerName); if (textSamplerLocation >= 0) glUniform1i(textSamplerLocation, static_cast(textTextureBase + static_cast(index))); } } ShaderTextureBindings::RuntimeTextureBindingPlan ShaderTextureBindings::BuildLayerRuntimeBindingPlan( - const LayerProgram& layerProgram, + const PassProgram& passProgram, GLuint layerInputTexture, const std::vector& sourceHistoryTextures, const std::vector& temporalHistoryTextures) const @@ -175,10 +175,10 @@ ShaderTextureBindings::RuntimeTextureBindingPlan ShaderTextureBindings::BuildLay }); } - const GLuint shaderTextureBase = layerProgram.shaderTextureBase != 0 ? layerProgram.shaderTextureBase : kSourceHistoryTextureUnitBase; - for (std::size_t index = 0; index < layerProgram.textureBindings.size(); ++index) + const GLuint shaderTextureBase = passProgram.shaderTextureBase != 0 ? passProgram.shaderTextureBase : kSourceHistoryTextureUnitBase; + for (std::size_t index = 0; index < passProgram.textureBindings.size(); ++index) { - const LayerProgram::TextureBinding& textureBinding = layerProgram.textureBindings[index]; + const LayerProgram::TextureBinding& textureBinding = passProgram.textureBindings[index]; plan.bindings.push_back({ "shaderTexture", textureBinding.samplerName, @@ -187,10 +187,10 @@ ShaderTextureBindings::RuntimeTextureBindingPlan ShaderTextureBindings::BuildLay }); } - const GLuint textTextureBase = shaderTextureBase + static_cast(layerProgram.textureBindings.size()); - for (std::size_t index = 0; index < layerProgram.textBindings.size(); ++index) + const GLuint textTextureBase = shaderTextureBase + static_cast(passProgram.textureBindings.size()); + for (std::size_t index = 0; index < passProgram.textBindings.size(); ++index) { - const LayerProgram::TextBinding& textBinding = layerProgram.textBindings[index]; + const LayerProgram::TextBinding& textBinding = passProgram.textBindings[index]; plan.bindings.push_back({ "textTexture", textBinding.samplerName, diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderTextureBindings.h b/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderTextureBindings.h index c6d14aa..28a8d0f 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderTextureBindings.h +++ b/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderTextureBindings.h @@ -10,6 +10,7 @@ class ShaderTextureBindings { public: using LayerProgram = OpenGLRenderer::LayerProgram; + using PassProgram = OpenGLRenderer::LayerProgram::PassProgram; struct RuntimeTextureBinding { @@ -29,9 +30,9 @@ public: bool UpdateTextBindingTexture(const RuntimeRenderState& state, LayerProgram::TextBinding& textBinding, std::string& error); GLint FindSamplerUniformLocation(GLuint program, const std::string& samplerName) const; GLuint ResolveShaderTextureBase(const RuntimeRenderState& state, unsigned historyCap) const; - void AssignLayerSamplerUniforms(GLuint program, const RuntimeRenderState& state, const LayerProgram& layerProgram, unsigned historyCap) const; + void AssignLayerSamplerUniforms(GLuint program, const RuntimeRenderState& state, const PassProgram& passProgram, unsigned historyCap) const; RuntimeTextureBindingPlan BuildLayerRuntimeBindingPlan( - const LayerProgram& layerProgram, + const PassProgram& passProgram, GLuint layerInputTexture, const std::vector& sourceHistoryTextures, const std::vector& temporalHistoryTextures) const;