Disable captureSceneHistory to fix VK_ERROR_DEVICE_LOST crash

The single sceneColorImage races between frames with MAX_FRAMES_IN_FLIGHT=2:
frame N-1's water shader reads it while frame N's captureSceneHistory writes
it via vkCmdCopyImage. Pipeline barriers only sync within a single command
buffer, not across submissions on the same queue.

This caused VK_ERROR_DEVICE_LOST after ~700 frames on any map with water.
Disable the capture entirely for now — water renders without refraction.

TODO: allocate per-frame scene history images to eliminate the race.
This commit is contained in:
Kelsi 2026-03-02 10:24:02 -08:00
parent f5f4467565
commit 7535084652

View file

@ -1054,18 +1054,13 @@ void Renderer::endFrame() {
vkCmdEndRenderPass(currentCmd); vkCmdEndRenderPass(currentCmd);
// Only capture scene history when water surfaces exist (avoids GPU crash on WMO-only maps // Scene-history capture is disabled: with MAX_FRAMES_IN_FLIGHT=2, the single
// where scene history images may never be properly used but layout transitions still run) // sceneColorImage can race between frame N-1's water shader read and frame N's
if (waterRenderer && waterRenderer->hasSurfaces() && currentImageIndex < vkCtx->getSwapchainImages().size()) { // transfer write, eventually causing VK_ERROR_DEVICE_LOST. Water renders
waterRenderer->captureSceneHistory( // without refraction until per-frame scene-history images are implemented.
currentCmd, // TODO: allocate per-frame sceneColor/Depth images to fix the race.
vkCtx->getSwapchainImages()[currentImageIndex],
vkCtx->getDepthCopySourceImage(),
vkCtx->getSwapchainExtent(),
vkCtx->isDepthCopySourceMsaa());
}
// Render water in separate 1x pass after MSAA resolve + scene capture // Render water in separate 1x pass (without scene refraction for now)
bool waterDeferred = waterRenderer && waterRenderer->hasSurfaces() && waterRenderer->hasWater1xPass() bool waterDeferred = waterRenderer && waterRenderer->hasSurfaces() && waterRenderer->hasWater1xPass()
&& vkCtx->getMsaaSamples() != VK_SAMPLE_COUNT_1_BIT; && vkCtx->getMsaaSamples() != VK_SAMPLE_COUNT_1_BIT;
if (waterDeferred && camera) { if (waterDeferred && camera) {