Update shader
This commit is contained in:
@@ -6,6 +6,10 @@
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
#ifndef GL_FRAMEBUFFER_BINDING
|
||||
#define GL_FRAMEBUFFER_BINDING 0x8CA6
|
||||
#endif
|
||||
|
||||
RuntimeRenderScene::~RuntimeRenderScene()
|
||||
{
|
||||
ShutdownGl();
|
||||
@@ -90,12 +94,50 @@ void RuntimeRenderScene::RenderFrame(uint64_t frameIndex, unsigned width, unsign
|
||||
{
|
||||
ConsumePreparedPrograms();
|
||||
|
||||
std::vector<LayerProgram*> readyLayers;
|
||||
for (const std::string& layerId : mLayerOrder)
|
||||
{
|
||||
LayerProgram* layer = FindLayer(layerId);
|
||||
if (!layer || !layer->renderer || !layer->renderer->HasProgram())
|
||||
continue;
|
||||
layer->renderer->RenderFrame(frameIndex, width, height);
|
||||
readyLayers.push_back(layer);
|
||||
}
|
||||
|
||||
if (readyLayers.empty())
|
||||
return;
|
||||
|
||||
GLint outputFramebuffer = 0;
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &outputFramebuffer);
|
||||
|
||||
if (readyLayers.size() == 1)
|
||||
{
|
||||
readyLayers.front()->renderer->RenderFrame(frameIndex, width, height);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EnsureLayerTargets(width, height))
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, static_cast<GLuint>(outputFramebuffer));
|
||||
readyLayers.back()->renderer->RenderFrame(frameIndex, width, height);
|
||||
return;
|
||||
}
|
||||
|
||||
GLuint layerInputTexture = 0;
|
||||
std::size_t nextTargetIndex = 0;
|
||||
for (std::size_t layerIndex = 0; layerIndex < readyLayers.size(); ++layerIndex)
|
||||
{
|
||||
const bool isFinalLayer = layerIndex == readyLayers.size() - 1;
|
||||
if (isFinalLayer)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, static_cast<GLuint>(outputFramebuffer));
|
||||
readyLayers[layerIndex]->renderer->RenderFrame(frameIndex, width, height, layerInputTexture, layerInputTexture);
|
||||
continue;
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mLayerFramebuffers[nextTargetIndex]);
|
||||
readyLayers[layerIndex]->renderer->RenderFrame(frameIndex, width, height, layerInputTexture, layerInputTexture);
|
||||
layerInputTexture = mLayerTextures[nextTargetIndex];
|
||||
nextTargetIndex = 1 - nextTargetIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,6 +151,7 @@ void RuntimeRenderScene::ShutdownGl()
|
||||
}
|
||||
mLayers.clear();
|
||||
mLayerOrder.clear();
|
||||
DestroyLayerTargets();
|
||||
}
|
||||
|
||||
void RuntimeRenderScene::ConsumePreparedPrograms()
|
||||
@@ -146,6 +189,68 @@ void RuntimeRenderScene::ConsumePreparedPrograms()
|
||||
}
|
||||
}
|
||||
|
||||
bool RuntimeRenderScene::EnsureLayerTargets(unsigned width, unsigned height)
|
||||
{
|
||||
if (width == 0 || height == 0)
|
||||
return false;
|
||||
if (mLayerFramebuffers[0] != 0 && mLayerFramebuffers[1] != 0 && mLayerTextures[0] != 0 && mLayerTextures[1] != 0
|
||||
&& mLayerTargetWidth == width && mLayerTargetHeight == height)
|
||||
return true;
|
||||
|
||||
DestroyLayerTargets();
|
||||
mLayerTargetWidth = width;
|
||||
mLayerTargetHeight = height;
|
||||
|
||||
glGenFramebuffers(2, mLayerFramebuffers);
|
||||
glGenTextures(2, mLayerTextures);
|
||||
for (int index = 0; index < 2; ++index)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, mLayerTextures[index]);
|
||||
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_RGBA8,
|
||||
static_cast<GLsizei>(width),
|
||||
static_cast<GLsizei>(height),
|
||||
0,
|
||||
GL_BGRA,
|
||||
GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
nullptr);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mLayerFramebuffers[index]);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mLayerTextures[index], 0);
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
DestroyLayerTargets();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
void RuntimeRenderScene::DestroyLayerTargets()
|
||||
{
|
||||
if (mLayerFramebuffers[0] != 0 || mLayerFramebuffers[1] != 0)
|
||||
glDeleteFramebuffers(2, mLayerFramebuffers);
|
||||
if (mLayerTextures[0] != 0 || mLayerTextures[1] != 0)
|
||||
glDeleteTextures(2, mLayerTextures);
|
||||
mLayerFramebuffers[0] = 0;
|
||||
mLayerFramebuffers[1] = 0;
|
||||
mLayerTextures[0] = 0;
|
||||
mLayerTextures[1] = 0;
|
||||
mLayerTargetWidth = 0;
|
||||
mLayerTargetHeight = 0;
|
||||
}
|
||||
|
||||
RuntimeRenderScene::LayerProgram* RuntimeRenderScene::FindLayer(const std::string& layerId)
|
||||
{
|
||||
for (LayerProgram& layer : mLayers)
|
||||
|
||||
@@ -36,6 +36,8 @@ private:
|
||||
};
|
||||
|
||||
void ConsumePreparedPrograms();
|
||||
bool EnsureLayerTargets(unsigned width, unsigned height);
|
||||
void DestroyLayerTargets();
|
||||
LayerProgram* FindLayer(const std::string& layerId);
|
||||
const LayerProgram* FindLayer(const std::string& layerId) const;
|
||||
static std::string Fingerprint(const RuntimeShaderArtifact& artifact);
|
||||
@@ -43,4 +45,8 @@ private:
|
||||
RuntimeShaderPrepareWorker mPrepareWorker;
|
||||
std::vector<LayerProgram> mLayers;
|
||||
std::vector<std::string> mLayerOrder;
|
||||
GLuint mLayerFramebuffers[2] = {};
|
||||
GLuint mLayerTextures[2] = {};
|
||||
unsigned mLayerTargetWidth = 0;
|
||||
unsigned mLayerTargetHeight = 0;
|
||||
};
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
namespace
|
||||
{
|
||||
constexpr GLuint kGlobalParamsBindingPoint = 0;
|
||||
constexpr GLuint kSourceTextureUnit = 0;
|
||||
constexpr GLuint kVideoInputTextureUnit = 0;
|
||||
constexpr GLuint kLayerInputTextureUnit = 1;
|
||||
|
||||
const char* kVertexShaderSource = R"GLSL(
|
||||
#version 430 core
|
||||
@@ -127,7 +128,7 @@ bool RuntimeShaderRenderer::BuildPreparedProgram(
|
||||
return true;
|
||||
}
|
||||
|
||||
void RuntimeShaderRenderer::RenderFrame(uint64_t frameIndex, unsigned width, unsigned height)
|
||||
void RuntimeShaderRenderer::RenderFrame(uint64_t frameIndex, unsigned width, unsigned height, GLuint sourceTexture, GLuint layerInputTexture)
|
||||
{
|
||||
if (mProgram == 0)
|
||||
return;
|
||||
@@ -137,7 +138,7 @@ void RuntimeShaderRenderer::RenderFrame(uint64_t frameIndex, unsigned width, uns
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
UpdateGlobalParams(frameIndex, width, height);
|
||||
BindRuntimeTextures();
|
||||
BindRuntimeTextures(sourceTexture, layerInputTexture);
|
||||
glBindVertexArray(mVertexArray);
|
||||
glUseProgram(mProgram);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
@@ -236,16 +237,16 @@ void RuntimeShaderRenderer::AssignSamplerUniforms(GLuint program)
|
||||
glUseProgram(program);
|
||||
const GLint videoInputLocation = glGetUniformLocation(program, "gVideoInput");
|
||||
if (videoInputLocation >= 0)
|
||||
glUniform1i(videoInputLocation, static_cast<GLint>(kSourceTextureUnit));
|
||||
glUniform1i(videoInputLocation, static_cast<GLint>(kVideoInputTextureUnit));
|
||||
const GLint videoInputArrayLocation = glGetUniformLocation(program, "gVideoInput_0");
|
||||
if (videoInputArrayLocation >= 0)
|
||||
glUniform1i(videoInputArrayLocation, static_cast<GLint>(kSourceTextureUnit));
|
||||
glUniform1i(videoInputArrayLocation, static_cast<GLint>(kVideoInputTextureUnit));
|
||||
const GLint layerInputLocation = glGetUniformLocation(program, "gLayerInput");
|
||||
if (layerInputLocation >= 0)
|
||||
glUniform1i(layerInputLocation, static_cast<GLint>(kSourceTextureUnit));
|
||||
glUniform1i(layerInputLocation, static_cast<GLint>(kLayerInputTextureUnit));
|
||||
const GLint layerInputArrayLocation = glGetUniformLocation(program, "gLayerInput_0");
|
||||
if (layerInputArrayLocation >= 0)
|
||||
glUniform1i(layerInputArrayLocation, static_cast<GLint>(kSourceTextureUnit));
|
||||
glUniform1i(layerInputArrayLocation, static_cast<GLint>(kLayerInputTextureUnit));
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
@@ -268,10 +269,14 @@ void RuntimeShaderRenderer::UpdateGlobalParams(uint64_t frameIndex, unsigned wid
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
}
|
||||
|
||||
void RuntimeShaderRenderer::BindRuntimeTextures()
|
||||
void RuntimeShaderRenderer::BindRuntimeTextures(GLuint sourceTexture, GLuint layerInputTexture)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + kSourceTextureUnit);
|
||||
glBindTexture(GL_TEXTURE_2D, mFallbackSourceTexture);
|
||||
const GLuint resolvedSourceTexture = sourceTexture != 0 ? sourceTexture : mFallbackSourceTexture;
|
||||
const GLuint resolvedLayerInputTexture = layerInputTexture != 0 ? layerInputTexture : resolvedSourceTexture;
|
||||
glActiveTexture(GL_TEXTURE0 + kVideoInputTextureUnit);
|
||||
glBindTexture(GL_TEXTURE_2D, resolvedSourceTexture);
|
||||
glActiveTexture(GL_TEXTURE0 + kLayerInputTextureUnit);
|
||||
glBindTexture(GL_TEXTURE_2D, resolvedLayerInputTexture);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ public:
|
||||
bool CommitShaderArtifact(const RuntimeShaderArtifact& artifact, std::string& error);
|
||||
bool CommitPreparedProgram(RuntimePreparedShaderProgram& preparedProgram, std::string& error);
|
||||
bool HasProgram() const { return mProgram != 0; }
|
||||
void RenderFrame(uint64_t frameIndex, unsigned width, unsigned height);
|
||||
void RenderFrame(uint64_t frameIndex, unsigned width, unsigned height, GLuint sourceTexture = 0, GLuint layerInputTexture = 0);
|
||||
void ShutdownGl();
|
||||
|
||||
static bool BuildPreparedProgram(
|
||||
@@ -35,7 +35,7 @@ private:
|
||||
static bool BuildProgram(const std::string& fragmentShaderSource, GLuint& program, GLuint& vertexShader, GLuint& fragmentShader, std::string& error);
|
||||
static void AssignSamplerUniforms(GLuint program);
|
||||
void UpdateGlobalParams(uint64_t frameIndex, unsigned width, unsigned height);
|
||||
void BindRuntimeTextures();
|
||||
void BindRuntimeTextures(GLuint sourceTexture, GLuint layerInputTexture);
|
||||
void DestroyProgram();
|
||||
void DestroyStaticGlResources();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user