博客 / 詳情

返回

Avalonia 簡易對比不同的 Win32CompositionMode 的性能情況

測試代碼非常簡單,只是嘗試修改一個控件的背景色,讓界面不斷更新而已

以下是 MainWindow.axaml 代碼

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
        x:Class="JowekukurNelaholefewhi.MainWindow"
        Title="JowekukurNelaholefewhi"
        ExtendClientAreaChromeHints="NoChrome"
        Background="Transparent"
        ExtendClientAreaToDecorationsHint="False">
	<Border x:Name="BackgroundBorder">
        <Button x:Name="ChangeTransparencyLevelHintButton" Width="200" Height="100" HorizontalAlignment="Center" VerticalAlignment="Center" Click="ChangeTransparencyLevelHintButton_OnClick"
                Background="Blue">
            <Button.Content>
                <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
                           Foreground="White">
                    Click to Change TransparencyLevelHint
                </TextBlock>
            </Button.Content>
        </Button>
    </Border>
</Window>

以下是 MainWindow.axaml.cs 代碼

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        RendererDiagnostics.DebugOverlays = RendererDebugOverlays.Fps;
        Loaded += MainWindow_Loaded;
    }

    private async void MainWindow_Loaded(object? sender, RoutedEventArgs e)
    {
        while (IsLoaded)
        {
            await Task.Delay(10);

            var color = new Color(0x02, NextByte(), NextByte(), NextByte());
            BackgroundBorder.Background = new ImmutableSolidColorBrush(color);
        }

        static byte NextByte() => (byte) Random.Shared.Next(byte.MaxValue);
    }

    private void ChangeTransparencyLevelHintButton_OnClick(object? sender, RoutedEventArgs e)
    {
        if (TransparencyLevelHint.First() == WindowTransparencyLevel.Transparent)
        {
            TransparencyLevelHint = [WindowTransparencyLevel.AcrylicBlur];
        }
        else
        {
            TransparencyLevelHint = [WindowTransparencyLevel.Transparent];
        }
    }
}

核心是在 MainWindow_Loaded 裏面不斷刷新界面

本文所採用的測試代碼放在 github 和 gitee 上,可以使用如下命令行拉取代碼。我整個代碼倉庫比較龐大,使用以下命令行可以進行部分拉取,拉取速度比較快

先創建一個空文件夾,接着使用命令行 cd 命令進入此空文件夾,在命令行裏面輸入以下代碼,即可獲取到本文的代碼

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 2599a486433e897590ba552cd9049a1bfcdf364f

以上使用的是國內的 gitee 的源,如果 gitee 不能訪問,請替換為 github 的源。請在命令行繼續輸入以下代碼,將 gitee 源換成 github 源進行拉取代碼。如果依然拉取不到代碼,可以發郵件向我要代碼

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin 2599a486433e897590ba552cd9049a1bfcdf364f

獲取代碼之後,進入 AvaloniaIDemo/JowekukurNelaholefewhi 文件夾,即可獲取到源代碼

不同的測試用例我沒有獨立代碼項目,只是通過 git 的 commit 區分

最近我在摸索 Avalonia 的渲染層,這個問題源自於 7 年前,我嘗試給 Avalonia 添加筆跡應用。在去年的時候,我發現 Avalonia 的筆跡性能非常糟糕,今年我設計了一個測試用例。在 Avalonia 窗口上疊加一個透明的 WPF 窗口,從 Avalonia 收到鼠標或觸摸輸入之後,再發送到 WPF 窗口上,讓 Avalonia 和 WPF 窗口同時對一個 Border 進行 RenderTransform 平移

此測試發現了 WPF 的渲染非常跟輸入,而 Avalonia 明顯落後

在我的測試用例裏面,特別讓 Avalonia 窗口去接收輸入,讓 Avalonia 驅動 WPF 的界面。如此可以排除 Avalonia 的輸入層帶來的延遲。完全只對比 Avalonia 和 WPF 的渲染層

詳細請參閲: https://github.com/AvaloniaUI/Avalonia/discussions/20562

實驗情況如下圖所示,藍色為 Avalonia 的控件,紅色是 WPF 的控件

為此,我嘗試了 Avalonia 的各個 Win32CompositionMode 來摸索渲染延遲。以下是我的實驗情況

本次實驗的機器配置如下:

  • 屏幕: 3840x2160 (4K) + 百分百 DPI
  • CPU: i5-12450H
  • GPU: 集顯

LowLatencyDxgiSwapChain

測試代碼: https://github.com/lindexi/lindexi_gd/tree/2599a486433e897590ba552cd9049a1bfcdf364f/AvaloniaIDemo/JowekukurNelaholefewhi

測試結果:

  • GPU: 佔用為 70-80 範圍
  • DWM: 佔用為 1
  • 幀率: 55-60 大部分時候靠近 60 幀率

WinUIComposition

測試代碼: https://github.com/lindexi/lindexi_gd/tree/8c3e57108cafaf5c6ab1c0b371e62f180ba62d9b/AvaloniaIDemo/JowekukurNelaholefewhi

  • GPU: 佔用在 70 附近
  • DWM: 佔用為 40 左右,可見合成過程中確實讓 GPU 非常繁忙
  • 幀率: 20-30 幀

雖然 GPU 沒有吃滿,但是已經掉幀了,感覺這裏應該有坑

DirectComposition

測試代碼: https://github.com/lindexi/lindexi_gd/tree/6b2adfb85f1516663f128d0c8a3a7465069dbdfd/AvaloniaIDemo/JowekukurNelaholefewhi

  • GPU: 佔用在 70 附近
  • DWM: 佔用為 40 左右
  • 幀率: 20-30 幀

可見 WinUIComposition 和 DirectComposition 的問題差不多

而 LowLatencyDxgiSwapChain 能夠獲取比較好的幀率,且對 DWM 佔用比較少

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.