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
mod belt;
mod device;
mod encoder;
use std::{
borrow::Cow,
future::Future,
mem::{align_of, size_of},
ptr::copy_nonoverlapping,
};
pub use belt::StagingBelt;
pub use device::{BufferInitDescriptor, DeviceExt};
pub use encoder::RenderEncoder;
pub fn make_spirv(data: &[u8]) -> super::ShaderSource {
const MAGIC_NUMBER: u32 = 0x0723_0203;
assert_eq!(
data.len() % size_of::<u32>(),
0,
"data size is not a multiple of 4"
);
let words = if data.as_ptr().align_offset(align_of::<u32>()) == 0 {
let (pre, words, post) = unsafe { data.align_to::<u32>() };
debug_assert!(pre.is_empty());
debug_assert!(post.is_empty());
Cow::from(words)
} else {
let mut words = vec![0u32; data.len() / size_of::<u32>()];
unsafe {
copy_nonoverlapping(data.as_ptr(), words.as_mut_ptr() as *mut u8, data.len());
}
Cow::from(words)
};
assert_eq!(
words[0], MAGIC_NUMBER,
"wrong magic word {:x}. Make sure you are using a binary SPIRV file.",
words[0]
);
super::ShaderSource::SpirV(words)
}
pub struct DownloadBuffer(super::Buffer, super::BufferMappedRange);
impl DownloadBuffer {
pub fn read_buffer(
device: &super::Device,
queue: &super::Queue,
buffer: &super::BufferSlice,
) -> impl Future<Output = Result<Self, super::BufferAsyncError>> + Send {
let size = match buffer.size {
Some(size) => size.into(),
None => buffer.buffer.map_context.lock().total_size - buffer.offset,
};
let download = device.create_buffer(&super::BufferDescriptor {
size,
usage: super::BufferUsage::COPY_DST | super::BufferUsage::MAP_READ,
mapped_at_creation: false,
label: None,
});
let mut encoder =
device.create_command_encoder(&super::CommandEncoderDescriptor { label: None });
encoder.copy_buffer_to_buffer(buffer.buffer, buffer.offset, &download, 0, size);
let command_buffer: super::CommandBuffer = encoder.finish();
queue.submit(Some(command_buffer));
let fut = download.slice(..).map_async(super::MapMode::Read);
async move {
fut.await?;
let mapped_range =
super::Context::buffer_get_mapped_range(&*download.context, &download.id, 0..size);
Ok(Self(download, mapped_range))
}
}
}
impl std::ops::Deref for DownloadBuffer {
type Target = [u8];
fn deref(&self) -> &[u8] {
super::BufferMappedRangeSlice::slice(&self.1)
}
}