1 /*
2  * Copyright 2011-2018 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "render/denoising.h"
18 
19 #include "kernel/filter/filter_defines.h"
20 
21 #include "util/util_foreach.h"
22 #include "util/util_map.h"
23 #include "util/util_system.h"
24 #include "util/util_task.h"
25 #include "util/util_time.h"
26 
27 #include <OpenImageIO/filesystem.h>
28 
29 CCL_NAMESPACE_BEGIN
30 
31 /* Utility Functions */
32 
print_progress(int num,int total,int frame,int num_frames)33 static void print_progress(int num, int total, int frame, int num_frames)
34 {
35   const char *label = "Denoise Frame ";
36   int cols = system_console_width();
37 
38   cols -= strlen(label);
39 
40   int len = 1;
41   for (int x = total; x > 9; x /= 10) {
42     len++;
43   }
44 
45   int bars = cols - 2 * len - 6;
46 
47   printf("\r%s", label);
48 
49   if (num_frames > 1) {
50     int frame_len = 1;
51     for (int x = num_frames - 1; x > 9; x /= 10) {
52       frame_len++;
53     }
54     bars -= frame_len + 2;
55     printf("%*d ", frame_len, frame);
56   }
57 
58   int v = int(float(num) * bars / total);
59   printf("[");
60   for (int i = 0; i < v; i++) {
61     printf("=");
62   }
63   if (v < bars) {
64     printf(">");
65   }
66   for (int i = v + 1; i < bars; i++) {
67     printf(" ");
68   }
69   printf(string_printf("] %%%dd / %d", len, total).c_str(), num);
70   fflush(stdout);
71 }
72 
73 /* Splits in at its last dot, setting suffix to the part after the dot and in to the part before
74  * it. Returns whether a dot was found. */
split_last_dot(string & in,string & suffix)75 static bool split_last_dot(string &in, string &suffix)
76 {
77   size_t pos = in.rfind(".");
78   if (pos == string::npos) {
79     return false;
80   }
81   suffix = in.substr(pos + 1);
82   in = in.substr(0, pos);
83   return true;
84 }
85 
86 /* Separate channel names as generated by Blender.
87  * If views is true:
88  *   Inputs are expected in the form RenderLayer.Pass.View.Channel, sets renderlayer to
89  *   "RenderLayer.View" Otherwise: Inputs are expected in the form RenderLayer.Pass.Channel */
parse_channel_name(string name,string & renderlayer,string & pass,string & channel,bool multiview_channels)90 static bool parse_channel_name(
91     string name, string &renderlayer, string &pass, string &channel, bool multiview_channels)
92 {
93   if (!split_last_dot(name, channel)) {
94     return false;
95   }
96   string view;
97   if (multiview_channels && !split_last_dot(name, view)) {
98     return false;
99   }
100   if (!split_last_dot(name, pass)) {
101     return false;
102   }
103   renderlayer = name;
104 
105   if (multiview_channels) {
106     renderlayer += "." + view;
107   }
108 
109   return true;
110 }
111 
112 /* Channel Mapping */
113 
114 struct ChannelMapping {
115   int channel;
116   string name;
117 };
118 
fill_mapping(vector<ChannelMapping> & map,int pos,string name,string channels)119 static void fill_mapping(vector<ChannelMapping> &map, int pos, string name, string channels)
120 {
121   for (const char *chan = channels.c_str(); *chan; chan++) {
122     map.push_back({pos++, name + "." + *chan});
123   }
124 }
125 
126 static const int INPUT_NUM_CHANNELS = 15;
127 static const int INPUT_DENOISING_DEPTH = 0;
128 static const int INPUT_DENOISING_NORMAL = 1;
129 static const int INPUT_DENOISING_SHADOWING = 4;
130 static const int INPUT_DENOISING_ALBEDO = 5;
131 static const int INPUT_NOISY_IMAGE = 8;
132 static const int INPUT_DENOISING_VARIANCE = 11;
133 static const int INPUT_DENOISING_INTENSITY = 14;
input_channels()134 static vector<ChannelMapping> input_channels()
135 {
136   vector<ChannelMapping> map;
137   fill_mapping(map, INPUT_DENOISING_DEPTH, "Denoising Depth", "Z");
138   fill_mapping(map, INPUT_DENOISING_NORMAL, "Denoising Normal", "XYZ");
139   fill_mapping(map, INPUT_DENOISING_SHADOWING, "Denoising Shadowing", "X");
140   fill_mapping(map, INPUT_DENOISING_ALBEDO, "Denoising Albedo", "RGB");
141   fill_mapping(map, INPUT_NOISY_IMAGE, "Noisy Image", "RGB");
142   fill_mapping(map, INPUT_DENOISING_VARIANCE, "Denoising Variance", "RGB");
143   fill_mapping(map, INPUT_DENOISING_INTENSITY, "Denoising Intensity", "X");
144   return map;
145 }
146 
147 static const int OUTPUT_NUM_CHANNELS = 3;
output_channels()148 static vector<ChannelMapping> output_channels()
149 {
150   vector<ChannelMapping> map;
151   fill_mapping(map, 0, "Combined", "RGB");
152   return map;
153 }
154 
155 /* Renderlayer Handling */
156 
detect_denoising_channels()157 bool DenoiseImageLayer::detect_denoising_channels()
158 {
159   /* Map device input to image channels. */
160   input_to_image_channel.clear();
161   input_to_image_channel.resize(INPUT_NUM_CHANNELS, -1);
162 
163   foreach (const ChannelMapping &mapping, input_channels()) {
164     vector<string>::iterator i = find(channels.begin(), channels.end(), mapping.name);
165     if (i == channels.end()) {
166       return false;
167     }
168 
169     size_t input_channel = mapping.channel;
170     size_t layer_channel = i - channels.begin();
171     input_to_image_channel[input_channel] = layer_to_image_channel[layer_channel];
172   }
173 
174   /* Map device output to image channels. */
175   output_to_image_channel.clear();
176   output_to_image_channel.resize(OUTPUT_NUM_CHANNELS, -1);
177 
178   foreach (const ChannelMapping &mapping, output_channels()) {
179     vector<string>::iterator i = find(channels.begin(), channels.end(), mapping.name);
180     if (i == channels.end()) {
181       return false;
182     }
183 
184     size_t output_channel = mapping.channel;
185     size_t layer_channel = i - channels.begin();
186     output_to_image_channel[output_channel] = layer_to_image_channel[layer_channel];
187   }
188 
189   /* Check that all buffer channels are correctly set. */
190   for (int i = 0; i < INPUT_NUM_CHANNELS; i++) {
191     assert(input_to_image_channel[i] >= 0);
192   }
193   for (int i = 0; i < OUTPUT_NUM_CHANNELS; i++) {
194     assert(output_to_image_channel[i] >= 0);
195   }
196 
197   return true;
198 }
199 
match_channels(int neighbor,const std::vector<string> & channelnames,const std::vector<string> & neighbor_channelnames)200 bool DenoiseImageLayer::match_channels(int neighbor,
201                                        const std::vector<string> &channelnames,
202                                        const std::vector<string> &neighbor_channelnames)
203 {
204   neighbor_input_to_image_channel.resize(neighbor + 1);
205   vector<int> &mapping = neighbor_input_to_image_channel[neighbor];
206 
207   assert(mapping.size() == 0);
208   mapping.resize(input_to_image_channel.size(), -1);
209 
210   for (int i = 0; i < input_to_image_channel.size(); i++) {
211     const string &channel = channelnames[input_to_image_channel[i]];
212     std::vector<string>::const_iterator frame_channel = find(
213         neighbor_channelnames.begin(), neighbor_channelnames.end(), channel);
214 
215     if (frame_channel == neighbor_channelnames.end()) {
216       return false;
217     }
218 
219     mapping[i] = frame_channel - neighbor_channelnames.begin();
220   }
221 
222   return true;
223 }
224 
225 /* Denoise Task */
226 
DenoiseTask(Device * device,Denoiser * denoiser,int frame,const vector<int> & neighbor_frames)227 DenoiseTask::DenoiseTask(Device *device,
228                          Denoiser *denoiser,
229                          int frame,
230                          const vector<int> &neighbor_frames)
231     : denoiser(denoiser),
232       device(device),
233       frame(frame),
234       neighbor_frames(neighbor_frames),
235       current_layer(0),
236       input_pixels(device, "filter input buffer", MEM_READ_ONLY),
237       num_tiles(0)
238 {
239   image.samples = denoiser->samples_override;
240 }
241 
~DenoiseTask()242 DenoiseTask::~DenoiseTask()
243 {
244   free();
245 }
246 
247 /* Device callbacks */
248 
acquire_tile(Device * device,Device * tile_device,RenderTile & tile)249 bool DenoiseTask::acquire_tile(Device *device, Device *tile_device, RenderTile &tile)
250 {
251   thread_scoped_lock tile_lock(tiles_mutex);
252 
253   if (tiles.empty()) {
254     return false;
255   }
256 
257   tile = tiles.front();
258   tiles.pop_front();
259 
260   device->map_tile(tile_device, tile);
261 
262   print_progress(num_tiles - tiles.size(), num_tiles, frame, denoiser->num_frames);
263 
264   return true;
265 }
266 
267 /* Mapping tiles is required for regular rendering since each tile has its separate memory
268  * which may be allocated on a different device.
269  * For standalone denoising, there is a single memory that is present on all devices, so the only
270  * thing that needs to be done here is to specify the surrounding tile geometry.
271  *
272  * However, since there is only one large memory, the denoised result has to be written to
273  * a different buffer to avoid having to copy an entire horizontal slice of the image. */
map_neighboring_tiles(RenderTileNeighbors & neighbors,Device * tile_device)274 void DenoiseTask::map_neighboring_tiles(RenderTileNeighbors &neighbors, Device *tile_device)
275 {
276   RenderTile &center_tile = neighbors.tiles[RenderTileNeighbors::CENTER];
277   RenderTile &target_tile = neighbors.target;
278 
279   /* Fill tile information. */
280   for (int i = 0; i < RenderTileNeighbors::SIZE; i++) {
281     if (i == RenderTileNeighbors::CENTER) {
282       continue;
283     }
284 
285     RenderTile &tile = neighbors.tiles[i];
286     int dx = (i % 3) - 1;
287     int dy = (i / 3) - 1;
288     tile.x = clamp(center_tile.x + dx * denoiser->tile_size.x, 0, image.width);
289     tile.w = clamp(center_tile.x + (dx + 1) * denoiser->tile_size.x, 0, image.width) - tile.x;
290     tile.y = clamp(center_tile.y + dy * denoiser->tile_size.y, 0, image.height);
291     tile.h = clamp(center_tile.y + (dy + 1) * denoiser->tile_size.y, 0, image.height) - tile.y;
292 
293     tile.buffer = center_tile.buffer;
294     tile.offset = center_tile.offset;
295     tile.stride = image.width;
296   }
297 
298   /* Allocate output buffer. */
299   device_vector<float> *output_mem = new device_vector<float>(
300       tile_device, "denoising_output", MEM_READ_WRITE);
301   output_mem->alloc(OUTPUT_NUM_CHANNELS * center_tile.w * center_tile.h);
302 
303   /* Fill output buffer with noisy image, assumed by kernel_filter_finalize
304    * when skipping denoising of some pixels. */
305   float *result = output_mem->data();
306   float *in = &image.pixels[image.num_channels * (center_tile.y * image.width + center_tile.x)];
307 
308   const DenoiseImageLayer &layer = image.layers[current_layer];
309   const int *input_to_image_channel = layer.input_to_image_channel.data();
310 
311   for (int y = 0; y < center_tile.h; y++) {
312     for (int x = 0; x < center_tile.w; x++, result += OUTPUT_NUM_CHANNELS) {
313       for (int i = 0; i < OUTPUT_NUM_CHANNELS; i++) {
314         result[i] = in[image.num_channels * x + input_to_image_channel[INPUT_NOISY_IMAGE + i]];
315       }
316     }
317     in += image.num_channels * image.width;
318   }
319 
320   output_mem->copy_to_device();
321 
322   /* Fill output tile info. */
323   target_tile = center_tile;
324   target_tile.buffer = output_mem->device_pointer;
325   target_tile.stride = target_tile.w;
326   target_tile.offset -= target_tile.x + target_tile.y * target_tile.stride;
327 
328   thread_scoped_lock output_lock(output_mutex);
329   assert(output_pixels.count(center_tile.tile_index) == 0);
330   output_pixels[target_tile.tile_index] = output_mem;
331 }
332 
unmap_neighboring_tiles(RenderTileNeighbors & neighbors)333 void DenoiseTask::unmap_neighboring_tiles(RenderTileNeighbors &neighbors)
334 {
335   RenderTile &center_tile = neighbors.tiles[RenderTileNeighbors::CENTER];
336   RenderTile &target_tile = neighbors.target;
337 
338   thread_scoped_lock output_lock(output_mutex);
339   assert(output_pixels.count(center_tile.tile_index) == 1);
340   device_vector<float> *output_mem = output_pixels[target_tile.tile_index];
341   output_pixels.erase(center_tile.tile_index);
342   output_lock.unlock();
343 
344   /* Copy denoised pixels from device. */
345   output_mem->copy_from_device(0, OUTPUT_NUM_CHANNELS * target_tile.w, target_tile.h);
346 
347   float *result = output_mem->data();
348   float *out = &image.pixels[image.num_channels * (target_tile.y * image.width + target_tile.x)];
349 
350   const DenoiseImageLayer &layer = image.layers[current_layer];
351   const int *output_to_image_channel = layer.output_to_image_channel.data();
352 
353   for (int y = 0; y < target_tile.h; y++) {
354     for (int x = 0; x < target_tile.w; x++, result += OUTPUT_NUM_CHANNELS) {
355       for (int i = 0; i < OUTPUT_NUM_CHANNELS; i++) {
356         out[image.num_channels * x + output_to_image_channel[i]] = result[i];
357       }
358     }
359     out += image.num_channels * image.width;
360   }
361 
362   /* Free device buffer. */
363   output_mem->free();
364   delete output_mem;
365 }
366 
release_tile()367 void DenoiseTask::release_tile()
368 {
369 }
370 
get_cancel()371 bool DenoiseTask::get_cancel()
372 {
373   return false;
374 }
375 
create_task(DeviceTask & task)376 void DenoiseTask::create_task(DeviceTask &task)
377 {
378   /* Callback functions. */
379   task.acquire_tile = function_bind(&DenoiseTask::acquire_tile, this, device, _1, _2);
380   task.map_neighbor_tiles = function_bind(&DenoiseTask::map_neighboring_tiles, this, _1, _2);
381   task.unmap_neighbor_tiles = function_bind(&DenoiseTask::unmap_neighboring_tiles, this, _1);
382   task.release_tile = function_bind(&DenoiseTask::release_tile, this);
383   task.get_cancel = function_bind(&DenoiseTask::get_cancel, this);
384 
385   /* Denoising parameters. */
386   task.denoising = denoiser->params;
387   task.denoising.type = DENOISER_NLM;
388   task.denoising.use = true;
389   task.denoising.store_passes = false;
390   task.denoising_from_render = false;
391 
392   task.denoising_frames.resize(neighbor_frames.size());
393   for (int i = 0; i < neighbor_frames.size(); i++) {
394     task.denoising_frames[i] = neighbor_frames[i] - frame;
395   }
396 
397   /* Buffer parameters. */
398   task.pass_stride = INPUT_NUM_CHANNELS;
399   task.target_pass_stride = OUTPUT_NUM_CHANNELS;
400   task.pass_denoising_data = 0;
401   task.pass_denoising_clean = -1;
402   task.frame_stride = image.width * image.height * INPUT_NUM_CHANNELS;
403 
404   /* Create tiles. */
405   thread_scoped_lock tile_lock(tiles_mutex);
406   thread_scoped_lock output_lock(output_mutex);
407 
408   tiles.clear();
409   assert(output_pixels.empty());
410   output_pixels.clear();
411 
412   int tiles_x = divide_up(image.width, denoiser->tile_size.x);
413   int tiles_y = divide_up(image.height, denoiser->tile_size.y);
414 
415   for (int ty = 0; ty < tiles_y; ty++) {
416     for (int tx = 0; tx < tiles_x; tx++) {
417       RenderTile tile;
418       tile.x = tx * denoiser->tile_size.x;
419       tile.y = ty * denoiser->tile_size.y;
420       tile.w = min(image.width - tile.x, denoiser->tile_size.x);
421       tile.h = min(image.height - tile.y, denoiser->tile_size.y);
422       tile.start_sample = 0;
423       tile.num_samples = image.layers[current_layer].samples;
424       tile.sample = 0;
425       tile.offset = 0;
426       tile.stride = image.width;
427       tile.tile_index = ty * tiles_x + tx;
428       tile.task = RenderTile::DENOISE;
429       tile.buffers = NULL;
430       tile.buffer = input_pixels.device_pointer;
431       tiles.push_back(tile);
432     }
433   }
434 
435   num_tiles = tiles.size();
436 }
437 
438 /* Denoiser Operations */
439 
load_input_pixels(int layer)440 bool DenoiseTask::load_input_pixels(int layer)
441 {
442   int w = image.width;
443   int h = image.height;
444   int num_pixels = image.width * image.height;
445   int frame_stride = num_pixels * INPUT_NUM_CHANNELS;
446 
447   /* Load center image */
448   DenoiseImageLayer &image_layer = image.layers[layer];
449 
450   float *buffer_data = input_pixels.data();
451   image.read_pixels(image_layer, buffer_data);
452   buffer_data += frame_stride;
453 
454   /* Load neighbor images */
455   for (int i = 0; i < image.in_neighbors.size(); i++) {
456     if (!image.read_neighbor_pixels(i, image_layer, buffer_data)) {
457       error = "Failed to read neighbor frame pixels";
458       return false;
459     }
460     buffer_data += frame_stride;
461   }
462 
463   /* Preprocess */
464   buffer_data = input_pixels.data();
465   for (int neighbor = 0; neighbor < image.in_neighbors.size() + 1; neighbor++) {
466     /* Clamp */
467     if (denoiser->params.clamp_input) {
468       for (int i = 0; i < num_pixels * INPUT_NUM_CHANNELS; i++) {
469         buffer_data[i] = clamp(buffer_data[i], -1e8f, 1e8f);
470       }
471     }
472 
473     /* Box blur */
474     int r = 5 * denoiser->params.radius;
475     float *data = buffer_data + 14;
476     array<float> temp(num_pixels);
477 
478     for (int y = 0; y < h; y++) {
479       for (int x = 0; x < w; x++) {
480         int n = 0;
481         float sum = 0.0f;
482         for (int dx = max(x - r, 0); dx < min(x + r + 1, w); dx++, n++) {
483           sum += data[INPUT_NUM_CHANNELS * (y * w + dx)];
484         }
485         temp[y * w + x] = sum / n;
486       }
487     }
488 
489     for (int y = 0; y < h; y++) {
490       for (int x = 0; x < w; x++) {
491         int n = 0;
492         float sum = 0.0f;
493 
494         for (int dy = max(y - r, 0); dy < min(y + r + 1, h); dy++, n++) {
495           sum += temp[dy * w + x];
496         }
497 
498         data[INPUT_NUM_CHANNELS * (y * w + x)] = sum / n;
499       }
500     }
501 
502     /* Highlight compression */
503     data = buffer_data + 8;
504     for (int y = 0; y < h; y++) {
505       for (int x = 0; x < w; x++) {
506         int idx = INPUT_NUM_CHANNELS * (y * w + x);
507         float3 color = make_float3(data[idx], data[idx + 1], data[idx + 2]);
508         color = color_highlight_compress(color, NULL);
509         data[idx] = color.x;
510         data[idx + 1] = color.y;
511         data[idx + 2] = color.z;
512       }
513     }
514 
515     buffer_data += frame_stride;
516   }
517 
518   /* Copy to device */
519   input_pixels.copy_to_device();
520 
521   return true;
522 }
523 
524 /* Task stages */
525 
load()526 bool DenoiseTask::load()
527 {
528   string center_filepath = denoiser->input[frame];
529   if (!image.load(center_filepath, error)) {
530     return false;
531   }
532 
533   if (!image.load_neighbors(denoiser->input, neighbor_frames, error)) {
534     return false;
535   }
536 
537   if (image.layers.empty()) {
538     error = "No image layers found to denoise in " + center_filepath;
539     return false;
540   }
541 
542   /* Allocate device buffer. */
543   int num_frames = image.in_neighbors.size() + 1;
544   input_pixels.alloc(image.width * INPUT_NUM_CHANNELS, image.height * num_frames);
545   input_pixels.zero_to_device();
546 
547   /* Read pixels for first layer. */
548   current_layer = 0;
549   if (!load_input_pixels(current_layer)) {
550     return false;
551   }
552 
553   return true;
554 }
555 
exec()556 bool DenoiseTask::exec()
557 {
558   for (current_layer = 0; current_layer < image.layers.size(); current_layer++) {
559     /* Read pixels for secondary layers, first was already loaded. */
560     if (current_layer > 0) {
561       if (!load_input_pixels(current_layer)) {
562         return false;
563       }
564     }
565 
566     /* Run task on device. */
567     DeviceTask task(DeviceTask::RENDER);
568     create_task(task);
569     device->task_add(task);
570     device->task_wait();
571 
572     printf("\n");
573   }
574 
575   return true;
576 }
577 
save()578 bool DenoiseTask::save()
579 {
580   bool ok = image.save_output(denoiser->output[frame], error);
581   free();
582   return ok;
583 }
584 
free()585 void DenoiseTask::free()
586 {
587   image.free();
588   input_pixels.free();
589   assert(output_pixels.empty());
590 }
591 
592 /* Denoise Image Storage */
593 
DenoiseImage()594 DenoiseImage::DenoiseImage()
595 {
596   width = 0;
597   height = 0;
598   num_channels = 0;
599   samples = 0;
600 }
601 
~DenoiseImage()602 DenoiseImage::~DenoiseImage()
603 {
604   free();
605 }
606 
close_input()607 void DenoiseImage::close_input()
608 {
609   in_neighbors.clear();
610 }
611 
free()612 void DenoiseImage::free()
613 {
614   close_input();
615   pixels.clear();
616 }
617 
parse_channels(const ImageSpec & in_spec,string & error)618 bool DenoiseImage::parse_channels(const ImageSpec &in_spec, string &error)
619 {
620   const std::vector<string> &channels = in_spec.channelnames;
621   const ParamValue *multiview = in_spec.find_attribute("multiView");
622   const bool multiview_channels = (multiview && multiview->type().basetype == TypeDesc::STRING &&
623                                    multiview->type().arraylen >= 2);
624 
625   layers.clear();
626 
627   /* Loop over all the channels in the file, parse their name and sort them
628    * by RenderLayer.
629    * Channels that can't be parsed are directly passed through to the output. */
630   map<string, DenoiseImageLayer> file_layers;
631   for (int i = 0; i < channels.size(); i++) {
632     string layer, pass, channel;
633     if (parse_channel_name(channels[i], layer, pass, channel, multiview_channels)) {
634       file_layers[layer].channels.push_back(pass + "." + channel);
635       file_layers[layer].layer_to_image_channel.push_back(i);
636     }
637   }
638 
639   /* Loop over all detected RenderLayers, check whether they contain a full set of input channels.
640    * Any channels that won't be processed internally are also passed through. */
641   for (map<string, DenoiseImageLayer>::iterator i = file_layers.begin(); i != file_layers.end();
642        ++i) {
643     const string &name = i->first;
644     DenoiseImageLayer &layer = i->second;
645 
646     /* Check for full pass set. */
647     if (!layer.detect_denoising_channels()) {
648       continue;
649     }
650 
651     layer.name = name;
652     layer.samples = samples;
653 
654     /* If the sample value isn't set yet, check if there is a layer-specific one in the input file.
655      */
656     if (layer.samples < 1) {
657       string sample_string = in_spec.get_string_attribute("cycles." + name + ".samples", "");
658       if (sample_string != "") {
659         if (!sscanf(sample_string.c_str(), "%d", &layer.samples)) {
660           error = "Failed to parse samples metadata: " + sample_string;
661           return false;
662         }
663       }
664     }
665 
666     if (layer.samples < 1) {
667       error = string_printf(
668           "No sample number specified in the file for layer %s or on the command line",
669           name.c_str());
670       return false;
671     }
672 
673     layers.push_back(layer);
674   }
675 
676   return true;
677 }
678 
read_pixels(const DenoiseImageLayer & layer,float * input_pixels)679 void DenoiseImage::read_pixels(const DenoiseImageLayer &layer, float *input_pixels)
680 {
681   /* Pixels from center file have already been loaded into pixels.
682    * We copy a subset into the device input buffer with channels reshuffled. */
683   const int *input_to_image_channel = layer.input_to_image_channel.data();
684 
685   for (int i = 0; i < width * height; i++) {
686     for (int j = 0; j < INPUT_NUM_CHANNELS; j++) {
687       int image_channel = input_to_image_channel[j];
688       input_pixels[i * INPUT_NUM_CHANNELS + j] =
689           pixels[((size_t)i) * num_channels + image_channel];
690     }
691   }
692 }
693 
read_neighbor_pixels(int neighbor,const DenoiseImageLayer & layer,float * input_pixels)694 bool DenoiseImage::read_neighbor_pixels(int neighbor,
695                                         const DenoiseImageLayer &layer,
696                                         float *input_pixels)
697 {
698   /* Load pixels from neighboring frames, and copy them into device buffer
699    * with channels reshuffled. */
700   size_t num_pixels = (size_t)width * (size_t)height;
701   array<float> neighbor_pixels(num_pixels * num_channels);
702   if (!in_neighbors[neighbor]->read_image(TypeDesc::FLOAT, neighbor_pixels.data())) {
703     return false;
704   }
705 
706   const int *input_to_image_channel = layer.neighbor_input_to_image_channel[neighbor].data();
707 
708   for (int i = 0; i < width * height; i++) {
709     for (int j = 0; j < INPUT_NUM_CHANNELS; j++) {
710       int image_channel = input_to_image_channel[j];
711       input_pixels[i * INPUT_NUM_CHANNELS + j] =
712           neighbor_pixels[((size_t)i) * num_channels + image_channel];
713     }
714   }
715 
716   return true;
717 }
718 
load(const string & in_filepath,string & error)719 bool DenoiseImage::load(const string &in_filepath, string &error)
720 {
721   if (!Filesystem::is_regular(in_filepath)) {
722     error = "Couldn't find file: " + in_filepath;
723     return false;
724   }
725 
726   unique_ptr<ImageInput> in(ImageInput::open(in_filepath));
727   if (!in) {
728     error = "Couldn't open file: " + in_filepath;
729     return false;
730   }
731 
732   in_spec = in->spec();
733   width = in_spec.width;
734   height = in_spec.height;
735   num_channels = in_spec.nchannels;
736 
737   if (!parse_channels(in_spec, error)) {
738     return false;
739   }
740 
741   if (layers.size() == 0) {
742     error = "Could not find a render layer containing denoising info";
743     return false;
744   }
745 
746   size_t num_pixels = (size_t)width * (size_t)height;
747   pixels.resize(num_pixels * num_channels);
748 
749   /* Read all channels into buffer. Reading all channels at once is faster
750    * than individually due to interleaved EXR channel storage. */
751   if (!in->read_image(TypeDesc::FLOAT, pixels.data())) {
752     error = "Failed to read image: " + in_filepath;
753     return false;
754   }
755 
756   return true;
757 }
758 
load_neighbors(const vector<string> & filepaths,const vector<int> & frames,string & error)759 bool DenoiseImage::load_neighbors(const vector<string> &filepaths,
760                                   const vector<int> &frames,
761                                   string &error)
762 {
763   if (frames.size() > DENOISE_MAX_FRAMES - 1) {
764     error = string_printf("Maximum number of neighbors (%d) exceeded\n", DENOISE_MAX_FRAMES - 1);
765     return false;
766   }
767 
768   for (int neighbor = 0; neighbor < frames.size(); neighbor++) {
769     int frame = frames[neighbor];
770     const string &filepath = filepaths[frame];
771 
772     if (!Filesystem::is_regular(filepath)) {
773       error = "Couldn't find neighbor frame: " + filepath;
774       return false;
775     }
776 
777     unique_ptr<ImageInput> in_neighbor(ImageInput::open(filepath));
778     if (!in_neighbor) {
779       error = "Couldn't open neighbor frame: " + filepath;
780       return false;
781     }
782 
783     const ImageSpec &neighbor_spec = in_neighbor->spec();
784     if (neighbor_spec.width != width || neighbor_spec.height != height) {
785       error = "Neighbor frame has different dimensions: " + filepath;
786       return false;
787     }
788 
789     foreach (DenoiseImageLayer &layer, layers) {
790       if (!layer.match_channels(neighbor, in_spec.channelnames, neighbor_spec.channelnames)) {
791         error = "Neighbor frame misses denoising data passes: " + filepath;
792         return false;
793       }
794     }
795 
796     in_neighbors.push_back(std::move(in_neighbor));
797   }
798 
799   return true;
800 }
801 
save_output(const string & out_filepath,string & error)802 bool DenoiseImage::save_output(const string &out_filepath, string &error)
803 {
804   /* Save image with identical dimensions, channels and metadata. */
805   ImageSpec out_spec = in_spec;
806 
807   /* Ensure that the output frame contains sample information even if the input didn't. */
808   for (int i = 0; i < layers.size(); i++) {
809     string name = "cycles." + layers[i].name + ".samples";
810     if (!out_spec.find_attribute(name, TypeDesc::STRING)) {
811       out_spec.attribute(name, TypeDesc::STRING, string_printf("%d", layers[i].samples));
812     }
813   }
814 
815   /* We don't need input anymore at this point, and will possibly
816    * overwrite the same file. */
817   close_input();
818 
819   /* Write to temporary file path, so we denoise images in place and don't
820    * risk destroying files when something goes wrong in file saving. */
821   string extension = OIIO::Filesystem::extension(out_filepath);
822   string unique_name = ".denoise-tmp-" + OIIO::Filesystem::unique_path();
823   string tmp_filepath = out_filepath + unique_name + extension;
824   unique_ptr<ImageOutput> out(ImageOutput::create(tmp_filepath));
825 
826   if (!out) {
827     error = "Failed to open temporary file " + tmp_filepath + " for writing";
828     return false;
829   }
830 
831   /* Open temporary file and write image buffers. */
832   if (!out->open(tmp_filepath, out_spec)) {
833     error = "Failed to open file " + tmp_filepath + " for writing: " + out->geterror();
834     return false;
835   }
836 
837   bool ok = true;
838   if (!out->write_image(TypeDesc::FLOAT, pixels.data())) {
839     error = "Failed to write to file " + tmp_filepath + ": " + out->geterror();
840     ok = false;
841   }
842 
843   if (!out->close()) {
844     error = "Failed to save to file " + tmp_filepath + ": " + out->geterror();
845     ok = false;
846   }
847 
848   out.reset();
849 
850   /* Copy temporary file to outputput filepath. */
851   string rename_error;
852   if (ok && !OIIO::Filesystem::rename(tmp_filepath, out_filepath, rename_error)) {
853     error = "Failed to move denoised image to " + out_filepath + ": " + rename_error;
854     ok = false;
855   }
856 
857   if (!ok) {
858     OIIO::Filesystem::remove(tmp_filepath);
859   }
860 
861   return ok;
862 }
863 
864 /* File pattern handling and outer loop over frames */
865 
Denoiser(DeviceInfo & device_info)866 Denoiser::Denoiser(DeviceInfo &device_info)
867 {
868   samples_override = 0;
869   tile_size = make_int2(64, 64);
870 
871   num_frames = 0;
872 
873   /* Initialize task scheduler. */
874   TaskScheduler::init();
875 
876   /* Initialize device. */
877   device = Device::create(device_info, stats, profiler, true);
878 
879   DeviceRequestedFeatures req;
880   req.use_denoising = true;
881   device->load_kernels(req);
882 }
883 
~Denoiser()884 Denoiser::~Denoiser()
885 {
886   delete device;
887   TaskScheduler::exit();
888 }
889 
run()890 bool Denoiser::run()
891 {
892   assert(input.size() == output.size());
893 
894   num_frames = output.size();
895 
896   for (int frame = 0; frame < num_frames; frame++) {
897     /* Skip empty output paths. */
898     if (output[frame].empty()) {
899       continue;
900     }
901 
902     /* Determine neighbor frame numbers that should be used for filtering. */
903     vector<int> neighbor_frames;
904     for (int f = frame - params.neighbor_frames; f <= frame + params.neighbor_frames; f++) {
905       if (f >= 0 && f < num_frames && f != frame) {
906         neighbor_frames.push_back(f);
907       }
908     }
909 
910     /* Execute task. */
911     DenoiseTask task(device, this, frame, neighbor_frames);
912     if (!task.load()) {
913       error = task.error;
914       return false;
915     }
916 
917     if (!task.exec()) {
918       error = task.error;
919       return false;
920     }
921 
922     if (!task.save()) {
923       error = task.error;
924       return false;
925     }
926 
927     task.free();
928   }
929 
930   return true;
931 }
932 
933 CCL_NAMESPACE_END
934