Skip to main content
GameDev.net gamedev.net
🔒 Locked

Checking for DX error returns

Started by Digital Extent Dec 31, 2002 at 12:51 AM 3 replies 400+ views
Original Post
Digital Extent
Digital Extent
Is it practical to check for every error returns from DirectX? For example: HRESULT r = function(); if (FAILED(r)) { //return failed or something } This may not be much, but there will be a lot of function called like this and wouldn''t it eat up speed to check everyone of these?
Programming is easy, thinking is hard.
Rick Scott
Rick Scott
The one you don''t check for will be the one that returns an error during run time.

Not only should you check every single return from DX (the Failed() macro is very little overhead), you might even want to check which return code it produced and handle it gently without destroying the whole game. There are lots of relatively benign errors that can show up and from which you can recover with ease without disrupting gameplay.
Digital Extent
Digital Extent
Should you limit it to certain call that is more likely to mess up the program?
Programming is easy, thinking is hard.
Rick Scott
Rick Scott
My heartfelt suggestions:

Check every DX return with at _least_ the FAILED() or SUCCEEDED() macro.

Then, browse through the DX Docs and find out which errors you can actually recover from gracefully, and check for those specifically. If, at the end of your project, an extremely time-critical piece of code is being slowed down by the check, you can downgrade it to FAILED() or SUCCEEDED() and see if that speeds up your program enough.
S1CA
S1CA
Three types of DirectX errors:

1) Things which CAN and sometimes WILL fail on an end users machine - for example CreateVertexBuffer, or indeed most of the Create* calls could fail in an out of memory situation because the user was running something in the background which was hogging the system memory.

2) PROGRAMMING ERRORS - say you didn''t check the caps or enumerate to see if a certain texture format were available, then CreateTexture() would fail because you passed it an invalid parameter. Programming errors would also include accidental slip ups such as declaring a buffer used in a dynamic fashion as static.

3) DRIVER ERRORS - some versions of the drivers supplied with hardware are bugged - sometimes quite badly. Usually any failure will show up in the major DirectX entry points (Create*, Draw* Present etc) rather than the minor ones - and usually without warning or even error return. At their worst they''ll crash the users machine when they occur.


For type 1, ALWAYS put in if (FAILED(hr)) type checks and appropriate upstream handling (e.g. react to the error properly - if you get an out of memory, bring up an error box asking the user to try shutting down background apps etc.


For type 2 I came up with a nice macro:


#define TRYDX(fn) do { \
HRESULT __dbgHResult__ = fn; \
if (FAILED(__dbgHResult__)) { \
_dbgLogDirectXError( __FILE__, __LINE__, __dbgHResult__, #fn ); \
} \
} while(0);


_dbgLogDirectXError does various things depending on settings elsewhere in the application:

- Translate the HRESULT into its human readable form using DXGetErrorDescription8() and similar.

- Log to the Output window.

- Log to a file.

- Optionally cause an assertion.

The definition of TRYDX is wrapped into a #ifdef _DEBUG so that the extra code only appears in debug builds since programming errors shouldn''t show in release builds. The alternative for release builds is simply: #define TRYDX(fn) (fn)

How to use the macro - simply wrap all non-type 1 DirectX calls in TRYDX, for example:

TRYDX(pDevice->SetTexture(blah));


The sort of report we get from TRYDX is:

E:\Projects\Blah.cpp(1061) : failed 0x88761013 (D3DERR_BLAH) code: [pDevice->SetTexture(blah)]

Useful things with that output format:

- The line and file are in MSVC error format so double clicking the logged line in the output window will jump to that line in the source code.

- The error code is already translated so by the time you get to the line in the source, you probably already have the fix

- The code is included, so if you aren''t running in the debugger, instead looking at a logfile from the testers you have a better idea of what has happened.



For type 3 errors, there isn''t much you can do - but you can structure your code so that user settings and such aren''t saved unless the application has been shutdown correctly (i.e. hasn''t crashed becuase of a bad setting).


--
Simon O''Connor
Creative Asylum Ltd
www.creative-asylum.com
Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.