mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-03 20:03:50 +00:00
refactor: extract fallback textures, add why-comments, name WMO constant
- character_renderer: extract duplicated fallback texture creation (white/transparent/flat-normal) into createFallbackTextures() — was copy-pasted between initialize() and clear() - wmo_renderer: replace magic 8192 with kMaxRetryTracked constant, add why-comment explaining the fallback-retry set cap (Dalaran has 2000+ unique WMO groups) - quest_handler: add why-comment on reqCount=0 fallback — escort/event quests can report kill credit without objective counts in query response
This commit is contained in:
parent
f313eec24e
commit
4acebff65c
4 changed files with 40 additions and 44 deletions
|
|
@ -251,6 +251,10 @@ public:
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Create 1×1 fallback textures used when real textures are missing or still loading.
|
||||||
|
// Called during both init and clear to ensure valid descriptor bindings at all times.
|
||||||
|
void createFallbackTextures(VkDevice device);
|
||||||
|
|
||||||
VkContext* vkCtx_ = nullptr;
|
VkContext* vkCtx_ = nullptr;
|
||||||
VkRenderPass renderPassOverride_ = VK_NULL_HANDLE;
|
VkRenderPass renderPassOverride_ = VK_NULL_HANDLE;
|
||||||
VkSampleCountFlagBits msaaSamplesOverride_ = VK_SAMPLE_COUNT_1_BIT;
|
VkSampleCountFlagBits msaaSamplesOverride_ = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
|
|
||||||
|
|
@ -533,7 +533,10 @@ void QuestHandler::registerOpcodes(DispatchTable& table) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (reqCount == 0) reqCount = count; // last-resort: avoid 0/0 display
|
// Some quests (e.g. escort/event quests) report kill credit updates without
|
||||||
|
// a corresponding objective count in SMSG_QUEST_QUERY_RESPONSE. Fall back to
|
||||||
|
// current count so the progress display shows "N/N" instead of "N/0".
|
||||||
|
if (reqCount == 0) reqCount = count;
|
||||||
quest.killCounts[entry] = {count, reqCount};
|
quest.killCounts[entry] = {count, reqCount};
|
||||||
|
|
||||||
std::string creatureName = owner_.getCachedCreatureName(entry);
|
std::string creatureName = owner_.getCachedCreatureName(entry);
|
||||||
|
|
|
||||||
|
|
@ -278,29 +278,7 @@ bool CharacterRenderer::initialize(VkContext* ctx, VkDescriptorSetLayout perFram
|
||||||
charVert.destroy();
|
charVert.destroy();
|
||||||
charFrag.destroy();
|
charFrag.destroy();
|
||||||
|
|
||||||
// --- Create white fallback texture ---
|
createFallbackTextures(device);
|
||||||
{
|
|
||||||
uint8_t white[] = {255, 255, 255, 255};
|
|
||||||
whiteTexture_ = std::make_unique<VkTexture>();
|
|
||||||
whiteTexture_->upload(*vkCtx_, white, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, false);
|
|
||||||
whiteTexture_->createSampler(device, VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_ADDRESS_MODE_REPEAT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Create transparent fallback texture ---
|
|
||||||
{
|
|
||||||
uint8_t transparent[] = {0, 0, 0, 0};
|
|
||||||
transparentTexture_ = std::make_unique<VkTexture>();
|
|
||||||
transparentTexture_->upload(*vkCtx_, transparent, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, false);
|
|
||||||
transparentTexture_->createSampler(device, VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_ADDRESS_MODE_REPEAT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Create flat normal placeholder texture (128,128,255,128) = neutral normal, 0.5 height ---
|
|
||||||
{
|
|
||||||
uint8_t flatNormal[] = {128, 128, 255, 128};
|
|
||||||
flatNormalTexture_ = std::make_unique<VkTexture>();
|
|
||||||
flatNormalTexture_->upload(*vkCtx_, flatNormal, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, false);
|
|
||||||
flatNormalTexture_->createSampler(device, VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_ADDRESS_MODE_REPEAT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Diagnostics-only: cache lifetime is currently tied to renderer lifetime.
|
// Diagnostics-only: cache lifetime is currently tied to renderer lifetime.
|
||||||
textureCacheBudgetBytes_ = envSizeMBOrDefault("WOWEE_CHARACTER_TEX_CACHE_MB", 4096) * 1024ull * 1024ull;
|
textureCacheBudgetBytes_ = envSizeMBOrDefault("WOWEE_CHARACTER_TEX_CACHE_MB", 4096) * 1024ull * 1024ull;
|
||||||
|
|
@ -449,24 +427,7 @@ void CharacterRenderer::clear() {
|
||||||
whiteTexture_.reset();
|
whiteTexture_.reset();
|
||||||
transparentTexture_.reset();
|
transparentTexture_.reset();
|
||||||
flatNormalTexture_.reset();
|
flatNormalTexture_.reset();
|
||||||
{
|
createFallbackTextures(device);
|
||||||
uint8_t white[] = {255, 255, 255, 255};
|
|
||||||
whiteTexture_ = std::make_unique<VkTexture>();
|
|
||||||
whiteTexture_->upload(*vkCtx_, white, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, false);
|
|
||||||
whiteTexture_->createSampler(device, VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_ADDRESS_MODE_REPEAT);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
uint8_t transparent[] = {0, 0, 0, 0};
|
|
||||||
transparentTexture_ = std::make_unique<VkTexture>();
|
|
||||||
transparentTexture_->upload(*vkCtx_, transparent, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, false);
|
|
||||||
transparentTexture_->createSampler(device, VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_ADDRESS_MODE_REPEAT);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
uint8_t flatNormal[] = {128, 128, 255, 128};
|
|
||||||
flatNormalTexture_ = std::make_unique<VkTexture>();
|
|
||||||
flatNormalTexture_->upload(*vkCtx_, flatNormal, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, false);
|
|
||||||
flatNormalTexture_->createSampler(device, VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_ADDRESS_MODE_REPEAT);
|
|
||||||
}
|
|
||||||
|
|
||||||
models.clear();
|
models.clear();
|
||||||
instances.clear();
|
instances.clear();
|
||||||
|
|
@ -487,6 +448,30 @@ void CharacterRenderer::clear() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CharacterRenderer::createFallbackTextures(VkDevice device) {
|
||||||
|
// White: default diffuse when no texture is assigned
|
||||||
|
{
|
||||||
|
uint8_t white[] = {255, 255, 255, 255};
|
||||||
|
whiteTexture_ = std::make_unique<VkTexture>();
|
||||||
|
whiteTexture_->upload(*vkCtx_, white, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, false);
|
||||||
|
whiteTexture_->createSampler(device, VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_ADDRESS_MODE_REPEAT);
|
||||||
|
}
|
||||||
|
// Transparent: placeholder for optional overlay layers (e.g. hair highlights)
|
||||||
|
{
|
||||||
|
uint8_t transparent[] = {0, 0, 0, 0};
|
||||||
|
transparentTexture_ = std::make_unique<VkTexture>();
|
||||||
|
transparentTexture_->upload(*vkCtx_, transparent, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, false);
|
||||||
|
transparentTexture_->createSampler(device, VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_ADDRESS_MODE_REPEAT);
|
||||||
|
}
|
||||||
|
// Flat normal: neutral normal map (128,128,255) + 0.5 height in alpha channel
|
||||||
|
{
|
||||||
|
uint8_t flatNormal[] = {128, 128, 255, 128};
|
||||||
|
flatNormalTexture_ = std::make_unique<VkTexture>();
|
||||||
|
flatNormalTexture_->upload(*vkCtx_, flatNormal, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, false);
|
||||||
|
flatNormalTexture_->createSampler(device, VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_ADDRESS_MODE_REPEAT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CharacterRenderer::destroyModelGPU(M2ModelGPU& gpuModel) {
|
void CharacterRenderer::destroyModelGPU(M2ModelGPU& gpuModel) {
|
||||||
if (!vkCtx_) return;
|
if (!vkCtx_) return;
|
||||||
VmaAllocator alloc = vkCtx_->getAllocator();
|
VmaAllocator alloc = vkCtx_->getAllocator();
|
||||||
|
|
|
||||||
|
|
@ -363,12 +363,16 @@ bool WMORenderer::loadModel(const pipeline::WMOModel& model, uint32_t id) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Track which WMO models have been force-reloaded after resolving only to
|
||||||
|
// fallback textures. Cap the set to avoid unbounded memory growth in worlds
|
||||||
|
// with many unique WMO groups (e.g. Dalaran has 2000+).
|
||||||
|
static constexpr size_t kMaxRetryTracked = 8192;
|
||||||
static std::unordered_set<uint32_t> retryReloadedModels;
|
static std::unordered_set<uint32_t> retryReloadedModels;
|
||||||
static bool retryReloadedModelsCapped = false;
|
static bool retryReloadedModelsCapped = false;
|
||||||
if (retryReloadedModels.size() > 8192) {
|
if (retryReloadedModels.size() > kMaxRetryTracked) {
|
||||||
retryReloadedModels.clear();
|
retryReloadedModels.clear();
|
||||||
if (!retryReloadedModelsCapped) {
|
if (!retryReloadedModelsCapped) {
|
||||||
core::Logger::getInstance().warning("WMO fallback-retry set exceeded 8192 entries; reset");
|
core::Logger::getInstance().warning("WMO fallback-retry set exceeded ", kMaxRetryTracked, " entries; reset");
|
||||||
retryReloadedModelsCapped = true;
|
retryReloadedModelsCapped = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue