Just set your display's refresh rate to 60hz, run the application, and take a picture of your screen with your phone's camera (or HDMI capture device).
Capture an image, then count how many spaces ahead the Reference is (going to the right, wrapping from right to left), and add 1. This should give you the number of frames of lag.
Important! For test results to be valid, hardware cursor must be enabled and supported by the windowing system, and captures must be taken with a hardware camera or HDMI output to capture card. Software capture will produce incorrect results. If V-Sync is off or the refresh rate doesn't match the physics rate, cap the framerate with Enter
or the test won't make much sense.
Since this test uses the hardware cursor, press Delete
to ungrab/regrab the cursor.
You may need the window to be in the foreground and unobscured, or some platforms might not perform direct scanout of the image. In cases where direct scanout is not available in windowed mode, record separate measurements in both windowed and fullscreen mode.
Note that these were taken on a system with an nVidia RTX 3070 running on Windows 11, with display set to 60hz and VRR disabled. Driver low latency was disabled. You may get different results with a different OS and drivers.
These tests were done without simulated load. You may get different results based on how much work the CPU/GPU is doing. This is something I would like to add testing for in the future.
vsync disabled
,frame_queue_size = 2
,swapchain_image_count = 3
= 0-1 framesvsync enabled
,frame_queue_size = 2
,swapchain_image_count = 3
= 5 framesvsync enabled
,frame_queue_size = 2
,swapchain_image_count = 2
= 4 framesvsync enabled
,frame_queue_size = 1
,swapchain_image_count = 2
= 3 framesvsync mailbox
,frame_queue_size = 2
,swapchain_image_count = 3
= 1 framevsync mailbox
,frame_queue_size = 2
,swapchain_image_count = 2
= 4 frames
vsync disabled
,frame_queue_size = 2
,swapchain_image_count = 3
= 1-3 framesvsync enabled
,frame_queue_size = 2
,swapchain_image_count = 3
= 2 framesvsync enabled
,frame_queue_size = 2
,swapchain_image_count = 2
= 2 framesvsync enabled
,frame_queue_size = 1
,swapchain_image_count = 2
= 2 framesvsync mailbox
,frame_queue_size = 2
,swapchain_image_count = 3
= 1-3 framesvsync mailbox
,frame_queue_size = 2
,swapchain_image_count = 2
= 1-3 frames
vsync disabled
,frame_queue_size = 2
,swapchain_image_count = 3
= 0-1 framesvsync enabled
,frame_queue_size = 2
,swapchain_image_count = 3
= 4 framesvsync enabled
,frame_queue_size = 2
,swapchain_image_count = 2
= 3 framesvsync enabled
,frame_queue_size = 1
,swapchain_image_count = 2
= 2 framesvsync mailbox
,frame_queue_size = 2
,swapchain_image_count = 3
= 1-3 framesvsync mailbox
,frame_queue_size = 2
,swapchain_image_count = 2
= 1-3 frames
vsync disabled
,frame_queue_size = 2
,swapchain_image_count = 3
= 0-1 framesvsync enabled
,frame_queue_size = 2
,swapchain_image_count = 3
= 4 framesvsync enabled
,frame_queue_size = 2
,swapchain_image_count = 2
= 3 framesvsync enabled
,frame_queue_size = 1
,swapchain_image_count = 2
= 2 frames
vsync disabled
= 0-1 framesvsync enabled
= 2 framesvsync enabled
,glfinish
= 2 frames
vsync disabled
= 1-3 framesvsync enabled
= 2 framesvsync enabled
,glfinish
= 2 frames
vsync disabled
= 0-1 framesvsync enabled
= 3 framesvsync enabled
,glfinish
= 1 frame
- nVidia's layered DXGI driver option adds one frame of latency
- Though this is masked somewhat:
glFinish
only seems to have a noticeable impact when using Native Presentation fullscreen
- Though this is masked somewhat:
- Even in the best case scenario (no layered DXGI,
frame_queue_size = 1
), neither Vulkan nor D3D12 can beat OpenGL, with the exception of Vulkan running withvsync mailbox
. - For some reason, Vulkan with
vsync mailbox
only seems to work correctly with layered DXGI
- https://chat.godotengine.org/channel/rendering/thread/9cwuxShgya9jDzXB2
- godotengine/godot#94973 (comment)
Tested with Forward+ Metal (MoltenVK)
vsync enabled
,frame_queue_size = 2
,swapchain_image_count = 3
= 3 frames
All tests are with vsync enabled
, frame_queue_size = 2
, swapchain_image_count = 3
- Vulkan, windowed, no waitable swapchain = 6 frames
- Vulkan, fullscreen, no waitable swapchain = 4 frames
- D3D12, no waitable swapchain = 4 frames
- D3D12, waitable swapchain = 2 frames
- OpenGL, windowed, no waitable swapchain = 3 frames
- OpenGL, windowed, waitable swapchain = 2 frames
- D3D12, windowed = 8 frames
All tests are with Vulkan, vsync enabled
, frame_queue_size = 2
, swapchain_image_count = 3
- compositing enabled, windowed, no present wait = 6 frames
- compositing enabled, windowed, present wait = 3 frames
- compositing disabled, windowed, no present wait = 4 frames
- compositing disabled, windowed, present wait = 2 frames
- compositing disabled, fullscreen, no present wait = 2 frames
- compositing disabled, fullscreen, present wait = 1 frame
Not all of these were tested with a different frame queue size.
Wayland stats are unavailable as Godot currently has no way to warp the mouse cursor on that platform.
Contributions welcome to help fill in missing data!
1 frame is excellent, 2 frames is great, 3 frames is okay, 4 or more frames is inadequate.
Platform, GPU Vendor, Backend | Worst Latency | Best Latency (current Godot) | Best Latency (pending improvements) | Notes |
---|---|---|---|---|
Windows, nVidia, Vulkan | 5 frames | 3 frames | 2 frames | 2 frames with Native windowed or frame_queue_size = 1 |
Windows, nVidia, D3D12 | 4 frames | 3 frames | 2 frames | 2 frames with frame_queue_size = 1 |
Windows, nVidia, OpenGL | 3 frames | 2 frames | 1 frame | 1 frame with glfinish and Native Presentation |
Windows, AMD, Vulkan | ??? | ??? | ??? | |
Windows, AMD, D3D12 | ??? | ??? | ??? | |
Windows, AMD, OpenGL | ??? | ??? | ??? | |
Windows, Intel, Vulkan | 6 frames | 4 frames | ??? | tentative, fullscreen required |
Windows, Intel, D3D12 | 4 frames | 4 frames | 2 frames | tentative, 2 frames with waitable swapchain |
Windows, Intel, OpenGL | 3 frames? | 3 frames | 2 frames? | tentative, 2 frames with waitable swapchain |
X11, nVidia, OpenGL | ??? | ??? | ??? | |
X11, nVidia, Vulkan | ??? | ??? | ??? | |
X11, AMD, OpenGL | ??? | ??? | ??? | |
X11, AMD, Vulkan | ??? | ??? | ??? | |
X11, Intel, OpenGL | ??? | ??? | ??? | |
X11, Intel, Vulkan | 6 frames | 2 frames | 1 frame | fullscreen required, 1 frame with present wait |
Apple, macOS, MoltenVK | ??? | 3 frames | ??? | tentative |
- Low latency mode
- RenderingDevice
- Compatibility
- Extraneous semaphore wait on swapchain - might be fixed by godotengine/godot#99257
- Waitable swapchains
- D3D12 - godotengine/godot#94960
- Vulkan - godotengine/godot#94973
- OpenGL
- Direct use of DXGI on Windows
- D3D12 (this one's a given)
- Vulkan - https://github.com/DarioSamo/godot/tree/vulkan_dxgi
- OpenGL - godotengine/godot#94503