Background normal map generation, queue-draining load screen warmup

- Normal map CPU work (luminance→blur→Sobel) moved to background threads,
  main thread only does GPU upload (~1-2ms vs 15-22ms per texture)
- Load screen warmup now waits until ALL spawn/equipment/gameobject queues
  are drained before transitioning (prevents naked character, NPC pop-in)
- Exit condition: min 2s + 5 consecutive empty iterations, hard cap 15s
- Equipment queue processes 8 items per warmup iteration instead of 1
- Added LoadingScreen::renderOverlay() for future world-behind-loading use
This commit is contained in:
Kelsi 2026-03-07 18:40:24 -08:00
parent 63efac9fa6
commit 02cf0e4df3
5 changed files with 218 additions and 60 deletions

View file

@ -13,6 +13,8 @@
#include <utility>
#include <future>
#include <deque>
#include <mutex>
#include <atomic>
namespace wowee {
namespace pipeline { class AssetManager; }
@ -304,15 +306,23 @@ private:
std::unique_ptr<VkTexture> generateNormalHeightMap(
const uint8_t* pixels, uint32_t width, uint32_t height, float& outVariance);
// Deferred normal map generation — avoids stalling loadModel
struct PendingNormalMap {
// Background normal map generation — CPU work on thread pool, GPU upload on main thread
struct NormalMapResult {
std::string cacheKey;
std::vector<uint8_t> pixels; // RGBA pixel data
std::vector<uint8_t> pixels; // RGBA normal map output
uint32_t width, height;
float variance;
};
std::deque<PendingNormalMap> pendingNormalMaps_;
// Completed results ready for GPU upload (populated by background threads)
std::mutex normalMapResultsMutex_;
std::deque<NormalMapResult> completedNormalMaps_;
std::atomic<int> pendingNormalMapCount_{0}; // in-flight background tasks
// Pure CPU normal map generation (thread-safe, no GPU access)
static NormalMapResult generateNormalHeightMapCPU(
std::string cacheKey, std::vector<uint8_t> pixels, uint32_t width, uint32_t height);
public:
void processPendingNormalMaps(int budget = 2);
void processPendingNormalMaps(int budget = 4);
private:
// Normal mapping / POM settings

View file

@ -24,6 +24,10 @@ public:
// Render the loading screen with progress bar and status text (pure ImGui)
void render();
// Draw loading screen as ImGui overlay (call within an existing ImGui frame).
// Used during warmup to overlay loading screen on top of the rendered world.
void renderOverlay();
void setProgress(float progress) { loadProgress = progress; }
void setStatus(const std::string& status) { statusText = status; }