Files
video-shader-toys/apps/LoopThroughWithOpenGLCompositing/gl/OpenGLRenderPass.cpp
Aiden 8ec87685b8
Some checks failed
CI / Native Windows Build And Tests (push) Has been cancelled
CI / React UI Build (push) Has been cancelled
CI / Windows Release Package (push) Has been cancelled
Shader clean up
2026-05-06 10:26:38 +10:00

173 lines
6.7 KiB
C++

#include "OpenGLRenderPass.h"
#include "GlRenderConstants.h"
#include "VideoFrameTransfer.h"
OpenGLRenderPass::OpenGLRenderPass(OpenGLRenderer& renderer) :
mRenderer(renderer)
{
}
void OpenGLRenderPass::Render(
bool hasInputSource,
const std::vector<RuntimeRenderState>& layerStates,
unsigned inputFrameWidth,
unsigned inputFrameHeight,
unsigned historyCap,
const TextBindingUpdater& updateTextBinding,
const GlobalParamsUpdater& updateGlobalParams)
{
if (hasInputSource && mRenderer.mFastTransferExtensionAvailable)
{
// Signal that we're about to draw using mCaptureTexture onto mFBOTexture.
VideoFrameTransfer::beginTextureInUse(VideoFrameTransfer::CPUtoGPU);
}
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
if (hasInputSource)
{
RenderDecodePass(inputFrameWidth, inputFrameHeight);
}
else
{
glBindFramebuffer(GL_FRAMEBUFFER, mRenderer.mDecodeFrameBuf);
glViewport(0, 0, inputFrameWidth, inputFrameHeight);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
}
if (layerStates.empty() || mRenderer.mLayerPrograms.empty())
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, mRenderer.mDecodeFrameBuf);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mRenderer.mIdFrameBuf);
glBlitFramebuffer(0, 0, inputFrameWidth, inputFrameHeight, 0, 0, inputFrameWidth, inputFrameHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glBindFramebuffer(GL_FRAMEBUFFER, mRenderer.mIdFrameBuf);
}
else
{
GLuint sourceTexture = mRenderer.mDecodedTexture;
GLuint sourceFrameBuffer = mRenderer.mDecodeFrameBuf;
for (std::size_t index = 0; index < layerStates.size() && index < mRenderer.mLayerPrograms.size(); ++index)
{
const std::size_t remaining = layerStates.size() - index;
const bool writeToMain = (remaining % 2) == 1;
RenderShaderProgram(
sourceTexture,
writeToMain ? mRenderer.mIdFrameBuf : mRenderer.mLayerTempFrameBuf,
mRenderer.mLayerPrograms[index],
layerStates[index],
inputFrameWidth,
inputFrameHeight,
historyCap,
updateTextBinding,
updateGlobalParams);
if (layerStates[index].temporalHistorySource == TemporalHistorySource::PreLayerInput)
mRenderer.mTemporalHistory.PushPreLayerFramebuffer(layerStates[index].layerId, sourceFrameBuffer, inputFrameWidth, inputFrameHeight);
sourceTexture = writeToMain ? mRenderer.mFBOTexture : mRenderer.mLayerTempTexture;
sourceFrameBuffer = writeToMain ? mRenderer.mIdFrameBuf : mRenderer.mLayerTempFrameBuf;
}
}
mRenderer.mTemporalHistory.PushSourceFramebuffer(mRenderer.mDecodeFrameBuf, inputFrameWidth, inputFrameHeight);
if (hasInputSource && mRenderer.mFastTransferExtensionAvailable)
VideoFrameTransfer::endTextureInUse(VideoFrameTransfer::CPUtoGPU);
}
void OpenGLRenderPass::RenderDecodePass(unsigned inputFrameWidth, unsigned inputFrameHeight)
{
glBindFramebuffer(GL_FRAMEBUFFER, mRenderer.mDecodeFrameBuf);
glViewport(0, 0, inputFrameWidth, inputFrameHeight);
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0 + kPackedVideoTextureUnit);
glBindTexture(GL_TEXTURE_2D, mRenderer.mCaptureTexture);
glBindVertexArray(mRenderer.mFullscreenVAO);
glUseProgram(mRenderer.mDecodeProgram);
const GLint packedResolutionLocation = glGetUniformLocation(mRenderer.mDecodeProgram, "uPackedVideoResolution");
const GLint decodedResolutionLocation = glGetUniformLocation(mRenderer.mDecodeProgram, "uDecodedVideoResolution");
if (packedResolutionLocation >= 0)
glUniform2f(packedResolutionLocation, static_cast<float>(inputFrameWidth / 2), static_cast<float>(inputFrameHeight));
if (decodedResolutionLocation >= 0)
glUniform2f(decodedResolutionLocation, static_cast<float>(inputFrameWidth), static_cast<float>(inputFrameHeight));
glDrawArrays(GL_TRIANGLES, 0, 3);
glUseProgram(0);
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
}
void OpenGLRenderPass::RenderShaderProgram(
GLuint sourceTexture,
GLuint destinationFrameBuffer,
LayerProgram& layerProgram,
const RuntimeRenderState& state,
unsigned inputFrameWidth,
unsigned inputFrameHeight,
unsigned historyCap,
const TextBindingUpdater& updateTextBinding,
const GlobalParamsUpdater& updateGlobalParams)
{
for (LayerProgram::TextBinding& textBinding : layerProgram.textBindings)
{
std::string textError;
if (!updateTextBinding(state, textBinding, textError))
OutputDebugStringA((textError + "\n").c_str());
}
glBindFramebuffer(GL_FRAMEBUFFER, destinationFrameBuffer);
glViewport(0, 0, inputFrameWidth, inputFrameHeight);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0 + kDecodedVideoTextureUnit);
glBindTexture(GL_TEXTURE_2D, sourceTexture);
mRenderer.mTemporalHistory.BindSamplers(state, sourceTexture, historyCap);
BindLayerTextureAssets(layerProgram);
glBindVertexArray(mRenderer.mFullscreenVAO);
glUseProgram(layerProgram.program);
updateGlobalParams(state, mRenderer.mTemporalHistory.SourceAvailableCount(), mRenderer.mTemporalHistory.AvailableCountForLayer(state.layerId));
glDrawArrays(GL_TRIANGLES, 0, 3);
glUseProgram(0);
glBindVertexArray(0);
UnbindLayerTextureAssets(layerProgram, historyCap);
}
void OpenGLRenderPass::BindLayerTextureAssets(const LayerProgram& layerProgram)
{
const GLuint shaderTextureBase = layerProgram.shaderTextureBase != 0 ? layerProgram.shaderTextureBase : kSourceHistoryTextureUnitBase;
for (std::size_t index = 0; index < layerProgram.textureBindings.size(); ++index)
{
glActiveTexture(GL_TEXTURE0 + shaderTextureBase + static_cast<GLuint>(index));
glBindTexture(GL_TEXTURE_2D, layerProgram.textureBindings[index].texture);
}
const GLuint textTextureBase = shaderTextureBase + static_cast<GLuint>(layerProgram.textureBindings.size());
for (std::size_t index = 0; index < layerProgram.textBindings.size(); ++index)
{
glActiveTexture(GL_TEXTURE0 + textTextureBase + static_cast<GLuint>(index));
glBindTexture(GL_TEXTURE_2D, layerProgram.textBindings[index].texture);
}
glActiveTexture(GL_TEXTURE0);
}
void OpenGLRenderPass::UnbindLayerTextureAssets(const LayerProgram& layerProgram, unsigned historyCap)
{
for (unsigned index = 0; index < historyCap; ++index)
{
glActiveTexture(GL_TEXTURE0 + kSourceHistoryTextureUnitBase + index);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0 + kSourceHistoryTextureUnitBase + historyCap + index);
glBindTexture(GL_TEXTURE_2D, 0);
}
const GLuint shaderTextureBase = layerProgram.shaderTextureBase != 0 ? layerProgram.shaderTextureBase : kSourceHistoryTextureUnitBase;
for (std::size_t index = 0; index < layerProgram.textureBindings.size() + layerProgram.textBindings.size(); ++index)
{
glActiveTexture(GL_TEXTURE0 + shaderTextureBase + static_cast<GLuint>(index));
glBindTexture(GL_TEXTURE_2D, 0);
}
glActiveTexture(GL_TEXTURE0 + kDecodedVideoTextureUnit);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
}