2 Commits

Author SHA1 Message Date
7d8f9a39d1 render target pool
All checks were successful
CI / React UI Build (push) Successful in 11s
CI / Native Windows Build And Tests (push) Successful in 2m15s
CI / Windows Release Package (push) Successful in 2m31s
2026-05-08 16:59:43 +10:00
5b6e30ad13 Render class 2026-05-08 16:55:16 +10:00
10 changed files with 347 additions and 129 deletions

View File

@@ -64,8 +64,11 @@ set(APP_SOURCES
"${APP_DIR}/gl/pipeline/OpenGLRenderPass.h" "${APP_DIR}/gl/pipeline/OpenGLRenderPass.h"
"${APP_DIR}/gl/pipeline/OpenGLRenderPipeline.cpp" "${APP_DIR}/gl/pipeline/OpenGLRenderPipeline.cpp"
"${APP_DIR}/gl/pipeline/OpenGLRenderPipeline.h" "${APP_DIR}/gl/pipeline/OpenGLRenderPipeline.h"
"${APP_DIR}/gl/pipeline/RenderPassDescriptor.h"
"${APP_DIR}/gl/renderer/OpenGLRenderer.cpp" "${APP_DIR}/gl/renderer/OpenGLRenderer.cpp"
"${APP_DIR}/gl/renderer/OpenGLRenderer.h" "${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.cpp"
"${APP_DIR}/gl/pipeline/OpenGLVideoIOBridge.h" "${APP_DIR}/gl/pipeline/OpenGLVideoIOBridge.h"
"${APP_DIR}/gl/shader/OpenGLShaderPrograms.cpp" "${APP_DIR}/gl/shader/OpenGLShaderPrograms.cpp"

View File

@@ -181,6 +181,7 @@
<ClCompile Include="gl\pipeline\OpenGLRenderPass.cpp" /> <ClCompile Include="gl\pipeline\OpenGLRenderPass.cpp" />
<ClCompile Include="gl\pipeline\OpenGLRenderPipeline.cpp" /> <ClCompile Include="gl\pipeline\OpenGLRenderPipeline.cpp" />
<ClCompile Include="gl\renderer\OpenGLRenderer.cpp" /> <ClCompile Include="gl\renderer\OpenGLRenderer.cpp" />
<ClCompile Include="gl\renderer\RenderTargetPool.cpp" />
<ClCompile Include="gl\shader\OpenGLShaderPrograms.cpp" /> <ClCompile Include="gl\shader\OpenGLShaderPrograms.cpp" />
<ClCompile Include="gl\pipeline\PngScreenshotWriter.cpp" /> <ClCompile Include="gl\pipeline\PngScreenshotWriter.cpp" />
<ClCompile Include="gl\shader\ShaderBuildQueue.cpp" /> <ClCompile Include="gl\shader\ShaderBuildQueue.cpp" />
@@ -206,7 +207,9 @@
<ClInclude Include="gl\OpenGLComposite.h" /> <ClInclude Include="gl\OpenGLComposite.h" />
<ClInclude Include="gl\pipeline\OpenGLRenderPass.h" /> <ClInclude Include="gl\pipeline\OpenGLRenderPass.h" />
<ClInclude Include="gl\pipeline\OpenGLRenderPipeline.h" /> <ClInclude Include="gl\pipeline\OpenGLRenderPipeline.h" />
<ClInclude Include="gl\pipeline\RenderPassDescriptor.h" />
<ClInclude Include="gl\renderer\OpenGLRenderer.h" /> <ClInclude Include="gl\renderer\OpenGLRenderer.h" />
<ClInclude Include="gl\renderer\RenderTargetPool.h" />
<ClInclude Include="gl\shader\OpenGLShaderPrograms.h" /> <ClInclude Include="gl\shader\OpenGLShaderPrograms.h" />
<ClInclude Include="gl\pipeline\PngScreenshotWriter.h" /> <ClInclude Include="gl\pipeline\PngScreenshotWriter.h" />
<ClInclude Include="gl\shader\ShaderBuildQueue.h" /> <ClInclude Include="gl\shader\ShaderBuildQueue.h" />

View File

@@ -36,6 +36,9 @@
<ClCompile Include="gl\renderer\OpenGLRenderer.cpp"> <ClCompile Include="gl\renderer\OpenGLRenderer.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="gl\renderer\RenderTargetPool.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="gl\shader\OpenGLShaderPrograms.cpp"> <ClCompile Include="gl\shader\OpenGLShaderPrograms.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
@@ -92,9 +95,15 @@
<ClInclude Include="gl\pipeline\OpenGLRenderPipeline.h"> <ClInclude Include="gl\pipeline\OpenGLRenderPipeline.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="gl\pipeline\RenderPassDescriptor.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="gl\renderer\OpenGLRenderer.h"> <ClInclude Include="gl\renderer\OpenGLRenderer.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="gl\renderer\RenderTargetPool.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="gl\shader\OpenGLShaderPrograms.h"> <ClInclude Include="gl\shader\OpenGLShaderPrograms.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>

View File

@@ -43,26 +43,16 @@ void OpenGLRenderPass::Render(
} }
else else
{ {
GLuint sourceTexture = mRenderer.DecodedTexture(); const std::vector<RenderPassDescriptor> passes = BuildLayerPassDescriptors(layerStates, layerPrograms);
GLuint sourceFrameBuffer = mRenderer.DecodeFramebuffer(); for (const RenderPassDescriptor& pass : passes)
for (std::size_t index = 0; index < layerStates.size() && index < layerPrograms.size(); ++index)
{ {
const std::size_t remaining = layerStates.size() - index; RenderLayerPass(
const bool writeToMain = (remaining % 2) == 1; pass,
RenderShaderProgram(
sourceTexture,
writeToMain ? mRenderer.CompositeFramebuffer() : mRenderer.LayerTempFramebuffer(),
layerPrograms[index],
layerStates[index],
inputFrameWidth, inputFrameWidth,
inputFrameHeight, inputFrameHeight,
historyCap, historyCap,
updateTextBinding, updateTextBinding,
updateGlobalParams); 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); glActiveTexture(GL_TEXTURE0);
} }
std::vector<RenderPassDescriptor> OpenGLRenderPass::BuildLayerPassDescriptors(
const std::vector<RuntimeRenderState>& layerStates,
std::vector<LayerProgram>& layerPrograms) const
{
std::vector<RenderPassDescriptor> 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( void OpenGLRenderPass::RenderShaderProgram(
GLuint sourceTexture, GLuint sourceTexture,
GLuint destinationFrameBuffer, GLuint destinationFrameBuffer,

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "OpenGLRenderer.h" #include "OpenGLRenderer.h"
#include "RenderPassDescriptor.h"
#include "ShaderTypes.h" #include "ShaderTypes.h"
#include "VideoIOFormat.h" #include "VideoIOFormat.h"
@@ -30,6 +31,16 @@ public:
private: private:
void RenderDecodePass(unsigned inputFrameWidth, unsigned inputFrameHeight, unsigned captureTextureWidth, VideoIOPixelFormat inputPixelFormat); void RenderDecodePass(unsigned inputFrameWidth, unsigned inputFrameHeight, unsigned captureTextureWidth, VideoIOPixelFormat inputPixelFormat);
std::vector<RenderPassDescriptor> BuildLayerPassDescriptors(
const std::vector<RuntimeRenderState>& layerStates,
std::vector<LayerProgram>& layerPrograms) const;
void RenderLayerPass(
const RenderPassDescriptor& pass,
unsigned inputFrameWidth,
unsigned inputFrameHeight,
unsigned historyCap,
const TextBindingUpdater& updateTextBinding,
const GlobalParamsUpdater& updateGlobalParams);
void RenderShaderProgram( void RenderShaderProgram(
GLuint sourceTexture, GLuint sourceTexture,
GLuint destinationFrameBuffer, GLuint destinationFrameBuffer,

View File

@@ -0,0 +1,36 @@
#pragma once
#include "OpenGLRenderer.h"
#include "ShaderTypes.h"
#include <gl/gl.h>
#include <cstddef>
#include <string>
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;
};

View File

@@ -12,15 +12,6 @@ namespace
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 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); 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) 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); ConfigureByteFrameTexture(captureTextureWidth, inputFrameHeight);
glBindTexture(GL_TEXTURE_2D, 0); 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, &mIdColorBuf);
glGenRenderbuffers(1, &mIdDepthBuf); glGenRenderbuffers(1, &mIdDepthBuf);
glGenVertexArrays(1, &mFullscreenVAO); glGenVertexArrays(1, &mFullscreenVAO);
glGenBuffers(1, &mGlobalParamsUBO); glGenBuffers(1, &mGlobalParamsUBO);
glBindFramebuffer(GL_FRAMEBUFFER, mDecodeFrameBuf); if (!mRenderTargets.Create(RenderTargetId::Decoded, inputFrameWidth, inputFrameHeight, GL_RGBA16F, GL_RGBA, GL_FLOAT, "decode", error))
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mDecodedTexture, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
error = "Cannot initialize decode framebuffer.";
return false; return false;
} if (!mRenderTargets.Create(RenderTargetId::LayerTemp, inputFrameWidth, inputFrameHeight, GL_RGBA16F, GL_RGBA, GL_FLOAT, "layer", error))
return false;
glBindFramebuffer(GL_FRAMEBUFFER, mLayerTempFrameBuf); if (!mRenderTargets.Create(RenderTargetId::Composite, inputFrameWidth, inputFrameHeight, GL_RGBA16F, GL_RGBA, GL_FLOAT, "composite", error))
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mLayerTempTexture, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
error = "Cannot initialize layer framebuffer.";
return false; 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); glBindRenderbuffer(GL_RENDERBUFFER, mIdDepthBuf);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, inputFrameWidth, inputFrameHeight); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, inputFrameWidth, inputFrameHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER, mIdDepthBuf); 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) if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{ {
error = "Cannot initialize framebuffer."; error = "Cannot initialize framebuffer.";
return false; return false;
} }
glGenTextures(1, &mOutputTexture); if (!mRenderTargets.Create(RenderTargetId::Output, outputFrameWidth, outputFrameHeight, GL_RGBA16F, GL_RGBA, GL_FLOAT, "output", error))
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.";
return false; return false;
} if (!mRenderTargets.Create(RenderTargetId::OutputPack, outputPackTextureWidth, outputFrameHeight, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, "output pack", error))
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.";
return false; return false;
}
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
glBindRenderbuffer(GL_RENDERBUFFER, 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); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);
glViewport(0, 0, mViewWidth, mViewHeight); glViewport(0, 0, mViewWidth, mViewHeight);
@@ -186,50 +129,21 @@ void OpenGLRenderer::DestroyResources()
glDeleteVertexArrays(1, &mFullscreenVAO); glDeleteVertexArrays(1, &mFullscreenVAO);
if (mGlobalParamsUBO != 0) if (mGlobalParamsUBO != 0)
glDeleteBuffers(1, &mGlobalParamsUBO); 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) if (mIdColorBuf != 0)
glDeleteRenderbuffers(1, &mIdColorBuf); glDeleteRenderbuffers(1, &mIdColorBuf);
if (mIdDepthBuf != 0) if (mIdDepthBuf != 0)
glDeleteRenderbuffers(1, &mIdDepthBuf); glDeleteRenderbuffers(1, &mIdDepthBuf);
if (mCaptureTexture != 0) if (mCaptureTexture != 0)
glDeleteTextures(1, &mCaptureTexture); 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) if (mTextureUploadBuffer != 0)
glDeleteBuffers(1, &mTextureUploadBuffer); glDeleteBuffers(1, &mTextureUploadBuffer);
mRenderTargets.Destroy();
mFullscreenVAO = 0; mFullscreenVAO = 0;
mGlobalParamsUBO = 0; mGlobalParamsUBO = 0;
mDecodeFrameBuf = 0;
mLayerTempFrameBuf = 0;
mIdFrameBuf = 0;
mOutputFrameBuf = 0;
mOutputPackFrameBuf = 0;
mIdColorBuf = 0; mIdColorBuf = 0;
mIdDepthBuf = 0; mIdDepthBuf = 0;
mCaptureTexture = 0; mCaptureTexture = 0;
mDecodedTexture = 0;
mLayerTempTexture = 0;
mFBOTexture = 0;
mOutputTexture = 0;
mOutputPackTexture = 0;
mTextureUploadBuffer = 0; mTextureUploadBuffer = 0;
mGlobalParamsUBOSize = 0; mGlobalParamsUBOSize = 0;

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "GLExtensions.h" #include "GLExtensions.h"
#include "RenderTargetPool.h"
#include "ShaderTypes.h" #include "ShaderTypes.h"
#include "TemporalHistoryBuffers.h" #include "TemporalHistoryBuffers.h"
@@ -45,17 +46,17 @@ public:
}; };
GLuint CaptureTexture() const { return mCaptureTexture; } GLuint CaptureTexture() const { return mCaptureTexture; }
GLuint DecodedTexture() const { return mDecodedTexture; } GLuint DecodedTexture() const { return mRenderTargets.Texture(RenderTargetId::Decoded); }
GLuint LayerTempTexture() const { return mLayerTempTexture; } GLuint LayerTempTexture() const { return mRenderTargets.Texture(RenderTargetId::LayerTemp); }
GLuint CompositeTexture() const { return mFBOTexture; } GLuint CompositeTexture() const { return mRenderTargets.Texture(RenderTargetId::Composite); }
GLuint OutputTexture() const { return mOutputTexture; } GLuint OutputTexture() const { return mRenderTargets.Texture(RenderTargetId::Output); }
GLuint OutputPackTexture() const { return mOutputPackTexture; } GLuint OutputPackTexture() const { return mRenderTargets.Texture(RenderTargetId::OutputPack); }
GLuint TextureUploadBuffer() const { return mTextureUploadBuffer; } GLuint TextureUploadBuffer() const { return mTextureUploadBuffer; }
GLuint DecodeFramebuffer() const { return mDecodeFrameBuf; } GLuint DecodeFramebuffer() const { return mRenderTargets.Framebuffer(RenderTargetId::Decoded); }
GLuint LayerTempFramebuffer() const { return mLayerTempFrameBuf; } GLuint LayerTempFramebuffer() const { return mRenderTargets.Framebuffer(RenderTargetId::LayerTemp); }
GLuint CompositeFramebuffer() const { return mIdFrameBuf; } GLuint CompositeFramebuffer() const { return mRenderTargets.Framebuffer(RenderTargetId::Composite); }
GLuint OutputFramebuffer() const { return mOutputFrameBuf; } GLuint OutputFramebuffer() const { return mRenderTargets.Framebuffer(RenderTargetId::Output); }
GLuint OutputPackFramebuffer() const { return mOutputPackFrameBuf; } GLuint OutputPackFramebuffer() const { return mRenderTargets.Framebuffer(RenderTargetId::OutputPack); }
GLuint FullscreenVertexArray() const { return mFullscreenVAO; } GLuint FullscreenVertexArray() const { return mFullscreenVAO; }
GLuint GlobalParamsUBO() const { return mGlobalParamsUBO; } GLuint GlobalParamsUBO() const { return mGlobalParamsUBO; }
GLuint DecodeProgram() const { return mDecodeProgram; } GLuint DecodeProgram() const { return mDecodeProgram; }
@@ -80,17 +81,7 @@ public:
private: private:
GLuint mCaptureTexture = 0; GLuint mCaptureTexture = 0;
GLuint mDecodedTexture = 0;
GLuint mLayerTempTexture = 0;
GLuint mFBOTexture = 0;
GLuint mOutputTexture = 0;
GLuint mOutputPackTexture = 0;
GLuint mTextureUploadBuffer = 0; GLuint mTextureUploadBuffer = 0;
GLuint mDecodeFrameBuf = 0;
GLuint mLayerTempFrameBuf = 0;
GLuint mIdFrameBuf = 0;
GLuint mOutputFrameBuf = 0;
GLuint mOutputPackFrameBuf = 0;
GLuint mIdColorBuf = 0; GLuint mIdColorBuf = 0;
GLuint mIdDepthBuf = 0; GLuint mIdDepthBuf = 0;
GLuint mFullscreenVAO = 0; GLuint mFullscreenVAO = 0;
@@ -105,5 +96,6 @@ private:
int mViewWidth = 0; int mViewWidth = 0;
int mViewHeight = 0; int mViewHeight = 0;
std::vector<LayerProgram> mLayerPrograms; std::vector<LayerProgram> mLayerPrograms;
RenderTargetPool mRenderTargets;
TemporalHistoryBuffers mTemporalHistory; TemporalHistoryBuffers mTemporalHistory;
}; };

View File

@@ -0,0 +1,132 @@
#include "RenderTargetPool.h"
#include <cstddef>
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)];
}

View File

@@ -0,0 +1,63 @@
#pragma once
#include "GLExtensions.h"
#include <array>
#include <string>
#include <vector>
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);
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<std::size_t>(id); }
std::array<RenderTarget, static_cast<std::size_t>(RenderTargetId::Count)> mTargets;
std::vector<RenderTarget> mTemporaryTargets;
};