microsoft / WindowsCompositionSamples

The Windows Composition Samples have moved here: https://github.com/microsoft/WindowsAppSDK-Samples/tree/main/Samples/SceneGraph
https://github.com/microsoft/WindowsAppSDK-Samples/tree/main/Samples/SceneGraph
MIT License
1.12k stars 287 forks source link

How to reduce the GPU cost for animations on composition light #331

Closed jasonwun closed 5 years ago

jasonwun commented 5 years ago

Issue Type

[ ] Bug Report
[ ] Feature Request
[ ] Sample request
[ ] Documentation issue or request
[X] Other – Question

Current Behavior

This is a closed issue that was originally posted on WinUI (#867). It seems more related on this repo.

In my app there are animations on two composition lights (PointLight). Somehow I notice that the effect exhausts my integrated GPU resources (nearly 100% utilization) and make the animation not fluent anymore. The CPU model on my SB2 is i7-8650U I thought the integrated GPU is powerful enough to handle the effect but the reality proves my wrong. The cost does not directly generate by my app but dwm.exe. It seems like the effect is delegated to Desktop Window Manager to handle it.
I'm wondering is there way to optimize my implementation and reduce the cost.

Expected Behavior

A reasonable cost, 60%~80% utilization is accepted

Steps to Reproduce (for bugs)

MainPage.xaml <Page x:Class="Test.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="using:Test" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Background="DarkGray" mc:Ignorable="d">

<Grid Loaded="Grid_Loaded">
    <GridView x:Name="GridView" ItemsSource="{x:Bind Source, Mode=OneWay}">
        <GridView.ItemTemplate>
            <DataTemplate x:DataType="x:String">
                <Grid>
                    <Image
                        Width="175"
                        Height="175"
                        Source="ms-appx:///Assets/Vap-logo-placeholder.jpg" />
                </Grid>
            </DataTemplate>
        </GridView.ItemTemplate>
    </GridView>
</Grid>

MainPage.xaml.cs

public sealed partial class MainPage : Page
{
    public ObservableCollection<string> Source { get; set; }
    private Compositor _compositor;
    private PointLight _pointLight;
    private PointLight _secondPointLight;
    private AmbientLight _ambientLight;
    private Visual _root;
    private const float lightDepth = 200f;
    private const int animationDelay = 600;
    private const int animationDuration = 120;

    public MainPage()
    {
        this.InitializeComponent();
        Source = new ObservableCollection<string>();
        for (int i = 0; i < 300; i++)
        {
            Source.Add("a");
        }
    }

    private async void Grid_Loaded(object sender, RoutedEventArgs e)
    {
        _compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
        _root = ElementCompositionPreview.GetElementVisual(GridView);
        _pointLight = _compositor.CreatePointLight();
        _secondPointLight = _compositor.CreatePointLight();
        _pointLight.Offset = new Vector3(200f, 500f, 300f);
        _secondPointLight.Offset = new Vector3(900f, 1000f, 300f);
        _pointLight.Intensity = 1.3f;
        _secondPointLight.Intensity = 1.3f;
        _ambientLight = _compositor.CreateAmbientLight();
        _ambientLight.Intensity = 0.20f;
        _ambientLight.Color = "#d3d3d3".ToColor();

        _pointLight.CoordinateSpace = _root;
        _pointLight.Targets.Add(_root);
        _secondPointLight.CoordinateSpace = _root;
        _secondPointLight.Targets.Add(_root);
        _ambientLight.Targets.Add(_root);

        #region First light animation
        Vector3KeyFrameAnimation lightPositionAnimation;
        lightPositionAnimation = _compositor.CreateVector3KeyFrameAnimation();
        lightPositionAnimation.InsertKeyFrame(.0f, new Vector3(200f, 700f, lightDepth), _compositor.CreateLinearEasingFunction());
        lightPositionAnimation.InsertKeyFrame(.16f, new Vector3(825f, 70f, lightDepth), _compositor.CreateLinearEasingFunction());
        lightPositionAnimation.InsertKeyFrame(.32f, new Vector3(2100f, 40f, lightDepth), _compositor.CreateLinearEasingFunction());
        lightPositionAnimation.InsertKeyFrame(.48f, new Vector3(825f, 70f, lightDepth), _compositor.CreateLinearEasingFunction());
        lightPositionAnimation.InsertKeyFrame(.64f, new Vector3(200f, 700f, lightDepth), _compositor.CreateLinearEasingFunction());
        lightPositionAnimation.InsertKeyFrame(.8f, new Vector3(200f, 100f, lightDepth), _compositor.CreateLinearEasingFunction());
        lightPositionAnimation.InsertKeyFrame(1f, new Vector3(200f, 700f, lightDepth), _compositor.CreateLinearEasingFunction());
        lightPositionAnimation.DelayTime = TimeSpan.FromMilliseconds(animationDelay);
        lightPositionAnimation.Duration = TimeSpan.FromSeconds(animationDuration);
        lightPositionAnimation.IterationBehavior = AnimationIterationBehavior.Forever;

        ColorKeyFrameAnimation lightColorAnimation;
        lightColorAnimation = _compositor.CreateColorKeyFrameAnimation();
        lightColorAnimation.InsertKeyFrame(0f, "#865c2a".ToColor());
        lightColorAnimation.InsertKeyFrame(.2f, "#955a21".ToColor());
        lightColorAnimation.InsertKeyFrame(.4f, "#6c891b".ToColor());
        lightColorAnimation.InsertKeyFrame(.6f, "#62962c".ToColor());
        lightColorAnimation.InsertKeyFrame(.8f, "#6c401b".ToColor());
        lightColorAnimation.InsertKeyFrame(1f, "#865c2a".ToColor());
        lightColorAnimation.DelayTime = TimeSpan.FromMilliseconds(animationDelay);
        lightColorAnimation.Duration = TimeSpan.FromSeconds(animationDuration);
        lightColorAnimation.IterationBehavior = AnimationIterationBehavior.Forever;

        _pointLight.StartAnimation("Offset", lightPositionAnimation);
        _pointLight.StartAnimation("Color", lightColorAnimation);
        #endregion

        #region Second light animation
        Vector3KeyFrameAnimation secondLightPositionAnimation;
        secondLightPositionAnimation = _compositor.CreateVector3KeyFrameAnimation();
        secondLightPositionAnimation.InsertKeyFrame(.0f, new Vector3(2300f, 700f, lightDepth), _compositor.CreateLinearEasingFunction());
        secondLightPositionAnimation.InsertKeyFrame(.16f, new Vector3(1800f, 900f, lightDepth), _compositor.CreateLinearEasingFunction());
        secondLightPositionAnimation.InsertKeyFrame(.32f, new Vector3(400f, 1200f, lightDepth), _compositor.CreateLinearEasingFunction());
        secondLightPositionAnimation.InsertKeyFrame(.48f, new Vector3(1800f, 900f, lightDepth), _compositor.CreateLinearEasingFunction());
        secondLightPositionAnimation.InsertKeyFrame(.64f, new Vector3(2300f, 700f, lightDepth), _compositor.CreateLinearEasingFunction());
        secondLightPositionAnimation.InsertKeyFrame(.8f, new Vector3(2300f, 100f, lightDepth), _compositor.CreateLinearEasingFunction());
        secondLightPositionAnimation.InsertKeyFrame(1f, new Vector3(2300f, 700f, lightDepth), _compositor.CreateLinearEasingFunction());
        secondLightPositionAnimation.Duration = TimeSpan.FromSeconds(animationDuration);
        secondLightPositionAnimation.DelayTime = TimeSpan.FromMilliseconds(animationDelay);
        secondLightPositionAnimation.IterationBehavior = AnimationIterationBehavior.Forever;

        ColorKeyFrameAnimation secondLightColorAnimation;
        secondLightColorAnimation = _compositor.CreateColorKeyFrameAnimation();
        secondLightColorAnimation.InsertKeyFrame(0f, "#81268b".ToColor());
        secondLightColorAnimation.InsertKeyFrame(.2f, "#68446c".ToColor());
        secondLightColorAnimation.InsertKeyFrame(.4f, "#368843".ToColor());
        secondLightColorAnimation.InsertKeyFrame(.6f, "#315b8a".ToColor());
        secondLightColorAnimation.InsertKeyFrame(.8f, "#7d2185".ToColor());
        secondLightColorAnimation.InsertKeyFrame(1f, "#81268b".ToColor());
        secondLightColorAnimation.Duration = TimeSpan.FromSeconds(animationDuration);
        secondLightColorAnimation.DelayTime = TimeSpan.FromMilliseconds(animationDelay);
        secondLightColorAnimation.IterationBehavior = AnimationIterationBehavior.Forever;

        _secondPointLight.StartAnimation("Offset", secondLightPositionAnimation);
        _secondPointLight.StartAnimation("Color", secondLightColorAnimation);
        #endregion
    }
}`

Your Environment

krenner commented 5 years ago

Hi jasonwun - Thanks for reporting the issue. We will take a look.