clay_core/buffer/
instance_buffer.rs1use std::marker::PhantomData;
2use ocl::{self, builders::KernelBuilder};
3use crate::{Pack, Push, Context};
4
5
6pub struct InstanceBuffer<T: Pack + 'static> {
8 buffer_int: ocl::Buffer<i32>,
9 buffer_float: ocl::Buffer<f32>,
10 count: usize,
11 phantom: PhantomData<T>,
12}
13
14impl<T: Pack> InstanceBuffer<T> {
15 pub fn new<'a, I: ExactSizeIterator<Item=&'a T>>(context: &Context, objects: I) -> crate::Result<Self> {
16 let mut buffer = Self::reserved(context, objects.len())?;
17 buffer.write(objects)?;
18 Ok(buffer)
19 }
20
21 pub fn reserved(context: &Context, count: usize) -> crate::Result<Self> {
22 let buffer_int = ocl::Buffer::<i32>::builder()
23 .queue(context.queue().clone())
24 .flags(ocl::flags::MEM_READ_ONLY)
25 .len((T::size_int()*count).max(1))
26 .fill_val(0 as i32)
27 .build()?;
28
29 let buffer_float = ocl::Buffer::<f32>::builder()
30 .queue(context.queue().clone())
31 .flags(ocl::flags::MEM_READ_ONLY)
32 .len((T::size_float()*count).max(1))
33 .fill_val(0 as f32)
34 .build()?;
35
36 Ok(Self {
37 buffer_int, buffer_float,
38 count, phantom: PhantomData::<T>,
39 })
40 }
41
42 pub fn write<'a, I: ExactSizeIterator<Item=&'a T>>(&mut self, objects: I) -> crate::Result<()> {
43 let len = objects.len();
44 let mut buffer_int = vec![0i32; T::size_int().max(1)*len];
45 let mut buffer_float = vec![0.0f32; T::size_float().max(1)*len];
46 for (obj, (ibuf, fbuf)) in objects.zip(
48 buffer_int.chunks_mut(Self::size_int().max(1))
49 .zip(buffer_float.chunks_mut(Self::size_float().max(1)))
50 ) {
51 obj.pack_to(&mut ibuf[..T::size_int()], &mut fbuf[..T::size_float()]);
52 }
53 if len == 0 || T::size_int() == 0 { buffer_int = vec![0]; }
54 if len == 0 || T::size_float() == 0 { buffer_float = vec![0.0]; }
55
56 if buffer_int.len() == self.buffer_int.len() && buffer_float.len() == self.buffer_float.len() {
57 self.buffer_int.cmd()
58 .offset(0)
59 .write(&buffer_int)
60 .enq()?;
61
62 self.buffer_float.cmd()
63 .offset(0)
64 .write(&buffer_float)
65 .enq()?;
66
67 Ok(())
68 } else {
69 Err("buffers size mismatch".into())
70 }
71 }
72
73 pub fn buffer_int(&self) -> &ocl::Buffer<i32> {
74 &self.buffer_int
75 }
76 pub fn buffer_float(&self) -> &ocl::Buffer<f32> {
77 &self.buffer_float
78 }
79
80 pub fn size_int() -> usize {
81 T::size_int()
82 }
83 pub fn size_float() -> usize {
84 T::size_float()
85 }
86 pub fn count(&self) -> usize {
87 self.count
88 }
89}
90
91impl<T: Pack> Push for InstanceBuffer<T> {
92 fn args_count() -> usize {
93 3
94 }
95 fn args_def(kb: &mut KernelBuilder) {
96 kb
97 .arg(None::<&ocl::Buffer<i32>>) .arg(None::<&ocl::Buffer<f32>>) .arg(0i32); }
101 fn args_set(&mut self, i: usize, k: &mut ocl::Kernel) -> crate::Result<()> {
102 k.set_arg(i + 0, self.buffer_int())?;
103 k.set_arg(i + 1, self.buffer_float())?;
104 k.set_arg(i + 2, self.count() as i32)?;
105 Ok(())
106 }
107}