diff --git a/source/blender/compositor/realtime_compositor/COM_context.hh b/source/blender/compositor/realtime_compositor/COM_context.hh index 296b4aae0d9..438da5533aa 100644 --- a/source/blender/compositor/realtime_compositor/COM_context.hh +++ b/source/blender/compositor/realtime_compositor/COM_context.hh @@ -112,6 +112,10 @@ class Context { * render pipeline. */ virtual RenderContext *render_context() const; + /* Gets called after the evaluation of each compositor operation. See overrides for possible + * uses. */ + virtual void evaluate_operation_post() const; + /* Returns true if the compositor evaluation is canceled and that the evaluator should stop * executing as soon as possible. */ virtual bool is_canceled() const; diff --git a/source/blender/compositor/realtime_compositor/intern/context.cc b/source/blender/compositor/realtime_compositor/intern/context.cc index 8421455003a..df7c1e93ce7 100644 --- a/source/blender/compositor/realtime_compositor/intern/context.cc +++ b/source/blender/compositor/realtime_compositor/intern/context.cc @@ -26,6 +26,8 @@ RenderContext *Context::render_context() const return nullptr; } +void Context::evaluate_operation_post() const {} + bool Context::is_canceled() const { if (!this->get_node_tree().runtime->test_break) { diff --git a/source/blender/compositor/realtime_compositor/intern/operation.cc b/source/blender/compositor/realtime_compositor/intern/operation.cc index d8f9f7ab508..795d45d083e 100644 --- a/source/blender/compositor/realtime_compositor/intern/operation.cc +++ b/source/blender/compositor/realtime_compositor/intern/operation.cc @@ -39,6 +39,8 @@ void Operation::evaluate() release_inputs(); release_unneeded_results(); + + context().evaluate_operation_post(); } Result &Operation::get_result(StringRef identifier) diff --git a/source/blender/render/intern/compositor.cc b/source/blender/render/intern/compositor.cc index 117d3940acb..fa49ba71688 100644 --- a/source/blender/render/intern/compositor.cc +++ b/source/blender/render/intern/compositor.cc @@ -453,6 +453,21 @@ class Context : public realtime_compositor::Context { { return input_data_.render_context; } + + void evaluate_operation_post() const override + { + /* If no render context exist, that means this is an interactive compositor evaluation due to + * the user editing the node tree. In that case, we wait until the operation finishes executing + * on the GPU before we continue to improve interactivity. The improvement comes from the fact + * that the user might be rapidly changing values, so we need to cancel previous evaluations to + * make editing faster, but we can't do that if all operations are submitted to the GPU all at + * once, and we can't cancel work that was already submitted to the GPU. This does have a + * performance penalty, but in practice, the improved interactivity is worth it according to + * user feedback. */ + if (!this->render_context()) { + GPU_finish(); + } + } }; /* Render Realtime Compositor */