Experimental Multi-Threaded Viewer

From FlightGear wiki
Jump to navigation Jump to search

1rightarrow.png See Multi-Threading in FlightGear for the main article about this subject.

Cquote1.png Perhaps multi-threading is not the answer, but you have to acknowledge that having 7 unused cores is kind of tempting and the first thing one might think about when trying to optimize for modern hardware.
— Icecode GL (Fernando García Liñán)  (Wed Jun 12, 2019). Microsoft Flight Simulator, a small graphics study.
(powered by Instant-Cquotes)

Note  we should be looking to find a way to get more performance on the rendering side as that's what generally limits the frame rate - on Richard's system he did once manage to get a 90% GPU load and a 75% CPU load for FG by enabling 20 OSG Database threads but generally both the CPU (single core) and GPU are running at close to 90% on my system with OSM and high random vegetation.

Experimental multi-threaded viewer
Started in 11/2019 (proof-of-concept)
Description multi-threaded viewer
Contributor(s) Richard Harrison[1]
Status experimental
70}% completed [2]
Changelog https://sourceforge.net/u/richard-harriso/activity/feed.rss
Topic branches:
$FG_SRC https://sourceforge.net/p/flightgear/flightgear/ci/2020-experimental-multithreaded-viewer/tree/

This article is a stub. You can help the wiki by expanding it.

Unless instructed to via config option, FG doesn't do multithreading, so using a single CPU would be the default behavior (and the multithreading isn't as efficient as one would hope because the code never was designed with this in mind).[3]

FG is very single threaded and its only multithreading capabilities come from OSG (its underlying engine). Your CPU has a lower single threaded benchmark score than many other CPUs, so its value mostly comes from the huge amount of cores, which again is useless for FG.[4]

Back in 2019, Richard reported that he has done quite a lot of research in this area and there is some extra performance to be had from using multiple cpu cores. For comparison, Richard is using the F-15 here because he knows that it is pretty well optimised for both Nasal and rendering performance; however it is still heavier than a lot of aircraft at an average of 3.7ms.

When Richard is using his experimental multi-threaded rendering, there is a small increase in performance which is almost equivalent to the 3.7ms of "the rest" - that usually works out to about an extra 10fps (on his system, with the F-15)[5]-

For a few years, Richard has been experimenting with having two threads, one for the rendering and another for the simulation. He's got something that is stable with the occasional glitch.

The net result in terms for performance is there is a frame rate increase, but only by a small amount - the time that the simulation takes. For the F-15 this is currently around 5ms. Simpler models will benefit less, so if a model takes <=1ms there will not be a benefit from this technique.[6]

There are really two things that are important, firstly (and most importantly to Richard) is to avoid frame pauses[1], secondly the overall frame rate. Recent changes to the model loader (DDS texture cache) have reduced frame pauses but there are still things to improve. These two things are also referred to a system load and latency - and are equally important.

For research purposes Richard managed to get the rendering to run in a separate thread to the main simulation loop- and this gives a small increase in performance - effectively the bit at the end of the OSGStats histogram - on the F-15 this is around 5-7ms[2].

Richard spent a lot of time optimising the F-15 over the last few years in general and the last few months in particular - both the 3d and also the Nasal / Canvas to get to the 5-7ms figure and not all aircraft are this well optimised - but there's not a lot we can do about that in the core.[7]


In the context of rendering simulator graphics, the most important thing is fluidity, and that is achieved with consistent frame rates and consistent update rates/amounts. This is something we learned after creating the original FlightGear architecture unfortunately. We thought if we just ran faster, then things would smooth out, and that's not entirely true. If we are running at 60hz and drop a single frame (momentarily down to 30hz) our eye's can pick that out. This is something that's fairly hard to achieve perfectly on a typical operating system like windows or linux. But the current flightgear timing architecture doesn't really help the situation, and the original scene graph library we used didn't offer any tools to manage this.

So by all means, architect a beautiful thread scheduling system that is robust to all the issues threads normally lead to, but keep precise time intervals in mind, or we will never climb out of the timing jitter hole we are currently in. (No worse than FSX probably, but we are no where close to the fluidity of sims like infinite flight and many other 3d games and simulators.) Don't fall into the trap of thinking we can climb out of the hole by just running faster, or boosting our average frame rates. That is only a partial solution.

The FlightGear property system is another beautifully designed piece of artwork. It is extremely powerful and useful for sharing 'state' between different program modules (even between nasal and C++). However, it is not thread safe, and it doesn't lend itself to being made thread safe. The property tree is such an integral part of the FlightGear design ... many of our past threading bugs and workarounds have come from ignoring that our property tree isn't thread safe, but pretending it is and trying to be mostly lucky most of the time. Some of our core developers have taken a really deep look at HLA/DIS as a way to rearchitect the flightgear core infrastructure in a way that is threadable and distributable.

Traditionally, simulation/graphics programs spend upwards of 90% of their time rendering the scene, so if you were to improve the threading of FlightGear, concentrating on the rendering system (engine?) will give you the most bang. Generally things like the FDM and systems modeling take a tiny fraction of the overall program time.

There is lots to digest here, and everything is very interconnected in a mature program like FlightGear ... and very few people (if any?) understand all the interconnections and dependencies simultaneously. [8]


On the F-15 there is only a maximum of 5ms that could be obtained by having a fully multi threaded FG - and realistically this isn't going to be worth the amount of development effort.

The problem is that OpenGL is fundamentally single threaded, although OpenGL does support multi threading it doesn't really gain much because of the driver architecture; and because of this there isn't much that can be gained from OSG from running in multiple threads. This is the problem that Vulkan was designed to fix and until FG supports Vulkan (which is years of work) there is no benefit to be had from multiple CPU's.

The solution to low frame rates is simply to buy a better GPU; if you can afford it. If you can't afford a better GPU then you'll have to turn down the graphics detail or use less demanding aircraft to get decent framerates.

Richard made a short video to try to explain this [9]


The current way Richard is multithreading the viewer is to split out the viewer->frame into the underlying calls:

  • wait for the idleThread to finish.
  • viewer->advance
  • viewer->eventTraversal
  • viewer->updateTraversal
  • release the simulation thread (idleThread.release)
  • viewer->renderingTraversals

This is experimental code to see if it is worth pursuing this route

To see exactly how much time is taken in the simulation firstly set /sim/rendering/sim-frame-count-reset to true (CTRL click in the property browser) and look at /sim/rendering/sim-host-avg-ms


It is generally understood that the lack of LOD in the terrain mesh is contributing to overall system load - and good progress was made on fixing that with the nextgen scenery project but work on that is currently stalled.

What Richard thinks is the best long term solution is to split the rendering into a separate process and keep rest the same - as long as an aircraft model can consume no more than 6.2ms per frame (peaking at 8.3ms) we can have at 120hz simulation core that can then feed the rendering process possibly using CIGI[3]. Now it maybe that he's biased towards this approach because it's what the big sims have been doing since the advent of digital image generation.

The only way Richard can see of truly making use of lots of cores is Vulkan Scene Graph switching to Vulkan because OpenGL is essentially single threaded. Richard has been following the VSG (Vulkan SceneGraph) development lists and progress is being made and this is likely the long term direction that we will need to take; and it might be that this is the time to separate out the rendering.[10]

In the short to medium term we can only improve what we've got, firstly with Compositor, possibly with nextgen scenery but multithreading isn't going to play a major part unless we can separate out the rendering so we'll be using 2.5 cores.