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:
@@ -319,6 +319,7 @@ void Core::DeclareTypesForQt()
|
||||
qRegisterMetaType<NodeDependency>();
|
||||
qRegisterMetaType<rational>();
|
||||
qRegisterMetaType<OpenGLTexturePtr>();
|
||||
qRegisterMetaType<OpenGLTextureCache::ReferencePtr>();
|
||||
qRegisterMetaType<NodeValueTable>();
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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 ¶ms)
|
||||
OpenGLTextureCache::ReferencePtr OpenGLTextureCache::Get(const VideoRenderingParams ¶ms, 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
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user