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 | ✗ | api.runtimeVersion = DecodeVersion(version); | |
| 90 | ✗ | if (api.runtimeVersion < kMinimumRuntimeVersion) { | |
| 91 | ✗ | return TooOld("the HIP runtime", api.runtimeVersion, kMinimumRuntimeVersion); | |
| 92 | } | ||
| 93 | |||
| 94 | ✗ | const hipError_t initialized = api.hipInit(0); | |
| 95 | ✗ | if (initialized == hipErrorNoDevice) { | |
| 96 | ✗ | return "the HIP runtime found no device"; | |
| 97 | } | ||
| 98 | ✗ | if (initialized != hipSuccess) { | |
| 99 | ✗ | return fmt::format("hipInit failed: {}", api.ErrorName(initialized)); | |
| 100 | } | ||
| 101 | |||
| 102 | ✗ | api.hipDriverGetVersion(&version); | |
| 103 | ✗ | api.driverVersion = DecodeVersion(version); | |
| 104 | ✗ | 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 | 11 | const Library library = Library::Load(names, paths); | |
| 117 | 11 | if (!library) { | |
| 118 | 11 | return "no HIP runtime was found"; | |
| 119 | } | ||
| 120 | |||
| 121 | ✗ | SymbolResolver resolve(library); | |
| 122 | ✗ | Api api; | |
| 123 | ✗ | api.library = library.Name(); | |
| 124 | ✗ | api.directory = library.Directory(); | |
| 125 | ✗ | ResolveFunctions(resolve, api); | |
| 126 | ✗ | if (resolve.Missing() != nullptr) { | |
| 127 | ✗ | return fmt::format("{} lacks {}", api.library, resolve.Missing()); | |
| 128 | } | ||
| 129 | ✗ | return Initialize(std::move(api)); | |
| 130 | 11 | } | |
| 131 | |||
| 132 | 30 | const Loaded<Api>& Cached() { | |
| 133 | 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 | ✗ | "hipRTC", compute::LoadRuntimeCompiler( | |
| 157 | "hipRTC", "hiprtc", "Code", names, paths, kMinimumRuntimeVersion, | ||
| 158 | ✗ | Available() ? GetApi().directory : std::filesystem::path{})); | |
| 159 | ✗ | return RequireLoaded(loaded); | |
| 160 | } | ||
| 161 | |||
| 162 | ✗ | const char* Api::ErrorName(hipError_t error) const { | |
| 163 | ✗ | const char* name = hipGetErrorName != nullptr ? hipGetErrorName(error) : nullptr; | |
| 164 | ✗ | return name != nullptr ? name : "unknown"; | |
| 165 | } | ||
| 166 | |||
| 167 | ✗ | void Api::Warn(hipError_t error, const char* what) const { | |
| 168 | ✗ | 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 | ✗ | if (error == hipSuccess) { | |
| 175 | ✗ | return; | |
| 176 | } | ||
| 177 | ✗ | const char* text = hipGetErrorString != nullptr ? hipGetErrorString(error) : nullptr; | |
| 178 | ✗ | if (LostDevice(error)) { | |
| 179 | ✗ | throw DeviceLostError("{} failed: the device was lost: {} ({}): {}", what, ErrorName(error), | |
| 180 | ✗ | error, text != nullptr ? text : ""); | |
| 181 | } | ||
| 182 | ✗ | throw ApiError(what, ErrorName(error), error, text != nullptr ? text : ""); | |
| 183 | } | ||
| 184 | |||
| 185 | } | ||
| 186 |