Jump to content

View more

Image of the Day

Boxes as reward for our ranking mode. ヾ(☆▽☆)
#indiedev #gamedev #gameart #screenshotsaturday https://t.co/ALF1InmM7K
IOTD | Top Screenshots

The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.

Sign up now

My thoughts on error handling, what are yours?

4: Adsense

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
4 replies to this topic

#1 Ubik   Members   


Posted 12 May 2013 - 09:03 AM

I've been thinking about error handling in OpenGL lately, as I'm slowly rewriting my hobby project, a C++ OpenGL wrapper. Error handling definitely one of those less exciting things, but still worth talking about in my opinion. I don't have any specific question here, other than maybe the very generic "how to do error handling?" or "how do you do it?" so would be happy to hear your thoughts and what approaches have you taken in your projects. Of course, comments on the text below are very welcome also.
So, here's my current thoughts on the subject. These are what I see to be the four overall options how to do the error handling:
1. No error handling in the application. Possibly the option to use in release mode, but with external tools to intercept calls this could work when developing too. I'm not knowledgeable about these at all, which probably explains why these options are not centered around what tool to use but how to handle errors within the code.
2. The "old-style" glGetError after every call to OpenGL. Use of glGet* functions is apparently not very good idea performance-wise, so probably will not be used in release configuration. Here I should add that I don't like having builds that differ from each other much, but in this case it seems justified. Maybe this could be done behind an if instead of #ifdef?
3. Synchronous use of the newer debug callback functionality, when using a debug context. (See http://www.opengl.org/registry/specs/ARB/debug_output.txt) I guess this kind of equates to the driver doing the glGetError internally, except that it can give much more in depth error messages.
4. Asynchronous use of the debug callback functionality. Set up similarly than the previous option, but has some implications which is why I separated it into its own point. More about this below.
There's also the more concrete level, that could be split into setup phase and then the handling of each actual OpenGL call. The setup phase is not very relevant to options 1 and 2, but obviously the 3 and 4 need to have the debug callback set up. Now, finally the part that really makes me think - let's go through the error handling options 2 to 4:
2. glGetError: Error handling can be done just by adding a check after every call. However, just outputting GL_INVALID_VALUE is hardly useful, so some context needs to be added. In C/C++ there are some macros like __FILE__ and __LINE__ that can be used. Going this way ends up with code where after every GL call there is something like "CHECK_GL_ERROR();" there. There could be more than that (in some cases also throw an exception etc.), but mostly there's going to be just the macro.
3. Synchronous debug callback: This does not require any special code where the OpenGL calls are made (at least not when nothing needs to happen in case of an error), but the context will be missing. I'm unsure if the vendor-specific debug messages will contain the function that was called - though that would make very much sense. Avoiding calling the same function from many places is not always possible (see glEnable).
Anyway, to add context to the callback, I could store somewhere the __FILE__ and __LINE__ before doing the call, and from there the callback can pull the information and add it to the output. So now the macro should be situated before the GL call. At this point I started to think about wrapping the call entirely into a macro call, because then the same same macro could then expand to either option 2 or 3. It could be done as something like "CHECKED_GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, bufferId));" Variadic macros, as far as I know, would make it possible to do something like "CALL_GL(glBindBuffer, GL_ARRAY_BUFFER, bufferId);" For some reason the second option appeals to me bit more, but the first one is probably easier to reason about when first time seeing the code.
4. Asynchronous debug callback: This is the preferred way to use the debug callback according to the debug output extension text The downside is that setting up the file and line information somewhere doesn't seem to really work because of the asynchronicity. They'd be nice to have, but maybe that's just the price that has to be paid for the performance? All the macro trickery is therefore unnecessary, but I'm thinking about if it would still be worth doing the wrapping calls in macros thing to allow the other options.

#2 C0lumbo   Members   


Posted 12 May 2013 - 10:02 AM

What I do in debug/optimised-debug builds is have a glGetError once per frame. If it detects an error, it'll printf it, then flick a switch which enables the 'thorough' testing mode which consists of a glGetError check after every single gl call. The hope is that if there's an error that fires every frame, then I'll get an assert on the problem line, without having the overhead of hundreds of glGetError calls per frame unless something has gone wrong.


In the event that flicking to the thorough mode doesn't catch the error next time around, then I just assert, and typically I'll run again with thorough mode enabled from the getgo.


In final builds I don't do any error checking.

#3 samoth   Members   


Posted 12 May 2013 - 11:00 AM

glGetError may affect your performance (I haven't noticed a significant impact myself, but many people including the authors of OpenGL Insights tell you such) and may at the same time not deliver good enough information to realize immediately what's wrong when doing the "typical" sporadic check.


For that reason, I'm using a debug context during development. You can turn it off by flipping a switch, and it's much more straightforward too (errors are synchronously reported to your callback function as they occur, not when you sporadically poll at some random time later). For a release build, it's California or Bust.


Either your code is correct (correct enough as to not produce errors with a debug context), then it must work, assuming the driver isn't buggy. On the other hand, if the driver is buggy, it probably won't work, but there's nothing you can do about it. You're fighting windmills, so not much point in doing a lot of error checking in release build.


I'm not sure if that approach is the best possible, but it's what I personally think is reasonable.

Edited by samoth, 12 May 2013 - 11:02 AM.

#4 Yours3!f   Members   


Posted 13 May 2013 - 10:09 AM

gDEBugger and/or CodeXL. Always works. For releases there shouldn't be any errors. However you may still want to look at them each frame.

#5 Ubik   Members   


Posted 13 May 2013 - 01:19 PM

Thanks for your replies, it's definitely been refreshing to get some new perspective. I'll naturally keep on following the thread (and subforum), and hopefully this proves to be helpful to other people too.


Looks like I've been thinking about how to manage the error handling sprinkled around all the GL code, when it probably could be more constructive to think whether it makes any sense to do it explicitly per command at all or generally how to keep this concern contained in it's own place. No point in extensive checking in release mode, point well taken, but also questionable much it makes sense to keep on following the eight or so relatively vague error codes alone even during development.


The once in a frame checking and runtime toggling of error reporting are things I haven't though of at all and they sound like sensible ways to avoid console or log spamming. When it comes to tools, last night I downloaded CodeXL, and should take a better look at it hopefully soon.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.