ascending_graphics/systems/
buffer.rs

1use crate::GpuDevice;
2use std::{marker::PhantomData, ops::Range};
3use wgpu::{Queue, util::DeviceExt};
4
5/// BufferStore is Storage used to hold and modify the byte arrays that get sent to the GPU.
6///
7#[derive(Default, Debug)]
8pub struct BufferStore {
9    /// Storage used for Vertex or Indicies.
10    pub store: Vec<u8>,
11    /// Storage used for index's
12    pub indexs: Vec<u8>,
13    /// Boolean used to deturmine if it got changed to tell
14    /// the system if we need to reupload the data to the gpu.
15    pub changed: bool,
16    /// Location Range within GPU this is Stored At
17    /// if this does not match the current location internally we will resend
18    /// the data to the gpu at the new location.
19    pub store_pos: Range<usize>,
20    /// Location Range within GPU this is Stored At
21    /// if this does not match the current location internally we will resend
22    /// the data to the gpu at the new location.
23    pub index_pos: Range<usize>,
24}
25
26impl BufferStore {
27    /// Used to create a [`BufferStore`].
28    ///
29    /// # Arguments
30    /// - store_size: Preset and filled Size of the buffer to avoid reallocating.
31    /// - index_size: Preset and filled Size of the buffer to avoid reallocating.
32    ///
33    pub fn new(store_size: usize, index_size: usize) -> Self {
34        let mut store = Vec::with_capacity(store_size);
35        let mut indexs = Vec::with_capacity(index_size);
36
37        store.resize_with(store_size, || 0);
38        indexs.resize_with(index_size, || 0);
39
40        Self {
41            store,
42            indexs,
43            changed: false,
44            store_pos: Range::default(),
45            index_pos: Range::default(),
46        }
47    }
48}
49
50/// Pass of Data from a Vertex or Static Vertex used to Set the
51/// renderers Vertex and Index buffer Objects.
52///
53pub struct BufferPass<'a> {
54    pub vertex_buffer: &'a wgpu::Buffer,
55    pub index_buffer: &'a wgpu::Buffer,
56}
57
58/// Trait used to create Passing [`BufferPass`] from their Structs.
59pub trait AsBufferPass<'a> {
60    /// Creates a [`BufferPass`] from the Holding Object.
61    fn as_buffer_pass(&'a self) -> BufferPass<'a>;
62}
63
64/// Hold for the Layouts in memory version of Vertex's, indices or Index's.
65/// Data of Each object within the same Layout.
66///
67#[derive(Default)]
68pub struct BufferData {
69    pub vertexs: Vec<u8>,
70    pub indexs: Vec<u8>,
71}
72
73/// GPU Buffer Management Struct. Used to keep track of Counts, Length and The Buffer in the GPU.
74///
75#[derive(Debug)]
76pub struct Buffer<K: BufferLayout> {
77    pub buffer: wgpu::Buffer,
78    pub count: usize,
79    pub len: usize,
80    pub max: usize,
81    phantom_data: PhantomData<K>,
82}
83
84impl<K: BufferLayout> Buffer<K> {
85    /// Used to create a [`Buffer`].
86    ///
87    /// # Arguments
88    /// - contents: The contents to Create the Buffer with.
89    /// - usage: wgpu usage flags [`wgpu::BufferUsages`]
90    /// - label: Label to be seen in GPU debugging.
91    ///
92    pub fn new(
93        gpu_device: &GpuDevice,
94        contents: &[u8],
95        usage: wgpu::BufferUsages,
96        label: Option<&str>,
97    ) -> Self {
98        Self {
99            buffer: gpu_device.device().create_buffer_init(
100                &wgpu::util::BufferInitDescriptor {
101                    label,
102                    contents,
103                    usage,
104                },
105            ),
106            count: 0,
107            len: 0,
108            max: contents.len(),
109            phantom_data: PhantomData,
110        }
111    }
112
113    /// Writes Data into the Buffer from its Position.
114    ///
115    /// # Panics
116    /// - This method fails if data overruns the size of buffer starting at pos.
117    ///
118    /// # Arguments
119    /// - data: the contents to write to the Buffer.
120    /// - pos: Position to write to the buffer from.
121    ///
122    pub fn write(&self, queue: &Queue, data: &[u8], pos: u64) {
123        if !data.is_empty() {
124            queue.write_buffer(&self.buffer, pos, data);
125        }
126    }
127
128    /// If the buffer len is empty.
129    ///
130    pub fn is_empty(&self) -> bool {
131        self.len == 0
132    }
133
134    /// Returns a [`wgpu::BufferSlice`] of the buffer to hand off to the GPU.
135    ///
136    pub fn buffer_slice(&self, range: Range<u64>) -> wgpu::BufferSlice<'_> {
137        self.buffer.slice(range)
138    }
139}
140
141pub trait BufferLayout {
142    ///WGPU's Shader Attributes
143    fn attributes() -> Vec<wgpu::VertexAttribute>;
144
145    ///Default Buffer set to a large size.
146    fn default_buffer() -> BufferData;
147
148    ///The size in bytes the vertex is
149    fn stride() -> usize;
150
151    /// Creates a Buffer at a capacity
152    /// Capacity is a count of objects.
153    fn with_capacity(
154        vertex_capacity: usize,
155        index_capacity: usize,
156    ) -> BufferData;
157}