29 #ifdef WITH_OPENIMAGEDENOISE
30 static bool oidn_progress_monitor_function(
void *user_ptr,
double )
55 inline operator bool()
const
57 return name[0] !=
'\0';
63 const char *name =
"";
69 bool use_denoising_albedo =
true;
81 bool need_scale =
false;
84 bool is_filtered =
false;
90 class OIDNDenoiseContext {
97 const bool allow_inplace_modification)
98 : denoiser_(denoiser),
99 denoise_params_(denoise_params),
100 buffer_params_(buffer_params),
101 render_buffers_(render_buffers),
103 allow_inplace_modification_(allow_inplace_modification),
106 if (denoise_params_.use_pass_albedo) {
110 if (denoise_params_.use_pass_normal) {
115 bool need_denoising()
const
117 if (buffer_params_.width == 0 && buffer_params_.height == 0) {
125 void read_guiding_passes()
127 read_guiding_pass(oidn_albedo_pass_);
128 read_guiding_pass(oidn_normal_pass_);
131 void denoise_pass(
const PassType pass_type)
133 OIDNPass oidn_color_pass(buffer_params_,
"color", pass_type);
138 if (oidn_color_pass.use_denoising_albedo) {
139 if (albedo_replaced_with_fake_) {
140 LOG(ERROR) <<
"Pass which requires albedo is denoised after fake albedo has been set.";
151 OIDNPass oidn_color_access_pass = read_input_pass(oidn_color_pass, oidn_output_pass);
153 oidn::DeviceRef oidn_device = oidn::newDevice();
154 oidn_device.set(
"setAffinity",
false);
155 oidn_device.commit();
159 oidn::FilterRef oidn_filter = oidn_device.newFilter(
"RT");
160 set_input_pass(oidn_filter, oidn_color_access_pass);
161 set_guiding_passes(oidn_filter, oidn_color_pass);
162 set_output_pass(oidn_filter, oidn_output_pass);
163 oidn_filter.setProgressMonitorFunction(oidn_progress_monitor_function, denoiser_);
164 oidn_filter.set(
"hdr",
true);
165 oidn_filter.set(
"srgb",
false);
168 oidn_filter.set(
"cleanAux",
true);
170 oidn_filter.commit();
172 filter_guiding_pass_if_needed(oidn_device, oidn_albedo_pass_);
173 filter_guiding_pass_if_needed(oidn_device, oidn_normal_pass_);
176 oidn_filter.execute();
179 const char *error_message;
180 const oidn::Error
error = oidn_device.getError(error_message);
181 if (
error != oidn::Error::None &&
error != oidn::Error::Cancelled) {
182 LOG(ERROR) <<
"OpenImageDenoise error: " << error_message;
185 postprocess_output(oidn_color_pass, oidn_output_pass);
189 void filter_guiding_pass_if_needed(oidn::DeviceRef &oidn_device, OIDNPass &oidn_pass)
192 oidn_pass.is_filtered) {
196 oidn::FilterRef oidn_filter = oidn_device.newFilter(
"RT");
197 set_pass(oidn_filter, oidn_pass);
198 set_output_pass(oidn_filter, oidn_pass);
199 oidn_filter.commit();
200 oidn_filter.execute();
202 oidn_pass.is_filtered =
true;
206 void read_guiding_pass(OIDNPass &oidn_pass)
212 DCHECK(!oidn_pass.use_compositing);
215 !is_pass_scale_needed(oidn_pass)) {
220 if (allow_inplace_modification_) {
221 scale_pass_in_render_buffers(oidn_pass);
225 read_pass_pixels_into_buffer(oidn_pass);
231 OIDNPass read_input_pass(OIDNPass &oidn_input_pass,
const OIDNPass &oidn_output_pass)
238 return oidn_input_pass;
241 float *buffer_data = render_buffers_->buffer.data();
242 float *pass_data = buffer_data + oidn_output_pass.offset;
245 destination.pixel_stride = buffer_params_.pass_stride;
247 read_pass_pixels(oidn_input_pass, destination);
249 OIDNPass oidn_input_pass_at_output = oidn_input_pass;
250 oidn_input_pass_at_output.offset = oidn_output_pass.offset;
252 return oidn_input_pass_at_output;
259 pass_access_info.
type = oidn_pass.type;
260 pass_access_info.
mode = oidn_pass.mode;
261 pass_access_info.
offset = oidn_pass.offset;
273 const PassAccessorCPU pass_accessor(pass_access_info, 1.0f, num_samples_);
281 pass_accessor.get_render_tile_pixels(render_buffers_, buffer_params, destination);
285 void read_pass_pixels_into_buffer(OIDNPass &oidn_pass)
287 VLOG_WORK <<
"Allocating temporary buffer for pass " << oidn_pass.name <<
" ("
298 read_pass_pixels(oidn_pass, destination);
303 void set_pass_referenced(oidn::FilterRef &oidn_filter,
305 const OIDNPass &oidn_pass)
307 const int64_t x = buffer_params_.full_x;
308 const int64_t y = buffer_params_.full_y;
318 float *buffer_data = render_buffers_->buffer.data();
320 oidn_filter.setImage(name,
321 buffer_data + buffer_offset + oidn_pass.offset,
322 oidn::Format::Float3,
330 void set_pass_from_buffer(oidn::FilterRef &oidn_filter,
const char *name, OIDNPass &oidn_pass)
335 oidn_filter.setImage(
336 name, oidn_pass.scaled_buffer.data(), oidn::Format::Float3,
width,
height, 0, 0, 0);
339 void set_pass(oidn::FilterRef &oidn_filter, OIDNPass &oidn_pass)
341 set_pass(oidn_filter, oidn_pass.name, oidn_pass);
343 void set_pass(oidn::FilterRef &oidn_filter,
const char *name, OIDNPass &oidn_pass)
345 if (oidn_pass.scaled_buffer.empty()) {
346 set_pass_referenced(oidn_filter, name, oidn_pass);
349 set_pass_from_buffer(oidn_filter, name, oidn_pass);
353 void set_input_pass(oidn::FilterRef &oidn_filter, OIDNPass &oidn_pass)
355 set_pass_referenced(oidn_filter, oidn_pass.name, oidn_pass);
358 void set_guiding_passes(oidn::FilterRef &oidn_filter, OIDNPass &oidn_pass)
360 if (oidn_albedo_pass_) {
361 if (oidn_pass.use_denoising_albedo) {
362 set_pass(oidn_filter, oidn_albedo_pass_);
367 set_fake_albedo_pass(oidn_filter);
371 if (oidn_normal_pass_) {
372 set_pass(oidn_filter, oidn_normal_pass_);
376 void set_fake_albedo_pass(oidn::FilterRef &oidn_filter)
381 if (!albedo_replaced_with_fake_) {
383 oidn_albedo_pass_.scaled_buffer.resize(num_pixel_components);
385 for (
int i = 0; i < num_pixel_components; ++i) {
386 oidn_albedo_pass_.scaled_buffer[i] = 0.5f;
389 albedo_replaced_with_fake_ =
true;
392 set_pass(oidn_filter, oidn_albedo_pass_);
395 void set_output_pass(oidn::FilterRef &oidn_filter, OIDNPass &oidn_pass)
397 set_pass(oidn_filter,
"output", oidn_pass);
402 void postprocess_output(
const OIDNPass &oidn_input_pass,
const OIDNPass &oidn_output_pass)
404 kernel_assert(oidn_input_pass.num_components == oidn_output_pass.num_components);
406 const int64_t x = buffer_params_.full_x;
407 const int64_t y = buffer_params_.full_y;
418 float *buffer_data = render_buffers_->buffer.data();
420 const bool has_pass_sample_count = (pass_sample_count_ !=
PASS_UNUSED);
421 const bool need_scale = has_pass_sample_count || oidn_input_pass.use_compositing;
424 float *buffer_row = buffer_data + buffer_offset +
y * row_stride;
439 if (oidn_output_pass.num_components == 3) {
442 else if (!oidn_input_pass.use_compositing) {
446 const float *noisy_pixel = buffer_pixel + oidn_input_pass.offset;
458 bool is_pass_scale_needed(OIDNPass &oidn_pass)
const
466 if (!oidn_pass.need_scale) {
470 if (num_samples_ == 1) {
479 void scale_pass_in_render_buffers(OIDNPass &oidn_pass)
481 const int64_t x = buffer_params_.full_x;
482 const int64_t y = buffer_params_.full_y;
493 float *buffer_data = render_buffers_->buffer.data();
495 const bool has_pass_sample_count = (pass_sample_count_ !=
PASS_UNUSED);
498 float *buffer_row = buffer_data + buffer_offset +
y * row_stride;
501 float *pass_pixel = buffer_pixel + oidn_pass.offset;
503 const float pixel_scale = 1.0f / (has_pass_sample_count ?
519 int num_samples_ = 0;
520 bool allow_inplace_modification_ =
false;
524 OIDNPass oidn_albedo_pass_;
525 OIDNPass oidn_normal_pass_;
530 bool albedo_replaced_with_fake_ =
false;
533 static unique_ptr<DeviceQueue> create_device_queue(
const RenderBuffers *render_buffers)
542 static void copy_render_buffers_from_device(unique_ptr<DeviceQueue> &
queue,
547 queue->synchronize();
554 static void copy_render_buffers_to_device(unique_ptr<DeviceQueue> &
queue,
559 queue->synchronize();
571 bool allow_inplace_modification)
574 <<
"OpenImageDenoiser is not supported on this platform or build.";
576 #ifdef WITH_OPENIMAGEDENOISE
580 unique_ptr<DeviceQueue>
queue = create_device_queue(render_buffers);
581 copy_render_buffers_from_device(
queue, render_buffers);
584 this,
params_, buffer_params, render_buffers,
num_samples, allow_inplace_modification);
586 if (
context.need_denoising()) {
589 const std::array<PassType, 3> passes = {
598 for (
const PassType pass_type : passes) {
599 context.denoise_pass(pass_type);
607 copy_render_buffers_to_device(
queue, render_buffers);
611 (
void)render_buffers;
613 (
void)allow_inplace_modification;
628 #ifndef WITH_OPENIMAGEDENOISE
635 "OpenImageDenoiser is not supported on this CPU: missing SSE 4.1 support");
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei stride
int get_pass_offset(PassType type, PassMode mode=PassMode::NOISY) const
virtual Device * ensure_denoiser_device(Progress *progress)
bool is_cancelled() const
Device * path_trace_device_
virtual unique_ptr< DeviceQueue > gpu_queue_create()
virtual void set_error(const string &error)
OIDNDenoiser(Device *path_trace_device, const DenoiseParams ¶ms)
virtual bool denoise_buffer(const BufferParams &buffer_params, RenderBuffers *render_buffers, const int num_samples, bool allow_inplace_modification) override
virtual uint get_device_type_mask() const override
static thread_mutex mutex_
virtual Device * ensure_denoiser_device(Progress *progress) override
bool use_approximate_shadow_catcher
bool use_approximate_shadow_catcher_background
PassInfo get_info() const
device_vector< float > buffer
T * resize(size_t newsize)
#define kernel_assert(cond)
#define CCL_NAMESPACE_END
@ DENOISER_PREFILTER_NONE
@ DENOISER_PREFILTER_ACCURATE
@ DENOISER_OPENIMAGEDENOISE
SyclQueue void void size_t num_bytes void
ccl_gpu_kernel_postfix ccl_global float int int int int int int int int int int int int num_components
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
ccl_gpu_kernel_postfix ccl_global float int int int int int int int pass_stride
ccl_global float * denoised_pixel
ccl_gpu_kernel_postfix ccl_global float int int int int ccl_global const float int int int int int int int int int int int int num_samples
ccl_gpu_kernel_postfix ccl_global float int int int int int int int int int int int int bool use_compositing
@ PASS_SHADOW_CATCHER_MATTE
#define DCHECK(expression)
static void error(const char *str)
static CCL_NAMESPACE_BEGIN bool openimagedenoise_supported()
CCL_NAMESPACE_BEGIN const char * pass_type_as_string(const PassType type)
bool use_denoising_albedo
std::unique_lock< std::mutex > thread_scoped_lock
CCL_NAMESPACE_BEGIN typedef std::mutex thread_mutex
ccl_device_inline uint __float_as_uint(float f)