Skip to content

Commit b629500

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

8 files changed

+336
-0
lines changed
13.1 KB
Binary file not shown.
Binary file not shown.
28.6 KB
Binary file not shown.
26.6 KB
Binary file not shown.
Binary file not shown.
23.2 KB
Binary file not shown.
Binary file not shown.

tutorials/rendering/jitter_stutter.rst

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

0 commit comments

Comments
 (0)