Improvement
This commit is contained in:
@@ -25,7 +25,8 @@ OpenGLRenderPipeline::OpenGLRenderPipeline(
|
||||
mRenderEffect(renderEffect),
|
||||
mOutputReady(outputReady),
|
||||
mPaint(paint),
|
||||
mOutputReadbackMode(ReadOutputReadbackModeFromEnvironment())
|
||||
mOutputReadbackMode(ReadOutputReadbackModeFromEnvironment()),
|
||||
mAsyncReadbackDepth(ReadAsyncReadbackDepthFromEnvironment())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -47,7 +48,9 @@ bool OpenGLRenderPipeline::RenderFrame(const RenderPipelineFrameContext& context
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mRenderer.OutputFramebuffer());
|
||||
if (mOutputReady)
|
||||
mOutputReady();
|
||||
if (state.outputPixelFormat == VideoIOPixelFormat::V210 || state.outputPixelFormat == VideoIOPixelFormat::Yuva10)
|
||||
if (state.outputPixelFormat == VideoIOPixelFormat::Bgra8)
|
||||
PackOutputForBgra8(state);
|
||||
else if (state.outputPixelFormat == VideoIOPixelFormat::V210 || state.outputPixelFormat == VideoIOPixelFormat::Yuva10)
|
||||
PackOutputFor10Bit(state);
|
||||
glFlush();
|
||||
|
||||
@@ -76,6 +79,24 @@ bool OpenGLRenderPipeline::RenderFrame(const RenderPipelineFrameContext& context
|
||||
return true;
|
||||
}
|
||||
|
||||
void OpenGLRenderPipeline::PackOutputForBgra8(const VideoIOState& state)
|
||||
{
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, mRenderer.OutputFramebuffer());
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mRenderer.OutputPackFramebuffer());
|
||||
glBlitFramebuffer(
|
||||
0,
|
||||
0,
|
||||
state.outputFrameSize.width,
|
||||
state.outputFrameSize.height,
|
||||
0,
|
||||
0,
|
||||
state.outputFrameSize.width,
|
||||
state.outputFrameSize.height,
|
||||
GL_COLOR_BUFFER_BIT,
|
||||
GL_NEAREST);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mRenderer.OutputPackFramebuffer());
|
||||
}
|
||||
|
||||
void OpenGLRenderPipeline::PackOutputFor10Bit(const VideoIOState& state)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mRenderer.OutputPackFramebuffer());
|
||||
@@ -109,11 +130,17 @@ bool OpenGLRenderPipeline::EnsureAsyncReadbackBuffers(std::size_t requiredBytes)
|
||||
if (requiredBytes == 0)
|
||||
return false;
|
||||
|
||||
if (mAsyncReadbackBytes == requiredBytes && mAsyncReadbackSlots[0].pixelPackBuffer != 0)
|
||||
if (mAsyncReadbackBytes == requiredBytes &&
|
||||
mAsyncReadbackSlots.size() == mAsyncReadbackDepth &&
|
||||
!mAsyncReadbackSlots.empty() &&
|
||||
mAsyncReadbackSlots[0].pixelPackBuffer != 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
ResetAsyncReadbackState();
|
||||
mAsyncReadbackBytes = requiredBytes;
|
||||
mAsyncReadbackSlots.resize(mAsyncReadbackDepth);
|
||||
for (AsyncReadbackSlot& slot : mAsyncReadbackSlots)
|
||||
{
|
||||
glGenBuffers(1, &slot.pixelPackBuffer);
|
||||
@@ -134,7 +161,7 @@ void OpenGLRenderPipeline::ResetAsyncReadbackState()
|
||||
for (AsyncReadbackSlot& slot : mAsyncReadbackSlots)
|
||||
slot.sizeBytes = 0;
|
||||
|
||||
if (mAsyncReadbackSlots[0].pixelPackBuffer != 0)
|
||||
if (!mAsyncReadbackSlots.empty() && mAsyncReadbackSlots[0].pixelPackBuffer != 0)
|
||||
{
|
||||
for (AsyncReadbackSlot& slot : mAsyncReadbackSlots)
|
||||
{
|
||||
@@ -149,6 +176,7 @@ void OpenGLRenderPipeline::ResetAsyncReadbackState()
|
||||
mAsyncReadbackWriteIndex = 0;
|
||||
mAsyncReadbackReadIndex = 0;
|
||||
mAsyncReadbackBytes = 0;
|
||||
mAsyncReadbackSlots.clear();
|
||||
}
|
||||
|
||||
void OpenGLRenderPipeline::FlushAsyncReadbackPipeline()
|
||||
@@ -170,12 +198,14 @@ void OpenGLRenderPipeline::FlushAsyncReadbackPipeline()
|
||||
bool OpenGLRenderPipeline::QueueAsyncReadback(const VideoIOState& state, OutputReadbackTiming& timing)
|
||||
{
|
||||
const auto queueStartTime = std::chrono::steady_clock::now();
|
||||
const bool usePackedOutput = state.outputPixelFormat == VideoIOPixelFormat::V210 || state.outputPixelFormat == VideoIOPixelFormat::Yuva10;
|
||||
const bool useTenBitPackedOutput = state.outputPixelFormat == VideoIOPixelFormat::V210 ||
|
||||
state.outputPixelFormat == VideoIOPixelFormat::Yuva10;
|
||||
const bool usePackFramebuffer = state.outputPixelFormat == VideoIOPixelFormat::Bgra8 || useTenBitPackedOutput;
|
||||
const std::size_t requiredBytes = static_cast<std::size_t>(state.outputFrameRowBytes) * state.outputFrameSize.height;
|
||||
const GLenum format = usePackedOutput ? GL_RGBA : GL_BGRA;
|
||||
const GLenum type = usePackedOutput ? GL_UNSIGNED_BYTE : GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
const GLuint framebuffer = usePackedOutput ? mRenderer.OutputPackFramebuffer() : mRenderer.OutputFramebuffer();
|
||||
const GLsizei readWidth = static_cast<GLsizei>(usePackedOutput ? state.outputPackTextureWidth : state.outputFrameSize.width);
|
||||
const GLenum format = useTenBitPackedOutput ? GL_RGBA : GL_BGRA;
|
||||
const GLenum type = useTenBitPackedOutput ? GL_UNSIGNED_BYTE : GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
const GLuint framebuffer = usePackFramebuffer ? mRenderer.OutputPackFramebuffer() : mRenderer.OutputFramebuffer();
|
||||
const GLsizei readWidth = static_cast<GLsizei>(useTenBitPackedOutput ? state.outputPackTextureWidth : state.outputFrameSize.width);
|
||||
const GLsizei readHeight = static_cast<GLsizei>(state.outputFrameSize.height);
|
||||
|
||||
const auto finishTiming = [&timing, queueStartTime]() {
|
||||
@@ -204,6 +234,12 @@ bool OpenGLRenderPipeline::QueueAsyncReadback(const VideoIOState& state, OutputR
|
||||
}
|
||||
}
|
||||
|
||||
if (mAsyncReadbackSlots.empty())
|
||||
{
|
||||
finishTiming();
|
||||
return false;
|
||||
}
|
||||
|
||||
AsyncReadbackSlot& slot = mAsyncReadbackSlots[mAsyncReadbackWriteIndex];
|
||||
if (slot.inFlight)
|
||||
{
|
||||
@@ -321,13 +357,17 @@ void OpenGLRenderPipeline::ReadOutputFrameSynchronously(const VideoIOState& stat
|
||||
{
|
||||
const auto readStartTime = std::chrono::steady_clock::now();
|
||||
const bool usePackedOutput = state.outputPixelFormat == VideoIOPixelFormat::V210 || state.outputPixelFormat == VideoIOPixelFormat::Yuva10;
|
||||
const bool usePackFramebuffer = state.outputPixelFormat == VideoIOPixelFormat::Bgra8 || usePackedOutput;
|
||||
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
||||
if (usePackedOutput)
|
||||
if (usePackFramebuffer)
|
||||
{
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, mRenderer.OutputPackFramebuffer());
|
||||
glReadPixels(0, 0, state.outputPackTextureWidth, state.outputFrameSize.height, GL_RGBA, GL_UNSIGNED_BYTE, destinationBytes);
|
||||
if (usePackedOutput)
|
||||
glReadPixels(0, 0, state.outputPackTextureWidth, state.outputFrameSize.height, GL_RGBA, GL_UNSIGNED_BYTE, destinationBytes);
|
||||
else
|
||||
glReadPixels(0, 0, state.outputFrameSize.width, state.outputFrameSize.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, destinationBytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -366,15 +406,19 @@ OpenGLRenderPipeline::OutputReadbackTiming OpenGLRenderPipeline::ReadOutputFrame
|
||||
return timing;
|
||||
}
|
||||
|
||||
if (TryConsumeAsyncReadback(outputFrame, 500000, timing))
|
||||
if (TryConsumeAsyncReadback(outputFrame, 0, timing))
|
||||
{
|
||||
(void)QueueAsyncReadback(state, timing);
|
||||
return timing;
|
||||
}
|
||||
|
||||
const bool queued = QueueAsyncReadback(state, timing);
|
||||
|
||||
if (queued && TryConsumeAsyncReadback(outputFrame, 0, timing))
|
||||
return timing;
|
||||
|
||||
if (TryCopyCachedOutputFrame(outputFrame, timing))
|
||||
{
|
||||
(void)QueueAsyncReadback(state, timing);
|
||||
return timing;
|
||||
}
|
||||
|
||||
@@ -386,8 +430,8 @@ OpenGLRenderPipeline::OutputReadbackTiming OpenGLRenderPipeline::ReadOutputFrame
|
||||
CacheOutputFrame(outputFrame);
|
||||
}
|
||||
|
||||
FlushAsyncReadbackPipeline();
|
||||
(void)QueueAsyncReadback(state, timing);
|
||||
if (!queued)
|
||||
(void)QueueAsyncReadback(state, timing);
|
||||
return timing;
|
||||
}
|
||||
|
||||
@@ -409,3 +453,27 @@ OpenGLRenderPipeline::OutputReadbackMode OpenGLRenderPipeline::ReadOutputReadbac
|
||||
|
||||
return OutputReadbackMode::AsyncPbo;
|
||||
}
|
||||
|
||||
std::size_t OpenGLRenderPipeline::ReadAsyncReadbackDepthFromEnvironment()
|
||||
{
|
||||
char* depthValue = nullptr;
|
||||
std::size_t depthValueSize = 0;
|
||||
if (_dupenv_s(&depthValue, &depthValueSize, "VST_OUTPUT_READBACK_DEPTH") != 0 || depthValue == nullptr)
|
||||
return 6;
|
||||
|
||||
const std::string value(depthValue);
|
||||
std::free(depthValue);
|
||||
try
|
||||
{
|
||||
const unsigned long requestedDepth = std::stoul(value);
|
||||
if (requestedDepth < 3)
|
||||
return 3;
|
||||
if (requestedDepth > 12)
|
||||
return 12;
|
||||
return static_cast<std::size_t>(requestedDepth);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user