#![allow(clippy::question_mark)]
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
#![allow(unused)]
use super::{Device, DeviceInfo, MemoryPool};
use crate::DType;
use crate::backend::{DeviceId, DeviceProgramId, Event, PoolBufferId, PoolId};
use crate::dtype::Constant;
use crate::error::{BackendError, ErrorStatus};
use crate::kernel::Kernel;
use crate::shape::Dim;
use crate::slab::Slab;
use libloading::Library;
use nanoserde::DeJson;
use std::ffi::{c_char, c_int, c_uint, c_void};
use std::ptr;
use std::sync::Arc;
#[derive(Debug, Default, DeJson)]
#[allow(clippy::question_mark)]
pub struct HIPConfig {
device_ids: Option<Vec<i32>>,
}
#[derive(Debug)]
pub struct HIPMemoryPool {
#[allow(unused)]
cuda: Arc<Library>,
context: HIPcontext,
device: HIPdevice,
free_bytes: Dim,
buffers: Slab<PoolBufferId, HIPBuffer>,
stream: HIPstream,
hipMemAlloc: unsafe extern "C" fn(*mut HIPdeviceptr, usize) -> HIPStatus,
hipMemcpyHtoDAsync: unsafe extern "C" fn(HIPdeviceptr, *const c_void, usize, HIPstream) -> HIPStatus,
hipMemcpyDtoHAsync: unsafe extern "C" fn(*mut c_void, HIPdeviceptr, usize, HIPstream) -> HIPStatus,
hipMemFree: unsafe extern "C" fn(HIPdeviceptr) -> HIPStatus,
hipEventCreate: unsafe extern "C" fn(*mut HIPevent, c_uint) -> HIPStatus,
hipEventRecord: unsafe extern "C" fn(HIPevent, HIPstream) -> HIPStatus,
hipStreamWaitEvent: unsafe extern "C" fn(HIPstream, HIPevent, c_uint) -> HIPStatus,
hipEventSynchronize: unsafe extern "C" fn(HIPevent) -> HIPStatus,
hipEventDestroy: unsafe extern "C" fn(HIPevent) -> HIPStatus,
hipCtxDestroy: unsafe extern "C" fn(HIPcontext) -> HIPStatus,
}
#[derive(Debug)]
pub(super) struct HIPBuffer {
ptr: u64,
bytes: Dim,
}
#[derive(Debug)]
pub struct HIPDevice {
device: HIPdevice,
memory_pool_id: PoolId,
dev_info: DeviceInfo,
compute_capability: [c_int; 2],
streams: Vec<HIPStream>,
programs: Slab<DeviceProgramId, HIPProgram>,
hipModuleLoadData: unsafe extern "C" fn(*mut HIPmodule, *const u8) -> HIPStatus,
hipModuleGetFunction: unsafe extern "C" fn(*mut HIPfunction, HIPmodule, *const c_char) -> HIPStatus,
hipModuleUnload: unsafe extern "C" fn(HIPmodule) -> HIPStatus,
hipStreamSynchronize: unsafe extern "C" fn(HIPstream) -> HIPStatus,
hipEventCreate: unsafe extern "C" fn(*mut HIPevent, c_uint) -> HIPStatus,
hipLaunchKernel: unsafe extern "C" fn(
HIPfunction,
c_uint,
c_uint,
c_uint,
c_uint,
c_uint,
c_uint,
c_uint,
HIPstream,
*mut *mut c_void,
*mut *mut c_void,
) -> HIPStatus,
hipEventRecord: unsafe extern "C" fn(HIPevent, HIPstream) -> HIPStatus,
hipStreamWaitEvent: unsafe extern "C" fn(HIPstream, HIPevent, c_uint) -> HIPStatus,
}
#[derive(Debug)]
pub(super) struct HIPProgram {
name: String,
module: HIPmodule,
function: HIPfunction,
global_work_size: [usize; 3],
local_work_size: [usize; 3],
}
#[derive(Debug)]
pub(super) struct HIPStream {
stream: HIPstream,
load: usize,
}
#[derive(Debug, Clone)]
pub struct HIPEvent {
event: HIPevent,
}
unsafe impl Send for HIPMemoryPool {}
unsafe impl Send for HIPDevice {}
unsafe impl Send for HIPBuffer {}
unsafe impl Send for HIPProgram {}
unsafe impl Send for HIPStream {}
unsafe impl Send for HIPEvent {}
pub(super) fn initialize_device(
config: &HIPConfig,
memory_pools: &mut Slab<PoolId, MemoryPool>,
devices: &mut Slab<DeviceId, Device>,
debug_dev: bool,
) -> Result<(), BackendError> {
let _ = config;
let hip_paths = [
"/lib64/libamdhip64.so",
"/lib/x86_64-linux-gnu/libamdhip64.so",
"/usr/lib64/hip/libhip_hcc.so",
"/usr/lib64/hip/libhiprtc.so",
"/opt/rocm/hip/lib/libhip_hcc.so",
"/opt/rocm/hip/lib/libhiprtc.so",
];
let hip = hip_paths.into_iter().find_map(|path| unsafe { Library::new(path) }.ok());
let Some(hip) = hip else {
return Err(BackendError { status: ErrorStatus::DyLibNotFound, context: "HIP runtime not found.".into() });
};
let hipInit: unsafe extern "C" fn(c_uint) -> HIPStatus = *unsafe { hip.get(b"hipInit\0") }.unwrap();
let hipDriverGetVersion: unsafe extern "C" fn(*mut c_int) -> HIPStatus =
*unsafe { hip.get(b"hipDriverGetVersion\0") }.unwrap();
let hipDeviceGetCount: unsafe extern "C" fn(*mut c_int) -> HIPStatus = *unsafe { hip.get(b"hipGetDeviceCount\0") }.unwrap();
let hipDeviceGet: unsafe extern "C" fn(*mut HIPdevice, c_int) -> HIPStatus = *unsafe { hip.get(b"hipDeviceGet\0") }.unwrap();
let hipDeviceGetName: unsafe extern "C" fn(*mut c_char, c_int, HIPdevice) -> HIPStatus =
*unsafe { hip.get(b"hipDeviceGetName\0") }.unwrap();
let hipDeviceComputeCapability: unsafe extern "C" fn(*mut c_int, *mut c_int, HIPdevice) -> HIPStatus =
*unsafe { hip.get(b"hipDeviceComputeCapability\0") }.unwrap();
let hipDeviceTotalMem: unsafe extern "C" fn(*mut usize, HIPdevice) -> HIPStatus =
*unsafe { hip.get(b"hipDeviceTotalMem\0") }.unwrap();
let hipCtxCreate: unsafe extern "C" fn(*mut HIPcontext, c_uint, HIPdevice) -> HIPStatus =
*unsafe { hip.get(b"hipCtxCreate\0") }.unwrap();
let hipMemAlloc = *unsafe { hip.get(b"hipMalloc\0") }.unwrap();
let hipMemFree = *unsafe { hip.get(b"hipFree\0") }.unwrap();
let hipMemcpyHtoDAsync = *unsafe { hip.get(b"hipMemcpyHtoDAsync\0") }.unwrap();
let hipMemcpyDtoHAsync = *unsafe { hip.get(b"hipMemcpyDtoHAsync\0") }.unwrap();
let hipModuleLoadData = *unsafe { hip.get(b"hipModuleLoadData\0") }.unwrap();
let hipModuleGetFunction = *unsafe { hip.get(b"hipModuleGetFunction\0") }.unwrap();
let hipLaunchKernel = *unsafe { hip.get(b"hipLaunchKernel\0") }.unwrap();
let hipStreamCreate: unsafe extern "C" fn(*mut HIPstream, c_uint) -> HIPStatus =
*unsafe { hip.get(b"hipStreamCreate\0") }.unwrap();
let hipStreamSynchronize = *unsafe { hip.get(b"hipStreamSynchronize\0") }.unwrap();
let hipStreamWaitEvent = *unsafe { hip.get(b"hipStreamWaitEvent\0") }.unwrap();
let hipModuleUnload = *unsafe { hip.get(b"hipModuleUnload\0") }.unwrap();
let hipEventCreate = *unsafe { hip.get(b"hipEventCreate\0") }.unwrap();
let hipEventRecord = *unsafe { hip.get(b"hipEventRecord\0") }.unwrap();
let hipEventSynchronize = *unsafe { hip.get(b"hipEventSynchronize\0") }.unwrap();
let hipEventDestroy = *unsafe { hip.get(b"hipEventDestroy\0") }.unwrap();
let hipCtxDestroy = *unsafe { hip.get(b"hipCtxDestroy\0") }.unwrap();
unsafe { hipInit(0) }.check(ErrorStatus::Initialization)?;
let mut driver_version = 0;
unsafe { hipDriverGetVersion(&raw mut driver_version) }.check(ErrorStatus::Initialization)?;
let mut num_devices = 0;
unsafe { hipDeviceGetCount(&raw mut num_devices) }.check(ErrorStatus::DeviceEnumeration)?;
if num_devices == 0 {
return Err(BackendError { status: ErrorStatus::DeviceEnumeration, context: "HIP no devices found.".into() });
}
let device_ids: Vec<_> = (0..num_devices)
.filter(|id| config.device_ids.as_ref().is_none_or(|ids| ids.contains(id)))
.collect();
if device_ids.is_empty() {
return Err(BackendError {
status: ErrorStatus::DeviceEnumeration,
context: "HIP all available devices configured out.".into(),
});
}
if debug_dev {
println!(
"Using HIP runtime, driver version: {}.{} on devices:",
driver_version / 1000,
(driver_version - (driver_version / 1000 * 1000)) / 10
);
}
let hip = Arc::new(hip);
for dev_id in device_ids {
let mut device = 0;
unsafe { hipDeviceGet(&raw mut device, dev_id) }.check(ErrorStatus::DeviceEnumeration)?;
let mut device_name = [0; 100];
let Ok(()) = unsafe { hipDeviceGetName(device_name.as_mut_ptr(), 100, device) }.check(ErrorStatus::DeviceQuery) else {
continue;
};
let mut major = 0;
let mut minor = 0;
let Ok(()) =
unsafe { hipDeviceComputeCapability(&raw mut major, &raw mut minor, device) }.check(ErrorStatus::DeviceQuery)
else {
continue;
};
if debug_dev {
println!("{:?}, compute capability: {major}.{minor}", unsafe {
std::ffi::CStr::from_ptr(device_name.as_ptr())
});
}
let mut free_bytes: usize = 0;
let Ok(()) = unsafe { hipDeviceTotalMem(&raw mut free_bytes, device) }.check(ErrorStatus::DeviceQuery) else {
continue;
};
let mut context: HIPcontext = ptr::null_mut();
unsafe { hipCtxCreate(&raw mut context, 0, device) }.check(ErrorStatus::Initialization)?;
let mut stream = ptr::null_mut();
unsafe { hipStreamCreate(&raw mut stream, 0) }.check(ErrorStatus::Initialization)?;
let pool = HIPMemoryPool {
cuda: hip.clone(),
context,
device,
free_bytes: free_bytes as u64,
buffers: Slab::new(),
stream,
hipEventCreate,
hipMemAlloc,
hipMemcpyHtoDAsync,
hipMemFree,
hipMemcpyDtoHAsync,
hipEventRecord,
hipStreamWaitEvent,
hipEventSynchronize,
hipEventDestroy,
hipCtxDestroy,
};
memory_pools.push(MemoryPool::HIP(pool));
let mut streams = Vec::new();
for _ in 0..8 {
let mut stream = ptr::null_mut();
if let Err(err) = unsafe { hipStreamCreate(&raw mut stream, 0) }.check(ErrorStatus::Initialization) {
if debug_dev {
println!("Device with id {dev_id} requested, but cuda stream initialization failed. {err:?}");
}
continue;
}
streams.push(HIPStream { stream, load: 0 });
}
let mut supported_dtypes = u32::MAX;
if major < 7 {
supported_dtypes &= !(1 << DType::F64 as u32);
}
let dev = HIPDevice {
device,
dev_info: DeviceInfo {
compute: 1024 * 1024 * 1024 * 1024,
max_global_work_dims: vec![64, 64, 64],
max_local_threads: 1,
max_local_work_dims: vec![1, 1, 1],
local_mem_size: 0,
max_register_bytes: 96,
preferred_vector_size: 16,
tensor_cores: major > 7,
warp_size: 64,
supported_dtypes,
},
streams,
programs: Slab::new(),
memory_pool_id: PoolId::from(usize::from(memory_pools.len()) - 1),
hipModuleLoadData,
hipModuleGetFunction,
hipModuleUnload,
compute_capability: [major, minor],
hipLaunchKernel,
hipStreamSynchronize,
hipEventCreate,
hipEventRecord,
hipStreamWaitEvent,
};
devices.push(Device::HIP(dev));
}
Ok(())
}
impl HIPMemoryPool {
#[allow(clippy::unused_self)]
#[allow(clippy::unnecessary_wraps)]
#[allow(clippy::needless_pass_by_ref_mut)]
#[allow(clippy::missing_const_for_fn)]
pub(super) fn deinitialize(&mut self) {
}
pub(super) const fn free_bytes(&self) -> Dim {
self.free_bytes
}
pub(super) fn allocate(&mut self, bytes: Dim) -> Result<(PoolBufferId, Event), BackendError> {
if bytes > self.free_bytes {
return Err(BackendError { status: ErrorStatus::MemoryAllocation, context: "Allocation failure".into() });
}
let mut ptr = u64::try_from(self.device).unwrap();
let mut event = ptr::null_mut();
unsafe { (self.hipEventCreate)(&raw mut event, 0x2) }.check(ErrorStatus::MemoryAllocation)?;
debug_assert!(!self.stream.is_null());
unsafe { (self.hipMemAlloc)(&raw mut ptr, bytes as usize) }.check(ErrorStatus::MemoryAllocation)?;
unsafe { (self.hipEventRecord)(event, self.stream) }.check(ErrorStatus::MemoryAllocation)?;
self.free_bytes = self.free_bytes.checked_sub(bytes).unwrap();
Ok((self.buffers.push(HIPBuffer { ptr, bytes }), Event::HIP(HIPEvent { event })))
}
#[allow(clippy::needless_pass_by_value)]
pub(super) fn deallocate(&mut self, buffer_id: PoolBufferId, mut event_wait_list: Vec<Event>) {
while let Some(Event::HIP(HIPEvent { event })) = event_wait_list.pop() {
if !event.is_null() {
unsafe { (self.hipStreamWaitEvent)(self.stream, event, 0) }
.check(ErrorStatus::MemoryDeallocation)
.unwrap();
unsafe { (self.hipEventDestroy)(event) }
.check(ErrorStatus::MemoryCopyP2H)
.unwrap();
}
}
let buffer = &mut self.buffers[buffer_id];
unsafe { (self.hipMemFree)(buffer.ptr) }
.check(ErrorStatus::MemoryDeallocation)
.unwrap();
self.free_bytes += buffer.bytes;
self.buffers.remove(buffer_id);
}
pub(super) fn host_to_pool(
&mut self,
src: &[u8],
dst: PoolBufferId,
mut event_wait_list: Vec<Event>,
) -> Result<Event, BackendError> {
let dst = &self.buffers[dst];
while let Some(Event::HIP(HIPEvent { event })) = event_wait_list.pop() {
if !event.is_null() {
unsafe { (self.hipStreamWaitEvent)(self.stream, event, 0) }.check(ErrorStatus::MemoryCopyH2P)?;
}
}
let mut event = ptr::null_mut();
unsafe { (self.hipEventCreate)(&raw mut event, 0x2) }.check(ErrorStatus::MemoryCopyH2P)?;
debug_assert!(!self.stream.is_null());
unsafe { (self.hipMemcpyHtoDAsync)(dst.ptr, src.as_ptr().cast(), src.len(), self.stream) }
.check(ErrorStatus::MemoryCopyH2P)?;
unsafe { (self.hipEventRecord)(event, self.stream) }.check(ErrorStatus::MemoryCopyH2P)?;
Ok(Event::HIP(HIPEvent { event }))
}
pub(super) fn pool_to_host(
&mut self,
src: PoolBufferId,
dst: &mut [u8],
mut event_wait_list: Vec<Event>,
) -> Result<(), BackendError> {
while let Some(Event::HIP(HIPEvent { event })) = event_wait_list.pop() {
if !event.is_null() {
unsafe { (self.hipStreamWaitEvent)(self.stream, event, 0) }.check(ErrorStatus::MemoryCopyP2H)?;
}
}
let src = &self.buffers[src];
let mut event = ptr::null_mut();
unsafe { (self.hipEventCreate)(&raw mut event, 0x2) }.check(ErrorStatus::MemoryCopyP2H)?;
unsafe { (self.hipMemcpyDtoHAsync)(dst.as_mut_ptr().cast(), src.ptr, dst.len(), self.stream) }
.check(ErrorStatus::MemoryCopyP2H)?;
unsafe { (self.hipEventRecord)(event, self.stream) }.check(ErrorStatus::MemoryCopyP2H)?;
unsafe { (self.hipEventSynchronize)(event) }.check(ErrorStatus::MemoryCopyP2H)?;
unsafe { (self.hipEventDestroy)(event) }.check(ErrorStatus::MemoryCopyP2H)?;
Ok(())
}
pub fn sync_events(&mut self, mut events: Vec<Event>) -> Result<(), BackendError> {
while let Some(Event::HIP(HIPEvent { event })) = events.pop() {
if !event.is_null() {
unsafe { (self.hipEventSynchronize)(event) }.check(ErrorStatus::KernelSync)?;
unsafe { (self.hipEventDestroy)(event) }.check(ErrorStatus::KernelSync)?;
}
}
Ok(())
}
#[allow(clippy::needless_pass_by_value)]
pub fn release_events(&mut self, events: Vec<Event>) {
for event in events {
let Event::HIP(HIPEvent { event }) = event else { unreachable!() };
unsafe { (self.hipEventDestroy)(event) }
.check(ErrorStatus::Deinitialization)
.unwrap();
}
}
}
impl Drop for HIPMemoryPool {
fn drop(&mut self) {
unsafe { (self.hipCtxDestroy)(self.context) };
}
}
impl HIPDevice {
#[allow(clippy::unused_self)]
#[allow(clippy::unnecessary_wraps)]
#[allow(clippy::needless_pass_by_ref_mut)]
pub(super) const fn deinitialize(&mut self) {
}
fn next_stream(&mut self) -> Result<usize, BackendError> {
let mut id = self.streams.iter().enumerate().min_by_key(|(_, s)| s.load).unwrap().0;
if self.streams[id].load > 20 {
unsafe { (self.hipStreamSynchronize)(self.streams[id].stream) }.check(ErrorStatus::KernelSync)?;
self.streams[id].load = 0;
id = self.streams.iter().enumerate().min_by_key(|(_, q)| q.load).unwrap().0;
}
Ok(id)
}
pub(super) const fn info(&self) -> &DeviceInfo {
&self.dev_info
}
pub(super) const fn memory_pool_id(&self) -> PoolId {
self.memory_pool_id
}
#[allow(unused)]
#[allow(clippy::type_complexity)]
fn compile_hip(&self, kernel: &Kernel, debug_asm: bool) -> Result<([Dim; 3], [Dim; 3], String, Vec<u8>), BackendError> {
todo!()
}
#[allow(unused)]
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn compile(&mut self, kernel: &Kernel, debug_asm: bool) -> Result<DeviceProgramId, BackendError> {
todo!()
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn launch(
&mut self,
program_id: DeviceProgramId,
memory_pool: &mut HIPMemoryPool,
args: &[PoolBufferId],
mut event_wait_list: Vec<Event>,
) -> Result<Event, BackendError> {
let stream_id = self.next_stream()?;
let program = &self.programs[program_id];
let mut kernel_params: Vec<*mut core::ffi::c_void> = Vec::new();
for &arg in args {
let arg = &memory_pool.buffers[arg];
let ptr: *const u64 = &raw const arg.ptr;
let ptr: *mut u64 = ptr.cast_mut();
kernel_params.push(ptr.cast());
}
while let Some(Event::HIP(HIPEvent { event })) = event_wait_list.pop() {
if !event.is_null() {
unsafe { (self.hipStreamWaitEvent)(self.streams[stream_id].stream, event, 0) }
.check(ErrorStatus::KernelLaunch)?;
}
}
let mut event = ptr::null_mut();
unsafe { (self.hipEventCreate)(&raw mut event, 0) }.check(ErrorStatus::KernelLaunch)?;
unsafe {
(self.hipLaunchKernel)(
program.function,
u32::try_from(program.global_work_size[0]).unwrap(),
u32::try_from(program.global_work_size[1]).unwrap(),
u32::try_from(program.global_work_size[2]).unwrap(),
u32::try_from(program.local_work_size[0]).unwrap(),
u32::try_from(program.local_work_size[1]).unwrap(),
u32::try_from(program.local_work_size[2]).unwrap(),
0,
self.streams[stream_id].stream,
kernel_params.as_mut_ptr(),
ptr::null_mut(),
)
}
.check(ErrorStatus::KernelLaunch)?;
unsafe { (self.hipEventRecord)(event, self.streams[stream_id].stream) }.check(ErrorStatus::KernelLaunch)?;
self.streams[stream_id].load += 1;
Ok(Event::HIP(HIPEvent { event }))
}
pub fn release(&mut self, program_id: DeviceProgramId) {
let _ = unsafe { (self.hipModuleUnload)(self.programs[program_id].module) }.check(ErrorStatus::Deinitialization);
self.programs.remove(program_id);
}
pub const fn free_compute(&self) -> u128 {
self.dev_info.compute
}
}
impl HIPStatus {
fn check(self, status: ErrorStatus) -> Result<(), BackendError> {
if self == Self::hipSuccess {
Ok(())
} else {
Err(BackendError { status, context: format!("Try rerunning with env var AMD_LOG_LEVEL=2 {self:?}").into() })
}
}
}
impl DType {
pub(super) const fn hip(&self) -> &str {
match self {
Self::BF16 => "hip_bfloat16",
Self::F16 => "half",
Self::F32 => "float",
Self::F64 => "double",
Self::U8 => "unsigned char",
Self::I8 => "char",
Self::I16 => "short",
Self::I32 => "int",
Self::I64 => "long",
Self::Bool => "bool",
Self::U16 => "unsigned short",
Self::U32 => "unsigned int",
Self::U64 => "unsigned long",
}
}
}
impl Constant {
fn hip(self) -> String {
match self {
Self::BF16(x) => format!("{}f", half::bf16::from_le_bytes(x)),
Self::F16(x) => format!("{}f", half::f16::from_le_bytes(x)),
Self::F32(x) => format!("{}f", f32::from_le_bytes(x)),
Self::F64(x) => format!("{}f", f64::from_le_bytes(x)),
Self::U8(x) => format!("{x}"),
Self::I8(x) => format!("{x}"),
Self::I16(x) => format!("{x}"),
Self::U16(x) => format!("{x}"),
Self::U32(x) => format!("{x}"),
Self::U64(x) => format!("{}", u64::from_le_bytes(x)),
Self::I32(x) => format!("{x}"),
Self::I64(x) => format!("{}", i64::from_le_bytes(x)),
Self::Bool(x) => format!("{x}"),
}
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
struct HIPctx_st {
_unused: [u8; 0],
}
type HIPcontext = *mut HIPctx_st;
type HIPdevice = c_int;
type HIPdeviceptr = u64;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
struct HIPmod_st {
_unused: [u8; 0],
}
type HIPmodule = *mut HIPmod_st;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
struct HIPfunc_st {
_unused: [u8; 0],
}
type HIPfunction = *mut HIPfunc_st;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
enum HIPdevice_attribute {
HIP_DEVICE_ATTRIBUTE_MAX_THREADS_PER_BLOCK = 1,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
struct HIPstream_st {
_unused: [u8; 0],
}
type HIPstream = *mut HIPstream_st;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
struct HIPevent_st {
_unused: [u8; 0],
}
type HIPevent = *mut HIPevent_st;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
enum hiprtcResult {
HIPRTC_SUCCESS = 0, HIPRTC_ERROR_OUT_OF_MEMORY = 1, HIPRTC_ERROR_PROGRAM_CREATION_FAILURE = 2, HIPRTC_ERROR_INVALID_INPUT = 3, HIPRTC_ERROR_INVALID_PROGRAM = 4, HIPRTC_ERROR_INVALID_OPTION = 5, HIPRTC_ERROR_COMPILATION = 6, HIPRTC_ERROR_BUILTIN_OPERATION_FAILURE = 7, HIPRTC_ERROR_NO_NAME_EXPRESSIONS_AFTER_COMPILATION = 8, HIPRTC_ERROR_NO_LOWERED_NAMES_BEFORE_COMPILATION = 9, HIPRTC_ERROR_NAME_EXPRESSION_NOT_VALID = 10, HIPRTC_ERROR_INTERNAL_ERROR = 11, HIPRTC_ERROR_LINKING = 100, }
impl hiprtcResult {
fn check(self, status: ErrorStatus) -> Result<(), BackendError> {
if self == Self::HIPRTC_SUCCESS {
Ok(())
} else {
Err(BackendError { status, context: format!("Try rerunning with env var AMD_LOG_LEVEL=2 {self:?}").into() })
}
}
}
#[allow(clippy::enum_variant_names)]
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
enum HIPStatus {
hipSuccess = 0,
hipErrorInvalidValue = 1,
hipErrorOutOfMemory = 2,
hipErrorNotInitialized = 3,
hipErrorDeinitialized = 4,
hipErrorProfilerDisabled = 5,
hipErrorProfilerNotInitialized = 6,
hipErrorProfilerAlreadyStarted = 7,
hipErrorProfilerAlreadyStopped = 8,
hipErrorInvalidConfiguration = 9,
hipErrorInvalidPitchValue = 12,
hipErrorInvalidSymbol = 13,
hipErrorInvalidDevicePointer = 17,
hipErrorInvalidMemcpyDirection = 21,
hipErrorInsufficientDriver = 35,
hipErrorMissingConfiguration = 52,
hipErrorPriorLaunchFailure = 53,
hipErrorInvalidDeviceFunction = 98,
hipErrorNoDevice = 100,
hipErrorInvalidDevice = 101,
hipErrorInvalidImage = 200,
hipErrorInvalidContext = 201,
hipErrorContextAlreadyCurrent = 202,
hipErrorMapFailed = 205,
hipErrorUnmapFailed = 206,
hipErrorArrayIsMapped = 207,
hipErrorAlreadyMapped = 208,
hipErrorNoBinaryForGpu = 209,
hipErrorAlreadyAcquired = 210,
hipErrorNotMapped = 211,
hipErrorNotMappedAsArray = 212,
hipErrorNotMappedAsPointer = 213,
hipErrorECCNotCorrectable = 214,
hipErrorUnsupportedLimit = 215,
hipErrorContextAlreadyInUse = 216,
hipErrorPeerAccessUnsupported = 217,
hipErrorInvalidKernelFile = 218,
hipErrorInvalidGraphicsContext = 219,
hipErrorInvalidSource = 300,
hipErrorFileNotFound = 301,
hipErrorSharedObjectSymbolNotFound = 302,
hipErrorSharedObjectInitFailed = 303,
hipErrorOperatingSystem = 304,
hipErrorInvalidHandle = 400,
hipErrorIllegalState = 401,
hipErrorNotFound = 500,
hipErrorNotReady = 600,
hipErrorIllegalAddress = 700,
hipErrorLaunchOutOfResources = 701,
hipErrorLaunchTimeOut = 702,
hipErrorPeerAccessAlreadyEnabled = 704,
hipErrorPeerAccessNotEnabled = 705,
hipErrorSetOnActiveProcess = 708,
hipErrorContextIsDestroyed = 709,
hipErrorAssert = 710,
hipErrorHostMemoryAlreadyRegistered = 712,
hipErrorHostMemoryNotRegistered = 713,
hipErrorLaunchFailure = 719,
hipErrorCooperativeLaunchTooLarge = 720,
hipErrorNotSupported = 801,
hipErrorStreamCaptureUnsupported = 900,
hipErrorStreamCaptureInvalidated = 901,
hipErrorStreamCaptureMerge = 902,
hipErrorStreamCaptureUnmatched = 903,
hipErrorStreamCaptureUnjoined = 904,
hipErrorStreamCaptureIsolation = 905,
hipErrorStreamCaptureImplicit = 906,
hipErrorCapturedEvent = 907,
hipErrorStreamCaptureWrongThread = 908,
hipErrorGraphExecUpdateFailure = 910,
hipErrorInvalidChannelDescriptor = 911,
hipErrorInvalidTexture = 912,
hipErrorUnknown = 999,
hipErrorRuntimeMemory = 1052,
hipErrorRuntimeOther = 1053,
hipErrorTbd, }