Background BLP texture pre-decoding + deferred WMO normal maps (12x streaming perf)

Move CPU-heavy BLP texture decoding from main thread to background worker
threads for all hot paths: terrain M2 models, WMO doodad M2s, WMO textures,
creature models, and gameobject WMOs. Each renderer (M2, WMO, Character) now
accepts a pre-decoded BLP cache that loadTexture() checks before falling back
to synchronous decode.

Defer WMO normal/height map generation (3 per-pixel passes: luminance, box
blur, Sobel) during terrain streaming finalization — this was the dominant
remaining bottleneck after BLP pre-decoding.

Terrain streaming stalls: 1576ms → 124ms worst case.
This commit is contained in:
Kelsi 2026-03-07 15:46:56 -08:00
parent 0313bd8692
commit 7ac990cff4
13 changed files with 573 additions and 109 deletions

View file

@ -2434,6 +2434,9 @@ void Renderer::update(float deltaTime) {
cameraController->update(deltaTime);
auto cameraEnd = std::chrono::steady_clock::now();
lastCameraUpdateMs = std::chrono::duration<double, std::milli>(cameraEnd - cameraStart).count();
if (lastCameraUpdateMs > 3.0) {
LOG_WARNING("SLOW cameraController->update: ", lastCameraUpdateMs, "ms");
}
// Update 3D audio listener position/orientation to match camera
if (camera) {
@ -2779,8 +2782,15 @@ void Renderer::update(float deltaTime) {
// Update M2 doodad animations (pass camera for frustum-culling bone computation)
if (m2Renderer && camera) {
auto m2Start = std::chrono::steady_clock::now();
m2Renderer->update(deltaTime, camera->getPosition(),
camera->getProjectionMatrix() * camera->getViewMatrix());
float m2Ms = std::chrono::duration<float, std::milli>(
std::chrono::steady_clock::now() - m2Start).count();
if (m2Ms > 3.0f) {
LOG_WARNING("SLOW m2Renderer->update: ", m2Ms, "ms (",
m2Renderer->getInstanceCount(), " instances)");
}
}
// Helper: play zone music, dispatching local files (file: prefix) vs MPQ paths