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