added support for multiple node iterations
Optimizes various effects, particularly blurs.
This commit is contained in:
@@ -50,7 +50,7 @@ bool AlphaOverBlend::IsAccelerated() const
|
||||
return true;
|
||||
}
|
||||
|
||||
QString AlphaOverBlend::CodeFragment() const
|
||||
QString AlphaOverBlend::AcceleratedCodeFragment() const
|
||||
{
|
||||
return ReadFileAsString(":/shaders/alphaover.frag");
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -70,7 +70,7 @@ bool OpacityNode::IsAccelerated() const
|
||||
return true;
|
||||
}
|
||||
|
||||
QString OpacityNode::CodeFragment() const
|
||||
QString OpacityNode::AcceleratedCodeFragment() const
|
||||
{
|
||||
return ReadFileAsString(":/shaders/opacity.frag");
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ bool SolidGenerator::IsAccelerated() const
|
||||
return true;
|
||||
}
|
||||
|
||||
QString SolidGenerator::CodeFragment() const
|
||||
QString SolidGenerator::AcceleratedCodeFragment() const
|
||||
{
|
||||
return ReadFileAsString(":/shaders/solid.frag");
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user