fix: wait for GPU idle before freeing M2/WMO model buffers to prevent device lost

cleanupUnusedModels() runs every 5 seconds and freed vertex/index buffers
without waiting for the GPU to finish the previous frame's command buffer.
This caused VK_ERROR_DEVICE_LOST (-4) after extended gameplay when tiles
stream out and their models are freed mid-render.

Add vkDeviceWaitIdle() before the buffer destroy loop in both M2Renderer
and WMORenderer cleanupUnusedModels(). The wait only happens when there are
models to remove, so quiet sessions have no overhead.
This commit is contained in:
Kelsi 2026-03-12 19:01:15 -07:00
parent eafd09aca0
commit cd01d07a91
2 changed files with 14 additions and 2 deletions

View file

@ -3905,7 +3905,14 @@ void M2Renderer::cleanupUnusedModels() {
}
}
// Delete GPU resources and remove from map
// Delete GPU resources and remove from map.
// Wait for the GPU to finish all in-flight frames before destroying any
// buffers — the previous frame's command buffer may still be referencing
// vertex/index buffers that are about to be freed. Without this wait,
// the GPU reads freed memory, which can cause VK_ERROR_DEVICE_LOST.
if (!toRemove.empty() && vkCtx_) {
vkDeviceWaitIdle(vkCtx_->getDevice());
}
for (uint32_t id : toRemove) {
auto it = models.find(id);
if (it != models.end()) {

View file

@ -835,7 +835,12 @@ void WMORenderer::cleanupUnusedModels() {
}
}
// Delete GPU resources and remove from map
// Delete GPU resources and remove from map.
// Ensure all in-flight frames are complete before freeing vertex/index buffers —
// the GPU may still be reading them from the previous frame's command buffer.
if (!toRemove.empty() && vkCtx_) {
vkDeviceWaitIdle(vkCtx_->getDevice());
}
for (uint32_t id : toRemove) {
unloadModel(id);
}