IMGUI: draw the overlay into the NGX output image on Vulkan (DLSS / DLSS-G) - #596
Open
thierbig wants to merge 1 commit into
Open
IMGUI: draw the overlay into the NGX output image on Vulkan (DLSS / DLSS-G)#596thierbig wants to merge 1 commit into
thierbig wants to merge 1 commit into
Conversation
When DLSS / DLSS-G is active the game presents the NGX-upscaled image rather than the swapchain image the ImGui overlay was rendered into, so the extender UI is invisible while upscaling is on. Hook NVSDK_NGX_VULKAN_EvaluateFeature_C (probing sl.interposer.dll, nvngx_dlss.dll and nvngx.dll) and, after NGX has produced its output, fetch the output image view from the NGX parameter block and render the ImGui draw data into it inside a LOAD_OP_LOAD render pass, restoring the image layout afterwards. Render passes are cached per format and framebuffers per image view. Also chain vkQueuePresentKHR / vkCreateSwapchainKHR through sl.interposer.dll when Streamline is loaded, so the present hook sits on the interposer rather than under it. Fix the function pointer types in hookDevice(): vkCreateSwapchainKHR, vkDestroySwapchainKHR and vkQueuePresentKHR were being cast to PFN_vkCreatePipelineCache* / PFN_vkQueuePresentKHR* (pointer-to-function- pointer), which happened to work but is not the declared type.
This was referenced Aug 13, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When DLSS / DLSS-G is active, the game presents the NGX-upscaled image rather than the swapchain image that the ImGui overlay was rendered into. The result is that the extender UI is completely invisible while upscaling is enabled — the overlay is drawn, but into an image that never reaches the screen.
Approach
Hook
NVSDK_NGX_VULKAN_EvaluateFeature_C, probingsl.interposer.dll,nvngx_dlss.dllandnvngx.dllin that order. The hook is installed lazily fromNewFrame(), since the NGX module is generally not loaded yet at backend-init time.After NGX has produced its output, the hook fetches the output image view out of the NGX parameter block via
NVSDK_NGX_Parameter_GetVoidPointerand renders the ImGui draw data into it inside aLOAD_OP_LOADrender pass, so the upscaled image is preserved and the overlay composites on top. The image is transitionedGENERAL→COLOR_ATTACHMENT_OPTIMALfor the pass and back toGENERALafterwards, so downstream consumers (frame generation in particular) see the layout they expect. Render passes are cached perVkFormatand framebuffers perVkImageView.vkQueuePresentKHRandvkCreateSwapchainKHRare also chained throughsl.interposer.dllwhen Streamline is loaded, so the present hook sits on top of the interposer rather than underneath it.Everything is gated on the NGX module actually being present — with no upscaler loaded,
tryInstallNgxEvaluateFeatureHook()finds nothing and the existing swapchain path is unchanged.Drive-by fix
hookDevice()was casting three device function pointers to the wrong types:These are pointer-to-function-pointer types, and the first two name the wrong function entirely. It works today because the value is passed straight through to
ResolveFunctionTrampoline, but it defeats type checking. Corrected to the declaredPFN_types with explicitreinterpret_cast.Notes
Single file,
Vulkan.inl, +276/-6. No changes to build configuration or third-party dependencies — the NGX types the hook needs are declared locally rather than pulling in the NGX SDK as a dependency.This supersedes #595, which was opened as a full fork sync and so carried the fork.s vendored
External/tree and local build configuration alongside this change. This PR isolates the feature.