Boost Mac performance with Metal and Delphi 10.4 by Erik van Bilsen
Erik van Bilsen - May 25, 2020
Erik van Bilsen - May 25, 2020
[SHOWTOGROUPS=4,20]
Is your Mac app a little unresponsive or does it feel sluggish? Does your MacBook laptop turn into a lap-heater when running your app? Then the new Metal support in Delphi 10.4 may be just the thing for you and your customers!
But before we get into that, let first look at the technologies that Delphi uses to render the GUI. These are split into 3 areas: canvas drawing, text layout and 3D rendering. Each of these 3 areas can use a different technology based on operating system and some global configuration flags. For the default configuration, the technologies used on Windows and macOS are:
You can check which technologies are currently used in your app by checking the type of the TCanvas, TTextLayout and TContext class.
GPU Based Rendering
Now the issue is that the CoreGraphics (or Quartz) rendering technology of macOS is quite slow, especially when used to render the GUI manually (as FireMonkey does).
Until now, you could try to switch to GPU based rendering by setting the GlobalUseGPUCanvas variable to True at application startup.
This changes the table to:
Now, 2D user interfaces are rendered using the same 3D context that is used for 3D applications. For calculating and rendering text layouts, Delphi uses its own implementation in this case (called TGPUTextLayout) that builds an atlas of character glyphs and renders these with the same 3D context.
However, using GlobalUseGPUCanvas on Windows results glitches and issues when using high-DPI displays. And on macOS, this flag doesn’t work at all and results in a EContext3DException when used. It works quite well for iOS and Android though…
So you were pretty much stuck with CoreGraphics on macOS. Until now that is…
Metal to the Rescue
Apple has deprecated OpenGL for a while now, and may drop support for it altogether in one of the next macOS/iOS versions. Instead, you have to use their own graphics API called Metal.
Make sure you add the FMX.Types unit to the uses clause.
Performance Gains
To measure the difference in performance between CoreGraphics and Metal, I created a small 2D FireMonkey application that stress tests the rendering engine. It is basically a form with a whole lot of controls on it, mostly copied from the ControlsDemo sample app that ships with Delphi. You can find it in our Для просмотра ссылки Войдиили Зарегистрируйся.
The application tries to repaint the window as fast as possible. To make sure the entire form is repainted, the background color is constantly changed. The application also tests the impact of rendering a 3D control (the globe) inside a 2D form. You can hide this control with the checkbox in the top-left corner to see the difference.
You need to build one of these 3 Release configurations:
[/SHOWTOGROUPS]
Is your Mac app a little unresponsive or does it feel sluggish? Does your MacBook laptop turn into a lap-heater when running your app? Then the new Metal support in Delphi 10.4 may be just the thing for you and your customers!
Rendering Technologies in DelphiI have been given permission by Embarcadero to blog about this new feature in the upcoming Delphi 10.4 release.
But before we get into that, let first look at the technologies that Delphi uses to render the GUI. These are split into 3 areas: canvas drawing, text layout and 3D rendering. Each of these 3 areas can use a different technology based on operating system and some global configuration flags. For the default configuration, the technologies used on Windows and macOS are:
Technology | Windows | macOS |
---|---|---|
Canvas | Direct2D | CoreGraphics (Quartz) |
Text layout | DirectWrite | CoreText |
3D Rendering | Direct3D | OpenGL |
This is the default configuration that is used if available. Note that Delphi may fallback to other technologies if the default is not available. For example, it may fallback to a GDI+ canvas if Direct2D is not available (although that will almost never be the case anymore these days).I am limiting this article to Windows and macOS. Maybe I will talk about mobile performance in a future article.
You can check which technologies are currently used in your app by checking the type of the TCanvas, TTextLayout and TContext class.
GPU Based Rendering
Now the issue is that the CoreGraphics (or Quartz) rendering technology of macOS is quite slow, especially when used to render the GUI manually (as FireMonkey does).
Until now, you could try to switch to GPU based rendering by setting the GlobalUseGPUCanvas variable to True at application startup.
This changes the table to:
Technology | Windows | macOS |
---|---|---|
Canvas | Direct3D | OpenGL |
Text layout | Custom | Custom |
3D Rendering | Direct3D | OpenGL |
However, using GlobalUseGPUCanvas on Windows results glitches and issues when using high-DPI displays. And on macOS, this flag doesn’t work at all and results in a EContext3DException when used. It works quite well for iOS and Android though…
So you were pretty much stuck with CoreGraphics on macOS. Until now that is…
Metal to the Rescue
Apple has deprecated OpenGL for a while now, and may drop support for it altogether in one of the next macOS/iOS versions. Instead, you have to use their own graphics API called Metal.
Fortunately, Delphi 10.4 has full support for Metal now. But is still defaults to using CoreGraphics, CoreText and OpenGL for backwards compatibility reasons.The trends in graphics APIs is to become more low-level and closer to the metal (no pun intended). We have seen this with DirectX 12, Vulkan and Metal. These APIs are considerable more difficult to work with than their predecessors, but provide greater performance in return. It is up to library/framework/engine developers now to provide more user-friendly access to these APIs.
If you want to take advantage of Metal (and you should), then all you have to do is to set the GlobalUseMetal variable to True before doing anything else. The best place to do that is inside the .dpr file, before you create your forms. For example:You may think that Metal is especially important for 3D applications, and doesn’t make much of a difference for 2D apps. However, the opposite is true (as you will see later): 2D applications in particular can take advantage of Metal because it eliminates the need for the slow CoreGraphics technology.
program MetalApp; uses System.StartUpCopy, FMX.Forms, FMX.Types, FMain in 'FMain.pas' {FormMain}; {$R *.res} begin GlobalUseMetal := True; Application.Initialize; Application.CreateForm(TFormMain, FormMain); Application.Run; end. |
Performance Gains
To measure the difference in performance between CoreGraphics and Metal, I created a small 2D FireMonkey application that stress tests the rendering engine. It is basically a form with a whole lot of controls on it, mostly copied from the ControlsDemo sample app that ships with Delphi. You can find it in our Для просмотра ссылки Войди
The application tries to repaint the window as fast as possible. To make sure the entire form is repainted, the background color is constantly changed. The application also tests the impact of rendering a 3D control (the globe) inside a 2D form. You can hide this control with the checkbox in the top-left corner to see the difference.
You need to build one of these 3 Release configurations:
- Default: uses the default rendering technology (CoreGraphics, CoreText and OpenGL on macOS).
- Metal: uses Metal for all rendering. This sets GlobalUseMetal to True.
- GPUCanvas: sets GlobalUseGPUCanvas to True. This uses the Direct3D on Windows and OpenGL on macOS for all rendering. Note that this configuration will not work on macOS and may lead to glitches on Windows.
[/SHOWTOGROUPS]