opengl SkiaSharp导致Windows上多个上下文的访问冲突

f4t66c6m  于 2023-11-18  发布在  Windows
关注(0)|答案(1)|浏览(151)

我正在为Mupen64Plus模拟器做一个前端,它支持自定义脚本,可以绘制它的视频输出。然而,我的实现在Windows上似乎是错误的(由于某种原因,在Linux上没有)。
这个MVE模仿了我用来渲染图形的系统。要编译它,你需要安装NuGet的Silk.NET.OpenGLSilk.NET.SDLSkiaSharp

  • 视频插件控制着大部分的渲染循环,它的动作通过调用Render()来表示。
  • 下面的行表示当视频插件请求交换缓冲区时发生的情况:
  • OpenGL输出被刷新
  • 它切换到一个单独的上下文来呈现Skia的输出
  • Skia的输出被刷新了
  • OpenGL渲染

它将在Windows上的第72行触发访问违规。

using System.Diagnostics;
using Silk.NET.OpenGL;
using Silk.NET.SDL;
using SkiaSharp;

Sdl sdl = Sdl.GetApi();

unsafe
{
    sdl.SetHint(Sdl.HintVideodriver, "x11");
    if (sdl.Init(Sdl.InitVideo | Sdl.InitEvents) != 0)
        SdlAbort();

    sdl.GLSetAttribute(GLattr.ContextMajorVersion, 4);
    sdl.GLSetAttribute(GLattr.ContextMinorVersion, 1);
    sdl.GLSetAttribute(GLattr.ContextProfileMask, (int) GLprofile.Compatibility);

    sdl.GLSetAttribute(GLattr.RedSize, 8);
    sdl.GLSetAttribute(GLattr.GreenSize, 8);
    sdl.GLSetAttribute(GLattr.BlueSize, 8);
    sdl.GLSetAttribute(GLattr.AlphaSize, 8);
    sdl.GLSetAttribute(GLattr.Doublebuffer, 1);
    sdl.GLSetAttribute(GLattr.StencilSize, 8);

    Window* window = sdl.CreateWindow("Test", Sdl.WindowposCentered, Sdl.WindowposCentered, 800, 600, (uint) WindowFlags.Opengl);
    void* mainCtx = sdl.GLCreateContext(window);
    GL mainGL = GL.GetApi(x => (IntPtr) sdl.GLGetProcAddress(x));

    void* skiaCtx = sdl.GLCreateContext(window);
    if (sdl.GLMakeCurrent(window, skiaCtx) != 0)
        SdlAbort();

    using var grContext = GRContext.CreateGl();
    Debug.Assert(grContext != null);
    using var surface =
        SKSurface.Create(grContext,
            new GRBackendRenderTarget(800, 600, 0, 8, new GRGlFramebufferInfo(0, (uint) GLEnum.Rgba8)),
            SKColorType.Rgba8888);
    Debug.Assert(surface != null);

    if (sdl.GLMakeCurrent(window, mainCtx) != 0)
        SdlAbort();

    Init(mainGL);

    bool shouldClose = false;
    while (true)
    {
        Event evt = new();
        while (sdl.PollEvent(ref evt) != 0)
        {
            switch ((EventType) evt.Type)
            {
                case EventType.Windowevent:
                    switch ((WindowEventID) evt.Window.Event)
                    {
                        case WindowEventID.Close:
                            shouldClose = true;
                            break;
                    }

                    break;
            }
        }

        Render(mainGL);
        mainGL.Flush();
        if (sdl.GLMakeCurrent(window, skiaCtx) != 0)
            SdlAbort();
        Render2(surface.Canvas);
        surface.Flush();
        if (sdl.GLMakeCurrent(window, mainCtx) != 0)
            SdlAbort();
        sdl.GLSwapWindow(window);

        if (shouldClose)
            break;
    }
    sdl.GLDeleteContext(mainCtx);
    sdl.DestroyWindow(window);

    sdl.QuitSubSystem(Sdl.InitVideo | Sdl.InitEvents);
}

void SdlAbort()
{
    throw new Exception($"SDL: {sdl.GetErrorS()}");
}

void Init(GL gl)
{

}

void Render(GL gl)
{
    gl.ClearColor(0.0f, 0.0f, 1.0f, 1.0f);
    gl.Clear(ClearBufferMask.ColorBufferBit);
}

void Render2(SKCanvas canvas)
{
    using var lime = new SKPaint
    {
        Color = SKColors.Lime
    };
    canvas.DrawCircle(300, 300, 100, lime);
}

字符串
是什么导致了这些类型的segfaults,我应该做些什么来避免它们?

qq24tv8q

qq24tv8q1#

事实证明,我所描述的错误是由我的虚拟机设置中错误的图形驱动程序引起的;使用不同的驱动程序可以工作。
我在这里记录了这个问题,现在已经修复了:https://gitlab.freedesktop.org/mesa/mesa/-/issues/9460

相关问题