Blender V4.3
device/hip/device.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "device/hip/device.h"
6
7#include "util/log.h"
8
9#ifdef WITH_HIP
10# include "device/device.h"
12
14
15# include "util/string.h"
16# include "util/windows.h"
17#endif /* WITH_HIP */
18
19#ifdef WITH_HIPRT
21#endif
22
24
26{
27#if !defined(WITH_HIP)
28 return false;
29#elif defined(WITH_HIP_DYNLOAD)
30 static bool initialized = false;
31 static bool result = false;
32
33 if (initialized)
34 return result;
35
36 initialized = true;
37 int hipew_result = hipewInit(HIPEW_INIT_HIP);
38 if (hipew_result == HIPEW_SUCCESS) {
39 VLOG_INFO << "HIPEW initialization succeeded";
40 if (HIPDevice::have_precompiled_kernels()) {
41 VLOG_INFO << "Found precompiled kernels";
42 result = true;
43 }
44 else if (hipewCompilerPath() != NULL) {
45 VLOG_INFO << "Found HIPCC " << hipewCompilerPath();
46 result = true;
47 }
48 else {
49 VLOG_INFO << "Neither precompiled kernels nor HIPCC was found,"
50 << " unable to use HIP";
51 }
52 }
53 else {
54 if (hipew_result == HIPEW_ERROR_ATEXIT_FAILED) {
55 VLOG_WARNING << "HIPEW initialization failed: Error setting up atexit() handler";
56 }
57 else if (hipew_result == HIPEW_ERROR_OLD_DRIVER) {
59 << "HIPEW initialization failed: Driver version too old, requires AMD Radeon Pro "
60 "21.Q4 driver or newer";
61 }
62 else {
63 VLOG_WARNING << "HIPEW initialization failed: Error opening HIP dynamic library";
64 }
65 }
66
67 return result;
68#else /* WITH_HIP_DYNLOAD */
69 return true;
70#endif /* WITH_HIP_DYNLOAD */
71}
72
73Device *device_hip_create(const DeviceInfo &info, Stats &stats, Profiler &profiler, bool headless)
74{
75#ifdef WITH_HIPRT
77 return new HIPRTDevice(info, stats, profiler, headless);
78 else
79 return new HIPDevice(info, stats, profiler, headless);
80#elif defined(WITH_HIP)
81 return new HIPDevice(info, stats, profiler, headless);
82#else
83 (void)info;
84 (void)stats;
85 (void)profiler;
86 (void)headless;
87
88 LOG(FATAL) << "Request to create HIP device without compiled-in support. Should never happen.";
89
90 return nullptr;
91#endif
92}
93
94#ifdef WITH_HIP
95static hipError_t device_hip_safe_init()
96{
97# ifdef _WIN32
98 __try
99 {
100 return hipInit(0);
101 }
102 __except (EXCEPTION_EXECUTE_HANDLER)
103 {
104 /* Ignore crashes inside the HIP driver and hope we can
105 * survive even with corrupted HIP installs. */
106 fprintf(stderr, "Cycles HIP: driver crashed, continuing without HIP.\n");
107 }
108
109 return hipErrorNoDevice;
110# else
111 return hipInit(0);
112# endif
113}
114#endif /* WITH_HIP */
115
117{
118#ifdef WITH_HIP
119 hipError_t result = device_hip_safe_init();
120 if (result != hipSuccess) {
121 if (result != hipErrorNoDevice)
122 fprintf(stderr, "HIP hipInit: %s\n", hipewErrorString(result));
123 return;
124 }
125
126 int count = 0;
127 result = hipGetDeviceCount(&count);
128 if (result != hipSuccess) {
129 fprintf(stderr, "HIP hipGetDeviceCount: %s\n", hipewErrorString(result));
130 return;
131 }
132
133# ifdef WITH_HIPRT
134 const bool has_hardware_raytracing = hiprtewInit();
135# else
136 const bool has_hardware_raytracing = false;
137# endif
138
139 vector<DeviceInfo> display_devices;
140
141 for (int num = 0; num < count; num++) {
142 char name[256];
143
144 result = hipDeviceGetName(name, 256, num);
145 if (result != hipSuccess) {
146 fprintf(stderr, "HIP :hipDeviceGetName: %s\n", hipewErrorString(result));
147 continue;
148 }
149
150 if (!hipSupportsDevice(num)) {
151 continue;
152 }
153
154 DeviceInfo info;
155
156 info.type = DEVICE_HIP;
157 info.description = string(name);
158 info.num = num;
159
160 info.has_nanovdb = true;
161 info.has_mnee = true;
162
163 info.has_gpu_queue = true;
164 /* Check if the device has P2P access to any other device in the system. */
165 for (int peer_num = 0; peer_num < count && !info.has_peer_memory; peer_num++) {
166 if (num != peer_num) {
167 int can_access = 0;
168 hipDeviceCanAccessPeer(&can_access, num, peer_num);
169 info.has_peer_memory = (can_access != 0);
170 }
171 }
172
173 info.use_hardware_raytracing = has_hardware_raytracing;
174
175 int pci_location[3] = {0, 0, 0};
176 hipDeviceGetAttribute(&pci_location[0], hipDeviceAttributePciDomainID, num);
177 hipDeviceGetAttribute(&pci_location[1], hipDeviceAttributePciBusId, num);
178 hipDeviceGetAttribute(&pci_location[2], hipDeviceAttributePciDeviceId, num);
179 info.id = string_printf("HIP_%s_%04x:%02x:%02x",
180 name,
181 (unsigned int)pci_location[0],
182 (unsigned int)pci_location[1],
183 (unsigned int)pci_location[2]);
184
185 info.denoisers = 0;
186# if defined(WITH_OPENIMAGEDENOISE)
187 /* Check first if OIDN supports it, not doing so can crash the HIP driver with
188 * "hipErrorNoBinaryForGpu: Unable to find code object for all current devices". */
189# if OIDN_VERSION >= 20300
190 if (hipSupportsDeviceOIDN(num) && oidnIsHIPDeviceSupported(num)) {
191# else
192 if (hipSupportsDeviceOIDN(num) && OIDNDenoiserGPU::is_device_supported(info)) {
193# endif
195 }
196# endif
197
198 /* If device has a kernel timeout and no compute preemption, we assume
199 * it is connected to a display and will freeze the display while doing
200 * computations. */
201 int timeout_attr = 0;
202 hipDeviceGetAttribute(&timeout_attr, hipDeviceAttributeKernelExecTimeout, num);
203
204 if (timeout_attr) {
205 VLOG_INFO << "Device is recognized as display.";
206 info.description += " (Display)";
207 info.display_device = true;
208 display_devices.push_back(info);
209 }
210 else {
211 VLOG_INFO << "Device has compute preemption or is not used for display.";
212 devices.push_back(info);
213 }
214
215 VLOG_INFO << "Added device \"" << info.description << "\" with id \"" << info.id << "\".";
216
218 VLOG_INFO << "Device with id \"" << info.id << "\" supports "
220 }
221
222 if (!display_devices.empty())
223 devices.insert(devices.end(), display_devices.begin(), display_devices.end());
224#else /* WITH_HIP */
225 (void)devices;
226#endif /* WITH_HIP */
227}
228
230{
231#ifdef WITH_HIP
232 hipError_t result = device_hip_safe_init();
233 if (result != hipSuccess) {
234 if (result != hipErrorNoDevice) {
235 return string("Error initializing HIP: ") + hipewErrorString(result);
236 }
237 return "No HIP device found\n";
238 }
239
240 int count;
241 result = hipGetDeviceCount(&count);
242 if (result != hipSuccess) {
243 return string("Error getting devices: ") + hipewErrorString(result);
244 }
245
246 string capabilities = "";
247 for (int num = 0; num < count; num++) {
248 char name[256];
249 if (hipDeviceGetName(name, 256, num) != hipSuccess) {
250 continue;
251 }
252 capabilities += string("\t") + name + "\n";
253 int value;
254# define GET_ATTR(attr) \
255 { \
256 if (hipDeviceGetAttribute(&value, hipDeviceAttribute##attr, num) == hipSuccess) { \
257 capabilities += string_printf("\t\thipDeviceAttribute" #attr "\t\t\t%d\n", value); \
258 } \
259 } \
260 (void)0
261 /* TODO(sergey): Strip all attributes which are not useful for us
262 * or does not depend on the driver.
263 */
264 GET_ATTR(MaxThreadsPerBlock);
265 GET_ATTR(MaxBlockDimX);
266 GET_ATTR(MaxBlockDimY);
267 GET_ATTR(MaxBlockDimZ);
268 GET_ATTR(MaxGridDimX);
269 GET_ATTR(MaxGridDimY);
270 GET_ATTR(MaxGridDimZ);
271 GET_ATTR(MaxSharedMemoryPerBlock);
272 GET_ATTR(TotalConstantMemory);
273 GET_ATTR(WarpSize);
274 GET_ATTR(MaxPitch);
275 GET_ATTR(MaxRegistersPerBlock);
276 GET_ATTR(ClockRate);
277 GET_ATTR(TextureAlignment);
278 GET_ATTR(MultiprocessorCount);
279 GET_ATTR(KernelExecTimeout);
280 GET_ATTR(Integrated);
281 GET_ATTR(CanMapHostMemory);
282 GET_ATTR(ComputeMode);
283 GET_ATTR(MaxTexture1DWidth);
284 GET_ATTR(MaxTexture2DWidth);
285 GET_ATTR(MaxTexture2DHeight);
286 GET_ATTR(MaxTexture3DWidth);
287 GET_ATTR(MaxTexture3DHeight);
288 GET_ATTR(MaxTexture3DDepth);
289 GET_ATTR(ConcurrentKernels);
290 GET_ATTR(EccEnabled);
291 GET_ATTR(MemoryClockRate);
292 GET_ATTR(MemoryBusWidth);
293 GET_ATTR(L2CacheSize);
294 GET_ATTR(MaxThreadsPerMultiProcessor);
295 GET_ATTR(ComputeCapabilityMajor);
296 GET_ATTR(ComputeCapabilityMinor);
297 GET_ATTR(MaxSharedMemoryPerMultiprocessor);
298 GET_ATTR(ManagedMemory);
299 GET_ATTR(IsMultiGpuBoard);
300# undef GET_ATTR
301 capabilities += "\n";
302 }
303
304 return capabilities;
305
306#else /* WITH_HIP */
307 return "";
308#endif /* WITH_HIP */
309}
310
DenoiserTypeMask denoisers
bool display_device
bool has_peer_memory
bool has_gpu_queue
DeviceType type
string description
bool use_hardware_raytracing
CCL_NAMESPACE_BEGIN const char * denoiserTypeToHumanReadable(DenoiserType type)
Definition denoise.cpp:9
@ DENOISER_OPENIMAGEDENOISE
Definition denoise.h:15
#define CCL_NAMESPACE_END
@ DEVICE_HIP
void device_hip_info(vector< DeviceInfo > &devices)
string device_hip_capabilities()
Device * device_hip_create(const DeviceInfo &info, Stats &stats, Profiler &profiler, bool headless)
CCL_NAMESPACE_BEGIN bool device_hip_init()
#define NULL
static bool initialized
int count
#define VLOG_INFO
Definition log.h:72
#define VLOG_WARNING
Definition log.h:70
#define LOG(severity)
Definition log.h:33
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
Definition string.cpp:23