3

I use the combination of DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT, GetFrameLatencyWaitableObject() and SetMaximumFrameLatency(UINT MaxLatency) to control the input lag vs. smoothness of my application as explained at https://learn.microsoft.com/en-us/windows/uwp/gaming/reduce-latency-with-dxgi-1-3-swap-chains. A value of 1 gives the lowest input lag, but sometimes I need a higher value to reduce jitter/stutter/slowdown caused by cpu and gpu cannot really work in parallel when the value is 1.

I want to be able to dynamically change this value based on the required input lag vs smoothness trade-off.

The problem I have noticed is that while it's possible to, between frames, increase this value by calling SetMaximumFrameLatency with a higher value than set before, I see no effect when decreasing this value by calling the function again with a lower value than the maximum value ever set for this swap chain by a previous call to the same function. So if I ever set it to 2, it is not possible to set it to 1 later. Is this a bug or undocumented "feature"? Or did I do something wrong?

The API itself does not return any error or similar; from the API point of view it appears to apply the new lower value correctly.

To test this, I have BufferCount = 16 and then adjust the max latency value from 1 to 16 which makes the current latency obvious to the eye. It's therefore apparent that dxgi does not apply new lower values.

I've tried to call functions in different orders, close the handle for the waitable object and recreate a new one when modifying the latency, but nothing works. The only workaround so far I'm aware of is to fully recreate the swap chain, which is annoying due to the requirement to unbind all context objects etc.

When initializing the game, I create the swap chain and set an initial latency using SetMaximumFrameLatency.

The game loop is then basically this:

  1. Call WaitForSingleObject on the waitable object handle.
  2. Process inputs.
  3. Render and present a frame.
  4. If it's decided that the latency should change at this point, call SetMaximumFrameLatency with the new value.

Other info:

  • Renderer: Direct3D 11
  • OS: Windows 11 21H2 version 22000.675
  • Graphics card: Intel UHD Graphics 620 / Nvidia GeForce MX150 (tried with both cards) with latest drivers, supporting WDDM 3.0
  • App type: Win32 desktop application
Emil
  • 16,784
  • 2
  • 41
  • 52
  • 1
    Not an answer to the question, but you could read through [Profiling DirectX Apps](https://learn.microsoft.com/en-us/windows/win32/direct2d/profiling-directx-applications) to verify your assumptions (and possibly even determine what's causing the issue). – IInspectable May 21 '22 at 07:24
  • 1
    Not sure this API implementation allows dynamic changes (have you tried to set it to 0 to reset it? untested; Also have you checked if the debug layer displays any warning output?) It's more a way of telling the system what kind of app you are (ie: game vs video playback, etc.). If you need more dynamic latency management, Windows 11 Composition Swapchain is the evolution of all this. https://learn.microsoft.com/en-us/windows/win32/comp_swapchain/comp-swapchain-portal – Simon Mourier May 21 '22 at 08:01
  • With GPUVIew I see in fullscreen that the Flip Queue has always 15 queued frames even after I revert from 16 to 1 in the frame latency setting. Setting it to 0 results in "DXGI ERROR: IDXGISwapChain2::SetMaximumFrameLatency: MaxLatency must be between 1 and 40. [ MISCELLANEOUS ERROR #218: ]". Neither DXGI nor D3D11 debug output prints anything related to this when I decrease the value (to a valid one). – Emil May 21 '22 at 10:14
  • I've experimented with WIn 11 Composition Swapchain, but apart from not being supported by Windows 10, the biggest issue I have is that the iflip requirements seem too strict compared to DXGI. On my computer (specs mentioned above), `IsPresentationSupportedWithIndependentFlip()` always returns false. If I try in fullscreen anyway, statistics then say DWN was used and hence one frame of extra latency. All the docs say drivers supporting WDDM 3.0 should support iflip, but trying with both my gfx cards, this method always returns false. With DXGI, iflip will always be used in fullscreen for me. – Emil May 21 '22 at 10:15
  • 1
    As far as I'm concerned, Neither *SetMaximumFrameLatency* [document](https://learn.microsoft.com/en-us/windows/win32/api/dxgi1_3/nf-dxgi1_3-idxgiswapchain2-setmaximumframelatency) nor official samples implied the Swap Chain *MaximumFrameLatency* can be changed dynamically. – YangXiaoPo-MSFT May 23 '22 at 07:10
  • 1
    The documentation doesn't say it can only be used once. Also no error is returned and no warning printed, which is otherwise common when the api is misused. Indeed, it can successfully be used to increase the value. – Emil May 23 '22 at 20:35

0 Answers0