Cycles: Allow to choose OIDN denoise device on per-scene basis. #117876

Closed
Nikita Sirgienko wants to merge 1 commits from Sirgienko/blender:ui_oidn_oidn_cpu_and_gpu_entry into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
15 changed files with 79 additions and 29 deletions

View File

@ -216,8 +216,33 @@ enum_guiding_directional_sampling_types = (
def enum_openimagedenoise_denoiser(self, context):
import _cycles
if _cycles.with_openimagedenoise:
return [('OPENIMAGEDENOISE', "OpenImageDenoise",
"Use Intel OpenImageDenoise AI denoiser", 4)]
has_oidn_cpu_devices = False
has_oidn_gpu_devices = False
items = []
compute_device_type = context.preferences.addons[__package__].preferences.get_compute_device_type()
# Blender always add CPU device to list of device of any compute type, so
# no need to request CPU devices separately.
for device in _cycles.available_devices(compute_device_type):
has_oidn_support_in_device = device[5];
device_type = device[1]
if has_oidn_support_in_device:
if device_type == 'CPU':
has_oidn_cpu_devices = True
else:
has_oidn_gpu_devices = True
if has_oidn_cpu_devices:
items.append(('OPENIMAGEDENOISE_CPU', "OpenImageDenoise on CPU",
Review

"OpenImageDenoise on CPU" or "OpenImageDenoise on GPU" are not exactly fully fitting in the default panel width, likely worth to change the default value in order to fit this strings fully, or use more short one.

"OpenImageDenoise on CPU" or "OpenImageDenoise on GPU" are not exactly fully fitting in the default panel width, likely worth to change the default value in order to fit this strings fully, or use more short one.
"Use Intel OpenImageDenoise AI denoiser on CPU", 4))
if has_oidn_gpu_devices:
items.append(('OPENIMAGEDENOISE_GPU', "OpenImageDenoise on GPU",
"Use Intel OpenImageDenoise AI denoiser on GPU", 8))
return items
return []

View File

@ -154,7 +154,10 @@ def get_effective_preview_denoiser(context):
if context.preferences.addons[__package__].preferences.get_devices_for_type('OPTIX'):
return 'OPTIX'
return 'OIDN'
if use_cpu(context):
return 'OPENIMAGEDENOISE_CPU'
else:
return 'OPENIMAGEDENOISE_GPU'
def use_mnee(context):
@ -231,7 +234,7 @@ class CYCLES_RENDER_PT_sampling_viewport_denoise(CyclesButtonsPanel, Panel):
col.prop(cscene, "preview_denoising_input_passes", text="Passes")
effective_preview_denoiser = get_effective_preview_denoiser(context)
if effective_preview_denoiser == 'OPENIMAGEDENOISE':
if effective_preview_denoiser == 'OPENIMAGEDENOISE_CPU' or effective_preview_denoiser == 'OPENIMAGEDENOISE_GPU':
col.prop(cscene, "preview_denoising_prefilter", text="Prefilter")
col.prop(cscene, "preview_denoising_start_sample", text="Start Sample")
@ -292,7 +295,7 @@ class CYCLES_RENDER_PT_sampling_render_denoise(CyclesButtonsPanel, Panel):
col.active = cscene.use_denoising
col.prop(cscene, "denoiser", text="Denoiser")
col.prop(cscene, "denoising_input_passes", text="Passes")
if cscene.denoiser == 'OPENIMAGEDENOISE':
if cscene.denoiser == 'OPENIMAGEDENOISE_CPU' or cscene.denoiser == 'OPENIMAGEDENOISE_GPU':
col.prop(cscene, "denoising_prefilter", text="Prefilter")

View File

@ -417,12 +417,16 @@ static PyObject *available_devices_func(PyObject * /*self*/, PyObject *args)
for (size_t i = 0; i < devices.size(); i++) {
DeviceInfo &device = devices[i];
string type_name = Device::string_from_type(device.type);
PyObject *device_tuple = PyTuple_New(5);
PyObject *device_tuple = PyTuple_New(6);
PyTuple_SET_ITEM(device_tuple, 0, pyunicode_from_string(device.description.c_str()));
PyTuple_SET_ITEM(device_tuple, 1, pyunicode_from_string(type_name.c_str()));
PyTuple_SET_ITEM(device_tuple, 2, pyunicode_from_string(device.id.c_str()));
PyTuple_SET_ITEM(device_tuple, 3, PyBool_FromLong(device.has_peer_memory));
PyTuple_SET_ITEM(device_tuple, 4, PyBool_FromLong(device.use_hardware_raytracing));
PyTuple_SET_ITEM(device_tuple,
Review

Duplication of the changes from #117734 - won't be needed after merging #117734 into the master.

Duplication of the changes from https://projects.blender.org/blender/blender/pulls/117734 - won't be needed after merging https://projects.blender.org/blender/blender/pulls/117734 into the master.
5,
PyBool_FromLong(device.denoisers & (DENOISER_OPENIMAGEDENOISE_CPU |
DENOISER_OPENIMAGEDENOISE_GPU)));
PyTuple_SET_ITEM(ret, i, device_tuple);
}

View File

@ -997,11 +997,20 @@ 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()) {
const vector<DeviceInfo> devices = Device::available_devices();
ccl::DenoiserTypeMask denoiser_mask_all = DENOISER_NONE;
for (const DeviceInfo &device : devices) {
denoiser_mask_all |= device.denoisers;
}
if (denoiser_mask_all & DENOISER_OPTIX) {
denoising.type = DENOISER_OPTIX;
}
else if (openimagedenoise_supported()) {
denoising.type = DENOISER_OPENIMAGEDENOISE;
else if (denoiser_mask_all & DENOISER_OPENIMAGEDENOISE_GPU) {
denoising.type = DENOISER_OPENIMAGEDENOISE_GPU;
}
else if (denoiser_mask_all & DENOISER_OPENIMAGEDENOISE_CPU) {
denoising.type = DENOISER_OPENIMAGEDENOISE_CPU;
}
else {
denoising.use = false;

View File

@ -37,7 +37,7 @@ void device_cpu_info(vector<DeviceInfo> &devices)
info.has_guiding = false;
}
if (openimagedenoise_supported()) {
info.denoisers |= DENOISER_OPENIMAGEDENOISE;
info.denoisers |= DENOISER_OPENIMAGEDENOISE_CPU;
}
devices.insert(devices.begin(), info);

View File

@ -166,7 +166,7 @@ void device_cuda_info(vector<DeviceInfo> &devices)
# if defined(WITH_OPENIMAGEDENOISE)
if (OIDNDenoiserGPU::is_device_supported(info)) {
info.denoisers |= DENOISER_OPENIMAGEDENOISE;
info.denoisers |= DENOISER_OPENIMAGEDENOISE_GPU;
}
# endif

View File

@ -11,8 +11,10 @@ const char *denoiserTypeToHumanReadable(DenoiserType type)
switch (type) {
case DENOISER_OPTIX:
return "OptiX";
case DENOISER_OPENIMAGEDENOISE:
return "OpenImageDenoise";
case DENOISER_OPENIMAGEDENOISE_CPU:
return "OpenImageDenoise on CPU";
case DENOISER_OPENIMAGEDENOISE_GPU:
return "OpenImageDenoise on GPU";
case DENOISER_NUM:
case DENOISER_NONE:
@ -29,7 +31,8 @@ const NodeEnum *DenoiseParams::get_type_enum()
if (type_enum.empty()) {
type_enum.insert("optix", DENOISER_OPTIX);
type_enum.insert("openimageio", DENOISER_OPENIMAGEDENOISE);
type_enum.insert("openimagedenoise_cpu", DENOISER_OPENIMAGEDENOISE_CPU);
type_enum.insert("openimagedenoise_gpu", DENOISER_OPENIMAGEDENOISE_GPU);
}
return &type_enum;
@ -57,7 +60,7 @@ NODE_DEFINE(DenoiseParams)
SOCKET_BOOLEAN(use, "Use", false);
SOCKET_ENUM(type, "Type", *type_enum, DENOISER_OPENIMAGEDENOISE);
SOCKET_ENUM(type, "Type", *type_enum, DENOISER_OPENIMAGEDENOISE_CPU);
SOCKET_INT(start_sample, "Start Sample", 0);

View File

@ -12,7 +12,8 @@ CCL_NAMESPACE_BEGIN
enum DenoiserType {
DENOISER_OPTIX = 2,
DENOISER_OPENIMAGEDENOISE = 4,
DENOISER_OPENIMAGEDENOISE_CPU = 4,
DENOISER_OPENIMAGEDENOISE_GPU = 8,
DENOISER_NUM,
DENOISER_NONE = 0,
@ -51,7 +52,7 @@ class DenoiseParams : public Node {
bool use = false;
/* Denoiser type. */
DenoiserType type = DENOISER_OPENIMAGEDENOISE;
DenoiserType type = DENOISER_OPENIMAGEDENOISE_CPU;
/* Viewport start sample. */
int start_sample = 0;

View File

@ -185,7 +185,7 @@ void device_hip_info(vector<DeviceInfo> &devices)
info.denoisers = 0;
# if defined(WITH_OPENIMAGEDENOISE)
if (OIDNDenoiserGPU::is_device_supported(info)) {
info.denoisers |= DENOISER_OPENIMAGEDENOISE;
info.denoisers |= DENOISER_OPENIMAGEDENOISE_GPU;
}
# endif

View File

@ -110,7 +110,7 @@ static void device_iterator_cb(
info.has_nanovdb = true;
# if defined(WITH_OPENIMAGEDENOISE)
if (OIDNDenoiserGPU::is_device_supported(info)) {
info.denoisers |= DENOISER_OPENIMAGEDENOISE;
info.denoisers |= DENOISER_OPENIMAGEDENOISE_GPU;
}
# endif

View File

@ -78,7 +78,7 @@ void device_optix_info(const vector<DeviceInfo> &cuda_devices, vector<DeviceInfo
info.denoisers |= DENOISER_OPTIX;
# if defined(WITH_OPENIMAGEDENOISE)
if (OIDNDenoiserGPU::is_device_supported(info)) {
info.denoisers |= DENOISER_OPENIMAGEDENOISE;
info.denoisers |= DENOISER_OPENIMAGEDENOISE_GPU;
}
# endif

View File

@ -21,22 +21,26 @@ unique_ptr<Denoiser> 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()) {
bool has_optix_denoise_device = Device::available_devices(DEVICE_MASK_OPTIX).size();
if (params.type == DENOISER_OPTIX && has_optix_denoise_device) {
return make_unique<OptiXDenoiser>(path_trace_device, params);
}
#endif
#ifdef WITH_OPENIMAGEDENOISE
if (params.type == DENOISER_OPENIMAGEDENOISE && path_trace_device->info.type != DEVICE_CPU &&
OIDNDenoiserGPU::is_device_supported(path_trace_device->info))
{
const ccl::vector<DeviceInfo> devices = Device::available_devices(DEVICE_MASK_ALL);
bool has_oidn_gpu_denoise_device = false;
for (const DeviceInfo device : devices) {
has_oidn_gpu_denoise_device |= device.denoisers & DENOISER_OPENIMAGEDENOISE_GPU;
}
if (params.type == DENOISER_OPENIMAGEDENOISE_GPU && has_oidn_gpu_denoise_device) {
return make_unique<OIDNDenoiserGPU>(path_trace_device, params);
}
#endif
/* Always fallback to OIDN. */
DenoiseParams oidn_params = params;
oidn_params.type = DENOISER_OPENIMAGEDENOISE;
oidn_params.type = DENOISER_OPENIMAGEDENOISE_CPU;
return make_unique<OIDNDenoiser>(path_trace_device, oidn_params);
}

View File

@ -24,7 +24,7 @@ thread_mutex OIDNDenoiser::mutex_;
OIDNDenoiser::OIDNDenoiser(Device *path_trace_device, const DenoiseParams &params)
: Denoiser(path_trace_device, params)
{
DCHECK_EQ(params.type, DENOISER_OPENIMAGEDENOISE);
DCHECK_EQ(params.type, DENOISER_OPENIMAGEDENOISE_CPU);
}
#ifdef WITH_OPENIMAGEDENOISE

View File

@ -77,7 +77,7 @@ bool OIDNDenoiserGPU::is_device_supported(const DeviceInfo &device)
OIDNDenoiserGPU::OIDNDenoiserGPU(Device *path_trace_device, const DenoiseParams &params)
: DenoiserGPU(path_trace_device, params)
{
DCHECK_EQ(params.type, DENOISER_OPENIMAGEDENOISE);
DCHECK_EQ(params.type, DENOISER_OPENIMAGEDENOISE_GPU);
}
OIDNDenoiserGPU::~OIDNDenoiserGPU()

View File

@ -129,7 +129,8 @@ NODE_DEFINE(Integrator)
static NodeEnum denoiser_type_enum;
denoiser_type_enum.insert("optix", DENOISER_OPTIX);
denoiser_type_enum.insert("openimagedenoise", DENOISER_OPENIMAGEDENOISE);
denoiser_type_enum.insert("openimagedenoise_cpu", DENOISER_OPENIMAGEDENOISE_CPU);
denoiser_type_enum.insert("openimagedenoise_gpu", DENOISER_OPENIMAGEDENOISE_GPU);
static NodeEnum denoiser_prefilter_enum;
denoiser_prefilter_enum.insert("none", DENOISER_PREFILTER_NONE);
@ -140,7 +141,7 @@ NODE_DEFINE(Integrator)
* it's best use OptiX and disable the normal pass since it does not always have
* the desired effect for that denoiser. */
SOCKET_BOOLEAN(use_denoise, "Use Denoiser", false);
SOCKET_ENUM(denoiser_type, "Denoiser Type", denoiser_type_enum, DENOISER_OPENIMAGEDENOISE);
SOCKET_ENUM(denoiser_type, "Denoiser Type", denoiser_type_enum, DENOISER_OPENIMAGEDENOISE_CPU);
SOCKET_INT(denoise_start_sample, "Start Sample to Denoise", 0);
SOCKET_BOOLEAN(use_denoise_pass_albedo, "Use Albedo Pass for Denoiser", true);
SOCKET_BOOLEAN(use_denoise_pass_normal, "Use Normal Pass for Denoiser", true);