ifcviewer: GPU cull fwd/rev reflection bucketing (step 3b)

Extend the GPU-cull indirect buffer from M to 2M commands: the first M
are the forward (non-reflected, CCW) bucket, the second M are the
reverse (reflected, CW) bucket.  The compact shader reads flags bit 0
from the AABB SSBO and routes each survivor to the appropriate bucket
via bucket = reflected ? mesh_id + M : mesh_id.

uploadGpuCullStaticBuffers() now precomputes exact per-mesh fwd/rev
instance counts so each bucket reserves only the slots it needs
(total visible_ssbo size unchanged — sum of fwd + rev = total).

Draw loop issues two MDIs per model under IFC_GPU_CULL: first M
commands CCW, next M commands CW.

Sub-draws doubled (172k → 345k) which further regresses FPS due to
command-processor overhead from zero-instance sub-draws — the same
issue noted in 3a.  MDI compaction remains the fix.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dion Moult
2026-04-17 07:41:29 +10:00
parent 0b122ae1f5
commit 069ef20c46
2 changed files with 95 additions and 41 deletions
+14 -7
View File
@@ -108,13 +108,20 @@ struct ModelGpuData {
// the instanceCount field of gpu_indirect_buffer is rewritten by the
// cull shader (zeroed by the reset shader, atomically incremented as
// survivors are appended into gpu_visible_ssbo at mesh_base[i] + local).
GLuint gpu_indirect_buffer = 0;
size_t gpu_indirect_capacity = 0;
GLuint gpu_visible_ssbo = 0;
size_t gpu_visible_capacity = 0;
GLuint gpu_mesh_base_ssbo = 0;
size_t gpu_mesh_base_capacity = 0;
uint32_t gpu_mesh_command_count = 0;
// Layout per model:
// commands[0..M) fwd bucket (non-reflected, CCW winding)
// commands[M..2M) rev bucket (reflected, CW winding)
// gpu_mesh_command_count = 2M; gpu_forward_command_count = M.
// Each bucket gets its own mesh_base[] slot and its own visible[]
// range, sized to the exact per-mesh count of fwd / rev instances.
GLuint gpu_indirect_buffer = 0;
size_t gpu_indirect_capacity = 0;
GLuint gpu_visible_ssbo = 0;
size_t gpu_visible_capacity = 0;
GLuint gpu_mesh_base_ssbo = 0;
size_t gpu_mesh_base_capacity = 0;
uint32_t gpu_mesh_command_count = 0;
uint32_t gpu_forward_command_count = 0;
// Dynamic visible-instance index buffer (std430, binding = 1).
// Re-uploaded each frame from visible_flat_.