[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