Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use DXGI to present frames rendered by Vulkan on Windows #5692

Open
Calinou opened this issue Oct 31, 2022 · 10 comments
Open

Use DXGI to present frames rendered by Vulkan on Windows #5692

Calinou opened this issue Oct 31, 2022 · 10 comments

Comments

@Calinou
Copy link
Member

Calinou commented Oct 31, 2022

Describe the project you are working on

The Godot editor 🙂

Describe the problem or limitation you are having in your project

Vulkan and OpenGL on Windows tend to exhibit lower smoothness and greater input lag compared to Direct3D applications (any version). This sometimes leads to the impression that OpenGL and Vulkan perform worse on Windows compared to Linux, when it's actually not the case – the issue is in the frame presentation itself.

A Direct3D 12 renderer is being worked on, but for users wishing to use Vulkan on Windows instead, they won't get the best possible experience.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Most AAA games using Vulkan use DirectX Graphics Infrastructure (DXGI) to create a window and present frames rendered via Vulkan. This has several benefits over using Vulkan directly like Godot currently does:

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

Quoting this comment and this comment from @HybridEidolon for posterity:

Although, for the DXGI path, does that just require Vulkan to render to surfaces obtained from a DXGI swapchain instead of a VK_KHR_swapchain, and present from DXGI side? That doesn't sound like it'd be too hard to write at least, even without the d3d12 backend.


For reference, this is a Hello World sample which uses DXGI 1.6 swapchain to present while rendering with Vulkan to the same images, which is likely the same approach used by Doom Eternal as mentioned.

A cursory glance at the code indicates the use of d3d12.h and dxgi1_6.h from the Windows 10 SDK. However, equivalent headers are available under MinGW, so they can be linked against the system d3d12/dxgi.dll. I'd think this would be possible to support without any additional SDK downloads for either compiler since it wouldn't rely on the DirectX shader compiler at all, unlike the full d3d12 driver.

If this enhancement will not be used often, can it be worked around with a few lines of script?

No, as presenting frames is handled by the renderer.

Is there a reason why this should be core and not an add-on in the asset library?

This is core rendering functionality.

@KeyboardDanni
Copy link

I was about to submit this very proposal when I found there already is one. Thanks, search function!

I'd like to add that this impacts OpenGL as well, not just Vulkan (for those wanting to use the Compatibility profile). For GL, other projects have reported success using the WGL_NV_DX_interop2 extension to swap via DXGI.

I'd also like to mention that there is a current workaround for those on nVidia drivers. Users can go to the nVidia Control Panel and set the "Vulkan/OpenGL present method" to "Prefer layered on DXGI Swapchain":

2023-01-26 18_49_15-NVIDIA Control Panel

AMD may provide a driver option in the future. It should be noted that the nVidia option is currently a workaround - as such, the user has to manually opt into this. It's not on by default.

PresentMon may be useful to verify that the correct swapchain is being used. A correct result should show Hardware Composed: Independent Flip. Currently Godot is showing Composed: Copy with GPU GDI.

@Jamsers
Copy link

Jamsers commented Oct 15, 2023

I suppose implementation on this can start when #70315 gets merged... from what i can gather here, we literally just need to use a DXGI swapchain, the presentation code stayed exactly the same as far as I can tell. I guess the data you give to the swapchain in Vulkan can also be given, as is, to a DX12 swapchain?

Currently swapchain creation seems to be here, in vulkan_context.cpp's _update_swap_chain.

In DX12 (#70315), swapchain creation seems to be here, in d3d12_context.cpp's _update_swap_chain.

So I suppose we do some DX12 initialization stuff even if the selected renderer is Vulkan, then in vulkan_context.cpp, we #include "drivers/d3d12/d3d12_context.h", and in all calls to _update_swap_chain, we do:

#ifdef WINDOWS_ENABLED
D3D12Context::_update_swap_chain(&window);
#else
VulkanContext::_update_swap_chain(&window);

Although since this is Vulkan/DX12, I'm sure it won't actually be as simple as all that...

@GeorgeS2019

This comment was marked as off-topic.

@DarioSamo
Copy link

DarioSamo commented Mar 7, 2024

I gave this a shot but the synchronization does not work as intended.

https://github.com/DarioSamo/godot/tree/vulkan_dxgi

A very dirty example and it'd definitely need more code reorganization to be done properly, but I'm unsure as to what the missing synchronization is between present and the command queue for this to work. Right now it does render but there's visible corruption glitches that go away if the frame is waited on instead from the CPU (which would be incorrect).

Maybe someone familiar with the inner workings of Vulkan/D3D12/DXGI can spot the error?

@GeorgeS2019
Copy link

GeorgeS2019 commented Mar 7, 2024

@DarioSamo thanks for your effort, your work helps the community one step closer to hosting Godot4 engine in e.g. winform, WPF, and WinUI

@GeorgeS2019
Copy link

@DarioSamo
if you could share a downloadable simple application exe showing how the DXGI possibilities open the integration of Godot4 in e.g. WPF, AvaloniaUI etc,

This will be game changing

@pochoco24
Copy link

When are we getting this feature added in Godot?

@Calinou
Copy link
Member Author

Calinou commented Aug 20, 2024

When are we getting this feature added in Godot?

There is a pull request implementing this for OpenGL, but none for Vulkan yet. We don't have an ETA on when this will be implemented.

@expikr
Copy link

expikr commented Oct 11, 2024

For Vulkan, are we certain that the lack of smoothness isn't just simply a mistake in choosing the wrong presentation mode, i.e. using mailbox instead of immediate? My understanding is that DXGI is a layer over kernel-mode drivers whereas Vulkan dirrectly interfaces with the drivers, so in terms of capability there is no reason for pure-Vulkan not to achieve presentation timing than DXGI when implemented correctly.

@Calinou
Copy link
Member Author

Calinou commented Oct 11, 2024

For Vulkan, are we certain that the lack of smoothness isn't just simply a mistake in choosing the wrong presentation mode, i.e. using mailbox instead of immediate? My understanding is that DXGI is a layer over kernel-mode drivers whereas Vulkan dirrectly interfaces with the drivers, so in terms of capability there is no reason for pure-Vulkan not to achieve presentation timing than DXGI when implemented correctly.

The V-Sync modes are correctly mapped already, and the default is FIFO (traditional V-Sync). Mailbox V-Sync isn't always supported depending on the hardware/driver/OS and it doesn't limit the framerate, which can lead to significantly increased power consumption, so it doesn't make for a good default.

You can use Special K or PresentMon on Godot to double-check the V-Sync mode being used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants