[Bf-blender-cvs] [c193800a603] cycles-x: Refactor CYcles X OptiX denoiser preparing for in-place operation

Sergey Sharybin noreply at git.blender.org
Fri Jul 9 17:32:18 CEST 2021


Commit: c193800a603d8c225769a104d96a1e4c0a37ae9c
Author: Sergey Sharybin
Date:   Fri Jul 9 14:34:53 2021 +0200
Branches: cycles-x
https://developer.blender.org/rBc193800a603d8c225769a104d96a1e4c0a37ae9c

Refactor CYcles X OptiX denoiser preparing for in-place operation

Currently no functional changes are expected. Making code ready for
re-using storage of the render buffers to store guiding passes when
this is possible.

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

M	intern/cycles/device/device_kernel.cpp
M	intern/cycles/device/optix/device_impl.cpp
M	intern/cycles/device/optix/device_impl.h
M	intern/cycles/kernel/device/cuda/kernel.cu
M	intern/cycles/kernel/kernel_types.h

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

diff --git a/intern/cycles/device/device_kernel.cpp b/intern/cycles/device/device_kernel.cpp
index 648ee090ce7..ca918c2f853 100644
--- a/intern/cycles/device/device_kernel.cpp
+++ b/intern/cycles/device/device_kernel.cpp
@@ -106,10 +106,14 @@ const char *device_kernel_as_string(DeviceKernel kernel)
       return "adaptive_sampling_filter_y";
 
     /* Denoising. */
-    case DEVICE_KERNEL_FILTER_CONVERT_TO_RGB:
-      return "filter_convert_to_rgb";
-    case DEVICE_KERNEL_FILTER_CONVERT_FROM_RGB:
-      return "filter_convert_from_rgb";
+    case DEVICE_KERNEL_FILTER_GUIDING_PREPROCESS:
+      return "filter_guiding_preprocess";
+    case DEVICE_KERNEL_FILTER_GUIDING_SET_FAKE_ALBEDO:
+      return "filter_guiding_set_fake_albedo";
+    case DEVICE_KERNEL_FILTER_COLOR_PREPROCESS:
+      return "filter_color_preprocess";
+    case DEVICE_KERNEL_FILTER_COLOR_POSTPROCESS:
+      return "filter_color_postprocess";
 
     /* Generic */
     case DEVICE_KERNEL_PREFIX_SUM:
diff --git a/intern/cycles/device/optix/device_impl.cpp b/intern/cycles/device/optix/device_impl.cpp
index 298b384797e..9bda428c462 100644
--- a/intern/cycles/device/optix/device_impl.cpp
+++ b/intern/cycles/device/optix/device_impl.cpp
@@ -531,25 +531,39 @@ class OptiXDevice::DenoiseContext {
       : denoise_params(task.params),
         render_buffers(task.render_buffers),
         buffer_params(task.buffer_params),
-        input_buffer(device, "denoiser input buffer"),
+        guiding_buffer(device, "denoiser guiding passes buffer"),
         num_samples(task.num_samples)
   {
     num_input_passes = 1;
     if (denoise_params.use_pass_albedo) {
       num_input_passes += 1;
       use_pass_albedo = true;
+      pass_denoising_albedo = buffer_params.get_pass_offset(PASS_DENOISING_ALBEDO);
       if (denoise_params.use_pass_normal) {
         num_input_passes += 1;
         use_pass_normal = true;
+        pass_denoising_normal = buffer_params.get_pass_offset(PASS_DENOISING_NORMAL);
       }
     }
 
-    /* Don't allocate color pass: denoised pass storage from the render buffers is used for both
-     * noisy pass input at a proper scale and result of the denoiser. */
-    const int input_buffer_stride = (num_input_passes - 1) * 3;
-    if (input_buffer_stride) {
-      input_buffer.alloc_to_device(buffer_params.width * buffer_params.height *
-                                   input_buffer_stride);
+    const int num_guiding_passes = num_input_passes - 1;
+
+    if (num_guiding_passes) {
+      guiding_params.pass_stride = 0;
+      if (use_pass_albedo) {
+        guiding_params.pass_albedo = guiding_params.pass_stride;
+        guiding_params.pass_stride += 3;
+      }
+      if (use_pass_normal) {
+        guiding_params.pass_normal = guiding_params.pass_stride;
+        guiding_params.pass_stride += 3;
+      }
+
+      guiding_params.stride = buffer_params.width;
+
+      guiding_buffer.alloc_to_device(buffer_params.width * buffer_params.height *
+                                     guiding_params.pass_stride);
+      guiding_params.device_pointer = guiding_buffer.device_pointer;
     }
 
     pass_sample_count = buffer_params.get_pass_offset(PASS_SAMPLE_COUNT);
@@ -560,9 +574,19 @@ class OptiXDevice::DenoiseContext {
   RenderBuffers *render_buffers = nullptr;
   const BufferParams &buffer_params;
 
-  /* Device-side storage of the input passes.
-   * Start with the input color pass, followed with optional albedo and normal passes. */
-  device_only_memory<float> input_buffer;
+  /* Device-side storage of the guiding passes. */
+  device_only_memory<float> guiding_buffer;
+
+  struct {
+    device_ptr device_pointer = 0;
+
+    /* NOTE: Are only initialized when the corresponding guiding pass is enabled. */
+    int pass_albedo = PASS_UNUSED;
+    int pass_normal = PASS_UNUSED;
+
+    int stride = -1;
+    int pass_stride = -1;
+  } guiding_params;
 
   /* Number of input passes. Including the color and extra auxillary passes. */
   int num_input_passes = 0;
@@ -570,15 +594,38 @@ class OptiXDevice::DenoiseContext {
   bool use_pass_normal = false;
 
   int num_samples = 0;
+
   int pass_sample_count = PASS_UNUSED;
+
+  /* NOTE: Are only initialized when the corresponding guiding pass is enabled. */
+  int pass_denoising_albedo = PASS_UNUSED;
+  int pass_denoising_normal = PASS_UNUSED;
+
+  /* For passes which don't need albedo channel for denoising we replace the actual albedo with
+   * the (0.5, 0.5, 0.5). This flag indicates that the real albedo pass has been replaced with
+   * the fake values and denoising of passes which do need albedo can no longer happen. */
+  bool albedo_replaced_with_fake = false;
 };
 
 class OptiXDevice::DenoisePass {
  public:
+  DenoisePass(const PassType type, const BufferParams &buffer_params) : type(type)
+  {
+    noisy_offset = buffer_params.get_pass_offset(type, PassMode::NOISY);
+    denoised_offset = buffer_params.get_pass_offset(type, PassMode::DENOISED);
+
+    const PassInfo pass_info = Pass::get_info(type);
+    use_compositing = pass_info.use_compositing;
+    use_denoising_albedo = pass_info.use_denoising_albedo;
+  }
+
   PassType type;
 
   int noisy_offset;
   int denoised_offset;
+
+  bool use_compositing;
+  bool use_denoising_albedo;
 };
 
 void OptiXDevice::denoise_buffer(const DeviceDenoiseTask &task)
@@ -591,9 +638,17 @@ void OptiXDevice::denoise_buffer(const DeviceDenoiseTask &task)
     return;
   }
 
+  if (!denoise_filter_guiding_preprocess(context)) {
+    LOG(ERROR) << "Error preprocessing guiding passes.";
+    return;
+  }
+
+  /* Passes which will use real albedo when it is available. */
   denoise_pass(context, PASS_COMBINED);
-  denoise_pass(context, PASS_SHADOW_CATCHER);
   denoise_pass(context, PASS_SHADOW_CATCHER_MATTE);
+
+  /* Passes which do not need albedo and hence if real is present it needs to become fake. */
+  denoise_pass(context, PASS_SHADOW_CATCHER);
 }
 
 DeviceQueue *OptiXDevice::get_denoise_queue()
@@ -601,14 +656,52 @@ DeviceQueue *OptiXDevice::get_denoise_queue()
   return &denoiser_.queue;
 }
 
+bool OptiXDevice::denoise_filter_guiding_preprocess(DenoiseContext &context)
+{
+  const BufferParams &buffer_params = context.buffer_params;
+
+  const int work_size = buffer_params.width * buffer_params.height;
+
+  void *args[] = {const_cast<device_ptr *>(&context.guiding_params.device_pointer),
+                  const_cast<int *>(&context.guiding_params.pass_stride),
+                  const_cast<int *>(&context.guiding_params.pass_albedo),
+                  const_cast<int *>(&context.guiding_params.pass_normal),
+                  &context.render_buffers->buffer.device_pointer,
+                  const_cast<int *>(&buffer_params.offset),
+                  const_cast<int *>(&buffer_params.stride),
+                  const_cast<int *>(&buffer_params.pass_stride),
+                  const_cast<int *>(&context.pass_sample_count),
+                  const_cast<int *>(&context.pass_denoising_albedo),
+                  const_cast<int *>(&context.pass_denoising_normal),
+                  const_cast<int *>(&buffer_params.full_x),
+                  const_cast<int *>(&buffer_params.full_y),
+                  const_cast<int *>(&buffer_params.width),
+                  const_cast<int *>(&buffer_params.height),
+                  const_cast<int *>(&context.num_samples)};
+
+  return denoiser_.queue.enqueue(DEVICE_KERNEL_FILTER_GUIDING_PREPROCESS, work_size, args);
+}
+
+bool OptiXDevice::denoise_filter_guiding_set_fake_albedo(DenoiseContext &context)
+{
+  const BufferParams &buffer_params = context.buffer_params;
+
+  const int work_size = buffer_params.width * buffer_params.height;
+
+  void *args[] = {const_cast<device_ptr *>(&context.guiding_params.device_pointer),
+                  const_cast<int *>(&context.guiding_params.pass_stride),
+                  const_cast<int *>(&context.guiding_params.pass_albedo),
+                  const_cast<int *>(&buffer_params.width),
+                  const_cast<int *>(&buffer_params.height)};
+
+  return denoiser_.queue.enqueue(DEVICE_KERNEL_FILTER_GUIDING_SET_FAKE_ALBEDO, work_size, args);
+}
+
 void OptiXDevice::denoise_pass(DenoiseContext &context, PassType pass_type)
 {
   const BufferParams &buffer_params = context.buffer_params;
 
-  DenoisePass pass;
-  pass.type = pass_type;
-  pass.noisy_offset = buffer_params.get_pass_offset(pass_type, PassMode::NOISY);
-  pass.denoised_offset = buffer_params.get_pass_offset(pass_type, PassMode::DENOISED);
+  const DenoisePass pass(pass_type, buffer_params);
 
   if (pass.noisy_offset == PASS_UNUSED) {
     return;
@@ -618,14 +711,23 @@ void OptiXDevice::denoise_pass(DenoiseContext &context, PassType pass_type)
     return;
   }
 
-  /* Read pixels from the noisy input pass, store them in the temporary buffer for further
-   * clamping. */
-  denoise_read_input_pixels(context, pass);
+  if (pass.use_denoising_albedo) {
+    if (context.albedo_replaced_with_fake) {
+      LOG(ERROR) << "Pass which requires albedo is denoised after fake albedo has been set.";
+      return;
+    }
+  }
+  else if (!context.albedo_replaced_with_fake) {
+    context.albedo_replaced_with_fake = true;
+    if (!denoise_filter_guiding_set_fake_albedo(context)) {
+      LOG(ERROR) << "Error replacing real albedo with the fake one.";
+      return;
+    }
+  }
 
-  /* Make sure input data is in [0 .. 10000] range by scaling the input buffer by the number of
-   * samples in the buffer. Additionally, fill in the auxillary passes needed by the denoiser which
-   * were not provided by the pass accessor. */
-  if (!denoise_filter_convert_to_rgb(context, pass)) {
+  /* Read and preprocess noisy color input pass. */
+  denoise_color_read(context, pass);
+  if (!denoise_filter_color_preprocess(context, pass)) {
     LOG(ERROR) << "Error connverting denoising passes to RGB buffer.";
     return;
   }
@@ -638,7 +740,7 @@ void OptiXDevice::denoise_pass(DenoiseContext &context, PassType pass_type)
   /* Store result in the combined pass of the render buffer.
    *
    * This will scale the denoiser result up to match the number of, possibly per-pixel, samples. */
-  if (!denoise_filter_convert_from_rgb(context, pass)) {
+  if (!denoise_filter_c

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list