Blender  V3.3
denoiser_oidn.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
5 
6 #include <array>
7 
8 #include "device/device.h"
9 #include "device/queue.h"
11 #include "session/buffers.h"
12 #include "util/array.h"
13 #include "util/log.h"
14 #include "util/openimagedenoise.h"
15 
18 
20 
22 
24  : Denoiser(path_trace_device, params)
25 {
27 }
28 
29 #ifdef WITH_OPENIMAGEDENOISE
30 static bool oidn_progress_monitor_function(void *user_ptr, double /*n*/)
31 {
32  OIDNDenoiser *oidn_denoiser = reinterpret_cast<OIDNDenoiser *>(user_ptr);
33  return !oidn_denoiser->is_cancelled();
34 }
35 
36 class OIDNPass {
37  public:
38  OIDNPass() = default;
39 
40  OIDNPass(const BufferParams &buffer_params,
41  const char *name,
42  PassType type,
44  : name(name), type(type), mode(mode)
45  {
46  offset = buffer_params.get_pass_offset(type, mode);
47  need_scale = (type == PASS_DENOISING_ALBEDO || type == PASS_DENOISING_NORMAL);
48 
49  const PassInfo pass_info = Pass::get_info(type);
50  num_components = pass_info.num_components;
51  use_compositing = pass_info.use_compositing;
52  use_denoising_albedo = pass_info.use_denoising_albedo;
53  }
54 
55  inline operator bool() const
56  {
57  return name[0] != '\0';
58  }
59 
60  /* Name of an image which will be passed to the OIDN library.
61  * Should be one of the following: color, albedo, normal, output.
62  * The albedo and normal images are optional. */
63  const char *name = "";
64 
67  int num_components = -1;
68  bool use_compositing = false;
69  bool use_denoising_albedo = true;
70 
71  /* Offset of beginning of this pass in the render buffers. */
72  int offset = -1;
73 
74  /* Denotes whether the data is to be scaled down with the number of passes.
75  * Is required for albedo and normal passes. The color pass OIDN will perform auto-exposure, so
76  * scaling is not needed for the color pass unless adaptive sampling is used.
77  *
78  * NOTE: Do not scale the output pass, as that requires to be a pointer in the original buffer.
79  * All the scaling on the output needed for integration with adaptive sampling will happen
80  * outside of generic pass handling. */
81  bool need_scale = false;
82 
83  /* The content of the pass has been pre-filtered. */
84  bool is_filtered = false;
85 
86  /* For the scaled passes, the data which holds values of scaled pixels. */
87  array<float> scaled_buffer;
88 };
89 
90 class OIDNDenoiseContext {
91  public:
92  OIDNDenoiseContext(OIDNDenoiser *denoiser,
93  const DenoiseParams &denoise_params,
94  const BufferParams &buffer_params,
95  RenderBuffers *render_buffers,
96  const int num_samples,
97  const bool allow_inplace_modification)
98  : denoiser_(denoiser),
99  denoise_params_(denoise_params),
100  buffer_params_(buffer_params),
101  render_buffers_(render_buffers),
102  num_samples_(num_samples),
103  allow_inplace_modification_(allow_inplace_modification),
104  pass_sample_count_(buffer_params_.get_pass_offset(PASS_SAMPLE_COUNT))
105  {
106  if (denoise_params_.use_pass_albedo) {
107  oidn_albedo_pass_ = OIDNPass(buffer_params_, "albedo", PASS_DENOISING_ALBEDO);
108  }
109 
110  if (denoise_params_.use_pass_normal) {
111  oidn_normal_pass_ = OIDNPass(buffer_params_, "normal", PASS_DENOISING_NORMAL);
112  }
113  }
114 
115  bool need_denoising() const
116  {
117  if (buffer_params_.width == 0 && buffer_params_.height == 0) {
118  return false;
119  }
120 
121  return true;
122  }
123 
124  /* Make the guiding passes available by a sequential denoising of various passes. */
125  void read_guiding_passes()
126  {
127  read_guiding_pass(oidn_albedo_pass_);
128  read_guiding_pass(oidn_normal_pass_);
129  }
130 
131  void denoise_pass(const PassType pass_type)
132  {
133  OIDNPass oidn_color_pass(buffer_params_, "color", pass_type);
134  if (oidn_color_pass.offset == PASS_UNUSED) {
135  return;
136  }
137 
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.";
141  return;
142  }
143  }
144 
145  OIDNPass oidn_output_pass(buffer_params_, "output", pass_type, PassMode::DENOISED);
146  if (oidn_output_pass.offset == PASS_UNUSED) {
147  LOG(DFATAL) << "Missing denoised pass " << pass_type_as_string(pass_type);
148  return;
149  }
150 
151  OIDNPass oidn_color_access_pass = read_input_pass(oidn_color_pass, oidn_output_pass);
152 
153  oidn::DeviceRef oidn_device = oidn::newDevice();
154  oidn_device.set("setAffinity", false);
155  oidn_device.commit();
156 
157  /* Create a filter for denoising a beauty (color) image using prefiltered auxiliary images too.
158  */
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);
166  if (denoise_params_.prefilter == DENOISER_PREFILTER_NONE ||
167  denoise_params_.prefilter == DENOISER_PREFILTER_ACCURATE) {
168  oidn_filter.set("cleanAux", true);
169  }
170  oidn_filter.commit();
171 
172  filter_guiding_pass_if_needed(oidn_device, oidn_albedo_pass_);
173  filter_guiding_pass_if_needed(oidn_device, oidn_normal_pass_);
174 
175  /* Filter the beauty image. */
176  oidn_filter.execute();
177 
178  /* Check for errors. */
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;
183  }
184 
185  postprocess_output(oidn_color_pass, oidn_output_pass);
186  }
187 
188  protected:
189  void filter_guiding_pass_if_needed(oidn::DeviceRef &oidn_device, OIDNPass &oidn_pass)
190  {
191  if (denoise_params_.prefilter != DENOISER_PREFILTER_ACCURATE || !oidn_pass ||
192  oidn_pass.is_filtered) {
193  return;
194  }
195 
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();
201 
202  oidn_pass.is_filtered = true;
203  }
204 
205  /* Make pixels of a guiding pass available by the denoiser. */
206  void read_guiding_pass(OIDNPass &oidn_pass)
207  {
208  if (!oidn_pass) {
209  return;
210  }
211 
212  DCHECK(!oidn_pass.use_compositing);
213 
214  if (denoise_params_.prefilter != DENOISER_PREFILTER_ACCURATE &&
215  !is_pass_scale_needed(oidn_pass)) {
216  /* Pass data is available as-is from the render buffers. */
217  return;
218  }
219 
220  if (allow_inplace_modification_) {
221  scale_pass_in_render_buffers(oidn_pass);
222  return;
223  }
224 
225  read_pass_pixels_into_buffer(oidn_pass);
226  }
227 
228  /* Special reader of the input pass.
229  * To save memory it will read pixels into the output, and let the denoiser to perform an
230  * in-place operation. */
231  OIDNPass read_input_pass(OIDNPass &oidn_input_pass, const OIDNPass &oidn_output_pass)
232  {
233  const bool use_compositing = oidn_input_pass.use_compositing;
234 
235  /* Simple case: no compositing is involved, no scaling is needed.
236  * The pass pixels will be referenced as-is, without extra processing. */
237  if (!use_compositing && !is_pass_scale_needed(oidn_input_pass)) {
238  return oidn_input_pass;
239  }
240 
241  float *buffer_data = render_buffers_->buffer.data();
242  float *pass_data = buffer_data + oidn_output_pass.offset;
243 
244  PassAccessor::Destination destination(pass_data, 3);
245  destination.pixel_stride = buffer_params_.pass_stride;
246 
247  read_pass_pixels(oidn_input_pass, destination);
248 
249  OIDNPass oidn_input_pass_at_output = oidn_input_pass;
250  oidn_input_pass_at_output.offset = oidn_output_pass.offset;
251 
252  return oidn_input_pass_at_output;
253  }
254 
255  /* Read pass pixels using PassAccessor into the given destination. */
256  void read_pass_pixels(const OIDNPass &oidn_pass, const PassAccessor::Destination &destination)
257  {
258  PassAccessor::PassAccessInfo pass_access_info;
259  pass_access_info.type = oidn_pass.type;
260  pass_access_info.mode = oidn_pass.mode;
261  pass_access_info.offset = oidn_pass.offset;
262 
263  /* Denoiser operates on passes which are used to calculate the approximation, and is never used
264  * on the approximation. The latter is not even possible because OIDN does not support
265  * denoising of semi-transparent pixels. */
266  pass_access_info.use_approximate_shadow_catcher = false;
267  pass_access_info.use_approximate_shadow_catcher_background = false;
268  pass_access_info.show_active_pixels = false;
269 
270  /* OIDN will perform an auto-exposure, so it is not required to know exact exposure configured
271  * by users. What is important is to use same exposure for read and write access of the pass
272  * pixels. */
273  const PassAccessorCPU pass_accessor(pass_access_info, 1.0f, num_samples_);
274 
275  BufferParams buffer_params = buffer_params_;
276  buffer_params.window_x = 0;
277  buffer_params.window_y = 0;
278  buffer_params.window_width = buffer_params.width;
279  buffer_params.window_height = buffer_params.height;
280 
281  pass_accessor.get_render_tile_pixels(render_buffers_, buffer_params, destination);
282  }
283 
284  /* Read pass pixels using PassAccessor into a temporary buffer which is owned by the pass.. */
285  void read_pass_pixels_into_buffer(OIDNPass &oidn_pass)
286  {
287  VLOG_WORK << "Allocating temporary buffer for pass " << oidn_pass.name << " ("
288  << pass_type_as_string(oidn_pass.type) << ")";
289 
290  const int64_t width = buffer_params_.width;
291  const int64_t height = buffer_params_.height;
292 
293  array<float> &scaled_buffer = oidn_pass.scaled_buffer;
294  scaled_buffer.resize(width * height * 3);
295 
296  const PassAccessor::Destination destination(scaled_buffer.data(), 3);
297 
298  read_pass_pixels(oidn_pass, destination);
299  }
300 
301  /* Set OIDN image to reference pixels from the given render buffer pass.
302  * No transform to the pixels is done, no additional memory is used. */
303  void set_pass_referenced(oidn::FilterRef &oidn_filter,
304  const char *name,
305  const OIDNPass &oidn_pass)
306  {
307  const int64_t x = buffer_params_.full_x;
308  const int64_t y = buffer_params_.full_y;
309  const int64_t width = buffer_params_.width;
310  const int64_t height = buffer_params_.height;
311  const int64_t offset = buffer_params_.offset;
312  const int64_t stride = buffer_params_.stride;
313  const int64_t pass_stride = buffer_params_.pass_stride;
314 
315  const int64_t pixel_index = offset + x + y * stride;
316  const int64_t buffer_offset = pixel_index * pass_stride;
317 
318  float *buffer_data = render_buffers_->buffer.data();
319 
320  oidn_filter.setImage(name,
321  buffer_data + buffer_offset + oidn_pass.offset,
322  oidn::Format::Float3,
323  width,
324  height,
325  0,
326  pass_stride * sizeof(float),
327  stride * pass_stride * sizeof(float));
328  }
329 
330  void set_pass_from_buffer(oidn::FilterRef &oidn_filter, const char *name, OIDNPass &oidn_pass)
331  {
332  const int64_t width = buffer_params_.width;
333  const int64_t height = buffer_params_.height;
334 
335  oidn_filter.setImage(
336  name, oidn_pass.scaled_buffer.data(), oidn::Format::Float3, width, height, 0, 0, 0);
337  }
338 
339  void set_pass(oidn::FilterRef &oidn_filter, OIDNPass &oidn_pass)
340  {
341  set_pass(oidn_filter, oidn_pass.name, oidn_pass);
342  }
343  void set_pass(oidn::FilterRef &oidn_filter, const char *name, OIDNPass &oidn_pass)
344  {
345  if (oidn_pass.scaled_buffer.empty()) {
346  set_pass_referenced(oidn_filter, name, oidn_pass);
347  }
348  else {
349  set_pass_from_buffer(oidn_filter, name, oidn_pass);
350  }
351  }
352 
353  void set_input_pass(oidn::FilterRef &oidn_filter, OIDNPass &oidn_pass)
354  {
355  set_pass_referenced(oidn_filter, oidn_pass.name, oidn_pass);
356  }
357 
358  void set_guiding_passes(oidn::FilterRef &oidn_filter, OIDNPass &oidn_pass)
359  {
360  if (oidn_albedo_pass_) {
361  if (oidn_pass.use_denoising_albedo) {
362  set_pass(oidn_filter, oidn_albedo_pass_);
363  }
364  else {
365  /* NOTE: OpenImageDenoise library implicitly expects albedo pass when normal pass has been
366  * provided. */
367  set_fake_albedo_pass(oidn_filter);
368  }
369  }
370 
371  if (oidn_normal_pass_) {
372  set_pass(oidn_filter, oidn_normal_pass_);
373  }
374  }
375 
376  void set_fake_albedo_pass(oidn::FilterRef &oidn_filter)
377  {
378  const int64_t width = buffer_params_.width;
379  const int64_t height = buffer_params_.height;
380 
381  if (!albedo_replaced_with_fake_) {
382  const int64_t num_pixel_components = width * height * 3;
383  oidn_albedo_pass_.scaled_buffer.resize(num_pixel_components);
384 
385  for (int i = 0; i < num_pixel_components; ++i) {
386  oidn_albedo_pass_.scaled_buffer[i] = 0.5f;
387  }
388 
389  albedo_replaced_with_fake_ = true;
390  }
391 
392  set_pass(oidn_filter, oidn_albedo_pass_);
393  }
394 
395  void set_output_pass(oidn::FilterRef &oidn_filter, OIDNPass &oidn_pass)
396  {
397  set_pass(oidn_filter, "output", oidn_pass);
398  }
399 
400  /* Scale output pass to match adaptive sampling per-pixel scale, as well as bring alpha channel
401  * back. */
402  void postprocess_output(const OIDNPass &oidn_input_pass, const OIDNPass &oidn_output_pass)
403  {
404  kernel_assert(oidn_input_pass.num_components == oidn_output_pass.num_components);
405 
406  const int64_t x = buffer_params_.full_x;
407  const int64_t y = buffer_params_.full_y;
408  const int64_t width = buffer_params_.width;
409  const int64_t height = buffer_params_.height;
410  const int64_t offset = buffer_params_.offset;
411  const int64_t stride = buffer_params_.stride;
412  const int64_t pass_stride = buffer_params_.pass_stride;
413  const int64_t row_stride = stride * pass_stride;
414 
415  const int64_t pixel_offset = offset + x + y * stride;
416  const int64_t buffer_offset = (pixel_offset * pass_stride);
417 
418  float *buffer_data = render_buffers_->buffer.data();
419 
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;
422 
423  for (int y = 0; y < height; ++y) {
424  float *buffer_row = buffer_data + buffer_offset + y * row_stride;
425  for (int x = 0; x < width; ++x) {
426  float *buffer_pixel = buffer_row + x * pass_stride;
427  float *denoised_pixel = buffer_pixel + oidn_output_pass.offset;
428 
429  if (need_scale) {
430  const float pixel_scale = has_pass_sample_count ?
431  __float_as_uint(buffer_pixel[pass_sample_count_]) :
432  num_samples_;
433 
437  }
438 
439  if (oidn_output_pass.num_components == 3) {
440  /* Pass without alpha channel. */
441  }
442  else if (!oidn_input_pass.use_compositing) {
443  /* Currently compositing passes are either 3-component (derived by dividing light passes)
444  * or do not have transparency (shadow catcher). Implicitly rely on this logic, as it
445  * simplifies logic and avoids extra memory allocation. */
446  const float *noisy_pixel = buffer_pixel + oidn_input_pass.offset;
447  denoised_pixel[3] = noisy_pixel[3];
448  }
449  else {
450  /* Assigning to zero since this is a default alpha value for 3-component passes, and it
451  * is an opaque pixel for 4 component passes. */
452  denoised_pixel[3] = 0;
453  }
454  }
455  }
456  }
457 
458  bool is_pass_scale_needed(OIDNPass &oidn_pass) const
459  {
460  if (pass_sample_count_ != PASS_UNUSED) {
461  /* With adaptive sampling pixels will have different number of samples in them, so need to
462  * always scale the pass to make pixels uniformly sampled. */
463  return true;
464  }
465 
466  if (!oidn_pass.need_scale) {
467  return false;
468  }
469 
470  if (num_samples_ == 1) {
471  /* If the avoid scaling if there is only one sample, to save up time (so we don't divide
472  * buffer by 1). */
473  return false;
474  }
475 
476  return true;
477  }
478 
479  void scale_pass_in_render_buffers(OIDNPass &oidn_pass)
480  {
481  const int64_t x = buffer_params_.full_x;
482  const int64_t y = buffer_params_.full_y;
483  const int64_t width = buffer_params_.width;
484  const int64_t height = buffer_params_.height;
485  const int64_t offset = buffer_params_.offset;
486  const int64_t stride = buffer_params_.stride;
487  const int64_t pass_stride = buffer_params_.pass_stride;
488  const int64_t row_stride = stride * pass_stride;
489 
490  const int64_t pixel_offset = offset + x + y * stride;
491  const int64_t buffer_offset = (pixel_offset * pass_stride);
492 
493  float *buffer_data = render_buffers_->buffer.data();
494 
495  const bool has_pass_sample_count = (pass_sample_count_ != PASS_UNUSED);
496 
497  for (int y = 0; y < height; ++y) {
498  float *buffer_row = buffer_data + buffer_offset + y * row_stride;
499  for (int x = 0; x < width; ++x) {
500  float *buffer_pixel = buffer_row + x * pass_stride;
501  float *pass_pixel = buffer_pixel + oidn_pass.offset;
502 
503  const float pixel_scale = 1.0f / (has_pass_sample_count ?
504  __float_as_uint(buffer_pixel[pass_sample_count_]) :
505  num_samples_);
506 
507  pass_pixel[0] = pass_pixel[0] * pixel_scale;
508  pass_pixel[1] = pass_pixel[1] * pixel_scale;
509  pass_pixel[2] = pass_pixel[2] * pixel_scale;
510  }
511  }
512  }
513 
514  OIDNDenoiser *denoiser_ = nullptr;
515 
516  const DenoiseParams &denoise_params_;
517  const BufferParams &buffer_params_;
518  RenderBuffers *render_buffers_ = nullptr;
519  int num_samples_ = 0;
520  bool allow_inplace_modification_ = false;
521  int pass_sample_count_ = PASS_UNUSED;
522 
523  /* Optional albedo and normal passes, reused by denoising of different pass types. */
524  OIDNPass oidn_albedo_pass_;
525  OIDNPass oidn_normal_pass_;
526 
527  /* For passes which don't need albedo channel for denoising we replace the actual albedo with
528  * the (0.5, 0.5, 0.5). This flag indicates that the real albedo pass has been replaced with
529  * the fake values and denoising of passes which do need albedo can no longer happen. */
530  bool albedo_replaced_with_fake_ = false;
531 };
532 
533 static unique_ptr<DeviceQueue> create_device_queue(const RenderBuffers *render_buffers)
534 {
535  Device *device = render_buffers->buffer.device;
536  if (device->info.has_gpu_queue) {
537  return device->gpu_queue_create();
538  }
539  return nullptr;
540 }
541 
542 static void copy_render_buffers_from_device(unique_ptr<DeviceQueue> &queue,
543  RenderBuffers *render_buffers)
544 {
545  if (queue) {
546  queue->copy_from_device(render_buffers->buffer);
547  queue->synchronize();
548  }
549  else {
550  render_buffers->copy_from_device();
551  }
552 }
553 
554 static void copy_render_buffers_to_device(unique_ptr<DeviceQueue> &queue,
555  RenderBuffers *render_buffers)
556 {
557  if (queue) {
558  queue->copy_to_device(render_buffers->buffer);
559  queue->synchronize();
560  }
561  else {
562  render_buffers->copy_to_device();
563  }
564 }
565 
566 #endif
567 
568 bool OIDNDenoiser::denoise_buffer(const BufferParams &buffer_params,
569  RenderBuffers *render_buffers,
570  const int num_samples,
571  bool allow_inplace_modification)
572 {
574  << "OpenImageDenoiser is not supported on this platform or build.";
575 
576 #ifdef WITH_OPENIMAGEDENOISE
578 
579  /* Make sure the host-side data is available for denoising. */
580  unique_ptr<DeviceQueue> queue = create_device_queue(render_buffers);
581  copy_render_buffers_from_device(queue, render_buffers);
582 
583  OIDNDenoiseContext context(
584  this, params_, buffer_params, render_buffers, num_samples, allow_inplace_modification);
585 
586  if (context.need_denoising()) {
587  context.read_guiding_passes();
588 
589  const std::array<PassType, 3> passes = {
590  {/* Passes which will use real albedo when it is available. */
593 
594  /* Passes which do not need albedo and hence if real is present it needs to become fake.
595  */
597 
598  for (const PassType pass_type : passes) {
599  context.denoise_pass(pass_type);
600  if (is_cancelled()) {
601  return false;
602  }
603  }
604 
605  /* TODO: It may be possible to avoid this copy, but we have to ensure that when other code
606  * copies data from the device it doesn't overwrite the denoiser buffers. */
607  copy_render_buffers_to_device(queue, render_buffers);
608  }
609 #else
610  (void)buffer_params;
611  (void)render_buffers;
612  (void)num_samples;
613  (void)allow_inplace_modification;
614 #endif
615 
616  /* This code is not supposed to run when compiled without OIDN support, so can assume if we made
617  * it up here all passes are properly denoised. */
618  return true;
619 }
620 
622 {
623  return DEVICE_MASK_CPU;
624 }
625 
627 {
628 #ifndef WITH_OPENIMAGEDENOISE
629  (void)progress;
630  path_trace_device_->set_error("Build without OpenImageDenoiser");
631  return nullptr;
632 #else
635  "OpenImageDenoiser is not supported on this CPU: missing SSE 4.1 support");
636  return nullptr;
637  }
638 
639  return Denoiser::ensure_denoiser_device(progress);
640 #endif
641 }
642 
unsigned int uint
Definition: BLI_sys_types.h:67
_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
volatile int lock
int height
Definition: buffers.h:72
int get_pass_offset(PassType type, PassMode mode=PassMode::NOISY) const
Definition: buffers.cpp:168
int window_y
Definition: buffers.h:79
int window_height
Definition: buffers.h:81
int window_width
Definition: buffers.h:80
NODE_DECLARE int width
Definition: buffers.h:71
int window_x
Definition: buffers.h:78
virtual Device * ensure_denoiser_device(Progress *progress)
Definition: denoiser.cpp:178
DenoiseParams params_
Definition: denoiser.h:110
bool is_cancelled() const
Definition: denoiser.h:91
Device * path_trace_device_
Definition: denoiser.h:109
bool has_gpu_queue
Definition: device/device.h:71
virtual unique_ptr< DeviceQueue > gpu_queue_create()
virtual void set_error(const string &error)
DeviceInfo info
OIDNDenoiser(Device *path_trace_device, const DenoiseParams &params)
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_
Definition: denoiser_oidn.h:32
virtual Device * ensure_denoiser_device(Progress *progress) override
PassInfo get_info() const
Definition: pass.cpp:136
device_vector< float > buffer
Definition: buffers.h:159
bool copy_from_device()
Definition: buffers.cpp:289
void copy_to_device()
Definition: buffers.cpp:301
T * resize(size_t newsize)
#define kernel_assert(cond)
Definition: cpu/compat.h:34
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
@ DENOISER_PREFILTER_NONE
Definition: denoise.h:29
@ DENOISER_PREFILTER_ACCURATE
Definition: denoise.h:37
@ DENOISER_OPENIMAGEDENOISE
Definition: denoise.h:14
@ DEVICE_MASK_CPU
Definition: device/device.h:49
SyclQueue * queue
SyclQueue void void size_t num_bytes void
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_gpu_kernel_postfix ccl_global float int int int int int int int int int int int int num_components
float pixel_scale
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
#define PASS_UNUSED
Definition: kernel/types.h:44
PassType
Definition: kernel/types.h:334
@ PASS_SHADOW_CATCHER_MATTE
Definition: kernel/types.h:394
@ PASS_SHADOW_CATCHER
Definition: kernel/types.h:392
@ PASS_DENOISING_NORMAL
Definition: kernel/types.h:377
@ PASS_COMBINED
Definition: kernel/types.h:338
@ PASS_NONE
Definition: kernel/types.h:335
@ PASS_SAMPLE_COUNT
Definition: kernel/types.h:371
@ PASS_DENOISING_ALBEDO
Definition: kernel/types.h:378
#define DCHECK(expression)
Definition: log.h:55
#define DCHECK_EQ(a, b)
Definition: log.h:64
#define VLOG_WORK
Definition: log.h:80
#define LOG(severity)
Definition: log.h:36
static void error(const char *str)
Definition: meshlaplacian.c:51
static CCL_NAMESPACE_BEGIN bool openimagedenoise_supported()
CCL_NAMESPACE_BEGIN const char * pass_type_as_string(const PassType type)
Definition: pass.cpp:11
PassMode
Definition: pass.h:19
__int64 int64_t
Definition: stdint.h:89
Definition: pass.h:26
bool use_compositing
Definition: pass.h:37
bool use_denoising_albedo
Definition: pass.h:42
int num_components
Definition: pass.h:27
std::unique_lock< std::mutex > thread_scoped_lock
Definition: thread.h:28
CCL_NAMESPACE_BEGIN typedef std::mutex thread_mutex
Definition: thread.h:27
ccl_device_inline uint __float_as_uint(float f)
Definition: util/math.h:263