chrono_batch_render/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
14 / 128
10.9%
Branches:
8 / 61
13.1%
Functions:
4 / 10
40.0%

device/hip/api.cpp
Line Branch Exec Source
1 // SPDX-License-Identifier: BSD-3-Clause
2 #include "chrono_batch_render/device/hip/api.h"
3
4 #include <utility>
5 #include <variant>
6
7 #include <fmt/format.h>
8
9 #include "chrono_batch_render/util/error.h"
10 #include "chrono_batch_render/util/library.h"
11 #include "chrono_batch_render/util/log.h"
12
13 namespace chrono::batch_render::device::hip {
14 namespace {
15
16 ✗ void ResolveFunctions(SymbolResolver& resolve, Api& api) {
17 ✗ resolve("hipInit", api.hipInit);
18 ✗ resolve("hipRuntimeGetVersion", api.hipRuntimeGetVersion);
19 ✗ resolve("hipDriverGetVersion", api.hipDriverGetVersion);
20 ✗ resolve("hipGetDeviceCount", api.hipGetDeviceCount);
21 ✗ resolve("hipGetErrorName", api.hipGetErrorName);
22 ✗ resolve("hipGetErrorString", api.hipGetErrorString);
23 ✗ resolve("hipGetLastError", api.hipGetLastError);
24 ✗ resolve("hipPeekAtLastError", api.hipPeekAtLastError);
25 ✗ resolve("hipDeviceGetName", api.hipDeviceGetName);
26 ✗ resolve("hipDeviceGetUuid", api.hipDeviceGetUuid);
27 ✗ resolve("hipDeviceTotalMem", api.hipDeviceTotalMem);
28 ✗ resolve("hipDeviceGetAttribute", api.hipDeviceGetAttribute);
29 ✗ resolve("hipGetDevicePropertiesR0600", api.hipGetDevicePropertiesR0600);
30 ✗ resolve("hipGetDevice", api.hipGetDevice);
31 ✗ resolve("hipSetDevice", api.hipSetDevice);
32 ✗ resolve("hipMalloc", api.hipMalloc);
33 ✗ resolve("hipFree", api.hipFree);
34 ✗ resolve("hipMemGetInfo", api.hipMemGetInfo);
35 ✗ resolve("hipMemPoolCreate", api.hipMemPoolCreate);
36 ✗ resolve("hipMemPoolDestroy", api.hipMemPoolDestroy);
37 ✗ resolve("hipMemPoolSetAttribute", api.hipMemPoolSetAttribute);
38 ✗ resolve("hipMallocFromPoolAsync", api.hipMallocFromPoolAsync);
39 ✗ resolve("hipFreeAsync", api.hipFreeAsync);
40 ✗ resolve("hipHostMalloc", api.hipHostMalloc);
41 ✗ resolve("hipHostFree", api.hipHostFree);
42 ✗ resolve("hipHostGetDevicePointer", api.hipHostGetDevicePointer);
43 ✗ resolve("hipStreamCreateWithFlags", api.hipStreamCreateWithFlags);
44 ✗ resolve("hipStreamDestroy", api.hipStreamDestroy);
45 ✗ resolve("hipStreamSynchronize", api.hipStreamSynchronize);
46 ✗ resolve("hipEventCreateWithFlags", api.hipEventCreateWithFlags);
47 ✗ resolve("hipEventDestroy", api.hipEventDestroy);
48 ✗ resolve("hipEventQuery", api.hipEventQuery);
49 ✗ resolve("hipEventSynchronize", api.hipEventSynchronize);
50 ✗ resolve("hipEventRecordWithFlags", api.hipEventRecordWithFlags);
51 ✗ resolve("hipStreamWaitEvent", api.hipStreamWaitEvent);
52 ✗ resolve("hipLaunchHostFunc", api.hipLaunchHostFunc);
53 ✗ resolve("hipImportExternalSemaphore", api.hipImportExternalSemaphore);
54 ✗ resolve("hipDestroyExternalSemaphore", api.hipDestroyExternalSemaphore);
55 ✗ resolve("hipImportExternalMemory", api.hipImportExternalMemory);
56 ✗ resolve("hipExternalMemoryGetMappedBuffer", api.hipExternalMemoryGetMappedBuffer);
57 ✗ resolve("hipDestroyExternalMemory", api.hipDestroyExternalMemory);
58 ✗ resolve("hipMemcpyDtoH", api.hipMemcpyDtoH);
59 ✗ resolve("hipSignalExternalSemaphoresAsync", api.hipSignalExternalSemaphoresAsync);
60 ✗ resolve("hipWaitExternalSemaphoresAsync", api.hipWaitExternalSemaphoresAsync);
61 ✗ resolve("hipEventElapsedTime", api.hipEventElapsedTime);
62 ✗ resolve("hipMemcpyAsync", api.hipMemcpyAsync);
63 ✗ resolve("hipMemsetD32Async", api.hipMemsetD32Async);
64 ✗ resolve("hipMemcpyHtoDAsync", api.hipMemcpyHtoDAsync);
65 ✗ resolve("hipModuleLoadData", api.hipModuleLoadData);
66 ✗ resolve("hipModuleUnload", api.hipModuleUnload);
67 ✗ resolve("hipModuleGetGlobal", api.hipModuleGetGlobal);
68 ✗ resolve("hipMemcpyHtoD", api.hipMemcpyHtoD);
69 ✗ resolve("hipModuleGetFunction", api.hipModuleGetFunction);
70 ✗ resolve("hipFuncGetAttribute", api.hipFuncGetAttribute);
71 ✗ resolve("hipModuleLaunchKernel", api.hipModuleLaunchKernel);
72 ✗ resolve("hipStreamBeginCapture", api.hipStreamBeginCapture);
73 ✗ resolve("hipStreamEndCapture", api.hipStreamEndCapture);
74 ✗ resolve("hipGraphInstantiateWithFlags", api.hipGraphInstantiateWithFlags);
75 ✗ resolve("hipGraphLaunch", api.hipGraphLaunch);
76 ✗ resolve("hipGraphExecDestroy", api.hipGraphExecDestroy);
77 ✗ resolve("hipGraphDestroy", api.hipGraphDestroy);
78 ✗ resolve("hipMipmappedArrayCreate", api.hipMipmappedArrayCreate);
79 ✗ resolve("hipMipmappedArrayGetLevel", api.hipMipmappedArrayGetLevel);
80 ✗ resolve("hipMipmappedArrayDestroy", api.hipMipmappedArrayDestroy);
81 ✗ resolve("hipMemcpyParam2DAsync", api.hipMemcpyParam2DAsync);
82 ✗ resolve("hipTexObjectCreate", api.hipTexObjectCreate);
83 ✗ resolve("hipTexObjectDestroy", api.hipTexObjectDestroy);
84 ✗ }
85
86 ✗ Loaded<Api> Initialize(Api api) {
87 ✗ int version = 0;
88 ✗ api.hipRuntimeGetVersion(&version);
89
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ api.runtimeVersion = DecodeVersion(version);
90
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (api.runtimeVersion < kMinimumRuntimeVersion) {
91 ✗ return TooOld("the HIP runtime", api.runtimeVersion, kMinimumRuntimeVersion);
92 }
93
94 ✗ const hipError_t initialized = api.hipInit(0);
95
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (initialized == hipErrorNoDevice) {
96 ✗ return "the HIP runtime found no device";
97 }
98
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (initialized != hipSuccess) {
99 ✗ return fmt::format("hipInit failed: {}", api.ErrorName(initialized));
100 }
101
102 ✗ api.hipDriverGetVersion(&version);
103 ✗ api.driverVersion = DecodeVersion(version);
104
0/1
✗ Branch 2 not taken.
✗ Log(LogLevel::Debug, "the HIP runtime is version {}", api.runtimeVersion.ToString());
105 ✗ return api;
106 }
107
108 11 Loaded<Api> Load() {
109 #if defined(_WIN32)
110 const auto names = {"amdhip64_7.dll", "amdhip64_6.dll"};
111 const std::initializer_list<const char*> paths = {};
112 #else
113 11 const auto names = {"libamdhip64.so.7", "libamdhip64.so.6"};
114 11 const auto paths = {"/opt/rocm/lib/libamdhip64.so.7", "/opt/rocm/lib/libamdhip64.so.6"};
115 #endif
116
1/1
✓ Branch 2 taken 11 times.
11 const Library library = Library::Load(names, paths);
117
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (!library) {
118
1/1
✓ Branch 1 taken 11 times.
11 return "no HIP runtime was found";
119 }
120
121
0/2
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✗ SymbolResolver resolve(library);
122 ✗ Api api;
123
0/1
✗ Branch 1 not taken.
✗ api.library = library.Name();
124
0/1
✗ Branch 1 not taken.
✗ api.directory = library.Directory();
125
0/1
✗ Branch 1 not taken.
✗ ResolveFunctions(resolve, api);
126
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (resolve.Missing() != nullptr) {
127
0/1
✗ Branch 1 not taken.
✗ return fmt::format("{} lacks {}", api.library, resolve.Missing());
128 }
129
0/1
✗ Branch 2 not taken.
✗ return Initialize(std::move(api));
130 11 }
131
132 30 const Loaded<Api>& Cached() {
133
5/6
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 19 times.
✓ Branch 3 taken 11 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 11 times.
✓ Branch 9 taken 11 times.
30 static const Loaded<Api> loaded = LogUnavailable("HIP", Load());
134 30 return loaded;
135 }
136
137 }
138
139 2 bool Available() {
140 2 return std::holds_alternative<Api>(Cached());
141 }
142
143 28 const Api& GetApi() {
144 28 return RequireLoaded(Cached());
145 }
146
147 ✗ const compute::RuntimeCompiler& GetHiprtc() {
148 #if defined(_WIN32)
149 const auto names = {"hiprtc0702.dll", "hiprtc0602.dll"};
150 const std::initializer_list<const char*> paths = {};
151 #else
152 ✗ const auto names = {"libhiprtc.so.7", "libhiprtc.so.6"};
153 ✗ const auto paths = {"/opt/rocm/lib/libhiprtc.so.7", "/opt/rocm/lib/libhiprtc.so.6"};
154 #endif
155 ✗ static const Loaded<compute::RuntimeCompiler> loaded = LogUnavailable(
156
0/1
✗ Branch 1 not taken.
✗ "hipRTC", compute::LoadRuntimeCompiler(
157 "hipRTC", "hiprtc", "Code", names, paths, kMinimumRuntimeVersion,
158
0/10
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✗ Branch 14 not taken.
✗ Branch 18 not taken.
✗ Available() ? GetApi().directory : std::filesystem::path{}));
159 ✗ return RequireLoaded(loaded);
160 }
161
162 ✗ const char* Api::ErrorName(hipError_t error) const {
163
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ const char* name = hipGetErrorName != nullptr ? hipGetErrorName(error) : nullptr;
164
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ return name != nullptr ? name : "unknown";
165 }
166
167 ✗ void Api::Warn(hipError_t error, const char* what) const {
168
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (error != hipSuccess) {
169 ✗ Log(LogLevel::Warning, "{} failed: {}", what, ErrorName(error));
170 }
171 ✗ }
172
173 ✗ void Api::Check(hipError_t error, const char* what) const {
174
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (error == hipSuccess) {
175 ✗ return;
176 }
177
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ const char* text = hipGetErrorString != nullptr ? hipGetErrorString(error) : nullptr;
178
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (LostDevice(error)) {
179 ✗ throw DeviceLostError("{} failed: the device was lost: {} ({}): {}", what, ErrorName(error),
180
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
✗ error, text != nullptr ? text : "");
181 }
182
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✗ Branch 13 not taken.
✗ throw ApiError(what, ErrorName(error), error, text != nullptr ? text : "");
183 }
184
185 }
186