Blender  V3.3
device/oneapi/device.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2021-2022 Intel Corporation */
3 
4 #include "device/oneapi/device.h"
5 
6 #include "util/log.h"
7 
8 #ifdef WITH_ONEAPI
9 # include "device/device.h"
11 
12 # include "util/path.h"
13 # include "util/string.h"
14 
15 # ifdef __linux__
16 # include <dlfcn.h>
17 # endif
18 #endif /* WITH_ONEAPI */
19 
21 
22 #ifdef WITH_ONEAPI
23 static OneAPIDLLInterface oneapi_dll;
24 #endif
25 
26 #ifdef _WIN32
27 # define LOAD_ONEAPI_SHARED_LIBRARY(path) (void *)(LoadLibrary(path))
28 # define FREE_SHARED_LIBRARY(handle) FreeLibrary((HMODULE)handle)
29 # define GET_SHARED_LIBRARY_SYMBOL(handle, name) GetProcAddress((HMODULE)handle, name)
30 #elif __linux__
31 # define LOAD_ONEAPI_SHARED_LIBRARY(path) dlopen(path, RTLD_NOW)
32 # define FREE_SHARED_LIBRARY(handle) dlclose(handle)
33 # define GET_SHARED_LIBRARY_SYMBOL(handle, name) dlsym(handle, name)
34 #endif
35 
37 {
38 #if !defined(WITH_ONEAPI)
39  return false;
40 #else
41 
42  string lib_path = path_get("lib");
43 # ifdef _WIN32
44  lib_path = path_join(lib_path, "cycles_kernel_oneapi.dll");
45 # else
46  lib_path = path_join(lib_path, "cycles_kernel_oneapi.so");
47 # endif
48  void *lib_handle = LOAD_ONEAPI_SHARED_LIBRARY(lib_path.c_str());
49 
50  /* This shouldn't happen, but it still makes sense to have a branch for this. */
51  if (lib_handle == NULL) {
52  LOG(ERROR) << "oneAPI kernel shared library cannot be loaded for some reason. This should not "
53  "happen, however, it occurs hence oneAPI rendering will be disabled";
54  return false;
55  }
56 
57 # define DLL_INTERFACE_CALL(function, return_type, ...) \
58  (oneapi_dll.function) = reinterpret_cast<decltype(oneapi_dll.function)>( \
59  GET_SHARED_LIBRARY_SYMBOL(lib_handle, #function)); \
60  if (oneapi_dll.function == NULL) { \
61  LOG(ERROR) << "oneAPI shared library function \"" << #function \
62  << "\" has not been loaded from kernel shared - disable oneAPI " \
63  "library disable oneAPI implementation due to this"; \
64  FREE_SHARED_LIBRARY(lib_handle); \
65  return false; \
66  }
68 # undef DLL_INTERFACE_CALL
69 
70  VLOG_INFO << "oneAPI kernel shared library has been loaded successfully";
71 
72  /* We need to have this oneapi kernel shared library during all life-span of the Blender.
73  * So it is not unloaded because of this.
74  * FREE_SHARED_LIBRARY(lib_handle); */
75 
76  /* NOTE(@nsirgien): we need to enable JIT cache from here and
77  * right now this cache policy is controlled by env. variables. */
78  /* NOTE(hallade) we also disable use of copy engine as it
79  * improves stability as of intel/LLVM SYCL-nightly/20220529.
80  * All these env variable can be set beforehand by end-users and
81  * will in that case -not- be overwritten. */
82 # ifdef _WIN32
83  if (getenv("SYCL_CACHE_PERSISTENT") == nullptr) {
84  _putenv_s("SYCL_CACHE_PERSISTENT", "1");
85  }
86  if (getenv("SYCL_CACHE_TRESHOLD") == nullptr) {
87  _putenv_s("SYCL_CACHE_THRESHOLD", "0");
88  }
89  if (getenv("SYCL_DEVICE_FILTER") == nullptr) {
90  _putenv_s("SYCL_DEVICE_FILTER", "host,level_zero");
91  }
92  if (getenv("SYCL_ENABLE_PCI") == nullptr) {
93  _putenv_s("SYCL_ENABLE_PCI", "1");
94  }
95  if (getenv("SYCL_PI_LEVEL_ZERO_USE_COPY_ENGINE_FOR_IN_ORDER_QUEUE") == nullptr) {
96  _putenv_s("SYCL_PI_LEVEL_ZERO_USE_COPY_ENGINE_FOR_IN_ORDER_QUEUE", "0");
97  }
98 # elif __linux__
99  setenv("SYCL_CACHE_PERSISTENT", "1", false);
100  setenv("SYCL_CACHE_THRESHOLD", "0", false);
101  setenv("SYCL_DEVICE_FILTER", "host,level_zero", false);
102  setenv("SYCL_ENABLE_PCI", "1", false);
103  setenv("SYCL_PI_LEVEL_ZERO_USE_COPY_ENGINE_FOR_IN_ORDER_QUEUE", "0", false);
104 # endif
105 
106  return true;
107 #endif
108 }
109 
110 #if defined(_WIN32) || defined(__linux__)
111 # undef LOAD_SYCL_SHARED_LIBRARY
112 # undef LOAD_ONEAPI_SHARED_LIBRARY
113 # undef FREE_SHARED_LIBRARY
114 # undef GET_SHARED_LIBRARY_SYMBOL
115 #endif
116 
117 Device *device_oneapi_create(const DeviceInfo &info, Stats &stats, Profiler &profiler)
118 {
119 #ifdef WITH_ONEAPI
120  return new OneapiDevice(info, oneapi_dll, stats, profiler);
121 #else
122  (void)info;
123  (void)stats;
124  (void)profiler;
125 
126  LOG(FATAL) << "Requested to create oneAPI device while not enabled for this build.";
127 
128  return nullptr;
129 #endif
130 }
131 
132 #ifdef WITH_ONEAPI
133 static void device_iterator_cb(const char *id, const char *name, int num, void *user_ptr)
134 {
136 
137  DeviceInfo info;
138 
139  info.type = DEVICE_ONEAPI;
140  info.description = name;
141  info.num = num;
142 
143  /* NOTE(@nsirgien): Should be unique at least on proper oneapi installation. */
144  info.id = id;
145 
146  info.has_nanovdb = true;
147  info.denoisers = 0;
148 
149  info.has_gpu_queue = true;
150 
151  /* NOTE(@nsirgien): oneAPI right now is focused on one device usage. In future it maybe will
152  * change, but right now peer access from one device to another device is not supported. */
153  info.has_peer_memory = false;
154 
155  /* NOTE(@nsirgien): Seems not possible to know from SYCL/oneAPI or Level0. */
156  info.display_device = false;
157 
158  devices->push_back(info);
159  VLOG_INFO << "Added device \"" << name << "\" with id \"" << info.id << "\".";
160 }
161 #endif
162 
164 {
165 #ifdef WITH_ONEAPI
166  (oneapi_dll.oneapi_iterate_devices)(device_iterator_cb, &devices);
167 #else /* WITH_ONEAPI */
168  (void)devices;
169 #endif /* WITH_ONEAPI */
170 }
171 
173 {
174  string capabilities;
175 #ifdef WITH_ONEAPI
176  char *c_capabilities = (oneapi_dll.oneapi_device_capabilities)();
177  if (c_capabilities) {
178  capabilities = c_capabilities;
179  (oneapi_dll.oneapi_free)(c_capabilities);
180  }
181 #endif
182  return capabilities;
183 }
184 
DenoiserTypeMask denoisers
Definition: device/device.h:73
bool display_device
Definition: device/device.h:66
bool has_peer_memory
Definition: device/device.h:70
bool has_nanovdb
Definition: device/device.h:67
bool has_gpu_queue
Definition: device/device.h:71
DeviceType type
Definition: device/device.h:62
string description
Definition: device/device.h:63
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
@ DEVICE_ONEAPI
Definition: device/device.h:44
Device * device_oneapi_create(const DeviceInfo &info, Stats &stats, Profiler &profiler)
void device_oneapi_info(vector< DeviceInfo > &devices)
CCL_NAMESPACE_BEGIN bool device_oneapi_init()
string device_oneapi_capabilities()
SyclQueue void void size_t num_bytes void
#define VLOG_INFO
Definition: log.h:77
#define LOG(severity)
Definition: log.h:36
Vector< CPUDevice > devices
list of all CPUDevices. for every hardware thread an instance of CPUDevice is created
string path_get(const string &sub)
Definition: path.cpp:338
string path_join(const string &dir, const string &file)
Definition: path.cpp:413