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).

Thomas Vincent
  • 2,214
  • 4
  • 17
  • 25
  • 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. – Jeroen Baert Jun 17 '11 at 14:10
  • @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 :) – Thomas Vincent Jun 17 '11 at 14:26

4 Answers4

8

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).

datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • 1
    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. – Thomas Vincent Jun 17 '11 at 14:36
  • 2
    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. – datenwolf Jun 17 '11 at 15:02
  • Really ? I actually use `glTexImage2D` ... I will dig into this ! – Thomas Vincent Jun 17 '11 at 15:23
  • +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. – Luca Jun 17 '11 at 15:35
  • 1
    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 ... – Thomas Vincent Jun 17 '11 at 16:14
  • Are you sure framebuffer objects are not shareable? In the [`glBindBuffer` manual page](http://www.opengl.org/sdk/docs/man/xhtml/glBindBuffer.xml), 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._ – onitake Aug 26 '12 at 11:45
  • @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. – datenwolf Aug 26 '12 at 13:21
  • @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](http://www.scribd.com/doc/26313104/42/Sharing-OpenGL-Data-Between-Contexts). You might be right though, in that the renderbuffer attached to the FBO is not shared, unless it is a PBO. – onitake Aug 27 '12 at 13:51
  • Sorry, meant to say texture, not PBO. I get confused sometimes with all this terminology. – onitake Aug 27 '12 at 14:04
  • 1
    @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**." http://www.opengl.org/registry/doc/glspec42.core.20120427.pdf – datenwolf Aug 27 '12 at 14:26
  • @datenwolf: Very interesting, thank you. However, it does say renderbuffer objects are shared. – onitake Aug 27 '12 at 17:33
  • @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. – datenwolf Aug 27 '12 at 17:35
  • @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. – onitake Aug 27 '12 at 18:21
  • @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. – datenwolf Aug 27 '12 at 18:28
  • @datenwolf: Is creating an extra FBO (serving as the container for the shared renderbuffer) such a big hassle? – onitake Sep 01 '12 at 15:52
  • @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. – datenwolf Sep 01 '12 at 17:33
  • @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. – onitake Sep 04 '12 at 10:38
  • @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. – datenwolf Sep 04 '12 at 12:24
  • @datenwolf: That sounds very counter-intuitive. Can you elaborate in what way textures are not affected by data format matching, but renderbuffers are? – onitake Sep 04 '12 at 13:46
  • @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. – datenwolf Sep 04 '12 at 14:46
  • `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? – onitake Sep 04 '12 at 15:33
  • @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. – datenwolf Sep 04 '12 at 16:01
  • @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. – onitake Sep 05 '12 at 14:58
4

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

KayWang
  • 71
  • 6
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.

sarat
  • 10,512
  • 7
  • 43
  • 74
1

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

elmarco
  • 31,633
  • 21
  • 64
  • 68
  • 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://stackoverflow.com/a/6387338/1277510 ? I wonder if that's what browser really have to do. It would be pretty bad for 4k rendering.. – elmarco Apr 01 '22 at 20:06