Board index FlightGear Development Canvas

Color and groups - beware!

Canvas is FlightGear's new fully scriptable 2D drawing system that will allow you to easily create new instruments, HUDs and even GUI dialogs and custom GUI widgets, without having to write C++ code and without having to rebuild FlightGear.

Color and groups - beware!

Postby Thorsten » Thu Mar 16, 2017 8:30 am

I've just learned something rather important about canvas.

After doing canvas a while, I guess all of us love the concept to suitably group things and then translate or hide the whole group, which is a very performance-friendly way to get the job done compared with moving all elements.

Now, I have the situation that the Shuttle HUD has several de-clutter levels which are progressively hidden as the de-clutter function is used. So, I introduce dc0 to dc3 as the groups and operate with selective setVisible() on them according to chosen de-clutter level. I also translate each of the groups with the parallax correction.

All nice and fine.

Then I do the brightness adjustment of the HUD by setting color on the group (specifically the alpha channel).

Code: Select all
var current_color = [hud_color[0], hud_color[1], hud_color[2], 0.2 + 0.7 * brightness];

   me.dc0.setColor(current_color);
   me.dc1.setColor(current_color);
   me.dc2.setColor(current_color);
   me.dc3.setColor(current_color);


I've just spent two hours finding out that the performance impact of doing this is insane. Unlike translations, rotations or visible statements acting on the top level of the group, this one seems to be passed recursively down the child elements, leading to a huge property I/O.

I guess knowing 3d rendering I could have suspected, but then again, it would be possible to implement this in an efficient way if the low-level renderer plays along,... so I didn't know.

Checking the canvas Nasal API page, it seems it's not even documented there that you can set color on the whole group - makes me wonder whether this is an accident or not...

Anyway, if you know what it does, it's a very useful function still - just it can't be used in a performance-critical place, and it should not be confused with performance-friendly group operations.
Thorsten
 
Posts: 10499
Joined: Mon Nov 02, 2009 8:33 am

Re: Color and groups - beware!

Postby Hooray » Thu Mar 16, 2017 8:09 pm

Just briefly, that's the intended behavior actually - back when we were talking about the whole idea of having a "styling" layer, those talks were primarily inspired by James' repeated remarks on using this for other parts of the 2D rendering back-end in FlightGear, to help unify that using the Canvas system to get rid of legacy features, and OpenGL code, using raw/fixed function pipline code (2D panels, HUD, PUI/GUI).

At that point, styling was no longer specific to a single use-case (think GUI/PUI), so that it did make sense to introduce an abstraction mechanism that is agnostic to the concrete use-case, which is in line with other Canvas features whose behavior is intended to work for cascades of elements (think hiding an element, changing its z-index/visibility).

I would agree that many of these implementation details are poorly documented, but that is primarily because a number of folks began declaring the Canvas UI effort a "dead-end" and actively discouraged any attempts at working on this, and other parts of its implementation - including the styling layer specifically.

I would say that the behavior should still look/feel somewhat familiar to people losely familiar with the notion of OOP, and inheritance specifically - no matter if that means, C++, Nasal or even "just" effects inheriting from other effects - at some point we have entites that implicitly inherit properties/attributes (behavior) from other elements, which is basically what the styling mechanism is all about.

However, that code was primarily inspired by the Canvas UI effort, so it didn't see much TLC when the Phi/Qt5 developments gained traction - even though styling is a concept that is not the slightest bit specific to the UI, i.e. would/should apply just as well to other Canvas use-cases, including complex MFDs.

What you may be encountering now is that you are triggering tons of recursive state updates - which in canvas terms basically means firing a huge chain of recursive listeners for each nested group/child element, which triggers an update (and potential redraw operation).

I don't think we were thinking in terms of complex avionics like shuttle when TheTom came up with the existing system, but I do remember that we had a discussion on the forum realizing that what we really needed was a way for property-tree level inheritance, analogous to Tim's effects framework, and that this would also solve a bunch of other challenges, including James' wish to implement instancing support (see the original topic for details).

It would surely be possible to move more of that code back into native C++ code and/or make the existing behavior optional, or introduce a new/better performing mechanism - as far as I can tell, many C++ level optimizations that we originally talked about were not really implemented when the whole Qt5 vs. PUI vs. Canvas UI situation unfolded, which is why and how certain plans suffered obviously.

Speaking in general, it is worth keeping in mind that the Canvas system really just supports a handful of elements, each of which support a few general and element-specific "events", which are mapped into property tree space using listeners for event handling purposes - which is to say that for anything having recursive scope, that also means dispatching events to the corresponding child nodes.

That is one of the reasons why our existing approach of using timers and listeners, and logic implemented in scripting space, is so problematic from a performance standpoint, but also from a distribution standpoint, i.e. anything involving setups where MFD/Canvas state may need to be selectively propagated/updated across multiple fgfs instance - no matter if that means FSWeekend/LinuxTag-like setups or multiplayer/multi-pilot setups sharing a cockpit with MFD state.

With these challenges in restrictions in mind is unfortunately becoming obvious that the way we have been coding Canvas MFDs is far too inflexible and does not lend itself to supporting these use-cases, short of introducing new dedicated elements for MFD entites like a page, button, mode, page element etc, so that the canvas tree/scene graph can use native C++/OSG data structures instead of having to go through Nasal space unnecessarily, at which point it would become much easier to implement such behavior without adding unnecessary overhead via listeners, timers and Nasal/C++ context switches.
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 11309
Joined: Tue Mar 25, 2008 8:40 am

Re: Color and groups - beware!

Postby Thorsten » Thu Mar 16, 2017 9:12 pm

Just briefly, that's the intended behavior actually


This is an information propagation problem, not a code problem. Once I knew what it does, the fix was trivial.

(Ironically, the use case is actually not very heavy as such - it's brightness (or rather alpha) adjustment of the HUD, and any aircraft with a HUD can potentially see similar issues if the alpha adjustment is one canvas-side).

I would say that the behavior should still look/feel somewhat familiar to people losely familiar with the notion of OOP, and inheritance specifically


The point is not that it's strange, the point is that it's completely to how setTranslation or setVisible work which are *not* recursively applied - so it could have been implemented differently, from the API naming convention this is far from obvious.
Thorsten
 
Posts: 10499
Joined: Mon Nov 02, 2009 8:33 am

Re: Color and groups - beware!

Postby Necolatis » Thu Mar 16, 2017 10:15 pm

I have had use for this also, I iterate through all elements in the HUD when the brightness is changed (in latest github version with your new HUD shader its only the alpha I set though).

I did not know that you could set colors on the group, otherwise I would have included it on the wiki Canvas API page when I wrote it. Maybe it was added later, since I seem to remember I checked the C code to find all methods when I made that page.

So is setting color on a group slower than iterating through all elements and setting it on each? Does it do the same?
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore


Hangar: https://sites.google.com/site/fghangar/
User avatar
Necolatis
 
Posts: 1906
Joined: Mon Oct 29, 2012 12:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2018.3.2
OS: Windows 10

Re: Color and groups - beware!

Postby Thorsten » Fri Mar 17, 2017 11:00 am

It'd actually be trivial to let the shader handle this - except we can't rely on people using the shader...
Thorsten
 
Posts: 10499
Joined: Mon Nov 02, 2009 8:33 am

Re: Color and groups - beware!

Postby Hooray » Sat Mar 18, 2017 7:21 am

if you don't want this feature the way it is currently implemented, it would be best to provide a dedicated property/API per element/group to override the old behavior and use a new/better performing alternative; please just don't touch any legacy functionality that may break things like the Canvas UI
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 11309
Joined: Tue Mar 25, 2008 8:40 am

Re: Color and groups - beware!

Postby Thorsten » Sat Mar 18, 2017 7:56 am

Whether this would work on the canvas level depends on how the low level code organizes the scenegraph with regard to color information. Obviously efficient hierarchies are done for transformation matrices and visibility, so it's quite possible to do this for color, the question is whether this is actually done or not.

But as I said, conceptually there's no need for canvas to talk to the shader, the HUD brightness knob can talk directly to the shader - we just need to organize the effects properly.
Thorsten
 
Posts: 10499
Joined: Mon Nov 02, 2009 8:33 am

Re: Color and groups - beware!

Postby Hooray » Sat Mar 18, 2017 8:17 am

Like you said previously, this won't work for the non-shader/non-effects use-case, which is currently still supported/priotized.
However, I think James and Mathias discussed on several ocassions that it may no longer be reasonable to do so necessarily - i.e. declaring a cut-off date/version, after which FlightGear may simply leave certain "cruft" behind, i.e. to be able to do "breaking changes" to support newer hardware (or OSG features).
I think, those talks began back when Fred began introducing Rembrandt support, and everybody (and their dog) wanted to make that the default startup mode :D
Seriously though, it may not be that far-fetched to discuss a cut-off date/version (e.g. FlightGear 2020.1), at which point the default startup settings would make certain assumptions, such as effects/shaders always being available, and FBO support to be working properly.

I guess this would be best discussed on the devel list and a corresponding wiki article created to pave the way for this, maybe with additions to the newsletter pointing to the article, and a corresponding sticky forum announcement asking for feedback.

As far as I remember, a number of contributors did have ideas to raise the hardware requirements, and accordingly, the default startup settings - but hesitated doing so, because of backward compatiblity requirements.

From the Canvas standpoint it would not be that bad to be able to re-implement certain functionality on top of features that cannot currently be assumed to be always available (e.g. shaders).

I think you also once mentioned that the ADI ball would be best implemented in the form of effects/shaders ?

Regarding the scenegraph organization, we really need to be using more OSG-level data structures and map those to "canvas properties", to do away with things that the C++ code is currently handling, especially those doing context switches between Nasal and native code using timers and listeners - the most prominent use-case being animations built on top of timers and listeners - OSG has native data structures for doing this sort of thing, and we only really need to introduce new elements (or even just attributes) to make use of those, which would also mean doing away with tons of Nasal-induced overhead due to timers and listeners animating a Canvas element currently.
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 11309
Joined: Tue Mar 25, 2008 8:40 am

Re: Color and groups - beware!

Postby Thorsten » Sat Mar 18, 2017 8:59 am

Well, actually I can live with a HUD not supporting brightness adjustment on legacy hardware which can't run any shaders. I'd be willing to cause this kind of breakage...
Thorsten
 
Posts: 10499
Joined: Mon Nov 02, 2009 8:33 am


Return to Canvas

Who is online

Users browsing this forum: No registered users and 1 guest