1mod belt;
7mod device;
8mod encoder;
9mod indirect;
10mod init;
11
12use std::sync::Arc;
13use std::{
14 borrow::Cow,
15 mem::{align_of, size_of},
16 ptr::copy_nonoverlapping,
17};
18
19pub use belt::StagingBelt;
20pub use device::{BufferInitDescriptor, DeviceExt};
21pub use encoder::RenderEncoder;
22pub use indirect::*;
23pub use init::*;
24pub use wgt::math::*;
25
26#[cfg(feature = "spirv")]
37pub fn make_spirv(data: &[u8]) -> super::ShaderSource {
38 super::ShaderSource::SpirV(make_spirv_raw(data))
39}
40
41pub fn make_spirv_raw(data: &[u8]) -> Cow<[u32]> {
46 const MAGIC_NUMBER: u32 = 0x0723_0203;
47 assert_eq!(
48 data.len() % size_of::<u32>(),
49 0,
50 "data size is not a multiple of 4"
51 );
52 assert_ne!(data.len(), 0, "data size must be larger than zero");
53
54 let mut words = if data.as_ptr().align_offset(align_of::<u32>()) == 0 {
57 let (pre, words, post) = unsafe { data.align_to::<u32>() };
58 debug_assert!(pre.is_empty());
59 debug_assert!(post.is_empty());
60 Cow::from(words)
61 } else {
62 let mut words = vec![0u32; data.len() / size_of::<u32>()];
63 unsafe {
64 copy_nonoverlapping(data.as_ptr(), words.as_mut_ptr() as *mut u8, data.len());
65 }
66 Cow::from(words)
67 };
68
69 if words[0] == MAGIC_NUMBER.swap_bytes() {
72 for word in Cow::to_mut(&mut words) {
73 *word = word.swap_bytes();
74 }
75 }
76
77 assert_eq!(
78 words[0], MAGIC_NUMBER,
79 "wrong magic word {:x}. Make sure you are using a binary SPIRV file.",
80 words[0]
81 );
82
83 words
84}
85
86pub struct DownloadBuffer(
88 Arc<super::Buffer>,
89 Box<dyn crate::context::BufferMappedRange>,
90);
91
92impl DownloadBuffer {
93 pub fn read_buffer(
95 device: &super::Device,
96 queue: &super::Queue,
97 buffer: &super::BufferSlice,
98 callback: impl FnOnce(Result<Self, super::BufferAsyncError>) + Send + 'static,
99 ) {
100 let size = match buffer.size {
101 Some(size) => size.into(),
102 None => buffer.buffer.map_context.lock().total_size - buffer.offset,
103 };
104
105 let download = Arc::new(device.create_buffer(&super::BufferDescriptor {
106 size,
107 usage: super::BufferUsages::COPY_DST | super::BufferUsages::MAP_READ,
108 mapped_at_creation: false,
109 label: None,
110 }));
111
112 let mut encoder =
113 device.create_command_encoder(&super::CommandEncoderDescriptor { label: None });
114 encoder.copy_buffer_to_buffer(buffer.buffer, buffer.offset, &download, 0, size);
115 let command_buffer: super::CommandBuffer = encoder.finish();
116 queue.submit(Some(command_buffer));
117
118 download
119 .clone()
120 .slice(..)
121 .map_async(super::MapMode::Read, move |result| {
122 if let Err(e) = result {
123 callback(Err(e));
124 return;
125 }
126
127 let mapped_range = super::DynContext::buffer_get_mapped_range(
128 &*download.context,
129 &download.id,
130 download.data.as_ref(),
131 0..size,
132 );
133 callback(Ok(Self(download, mapped_range)));
134 });
135 }
136}
137
138impl std::ops::Deref for DownloadBuffer {
139 type Target = [u8];
140 fn deref(&self) -> &[u8] {
141 self.1.slice()
142 }
143}