[Bf-blender-cvs] [063b52b7f28] temp-compositor-fixes: Compositor: Add OIDN prefiltering option to Denoise node

Manuel Castilla noreply at git.blender.org
Sun Sep 19 20:40:54 CEST 2021


Commit: 063b52b7f283a191b72dd48a3dadfeeea5cf42e1
Author: Manuel Castilla
Date:   Sun Sep 19 20:12:53 2021 +0200
Branches: temp-compositor-fixes
https://developer.blender.org/rB063b52b7f283a191b72dd48a3dadfeeea5cf42e1

Compositor: Add OIDN prefiltering option to Denoise node

It's equivalent to the OpenImageDenoise prefiltering option in Cycles.
See D12043.

Prefilter modes:
- None: No prefiltering, use when guiding passes are noise-free.
- Fast: Denoise image and guiding passes together. Improves quality when
guiding passes are noisy using least amount of extra processing time.
- Accurate: Prefilter noisy guiding passes before denoising image.
Improves quality when guiding passes are noisy using extra
processing time.

Reviewed By: #compositing, jbakker, sergey

Differential Revision: https://developer.blender.org/D12342

===================================================================

M	source/blender/compositor/nodes/COM_DenoiseNode.cc
M	source/blender/compositor/operations/COM_DenoiseOperation.cc
M	source/blender/compositor/operations/COM_DenoiseOperation.h
M	source/blender/editors/space_node/drawnode.cc
M	source/blender/makesdna/DNA_node_types.h
M	source/blender/makesrna/intern/rna_nodetree.c
M	source/blender/nodes/composite/nodes/node_composite_denoise.c

===================================================================

diff --git a/source/blender/compositor/nodes/COM_DenoiseNode.cc b/source/blender/compositor/nodes/COM_DenoiseNode.cc
index e58a9c7ba9a..cc9328414ef 100644
--- a/source/blender/compositor/nodes/COM_DenoiseNode.cc
+++ b/source/blender/compositor/nodes/COM_DenoiseNode.cc
@@ -31,6 +31,12 @@ DenoiseNode::DenoiseNode(bNode *editorNode) : Node(editorNode)
 void DenoiseNode::convertToOperations(NodeConverter &converter,
                                       const CompositorContext & /*context*/) const
 {
+  if (!COM_is_denoise_supported()) {
+    converter.mapOutputSocket(getOutputSocket(0),
+                              converter.addInputProxy(getInputSocket(0), false));
+    return;
+  }
+
   bNode *node = this->getbNode();
   NodeDenoise *denoise = (NodeDenoise *)node->storage;
 
@@ -39,8 +45,28 @@ void DenoiseNode::convertToOperations(NodeConverter &converter,
   operation->setDenoiseSettings(denoise);
 
   converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0));
-  converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
-  converter.mapInputSocket(getInputSocket(2), operation->getInputSocket(2));
+  if (denoise && denoise->prefilter == CMP_NODE_DENOISE_PREFILTER_ACCURATE) {
+    {
+      DenoisePrefilterOperation *normal_prefilter = new DenoisePrefilterOperation(
+          DataType::Vector);
+      normal_prefilter->set_image_name("normal");
+      converter.addOperation(normal_prefilter);
+      converter.mapInputSocket(getInputSocket(1), normal_prefilter->getInputSocket(0));
+      converter.addLink(normal_prefilter->getOutputSocket(), operation->getInputSocket(1));
+    }
+    {
+      DenoisePrefilterOperation *albedo_prefilter = new DenoisePrefilterOperation(DataType::Color);
+      albedo_prefilter->set_image_name("albedo");
+      converter.addOperation(albedo_prefilter);
+      converter.mapInputSocket(getInputSocket(2), albedo_prefilter->getInputSocket(0));
+      converter.addLink(albedo_prefilter->getOutputSocket(), operation->getInputSocket(2));
+    }
+  }
+  else {
+    converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
+    converter.mapInputSocket(getInputSocket(2), operation->getInputSocket(2));
+  }
+
   converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0));
 }
 
diff --git a/source/blender/compositor/operations/COM_DenoiseOperation.cc b/source/blender/compositor/operations/COM_DenoiseOperation.cc
index e7f2d5a740a..0c660e0b723 100644
--- a/source/blender/compositor/operations/COM_DenoiseOperation.cc
+++ b/source/blender/compositor/operations/COM_DenoiseOperation.cc
@@ -28,6 +28,137 @@ static pthread_mutex_t oidn_lock = BLI_MUTEX_INITIALIZER;
 
 namespace blender::compositor {
 
+bool COM_is_denoise_supported()
+{
+#ifdef WITH_OPENIMAGEDENOISE
+  /* Always supported through Accelerate framework BNNS on macOS. */
+#  ifdef __APPLE__
+  return true;
+#  else
+  return BLI_cpu_support_sse41();
+#  endif
+
+#else
+  return false;
+#endif
+}
+
+class DenoiseFilter {
+ private:
+#ifdef WITH_OPENIMAGEDENOISE
+  oidn::DeviceRef device;
+  oidn::FilterRef filter;
+#endif
+  bool initialized_ = false;
+
+ public:
+  ~DenoiseFilter()
+  {
+    BLI_assert(!initialized_);
+  }
+
+#ifdef WITH_OPENIMAGEDENOISE
+  void init_and_lock_denoiser(MemoryBuffer *output)
+  {
+    /* Since it's memory intensive, it's better to run only one instance of OIDN at a time.
+     * OpenImageDenoise is multithreaded internally and should use all available cores
+     * nonetheless. */
+    BLI_mutex_lock(&oidn_lock);
+
+    device = oidn::newDevice();
+    device.commit();
+    filter = device.newFilter("RT");
+    initialized_ = true;
+    set_image("output", output);
+  }
+
+  void deinit_and_unlock_denoiser()
+  {
+    BLI_mutex_unlock(&oidn_lock);
+    initialized_ = false;
+  }
+
+  void set_image(const StringRef name, MemoryBuffer *buffer)
+  {
+    BLI_assert(initialized_);
+    BLI_assert(!buffer->is_a_single_elem());
+    filter.setImage(name.data(),
+                    buffer->getBuffer(),
+                    oidn::Format::Float3,
+                    buffer->getWidth(),
+                    buffer->getHeight(),
+                    0,
+                    buffer->get_elem_bytes_len());
+  }
+
+  template<typename T> void set(const StringRef option_name, T value)
+  {
+    BLI_assert(initialized_);
+    filter.set(option_name.data(), value);
+  }
+
+  void execute()
+  {
+    BLI_assert(initialized_);
+    filter.commit();
+    filter.execute();
+  }
+
+#else
+  void init_and_lock_denoiser(MemoryBuffer *UNUSED(output))
+  {
+  }
+
+  void deinit_and_unlock_denoiser()
+  {
+  }
+
+  void set_image(const StringRef UNUSED(name), MemoryBuffer *UNUSED(buffer))
+  {
+  }
+
+  template<typename T> void set(const StringRef UNUSED(option_name), T UNUSED(value))
+  {
+  }
+
+  void execute()
+  {
+  }
+#endif
+};
+
+DenoiseBaseOperation::DenoiseBaseOperation()
+{
+  flags.is_fullframe_operation = true;
+  output_rendered_ = false;
+}
+
+bool DenoiseBaseOperation::determineDependingAreaOfInterest(rcti * /*input*/,
+                                                            ReadBufferOperation *readOperation,
+                                                            rcti *output)
+{
+  if (isCached()) {
+    return false;
+  }
+
+  rcti newInput;
+  newInput.xmax = this->getWidth();
+  newInput.xmin = 0;
+  newInput.ymax = this->getHeight();
+  newInput.ymin = 0;
+  return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
+}
+
+void DenoiseBaseOperation::get_area_of_interest(const int UNUSED(input_idx),
+                                                const rcti &UNUSED(output_area),
+                                                rcti &r_input_area)
+{
+  r_input_area.xmin = 0;
+  r_input_area.xmax = this->getWidth();
+  r_input_area.ymin = 0;
+  r_input_area.ymax = this->getHeight();
+}
+
 DenoiseOperation::DenoiseOperation()
 {
   this->addInputSocket(DataType::Color);
@@ -35,8 +166,6 @@ DenoiseOperation::DenoiseOperation()
   this->addInputSocket(DataType::Color);
   this->addOutputSocket(DataType::Color);
   this->m_settings = nullptr;
-  flags.is_fullframe_operation = true;
-  output_rendered_ = false;
 }
 void DenoiseOperation::initExecution()
 {
@@ -54,6 +183,25 @@ void DenoiseOperation::deinitExecution()
   SingleThreadedOperation::deinitExecution();
 }
 
+static bool are_guiding_passes_noise_free(NodeDenoise *settings)
+{
+  switch (settings->prefilter) {
+    case CMP_NODE_DENOISE_PREFILTER_NONE:
+    case CMP_NODE_DENOISE_PREFILTER_ACCURATE: /* Prefiltered with #DenoisePrefilterOperation. */
+      return true;
+    case CMP_NODE_DENOISE_PREFILTER_FAST:
+    default:
+      return false;
+  }
+}
+
+void DenoiseOperation::hash_output_params()
+{
+  if (m_settings) {
+    hash_params((int)m_settings->hdr, are_guiding_passes_noise_free(m_settings));
+  }
+}
+
 MemoryBuffer *DenoiseOperation::createMemoryBuffer(rcti *rect2)
 {
   MemoryBuffer *tileColor = (MemoryBuffer *)this->m_inputProgramColor->initializeTileData(rect2);
@@ -69,22 +217,6 @@ MemoryBuffer *DenoiseOperation::createMemoryBuffer(rcti *rect2)
   return result;
 }
 
-bool DenoiseOperation::determineDependingAreaOfInterest(rcti * /*input*/,
-                                                        ReadBufferOperation *readOperation,
-                                                        rcti *output)
-{
-  if (isCached()) {
-    return false;
-  }
-
-  rcti newInput;
-  newInput.xmax = this->getWidth();
-  newInput.xmin = 0;
-  newInput.ymax = this->getHeight();
-  newInput.ymin = 0;
-  return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
-}
-
 void DenoiseOperation::generateDenoise(MemoryBuffer *output,
                                        MemoryBuffer *input_color,
                                        MemoryBuffer *input_normal,
@@ -96,104 +228,46 @@ void DenoiseOperation::generateDenoise(MemoryBuffer *output,
     return;
   }
 
-#ifdef WITH_OPENIMAGEDENOISE
-  /* Always supported through Accelerate framework BNNS on macOS. */
-#  ifndef __APPLE__
-  if (BLI_cpu_support_sse41())
-#  endif
-  {
-    /* OpenImageDenoise needs full buffers. */
-    MemoryBuffer *buf_color = input_color->is_a_single_elem() ? input_color->inflate() :
-                                                                input_color;
-    MemoryBuffer *buf_normal = input_normal && input_normal->is_a_single_elem() ?
-                                   input_normal->inflate() :
-                                   input_normal;
-    MemoryBuffer *buf_albedo = input_albedo && input_albedo->is_a_single_elem() ?
-                                   input_albedo->inflate() :
-                                   input_albedo;
+  BLI_assert(COM_is_denoise_supported());
+  /* OpenImageDenoise needs full buffers. */
+  MemoryBuffer *buf_color = input_color->is_a_single_elem() ? input_color->inflate() : input_color;
+  MemoryBuffer *buf_normal = input_normal && input_normal->is_a_single_elem() ?
+                                 input_normal->inflate() :
+                                 input_normal;
+  MemoryBuffer *buf_albedo = input_albedo && input_albedo->is_a_single_elem() ?
+                                 input_albedo->inflate() :
+                                 input_albedo;
 
-    /* Since it's memory intensive, it's better to run only one instance of OIDN at a time.
-     * OpenImageDenoise is multithreaded internally and should use all available cores nonetheless.
-     */
-    BLI_mutex_lock(&oidn_lock);
+  DenoiseFilter filter;
+  filter.init_and_lock_denoiser(output);
 
-    oidn::DeviceRef device = oidn::newDevice();
-    device.commit();
+  filter.set_image("color", buf_color);
+  filter.set_image("normal", buf_normal);
+  filter.set_image("albedo", buf_albedo);
 
-    oidn::FilterRef filter = device.newFilter("RT");
-    filter.setImage("color",
-                    buf_color->getBuffer(),
-                    oidn::Format::Float3,
-                    buf_color->getWidth(),
-                    buf_color->getHeight(),
-                    0,
-                    sizeof(float[4]));
-    if (buf_normal && buf_normal->getBuffer()) {
-      filter

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list