1 /* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
3 * SPDX-License-Identifier: Apache-2.0 */
5 #include "device/hip/device.h"
10 # include "device/device.h"
11 # include "device/hip/device_impl.h"
13 # include "integrator/denoiser_oidn_gpu.h"
15 # include "util/string.h"
16 # include "util/windows.h"
20 # include "device/hiprt/device_impl.h"
25 bool device_hip_init()
27 #if !defined(WITH_HIP)
29 #elif defined(WITH_HIP_DYNLOAD)
30 static bool initialized
= false;
31 static bool result
= false;
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";
44 else if (hipewCompilerPath() != NULL
) {
45 VLOG_INFO
<< "Found HIPCC " << hipewCompilerPath();
49 VLOG_INFO
<< "Neither precompiled kernels nor HIPCC was found,"
50 << " unable to use HIP";
54 if (hipew_result
== HIPEW_ERROR_ATEXIT_FAILED
) {
55 VLOG_WARNING
<< "HIPEW initialization failed: Error setting up atexit() handler";
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";
63 VLOG_WARNING
<< "HIPEW initialization failed: Error opening HIP dynamic library";
68 #else /* WITH_HIP_DYNLOAD */
70 #endif /* WITH_HIP_DYNLOAD */
73 Device
*device_hip_create(const DeviceInfo
&info
, Stats
&stats
, Profiler
&profiler
)
76 if (info
.use_hardware_raytracing
)
77 return new HIPRTDevice(info
, stats
, profiler
);
79 return new HIPDevice(info
, stats
, profiler
);
80 #elif defined(WITH_HIP)
81 return new HIPDevice(info
, stats
, profiler
);
87 LOG(FATAL
) << "Request to create HIP device without compiled-in support. Should never happen.";
94 static hipError_t
device_hip_safe_init()
101 __except (EXCEPTION_EXECUTE_HANDLER
)
103 /* Ignore crashes inside the HIP driver and hope we can
104 * survive even with corrupted HIP installs. */
105 fprintf(stderr
, "Cycles HIP: driver crashed, continuing without HIP.\n");
108 return hipErrorNoDevice
;
113 #endif /* WITH_HIP */
115 void device_hip_info(vector
<DeviceInfo
> &devices
)
118 hipError_t result
= device_hip_safe_init();
119 if (result
!= hipSuccess
) {
120 if (result
!= hipErrorNoDevice
)
121 fprintf(stderr
, "HIP hipInit: %s\n", hipewErrorString(result
));
126 result
= hipGetDeviceCount(&count
);
127 if (result
!= hipSuccess
) {
128 fprintf(stderr
, "HIP hipGetDeviceCount: %s\n", hipewErrorString(result
));
133 const bool has_hardware_raytracing
= hiprtewInit();
135 const bool has_hardware_raytracing
= false;
138 vector
<DeviceInfo
> display_devices
;
140 for (int num
= 0; num
< count
; num
++) {
143 result
= hipDeviceGetName(name
, 256, num
);
144 if (result
!= hipSuccess
) {
145 fprintf(stderr
, "HIP :hipDeviceGetName: %s\n", hipewErrorString(result
));
149 if (!hipSupportsDevice(num
)) {
155 info
.type
= DEVICE_HIP
;
156 info
.description
= string(name
);
159 info
.has_nanovdb
= true;
160 info
.has_light_tree
= true;
161 info
.has_mnee
= true;
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
) {
168 hipDeviceCanAccessPeer(&can_access
, num
, peer_num
);
169 info
.has_peer_memory
= (can_access
!= 0);
173 info
.use_hardware_raytracing
= has_hardware_raytracing
;
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",
181 (unsigned int)pci_location
[0],
182 (unsigned int)pci_location
[1],
183 (unsigned int)pci_location
[2]);
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 (hipSupportsDeviceOIDN(num
) && OIDNDenoiserGPU::is_device_supported(info
)) {
190 info
.denoisers
|= DENOISER_OPENIMAGEDENOISE
;
194 /* If device has a kernel timeout and no compute preemption, we assume
195 * it is connected to a display and will freeze the display while doing
197 int timeout_attr
= 0;
198 hipDeviceGetAttribute(&timeout_attr
, hipDeviceAttributeKernelExecTimeout
, num
);
201 VLOG_INFO
<< "Device is recognized as display.";
202 info
.description
+= " (Display)";
203 info
.display_device
= true;
204 display_devices
.push_back(info
);
207 VLOG_INFO
<< "Device has compute preemption or is not used for display.";
208 devices
.push_back(info
);
211 VLOG_INFO
<< "Added device \"" << info
.description
<< "\" with id \"" << info
.id
<< "\".";
213 if (info
.denoisers
& DENOISER_OPENIMAGEDENOISE
)
214 VLOG_INFO
<< "Device with id \"" << info
.id
<< "\" is supporting "
215 << denoiserTypeToHumanReadable(DENOISER_OPENIMAGEDENOISE
) << ".";
218 if (!display_devices
.empty())
219 devices
.insert(devices
.end(), display_devices
.begin(), display_devices
.end());
222 #endif /* WITH_HIP */
225 string
device_hip_capabilities()
228 hipError_t result
= device_hip_safe_init();
229 if (result
!= hipSuccess
) {
230 if (result
!= hipErrorNoDevice
) {
231 return string("Error initializing HIP: ") + hipewErrorString(result
);
233 return "No HIP device found\n";
237 result
= hipGetDeviceCount(&count
);
238 if (result
!= hipSuccess
) {
239 return string("Error getting devices: ") + hipewErrorString(result
);
242 string capabilities
= "";
243 for (int num
= 0; num
< count
; num
++) {
245 if (hipDeviceGetName(name
, 256, num
) != hipSuccess
) {
248 capabilities
+= string("\t") + name
+ "\n";
250 # define GET_ATTR(attr) \
252 if (hipDeviceGetAttribute(&value, hipDeviceAttribute##attr, num) == hipSuccess) { \
253 capabilities += string_printf("\t\thipDeviceAttribute" #attr "\t\t\t%d\n", value); \
257 /* TODO(sergey): Strip all attributes which are not useful for us
258 * or does not depend on the driver.
260 GET_ATTR(MaxThreadsPerBlock
);
261 GET_ATTR(MaxBlockDimX
);
262 GET_ATTR(MaxBlockDimY
);
263 GET_ATTR(MaxBlockDimZ
);
264 GET_ATTR(MaxGridDimX
);
265 GET_ATTR(MaxGridDimY
);
266 GET_ATTR(MaxGridDimZ
);
267 GET_ATTR(MaxSharedMemoryPerBlock
);
268 GET_ATTR(TotalConstantMemory
);
271 GET_ATTR(MaxRegistersPerBlock
);
273 GET_ATTR(TextureAlignment
);
274 GET_ATTR(MultiprocessorCount
);
275 GET_ATTR(KernelExecTimeout
);
276 GET_ATTR(Integrated
);
277 GET_ATTR(CanMapHostMemory
);
278 GET_ATTR(ComputeMode
);
279 GET_ATTR(MaxTexture1DWidth
);
280 GET_ATTR(MaxTexture2DWidth
);
281 GET_ATTR(MaxTexture2DHeight
);
282 GET_ATTR(MaxTexture3DWidth
);
283 GET_ATTR(MaxTexture3DHeight
);
284 GET_ATTR(MaxTexture3DDepth
);
285 GET_ATTR(ConcurrentKernels
);
286 GET_ATTR(EccEnabled
);
287 GET_ATTR(MemoryClockRate
);
288 GET_ATTR(MemoryBusWidth
);
289 GET_ATTR(L2CacheSize
);
290 GET_ATTR(MaxThreadsPerMultiProcessor
);
291 GET_ATTR(ComputeCapabilityMajor
);
292 GET_ATTR(ComputeCapabilityMinor
);
293 GET_ATTR(MaxSharedMemoryPerMultiprocessor
);
294 GET_ATTR(ManagedMemory
);
295 GET_ATTR(IsMultiGpuBoard
);
297 capabilities
+= "\n";
304 #endif /* WITH_HIP */