use opencl_sys::*;
use blaze_proc::docfg;
use std::{ptr::{NonNull, addr_of_mut}, ffi::c_void, ops::{Deref, DerefMut}, mem::MaybeUninit};
use crate::{core::*, context::RawContext, buffer::{flags::MemFlags}, event::WaitList, prelude::RawEvent, memobj::MemObject};
use super::{ImageFormat, ImageDesc};
#[derive(Debug, Clone)]
#[repr(transparent)]
pub struct RawImage (MemObject);
impl RawImage {
#[docfg(feature = "cl1_2")]
pub unsafe fn new (ctx: &RawContext, flags: MemFlags, format: ImageFormat, desc: ImageDesc, host_ptr: Option<NonNull<c_void>>) -> Result<Self> {
use std::ptr::addr_of;
let image_format = format.into_raw();
let image_desc = desc.to_raw();
let flags = flags.to_bits();
let host_ptr = match host_ptr {
Some(x) => x.as_ptr(),
None => core::ptr::null_mut()
};
let mut err = 0;
let id = opencl_sys::clCreateImage(ctx.id(), flags, addr_of!(image_format), addr_of!(image_desc), host_ptr, addr_of_mut!(err));
if err != 0 { return Err(Error::from(err)) }
let id = MemObject::from_id(id).unwrap();
Ok(Self(id))
}
#[cfg_attr(feature = "cl1_2", deprecated(note = "use `new`"))]
pub unsafe fn new_2d (ctx: &RawContext, flags: MemFlags, format: ImageFormat, desc: ImageDesc, host_ptr: Option<NonNull<c_void>>) -> Result<Self> {
let mut image_format = format.into_raw();
let flags = flags.to_bits();
let host_ptr = match host_ptr {
Some(x) => x.as_ptr(),
None => core::ptr::null_mut()
};
let mut err = 0;
#[allow(deprecated)]
let id = opencl_sys::clCreateImage2D(ctx.id(), flags, addr_of_mut!(image_format), desc.width, desc.height, desc.row_pitch, host_ptr, addr_of_mut!(err));
if err != 0 { return Err(Error::from(err)) }
let id = MemObject::from_id(id).unwrap();
Ok(Self(id))
}
#[cfg_attr(feature = "cl1_2", deprecated(note = "use `new`"))]
pub unsafe fn new_3d (ctx: &RawContext, flags: MemFlags, format: ImageFormat, desc: ImageDesc, host_ptr: Option<NonNull<c_void>>) -> Result<Self> {
let mut image_format = format.into_raw();
let flags = flags.to_bits();
let host_ptr = match host_ptr {
Some(x) => x.as_ptr(),
None => core::ptr::null_mut()
};
let mut err = 0;
#[allow(deprecated)]
let id = opencl_sys::clCreateImage3D(ctx.id(), flags, addr_of_mut!(image_format), desc.width, desc.height, desc.depth, desc.row_pitch, desc.slice_pitch, host_ptr, addr_of_mut!(err));
if err != 0 { return Err(Error::from(err)) }
let id = MemObject::from_id(id).unwrap();
Ok(Self(id))
}
#[inline(always)]
pub fn format (&self) -> Result<ImageFormat> {
let v = self.get_info::<cl_image_format>(CL_IMAGE_FORMAT)?;
Ok(ImageFormat::from_raw(v).unwrap())
}
#[inline(always)]
pub fn element_size (&self) -> Result<usize> {
self.get_info(CL_IMAGE_ELEMENT_SIZE)
}
#[inline(always)]
pub fn row_pitch (&self) -> Result<usize> {
self.get_info(CL_IMAGE_ROW_PITCH)
}
#[inline(always)]
pub fn slice_pitch (&self) -> Result<usize> {
self.get_info(CL_IMAGE_SLICE_PITCH)
}
#[inline(always)]
pub fn width (&self) -> Result<usize> {
self.get_info(CL_IMAGE_WIDTH)
}
#[inline(always)]
pub fn height (&self) -> Result<usize> {
self.get_info(CL_IMAGE_HEIGHT)
}
#[inline(always)]
pub fn depth (&self) -> Result<usize> {
self.get_info(CL_IMAGE_DEPTH)
}
#[docfg(feature = "cl1_2")]
#[inline(always)]
pub fn array_size (&self) -> Result<usize> {
self.get_info(opencl_sys::CL_IMAGE_ARRAY_SIZE)
}
#[docfg(feature = "cl1_2")]
#[cfg_attr(feature = "2", deprecated(note = "use `other`"))]
#[inline(always)]
pub fn buffer (&self) -> Result<Option<MemObject>> {
self.get_info::<cl_mem>(opencl_sys::CL_IMAGE_ARRAY_SIZE).map(MemObject::from_id)
}
#[docfg(feature = "cl1_2")]
#[inline(always)]
pub fn mip_levels (&self) -> Result<usize> {
self.get_info(opencl_sys::CL_IMAGE_NUM_MIP_LEVELS)
}
#[docfg(feature = "cl1_2")]
#[inline(always)]
pub fn samples (&self) -> Result<usize> {
self.get_info(opencl_sys::CL_IMAGE_NUM_SAMPLES)
}
#[inline]
fn get_info<T: Copy> (&self, ty: cl_image_info) -> Result<T> {
let mut result = MaybeUninit::<T>::uninit();
unsafe {
tri!(clGetImageInfo(self.id(), ty, core::mem::size_of::<T>(), result.as_mut_ptr().cast(), core::ptr::null_mut()));
Ok(result.assume_init())
}
}
}
impl RawImage {
#[inline]
pub unsafe fn read_to_ptr (&self, origin: [usize; 3], region: [usize; 3], row_pitch: Option<usize>, slice_pitch: Option<usize>, dst: *mut c_void, queue: &CommandQueue, wait: impl Into<WaitList>) -> Result<RawEvent> {
let row_pitch = row_pitch.unwrap_or_default();
let slice_pitch = slice_pitch.unwrap_or_default();
let wait : WaitList = wait.into();
let (num_events_in_wait_list, event_wait_list) = wait.raw_parts();
let mut evt = core::ptr::null_mut();
tri!(clEnqueueReadImage(queue.id(), self.id(), CL_FALSE, origin.as_ptr(), region.as_ptr(), row_pitch, slice_pitch, dst, num_events_in_wait_list, event_wait_list, addr_of_mut!(evt)));
Ok(RawEvent::from_id(evt).unwrap())
}
#[inline]
pub unsafe fn write_from_ptr (&mut self, origin: [usize; 3], region: [usize; 3], row_pitch: Option<usize>, slice_pitch: Option<usize>, src: *const c_void, queue: &CommandQueue, wait: impl Into<WaitList>) -> Result<RawEvent> {
let row_pitch = row_pitch.unwrap_or_default();
let slice_pitch = slice_pitch.unwrap_or_default();
let wait : WaitList = wait.into();
let (num_events_in_wait_list, event_wait_list) = wait.raw_parts();
let mut evt = core::ptr::null_mut();
tri!(clEnqueueWriteImage(queue.id(), self.id(), CL_FALSE, origin.as_ptr(), region.as_ptr(), row_pitch, slice_pitch, src, num_events_in_wait_list, event_wait_list, addr_of_mut!(evt)));
Ok(RawEvent::from_id(evt).unwrap())
}
#[inline]
pub unsafe fn copy_from (&mut self, offset_dst: [usize; 3], src: &RawImage, offset_src: [usize; 3], region: [usize; 3], queue: &CommandQueue, wait: impl Into<WaitList>) -> Result<RawEvent> {
let wait : WaitList = wait.into();
let (num_events_in_wait_list, event_wait_list) = wait.raw_parts();
let mut evt = core::ptr::null_mut();
tri!(clEnqueueCopyImage(queue.id(), src.id(), self.id(), offset_src.as_ptr(), offset_dst.as_ptr(), region.as_ptr(), num_events_in_wait_list, event_wait_list, addr_of_mut!(evt)));
Ok(RawEvent::from_id(evt).unwrap())
}
#[inline(always)]
pub unsafe fn copy_to (&self, offset_src: [usize; 3], dst: &mut RawImage, offset_dst: [usize; 3], region: [usize; 3], queue: &CommandQueue, wait: impl Into<WaitList>) -> Result<RawEvent> {
Self::copy_from(dst, offset_dst, self, offset_src, region, queue, wait)
}
#[docfg(feature = "cl1_2")]
#[inline]
pub unsafe fn fill (&mut self, color: *const c_void, origin: [usize; 3], region: [usize; 3], queue: &CommandQueue, wait: impl Into<WaitList>) -> Result<RawEvent> {
let wait : WaitList = wait.into();
let (num_events_in_wait_list, event_wait_list) = wait.raw_parts();
let mut evt = core::ptr::null_mut();
tri!(clEnqueueFillImage(queue.id(), self.id(), color, origin.as_ptr(), region.as_ptr(), num_events_in_wait_list, event_wait_list, addr_of_mut!(evt)));
Ok(RawEvent::from_id(evt).unwrap())
}
#[inline(always)]
pub unsafe fn map_read<T, W: Into<WaitList>> (&self, origin: [usize; 3], region: [usize; 3], queue: &CommandQueue, wait: W) -> Result<(*const T, usize, usize, RawEvent)> {
let (ptr, image_row_pitch, image_slice_pitch, evt) = self.__map_inner::<T, W, CL_MAP_READ>(origin, region, queue, wait)?;
Ok((ptr as *const _, image_row_pitch, image_slice_pitch, evt))
}
#[inline(always)]
pub unsafe fn map_write<T, W: Into<WaitList>> (&self, origin: [usize; 3], region: [usize; 3], queue: &CommandQueue, wait: W) -> Result<(*mut T, usize, usize, RawEvent)> {
self.__map_inner::<T, W, CL_MAP_WRITE>(origin, region, queue, wait)
}
#[inline(always)]
pub unsafe fn map_read_write<T, W: Into<WaitList>> (&self, origin: [usize; 3], region: [usize; 3], queue: &CommandQueue, wait: W) -> Result<(*mut T, usize, usize, RawEvent)> {
self.__map_inner::<T, W, {CL_MAP_READ | CL_MAP_WRITE}>(origin, region, queue, wait)
}
unsafe fn __map_inner<T, W: Into<WaitList>, const FLAGS : cl_mem_flags> (&self, origin: [usize; 3], region: [usize; 3], queue: &CommandQueue, wait: W) -> Result<(*mut T, usize, usize, RawEvent)> {
let wait : WaitList = wait.into();
let (num_events_in_wait_list, event_wait_list) = wait.raw_parts();
let mut image_row_pitch = 0;
let mut image_slice_pitch = 0;
let mut evt = core::ptr::null_mut();
let mut err = 0;
let ptr = clEnqueueMapImage(queue.id(), self.id(), CL_FALSE, FLAGS, origin.as_ptr(), region.as_ptr(), addr_of_mut!(image_row_pitch), addr_of_mut!(image_slice_pitch), num_events_in_wait_list, event_wait_list, addr_of_mut!(evt), addr_of_mut!(err));
if err != 0 { return Err(Error::from(err)) }
Ok((ptr.cast(), image_row_pitch, image_slice_pitch, RawEvent::from_id(evt).unwrap()))
}
}
impl Deref for RawImage {
type Target = MemObject;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for RawImage {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl Into<MemObject> for RawImage {
#[inline(always)]
fn into(self) -> MemObject {
self.0
}
}