picoe / Eto.Veldrid

Veldrid control for Eto.Forms
MIT License
15 stars 6 forks source link

Crash if the viewport is on a tabpage and tab is changed away and back #11

Closed philstopford closed 5 years ago

philstopford commented 5 years ago

Take the existing MainForm() constructor and make it :

` public MainForm(GraphicsBackend backend, string executableDirectory, string shaderSubdirectory) { InitializeComponent();

        Shown += (sender, e) => FormReady = true;

        PixelLayout mpl = new PixelLayout();
        Content = mpl;

        TabControl tc = new TabControl();
        TabPage tp = new TabPage();
        tc.Pages.Add(tp);
        TabPage tp2 = new TabPage();
        tc.Pages.Add(tp2);
        PixelLayout pl = new PixelLayout();
        tp.Content = pl;

        Panel p = new Panel();
        p.Size = new Size(100, 100);
        pl.Add(p, 1, 1);

        mpl.Add(tc, 1, 1);

        Surface = new VeldridSurface(backend);
        Surface.VeldridInitialized += (sender, e) => VeldridReady = true;

        p.Content = Surface;

        ovpSettings = new OVPSettings();
        ovpSettings.enableFilledPolys = true;
        ovpSettings.drawPoints = true;

        PointF[] testPoly = new PointF[6];
        testPoly[0] = new PointF(2.0f, 2.0f);
        testPoly[1] = new PointF(15.0f, 12.0f);
        testPoly[2] = new PointF(8.0f, 24.0f);
        testPoly[3] = new PointF(8.0f, 15.0f);
        testPoly[4] = new PointF(3.0f, 2.0f);
        testPoly[5] = new PointF(2.0f, 2.0f);

        PointF[] testPoly2 = new PointF[6];
        testPoly2[0] = new PointF(12.0f, 2.0f);
        testPoly2[1] = new PointF(25.0f, 12.0f);
        testPoly2[2] = new PointF(18.0f, 24.0f);
        testPoly2[3] = new PointF(18.0f, 15.0f);
        testPoly2[4] = new PointF(13.0f, 2.0f);
        testPoly2[5] = new PointF(12.0f, 2.0f);

        ovpSettings.addPolygon(testPoly2, Color.FromArgb(0, 255, 255), 1.0f, true);

        ovpSettings.addPolygon(testPoly, Color.FromArgb(255, 0, 0), 1.0f, true);

        ovpSettings.addPolygon(testPoly2, Color.FromArgb(0, 255, 255), 1.0f, false);

        ovpSettings.addPolygon(testPoly, Color.FromArgb(255, 0, 0), 1.0f, false);

        Driver = new VeldridDriver(ref ovpSettings, ref Surface)
        {
            Surface = Surface,
            ExecutableDirectory = executableDirectory,
            ShaderSubdirectory = shaderSubdirectory
        };
    }

`

Change to the second tab and then back to the first. A crash will occur:

{"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."}'

in the SwapChain call below:

` public void InitializeOtherApi() { Control.Loaded += (sender, e) => { // To embed Veldrid in an Eto control, all these platform-specific // versions of InitializeOtherApi use the technique outlined here: // // https://github.com/mellinoe/veldrid/issues/155 // var source = SwapchainSource.CreateWin32( WinFormsControl.Handle, Marshal.GetHINSTANCE(typeof(VeldridSurface).Module));

            Widget.Swapchain = Widget.GraphicsDevice.ResourceFactory.CreateSwapchain(
                new SwapchainDescription(
                    source,
                    (uint)RenderWidth,
                    (uint)RenderHeight,
                    PixelFormat.R32_Float,
                    false));

            Callback.OnVeldridInitialized(Widget, EventArgs.Empty);
        };
    }
}

`

ItEndsWithTens commented 5 years ago

Strange, it's working on my end. I see mention of "WinFormsControl", so I assume this is the WPF version, but whether I run it with Vulkan, D3D, or OpenGL, I can switch back and forth between those tabs just fine.

What kind of system are you running this on? I've got Windows 10, version 1903, and an AMD RX 460 with the Adrenalin 19.6.3 drivers.

philstopford commented 5 years ago

GeForce GTX 1060, latest available drivers (436.30). Win 10 Pro 1903

It's the Vulkan backend that seems to object.

ItEndsWithTens commented 5 years ago

Hmm. I do think it's odd that it's hitting that init function a second time, I guess the Control.Loaded event is being raised every time you switch to the tab on your system. Maybe a graphics driver difference.

What if you replace the InitializeOtherApi method with this:

public void InitializeOtherApi()
{
    Control.Loaded += OneTimeControlInit;
}

private void OneTimeControlInit(object sender, System.Windows.RoutedEventArgs e)
{
    // To embed Veldrid in an Eto control, all these platform-specific
    // versions of InitializeOtherApi use the technique outlined here:
    //
    //   https://github.com/mellinoe/veldrid/issues/155
    //
    var source = SwapchainSource.CreateWin32(
        WinFormsControl.Handle,
        Marshal.GetHINSTANCE(typeof(VeldridSurface).Module));
        Widget.Swapchain = Widget.GraphicsDevice.ResourceFactory.CreateSwapchain(
        new SwapchainDescription(
            source,
            (uint)RenderWidth,
            (uint)RenderHeight,
            PixelFormat.R32_Float,
            false));

    Control.Loaded -= OneTimeControlInit;

    Callback.OnVeldridInitialized(Widget, EventArgs.Empty);
}

That way the handler removes itself after the first initialization and won't be called again. It seems to keep working on my computer, at least.

philstopford commented 5 years ago

That seems to make things happier.