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
//! Static GPU typed arrays.
//!
//! A GPU buffer is a typed continuous region of data. It has a size and can hold several elements.
use core::marker::PhantomData;
use core::mem;
use std::vec::Vec;
/// Implement this trait to provide buffers.
pub trait HasBuffer {
/// A type representing minimal information to operate on a buffer. For instance, a size, a
/// pointer, a method to retrieve data, a handle, whatever.
type ABuffer;
/// Create a new buffer with a given size.
fn new(size: usize) -> Self::ABuffer;
/// Destroy a buffer.
fn free(&mut Self::ABuffer);
/// Write values into the buffer.
///
/// # Warnings
///
/// Those warnings are just **hints**. The behavior for each warning is specific and should be
/// accounted.
///
/// `Err(BufferError::TooManyValues)` if you provide more values than the buffer’s size. In that
/// case, the extra items are just ignored and all others are written; that is, the `values`
/// argument is considered having the same size as `buffer`.
///
/// `Err(BufferError::TooFewValues)` if you provide less values than the buffer’s size. In that
/// case, all `values` are written and the missing ones remain the same in `buffer`.
fn write_whole<T>(buffer: &Self::ABuffer, values: &[T]) -> Result<(),BufferError>;
/// Write a single value in the buffer at a given offset.
///
/// # Failures
///
/// `Err(BufferError::Overflow)` if you provide an offset that doesn’t lie in the allocated GPU
/// region.
fn write<T>(buffer: &Self::ABuffer, offset: usize, x: T) -> Result<(), BufferError> where T: Copy;
/// Read all values from the buffer.
fn read_whole<T>(buffer: &Self::ABuffer, nb: usize) -> Vec<T> where T: Copy;
/// Read a single value from the buffer at a given offset.
///
/// # Failures
///
/// `None` if you provide an offset that doesn’t lie in the allocated GPU region.
fn read<T>(buffer: &Self::ABuffer, offset: usize) -> Option<T> where T: Copy;
}
/// Buffer errors.
#[derive(Debug)]
pub enum BufferError {
Overflow,
TooFewValues,
TooManyValues
}
/// A `Buffer` is a GPU region you can picture as an array. It has a static size and cannot be
/// resized. The size is expressed in number of elements lying in the buffer, not in bytes.
#[derive(Debug)]
pub struct Buffer<C, A, T> where C: HasBuffer {
pub repr: C::ABuffer,
pub size: usize, // FIXME: should be compile-time, not runtime
_a: PhantomData<A>,
_t: PhantomData<T>
}
impl<C, A, T> Buffer<C, A, T> where C: HasBuffer {
/// Create a new `Buffer` with a given number of elements.
pub fn new(_: A, size: usize) -> Buffer<C, A, T> {
let buffer = C::new(size * mem::size_of::<T>());
Buffer { repr: buffer, size: size, _a: PhantomData, _t: PhantomData }
}
/// Retrieve an element from the `Buffer`.
///
/// Checks boundaries.
pub fn get(&self, i: u32) -> Option<T> where T: Copy {
C::read(&self.repr, i as usize * mem::size_of::<T>())
}
/// Retrieve the whole content of the `Buffer`.
pub fn whole(&self) -> Vec<T> where T: Copy {
C::read_whole(&self.repr, self.size)
}
/// Set a value at a given index in the `Buffer`.
///
/// Checks boundaries.
pub fn set(&mut self, i: u32, x: T) -> Result<(), BufferError> where T: Copy {
C::write(&self.repr, i as usize * mem::size_of::<T>(), x)
}
/// Fill the `Buffer` with a single value.
pub fn clear(&self, x: T) where T: Copy {
let _ = C::write_whole(&self.repr, &vec![x; self.size]);
}
/// Fill the whole buffer with an array.
pub fn fill(&self, values: &[T]) {
let _ = C::write_whole(&self.repr, values);
}
}
impl<C, A, T> Drop for Buffer<C, A, T> where C: HasBuffer {
fn drop(&mut self) {
C::free(&mut self.repr)
}
}