srs2dge_core/buffer/
mod.rs

1use crate::{label, target::Target, Frame};
2use bytemuck::Pod;
3use std::{marker::PhantomData, mem, num::NonZeroU64, ops::RangeBounds};
4use wgpu::{
5    util::{BufferInitDescriptor, DeviceExt},
6    BufferAddress, BufferDescriptor, BufferUsages,
7};
8
9//
10
11pub use index::*;
12pub use indirect::*;
13pub use uniform::*;
14pub use vertex::*;
15
16//
17
18pub mod index;
19pub mod indirect;
20pub mod prelude;
21pub mod uniform;
22pub mod vertex;
23
24//
25
26#[derive(Debug)]
27pub struct Buffer<T, const USAGE: u32> {
28    buffer: wgpu::Buffer,
29    elements: usize,
30    _p: PhantomData<T>,
31}
32
33#[derive(Debug, Clone, Copy)]
34pub struct BufferSlice<'b, T, const USAGE: u32> {
35    slice: wgpu::BufferSlice<'b>,
36    _p: PhantomData<T>,
37}
38
39//
40
41impl<T, const USAGE: u32> Buffer<T, USAGE>
42where
43    T: Pod,
44{
45    pub fn new_with(target: &Target, data: &[T]) -> Self {
46        let buffer = target.device.create_buffer_init(&BufferInitDescriptor {
47            label: label!(),
48            usage: BufferUsages::from_bits_truncate(USAGE),
49            contents: bytemuck::cast_slice(data),
50        });
51
52        Self::with_buffer(buffer, data.len())
53    }
54
55    pub fn new_single(target: &Target, data: T) -> Self {
56        let buffer = target.device.create_buffer_init(&BufferInitDescriptor {
57            label: label!(),
58            usage: BufferUsages::from_bits_truncate(USAGE),
59            contents: bytemuck::cast_slice(&[data]),
60        });
61
62        Self::with_buffer(buffer, 1)
63    }
64
65    pub fn upload(&self, target: &mut Target, frame: &mut Frame, new_data: &[T]) {
66        let mut mapping = frame.write_buffer(
67            &self.buffer,
68            0,
69            NonZeroU64::new(Self::size_of(self.elements) as _).unwrap(),
70            &target.device,
71        );
72
73        let new_data = bytemuck::cast_slice(new_data);
74        mapping[..new_data.len()].copy_from_slice(new_data);
75    }
76}
77
78impl<T, const USAGE: u32> Buffer<T, USAGE>
79where
80    T: Pod,
81{
82    pub fn new(target: &Target, elements: usize) -> Self {
83        let buffer = target.device.create_buffer(&BufferDescriptor {
84            label: label!(),
85            size: Self::size_of(elements) as _,
86            usage: BufferUsages::from_bits_truncate(USAGE),
87            mapped_at_creation: false,
88        });
89
90        Self::with_buffer(buffer, elements)
91    }
92
93    pub fn inner(&self) -> &wgpu::Buffer {
94        &self.buffer
95    }
96
97    pub fn capacity(&self) -> usize {
98        self.elements
99    }
100
101    pub fn slice<S>(&self, range: S) -> BufferSlice<T, USAGE>
102    where
103        S: RangeBounds<BufferAddress>,
104    {
105        BufferSlice {
106            slice: self.buffer.slice(range),
107            _p: PhantomData::default(),
108        }
109    }
110
111    fn with_buffer(buffer: wgpu::Buffer, elements: usize) -> Self {
112        Self {
113            buffer,
114            elements,
115            _p: Default::default(),
116        }
117    }
118
119    fn size_of(elements: usize) -> usize {
120        mem::size_of::<T>() * elements
121    }
122}
123
124impl<'b, T, const USAGE: u32> BufferSlice<'b, T, USAGE> {
125    pub fn inner(&self) -> wgpu::BufferSlice {
126        self.slice
127    }
128}
129
130//
131
132pub trait AsBufferSlice<T, const USAGE: u32> {
133    fn as_slice(&self) -> BufferSlice<T, USAGE>;
134}
135
136//
137
138impl<T, const USAGE: u32> AsBufferSlice<T, USAGE> for Buffer<T, USAGE>
139where
140    T: Pod,
141{
142    fn as_slice(&self) -> BufferSlice<T, USAGE> {
143        self.slice(..)
144    }
145}
146
147impl<'b, T, const USAGE: u32> AsBufferSlice<T, USAGE> for BufferSlice<'b, T, USAGE>
148where
149    T: Pod,
150{
151    fn as_slice(&self) -> Self {
152        *self
153    }
154}