wgpu_3dgs_core/buffer/
mod.rs1mod gaussian;
2mod gaussian_transform;
3mod model_transform;
4
5pub use gaussian::*;
6pub use gaussian_transform::*;
7pub use model_transform::*;
8
9use crate::{DownloadBufferError, FixedSizeBufferWrapperError};
10
11pub trait BufferWrapper: Into<wgpu::Buffer> {
13 const DEFAULT_USAGES: wgpu::BufferUsages = wgpu::BufferUsages::from_bits_retain(
15 wgpu::BufferUsages::UNIFORM.bits() | wgpu::BufferUsages::COPY_DST.bits(),
16 );
17
18 fn buffer(&self) -> &wgpu::Buffer;
20
21 fn download<T: bytemuck::NoUninit + bytemuck::AnyBitPattern>(
23 &self,
24 device: &wgpu::Device,
25 queue: &wgpu::Queue,
26 ) -> impl Future<Output = Result<Vec<T>, DownloadBufferError>> + Send
27 where
28 Self: Send + Sync,
29 {
30 async {
31 let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
32 label: Some("Buffer Wrapper Download Encoder"),
33 });
34 let download = self.prepare_download(device, &mut encoder);
35 queue.submit(Some(encoder.finish()));
36
37 Self::map_download(&download, device).await
38 }
39 }
40
41 fn prepare_download(
46 &self,
47 device: &wgpu::Device,
48 encoder: &mut wgpu::CommandEncoder,
49 ) -> wgpu::Buffer {
50 let download = device.create_buffer(&wgpu::BufferDescriptor {
51 label: Some("Buffer Wrapper Prepare Download Buffer"),
52 size: self.buffer().size(),
53 usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::MAP_READ,
54 mapped_at_creation: false,
55 });
56
57 encoder.copy_buffer_to_buffer(self.buffer(), 0, &download, 0, download.size());
58
59 download
60 }
61
62 fn map_download<T: bytemuck::NoUninit + bytemuck::AnyBitPattern>(
69 download: &wgpu::Buffer,
70 device: &wgpu::Device,
71 ) -> impl Future<Output = Result<Vec<T>, DownloadBufferError>> + Send {
72 Self::map_download_with_poll_type(download, device, wgpu::PollType::wait_indefinitely())
73 }
74
75 fn map_download_with_poll_type<T: bytemuck::NoUninit + bytemuck::AnyBitPattern>(
79 download: &wgpu::Buffer,
80 device: &wgpu::Device,
81 poll_type: wgpu::PollType,
82 ) -> impl Future<Output = Result<Vec<T>, DownloadBufferError>> + Send {
83 async {
84 let (tx, rx) = oneshot::channel();
85 let buffer_slice = download.slice(..);
86 buffer_slice.map_async(wgpu::MapMode::Read, move |result| {
87 if let Err(e) = tx.send(result) {
88 log::error!("Error occurred while sending buffer download data: {e:?}");
89 }
90 });
91 device.poll(poll_type)?;
92 rx.await??;
93
94 let edits = bytemuck::allocation::pod_collect_to_vec(&buffer_slice.get_mapped_range());
95 download.unmap();
96
97 Ok(edits)
98 }
99 }
100}
101
102impl BufferWrapper for wgpu::Buffer {
103 fn buffer(&self) -> &wgpu::Buffer {
104 self
105 }
106}
107
108pub trait FixedSizeBufferWrapper: BufferWrapper + TryFrom<wgpu::Buffer> {
110 type Pod;
112
113 fn pod_size() -> wgpu::BufferAddress {
115 std::mem::size_of::<Self::Pod>() as wgpu::BufferAddress
116 }
117
118 fn verify_buffer_size(buffer: &wgpu::Buffer) -> Result<(), FixedSizeBufferWrapperError> {
122 let expected_size = Self::pod_size();
123 let buffer_size = buffer.size();
124 if buffer_size != expected_size {
125 return Err(FixedSizeBufferWrapperError::BufferSizeMismatched {
126 buffer_size,
127 expected_size,
128 });
129 }
130 Ok(())
131 }
132
133 fn download_single(
135 &self,
136 device: &wgpu::Device,
137 queue: &wgpu::Queue,
138 ) -> impl Future<Output = Result<Self::Pod, DownloadBufferError>> + Send
139 where
140 Self: Send + Sync,
141 Self::Pod: bytemuck::NoUninit + bytemuck::AnyBitPattern,
142 {
143 async move {
144 let vec = self.download::<Self::Pod>(device, queue).await?;
145 Ok(vec.into_iter().next().expect("downloaded single element"))
146 }
147 }
148}