From fa97d01b0da34e9f764e8dc334e58e5a9d236bb5 Mon Sep 17 00:00:00 2001 From: jpolo1224 Date: Mon, 10 Aug 2026 23:14:07 -0400 Subject: [PATCH] VK: do not emulate predication where we disabled the extension ourselves Emulated conditional rendering exists for hardware that never had the extension. Turning the extension off as a driver workaround enabled it by accident, because both are selected by the same test, and the two halves do not fit together: begin_conditional_rendering returns early without building m_cond_render_buffer, while the vertex shader still reads that buffer at offset 0. It gets a zeroed scratch buffer, predicates every draw away, and the game renders black with audio and overlays still running. The all-ones word that disables predication sits at offset 4 and is never reached, since the fallback leaves hw_cond_active set. Off on these drivers means occlusion results stop culling draws, which is the trade the workaround already documents. The vendor comes off the GPU rather than from get_driver_vendor(), whose cached value is not assigned until later in the same function and would still hold the previous device's. --- rpcs3/Emu/RSX/VK/VKHelpers.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.cpp b/rpcs3/Emu/RSX/VK/VKHelpers.cpp index feda1a62b..57ab0e92e 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.cpp +++ b/rpcs3/Emu/RSX/VK/VKHelpers.cpp @@ -102,7 +102,27 @@ namespace vk g_drv_sanitize_fp_values = false; g_drv_disable_fence_reset = false; g_drv_strict_query_scopes = !!g_cfg.video.strict_rendering_mode; - g_drv_emulate_cond_render = (g_cfg.video.relaxed_zcull_sync && !g_render_device->get_conditional_render_support()); + // Emulated predication is for hardware that never had the extension. Where we turned it + // off ourselves as a driver workaround, it must stay off: the two are the same code + // path, and turning the extension off makes begin_conditional_rendering return before it + // builds m_cond_render_buffer, while the vertex shader keeps reading that buffer at + // offset 0. It finds a zeroed scratch buffer, predicates every draw away, and the game + // renders black with audio and overlays still running. The all-ones word that disables + // predication lives at offset 4 and is never reached, because the fallback leaves + // hw_cond_active set. + // + // Off means occlusion results stop culling draws, which is the trade the workaround + // already documents: more GPU work, and a session that survives. + // Straight off the GPU: the cached g_driver_vendor is not assigned until further down + // this function, so get_driver_vendor() would still hold the previous device's value. + const auto cond_render_vendor = g_render_device->gpu().get_driver_vendor(); + const bool cond_render_blocked_by_driver = + cond_render_vendor == vk::driver_vendor::ADRENO || + cond_render_vendor == vk::driver_vendor::TURNIP; + + g_drv_emulate_cond_render = (g_cfg.video.relaxed_zcull_sync && + !g_render_device->get_conditional_render_support() && + !cond_render_blocked_by_driver); g_num_processed_frames = 0; g_num_total_frames = 0; g_heap_compatible_buffer_types = 0;