1use bytemuck::bytes_of;
2use wgpu::{Buffer, BufferUsages, Device, Queue};
3
4#[repr(C)]
5#[derive(Clone, Copy)]
6struct IndexedArgs {
7 index_count: u32,
8 instance_count: u32,
9 first_index: u32,
10 base_vertex: i32,
11 first_instance: u32,
12}
13
14pub struct IndexedCommands {
15 buffer: Buffer,
16 count: u32,
17 stride: u64,
18}
19
20impl IndexedCommands {
21 pub fn new(device: &Device, label: &'static str, count: usize, regions: usize) -> Self {
22 assert!(
23 count > 0,
24 "an indirect draw table holds at least one command"
25 );
26 assert!(regions > 0, "an indirect draw table holds a region");
27 let stride = (count * size_of::<IndexedArgs>()) as u64;
28 let buffer = device.create_buffer(&wgpu::BufferDescriptor {
29 label: Some(label),
30 size: stride * regions as u64,
31 usage: BufferUsages::INDIRECT | BufferUsages::STORAGE | BufferUsages::COPY_DST,
32 mapped_at_creation: false,
33 });
34 Self {
35 buffer,
36 count: count as u32,
37 stride,
38 }
39 }
40
41 pub fn buffer(&self) -> &Buffer {
42 &self.buffer
43 }
44
45 pub fn count(&self) -> u32 {
46 self.count
47 }
48
49 pub fn offset(&self, region: usize) -> u64 {
50 self.stride * region as u64
51 }
52}
53
54pub struct InstanceCommands {
55 buffer: Buffer,
56}
57
58impl InstanceCommands {
59 pub fn new(device: &Device, label: &'static str) -> Self {
60 let buffer = device.create_buffer(&wgpu::BufferDescriptor {
61 label: Some(label),
62 size: size_of::<[u32; 4]>() as u64,
63 usage: BufferUsages::INDIRECT | BufferUsages::STORAGE | BufferUsages::COPY_DST,
64 mapped_at_creation: false,
65 });
66 Self { buffer }
67 }
68
69 pub fn reset(&self, queue: &Queue, vertex_count: u32) {
70 queue.write_buffer(&self.buffer, 0, bytes_of(&[vertex_count, 0, 0, 0]));
71 }
72
73 pub fn buffer(&self) -> &Buffer {
74 &self.buffer
75 }
76}