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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
use crate::GpuDevice;
use std::{marker::PhantomData, ops::Range};
use wgpu::util::DeviceExt;

/// BufferStore is Storage used to hold and modify the byte arrays that get sent to the GPU.
///
#[derive(Default)]
pub struct BufferStore {
    /// Storage used for Vertex or Indicies.
    pub store: Vec<u8>,
    /// Storage used for index's
    pub indexs: Vec<u8>,
    /// Boolean used to deturmine if it got changed to tell
    /// the system if we need to reupload the data to the gpu.
    pub changed: bool,
    /// Location Range within GPU this is Stored At
    /// if this does not match the current location internally we will resend
    /// the data to the gpu at the new location.
    pub store_pos: Range<usize>,
    /// Location Range within GPU this is Stored At
    /// if this does not match the current location internally we will resend
    /// the data to the gpu at the new location.
    pub index_pos: Range<usize>,
}

impl BufferStore {
    /// Used to create a [`BufferStore`].
    ///
    /// # Arguments
    /// - store_size: Preset and filled Size of the buffer to avoid reallocating.
    /// - index_size: Preset and filled Size of the buffer to avoid reallocating.
    ///
    pub fn new(store_size: usize, index_size: usize) -> Self {
        let mut store = Vec::with_capacity(store_size);
        let mut indexs = Vec::with_capacity(index_size);

        store.resize_with(store_size, || 0);
        indexs.resize_with(index_size, || 0);

        Self {
            store,
            indexs,
            changed: false,
            store_pos: Range::default(),
            index_pos: Range::default(),
        }
    }
}

/// Pass of Data from a Vertex or Static Vertex used to Set the
/// renderers Vertex and Index buffer Objects.
///
pub struct BufferPass<'a> {
    pub vertex_buffer: &'a wgpu::Buffer,
    pub index_buffer: &'a wgpu::Buffer,
}

/// Trait used to create Passing [`BufferPass`] from their Structs.
pub trait AsBufferPass<'a> {
    /// Creates a [`BufferPass`] from the Holding Object.
    fn as_buffer_pass(&'a self) -> BufferPass<'a>;
}

/// Hold for the Layouts in memory version of Vertex's, indices or Index's.
/// Data of Each object within the same Layout.
///
#[derive(Default)]
pub struct BufferData {
    pub vertexs: Vec<u8>,
    pub indexs: Vec<u8>,
}

/// GPU Buffer Management Struct. Used to keep track of Counts, Length and The Buffer in the GPU.
///
pub struct Buffer<K: BufferLayout> {
    pub buffer: wgpu::Buffer,
    pub count: usize,
    pub len: usize,
    pub max: usize,
    phantom_data: PhantomData<K>,
}

impl<K: BufferLayout> Buffer<K> {
    /// Used to create a [`Buffer`].
    ///
    /// # Arguments
    /// - contents: The contents to Create the Buffer with.
    /// - usage: wgpu usage flags [`wgpu::BufferUsages`]
    /// - label: Label to be seen in GPU debugging.
    ///
    pub fn new(
        gpu_device: &GpuDevice,
        contents: &[u8],
        usage: wgpu::BufferUsages,
        label: Option<&str>,
    ) -> Self {
        Self {
            buffer: gpu_device.device().create_buffer_init(
                &wgpu::util::BufferInitDescriptor {
                    label,
                    contents,
                    usage,
                },
            ),
            count: 0,
            len: 0,
            max: contents.len(),
            phantom_data: PhantomData,
        }
    }

    /// Writes Data into the Buffer from its Position.
    ///
    /// # Panics
    /// - This method fails if data overruns the size of buffer starting at pos.
    ///
    /// # Arguments
    /// - data: the contents to write to the Buffer.
    /// - pos: Position to write to the buffer from.
    ///
    pub fn write(&self, device: &GpuDevice, data: &[u8], pos: u64) {
        device.queue.write_buffer(&self.buffer, pos, data);
    }

    /// If the buffer len is empty.
    ///
    pub fn is_empty(&self) -> bool {
        self.len == 0
    }

    /// Returns a [`wgpu::BufferSlice`] of the buffer to hand off to the GPU.
    ///
    pub fn buffer_slice(&self, range: Range<u64>) -> wgpu::BufferSlice {
        self.buffer.slice(range)
    }
}

pub trait BufferLayout {
    ///WGPU's Shader Attributes
    fn attributes() -> Vec<wgpu::VertexAttribute>;

    ///Default Buffer set to a large size.
    fn default_buffer() -> BufferData;

    ///The size in bytes the vertex is
    fn stride() -> usize;

    /// Creates a Buffer at a capacity
    /// Capacity is a count of objects.
    fn with_capacity(
        vertex_capacity: usize,
        index_capacity: usize,
    ) -> BufferData;
}