From fd8bb41224a2ce0fd9c018eaffc943485ea5955e Mon Sep 17 00:00:00 2001 From: Stefan Werner Date: Wed, 13 Dec 2023 21:38:19 +0100 Subject: [PATCH] Cycles: Enable HIP devices for OpenImageDenoise This enables the HIP backend of OpenImageDenoise on supported devices. Co-authored-by: Werner, Stefan Pull Request: https://projects.blender.org/blender/blender/pulls/115854 --- .../cmake/openimagedenoise.cmake | 1 + intern/cycles/device/hip/device.cpp | 7 +++ intern/cycles/integrator/denoiser.cpp | 4 +- .../cycles/integrator/denoiser_oidn_gpu.cpp | 53 +++++++++++++++++-- 4 files changed, 61 insertions(+), 4 deletions(-) diff --git a/build_files/build_environment/cmake/openimagedenoise.cmake b/build_files/build_environment/cmake/openimagedenoise.cmake index 62da42a01a1..04d5b848aeb 100644 --- a/build_files/build_environment/cmake/openimagedenoise.cmake +++ b/build_files/build_environment/cmake/openimagedenoise.cmake @@ -14,6 +14,7 @@ if(NOT APPLE) ${OIDN_EXTRA_ARGS} -DOIDN_DEVICE_SYCL=ON -DOIDN_DEVICE_SYCL_AOT=OFF + -DOIDN_DEVICE_HIP=ON -DLEVEL_ZERO_ROOT=${LIBDIR}/level-zero/lib ) endif() diff --git a/intern/cycles/device/hip/device.cpp b/intern/cycles/device/hip/device.cpp index d102805b778..c5f3083c7f4 100644 --- a/intern/cycles/device/hip/device.cpp +++ b/intern/cycles/device/hip/device.cpp @@ -10,6 +10,8 @@ # include "device/device.h" # include "device/hip/device_impl.h" +# include "integrator/denoiser_oidn_gpu.h" + # include "util/string.h" # include "util/windows.h" #endif /* WITH_HIP */ @@ -158,6 +160,11 @@ void device_hip_info(vector &devices) info.has_light_tree = true; info.has_mnee = true; info.denoisers = 0; +# if defined(WITH_OPENIMAGEDENOISE) + if (OIDNDenoiserGPU::is_device_supported(info)) { + info.denoisers |= DENOISER_OPENIMAGEDENOISE; + } +# endif info.has_gpu_queue = true; /* Check if the device has P2P access to any other device in the system. */ diff --git a/intern/cycles/integrator/denoiser.cpp b/intern/cycles/integrator/denoiser.cpp index 2735de9a12e..271b7778ece 100644 --- a/intern/cycles/integrator/denoiser.cpp +++ b/intern/cycles/integrator/denoiser.cpp @@ -27,7 +27,9 @@ unique_ptr Denoiser::create(Device *path_trace_device, const DenoisePa #endif #ifdef WITH_OPENIMAGEDENOISE - if (params.type == DENOISER_OPENIMAGEDENOISE && path_trace_device->info.type == DEVICE_ONEAPI) { + if (params.type == DENOISER_OPENIMAGEDENOISE && + OIDNDenoiserGPU::is_device_supported(path_trace_device->info)) + { return make_unique(path_trace_device, params); } #endif diff --git a/intern/cycles/integrator/denoiser_oidn_gpu.cpp b/intern/cycles/integrator/denoiser_oidn_gpu.cpp index f1025c178c6..79bab94f310 100644 --- a/intern/cycles/integrator/denoiser_oidn_gpu.cpp +++ b/intern/cycles/integrator/denoiser_oidn_gpu.cpp @@ -30,16 +30,48 @@ CCL_NAMESPACE_BEGIN bool OIDNDenoiserGPU::is_device_supported(const DeviceInfo &device) { - /* Currently falls back to checking just the device type, can be improved. */ + int device_type = OIDN_DEVICE_TYPE_DEFAULT; switch (device.type) { # ifdef OIDN_DEVICE_SYCL - /* Assume all devices with Cycles support are also supported by OIDN2. */ case DEVICE_ONEAPI: - return true; + device_type = OIDN_DEVICE_TYPE_SYCL; + break; # endif +# ifdef OIDN_DEVICE_HIP + case DEVICE_HIP: + device_type = OIDN_DEVICE_TYPE_HIP; + break; +# endif +# ifdef OIDN_DEVICE_CUDA + case DEVICE_CUDA: + case DEVICE_OPTIX: + device_type = OIDN_DEVICE_TYPE_CUDA; + break; +# endif + case DEVICE_CPU: + /* This is the GPU denoiser - CPU devices shouldn't end up here. */ + assert(0); default: return false; } + + /* Match GPUs by their PCI ID. */ + const int num_devices = oidnGetNumPhysicalDevices(); + for (int i = 0; i < num_devices; i++) { + if (oidnGetPhysicalDeviceInt(i, "type") == device_type) { + if (oidnGetPhysicalDeviceBool(i, "pciAddressSupported")) { + unsigned int pci_domain = oidnGetPhysicalDeviceInt(i, "pciDomain"); + unsigned int pci_bus = oidnGetPhysicalDeviceInt(i, "pciBus"); + unsigned int pci_device = oidnGetPhysicalDeviceInt(i, "pciDevice"); + string pci_id = string_printf("%04x:%02x:%02x", pci_domain, pci_bus, pci_device); + if (device.id.find(pci_id) != string::npos) { + return true; + } + } + } + } + + return false; } OIDNDenoiserGPU::OIDNDenoiserGPU(Device *path_trace_device, const DenoiseParams ¶ms) @@ -78,6 +110,9 @@ uint OIDNDenoiserGPU::get_device_type_mask() const uint device_mask = 0; # ifdef OIDN_DEVICE_SYCL device_mask |= DEVICE_MASK_ONEAPI; +# endif +# ifdef OIDN_DEVICE_HIP + device_mask |= DEVICE_MASK_HIP; # endif return device_mask; } @@ -122,15 +157,27 @@ bool OIDNDenoiserGPU::denoise_create_if_needed(DenoiseContext &context) 1); denoiser_queue_->init_execution(); break; +# endif +# if defined(OIDN_DEVICE_HIP) && defined(WITH_HIP) + case DEVICE_HIP: { + hipStream_t stream = nullptr; + oidn_device_ = oidnNewHIPDevice(&denoiser_device_->info.num, &stream, 1); + break; + } # endif default: break; } + if (!oidn_device_) { denoiser_device_->set_error("Failed to create OIDN device"); return false; } + if (denoiser_queue_) { + denoiser_queue_->init_execution(); + } + oidnCommitDevice(oidn_device_); oidn_filter_ = create_filter();