Share OpenGL frame buffer / render buffer between two applications
Asked Answered
E

4

17

Let's say I have an application A which is responsible for painting stuff on-screen via OpenGL library. For tight integration purposes I would like to let this application A do its job, but render in a FBO or directly in a render buffer and allow an application B to have read-only access to this buffer to handle the display on-screen (basically rendering it as a 2D texture).

It seems FBOs belong to OpenGL contexts and contexts are not shareable between processes. I definitely understand that allowing several processes two mess with the same context is evil. But in my particular case, I think it's reasonable to think it could be pretty safe.

EDIT:

Render size is near full screen, I was thinking of a 2048x2048 32bits buffer (I don't use the alpha channel for now but why not later).

Emlin answered 17/6, 2011 at 14:7 Comment(2)
Is real-time updating required? You could write the rendered image to a file and load it in B. Other than that, sharing FBO's in OpenGL is not that simple. Maybe you can share the buffers on GPU level.Jobholder
@Jeroen Real-time is required ... I was trying to limit the scope of the question to not tackle the sync problem too soon but your are right it's important :)Emlin
J
9

Framebuffer Objects can not be shared between OpenGL contexts, be it that they belong to the same process or not. But textures can be shared and textures can be used as color buffer attachment to a framebuffer objects.

Sharing OpenGL contexts between processes it actually possible if the graphics system provides the API for this job. In the case of X11/GLX it is possible to share indirect rendering contexts between multiple processes. It may be possible in Windows by emplyoing a few really, really crude hacks. MacOS X, no idea how to do this.

So what's probably the easiest to do is using a Pixel Buffer Object to gain performant access to the rendered picture. Then send it over to the other application through shared memory and upload it into a texture there (again through pixel buffer object).

Juridical answered 17/6, 2011 at 14:27 Comment(23)
I tried that already, and I faced performance issue (A can provide near full screen texture ...). That's why I ask for in memory card memory sharing.Emlin
Well, you'd have to share the OpenGL context across processes, which is actually possible if you lift some of the protections between the processes. However may I ask how you upload your texture? glTexImage2D or glTexSubImage2D? The later is faster by several orders of magnitude.Juridical
Really ? I actually use glTexImage2D ... I will dig into this !Emlin
+1 I've used shared memory in these cases, and it is very performant. At high rate it may be necessary a mutex for synchromization.Hellfire
I have to say it make a difference ... :) should be basic stuff for you but thanks for this tips ! Sounds fair in my case to do it that way ... A little disappointed thought to have to go out of the memory card ...Emlin
Are you sure framebuffer objects are not shareable? In the glBindBuffer manual page, it says Buffer object names and the corresponding buffer object contents are local to the shared display-list space (see glXCreateContext) of the current GL rendering context; two rendering contexts share buffer object names only if they also share display lists.Hibernal
@onitake: Buffer objects are something different than framebuffer objects. (buffer =/= framebuffer). You attach rendertargets to a FBO. A texture may be such a rendertarget and textures are shared between contexts.Juridical
@datenwolf: I know that. Resource sharing is a hot topic amongst OpenGL implementors, and it seems a lot of progress is being made. FBOs are something that is shared, at least according to this book excerpt. You might be right though, in that the renderbuffer attached to the FBO is not shared, unless it is a PBO.Hibernal
Sorry, meant to say texture, not PBO. I get confused sometimes with all this terminology.Hibernal
@onitake: That book except is wrong. Please read appendix D of the OpenGL-4.2 core specification: "Objects which contain references to other objects include framebuffer, program pipeline, query, transform feedback, and vertex array objects. Such objects are called container objects and are not shared." opengl.org/registry/doc/glspec42.core.20120427.pdfJuridical
@datenwolf: Very interesting, thank you. However, it does say renderbuffer objects are shared.Hibernal
@onitake: Yes, but renderbuffers are not framebuffer objects. Technically a renderbuffer does not differ much from a texture, only that you cannot use it as a sampler data source.Juridical
@datenwolf: True, but the question was about sharing rendered image data between contexts. Depending on how the GL implements screen drawing, wouldn't a shared onscreen renderbuffer be the best solution? Write to it from one context, then display it on the second. You could also use glBlitFramebuffer to copy from one renderbuffer to another.Hibernal
@onitake: Renderbuffers are never onscreen. A renderbuffer is always meant for attachment to an off-screen FBO. Also renderbuffers can not be conveniently used as a image source, i.e. you can bind them as textures. Also glBlitFramebuffer works only between FBOs, not renderbuffers, and works regardless of if there's a texture or a renderbuffer attached.Juridical
@datenwolf: Is creating an extra FBO (serving as the container for the shared renderbuffer) such a big hassle?Hibernal
@onitake: This is not so much about being difficult or not, but usefullnes. A shared FBO is of little use, because a FBO does not carry any data; or at least none, that's being woth sharing. The really interesting data is the images contained in the renderbuffers or textures you mey attach to FBOs and those are shared among contexts just fine.Juridical
@datenwolf: True, but you still need to blit the output contained in the shared texture or renderbuffer to the output framebuffer. If you use textures, there might be constraints on data format, size, multisampling or other things, and it would probably make sense to do as little modification on the frame as possible. So, I think sharing a renderbuffer is better than rendering into a texture, then rendering from that texture again.Hibernal
@onitake: Rendering from a texture is the most efficient you can get. Your concerns about data formats, size, etc. do in fact apply, to some degree, to renderbuffers, but not textures.Juridical
@datenwolf: That sounds very counter-intuitive. Can you elaborate in what way textures are not affected by data format matching, but renderbuffers are?Hibernal
@onitake: Renderbuffers can only be used as FBO attachments, even if they are to be used as a data source only (glReadPixels, glCopyPixels). By attaching renderbuffers to an FBO the format of the whole FBO is configured, this re-/configuration is expensive. FBOs are optimized for a writing access pattern mostly; gl{Read|Copy}Pixels is a slow operation. Textures OTOH are meant to be used as a data source on arbitrary target framebuffer configurations, but more importantly the format of a texture has no influence on the access pattern toward the target FBO.Juridical
glReadPixels and glCopyPixels are not relevant here, as they do not copy between framebuffers (or from texture to framebuffer). That's why i suggested glBlitFramebuffer, this allows copying from one FBO to another. There is also no runtime reconfiguration, as the rendering task uses the shared renderbuffer as target, while the drawing task uses it as source. If the configurations of the FBOs/renderbuffers match, there is no overhead involved. Admittedly - one could also bind the texture to a FBO and use glBlitFramebuffer on that. Why not just try out which is faster?Hibernal
@onitake: glCopyPixels can be implemented on top of glBlitFramebuffer. The problem is, that the mere act of binding a renderbuffer (or a texture) to a FBO triggers FBO reconfiguration. However, (and I just remembered that), glCopyPixels and glBlitFramebuffer introduce a synchronization point (on either side). This alone can have a major impact on the throughput.Juridical
@datenwolf: That is correct, but so does using a texture as render target, then using that texture as sampler for another render stage. You may avoid stalls using ping-pong rendering or some other trick of course. As for reconfiguration: That is only done one single time, during setup. The shared renderbuffer is bound to the draw FBO in the renderer and the read FBO in the displayer. After that, the configuration won't change any more.Hibernal
P
4

In MacOS,you can use IOSurface to share framebuffer between two application.

Partridge answered 16/6, 2021 at 3:24 Comment(2)
A code example or blog post would be awesome (similar to https://mcmap.net/q/707031/-share-opengl-frame-buffer-render-buffer-between-two-applications). ThanksMunro
@Munro try this ~ github.com/fruitsamples/MultiGPUIOSurfacePartridge
S
1

In my understanding, you won't be able to share the objects between the process under Windows, unless it's a kernel mode object. Even the shared textures and contexts can create performance hits also it has give you the additional responsibility of syncing the SwapBuffer() calls. Especially under windows platform the OpenGL implementation is notorious.

In my opinion, you can relay on inter-process communication mechanisms like Events, mutex, window messages, pipes to sync the rendering. but just realize that there's a performance consideration on approaching in this way. Kernel mode objects are good but the transition to kernel each time has a cost of 100ms. Which is damns costly for a high performance rendering application. In my opinion you have to reconsider the multi-process rendering design.

Salsify answered 17/6, 2011 at 15:1 Comment(0)
M
1

On Linux, a solution is to use DMABUF, as explained in this blog: https://blaztinn.gitlab.io/post/dmabuf-texture-sharing/

Munro answered 31/3, 2022 at 13:10 Comment(1)
np. I suggest you remove the win32 & qt specifics from your question, as apparently you were looking for a portable solution. Btw, did you find anything better on Windows than https://mcmap.net/q/707031/-share-opengl-frame-buffer-render-buffer-between-two-applications ? I wonder if that's what browser really have to do. It would be pretty bad for 4k rendering..Munro

© 2022 - 2024 — McMap. All rights reserved.