Skip to main content

gpu/data/
buffer.rs

1use crate::prelude::*;
2use crate::{Context, GLContext};
3
4type BufferResource = <glow::Context as HasContext>::Buffer;
5
6use super::as_u8_mut_slice;
7use super::as_u8_slice;
8
9/// A `Buffer` representation.
10pub struct Buffer {
11    gl       : GLContext,
12    resource : BufferResource
13}
14
15impl Buffer {
16    fn new(context:&Context) -> Self {
17        let gl = context.gl_context();
18        let resource = unsafe {
19            gl.create_buffer().expect("Couldn't create Buffer")
20        };
21        Self { gl, resource }
22    }
23
24    /// Gets the `BufferResource`.
25    pub fn resource(&self) -> BufferResource {
26        self.resource
27    }
28
29    /// Creates a new `Buffer` from a slice.
30    pub fn from_data<T>(context:&Context, data: &[T]) -> Self {
31        let mut buffer = Buffer::new(context);
32        buffer.set_data(data);
33        buffer
34    }
35
36    /// Allocates a new `Buffer` with `n_bytes`.
37    pub fn allocate(context:&Context, n_bytes:usize) -> Self {
38        let mut buffer = Buffer::new(context);
39        if n_bytes > 0 { buffer.reallocate(n_bytes); }
40        buffer
41    }
42
43    pub(crate) fn bind(&self) {
44        let resource = self.resource();
45        let resource = if resource == Default::default() { None } else { Some(resource) };
46        unsafe {
47            self.gl.bind_buffer(glow::ARRAY_BUFFER, resource);
48        }
49    }
50
51    /// Gets the size in bytes.
52    pub fn size(&self) -> usize {
53        self.bind();
54        unsafe {
55            self.gl.get_buffer_parameter_i32(glow::ARRAY_BUFFER, glow::BUFFER_SIZE) as usize
56        }
57    }
58
59    /// Sets the data on the GPU side.
60    pub fn set_data<T>(&mut self, data: &[T]) {
61        self.bind();
62        unsafe {
63            let slice = as_u8_slice(data);
64            self.gl.buffer_data_u8_slice(glow::ARRAY_BUFFER, slice, glow::STATIC_DRAW);
65        }
66    }
67
68    /// Gets the data on the GPU side.
69    pub fn data<T>(&self) -> Vec<T> {
70        let size = self.size();
71        let capacity = size / std::mem::size_of::<T>();
72        let mut data : Vec<T> = Vec::with_capacity(capacity);
73        self.bind();
74        unsafe {
75            data.set_len(capacity);
76            let offset = 0;
77            let data   = as_u8_mut_slice(data.as_mut());
78            self.gl.get_buffer_sub_data(glow::ARRAY_BUFFER, offset, data);
79        }
80        data
81    }
82
83    /// Reallocates the memory with `size`.
84    pub fn reallocate(&mut self, size: usize) {
85        self.bind();
86        unsafe {
87            self.gl.buffer_data_size(glow::ARRAY_BUFFER, size as i32, glow::STATIC_DRAW);
88        }
89    }
90}
91
92impl Drop for Buffer {
93    fn drop(&mut self) {
94        unsafe {
95            self.gl.delete_buffer(self.resource());
96        }
97    }
98}