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 #ifndef __DENOISING_H__
18 #define __DENOISING_H__
19 
20 #include "device/device.h"
21 #include "device/device_denoising.h"
22 
23 #include "render/buffers.h"
24 
25 #include "util/util_string.h"
26 #include "util/util_unique_ptr.h"
27 #include "util/util_vector.h"
28 
29 #include <OpenImageIO/imageio.h>
30 
31 OIIO_NAMESPACE_USING
32 
33 CCL_NAMESPACE_BEGIN
34 
35 /* Denoiser */
36 
37 class Denoiser {
38  public:
39   Denoiser(DeviceInfo &device_info);
40   ~Denoiser();
41 
42   bool run();
43 
44   /* Error message after running, in case of failure. */
45   string error;
46 
47   /* Sequential list of frame filepaths to denoise. */
48   vector<string> input;
49   /* Sequential list of frame filepaths to write result to. Empty entries
50    * are skipped, so only a subset of the sequence can be denoised while
51    * taking into account all input frames. */
52   vector<string> output;
53 
54   /* Sample number override, takes precedence over values from input frames. */
55   int samples_override;
56   /* Tile size for processing on device. */
57   int2 tile_size;
58 
59   /* Equivalent to the settings in the regular denoiser. */
60   DenoiseParams params;
61 
62  protected:
63   friend class DenoiseTask;
64 
65   Stats stats;
66   Profiler profiler;
67   Device *device;
68 
69   int num_frames;
70 };
71 
72 /* Denoise Image Layer */
73 
74 struct DenoiseImageLayer {
75   string name;
76   /* All channels belonging to this DenoiseImageLayer. */
77   vector<string> channels;
78   /* Layer to image channel mapping. */
79   vector<int> layer_to_image_channel;
80 
81   /* Sample amount that was used for rendering this layer. */
82   int samples;
83 
84   /* Device input channel will be copied from image channel input_to_image_channel[i]. */
85   vector<int> input_to_image_channel;
86 
87   /* input_to_image_channel of the secondary frames, if any are used. */
88   vector<vector<int>> neighbor_input_to_image_channel;
89 
90   /* Write i-th channel of the processing output to output_to_image_channel[i]-th channel of the
91    * file. */
92   vector<int> output_to_image_channel;
93 
94   /* Detect whether this layer contains a full set of channels and set up the offsets accordingly.
95    */
96   bool detect_denoising_channels();
97 
98   /* Map the channels of a secondary frame to the channels that are required for processing,
99    * fill neighbor_input_to_image_channel if all are present or return false if a channel are
100    * missing. */
101   bool match_channels(int neighbor,
102                       const std::vector<string> &channelnames,
103                       const std::vector<string> &neighbor_channelnames);
104 };
105 
106 /* Denoise Image Data */
107 
108 class DenoiseImage {
109  public:
110   DenoiseImage();
111   ~DenoiseImage();
112 
113   /* Dimensions */
114   int width, height, num_channels;
115 
116   /* Samples */
117   int samples;
118 
119   /* Pixel buffer with interleaved channels. */
120   array<float> pixels;
121 
122   /* Image file handles */
123   ImageSpec in_spec;
124   vector<unique_ptr<ImageInput>> in_neighbors;
125 
126   /* Render layers */
127   vector<DenoiseImageLayer> layers;
128 
129   void free();
130 
131   /* Open the input image, parse its channels, open the output image and allocate the output
132    * buffer. */
133   bool load(const string &in_filepath, string &error);
134 
135   /* Load neighboring frames. */
136   bool load_neighbors(const vector<string> &filepaths, const vector<int> &frames, string &error);
137 
138   /* Load subset of pixels from file buffer into input buffer, as needed for denoising
139    * on the device. Channels are reshuffled following the provided mapping. */
140   void read_pixels(const DenoiseImageLayer &layer, float *input_pixels);
141   bool read_neighbor_pixels(int neighbor, const DenoiseImageLayer &layer, float *input_pixels);
142 
143   bool save_output(const string &out_filepath, string &error);
144 
145  protected:
146   /* Parse input file channels, separate them into DenoiseImageLayers,
147    * detect DenoiseImageLayers with full channel sets,
148    * fill layers and set up the output channels and passthrough map. */
149   bool parse_channels(const ImageSpec &in_spec, string &error);
150 
151   void close_input();
152 };
153 
154 /* Denoise Task */
155 
156 class DenoiseTask {
157  public:
158   DenoiseTask(Device *device, Denoiser *denoiser, int frame, const vector<int> &neighbor_frames);
159   ~DenoiseTask();
160 
161   /* Task stages */
162   bool load();
163   bool exec();
164   bool save();
165   void free();
166 
167   string error;
168 
169  protected:
170   /* Denoiser parameters and device */
171   Denoiser *denoiser;
172   Device *device;
173 
174   /* Frame number to be denoised */
175   int frame;
176   vector<int> neighbor_frames;
177 
178   /* Image file data */
179   DenoiseImage image;
180   int current_layer;
181 
182   /* Device input buffer */
183   device_vector<float> input_pixels;
184 
185   /* Tiles */
186   thread_mutex tiles_mutex;
187   list<RenderTile> tiles;
188   int num_tiles;
189 
190   thread_mutex output_mutex;
191   map<int, device_vector<float> *> output_pixels;
192 
193   /* Task handling */
194   bool load_input_pixels(int layer);
195   void create_task(DeviceTask &task);
196 
197   /* Device task callbacks */
198   bool acquire_tile(Device *device, Device *tile_device, RenderTile &tile);
199   void map_neighboring_tiles(RenderTileNeighbors &neighbors, Device *tile_device);
200   void unmap_neighboring_tiles(RenderTileNeighbors &neighbors);
201   void release_tile();
202   bool get_cancel();
203 };
204 
205 CCL_NAMESPACE_END
206 
207 #endif /* __DENOISING_H__ */
208