Skip to content

Streamline DLSS-G (Vulkan) — pacer reuses its present-semaphore -> VUID-vkQueueSubmit-pSignalSemaphores-00067 #112

Description

@WoozChucky

Summary

With DLSS-G enabled through Streamline's Vulkan interposer, the validation layer reports
VUID-vkQueueSubmit-pSignalSemaphores-00067 every frame. SL's own pacer queue
(nv.sl.dlss_g.cmdQ.pacer) re-signals its own present-semaphore
(nv.sl.dlss_g.cmdCtx.pacer.present-semaphore) for a new swapchain image before the previously
presented image using that semaphore has been re-acquired (or waited on with a
VK_KHR_swapchain_maintenance1 present fence). All objects in the error are SL-owned
(nv.sl.dlss_g.*); the application never submits to that queue or signals that semaphore.

Environment

  • GPU: NVIDIA GeForce RTX 5090 (discrete).
  • Driver: NVIDIA 610.47 (driverVersion 610.47.0.0).
  • Vulkan: instance/loader 1.4.350, device apiVersion 1.4.341; app requests VK_API_VERSION_1_4.
  • Vulkan SDK: 1.4.350.0. Validation layer: VK_LAYER_KHRONOS_validation (1.4.350 SDK).
  • OS: Windows 11 Pro 10.0.26200 (x64).
  • Streamline SDK: v2.12.0 (interposer mode — slInit → interposing vkGetInstanceProcAddr fed to
    the Vulkan loader). Also reproduced on v2.11.1.
  • SL features loaded: kFeatureDLSS (Super-Res/DLAA), kFeatureDLSS_RR, kFeatureReflex,
    kFeaturePCL, kFeatureDLSS_G. (The repro requires kFeatureDLSS_G; with it removed and the other
    four still loaded, the run is 100% validation-clean.)

Enabled Vulkan extensions (application-requested; Streamline adds its own DLSS/Reflex instance+device extensions transparently via the interposer)

  • Instance: VK_KHR_surface, VK_KHR_win32_surface (GLFW), VK_EXT_debug_utils (debug builds).
    (VK_EXT_validation_features is intentionally NOT requested when SL interposes — SL's vkCreateInstance
    wrapper rejects it.)
  • Device: VK_KHR_swapchain, VK_EXT_memory_budget, VK_KHR_acceleration_structure,
    VK_KHR_ray_query, VK_KHR_deferred_host_operations.
  • Relevant enabled features: Vulkan 1.2 (descriptorIndexing, timelineSemaphore, bufferDeviceAddress,
    runtimeDescriptorArray, descriptorBinding*), Vulkan 1.3 (privateData, synchronization2,
    dynamicRendering), extendedDynamicState, accelerationStructure, rayQuery, multiDrawIndirect,
    drawIndirectFirstInstance, samplerAnisotropy, shaderDrawParameters.

Application present/sync setup (the app already follows the recommended 00067-avoiding pattern)

  • UNORM swapchain (VK_FORMAT_B8G8R8A8_UNORM, eSrgbNonlinear), imageUsage = COLOR_ATTACHMENT | TRANSFER_SRC | TRANSFER_DST, minImageCount 3 (also tried 6), present via vkQueuePresentKHR (interposed).
  • The application's render-finished binary semaphores are allocated per swapchain image and indexed by
    the acquired image index
    (approach (a) from the swapchain-semaphore-reuse guide — the recommended way
    to avoid 00067); acquire (present-complete) semaphores are per-frame; single graphics+present queue;
    timeline semaphore for frame pacing. So the application's own present synchronization does not trip
    00067. The flagged semaphore (nv.sl.dlss_g.cmdCtx.pacer.present-semaphore) is not an application
    semaphore — it is signaled on SL's own pacer queue, which does not follow either recommended approach.

Repro

  1. Initialize Streamline in interposer mode; load DLSS-G.
  2. Render + present normally through the interposed swapchain.
  3. The VUID fires continuously — even with DLSS-G mode = eOff (the pacer owns present once DLSS-G is
    loaded), i.e. it does not require an active frame-generation multiplier.

Exact validation message

Capture from the baseline config: minImageCount requested = 3, driver allocated exactly 3
images
(confirmed via vkGetSwapchainImagesKHR), no VK_KHR_swapchain_maintenance1.

vkQueueSubmit(): pSubmits[0].pSignalSemaphores[1] (VkSemaphore 0x...[nv.sl.dlss_g.cmdCtx.pacer.present-semaphore])
is being signaled by VkQueue 0x...[nv.sl.dlss_g.cmdQ.pacer], but it may still be in use by VkSwapchainKHR 0x...[Swapchain].
Most recently acquired image indices: 0, 0, 0, 0, 0, 0, [0], 1.
(Brackets mark the last use of VkSemaphore 0x...[nv.sl.dlss_g.cmdCtx.pacer.present-semaphore] in a presentation operation.)
Swapchain image 0 was presented but was not re-acquired, so VkSemaphore 0x...[nv.sl.dlss_g.cmdCtx.pacer.present-semaphore]
may still be in use and cannot be safely reused with image index 1.
(VUID-vkQueueSubmit-pSignalSemaphores-00067)

Notes: the swapchain has 3 images (0, 1, 2); the "Most recently acquired image indices" line is
the validation layer's fixed rolling history of the last 8 vkAcquireNextImageKHR calls (not the image
count) — here the driver returned images 0/1 across those 8 acquires. With
VK_KHR_swapchain_maintenance1 enabled the wording changes to "…was neither re-acquired nor waited on
using a VK_KHR_swapchain_maintenance1 fence…"
(see the verification notes below).

What was verified (application-side, all confirmed NOT the cause)

  • Application does not own the offending objects. Logged every application vkCreateImage handle —
    the swapchain backbuffer SL copies/presents is not among them; the semaphore + queue are nv.sl.dlss_g.*.
  • --no-sl (no interposer) is 100% validation-clean — the error only exists when SL DLSS-G is active.
  • Not loading kFeatureDLSS_G (everything else SL — DLSS/DLAA/RR/Reflex/PCL — still loaded) is 100%
    validation-clean.
    This isolates the error entirely to SL spinning up the DLSS-G pacer; it is unrelated
    to the application's synchronization2/barrier usage or its own present synchronization.
  • Enabling VK_KHR/EXT_swapchain_maintenance1 does NOT help. We enabled VK_EXT_surface_maintenance1
    (+ VK_KHR_get_surface_capabilities2) at instance level and VK_EXT_swapchain_maintenance1 + its feature
    at device level (SL did not reject these; the device created successfully). The validation message then
    updated to "…nor waited on using a VK_KHR_swapchain_maintenance1 fence…" — i.e. the capability is
    present — but the pacer still does not use a present fence, so the VUID persists. The pacer's present
    path does not adopt maintenance1 fences even when the device supports them.
  • Increasing the requested swapchain minImageCount does NOT help. Bumping from 3 to 6 made the
    acquired-image indices cycle across all images (e.g. 2, 1, 3, 0, 4, 2, [1], 5 instead of 0, 0, …, [0], 1),
    confirming more images are in flight — but the pacer still reuses a single present-semaphore across
    them, so the VUID persists unchanged. The pacer does not allocate a present-semaphore per swapchain image.

Expected behavior

Per the Vulkan swapchain-semaphore-reuse guidance
(https://docs.vulkan.org/guide/latest/swapchain_semaphore_reuse.html), the code that calls
vkQueuePresentKHR (here, SL's pacer) must either (a) use a separate present-semaphore per swapchain
image, indexed by the acquired image index
, or (b) use a VK_KHR_swapchain_maintenance1 present
fence
. The pacer currently does neither, reusing a single present-semaphore across images before the
prior present completes.

Request

Have the DLSS-G Vulkan pacer either allocate per-acquired-image present-semaphores or adopt
VK_KHR_swapchain_maintenance1 present fences (when the device enables the extension) so it no longer
trips VUID-vkQueueSubmit-pSignalSemaphores-00067.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ackAcknowledged. We may or may not do something, but won’t commit either way.bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions