Fix the ImGui overlay and DLSS-G interlock under vkd3d-proton #1138
No reviewers
Labels
No labels
0.9
3rd party
bug
documentation
duplicate
enhancement
invalid
linux
master
question
undetermined
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
roman/OptiScaler2!1138
Loading…
Reference in a new issue
No description provided.
Delete branch "y4my4my4m/proton-overlay-fixes"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Opening the OptiScaler menu on a D3D12 game under Proton removes the GPU device. This fixes that, and four related problems found while tracking it down.
Tested on an RTX 4090 / Cyberpunk 2077 / vkd3d-proton. Builds clean.
The overlay draws through Vulkan on a D3D12 game
IdentifyGpu::getPrimaryGpu().usesDxvkis true for a vkd3d-proton D3D12 title as well as a DXVK D3D11 one, soLocalPresenttakes the early return atwrapped_swapchain.cpp:327andMenuOverlayDx::Presentis never reached.MenuOverlayVkbecomes the live ImGui backend.It then submits on a
VkQueueit selected itself, unserialised, into the present path Streamline owns._vkPresentMutexis declared twice --menu_overlay_vk.cpp:20andVulkan_Hooks.cpp:33-- and locked nowhere; thelock_guardat:514is commented out. With DLSS-G active, the first menu open removes the device:VK_ERROR_DEVICE_LOSTreported by vkd3d's ownhk_vkQueueSubmit2about half a second after the overlay's submit.Measured across two runs: menu open with DLSS-G off survived 1257 overlay submits; with DLSS-G on it died after 4. A separate 82-second run with DLSS-G on and the menu never opened had zero device losses.
The early return is now D3D11 only, so these titles reach
MenuOverlayDx::Presentand draw on the game's own queue.ImGui holds one renderer backend in
io.BackendRendererUserDataandvkCreateSwapchainKHRis hooked either way, so both overlays would claim it.MenuOverlayVkstands down for a vkd3d-proton D3D12 swapchain, andMenuOverlayDx::Presentcarries the reverse guard in case a different DXVK build creates the VkSwapchain first. Worst case becomes no overlay rather than a wild pointer.The DLSS-G interlock never armed
Streamline_Hooks.cppalready forcesDLSSGMode::eOffwitheRetainResourcesWhenOffwhile the menu is visible, and chargesdelayMenuRenderBy-- exactly the protection needed here. It is keyed onstate.swapchainApi == API::Vulkan. Under vkd3d-proton that value isDX12while the Vulkan overlay is the live backend, so the guard silently never applied.It is now keyed on the overlay, via a new
State::menuOverlayIsVulkanset whenMenuOverlayVk's objects are built and cleared on every teardown path.swapchainApiis deliberately left alone: it also drivesmenu_common.cpp:3197-3275and:4643-4690, and flipping it would grey out DLSS-G and FSR-FG in the menu.The gate is factored into
StreamlineHooks::applyMenuDlssgInterlockand called fromDLSSG_Dx12::Dispatchtoo, which pushedeOnthrough the rawStreamlineProxy::DLSSGSetOptionsexport and bypassed the hook entirely.The frozen check trips under frame generation
TickFrozenCheckruns per present;_frameCountadvances per evaluate. Two problems: these titles reach bothLocalPresentandhkvkQueuePresentKHR, so it ticked twice per present and halved the threshold; and the flat> 10assumes one present per evaluate, which frame generation breaks by design. At 4X and above the feature reads as frozen while the game is running, and the menu flashes "is active, but not currently used by the game" every few frames.One tick per present, and the threshold scales with
dlssgDetectedInterpolationCount.DisableFlipMetering stopped working with Streamline 2.14
dllmain.cpponly loads and hooks NVAPI whennvapi64.dllis already present, which at init it is not. Streamline 2.14 resolves its NVAPI entry points as it initialises -- before theQueryInterfacedetour is installed -- so the module is hooked but the caller holds pre-hook addresses and the deny list is never consulted.Confirmed by log ordering:
nvapi64.dllloads at12.690, the hook lands at12.819. With the window closed,FlipMetering is disabled!fires; without it, never.NVAPI is now loaded and hooked up front when the option asks for it, guarded on Nvidia and on the option being set, so no process gains NVAPI it would not otherwise have had.
Three latent defects in menu_overlay_vk
Found while diagnosing the above. None caused the device loss; the second cost real diagnosis time.
_ImVulkan_Info.CheckVkResultFnwas never assigned, so ImGui's Vulkan backend discarded everyVkResultincludingDEVICE_LOST(imgui_impl_vulkan.cpp:429is a no-op without it).fd->BackbufferViewafter the preceding block had nulled it, so framebuffers were never destroyed.QueuePresentandDestroyVulkanObjectswere unserialised. Now_vkCleanMutex, released acrossMenuOverlayBase::RenderMenuand re-validated on re-acquisition --RenderMenucan re-enterDestroyVulkanObjectsthroughIdentifyGpu::getPrimaryGpu()and the swapchain hook, so a non-recursive mutex held across it would deadlock. The dead duplicate_vkPresentMutexdeclarations are removed.Scope
Windows and native-Vulkan behaviour is unchanged:
menuOverlayIsVulkanis false there and every gate evaluates as before. The routing change affects Proton D3D12 titles, which is the population currently losing the device.Not runtime-tested on Windows or on a native Vulkan title; I have neither.
View command line instructions
Manual merge helper
Use this merge commit message when completing the merge manually.
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.