Layer program split
All checks were successful
CI / React UI Build (push) Successful in 11s
CI / Native Windows Build And Tests (push) Successful in 2m14s
CI / Windows Release Package (push) Successful in 2m26s

This commit is contained in:
2026-05-08 17:10:29 +10:00
parent f458eb0130
commit 87cb55b80b
9 changed files with 91 additions and 68 deletions

View File

@@ -101,6 +101,8 @@ std::vector<RenderPassDescriptor> 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<RenderPassDescriptor> 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<GLuint> sourceHistoryTextures = mRenderer.TemporalHistory().ResolveSourceHistoryTextures(sourceTexture, state.isTemporal ? historyCap : 0);
const std::vector<GLuint> 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);

View File

@@ -14,6 +14,7 @@ class OpenGLRenderPass
{
public:
using LayerProgram = OpenGLRenderer::LayerProgram;
using PassProgram = OpenGLRenderer::LayerProgram::PassProgram;
using TextBindingUpdater = std::function<bool(const RuntimeRenderState&, LayerProgram::TextBinding&, std::string&)>;
using GlobalParamsUpdater = std::function<bool(const RuntimeRenderState&, unsigned, unsigned)>;
@@ -45,7 +46,7 @@ private:
void RenderShaderProgram(
GLuint sourceTexture,
GLuint destinationFrameBuffer,
LayerProgram& layerProgram,
PassProgram& passProgram,
const RuntimeRenderState& state,
unsigned inputFrameWidth,
unsigned inputFrameHeight,

View File

@@ -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;
};

View File

@@ -155,7 +155,9 @@ void OpenGLRenderer::DestroyResources()
void OpenGLRenderer::DestroySingleLayerProgram(LayerProgram& layerProgram)
{
for (LayerProgram::TextureBinding& binding : layerProgram.textureBindings)
for (LayerProgram::PassProgram& passProgram : layerProgram.passes)
{
for (LayerProgram::TextureBinding& binding : passProgram.textureBindings)
{
if (binding.texture != 0)
{
@@ -163,9 +165,9 @@ void OpenGLRenderer::DestroySingleLayerProgram(LayerProgram& layerProgram)
binding.texture = 0;
}
}
layerProgram.textureBindings.clear();
passProgram.textureBindings.clear();
for (LayerProgram::TextBinding& binding : layerProgram.textBindings)
for (LayerProgram::TextBinding& binding : passProgram.textBindings)
{
if (binding.texture != 0)
{
@@ -173,25 +175,27 @@ void OpenGLRenderer::DestroySingleLayerProgram(LayerProgram& layerProgram)
binding.texture = 0;
}
}
layerProgram.textBindings.clear();
passProgram.textBindings.clear();
if (layerProgram.program != 0)
if (passProgram.program != 0)
{
glDeleteProgram(layerProgram.program);
layerProgram.program = 0;
glDeleteProgram(passProgram.program);
passProgram.program = 0;
}
if (layerProgram.fragmentShader != 0)
if (passProgram.fragmentShader != 0)
{
glDeleteShader(layerProgram.fragmentShader);
layerProgram.fragmentShader = 0;
glDeleteShader(passProgram.fragmentShader);
passProgram.fragmentShader = 0;
}
if (layerProgram.vertexShader != 0)
if (passProgram.vertexShader != 0)
{
glDeleteShader(layerProgram.vertexShader);
layerProgram.vertexShader = 0;
glDeleteShader(passProgram.vertexShader);
passProgram.vertexShader = 0;
}
}
layerProgram.passes.clear();
}
void OpenGLRenderer::DestroyLayerPrograms()

View File

@@ -37,6 +37,10 @@ public:
std::string layerId;
std::string shaderId;
struct PassProgram
{
std::string passId;
GLuint shaderTextureBase = 0;
GLuint program = 0;
GLuint vertexShader = 0;
@@ -45,6 +49,9 @@ public:
std::vector<TextBinding> textBindings;
};
std::vector<PassProgram> passes;
};
GLuint CaptureTexture() const { return mCaptureTexture; }
GLuint DecodedTexture() const { return mRenderTargets.Texture(RenderTargetId::Decoded); }
GLuint LayerTempTexture() const { return mRenderTargets.Texture(RenderTargetId::LayerTemp); }

View File

@@ -5,6 +5,7 @@
#include "GlShaderSources.h"
#include <cstring>
#include <utility>
#include <vector>
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;
}

View File

@@ -10,6 +10,7 @@ class ShaderProgramCompiler
{
public:
using LayerProgram = OpenGLRenderer::LayerProgram;
using PassProgram = OpenGLRenderer::LayerProgram::PassProgram;
ShaderProgramCompiler(OpenGLRenderer& renderer, RuntimeHost& runtimeHost, ShaderTextureBindings& textureBindings);

View File

@@ -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<GLint>(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<GLint>(shaderTextureBase + static_cast<GLuint>(index)));
}
const GLuint textTextureBase = shaderTextureBase + static_cast<GLuint>(layerProgram.textureBindings.size());
for (std::size_t index = 0; index < layerProgram.textBindings.size(); ++index)
const GLuint textTextureBase = shaderTextureBase + static_cast<GLuint>(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<GLint>(textTextureBase + static_cast<GLuint>(index)));
}
}
ShaderTextureBindings::RuntimeTextureBindingPlan ShaderTextureBindings::BuildLayerRuntimeBindingPlan(
const LayerProgram& layerProgram,
const PassProgram& passProgram,
GLuint layerInputTexture,
const std::vector<GLuint>& sourceHistoryTextures,
const std::vector<GLuint>& 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<GLuint>(layerProgram.textureBindings.size());
for (std::size_t index = 0; index < layerProgram.textBindings.size(); ++index)
const GLuint textTextureBase = shaderTextureBase + static_cast<GLuint>(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,

View File

@@ -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<GLuint>& sourceHistoryTextures,
const std::vector<GLuint>& temporalHistoryTextures) const;