Saturday, February 11, 2017

Crazy Ideas Folder: OpenGL Renders in "Background" Mode via Mesa GL?

This evening, I caught a mid-conversation snippet that had me thinking, "Is that really so? I'm not so certain about that..."  (or perhaps my supervisor's frequent utterings during our meetings have been starting to get ingrained in my mind XD).  Anyway, the quote in question was:

"it's not possible to do opengl render in a background mode"

Really?!  I know it's not **currently** possible to do an OpenGL render in background mode, and perhaps there are limits to what we can achieve (especially if you're not allowed to spawn any windows and/or there's no graphics card on the rendermachine).

However, something from the vague hazy memories of the past tell me that this is not a cut-and-dried certainty.

So first, why can't you currently do OpenGL renders in background mode? Well, put simply, in "background mode", when Blender starts up, it doesn't create an OpenGL context. An OpenGL context is needed so that the drawing commands used to render the viewport/GPencil strokes (used in the OpenGL render) know where to perform their magic.

This leads to: Why don't we create an OpenGL context in background mode? Well, as its name implies, "background mode" is intended for running Blender in the background (i.e. "headless" on some server somewhere, likely as part of a renderfarm). As you know, renderfarm computers may not have graphics cards (AFAIK, most of them don't, unless you're a Blender user who's built their own cluster form Cycles GPU rendering), so it's important to not have any dependencies on system/hardware-provided OpenGL support to be able to render in background mode.

Another thing to point out is that, under normal circumstances (at least historically), you couldn't easily render to anything other than a window on screen. Of course, this hasn't been the case for over a decade now, but when Blender was first coded, IIRC things like offscreen framebuffers were either non-existent or very poorly supported across different hardware.

Then how could we do OpenGL renders in background mode then? Note how above I specifically mentioned that this is mainly a problem if we need to depend on hardware support for OpenGL drawing/rendering... This offers a (theoretically) very simple solution: let's just do it in software then!

And that's where Mesa GL/Mesa 3D comes in. Mesa 3D is an open source library (you may have heard of it, especially if you've submitted a bug report to our bug tracker about glitchy screens, and we asked you to download a "gl.dll" or similar and dump it beside the blender.exe binary) that provides a software implementation of OpenGL. That's right, it's completely CPU-based, and doesn't need/require access to a GPU. Of course, it'll be slower than the dedicated hardware, but in a pinch, it'll do the job.  (I'm not sure how well it copes with the new-style OpenGL that the 2.8 viewport project is pushing towards though, since the last time I looked at/into this was over a decade ago)

Let's connect the dots further:
1) Let's say that Mesa 3D provides some sort of mechanism to construct an OpenGL context for offscreen rendering without requiring any hardware support...
2) And let's say that perhaps we could use this mechanism to create OpenGL contexts as-required in background mode to render the required OpenGL renders...
3) And let's say that we can read the pixel data out of the offscreen buffer that the Mesa 3D context write into, using it in one of Blender's Image Buffers, just like the output of any other renderer...

Believe it or not, these things are all either here already, or very close to being a reality. For starters, the infrastructure for #3 is practically in place now - that's how the OpenGL renders (the camera button on the 3D view header) works.

And a bit of quick Googling reveals that Mesa does in fact provide said (hypothetical) mechanisms...
For example, see the following links (in the following order):

So apparently, Mesa 3D provides a "'null display' driver, OSMeta" exactly for this purpose.

Perhaps the only real challenges are figuring out how to integrate this into/with Blender so that in background mode, we can use this. Specifically (without having looked any further into it at this point), I'm guessing that you'll have to find a way to deal with the following problems:
   1) Do we compile Mesa into Blender, or have it as a .dll on the side (loaded like the old 2.4x plugins perhaps?) that we can load when doing background rendering and need OpenGL support?
   2) Or do we have a special build/build-option/or branch of Blender which is set up to always defer to Mesa over the system OpenGL, solving whatever gl-function binding problems there might be with trying to keep blender.exe able to function with both and the system opengl.dll. In fact, is it even possible to have MesaGL and system OpenGL functions available to the program at the same time... (something tells me that those symbols generally need to be resolved at program load time)
   3) How much of mesa do we need to include to be able to use this OSMeta driver?
   4) How do we patch CMake around to add this support?
   5) Will it actually work to an acceptable level after all this trouble?

I suspect that this would make a good weekend project for anyone so inclined (and with the skill to do so). Personally, I don't have the time to tackle this for now, but if I did, it would be something I'd be curious to tinker around with just for the hell of it... If nothing else, it'd be fun to have a custom OpenGL renderer where I can just set the line thicknesses to whatever the hell I want them to be, and then use Grease Pencil with that... (we've got much better plans for where we'd like to go with GPencil drawing, but for a quick hack, this method might just be a faster path to quickly test out some things) :)

Any takers?


  1. First - drop the distinction between mesa and opengl - mesa provides an opengl library, this may or may not have all the same features available in the Apple/MS/nvidia provided opengl libraries but it is still an opengl library. Also mesa does provide GPU hardware acceleration support.

    First a distinction should be made with the blender build. A normal build can be run in background mode while still linked against libgl and libx11... but a build using WITH_HEADLESS would not have the ability to use libgl. As libgl is linked to libx11 I see no point in trying to offer a different build option for blender.

    That leads to a code change that allows an offscreen buffer to be created for gl rendering when blender is started in background mode.

    1. Hi,

      Thanks for the clarifications. I will note that I haven't really been following Mesa development too much, so much of this was based on 2008-ish Mesa (which would've been the last time I really looked into it much).

      As an "official option", I agree that there's probably not much point trying to do it. Too much trouble for what is probably an edge case.

      However, as an interesting example of "could it be done if we really needed it to work" (e.g. perhaps you're doing some visual-fx project that takes ages to render via a renderfarm, and includes some GP-sketched elements that you don't want to have to pre-render), then this is IMO an interesting exercise.

      I also want to clarify that I wasn't in fact referring to WITH_HEADLESS. *That* is a whole other kettle of fish completely, and not really worth considering at all. I was however referring to just the standard Blender build, which DOES include all GL stuff (and drawing code). It's just that with the background flag set, the setup uses a different code branch that doesn't invoke the GL stuff.

  2. that's not so crazy idea but the normal way used in supercomputers which has no GPUs.