1pub enum BufferSource<'a> {
2 Data(&'a [u8]),
3 Buffer(wgpu::Buffer),
4}
5
6impl<'a> From<&'a [u8]> for BufferSource<'a> {
7 fn from(data: &'a [u8]) -> Self {
8 BufferSource::Data(data)
9 }
10}
11
12impl<'a> From<wgpu::Buffer> for BufferSource<'a> {
13 fn from(buffer: wgpu::Buffer) -> Self {
14 BufferSource::Buffer(buffer)
15 }
16}
17
18pub enum BindingResource<'a> {
19 UniformBuffer(BufferSource<'a>),
20 StorageBuffer(BufferSource<'a>),
21 TextureView(&'a wgpu::TextureView),
22 Sampler(&'a wgpu::Sampler),
23}
24
25pub fn build_buffer(device: &wgpu::Device, contents: &[u8], usage: wgpu::BufferUsages) -> wgpu::Buffer {
26 use wgpu::util::DeviceExt;
27 device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
28 label: None,
29 contents,
30 usage,
31 })
32}
33
34pub fn resolve_buffer(device: &wgpu::Device, source: BufferSource<'_>, usage: wgpu::BufferUsages) -> wgpu::Buffer {
35 match source {
36 BufferSource::Data(data) => build_buffer(device, data, usage),
37 BufferSource::Buffer(buffer) => buffer,
38 }
39}
40
41pub fn resolve_uniform_buffer(device: &wgpu::Device, source: BufferSource<'_>) -> wgpu::Buffer {
42 resolve_buffer(device, source, wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST)
43}
44
45pub fn resolve_storage_buffer(device: &wgpu::Device, source: BufferSource<'_>) -> wgpu::Buffer {
46 resolve_buffer(device, source, wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST)
47}
48
49pub fn build_uniform_bind_group<'a>(
50 device: &wgpu::Device,
51 layout: &wgpu::BindGroupLayout,
52 source: impl Into<BufferSource<'a>>,
53) -> (wgpu::Buffer, wgpu::BindGroup) {
54 let (mut buffers, bind_group) = build_bind_group(device, layout, vec![BindingResource::UniformBuffer(source.into())]);
55 (buffers.remove(0), bind_group)
56}
57
58pub fn update_uniform_buffer(queue: &wgpu::Queue, buffer: &wgpu::Buffer, data: &[u8]) {
59 queue.write_buffer(buffer, 0, data);
60}
61
62pub fn build_bind_group<'a>(
66 device: &wgpu::Device,
67 layout: &wgpu::BindGroupLayout,
68 resources: Vec<BindingResource<'a>>,
69) -> (Vec<wgpu::Buffer>, wgpu::BindGroup) {
70 enum Resolved<'a> {
71 Buffer(wgpu::Buffer),
72 TextureView(&'a wgpu::TextureView),
73 Sampler(&'a wgpu::Sampler),
74 }
75
76 let resolved: Vec<Resolved> = resources
77 .into_iter()
78 .map(|r| match r {
79 BindingResource::UniformBuffer(src) => Resolved::Buffer(resolve_uniform_buffer(device, src)),
80 BindingResource::StorageBuffer(src) => Resolved::Buffer(resolve_storage_buffer(device, src)),
81 BindingResource::TextureView(view) => Resolved::TextureView(view),
82 BindingResource::Sampler(sampler) => Resolved::Sampler(sampler),
83 })
84 .collect();
85
86 let bind_group = {
87 let entries: Vec<wgpu::BindGroupEntry> = resolved
88 .iter()
89 .enumerate()
90 .map(|(i, r)| wgpu::BindGroupEntry {
91 binding: i as u32,
92 resource: match r {
93 Resolved::Buffer(buf) => buf.as_entire_binding(),
94 Resolved::TextureView(view) => wgpu::BindingResource::TextureView(view),
95 Resolved::Sampler(sampler) => wgpu::BindingResource::Sampler(sampler),
96 },
97 })
98 .collect();
99
100 device.create_bind_group(&wgpu::BindGroupDescriptor {
101 label: None,
102 layout,
103 entries: &entries,
104 })
105 };
106
107 let buffers = resolved
108 .into_iter()
109 .filter_map(|r| match r {
110 Resolved::Buffer(buf) => Some(buf),
111 _ => None,
112 })
113 .collect();
114
115 (buffers, bind_group)
116}