1use super::BufferKey;
2
3#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
5pub enum BufferType {
6 Vertex,
7 Index,
8}
9
10impl From<BufferType> for u32 {
11 fn from(ty: BufferType) -> Self {
12 match ty {
13 BufferType::Vertex => glow::ARRAY_BUFFER,
14 BufferType::Index => glow::ELEMENT_ARRAY_BUFFER,
15 }
16 }
17}
18
19#[derive(Copy, Clone, Debug, Eq, PartialEq)]
24pub enum Usage {
25 Stream,
26 Static,
27 Dynamic,
28}
29
30impl Usage {
31 pub fn to_gl(self) -> u32 {
32 match self {
33 Usage::Stream => glow::STREAM_DRAW,
34 Usage::Static => glow::STATIC_DRAW,
35 Usage::Dynamic => glow::DYNAMIC_DRAW,
36 }
37 }
38}
39
40#[derive(Clone, Debug, PartialEq, Eq)]
48pub struct Buffer {
49 size: usize,
50 handle: BufferKey,
51 buffer_type: BufferType,
52 usage: Usage,
53}
54
55impl Buffer {
56 pub fn new(
58 ctx: &mut super::Context,
59 size: usize,
60 buffer_type: BufferType,
61 usage: Usage,
62 ) -> Result<Self, super::GraphicsError> {
63 let handle = ctx.new_buffer(size, buffer_type, usage, None)?;
64 Ok(Self {
65 size,
66 handle,
67 buffer_type,
68 usage,
69 })
70 }
71
72 pub fn with_data(
74 ctx: &mut super::Context,
75 data: &[u8],
76 buffer_type: BufferType,
77 usage: Usage,
78 ) -> Result<Self, super::GraphicsError> {
79 let size = data.len();
80 let handle = ctx.new_buffer(size, buffer_type, usage, Some(data))?;
81 Ok(Self {
82 size,
83 handle,
84 buffer_type,
85 usage,
86 })
87 }
88
89 pub fn handle(&self) -> BufferKey {
92 self.handle
93 }
94
95 pub fn size(&self) -> usize {
97 self.size
98 }
99
100 pub fn buffer_type(&self) -> BufferType {
102 self.buffer_type
103 }
104
105 pub fn usage(&self) -> Usage {
107 self.usage
108 }
109}
110
111#[derive(Copy, Clone, Debug, Eq, PartialEq)]
112pub struct ModifiedRange<D> {
113 pub offset: D,
114 pub size: D,
115}
116
117#[derive(Debug, PartialEq)]
118pub struct Mapped<T, D: ndarray::Dimension> {
119 pub(crate) inner: T,
120 pub(crate) memory_map: ndarray::Array<u8, D>,
121 pub(crate) modified_range: Option<ModifiedRange<D>>,
122}
123
124impl<T, D> Mapped<T, D>
125where
126 D: ndarray::Dimension,
127{
128 pub fn with_shape<S>(inner: T, shape: S) -> Self
129 where
130 S: ndarray::ShapeBuilder<Dim = D>,
131 {
132 Self {
133 inner,
134 memory_map: ndarray::Array::default(shape),
135 modified_range: None,
136 }
137 }
138
139 pub fn inner(&self) -> &T {
140 &self.inner
141 }
142
143 pub fn memory_map(&self) -> &[u8] {
144 self.memory_map.as_slice_memory_order().unwrap()
145 }
146}
147
148impl<T> Mapped<T, ndarray::Ix1> {
149 pub fn from_vec(inner: T, vec: Vec<u8>) -> Self {
150 Self {
151 inner,
152 memory_map: vec.into(),
153 modified_range: None,
154 }
155 }
156
157 pub fn write(&mut self, data: &[u8], offset: usize) {
161 self.memory_map.as_slice_memory_order_mut().unwrap()[offset..(offset + data.len())]
162 .copy_from_slice(data);
163 self.set_modified_range(offset, data.len());
164 }
165
166 pub fn modified_range(&self) -> Option<ModifiedRange<usize>> {
167 self.modified_range.map(|range| ModifiedRange {
168 offset: range.offset[0],
169 size: range.size[0],
170 })
171 }
172
173 fn set_modified_range(&mut self, offset: usize, modified_size: usize) {
176 let range = self.modified_range.get_or_insert(ModifiedRange {
177 offset: ndarray::Ix1(0),
178 size: ndarray::Ix1(0),
179 });
180 let old_range_end = range.offset + range.size;
184 range.offset = ndarray::Ix1(std::cmp::min(range.offset[0], offset));
185
186 let new_range_end = std::cmp::max(offset + modified_size, old_range_end[0]);
187 range.size = ndarray::Ix1(new_range_end - range.offset[0]);
188 }
189}
190
191pub type MappedBuffer = Mapped<Buffer, ndarray::Ix1>;
192impl MappedBuffer {
193 pub fn with_buffer(
194 ctx: &mut super::Context,
195 size: usize,
196 buffer_type: BufferType,
197 usage: Usage,
198 ) -> Result<Self, super::GraphicsError> {
199 let inner = Buffer::new(ctx, size, buffer_type, usage)?;
200 let memory_map = ndarray::Array1::from(vec![0u8; inner.size()]);
201 Ok(Self {
202 inner,
203 memory_map,
204 modified_range: None,
205 })
206 }
207
208 pub fn unmap(&mut self, ctx: &mut super::Context) {
209 ctx.unmap_buffer(self);
210 self.modified_range = None;
211 }
212}
213
214