diff --git a/intern/cycles/integrator/denoiser.cpp b/intern/cycles/integrator/denoiser.cpp index 2a5f99f358b..28cdeeb630a 100644 --- a/intern/cycles/integrator/denoiser.cpp +++ b/intern/cycles/integrator/denoiser.cpp @@ -125,20 +125,41 @@ static Device *find_best_device(Device *device, DenoiserType type) return best_device; } +static DeviceInfo find_best_denoiser_device_info(const vector &device_infos, + DenoiserType denoiser_type) +{ + for (const DeviceInfo &device_info : device_infos) { + if ((device_info.denoisers & denoiser_type) == 0) { + continue; + } + + /* TODO(sergey): Use one of the already configured devices, so that OptiX denoising can happen + * on a physical CUDA device which is already used for rendering. */ + + /* TODO(sergey): Choose fastest device for denoising. */ + + return device_info; + } + + DeviceInfo none_device; + none_device.type = DEVICE_NONE; + return none_device; +} + static unique_ptr create_denoiser_device(Device *path_trace_device, - const uint device_type_mask) + const uint device_type_mask, + DenoiserType denoiser_type) { const vector device_infos = Device::available_devices(device_type_mask); if (device_infos.empty()) { return nullptr; } - /* TODO(sergey): Use one of the already configured devices, so that OptiX denoising can happen on - * a physical CUDA device which is already used for rendering. */ - - /* TODO(sergey): Choose fastest device for denoising. */ - - const DeviceInfo denoiser_device_info = device_infos.front(); + const DeviceInfo denoiser_device_info = find_best_denoiser_device_info(device_infos, + denoiser_type); + if (denoiser_device_info.type == DEVICE_NONE) { + return nullptr; + } unique_ptr denoiser_device( Device::create(denoiser_device_info, path_trace_device->stats, path_trace_device->profiler)); @@ -186,7 +207,8 @@ Device *Denoiser::ensure_denoiser_device(Progress *progress) device_creation_attempted_ = true; const uint device_type_mask = get_device_type_mask(); - local_denoiser_device_ = create_denoiser_device(path_trace_device_, device_type_mask); + local_denoiser_device_ = create_denoiser_device( + path_trace_device_, device_type_mask, params_.type); denoiser_device_ = local_denoiser_device_.get(); return denoiser_device_; diff --git a/intern/cycles/integrator/denoiser_oidn.cpp b/intern/cycles/integrator/denoiser_oidn.cpp index a08aec513fc..4676e69c4fb 100644 --- a/intern/cycles/integrator/denoiser_oidn.cpp +++ b/intern/cycles/integrator/denoiser_oidn.cpp @@ -37,8 +37,6 @@ OIDNDenoiser::OIDNDenoiser(Device *path_trace_device, const DenoiseParams ¶m : Denoiser(path_trace_device, params) { DCHECK_EQ(params.type, DENOISER_OPENIMAGEDENOISE); - - DCHECK(openimagedenoise_supported()) << "OpenImageDenoiser is not supported on this platform."; } #ifdef WITH_OPENIMAGEDENOISE @@ -585,6 +583,9 @@ bool OIDNDenoiser::denoise_buffer(const BufferParams &buffer_params, const int num_samples, bool allow_inplace_modification) { + DCHECK(openimagedenoise_supported()) + << "OpenImageDenoiser is not supported on this platform or build."; + #ifdef WITH_OPENIMAGEDENOISE thread_scoped_lock lock(mutex_); @@ -635,4 +636,20 @@ uint OIDNDenoiser::get_device_type_mask() const return DEVICE_MASK_CPU; } +Device *OIDNDenoiser::ensure_denoiser_device(Progress *progress) +{ +#ifndef WITH_OPENIMAGEDENOISE + path_trace_device_->set_error("Build without OpenImageDenoiser"); + return nullptr; +#else + if (!openimagedenoise_supported()) { + path_trace_device_->set_error( + "OpenImageDenoiser is not supported on this CPU: missing SSE 4.1 support"); + return nullptr; + } + + return Denoiser::ensure_denoiser_device(progress); +#endif +} + CCL_NAMESPACE_END diff --git a/intern/cycles/integrator/denoiser_oidn.h b/intern/cycles/integrator/denoiser_oidn.h index a0ec3e26b9c..2b815be973e 100644 --- a/intern/cycles/integrator/denoiser_oidn.h +++ b/intern/cycles/integrator/denoiser_oidn.h @@ -38,6 +38,7 @@ class OIDNDenoiser : public Denoiser { protected: virtual uint get_device_type_mask() const override; + virtual Device *ensure_denoiser_device(Progress *progress) override; /* We only perform one denoising at a time, since OpenImageDenoise itself is multithreaded. * Use this mutex whenever images are passed to the OIDN and needs to be denoised. */