There are two main types of Axis aligned bounding boxes in an Entity: Local and World.
- Local aabbs can be stored per Mesh. Shared per instance.
- World aabbs is unique to each entity instance and must be stored per entity.
Option 1.- Store local aabbs per Entity. Throughput-wise, it seems that having a copy of local aabbs per Entity could be faster for SIMD processing (I haven't done any profiling to back this up), because we can concatenate 4 local aabbs against their derived transforms (ArrayMatrix4) and store the result where the World Aabb is stored. This chart summarizes the algorithm: Option 2.- Store shared local aabbs per Mesh. Memory wise, load the 4 aabbs from the Mesh in AoS form, then transpose to get the SoA. Note that each local aabb in the mesh may not be contiguous in memory (may be we could enforce that?)
Option 1 seems the most straightforward. And on first sight, faster. However I have a hard time thinking that so. Imagine a scene with a million objects (currently impossible with Ogre 1.x, at least if you expect playable framerate).
An aabb needs 24 bytes. Storing local aabbs per Entity means that we would need 22.89 MB of RAM just for the local entities (+ another 22.89MB of the world aabbs, + 61MB for the derived transforms, + more memory for everything else in an Entity).
Given we're trying to render a scene with a very high number of entities, it's safe to assume the computer requirements are of at least 2GB of RAM. So memory limit isn't a concern. However cache is.
For example, my Intel Core 2 Quad Extree QX9650 has one of the biggest cache sizes in the Core 2 family (Two L2 caches of 6MB each, total = 12MB) and the biggest Core i7s have around 8MB of L3 cache.
So clearly not even the local aabbs from all entities fit in the cache.
With these requirements, throughput is more important than latency, so cache doesn't really matter, unless our code is too dependant on it.
My point is, ditching 22.89MB of bandwidth per frame by switching from per-instance local aabbs to shared per-mesh aabb could prevent lots of cache trashing.
This One-million-objects scene would need a lot of asset re use, so it's safe to assume there aren't more than 500 Meshes in use, let's say 1.000 to be pesimistic. That would be 31.25kb, which nicely fits in L2 caches! (if stored contiguously) and can stay 'hot' (even half of them enter in the L1 d-cache!).
In case you realized, I calculated the shared aabb by adding some padding, so shared local aabbs would need 32 bytes, not 24 (this is easier to transpose and needs 2 movaps instead of 6 movss plus transpose difficulties)
The problem with Option 2, is that it needs the extra loads and a transpose, which translates to more ops. However, this can be amortized by using more Cores; you can't amortize memory consumption & cache trashing with more cores (in other words, Option 2 could scale better than Option 1)
And Option 1 isn't free either. Whenever too many Entities belonging to the same RenderQueue have been removed (or they switch to a different RenderQueue) a cleanup is triggered to ensure that all Entities have their per-instance contiguous (WorldAbbb - 24 bytes, World sphere - 4 bytes, Parent Ptr - 4 bytes, World Matrix AoS cache - 64 bytes) and expensive memory transfers may ensue.
On the other hand, the example of 1 million entities may be a bit extreme. To render such high amount of instances, perhaps a custom solution where AABBs are evaluated at higher levels (i.e. group 1000 instances together) would be a much better approach for this hypothetical scenario.
So, sumarizing:
Option 1
Advantages:
- Straightforward. Simple
- Little ops
- More bandwidth
- Potentially more cache trashing
- Adds more overhead to memory maintenance
Advantages:
- Very little memory & bandwidth footprint
- May scale better
- More ops can be amortized by using more cores
- More ops (requires more loads and transpose)
- Slightly more complex code
- Needs an additional level of indirection
I would like your input.
Thank you
Cheers
Matias
Edit: Added a disadvantage to Option 2 I didn't see at the time.



