swampthing wrote in Wed Oct 09, 2019 12:36 pm:... from my experience more JSBsim systems and less nasal = beter FPS. I don't think for some things you can move away from nasal all together. It comes down to what your plane requires. I'm not aware of any way to make canvas displays with JSBsim code for instance. I'm not against nasal but I can see where people may want to do full JSBsim sytems and I think for the most part if you can get a good grasp of it, you can with JSBsim.
Actually, that's a valid point: Originally, the whole Canvas idea started out as a property-driven 2D drawing system, but admittedly, what we ended up with is a system that is meanwhile tightly coupled to Nasal unfortunately. Indeed, there are some things where you definitely need to use Nasal to set up/initialize things. But under the hood, 99% still is pure property I/O, which is also why the property tree is becoming a bottleneck.
In general, Nasal is not the problem here - but the way the Canvas system is designed, and the way both, Nasal and Canvas, are integrated - it's a single-threaded setup, i.e. we are inevitably adding framerate-limited scripted code that runs at <= 60 hz to the main loop, to update rendering related state. This is a bit problematic, but it's not a real problem to fix.
It would be a problem to fix up existing Canvas-code (think NavDisplay, PFDs, EICAS etc), but with a few minor tweaks, we could come up with a dedicated Canvas mode where scripts updating a canvas property tree, are running out of the main loop. This would mean that they could not access any of the mainloop-APIs, but apart from that, it's actually a no-brainer, i.e. a straigthforward thing to do.
Out of the box, OSG comes with support for creating and updating textures asynchronously, we just aren't using this currently - for obvious reasons, coding such a Canvas texture, would be a different thing. But the hooks required to make this happen, are fairly straigthforward.
One starting point would be changing the assumption that all canvas texture PROPERTIES live in the global property tree, instead each Canvas texture would get its own SGPropertyNode, which isn't accessible from anywhere else.
At that point, you have a Canvas/OD_Gauge context that can be updated by changing said PRIVATE property tree. As long as this property tree is only ever updated from single place (thread), multi-threading things becomes possible, because you only need to serialize access whenever you want fetch/display the updated texture. But apart from that, the update/redraw mechanism could be running in a background thread.
From a Canvas perspective, one obvious issue is dealing with Canvas textures that fetch data/imagery from other textures, because that, too, would require synchronization.
But other than that, you would end up with a Canvas system whose textures can be asynchronously updated by a background thread, scripts doing so would look a bit different, because they would lack access to 90% of the common FG APIs (think geodinfo and friends), because those cannot be considered to be thread-safe.
As you can probably tell, this is something that we once discussed behind the scenes - and it would nicely align with the original idea of "remote properties", i.e. sync'ing and replicating properties between property trees from different threads/processes, the main thing needed to do this is a subscribe/publish mechanism that works over sockets (or some other IPC): http://wiki.flightgear.org/Remote_Properties
This is something where Richard's Emesary work could become highly useful, because the cost of adapting the Canvas system to optionally support an out-of-mainloop mode would be marginal - further, bugman's ongoing work on unit-testing and unit-testing Nasal in particular, should come in very handy, because it would become much easier to start up dedicated FGNasalSys instances (our in-sim Nasal interpreter) that may not run inside the main loop, i.e. lacking most standard FG APIs.
Now, when it comes to using Canvas without Nasal, that's actually a valid use-case, and I find it important to keep that use-case in mind, because over time, we've seen more and more attempts at coming up with frameworks, that basically shield back-end code from changes to front-end code (and vice versa), this is why it is important to primarily work through the property tree, and not rely on dedicated Nasal bindings (cppbind).
It would be a good thing to keep this in mind, because doing so means that multi-instance setups supporting Canvas would become much easier, i.e. there is no problem using Nasal at all, as long as it happens through well-defined interfaces that basically hide the scripting aspect.
Furthermore, a number of core devs have been thinking about using the Canvas system for scenery-related runtime-drawing, which would also require Canvas to become thread-safe, i.e. using a dedicated/private property tree instance to isolate all access to the property tree that is used to update/redraw such textures, which would mean that anything involving OSM2City, photo-scenery, but even random buildings, could be enormously boosted by making the Canvas system available accordingly:
Most recently, James posted this a couple of days ago:
https://sourceforge.net/p/flightgear/ma ... /36781190/
James Turner wrote:We actually have quite a lot of code examples of the ‘painting’ part - since the map-widget, Canvas-map, and launcher-map all do this kind of thing to render some limited GIS data (eg, taxiways, runways or urban areas) into different 2D surfaces - often even, a texture. One could even imagine a system where Canvas itself is used to do the drawing, although then we have to efficiently get the source data available to Canvas/Nasal, and deal with threading issues since this work has to happen asynchronously in an OSG pager thread.
http://wiki.flightgear.org/Canvas_Scenery_Overlays
http://wiki.flightgear.org/Photoscenery
Speaking in general, once each Canvas texture uses its own, private, property-tree instance, it would be fairly straightforward to also add private instances of a Nasal interpreter and a "property rules" system to each canvas - these are existing features in simgear/flightgear, once you add SGSocket-based connectivity and Richard's Emesary system, you have a 2D drawing system that can run asynchronously, out of the main loop, and you don't even have to use Nasal, but can use property rules (or JSBSim systems) to create/update OpenGL textures.
Again, like I said, it's not difficult to add a SGPropertyNode instance to each Canvas texture, but it paves the way for a future where a Canvas texture and the logic creating/updating it, can live (run) outside the main loop, with the main loop only fetching the final image, or possibly streaming it from another process (for which we already have working code, thanks to ThomasS).
Torsten's autopilot/property rules code is highly functional and it could be easily extended to support event handling constructs, so that we can do away with Nasal based timers and listeners to update a Canvas. Richard's Emesary system is a very neat mechanism to establish the coding protocols to do message-based programming, and once you have these systems hooked up to a single private property tree instance, you can literally have your cake and eat it. Most of this is really code we already have, it's just not yet integrated. But once that is tackled by someone, you also end up with a Canvas system that can boost development of anything involving autogen-scenery like osm2city, think random buildings and osm2city integrated via the Canvas system.
These steps would also help move towoards a CompositeViewer based FlightGear architecture:
http://wiki.flightgear.org/CompositeViewer_Support
http://wiki.flightgear.org/Canvas_Troub ... internally
http://wiki.flightgear.org/Compositor
As usual, we have a ton of great code all over the place, just lacking the manpower (and overall plan) to integrate things properly.
But as can be seen, many areas in FlightGear could enormously benefit by adapting the Canvas system to OPTIONALLY support per-texture property trees that are conceptually private, so each canvas texture can have its own scripting interpreter instance, property rules and timers/events (listeners).
The key efforts here are really bugman's work on unit testing and Richard's work on Emesary - using their groundwork, sooner or later, someone will be brave enough to come up with a new canvas mode that can run asynchronous Nasal scripts to create and update a texture , while those scripts will look very different, and probably even intimidate people new to message-based coding and multi-threading, they will come with the benefit of not cluttering the main loop, i.e. providing stable frame rates and frame spacing.