mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-22 13:18:00 +00:00
ifcviewer: pack the cull-hot instance fields and skip unchanged culls
On the single-threaded web build the CPU cull WAS the frame: 52-60 ms of a 60 ms frame at 640k instances (desktop hides the same cost across cores via std::async, which web cannot use without COOP/COEP+pthreads). Two changes, both also helping desktop: - ModelGpuData::CullInstance packs the six AABB floats and three ids the cull reads into 40 contiguous bytes. InstanceInfo is 232 bytes with the AABB 200 bytes away from the ids, so the walk paid two or three cache lines per instance. Rebuilt by rebuildCullInstances at model apply and inside uploadInstanceRecords, which every recompose, transform and colour-override change already funnels through. Measured on web: 94 ns/instance -> 36 ns/instance during a continuous orbit (~2.6x). - render() re-culls only when a cull input changed: the camera, a cull-relevant setting (contribution px, LOD px, x-ray, HiZ on/off), a fresh HiZ pyramid, or scene_epoch_ — bumped by chunk residency, visibility, colours, transforms, model add/remove/hide/unload. A frame requested for an overlay redraw, pick feedback, or a streaming tick where nothing landed draws from the buffers the last cull uploaded and skips the walk entirely. Benchmarks are exempt so bench numbers keep measuring the real cull. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -395,6 +395,25 @@ struct ModelGpuData {
|
||||
std::vector<MeshInfo> meshes;
|
||||
std::vector<InstanceInfo> instances;
|
||||
|
||||
// The cull-hot per-instance fields packed contiguously. InstanceInfo is
|
||||
// 232 bytes with the AABB 200 bytes from the ids, so the per-frame cull
|
||||
// paid two or three cache lines per instance — at half a million
|
||||
// instances that is the whole frame budget on the single-threaded web
|
||||
// build. 40 bytes per entry here makes the walk sequential. Rebuilt by
|
||||
// rebuildCullInstances wherever instances change (applyCachedModel,
|
||||
// uploadInstanceRecords — which every recompose and colour change
|
||||
// already funnels through).
|
||||
struct CullInstance {
|
||||
float aabb_min[3];
|
||||
float aabb_max[3];
|
||||
std::uint32_t mesh_id;
|
||||
std::uint32_t object_id;
|
||||
std::uint32_t color_override_rgba8;
|
||||
std::uint32_t chunk_idx;
|
||||
};
|
||||
static_assert(sizeof(CullInstance) == 40, "keep the cull walk dense");
|
||||
std::vector<CullInstance> cull_instances;
|
||||
|
||||
// Per-mesh "any vertex has alpha < 255?" flag, indexed by mesh_id.
|
||||
// Populated at uploadStreamedMesh / applyStreamedChunk as vertex bytes
|
||||
// become CPU-resident. Used at cull time to classify each instance
|
||||
@@ -501,5 +520,7 @@ void releaseWgpuModelGpuData(ModelGpuData& m, BufferPool& pool);
|
||||
// and the per-chunk cull buffers. Chunk bookkeeping is left intact so the
|
||||
// buffers can be re-created — the undo step of a failed model load.
|
||||
void releaseModelBuffers(ModelGpuData& m);
|
||||
// Refresh ModelGpuData::cull_instances from instances + instance_chunk_idx.
|
||||
void rebuildCullInstances(ModelGpuData& m);
|
||||
|
||||
#endif // WGPUMODELGPUDATA_H
|
||||
|
||||
Reference in New Issue
Block a user