mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-18 14:31:39 +00:00
wgpu: streaming + HiZ correctness fixes
Three correctness bugs found and fixed, plus an unrelated fly-mode deadlock surfaced along the way. HiZ false-rejection at the bottom of the screen ------------------------------------------------ The mip-pyramid sizing floored when halving — for a 256×70 mip 0 the level-3 mip is 32×8, but mip-0 row 69 maps to ly = 69>>3 = 8, which is out of bounds for an 8-row mip. ly1 then clamps down to 7 while ly0 stays at 8, the sampling loop runs zero times, max_d retains its initial 0.0, and `min_z > 0` rejects every AABB whose projected y range touches the bottom row. Same class for the right edge on very wide viewports. Fix: ceil rather than floor when halving mip dimensions so every parent row has a covering child texel, plus std::clamp on both lookup endpoints as belt-and-suspenders for any future mip-sizing change. Surfaced after the user added more sidecars and saw "anything near the bottom of the screen, no matter close or far" disappear ~0.5 s after camera stops — that delay was the strict-VP gate + readback latency opening the HiZ window. Found via WGPU_HIZ_TRACE rejection logs that showed every rejection had `max_d=0` and `ly0 > ly1`. Streaming priority lets the ocean starve out the bracing --------------------------------------------------------- Per-instance projected screen footprint was estimated as bounding- sphere radius squared. BIM geometry is overwhelmingly thin-in-one-axis (slabs, pipes, columns, windows) and a flat ocean plane viewed nearly edge-on gets a sphere projection ~250× larger than its actual screen rect. Its chunk dominated the priority ranking and evicted the brace chunks despite the braces being one of the closest visible things. Fix: per-instance priority is now the screen-space AABB rectangle area (world AABB extents projected onto the camera right/up basis vectors, divided by view-z). Sphere radius is retained for the contribution cull and LOD pick because conservative-over is the right failure mode there. Stale-VP HiZ gate ----------------- HiZ resolves into an async ping-pong of staging buffers, so the pyramid resident at cull time was typically captured one or two frames ago. During camera motion the captured VP differs from vp_this_frame and AABBs end up sampling depth taken for what was at slightly-different screen positions in the old view. Strict by default now: HiZ engages only when hiz_vp_ == vp_this_frame. WGPU_HIZ_MOTION=1 trusts the stale pyramid (matches GL's default). Fly mode Shift+Q deadlock -------------------------- keyPressEvent requested a redraw only on the first key of a new held set (was_empty). Pressing Shift first then Q never satisfied that condition because Shift had already populated the set, so the render loop never ticked. Now every relevant keypress calls requestUpdate unconditionally. HiZ stays opt-in behind WGPU_HIZ=1 for one release while the fix bakes; WGPU_HIZ_TRACE=1 keeps the per-rejection diagnostic available for future bugs. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -210,6 +210,14 @@ struct WgpuModelGpuData {
|
||||
// with load_count >> 1 has been cycling — used by the stream
|
||||
// debug log (WGPU_STREAM_DEBUG=1) to surface thrash.
|
||||
uint32_t load_count = 0;
|
||||
// Per-frame instance-aware priority. Sum of px² projected
|
||||
// contributions of every instance owned by this chunk —
|
||||
// captures the chunk's actual on-screen footprint, not the
|
||||
// (often loose) AABB union projection. Computed once per
|
||||
// frame at the top of driveStreamingLoads from the camera
|
||||
// state; the candidate/resident priority lambdas just read
|
||||
// this. See task #57 for the rationale.
|
||||
float current_priority = 0.0f;
|
||||
};
|
||||
std::vector<Chunk> chunks;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user