agpu/graphics/buffer/
builder.rs1use bytemuck::Pod;
2use wgpu::util::DeviceExt;
3
4use crate::{Buffer, Gpu};
5
6pub enum BufferInitContent<'a> {
7 Data(&'a [u8]),
9 Size(u64),
11}
12
13pub struct BufferBuilder<'a> {
14 pub gpu: Gpu,
15 pub label: Option<&'a str>,
16 pub usage: wgpu::BufferUsages,
17}
18impl<'a> BufferBuilder<'a> {
19 #[must_use]
20 pub const fn new(gpu: Gpu, label: &'a str) -> Self {
21 BufferBuilder {
22 gpu,
23 label: Some(label),
24 usage: wgpu::BufferUsages::empty(),
25 }
26 }
27
28 pub fn with_label(mut self, label: &'a str) -> Self {
30 self.label = Some(label);
31 self
32 }
33
34 pub fn as_index_buffer(mut self) -> Self {
36 self.usage |= wgpu::BufferUsages::INDEX;
37 self
38 }
39
40 pub fn as_vertex_buffer(mut self) -> Self {
42 self.usage |= wgpu::BufferUsages::VERTEX;
43 self
44 }
45
46 pub fn as_uniform_buffer(mut self) -> Self {
48 self.usage |= wgpu::BufferUsages::UNIFORM;
49 self
50 }
51
52 pub fn as_storage_buffer(mut self) -> Self {
54 self.usage |= wgpu::BufferUsages::STORAGE;
55 self
56 }
57
58 pub fn as_indirect_buffer(mut self) -> Self {
60 self.usage |= wgpu::BufferUsages::INDIRECT;
61 self
62 }
63
64 pub fn allow_map_read(mut self) -> Self {
66 self.usage |= wgpu::BufferUsages::MAP_READ;
67 self
68 }
69
70 pub fn allow_map_write(mut self) -> Self {
72 self.usage |= wgpu::BufferUsages::MAP_WRITE;
73 self
74 }
75
76 pub fn allow_copy_to(mut self) -> Self {
78 self.usage |= wgpu::BufferUsages::COPY_DST;
79 self
80 }
81
82 pub fn allow_copy_from(mut self) -> Self {
84 self.usage |= wgpu::BufferUsages::COPY_SRC;
85 self
86 }
87
88 pub fn allow_copy(self) -> Self {
89 self.allow_copy_to().allow_copy_from()
90 }
91
92 pub fn with_usage(mut self, usage: wgpu::BufferUsages) -> Self {
95 self.usage = usage;
96 self
97 }
98 pub fn add_usage(mut self, usage: wgpu::BufferUsages) -> Self {
101 self.usage |= usage;
102 self
103 }
104 pub fn rm_usage(mut self, usage: wgpu::BufferUsages) -> Self {
107 self.usage &= !usage;
108 self
109 }
110
111 fn create_impl(&self, init: BufferInitContent) -> (wgpu::Buffer, u64) {
113 match init {
114 BufferInitContent::Data(data) => (
115 self.gpu
116 .device
117 .create_buffer_init(&wgpu::util::BufferInitDescriptor {
118 label: self.label,
119 usage: self.usage,
120 contents: data,
121 }),
122 data.len() as u64,
123 ),
124 BufferInitContent::Size(size) => (
125 self.gpu.device.create_buffer(&wgpu::BufferDescriptor {
126 label: self.label,
127 size,
128 usage: self.usage,
129 mapped_at_creation: false,
130 }),
131 size,
132 ),
133 }
134 }
135
136 #[must_use]
138 pub fn create<T>(&self, contents: &[T]) -> Buffer
139 where
140 T: Pod,
141 {
142 let (inner, size) =
143 self.create_impl(BufferInitContent::Data(bytemuck::cast_slice(contents)));
144
145 Buffer {
146 inner,
147 gpu: self.gpu.clone(),
148 size,
149 label: self.label.map(|a| a.to_string()).unwrap_or_default(),
150 usages: self.usage,
151 }
152 }
153
154 #[must_use]
156 pub fn create_uninit(&self, size: u64) -> Buffer {
157 let (inner, size) = self.create_impl(BufferInitContent::Size(size));
158
159 Buffer {
160 inner,
161 gpu: self.gpu.clone(),
162 size,
163 label: self.label.map(|a| a.to_string()).unwrap_or_default(),
164 usages: self.usage,
165 }
166 }
167
168 pub fn create_empty<T>(&self, count: usize) -> Buffer
169 where
170 T: Sized,
171 {
172 self.create_uninit((count * std::mem::size_of::<T>()) as u64)
173 }
174}