added support for multiple node iterations

Optimizes various effects, particularly blurs.
This commit is contained in:
itsmattkc
2019-12-15 00:39:28 +11:00
parent 23905f1eee
commit 0b7782e129
16 changed files with 82 additions and 30 deletions
+1 -1
View File
@@ -50,7 +50,7 @@ bool AlphaOverBlend::IsAccelerated() const
return true;
}
QString AlphaOverBlend::CodeFragment() const
QString AlphaOverBlend::AcceleratedCodeFragment() const
{
return ReadFileAsString(":/shaders/alphaover.frag");
}
+1 -1
View File
@@ -35,7 +35,7 @@ public:
virtual QString Description() const override;
virtual bool IsAccelerated() const override;
virtual QString CodeFragment() const override;
virtual QString AcceleratedCodeFragment() const override;
protected:
@@ -29,7 +29,7 @@ bool CrossDissolveTransition::IsAccelerated() const
return true;
}
QString CrossDissolveTransition::CodeFragment() const
QString CrossDissolveTransition::AcceleratedCodeFragment() const
{
return ReadFileAsString(":/shaders/crossdissolve.frag");
}
@@ -15,7 +15,7 @@ public:
virtual QString Description() const override;
virtual bool IsAccelerated() const override;
virtual QString CodeFragment() const override;
virtual QString AcceleratedCodeFragment() const override;
};
#endif // CROSSDISSOLVETRANSITION_H
@@ -29,7 +29,7 @@ bool DipToBlackTransition::IsAccelerated() const
return true;
}
QString DipToBlackTransition::CodeFragment() const
QString DipToBlackTransition::AcceleratedCodeFragment() const
{
return ReadFileAsString(":/shaders/diptoblack.frag");
}
@@ -15,7 +15,7 @@ public:
virtual QString Description() const override;
virtual bool IsAccelerated() const override;
virtual QString CodeFragment() const override;
virtual QString AcceleratedCodeFragment() const override;
};
#endif // DIPTOBLACKTRANSITION_H
+1 -1
View File
@@ -70,7 +70,7 @@ bool OpacityNode::IsAccelerated() const
return true;
}
QString OpacityNode::CodeFragment() const
QString OpacityNode::AcceleratedCodeFragment() const
{
return ReadFileAsString(":/shaders/opacity.frag");
}
+1 -1
View File
@@ -40,7 +40,7 @@ public:
virtual void Retranslate() override;
virtual bool IsAccelerated() const override;
virtual QString CodeFragment() const override;
virtual QString AcceleratedCodeFragment() const override;
NodeInput* texture_input() const;
+1 -1
View File
@@ -58,7 +58,7 @@ bool SolidGenerator::IsAccelerated() const
return true;
}
QString SolidGenerator::CodeFragment() const
QString SolidGenerator::AcceleratedCodeFragment() const
{
return ReadFileAsString(":/shaders/solid.frag");
}
+1 -1
View File
@@ -42,7 +42,7 @@ public:
virtual QString Description() const override;
virtual bool IsAccelerated() const override;
virtual QString CodeFragment() const override;
virtual QString AcceleratedCodeFragment() const override;
virtual void Retranslate() override;
+2 -2
View File
@@ -51,12 +51,12 @@ bool VideoInput::IsAccelerated() const
return true;
}
QString VideoInput::CodeVertex() const
QString VideoInput::AcceleratedCodeVertex() const
{
return ReadFileAsString(":/shaders/videoinput.vert");
}
QString VideoInput::CodeFragment() const
QString VideoInput::AcceleratedCodeFragment() const
{
return ReadFileAsString(":/shaders/videoinput.frag");
}
+2 -2
View File
@@ -21,8 +21,8 @@ public:
NodeInput* matrix_input() const;
virtual bool IsAccelerated() const override;
virtual QString CodeVertex() const override;
virtual QString CodeFragment() const override;
virtual QString AcceleratedCodeVertex() const override;
virtual QString AcceleratedCodeFragment() const override;
virtual void Retranslate() override;
+12 -2
View File
@@ -370,16 +370,26 @@ bool Node::IsAccelerated() const
return false;
}
QString Node::CodeVertex() const
QString Node::AcceleratedCodeVertex() const
{
return QString();
}
QString Node::CodeFragment() const
QString Node::AcceleratedCodeFragment() const
{
return QString();
}
int Node::AcceleratedCodeIterations() const
{
return 1;
}
NodeInput *Node::AcceleratedCodeIterativeInput() const
{
return nullptr;
}
NodeParam *Node::GetParameterWithID(const QString &id) const
{
foreach (NodeParam* param, params_) {
+14 -2
View File
@@ -137,12 +137,24 @@ public:
/**
* @brief Generate hardware accelerated code for this Node
*/
virtual QString CodeVertex() const;
virtual QString AcceleratedCodeVertex() const;
/**
* @brief Generate hardware accelerated code for this Node
*/
virtual QString CodeFragment() const;
virtual QString AcceleratedCodeFragment() const;
/**
* @brief Number of iterations to run the accelerated code
*
* Some code is faster if it's merely repeated on a resulting texture rather than run once on the same buffer.
*/
virtual int AcceleratedCodeIterations() const;
/**
* @brief Parameter that should receive the buffer on an iteration past the first
*/
virtual NodeInput* AcceleratedCodeIterativeInput() const;
/**
* @brief Returns the parameter with the specified ID (or nullptr if it doesn't exist)
+2 -2
View File
@@ -86,8 +86,8 @@ bool OpenGLBackend::CompileInternal()
// Since we have shader code, compile it now
OpenGLShaderPtr program;
QString frag_code = n->CodeFragment();
QString vert_code = n->CodeVertex();
QString frag_code = n->AcceleratedCodeFragment();
QString vert_code = n->AcceleratedCodeVertex();
if (frag_code.isEmpty()) {
frag_code = OpenGLShader::CodeDefaultFragment();
+40 -10
View File
@@ -154,11 +154,15 @@ void OpenGLWorker::RunNodeAccelerated(const Node *node, const TimeRange &range,
return;
}
// Create the output texture
OpenGLTextureCache::ReferencePtr output_ref = texture_cache_->Get(ctx_, video_params());
// Create the output textures
QList<OpenGLTextureCache::ReferencePtr> dst_refs;
dst_refs.append(texture_cache_->Get(ctx_, video_params()));
GLuint iterative_input = 0;
buffer_.Attach(output_ref->texture(), true);
buffer_.Bind();
// If this node requires multiple iterations, get a texture for it too
if (node->AcceleratedCodeIterations() > 1 && node->AcceleratedCodeIterativeInput()) {
dst_refs.append(texture_cache_->Get(ctx_, video_params()));
}
// Lock the shader so no other thread interferes as we set parameters and draw (and we don't interfere with any others)
shader->Lock();
@@ -237,6 +241,11 @@ void OpenGLWorker::RunNodeAccelerated(const Node *node, const TimeRange &range,
}
}
// If this texture binding is the iterative input, set it here
if (input == node->AcceleratedCodeIterativeInput()) {
iterative_input = input_texture_count;
}
olive::gl::PrepareToDraw(functions_);
input_texture_count++;
@@ -300,8 +309,32 @@ void OpenGLWorker::RunNodeAccelerated(const Node *node, const TimeRange &range,
}
}
// Blit this texture through this shader
olive::gl::Blit(shader);
// Some nodes use multiple iterations for optimization
OpenGLTextureCache::ReferencePtr output_tex;
for (int iteration=0;iteration<node->AcceleratedCodeIterations();iteration++) {
// Set iteration number
shader->setUniformValue("ove_iteration", iteration);
// If this is not the first iteration, set the parameter that will receive the last iteration's texture
OpenGLTextureCache::ReferencePtr source_tex = dst_refs.at((iteration+1)%dst_refs.size());
OpenGLTextureCache::ReferencePtr destination_tex = dst_refs.at(iteration%dst_refs.size());
if (iteration > 0) {
functions_->glActiveTexture(GL_TEXTURE0 + iterative_input);
functions_->glBindTexture(GL_TEXTURE_2D, source_tex->texture()->texture());
}
buffer_.Attach(destination_tex->texture(), true);
buffer_.Bind();
// Blit this texture through this shader
olive::gl::Blit(shader);
buffer_.Release();
buffer_.Detach();
// Update output reference to the last texture we wrote to
output_tex = destination_tex;
}
// Make sure all OpenGL functions are complete by this point before unlocking the shader (or another thread may
// change its parameters before our drawing in this thread is done)
@@ -319,10 +352,7 @@ void OpenGLWorker::RunNodeAccelerated(const Node *node, const TimeRange &range,
shader->release();
buffer_.Release();
buffer_.Detach();
output_params->Push(NodeParam::kTexture, QVariant::fromValue(output_ref));
output_params->Push(NodeParam::kTexture, QVariant::fromValue(output_tex));
}
void OpenGLWorker::TextureToBuffer(const QVariant &tex_in, QByteArray &buffer)