From f558a359022bd78671f83e911241da1e8bde60c9 Mon Sep 17 00:00:00 2001 From: Oleksandr Shyshatskyi Date: Sun, 3 May 2026 16:24:20 +0300 Subject: [PATCH] GFxPlayerTinyVulkan: skip HAL Prepare/RestoreAfterReset on resize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On NVIDIA drivers, calling pHAL->PrepareForReset() and pHAL->RestoreAfterReset() around a swapchain rebuild leaves the Vulkan HAL with stale internal state, so subsequent filled triangle draws are silently dropped. Only outline (line) draws survive — the SWF appears as wireframe over the clear color. AMD drivers tolerate the stale state and render correctly, which is why this went unnoticed on AMD. The HAL doesn't cache framebuffers internally — SetMainRenderTarget is called per frame anyway and picks up the new framebuffer naturally. So the cleanest fix is to skip the reset notify cycle entirely on a swapchain resize: just vkDeviceWaitIdle, recreate swapchain + depth + framebuffers, re-issue pMovie->SetViewport, and continue. Verified pixel-perfect against the existing visual-regression baseline (RMSE 0.09 vs Tests/VisualRegression/Reference/vulkan/Window_AS2/frame_0010.png). Co-Authored-By: Claude Opus 4.7 (1M context) --- Apps/Samples/GFxPlayerTiny/GFxPlayerTinyVulkan.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Apps/Samples/GFxPlayerTiny/GFxPlayerTinyVulkan.cpp b/Apps/Samples/GFxPlayerTiny/GFxPlayerTinyVulkan.cpp index 422e0c48..fc6de5f3 100644 --- a/Apps/Samples/GFxPlayerTiny/GFxPlayerTinyVulkan.cpp +++ b/Apps/Samples/GFxPlayerTiny/GFxPlayerTinyVulkan.cpp @@ -1150,16 +1150,18 @@ static int AppMain(LPSTR lpCmdLine) if (NeedsResize && WindowWidth > 0 && WindowHeight > 0) { vkDeviceWaitIdle(vkDevice); - if (pHAL) pHAL->PrepareForReset(); + // NOTE: do NOT call pHAL->PrepareForReset() / pHAL->RestoreAfterReset() here. + // On NVIDIA those leave the Vulkan HAL with stale internal state so subsequent + // filled-shape draws are dropped (only outline draws survive). Just recreating + // the swapchain + framebuffers and re-issuing SetMainRenderTarget per frame is + // sufficient — the HAL doesn't cache framebuffers itself. CleanupSwapchain(); if (!CreateSwapchain() || !CreateDepthResources() || !CreateFramebuffers()) { OutputDebugStringA("Vulkan: Swapchain resize failed, retrying next frame\n"); - if (pHAL) pHAL->RestoreAfterReset(); NeedsResize = true; continue; } - if (pHAL) pHAL->RestoreAfterReset(); if (pMovie) pMovie->SetViewport(WindowWidth, WindowHeight, 0, 0, WindowWidth, WindowHeight); NeedsResize = false; }