The M2 cull SSBO upload and the CPU-fallback culling path both
recomputed worldRadius / cullRadius / effectiveMaxDistSqFactor /
paddedRadius for every instance every frame, even though all of
those values depend only on static instance state (bound radius,
scale, disable-animation flag, ground-detail flag).
Add recomputeCachedCullFactors() to M2Instance and call it once
when an instance is added (both addInstance overloads). The
per-frame upload reduces to one multiply (maxRenderDistanceSq *
cached factor) plus flag packing, and the CPU-fallback culling
path drops the same redundant math. For 5000+ doodad instances
that's measurable.