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
+1
View File
@@ -319,6 +319,7 @@ void Core::DeclareTypesForQt()
qRegisterMetaType<NodeDependency>();
qRegisterMetaType<rational>();
qRegisterMetaType<OpenGLTexturePtr>();
qRegisterMetaType<OpenGLTextureCache::ReferencePtr>();
qRegisterMetaType<NodeValueTable>();
}
+3 -4
View File
@@ -32,7 +32,7 @@ bool OpenGLBackend::InitInternal()
// Initiate one thread per CPU core
for (int i=0;i<threads().size();i++) {
// Create one processor object for each thread
OpenGLWorker* processor = new OpenGLWorker(share_ctx, &shader_cache_, frame_cache());
OpenGLWorker* processor = new OpenGLWorker(share_ctx, &shader_cache_, &texture_cache_, frame_cache());
processor->SetParameters(params());
processors_.append(processor);
}
@@ -145,9 +145,8 @@ void OpenGLBackend::ThreadCompletedFrame(NodeDependency path, QByteArray hash, N
SetWorkerBusyState(static_cast<RenderWorker*>(sender()), false);
QVariant value = table.Get(NodeParam::kTexture);
OpenGLTexturePtr texture = value.value<OpenGLTexturePtr>();
if (!texture) {
if (value.isNull()) {
// No frame received, we set hash to an empty
frame_cache()->RemoveHash(path.in(), hash);
} else {
@@ -159,7 +158,7 @@ void OpenGLBackend::ThreadCompletedFrame(NodeDependency path, QByteArray hash, N
"Download",
Q_ARG(NodeDependency, path),
Q_ARG(QByteArray, hash),
Q_ARG(QVariant, QVariant::fromValue(texture)),
Q_ARG(QVariant, value),
Q_ARG(QString, cache_fn));
last_download_thread_++;
@@ -5,6 +5,7 @@
#include "openglframebuffer.h"
#include "openglworker.h"
#include "opengltexture.h"
#include "opengltexturecache.h"
#include "openglshader.h"
#include "openglshadercache.h"
@@ -34,6 +35,8 @@ private:
OpenGLShaderCache shader_cache_;
OpenGLTextureCache texture_cache_;
int last_download_thread_;
private slots:
+2 -2
View File
@@ -44,7 +44,7 @@ bool OpenGLTexture::IsCreated() const
return (texture_ != 0);
}
void OpenGLTexture::Create(QOpenGLContext *ctx, int width, int height, const olive::PixelFormat &format, void* data)
void OpenGLTexture::Create(QOpenGLContext *ctx, int width, int height, const olive::PixelFormat &format, const void* data)
{
if (ctx == nullptr) {
qWarning() << "RenderTexture::Create was passed an invalid context";
@@ -182,7 +182,7 @@ uchar *OpenGLTexture::Download() const
return data;
}
void OpenGLTexture::CreateInternal(GLuint* tex, void *data)
void OpenGLTexture::CreateInternal(GLuint* tex, const void *data)
{
QOpenGLFunctions* f = context_->functions();
+2 -2
View File
@@ -40,7 +40,7 @@ public:
DISABLE_COPY_MOVE(OpenGLTexture)
void Create(QOpenGLContext* ctx, int width, int height, const olive::PixelFormat &format, void *data = nullptr);
void Create(QOpenGLContext* ctx, int width, int height, const olive::PixelFormat &format, const void *data = nullptr);
void Create(QOpenGLContext* ctx, FramePtr frame);
bool IsCreated() const;
@@ -67,7 +67,7 @@ public slots:
void Destroy();
private:
void CreateInternal(GLuint *tex, void *data = nullptr);
void CreateInternal(GLuint *tex, const void *data = nullptr);
QOpenGLContext* context_;
@@ -7,7 +7,7 @@ OpenGLTextureCache::~OpenGLTextureCache()
}
}
OpenGLTextureCache::ReferencePtr OpenGLTextureCache::Get(const VideoRenderingParams &params)
OpenGLTextureCache::ReferencePtr OpenGLTextureCache::Get(const VideoRenderingParams &params, const void *data)
{
OpenGLTexturePtr texture = nullptr;
@@ -28,10 +28,14 @@ OpenGLTextureCache::ReferencePtr OpenGLTextureCache::Get(const VideoRenderingPar
lock_.unlock();
QOpenGLContext* ctx = QOpenGLContext::currentContext();
// If we didn't find a texture, we'll need to create one
if (!texture) {
texture = std::make_shared<OpenGLTexture>();
texture->Create(QOpenGLContext::currentContext(), params.effective_width(), params.effective_height(), params.format());
texture->Create(ctx, params.effective_width(), params.effective_height(), params.format(), data);
} else if (data) {
texture->Upload(data);
}
return std::make_shared<Reference>(this, texture);
@@ -3,6 +3,7 @@
#include <QMutex>
#include "openglframebuffer.h"
#include "opengltexture.h"
#include "render/videoparams.h"
@@ -34,7 +35,7 @@ public:
DISABLE_COPY_MOVE(OpenGLTextureCache)
ReferencePtr Get(const VideoRenderingParams& params);
ReferencePtr Get(const VideoRenderingParams& params, const void *data = nullptr);
private:
void Relinquish(Reference* ref);
@@ -47,4 +48,6 @@ private:
};
Q_DECLARE_METATYPE(OpenGLTextureCache::ReferencePtr)
#endif // OPENGLTEXTURECACHE_H
+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());
+4
View File
@@ -7,12 +7,14 @@
#include "../videorenderworker.h"
#include "openglframebuffer.h"
#include "openglshadercache.h"
#include "opengltexturecache.h"
class OpenGLWorker : public VideoRenderWorker {
Q_OBJECT
public:
OpenGLWorker(QOpenGLContext* share_ctx,
OpenGLShaderCache* shader_cache,
OpenGLTextureCache* texture_cache,
VideoRenderFrameCache* frame_cache,
QObject* parent = nullptr);
@@ -64,6 +66,8 @@ private:
OpenGLShaderCache* shader_cache_;
OpenGLTextureCache* texture_cache_;
private slots:
void FinishInit();