use std::{ptr::{NonNull, addr_of_mut}, ffi::c_void, mem::MaybeUninit};
use num_enum::{IntoPrimitive, TryFromPrimitive};
use opencl_sys::*;
use crate::prelude::{*};
#[repr(transparent)]
pub struct Sampler (NonNull<c_void>);
impl Sampler {
#[inline(always)]
pub fn new (props: SamplerProperties) -> Result<Self> {
Self::new_in(&Global, props)
}
#[cfg(not(featue = "cl2"))]
pub fn new_in (ctx: &RawContext, props: SamplerProperties) -> Result<Self> {
let mut err = 0;
let id;
#[allow(deprecated)]
unsafe {
id = clCreateSampler(ctx.id(), props.normalized_coords as cl_bool, props.addressing_mode as cl_addressing_mode, props.filter_mode as cl_filter_mode, addr_of_mut!(err));
if err != 0 { return Err(Error::from(err)) }
Ok(Self::from_id(id).unwrap())
}
}
#[cfg(featue = "cl2")]
pub fn new_in (ctx: &RawContext, props: SamplerProperties) -> Result<Self> {
let mut err = 0;
let id;
unsafe {
cfg_if::cfg_if! {
if #[cfg(feature = "strict")] {
let props = props.to_bits();
id = clCreateSamplerWithProperties(ctx.id(), props.as_ptr(), addr_of_mut!(err))
} else {
#[allow(deprecated)]
if ctx.greatest_common_version()? >= Version::CL2 {
let props = props.to_bits();
id = clCreateSamplerWithProperties(ctx.id(), props.as_ptr(), addr_of_mut!(err));
} else {
id = clCreateSampler(ctx.id(), props.normalized_coords as cl_bool, props.addressing_mode as cl_addressing_mode, props.filter_mode as cl_filter_mode, addr_of_mut!(err))
}
}
}
if err != 0 { return Err(Error::from(err)) }
Ok(Self::from_id(id).unwrap())
}
}
#[inline(always)]
pub const unsafe fn from_id (id: cl_sampler) -> Option<Self> {
NonNull::new(id).map(Self)
}
#[inline(always)]
pub const unsafe fn from_id_unchecked (id: cl_sampler) -> Self {
Self(NonNull::new_unchecked(id))
}
#[inline(always)]
pub const fn id (&self) -> cl_sampler {
self.0.as_ptr()
}
}
impl Sampler {
#[inline(always)]
pub fn reference_count (&self) -> Result<u32> {
self.get_info(CL_SAMPLER_REFERENCE_COUNT)
}
#[inline(always)]
pub fn context (&self) -> Result<RawContext> {
self.get_info(CL_SAMPLER_CONTEXT)
}
#[inline(always)]
pub fn normalized_coords (&self) -> Result<bool> {
let v = self.get_info::<cl_bool>(CL_SAMPLER_NORMALIZED_COORDS)?;
Ok(v != 0)
}
#[inline(always)]
pub fn addressing_mode (&self) -> Result<AddressingMode> {
self.get_info(CL_SAMPLER_ADDRESSING_MODE)
}
#[inline(always)]
pub fn filter_mode (&self) -> Result<FilterMode> {
self.get_info(CL_SAMPLER_FILTER_MODE)
}
#[cfg(feature = "cl3")]
#[inline(always)]
pub fn properties (&self) -> Result<SamplerProperties> {
let v = self.get_info_array::<cl_sampler_properties>(CL_SAMPLER_PROPERTIES)?;
Ok(SamplerProperties::from_bits(&v))
}
#[cfg(not(feature = "cl3"))]
#[inline]
pub fn properties (&self) -> Result<SamplerProperties> {
let normalized_coords = self.normalized_coords()?;
let addressing_mode = self.addressing_mode()?;
let filter_mode = self.filter_mode()?;
Ok(SamplerProperties::new(normalized_coords, addressing_mode, filter_mode))
}
#[inline]
fn get_info<T: Copy> (&self, ty: cl_sampler_info) -> Result<T> {
let mut result = MaybeUninit::<T>::uninit();
unsafe {
tri!(clGetSamplerInfo(self.id(), ty, core::mem::size_of::<T>(), result.as_mut_ptr().cast(), core::ptr::null_mut()));
Ok(result.assume_init())
}
}
#[inline]
fn get_info_array<T: Copy> (&self, ty: cl_sampler_info) -> Result<Box<[T]>> {
let mut size = 0;
unsafe {
tri!(clGetSamplerInfo(self.id(), ty, 0, core::ptr::null_mut(), addr_of_mut!(size)))
}
let len = size / core::mem::size_of::<T>();
let mut result = Box::<[T]>::new_uninit_slice(len);
unsafe {
tri!(clGetSamplerInfo(self.id(), ty, size, result.as_mut_ptr().cast(), core::ptr::null_mut()));
Ok(result.assume_init())
}
}
}
impl Clone for Sampler {
#[inline(always)]
fn clone(&self) -> Self {
unsafe {
tri_panic!(clRetainSampler(self.id()))
}
Self(self.0)
}
}
impl Drop for Sampler {
#[inline(always)]
fn drop(&mut self) {
unsafe {
tri_panic!(clReleaseSampler(self.id()))
}
}
}
unsafe impl Send for Sampler {}
unsafe impl Sync for Sampler {}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub struct SamplerProperties {
pub normalized_coords: bool,
pub addressing_mode: AddressingMode,
pub filter_mode: FilterMode
}
impl SamplerProperties {
const LEN : usize = 3 * 2 + 1;
#[inline(always)]
pub const fn new (normalized_coords: bool, addressing_node: AddressingMode, filter_mode: FilterMode) -> Self {
Self { normalized_coords, addressing_mode: addressing_node, filter_mode }
}
#[inline]
pub fn from_bits (bits: &[cl_sampler_properties]) -> Self {
let mut result = Self::default();
if bits.len() == 0 { return result; }
for i in (0..Self::LEN).step_by(2) {
if bits.len() == i { return result; }
match bits[i] as u32 {
CL_SAMPLER_NORMALIZED_COORDS => result.normalized_coords = bits[i + 1] != 0,
CL_SAMPLER_ADDRESSING_MODE => result.addressing_mode = AddressingMode::try_from_primitive(bits[i + 1] as u32).unwrap(),
CL_SAMPLER_FILTER_MODE => result.filter_mode = FilterMode::try_from_primitive(bits[i + 1] as u32).unwrap(),
0 => return result,
_ => unimplemented!()
}
}
todo!()
}
#[inline(always)]
pub fn to_bits (&self) -> [cl_sampler_properties; Self::LEN] {
[
CL_SAMPLER_NORMALIZED_COORDS as cl_sampler_properties, self.normalized_coords as cl_sampler_properties,
CL_SAMPLER_ADDRESSING_MODE as cl_sampler_properties, self.addressing_mode as cl_sampler_properties,
CL_SAMPLER_FILTER_MODE as cl_sampler_properties, self.filter_mode as cl_sampler_properties,
0
]
}
}
impl Default for SamplerProperties {
#[inline(always)]
fn default() -> Self {
Self {
normalized_coords: true,
addressing_mode: Default::default(),
filter_mode: Default::default()
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, IntoPrimitive, TryFromPrimitive)]
#[non_exhaustive]
#[repr(u32)]
pub enum AddressingMode {
None = CL_ADDRESS_NONE,
ClampToEdge = CL_ADDRESS_CLAMP_TO_EDGE,
Clamp = CL_ADDRESS_CLAMP,
Repeat = CL_ADDRESS_REPEAT,
MirroredRepeat = CL_ADDRESS_MIRRORED_REPEAT
}
impl Default for AddressingMode {
#[inline(always)]
fn default() -> Self {
Self::Clamp
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, IntoPrimitive, TryFromPrimitive)]
#[non_exhaustive]
#[repr(u32)]
pub enum FilterMode {
Nearest = CL_FILTER_NEAREST,
Linear = CL_FILTER_LINEAR
}
impl Default for FilterMode {
#[inline(always)]
fn default() -> Self {
Self::Nearest
}
}