use super::buffer_descriptor::BufferDescriptor;
use super::opencl_vertex_buffer::{OpenClCommandQueue, OpenClContext, OpenClVertexBuffer};
use crate::far::StencilTable;
use opensubdiv_petite_sys as sys;
use crate::Error;
use std::marker::PhantomData;
use std::ptr::NonNull;
type Result<T, E = Error> = std::result::Result<T, E>;
#[derive(Debug)]
pub struct OpenClKernel<'a> {
ptr: NonNull<std::ffi::c_void>,
_marker: PhantomData<&'a std::ffi::c_void>,
}
impl<'a> OpenClKernel<'a> {
pub unsafe fn from_ptr(ptr: *mut std::ffi::c_void) -> Option<OpenClKernel<'a>> {
NonNull::new(ptr).map(|ptr| OpenClKernel {
ptr,
_marker: PhantomData,
})
}
pub(crate) fn as_ptr(&self) -> *mut std::ffi::c_void {
self.ptr.as_ptr()
}
}
pub fn evaluate_stencils(
src_buffer: &OpenClVertexBuffer,
src_desc: BufferDescriptor,
dst_buffer: &mut OpenClVertexBuffer,
dst_desc: BufferDescriptor,
stencil_table: &OpenClStencilTable,
kernel: &OpenClKernel,
command_queue: &OpenClCommandQueue,
) -> Result<()> {
unsafe {
if sys::osd::CLEvaluator_EvalStencils(
src_buffer.0,
src_desc.0,
dst_buffer.0,
dst_desc.0,
stencil_table.ptr,
kernel.as_ptr() as *const _,
command_queue.as_ptr() as *const _,
) {
Ok(())
} else {
Err(Error::EvalStencilsFailed)
}
}
}
pub struct OpenClStencilTable<'a> {
pub(crate) ptr: sys::osd::OpenCLStencilTablePtr,
st: std::marker::PhantomData<&'a StencilTable>,
}
impl<'a> OpenClStencilTable<'a> {
pub fn new(
st: &'a StencilTable,
context: &OpenClContext,
) -> crate::Result<OpenClStencilTable<'a>> {
let ptr = unsafe { sys::osd::CLStencilTable_Create(st.0, context.as_ptr() as *const _) };
if ptr.is_null() {
return Err(crate::Error::GpuBackend(
"Could not create OpenCLStencilTable".to_string(),
));
}
Ok(OpenClStencilTable {
ptr,
st: std::marker::PhantomData,
})
}
}
impl Drop for OpenClStencilTable<'_> {
fn drop(&mut self) {
unsafe {
sys::osd::CLStencilTable_destroy(self.ptr);
}
}
}