Skip to content

Commit f122319

Browse files
committed
upgraded to wgpu 29 and switched to front to back blending
1 parent 6584b04 commit f122319

File tree

9 files changed

+589
-374
lines changed

9 files changed

+589
-374
lines changed

Cargo.lock

Lines changed: 507 additions & 307 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ description = "3D Gaussian Splatting Viewer"
88
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
99

1010
[dependencies]
11-
wgpu = { version = "27.0" }
11+
wgpu = { version = "29.0.1" }
1212
winit = "0.30.12"
1313
cgmath = { version = "0.18.0", features = [
1414
"bytemuck",
1515
], git = 'https://github.com/rustgd/cgmath' }
16-
env_logger = "0.11.9"
17-
clap = { version = "4.5.60", features = ["derive"] }
16+
env_logger = "0.11.10"
17+
clap = { version = "4.6", features = ["derive"] }
1818
bytemuck = { version = "1.25", features = ["derive"] }
1919
anyhow = "1.0.102"
2020
ply-rs = "0.1.3"
@@ -25,15 +25,14 @@ num-traits = "0.2.19"
2525
half = { version = "2.7.1", features = ["bytemuck", "num-traits"] }
2626
log = "0.4.29"
2727
rayon = "1.11.0"
28-
image = "0.25.9"
28+
image = "0.25.10"
2929
indicatif = "0.18.4"
3030

3131

32-
egui = "0.33.3"
33-
egui-wgpu = "0.33.3"
34-
egui-winit = { version = "0.33.3", features = [], default-features = false }
35-
egui_plot = "0.34.1"
36-
egui_dnd = "0.14.0"
32+
egui = "0.34.0"
33+
egui-wgpu = "0.34.0"
34+
egui-winit = { version = "0.34.0", features = [], default-features = false }
35+
egui_plot = "0.35.0"
3736

3837
rand = "0.10.0"
3938
npyz = { version = "0.8.4", features = ["npz", "half"], optional = true }

src/bin/measure.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ use std::{
88
};
99
#[allow(unused_imports)]
1010
use web_splats::{
11-
io, GaussianRenderer, PerspectiveCamera, PointCloud, Scene, SceneCamera, SplattingArgs, Split,
12-
WGPUContext,
11+
GaussianRenderer, PerspectiveCamera, PointCloud, Scene, SceneCamera, SplattingArgs, Split,
12+
WGPUContext, io,
1313
};
1414

1515
#[derive(Debug, Parser)]
@@ -86,10 +86,12 @@ async fn render_views(
8686
load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
8787
store: wgpu::StoreOp::Store,
8888
},
89+
depth_slice: None,
8990
})],
9091
depth_stencil_attachment: None,
9192
timestamp_writes: None,
9293
occlusion_query_set: None,
94+
multiview_mask: None,
9395
});
9496
renderer.render(&mut render_pass, &pc);
9597
}
@@ -134,17 +136,19 @@ async fn render_views(
134136
load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
135137
store: wgpu::StoreOp::Store,
136138
},
139+
depth_slice: None,
137140
})],
138141
depth_stencil_attachment: None,
139142
timestamp_writes: None,
140143
occlusion_query_set: None,
144+
multiview_mask: None,
141145
});
142146
renderer.render(&mut render_pass, &pc);
143147
}
144148
queue.submit(std::iter::once(encoder.finish()));
145149
}
146150
}
147-
device.poll(wgpu::MaintainBase::Wait);
151+
device.poll(wgpu::PollType::wait_indefinitely());
148152
let end = Instant::now();
149153
let duration = end - start;
150154
println!(
@@ -165,8 +169,9 @@ async fn main() {
165169
let scene_file = File::open(opt.scene).unwrap();
166170

167171
let scene = Scene::from_json(scene_file).unwrap();
168-
169-
let wgpu_context = WGPUContext::new_instance().await;
172+
let instance =
173+
wgpu::Instance::new(wgpu::InstanceDescriptor::new_without_display_handle_from_env());
174+
let wgpu_context = WGPUContext::new(&instance, None).await;
170175
let device = &wgpu_context.device;
171176
let queue = &wgpu_context.queue;
172177

src/bin/render.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,12 @@ async fn render_views(
114114
load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
115115
store: wgpu::StoreOp::Store,
116116
},
117+
depth_slice: None,
117118
})],
118119
depth_stencil_attachment: None,
119120
timestamp_writes: None,
120121
occlusion_query_set: None,
122+
multiview_mask: None,
121123
});
122124
renderer.render(&mut render_pass, &pc);
123125
}
@@ -142,7 +144,9 @@ async fn main() {
142144

143145
let scene = Scene::from_json(scene_file).unwrap();
144146

145-
let wgpu_context = WGPUContext::new_instance().await;
147+
let instance =
148+
wgpu::Instance::new(wgpu::InstanceDescriptor::new_without_display_handle_from_env());
149+
let wgpu_context = WGPUContext::new(&instance, None).await;
146150
let device = &wgpu_context.device;
147151
let queue = &wgpu_context.queue;
148152

@@ -226,8 +230,7 @@ pub async fn download_texture(
226230
let sub_idx = queue.submit(std::iter::once(encoder.finish()));
227231

228232
let mut image = {
229-
let data: wgpu::BufferView<'_> =
230-
download_buffer(device, &staging_buffer, Some(sub_idx)).await;
233+
let data: wgpu::BufferView = download_buffer(device, &staging_buffer, Some(sub_idx)).await;
231234

232235
ImageBuffer::<Rgba<u8>, _>::from_raw(
233236
bytes_per_row / texel_size,
@@ -245,19 +248,19 @@ pub async fn download_texture(
245248
return image::imageops::crop(&mut image, 0, 0, fb_size.width, fb_size.height).to_image();
246249
}
247250

248-
async fn download_buffer<'a>(
251+
async fn download_buffer(
249252
device: &wgpu::Device,
250-
buffer: &'a wgpu::Buffer,
253+
buffer: &wgpu::Buffer,
251254
wait_idx: Option<wgpu::SubmissionIndex>,
252-
) -> wgpu::BufferView<'a> {
255+
) -> wgpu::BufferView {
253256
let slice = buffer.slice(..);
254257

255258
let (tx, rx) = futures_intrusive::channel::shared::oneshot_channel();
256259
slice.map_async(wgpu::MapMode::Read, move |result| tx.send(result).unwrap());
257260
device
258-
.poll(match wait_idx {
259-
Some(idx) => wgpu::MaintainBase::WaitForSubmissionIndex(idx),
260-
None => wgpu::MaintainBase::Wait,
261+
.poll(wgpu::PollType::Wait {
262+
submission_index: wait_idx,
263+
timeout: None,
261264
})
262265
.unwrap();
263266
rx.receive().await.unwrap().unwrap();

src/gpu_rs.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ unsafe fn any_as_u8_slice<T: Sized>(p: &T) -> &[u8] {
6363
impl GPURSSorter {
6464
// The new call also needs the queue to be able to determine the maximum subgroup size (Does so by running test runs)
6565
pub async fn new(device: &wgpu::Device, queue: &wgpu::Queue) -> Self {
66-
let sg_size = device.limits().min_subgroup_size;
66+
let sg_size = device.adapter_info().subgroup_min_size;
6767
if sg_size == 0 || sg_size > 512 {
6868
let mut cur_sorter: GPURSSorter;
6969

@@ -195,8 +195,8 @@ impl GPURSSorter {
195195
let pipeline_layout: wgpu::PipelineLayout =
196196
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
197197
label: Some("radix sort pipeline layout"),
198-
bind_group_layouts: &[&bind_group_layout],
199-
push_constant_ranges: &[],
198+
bind_group_layouts: &[Some(&bind_group_layout)],
199+
immediate_size: 0,
200200
});
201201

202202
let raw_shader: &str = include_str!("shaders/radix_sort.wgsl");

src/lib.rs

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ use std::{
44
sync::Arc,
55
};
66

7+
use egui_wgpu::EguiDisplayHandle;
78
use renderer::Display;
89
#[cfg(not(target_arch = "wasm32"))]
910
use std::time::{Duration, Instant};
1011
#[cfg(target_arch = "wasm32")]
1112
use web_time::{Duration, Instant};
12-
use wgpu::Backends;
1313

1414
use cgmath::{Deg, EuclideanSpace, Point3, Quaternion, UlpsEq, Vector2, Vector3};
1515
use egui::FullOutput;
@@ -66,15 +66,6 @@ pub struct WGPUContext {
6666
}
6767

6868
impl WGPUContext {
69-
pub async fn new_instance() -> Self {
70-
let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
71-
backends: Backends::PRIMARY,
72-
..Default::default()
73-
});
74-
75-
return WGPUContext::new(&instance, None).await;
76-
}
77-
7869
pub async fn new(instance: &wgpu::Instance, surface: Option<&wgpu::Surface<'static>>) -> Self {
7970
let adapter = wgpu::util::initialize_adapter_from_env_or_default(instance, surface)
8071
.await
@@ -168,7 +159,9 @@ impl WindowContext {
168159

169160
let window = Arc::new(window);
170161

171-
let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor::default());
162+
let instance = wgpu::Instance::new(
163+
wgpu::InstanceDescriptor::new_with_display_handle_from_env(window.clone_for_wgpu()),
164+
);
172165

173166
let surface: wgpu::Surface = instance.create_surface(window.clone())?;
174167

@@ -399,10 +392,14 @@ impl WindowContext {
399392
&mut self,
400393
redraw_scene: bool,
401394
shapes: Option<FullOutput>,
402-
) -> Result<(), wgpu::SurfaceError> {
395+
) -> Result<(), wgpu::CurrentSurfaceTexture> {
403396
self.stopwatch.as_mut().map(|s| s.reset());
404397

405-
let output = self.surface.get_current_texture()?;
398+
let output = match self.surface.get_current_texture() {
399+
wgpu::CurrentSurfaceTexture::Success(surface_texture) => surface_texture,
400+
wgpu::CurrentSurfaceTexture::Suboptimal(surface_texture) => surface_texture,
401+
err => return Err(err),
402+
};
406403
let view_rgb = output.texture.create_view(&wgpu::TextureViewDescriptor {
407404
format: Some(self.config.format.remove_srgb_suffix()),
408405
..Default::default()
@@ -452,7 +449,7 @@ impl WindowContext {
452449
view: self.display.texture(),
453450
resolve_target: None,
454451
ops: wgpu::Operations {
455-
load: wgpu::LoadOp::Clear(self.splatting_args.background_color),
452+
load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
456453
store: wgpu::StoreOp::Store,
457454
},
458455
depth_slice: None,
@@ -835,9 +832,9 @@ pub async fn open_window<R: Read + Seek + Send + Sync + 'static>(
835832
match state.render(request_redraw,state.ui_visible.then_some(shapes)) {
836833
Ok(_) => {}
837834
// Reconfigure the surface if lost
838-
Err(wgpu::SurfaceError::Lost) => state.resize(state.window.inner_size(), None),
835+
Err(wgpu::CurrentSurfaceTexture::Suboptimal(_)) => state.resize(state.window.inner_size(), None),
836+
Err(wgpu::CurrentSurfaceTexture::Lost) => state.resize(state.window.inner_size(), None),
839837
// The system is out of memory, we should probably quit
840-
Err(wgpu::SurfaceError::OutOfMemory) =>target.exit(),
841838
// All other errors (Outdated, Timeout) should be resolved by the next frame
842839
Err(e) => println!("error: {:?}", e),
843840
}

src/renderer.rs

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ impl GaussianRenderer {
4040
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
4141
label: Some("render pipeline layout"),
4242
bind_group_layouts: &[
43-
&PointCloud::bind_group_layout_render(device), // Needed for points_2d (on binding 2)
44-
&GPURSSorter::bind_group_layout_rendering(device), // Needed for indices (on binding 4)
43+
Some(&PointCloud::bind_group_layout_render(device)), // Needed for points_2d (on binding 2)
44+
Some(&GPURSSorter::bind_group_layout_rendering(device)), // Needed for indices (on binding 4)
4545
],
46-
push_constant_ranges: &[],
46+
immediate_size: 0,
4747
});
4848

4949
let shader = device.create_shader_module(wgpu::include_wgsl!("shaders/gaussian.wgsl"));
@@ -62,7 +62,21 @@ impl GaussianRenderer {
6262
entry_point: Some("fs_main"),
6363
targets: &[Some(wgpu::ColorTargetState {
6464
format: color_format,
65-
blend: Some(wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING),
65+
// front to back blending
66+
// this gives better visuals compared to back to front blending
67+
// if used with 8 bit textures
68+
blend: Some(wgpu::BlendState {
69+
color: wgpu::BlendComponent {
70+
src_factor: wgpu::BlendFactor::OneMinusDstAlpha,
71+
dst_factor: wgpu::BlendFactor::One,
72+
operation: wgpu::BlendOperation::Add,
73+
},
74+
alpha: wgpu::BlendComponent {
75+
src_factor: wgpu::BlendFactor::OneMinusDstAlpha,
76+
dst_factor: wgpu::BlendFactor::One,
77+
operation: wgpu::BlendOperation::Add,
78+
},
79+
}),
6680
write_mask: wgpu::ColorWrites::ALL,
6781
})],
6882
compilation_options: Default::default(),
@@ -78,8 +92,8 @@ impl GaussianRenderer {
7892
},
7993
depth_stencil: None,
8094
multisample: wgpu::MultisampleState::default(),
81-
multiview: None,
8295
cache: None,
96+
multiview_mask: None,
8397
});
8498

8599
let draw_indirect_buffer = device.create_buffer(&wgpu::BufferDescriptor {
@@ -349,16 +363,18 @@ impl PreprocessPipeline {
349363
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
350364
label: Some("preprocess pipeline layout"),
351365
bind_group_layouts: &[
352-
&UniformBuffer::<CameraUniform>::bind_group_layout(device),
353-
&if !compressed {
366+
Some(&UniformBuffer::<CameraUniform>::bind_group_layout(device)),
367+
Some(&if !compressed {
354368
PointCloud::bind_group_layout(device)
355369
} else {
356370
PointCloud::bind_group_layout_compressed(device)
357-
},
358-
&GPURSSorter::bind_group_layout_preprocess(device),
359-
&UniformBuffer::<SplattingArgsUniform>::bind_group_layout(device),
371+
}),
372+
Some(&GPURSSorter::bind_group_layout_preprocess(device)),
373+
Some(&UniformBuffer::<SplattingArgsUniform>::bind_group_layout(
374+
device,
375+
)),
360376
],
361-
push_constant_ranges: &[],
377+
immediate_size: 0,
362378
});
363379

364380
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
@@ -432,11 +448,13 @@ impl Display {
432448
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
433449
label: Some("display pipeline layout"),
434450
bind_group_layouts: &[
435-
&Self::bind_group_layout(device),
436-
&UniformBuffer::<CameraUniform>::bind_group_layout(device),
437-
&UniformBuffer::<SplattingArgsUniform>::bind_group_layout(device),
451+
Some(&Self::bind_group_layout(device)),
452+
Some(&UniformBuffer::<CameraUniform>::bind_group_layout(device)),
453+
Some(&UniformBuffer::<SplattingArgsUniform>::bind_group_layout(
454+
device,
455+
)),
438456
],
439-
push_constant_ranges: &[],
457+
immediate_size: 0,
440458
});
441459
let shader = device.create_shader_module(include_wgsl!("shaders/display.wgsl"));
442460
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
@@ -464,7 +482,7 @@ impl Display {
464482
})],
465483
compilation_options: Default::default(),
466484
}),
467-
multiview: None,
485+
multiview_mask: None,
468486
cache: None,
469487
});
470488
let (view, bind_group) = Self::create_render_target(device, source_format, width, height);

src/shaders/preprocess.wgsl

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -267,10 +267,7 @@ fn preprocess(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgr
267267
pack2x16float(color.rg), pack2x16float(color.ba),
268268
);
269269
// filling the sorting buffers and the indirect sort dispatch buffer
270-
let znear = -camera.proj[3][2] / camera.proj[2][2];
271-
let zfar = -camera.proj[3][2] / (camera.proj[2][2] - (1.));
272-
// filling the sorting buffers and the indirect sort dispatch buffer
273-
sort_depths[store_idx] = bitcast<u32>(zfar - pos2d.z) ;//u32(f32(0xffffffu) - pos2d.z / zfar * f32(0xffffffu));
270+
sort_depths[store_idx] = bitcast<u32>(pos2d.z);
274271
sort_indices[store_idx] = store_idx;
275272

276273
let keys_per_wg = 256u * 15u; // Caution: if workgroup size (256) or keys per thread (15) changes the dispatch is wrong!!

src/shaders/preprocess_compressed.wgsl

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -318,11 +318,7 @@ fn preprocess(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgr
318318
pack2x16float(color.rg), pack2x16float(color.ba),
319319
);
320320

321-
// filling the sorting buffers and the indirect sort dispatch buffer
322-
let znear = -camera.proj[3][2] / camera.proj[2][2];
323-
let zfar = -camera.proj[3][2] / (camera.proj[2][2] - (1.));
324-
// filling the sorting buffers and the indirect sort dispatch buffer
325-
sort_depths[store_idx] = u32(f32(0xffffffu) - (pos2d.z - znear) / (zfar - znear) * f32(0xffffffu));
321+
sort_depths[store_idx] = bitcast<u32>(pos2d.z);
326322
sort_indices[store_idx] = store_idx;
327323

328324
let keys_per_wg = 256u * 15u; // Caution: if workgroup size (256) or keys per thread (15) changes the dispatch is wrong!!

0 commit comments

Comments
 (0)