fixed various caching issues

This commit is contained in:
itsmattkc
2019-09-02 22:58:44 +10:00
parent 3a9af58344
commit 12bc5839a6
19 changed files with 196 additions and 61 deletions
+5 -10
View File
@@ -27,6 +27,7 @@ Block::Block() :
{
previous_input_ = new NodeInput("prev_block");
previous_input_->add_data_input(NodeParam::kBlock);
previous_input_->set_dependent(false);
AddParameter(previous_input_);
block_output_ = new NodeOutput("block_out");
@@ -63,8 +64,12 @@ const rational& Block::length()
void Block::set_length(const rational &length)
{
Lock();
length_ = length;
Unlock();
RefreshFollowing();
}
@@ -181,16 +186,6 @@ void Block::set_media_in(const rational &media_in)
}
}
QList<NodeDependency> Block::RunDependencies(NodeOutput* param, const rational &time)
{
// Base Blocks have no direct dependencies
Q_UNUSED(param)
Q_UNUSED(time)
return QList<NodeDependency>();
}
rational Block::SequenceToMediaTime(const rational &sequence_time)
{
// These constants are not considered "values" per se, so we don't modify them
-5
View File
@@ -67,11 +67,6 @@ public:
const rational& media_in();
void set_media_in(const rational& media_in);
/**
* @brief Override removes previous input as that is not a direct dependency
*/
virtual QList<NodeDependency> RunDependencies(NodeOutput* output, const rational &time) override;
public slots:
/**
* @brief Refreshes internal cache of in/out points up to date
+33 -5
View File
@@ -20,11 +20,13 @@
#include "input.h"
#include "node.h"
#include "output.h"
NodeInput::NodeInput(const QString& id) :
NodeParam(id),
keyframing_(false)
keyframing_(false),
dependent_(true)
{
// Have at least one keyframe/value active at any time
keyframes_.append(NodeKeyframe());
@@ -74,8 +76,6 @@ QVariant NodeInput::get_value(const rational& time)
{
QVariant v;
lock_.lock();
if (time_ != time) {
// Retrieve the value
if (!edges_.isEmpty()) {
@@ -92,13 +92,15 @@ QVariant NodeInput::get_value(const rational& time)
v = value_;
lock_.unlock();
return v;
}
void NodeInput::set_value(const QVariant &value)
{
bool lock_mutex = (parent() != nullptr);
if (lock_mutex) parent()->Lock();
if (keyframing()) {
// FIXME: Keyframing code using time()
} else {
@@ -107,6 +109,8 @@ void NodeInput::set_value(const QVariant &value)
emit ValueChanged(RATIONAL_MIN, RATIONAL_MAX);
}
if (lock_mutex) parent()->Unlock();
}
bool NodeInput::keyframing()
@@ -119,7 +123,31 @@ void NodeInput::set_keyframing(bool k)
keyframing_ = k;
}
bool NodeInput::dependent()
{
return dependent_;
}
void NodeInput::set_dependent(bool d)
{
dependent_ = d;
}
const QList<NodeParam::DataType> &NodeInput::inputs()
{
return inputs_;
}
void NodeInput::CopyValues(NodeInput *source, NodeInput *dest)
{
// Copy values
dest->keyframes_ = source->keyframes_;
// Copy keyframing state
dest->set_keyframing(source->keyframing());
// Copy connections
if (source->get_connected_output() != nullptr) {
ConnectEdge(source->get_connected_output(), dest);
}
}
+22
View File
@@ -103,11 +103,28 @@ public:
*/
void set_keyframing(bool k);
/**
* @brief Return whether the Node is dependent on this input or not
*
* \see set_dependent()
*/
bool dependent();
/**
* @brief Set whether the Node is dependent on this input
*/
void set_dependent(bool d);
/**
* @brief A list of input data types accepted by this parameter
*/
const QList<DataType>& inputs();
/**
* @brief Copy all values including keyframe information and connections from another NodeInput
*/
static void CopyValues(NodeInput* source, NodeInput* dest);
signals:
void ValueChanged(const rational& start, const rational& end);
@@ -132,6 +149,11 @@ private:
*/
bool keyframing_;
/**
* @brief Internal dependent setting
*/
bool dependent_;
};
#endif // NODEINPUT_H
-1
View File
@@ -103,7 +103,6 @@ void MediaInput::Hash(QCryptographicHash *hash, NodeOutput *from, const rational
// Use frame value from Decoder
if (from == texture_output_ && SetupDecoder()) {
qDebug() << "[MediaInput] Hashing pts" << decoder_->GetTimestampFromTime(time);
hash->addData(QString::number(decoder_->GetTimestampFromTime(time)).toUtf8());
// FIXME: Add OCIO data
// FIXME: Add alpha association value
+46 -13
View File
@@ -98,6 +98,36 @@ void Node::InvalidateCache(const rational &start_range, const rational &end_rang
}
}
void Node::Lock()
{
lock_.lock();
}
void Node::Unlock()
{
lock_.unlock();
}
void Node::CopyInputs(Node *source, Node *destination)
{
Q_ASSERT(source->id() == destination->id());
QList<NodeParam*> src_param = source->parameters();
QList<NodeParam*> dst_param = destination->parameters();
for (int i=0;i<src_param.size();i++) {
if (src_param.at(i)->type() == NodeParam::kInput) {
NodeInput* src = static_cast<NodeInput*>(src_param.at(i));
if (src->dependent()) {
NodeInput* dst = static_cast<NodeInput*>(dst_param.at(i));
NodeInput::CopyValues(src, dst);
}
}
}
}
void Node::IgnoreCacheInvalidationFrom(NodeInput *input)
{
ignore_invalid_cache_inputs_.append(input);
@@ -131,13 +161,7 @@ NodeOutput *Node::LastProcessedOutput()
QVariant Node::Run(NodeOutput* output, const rational& time)
{
lock_.lock();
QVariant v = Value(output, time);
lock_.unlock();
return v;
return Value(output, time);
}
NodeParam *Node::ParamAt(int index)
@@ -178,7 +202,9 @@ void GetDependenciesInternal(Node* n, QList<Node*>& list, bool traverse) {
foreach (NodeEdgePtr edge, param_edges) {
Node* connected_node = edge->output()->parent();
list.append(connected_node);
if (!list.contains(connected_node)) {
list.append(connected_node);
}
if (traverse) {
GetDependenciesInternal(connected_node, list, traverse);
@@ -250,13 +276,17 @@ QList<NodeDependency> Node::RunDependencies(NodeOutput *output, const rational &
foreach (NodeParam* p, params) {
if (p->type() == NodeParam::kInput) {
NodeOutput* potential_dep = static_cast<NodeInput*>(p)->get_connected_output();
NodeInput* input = static_cast<NodeInput*>(p);
if (potential_dep != nullptr) {
run_deps.append(NodeDependency(potential_dep, time));
// Check if Node is dependent on this input or not
if (input->dependent()) {
NodeOutput* potential_dep = input->get_connected_output();
if (potential_dep != nullptr) {
run_deps.append(NodeDependency(potential_dep, time));
}
}
}
}
return run_deps;
@@ -285,11 +315,14 @@ void Node::Hash(QCryptographicHash *hash, NodeOutput* from, const rational &time
{
// Add this Node's ID
hash->addData(id().toUtf8());
qDebug() << "Hashing" << id();
// Add each value
QList<NodeParam*> params = parameters();
foreach (NodeParam* param, params) {
if (param->type() == NodeParam::kInput && !param->IsConnected()) {
if (param->type() == NodeParam::kInput
&& !param->IsConnected()
&& static_cast<NodeInput*>(param)->dependent()) {
// Get the value at this time
QVariant v = static_cast<NodeInput*>(param)->get_value(time);
hash->addData(v.toByteArray()); // FIXME: Does this work on all value types?
+20 -3
View File
@@ -130,9 +130,9 @@ public:
QList<Node*> GetImmediateDependencies();
/**
* @brief Thread-safe wrapper for Process()
* @brief Wrapper for Process()
*
* It's recommended to call this directly over Process(), yet in derivatives of Node, override Process().
* It's recommended to call this directly over Value(), yet in derivatives of Node, override Value().
*/
QVariant Run(NodeOutput* output, const rational& time);
@@ -175,6 +175,23 @@ public:
*/
virtual void InvalidateCache(const rational& start_range, const rational& end_range, NodeInput* from = nullptr);
/**
* @brief Lock mutex (for thread safety)
*/
void Lock();
/**
* @brief Unock mutex (for thread safety)
*/
void Unlock();
/**
* @brief Copies inputs from from Node to another including connections
*
* Nodes must be of the same types (i.e. have the same ID)
*/
static void CopyInputs(Node* source, Node* destination);
protected:
/**
* @brief Add a parameter to this node
@@ -265,7 +282,7 @@ private:
NodeOutput* last_processed_parameter_;
/**
* @brief Used for thread safety in Run()
* @brief Used for thread safety
*/
QMutex lock_;
-4
View File
@@ -51,8 +51,6 @@ QVariant NodeOutput::get_value(const rational& time)
{
QVariant v;
lock_.lock();
if (time_ != time) {
// Update the value
value_ = parent()->Run(this, time);
@@ -62,8 +60,6 @@ QVariant NodeOutput::get_value(const rational& time)
v = value_;
lock_.unlock();
return v;
}
+19
View File
@@ -31,6 +31,7 @@ TrackOutput::TrackOutput() :
{
track_input_ = new NodeInput("track_in");
track_input_->add_data_input(NodeParam::kTrack);
track_input_->set_dependent(false);
AddParameter(track_input_);
track_output_ = new NodeOutput("track_out");
@@ -359,6 +360,10 @@ void TrackOutput::RemoveBlock(Block *block)
void TrackOutput::RippleRemoveBlock(Block *block)
{
BlockInvalidateCache();
rational remove_in = block->in();
Block* previous = block->previous();
Block* next = block->next();
@@ -374,6 +379,10 @@ void TrackOutput::RippleRemoveBlock(Block *block)
Block::ConnectBlocks(previous, next);
}
UnblockInvalidateCache();
InvalidateCache(remove_in, in());
// FIXME: Should there be removing the Blocks from the graph?
}
@@ -391,8 +400,12 @@ Block* TrackOutput::SplitBlock(Block *block, rational time)
Block* copy = block->copy();
copy->set_length(original_length - block->length());
copy->set_media_in(block->media_in() + block->length());
InsertBlockAfter(copy, block);
Node::CopyInputs(block, copy);
UnblockInvalidateCache();
return copy;
@@ -449,6 +462,8 @@ void TrackOutput::RippleRemoveArea(rational in, rational out, Block *insert)
}
}
BlockInvalidateCache();
// If we picked up a block to splice
if (splice != nullptr) {
@@ -495,6 +510,10 @@ void TrackOutput::RippleRemoveArea(rational in, rational out, Block *insert)
InsertBlockBetweenBlocks(insert, trim_out_to_in, trim_in_to_out);
}
}
UnblockInvalidateCache();
InvalidateCache(in, out);
}
void TrackOutput::ReplaceBlock(Block *old, Block *replace)
+12
View File
@@ -149,11 +149,17 @@ NodeEdgePtr NodeParam::ConnectEdge(NodeOutput *output, NodeInput *input)
NodeEdgePtr edge = std::make_shared<NodeEdge>(output, input);
output->parent()->Lock();
input->parent()->Lock();
output->edges_.append(edge);
input->edges_.append(edge);
input->ClearCachedValue();
output->parent()->Unlock();
input->parent()->Unlock();
// Emit a signal than an edge was added (only one signal needs emitting)
emit input->EdgeAdded(edge);
@@ -165,11 +171,17 @@ void NodeParam::DisconnectEdge(NodeEdgePtr edge)
NodeOutput* output = edge->output();
NodeInput* input = edge->input();
output->parent()->Lock();
input->parent()->Lock();
output->edges_.removeAll(edge);
input->edges_.removeAll(edge);
input->ClearCachedValue();
output->parent()->Unlock();
input->parent()->Unlock();
emit input->EdgeRemoved(edge);
}
-5
View File
@@ -231,11 +231,6 @@ protected:
*/
QVector<NodeEdgePtr> edges_;
/**
* @brief Used for thread safety
*/
QMutex lock_;
/**
* @brief Currently cached value
*/
+4
View File
@@ -98,6 +98,8 @@ QVariant RendererProcessor::Value(NodeOutput* output, const rational& time)
// Find frame in map
if (time_hash_map_.contains(time)) {
qDebug() << "Showed:" << time_hash_map_[time].toHex();
QString fn = CachePathName(time_hash_map_[time]);
if (QFileInfo::exists(fn)) {
@@ -362,6 +364,8 @@ void RendererProcessor::DownloadThreadFinished(const rational& time)
texture_output_->ClearCachedValue();
foreach (NodeEdgePtr edge, edges) {
edge->input()->ClearCachedValue();
edge->input()->parent()->InvalidateCache(time,
time,
edge->input());
@@ -85,11 +85,20 @@ void RendererProcessThread::ProcessLoop()
NodeOutput* output_to_process = path_.node();
Node* node_to_process = output_to_process->parent();
node_to_process->Lock();
QList<Node*> all_deps = node_to_process->GetDependencies();
foreach (Node* dep, all_deps) {
dep->Lock();
}
// Check hash
QCryptographicHash hasher(QCryptographicHash::Sha1);
node_to_process->Hash(&hasher, output_to_process, path_.time());
hash_ = hasher.result();
texture_ = nullptr;
if (!parent_->HasHash(hash_)) {
QList<NodeDependency> deps = node_to_process->RunDependencies(output_to_process, path_.time());
@@ -106,6 +115,12 @@ void RendererProcessThread::ProcessLoop()
render_instance()->context()->functions()->glFinish();
}
foreach (Node* dep, all_deps) {
dep->Unlock();
}
node_to_process->Unlock();
emit FinishedPath();
}
}
@@ -31,6 +31,7 @@ RendererThreadBase::RendererThreadBase(QOpenGLContext *share_ctx, const int &wid
mode_(mode),
render_instance_(nullptr)
{
connect(share_ctx_, SIGNAL(aboutToBeDestroyed()), this, SLOT(Cancel()));
}
void RendererThreadBase::Cancel()
@@ -39,14 +39,15 @@ public:
const olive::PixelFormat& format,
const olive::RenderMode& mode);
void Cancel();
RenderInstance* render_instance();
void StartThread(Priority priority = InheritPriority);
virtual void run() override;
public slots:
void Cancel();
protected:
virtual void ProcessLoop() = 0;
+4
View File
@@ -48,6 +48,8 @@ void RenderFramebuffer::Create(QOpenGLContext *ctx)
context_ = ctx;
connect(context_, SIGNAL(aboutToBeDestroyed()), this, SLOT(Destroy()));
// Create framebuffer object
context_->functions()->glGenFramebuffers(1, &buffer_);
}
@@ -55,6 +57,8 @@ void RenderFramebuffer::Create(QOpenGLContext *ctx)
void RenderFramebuffer::Destroy()
{
if (context_ != nullptr) {
disconnect(context_, SIGNAL(aboutToBeDestroyed()), this, SLOT(Destroy()));
context_->functions()->glDeleteFramebuffers(1, &buffer_);
buffer_ = 0;
+4 -2
View File
@@ -27,6 +27,7 @@
class RenderFramebuffer : public QObject
{
Q_OBJECT
public:
RenderFramebuffer();
~RenderFramebuffer();
@@ -37,8 +38,6 @@ public:
void Create(QOpenGLContext *ctx);
void Destroy();
bool IsCreated() const;
void Bind();
@@ -53,6 +52,9 @@ public:
const GLuint& buffer() const;
public slots:
void Destroy();
private:
void AttachInternal(GLuint tex);
+4 -4
View File
@@ -25,10 +25,6 @@
#include "render/pixelservice.h"
// FIXME: Test code
QMutex m;
// End test code
RenderTexture::RenderTexture() :
context_(nullptr),
texture_(0)
@@ -64,6 +60,8 @@ void RenderTexture::Create(QOpenGLContext *ctx, int width, int height, const oli
height_ = height;
format_ = format;
connect(context_, SIGNAL(aboutToBeDestroyed()), this, SLOT(Destroy()));
// Create main texture
CreateInternal(&texture_, data);
@@ -76,6 +74,8 @@ void RenderTexture::Create(QOpenGLContext *ctx, int width, int height, const oli
void RenderTexture::Destroy()
{
if (context_ != nullptr) {
disconnect(context_, SIGNAL(aboutToBeDestroyed()), this, SLOT(Destroy()));
context_->functions()->glDeleteTextures(1, &texture_);
texture_ = 0;
+4 -7
View File
@@ -26,13 +26,9 @@
#include "pixelformat.h"
// FIXME: Test code
#include <QMutex>
extern QMutex m;
// End test code
class RenderTexture : public QObject
{
Q_OBJECT
public:
enum Type {
kSingleBuffer,
@@ -51,8 +47,6 @@ public:
bool IsCreated() const;
void Destroy();
void Bind();
void Release();
@@ -73,6 +67,9 @@ public:
uchar *Download() const;
public slots:
void Destroy();
private:
void CreateInternal(GLuint *tex, void *data = nullptr);