Texture binding
This commit is contained in:
@@ -173,52 +173,16 @@ void OpenGLRenderPass::RenderShaderProgram(
|
||||
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.TemporalHistory().BindSamplers(state, sourceTexture, historyCap);
|
||||
BindLayerTextureAssets(layerProgram);
|
||||
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.BindRuntimeTexturePlan(texturePlan);
|
||||
glBindVertexArray(mRenderer.FullscreenVertexArray());
|
||||
glUseProgram(layerProgram.program);
|
||||
updateGlobalParams(state, mRenderer.TemporalHistory().SourceAvailableCount(), mRenderer.TemporalHistory().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);
|
||||
mTextureBindings.UnbindRuntimeTexturePlan(texturePlan);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "OpenGLRenderer.h"
|
||||
#include "RenderPassDescriptor.h"
|
||||
#include "ShaderTextureBindings.h"
|
||||
#include "ShaderTypes.h"
|
||||
#include "VideoIOFormat.h"
|
||||
|
||||
@@ -51,8 +52,7 @@ private:
|
||||
unsigned historyCap,
|
||||
const TextBindingUpdater& updateTextBinding,
|
||||
const GlobalParamsUpdater& updateGlobalParams);
|
||||
void BindLayerTextureAssets(const LayerProgram& layerProgram);
|
||||
void UnbindLayerTextureAssets(const LayerProgram& layerProgram, unsigned historyCap);
|
||||
|
||||
OpenGLRenderer& mRenderer;
|
||||
ShaderTextureBindings mTextureBindings;
|
||||
};
|
||||
|
||||
@@ -212,6 +212,29 @@ void TemporalHistoryBuffers::BindSamplers(const RuntimeRenderState& state, GLuin
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
std::vector<GLuint> TemporalHistoryBuffers::ResolveSourceHistoryTextures(GLuint fallbackTexture, unsigned historyCap) const
|
||||
{
|
||||
std::vector<GLuint> textures;
|
||||
textures.reserve(historyCap);
|
||||
for (unsigned index = 0; index < historyCap; ++index)
|
||||
textures.push_back(ResolveTexture(sourceHistoryRing, fallbackTexture, index));
|
||||
return textures;
|
||||
}
|
||||
|
||||
std::vector<GLuint> TemporalHistoryBuffers::ResolveTemporalHistoryTextures(const RuntimeRenderState& state, GLuint fallbackTexture, unsigned historyCap) const
|
||||
{
|
||||
const Ring* temporalRing = nullptr;
|
||||
auto it = preLayerHistoryByLayerId.find(state.layerId);
|
||||
if (it != preLayerHistoryByLayerId.end())
|
||||
temporalRing = &it->second;
|
||||
|
||||
std::vector<GLuint> textures;
|
||||
textures.reserve(historyCap);
|
||||
for (unsigned index = 0; index < historyCap; ++index)
|
||||
textures.push_back(temporalRing ? ResolveTexture(*temporalRing, fallbackTexture, index) : fallbackTexture);
|
||||
return textures;
|
||||
}
|
||||
|
||||
GLuint TemporalHistoryBuffers::ResolveTexture(const Ring& ring, GLuint fallbackTexture, std::size_t framesAgo) const
|
||||
{
|
||||
if (ring.filledCount == 0 || ring.slots.empty())
|
||||
|
||||
@@ -40,6 +40,8 @@ public:
|
||||
void PushSourceFramebuffer(GLuint sourceFramebuffer, unsigned frameWidth, unsigned frameHeight);
|
||||
void PushPreLayerFramebuffer(const std::string& layerId, GLuint sourceFramebuffer, unsigned frameWidth, unsigned frameHeight);
|
||||
void BindSamplers(const RuntimeRenderState& state, GLuint currentSourceTexture, unsigned historyCap);
|
||||
std::vector<GLuint> ResolveSourceHistoryTextures(GLuint fallbackTexture, unsigned historyCap) const;
|
||||
std::vector<GLuint> ResolveTemporalHistoryTextures(const RuntimeRenderState& state, GLuint fallbackTexture, unsigned historyCap) const;
|
||||
GLuint ResolveTexture(const Ring& ring, GLuint fallbackTexture, std::size_t framesAgo) const;
|
||||
unsigned SourceAvailableCount() const;
|
||||
unsigned AvailableCountForLayer(const std::string& layerId) const;
|
||||
|
||||
@@ -101,51 +101,24 @@ bool ShaderProgramCompiler::CompilePreparedLayerProgram(const RuntimeRenderState
|
||||
std::vector<LayerProgram::TextBinding> textBindings;
|
||||
mTextureBindings.CreateTextBindings(state, textBindings);
|
||||
|
||||
layerProgram.layerId = state.layerId;
|
||||
layerProgram.shaderId = state.shaderId;
|
||||
layerProgram.shaderTextureBase = mTextureBindings.ResolveShaderTextureBase(state, mRuntimeHost.GetMaxTemporalHistoryFrames());
|
||||
layerProgram.textureBindings.swap(textureBindings);
|
||||
layerProgram.textBindings.swap(textBindings);
|
||||
|
||||
const GLuint globalParamsIndex = glGetUniformBlockIndex(newProgram.get(), "GlobalParams");
|
||||
if (globalParamsIndex != GL_INVALID_INDEX)
|
||||
glUniformBlockBinding(newProgram.get(), globalParamsIndex, kGlobalParamsBindingPoint);
|
||||
|
||||
const unsigned historyCap = mRuntimeHost.GetMaxTemporalHistoryFrames();
|
||||
const GLuint shaderTextureBase = state.isTemporal ? kSourceHistoryTextureUnitBase + historyCap + historyCap : kSourceHistoryTextureUnitBase;
|
||||
glUseProgram(newProgram.get());
|
||||
const GLint videoInputLocation = glGetUniformLocation(newProgram.get(), "gVideoInput");
|
||||
if (videoInputLocation >= 0)
|
||||
glUniform1i(videoInputLocation, static_cast<GLint>(kDecodedVideoTextureUnit));
|
||||
for (unsigned index = 0; index < historyCap; ++index)
|
||||
{
|
||||
const std::string sourceSamplerName = "gSourceHistory" + std::to_string(index);
|
||||
const GLint sourceSamplerLocation = glGetUniformLocation(newProgram.get(), sourceSamplerName.c_str());
|
||||
if (sourceSamplerLocation >= 0)
|
||||
glUniform1i(sourceSamplerLocation, static_cast<GLint>(kSourceHistoryTextureUnitBase + index));
|
||||
|
||||
const std::string temporalSamplerName = "gTemporalHistory" + std::to_string(index);
|
||||
const GLint temporalSamplerLocation = glGetUniformLocation(newProgram.get(), temporalSamplerName.c_str());
|
||||
if (temporalSamplerLocation >= 0)
|
||||
glUniform1i(temporalSamplerLocation, static_cast<GLint>(kSourceHistoryTextureUnitBase + historyCap + index));
|
||||
}
|
||||
for (std::size_t index = 0; index < textureBindings.size(); ++index)
|
||||
{
|
||||
const GLint textureSamplerLocation = mTextureBindings.FindSamplerUniformLocation(newProgram.get(), textureBindings[index].samplerName);
|
||||
if (textureSamplerLocation >= 0)
|
||||
glUniform1i(textureSamplerLocation, static_cast<GLint>(shaderTextureBase + static_cast<GLuint>(index)));
|
||||
}
|
||||
const GLuint textTextureBase = shaderTextureBase + static_cast<GLuint>(textureBindings.size());
|
||||
for (std::size_t index = 0; index < textBindings.size(); ++index)
|
||||
{
|
||||
const GLint textSamplerLocation = mTextureBindings.FindSamplerUniformLocation(newProgram.get(), textBindings[index].samplerName);
|
||||
if (textSamplerLocation >= 0)
|
||||
glUniform1i(textSamplerLocation, static_cast<GLint>(textTextureBase + static_cast<GLuint>(index)));
|
||||
}
|
||||
mTextureBindings.AssignLayerSamplerUniforms(newProgram.get(), state, layerProgram, historyCap);
|
||||
glUseProgram(0);
|
||||
|
||||
layerProgram.layerId = state.layerId;
|
||||
layerProgram.shaderId = state.shaderId;
|
||||
layerProgram.shaderTextureBase = shaderTextureBase;
|
||||
layerProgram.program = newProgram.release();
|
||||
layerProgram.vertexShader = newVertexShader.release();
|
||||
layerProgram.fragmentShader = newFragmentShader.release();
|
||||
layerProgram.textureBindings.swap(textureBindings);
|
||||
layerProgram.textBindings.swap(textBindings);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -102,3 +102,122 @@ GLint ShaderTextureBindings::FindSamplerUniformLocation(GLuint program, const st
|
||||
return location;
|
||||
return glGetUniformLocation(program, (samplerName + "_0").c_str());
|
||||
}
|
||||
|
||||
GLuint ShaderTextureBindings::ResolveShaderTextureBase(const RuntimeRenderState& state, unsigned historyCap) const
|
||||
{
|
||||
return state.isTemporal ? kSourceHistoryTextureUnitBase + historyCap + historyCap : kSourceHistoryTextureUnitBase;
|
||||
}
|
||||
|
||||
void ShaderTextureBindings::AssignLayerSamplerUniforms(GLuint program, const RuntimeRenderState& state, const LayerProgram& layerProgram, unsigned historyCap) const
|
||||
{
|
||||
const GLuint shaderTextureBase = ResolveShaderTextureBase(state, historyCap);
|
||||
|
||||
const GLint videoInputLocation = glGetUniformLocation(program, "gVideoInput");
|
||||
if (videoInputLocation >= 0)
|
||||
glUniform1i(videoInputLocation, static_cast<GLint>(kDecodedVideoTextureUnit));
|
||||
|
||||
for (unsigned index = 0; index < historyCap; ++index)
|
||||
{
|
||||
const std::string sourceSamplerName = "gSourceHistory" + std::to_string(index);
|
||||
const GLint sourceSamplerLocation = glGetUniformLocation(program, sourceSamplerName.c_str());
|
||||
if (sourceSamplerLocation >= 0)
|
||||
glUniform1i(sourceSamplerLocation, static_cast<GLint>(kSourceHistoryTextureUnitBase + index));
|
||||
|
||||
const std::string temporalSamplerName = "gTemporalHistory" + std::to_string(index);
|
||||
const GLint temporalSamplerLocation = glGetUniformLocation(program, temporalSamplerName.c_str());
|
||||
if (temporalSamplerLocation >= 0)
|
||||
glUniform1i(temporalSamplerLocation, static_cast<GLint>(kSourceHistoryTextureUnitBase + historyCap + index));
|
||||
}
|
||||
|
||||
for (std::size_t index = 0; index < layerProgram.textureBindings.size(); ++index)
|
||||
{
|
||||
const GLint textureSamplerLocation = FindSamplerUniformLocation(program, layerProgram.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 GLint textSamplerLocation = FindSamplerUniformLocation(program, layerProgram.textBindings[index].samplerName);
|
||||
if (textSamplerLocation >= 0)
|
||||
glUniform1i(textSamplerLocation, static_cast<GLint>(textTextureBase + static_cast<GLuint>(index)));
|
||||
}
|
||||
}
|
||||
|
||||
ShaderTextureBindings::RuntimeTextureBindingPlan ShaderTextureBindings::BuildLayerRuntimeBindingPlan(
|
||||
const LayerProgram& layerProgram,
|
||||
GLuint layerInputTexture,
|
||||
const std::vector<GLuint>& sourceHistoryTextures,
|
||||
const std::vector<GLuint>& temporalHistoryTextures) const
|
||||
{
|
||||
RuntimeTextureBindingPlan plan;
|
||||
plan.bindings.push_back({ "layerInput", "gVideoInput", layerInputTexture, kDecodedVideoTextureUnit });
|
||||
|
||||
for (std::size_t index = 0; index < sourceHistoryTextures.size(); ++index)
|
||||
{
|
||||
plan.bindings.push_back({
|
||||
"sourceHistory",
|
||||
"gSourceHistory" + std::to_string(index),
|
||||
sourceHistoryTextures[index],
|
||||
kSourceHistoryTextureUnitBase + static_cast<GLuint>(index)
|
||||
});
|
||||
}
|
||||
|
||||
const GLuint temporalBase = kSourceHistoryTextureUnitBase + static_cast<GLuint>(sourceHistoryTextures.size());
|
||||
for (std::size_t index = 0; index < temporalHistoryTextures.size(); ++index)
|
||||
{
|
||||
plan.bindings.push_back({
|
||||
"temporalHistory",
|
||||
"gTemporalHistory" + std::to_string(index),
|
||||
temporalHistoryTextures[index],
|
||||
temporalBase + static_cast<GLuint>(index)
|
||||
});
|
||||
}
|
||||
|
||||
const GLuint shaderTextureBase = layerProgram.shaderTextureBase != 0 ? layerProgram.shaderTextureBase : kSourceHistoryTextureUnitBase;
|
||||
for (std::size_t index = 0; index < layerProgram.textureBindings.size(); ++index)
|
||||
{
|
||||
const LayerProgram::TextureBinding& textureBinding = layerProgram.textureBindings[index];
|
||||
plan.bindings.push_back({
|
||||
"shaderTexture",
|
||||
textureBinding.samplerName,
|
||||
textureBinding.texture,
|
||||
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 LayerProgram::TextBinding& textBinding = layerProgram.textBindings[index];
|
||||
plan.bindings.push_back({
|
||||
"textTexture",
|
||||
textBinding.samplerName,
|
||||
textBinding.texture,
|
||||
textTextureBase + static_cast<GLuint>(index)
|
||||
});
|
||||
}
|
||||
|
||||
return plan;
|
||||
}
|
||||
|
||||
void ShaderTextureBindings::BindRuntimeTexturePlan(const RuntimeTextureBindingPlan& plan) const
|
||||
{
|
||||
for (const RuntimeTextureBinding& binding : plan.bindings)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + binding.textureUnit);
|
||||
glBindTexture(GL_TEXTURE_2D, binding.texture);
|
||||
}
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
void ShaderTextureBindings::UnbindRuntimeTexturePlan(const RuntimeTextureBindingPlan& plan) const
|
||||
{
|
||||
for (const RuntimeTextureBinding& binding : plan.bindings)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + binding.textureUnit);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
@@ -11,8 +11,30 @@ class ShaderTextureBindings
|
||||
public:
|
||||
using LayerProgram = OpenGLRenderer::LayerProgram;
|
||||
|
||||
struct RuntimeTextureBinding
|
||||
{
|
||||
std::string semanticName;
|
||||
std::string samplerName;
|
||||
GLuint texture = 0;
|
||||
GLuint textureUnit = 0;
|
||||
};
|
||||
|
||||
struct RuntimeTextureBindingPlan
|
||||
{
|
||||
std::vector<RuntimeTextureBinding> bindings;
|
||||
};
|
||||
|
||||
bool LoadTextureAsset(const ShaderTextureAsset& textureAsset, GLuint& textureId, std::string& error);
|
||||
void CreateTextBindings(const RuntimeRenderState& state, std::vector<LayerProgram::TextBinding>& textBindings);
|
||||
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;
|
||||
RuntimeTextureBindingPlan BuildLayerRuntimeBindingPlan(
|
||||
const LayerProgram& layerProgram,
|
||||
GLuint layerInputTexture,
|
||||
const std::vector<GLuint>& sourceHistoryTextures,
|
||||
const std::vector<GLuint>& temporalHistoryTextures) const;
|
||||
void BindRuntimeTexturePlan(const RuntimeTextureBindingPlan& plan) const;
|
||||
void UnbindRuntimeTexturePlan(const RuntimeTextureBindingPlan& plan) const;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user