5#if defined(WITH_OPENIMAGEDENOISE)
18# if OIDN_VERSION_MAJOR < 2
19# define oidnSetFilterBool oidnSetFilter1b
20# define oidnSetFilterInt oidnSetFilter1i
21# define oidnExecuteFilterAsync oidnExecuteFilter
26# if OIDN_VERSION < 20300
27static const char *oidn_device_type_to_string(
const OIDNDeviceType type)
30 case OIDN_DEVICE_TYPE_DEFAULT:
32 case OIDN_DEVICE_TYPE_CPU:
36# if OIDN_VERSION_MAJOR >= 2
37 case OIDN_DEVICE_TYPE_SYCL:
39 case OIDN_DEVICE_TYPE_CUDA:
41 case OIDN_DEVICE_TYPE_HIP:
46# if (OIDN_VERSION_MAJOR > 2) || ((OIDN_VERSION_MAJOR == 2) && (OIDN_VERSION_MINOR >= 2))
47 case OIDN_DEVICE_TYPE_METAL:
55bool OIDNDenoiserGPU::is_device_supported(
const DeviceInfo &device)
57# if OIDN_VERSION >= 20300
72 if (multi_device.
type !=
DEVICE_CPU && is_device_supported(multi_device)) {
81 <<
") for OIDN GPU support";
83 int device_type = OIDN_DEVICE_TYPE_DEFAULT;
84 switch (device.
type) {
85# ifdef OIDN_DEVICE_SYCL
87 device_type = OIDN_DEVICE_TYPE_SYCL;
90# ifdef OIDN_DEVICE_HIP
92 device_type = OIDN_DEVICE_TYPE_HIP;
95# ifdef OIDN_DEVICE_CUDA
98 device_type = OIDN_DEVICE_TYPE_CUDA;
101# ifdef OIDN_DEVICE_METAL
103 const int num_devices = oidnGetNumPhysicalDevices();
104 LOG_TRACE <<
"Found " << num_devices <<
" OIDN device(s)";
105 for (
int i = 0;
i < num_devices;
i++) {
106 const int type = oidnGetPhysicalDeviceInt(
i,
"type");
107 const char *
name = oidnGetPhysicalDeviceString(
i,
"name");
109 <<
"\", type=" << oidn_device_type_to_string(OIDNDeviceType(type));
110 if (type == OIDN_DEVICE_TYPE_METAL) {
111 if (device.
id.find(
name) != std::string::npos) {
112 LOG_TRACE <<
"OIDN device name matches the Cycles device name";
117 LOG_TRACE <<
"No matched OIDN device found";
129 const int num_devices = oidnGetNumPhysicalDevices();
130 LOG_TRACE <<
"Found " << num_devices <<
" OIDN device(s)";
131 for (
int i = 0;
i < num_devices;
i++) {
132 const int type = oidnGetPhysicalDeviceInt(
i,
"type");
133 const char *
name = oidnGetPhysicalDeviceString(
i,
"name");
135 <<
"\" type=" << oidn_device_type_to_string(OIDNDeviceType(type));
136 if (type == device_type) {
137 if (oidnGetPhysicalDeviceBool(
i,
"pciAddressSupported")) {
138 unsigned int pci_domain = oidnGetPhysicalDeviceInt(
i,
"pciDomain");
139 unsigned int pci_bus = oidnGetPhysicalDeviceInt(
i,
"pciBus");
140 unsigned int pci_device = oidnGetPhysicalDeviceInt(
i,
"pciDevice");
141 string pci_id =
string_printf(
"%04x:%02x:%02x", pci_domain, pci_bus, pci_device);
142 LOG_INFO <<
"OIDN device PCI-e identifier: " << pci_id;
143 if (device.
id.find(pci_id) != string::npos) {
144 LOG_TRACE <<
"OIDN device PCI-e identifier matches the Cycles device ID";
149 LOG_TRACE <<
"Device does not support pciAddressSupported";
153 LOG_TRACE <<
"No matched OIDN device found";
164OIDNDenoiserGPU::~OIDNDenoiserGPU()
166 release_all_resources();
169bool OIDNDenoiserGPU::denoise_buffer(
const BufferParams &buffer_params,
171 const int num_samples,
172 bool allow_inplace_modification)
175 buffer_params, render_buffers, num_samples, allow_inplace_modification);
178uint OIDNDenoiserGPU::get_device_type_mask()
const
180 uint device_mask = 0;
181# ifdef OIDN_DEVICE_SYCL
184# ifdef OIDN_DEVICE_METAL
187# ifdef OIDN_DEVICE_CUDA
191# ifdef OIDN_DEVICE_HIP
197OIDNFilter OIDNDenoiserGPU::create_filter()
199 const char *error_message =
nullptr;
200 OIDNFilter
filter = oidnNewFilter(oidn_device_,
"RT");
202 const OIDNError err = oidnGetDeviceError(oidn_device_, &error_message);
203 if (OIDN_ERROR_NONE != err) {
204 LOG_ERROR <<
"OIDN error: " << error_message;
205 set_error(error_message);
209# if OIDN_VERSION_MAJOR >= 2
212# if OIDN_VERSION >= 20300
213 oidnSetFilterInt(
filter,
"quality", OIDN_QUALITY_FAST);
217 oidnSetFilterInt(
filter,
"quality", OIDN_QUALITY_BALANCED);
221 oidnSetFilterInt(
filter,
"quality", OIDN_QUALITY_HIGH);
228bool OIDNDenoiserGPU::commit_and_execute_filter(OIDNFilter
filter, ExecMode mode)
230 const char *error_message =
nullptr;
231 OIDNError err = OIDN_ERROR_NONE;
235 if (mode == ExecMode::ASYNC) {
236 oidnExecuteFilterAsync(
filter);
239 oidnExecuteFilter(
filter);
243 err = oidnGetDeviceError(oidn_device_, &error_message);
244 if (err != OIDN_ERROR_OUT_OF_MEMORY || max_mem_ < 200) {
247 max_mem_ = max_mem_ / 2;
248 oidnSetFilterInt(
filter,
"maxMemoryMB", max_mem_);
251 if (err != OIDN_ERROR_NONE) {
252 if (error_message ==
nullptr) {
253 error_message =
"Unspecified OIDN error";
255 LOG_ERROR <<
"OIDN error: " << error_message;
256 set_error(error_message);
262bool OIDNDenoiserGPU::denoise_create_if_needed(DenoiseContext &context)
264 const bool recreate_denoiser = (oidn_device_ ==
nullptr) || (oidn_filter_ ==
nullptr) ||
265 (use_pass_albedo_ !=
context.use_pass_albedo) ||
266 (use_pass_normal_ !=
context.use_pass_normal) ||
267 (quality_ != params_.quality);
268 if (!recreate_denoiser) {
273 release_all_resources();
275 switch (denoiser_device_->info.type) {
276# if defined(OIDN_DEVICE_SYCL) && defined(WITH_ONEAPI)
278 oidn_device_ = oidnNewSYCLDevice(
279 (
const sycl::queue *)
reinterpret_cast<OneapiDevice *
>(denoiser_device_)->sycl_queue(),
283# if defined(OIDN_DEVICE_METAL) && defined(WITH_METAL)
285 denoiser_queue_->init_execution();
286 const MTLCommandQueue_id queue = (
const MTLCommandQueue_id)denoiser_queue_->native_queue();
287 oidn_device_ = oidnNewMetalDevice(&queue, 1);
290# if defined(OIDN_DEVICE_CUDA) && defined(WITH_CUDA)
294 cudaStream_t stream =
nullptr;
295 oidn_device_ = oidnNewCUDADevice(&denoiser_device_->info.num, &stream, 1);
299# if defined(OIDN_DEVICE_HIP) && defined(WITH_HIP)
301 hipStream_t stream =
nullptr;
302 oidn_device_ = oidnNewHIPDevice(&denoiser_device_->info.num, &stream, 1);
311 set_error(
"Failed to create OIDN device");
315 if (denoiser_queue_) {
316 denoiser_queue_->init_execution();
319 oidnCommitDevice(oidn_device_);
321 quality_ = params_.quality;
323 oidn_filter_ = create_filter();
324 if (oidn_filter_ ==
nullptr) {
328 oidnSetFilterBool(oidn_filter_,
"hdr",
true);
329 oidnSetFilterBool(oidn_filter_,
"srgb",
false);
331 const char *custom_weight_path = getenv(
"CYCLES_OIDN_CUSTOM_WEIGHTS");
332 if (custom_weight_path) {
334 oidnSetSharedFilterData(
335 oidn_filter_,
"weights", custom_weights.data(), custom_weights.size());
338 LOG_ERROR <<
"Failed to load custom OpenImageDenoise weights";
343 albedo_filter_ = create_filter();
344 if (albedo_filter_ ==
nullptr) {
350 normal_filter_ = create_filter();
351 if (normal_filter_ ==
nullptr) {
357 use_pass_albedo_ =
context.use_pass_albedo;
358 use_pass_normal_ =
context.use_pass_normal;
361 is_configured_ =
false;
365bool OIDNDenoiserGPU::denoise_configure_if_needed(DenoiseContext &context)
370 if (is_configured_ && (configured_size_.x ==
size.x && configured_size_.y ==
size.y)) {
374 is_configured_ =
true;
375 configured_size_ =
size;
380bool OIDNDenoiserGPU::denoise_run(
const DenoiseContext &context,
const DenoisePass &pass)
385 set_filter_pass(oidn_filter_,
387 context.render_buffers->buffer.device_pointer,
391 pass.denoised_offset *
sizeof(
float),
392 pass_stride_in_bytes,
393 pass_stride_in_bytes *
context.buffer_params.stride);
395 set_filter_pass(oidn_filter_,
397 context.render_buffers->buffer.device_pointer,
401 pass.denoised_offset *
sizeof(
float),
402 pass_stride_in_bytes,
403 pass_stride_in_bytes *
context.buffer_params.stride);
406 if (
context.num_input_passes > 1) {
409 const int64_t row_stride_in_bytes =
context.guiding_params.stride * pixel_stride_in_bytes;
412 set_filter_pass(oidn_filter_,
418 context.guiding_params.pass_albedo *
sizeof(
float),
419 pixel_stride_in_bytes,
420 row_stride_in_bytes);
423 set_filter_pass(albedo_filter_,
429 context.guiding_params.pass_albedo *
sizeof(
float),
430 pixel_stride_in_bytes,
431 row_stride_in_bytes);
433 set_filter_pass(albedo_filter_,
439 context.guiding_params.pass_albedo *
sizeof(
float),
440 pixel_stride_in_bytes,
441 row_stride_in_bytes);
443 if (!commit_and_execute_filter(albedo_filter_, ExecMode::ASYNC)) {
450 set_filter_pass(oidn_filter_,
456 context.guiding_params.pass_normal *
sizeof(
float),
457 pixel_stride_in_bytes,
458 row_stride_in_bytes);
461 set_filter_pass(normal_filter_,
467 context.guiding_params.pass_normal *
sizeof(
float),
468 pixel_stride_in_bytes,
469 row_stride_in_bytes);
471 set_filter_pass(normal_filter_,
477 context.guiding_params.pass_normal *
sizeof(
float),
478 pixel_stride_in_bytes,
479 row_stride_in_bytes);
481 if (!commit_and_execute_filter(normal_filter_, ExecMode::ASYNC)) {
489 return commit_and_execute_filter(oidn_filter_);
492void OIDNDenoiserGPU::set_filter_pass(OIDNFilter
filter,
498 const size_t offset_in_bytes,
499 const size_t pixel_stride_in_bytes,
500 const size_t row_stride_in_bytes)
502# if defined(OIDN_DEVICE_METAL) && defined(WITH_METAL)
504 void *mtl_buffer = denoiser_device_->get_native_buffer(
ptr);
505 OIDNBuffer oidn_buffer = oidnNewSharedBufferFromMetal(oidn_device_, mtl_buffer);
507 oidnSetFilterImage(
filter,
514 pixel_stride_in_bytes,
515 row_stride_in_bytes);
517 oidnReleaseBuffer(oidn_buffer);
522 oidnSetSharedFilterImage(
filter,
529 pixel_stride_in_bytes,
530 row_stride_in_bytes);
534void OIDNDenoiserGPU::release_all_resources()
536 if (albedo_filter_) {
537 oidnReleaseFilter(albedo_filter_);
538 albedo_filter_ =
nullptr;
540 if (normal_filter_) {
541 oidnReleaseFilter(normal_filter_);
542 normal_filter_ =
nullptr;
545 oidnReleaseFilter(oidn_filter_);
546 oidn_filter_ =
nullptr;
549 oidnReleaseDevice(oidn_device_);
550 oidn_device_ =
nullptr;
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
bool denoise_buffer(const BufferParams &buffer_params, RenderBuffers *render_buffers, const int num_samples, bool allow_inplace_modification) override
vector< DeviceInfo > multi_devices
DenoiserTypeMask denoisers
@ DENOISER_QUALITY_BALANCED
@ DENOISER_PREFILTER_FAST
@ DENOISER_PREFILTER_ACCURATE
@ DENOISER_OPENIMAGEDENOISE
#define CCL_NAMESPACE_END
#define assert(assertion)
int context(const bContext *C, const char *member, bContextDataResult *result)
bool path_read_binary(const string &path, vector< uint8_t > &binary)
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)