INput
This commit is contained in:
83
apps/RenderCadenceCompositor/render/InputFrameTexture.cpp
Normal file
83
apps/RenderCadenceCompositor/render/InputFrameTexture.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
#include "InputFrameTexture.h"
|
||||
|
||||
InputFrameTexture::~InputFrameTexture()
|
||||
{
|
||||
ShutdownGl();
|
||||
}
|
||||
|
||||
GLuint InputFrameTexture::PollAndUpload(InputFrameMailbox* mailbox)
|
||||
{
|
||||
if (mailbox == nullptr)
|
||||
return mTexture;
|
||||
|
||||
InputFrame frame;
|
||||
if (!mailbox->TryAcquireLatest(frame))
|
||||
{
|
||||
++mUploadMisses;
|
||||
return mTexture;
|
||||
}
|
||||
|
||||
if (frame.bytes != nullptr && frame.pixelFormat == VideoIOPixelFormat::Bgra8 && EnsureTexture(frame))
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, mTexture);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, frame.rowBytes > 0 ? static_cast<GLint>(frame.rowBytes / 4) : 0);
|
||||
glTexSubImage2D(
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
static_cast<GLsizei>(frame.width),
|
||||
static_cast<GLsizei>(frame.height),
|
||||
GL_BGRA,
|
||||
GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
frame.bytes);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
++mUploadedFrames;
|
||||
}
|
||||
|
||||
mailbox->Release(frame);
|
||||
return mTexture;
|
||||
}
|
||||
|
||||
void InputFrameTexture::ShutdownGl()
|
||||
{
|
||||
if (mTexture != 0)
|
||||
glDeleteTextures(1, &mTexture);
|
||||
mTexture = 0;
|
||||
mWidth = 0;
|
||||
mHeight = 0;
|
||||
}
|
||||
|
||||
bool InputFrameTexture::EnsureTexture(const InputFrame& frame)
|
||||
{
|
||||
if (frame.width == 0 || frame.height == 0)
|
||||
return false;
|
||||
|
||||
if (mTexture != 0 && mWidth == frame.width && mHeight == frame.height)
|
||||
return true;
|
||||
|
||||
ShutdownGl();
|
||||
glGenTextures(1, &mTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, mTexture);
|
||||
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>(frame.width),
|
||||
static_cast<GLsizei>(frame.height),
|
||||
0,
|
||||
GL_BGRA,
|
||||
GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
nullptr);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
mWidth = frame.width;
|
||||
mHeight = frame.height;
|
||||
return mTexture != 0;
|
||||
}
|
||||
30
apps/RenderCadenceCompositor/render/InputFrameTexture.h
Normal file
30
apps/RenderCadenceCompositor/render/InputFrameTexture.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "../frames/InputFrameMailbox.h"
|
||||
#include "GLExtensions.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class InputFrameTexture
|
||||
{
|
||||
public:
|
||||
InputFrameTexture() = default;
|
||||
InputFrameTexture(const InputFrameTexture&) = delete;
|
||||
InputFrameTexture& operator=(const InputFrameTexture&) = delete;
|
||||
~InputFrameTexture();
|
||||
|
||||
GLuint PollAndUpload(InputFrameMailbox* mailbox);
|
||||
GLuint Texture() const { return mTexture; }
|
||||
uint64_t UploadedFrames() const { return mUploadedFrames; }
|
||||
uint64_t UploadMisses() const { return mUploadMisses; }
|
||||
void ShutdownGl();
|
||||
|
||||
private:
|
||||
bool EnsureTexture(const InputFrame& frame);
|
||||
|
||||
GLuint mTexture = 0;
|
||||
unsigned mWidth = 0;
|
||||
unsigned mHeight = 0;
|
||||
uint64_t mUploadedFrames = 0;
|
||||
uint64_t mUploadMisses = 0;
|
||||
};
|
||||
@@ -1,9 +1,11 @@
|
||||
#include "RenderThread.h"
|
||||
|
||||
#include "../frames/InputFrameMailbox.h"
|
||||
#include "../frames/SystemFrameExchange.h"
|
||||
#include "../frames/SystemFrameTypes.h"
|
||||
#include "../logging/Logger.h"
|
||||
#include "../platform/HiddenGlWindow.h"
|
||||
#include "InputFrameTexture.h"
|
||||
#include "readback/Bgra8ReadbackPipeline.h"
|
||||
#include "GLExtensions.h"
|
||||
#include "runtime/RuntimeRenderScene.h"
|
||||
@@ -20,6 +22,13 @@ RenderThread::RenderThread(SystemFrameExchange& frameExchange, Config config) :
|
||||
{
|
||||
}
|
||||
|
||||
RenderThread::RenderThread(SystemFrameExchange& frameExchange, InputFrameMailbox* inputMailbox, Config config) :
|
||||
mFrameExchange(frameExchange),
|
||||
mInputMailbox(inputMailbox),
|
||||
mConfig(config)
|
||||
{
|
||||
}
|
||||
|
||||
RenderThread::~RenderThread()
|
||||
{
|
||||
Stop();
|
||||
@@ -109,6 +118,7 @@ void RenderThread::ThreadMain()
|
||||
SimpleMotionRenderer renderer;
|
||||
RuntimeRenderScene runtimeRenderScene;
|
||||
Bgra8ReadbackPipeline readback;
|
||||
InputFrameTexture inputTexture;
|
||||
if (!runtimeRenderScene.StartPrepareWorker(std::move(prepareWindow), error))
|
||||
{
|
||||
SignalStartupFailure(error.empty() ? "Runtime shader prepare worker initialization failed." : error);
|
||||
@@ -145,9 +155,10 @@ void RenderThread::ThreadMain()
|
||||
}
|
||||
|
||||
TryCommitReadyRuntimeShader(runtimeRenderScene);
|
||||
if (!readback.RenderAndQueue(frameIndex, [this, &renderer, &runtimeRenderScene](uint64_t index) {
|
||||
const GLuint videoInputTexture = inputTexture.PollAndUpload(mInputMailbox);
|
||||
if (!readback.RenderAndQueue(frameIndex, [this, &renderer, &runtimeRenderScene, videoInputTexture](uint64_t index) {
|
||||
if (runtimeRenderScene.HasLayers())
|
||||
runtimeRenderScene.RenderFrame(index, mConfig.width, mConfig.height);
|
||||
runtimeRenderScene.RenderFrame(index, mConfig.width, mConfig.height, videoInputTexture);
|
||||
else
|
||||
renderer.RenderFrame(index);
|
||||
}))
|
||||
@@ -175,6 +186,7 @@ void RenderThread::ThreadMain()
|
||||
}
|
||||
|
||||
readback.Shutdown();
|
||||
inputTexture.ShutdownGl();
|
||||
runtimeRenderScene.ShutdownGl();
|
||||
renderer.ShutdownGl();
|
||||
window.ClearCurrent();
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <thread>
|
||||
|
||||
class SystemFrameExchange;
|
||||
class InputFrameMailbox;
|
||||
|
||||
class RenderThread
|
||||
{
|
||||
@@ -39,6 +40,7 @@ public:
|
||||
};
|
||||
|
||||
RenderThread(SystemFrameExchange& frameExchange, Config config);
|
||||
RenderThread(SystemFrameExchange& frameExchange, InputFrameMailbox* inputMailbox, Config config);
|
||||
RenderThread(const RenderThread&) = delete;
|
||||
RenderThread& operator=(const RenderThread&) = delete;
|
||||
~RenderThread();
|
||||
@@ -63,6 +65,7 @@ private:
|
||||
bool TryTakePendingRenderLayers(std::vector<RenderCadenceCompositor::RuntimeRenderLayerModel>& layers);
|
||||
|
||||
SystemFrameExchange& mFrameExchange;
|
||||
InputFrameMailbox* mInputMailbox = nullptr;
|
||||
Config mConfig;
|
||||
std::thread mThread;
|
||||
std::atomic<bool> mStopping{ false };
|
||||
|
||||
@@ -120,7 +120,7 @@ bool RuntimeRenderScene::HasLayers()
|
||||
return false;
|
||||
}
|
||||
|
||||
void RuntimeRenderScene::RenderFrame(uint64_t frameIndex, unsigned width, unsigned height)
|
||||
void RuntimeRenderScene::RenderFrame(uint64_t frameIndex, unsigned width, unsigned height, GLuint videoInputTexture)
|
||||
{
|
||||
ConsumePreparedPrograms();
|
||||
|
||||
@@ -148,18 +148,18 @@ void RuntimeRenderScene::RenderFrame(uint64_t frameIndex, unsigned width, unsign
|
||||
|
||||
if (readyLayers.size() == 1)
|
||||
{
|
||||
RenderLayer(*readyLayers.front(), frameIndex, width, height, 0, static_cast<GLuint>(outputFramebuffer), true);
|
||||
RenderLayer(*readyLayers.front(), frameIndex, width, height, videoInputTexture, videoInputTexture, static_cast<GLuint>(outputFramebuffer), true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EnsureLayerTargets(width, height))
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, static_cast<GLuint>(outputFramebuffer));
|
||||
RenderLayer(*readyLayers.back(), frameIndex, width, height, 0, static_cast<GLuint>(outputFramebuffer), true);
|
||||
RenderLayer(*readyLayers.back(), frameIndex, width, height, videoInputTexture, videoInputTexture, static_cast<GLuint>(outputFramebuffer), true);
|
||||
return;
|
||||
}
|
||||
|
||||
GLuint layerInputTexture = 0;
|
||||
GLuint layerInputTexture = videoInputTexture;
|
||||
std::size_t nextTargetIndex = 0;
|
||||
for (std::size_t layerIndex = 0; layerIndex < readyLayers.size(); ++layerIndex)
|
||||
{
|
||||
@@ -167,11 +167,11 @@ void RuntimeRenderScene::RenderFrame(uint64_t frameIndex, unsigned width, unsign
|
||||
if (isFinalLayer)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, static_cast<GLuint>(outputFramebuffer));
|
||||
RenderLayer(*readyLayers[layerIndex], frameIndex, width, height, layerInputTexture, static_cast<GLuint>(outputFramebuffer), true);
|
||||
RenderLayer(*readyLayers[layerIndex], frameIndex, width, height, videoInputTexture, layerInputTexture, static_cast<GLuint>(outputFramebuffer), true);
|
||||
continue;
|
||||
}
|
||||
|
||||
RenderLayer(*readyLayers[layerIndex], frameIndex, width, height, layerInputTexture, mLayerFramebuffers[nextTargetIndex], true);
|
||||
RenderLayer(*readyLayers[layerIndex], frameIndex, width, height, videoInputTexture, layerInputTexture, mLayerFramebuffers[nextTargetIndex], true);
|
||||
layerInputTexture = mLayerTextures[nextTargetIndex];
|
||||
nextTargetIndex = 1 - nextTargetIndex;
|
||||
}
|
||||
@@ -309,6 +309,7 @@ GLuint RuntimeRenderScene::RenderLayer(
|
||||
uint64_t frameIndex,
|
||||
unsigned width,
|
||||
unsigned height,
|
||||
GLuint videoInputTexture,
|
||||
GLuint layerInputTexture,
|
||||
GLuint outputFramebuffer,
|
||||
bool renderToOutput)
|
||||
@@ -327,7 +328,11 @@ GLuint RuntimeRenderScene::RenderLayer(
|
||||
if (!pass.inputNames.empty())
|
||||
{
|
||||
const std::string& inputName = pass.inputNames.front();
|
||||
if (inputName != "layerInput" && inputName != "videoInput")
|
||||
if (inputName == "videoInput")
|
||||
{
|
||||
sourceTexture = videoInputTexture;
|
||||
}
|
||||
else if (inputName != "layerInput")
|
||||
{
|
||||
for (std::size_t index = 0; index < 2; ++index)
|
||||
{
|
||||
@@ -344,7 +349,7 @@ GLuint RuntimeRenderScene::RenderLayer(
|
||||
if (writesLayerOutput && renderToOutput)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, outputFramebuffer);
|
||||
pass.renderer->RenderFrame(frameIndex, width, height, sourceTexture, sourceTexture);
|
||||
pass.renderer->RenderFrame(frameIndex, width, height, sourceTexture, layerInputTexture);
|
||||
lastOutputTexture = 0;
|
||||
continue;
|
||||
}
|
||||
@@ -355,7 +360,7 @@ GLuint RuntimeRenderScene::RenderLayer(
|
||||
const std::size_t targetIndex = nextTargetIndex;
|
||||
nextTargetIndex = nextTargetIndex == 2 ? 3 : 2;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mLayerFramebuffers[targetIndex]);
|
||||
pass.renderer->RenderFrame(frameIndex, width, height, sourceTexture, sourceTexture);
|
||||
pass.renderer->RenderFrame(frameIndex, width, height, sourceTexture, layerInputTexture);
|
||||
const std::size_t namedIndex = targetIndex - 2;
|
||||
namedOutputs[namedIndex] = mLayerTextures[targetIndex];
|
||||
namedOutputNames[namedIndex] = pass.outputName;
|
||||
|
||||
@@ -22,7 +22,7 @@ public:
|
||||
bool StartPrepareWorker(std::unique_ptr<HiddenGlWindow> sharedWindow, std::string& error);
|
||||
bool CommitRenderLayers(const std::vector<RenderCadenceCompositor::RuntimeRenderLayerModel>& layers, std::string& error);
|
||||
bool HasLayers();
|
||||
void RenderFrame(uint64_t frameIndex, unsigned width, unsigned height);
|
||||
void RenderFrame(uint64_t frameIndex, unsigned width, unsigned height, GLuint videoInputTexture = 0);
|
||||
void ShutdownGl();
|
||||
|
||||
private:
|
||||
@@ -48,7 +48,7 @@ private:
|
||||
void TryCommitPendingPrograms(LayerProgram& layer);
|
||||
bool EnsureLayerTargets(unsigned width, unsigned height);
|
||||
void DestroyLayerTargets();
|
||||
GLuint RenderLayer(LayerProgram& layer, uint64_t frameIndex, unsigned width, unsigned height, GLuint layerInputTexture, GLuint outputFramebuffer, bool renderToOutput);
|
||||
GLuint RenderLayer(LayerProgram& layer, uint64_t frameIndex, unsigned width, unsigned height, GLuint videoInputTexture, GLuint layerInputTexture, GLuint outputFramebuffer, bool renderToOutput);
|
||||
LayerProgram* FindLayer(const std::string& layerId);
|
||||
const LayerProgram* FindLayer(const std::string& layerId) const;
|
||||
LayerProgram::PassProgram* FindPass(LayerProgram& layer, const std::string& passId);
|
||||
|
||||
Reference in New Issue
Block a user