From 5b6e30ad131814a099ef1ac3225bf2fd4f1bf5e4 Mon Sep 17 00:00:00 2001 From: Aiden Date: Fri, 8 May 2026 16:55:16 +1000 Subject: [PATCH] Render class --- CMakeLists.txt | 1 + .../LoopThroughWithOpenGLCompositing.vcxproj | 1 + ...roughWithOpenGLCompositing.vcxproj.filters | 3 + .../gl/pipeline/OpenGLRenderPass.cpp | 83 +++++++++++++++---- .../gl/pipeline/OpenGLRenderPass.h | 11 +++ .../gl/pipeline/RenderPassDescriptor.h | 36 ++++++++ .../gl/renderer/RenderTargetPool.h | 51 ++++++++++++ 7 files changed, 172 insertions(+), 14 deletions(-) create mode 100644 apps/LoopThroughWithOpenGLCompositing/gl/pipeline/RenderPassDescriptor.h create mode 100644 apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a58323c..1f70d9c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,6 +64,7 @@ set(APP_SOURCES "${APP_DIR}/gl/pipeline/OpenGLRenderPass.h" "${APP_DIR}/gl/pipeline/OpenGLRenderPipeline.cpp" "${APP_DIR}/gl/pipeline/OpenGLRenderPipeline.h" + "${APP_DIR}/gl/pipeline/RenderPassDescriptor.h" "${APP_DIR}/gl/renderer/OpenGLRenderer.cpp" "${APP_DIR}/gl/renderer/OpenGLRenderer.h" "${APP_DIR}/gl/pipeline/OpenGLVideoIOBridge.cpp" diff --git a/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj b/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj index 65a2b9c..6f8b9ec 100644 --- a/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj +++ b/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj @@ -206,6 +206,7 @@ + diff --git a/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj.filters b/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj.filters index 151acb1..cae0ed3 100644 --- a/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj.filters +++ b/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj.filters @@ -92,6 +92,9 @@ Header Files + + Header Files + Header Files diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/OpenGLRenderPass.cpp b/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/OpenGLRenderPass.cpp index 8c86fb9..510e662 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/OpenGLRenderPass.cpp +++ b/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/OpenGLRenderPass.cpp @@ -43,26 +43,16 @@ void OpenGLRenderPass::Render( } else { - GLuint sourceTexture = mRenderer.DecodedTexture(); - GLuint sourceFrameBuffer = mRenderer.DecodeFramebuffer(); - for (std::size_t index = 0; index < layerStates.size() && index < layerPrograms.size(); ++index) + const std::vector passes = BuildLayerPassDescriptors(layerStates, layerPrograms); + for (const RenderPassDescriptor& pass : passes) { - const std::size_t remaining = layerStates.size() - index; - const bool writeToMain = (remaining % 2) == 1; - RenderShaderProgram( - sourceTexture, - writeToMain ? mRenderer.CompositeFramebuffer() : mRenderer.LayerTempFramebuffer(), - layerPrograms[index], - layerStates[index], + RenderLayerPass( + pass, inputFrameWidth, inputFrameHeight, historyCap, updateTextBinding, updateGlobalParams); - if (layerStates[index].temporalHistorySource == TemporalHistorySource::PreLayerInput) - mRenderer.TemporalHistory().PushPreLayerFramebuffer(layerStates[index].layerId, sourceFrameBuffer, inputFrameWidth, inputFrameHeight); - sourceTexture = writeToMain ? mRenderer.CompositeTexture() : mRenderer.LayerTempTexture(); - sourceFrameBuffer = writeToMain ? mRenderer.CompositeFramebuffer() : mRenderer.LayerTempFramebuffer(); } } @@ -97,6 +87,71 @@ void OpenGLRenderPass::RenderDecodePass(unsigned inputFrameWidth, unsigned input glActiveTexture(GL_TEXTURE0); } +std::vector OpenGLRenderPass::BuildLayerPassDescriptors( + const std::vector& layerStates, + std::vector& layerPrograms) const +{ + std::vector passes; + const std::size_t passCount = layerStates.size() < layerPrograms.size() ? layerStates.size() : layerPrograms.size(); + passes.reserve(passCount); + + GLuint sourceTexture = mRenderer.DecodedTexture(); + GLuint sourceFramebuffer = mRenderer.DecodeFramebuffer(); + for (std::size_t index = 0; index < passCount; ++index) + { + const RuntimeRenderState& state = layerStates[index]; + LayerProgram& layerProgram = layerPrograms[index]; + const std::size_t remaining = layerStates.size() - index; + const bool writeToMain = (remaining % 2) == 1; + + RenderPassDescriptor pass; + pass.kind = RenderPassKind::LayerEffect; + pass.outputTarget = writeToMain ? RenderPassOutputTarget::Composite : RenderPassOutputTarget::LayerTemp; + pass.passIndex = index; + pass.passId = state.layerId; + pass.layerId = state.layerId; + pass.shaderId = state.shaderId; + pass.sourceTexture = sourceTexture; + pass.sourceFramebuffer = sourceFramebuffer; + pass.destinationFramebuffer = writeToMain ? mRenderer.CompositeFramebuffer() : mRenderer.LayerTempFramebuffer(); + pass.layerProgram = &layerProgram; + pass.layerState = &state; + pass.capturePreLayerHistory = state.temporalHistorySource == TemporalHistorySource::PreLayerInput; + passes.push_back(pass); + + sourceTexture = writeToMain ? mRenderer.CompositeTexture() : mRenderer.LayerTempTexture(); + sourceFramebuffer = writeToMain ? mRenderer.CompositeFramebuffer() : mRenderer.LayerTempFramebuffer(); + } + + return passes; +} + +void OpenGLRenderPass::RenderLayerPass( + const RenderPassDescriptor& pass, + unsigned inputFrameWidth, + unsigned inputFrameHeight, + unsigned historyCap, + const TextBindingUpdater& updateTextBinding, + const GlobalParamsUpdater& updateGlobalParams) +{ + if (pass.layerProgram == nullptr || pass.layerState == nullptr) + return; + + RenderShaderProgram( + pass.sourceTexture, + pass.destinationFramebuffer, + *pass.layerProgram, + *pass.layerState, + inputFrameWidth, + inputFrameHeight, + historyCap, + updateTextBinding, + updateGlobalParams); + + if (pass.capturePreLayerHistory) + mRenderer.TemporalHistory().PushPreLayerFramebuffer(pass.layerId, pass.sourceFramebuffer, inputFrameWidth, inputFrameHeight); +} + void OpenGLRenderPass::RenderShaderProgram( GLuint sourceTexture, GLuint destinationFrameBuffer, diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/OpenGLRenderPass.h b/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/OpenGLRenderPass.h index 43beb39..18e7739 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/OpenGLRenderPass.h +++ b/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/OpenGLRenderPass.h @@ -1,6 +1,7 @@ #pragma once #include "OpenGLRenderer.h" +#include "RenderPassDescriptor.h" #include "ShaderTypes.h" #include "VideoIOFormat.h" @@ -30,6 +31,16 @@ public: private: void RenderDecodePass(unsigned inputFrameWidth, unsigned inputFrameHeight, unsigned captureTextureWidth, VideoIOPixelFormat inputPixelFormat); + std::vector BuildLayerPassDescriptors( + const std::vector& layerStates, + std::vector& layerPrograms) const; + void RenderLayerPass( + const RenderPassDescriptor& pass, + unsigned inputFrameWidth, + unsigned inputFrameHeight, + unsigned historyCap, + const TextBindingUpdater& updateTextBinding, + const GlobalParamsUpdater& updateGlobalParams); void RenderShaderProgram( GLuint sourceTexture, GLuint destinationFrameBuffer, diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/RenderPassDescriptor.h b/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/RenderPassDescriptor.h new file mode 100644 index 0000000..3e108bf --- /dev/null +++ b/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/RenderPassDescriptor.h @@ -0,0 +1,36 @@ +#pragma once + +#include "OpenGLRenderer.h" +#include "ShaderTypes.h" + +#include + +#include +#include + +enum class RenderPassKind +{ + LayerEffect +}; + +enum class RenderPassOutputTarget +{ + LayerTemp, + Composite +}; + +struct RenderPassDescriptor +{ + RenderPassKind kind = RenderPassKind::LayerEffect; + RenderPassOutputTarget outputTarget = RenderPassOutputTarget::Composite; + std::size_t passIndex = 0; + std::string passId; + std::string layerId; + std::string shaderId; + GLuint sourceTexture = 0; + GLuint sourceFramebuffer = 0; + GLuint destinationFramebuffer = 0; + OpenGLRenderer::LayerProgram* layerProgram = nullptr; + const RuntimeRenderState* layerState = nullptr; + bool capturePreLayerHistory = false; +}; diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.h b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.h new file mode 100644 index 0000000..1c0f1c1 --- /dev/null +++ b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.h @@ -0,0 +1,51 @@ +#pragma once + +#include + +#include +#include + +enum class RenderTargetId +{ + Decoded, + LayerTemp, + Composite, + Output, + OutputPack, + Count +}; + +struct RenderTarget +{ + GLuint texture = 0; + GLuint framebuffer = 0; + unsigned width = 0; + unsigned height = 0; + GLenum internalFormat = GL_RGBA8; + GLenum pixelFormat = GL_RGBA; + GLenum pixelType = GL_UNSIGNED_BYTE; +}; + +class RenderTargetPool +{ +public: + bool Create( + RenderTargetId id, + unsigned width, + unsigned height, + GLenum internalFormat, + GLenum pixelFormat, + GLenum pixelType, + const char* errorPrefix, + std::string& error); + void Destroy(); + + GLuint Texture(RenderTargetId id) const { return Target(id).texture; } + GLuint Framebuffer(RenderTargetId id) const { return Target(id).framebuffer; } + const RenderTarget& Target(RenderTargetId id) const; + +private: + static std::size_t TargetIndex(RenderTargetId id) { return static_cast(id); } + + std::array(RenderTargetId::Count)> mTargets; +};