nodes: rework so that jobs can be completely deferred
Big optimization requiring a lot of refactoring.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
class FootageJob
|
||||
class FootageJob : public AcceleratedJob
|
||||
{
|
||||
public:
|
||||
FootageJob() :
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
class SampleJob : public AcceleratedJob {
|
||||
class SampleJob : public AcceleratedJob
|
||||
{
|
||||
public:
|
||||
SampleJob()
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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())));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -31,6 +31,10 @@ Texture::~Texture()
|
||||
if (renderer_) {
|
||||
renderer_->DestroyTexture(this);
|
||||
}
|
||||
|
||||
if (job_) {
|
||||
delete job_;
|
||||
}
|
||||
}
|
||||
|
||||
void Texture::Upload(void *data, int linesize)
|
||||
|
||||
+37
-4
@@ -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>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user