mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
Fix water descriptor pool leak and add water rendering diagnostics
- Add VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT to water material descriptor pool so individual sets can be freed when tiles are unloaded - Free descriptor sets in destroyWaterMesh() instead of leaking them - Add terrain manager unloadAll() during logout to properly clear stale tiles, water surfaces, and queues between sessions - Add diagnostic logging for water surface loading, material allocation failures, and render skip reasons to investigate missing water
This commit is contained in:
parent
94e4a0bdb3
commit
872b10fe68
4 changed files with 38 additions and 5 deletions
|
|
@ -172,6 +172,7 @@ private:
|
|||
VkImageView sceneDepthView = VK_NULL_HANDLE;
|
||||
VkExtent2D sceneHistoryExtent = {0, 0};
|
||||
bool sceneHistoryReady = false;
|
||||
mutable uint32_t renderDiagCounter_ = 0;
|
||||
|
||||
// Planar reflection resources
|
||||
static constexpr uint32_t REFLECTION_WIDTH = 512;
|
||||
|
|
|
|||
|
|
@ -661,7 +661,10 @@ void Application::logoutToLogin() {
|
|||
if (auto* m2 = renderer->getM2Renderer()) {
|
||||
m2->clear();
|
||||
}
|
||||
// TerrainManager will be re-initialized on next world entry
|
||||
// Unload all terrain tiles + water surfaces so next world entry starts fresh
|
||||
if (auto* terrain = renderer->getTerrainManager()) {
|
||||
terrain->unloadAll();
|
||||
}
|
||||
if (auto* questMarkers = renderer->getQuestMarkerRenderer()) {
|
||||
questMarkers->clear();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -705,7 +705,15 @@ bool TerrainManager::advanceFinalization(FinalizingTile& ft) {
|
|||
// Load water immediately after terrain (same frame) — water is now
|
||||
// deduplicated to ~1-2 merged surfaces per tile, so this is fast.
|
||||
if (waterRenderer) {
|
||||
size_t beforeSurfaces = waterRenderer->getSurfaceCount();
|
||||
waterRenderer->loadFromTerrain(pending->terrain, true, x, y);
|
||||
size_t afterSurfaces = waterRenderer->getSurfaceCount();
|
||||
if (afterSurfaces > beforeSurfaces) {
|
||||
LOG_INFO("Water: tile [", x, ",", y, "] added ", afterSurfaces - beforeSurfaces,
|
||||
" surfaces (total: ", afterSurfaces, ")");
|
||||
}
|
||||
} else {
|
||||
LOG_WARNING("Water: waterRenderer is null during tile [", x, ",", y, "] finalization!");
|
||||
}
|
||||
|
||||
// Ensure M2 renderer has asset manager
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ bool WaterRenderer::initialize(VkContext* ctx, VkDescriptorSetLayout perFrameLay
|
|||
|
||||
VkDescriptorPoolCreateInfo poolInfo{};
|
||||
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
|
||||
poolInfo.maxSets = MAX_WATER_SETS;
|
||||
poolInfo.poolSizeCount = 1;
|
||||
poolInfo.pPoolSizes = &poolSize;
|
||||
|
|
@ -541,6 +542,8 @@ void WaterRenderer::updateMaterialUBO(WaterSurface& surface) {
|
|||
write.pBufferInfo = &bufInfo;
|
||||
|
||||
vkUpdateDescriptorSets(vkCtx->getDevice(), 1, &write, 0, nullptr);
|
||||
} else {
|
||||
LOG_WARNING("Water: failed to allocate material descriptor set (pool exhaustion?)");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -802,8 +805,10 @@ void WaterRenderer::loadFromTerrain(const pipeline::ADTTerrain& terrain, bool ap
|
|||
totalSurfaces++;
|
||||
}
|
||||
|
||||
LOG_DEBUG("Water: Loaded ", totalSurfaces, " surfaces from tile [", tileX, ",", tileY,
|
||||
"] (", mergeGroups.size(), " groups), total surfaces: ", surfaces.size());
|
||||
if (totalSurfaces > 0) {
|
||||
LOG_INFO("Water: Loaded ", totalSurfaces, " surfaces from tile [", tileX, ",", tileY,
|
||||
"] (", mergeGroups.size(), " groups), total surfaces: ", surfaces.size());
|
||||
}
|
||||
}
|
||||
|
||||
void WaterRenderer::removeTile(int tileX, int tileY) {
|
||||
|
|
@ -936,8 +941,21 @@ void WaterRenderer::clear() {
|
|||
void WaterRenderer::render(VkCommandBuffer cmd, VkDescriptorSet perFrameSet,
|
||||
const Camera& /*camera*/, float /*time*/, bool use1x) {
|
||||
VkPipeline pipeline = (use1x && water1xPipeline) ? water1xPipeline : waterPipeline;
|
||||
if (!renderingEnabled || surfaces.empty() || !pipeline) return;
|
||||
if (!sceneSet) return;
|
||||
if (!renderingEnabled || surfaces.empty() || !pipeline) {
|
||||
if (renderDiagCounter_++ % 300 == 0 && !surfaces.empty()) {
|
||||
LOG_WARNING("Water: render skipped — enabled=", renderingEnabled,
|
||||
" surfaces=", surfaces.size(),
|
||||
" pipeline=", (pipeline ? "ok" : "null"),
|
||||
" use1x=", use1x);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!sceneSet) {
|
||||
if (renderDiagCounter_++ % 300 == 0) {
|
||||
LOG_WARNING("Water: render skipped — sceneSet is null, surfaces=", surfaces.size());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||
|
||||
|
|
@ -1251,6 +1269,9 @@ void WaterRenderer::destroyWaterMesh(WaterSurface& surface) {
|
|||
destroyBuffer(allocator, ab);
|
||||
surface.materialUBO = VK_NULL_HANDLE;
|
||||
}
|
||||
if (surface.materialSet && materialDescPool) {
|
||||
vkFreeDescriptorSets(vkCtx->getDevice(), materialDescPool, 1, &surface.materialSet);
|
||||
}
|
||||
surface.materialSet = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue