render: create less textures

This commit is contained in:
itsmattkc
2022-07-26 09:40:26 -07:00
parent fb8bb654a0
commit e3403a5a53
9 changed files with 156 additions and 127 deletions
+27 -6
View File
@@ -61,6 +61,9 @@ FFmpegDecoder::FFmpegDecoder() :
input_fmt_(AV_PIX_FMT_NONE),
native_internal_pix_fmt_(VideoParams::kFormatInvalid),
native_output_pix_fmt_(VideoParams::kFormatInvalid),
y_tex_(nullptr),
u_tex_(nullptr),
v_tex_(nullptr),
working_frame_(nullptr),
working_packet_(nullptr),
cache_at_zero_(false),
@@ -216,7 +219,12 @@ TexturePtr FFmpegDecoder::RetrieveVideoInternal(Renderer *renderer, const ration
plane_params.set_channel_count(1);
plane_params.set_divider(1);
plane_params.set_format(native_internal_pix_fmt_);
TexturePtr y_plane = renderer->CreateTexture(plane_params, f->data[0], f->linesize[0] / px_size);
if (!y_tex_) {
y_tex_ = renderer->CreateTexture(plane_params, f->data[0], f->linesize[0] / px_size);
} else {
y_tex_->Upload(f->data[0], f->linesize[0] / px_size);
}
if (src_fmt == AV_PIX_FMT_YUV420P
|| src_fmt == AV_PIX_FMT_YUV422P
@@ -236,13 +244,22 @@ TexturePtr FFmpegDecoder::RetrieveVideoInternal(Renderer *renderer, const ration
plane_params.set_height(plane_params.height()/2);
}
TexturePtr u_plane = renderer->CreateTexture(plane_params, f->data[1], f->linesize[1] / px_size);
TexturePtr v_plane = renderer->CreateTexture(plane_params, f->data[2], f->linesize[2] / px_size);
if (!u_tex_) {
u_tex_ = renderer->CreateTexture(plane_params, f->data[1], f->linesize[1] / px_size);
} else {
u_tex_->Upload(f->data[1], f->linesize[1] / px_size);
}
if (!v_tex_) {
v_tex_ = renderer->CreateTexture(plane_params, f->data[2], f->linesize[2] / px_size);
} else {
v_tex_->Upload(f->data[2], f->linesize[2] / px_size);
}
ShaderJob job;
job.Insert(QStringLiteral("y_channel"), NodeValue(NodeValue::kTexture, QVariant::fromValue(y_plane)));
job.Insert(QStringLiteral("u_channel"), NodeValue(NodeValue::kTexture, QVariant::fromValue(u_plane)));
job.Insert(QStringLiteral("v_channel"), NodeValue(NodeValue::kTexture, QVariant::fromValue(v_plane)));
job.Insert(QStringLiteral("y_channel"), NodeValue(NodeValue::kTexture, QVariant::fromValue(y_tex_)));
job.Insert(QStringLiteral("u_channel"), NodeValue(NodeValue::kTexture, QVariant::fromValue(u_tex_)));
job.Insert(QStringLiteral("v_channel"), NodeValue(NodeValue::kTexture, QVariant::fromValue(v_tex_)));
job.Insert(QStringLiteral("bits_per_pixel"), NodeValue(NodeValue::kInt, bits_per_pixel));
job.Insert(QStringLiteral("jpeg_range"), NodeValue(NodeValue::kBoolean, jpeg_range));
@@ -296,6 +313,10 @@ void FFmpegDecoder::CloseInternal()
input_fmt_ = AV_PIX_FMT_NONE;
native_internal_pix_fmt_ = VideoParams::kFormatInvalid;
native_output_pix_fmt_ = VideoParams::kFormatInvalid;
y_tex_ = nullptr;
u_tex_ = nullptr;
v_tex_ = nullptr;
}
QString FFmpegDecoder::id() const
+4
View File
@@ -165,6 +165,10 @@ private:
VideoParams::Format native_output_pix_fmt_;
int native_channel_count_;
TexturePtr y_tex_;
TexturePtr u_tex_;
TexturePtr v_tex_;
AVFrame *working_frame_;
AVPacket *working_packet_;
+27 -53
View File
@@ -107,7 +107,7 @@ void OpenGLRenderer::Init(QOpenGLContext *existing_ctx)
bool OpenGLRenderer::Init()
{
QMutexLocker locker(&global_opengl_mutex);
GL_PREAMBLE;
if (context_) {
qCritical() << "Can't initialize already initialized OpenGLRenderer";
@@ -187,16 +187,11 @@ void OpenGLRenderer::ClearDestination(Texture *texture, double r, double g, doub
}
}
QVariant OpenGLRenderer::CreateNativeTexture2D(int width, int height, VideoParams::Format format, int channel_count, const void *data, int linesize)
QVariant OpenGLRenderer::CreateNativeTexture(int width, int height, int depth, VideoParams::Format format, int channel_count, const void *data, int linesize)
{
GL_PREAMBLE;
return CreateNativeTexture2DInternal(width, height, format, channel_count, data, linesize);
}
QVariant OpenGLRenderer::CreateNativeTexture3D(int width, int height, int depth, VideoParams::Format format, int channel_count, const void *data, int linesize)
{
GL_PREAMBLE;
bool is_3d = depth > 1;
// Generate new texture
GLuint texture;
@@ -205,18 +200,27 @@ QVariant OpenGLRenderer::CreateNativeTexture3D(int width, int height, int depth,
functions_->glPixelStorei(GL_UNPACK_ROW_LENGTH, linesize);
GLenum target_current = is_3d ? GL_TEXTURE_BINDING_3D : GL_TEXTURE_BINDING_2D;
GLenum target = is_3d ? GL_TEXTURE_3D : GL_TEXTURE_2D;
GLint current_tex;
functions_->glGetIntegerv(GL_TEXTURE_BINDING_3D, &current_tex);
functions_->glGetIntegerv(target_current, &current_tex);
functions_->glBindTexture(GL_TEXTURE_3D, texture);
functions_->glBindTexture(target, texture);
context_->extraFunctions()->glTexImage3D(GL_TEXTURE_3D, 0, GetInternalFormat(format, channel_count),
width, height, depth, 0, GetPixelFormat(channel_count),
GetPixelType(format), data);
if (is_3d) {
context_->extraFunctions()->glTexImage3D(target, 0, GetInternalFormat(format, channel_count),
width, height, depth, 0, GetPixelFormat(channel_count),
GetPixelType(format), data);
} else {
functions_->glTexImage2D(target, 0, GetInternalFormat(format, channel_count),
width, height, 0, GetPixelFormat(channel_count),
GetPixelType(format), data);
}
functions_->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
functions_->glBindTexture(GL_TEXTURE_3D, current_tex);
functions_->glBindTexture(target, current_tex);
return texture;
}
@@ -294,8 +298,10 @@ void OpenGLRenderer::UploadToTexture(Texture *texture, const void *data, int lin
GLuint t = texture->id().value<GLuint>();
const VideoParams& p = texture->params();
GLenum tex_type = texture->type() == Texture::k2D ? GL_TEXTURE_2D : GL_TEXTURE_3D;
GLenum tex_binding = texture->type() == Texture::k2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_3D;
bool is_3d = texture->params().is_3d();
GLenum tex_type = !is_3d ? GL_TEXTURE_2D : GL_TEXTURE_3D;
GLenum tex_binding = !is_3d ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_3D;
// Store currently bound texture so it can be restored later
GLint current_tex;
@@ -308,7 +314,7 @@ void OpenGLRenderer::UploadToTexture(Texture *texture, const void *data, int lin
{
PRINT_GL_ERRORS;
if (texture->type() == Texture::k2D) {
if (!is_3d) {
functions_->glTexSubImage2D(tex_type, 0, 0, 0,
p.effective_width(), p.effective_height(),
GetPixelFormat(p.channel_count()), GetPixelType(p.format()),
@@ -502,7 +508,7 @@ void OpenGLRenderer::Blit(QVariant s, ShaderJob job, Texture *destination, Video
functions_->glActiveTexture(GL_TEXTURE0 + i);
GLenum target = (texture && texture->type() == Texture::k3D) ? GL_TEXTURE_3D : GL_TEXTURE_2D;
GLenum target = (texture && texture->params().is_3d()) ? GL_TEXTURE_3D : GL_TEXTURE_2D;
functions_->glBindTexture(target, tex_id);
if (tex_id) {
@@ -584,11 +590,11 @@ void OpenGLRenderer::Blit(QVariant s, ShaderJob job, Texture *destination, Video
TexturePtr output_tex, input_tex;
if (real_iteration_count > 1) {
// Create one texture to bounce off
output_tex = CreateTextureFromNativeHandle(CreateNativeTexture2DInternal(destination_params), destination_params);
output_tex = CreateTexture(destination_params);
if (real_iteration_count > 2) {
// Create a second texture bounce off
input_tex = CreateTextureFromNativeHandle(CreateNativeTexture2DInternal(destination_params), destination_params);
input_tex = CreateTexture(destination_params);
}
}
@@ -648,7 +654,7 @@ void OpenGLRenderer::Blit(QVariant s, ShaderJob job, Texture *destination, Video
// Release any textures we bound before
for (int i=textures_to_bind.size()-1; i>=0; i--) {
TexturePtr texture = textures_to_bind.at(i).texture;
GLenum target = (texture && texture->type() == Texture::k3D) ? GL_TEXTURE_3D : GL_TEXTURE_2D;
GLenum target = (texture && texture->params().is_3d()) ? GL_TEXTURE_3D : GL_TEXTURE_2D;
functions_->glActiveTexture(GL_TEXTURE0 + i);
functions_->glBindTexture(target, 0);
}
@@ -788,38 +794,6 @@ void OpenGLRenderer::ClearDestinationInternal(double r, double g, double b, doub
functions_->glClear(GL_COLOR_BUFFER_BIT);
}
QVariant OpenGLRenderer::CreateNativeTexture2DInternal(int width, int height, VideoParams::Format format, int channel_count, const void *data, int linesize)
{
GLuint texture;
functions_->glGenTextures(1, &texture);
texture_params_.insert(texture, {width, height, 1, format, channel_count});
functions_->glPixelStorei(GL_UNPACK_ROW_LENGTH, linesize);
GLint current_tex;
functions_->glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_tex);
functions_->glBindTexture(GL_TEXTURE_2D, texture);
{
PRINT_GL_ERRORS;
functions_->glTexImage2D(GL_TEXTURE_2D, 0, GetInternalFormat(format, channel_count),
width, height, 0, GetPixelFormat(channel_count),
GetPixelType(format), data);
}
functions_->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
functions_->glBindTexture(GL_TEXTURE_2D, current_tex);
return texture;
}
QVariant OpenGLRenderer::CreateNativeTexture2DInternal(const VideoParams &params, const void *data, int linesize)
{
return CreateNativeTexture2DInternal(params.effective_width(), params.effective_height(), params.format(), params.channel_count(), data, linesize);
}
GLuint OpenGLRenderer::CompileShader(GLenum type, const QString &code)
{
static const QString shader_preamble =
+7 -12
View File
@@ -47,18 +47,10 @@ public:
virtual void PostDestroy() override;
public slots:
virtual void PostInit() override;
virtual void DestroyInternal() override;
virtual void ClearDestination(olive::Texture *texture = nullptr, double r = 0.0, double g = 0.0, double b = 0.0, double a = 0.0) override;
virtual QVariant CreateNativeTexture2D(int width, int height, olive::VideoParams::Format format, int channel_count, const void* data = nullptr, int linesize = 0) override;
virtual QVariant CreateNativeTexture3D(int width, int height, int depth, olive::VideoParams::Format format, int channel_count, const void* data = nullptr, int linesize = 0) override;
virtual void DestroyNativeTexture(QVariant texture) override;
virtual QVariant CreateNativeShader(olive::ShaderCode code) override;
virtual void DestroyNativeShader(QVariant shader) override;
@@ -71,13 +63,19 @@ public slots:
virtual Color GetPixelFromTexture(olive::Texture *texture, const QPointF &pt) override;
protected slots:
protected:
virtual void Blit(QVariant shader,
olive::ShaderJob job,
olive::Texture* destination,
olive::VideoParams destination_params,
bool clear_destination) override;
virtual QVariant CreateNativeTexture(int width, int height, int depth, olive::VideoParams::Format format, int channel_count, const void* data = nullptr, int linesize = 0) override;
virtual void DestroyNativeTexture(QVariant texture) override;
virtual void DestroyInternal() override;
private:
static GLint GetInternalFormat(VideoParams::Format format, int channel_layout);
@@ -93,9 +91,6 @@ private:
void ClearDestinationInternal(double r = 0.0, double g = 0.0, double b = 0.0, double a = 0.0);
QVariant CreateNativeTexture2DInternal(int width, int height, olive::VideoParams::Format format, int channel_count, const void* data = nullptr, int linesize = 0);
QVariant CreateNativeTexture2DInternal(const VideoParams &params, const void* data = nullptr, int linesize = 0);
GLuint CompileShader(GLenum type, const QString &code);
QOpenGLContext* context_;
+58 -26
View File
@@ -20,36 +20,54 @@
#include "renderer.h"
#include <QDateTime>
#include <QTimer>
#include <QVector2D>
#include "common/ocioutils.h"
namespace olive {
Renderer::Renderer(QObject *parent) :
QObject(parent)
{
}
TexturePtr Renderer::CreateTexture(const VideoParams &params, Texture::Type type, const void *data, int linesize)
{
QVariant v;
if (type == Texture::k3D) {
v = CreateNativeTexture3D(params.effective_width(), params.effective_height(),
params.effective_depth(), params.format(), params.channel_count(), data, linesize);
} else {
v = CreateNativeTexture2D(params.effective_width(), params.effective_height(), params.format(),
params.channel_count(), data, linesize);
}
return CreateTextureFromNativeHandle(v, params, type);
QTimer *texture_garbage_collector = new QTimer(this);
texture_garbage_collector->setInterval(MAX_TEXTURE_LIFE);
connect(texture_garbage_collector, &QTimer::timeout, this, &Renderer::ClearOldTextures);
texture_garbage_collector->start();
}
TexturePtr Renderer::CreateTexture(const VideoParams &params, const void *data, int linesize)
{
return CreateTexture(params, Texture::k2D, data, linesize);
QVariant v;
/*for (auto it=texture_cache_.begin(); it!=texture_cache_.end(); it++) {
if (it->width == params.effective_width()
&& it->height == params.effective_height()
&& it->depth == params.effective_depth()
&& it->format == params.format()
&& it->channel_count == params.channel_count()) {
this->Flush();
v = it->handle;
texture_cache_.erase(it);
break;
}
}*/
v = CreateNativeTexture(params.effective_width(), params.effective_height(), params.effective_depth(),
params.format(), params.channel_count(), data, linesize);
return CreateTextureFromNativeHandle(v, params);
}
void Renderer::DestroyTexture(Texture *texture)
{
/*texture_cache_.push_back({texture->params().effective_width(),
texture->params().effective_height(),
texture->params().effective_depth(),
texture->params().format(),
texture->params().channel_count(),
texture->id(),
QDateTime::currentMSecsSinceEpoch()});*/
DestroyNativeTexture(texture->id());
}
TexturePtr Renderer::InterlaceTexture(TexturePtr top, TexturePtr bottom, const VideoParams &params)
@@ -83,6 +101,11 @@ QVariant Renderer::GetDefaultShader()
void Renderer::Destroy()
{
for (auto it=texture_cache_.begin(); it!=texture_cache_.end(); it++) {
DestroyNativeTexture(it->handle);
}
texture_cache_.clear();
if (!default_shader_.isNull()) {
DestroyNativeShader(default_shader_);
default_shader_.clear();
@@ -98,13 +121,13 @@ void Renderer::Destroy()
DestroyInternal();
}
TexturePtr Renderer::CreateTextureFromNativeHandle(const QVariant &v, const VideoParams &params, Texture::Type type)
TexturePtr Renderer::CreateTextureFromNativeHandle(const QVariant &v, const VideoParams &params)
{
if (v.isNull()) {
return nullptr;
}
return std::make_shared<Texture>(this, v, params, type);
return std::make_shared<Texture>(this, v, params);
}
bool Renderer::GetColorContext(const ColorTransformJob &color_job, Renderer::ColorContext *ctx)
@@ -175,8 +198,7 @@ bool Renderer::GetColorContext(const ColorTransformJob &color_job, Renderer::Col
}
// Allocate 3D LUT
color_ctx.lut3d_textures[i].texture = CreateTexture(VideoParams(edge_len, edge_len, edge_len, VideoParams::kFormatFloat32, VideoParams::kRGBChannelCount),
Texture::k3D, values);
color_ctx.lut3d_textures[i].texture = CreateTexture(VideoParams(edge_len, edge_len, edge_len, VideoParams::kFormatFloat32, VideoParams::kRGBChannelCount), values);
color_ctx.lut3d_textures[i].name = sampler_name;
color_ctx.lut3d_textures[i].interpolation = (interpolation == OCIO::INTERP_NEAREST) ? Texture::kNearest : Texture::kLinear;
}
@@ -206,9 +228,7 @@ bool Renderer::GetColorContext(const ColorTransformJob &color_job, Renderer::Col
}
// Allocate 1D LUT
color_ctx.lut1d_textures[i].texture = CreateTexture(VideoParams(width, height, VideoParams::kFormatFloat32, (channel == OCIO::GpuShaderDesc::TEXTURE_RED_CHANNEL) ? 1 : VideoParams::kRGBChannelCount),
Texture::k2D,
values);
color_ctx.lut1d_textures[i].texture = CreateTexture(VideoParams(width, height, VideoParams::kFormatFloat32, (channel == OCIO::GpuShaderDesc::TEXTURE_RED_CHANNEL) ? 1 : VideoParams::kRGBChannelCount), values);
color_ctx.lut1d_textures[i].name = sampler_name;
color_ctx.lut1d_textures[i].interpolation = (interpolation == OCIO::INTERP_NEAREST) ? Texture::kNearest : Texture::kLinear;
}
@@ -219,6 +239,18 @@ bool Renderer::GetColorContext(const ColorTransformJob &color_job, Renderer::Col
}
}
void Renderer::ClearOldTextures()
{
for (auto it=texture_cache_.begin(); it!=texture_cache_.end(); ) {
if (it->accessed < QDateTime::currentMSecsSinceEpoch() - MAX_TEXTURE_LIFE) {
DestroyNativeTexture(it->handle);
it = texture_cache_.erase(it);
} else {
it++;
}
}
}
void Renderer::BlitColorManaged(const ColorTransformJob &color_job, Texture *destination, const VideoParams &params)
{
ColorContext color_ctx;
+27 -12
View File
@@ -45,9 +45,10 @@ public:
virtual bool Init() = 0;
TexturePtr CreateTexture(const VideoParams& params, Texture::Type type, const void* data = nullptr, int linesize = 0);
TexturePtr CreateTexture(const VideoParams& params, const void *data = nullptr, int linesize = 0);
void DestroyTexture(Texture *texture);
void BlitToTexture(QVariant shader,
olive::ShaderJob job,
olive::Texture* destination,
@@ -82,18 +83,10 @@ public:
virtual void PostDestroy() = 0;
public slots:
virtual void PostInit() = 0;
virtual void DestroyInternal() = 0;
virtual void ClearDestination(olive::Texture *texture = nullptr, double r = 0.0, double g = 0.0, double b = 0.0, double a = 0.0) = 0;
virtual QVariant CreateNativeTexture2D(int width, int height, olive::VideoParams::Format format, int channel_count, const void* data = nullptr, int linesize = 0) = 0;
virtual QVariant CreateNativeTexture3D(int width, int height, int depth, olive::VideoParams::Format format, int channel_count, const void* data = nullptr, int linesize = 0) = 0;
virtual void DestroyNativeTexture(QVariant texture) = 0;
virtual QVariant CreateNativeShader(olive::ShaderCode code) = 0;
virtual void DestroyNativeShader(QVariant shader) = 0;
@@ -106,15 +99,18 @@ public slots:
virtual Color GetPixelFromTexture(olive::Texture *texture, const QPointF &pt) = 0;
protected slots:
protected:
virtual void Blit(QVariant shader,
olive::ShaderJob job,
olive::Texture* destination,
olive::VideoParams destination_params,
bool clear_destination) = 0;
protected:
TexturePtr CreateTextureFromNativeHandle(const QVariant &v, const VideoParams &params, Texture::Type type = Texture::k2D);
virtual QVariant CreateNativeTexture(int width, int height, int depth, olive::VideoParams::Format format, int channel_count, const void* data = nullptr, int linesize = 0) = 0;
virtual void DestroyNativeTexture(QVariant texture) = 0;
virtual void DestroyInternal() = 0;
private:
struct ColorContext {
@@ -130,16 +126,35 @@ private:
};
TexturePtr CreateTextureFromNativeHandle(const QVariant &v, const VideoParams &params);
bool GetColorContext(const ColorTransformJob &color_job, ColorContext* ctx);
QHash<QString, ColorContext> color_cache_;
struct CachedTexture
{
int width;
int height;
int depth;
VideoParams::Format format;
int channel_count;
QVariant handle;
qint64 accessed;
};
const int MAX_TEXTURE_LIFE = 10000;
std::list<CachedTexture> texture_cache_;
QMutex color_cache_mutex_;
QVariant default_shader_;
QVariant interlace_texture_;
private slots:
void ClearOldTextures();
};
}
+1 -1
View File
@@ -29,7 +29,7 @@ const Texture::Interpolation Texture::kDefaultInterpolation = Texture::kMipmappe
Texture::~Texture()
{
if (renderer_) {
renderer_->DestroyNativeTexture(id_);
renderer_->DestroyTexture(this);
}
}
+3 -17
View File
@@ -32,11 +32,6 @@ class Renderer;
class Texture
{
public:
enum Type {
k2D,
k3D
};
enum Interpolation {
kNearest,
kLinear,
@@ -50,19 +45,17 @@ public:
*/
Texture(const VideoParams& param) :
renderer_(nullptr),
params_(param),
type_(k2D)
params_(param)
{
}
/**
* @brief Construct a real texture linked to a renderer backend
*/
Texture(Renderer* renderer, const QVariant& native, const VideoParams& param, Type type) :
Texture(Renderer* renderer, const QVariant& native, const VideoParams& param) :
renderer_(renderer),
params_(param),
id_(native),
type_(type)
id_(native)
{
}
@@ -117,11 +110,6 @@ public:
return params_.pixel_aspect_ratio();
}
Type type() const
{
return type_;
}
Renderer* renderer() const
{
return renderer_;
@@ -134,8 +122,6 @@ private:
QVariant id_;
Type type_;
};
using TexturePtr = std::shared_ptr<Texture>;
+2
View File
@@ -121,6 +121,8 @@ public:
calculate_effective_size();
}
bool is_3d() const { return depth_ > 1; }
const rational& time_base() const
{
return time_base_;