2

I am building a .NET MAUI app that's designed to run on iOS, specifically on an iPad Pro. In it I need to be be able to sample sections of an image based on a number of parameters and display that on screen, so I thought the best way to do that would be through a shader and the SkiaSharp SKRuntimeEffect and SKShader classes seemed like a good way to do it. I made a custom control that inherits from SKCanvasView and wrote an SkSL shader. However, whenever the code reaches the DrawRect() call in the OnPaintSurface method of the class, the app crashes immediately.

I have made a bare bones app that has only a custom control with a trivial shader that just sets each pixel colour to red and the crash still happens. The code for the custom control is:

using SkiaSharp;
using SkiaSharp.Views.Maui.Controls;
using System.Diagnostics;

namespace SkiaShaderTest.Controls
{
    public class Panel : SKCanvasView
    {
        public static BindableProperty ShaderOnProperty = BindableProperty.Create(
            nameof(ShaderOn),
            typeof(bool),
            typeof(Panel),
            false,
            propertyChanged: (bindable, oldValue, newValue) =>
            {
                var panel = (Panel)bindable;
                panel.InvalidateSurface();
            }
        );

        public bool ShaderOn
        {
            get => (bool)GetValue(ShaderOnProperty);
            set => SetValue(ShaderOnProperty, value);
        }


        protected override void OnPaintSurface(SkiaSharp.Views.Maui.SKPaintSurfaceEventArgs args)
        {
            var canvas = args.Surface.Canvas;
            var info = args.Info;

            canvas.Clear();

            if (ShaderOn)
            {
                var src = @"
                    float4 main(float2 fragCoord) {
                        return float4(1,0,0,1);
                    }";
                using var effect = SKRuntimeEffect.Create(src, out string error);
                using var shader = effect.ToShader(true);


                using (SKPaint paint = new SKPaint() { Shader = shader })
                {
                    try
                    {
                        canvas.DrawRect(info.Rect, paint);
                    }
                    catch (Exception e)
                    {
                        Debug.WriteLine($"Exception {e.GetType()}: {e.Message}");
                    }
                }
            }
            else
            {
                using (SKPaint paint = new SKPaint())
                {
                    paint.Color = SKColors.BlueViolet;
                    canvas.DrawRect(info.Rect, paint);
                }
            }
        }

    }
}

And this is the xaml layout of the app:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="SkiaShaderTest.MainPage"
             xmlns:controls="clr-namespace:SkiaShaderTest.Controls"
>

 <Grid RowDefinitions="*,auto" IgnoreSafeArea="True">
        <controls:Panel x:Name="panel"
                HorizontalOptions="FillAndExpand"
                VerticalOptions="FillAndExpand"
                Grid.Row="0"
                Grid.RowSpan="2"/>

        <CheckBox
            IsChecked="{Binding ShaderOn, Source={x:Reference panel}, Mode=TwoWay}"
            MinimumWidthRequest="100"
            BackgroundColor="RoyalBlue"
            Color="AliceBlue"
            HorizontalOptions="Center"
            VerticalOptions="End"
            />
    </Grid>

</ContentPage>

The full code of this example app can be found here: https://github.com/LFLumirithmic/SkiaShaderTest

Every time the line canvas.DrawRect(info.Rect, paint); is reached (when the ShaderOn flag is set to true), the app crashes instantly.

I have tried it on the iPad itself (it's an iPad Pro (12.9 inch) (4th generation)), in an iOS simulator, on the Mac Mini that I use to build to the iPad and on a separate Windows 11 laptop. On the iPad it crashes with no error messages or console output whatsoever, without even throwing an exception. On the Mac, it also doesn't throw an exception, but gives the following console output: https://github.com/LFLumirithmic/SkiaShaderTest/blob/main/mac-console-output.rtf

On Windows, however, it does throw an exception with this output:

System.Runtime.InteropServices.SEHException
  HResult=0x80004005
  Message=External component has thrown an exception.
  Source=<Cannot evaluate the exception source>
  StackTrace:
<Cannot evaluate the exception stack trace>

(note that it doesn't reach the code in the catch block, the visual studio debugger simply throws the exception at the actual DrawRect() line)

I tried to create one of the default shaders that can be created using the SkiaSharp C# API, for example:

using (SKPaint paint = new SKPaint())
{
    SKShader shader = SKShader.CreateLinearGradient(
        new SKPoint(0, 0),
        new SKPoint(1000, 1000),
        new SKColor[]
        {
            new SKColor(0,0,255),
            new SKColor(0,255,0)
         },
         null,
         SKShaderTileMode.Repeat
     );
     paint.Shader = shader;
     canvas.DrawRect(info.Rect, paint);
}

and that works perfectly.

These are the SkiaSharp packages I've got installed through NuGet in my Visual Studio project

As far as I can tell, these are the correct packages and the latest versions thereof.

The console output I see on the Mac and the exception thrown on Windows seem to point to there being an error inside SkiaSharp itself, but I very much don't want to discount the possibility that I'm doing something wrong.

Does anyone have an idea of what I might be doing wrong and/or how this issue might be fixed?

LFLumi
  • 21
  • 2
  • Alternatively, does anyone know of an alternative to SkiaSharp and SKCanvasView for getting a shader to draw to screen in a .NET MAUI App? Perhaps a way to do it inside a GraphicsView? – LFLumi Jun 18 '23 at 23:02
  • 1) 3D: [OpenGLView](https://learn.microsoft.com/en-us/dotnet/api/microsoft.maui.controls.openglview?view=net-maui-7.0). 2) Without `{ Shader = shader }`, the DrawRect doesn't crash? (I see the "else" case is essentially that; just making sure.) 3) `out string error` - does that contain anything? – ToolmakerSteve Jun 19 '23 at 00:43
  • 4) The Skia Shader examples I see use `half4 main(float2 fragCoord) { ... }`. Instead of `float4`. – ToolmakerSteve Jun 19 '23 at 00:54
  • @ToolmakerSteve thanks for the suggestions. 1) Unfortunately, OpenGLView is already deprecated and is due to be removed altogether in .NET 8 so I'd rather use something that will have support. 2) Yeah, it doesn't crash without it. 3) The error is null - the error usually contains any shader compiler error, in which case the effect object is null. 4) Makes no difference, sadly. Skia shaders can have half4/float4/vec4 as return values or float2/vec2 as the function parameter. I'll make an edit to clarify some of this points. – LFLumi Jun 19 '23 at 10:20
  • I hadn’t realized .Net and Maui were dropping OpenGL support. What .net version are you testing on? If it is 7, have you tried `builder.UseMauiCompatibility`? I see that is needed for Maui OpenGl; maybe shaders need it. – ToolmakerSteve Jun 19 '23 at 13:05
  • I recommend adding an issue at [github SkiaSharp issues](https://github.com/mono/SkiaSharp/issues). That is where the `SkiaSharp.Views.Maui.Controls` namespace code is, including class SkCanvasView. – ToolmakerSteve Jun 19 '23 at 20:31
  • Related to this issue: [SKRuntimeEffect compilation is missing build-in functions](https://github.com/mono/SkiaSharp/issues/1868). – Liqun Shen-MSFT Jun 20 '23 at 02:29
  • Thanks for the suggestions again. I tried `builder.UseMauiCompatibility`, but it didn't change anything - according to the .NET MAUI documentation, that's needed to enable OpenGLView within .NET 7 where it is deprecated. And I've already opened issues on the SkiaSharp repo as well as the maui one – LFLumi Jun 20 '23 at 13:28
  • Yes I saw the GitHub issue you raised: [Custom shader in SKCanvasView crashes .NET MAUI App](https://github.com/mono/SkiaSharp/issues/2496). Thanks for your share. – Liqun Shen-MSFT Jul 13 '23 at 09:36

0 Answers0