[Bf-blender-cvs] [7dc807b4e2b] cycles-x: Refactor Cycles X OIDN denoiser to use PassAccessor

Sergey Sharybin noreply at git.blender.org
Tue Jun 15 12:04:12 CEST 2021


Commit: 7dc807b4e2b98359e0b2291557f45839498d6f32
Author: Sergey Sharybin
Date:   Fri Jun 11 17:31:50 2021 +0200
Branches: cycles-x
https://developer.blender.org/rB7dc807b4e2b98359e0b2291557f45839498d6f32

Refactor Cycles X OIDN denoiser to use PassAccessor

No functional changes, just laying down code which is needed to denoise
passes different from combined.

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

M	intern/cycles/integrator/denoiser_oidn.cpp

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

diff --git a/intern/cycles/integrator/denoiser_oidn.cpp b/intern/cycles/integrator/denoiser_oidn.cpp
index f0a7472a727..e94d570d9de 100644
--- a/intern/cycles/integrator/denoiser_oidn.cpp
+++ b/intern/cycles/integrator/denoiser_oidn.cpp
@@ -19,6 +19,7 @@
 #include <array>
 
 #include "device/device.h"
+#include "integrator/pass_accessor_cpu.h"
 #include "render/buffers.h"
 #include "util/util_array.h"
 #include "util/util_logging.h"
@@ -69,14 +70,30 @@ void OIDNDenoiser::load_kernels(Progress * /*progress*/)
 }
 
 #ifdef WITH_OPENIMAGEDENOISE
-struct OIDNPass {
+class OIDNPass {
+ public:
+  OIDNPass() = default;
+
+  OIDNPass(const BufferParams &buffer_params,
+           const char *name,
+           PassType type,
+           PassMode mode = PassMode::NOISY)
+      : name(name), type(type), mode(mode)
+  {
+    offset = buffer_params.get_pass_offset(type, mode);
+    need_scale = (type == PASS_DENOISING_ALBEDO || type == PASS_DENOISING_NORMAL);
+  }
+
   /* Name of an image which will be passed to the OIDN library.
    * Should be one of the following: color, albedo, normal, output.
    * The albedo and normal images are optional. */
-  const char *name;
+  const char *name = "";
+
+  PassType type = PASS_NONE;
+  PassMode mode = PassMode::NOISY;
 
   /* Offset of beginning of this pass in the render buffers. */
-  const int offset;
+  int offset = -1;
 
   /* Denotes whether the data is to be scaled down with the number of passes.
    * Is required for albedo and normal passes. The color pass OIDN will perform auto-exposure, so
@@ -85,118 +102,175 @@ struct OIDNPass {
    * NOTE: Do not scale the outout pass, as that requires to be a pointer in the original buffer.
    * All the scaling on the output needed for integration with adaptive sampling will happen
    * outside of generic pass handling. */
-  const bool need_scale;
-
-  /* Whether or not send this pass to the OIDN. */
-  const bool use;
+  bool need_scale = false;
 
   /* For the scaled passes, the data which holds values of scaled pixels. */
   array<float> scaled_buffer;
 };
 
-static void oidn_add_pass_if_needed(oidn::FilterRef *oidn_filter,
-                                    OIDNPass &oidn_pass,
-                                    RenderBuffers *render_buffers,
-                                    const BufferParams &buffer_params,
-                                    const float scale)
-{
-  if (!oidn_pass.use) {
-    return;
+class OIDNDeenoiseContext {
+ public:
+  OIDNDeenoiseContext(const DenoiseParams &denoise_params,
+                      const BufferParams &buffer_params,
+                      RenderBuffers *render_buffers,
+                      oidn::FilterRef *oidn_filter,
+                      const int num_samples)
+      : denoise_params_(denoise_params),
+        buffer_params_(buffer_params),
+        render_buffers_(render_buffers),
+        oidn_filter_(oidn_filter),
+        num_samples_(num_samples),
+        pass_sample_count_(buffer_params_.get_pass_offset(PASS_SAMPLE_COUNT))
+  {
   }
 
-  const int64_t x = buffer_params.full_x;
-  const int64_t y = buffer_params.full_y;
-  const int64_t width = buffer_params.width;
-  const int64_t height = buffer_params.height;
-  const int64_t offset = buffer_params.offset;
-  const int64_t stride = buffer_params.stride;
-  const int64_t pass_stride = buffer_params.pass_stride;
-
-  const int64_t pixel_offset = offset + x + y * stride;
-  const int64_t buffer_offset = (pixel_offset * pass_stride);
-  const int64_t pixel_stride = pass_stride;
-  const int64_t row_stride = stride * pixel_stride;
-
-  const int pass_sample_count = buffer_params.get_pass_offset(PASS_SAMPLE_COUNT);
-
-  float *buffer_data = reinterpret_cast<float *>(render_buffers->buffer.host_pointer);
-
-  if (!oidn_pass.need_scale || (scale == 1.0f && pass_sample_count == PASS_UNUSED)) {
-    oidn_filter->setImage(oidn_pass.name,
-                          buffer_data + buffer_offset + oidn_pass.offset,
-                          oidn::Format::Float3,
-                          width,
-                          height,
-                          0,
-                          pixel_stride * sizeof(float),
-                          row_stride * sizeof(float));
-    return;
+  void denoise()
+  {
+    /* Add input images.
+     *
+     * NOTE: Store passes for the entire duration od denoising because OIDN denoiser might
+     * reference pixels from the pass buffer. */
+
+    OIDNPass oidn_color_pass(buffer_params_, "color", PASS_COMBINED);
+    OIDNPass oidn_albedo_pass;
+    OIDNPass oidn_normal_pass;
+
+    set_pass(oidn_color_pass);
+
+    if (denoise_params_.use_pass_albedo) {
+      oidn_albedo_pass = OIDNPass(buffer_params_, "albedo", PASS_DENOISING_ALBEDO);
+      set_pass(oidn_albedo_pass);
+    }
+
+    if (denoise_params_.use_pass_normal) {
+      oidn_normal_pass = OIDNPass(buffer_params_, "normal", PASS_DENOISING_NORMAL);
+      set_pass(oidn_normal_pass);
+    }
+
+    /* Add output pass. */
+    OIDNPass oidn_output_pass(buffer_params_, "output", PASS_COMBINED, PassMode::DENOISED);
+    set_pass_referenced(oidn_output_pass);
+
+    /* Execute filter. */
+    oidn_filter_->commit();
+    oidn_filter_->execute();
+
+    postprocess_output(oidn_color_pass, oidn_output_pass);
   }
 
-  array<float> &scaled_buffer = oidn_pass.scaled_buffer;
-  scaled_buffer.resize(width * height * 3);
+ protected:
+  /* Set OIDN image to reference pixels from the given render buffer pass.
+   * No transform to the pixels is done, no additional memory is used. */
+  void set_pass_referenced(const OIDNPass &oidn_pass)
+  {
+    const int64_t x = buffer_params_.full_x;
+    const int64_t y = buffer_params_.full_y;
+    const int64_t width = buffer_params_.width;
+    const int64_t height = buffer_params_.height;
+    const int64_t offset = buffer_params_.offset;
+    const int64_t stride = buffer_params_.stride;
+    const int64_t pass_stride = buffer_params_.pass_stride;
+
+    const int64_t pixel_index = offset + x + y * stride;
+    const int64_t buffer_offset = pixel_index * pass_stride;
+
+    float *buffer_data = render_buffers_->buffer.data();
+
+    oidn_filter_->setImage(oidn_pass.name,
+                           buffer_data + buffer_offset + oidn_pass.offset,
+                           oidn::Format::Float3,
+                           width,
+                           height,
+                           0,
+                           pass_stride * sizeof(float),
+                           stride * pass_stride * sizeof(float));
+  }
 
-  for (int y = 0; y < height; ++y) {
-    const float *buffer_row = buffer_data + buffer_offset + y * row_stride;
-    float *scaled_row = scaled_buffer.data() + y * width * 3;
+  void set_pass_scaled(OIDNPass &oidn_pass)
+  {
+    const int64_t width = buffer_params_.width;
+    const int64_t height = buffer_params_.height;
 
-    for (int x = 0; x < width; ++x) {
-      const float *buffer_pixel = buffer_row + x * pixel_stride;
-      const float *pass_pixel = buffer_pixel + oidn_pass.offset;
+    array<float> &scaled_buffer = oidn_pass.scaled_buffer;
+    scaled_buffer.resize(width * height * 3);
 
-      float pixel_scale = scale;
-      if (pass_sample_count != PASS_UNUSED) {
-        pixel_scale = 1.0f / __float_as_uint(buffer_pixel[pass_sample_count]);
-      }
+    PassAccessor::PassAccessInfo pass_access_info;
+    pass_access_info.type = oidn_pass.type;
+    pass_access_info.offset = oidn_pass.offset;
 
-      scaled_row[x * 3 + 0] = pass_pixel[0] * pixel_scale;
-      scaled_row[x * 3 + 1] = pass_pixel[1] * pixel_scale;
-      scaled_row[x * 3 + 2] = pass_pixel[2] * pixel_scale;
-    }
+    /* Denoiser operates on passes which are used to calculate the approximation, and is never used
+     * on the approximation. The latter is not even possible because OIDN does not support
+     * denoising of semi-transparent pixels. */
+    pass_access_info.use_approximate_shadow_catcher = false;
+    pass_access_info.show_active_pixels = false;
+
+    /* OIDN will perform an auto-exposure, so it is not required to know exact exposure configured
+     * by users. What is important is to use same exposure for read and write access of the pass
+     * pixels. */
+    const PassAccessorCPU pass_accessor(pass_access_info, 1.0f, num_samples_);
+    const PassAccessor::Destination destination(scaled_buffer.data(), 3);
+
+    pass_accessor.get_render_tile_pixels(render_buffers_, buffer_params_, destination);
+
+    oidn_filter_->setImage(
+        oidn_pass.name, scaled_buffer.data(), oidn::Format::Float3, width, height, 0, 0, 0);
   }
 
-  oidn_filter->setImage(
-      oidn_pass.name, scaled_buffer.data(), oidn::Format::Float3, width, height, 0, 0, 0);
-}
+  void set_pass(OIDNPass &oidn_pass)
+  {
+    if (!oidn_pass.need_scale || (num_samples_ == 1 && pass_sample_count_ == PASS_UNUSED)) {
+      set_pass_referenced(oidn_pass);
+      return;
+    }
 
-static void oidn_scale_combined_pass_after_denoise(const BufferParams &buffer_params,
-                                                   RenderBuffers *render_buffers)
-{
-  const int pass_sample_count = buffer_params.get_pass_offset(PASS_SAMPLE_COUNT);
-  if (pass_sample_count == PASS_UNUSED) {
-    return;
+    set_pass_scaled(oidn_pass);
   }
 
-  const int64_t x = buffer_params.full_x;
-  const int64_t y = buffer_params.full_y;
-  const int64_t width = buffer_params.width;
-  const int64_t height = buffer_params.height;
-  const int64_t offset = buffer_params.offset;
-  const int64_t stride = buffer_params.stride;
-  const int64_t pass_stride = buffer_params.pass_stride;
-  const int64_t pixel_stride = pass_stride;
-  const int64_t row_stride = stride * pixel_stride;
-
-  const int64_t pixel_offset = offset + x + y * stride;
-  const int64_t buffer_offset = (pixel_offset * pass_stride);
-
-  float *buffer_data = reinterpret_cast<float *>(render_buffers->buffer.host_pointer);
-
-  const int pass_denoised = buffer_params.get_pass_offset(PASS_COMBINED, PassMode::DENOISED);
-
-  for (int y = 0; y < height; ++y) {
-    float *buffer_row = buffer_data + buffer_offset + y * row_stride;
-    for (int x = 0; x < width; ++x) {
-      float *buffer_pixel = buffer_row + x * pixel_s

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list