Known Incompatibility: X-Plane 11, XSB 1.3.2 and the IXEG 733 1.0.x

Yesterday night I was able to confirm that there is a compatibility issue that exists with the specific combination of:

  • the IXEG 733 version 1.0.7 (and presumably earlier) with its respective version of Gizmo
  • XSquawkBox Version 1.3.2
  • X-Plane 11.0r1 (also known to affect the betas, but does not affect X-Plane 10)

The bug will result in Legacy CSL aircraft failing to load their textures, and significant VRAM usage proportional to the amount of time Legacy CSL aircraft are visible in frame.

Until the IXEG 733 is updated with full X-Plane 11 compatibility, I can only recommend that you do not use it with X-Plane 11.  If you must use it with X-Plane 11, then you will need to use XSquawkBox 1.3.1 until XSquawkBox 1.3.3 is released as 1.3.3 will contain a fix for our half of the problem.

Please do NOT report any further bugs relating to this combination of software to Laminar Software, to VATSIM, or to myself.

(Update 3 April thanks to some insight from Ben – CC)

As for the technical details which all relate to the open source libxplanemp, you need to understand a little bit about how OpenGL error handling works.

When a OpenGL API function encounters an error, it sets an internal error state rather than reporting it back as part of the results of that specific operation. This is so it can actually perform the operations asynchronously. The error is persisted until the programmer asks OpenGL  if there were any errors via glGetError().  glGetError() returns a single error from OpenGL, but the design permits for multiple errors to be reported by different subsystems or locations. This is handled by reporting errors with successive calls of glGetError() until there’s no more errors to report. (It’s highly unlikely we’d encounter such a situation inside of X-Plane, but it a requirement by specification). However, it also has the side-effect that it stalls the asynchronous GL operations pipeline as any queued operations prior to the test for errors have to complete before the error state can be determined.

Now, right off the bat, there were four bugs in xplanemp around this particular premise.

First bug was when we encountered an error at the end of our texture load, we were not taking the necessary step to loop over glGetError() until there were no further errors reported.

The Second bug was that we were assuming that if GL errors took place outside of our code, they’d be cleaned up correctly, and as such, no attempt was made to ensure that the errors detected at the end of texture load, actually occurred during texture load.

The third bug was whenever we encountered a bug from a texture load, we assumed that it had occurred when we tried to load the texture, and that there’d be no resources consumed by the failure (nor would there be efforts to retry the load) and we weren’t releasing the texture resources.

The final bug is that we shouldn’t be checking for errors anyway – at least not in a production build. There is nothing that we do during texture load that should generate an OpenGL error that we can’t prevent by using some reasonable sanity checks before it even reaches OpenGL.  Further to that – it’s not even guaranteed that the most likely error (resource exhaustion) will be reported!

These four bugs meant that we were susceptible to other people’s problems with OpenGL, leaked memory whenever we failed a texture load, were equally guilty of not cleaning up the error state (to specification) when we were done, and have been stalling the rendering pipeline every time we loaded a new texture.

All four of these are now fixed in the xplanemp codebase.

Generally, this hasn’t actually been a problem – most plugins are well behaved and the bug hadn’t manifested once on my test systems until I found the specific combination of XP11 and the IXEG B733/Gizmo.

So what does the IXEG 733 and Gizmo have to do with this I hear you ask?

In order to help debug this problem, I implemented a set of hooks into xplanemp that use the KHR_debug extension to catch and report OpenGL errors as they happen, intended for use by software developers using OpenGL.

Whenever there was the potential for a meltdown, with the GL debugging code enabled, I was finding plenty of reports such as:

XSB: GL Debug: [ERR] GL_INVALID_OPERATION error generated. Calling glEnd from the current immediate mode state is invalid. Check glBegin() / glEnd() pairs.
XSB: GL Debug: [ERR] GL_INVALID_OPERATION error generated. Calling glEnableVertexAttribArray from the current immediate mode state is invalid. Check glBegin() / glEnd() pairs.
XSB: GL Debug: [ERR] GL_INVALID_OPERATION error generated. Calling glDisableClientState from the current immediate mode state is invalid. Check glBegin() / glEnd() pairs.

These errors were all occurring outside of our texture load function, and were not occurring with a clean X-Plane 11 installation with XSquawkBox installed and very little else.

More than that, they were happening without XSB’s intervention (XSB doesn’t really touch OpenGL until you connect to the network, whereas these errors are visible prior to connection).

Eventually, with the help of an enthusiastic user and by the process of elimination, the factor to set off the errors was traced to the IXEG 733 and Gizmo64, and was only reproducible on XPlane 11. Unfortunately I cannot tell if it’s IXEG or Gizmo64 specifically to blame for the GL errors.