Skip to content

Commit 62deee7

Browse files
committed
Expand the sections regarding Jitter, Stutter and Latency
1 parent 77d6ca0 commit 62deee7

8 files changed

+339
-0
lines changed
13.1 KB
Loading
36 KB
Loading
28.6 KB
Loading
26.6 KB
Loading
35.2 KB
Loading
23.2 KB
Loading
20 KB
Loading

tutorials/rendering/jitter_stutter.rst

Lines changed: 339 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,224 @@ iOS
147147
iOS devices are generally stutter-free, but older devices running newer versions
148148
of the operating system may exhibit problems. This is generally unavoidable.
149149

150+
Troubleshooting Guide
151+
----------------------
152+
153+
After an extensive evaluation of reported tickets and thorough testing of Godot on different HW,
154+
we found that Godot is blamed for many stutter, jitter or input lag that is not caused by Godot,
155+
but rather by 3rd Party Software or malfunctioning Hardware.
156+
157+
This guide will help you find the root cause of these issues.
158+
159+
**Please read it carefully and exhaust all options before reporting a ticket on Godot.**
160+
161+
Bad HDMI / DisplayPort cable
162+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
163+
164+
A broken cable may appear to function properly, but cause signal synchronization
165+
issues that go apparently unnoticed. However these issues can manifest when V-Sync
166+
is on and apps (including, but not limited, to Godot) running in exclusive fullscreen
167+
constantly have FPS jitter or slowdowns even in the most basic of scenes.
168+
169+
If you see simple demo apps struggle to reach 60 fps (e.g. it reaches 60 fps then
170+
every 2 seconds slows down to 55 or 40 FPS and then goes back up) you may have a bad cable.
171+
172+
**Solution:** Replace the HDMI / DP cable.
173+
174+
**Workaround:** Disable V-Sync and use the FPS limiter by launching with: ``--disable-vsync --max-fps <fps>``
175+
176+
Broken Monitor Firmware
177+
~~~~~~~~~~~~~~~~~~~~~~~
178+
179+
Similar to a bad HDMI / DP cable, a poor interaction between your monitor firmware and
180+
your GPU can cause jitter or periodic slowdown.
181+
182+
Unfortunately the simple answer is to replace the monitor. You might have luck contacting
183+
your Monitor manufacturer (e.g. LG, Samsung, Viewsonic, etc) and/or your GPU vendor
184+
(e.g. NVIDIA, AMD, Intel) and ask them for a solution or workaround.
185+
186+
**Solution:** Replace the monitor, or ask the manufacturer for a firmware/driver update.
187+
188+
**Workaround:** Disable V-Sync and use the FPS limiter by launching with: ``--disable-vsync --max-fps <fps>``
189+
190+
Multiple Monitors
191+
~~~~~~~~~~~~~~~~~
192+
193+
If you've got multiple monitors, ensure they are all in the same resolution, frequency (Hz),
194+
and bit depth (e.g. 16-bit vs 24-bit, HDR vs SDR).
195+
196+
If they're not, change their settings until they match.
197+
198+
If problems persist, try disabling all but one of the monitors.
199+
200+
Overheating and throttling
201+
~~~~~~~~~~~~~~~~~~~~~~~~~~
202+
203+
Jitter or stutter may be caused by an overheating CPU and/or GPU that throttles itself down.
204+
You can use temperature monitor software to see if this is the case.
205+
206+
**Solution:** Fix the cooling problem.
207+
208+
Inconsistent Power Saving
209+
~~~~~~~~~~~~~~~~~~~~~~~~~
210+
211+
In some cases the OS or driver keeps switching the CPU and/or GPU frequencies up and
212+
down; causing an uneven experience.
213+
214+
**Solution (Windows):** Set the Power Profile to "High Performance":
215+
216+
.. image:: img/windows-high-performance-profile.webp
217+
218+
.. tip::
219+
220+
Sometimes "CPU Boost" where a single CPU core goes into overdrive can be a problem.
221+
You can prevent CPU Boost by editing your *current* energy plan and set
222+
**Processor power management > Maximum processor state** to 99% instead of 100%:
223+
224+
.. image:: img/windows-no-boost.webp
225+
226+
For NVIDIA on Windows, set "Power management mode" on "Prefer maximum performance".
227+
228+
.. image:: img/nv-power-profile.webp
229+
230+
**Solution (Linux):** Set the CPU governor to Performance:
231+
232+
.. code:: sh
233+
234+
sudo cpupower frequency-set -g performance
235+
236+
# AMD
237+
echo high | sudo tee /sys/class/drm/card1/device/power_dpm_force_performance_level
238+
239+
You can try `CoreCtrl <https://gitlab.com/corectrl/corectrl>`__ or `Feral GameMode <https://github.com/FeralInteractive/gamemode>`__
240+
for user-friendly GUI to control power profiles for individual applications.
241+
242+
On NVIDIA, open **nvidia-settings** and go to **GPU 0 > PowerMizer > Preferred Mode: Prefer Maximum Performance**.
243+
244+
.. image:: img/nv-linux-powermizer.webp
245+
246+
Windows: Unlicensed
247+
~~~~~~~~~~~~~~~~~~~
248+
249+
First of all, "unactivated" or "unlicensed" Windows can have arbitrary limitations imposed by Microsoft.
250+
These limitations can change over time and an important one is that Microsoft may decide to restrict
251+
applications from entering "Hardware Independent Flip" modes which provides the lowest latency experience
252+
while in fullscreen.
253+
254+
Second, even if Microsoft decides to not artificially limit "Hardware Independent Flip"; if
255+
you're seeing this watermark:
256+
257+
.. image:: img/activate-windows.webp
258+
259+
Chances are you're not running in "Hardware Independent Flip" because Windows must use DWM
260+
compositing to display the watermark on top of Godot. And DWM Compositing prevents entering the desired mode.
261+
262+
**Solution:** Activate Windows by buying an original license key.
263+
264+
Windows: Presentation Mode
265+
~~~~~~~~~~~~~~~~~~~~~~~~~~
266+
267+
Windows has many ways of presenting to the screen. `Special K has an in-depth explanation of them <https://wiki.special-k.info/Presentation_Model>`__
268+
269+
But we can basically reduce them to the following:
270+
271+
**Good**
272+
273+
1. Hardware: Independent Flip (also called "iFlip").
274+
2. Hardware: Legacy Flip.
275+
3. Hardware Composed: Independent Flip.
276+
277+
**Bad**
278+
279+
1. Composed: Flip.
280+
281+
You can use `PresentMon <https://github.com/GameTechDev/PresentMon/releases>`__ to see which mode Godot is in.
282+
While in Fullscreen, Godot should be in one of the "good" ones.
283+
284+
If Godot is not in one of the "bad" ones, there may be an overlay that is causing problems
285+
(e.g. AMD Overlay, NVIDIA's overlay, Microsoft Game Bar, "Activate Windows" watermark, etc).
286+
287+
Godot can only enter the good ones if it's fully covering a single monitor with nothing on top.
288+
Some newer HW may be able to enter "Hardware Composed: Independent Flip" even if not fullscreen though.
289+
290+
.. warning::
291+
292+
**Set PresentMon to windowed mode**. Otherwise PresentMon's overlay `ironically prevents apps <https://github.com/GameTechDev/PresentMon/issues/367>`__
293+
from entering the "good" modes as it is displayed on top of Godot.
294+
You will have to use the recording option and later see the CSV capture to see what mode Godot was in.
295+
296+
.. warning::
297+
298+
Resources online assert that "Hardware Composed: Independent Flip" is the superior method of all.
299+
However our measurements do not conclusively align with such claims. Ultimately the best experience
300+
is done when all resources are entirely dedicated to one process. "Hardware Composed: Independent Flip"
301+
suggests that resources are being diverted to display something else too, even if that something is
302+
just giving CPU time to the DWM process.
303+
304+
305+
Windows: NVIDIA Presentation Method
306+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
307+
308+
.. tip::
309+
310+
This section only applies to Vulkan and OpenGL. It does not affect D3D12.
311+
312+
NVIDIA has two presentation methods: "Prefer native" and "Prefer layered on DXGI Swapchain":
313+
314+
.. image:: img/nv-present-method.webp
315+
316+
Switching to one or the other may give you better results.
317+
318+
Linux: NVIDIA
319+
~~~~~~~~~~~~~
320+
321+
On Linux machines using proprietary NVIDIA drivers, every time the process **nvidia-smi** is launched it
322+
causes a stutter. Unfortunately, many 3rd party apps periodically launch **nvidia-smi** to get GPU temperature
323+
and frequency and display it on an overlay or similar. For example running **nvidia-smi** once
324+
per second completely ruins the gaming experience.
325+
326+
If an app can tell you GPU frequency, fan speed or temperature, then it is a suspect.
327+
328+
Disabling or removing such apps will fix the problem.
329+
330+
You should report the developer of those broken apps that they must not launch **nvidia-smi** to
331+
query such information, and ask them to use `NVML <https://developer.nvidia.com/management-library-nvml>`__ instead.
332+
333+
The following is a non-exhaustive list of known apps to cause stutter on NVIDIA Linux systems:
334+
335+
- `CPU-X <https://github.com/TheTumultuousUnicornOfDarkness/CPU-X>`__.
336+
- Linux Mint's Mate panel application "CPU Frequency Scaling Monitor" applet.
337+
338+
339+
Linux: xfce
340+
~~~~~~~~~~~
341+
342+
xfce's compositor is not good for low latency games and can cause jitter. Disable it.
343+
344+
Open the **Start menu > Window Manager Tweaks > Compositor** and uncheck **Enable display compositing**.
345+
346+
.. image:: img/xfce-disable-compositor.webp
347+
348+
If you still want to use a Compositor on xfce, prefer using a better one like picom:
349+
350+
.. code:: sh
351+
352+
sudo apt install picom
353+
354+
You can configure picom at ``~/.config/picom/picom.conf``:
355+
356+
.. code:: text
357+
358+
# menu = { shadow = false; };
359+
dropdown_menu = { shadow = false; };
360+
popup_menu = { shadow = false; };
361+
utility = { shadow = false; };
362+
unredir-if-possible = true;
363+
364+
The important one is **unredir-if-possible** which allows Godot to draw directly to screen in
365+
fullscreen mode, which minimizes latency.
366+
367+
150368
Input lag
151369
---------
152370

@@ -241,6 +459,127 @@ If your mouse offers multiple :abbr:`DPI (Dots Per Inch)` settings, consider als
241459
On Linux, disabling compositing in window managers that allow it (such as KWin
242460
or Xfwm) can reduce input lag significantly.
243461

462+
Latency Reduction
463+
~~~~~~~~~~~~~~~~~
464+
465+
Starting with Godot 4.5, new pacing methods were introduced to reduce latency (and alleviate Jitter):
466+
467+
1. ``rendering/rendering_device/vsync/latency_mode``. It supports 4 options:
468+
469+
* ``low_extreme`` (only available through the GDScript API and command line interface. Cannot be set by default).
470+
* ``low`` (default).
471+
* ``medium``.
472+
* ``high_throughput``.
473+
474+
2. ``PacingMethod``, a fallback solution when Waitable Swapchains is not available:
475+
476+
* ``SEQUENTIAL``: The CPU always stalls for the GPU to minimize latency. **This can heavily penalize framerate and does not always result in lower latency**. This method can only reduce latency if the system was already fast enough to hit V-Sync's framerate.
477+
* ``PARALLEL``: The CPU and GPU try to run in parallel. This is the usual method of 2D and 3D rendering.
478+
* ``AUTO`` automatically selects between SEQUENTIAL or PARALLEL based on current CPU and GPU performance. AUTO will only select SEQUENTIAL if the system is fast enough.
479+
480+
Waitable Swapchains are by far the superior method, but if that's not available AUTO/SEQUENTIAL will be used instead.
481+
482+
.. warning::
483+
484+
In all cases (*including* Waitable Swapchain method), **lowering latency implies sacrificing framerate**.
485+
The question is, how much FPS (frames per second) are you willing to sacrifice for latency. The relationship is not linear,
486+
which means the lower the latency you want to achieve the greater the FPS sacrifice, which can get ridiculously high.
487+
This is not a bug, it is just the nature of how it works.
488+
489+
.. warning::
490+
491+
Lowering latency makes Godot more susceptible to **microstutter**.
492+
Thus if you're experiencing microstutter, use these options to *increase* latency instead.
493+
494+
.. warning::
495+
``low_extreme`` might get you better latency (or even be a placebo) but always at a very large FPS cost.
496+
Furthermore it may reintroduce microstutter. Caution is advised when seeking to lower latency too much.
497+
498+
.. warning::
499+
Just because ``low_extreme`` works great in your machine doesn't mean it will work fine
500+
in other machines. Don't deploy to end users with this setting as a default.
501+
502+
The following table summarizes what Godot does based on each setting and available feature:
503+
504+
.. table::
505+
:widths: auto
506+
507+
+-----------------+-----------------------------------------------------------------+---------------------------------+
508+
| Setting | Target: Frames of latency (if Waitable Swapchains are available)| Waitable Swapchains Unavailable |
509+
+=================+=================================================================+=================================+
510+
| low_extreme | 0 | SEQUENTIAL |
511+
+-----------------+-----------------------------------------------------------------+---------------------------------+
512+
| low | 1 | AUTO |
513+
+-----------------+-----------------------------------------------------------------+---------------------------------+
514+
| medium | rendering/rendering_device/vsync/frame_queue_size | PARALLEL (Disabled) |
515+
+-----------------+-----------------------------------------------------------------+---------------------------------+
516+
| high_throughput | Disabled | PARALLEL (Disabled) |
517+
+-----------------+-----------------------------------------------------------------+---------------------------------+
518+
519+
This table is read like this:
520+
521+
- If Waitable Swapchains are available, at "low" Godot will target 1 frame of latency. Otherwise, at "low" it will use AUTO as fallback.
522+
- If Waitable Swapchains are available, at "medium" Godot will use the value in frame_queue_size as target for frames of latency. Otherwise it uses PARALLEL mode (which is the same as having no pacing method).
523+
524+
525+
.. tip::
526+
527+
Godot's behavior on version 4.4 and earlier corresponds to ``high_throughput``.
528+
529+
**Troubleshooting:**
530+
531+
If you suspect Godot's pacing methods are malfunctioning, there are several steps you can take.
532+
533+
The first thing we need to do is to run with ``--verbose`` to know which pacing methods are available.
534+
You should see something like this:
535+
536+
.. code:: text
537+
538+
Supported Pacing Methods (mask 03):
539+
SEQUENTIAL_SYNC
540+
WAITABLE_SWAPCHAIN
541+
Current Pacing Method (may change later): WAITABLE_SWAPCHAIN
542+
543+
In this case, Waitable Swapchain is being used. This is great! The second thing we should try is running with a different latency mode:
544+
Let's say: ``--latency-mode medium``. There's 4 options to try (note: ``high_throughput`` just disables any pacing method).
545+
If the problem is gone, then we're done.
546+
547+
But let's say we want to try another method. For some reason, we suspect waitable swapchains are malfunctioning.
548+
We can try masking this feature out:
549+
550+
- ``--pacing-mode-mask 0x01`` will force to only use SEQUENTIAL_SYNC (if available).
551+
- ``--pacing-mode-mask 0x02`` will force to only use WAITABLE_SWAPCHAIN (if available).
552+
553+
The following table shows the masks for each settings (these masks can be OR'ed together):
554+
555+
.. table::
556+
:widths: auto
557+
558+
+--------------------+------+
559+
| Setting | Mask |
560+
+====================+======+
561+
| SEQUENTIAL_SYNC | 0x01 |
562+
+--------------------+------+
563+
| WAITABLE_SWAPCHAIN | 0x02 |
564+
+--------------------+------+
565+
| ANDROID_SWAPPY | 0x04 |
566+
+--------------------+------+
567+
568+
Thus by launching with ``--pacing-mode-mask 0x01`` we can experience how it runs by using ``SEQUENTIAL_SYNC``.
569+
Now that we are in sequential sync pacing mode; again we can try ``--latency-mode`` makes any difference.
570+
You can try ``low_extreme`` (SEQUENTIAL), ``low`` (AUTO) and ``medium`` (PARALLEL) to see if they make a difference.
571+
572+
**When to report issues:**
573+
574+
- If WAITABLE_SWAPCHAIN at ``low`` or ``medium`` settings are causing problems. This could indicate an issue with the rendering API, the OS, or HW.
575+
- If SEQUENTIAL_SYNC at ``low`` is causing problems but works fine at ``low_extreme`` or ``medium``. This would indicate a problem in Godot's AUTO algorithm.
576+
- If ANDROID_SWAPPY is causing problems.
577+
578+
**What NOT to report:**
579+
- ``low`` or ``low_extreme`` reduces the FPS.
580+
- ``AUTO`` does not improve latency.
581+
- ``SEQUENTIAL_SYNC`` does not improve latency.
582+
244583
Reporting jitter, stutter or input lag problems
245584
-----------------------------------------------
246585

0 commit comments

Comments
 (0)