nodes: rework so that jobs can be completely deferred

Big optimization requiring a lot of refactoring.
This commit is contained in:
itsmattkc
2022-09-24 18:44:59 -07:00
parent 658fe9da7e
commit c0d8ff403f
57 changed files with 593 additions and 588 deletions
+4 -1
View File
@@ -26,10 +26,13 @@
namespace olive {
class AcceleratedJob {
class AcceleratedJob
{
public:
AcceleratedJob() = default;
virtual ~AcceleratedJob(){}
NodeValue Get(const QString& input) const
{
return value_map_.value(input);
+8 -7
View File
@@ -24,13 +24,16 @@
#include <QString>
#include <QVariant>
#include "node/value.h"
#include "render/job/acceleratedjob.h"
namespace olive {
class CacheJob
class CacheJob : public AcceleratedJob
{
public:
CacheJob() = default;
CacheJob(const QString &filename, const QVariant &fallback = QVariant())
CacheJob(const QString &filename, const NodeValue &fallback = NodeValue())
{
filename_ = filename;
}
@@ -38,18 +41,16 @@ public:
const QString &GetFilename() const { return filename_; }
void SetFilename(const QString &s) { filename_ = s; }
const QVariant &GetFallback() const { return fallback_; }
void SetFallback(const QVariant &val) { fallback_ = val; }
const NodeValue &GetFallback() const { return fallback_; }
void SetFallback(const NodeValue &val) { fallback_ = val; }
private:
QString filename_;
QVariant fallback_;
NodeValue fallback_;
};
}
Q_DECLARE_METATYPE(olive::CacheJob)
#endif // CACHEJOB_H
+16 -8
View File
@@ -24,7 +24,7 @@
#include <QMatrix4x4>
#include <QString>
#include "render/job/generatejob.h"
#include "acceleratedjob.h"
#include "render/alphaassoc.h"
#include "render/colorprocessor.h"
#include "render/texture.h"
@@ -33,18 +33,23 @@ namespace olive {
class Node;
class ColorTransformJob : public GenerateJob
class ColorTransformJob : public AcceleratedJob
{
public:
ColorTransformJob()
{
processor_ = nullptr;
input_texture_ = nullptr;
custom_shader_src_ = nullptr;
input_alpha_association_ = kAlphaNone;
clear_destination_ = true;
}
ColorTransformJob(const NodeValueRow &row) :
ColorTransformJob()
{
Insert(row);
}
QString id() const
{
if (id_.isEmpty()) {
@@ -56,8 +61,13 @@ public:
void SetOverrideID(const QString &id) { id_ = id; }
TexturePtr GetInputTexture() const { return input_texture_; }
void SetInputTexture(TexturePtr tex) { input_texture_ = tex; }
const NodeValue &GetInputTexture() const { return input_texture_; }
void SetInputTexture(const NodeValue &tex) { input_texture_ = tex; }
void SetInputTexture(TexturePtr tex)
{
Q_ASSERT(!tex->IsDummy());
input_texture_ = NodeValue(NodeValue::kTexture, tex);
}
ColorProcessorPtr GetColorProcessor() const { return processor_; }
void SetColorProcessor(ColorProcessorPtr p) { processor_ = p; }
@@ -89,7 +99,7 @@ private:
ColorProcessorPtr processor_;
QString id_;
TexturePtr input_texture_;
NodeValue input_texture_;
const Node *custom_shader_src_;
QString custom_shader_id_;
@@ -108,6 +118,4 @@ private:
}
Q_DECLARE_METATYPE(olive::ColorTransformJob)
#endif // COLORTRANSFORMJOB_H
+1 -1
View File
@@ -25,7 +25,7 @@
namespace olive {
class FootageJob
class FootageJob : public AcceleratedJob
{
public:
FootageJob() :
+7 -18
View File
@@ -22,33 +22,22 @@
#define GENERATEJOB_H
#include "acceleratedjob.h"
#include "render/videoparams.h"
#include "codec/frame.h"
namespace olive {
class GenerateJob : public AcceleratedJob {
class GenerateJob : public AcceleratedJob
{
public:
GenerateJob()
GenerateJob() = default;
GenerateJob(const NodeValueRow &row) :
GenerateJob()
{
requested_format_ = VideoParams::kFormatInvalid;
Insert(row);
}
VideoParams::Format GetRequestedFormat() const { return requested_format_; }
void SetRequestedFormat(VideoParams::Format f) { requested_format_ = f; }
const QString &GetColorspace() const { return colorspace_; }
void SetColorspace(const QString &s) { colorspace_ = s; }
private:
VideoParams::Format requested_format_;
QString colorspace_;
};
}
Q_DECLARE_METATYPE(olive::GenerateJob)
#endif // GENERATEJOB_H
+2 -1
View File
@@ -27,7 +27,8 @@
namespace olive {
class SampleJob : public AcceleratedJob {
class SampleJob : public AcceleratedJob
{
public:
SampleJob()
{
+9 -11
View File
@@ -24,19 +24,24 @@
#include <QMatrix4x4>
#include <QVector>
#include "generatejob.h"
#include "render/colorprocessor.h"
#include "acceleratedjob.h"
#include "render/texture.h"
namespace olive {
class ShaderJob : public GenerateJob {
class ShaderJob : public AcceleratedJob
{
public:
ShaderJob()
{
iterations_ = 1;
iterative_input_ = nullptr;
will_change_image_size_ = true;
}
ShaderJob(const NodeValueRow &row) :
ShaderJob()
{
Insert(row);
}
const QString& GetShaderID() const
@@ -100,9 +105,6 @@ public:
return vertex_overrides_;
}
bool GetWillChangeImageSize() const { return will_change_image_size_; }
void SetWillChangeImageSize(bool e) { will_change_image_size_ = e; }
private:
QString shader_id_;
@@ -114,12 +116,8 @@ private:
QVector<float> vertex_overrides_;
bool will_change_image_size_;
};
}
Q_DECLARE_METATYPE(olive::ShaderJob)
#endif // SHADERJOB_H
+1
View File
@@ -415,6 +415,7 @@ void OpenGLRenderer::Blit(QVariant s, ShaderJob job, Texture *destination, Video
// This variable is used in the shader, let's set it
const NodeValue& value = it.value();
// Arrays are not currently supported in this system
if (value.array()) {
continue;
}
+1 -1
View File
@@ -292,7 +292,7 @@ void Renderer::BlitColorManaged(const ColorTransformJob &color_job, Texture *des
}
ShaderJob job;
job.Insert(QStringLiteral("ove_maintex"), NodeValue(NodeValue::kTexture, QVariant::fromValue(color_job.GetInputTexture())));
job.Insert(QStringLiteral("ove_maintex"), color_job.GetInputTexture());
job.Insert(QStringLiteral("ove_mvpmat"), NodeValue(NodeValue::kMatrix, color_job.GetTransformMatrix()));
job.Insert(QStringLiteral("ove_cropmatrix"), NodeValue(NodeValue::kMatrix, color_job.GetCropMatrix().inverted()));
job.Insert(QStringLiteral("ove_maintex_alpha"), NodeValue(NodeValue::kInt, int(color_job.GetInputAlphaAssociation())));
+30 -21
View File
@@ -54,8 +54,13 @@ TexturePtr RenderProcessor::GenerateTexture(const rational &time, const rational
NodeValue tex_val = table.Get(NodeValue::kTexture);
QElapsedTimer t;
t.restart();
ResolveJobs(tex_val);
qDebug() << "Frame took" << t.elapsed();
return tex_val.toTexture();
}
@@ -406,7 +411,7 @@ NodeValueTable RenderProcessor::GenerateBlockTable(const Track *track, const Tim
}
}
void RenderProcessor::ProcessVideoFootage(TexturePtr destination, const FootageJob &stream, const rational &input_time)
void RenderProcessor::ProcessVideoFootage(TexturePtr destination, const FootageJob *stream, const rational &input_time)
{
if (ticket_->property("type").value<RenderManager::TicketType>() != RenderManager::kTypeVideo) {
// Video cannot contribute to audio, so we do nothing here
@@ -416,7 +421,7 @@ void RenderProcessor::ProcessVideoFootage(TexturePtr destination, const FootageJ
// Check the still frame cache. On large frames such as high resolution still images, uploading
// and color managing them for every frame is a waste of time, so we implement a small cache here
// to optimize such a situation
VideoParams stream_data = stream.video_params();
VideoParams stream_data = stream->video_params();
ColorManager* color_manager = Node::ValueToPtr<ColorManager>(ticket_->property("colormanager"));
@@ -427,9 +432,9 @@ void RenderProcessor::ProcessVideoFootage(TexturePtr destination, const FootageJ
qWarning() << "HAVEN'T GOTTEN DEFAULT INPUT COLORSPACE";
}
Decoder::CodecStream default_codec_stream(stream.filename(), stream_data.stream_index(), GetCurrentBlock());
Decoder::CodecStream default_codec_stream(stream->filename(), stream_data.stream_index(), GetCurrentBlock());
QString decoder_id = stream.decoder();
QString decoder_id = stream->decoder();
DecoderPtr decoder = nullptr;
@@ -447,7 +452,7 @@ void RenderProcessor::ProcessVideoFootage(TexturePtr destination, const FootageJ
QString frame_filename;
int64_t frame_number = stream_data.get_time_in_timebase_units(input_time);
frame_filename = Decoder::TransformImageSequenceFileName(stream.filename(), frame_number);
frame_filename = Decoder::TransformImageSequenceFileName(stream->filename(), frame_number);
// Decoder will close automatically since it's a stream_ptr
decoder->Open(Decoder::CodecStream(frame_filename, stream_data.stream_index(), GetCurrentBlock()));
@@ -458,11 +463,11 @@ void RenderProcessor::ProcessVideoFootage(TexturePtr destination, const FootageJ
if (decoder && render_ctx_) {
Decoder::RetrieveVideoParams p;
p.divider = stream.video_params().divider();
p.divider = stream->video_params().divider();
p.maximum_format = destination->format();
if (!IsCancelled()) {
VideoParams tex_params = stream.video_params();
VideoParams tex_params = stream->video_params();
if (tex_params.is_valid()) {
TexturePtr unmanaged_texture;
@@ -503,16 +508,16 @@ void RenderProcessor::ProcessVideoFootage(TexturePtr destination, const FootageJ
}
}
void RenderProcessor::ProcessAudioFootage(SampleBuffer &destination, const FootageJob &stream, const TimeRange &input_time)
void RenderProcessor::ProcessAudioFootage(SampleBuffer &destination, const FootageJob *stream, const TimeRange &input_time)
{
DecoderPtr decoder = ResolveDecoderFromInput(stream.decoder(), Decoder::CodecStream(stream.filename(), stream.audio_params().stream_index(), nullptr));
DecoderPtr decoder = ResolveDecoderFromInput(stream->decoder(), Decoder::CodecStream(stream->filename(), stream->audio_params().stream_index(), nullptr));
if (decoder) {
const AudioParams& audio_params = GetCacheAudioParams();
Decoder::RetrieveAudioStatus status = decoder->RetrieveAudio(destination,
input_time, audio_params,
stream.cache_path(),
stream->cache_path(),
loop_mode(),
static_cast<RenderMode::Mode>(ticket_->property("mode").toInt()));
@@ -522,13 +527,13 @@ void RenderProcessor::ProcessAudioFootage(SampleBuffer &destination, const Foota
}
}
void RenderProcessor::ProcessShader(TexturePtr destination, const Node *node, const ShaderJob &job)
void RenderProcessor::ProcessShader(TexturePtr destination, const Node *node, const ShaderJob *job)
{
if (!render_ctx_) {
return;
}
QString full_shader_id = QStringLiteral("%1:%2").arg(node->id(), job.GetShaderID());
QString full_shader_id = QStringLiteral("%1:%2").arg(node->id(), job->GetShaderID());
QMutexLocker locker(shader_cache_->mutex());
@@ -536,16 +541,20 @@ void RenderProcessor::ProcessShader(TexturePtr destination, const Node *node, co
if (shader.isNull()) {
// Since we have shader code, compile it now
shader = render_ctx_->CreateNativeShader(node->GetShaderCode(job.GetShaderID()));
shader = render_ctx_->CreateNativeShader(node->GetShaderCode(job->GetShaderID()));
if (shader.isNull()) {
// Couldn't find or build the shader required
return;
}
shader_cache_->insert(full_shader_id, shader);
}
locker.unlock();
// Run shader
render_ctx_->BlitToTexture(shader, job, destination.get());
render_ctx_->BlitToTexture(shader, *job, destination.get());
}
void RenderProcessor::ProcessSamples(SampleBuffer &destination, const Node *node, const TimeRange &range, const SampleJob &job)
@@ -579,16 +588,16 @@ void RenderProcessor::ProcessSamples(SampleBuffer &destination, const Node *node
}
}
void RenderProcessor::ProcessColorTransform(TexturePtr destination, const Node *node, const ColorTransformJob &job)
void RenderProcessor::ProcessColorTransform(TexturePtr destination, const Node *node, const ColorTransformJob *job)
{
if (!render_ctx_) {
return;
}
render_ctx_->BlitColorManaged(job, destination.get());
render_ctx_->BlitColorManaged(*job, destination.get());
}
void RenderProcessor::ProcessFrameGeneration(TexturePtr destination, const Node *node, const GenerateJob &job)
void RenderProcessor::ProcessFrameGeneration(TexturePtr destination, const Node *node, const GenerateJob *job)
{
if (!render_ctx_) {
return;
@@ -599,14 +608,14 @@ void RenderProcessor::ProcessFrameGeneration(TexturePtr destination, const Node
frame->set_video_params(destination->params());
frame->allocate();
node->GenerateFrame(frame, job);
node->GenerateFrame(frame, *job);
destination->Upload(frame->data(), frame->linesize_pixels());
}
TexturePtr RenderProcessor::ProcessVideoCacheJob(const CacheJob &val)
TexturePtr RenderProcessor::ProcessVideoCacheJob(const CacheJob *val)
{
FramePtr frame = FrameHashCache::LoadCacheFrame(val.GetFilename());
FramePtr frame = FrameHashCache::LoadCacheFrame(val->GetFilename());
if (frame) {
TexturePtr tex = CreateTexture(frame->video_params());
if (tex) {
@@ -615,7 +624,7 @@ TexturePtr RenderProcessor::ProcessVideoCacheJob(const CacheJob &val)
}
} else {
QStringList s = ticket_->property("badcache").toStringList();
s.append(val.GetFilename());
s.append(val->GetFilename());
ticket_->setProperty("badcache", s);
}
+6 -6
View File
@@ -44,19 +44,19 @@ public:
protected:
virtual NodeValueTable GenerateBlockTable(const Track *track, const TimeRange &range) override;
virtual void ProcessVideoFootage(TexturePtr destination, const FootageJob &stream, const rational &input_time) override;
virtual void ProcessVideoFootage(TexturePtr destination, const FootageJob *stream, const rational &input_time) override;
virtual void ProcessAudioFootage(SampleBuffer &destination, const FootageJob &stream, const TimeRange &input_time) override;
virtual void ProcessAudioFootage(SampleBuffer &destination, const FootageJob *stream, const TimeRange &input_time) override;
virtual void ProcessShader(TexturePtr destination, const Node *node, const ShaderJob& job) override;
virtual void ProcessShader(TexturePtr destination, const Node *node, const ShaderJob *job) override;
virtual void ProcessSamples(SampleBuffer &destination, const Node *node, const TimeRange &range, const SampleJob &job) override;
virtual void ProcessColorTransform(TexturePtr destination, const Node *node, const ColorTransformJob& job) override;
virtual void ProcessColorTransform(TexturePtr destination, const Node *node, const ColorTransformJob *job) override;
virtual void ProcessFrameGeneration(TexturePtr destination, const Node *node, const GenerateJob& job) override;
virtual void ProcessFrameGeneration(TexturePtr destination, const Node *node, const GenerateJob *job) override;
virtual TexturePtr ProcessVideoCacheJob(const CacheJob &val) override;
virtual TexturePtr ProcessVideoCacheJob(const CacheJob *val) override;
virtual TexturePtr CreateTexture(const VideoParams &p) override;
+4
View File
@@ -31,6 +31,10 @@ Texture::~Texture()
if (renderer_) {
renderer_->DestroyTexture(this);
}
if (job_) {
delete job_;
}
}
void Texture::Upload(void *data, int linesize)
+37 -4
View File
@@ -27,8 +27,12 @@
namespace olive {
class AcceleratedJob;
class Renderer;
class Texture;
using TexturePtr = std::shared_ptr<Texture>;
class Texture
{
public:
@@ -45,17 +49,26 @@ public:
*/
Texture(const VideoParams& param) :
renderer_(nullptr),
params_(param)
params_(param),
job_(nullptr)
{
}
template <typename T>
Texture(const VideoParams &p, const T &j) :
Texture(p)
{
job_ = new T(j);
}
/**
* @brief Construct a real texture linked to a renderer backend
*/
Texture(Renderer* renderer, const QVariant& native, const VideoParams& param) :
renderer_(renderer),
params_(param),
id_(native)
id_(native),
job_(nullptr)
{
}
@@ -71,6 +84,18 @@ public:
return params_;
}
template <typename T>
static TexturePtr Job(const VideoParams &p, const T &j)
{
return std::make_shared<Texture>(p, j);
}
template <typename T>
TexturePtr toJob(const T &job)
{
return Texture::Job(params_, job);
}
void Upload(void* data, int linesize);
void Download(void* data, int linesize);
@@ -90,6 +115,11 @@ public:
return params_.effective_height();
}
QVector2D virtual_resolution() const
{
return QVector2D(params_.square_pixel_width(), params_.height());
}
VideoParams::Format format() const
{
return params_.format();
@@ -115,6 +145,9 @@ public:
return renderer_;
}
bool IsJob() const { return job_; }
AcceleratedJob *job() const { return job_; }
private:
Renderer* renderer_;
@@ -122,9 +155,9 @@ private:
QVariant id_;
};
AcceleratedJob *job_;
using TexturePtr = std::shared_ptr<Texture>;
};
}