"ERROR creating stencil attachment" 在带有 OpenTK 的 SkiaSharp 中

"ERROR creating stencil attachment" in SkiaSharp with OpenTK

我试图让 SkiaSharp 在 Windows 应用程序中使用 OpenGL 后端,所以我在互联网上找到了这个示例 https://gist.github.com/d-kr/eeced4157bf926accc9c6ad435d37a37

问题

在我的笔记本电脑上 运行使用 GTX1050 一切正常,但在我的台式机 运行使用 GTX1060 时却不行。两个系统 运行 Windows。如您在下图中所见,创建并填充了 OpenTK GameWindow。

在我的笔记本电脑上你可以看到正在绘制圆圈,但在我的桌面上它会抛出一条错误消息说 ERROR creating stencil attachment. Draw skipped。我能够追踪到 OnRenderFrame() 的错误,发生在调用 canvas.DrawCircle() 时。

第一次尝试

我非常了解 SkiaSharp,但我对 OpenTK 还很陌生。 我在这里遗漏了什么? 在 Google 上我只找到了这个 post https://groups.google.com/forum/#!topic/skia-discuss/m53JH2scDh4 这表明这是某种 设置或硬件问题。那么我从哪里开始调试呢? 这些是我的依赖项:

提前致谢!


必要的代码

using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;
using SkiaSharp;
using System;
using System.Diagnostics;

// https://gist.github.com/d-kr/eeced4157bf926accc9c6ad435d37a37

namespace NetCoreDesktop
{
    public sealed class MainWindow : GameWindow
    {


    private GRContext context;
    private GRBackendRenderTargetDesc renderTarget;

    public MainWindow()
        : base(1280, // initial width
        720, // initial height
        GraphicsMode.Default,
        "window",  // initial title
        GameWindowFlags.Default,
        DisplayDevice.Default,
        1, // OpenGL major version
        0, // OpenGL minor version
        GraphicsContextFlags.ForwardCompatible) {
            Title += ": OpenGL Version: " + GL.GetString(StringName.Version);
    }

    protected override void OnLoad(EventArgs e) {
        base.OnLoad(e);
        var glInterface = GRGlInterface.CreateNativeGlInterface();
        Debug.Assert(glInterface.Validate());
        this.context = GRContext.Create(GRBackend.OpenGL, glInterface);
        Debug.Assert(this.context.Handle != IntPtr.Zero);
        this.renderTarget = CreateRenderTarget();
        CursorVisible = true;
    }

    protected override void OnUnload(EventArgs e) {
        base.OnUnload(e);
        this.context?.Dispose();
        this.context = null;
    }

    protected override void OnResize(EventArgs e) {
        GL.Viewport(0, 0, Width, Height);
    }


    protected override void OnUpdateFrame(FrameEventArgs e) {
        HandleKeyboard();
    }
    private void HandleKeyboard() {
        var keyState = Keyboard.GetState();
        if (keyState.IsKeyDown(Key.Escape)) {
            Exit();
        }
    }

    public static GRBackendRenderTargetDesc CreateRenderTarget() {
        GL.GetInteger(GetPName.FramebufferBinding, out int framebuffer);
        GL.GetInteger(GetPName.StencilBits, out int stencil);
        GL.GetInteger(GetPName.Samples, out int samples);
        int bufferWidth = 0;
        int bufferHeight = 0;
        GL.GetRenderbufferParameter(RenderbufferTarget.Renderbuffer, RenderbufferParameterName.RenderbufferWidth, out bufferWidth);
        GL.GetRenderbufferParameter(RenderbufferTarget.Renderbuffer, RenderbufferParameterName.RenderbufferHeight, out bufferHeight);

        return new GRBackendRenderTargetDesc {
            Width = bufferWidth,
            Height = bufferHeight,
            Config = GRPixelConfig.Bgra8888, // Question: Is this the right format and how to do it platform independent?
            Origin = GRSurfaceOrigin.TopLeft,
            SampleCount = samples,
            StencilBits = stencil,
            RenderTargetHandle = (IntPtr)framebuffer,
        };
    }


    protected override void OnRenderFrame(FrameEventArgs e) {
        base.OnRenderFrame(e);

        Title = $"(Vsync: {VSync}) FPS: {1f / e.Time:0}";

        Color4 backColor;
        backColor.A = 1.0f;
        backColor.R = 0.1f;
        backColor.G = 0.1f;
        backColor.B = 0.3f;
        GL.ClearColor(backColor);
        GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

        this.renderTarget.Width = this.Width;
        this.renderTarget.Height = this.Height;

        using (var surface = SKSurface.Create(this.context, this.renderTarget)) {
            Debug.Assert(surface != null);
            Debug.Assert(surface.Handle != IntPtr.Zero);

            var canvas = surface.Canvas;

            canvas.Flush();

            var info = this.renderTarget;

            //canvas.Clear(SKColors.Beige);

            using (SKPaint paint = new SKPaint {
                Style = SKPaintStyle.Stroke,
                Color = SKColors.Red,
                StrokeWidth = 25
            }) {
                canvas.DrawCircle(info.Width / 2, info.Height / 2, 100, paint);
                paint.Style = SKPaintStyle.Fill;
                paint.Color = SKColors.Blue;
                canvas.DrawCircle(info.Width / 2, info.Height / 2, 100, paint);
            }

            canvas.Flush();
        }
        this.context.Flush();
        SwapBuffers();
    }


}
}

出于某种原因,StencilBits 设置为零,这是无效的。将其设置为固定值(如 1)会有所帮助。

public static GRBackendRenderTargetDesc CreateRenderTarget() {
    ...
    return new GRBackendRenderTargetDesc {
        ...
        StencilBits = 1,
        ...
    };
}