mono / SkiaSharp

SkiaSharp is a cross-platform 2D graphics API for .NET platforms based on Google's Skia Graphics Library. It provides a comprehensive 2D API that can be used across mobile, server and desktop models to render images.
MIT License
4.54k stars 542 forks source link

[BUG] SKGLElement on multiple threads #2872

Open Frostchi opened 6 months ago

Frostchi commented 6 months ago

Description

Using the new SKGLElement in SkiaSharp, I get an access violation at the following location in GLWPFControl when I try create an additional SKGLElement on a new Thread:

    public unsafe static IntPtr DXRegisterObjectNV(IntPtr hDevice, IntPtr dxObject, uint name, uint type, WGL_NV_DX_interop access)
    {
        return ((delegate* unmanaged[Stdcall]<IntPtr, IntPtr, uint, uint, WGL_NV_DX_interop, IntPtr>)EntryPoints[21])(hDevice, dxObject, name, type, access);
    }

Code

                var t = new Thread(() =>
                {
                    var form = new MainWindow(); // Main Window has an SKGLElement defined in XAML
                    form.Show();
                    // Start the Dispatcher loop
                    System.Windows.Threading.Dispatcher.Run();
                });
                t.SetApartmentState(ApartmentState.STA);
                t.Start();

Expected Behavior

Ability to create multiple controls (across multiple threads) in application like in SkiaSharp.Views.WindowsForms

Actual Behavior

Unable to do this

Version of SkiaSharp

3.x (Alpha)

Last Known Good Version of SkiaSharp

Other (Please indicate in the description)

IDE / Editor

Visual Studio (Windows)

Platform / Operating System

Windows

Platform / Operating System Version

Windows 11 23H2 64 bit

Devices

No response

Relevant Screenshots

No response

Relevant Log Output

Call stack:

    [Managed to Native Transition]  
>   OpenTK.Graphics.dll!OpenTK.Graphics.Wgl.Wgl.DXRegisterObjectNV(nint hDevice, nint dxObject, uint name, uint type, OpenTK.Platform.Windows.WGL_NV_DX_interop access) Line 533    C#
    GLWpfControl.dll!OpenTK.Wpf.DxGLFramebuffer.DxGLFramebuffer(OpenTK.Wpf.DxGlContext context, int width, int height, double dpiScaleX, double dpiScaleY, OpenTK.Wpf.Interop.Format format)    Unknown
    GLWpfControl.dll!OpenTK.Wpf.GLWpfControlRenderer.SetSize(int width, int height, double dpiScaleX, double dpiScaleY, OpenTK.Wpf.Interop.Format format)   Unknown
    GLWpfControl.dll!OpenTK.Wpf.GLWpfControl.SetupRenderSize()  Unknown
    GLWpfControl.dll!OpenTK.Wpf.GLWpfControl.OnRender(System.Windows.Media.DrawingContext drawingContext)   Unknown
    xxxxxx.dll!SkiaSharp.Views.WPF.SKGLElement.OnRender(System.Windows.Media.DrawingContext drawingContext) Unknown
    PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect)    Unknown
    PresentationFramework.dll!System.Windows.Controls.Grid.ArrangeOverride(System.Windows.Size arrangeSize) Unknown
    PresentationFramework.dll!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect finalRect)    Unknown
    PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect)    Unknown
    PresentationFramework.dll!MS.Internal.Helper.ArrangeElementWithSingleChild(System.Windows.UIElement element, System.Windows.Size arrangeSize)   Unknown
    PresentationFramework.dll!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect finalRect)    Unknown
    PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect)    Unknown
    PresentationFramework.dll!System.Windows.Controls.Border.ArrangeOverride(System.Windows.Size finalSize) Unknown
    PresentationFramework.dll!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect finalRect)    Unknown
    PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect)    Unknown
    PresentationFramework.dll!System.Windows.Controls.Control.ArrangeOverride(System.Windows.Size arrangeBounds)    Unknown
    PresentationFramework.dll!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect finalRect)    Unknown
    PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect)    Unknown
    PresentationFramework.dll!MS.Internal.Helper.ArrangeElementWithSingleChild(System.Windows.UIElement element, System.Windows.Size arrangeSize)   Unknown
    PresentationFramework.dll!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect finalRect)    Unknown
    PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect)    Unknown
    PresentationFramework.dll!MS.Internal.Helper.ArrangeElementWithSingleChild(System.Windows.UIElement element, System.Windows.Size arrangeSize)   Unknown
    PresentationFramework.dll!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect finalRect)    Unknown
    PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect)    Unknown
    PresentationFramework.dll!System.Windows.Controls.Grid.ArrangeOverride(System.Windows.Size arrangeSize) Unknown
    PresentationFramework.dll!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect finalRect)    Unknown
    PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect)    Unknown
    PresentationFramework.dll!System.Windows.Controls.Border.ArrangeOverride(System.Windows.Size finalSize) Unknown
    PresentationFramework.dll!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect finalRect)    Unknown
    PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect)    Unknown
    PresentationFramework.dll!System.Windows.Controls.Control.ArrangeOverride(System.Windows.Size arrangeBounds)    Unknown
    PresentationFramework.dll!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect finalRect)    Unknown
    PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect)    Unknown
    PresentationFramework.dll!System.Windows.Controls.Border.ArrangeOverride(System.Windows.Size finalSize) Unknown
    PresentationFramework.dll!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect finalRect)    Unknown
    PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect)    Unknown
    PresentationFramework.dll!System.Windows.Controls.Grid.ArrangeOverride(System.Windows.Size arrangeSize) Unknown
    PresentationFramework.dll!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect finalRect)    Unknown
    PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect)    Unknown
    PresentationFramework.dll!System.Windows.Controls.Control.ArrangeOverride(System.Windows.Size arrangeBounds)    Unknown
    PresentationFramework.dll!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect finalRect)    Unknown
    PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect)    Unknown
    PresentationFramework.dll!MS.Internal.Helper.ArrangeElementWithSingleChild(System.Windows.UIElement element, System.Windows.Size arrangeSize)   Unknown
    PresentationFramework.dll!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect finalRect)    Unknown
    PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect)    Unknown
    PresentationFramework.dll!MS.Internal.Helper.ArrangeElementWithSingleChild(System.Windows.UIElement element, System.Windows.Size arrangeSize)   Unknown
    PresentationFramework.dll!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect finalRect)    Unknown
    PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect)    Unknown
    PresentationFramework.dll!System.Windows.Controls.Decorator.ArrangeOverride(System.Windows.Size arrangeSize)    Unknown
    PresentationFramework.dll!System.Windows.Documents.AdornerDecorator.ArrangeOverride(System.Windows.Size finalSize)  Unknown
    PresentationFramework.dll!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect finalRect)    Unknown
    PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect)    Unknown
    PresentationFramework.dll!System.Windows.Controls.Grid.ArrangeOverride(System.Windows.Size arrangeSize) Unknown
    PresentationFramework.dll!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect finalRect)    Unknown
    PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect)    Unknown
    PresentationFramework.dll!System.Windows.Controls.Control.ArrangeOverride(System.Windows.Size arrangeBounds)    Unknown
    PresentationFramework.dll!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect finalRect)    Unknown
    PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect)    Unknown
    PresentationFramework.dll!System.Windows.Controls.Grid.ArrangeOverride(System.Windows.Size arrangeSize) Unknown
    PresentationFramework.dll!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect finalRect)    Unknown
    PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect)    Unknown
    PresentationFramework.dll!System.Windows.Controls.Decorator.ArrangeOverride(System.Windows.Size arrangeSize)    Unknown
    PresentationFramework.dll!System.Windows.Documents.AdornerDecorator.ArrangeOverride(System.Windows.Size finalSize)  Unknown
    PresentationFramework.dll!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect finalRect)    Unknown
    PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect)    Unknown
    PresentationFramework.dll!System.Windows.Controls.Grid.ArrangeOverride(System.Windows.Size arrangeSize) Unknown
    PresentationFramework.dll!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect finalRect)    Unknown
    PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect)    Unknown
    PresentationFramework.dll!System.Windows.Window.ArrangeOverride(System.Windows.Size arrangeBounds)  Unknown
    PresentationFramework.dll!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect finalRect)    Unknown
    PresentationCore.dll!System.Windows.UIElement.Arrange(System.Windows.Rect finalRect)    Unknown
    PresentationCore.dll!System.Windows.Interop.HwndSource.SetLayoutSize()  Unknown
    PresentationCore.dll!System.Windows.Interop.HwndSource.RootVisualInternal.set(System.Windows.Media.Visual value)    Unknown
    PresentationFramework.dll!System.Windows.Window.SetRootVisualAndUpdateSTC() Unknown
    PresentationFramework.dll!System.Windows.Window.SetupInitialState(double requestedTop, double requestedLeft, double requestedWidth, double requestedHeight) Unknown
    PresentationFramework.dll!System.Windows.Window.CreateSourceWindow(bool duringShow) Unknown
    PresentationFramework.dll!System.Windows.Window.ShowHelper(object booleanBox)   Unknown
    PresentationFramework.dll!System.Windows.Window.Show()  Unknown

Code of Conduct

Frostchi commented 6 months ago

Not sure if related to https://github.com/opentk/GLWpfControl/issues/58

NogginBops commented 6 months ago

Currently creating GLWPFControls on separate threads is likely not going to work as GLWPFControl is using a static shared OpenGL context which can only be current on one thread. This is a problem when creating controls from another thread as this will call functions that need to access the opengl context, but this context is not going to be current on the separate thread.

There might be some ways around this, I've been slowly refactoring the GLWPFControl code to avoid some of these types of issues (more explicit handling of contexts), but I've not finished that work, not sure when I'll have time to.

Frostchi commented 6 months ago

Currently creating GLWPFControls on separate threads is likely not going to work as GLWPFControl is using a static shared OpenGL context which can only be current on one thread. This is a problem when creating controls from another thread as this will call functions that need to access the opengl context, but this context is not going to be current on the separate thread.

There might be some ways around this, I've been slowly refactoring the GLWPFControl code to avoid some of these types of issues (more explicit handling of contexts), but I've not finished that work, not sure when I'll have time to.

Thanks for the quick response! I am going to hold off on my Winforms -> WPF rewrite for the time being in that case... :grin: