diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f70d9c..e110aea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,6 +67,8 @@ set(APP_SOURCES "${APP_DIR}/gl/pipeline/RenderPassDescriptor.h" "${APP_DIR}/gl/renderer/OpenGLRenderer.cpp" "${APP_DIR}/gl/renderer/OpenGLRenderer.h" + "${APP_DIR}/gl/renderer/RenderTargetPool.cpp" + "${APP_DIR}/gl/renderer/RenderTargetPool.h" "${APP_DIR}/gl/pipeline/OpenGLVideoIOBridge.cpp" "${APP_DIR}/gl/pipeline/OpenGLVideoIOBridge.h" "${APP_DIR}/gl/shader/OpenGLShaderPrograms.cpp" diff --git a/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj b/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj index 6f8b9ec..5257d31 100644 --- a/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj +++ b/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj @@ -181,6 +181,7 @@ + @@ -208,6 +209,7 @@ + diff --git a/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj.filters b/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj.filters index cae0ed3..c19a028 100644 --- a/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj.filters +++ b/apps/LoopThroughWithOpenGLCompositing/LoopThroughWithOpenGLCompositing.vcxproj.filters @@ -36,6 +36,9 @@ Source Files + + Source Files + Source Files @@ -98,6 +101,9 @@ Header Files + + Header Files + Header Files diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.cpp b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.cpp index 19fbd8e..1f1f8b0 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.cpp +++ b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.cpp @@ -12,15 +12,6 @@ namespace glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); } - - void ConfigureDisplayFrameTexture(unsigned width, unsigned height) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, NULL); - } } bool OpenGLRenderer::InitializeResources(unsigned inputFrameWidth, unsigned inputFrameHeight, unsigned captureTextureWidth, unsigned outputFrameWidth, unsigned outputFrameHeight, unsigned outputPackTextureWidth, std::string& error) @@ -35,80 +26,32 @@ bool OpenGLRenderer::InitializeResources(unsigned inputFrameWidth, unsigned inpu ConfigureByteFrameTexture(captureTextureWidth, inputFrameHeight); glBindTexture(GL_TEXTURE_2D, 0); - glGenTextures(1, &mDecodedTexture); - glBindTexture(GL_TEXTURE_2D, mDecodedTexture); - ConfigureDisplayFrameTexture(inputFrameWidth, inputFrameHeight); - glBindTexture(GL_TEXTURE_2D, 0); - - glGenTextures(1, &mLayerTempTexture); - glBindTexture(GL_TEXTURE_2D, mLayerTempTexture); - ConfigureDisplayFrameTexture(inputFrameWidth, inputFrameHeight); - glBindTexture(GL_TEXTURE_2D, 0); - - glGenFramebuffers(1, &mDecodeFrameBuf); - glGenFramebuffers(1, &mLayerTempFrameBuf); - glGenFramebuffers(1, &mIdFrameBuf); - glGenFramebuffers(1, &mOutputFrameBuf); - glGenFramebuffers(1, &mOutputPackFrameBuf); glGenRenderbuffers(1, &mIdColorBuf); glGenRenderbuffers(1, &mIdDepthBuf); glGenVertexArrays(1, &mFullscreenVAO); glGenBuffers(1, &mGlobalParamsUBO); - glBindFramebuffer(GL_FRAMEBUFFER, mDecodeFrameBuf); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mDecodedTexture, 0); - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - { - error = "Cannot initialize decode framebuffer."; + if (!mRenderTargets.Create(RenderTargetId::Decoded, inputFrameWidth, inputFrameHeight, GL_RGBA16F, GL_RGBA, GL_FLOAT, "decode", error)) return false; - } - - glBindFramebuffer(GL_FRAMEBUFFER, mLayerTempFrameBuf); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mLayerTempTexture, 0); - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - { - error = "Cannot initialize layer framebuffer."; + if (!mRenderTargets.Create(RenderTargetId::LayerTemp, inputFrameWidth, inputFrameHeight, GL_RGBA16F, GL_RGBA, GL_FLOAT, "layer", error)) + return false; + if (!mRenderTargets.Create(RenderTargetId::Composite, inputFrameWidth, inputFrameHeight, GL_RGBA16F, GL_RGBA, GL_FLOAT, "composite", error)) return false; - } - - glBindFramebuffer(GL_FRAMEBUFFER, mIdFrameBuf); - glGenTextures(1, &mFBOTexture); - glBindTexture(GL_TEXTURE_2D, mFBOTexture); - ConfigureDisplayFrameTexture(inputFrameWidth, inputFrameHeight); + glBindFramebuffer(GL_FRAMEBUFFER, CompositeFramebuffer()); glBindRenderbuffer(GL_RENDERBUFFER, mIdDepthBuf); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, inputFrameWidth, inputFrameHeight); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER, mIdDepthBuf); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mFBOTexture, 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { error = "Cannot initialize framebuffer."; return false; } - glGenTextures(1, &mOutputTexture); - glBindTexture(GL_TEXTURE_2D, mOutputTexture); - ConfigureDisplayFrameTexture(outputFrameWidth, outputFrameHeight); - - glBindFramebuffer(GL_FRAMEBUFFER, mOutputFrameBuf); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mOutputTexture, 0); - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - { - error = "Cannot initialize output framebuffer."; + if (!mRenderTargets.Create(RenderTargetId::Output, outputFrameWidth, outputFrameHeight, GL_RGBA16F, GL_RGBA, GL_FLOAT, "output", error)) return false; - } - - glGenTextures(1, &mOutputPackTexture); - glBindTexture(GL_TEXTURE_2D, mOutputPackTexture); - ConfigureByteFrameTexture(outputPackTextureWidth, outputFrameHeight); - - glBindFramebuffer(GL_FRAMEBUFFER, mOutputPackFrameBuf); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mOutputPackTexture, 0); - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - { - error = "Cannot initialize output pack framebuffer."; + if (!mRenderTargets.Create(RenderTargetId::OutputPack, outputPackTextureWidth, outputFrameHeight, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, "output pack", error)) return false; - } glBindTexture(GL_TEXTURE_2D, 0); glBindRenderbuffer(GL_RENDERBUFFER, 0); @@ -169,7 +112,7 @@ void OpenGLRenderer::PresentToWindow(HDC hdc, unsigned outputFrameWidth, unsigne } } - glBindFramebuffer(GL_READ_FRAMEBUFFER, mOutputFrameBuf); + glBindFramebuffer(GL_READ_FRAMEBUFFER, OutputFramebuffer()); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glDisable(GL_SCISSOR_TEST); glViewport(0, 0, mViewWidth, mViewHeight); @@ -186,50 +129,21 @@ void OpenGLRenderer::DestroyResources() glDeleteVertexArrays(1, &mFullscreenVAO); if (mGlobalParamsUBO != 0) glDeleteBuffers(1, &mGlobalParamsUBO); - if (mDecodeFrameBuf != 0) - glDeleteFramebuffers(1, &mDecodeFrameBuf); - if (mLayerTempFrameBuf != 0) - glDeleteFramebuffers(1, &mLayerTempFrameBuf); - if (mIdFrameBuf != 0) - glDeleteFramebuffers(1, &mIdFrameBuf); - if (mOutputFrameBuf != 0) - glDeleteFramebuffers(1, &mOutputFrameBuf); - if (mOutputPackFrameBuf != 0) - glDeleteFramebuffers(1, &mOutputPackFrameBuf); if (mIdColorBuf != 0) glDeleteRenderbuffers(1, &mIdColorBuf); if (mIdDepthBuf != 0) glDeleteRenderbuffers(1, &mIdDepthBuf); if (mCaptureTexture != 0) glDeleteTextures(1, &mCaptureTexture); - if (mDecodedTexture != 0) - glDeleteTextures(1, &mDecodedTexture); - if (mLayerTempTexture != 0) - glDeleteTextures(1, &mLayerTempTexture); - if (mFBOTexture != 0) - glDeleteTextures(1, &mFBOTexture); - if (mOutputTexture != 0) - glDeleteTextures(1, &mOutputTexture); - if (mOutputPackTexture != 0) - glDeleteTextures(1, &mOutputPackTexture); if (mTextureUploadBuffer != 0) glDeleteBuffers(1, &mTextureUploadBuffer); + mRenderTargets.Destroy(); mFullscreenVAO = 0; mGlobalParamsUBO = 0; - mDecodeFrameBuf = 0; - mLayerTempFrameBuf = 0; - mIdFrameBuf = 0; - mOutputFrameBuf = 0; - mOutputPackFrameBuf = 0; mIdColorBuf = 0; mIdDepthBuf = 0; mCaptureTexture = 0; - mDecodedTexture = 0; - mLayerTempTexture = 0; - mFBOTexture = 0; - mOutputTexture = 0; - mOutputPackTexture = 0; mTextureUploadBuffer = 0; mGlobalParamsUBOSize = 0; diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.h b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.h index 357fa3c..dac49bc 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.h +++ b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.h @@ -1,6 +1,7 @@ #pragma once #include "GLExtensions.h" +#include "RenderTargetPool.h" #include "ShaderTypes.h" #include "TemporalHistoryBuffers.h" @@ -45,17 +46,17 @@ public: }; GLuint CaptureTexture() const { return mCaptureTexture; } - GLuint DecodedTexture() const { return mDecodedTexture; } - GLuint LayerTempTexture() const { return mLayerTempTexture; } - GLuint CompositeTexture() const { return mFBOTexture; } - GLuint OutputTexture() const { return mOutputTexture; } - GLuint OutputPackTexture() const { return mOutputPackTexture; } + GLuint DecodedTexture() const { return mRenderTargets.Texture(RenderTargetId::Decoded); } + GLuint LayerTempTexture() const { return mRenderTargets.Texture(RenderTargetId::LayerTemp); } + GLuint CompositeTexture() const { return mRenderTargets.Texture(RenderTargetId::Composite); } + GLuint OutputTexture() const { return mRenderTargets.Texture(RenderTargetId::Output); } + GLuint OutputPackTexture() const { return mRenderTargets.Texture(RenderTargetId::OutputPack); } GLuint TextureUploadBuffer() const { return mTextureUploadBuffer; } - GLuint DecodeFramebuffer() const { return mDecodeFrameBuf; } - GLuint LayerTempFramebuffer() const { return mLayerTempFrameBuf; } - GLuint CompositeFramebuffer() const { return mIdFrameBuf; } - GLuint OutputFramebuffer() const { return mOutputFrameBuf; } - GLuint OutputPackFramebuffer() const { return mOutputPackFrameBuf; } + GLuint DecodeFramebuffer() const { return mRenderTargets.Framebuffer(RenderTargetId::Decoded); } + GLuint LayerTempFramebuffer() const { return mRenderTargets.Framebuffer(RenderTargetId::LayerTemp); } + GLuint CompositeFramebuffer() const { return mRenderTargets.Framebuffer(RenderTargetId::Composite); } + GLuint OutputFramebuffer() const { return mRenderTargets.Framebuffer(RenderTargetId::Output); } + GLuint OutputPackFramebuffer() const { return mRenderTargets.Framebuffer(RenderTargetId::OutputPack); } GLuint FullscreenVertexArray() const { return mFullscreenVAO; } GLuint GlobalParamsUBO() const { return mGlobalParamsUBO; } GLuint DecodeProgram() const { return mDecodeProgram; } @@ -80,17 +81,7 @@ public: private: GLuint mCaptureTexture = 0; - GLuint mDecodedTexture = 0; - GLuint mLayerTempTexture = 0; - GLuint mFBOTexture = 0; - GLuint mOutputTexture = 0; - GLuint mOutputPackTexture = 0; GLuint mTextureUploadBuffer = 0; - GLuint mDecodeFrameBuf = 0; - GLuint mLayerTempFrameBuf = 0; - GLuint mIdFrameBuf = 0; - GLuint mOutputFrameBuf = 0; - GLuint mOutputPackFrameBuf = 0; GLuint mIdColorBuf = 0; GLuint mIdDepthBuf = 0; GLuint mFullscreenVAO = 0; @@ -105,5 +96,6 @@ private: int mViewWidth = 0; int mViewHeight = 0; std::vector mLayerPrograms; + RenderTargetPool mRenderTargets; TemporalHistoryBuffers mTemporalHistory; }; diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.cpp b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.cpp new file mode 100644 index 0000000..012e39e --- /dev/null +++ b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.cpp @@ -0,0 +1,132 @@ +#include "RenderTargetPool.h" + +#include + +namespace +{ + void ConfigureRenderTargetTexture( + unsigned width, + unsigned height, + GLenum internalFormat, + GLenum pixelFormat, + GLenum pixelType) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, pixelFormat, pixelType, NULL); + } +} + +bool RenderTargetPool::Create( + RenderTargetId id, + unsigned width, + unsigned height, + GLenum internalFormat, + GLenum pixelFormat, + GLenum pixelType, + const char* errorPrefix, + std::string& error) +{ + RenderTarget& target = mTargets[TargetIndex(id)]; + if (target.texture != 0 || target.framebuffer != 0) + { + error = std::string(errorPrefix) + " render target was already initialized."; + return false; + } + + glGenTextures(1, &target.texture); + glBindTexture(GL_TEXTURE_2D, target.texture); + ConfigureRenderTargetTexture(width, height, internalFormat, pixelFormat, pixelType); + glBindTexture(GL_TEXTURE_2D, 0); + + glGenFramebuffers(1, &target.framebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, target.framebuffer); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target.texture, 0); + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + { + error = std::string("Cannot initialize ") + errorPrefix + " framebuffer."; + glBindFramebuffer(GL_FRAMEBUFFER, 0); + return false; + } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + target.width = width; + target.height = height; + target.internalFormat = internalFormat; + target.pixelFormat = pixelFormat; + target.pixelType = pixelType; + return true; +} + +bool RenderTargetPool::ReserveTemporaryTargets( + std::size_t count, + unsigned width, + unsigned height, + GLenum internalFormat, + GLenum pixelFormat, + GLenum pixelType, + std::string& error) +{ + if (!mTemporaryTargets.empty()) + { + error = "Temporary render targets were already initialized."; + return false; + } + + mTemporaryTargets.resize(count); + for (std::size_t index = 0; index < mTemporaryTargets.size(); ++index) + { + RenderTarget& target = mTemporaryTargets[index]; + glGenTextures(1, &target.texture); + glBindTexture(GL_TEXTURE_2D, target.texture); + ConfigureRenderTargetTexture(width, height, internalFormat, pixelFormat, pixelType); + glBindTexture(GL_TEXTURE_2D, 0); + + glGenFramebuffers(1, &target.framebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, target.framebuffer); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target.texture, 0); + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + { + error = "Cannot initialize temporary render target."; + glBindFramebuffer(GL_FRAMEBUFFER, 0); + return false; + } + + target.width = width; + target.height = height; + target.internalFormat = internalFormat; + target.pixelFormat = pixelFormat; + target.pixelType = pixelType; + } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + return true; +} + +void RenderTargetPool::Destroy() +{ + for (RenderTarget& target : mTargets) + { + if (target.framebuffer != 0) + glDeleteFramebuffers(1, &target.framebuffer); + if (target.texture != 0) + glDeleteTextures(1, &target.texture); + target = RenderTarget(); + } + + for (RenderTarget& target : mTemporaryTargets) + { + if (target.framebuffer != 0) + glDeleteFramebuffers(1, &target.framebuffer); + if (target.texture != 0) + glDeleteTextures(1, &target.texture); + } + mTemporaryTargets.clear(); +} + +const RenderTarget& RenderTargetPool::Target(RenderTargetId id) const +{ + return mTargets[TargetIndex(id)]; +} diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.h b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.h index 1c0f1c1..6ca08d6 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.h +++ b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.h @@ -1,9 +1,10 @@ #pragma once -#include +#include "GLExtensions.h" #include #include +#include enum class RenderTargetId { @@ -38,14 +39,25 @@ public: GLenum pixelType, const char* errorPrefix, std::string& error); + bool ReserveTemporaryTargets( + std::size_t count, + unsigned width, + unsigned height, + GLenum internalFormat, + GLenum pixelFormat, + GLenum pixelType, + 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; + const RenderTarget& TemporaryTarget(std::size_t index) const { return mTemporaryTargets[index]; } + std::size_t TemporaryTargetCount() const { return mTemporaryTargets.size(); } private: static std::size_t TargetIndex(RenderTargetId id) { return static_cast(id); } std::array(RenderTargetId::Count)> mTargets; + std::vector mTemporaryTargets; };