Skip to main content

SelectionBuffer

Struct SelectionBuffer 

Source
pub struct SelectionBuffer(/* private fields */);
Expand description

The selection storage buffer.

This buffer holds the selection bitmask for Gaussians, where each bit represents whether a Gaussian is selected (1) or not (0).

Implementations§

Source§

impl SelectionBuffer

Source

pub fn new(device: &Device, gaussian_count: u32) -> Self

Create a new selection buffer.

Examples found in repository?
examples/filter_selection.rs (line 195)
98async fn main() {
99    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
100
101    let args = Args::parse();
102    let model_path = &args.model;
103    let pos = Vec3::from_slice(&args.pos);
104    let rot = Quat::from_slice(&args.rot);
105    let scale = Vec3::from_slice(&args.scale);
106    let shape = match args.shape {
107        Shape::Sphere => gs::SelectionBundle::<GaussianPod>::create_sphere_bundle,
108        Shape::Box => gs::SelectionBundle::<GaussianPod>::create_box_bundle,
109    };
110    let repeat = args.repeat;
111    let offset = Vec3::from_slice(&args.offset);
112
113    log::debug!("Creating wgpu instance");
114    let instance =
115        wgpu::Instance::new(wgpu::InstanceDescriptor::new_without_display_handle_from_env());
116
117    log::debug!("Requesting adapter");
118    let adapter = instance
119        .request_adapter(&wgpu::RequestAdapterOptions::default())
120        .await
121        .expect("adapter");
122
123    log::debug!("Requesting device");
124    let (device, queue) = adapter
125        .request_device(&wgpu::DeviceDescriptor {
126            label: Some("Device"),
127            required_limits: adapter.limits(),
128            ..Default::default()
129        })
130        .await
131        .expect("device");
132
133    log::debug!("Creating gaussians");
134    let gaussians = [
135        gs::core::GaussiansSource::Ply,
136        gs::core::GaussiansSource::Spz,
137    ]
138    .into_iter()
139    .find_map(|source| gs::core::Gaussians::read_from_file(model_path, source).ok())
140    .expect("gaussians");
141
142    log::debug!("Creating gaussians buffer");
143    let gaussians_buffer = gs::core::GaussiansBuffer::<GaussianPod>::new(&device, &gaussians);
144
145    log::debug!("Creating model transform buffer");
146    let model_transform = gs::core::ModelTransformBuffer::new(&device);
147
148    log::debug!("Creating Gaussian transform buffer");
149    let gaussian_transform = gs::core::GaussianTransformBuffer::new(&device);
150
151    log::debug!("Creating shape selection compute bundle");
152    let shape_selection = shape(&device);
153
154    log::debug!("Creating selection bundle");
155    let selection_bundle = gs::SelectionBundle::<GaussianPod>::new(&device, vec![shape_selection]);
156
157    log::debug!("Creating shape selection buffers");
158    let shape_selection_buffers = (0..repeat)
159        .map(|i| {
160            let offset_pos = pos + offset * i as f32;
161            let buffer = gs::InvTransformBuffer::new(&device);
162            buffer.update_with_scale_rot_pos(&queue, scale, rot, offset_pos);
163            buffer
164        })
165        .collect::<Vec<_>>();
166
167    log::debug!("Creating shape selection bind groups");
168    let shape_selection_bind_groups = shape_selection_buffers
169        .iter()
170        .map(|buffer| {
171            selection_bundle.bundles[0]
172                .create_bind_group(
173                    &device,
174                    // index 0 is the Gaussians buffer, so we use 1,
175                    // see docs of create_sphere_bundle or create_box_bundle
176                    1,
177                    [buffer.buffer().as_entire_binding()],
178                )
179                .expect("bind group")
180        })
181        .collect::<Vec<_>>();
182
183    log::debug!("Creating selection expression");
184    let selection_expr = shape_selection_bind_groups.into_iter().fold(
185        gs::SelectionExpr::Identity,
186        |acc, bind_group| {
187            acc.union(gs::SelectionExpr::selection(
188                0, // the 0 here is the bundle index in the selection bundle
189                vec![bind_group],
190            ))
191        },
192    );
193
194    log::debug!("Creating destination buffer");
195    let dest = gs::SelectionBuffer::new(&device, gaussians_buffer.len() as u32);
196
197    log::info!("Starting selection process");
198    let time = std::time::Instant::now();
199
200    log::debug!("Selecting Gaussians");
201    let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
202        label: Some("Selection Encoder"),
203    });
204
205    selection_bundle.evaluate(
206        &device,
207        &mut encoder,
208        &selection_expr,
209        &dest,
210        &model_transform,
211        &gaussian_transform,
212        &gaussians_buffer,
213    );
214
215    queue.submit(Some(encoder.finish()));
216
217    device
218        .poll(wgpu::PollType::wait_indefinitely())
219        .expect("poll");
220
221    log::info!("Editing process completed in {:?}", time.elapsed());
222
223    log::debug!("Filtering Gaussians");
224    let selected_gaussians = dest
225        .download::<u32>(&device, &queue)
226        .await
227        .expect("selected download")
228        .iter()
229        .flat_map(|group| {
230            std::iter::repeat_n(group, 32)
231                .enumerate()
232                .map(|(i, g)| g & (1 << i) != 0)
233        })
234        .zip(gaussians.iter_gaussian())
235        .filter(|(selected, _)| *selected)
236        .map(|(_, g)| g)
237        .collect::<Vec<_>>();
238
239    let selected_gaussians = match &args.output[args.output.len().saturating_sub(4)..] {
240        ".ply" => gs::core::Gaussians::Ply(gs::core::PlyGaussians::from_iter(
241            selected_gaussians.into_iter(),
242        )),
243        ".spz" => {
244            gs::core::Gaussians::Spz(
245                gs::core::SpzGaussians::from_gaussians_with_options(
246                    selected_gaussians,
247                    &gs::core::SpzGaussiansFromGaussianSliceOptions {
248                        version: 2, // Version 2 is more widely supported as of now
249                        ..Default::default()
250                    },
251                )
252                .expect("SpzGaussians from gaussians"),
253            )
254        }
255        _ => panic!("Unsupported output file extension, expected .ply or .spz"),
256    };
257
258    log::debug!("Writing modified Gaussians to output file");
259    selected_gaussians
260        .write_to_file(&args.output)
261        .expect("write modified Gaussians to output file");
262
263    log::info!("Filtered Gaussians written to {}", args.output);
264}
Source

pub fn new_with_label(device: &Device, label: &str, gaussian_count: u32) -> Self

Create a new selection buffer with additional label.

Trait Implementations§

Source§

impl BufferWrapper for SelectionBuffer

Source§

const DEFAULT_USAGES: BufferUsages

The default usages.
Source§

fn buffer(&self) -> &Buffer

Returns a reference to the buffer data.
Source§

fn download<'life0, 'life1, 'life2, 'async_trait, T>( &'life0 self, device: &'life1 Device, queue: &'life2 Queue, ) -> Pin<Box<dyn Future<Output = Result<Vec<T>, DownloadBufferError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: Send + Sync + 'async_trait, T: 'async_trait + NoUninit + AnyBitPattern,

Download the buffer data into a Vec.
Source§

fn prepare_download( &self, device: &Device, encoder: &mut CommandEncoder, ) -> Buffer

Prepare for downloading the buffer data. Read more
Source§

fn map_download<'life0, 'life1, 'async_trait, T>( download: &'life0 Buffer, device: &'life1 Device, ) -> Pin<Box<dyn Future<Output = Result<Vec<T>, DownloadBufferError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, T: 'async_trait + NoUninit + AnyBitPattern, Self: Send + 'async_trait,

Map the download buffer to read the buffer data. Read more
Source§

fn map_download_with_poll_type<'life0, 'life1, 'async_trait, T>( download: &'life0 Buffer, device: &'life1 Device, poll_type: PollType<SubmissionIndex>, ) -> Pin<Box<dyn Future<Output = Result<Vec<T>, DownloadBufferError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, T: 'async_trait + NoUninit + AnyBitPattern,

Map the download buffer to read the buffer data with custom wgpu::PollType. Read more
Source§

impl Clone for SelectionBuffer

Source§

fn clone(&self) -> SelectionBuffer

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for SelectionBuffer

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl From<Buffer> for SelectionBuffer

Source§

fn from(buffer: Buffer) -> Self

Converts to this type from the input type.
Source§

impl From<SelectionBuffer> for Buffer

Source§

fn from(wrapper: SelectionBuffer) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Downcast<T> for T

Source§

fn downcast(&self) -> &T

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> Upcast<T> for T

Source§

fn upcast(&self) -> Option<&T>

Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,