Blender  V3.3
denoiser.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #include "integrator/denoiser.h"
5 
6 #include "device/device.h"
9 #include "session/buffers.h"
10 #include "util/log.h"
11 #include "util/progress.h"
12 
14 
15 unique_ptr<Denoiser> Denoiser::create(Device *path_trace_device, const DenoiseParams &params)
16 {
17  DCHECK(params.use);
18 
20  return make_unique<OptiXDenoiser>(path_trace_device, params);
21  }
22 
23  /* Always fallback to OIDN. */
24  DenoiseParams oidn_params = params;
25  oidn_params.type = DENOISER_OPENIMAGEDENOISE;
26  return make_unique<OIDNDenoiser>(path_trace_device, oidn_params);
27 }
28 
29 Denoiser::Denoiser(Device *path_trace_device, const DenoiseParams &params)
30  : path_trace_device_(path_trace_device), params_(params)
31 {
32  DCHECK(params.use);
33 }
34 
36 {
38 
39  if (params.type == params_.type) {
40  params_ = params;
41  }
42  else {
43  LOG(ERROR) << "Attempt to change denoiser type.";
44  }
45 }
46 
48 {
49  return params_;
50 }
51 
53 {
54  const Device *denoiser_device = ensure_denoiser_device(progress);
55 
56  if (!denoiser_device) {
57  path_trace_device_->set_error("No device available to denoise on");
58  return false;
59  }
60 
61  VLOG_WORK << "Will denoise on " << denoiser_device->info.description << " ("
62  << denoiser_device->info.id << ")";
63 
64  return true;
65 }
66 
68 {
69  return denoiser_device_;
70 }
71 
72 /* Check whether given device is single (not a MultiDevice) and supports requested denoiser. */
74 {
75  if (device->info.type == DEVICE_MULTI) {
76  /* Assume multi-device is never created with a single sub-device.
77  * If one requests such configuration it should be checked on the session level. */
78  return false;
79  }
80 
81  if (!device->info.multi_devices.empty()) {
82  /* Some configurations will use multi_devices, but keep the type of an individual device.
83  * This does simplify checks for homogeneous setups, but here we really need a single device.
84  */
85  return false;
86  }
87 
88  /* Check the denoiser type is supported. */
89  return (device->info.denoisers & type);
90 }
91 
92 /* Find best suitable device to perform denoiser on. Will iterate over possible sub-devices of
93  * multi-device.
94  *
95  * If there is no device available which supports given denoiser type nullptr is returned. */
97 {
98  Device *best_device = nullptr;
99 
100  device->foreach_device([&](Device *sub_device) {
101  if ((sub_device->info.denoisers & type) == 0) {
102  return;
103  }
104 
105  if (!best_device) {
106  best_device = sub_device;
107  }
108  else {
109  /* Prefer a device that can use graphics interop for faster display update. */
110  if (sub_device->should_use_graphics_interop() &&
111  !best_device->should_use_graphics_interop()) {
112  best_device = sub_device;
113  }
114 
115  /* TODO(sergey): Choose fastest device from available ones. Taking into account performance
116  * of the device and data transfer cost. */
117  }
118  });
119 
120  return best_device;
121 }
122 
124  DenoiserType denoiser_type)
125 {
126  for (const DeviceInfo &device_info : device_infos) {
127  if ((device_info.denoisers & denoiser_type) == 0) {
128  continue;
129  }
130 
131  /* TODO(sergey): Use one of the already configured devices, so that OptiX denoising can happen
132  * on a physical CUDA device which is already used for rendering. */
133 
134  /* TODO(sergey): Choose fastest device for denoising. */
135 
136  return device_info;
137  }
138 
139  DeviceInfo none_device;
140  none_device.type = DEVICE_NONE;
141  return none_device;
142 }
143 
144 static unique_ptr<Device> create_denoiser_device(Device *path_trace_device,
145  const uint device_type_mask,
146  DenoiserType denoiser_type)
147 {
148  const vector<DeviceInfo> device_infos = Device::available_devices(device_type_mask);
149  if (device_infos.empty()) {
150  return nullptr;
151  }
152 
153  const DeviceInfo denoiser_device_info = find_best_denoiser_device_info(device_infos,
154  denoiser_type);
155  if (denoiser_device_info.type == DEVICE_NONE) {
156  return nullptr;
157  }
158 
159  unique_ptr<Device> denoiser_device(
160  Device::create(denoiser_device_info, path_trace_device->stats, path_trace_device->profiler));
161 
162  if (!denoiser_device) {
163  return nullptr;
164  }
165 
166  if (denoiser_device->have_error()) {
167  return nullptr;
168  }
169 
170  /* Only need denoising feature, everything else is unused. */
171  if (!denoiser_device->load_kernels(KERNEL_FEATURE_DENOISING)) {
172  return nullptr;
173  }
174 
175  return denoiser_device;
176 }
177 
179 {
180  /* The best device has been found already, avoid sequential lookups.
181  * Additionally, avoid device re-creation if it has failed once. */
183  return denoiser_device_;
184  }
185 
186  /* Simple case: rendering happens on a single device which also supports denoiser. */
189  return denoiser_device_;
190  }
191 
192  /* Find best device from the ones which are already used for rendering. */
194  if (denoiser_device_) {
195  return denoiser_device_;
196  }
197 
198  if (progress) {
199  progress->set_status("Loading denoising kernels (may take a few minutes the first time)");
200  }
201 
203 
204  const uint device_type_mask = get_device_type_mask();
206  path_trace_device_, device_type_mask, params_.type);
208 
209  return denoiser_device_;
210 }
211 
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 GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
DenoiserType type
Definition: denoise.h:53
virtual Device * ensure_denoiser_device(Progress *progress)
Definition: denoiser.cpp:178
static unique_ptr< Denoiser > create(Device *path_trace_device, const DenoiseParams &params)
Definition: denoiser.cpp:15
bool device_creation_attempted_
Definition: denoiser.h:119
void set_params(const DenoiseParams &params)
Definition: denoiser.cpp:35
DenoiseParams params_
Definition: denoiser.h:110
unique_ptr< Device > local_denoiser_device_
Definition: denoiser.h:118
virtual bool load_kernels(Progress *progress)
Definition: denoiser.cpp:52
virtual uint get_device_type_mask() const =0
Device * get_denoiser_device() const
Definition: denoiser.cpp:67
Device * denoiser_device_
Definition: denoiser.h:114
const DenoiseParams & get_params() const
Definition: denoiser.cpp:47
Denoiser(Device *path_trace_device, const DenoiseParams &params)
Definition: denoiser.cpp:29
Device * path_trace_device_
Definition: denoiser.h:109
vector< DeviceInfo > multi_devices
Definition: device/device.h:75
DenoiserTypeMask denoisers
Definition: device/device.h:73
DeviceType type
Definition: device/device.h:62
string description
Definition: device/device.h:63
static vector< DeviceInfo > available_devices(uint device_type_mask=DEVICE_MASK_ALL)
static Device * create(const DeviceInfo &info, Stats &stats, Profiler &profiler)
Profiler & profiler
Stats & stats
virtual void foreach_device(const function< void(Device *)> &callback)
virtual void set_error(const string &error)
DeviceInfo info
virtual bool should_use_graphics_interop()
void set_status(const string &status_, const string &substatus_="")
Definition: progress.h:248
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
DenoiserType
Definition: denoise.h:12
@ DENOISER_OPTIX
Definition: denoise.h:13
@ DENOISER_OPENIMAGEDENOISE
Definition: denoise.h:14
static unique_ptr< Device > create_denoiser_device(Device *path_trace_device, const uint device_type_mask, DenoiserType denoiser_type)
Definition: denoiser.cpp:144
static DeviceInfo find_best_denoiser_device_info(const vector< DeviceInfo > &device_infos, DenoiserType denoiser_type)
Definition: denoiser.cpp:123
static bool is_single_supported_device(Device *device, DenoiserType type)
Definition: denoiser.cpp:73
static Device * find_best_device(Device *device, DenoiserType type)
Definition: denoiser.cpp:96
@ DEVICE_MASK_OPTIX
Definition: device/device.h:51
@ DEVICE_NONE
Definition: device/device.h:37
@ DEVICE_MULTI
Definition: device/device.h:40
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
@ KERNEL_FEATURE_DENOISING
#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