Skip to content

Memory Leak from CanvasBitmap #1009

@solocle

Description

@solocle

Saw this as a major issue in a production project, rising to 40GB of commit charge in half an hour.

The issue seems to be hardware-linked, as it doesn't seem occur on an Nvidia RTX, but does on Intel Arc A40.

Minimum reproduction:

New UWP .NET 9 project (also seen in .NET Native)

MainPage.xaml

<Page
    x:Class="CanvasMemoryLeak.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:CanvasMemoryLeak"
    xmlns:win2d="using:Microsoft.Graphics.Canvas.UI.Xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <win2d:CanvasAnimatedControl x:Name="Leaky" Draw="Leaky_Draw" Update="Leaky_Update" />
</Page>

MainPage.xaml.cs

using Windows.UI.Xaml.Controls;
using Microsoft.Graphics.Canvas.UI.Xaml;
using Windows.UI;
using System.Runtime.InteropServices.WindowsRuntime;
using Microsoft.Graphics.Canvas;
using System;
using Microsoft.Graphics.Canvas.Effects;

namespace CanvasMemoryLeak
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a <see cref="Frame">.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            InitializeComponent();
            Buffer = new byte[WIDTH * HEIGHT];
            Buffer.AsSpan().Fill(127);

        }

        private const ushort WIDTH = 640;
        private const ushort HEIGHT = 480;

        private byte[] Buffer;

        private static readonly ColorSourceEffect White = new ColorSourceEffect() { Color = Colors.White };
        private static readonly ColorSourceEffect Black = new ColorSourceEffect() { Color = Colors.Black };

        private void Leaky_Draw(ICanvasAnimatedControl sender, CanvasAnimatedDrawEventArgs args)
        {
            var ds = args.DrawingSession;
            ds.Clear(Colors.Black);
            var source = Buffer.AsBuffer();
            using (var bmp = CanvasBitmap.CreateFromBytes(ds,source, WIDTH, HEIGHT, Windows.Graphics.DirectX.DirectXPixelFormat.A8UIntNormalized))
            {
                using(var alpha = new AlphaMaskEffect() { Source = White, AlphaMask = bmp })
                {
                    using (var blend = new BlendEffect() { Foreground = alpha, Background = Black, Mode = BlendEffectMode.Screen })
                        ds.DrawImage(blend);
                }
            }
        }

        private void Leaky_Update(ICanvasAnimatedControl sender, CanvasAnimatedUpdateEventArgs args)
        {
            var random = new Random();
            for (int pos = 0; pos < Buffer.Length; pos++)
            {
                int value = Buffer[pos];
                value += random.Next(-10, 10);
                Buffer[pos] = (byte)Math.Clamp(value, 0, 255);
            }
        }
    }
}
`

System Configuration:
i7-14700
32GB RAM
Intel Arc Pro A40 driver 32.0.101.6979

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions