Skip to content

Commit

Permalink
using ManagedBindGroup, fixed wgpu runtime errors w/ bingroup invalid…
Browse files Browse the repository at this point in the history
…ation
  • Loading branch information
schell committed Jan 17, 2025
1 parent 8b30735 commit 34a8145
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 66 deletions.
2 changes: 2 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
[alias]
xtask = "run --package xtask --"
shaders = "xtask compile-shaders"
linkage = "xtask generati-linkage"

[build]
rustflags = ["--cfg=web_sys_unstable_apis"]
Expand Down
3 changes: 1 addition & 2 deletions crates/example/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,7 @@ impl App {
.with_background_color(DARK_BLUE_BG_COLOR)
.with_bloom_mix_strength(0.5)
.with_bloom_filter_radius(4.0)
.with_msaa_sample_count(4)
.with_debug_overlay(true);
.with_msaa_sample_count(4);
let camera = stage.new_value(Camera::default());
let sunlight = stage.new_value(DirectionalLight {
direction: Vec3::NEG_Y,
Expand Down
81 changes: 48 additions & 33 deletions crates/renderling/src/cull/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crabslab::{Array, Slab};
use glam::UVec2;
use snafu::{OptionExt, Snafu};

use crate::texture::Texture;
use crate::{bindgroup::ManagedBindGroup, texture::Texture};

use super::DepthPyramidDescriptor;

Expand Down Expand Up @@ -40,11 +40,14 @@ impl From<SlabAllocatorError> for CullingError {
/// Computes frustum and occlusion culling on the GPU.
pub struct ComputeCulling {
pipeline: wgpu::ComputePipeline,
bindgroup_layout: wgpu::BindGroupLayout,
bindgroup: wgpu::BindGroup,

pyramid_slab_buffer: SlabBuffer<wgpu::Buffer>,
stage_slab_buffer: SlabBuffer<wgpu::Buffer>,
indirect_slab_buffer: SlabBuffer<wgpu::Buffer>,

bindgroup_layout: wgpu::BindGroupLayout,
bindgroup: ManagedBindGroup,

pub(crate) compute_depth_pyramid: ComputeDepthPyramid,
}

Expand Down Expand Up @@ -86,10 +89,9 @@ impl ComputeCulling {

pub fn new(
runtime: impl AsRef<WgpuRuntime>,
size: UVec2,
sample_count: u32,
stage_slab_buffer: &SlabBuffer<wgpu::Buffer>,
indirect_slab_buffer: &SlabBuffer<wgpu::Buffer>,
depth_texture: &Texture,
) -> Self {
let runtime = runtime.as_ref();
let device = &runtime.device;
Expand Down Expand Up @@ -143,22 +145,22 @@ impl ComputeCulling {
compilation_options: wgpu::PipelineCompilationOptions::default(),
cache: None,
});
let compute_depth_pyramid = ComputeDepthPyramid::new(runtime, size, sample_count);
let compute_depth_pyramid = ComputeDepthPyramid::new(runtime, depth_texture);
let pyramid_slab_buffer = compute_depth_pyramid
.compute_copy_depth
.pyramid_slab_buffer
.clone();
let bindgroup = Self::new_bindgroup(
stage_slab_buffer,
&pyramid_slab_buffer,
&indirect_slab_buffer,
indirect_slab_buffer,
&bindgroup_layout,
device,
);
Self {
pipeline,
bindgroup_layout,
bindgroup,
bindgroup: ManagedBindGroup::new(bindgroup),
compute_depth_pyramid,
pyramid_slab_buffer,
stage_slab_buffer: stage_slab_buffer.clone(),
Expand All @@ -171,21 +173,31 @@ impl ComputeCulling {
}

pub fn run(&mut self, indirect_draw_count: u32, depth_texture: &Texture) {
log::trace!(
"indirect_draw_count: {indirect_draw_count}, sample_count: {}",
depth_texture.texture.sample_count()
);
// Compute the depth pyramid from last frame's depth buffer
self.compute_depth_pyramid.run(depth_texture);

let should_recreate_bindgroup = self.stage_slab_buffer.synchronize()
|| self.indirect_slab_buffer.synchronize()
|| self.pyramid_slab_buffer.synchronize();
if should_recreate_bindgroup {
self.bindgroup = Self::new_bindgroup(
let stage_slab_invalid = self.stage_slab_buffer.synchronize();
let indirect_slab_invalid = self.indirect_slab_buffer.synchronize();
let pyramid_slab_invalid = self.pyramid_slab_buffer.synchronize();
let should_recreate_bindgroup =
stage_slab_invalid || indirect_slab_invalid || pyramid_slab_invalid;
log::trace!("stage_slab_invalid: {stage_slab_invalid}");
log::trace!("indirect_slab_invalid: {indirect_slab_invalid}");
log::trace!("pyramid_slab_invalid: {pyramid_slab_invalid}");
let bindgroup = self.bindgroup.get(should_recreate_bindgroup, || {
log::debug!("recreating compute-culling bindgroup");
Self::new_bindgroup(
&self.stage_slab_buffer,
&self.pyramid_slab_buffer,
&self.indirect_slab_buffer,
&self.bindgroup_layout,
self.compute_depth_pyramid.depth_pyramid.slab.device(),
);
}
)
});
let runtime = self.runtime();
let mut encoder = runtime
.device
Expand All @@ -196,7 +208,7 @@ impl ComputeCulling {
timestamp_writes: None,
});
compute_pass.set_pipeline(&self.pipeline);
compute_pass.set_bind_group(0, Some(&self.bindgroup), &[]);
compute_pass.set_bind_group(0, Some(bindgroup.as_ref()), &[]);
compute_pass.dispatch_workgroups(indirect_draw_count / 32 + 1, 1, 1);
}
runtime.queue.submit(Some(encoder.finish()));
Expand Down Expand Up @@ -309,7 +321,7 @@ struct ComputeCopyDepth {
bindgroup_layout: wgpu::BindGroupLayout,
sample_count: u32,
pyramid_slab_buffer: SlabBuffer<wgpu::Buffer>,
bindgroup: Option<wgpu::BindGroup>,
bindgroup: ManagedBindGroup,
}

impl ComputeCopyDepth {
Expand Down Expand Up @@ -411,14 +423,21 @@ impl ComputeCopyDepth {
})
}

pub fn new(sample_count: u32, depth_pyramid: &DepthPyramid) -> Self {
pub fn new(depth_pyramid: &DepthPyramid, depth_texture: &Texture) -> Self {
let device = depth_pyramid.slab.device();
let sample_count = depth_texture.texture.sample_count();
let bindgroup_layout = Self::create_bindgroup_layout(device, sample_count);
let pipeline = Self::create_pipeline(device, &bindgroup_layout, sample_count > 1);
let pyramid_slab_buffer = depth_pyramid.slab.upkeep();
let buffer = Self::create_bindgroup(
device,
&bindgroup_layout,
&pyramid_slab_buffer,
&depth_texture.view,
);
Self {
pipeline,
bindgroup: None,
bindgroup: ManagedBindGroup::new(buffer),
bindgroup_layout,
pyramid_slab_buffer,
sample_count,
Expand Down Expand Up @@ -458,17 +477,15 @@ impl ComputeCopyDepth {
let _ = pyramid.slab.upkeep();
let should_recreate_bindgroup =
self.pyramid_slab_buffer.synchronize() || sample_count_mismatch || size_changed;
if should_recreate_bindgroup {
self.bindgroup = Some(Self::create_bindgroup(
pyramid.slab.device(),
let bindgroup = self.bindgroup.get(should_recreate_bindgroup, || {
Self::create_bindgroup(
&runtime.device,
&self.bindgroup_layout,
&self.pyramid_slab_buffer,
&depth_texture.view,
));
}
)
});

// UNWRAP: safe because we just set it above^
let bindgroup = self.bindgroup.as_ref().unwrap();
let mut encoder = runtime
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: Self::LABEL });
Expand All @@ -478,7 +495,7 @@ impl ComputeCopyDepth {
..Default::default()
});
compute_pass.set_pipeline(&self.pipeline);
compute_pass.set_bind_group(0, Some(bindgroup), &[]);
compute_pass.set_bind_group(0, Some(bindgroup.as_ref()), &[]);
let x = size.x / 32 + 1;
let y = size.y / 32 + 1;
let z = 1;
Expand Down Expand Up @@ -579,7 +596,7 @@ impl ComputeDownsampleDepth {
}

for i in 1..pyramid.mip_data.len() {
log::trace!("downsampling to mip {i}");
log::trace!("downsampling to mip {i}..{}", pyramid.mip_data.len());
// Update the mip_level we're operating on.
let size = pyramid.desc.modify(|desc| {
desc.mip_level = i as u32;
Expand Down Expand Up @@ -615,7 +632,6 @@ impl ComputeDownsampleDepth {

/// Computes occlusion culling on the GPU.
pub struct ComputeDepthPyramid {
sample_count: u32,
pub(crate) depth_pyramid: DepthPyramid,
compute_copy_depth: ComputeCopyDepth,
compute_downsample_depth: ComputeDownsampleDepth,
Expand All @@ -624,16 +640,15 @@ pub struct ComputeDepthPyramid {
impl ComputeDepthPyramid {
const _LABEL: Option<&'static str> = Some("compute-depth-pyramid");

pub fn new(runtime: impl AsRef<WgpuRuntime>, size: UVec2, sample_count: u32) -> Self {
pub fn new(runtime: impl AsRef<WgpuRuntime>, depth_texture: &Texture) -> Self {
let runtime = runtime.as_ref();
let depth_pyramid = DepthPyramid::new(runtime, size);
let compute_copy_depth = ComputeCopyDepth::new(sample_count, &depth_pyramid);
let depth_pyramid = DepthPyramid::new(runtime, depth_texture.size());
let compute_copy_depth = ComputeCopyDepth::new(&depth_pyramid, depth_texture);
let compute_downsample_depth = ComputeDownsampleDepth::new(&depth_pyramid);
Self {
depth_pyramid,
compute_copy_depth,
compute_downsample_depth,
sample_count,
}
}

Expand Down
23 changes: 13 additions & 10 deletions crates/renderling/src/draw/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,19 +53,21 @@ pub struct IndirectDraws {
impl IndirectDraws {
fn new(
runtime: impl AsRef<WgpuRuntime>,
size: UVec2,
sample_count: u32,
stage_slab_buffer: &SlabBuffer<wgpu::Buffer>,
depth_texture: &Texture,
) -> Self {
let runtime = runtime.as_ref();
let indirect_slab = SlabAllocator::new(runtime, wgpu::BufferUsages::INDIRECT);
let indirect_slab = SlabAllocator::new_with_label(
runtime,
wgpu::BufferUsages::INDIRECT,
Some("indirect-slab"),
);
Self {
compute_culling: ComputeCulling::new(
runtime,
size,
sample_count,
stage_slab_buffer,
&indirect_slab.upkeep(),
depth_texture,
),
slab: indirect_slab,
draws: vec![],
Expand All @@ -91,7 +93,10 @@ impl IndirectDraws {
self.invalidate();
// Pre-upkeep to reclaim resources - this is necessary because
// the draw buffer has to be contiguous (it can't start with a bunch of trash)
self.slab.upkeep();
let indirect_buffer = self.slab.upkeep();
if indirect_buffer.is_new_this_upkeep() {
log::warn!("new indirect buffer");
}
self.draws = internal_renderlets
.iter()
.map(|ir: &InternalRenderlet| {
Expand Down Expand Up @@ -173,9 +178,8 @@ impl DrawCalls {
pub fn new(
ctx: &Context,
use_compute_culling: bool,
size: UVec2,
sample_count: u32,
stage_slab_buffer: &SlabBuffer<wgpu::Buffer>,
depth_texture: &Texture,
) -> Self {
let can_use_multi_draw_indirect = ctx.get_adapter().features().contains(
wgpu::Features::INDIRECT_FIRST_INSTANCE | wgpu::Features::MULTI_DRAW_INDIRECT,
Expand All @@ -194,9 +198,8 @@ impl DrawCalls {
log::debug!("Using indirect drawing method and compute culling");
DrawingStrategy::Indirect(IndirectDraws::new(
ctx,
size,
sample_count,
stage_slab_buffer,
depth_texture,
))
} else {
log::debug!("Using direct drawing method");
Expand Down
3 changes: 2 additions & 1 deletion crates/renderling/src/skybox/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,8 @@ impl Skybox {
let runtime = runtime.as_ref();
log::trace!("creating skybox");

let slab = SlabAllocator::new(runtime, wgpu::BufferUsages::VERTEX);
let slab =
SlabAllocator::new_with_label(runtime, wgpu::BufferUsages::VERTEX, Some("skybox-slab"));

let proj = Mat4::perspective_rh(std::f32::consts::FRAC_PI_2, 1.0, 0.1, 10.0);
let camera = slab.new_value(Camera::default().with_projection(proj));
Expand Down
17 changes: 5 additions & 12 deletions crates/renderling/src/stage/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,8 @@ impl Stage {
let resolution @ UVec2 { x: w, y: h } = ctx.get_size();
let atlas_size = *ctx.atlas_size.read().unwrap();
let atlas = Atlas::new(ctx, atlas_size).unwrap();
let mngr = SlabAllocator::new(runtime, wgpu::BufferUsages::empty());
let mngr =
SlabAllocator::new_with_label(runtime, wgpu::BufferUsages::empty(), Some("stage-slab"));
let pbr_config = mngr.new_value(PbrConfig {
atlas_size: UVec2::new(atlas_size.width, atlas_size.height),
resolution,
Expand All @@ -200,12 +201,7 @@ impl Stage {
h,
multisample_count,
)));
let depth_texture = Arc::new(RwLock::new(Texture::create_depth_texture(
device,
w,
h,
multisample_count,
)));
let depth_texture = Texture::create_depth_texture(device, w, h, multisample_count);
let msaa_render_target = Default::default();
// UNWRAP: safe because no other references at this point (created above^)
let bloom = Bloom::new(ctx, &hdr_texture.read().unwrap());
Expand All @@ -221,10 +217,10 @@ impl Stage {
draw_calls: Arc::new(RwLock::new(DrawCalls::new(
ctx,
true,
UVec2::new(w, h),
multisample_count,
&mngr.upkeep(),
&depth_texture,
))),
depth_texture: Arc::new(RwLock::new(depth_texture)),
buffers_bindgroup: ManagedBindGroup::new(crate::linkage::slab_bindgroup(
device,
&stage_slab_buffer,
Expand All @@ -234,7 +230,6 @@ impl Stage {
mngr,
pbr_config,
lights: Arc::new(RwLock::new(lights)),

stage_pipeline: Arc::new(RwLock::new(stage_pipeline)),
atlas,
skybox: Arc::new(RwLock::new(Skybox::empty(runtime))),
Expand All @@ -245,11 +240,9 @@ impl Stage {
tonemapping,
has_bloom: AtomicBool::from(true).into(),
textures_bindgroup: Default::default(),

debug_overlay: DebugOverlay::new(device, ctx.get_render_target().format()),
has_debug_overlay: Arc::new(false.into()),
hdr_texture,
depth_texture,
msaa_render_target,
msaa_sample_count: Arc::new(multisample_count.into()),
clear_color_attachments: Arc::new(true.into()),
Expand Down
Loading

0 comments on commit 34a8145

Please sign in to comment.