crystal_api/
buffer.rs

1use std::{
2    marker::PhantomData,
3    ops::{Index, IndexMut, Range, RangeFrom, RangeFull, RangeTo},
4    sync::Arc,
5};
6
7use crate::proxies::BufferProxy;
8
9/// Stores GPU data.
10/// Can be indexed with `u64` only!
11pub struct Buffer<T> {
12    pub(crate) inner: Arc<dyn BufferProxy>,
13    _t: PhantomData<T>,
14}
15
16impl<T> Buffer<T> {
17    pub(crate) fn new(proxy: Arc<dyn BufferProxy>) -> Self {
18        Self {
19            inner: proxy,
20            _t: PhantomData,
21        }
22    }
23
24    /// Returns true if buffer is empty
25    #[inline]
26    pub fn is_empty(&self) -> bool {
27        self.len() == 0
28    }
29
30    /// Returns length of buffer
31    #[inline]
32    pub fn len(&self) -> u64 {
33        self.inner.get_size() / size_of::<T>() as u64
34    }
35}
36
37impl<T> Index<u64> for Buffer<T> {
38    type Output = T;
39    #[inline]
40    fn index(&self, index: u64) -> &Self::Output {
41        let size = size_of::<T>() as u64;
42        let offset = index * size;
43        let bytes = self.inner.get_memory(offset..offset + size);
44        unsafe { &*((bytes.as_ptr()) as *const T) }
45    }
46}
47
48impl<T> IndexMut<u64> for Buffer<T> {
49    #[inline]
50    fn index_mut(&mut self, index: u64) -> &mut Self::Output {
51        let size = size_of::<T>() as u64;
52        let offset = index * size;
53        let bytes = self.inner.get_memory(offset..offset + size);
54        unsafe { &mut *((bytes.as_ptr()) as *mut T) }
55    }
56}
57
58impl<T> Index<Range<u64>> for Buffer<T> {
59    type Output = [T];
60    #[inline]
61    fn index(&self, range: Range<u64>) -> &Self::Output {
62        let bytes = self
63            .inner
64            .get_memory(range.start * size_of::<T>() as u64..range.end * size_of::<T>() as u64);
65        let len = (range.end - range.start) as usize;
66        unsafe { std::slice::from_raw_parts(bytes.as_ptr() as *const T, len) }
67    }
68}
69
70impl<T> IndexMut<Range<u64>> for Buffer<T> {
71    #[inline]
72    fn index_mut(&mut self, range: Range<u64>) -> &mut Self::Output {
73        let bytes = self
74            .inner
75            .get_memory(range.start * size_of::<T>() as u64..range.end * size_of::<T>() as u64);
76        let len = (range.end - range.start) as usize;
77        unsafe { std::slice::from_raw_parts_mut(bytes.as_ptr() as *mut T, len) }
78    }
79}
80
81impl<T> Index<RangeFull> for Buffer<T> {
82    type Output = [T];
83    #[inline]
84    fn index(&self, _index: RangeFull) -> &Self::Output {
85        &self[0..self.len()]
86    }
87}
88
89impl<T> IndexMut<RangeFull> for Buffer<T> {
90    #[inline]
91    fn index_mut(&mut self, _index: RangeFull) -> &mut Self::Output {
92        let size = self.len();
93        &mut self[0..size]
94    }
95}
96
97impl<T> Index<RangeTo<u64>> for Buffer<T> {
98    type Output = [T];
99    #[inline]
100    fn index(&self, range: RangeTo<u64>) -> &Self::Output {
101        &self[0..range.end]
102    }
103}
104
105impl<T> IndexMut<RangeTo<u64>> for Buffer<T> {
106    #[inline]
107    fn index_mut(&mut self, range: RangeTo<u64>) -> &mut Self::Output {
108        &mut self[0..range.end]
109    }
110}
111
112impl<T> Index<RangeFrom<u64>> for Buffer<T> {
113    type Output = [T];
114    #[inline]
115    fn index(&self, range: RangeFrom<u64>) -> &Self::Output {
116        &self[range.start..self.len()]
117    }
118}
119
120impl<T> IndexMut<RangeFrom<u64>> for Buffer<T> {
121    #[inline]
122    fn index_mut(&mut self, range: RangeFrom<u64>) -> &mut Self::Output {
123        let size = self.len();
124        &mut self[range.start..size]
125    }
126}