implemented texture cache for performance

Creating and destroying textures is a slow process, particularly when we can
re-use them throughout most of the render chain. We now keep them stored so
they can be re-used which improves performance substantially.
This commit is contained in:
itsmattkc
2019-12-10 14:53:47 +11:00
parent 6ac33d8dc4
commit 91c7d8aa4d
9 changed files with 55 additions and 35 deletions
+30 -24
View File
@@ -7,12 +7,13 @@
#include "render/colormanager.h"
#include "render/pixelservice.h"
OpenGLWorker::OpenGLWorker(QOpenGLContext *share_ctx, OpenGLShaderCache *shader_cache, VideoRenderFrameCache *frame_cache, QObject *parent) :
OpenGLWorker::OpenGLWorker(QOpenGLContext *share_ctx, OpenGLShaderCache *shader_cache, OpenGLTextureCache *texture_cache, VideoRenderFrameCache *frame_cache, QObject *parent) :
VideoRenderWorker(frame_cache, parent),
share_ctx_(share_ctx),
ctx_(nullptr),
functions_(nullptr),
shader_cache_(shader_cache)
shader_cache_(shader_cache),
texture_cache_(texture_cache)
{
surface_.create();
}
@@ -95,8 +96,9 @@ void OpenGLWorker::FrameToValue(StreamPtr stream, FramePtr frame, NodeValueTable
}
}
OpenGLTexturePtr footage_tex = std::make_shared<OpenGLTexture>();
footage_tex->Create(ctx_, frame);
VideoRenderingParams footage_params(frame->width(), frame->height(), stream->timebase(), frame->format(), video_params().mode());
OpenGLTextureCache::ReferencePtr footage_tex_ref = texture_cache_->Get(footage_params, frame->data());
if (video_params().mode() == olive::kOffline) {
if (!color_processor->IsEnabled()) {
@@ -104,27 +106,29 @@ void OpenGLWorker::FrameToValue(StreamPtr stream, FramePtr frame, NodeValueTable
}
// Create destination texture
OpenGLTexturePtr associated_tex = std::make_shared<OpenGLTexture>();
associated_tex->Create(ctx_, footage_tex->width(), footage_tex->height(), footage_tex->format());
OpenGLTextureCache::ReferencePtr associated_tex_ref = texture_cache_->Get(footage_params);
// Set viewport for texture size
functions_->glViewport(0, 0, footage_tex->width(), footage_tex->height());
functions_->glViewport(0, 0, footage_tex_ref->texture()->width(), footage_tex_ref->texture()->height());
buffer_.Attach(associated_tex);
buffer_.Attach(associated_tex_ref->texture());
buffer_.Bind();
footage_tex->Bind();
footage_tex_ref->texture()->Bind();
functions_->glClearColor(0.0, 0.0, 0.0, 0.0);
functions_->glClear(GL_COLOR_BUFFER_BIT);
// Blit old texture to new texture through OCIO shader
color_processor->ProcessOpenGL();
footage_tex->Release();
footage_tex_ref->texture()->Release();
buffer_.Release();
buffer_.Detach();
footage_tex = associated_tex;
footage_tex_ref = associated_tex_ref;
}
table->Push(NodeParam::kTexture, QVariant::fromValue(footage_tex));
table->Push(NodeParam::kTexture, QVariant::fromValue(footage_tex_ref));
}
void OpenGLWorker::CloseInternal()
@@ -150,13 +154,15 @@ void OpenGLWorker::RunNodeAccelerated(const Node *node, const NodeValueDatabase
}
// Create the output texture
OpenGLTexturePtr output = std::make_shared<OpenGLTexture>();
output->Create(ctx_, video_params().effective_width(), video_params().effective_height(), video_params().format());
OpenGLTextureCache::ReferencePtr output_ref = texture_cache_->Get(video_params());
buffer_.Attach(output);
buffer_.Attach(output_ref->texture());
buffer_.Bind();
functions_->glClearColor(0.0, 0.0, 0.0, 0.0);
functions_->glClear(GL_COLOR_BUFFER_BIT);
// Lock the shader so no other thread interferes as we set parameters and draw (and we don't interfere with any others)
shader->Lock();
shader->bind();
@@ -206,11 +212,11 @@ void OpenGLWorker::RunNodeAccelerated(const Node *node, const NodeValueDatabase
case NodeInput::kFootage:
case NodeInput::kTexture:
{
OpenGLTexturePtr texture = value.value<OpenGLTexturePtr>();
OpenGLTextureCache::ReferencePtr texture = value.value<OpenGLTextureCache::ReferencePtr>();
functions_->glActiveTexture(GL_TEXTURE0 + input_texture_count);
GLuint tex_id = texture ? texture->texture() : 0;
GLuint tex_id = texture ? texture->texture()->texture() : 0;
functions_->glBindTexture(GL_TEXTURE_2D, tex_id);
// Set value to bound texture
@@ -228,8 +234,8 @@ void OpenGLWorker::RunNodeAccelerated(const Node *node, const NodeValueDatabase
int res_param_location = shader->uniformLocation(QStringLiteral("%1_resolution").arg(input->id()));
if (res_param_location > -1) {
shader->setUniformValue(res_param_location,
static_cast<GLfloat>(texture->width()),
static_cast<GLfloat>(texture->height()));
static_cast<GLfloat>(texture->texture()->width()),
static_cast<GLfloat>(texture->texture()->height()));
}
}
@@ -288,23 +294,23 @@ void OpenGLWorker::RunNodeAccelerated(const Node *node, const NodeValueDatabase
buffer_.Detach();
output_params->Push(NodeParam::kTexture, QVariant::fromValue(output));
output_params->Push(NodeParam::kTexture, QVariant::fromValue(output_ref));
}
void OpenGLWorker::TextureToBuffer(const QVariant &tex_in, QByteArray &buffer)
{
OpenGLTexturePtr texture = tex_in.value<OpenGLTexturePtr>();
OpenGLTextureCache::ReferencePtr texture = tex_in.value<OpenGLTextureCache::ReferencePtr>();
PixelFormatInfo format_info = PixelService::GetPixelFormatInfo(video_params().format());
QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions();
buffer_.Attach(texture);
buffer_.Attach(texture->texture());
f->glBindFramebuffer(GL_READ_FRAMEBUFFER, buffer_.buffer());
f->glReadPixels(0,
0,
texture->width(),
texture->height(),
texture->texture()->width(),
texture->texture()->height(),
format_info.pixel_format,
format_info.gl_pixel_type,
buffer.data());