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