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
pub mod buffer;
pub use buffer::*;
pub mod pool;
pub use pool::*;
pub type OwnedLabel = Option<String>;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct BufferInitDescriptor<'a> {
pub label: wgpu::Label<'a>,
pub contents: &'a [u8],
pub size: Option<wgpu::BufferAddress>,
pub usage: wgpu::BufferUsage,
}
pub fn create_buffer_init(
device: &wgpu::Device,
descriptor: &BufferInitDescriptor<'_>,
) -> wgpu::Buffer {
let unpadded_size = {
let contents_size = descriptor.contents.len() as wgpu::BufferAddress;
match descriptor.size {
None => contents_size,
Some(specified_size) => {
assert!(
specified_size >= contents_size,
"specified size must at least be size of contents"
);
specified_size
}
}
};
let align_mask = wgpu::COPY_BUFFER_ALIGNMENT - 1;
let padded_size = ((unpadded_size + align_mask) & !align_mask).max(wgpu::COPY_BUFFER_ALIGNMENT);
let normal_descriptor = wgpu::BufferDescriptor {
label: descriptor.label,
size: padded_size,
usage: descriptor.usage,
mapped_at_creation: true,
};
let buffer = device.create_buffer(&normal_descriptor);
{
let mut slice = buffer.slice(..).get_mapped_range_mut();
slice[0..unpadded_size as usize].copy_from_slice(descriptor.contents);
for i in unpadded_size..padded_size {
slice[i as usize] = 0;
}
}
buffer.unmap();
buffer
}
pub struct SizedBuffer {
pub size: wgpu::BufferAddress,
pub buffer: wgpu::Buffer,
}
impl SizedBuffer {
pub fn new(size: wgpu::BufferAddress, buffer: wgpu::Buffer) -> Self {
Self { size, buffer }
}
}
pub(crate) struct WriteDescriptor<'a> {
pub label: wgpu::Label<'a>,
pub data: &'a [u8],
pub usage: wgpu::BufferUsage,
}
#[inline]
pub(crate) fn write(
device: &wgpu::Device,
queue: &wgpu::Queue,
buffer: SizedBuffer,
descriptor: &WriteDescriptor,
) -> SizedBuffer {
let data_size = descriptor.data.len() as wgpu::BufferAddress;
let enough_space = data_size <= buffer.size;
if enough_space {
queue.write_buffer(&buffer.buffer, 0, descriptor.data);
buffer
} else {
let new = create_buffer_init(
device,
&BufferInitDescriptor {
label: descriptor.label,
contents: descriptor.data,
size: None,
usage: descriptor.usage,
},
);
SizedBuffer::new(data_size, new)
}
}