1

I have been using OpenGL and OpenGL ES for a long time, and I know them pretty well. They're also really, really annoying to use, and I haven't really seen this discussed anywhere. Here are some examples of bad design I have noticed:

  • Global states everywhere. There are states for every feature, often implicit, sometimes hidden. Without reading documentation in detail it's hard to figure out what values are legal for which states and what influences them. Since they are global, it's a nightmare to debug, even with a single-threaded program.
  • Error handling is quite possibly hands down the worst I have ever seen in any framework. I consider the fact that errors need to be checked manually a hardware limitation, so I'll let that slide. But there are only a couple of error flags. Those flags are often used multiple times within the context of a single function to signify different things, leaving you with no options but to guess why it occurs. There is only one "slot" for errors so effectively if you don't check after every function, you will never get to the bottom of it properly, since errors will get lost if there is more than one before checking.
  • Function signatures are often counterintuitive and misleading. Arguments that take any number, but actually only a couple of values are legal. Enums Arguments that have only one possible legal value (such as border=0 in glTexImage2D) leaving you wondering why they're even there (compatibility with future versions of the API? No, they're never changed to accept any other values). Redundant enums accepted by functions that can only handle one type of value anyway, such GL_TEXTURE_3D for functions that only operate on 3D textures.
  • Extensions required to do almost everything. Querying the GPU for supported extensions is a huge pain.
  • Misleadingly similar function names for functions that actually do very different things, such as glGenTextures/glCreateTextures
  • Obscure, arcane rules for framebuffer completeness (for example when you want to render to a texture). Without reading documentation in detail you will routinely run into situations where you're unable to figure out why your framebuffer is considered incomplete. This is made even worse by the previously mentioned fact that error handling is abysmal, and error codes are shared by different errors. Try reading the attachment completeness rules to get an idea just how bad it is. There is also no feedback as to which framebuffer attachment is the bad one.
  • Fixed function pipeline can be mixed with the new pipeline with shaders, leading to a HUGE mess
  • Absolutely no checking for any kinds of errors at compile time, although I appreciate that most of this would be hardware-dependent anyway
  • Lots of redundant functions (just see how many variants of glUniform or glGet there are)

With all these, and many other flaws, OpenGL seems to be just fine. It's extremely popular, dominates on mobile devices, is in active development, and supported on all kinds of GPUs. Why? Why is all this tolerated, and most importantly why was it designed this way? I know that GPUs are very particular devices and communication between CPU, GPU, memory, etc requires certain constraints, but most of it seems to be due to bad design that could be avoided.

  • 7
    Let's see you design something in 1992 that has to work on 1992 era hardware and work with 1992 era tooling, without the lessons learned since then, and see if you come up with anything halfway decent. – whatsisname Nov 12 '16 at 0:48
  • @whatsisname: To be fair, the OpenGL ARB made a number of mistakes that were not strictly necessary. Decisions that, at the time, could easily be seen to be incorrect, as they had other APIs to look at by comparison. But these are more specific issues (and the Longs Peak fiasco), not the general issues that the OP is talking about. – Nicol Bolas Nov 12 '16 at 3:54
  • All of your points look like fairly standard C programming. Sure, it's not great, but it certainly doesn't seem exceptionally bad. – amon Nov 12 '16 at 6:40
  • 3
    You've got it backwards. For much of the market, OpenGL is the only option. That means that it doesn't have to be good to succeed - it's not like people could switch to something else in disgust! Therefore, OpenGL is not popular despite being bad - it's bad because it's so successful that it's practically a monopoly. (I'm not accusing anyone of deliberately exploiting a monopoly position, Microsoft-style. But the incentives in the software market are relentless, and if you don't have to improve usability to succeed, chances are you'll choose to work on new features instead anytime.) – Kilian Foth Nov 12 '16 at 7:18
  • I don't get why you complain about GL_TEXTURE_3D only used for 3D textures? It literally says, TEXTURE_3D. If you want a 2D texture just type GL_TEXTURE_2D. There should be no problem with Redunat stuff like this, it is more versitle – Nfagie Yansaneh Aug 13 '17 at 8:19
4

It's extremely popular, dominates on mobile devices, is in active development, and supported on all kinds of GPUs. Why?

Well... what's your alternative?

Ignoring Vulkan, if you want to write a cross-platform application for mobile devices, and you want to use hardware 3D, what exactly are you going to use except OpenGL ES?

Nobody has ever claimed (at least recently) that OpenGL is a sensible, well-designed API. But it works; it gets the job done, and there's no more broadly available, cross-platform alternative.


And now for some fact checking:

There is only one "slot" for errors so effectively if you don't check after every function, you will never get to the bottom of it properly, since errors will get lost if there is more than one before checking.

That's false. Errors in OpenGL are queued. Each call to glGetError returns the error least recently added to the queue. OpenGL errors are not lost in OpenGL.

The problem with not checking for errors reasonably frequently is that, if you don't, then it'll be hard to know which function was responsible for which error.

such as border=0 in glTexImage2D

That exists because textures pre-GL 3.1 could have border texels. But since no consumer-grade hardware supported border texels, they removed it from core OpenGL in 3.1. But you can't just remove a parameter from a function; that would break ABIs all over the place. So they took the path of least resistance: keep the parameter, but required that it be zero.

ES retained it to preserve API compatibility with desktop OpenGL.

In general, pretty much every annoyance of the OpenGL API ultimately comes down to some level of "because backwards compatibility".

Absolutely no checking for any kinds of errors at compile time

OpenGL is a C API. There's not much room in C for compile-time verification of stuff.

  • 2
    "Well... what's your alternative?" It's like saying zillions of flies eat shit, so it must be good. The OP is spot on.with his complaints. Alas, if there's only shit to eat, we have to take it ;-) – qwerty_so Nov 12 '16 at 11:26
  • @ThomasKilian: ""Well... what's your alternative?" It's like saying zillions of flies eat shit, so it must be good." ... no, that's not what I said at all. It's not about how many people are doing something; it's about the fact that there's no cross-platform alternative. – Nicol Bolas Nov 12 '16 at 15:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.