Blender  V3.3
denoising.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #include "session/denoising.h"
5 
6 #include "util/map.h"
7 #include "util/system.h"
8 #include "util/task.h"
9 #include "util/time.h"
10 
11 #include <OpenImageIO/filesystem.h>
12 
14 
15 /* Utility Functions */
16 
17 /* Splits in at its last dot, setting suffix to the part after the dot and in to the part before
18  * it. Returns whether a dot was found. */
19 static bool split_last_dot(string &in, string &suffix)
20 {
21  size_t pos = in.rfind(".");
22  if (pos == string::npos) {
23  return false;
24  }
25  suffix = in.substr(pos + 1);
26  in = in.substr(0, pos);
27  return true;
28 }
29 
30 /* Separate channel names as generated by Blender.
31  * If views is true:
32  * Inputs are expected in the form RenderLayer.Pass.View.Channel, sets renderlayer to
33  * "RenderLayer.View" Otherwise: Inputs are expected in the form RenderLayer.Pass.Channel */
34 static bool parse_channel_name(
35  string name, string &renderlayer, string &pass, string &channel, bool multiview_channels)
36 {
37  if (!split_last_dot(name, channel)) {
38  return false;
39  }
40  string view;
41  if (multiview_channels && !split_last_dot(name, view)) {
42  return false;
43  }
44  if (!split_last_dot(name, pass)) {
45  return false;
46  }
47  renderlayer = name;
48 
49  if (multiview_channels) {
50  renderlayer += "." + view;
51  }
52 
53  return true;
54 }
55 
56 /* Channel Mapping */
57 
59  int channel;
60  string name;
61 };
62 
63 static void fill_mapping(vector<ChannelMapping> &map, int pos, string name, string channels)
64 {
65  for (const char *chan = channels.c_str(); *chan; chan++) {
66  map.push_back({pos++, name + "." + *chan});
67  }
68 }
69 
70 static const int INPUT_NUM_CHANNELS = 13;
71 static const int INPUT_NOISY_IMAGE = 0;
72 static const int INPUT_DENOISING_NORMAL = 3;
73 static const int INPUT_DENOISING_ALBEDO = 6;
74 static const int INPUT_MOTION = 9;
76 {
78  fill_mapping(map, INPUT_NOISY_IMAGE, "Combined", "RGB");
79  fill_mapping(map, INPUT_DENOISING_NORMAL, "Denoising Normal", "XYZ");
80  fill_mapping(map, INPUT_DENOISING_ALBEDO, "Denoising Albedo", "RGB");
81  fill_mapping(map, INPUT_MOTION, "Vector", "XYZW");
82  return map;
83 }
84 
85 static const int OUTPUT_NUM_CHANNELS = 3;
87 {
89  fill_mapping(map, 0, "Combined", "RGB");
90  return map;
91 }
92 
93 /* Render-layer Handling. */
94 
96 {
97  /* Map device input to image channels. */
98  input_to_image_channel.clear();
100 
101  for (const ChannelMapping &mapping : input_channels()) {
102  vector<string>::iterator i = find(channels.begin(), channels.end(), mapping.name);
103  if (i == channels.end()) {
104  return false;
105  }
106 
107  size_t input_channel = mapping.channel;
108  size_t layer_channel = i - channels.begin();
109  input_to_image_channel[input_channel] = layer_to_image_channel[layer_channel];
110  }
111 
112  /* Map device output to image channels. */
113  output_to_image_channel.clear();
115 
116  for (const ChannelMapping &mapping : output_channels()) {
117  vector<string>::iterator i = find(channels.begin(), channels.end(), mapping.name);
118  if (i == channels.end()) {
119  return false;
120  }
121 
122  size_t output_channel = mapping.channel;
123  size_t layer_channel = i - channels.begin();
124  output_to_image_channel[output_channel] = layer_to_image_channel[layer_channel];
125  }
126 
127  /* Check that all buffer channels are correctly set. */
128  for (int i = 0; i < INPUT_NUM_CHANNELS; i++) {
129  assert(input_to_image_channel[i] >= 0);
130  }
131  for (int i = 0; i < OUTPUT_NUM_CHANNELS; i++) {
132  assert(output_to_image_channel[i] >= 0);
133  }
134 
135  return true;
136 }
137 
138 bool DenoiseImageLayer::match_channels(const std::vector<string> &channelnames,
139  const std::vector<string> &neighbor_channelnames)
140 {
142 
143  assert(mapping.size() == 0);
144  mapping.resize(output_to_image_channel.size(), -1);
145 
146  for (int i = 0; i < output_to_image_channel.size(); i++) {
147  const string &channel = channelnames[output_to_image_channel[i]];
148  std::vector<string>::const_iterator frame_channel = find(
149  neighbor_channelnames.begin(), neighbor_channelnames.end(), channel);
150 
151  if (frame_channel == neighbor_channelnames.end()) {
152  return false;
153  }
154 
155  mapping[i] = frame_channel - neighbor_channelnames.begin();
156  }
157 
158  return true;
159 }
160 
161 /* Denoise Task */
162 
163 DenoiseTask::DenoiseTask(Device *device, DenoiserPipeline *denoiser, int frame)
164  : denoiser(denoiser), device(device), frame(frame), current_layer(0), buffers(device)
165 {
166 }
167 
169 {
170  free();
171 }
172 
173 /* Denoiser Operations */
174 
176 {
177  /* Load center image */
178  DenoiseImageLayer &image_layer = image.layers[layer];
179 
180  float *buffer_data = buffers.buffer.data();
181  image.read_pixels(image_layer, buffers.params, buffer_data);
182 
183  /* Load previous image */
184  if (frame > 0 && !image.read_previous_pixels(image_layer, buffers.params, buffer_data)) {
185  error = "Failed to read neighbor frame pixels";
186  return false;
187  }
188 
189  /* Copy to device */
191 
192  return true;
193 }
194 
195 /* Task stages */
196 
198 {
199  Pass *pass = new Pass();
200  pass->set_type(type);
201  pass->set_mode(mode);
202 
203  passes.push_back(pass);
204 }
205 
207 {
208  string center_filepath = denoiser->input[frame];
209  if (!image.load(center_filepath, error)) {
210  return false;
211  }
212 
213  /* Use previous frame output as input for subsequent frames. */
214  if (frame > 0 && !image.load_previous(denoiser->output[frame - 1], error)) {
215  return false;
216  }
217 
218  if (image.layers.empty()) {
219  error = "No image layers found to denoise in " + center_filepath;
220  return false;
221  }
222 
223  /* Enable temporal denoising for frames after the first (which will use the output from the
224  * previous frames). */
225  DenoiseParams params = denoiser->denoiser->get_params();
226  params.temporally_stable = frame > 0;
227  denoiser->denoiser->set_params(params);
228 
229  /* Allocate device buffer. */
230  vector<Pass *> passes;
237 
238  BufferParams buffer_params;
239  buffer_params.width = image.width;
240  buffer_params.height = image.height;
241  buffer_params.full_x = 0;
242  buffer_params.full_y = 0;
243  buffer_params.full_width = image.width;
244  buffer_params.full_height = image.height;
245  buffer_params.update_passes(passes);
246 
247  for (Pass *pass : passes) {
248  delete pass;
249  }
250 
251  buffers.reset(buffer_params);
252 
253  /* Read pixels for first layer. */
254  current_layer = 0;
256  return false;
257  }
258 
259  return true;
260 }
261 
263 {
264  for (current_layer = 0; current_layer < image.layers.size(); current_layer++) {
265  /* Read pixels for secondary layers, first was already loaded. */
266  if (current_layer > 0) {
268  return false;
269  }
270  }
271 
272  /* Run task on device. */
273  denoiser->denoiser->denoise_buffer(buffers.params, &buffers, 1, true);
274 
275  /* Copy denoised pixels from device. */
277 
278  float *result = buffers.buffer.data(), *out = image.pixels.data();
279 
281  const int *output_to_image_channel = layer.output_to_image_channel.data();
282 
283  for (int y = 0; y < image.height; y++) {
284  for (int x = 0; x < image.width; x++, result += buffers.params.pass_stride) {
285  for (int j = 0; j < OUTPUT_NUM_CHANNELS; j++) {
287  int image_channel = output_to_image_channel[j];
288  out[image.num_channels * x + image_channel] = result[offset + j];
289  }
290  }
292  }
293 
294  printf("\n");
295  }
296 
297  return true;
298 }
299 
301 {
302  bool ok = image.save_output(denoiser->output[frame], error);
303  free();
304  return ok;
305 }
306 
308 {
309  image.free();
310  buffers.buffer.free();
311 }
312 
313 /* Denoise Image Storage */
314 
316 {
317  width = 0;
318  height = 0;
319  num_channels = 0;
320  samples = 0;
321 }
322 
324 {
325  free();
326 }
327 
329 {
330  in_previous.reset();
331 }
332 
334 {
335  close_input();
336  pixels.clear();
337 }
338 
339 bool DenoiseImage::parse_channels(const ImageSpec &in_spec, string &error)
340 {
341  const std::vector<string> &channels = in_spec.channelnames;
342  const ParamValue *multiview = in_spec.find_attribute("multiView");
343  const bool multiview_channels = (multiview && multiview->type().basetype == TypeDesc::STRING &&
344  multiview->type().arraylen >= 2);
345 
346  layers.clear();
347 
348  /* Loop over all the channels in the file, parse their name and sort them
349  * by RenderLayer.
350  * Channels that can't be parsed are directly passed through to the output. */
351  map<string, DenoiseImageLayer> file_layers;
352  for (int i = 0; i < channels.size(); i++) {
353  string layer, pass, channel;
354  if (parse_channel_name(channels[i], layer, pass, channel, multiview_channels)) {
355  file_layers[layer].channels.push_back(pass + "." + channel);
356  file_layers[layer].layer_to_image_channel.push_back(i);
357  }
358  }
359 
360  /* Loop over all detected RenderLayers, check whether they contain a full set of input channels.
361  * Any channels that won't be processed internally are also passed through. */
362  for (map<string, DenoiseImageLayer>::iterator i = file_layers.begin(); i != file_layers.end();
363  ++i) {
364  const string &name = i->first;
365  DenoiseImageLayer &layer = i->second;
366 
367  /* Check for full pass set. */
368  if (!layer.detect_denoising_channels()) {
369  continue;
370  }
371 
372  layer.name = name;
373  layer.samples = samples;
374 
375  /* If the sample value isn't set yet, check if there is a layer-specific one in the input file.
376  */
377  if (layer.samples < 1) {
378  string sample_string = in_spec.get_string_attribute("cycles." + name + ".samples", "");
379  if (sample_string != "") {
380  if (!sscanf(sample_string.c_str(), "%d", &layer.samples)) {
381  error = "Failed to parse samples metadata: " + sample_string;
382  return false;
383  }
384  }
385  }
386 
387  if (layer.samples < 1) {
389  "No sample number specified in the file for layer %s or on the command line",
390  name.c_str());
391  return false;
392  }
393 
394  layers.push_back(layer);
395  }
396 
397  return true;
398 }
399 
401  const BufferParams &params,
402  float *input_pixels)
403 {
404  /* Pixels from center file have already been loaded into pixels.
405  * We copy a subset into the device input buffer with channels reshuffled. */
406  const int *input_to_image_channel = layer.input_to_image_channel.data();
407 
408  for (int i = 0; i < width * height; i++) {
409  for (int j = 0; j < 3; ++j) {
410  int offset = params.get_pass_offset(PASS_COMBINED);
411  int image_channel = input_to_image_channel[INPUT_NOISY_IMAGE + j];
412  input_pixels[i * params.pass_stride + offset + j] =
413  pixels[((size_t)i) * num_channels + image_channel];
414  }
415  for (int j = 0; j < 3; ++j) {
416  int offset = params.get_pass_offset(PASS_DENOISING_NORMAL);
417  int image_channel = input_to_image_channel[INPUT_DENOISING_NORMAL + j];
418  input_pixels[i * params.pass_stride + offset + j] =
419  pixels[((size_t)i) * num_channels + image_channel];
420  }
421  for (int j = 0; j < 3; ++j) {
422  int offset = params.get_pass_offset(PASS_DENOISING_ALBEDO);
423  int image_channel = input_to_image_channel[INPUT_DENOISING_ALBEDO + j];
424  input_pixels[i * params.pass_stride + offset + j] =
425  pixels[((size_t)i) * num_channels + image_channel];
426  }
427  for (int j = 0; j < 4; ++j) {
428  int offset = params.get_pass_offset(PASS_MOTION);
429  int image_channel = input_to_image_channel[INPUT_MOTION + j];
430  input_pixels[i * params.pass_stride + offset + j] =
431  pixels[((size_t)i) * num_channels + image_channel];
432  }
433  }
434 }
435 
437  const BufferParams &params,
438  float *input_pixels)
439 {
440  /* Load pixels from neighboring frames, and copy them into device buffer
441  * with channels reshuffled. */
442  size_t num_pixels = (size_t)width * (size_t)height;
443  array<float> neighbor_pixels(num_pixels * num_channels);
444  if (!in_previous->read_image(TypeDesc::FLOAT, neighbor_pixels.data())) {
445  return false;
446  }
447 
448  const int *output_to_image_channel = layer.previous_output_to_image_channel.data();
449 
450  for (int i = 0; i < width * height; i++) {
451  for (int j = 0; j < 3; ++j) {
452  int offset = params.get_pass_offset(PASS_DENOISING_PREVIOUS);
453  int image_channel = output_to_image_channel[j];
454  input_pixels[i * params.pass_stride + offset + j] =
455  neighbor_pixels[((size_t)i) * num_channels + image_channel];
456  }
457  }
458 
459  return true;
460 }
461 
462 bool DenoiseImage::load(const string &in_filepath, string &error)
463 {
464  if (!Filesystem::is_regular(in_filepath)) {
465  error = "Couldn't find file: " + in_filepath;
466  return false;
467  }
468 
469  unique_ptr<ImageInput> in(ImageInput::open(in_filepath));
470  if (!in) {
471  error = "Couldn't open file: " + in_filepath;
472  return false;
473  }
474 
475  in_spec = in->spec();
476  width = in_spec.width;
477  height = in_spec.height;
478  num_channels = in_spec.nchannels;
479 
480  if (!parse_channels(in_spec, error)) {
481  return false;
482  }
483 
484  if (layers.empty()) {
485  error = "Could not find a render layer containing denoising data and motion vector passes";
486  return false;
487  }
488 
489  size_t num_pixels = (size_t)width * (size_t)height;
491 
492  /* Read all channels into buffer. Reading all channels at once is faster
493  * than individually due to interleaved EXR channel storage. */
494  if (!in->read_image(TypeDesc::FLOAT, pixels.data())) {
495  error = "Failed to read image: " + in_filepath;
496  return false;
497  }
498 
499  return true;
500 }
501 
502 bool DenoiseImage::load_previous(const string &filepath, string &error)
503 {
504  if (!Filesystem::is_regular(filepath)) {
505  error = "Couldn't find neighbor frame: " + filepath;
506  return false;
507  }
508 
509  unique_ptr<ImageInput> in_neighbor(ImageInput::open(filepath));
510  if (!in_neighbor) {
511  error = "Couldn't open neighbor frame: " + filepath;
512  return false;
513  }
514 
515  const ImageSpec &neighbor_spec = in_neighbor->spec();
516  if (neighbor_spec.width != width || neighbor_spec.height != height) {
517  error = "Neighbor frame has different dimensions: " + filepath;
518  return false;
519  }
520 
521  for (DenoiseImageLayer &layer : layers) {
522  if (!layer.match_channels(in_spec.channelnames, neighbor_spec.channelnames)) {
523  error = "Neighbor frame misses denoising data passes: " + filepath;
524  return false;
525  }
526  }
527 
528  in_previous = std::move(in_neighbor);
529 
530  return true;
531 }
532 
533 bool DenoiseImage::save_output(const string &out_filepath, string &error)
534 {
535  /* Save image with identical dimensions, channels and metadata. */
536  ImageSpec out_spec = in_spec;
537 
538  /* Ensure that the output frame contains sample information even if the input didn't. */
539  for (int i = 0; i < layers.size(); i++) {
540  string name = "cycles." + layers[i].name + ".samples";
541  if (!out_spec.find_attribute(name, TypeDesc::STRING)) {
542  out_spec.attribute(name, TypeDesc::STRING, string_printf("%d", layers[i].samples));
543  }
544  }
545 
546  /* We don't need input anymore at this point, and will possibly
547  * overwrite the same file. */
548  close_input();
549 
550  /* Write to temporary file path, so we denoise images in place and don't
551  * risk destroying files when something goes wrong in file saving. */
552  string extension = OIIO::Filesystem::extension(out_filepath);
553  string unique_name = ".denoise-tmp-" + OIIO::Filesystem::unique_path();
554  string tmp_filepath = out_filepath + unique_name + extension;
555  unique_ptr<ImageOutput> out(ImageOutput::create(tmp_filepath));
556 
557  if (!out) {
558  error = "Failed to open temporary file " + tmp_filepath + " for writing";
559  return false;
560  }
561 
562  /* Open temporary file and write image buffers. */
563  if (!out->open(tmp_filepath, out_spec)) {
564  error = "Failed to open file " + tmp_filepath + " for writing: " + out->geterror();
565  return false;
566  }
567 
568  bool ok = true;
569  if (!out->write_image(TypeDesc::FLOAT, pixels.data())) {
570  error = "Failed to write to file " + tmp_filepath + ": " + out->geterror();
571  ok = false;
572  }
573 
574  if (!out->close()) {
575  error = "Failed to save to file " + tmp_filepath + ": " + out->geterror();
576  ok = false;
577  }
578 
579  out.reset();
580 
581  /* Copy temporary file to output filepath. */
582  string rename_error;
583  if (ok && !OIIO::Filesystem::rename(tmp_filepath, out_filepath, rename_error)) {
584  error = "Failed to move denoised image to " + out_filepath + ": " + rename_error;
585  ok = false;
586  }
587 
588  if (!ok) {
589  OIIO::Filesystem::remove(tmp_filepath);
590  }
591 
592  return ok;
593 }
594 
595 /* File pattern handling and outer loop over frames */
596 
598 {
599  /* Initialize task scheduler. */
601 
602  /* Initialize device. */
603  device = Device::create(device_info, stats, profiler);
605 
607  denoiser->load_kernels(nullptr);
608 }
609 
611 {
612  denoiser.reset();
613  delete device;
615 }
616 
618 {
619  assert(input.size() == output.size());
620 
621  int num_frames = output.size();
622 
623  for (int frame = 0; frame < num_frames; frame++) {
624  /* Skip empty output paths. */
625  if (output[frame].empty()) {
626  continue;
627  }
628 
629  /* Execute task. */
630  DenoiseTask task(device, this, frame);
631  if (!task.load()) {
632  error = task.error;
633  return false;
634  }
635 
636  if (!task.exec()) {
637  error = task.error;
638  return false;
639  }
640 
641  if (!task.save()) {
642  error = task.error;
643  return false;
644  }
645 
646  task.free();
647  }
648 
649  return true;
650 }
651 
static AppView * view
_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
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a producing a negative Combine Generate a color from its and blue channels(Deprecated)") DefNode(ShaderNode
int pass_stride
Definition: buffers.h:93
int full_x
Definition: buffers.h:84
int full_width
Definition: buffers.h:86
int height
Definition: buffers.h:72
int get_pass_offset(PassType type, PassMode mode=PassMode::NOISY) const
Definition: buffers.cpp:168
int full_height
Definition: buffers.h:87
NODE_DECLARE int width
Definition: buffers.h:71
int full_y
Definition: buffers.h:85
void update_passes()
Definition: buffers.cpp:121
void read_pixels(const DenoiseImageLayer &layer, const BufferParams &params, float *input_pixels)
Definition: denoising.cpp:400
bool parse_channels(const ImageSpec &in_spec, string &error)
Definition: denoising.cpp:339
void close_input()
Definition: denoising.cpp:328
array< float > pixels
Definition: denoising.h:98
vector< DenoiseImageLayer > layers
Definition: denoising.h:105
bool read_previous_pixels(const DenoiseImageLayer &layer, const BufferParams &params, float *input_pixels)
Definition: denoising.cpp:436
int num_channels
Definition: denoising.h:92
bool load(const string &in_filepath, string &error)
Definition: denoising.cpp:462
unique_ptr< ImageInput > in_previous
Definition: denoising.h:102
bool load_previous(const string &in_filepath, string &error)
Definition: denoising.cpp:502
bool save_output(const string &out_filepath, string &error)
Definition: denoising.cpp:533
ImageSpec in_spec
Definition: denoising.h:101
DenoiserPipeline * denoiser
Definition: denoising.h:153
RenderBuffers buffers
Definition: denoising.h:163
bool load()
Definition: denoising.cpp:206
string error
Definition: denoising.h:149
DenoiseTask(Device *device, DenoiserPipeline *denoiser, int frame)
Definition: denoising.cpp:163
bool exec()
Definition: denoising.cpp:262
bool save()
Definition: denoising.cpp:300
bool load_input_pixels(int layer)
Definition: denoising.cpp:175
int current_layer
Definition: denoising.h:161
void free()
Definition: denoising.cpp:307
DenoiseImage image
Definition: denoising.h:160
std::unique_ptr< Denoiser > denoiser
Definition: denoising.h:48
DenoiserPipeline(DeviceInfo &device_info, const DenoiseParams &params)
Definition: denoising.cpp:597
Device * device
Definition: denoising.h:47
vector< string > input
Definition: denoising.h:36
Profiler profiler
Definition: denoising.h:46
vector< string > output
Definition: denoising.h:40
static unique_ptr< Denoiser > create(Device *path_trace_device, const DenoiseParams &params)
Definition: denoiser.cpp:15
static Device * create(const DeviceInfo &info, Stats &stats, Profiler &profiler)
virtual bool load_kernels(uint)
Definition: pass.h:48
device_vector< float > buffer
Definition: buffers.h:159
BufferParams params
Definition: buffers.h:156
void reset(const BufferParams &params)
Definition: buffers.cpp:274
static void exit()
Definition: task.cpp:83
static void init(int num_threads=0)
Definition: task.cpp:62
T * resize(size_t newsize)
void clear()
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
static const int INPUT_NOISY_IMAGE
Definition: denoising.cpp:71
static const int OUTPUT_NUM_CHANNELS
Definition: denoising.cpp:85
static void fill_mapping(vector< ChannelMapping > &map, int pos, string name, string channels)
Definition: denoising.cpp:63
static bool parse_channel_name(string name, string &renderlayer, string &pass, string &channel, bool multiview_channels)
Definition: denoising.cpp:34
static CCL_NAMESPACE_BEGIN bool split_last_dot(string &in, string &suffix)
Definition: denoising.cpp:19
static vector< ChannelMapping > input_channels()
Definition: denoising.cpp:75
static const int INPUT_DENOISING_ALBEDO
Definition: denoising.cpp:73
static const int INPUT_DENOISING_NORMAL
Definition: denoising.cpp:72
static const int INPUT_NUM_CHANNELS
Definition: denoising.cpp:70
static vector< ChannelMapping > output_channels()
Definition: denoising.cpp:86
static const int INPUT_MOTION
Definition: denoising.cpp:74
static void add_pass(vector< Pass * > &passes, PassType type, PassMode mode=PassMode::NOISY)
Definition: denoising.cpp:197
uint pos
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_gpu_kernel_postfix ccl_global float int num_pixels
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
@ KERNEL_FEATURE_DENOISING
PassType
Definition: kernel/types.h:334
@ PASS_DENOISING_NORMAL
Definition: kernel/types.h:377
@ PASS_MOTION
Definition: kernel/types.h:365
@ PASS_COMBINED
Definition: kernel/types.h:338
@ PASS_DENOISING_ALBEDO
Definition: kernel/types.h:378
@ PASS_DENOISING_PREVIOUS
Definition: kernel/types.h:380
static void error(const char *str)
Definition: meshlaplacian.c:51
bool remove(void *owner, const AttributeIDRef &attribute_id)
std::unique_ptr< IDProperty, IDPropertyDeleter > create(StringRefNull prop_name, int32_t value)
Allocate a new IDProperty of type IDP_INT, set its name and value.
struct blender::compositor::@179::@181 task
static const pxr::TfToken out("out", pxr::TfToken::Immortal)
static void unique_name(bNode *node)
SocketIndexByIdentifierMap * map
PassMode
Definition: pass.h:19
@ FLOAT
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
Definition: string.cpp:22
vector< int > previous_output_to_image_channel
Definition: denoising.h:71
vector< int > input_to_image_channel
Definition: denoising.h:64
bool match_channels(const std::vector< string > &channelnames, const std::vector< string > &neighbor_channelnames)
Definition: denoising.cpp:138
bool detect_denoising_channels()
Definition: denoising.cpp:95
vector< int > output_to_image_channel
Definition: denoising.h:68
vector< string > channels
Definition: denoising.h:56
vector< int > layer_to_image_channel
Definition: denoising.h:58