diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 4c80fff37d5..91738794a6c 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -144,17 +144,20 @@ def show_device_active(context): return backend_has_active_gpu(context) -def get_effective_preview_denoiser(context): +def get_effective_preview_denoiser(context, has_oidn_gpu): scene = context.scene cscene = scene.cycles if cscene.preview_denoiser != "AUTO": return cscene.preview_denoiser + if has_oidn_gpu: + return 'OPENIMAGEDENOISE' + if context.preferences.addons[__package__].preferences.get_devices_for_type('OPTIX'): return 'OPTIX' - return 'OIDN' + return 'OPENIMAGEDENOISE' def has_oidn_gpu_devices(context): @@ -234,7 +237,9 @@ class CYCLES_RENDER_PT_sampling_viewport_denoise(CyclesButtonsPanel, Panel): col.prop(cscene, "preview_denoiser", text="Denoiser") col.prop(cscene, "preview_denoising_input_passes", text="Passes") - effective_preview_denoiser = get_effective_preview_denoiser(context) + has_oidn_gpu = has_oidn_gpu_devices(context) + effective_preview_denoiser = get_effective_preview_denoiser(context, has_oidn_gpu) + print(has_oidn_gpu, effective_preview_denoiser) if effective_preview_denoiser == 'OPENIMAGEDENOISE': col.prop(cscene, "preview_denoising_prefilter", text="Prefilter") @@ -242,7 +247,7 @@ class CYCLES_RENDER_PT_sampling_viewport_denoise(CyclesButtonsPanel, Panel): if effective_preview_denoiser == 'OPENIMAGEDENOISE': row = col.row() - row.active = not use_cpu(context) and has_oidn_gpu_devices(context) + row.active = not use_cpu(context) and has_oidn_gpu row.prop(cscene, "preview_denoising_use_gpu", text="Use GPU") diff --git a/intern/cycles/blender/python.cpp b/intern/cycles/blender/python.cpp index b65a5fe3f83..ace67591250 100644 --- a/intern/cycles/blender/python.cpp +++ b/intern/cycles/blender/python.cpp @@ -758,7 +758,7 @@ static PyObject *denoise_func(PyObject * /*self*/, PyObject *args, PyObject *key (ID *)PyLong_AsVoidPtr(pyscene), &RNA_ViewLayer, PyLong_AsVoidPtr(pyviewlayer)); BL::ViewLayer b_view_layer(viewlayerptr); - DenoiseParams params = BlenderSync::get_denoise_params(b_scene, b_view_layer, true); + DenoiseParams params = BlenderSync::get_denoise_params(b_scene, b_view_layer, true, device); params.use = true; /* Parse file paths list. */ diff --git a/intern/cycles/blender/session.cpp b/intern/cycles/blender/session.cpp index 64f36f7ca4a..39ec87ce86d 100644 --- a/intern/cycles/blender/session.cpp +++ b/intern/cycles/blender/session.cpp @@ -398,8 +398,14 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_) /* update scene */ BL::Object b_camera_override(b_engine.camera_override()); sync->sync_camera(b_render, b_camera_override, width, height, b_rview_name.c_str()); - sync->sync_data( - b_render, b_depsgraph, b_v3d, b_camera_override, width, height, &python_thread_state); + sync->sync_data(b_render, + b_depsgraph, + b_v3d, + b_camera_override, + width, + height, + &python_thread_state, + session_params.device); builtin_images_load(); /* Attempt to free all data which is held by Blender side, since at this @@ -669,6 +675,10 @@ void BlenderSession::bake(BL::Depsgraph &b_depsgraph_, { b_depsgraph = b_depsgraph_; + /* Get session parameters. */ + const SessionParams session_params = BlenderSync::get_session_params( + b_engine, b_userpref, b_scene, background); + /* Initialize bake manager, before we load the baking kernels. */ scene->bake_manager->set(scene, b_object.name()); @@ -679,8 +689,14 @@ void BlenderSession::bake(BL::Depsgraph &b_depsgraph_, /* Sync scene. */ BL::Object b_camera_override(b_engine.camera_override()); sync->sync_camera(b_render, b_camera_override, width, height, ""); - sync->sync_data( - b_render, b_depsgraph, b_v3d, b_camera_override, width, height, &python_thread_state); + sync->sync_data(b_render, + b_depsgraph, + b_v3d, + b_camera_override, + width, + height, + &python_thread_state, + session_params.device); /* Save the current state of the denoiser, as it might be disabled by the pass configuration (for * passed which do not support denoising). */ @@ -720,10 +736,7 @@ void BlenderSession::bake(BL::Depsgraph &b_depsgraph_, } if (bake_object && !session->progress.get_cancel()) { - /* Get session and buffer parameters. */ - const SessionParams session_params = BlenderSync::get_session_params( - b_engine, b_userpref, b_scene, background); - + /* Get buffer parameters. */ BufferParams buffer_params; buffer_params.width = bake_width; buffer_params.height = bake_height; @@ -801,8 +814,14 @@ void BlenderSession::synchronize(BL::Depsgraph &b_depsgraph_) b_depsgraph = b_depsgraph_; BL::Object b_camera_override(b_engine.camera_override()); - sync->sync_data( - b_render, b_depsgraph, b_v3d, b_camera_override, width, height, &python_thread_state); + sync->sync_data(b_render, + b_depsgraph, + b_v3d, + b_camera_override, + width, + height, + &python_thread_state, + session_params.device); if (b_rv3d) { sync->sync_view(b_v3d, b_rv3d, width, height); diff --git a/intern/cycles/blender/sync.cpp b/intern/cycles/blender/sync.cpp index 255b05998da..13aa5f4d13d 100644 --- a/intern/cycles/blender/sync.cpp +++ b/intern/cycles/blender/sync.cpp @@ -23,6 +23,8 @@ #include "blender/sync.h" #include "blender/util.h" +#include "integrator/denoiser.h" + #include "util/debug.h" #include "util/foreach.h" #include "util/hash.h" @@ -251,7 +253,8 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render, BL::Object &b_override, int width, int height, - void **python_thread_state) + void **python_thread_state, + const DeviceInfo &device_info) { /* For auto refresh images. */ ImageManager *image_manager = scene->image_manager; @@ -271,7 +274,7 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render, const bool background = !b_v3d; sync_view_layer(b_view_layer); - sync_integrator(b_view_layer, background); + sync_integrator(b_view_layer, background, device_info); sync_film(b_view_layer, b_v3d); sync_shaders(b_depsgraph, b_v3d, auto_refresh_update); sync_images(); @@ -300,7 +303,9 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render, /* Integrator */ -void BlenderSync::sync_integrator(BL::ViewLayer &b_view_layer, bool background) +void BlenderSync::sync_integrator(BL::ViewLayer &b_view_layer, + bool background, + const DeviceInfo &device_info) { PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); @@ -457,7 +462,8 @@ void BlenderSync::sync_integrator(BL::ViewLayer &b_view_layer, bool background) integrator->set_guiding_roughness_threshold(get_float(cscene, "guiding_roughness_threshold")); } - DenoiseParams denoise_params = get_denoise_params(b_scene, b_view_layer, background); + DenoiseParams denoise_params = get_denoise_params( + b_scene, b_view_layer, background, device_info); /* No denoising support for vertex color baking, vertices packed into image * buffer have no relation to neighbors. */ @@ -955,7 +961,8 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine &b_engine, DenoiseParams BlenderSync::get_denoise_params(BL::Scene &b_scene, BL::ViewLayer &b_view_layer, - bool background) + bool background, + const DeviceInfo &device_info) { enum DenoiserInput { DENOISER_INPUT_RGB = 1, @@ -1009,13 +1016,8 @@ DenoiseParams BlenderSync::get_denoise_params(BL::Scene &b_scene, /* Auto select fastest denoiser. */ if (denoising.type == DENOISER_NONE) { - if (!Device::available_devices(DEVICE_MASK_OPTIX).empty()) { - denoising.type = DENOISER_OPTIX; - } - else if (openimagedenoise_supported()) { - denoising.type = DENOISER_OPENIMAGEDENOISE; - } - else { + denoising.type = Denoiser::automatic_viewport_denoiser_type(device_info); + if (denoising.type == DENOISER_NONE) { denoising.use = false; } } diff --git a/intern/cycles/blender/sync.h b/intern/cycles/blender/sync.h index 2c892c21e7f..feaef01f743 100644 --- a/intern/cycles/blender/sync.h +++ b/intern/cycles/blender/sync.h @@ -65,10 +65,13 @@ class BlenderSync { BL::Object &b_override, int width, int height, - void **python_thread_state); + void **python_thread_state, + const DeviceInfo &device_info); void sync_view_layer(BL::ViewLayer &b_view_layer); void sync_render_passes(BL::RenderLayer &b_render_layer, BL::ViewLayer &b_view_layer); - void sync_integrator(BL::ViewLayer &b_view_layer, bool background); + void sync_integrator(BL::ViewLayer &b_view_layer, + bool background, + const DeviceInfo &device_info); void sync_camera(BL::RenderSettings &b_render, BL::Object &b_override, int width, @@ -98,7 +101,8 @@ class BlenderSync { static DenoiseParams get_denoise_params(BL::Scene &b_scene, BL::ViewLayer &b_view_layer, - bool background); + bool background, + const DeviceInfo &device); private: /* sync */ diff --git a/intern/cycles/integrator/denoiser.cpp b/intern/cycles/integrator/denoiser.cpp index 99c1bbf0bf7..f7b2567d154 100644 --- a/intern/cycles/integrator/denoiser.cpp +++ b/intern/cycles/integrator/denoiser.cpp @@ -5,13 +5,16 @@ #include "integrator/denoiser.h" #include "device/device.h" + #include "integrator/denoiser_oidn.h" #ifdef WITH_OPENIMAGEDENOISE # include "integrator/denoiser_oidn_gpu.h" #endif #include "integrator/denoiser_optix.h" #include "session/buffers.h" + #include "util/log.h" +#include "util/openimagedenoise.h" #include "util/progress.h" CCL_NAMESPACE_BEGIN @@ -20,14 +23,8 @@ unique_ptr Denoiser::create(Device *path_trace_device, const DenoisePa { DCHECK(params.use); -#ifdef WITH_OPTIX - if (params.type == DENOISER_OPTIX && Device::available_devices(DEVICE_MASK_OPTIX).size()) { - return make_unique(path_trace_device, params); - } -#endif - #ifdef WITH_OPENIMAGEDENOISE - /* If available and allowed, then we will use OpenImageDenoise on GPU, otherwise on CPU. */ + /* If available and allowed, then we will use OpenImageDenoise on GPU. */ if (params.type == DENOISER_OPENIMAGEDENOISE && params.use_gpu && path_trace_device->info.type != DEVICE_CPU && OIDNDenoiserGPU::is_device_supported(path_trace_device->info)) @@ -36,12 +33,35 @@ unique_ptr Denoiser::create(Device *path_trace_device, const DenoisePa } #endif - /* Always fallback to OIDN. */ +#ifdef WITH_OPTIX + /* Use OptiX on GPU if supported. */ + if (params.type == DENOISER_OPTIX && Device::available_devices(DEVICE_MASK_OPTIX).size()) { + return make_unique(path_trace_device, params); + } +#endif + + /* Always fallback to OIDN on CPU. */ DenoiseParams oidn_params = params; oidn_params.type = DENOISER_OPENIMAGEDENOISE; return make_unique(path_trace_device, oidn_params); } +DenoiserType Denoiser::automatic_viewport_denoiser_type(const DeviceInfo &path_trace_device_info) +{ + if (OIDNDenoiserGPU::is_device_supported(path_trace_device_info)) { + return DENOISER_OPENIMAGEDENOISE; + } + else if (!Device::available_devices(DEVICE_MASK_OPTIX).empty()) { + return DENOISER_OPTIX; + } + else if (openimagedenoise_supported()) { + return DENOISER_OPENIMAGEDENOISE; + } + else { + return DENOISER_NONE; + } +} + Denoiser::Denoiser(Device *path_trace_device, const DenoiseParams ¶ms) : path_trace_device_(path_trace_device), params_(params) { diff --git a/intern/cycles/integrator/denoiser.h b/intern/cycles/integrator/denoiser.h index 04d161cea39..9de303944f1 100644 --- a/intern/cycles/integrator/denoiser.h +++ b/intern/cycles/integrator/denoiser.h @@ -40,6 +40,9 @@ class Denoiser { void set_params(const DenoiseParams ¶ms); const DenoiseParams &get_params() const; + /* Recommended type for viewport denoising. */ + static DenoiserType automatic_viewport_denoiser_type(const DeviceInfo &path_trace_device_info); + /* Create devices and load kernels needed for denoising. * The progress is used to communicate state when kernels actually needs to be loaded. * diff --git a/intern/cycles/integrator/denoiser_oidn_gpu.cpp b/intern/cycles/integrator/denoiser_oidn_gpu.cpp index 6e4ffa6b801..cb180d3694d 100644 --- a/intern/cycles/integrator/denoiser_oidn_gpu.cpp +++ b/intern/cycles/integrator/denoiser_oidn_gpu.cpp @@ -57,6 +57,16 @@ static const char *oidn_device_type_to_string(const OIDNDeviceType type) bool OIDNDenoiserGPU::is_device_supported(const DeviceInfo &device) { + if (device.type == DEVICE_MULTI) { + for (const DeviceInfo &multi_device : device.multi_devices) { + if (multi_device.type != DEVICE_CPU && is_device_supported(multi_device)) { + return true; + } + } + + return false; + } + VLOG_DEBUG << "Checking device " << device.description << " (" << device.id << ") for OIDN GPU support"; @@ -517,3 +527,4 @@ void OIDNDenoiserGPU::release_all_resources() CCL_NAMESPACE_END #endif +