leadedge / Spout2

A video frame sharing system for Microsoft Windows
BSD 2-Clause "Simplified" License
748 stars 137 forks source link

Support for Vulkan #69

Closed medcelerate closed 3 years ago

medcelerate commented 3 years ago

I would love to see support for using the vulkan api for interprocess GPU communication as an option. Would mean spout could be used on Linux systems as well. https://www.google.com/amp/s/amp.reddit.com/r/vulkan/comments/60bdtn/interprocess_communication_on_the_gpu/

leadedge commented 3 years ago

Hi @medcelerate,

I am sure that some sort of library using Vulkan shared memory could be conceived, but it's some way off because, at the core, Spout is based on DirectX shared textures.

To use current methods, the sender information structure saved in shared memory would have to be examined to see whether such an exchange is possible.

However, this old article shows the principle of interaction between Vulkan and DirectX shared textures, which can be used to interface with existing Spout methods .

The developer has control over this process where the connection between Vulkan shared memory and DirectX shared texture is within the application itself.

Perhaps these things could handled within a library function but it would take some time and experience with Vulkan to do so.

Sadly I lack both these things, but would be pleased to assist anybody who wants to implement the Vulkan/DirectX interface in their application or to discuss ideas they may have about how sharing Vulkan images with a library function might work.

leadedge commented 3 years ago

I will close this for now. The option is possible but will not be for a while.

DarioDaF commented 3 months ago

Hi, I've looked at the code and some references online for interoperability, I could give it a go in the free time basing stuff on: https://github.com/malstraem/vulkan-interop-directx

As far as I can tell SpoutDirectX.cpp is the only "live" code that is required for actual transfer and SpoutGL.cpp is only for moving the texture into DX.

We could discuss some general overview of the control structures if there is something that you think is important to do the task

leadedge commented 3 months ago

Since 3 years ago, both Resolume and TouchDesigner developers have integrated Spout into their Vulkan code, essentially using the methods outlined in the original Nvidia article together with their own DirectX texture management and Spout methods for sender name management and shared memory. These methods are contained in the classes SpoutSenderNames and SpoutSharedMemory. SpoutDirectX can also be used for DirectX device and texture creation.

SpoutGL is specific for OpenGL and uses the Nvidia OpenGL/DirectX interop extensions available in the graphics driver to copy between OpenGL and DirectX textures. This would not be required at all in any development for Vulkan.

If your application can integrate the interop of the project you refer to, or if you can copy the Vulkan image using other methods, once you have the DirectX shared texture derived from the Vulkan image, this could be used for Spout texture sharing.

Given the shared texture, it should be possible to use the more recent SpoutDX methods directly. A single "SendTexture" call might be all that is required. Use SetsenderName somewhere prior to that to establish the sender name.

One caveat is that synchronisation using keyed DirectX shared textures can't be used because while it synchronises a single sender/receiver pair, multiple receivers can result in unacceptable hesitations. Also NT share handles are not supported.

DarioDaF commented 3 months ago

The last part is not completely clear to me, I'll have to look into that. It was mainly a consideration if it would be accepted a PR to add like SpoutDX and SpoutGL an equivalent SpoutVk that can be used seamingly to interact with other spout clients/servers, so that it can be more widely used than having the vulkan wrapper in something like spout_gd (the target platform I want to use with Godot4 Vulkan renderer)

leadedge commented 3 months ago

The last comments are a result of experience with Resolume and TouchDesigner. These issues will become clear when creating the DirectX texture and Vulkan image from it's handle.

I have looked into this previously and, as indicated above, I believe that it is possible using the SpoutDX class. This would be similar to DirectX12 but using the SpoutDX class directly.

To include this as part of the Spout SDK requires sender and receiver examples, but the overhead for Vulkan is not suitable for incorporation into the SDK. It could be done by modification of chosen LunarG samples, and documentation for build, but I have found that building the samples is not a straightforward process and requires experience with git and git-lfs, even to download the repository. Instructions for Cmake failed for me and in the end I ran out of time to complete the process successfully.

However, I looked into this again just now and had success with examples by Willems. Cmake desktop imports all the dependencies properly and the project builds without error, which gives a path forward.

The "triangle" example might be suitable for a sender with the DirectX12 example as a guide.

To set this up, add a "SpoutDX" folder in the "triangle" example folder and include the SpoutDX files as shown for the DirectX12 example. Add these files to a SpoutDX filter in the triangle project, add "#include "SpoutDX\SpoutDX.h" to triangle.cpp and "spoutDX sender" to the VulkanExample class. In the constructor of this class, DirectX can be initialized "sender.OpenDirectX11()" and the sender given a name "sender.SetSenderName("Vulkan sender example")". The sender is released in the destructor "sender.ReleaseSender()".

For the process I have in mind, it remains to discover where a Vulkan external memory image could be created and connected with a swapchain image in some way. It would be bound using the handle of a shared DirectX 11 shared texture which would be used in SpoutDX::SendTexture(ID3D11Texture2D* pTexture).

With the Nvidia guidelines I have encountered problems of missing extensions. Is there any simple example you have come across other than the one you have mentioned?

kanimaru commented 2 months ago

Could we reopen the issue when someone is working on it? I would looking forward to have vulkan support for Godot :)!

leadedge commented 2 months ago

Yes that's what this needs. I looked further at the basic triangle example by Willems, but turning the concept to reality goes beyond my abilities with Vulkan. In any case, the end result would not be simple enough for an example, like for DirectX12. The main result was that using SpoutDX is successful for the output and I could probably help with that part of it.