Realtime Compositor: Support canceling evaluation

This patch adds support for canceling compositor evaluations for the
realtime compositor. Only the canceling of the Denoise operation is
supported for now. That's because inter-operation canceling is not
feasible since all work will have been submitted to the GPU driver
before the user is able to cancel. So some kind of blocking operations
would need to used to actually allow canceling, which is not something
we are going to investigate as part of this patch.

Pull Request: https://projects.blender.org/blender/blender/pulls/117725
This commit is contained in:
Omar Emara
2024-02-16 08:32:03 +01:00
committed by Omar Emara
parent 8cfcd64185
commit e7ffe74920
3 changed files with 29 additions and 0 deletions

View File

@@ -112,6 +112,10 @@ class Context {
* render pipeline. */
virtual RenderContext *render_context() 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;
/* Get the size of the compositing region. See get_compositing_region(). The output size is
* sanitized such that it is at least 1 in both dimensions. However, the developer is expected to
* gracefully handled zero sizes regions by checking the is_valid_compositing_region method. */

View File

@@ -5,10 +5,13 @@
#include "BLI_math_vector.hh"
#include "BLI_rect.h"
#include "DNA_node_types.h"
#include "DNA_vec_types.h"
#include "GPU_shader.h"
#include "BKE_node_runtime.hh"
#include "COM_context.hh"
#include "COM_render_context.hh"
#include "COM_static_cache_manager.hh"
@@ -23,6 +26,14 @@ RenderContext *Context::render_context() const
return nullptr;
}
bool Context::is_canceled() const
{
if (!this->get_node_tree().runtime->test_break) {
return false;
}
return this->get_node_tree().runtime->test_break(get_node_tree().runtime->tbh);
}
int2 Context::get_compositing_region_size() const
{
const rcti compositing_region = get_compositing_region();

View File

@@ -76,6 +76,17 @@ static void node_composit_buts_denoise(uiLayout *layout, bContext * /*C*/, Point
using namespace blender::realtime_compositor;
/* A callback to cancel the filter operations by evaluating the context's is_canceled method. The
* API specifies that true indicates the filter should continue, while false indicates it should
* stop, so invert the condition. This callback can also be used to track progress using the given
* n argument, but we currently don't make use of it. See OIDNProgressMonitorFunction in the API
* for more information. */
static bool oidn_progress_monitor_function(void *user_ptr, double /*n*/)
{
const Context *context = static_cast<const Context *>(user_ptr);
return !context->is_canceled();
}
class DenoiseOperation : public NodeOperation {
public:
using NodeOperation::NodeOperation;
@@ -108,6 +119,7 @@ class DenoiseOperation : public NodeOperation {
filter.setImage("output", color, oidn::Format::Float3, width, height, 0, pixel_stride);
filter.set("hdr", use_hdr());
filter.set("cleanAux", auxiliary_passes_are_clean());
filter.setProgressMonitorFunction(oidn_progress_monitor_function, &context());
/* If the albedo input is not a single value input, download the albedo texture, denoise it
* in-place if denoising auxiliary passes is needed, and set it to the main filter. */
@@ -122,6 +134,7 @@ class DenoiseOperation : public NodeOperation {
"albedo", albedo, oidn::Format::Float3, width, height, 0, pixel_stride);
albedoFilter.setImage(
"output", albedo, oidn::Format::Float3, width, height, 0, pixel_stride);
albedoFilter.setProgressMonitorFunction(oidn_progress_monitor_function, &context());
albedoFilter.commit();
albedoFilter.execute();
}
@@ -144,6 +157,7 @@ class DenoiseOperation : public NodeOperation {
"normal", normal, oidn::Format::Float3, width, height, 0, pixel_stride);
normalFilter.setImage(
"output", normal, oidn::Format::Float3, width, height, 0, pixel_stride);
normalFilter.setProgressMonitorFunction(oidn_progress_monitor_function, &context());
normalFilter.commit();
normalFilter.execute();
}