# In OpenGL, is it a bad idea to "combine" immediate mode and retained mode for the sake of GUIs?

Suppose I have a 3D scene being drawn with glDrawArrays(...) and I want to render something simple, like a 2D overlay. Would it be a bad idea to use immediate mode for such a thing, instead of setting up a 2D renderer with retained mode?

Example:

void Draw()
{
// Draw the 3D scene:
// *does stuff*
glDrawArrays(...);
// *some other stuff*

// Setup a quad with immediate mode (for something like a vignette overlay)
glTexCoord2f(...); glVertex2f(...);
glEnd();
}

• Minecraft does this. It works fine, except for limiting your OpenGL version (to <3.1 or a compatibility profile) and for making your GUI less faster. Mar 14 '18 at 19:33
• Note Minecraft also has its own set of functions that simulate immediate mode using vertex arrays - it's not difficult to write. I'm not sure if they're using them for the GUI yet. Mar 14 '18 at 19:36

It is a bad idea insofar as it is nonsensical. There is nothing to "set up" that you have not already done, except for an ortho projection matrix (which you will have to do in any case).

Portability is probably not a problem, although it should be. IHVs seem to be very reluctant to drop support for immediate mode for the foreseeable future (it seems to "work fine" even in core profiles), so although immediate mode should have died out long ago, it will probably stay forever. Performance is another story. Do you really want something that accounts for 0.1% of the scene complexity to consume 15-20% of the CPU time -- GL calls are relatively lightweight, compared to e.g. DX, but they are not free -- and 15-20% of real frame time due to stalling the pipeline? Can you even afford that with your time budget? Most games can't.

And then of course, the quirks. Oh the quirks. The apparent beauty of immediate mode is that it is (seemingly) easy and straightforward to do something like drawing a couple of quads quick. In reality, immediate mode can be such a pain in the rear, it's so full of non-obvious pitfalls.
On the other hand side, it is just as easy (and more straightforward if you ask me!) to just write a small 5-LOC function DrawQuad which when called adds vertex coordinates and indices to a memory buffer and increments a counter. Which, surprise, you can then draw with glDrawArrays/Elements and which you can reuse (the GPU copy, not just the userland copy!) the next frame as-is as long as nothing is changed.
Immediate mode must, there is no other way, allocate a buffer and do a PCIe transfer every time. Or, something equivalent in latency (GPU reading main memory over the bus, whatever). The driver cannot possibly know (or assume) that the data remained exactly the same as the frame before.

Getting data to the GPU is a high-speed, but also a high-latency operation. Not only is the bus transfer per se a complicated, high latency protocol (several protocol layers, packetizing, acknowledgements, etc.), but also not all GPUs are even able to transfer and draw at the same time, or if they can do it, they may not be able at all times to switch between or initiate new operations freely while doing something different. Read as: Thou shalt not transfer vainly.

• "There is nothing to "set up" that you have not already done" Batch rendering? Mar 7 '18 at 11:32
• Although IHVs are reluctant to drop immediate mode, there are also video drivers in Linux which don't support higher OpenGL version unless you request Core Profile. This in particular means Intel HD graphics (intel driver), but also NVidia and AMD chips when using open-source drivers (nouveau and amdgpu respectively). Similarly, on MacOS you also don't have Compatibility Profile with OpenGL>2.1. Mar 7 '18 at 12:49
• @HolyBlackCat: I'm not sure what you mean? OP states having a working 3D pipeline based on glDrawArrays. So there's everything set up which is needed to do yet another call to glDrawElements (or Array, whichever) to draw all the quads for the GUI (after writing the vertices to a buffer). Functions are loaded, you have a framework for allocating buffers, etc. Nothing special to do about batching the GUI, really. Just bind (or not, if you have enough TUs left to leave it bound) the GUI texture, set the ortho matrix, and do one additional draw call. How do you want to batch any better? Mar 7 '18 at 13:37
• (Of course I do agree that immediate mode is bad.) Sorry if I wasn't clear. I mean the process of filling said vertex buffer. That's easy, but it's slightly more work that using immediate mode. Mar 7 '18 at 13:46

I personally only see it as being bad for two reasons:

1. It is very outdated and deprecated. And,
2. It is much slower than the modern ways of drawing with OpenGL.

But, if it's working out, and performance isn't going to be an issue, and if it is not a problem for you to use deprecated OpenGL functions in your program, then I believe you could do it. It will be slower have TONS and TONS of GUIs, but if it's not that many, again, go for it.

Understand this, though. That at the end of the day, OpenGL is doing the same thing; drawing to the screen. Immediate mode is just much slower if you have a lot of things being processed. So, you should pick what is the most useful for the task you have in mind. Hope this helps you out!

Another downside is that it makes your code less portable. Certain OpenGL variants do not support immediate mode at all, for example, OpenGL ES. (and as bigger-caliber Android-based devices such as tablets gain more traction, it could become important)

Using immediate mode is completely unnecessary for gui related work.

To create a simple gui item, let's say, a button:

1. You need a quad/triangle strip mesh,
2. A texture for the mesh
3. An orthographic projection transform

In this way, you can just write a simple pass-through shader that ignores lighting considerations, and you just scale the gui item to a pixel scale, or some percentage of the window, and then do a painters algorithm for rendering.

In this way, you can do a full ui system with all the performance benefits of retained mode.