November 8, 2019 at 6:49 pm #4425
I have an opengl app that uses spout to send its output to resolume.
Both my app and resolume are developed using opengl.
I am trying to understand why do we need to go through directx to share textures between those 2 apps.
It seems like it adds unnecessary overhead to convert twice the textures between opengl and directx when they already are at the right “format”.
Could anyone shed some light?
INovember 8, 2019 at 7:00 pm #4426
As an additional question, for this specific use case,( linking a custom opengl app to resolume) , does anyone know if it would be as performant to use NDI between those two apps instead of spout?
This would make it work out of the box on windows and osx.November 9, 2019 at 1:01 am #4429
The interop between OpenGL and DirectX is necessary in order to use DirectX shared textures. OpenGL does not have an equivalent function. In fact it is quite efficient. The DirectX and OpenGL textures are simply linked. There is no copy process between DirectX and OpenGL, so a transfer copy is only done once. This achieves around 0.5 msec per frame for a texture copy. There are other things that affect it of course such as vertical sync and OpenGL processing, but it is still very fast.
The OpenGL/DirectX interop extension is Windows only and depends on NVIDIA compatible graphics. As you know, Syphon does the same job for OSX. The only common factor with all operating systems is CPU memory and that is what NDI uses. It is designed for transferring video over a network and the documentation indicates that it is compatible with 4K. Resolume has recently updated to NDI 4.0, so you should be able to assess whether it is suitable for you.November 9, 2019 at 3:44 pm #4430
Thanks for you answer it’s quite enlightening.
I understand now that opengl lacks a texture sharing feature.
Would you give a link or explain in a few words what happen when an opengl texture is “linked” / “converted” into a directx texture? You mentioned the word “transfer copy”. Does this mean there is an actual byte-to-byte copy done in the memory of the graphic card? And that this copy happens every time we call sendTexture/receiveTexture and that it is very fast?
Also, would you be able to explain how, in my specific use case (custom opengl app, single buffer -> Spout -> Resolume), I don’t experience any “syncing” issue even though I don’t use double buffering in the opengl app?
How come Resolume never reads a texture that is being “transfer” copied? Do you use double buffering (ie. using 2 directx textures) in the spout low level code so that it never happens?
Thanks for your help!November 9, 2019 at 9:47 pm #4435
Have a look at the DirectX/Opengl interop extension. The Directx and OpenGL textures are linked in such a way that this extension manages the transfer of data when the linked OpenGL texture is accessed. You only have to work with the OpenGL texture. The DirectX one is behind the scenes but you never access it from OpenGL directly. Effectively you have an OpenGL texture that is shared. Any copy is made using OpenGL methods. Spout uses an fbo blit, or if the blit extension is not available, glCopyTexSubImage2D. Have a look at spoutGLDXinterop::CopyTexture. The Resolume receiver will be doing this.
Spout handles synchronisation between the two applications so that there is no read while the other is writing and vice versa. There is no double buffering of the DirectX textures. The copy speed is much less than the vertical sync cycle so you will not normally notice anything. But you will find a difference in frame rate if you enable/disable vertical sync.November 10, 2019 at 1:21 pm #4448
Thanks, I read the extension documentation and part of spout sdk source code.
If I understood correctly, there are 2 fbo blits per cycle.
The first one is from the spout sender, it copies an opengl texture to the shared opengl texture.
The second one is from the spout receiver, it copies from the shared opengl texture to an opengl texture.
Is there any technical reason I am not seeing that would explain why we need 2 blits per cycle?
Wouldn’t it be possible to have a spout sender that directly renders to the shared opengl texture instead of copying a separate texture to the shared one?
Or a Spout receiver that directly accesses the shared opengl texture?
This would save 1 blit right?November 10, 2019 at 11:30 pm #4458
It’s usually easier to work in this way, but direct render to the shared texture is possible if the application can do so.
Have a look at SpoutGLDXinterop.cpp :
These functions perform the necessary mutex and interop locks and then bind or unbind the OpenGL texture. You use them as you would bin/unbind normally.
There are also DrawSharedTexture and DrawToSharedTexture. But these are written with legacy OpenGL code and are not compatible with more recent OpenGL 4 methods.
You must be logged in to reply to this topic.