FSX:SE D2D vs. GDI+: Can anyone tell me if there are advantages between one over the other?

#1
Hi everyone,

Is 2D2 gauge (written for FSX) taking advantage of graphics acceleration hardware?

I've done a lot of GDI+ custom gauge programming, and all in all, I'm quite happy with it. However, lately I've noticed some major bottlenecks and FPS losses, and I was wondering if anyone has any experience with what NOT to do. In particular, a bitmap stretching is a huge no-no, as the rescaling of bitmaps in GDI+ is a very resource intensive process. In general, I've been trying to get away from using bitmaps for simple MFD-type line art. However, I've noticed also that a serious bottleneck can be a RotateTransform() call, especially in a container consisting of text.

Case in point: I tried moving away from bitmap-type compass wheel with a mask "window" (HSI) to a code-generated HSI "card" set consisting of a circle, 36 tick marks and 36 10-degree labels. Creating this in GDI+ requires 36 RotateTransform() calls on the label containers, and this seems to draw a rather large FPS penalty.

So, I was wondering if a move to D2D would speed things up? Does anyone have any experience or benchmarks with this?
 
#2
I think going to D2D would be a step backwards. If you are having GDI+ performance issues, it's going to be about how you have written your rendering code. GDI+ is a pretty decent rendering engine.
 
#3
Hmmm - okay, thanks! I was sure that someone stated that D2D was preferred over GDI+ because it takes advantage of hardware acceleration, but I'm not sure if that applies to the context of FSX gauges.

Perhaps I'll do some benchmarking myself and see how they compare.
 
#4
If you're going to benchmark the manipulation of bitmaps... then you're looking in the wrong direction to begin with. With GDI+ you don't typically render bitmaps at all, you render everything by drawing it all. If a compass rose is killing your frame rates, it's not GDI+ that's the issue... it's your code for drawing the compass rose. Also, GDI+ gauges tend to use separate threads these days to get their rendering done. There is an example here on how to create a threaded gauge for GDI+ rendering. My first foray in to GDI+ was Eaglesoft's Citation X. It has 10 or 11 GDI+ rendered screens in it's VC.
 

JB3DG

Resource contributor
#5
@Misho I was the one who first tried out D2D and posted the examples here in the forum and resources section. While it does in some respects work faster than GDI+, it is a pain to work with (D3D11 is actually nicer) and some operations for dynamic complex shapes can slow things down. As such, I turned my back on it very quickly. As Ed says, multi threaded GDI+ is much better, but be careful about using Raster images with it as they will eat processing resources.

That said, I have abandoned both D2D and GDI+ now. I wrote my own 2D vector rendering library that uses D3D11 so I can use it with P3D's PDK. I mimicked the GDI+ function call structure but also added many other features that I have long wanted. Can't share though, as it is proprietary to MV.
 
#7
@Misho I was the one who first tried out D2D and posted the examples here in the forum and resources section. While it does in some respects work faster than GDI+, it is a pain to work with (D3D11 is actually nicer) and some operations for dynamic complex shapes can slow things down. As such, I turned my back on it very quickly. As Ed says, multi threaded GDI+ is much better, but be careful about using Raster images with it as they will eat processing resources.

That said, I have abandoned both D2D and GDI+ now. I wrote my own 2D vector rendering library that uses D3D11 so I can use it with P3D's PDK. I mimicked the GDI+ function call structure but also added many other features that I have long wanted. Can't share though, as it is proprietary to MV.
Yes, sir, and I thank you, it got me going with the D2D setup, plus, I also have a GDI+ template that MS's ESP provided from way back, when Microsoft evolved FSX to ESP (which I understand, is the predecessor to P3D.) Now, I have no idea if the ESP's GDI+ template is multi-threaded... how can I tell?

Incidentally - You made the D2D template freely available in FSDeveloper's resources (wiki) section, but I don't see ESP GDI+ template. If allowed, I'd gladly provide it, just let me know how.
 
Last edited:

JB3DG

Resource contributor
#8
https://www.fsdeveloper.com/forum/resources/gdi-gauges-drawing-msdn-example.162/

The ESP version (link above) isn't multi threaded. The DrawThread.cpp in the D2D example however shows how to implement a separate thread and sync it with the gauge callback. I think you may have to have 3 different flag states, one signalling when the gauge callback refreshes (telling the drawthread to run), the next which is set by the draw thread (telling the gauge callback to call SET_OFF_SCREEN), and the last indicating that SET_OFF_SCREEN has been called so the gauge callback can refresh it on the next call. That way you can avoid some nasty flashing I have encountered when using GDI+ in a separate thread.
 
#9
Oh, there it is! I am still trying to figure out difference between wiki and resources on this site ;) Ok great, I'll check it out and see if it's worth implementing. I've never had any nasty flashing - I just ran into some performance issues that I'm trying to nail down.
 
#10
D2D is interesting because it is accelerated, but if you plan to use it in a FS gauge in the "standard" way, using IMAGE_CREATE_DIBSECTION drawing flag, it has no interest because what you draw in the fast memory of the graphic card using D2D will have to be transfered to a 2D bitmap to be rendered in the gauge, and this is where all time is lost. I am not expert enought in D2D to know if there still is an benefit in using D2D, but like other developers who contributed to this discussion, I also sticked to (optimized) GDI+.
Because of my past experiences who gave me some knowledge of OpenGL, I also tried this for gauge 2D drawing and the problem is the same. At the time I tried (with FS2004), it was even worse because FS2004 had no OpenGL renedring capbilities so it had to be rendered with a software engine, a nightmare...
In conclusion, I would say that if it was really interesting, other developers would have done it, and as far as I know it is not the case. Many products use GDI+ and others use their own rendering engine.

Eric
 

JB3DG

Resource contributor
#11
I used D3D11 at one point with SSE instructions to transfer the image to the gauge. The transfer from GPU to CPU wasn't too bad for smaller glass displays. I have dumped the FS gauge system for displays though. Since Milviz went P3Dv4 only, I have switched to using the PDK and pure D3D11.
 
#12
D2D is interesting because it is accelerated, but if you plan to use it in a FS gauge in the "standard" way, using IMAGE_CREATE_DIBSECTION drawing flag, it has no interest because what you draw in the fast memory of the graphic card using D2D will have to be transfered to a 2D bitmap to be rendered in the gauge, and this is where all time is lost. I am not expert enought in D2D to know if there still is an benefit in using D2D, but like other developers who contributed to this discussion, I also sticked to (optimized) GDI+.
Because of my past experiences who gave me some knowledge of OpenGL, I also tried this for gauge 2D drawing and the problem is the same. At the time I tried (with FS2004), it was even worse because FS2004 had no OpenGL renedring capbilities so it had to be rendered with a software engine, a nightmare...
In conclusion, I would say that if it was really interesting, other developers would have done it, and as far as I know it is not the case. Many products use GDI+ and others use their own rendering engine.

Eric
Great - thanks for the insight! I'm actually relieved! What I am finding in my various test rigs is that the GDI+ gauge, especially complex one, takes a huge hit on CPU, no matter what graphics card the system has. My "worst" rig I test on is a 6 year old, and mediocre for that time, 4-core 8GB AMD. On this rig I have a decent GPU GeForce GTX 1060. What I observe is:

  • I open a flight in the outside view and I get 60fps.
  • When I go to VC with my GDI+ gauges, I get an instant 20fps drop. This includes the "known" an dreaded VC FPS drop when cursor is displayed, and the hit from my gauge. If the cursor goes away after a few seconds, I get "back" 5-10 fps.
  • When I return to my outside view, I do not get my 60 fps back. It is as if the FSX is saying "oh, you want me now to process gauge? Sure, but I'll be doing it in all the views from now on"...
  • The only way to get my FPS back is to flip a switch that turns my gauge completely off (within vc - it just disables rendering routines)
On my "better" test rigs the FPS loss is as above, but at around 5-10 fps, instead of 20.

Is this about the right "behavior" for the VC cockpits? Is everyone more or less observing this?
 
#15
Threading is a must for complex graphics... also, you need to be careful about how you set up your GDI+ code. Don't create/destroy things all over the place... very, very bad performance.
 
#16
Threading is a must for complex graphics... also, you need to be careful about how you set up your GDI+ code. Don't create/destroy things all over the place... very, very bad performance.
Thanks for the tips. I do pre-load all my bitmaps, but here and there I do have pens and brushes local to functions, didn't think that would be a huge load. Containers and clipping masks are all created and destroyed locally - I don't see how else to do that since they are nested.
 
#19
Bitmaps have a performance cost... no matter what. They should always be used sparingly, if at all. Pens and brushes and fonts... should be only made once... nothing about them changes with regards to display sizing, etc... so they are truly static items. While you might think creating them on the fly isn't a performance issue... it's memory allocation, initialization, etc... it takes CPU cycles, which takes time. It all adds up.
 
#20
I can't say more than what WarpD already said. I use all the "tricks" he described and I have decent performance, even on my old PC from 2008 that runs FS 2004 with a GTX240!!
As WarpD said, GDI+ hates bitmap. I use GDI+ only for glass cockpit displays on which everything is drawn with lines, rectangles, circles,... What we call vector graphics.
Some years ago, I developed AVG, Analog Vector Gauges. The goal was to use GDI+ and its smooth graphics capabilities (anti-aliasing, smooth sub-pixel rotation, transparency,...) to draw standard Cessna Gauges, with needles and rotating parts. It was smooth and beautiful, but terribly slow...
 
Top