• Which the release of FS2020 we see an explosition of activity on the forun and of course we are very happy to see this. But having all questions about FS2020 in one forum becomes a bit messy. So therefore we would like to ask you all to use the following guidelines when posting your questions:

    • Tag FS2020 specific questions with the MSFS2020 tag.
    • Questions about making 3D assets can be posted in the 3D asset design forum. Either post them in the subforum of the modelling tool you use or in the general forum if they are general.
    • Questions about aircraft design can be posted in the Aircraft design forum
    • Questions about airport design can be posted in the FS2020 airport design forum. Once airport development tools have been updated for FS2020 you can post tool speciifc questions in the subforums of those tools as well of course.
    • Questions about terrain design can be posted in the FS2020 terrain design forum.
    • Questions about SimConnect can be posted in the SimConnect forum.

    Any other question that is not specific to an aspect of development or tool can be posted in the General chat forum.

    By following these guidelines we make sure that the forums remain easy to read for everybody and also that the right people can find your post to answer it.

FSX:SE Separate gauge dll slows down the rendering of other dll gauges?

Messages
820
Country
ca-ontario
Hi all,

I have a gauge DLL with several gauges inside. This gauge DLL was developed using GDI+ template and then applied multi-threading code as in the D2D gauge template, both templates available in the resources section. Everything is working as advertised. Then I added a new gauge which seemed to be graphically intensive (circular gradient fills with alphas), and it bogged the whole gauge rendering speed down noticeably. Note, the whole sim runs fine, but the gauge display refresh went from the default 18hz down to, I'd say, about 7-8 Hz. So - seeing this, I decided to separate this "bad" gauge from the rest of the "good" gauge into its own DLL. They both render into virtual cockpit textures, and each has its own [VCockpit0n] entry in panel.cfg.

However, I am still seeing the frame rate drain, as before, on both gauges.

My question is, I was expecting that the "bad" gauge would be a separate drawing process and run at its own refresh rate, and the "good" gauge would be allowed to run at its own merry 18hz. What am I doing wrong?
 
Messages
531
Country
france
As far as I know, you are doing nothing wrong Misho. The drawing process in FSX is single-threaded, I even believe that FSX in itself is single-threaded. It means that if a gauge consumes CPU time to draw, it slows down all the other gauges and also the sim itself, thus reducing the frame rate. I experienced the same some years ago with GDI+ intensive gauges, when the average PC was not as powerful as today. At this time, I tried to implement multi-threading in the drawing process of the gauge so that if it takes time to draw, the gauge is slow in its own thread while the others keep running as fast as possible in the FSX main thread. It was almost working and I finally gave it up.
Even longer ago, I had a navigation display that was using a text navigation database. Fetching this kind of database is much slower than a SQL request, so getting info from the base was slowing the whole sim for the same reason. This time I successfully used multi-threading and the search time in the database was not affecting the displays.

Eric
 
Messages
2,084
Country
us-ohio
I am concerned about the comment of "refresh went from default 18hz". The actual render cycle is based on frame rate. A gauge update cycle is 18hz, but that is not the same as the render cycle. Are you certain you're doing the actual render outside of the callback loop?
 
Messages
918
Country
indonesia
the scripting technique could cause frame rate eater.
about "circular gradient? is it bitmap/images?
GDI+ is not good friend for rendering images. use scripts code to draw.
 
Messages
820
Country
ca-ontario
Thanks everyone!
It means that if a gauge consumes CPU time to draw, it slows down all the other gauges and also the sim itself, thus reducing the frame rate.
As I stated, the sim itself runs at smooth 60 fps. The "bad" gauge appears to have a minimal impact on the main sim rendering. It, however, does slow down other dll gauges...

I am concerned about the comment of "refresh went from default 18hz". The actual render cycle is based on frame rate. A gauge update cycle is 18hz, but that is not the same as the render cycle. Are you certain you're doing the actual render outside of the callback loop?

I have a MFD.dll that draws, for example, an attitude ball, and it updates smooth. When I activate the "bad" gauge (let's call it "bad.dll"), it immediately slows down MFD.dll - the attitude ball update gets choppy. As for the callback loop - my code is implemented exactly as laid out in the templates I mentioned above. While I don't pretend to understand the intricacies of D2D and how the author set it up to work with threading, the GDI+ and D2D setups are fairly similar, so the implementation of threading code used in D2D was relatively simple (as the author pointed out).

about "circular gradient? is it bitmap/images?

No - no bitmaps or images of any kind in the gauge. I am using GDI+ object PathGradientBrush which creates gradients along given paths. In my case, a path is a circle. I need to create a circle filled with gradient, starting from solid color in the centre to an alpha fadeout towards the edges - a fuzzy ball. I need to do this using code, because the gradient and alpha parametrically changes. And literally, one line:

mGraphics->FillEllipse(&pthGrBrush, Rect);

is the cause of the slowdown.
 
Messages
918
Country
indonesia
Did you destruct it?
I use several gradient draw, no frame rate impact.
Use double destruction, after drawn and normal destruction when gauge ended.
 
Messages
820
Country
ca-ontario
Did you destruct it?
I use several gradient draw, no frame rate impact.
Use double destruction, after drawn and normal destruction when gauge ended.

I use local object with implicit constructor:

PathGradientBrush pthGrBrush(&path);

Not an explicit constructor with global pointer:

PathGradientBrush *pthGrBrush = new PathGradientBrush(&path); ... delete pthGrBrush;

Is that what you mean? But that is just memory management, not the actual drawing.
 
Messages
918
Country
indonesia
for path gradient, I not create global pointer.

Code:
        PathGradientBrush pgradBrushF(&engFpath);
        pgradBrushF.SetCenterPoint(Point(39, 600));
        pgradBrushF.SetCenterColor(Color(255, 0, 255, 255));
        Color warnaF[6] = { Color(255, 0, 80, 80), Color(255, 0, 255, 255), Color(255, 0, 80, 80), Color(255, 0, 80, 80), Color(255, 0, 255, 255), Color(255, 0, 80, 80) };
        pgradBrushF.SetSurroundColors(warnaF, 6);
        pgradBrushF.SetFocusScales(0.9f, 0.9f);
        g.FillRegion(&pgradBrushF, &regionF);
 
Messages
820
Country
ca-ontario
for path gradient, I not create global pointer.

Code:
        PathGradientBrush pgradBrushF(&engFpath);
        pgradBrushF.SetCenterPoint(Point(39, 600));
        pgradBrushF.SetCenterColor(Color(255, 0, 255, 255));
        Color warnaF[6] = { Color(255, 0, 80, 80), Color(255, 0, 255, 255), Color(255, 0, 80, 80), Color(255, 0, 80, 80), Color(255, 0, 255, 255), Color(255, 0, 80, 80) };
        pgradBrushF.SetSurroundColors(warnaF, 6);
        pgradBrushF.SetFocusScales(0.9f, 0.9f);
        g.FillRegion(&pgradBrushF, &regionF);

That's exactly what I do. pgradBrushF goes out of scope and is automatically cleaned up.

So - how exactly do you "double destruct" it? What did you mean by that?
 
Messages
820
Country
ca-ontario
Ok, I understand - but what's the syntax? What does the code look like? Is there a GDI+ call that is used to properly destroy this object?
 
Messages
918
Country
indonesia
this my code, delete immediately after.
Code:
            brownhrznBrush = new LinearGradientBrush(
                Point(int(-sbx / 2.f), int(ladder)),
                Point(int(-sbx / 2.f), int(ladder + 135.f)),
                Color(255, 205, 160, 78),
                Color(255, 47, 35, 13));

            REAL relativeIntensities[] = { 0.0f, 0.5f, 1.0f };
            REAL relativePositions[] = { 0.0f, 0.4f, 1.0f };
            (*brownhrznBrush).SetBlend(relativeIntensities, relativePositions, 3);
            g.FillRectangle(brownhrznBrush, RectF(roll > -15 && roll < 105 ? -600.f : roll < -125 || roll > 165 ? -830 : -700, ladder, 3.f * sx, sby));
            SAFE_DELETE(brownhrznBrush)

I not sure you mixed up D2D and GDI+ or not. I using same template and using GDI+ only.
 
Messages
820
Country
ca-ontario
Ah ok, I see what you meant. Assuming that SAFE_DELETE is just a macro for "delete ptr; ptr = NULL", yeah that does not do anything (I had a feeling it wouldn't but I implemented and tested it just to make sure). The culprit is the call itself, or who knows, maybe threading in this case works as a detriment.

Thanks for the help and the suggestion. I'll gladly entertain any other suggestions...
 
Top