forked from 1b-agent/opencadstudio-upstream
perf(render): skip hatch pass while navigating (interaction LOD)
The batched hatch pass evaluates its fill procedurally per fragment — a point-in-polygon test over the whole boundary plus the pattern test, with a `discard` that disables early-Z. When the view sits inside a hatch its quad covers the screen, so panning / zooming re-runs that full-screen shader every frame (~40 ms/frame on a hatch-heavy plan) even though the rest of the scene is cheap — the wire pass and CPU prepare are negligible by comparison. Suppress the hatch pass while the view is actively panning / zooming / orbiting, detected from `camera_generation` plus a short settle timer (`Scene::navigating_lod`), and fold that state into the render signature so the moment the view settles it renders hatches once and the scene-render cache holds that full-quality frame. A brief `is_settling` subscription keeps requesting frames just past the settle point so the hatched frame renders even when no input event would otherwise fire. Mirrors AutoCAD's adaptive degradation. The paper sheet keeps its fills.
This commit is contained in:
1 parent
f99f1cd7a5
commit
a55e1ac4f8
4 files changed
+82
-5
No files matched your search
@@ -191,6 +191,10 @@ pub struct Pipeline {
|
||||
/// `render_sig`, so `render` may skip the geometry passes. Read (never
|
||||
/// written) by `render`, which always runs after `prepare` for the frame.
|
||||
pub skip_geometry: bool,
|
||||
/// Interaction LOD: set by `prepare` when the view is actively navigating, so
|
||||
/// `render` skips the (per-pixel, GPU-dominating) hatch pass this frame. The
|
||||
/// scene-render cache holds the full-quality frame once the view settles.
|
||||
pub skip_hatch_frame: bool,
|
||||
}
|
||||
|
||||
impl Pipeline {
|
||||
@@ -1171,6 +1175,7 @@ impl Pipeline {
|
||||
wire_handle_index: rustc_hash::FxHashMap::default(),
|
||||
render_sig: u64::MAX,
|
||||
skip_geometry: false,
|
||||
skip_hatch_frame: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1611,11 +1616,15 @@ impl Pipeline {
|
||||
if let (Some(batch), Some(pipeline)) =
|
||||
(&self.gpu_hatch_batched, &self.hatch_batched_pipeline)
|
||||
{
|
||||
pass.set_pipeline(pipeline);
|
||||
pass.set_bind_group(0, &self.uniform_bind_group, &[]);
|
||||
pass.set_bind_group(1, &batch.bind_group, &[]);
|
||||
pass.set_vertex_buffer(0, batch.vertex_buffer.slice(..));
|
||||
pass.draw(0..batch.vertex_count, 0..1);
|
||||
// Skipped while navigating (interaction LOD) — the per-pixel
|
||||
// hatch pass dominates the GPU frame on hatch-heavy drawings.
|
||||
if !self.skip_hatch_frame {
|
||||
pass.set_pipeline(pipeline);
|
||||
pass.set_bind_group(0, &self.uniform_bind_group, &[]);
|
||||
pass.set_bind_group(1, &batch.bind_group, &[]);
|
||||
pass.set_vertex_buffer(0, batch.vertex_buffer.slice(..));
|
||||
pass.draw(0..batch.vertex_count, 0..1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user