X-Plane 12.04b3 ships with a new feature called “Zink”, which we hope is going to alleviate a lot of the long standing issues that many users, especially with AMD GPUs have suffered from. This hopefully provides a work around for both flickering plugin drawing, eg. EFIS screens that either flicker or are missing altogether, but also potential improvements in performance by decreasing driver overhead.
If this sounds like you, you are welcome to give this a try right now by upgrading to 12.04b3, going into the Graphics settings and checking the “Use Zink plugin bridge” check box. Restart X-Plane and if everything goes to plan, X-Plane should look exactly the way you are used to but most importantly your plugins should look right and your performance might be better too. Because Zink is built on top of Vulkan, it’s only available to Windows and Linux users and is not applicable to macOS and Metal.
If you only take one thing away from this blog post, I hope it’s this image showing the difference between native Vulkan/OpenGL interop as well as Zink interop gives you an idea of why we are excited about this:
Now that I hopefully have your attention, let me elaborate how we got here and what this means for both users and developers. First of, Zink is actually a graphics driver that sits between plugins and X-Plane and translates plugin OpenGL rendering into native Vulkan commands that get executed by the same Vulkan device that X-Plane is using for rendering. Of course, X-Plane itself no longer uses OpenGL, but it’s is still very important for plugin development. A long time ago, when X-Plane was still OpenGL based and the plugin SDK was first made, it seemed like an absolute no-brainer to just expose the X-Plane OpenGL context to plugins directly and let them handle all their drawing needs themselves. It gives the most flexibility and control over everything, and it also makes it easy for the SDK because there is no need to make fancy drawing routines to be used by plugins.
Fast forward to the Vulkan and Metal port and we suddenly have an issue: Neither Vulkan nor Metal is OpenGL, but there are now hundreds of plugins out there that all assume X-Plane uses OpenGL and the OpenGL context is there. Killing OpenGL for plugins would mean countless plugins would stop working, requiring potentially lengthy update processes or maybe they’ll just never work at all again because the author lost interest in X-Plane or developing the plugin. This is how we ended up with the OpenGL Bridge in X-Plane 11.50: We create a real OpenGL context, share some memory from within Vulkan to that OpenGL context, then let plugins continue to draw how they used to do. X-Plane takes care of all of the heavy synchronization and resource creation rules under the hood and everyone is happy. Everyone? Well, no, not quite…
The problem with Vulkan/OpenGL interop
The big problem with Vulkan/OpenGL interop is that it relies on the driver to support this properly. As it turns out, driver support for this is flaky at best, if you own an AMD card you can probably tell long stories about issues. The most prominent one is flickering or altogether missing rendering, in which case plugin drawing is either completely missing or flickering in and out of existence making it basically impossible to use plugins. The other issue is performance, captured in the screenshot above, where the OpenGL bridge adds almost 10ms per frame, although I have seen numbers as bad as 30ms per frame. For reference, 33ms is the time one frame can take at most to reach 30 FPS! This wasn’t always the case, it used to run much better, but driver regressions are a real thing and this isn’t really something the hardware vendors test. Not that I can be too mad about this, X-Plane is one of the very few applications that uses this feature at all. Despite having filed numerous bug reports with the vendors, unfortunately the problems were never completely fixed, so even during the 11.50 days we started thinking about alternatives. During the X-Plane 11 days it was at least somewhat easy to tell users to switch back to OpenGL to avoid the flickering, even though that usually meant a hit in performance because the Vulkan backend was just so much faster.
There are of course other open source OpenGL drivers out there that aren’t Zink. The most well known one is probably Angle, a implementation of OpenGL ES by Google. None of them work for us however, because of another terrible decision made many years ago: X-Plane has always used a compatibility profile OpenGL context. What that means doesn’t matter, but the end result is that X-Plane and by extension plugins, rely on the existence of OpenGL commands from the 90s! Most modern implementations of OpenGL will happily ignore everything from the compatibility profile because it’s a nightmare to implement and doesn’t map very nicely to modern hardware at all. But a lot of plugins make use of these old features and rely on the fixed function pipeline. Which, by the way, is also the reason we didn’t just expose Vulkan or Metal to developers. Writing either a Vulkan or Metal renderer requires a ton of overhead, is deeply complicated and error prone. Writing correct code requires testing on different hardware, reading a few thousand pages of specification text and having a good understanding of the underlying hardware. Most plugin developers don’t venture past the fixed function pipeline, it would be absolutely unreasonable to expect them to spend the time and effort involved in this.
What’s a Zink?
Luckily we don’t have to throw any developers into the deep end because there is Zink. Zink is part of the Mesa open source project and is a backend for the Gallium driver, which is the OpenGL frontend provided by Mesa. Okay, lots of big words here, let’s simplify this a bit: Gallium implements OpenGL 1.0 to OpenGL 4.6, which basically means “all of OpenGL”. But it doesn’t actually do anything with it, it just does all of the heavy lifting required to make OpenGL work. Backends are what actually turn the intermediate data that Gallium produces into real commands to be executed by a GPU. There are a lot of these backends: For example there are multiple software renderers that just use the CPU, there are implementations that talk to AMD GPUs, Nvidia GPUs, Intel GPUs, things I never even heard about, it’s all there. But among all of those backends there is also Zink. Zink just takes what Gallium produces and builds Vulkan commands out of it to be executed by any Vulkan capable hardware. This is what makes Zink so great for us, it’s a real OpenGL implementation that includes all of the hard and complicated bits we need to make plugins work.
Of course I’ve made it sound easier than it really is, “just” writing a Gallium backend that magically speaks Vulkan is a lot of hard work. The unsung hero of all this is Mike Blumenkrantz, head honcho and lead developer of Zink. He’s spent years getting Zink to the point it is at and is contentiously working on improving it, both in terms of supported features as well as performance. He’s also an absolute legend and none of this Zink interop X-Plane stuff would exist if it wasn’t for his help, not just in getting Zink to where it is but also answering tons of our questions during the integration. Big shout out to Mike! While I’m doing shout outs, it would be unfair of me to not also mention AMD. While they are partially the reason we are here today, they also provided us with help and driver updates to make Zink work together with X-Plane and every engineer of theirs that I have met along this journey has been nothing but kind and helpful.
I’m a user, how does this affect me?
If you are on X-Plane 12.04b3, open your graphics settings and enable the Zink backend. By default we run with the native OpenGL backend for compatibility reasons, although the long term goal is to switch to Zink exclusively, but not anytime soon. There is a chance some or all of your plugins will explode, we’ve done testing with third party developers on this, but the area touched by this immense and we can’t test every plugin out there. If it breaks, no worries, please file a bug report and let us know, fall back to the native OpenGL backend and try again in the future. The idea behind Zink is to make it as much a “it just works” thing as possible, but it’s the first step and if it isn’t perfect right out of the gate, I hope you have some patience with us. I’m saying this because like I said, the surface area touched is immense here and shipping a whole graphics driver with an application isn’t really something super common and, as I have found out, sometimes breaks stuff.
The good news is that Zink is open source and we are building it ourselves, which means that for the first time we can actually see under the hood when things explode. I have very high hopes that this will help us track down issues much faster than usually. Normally drivers come with all debug data stripped, so a few times I have seen bugs that just end somewhere in the driver with no way to tell what even happened or how to reproduce it. Sometimes we don’t even have any information at all because it got so thoroughly muddied.
I’m a developer, how does this affect me?
Well, same as above: Test your plugins, file bugs, be patient. But also, there are a few things you might want to be aware of in general:
First, X-Plane now finally lets you enable a debug GL context. If you run X-Plane with --debug_gl, X-Plane will make a debug GL context for you and then wire up the necessary callbacks. By default it’ll print all messages into stdout and errors get a big in sim pop up. But you can always redirect it to something of your choosing by calling glDebugMessageCallbackARB() with your own callback. Please don’t ship plugins with a handler enabled though, because it might lead to other developers not being able to set their own callback as there can only be one. The debug GL context is available when running through Zink and also the native GL driver.
Gotcha wise, there are two that I’m aware of:
In theory you can make a shared GL context for background GL processing, but it might not be 100% stable. I’m still trying to track down an issue somewhere in the stack that leads to resources being incorrectly deleted, so if you run into issues with a shared GL context, this might be it. Please try it though!
Don’t disable and/or enable GL_FRAMEBUFFER_SRGB, this will lead to all subsequent rendering to disappear. This bug I have tracked down further into Mesa and the problem is that the driver will create a copy of the image to add or remove the sRGB bit, but it never ends up copying the result back over. In theory this should be handled by just a view on the same image without any copies, but either way this is currently broken.
If you want to test Zink as part of some CI solution, you can also run X-Plane with --zink or --no_zink through the command line and it’ll override whatever was set in the graphics settings.
I’m on macOS and I feel left out
First of all, I’m sorry to hear that. 12.04 has great things for macOS users as well that I’m sure you’ll love. Long term, we are having ideas of running Zink on macOS too, just this time on top of Metal. GL on macOS is already emulated through Metal, it’s just done by Apple without visibility or ways to tap into that. We have a bit of a pipe dream of running plugins on top of Zink on top of MoltenVK on top of Metal, but this is purely in the ideas bin right now and no code for this has been written. There would be two advantages for this approach though: First, Apple has deprecated OpenGL already in macOS and while I do believe they will continue to support it, lest their pro users will climb on their roof and shout bloody murder, they clearly have no interest in expanding OpenGL support any further. Secondly, if we get OpenGL bridging down to just Zink on all platforms, it’d be a boon for developers because they can target just one OpenGL implementation and cover all platforms in one go. It’d also finally bring OpenGL 4.6 support to macOS, which is currently held back to OpenGL 2.1.
Back in June, Ben shared some information regarding X-Plane’s next generation lighting pipeline. It’s now time to go back to the future and talk about another piece of the next generation: Vegetation. In case you have missed it, Chris and Thomson made an awesome preview video for this as well:
With Vulkan and Metal, X-Plane is now firmly in the driver’s seat for VRAM management. This lets us eliminate stutters that were previously present with OpenGL and almost impossible to avoid. It has, however, one big and noticeable downside: when you run out of VRAM, you get blurry textures.
Of course the goal wasn’t to replace stuttering with blurry textures, and we believe that given the normal work load of X-Plane, you should not be seeing this. The fact that so many users are seeing blurry textures, especially on big cards with lots of VRAM, points to the VRAM code being buggy in all the ways beta code can be buggy.
How much VRAM do I need?
Just to get the obvious out of the way, our system requirements have not changed for 11.50. Our minimum VRAM requirement for X-Plane 11 is still 1Gb. We expect these cards to be able to run 1080p with lowered texture resolution, providing an equal experience to X-Plane 11.41. With 2Gb we expect users to be able to run HDR with medium texture resolution on 1080p systems. 4Gb and higher should be able to run HDR at with high resolution textures with 2k monitor resolutions. With 6Gb and higher, 4k monitor resolution should be possible.
Nvidia announced their latest bitcoin graphics cards on August 20th at Gamescom this year. Among the usual increase in transistors, they also disappointed all crypto miners by adding a feature that cannot (yet) be used to calculate cryptographic hashes: Ray Tracing! Ray tracing has long been seen as somewhat of a holy grail of graphics rendering, because it’s much closer to replicating the real world than traditional rasterization and shading. However, doing ray tracing in real time has been close to impossible so far. But hey, Nvidia just announced their new RTX GPUs that can do it, so when is X-Plane going to get a fancy ray traced renderer? This and various other questions that have been asked by X-Plane users, as well as some myths, shall be answered! If you have a question that isn’t answered here, feel free to ask it in the comments.
What Nvidia has shown is absolutely impressive. Unfortunately, the fine print of all the marketing hype is that sadly it can’t just be thrown in without engineering effort. The first thing needed is actual RTX hardware, which no one at LR currently has. The second thing needed is a Vulkan-based app; we are getting there, but not in any way that would support RTX. (the whole goal of the Vulkan renderer is to not change the way the world looks, so we’ll first need a shipping production Vulkan renderer.) But then… well, it’s not entirely clear what it takes to actually write a ray traced renderer in all of its details. Nvidia has not yet published the specification for the Vulkan extension (VK_NV_raytracing), but they have published slides from presentations. One thing is very clear: you can’t just copy and paste five lines of Nvidia sample code and suddenly wake up in a ray traced world.
What Nvidia provides is the scaffolding necessary to describe a scene, as well as to provide new types of shaders that allow casting rays from point A to point B and then report back what they hit along the way. This is a huge amount of work that the hardware is providing here, but it’s not the promised “5 lines and you’ll have ray tracing in your application” that’s being promised. To adopt ray tracing you will have to write the whole ray tracer yourself, from scratch; the hardware just enables you to do so now. This is akin to implementing HDR or PBR: Shaders are the base requirement to implement both of these, but once you have shaders you still need to actually implement HDR or PBR on top of them. Another example is building a house and being provided a plot of land that can support it. Sure, it’s great, now you have a place to build your house, but you still have to come up with a blueprint, pick materials to use and then actually build the thing. Implementing ray tracing will take a great amount of engineering effort, nobody is throwing in awesome reflections with every purchase of one RTX2080Ti for free!
The other thing that’s not entirely clear is how well ray tracing will even perform in an environment like X-Plane! Worlds in X-Plane are huge and open, not small scenes from a shooter with tight spacing. Lot’s of rays are needed, and they have to travel quite far, potentially intersecting with large amounts of geometry. How good does the hardware and API scale up to these sizes? Only time will tell. That’s of course not to diminish Nvidias achievement here, it’s an incredible feat of technology in its own right and this is just the first generation!
The other thing worth mentioning is that ray tracing is not just something that Nvidia secretly cooked up in their basement for a decade. This is going to be an industry wide thing, with APIs that will work across vendors! Historically one vendor has come out with a fancy new way to do things which then became the standard adopted by other vendors. Nvidia has come forward and offered their extension as base for a core Khronos extension for Vulkan. They have a vested interested in making a cross vendor, cross platform API available.
In the foreseeable future, rasterizing renderers are unlikely to go anywhere. Rather, ray tracing for the time being can be used for additional effects that are otherwise hard to achieve. Clearly Nvidia is acknowledging this as well by providing a traditional rasterization engine that by itself is more powerful than previous generation ones. This also means that if X-Plane were to adopt ray tracing tomorrow, you could still run it on your old hardware, you’d just get extra shiny on top if you have ray tracing capable hardware.
Last but not least, this is another reason why you should stay away from the shaders! One day we’ll wake up in the glorious Vulkan future which will open the door to the glorious ray tracing future. All of this means that we’ll have to keep changing our shaders.
X-Plane has always shipped with the shaders visible to everyone as plain text in the Resources/shader directory. Partly this was due to making it convenient to load the shaders into OpenGL itself, but we also don’t have anything to hide there either so it doesn’t make much sense to try to hide them. You are more than welcome to look and poke at our shaders and if you learn something about X-Plane in the process, that’s awesome!
However, the one big caveat to that is that we never considered the shaders to be part of the publicly accessible interface and they are in no way stable across versions. X-Plane is an actively developed product and we are making a lot of changes to the codebase, including the shaders, so you should never ever distribute a plugin or tool that modifies the shaders. Since we give no guarantee that our shaders will remain stable across versions, you’ll always be left worrying that we might break your add-on.
Additionally, there is a big change to the shader system coming in 11.30 that will definitely break all existing plugins that are modifying shaders. This blog post will cover the upcoming changes and hopefully convince everyone that the shader system is in flux and not to be relied upon as a basis for add-ons. Read More
With 11.10 there is a new way aircraft only shadows are done, as well as how aircraft icons are generated. The big change is how we calculate the volume of the aircraft which up until now was based on all OBJ files that the aircraft ships with, including things like ground- and fuel trucks, stairs etc. The reason this is undesirable is because the greater the volume of the aircraft, the worse its realtime shadow quality will be because we use the volume of the aircraft to calculate our shadow map area. The bigger that area, the worse the shadow quality and the more pixelated it will look like. In an ideal world, the aircraft volume tightly hugs around the actual aircraft and we get the best shadow quality possible. With 11.10, hopefully this ideal world is finally here!
Why and how we failed before
Before 11.10 the aircraft volume was based on the volume of, well, the aircraft. However, this includes things such as the aforementioned ground trucks, fuel trucks and what have you, that artificially blow up the volume calculation. The problem is, all these objects are technically part of the aircraft (eg. we move them around with the aircraft), but they are for the most part invisible and most people wouldn’t actually consider them to be part of the aircraft proper.
In 11.05 we added a change to also consider the physical volume which kind of has the right size for the plane but doesn’t include OBJs. It is based on the physical size of the plane only, which sounds like it’s the right thing. However, as it turns out, this volume breaks badly for things such as helicopters because the rotor of some third party helicopters are attached OBJs and won’t be considered part of the physical volume of the helicopter.
At this point I should probably also quickly note what happens if the shadow volume is too small: Everything that gets clipped by the shadow volume will cast a shadow into infinity and beyond due to the way the shadow mapping works. This is especially bad for the helicopters that now have very quickly rotating bits that are constantly clipped by the shadow volume resulting in shadows flickering all over the place.
In short: What we want is a shadow volume that is as tight as possible around the aircraft for shadow quality, but not too tight because that also leads to problems.
What’s new in 11.10
In 11.10 the algorithm to compute the shadow volume has been completely changed. Instead of trying to jiggle around with the physical volume and the volume of all OBJs together and then coming up with a sane value, X-Plane now looks at what is actually being rendered. We start out with the physical bounding volume as before, but then we look at what is actually rendered! For that, we go through every OBJ that is marked as casting shadows and run the OBJ engine as if we were to render the whole thing. So OBJ animations as well as kill datarefs etc are considered. This happens during the first frame, so everything is set up the way it would be during normal rendering. Everything that is visible will be marked as such and the shadow volume will be expanded to include this OBJ.
The result is a volume with a tight fit around what is actually visible and therefore considered “aircraft”. Everything else is not included in the shadow volume and therefore stops casting shadows altogether. Of course, this is only in aircraft only shadow mode and is not used when scenery shadows are on. In that case, everything is handled like it was before and everything that is supposed to cast shadows does cast shadows. So, if you see missing shadows in aircraft only shadow mode, this is probably due to this change.
To visualize the differences, here are 4 screenshots showing the quality difference as well as the new shadow volume:
One thing that should be noted though is that going forwards these kinds of extra OBJs should really be done via the new drawing API in the 3.0 SDK! This allows us to very accurately determine the size of the aircraft but it also means that culling will become more accurate. The old method will of course continue to work, but it’s not the best or most efficient way to approach ground vehicles and other ground clutter.
Aircraft icons
The calculated volume for the whole aircraft with attached OBJs was also used for the aircraft icon generation. This led to some weird cases where the camera was positioned in such way that the aircraft was incredibly tiny due to the fact that we tried to get “everything” in at once. So far the recommendation was for authors to create a version of their aircraft without all the extra OBJs attached, but now that we have an adequate measure of the aircraft volume this is fixed as well! Aircraft icons should be correctly generated now with the camera positioned to capture the plane at the right distance.
There is one more fix for aircraft icons: Some authors created aircraft that did some clever culling based on where the pilots head is and then using the kill dataref to prevent parts of the aircraft from being rendered. Reading the view dataref now correctly reports the camera as being an external camera so that those custom culling solutions work with the aircraft icon generator. If your aircraft still doesn’t generate proper icons after 11.10, please file a bug report and let us know!