mirror of
https://github.com/blender/blender
synced 2026-09-29 04:37:17 +03:00
A bug that existed in Level Zero loader versions up to 1.28.2 (fixed by https://github.com/oneapi-src/level-zero/pull/435). It causes a crash when calling `zeInitDrivers` a second time when no Level Zero drivers are available. In Cycles and the Compositor module, this behavior is triggered when `sycl::platform::get_platforms()` is called (in the case of the Compositor module transitively via OIDN). SYCL loads both the Level Zero v1 and v2 adapters, which both call the problematic function. As a workaround, the SYCL UR Level Zero v1 adapter library files are no longer bundled and the `SYCL_UR_USE_LEVEL_ZERO_V2=1` environment variable is set to force devices to use the v2 adapter that would otherwise default to v1. The v2 adapter has been shipped by Blender starting with 5.0 (using DPC++ version 6.2), but has been available in DPC++ since version 6.0. Pull Request: https://projects.blender.org/blender/blender/pulls/163087
191 lines
5.6 KiB
C++
191 lines
5.6 KiB
C++
/* SPDX-FileCopyrightText: 2021-2022 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 */
|
|
|
|
#include "device/oneapi/device.h"
|
|
#include "device/device.h"
|
|
|
|
#include "util/log.h"
|
|
|
|
#ifdef WITH_ONEAPI
|
|
# include "device/oneapi/device_impl.h"
|
|
# include "integrator/denoiser_oidn_gpu.h" // IWYU pragma: keep
|
|
|
|
# include "util/string.h"
|
|
|
|
# ifdef __linux__
|
|
# include <dlfcn.h>
|
|
# endif
|
|
#endif /* WITH_ONEAPI */
|
|
|
|
CCL_NAMESPACE_BEGIN
|
|
|
|
bool device_oneapi_init()
|
|
{
|
|
#if !defined(WITH_ONEAPI)
|
|
return false;
|
|
#else
|
|
|
|
/* NOTE(@nsirgien): we need to enable JIT cache from here and
|
|
* right now this cache policy is controlled by env. variables. */
|
|
/* NOTE(@xavierh-intel) we enable the use of copy engine, incl. for fill
|
|
* operations as it lowers the overhead from zeCommandListAppendMemoryFill
|
|
* when running paths_array kernels on Linux+A750.
|
|
* All these env variable can be set beforehand by end-users and
|
|
* will in that case -not- be overwritten. */
|
|
/* By default, enable only Level-Zero and if all devices are allowed, also CUDA and HIP.
|
|
* OpenCL backend isn't currently well supported. */
|
|
# ifdef _WIN32
|
|
if (getenv("SYCL_CACHE_PERSISTENT") == nullptr) {
|
|
_putenv_s("SYCL_CACHE_PERSISTENT", "1");
|
|
}
|
|
if (getenv("SYCL_CACHE_THRESHOLD") == nullptr) {
|
|
_putenv_s("SYCL_CACHE_THRESHOLD", "0");
|
|
}
|
|
if (getenv("ONEAPI_DEVICE_SELECTOR") == nullptr) {
|
|
if (getenv("CYCLES_ONEAPI_ALL_DEVICES") == nullptr) {
|
|
_putenv_s("ONEAPI_DEVICE_SELECTOR", "level_zero:*");
|
|
}
|
|
else {
|
|
_putenv_s("ONEAPI_DEVICE_SELECTOR", "!opencl:*");
|
|
}
|
|
}
|
|
/* SYSMAN is needed for free_memory queries. */
|
|
if (getenv("ZES_ENABLE_SYSMAN") == nullptr) {
|
|
_putenv_s("ZES_ENABLE_SYSMAN", "1");
|
|
}
|
|
if (getenv("UR_L0_USE_COPY_ENGINE") == nullptr) {
|
|
_putenv_s("UR_L0_USE_COPY_ENGINE", "1");
|
|
}
|
|
if (getenv("UR_L0_USE_COPY_ENGINE_FOR_FILL") == nullptr) {
|
|
_putenv_s("UR_L0_USE_COPY_ENGINE_FOR_FILL", "1");
|
|
}
|
|
/* As a fix for #163040, the v1 Level Zero adapter is not included. */
|
|
if (getenv("SYCL_UR_USE_LEVEL_ZERO_V2") == nullptr) {
|
|
_putenv_s("SYCL_UR_USE_LEVEL_ZERO_V2", "1");
|
|
}
|
|
# elif __linux__
|
|
setenv("SYCL_CACHE_PERSISTENT", "1", false);
|
|
setenv("SYCL_CACHE_THRESHOLD", "0", false);
|
|
if (getenv("CYCLES_ONEAPI_ALL_DEVICES") == nullptr) {
|
|
setenv("ONEAPI_DEVICE_SELECTOR", "level_zero:*", false);
|
|
}
|
|
else {
|
|
setenv("ONEAPI_DEVICE_SELECTOR", "!opencl:*", false);
|
|
}
|
|
/* SYSMAN is needed for free_memory queries. */
|
|
setenv("ZES_ENABLE_SYSMAN", "1", false);
|
|
setenv("UR_L0_USE_COPY_ENGINE", "1", false);
|
|
setenv("UR_L0_USE_COPY_ENGINE_FOR_FILL", "1", false);
|
|
/* As a fix for #159584, the v1 Level Zero adapter is not included. */
|
|
setenv("SYCL_UR_USE_LEVEL_ZERO_V2", "1", false);
|
|
# endif
|
|
|
|
return true;
|
|
#endif
|
|
}
|
|
|
|
unique_ptr<Device> device_oneapi_create(const DeviceInfo &info,
|
|
Stats &stats,
|
|
Profiler &profiler,
|
|
bool headless)
|
|
{
|
|
#ifdef WITH_ONEAPI
|
|
return make_unique<OneapiDevice>(info, stats, profiler, headless);
|
|
#else
|
|
(void)info;
|
|
(void)stats;
|
|
(void)profiler;
|
|
(void)headless;
|
|
|
|
LOG_FATAL << "Requested to create oneAPI device while not enabled for this build.";
|
|
|
|
return nullptr;
|
|
#endif
|
|
}
|
|
|
|
#ifdef WITH_ONEAPI
|
|
static void device_iterator_cb(const char *id,
|
|
const char *name,
|
|
const int num,
|
|
bool hwrt_support,
|
|
bool oidn_support,
|
|
bool has_execution_optimization,
|
|
bool meets_driver_requirement,
|
|
void *user_ptr)
|
|
{
|
|
vector<DeviceInfo> *devices = (vector<DeviceInfo> *)user_ptr;
|
|
|
|
DeviceInfo info;
|
|
|
|
info.type = DEVICE_ONEAPI;
|
|
info.description = name;
|
|
info.num = num;
|
|
|
|
/* NOTE(@nsirgien): Should be unique at least on proper oneapi installation. */
|
|
info.id = id;
|
|
|
|
info.has_nanovdb = true;
|
|
# if defined(WITH_OPENIMAGEDENOISE)
|
|
# if OIDN_VERSION >= 20300
|
|
if (oidn_support) {
|
|
# else
|
|
if (OIDNDenoiserGPU::is_device_supported(info)) {
|
|
# endif
|
|
info.denoisers |= DENOISER_OPENIMAGEDENOISE;
|
|
}
|
|
# endif
|
|
(void)oidn_support;
|
|
|
|
info.has_gpu_queue = true;
|
|
|
|
/* NOTE(@nsirgien): oneAPI right now is focused on one device usage. In future it maybe will
|
|
* change, but right now peer access from one device to another device is not supported. */
|
|
info.has_peer_memory = false;
|
|
|
|
/* NOTE(@nsirgien): Seems not possible to know from SYCL/oneAPI or Level0. */
|
|
info.display_device = false;
|
|
|
|
# ifdef WITH_EMBREE_GPU
|
|
info.use_hardware_raytracing = hwrt_support;
|
|
# else
|
|
info.use_hardware_raytracing = false;
|
|
(void)hwrt_support;
|
|
# endif
|
|
|
|
info.has_execution_optimization = has_execution_optimization;
|
|
info.meets_driver_requirement = meets_driver_requirement;
|
|
|
|
devices->push_back(info);
|
|
LOG_INFO << "Added device \"" << info.description << "\" with id \"" << info.id << "\".";
|
|
|
|
if (info.denoisers & DENOISER_OPENIMAGEDENOISE) {
|
|
LOG_INFO << "Device with id \"" << info.id << "\" supports "
|
|
<< denoiserTypeToHumanReadable(DENOISER_OPENIMAGEDENOISE) << ".";
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void device_oneapi_info(vector<DeviceInfo> &devices)
|
|
{
|
|
#ifdef WITH_ONEAPI
|
|
OneapiDevice::iterate_devices(device_iterator_cb, &devices);
|
|
#else /* WITH_ONEAPI */
|
|
(void)devices;
|
|
#endif /* WITH_ONEAPI */
|
|
}
|
|
|
|
string device_oneapi_capabilities()
|
|
{
|
|
string capabilities;
|
|
#ifdef WITH_ONEAPI
|
|
char *c_capabilities = OneapiDevice::device_capabilities();
|
|
if (c_capabilities) {
|
|
capabilities = c_capabilities;
|
|
free(c_capabilities);
|
|
}
|
|
#endif
|
|
return capabilities;
|
|
}
|
|
|
|
CCL_NAMESPACE_END
|