three_d/core/buffer/
uniform_buffer.rs1use crate::core::*;
2
3pub struct UniformBuffer {
8 context: Context,
9 id: crate::context::Buffer,
10 offsets: Vec<usize>,
11 data: Vec<f32>,
12}
13
14impl UniformBuffer {
15 pub fn new(context: &Context, sizes: &[u32]) -> UniformBuffer {
22 let id = unsafe { context.create_buffer().expect("Failed creating buffer") };
23
24 let mut offsets = Vec::new();
25 let mut length = 0;
26 for size in sizes {
27 offsets.push(length);
28 length += *size as usize;
29 }
30 let buffer = UniformBuffer {
31 context: context.clone(),
32 id,
33 offsets,
34 data: vec![0.0; length],
35 };
36 buffer.send();
37 buffer
38 }
39
40 pub(crate) fn bind(&self, id: u32) {
41 unsafe {
42 self.context
43 .bind_buffer_base(crate::context::UNIFORM_BUFFER, id, Some(self.id))
44 };
45 }
46
47 pub fn update(&mut self, index: u32, data: &[f32]) {
55 if let Some((offset, length)) = self.offset_length(index as usize) {
56 if data.len() != length {
57 panic!(
58 "data for element at index {0} has length {1} but a length of {2} was expected",
59 index,
60 data.len(),
61 length,
62 );
63 }
64 self.data
65 .splice(offset..offset + length, data.iter().cloned());
66 self.send();
67 } else {
68 panic!(
69 "the index {} is outside the expected range [0, {}]",
70 index,
71 self.offsets.len() - 1
72 );
73 }
74 }
76
77 pub fn get(&self, index: u32) -> Option<&[f32]> {
81 self.offset_length(index as usize)
82 .map(|(offset, length)| &self.data[offset..offset + length])
83 }
84
85 fn offset_length(&self, index: usize) -> Option<(usize, usize)> {
86 if index >= self.offsets.len() {
87 None
88 } else {
89 let offset = self.offsets[index];
90 let length = if index + 1 == self.offsets.len() {
91 self.data.len()
92 } else {
93 self.offsets[index + 1]
94 } - offset;
95 Some((offset, length))
96 }
97 }
98
99 fn send(&self) {
100 unsafe {
101 self.context
102 .bind_buffer(crate::context::UNIFORM_BUFFER, Some(self.id));
103 self.context.buffer_data_u8_slice(
104 crate::context::UNIFORM_BUFFER,
105 to_byte_slice(&self.data),
106 crate::context::STATIC_DRAW,
107 );
108 self.context
109 .bind_buffer(crate::context::UNIFORM_BUFFER, None);
110 }
111 }
112}
113
114impl Drop for UniformBuffer {
115 fn drop(&mut self) {
116 unsafe {
117 self.context.delete_buffer(self.id);
118 }
119 }
120}