Skip to content

Meshlet BVH Culling #19318

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 24 commits into
base: main
Choose a base branch
from
Open

Meshlet BVH Culling #19318

wants to merge 24 commits into from

Conversation

atlv24
Copy link
Contributor

@atlv24 atlv24 commented May 21, 2025

Objective

  • Merge @SparkyPotato 's efforts to implement BVH-accelerated meshlet culling.

Solution

  • Add hot reloading support
  • Fix near-plane overculling
  • Fix hzb sampling
  • Fix orthographic error metric

Testing

  • Meshlet example, Nsight, hot-reloading and careful thinking

@JMS55 JMS55 self-requested a review May 21, 2025 14:53
@atlv24 atlv24 added C-Feature A new feature, making something new possible A-Rendering Drawing game state to the screen S-Needs-Review Needs reviewer attention (from anyone!) to move forward D-Shaders This code uses GPU shader languages labels May 22, 2025
return min(min(a, b), min(c, d));
}

// TODO: We should probably be using a POT HZB texture?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should keep this TODO. The current HZB generation is wrong and misses information on the edges of certain mip levels, requiring us to be over-conservative in our culling.

}

fn occlusion_cull_screen_aabb(aabb: ScreenAabb, screen: vec2<f32>) -> bool {
let hzb_size = ceil(screen);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mip 0 of the HZB is floor(screen * 0.5).


// note: add 1 before max because the unsigned overflow behavior is intentional
// it wraps around firstLeadingBit(0) = ~0 to 0
var mip = max(firstLeadingBit(max_size) + 1u, 2u) - 1u;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the above change, I tested the following and it works, letting us sample one mip finer:

// note: add 1 before max because the unsigned overflow behavior is intentional
// it wraps around firstLeadingBit(0) = ~0 to 0
// TODO: we actually sample a 4x4 block, so ideally this would be `max(..., 3u) - 3u`.
// However, since our HZB is not a power of two, we need to be extra-conservative to not over-cull, so we go up a mip.
var mip = max(firstLeadingBit(max_size) + 1u, 2u) - 2u;

let smin = min_texel >> vec2<u32>(mip);
let smax = max_texel >> vec2<u32>(mip);

mip -= 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the above changes, this can be removed.

Comment on lines +22 to +29
// let world_sphere_radius = lod_sphere.w * world_scale;
// let norm_error = simplification_error / world_sphere_radius * 0.25;
// return norm_error * view.viewport.w < 1.0;
let world_error = simplification_error * world_scale;
let proj = projection[1][1];
let height = 2.0 / proj;
let norm_error = world_error / height;
return norm_error * view.viewport.w < 1.0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsure how correct my change (from the commented code) is, though it seems to work.

@JMS55 JMS55 added this to the 0.17 milestone May 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Rendering Drawing game state to the screen C-Feature A new feature, making something new possible D-Shaders This code uses GPU shader languages S-Needs-Review Needs reviewer attention (from anyone!) to move forward
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

3 participants