picoe / Eto.Veldrid

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

Gtk: GLArea tweaks #23

Closed cwensley closed 5 months ago

cwensley commented 3 years ago

Attempt to fix flicker issues on Gtk/Linux by initializing Veldrid during the Realize event.

Hopefully fixes #21

cwensley commented 3 years ago

@philstopford please give this a test before I merge it in.

philstopford commented 3 years ago

@cwensley : just wondered if you'd had time to revisit this :)

cwensley commented 3 years ago

@philstopford Perhaps this will work for you.. let me know!

philstopford commented 3 years ago

@cwensley : sorry, took a while to get this building on Linux. Sadly, it seems to fail with the following on my nVidia hardware :

(TestEtoVeldrid.Gtk:250387): Gdk-ERROR **: 19:04:31.811: The program 'TestEtoVeldrid.Gtk' received an X Window System error. This probably reflects a bug in the program. The error was 'GLXBadContextTag'. (Details: serial 417 error_code 162 request_code 151 (GLX) minor_code 26) (Note to programmers: normally, X errors are reported asynchronously; that is, you will receive the error a while after causing it. To debug your program, run it with the GDK_SYNCHRONIZE environment variable to change this behavior. You can then get a meaningful backtrace from your debugger if you break on the gdk_x_error() function.)

philstopford commented 3 years ago

Just following up on this.

philstopford commented 3 years ago

Just to add some information here that may relate to the pull request for OpenTK and its interaction with Vulkan, with help from kind folks in the Veldrid discord channel, and renderdoc, it became apparent that there is a fight between two windows, it seems. One is OpenGL and one is Vulkan.

https://user-images.githubusercontent.com/1983851/114491869-6341ba00-9be5-11eb-9799-b9f8b95fe89c.mp4

ItEndsWithTens commented 3 years ago

I'm getting back into the swing of things, and in reviewing this Vulkan flickering problem, I realize my brilliant last minute ideas were a sizable part of the problem here.

Back when I was preparing to hand off ownership of the Eto.Veldrid project, Curtis suggested not worrying about the Vulkan backend (in response I believe to some sort of driver problems?) and just focusing on Direct3D for Windows, Metal for macOS, and OpenGL for Linux. He also pointed out it would be easy enough to avoid the complexity of OpenGL context creation by simply using Gtk's built-in GLArea as the Linux platform handler.

I set up the backend selection code as suggested, but only when it came to the defaults, because I had the bright idea that Vulkan could still be offered as an option at the discretion of users. It was easy enough to implement, so I figured there would be no harm. Unfortunately GLArea, by its nature, always wants to create an OpenGL context, so when a user tries to force Vulkan they end up with two graphics backends fighting each other.

My most sheepish apologies for making Vulkan seem like a valid choice in Linux without actually properly accommodating that code path. I'm having marginal success poking around this PR by making GtkVeldridSurfaceHandler a Gtk.Widget control and instead of GLArea creating a DrawingArea, but it's still a bit janky, and I'm not sure it'll be doable to conditionally create the appropriate platform control based on what backend is selected.

I'll keep at it, but unless there's a readily apparent and reasonable way to only use GLArea when OpenGL is the backend, I worry it might be necessary to drop support for Vulkan in Linux for the time being.

cwensley commented 3 years ago

Ok I've added some stuff to only create the GLArea when using the OpenGL backend on linux. I have no idea if it works with Vulkan (I can't test on my setup), but maybe it will 🤷🏻‍♂️.

philstopford commented 3 years ago

Taking the updated code for a spin, I get an immediate GLX bad context error. Forcing the backend to Vulkan by setting backend in the constructor, I get this : test_gtk

I haven't figured out why the debugger never traps on the GLX error. The debug build just quits out no matter what I try.

ItEndsWithTens commented 3 years ago

Testing on the Samsung Chromebook 3 I mentioned a couple weeks ago on Gitter (inside is an Atom x5-E8000 with some variant of Intel's integrated graphics, and by running Ubuntu 16.04 through crouton I'm able to test Vulkan), I have no problems with the OpenGL backend. Draws as expected, resizes properly, responds to mouse and keyboard events, everything seems okay.

Forcing the Vulkan backend gives me the same black control Phil saw in his previous post. Trying to set some breakpoints suggests that the Vulkan path in this latest commit doesn't hook up the Callback.OnDraw method to anything. I added it myself by connecting it in Control_InitializeGraphicsBackend to both the Control.Drawn and Control.SizeAllocated events, and also added calls to it in both of the handler's overloads of Invalidate. This gives some result, and I can see the pink background and multicolored square, but the square just jitters in place. It does rotate correctly during a resize, albeit with intermittent black flashes, but when sitting still it just jitters back and forth even when pausing its rotation. I suspect I'm just not adding OnDraw calls in all the right places.

My other laptop, with Nvidia hardware, only has a Quadro 1000M (running Linux Mint 20, with the 390 Nvidia drivers), so no Vulkan support, but the OpenGL backend shows a black screen there. I think that's just part of the existing Nvidia OpenGL/GLArea issues we know about from this project and Eto.OpenTK, so probably not cause for alarm.

At no point did I get any "bad context" crashes, though. I've had the same frustration trying to get a debugger to break on those when they happen, but in this case I'm not getting any such error to begin with.

cwensley commented 3 years ago

@ItEndsWithTens thanks for looking into that, yes I figured I missed that part, wiring up the Drawn/SizeAllocated events. As for it not working unless resizing it's probably because the handler overrides the Invalidate() methods, and should call the base class if glArea is null.

ItEndsWithTens commented 3 years ago

Hmm...not seeing an improvement, I'm sorry to say. I tried this:

void Eto.Forms.Control.IHandler.Invalidate(Rectangle rect, bool invalidateChildren)
{
    if (glArea == null)
    {
        base.Invalidate(rect, invalidateChildren);
    }
    else
    {
        skipDraw = false;
        glArea.QueueRender();
    }
}

void Eto.Forms.Control.IHandler.Invalidate(bool invalidateChildren)
{
    if (glArea == null)
    {
        base.Invalidate(invalidateChildren);
    }
    else
    {
        skipDraw = false;
        glArea.QueueRender();
    }
}

The jittering is still there when idle, and resizing still makes things work (excepting the periodic black flashes when doing so). Is this what you meant as far as calling the base class, or do I need to to something else?

philstopford commented 3 years ago

@cwensley : Just wondering whether you'd had time to see if there's a way to resolve the remaining niggles. Not sure whether remote access to a host with an nVidia card installed would be helpful.

philstopford commented 3 years ago

@NogginBops : I was wondering whether you might have some insights on this, where OpenTK results in a GLX error on nVidia hardware.

NogginBops commented 3 years ago

@philstopford sorry for not responding earlier to your other reply, been busy. I'm having a hard time understanding how this PR relates to OpenTK as I don't see any code directly related to OpenTK in the PR. I searched this repo for "OpenTK" and only found results in issues and PRs, no code. So I'm not sure where I'm supposed to look tbh.

ItEndsWithTens commented 3 years ago

@NogginBops @philstopford Sorry everybody! I should have chimed in earlier when I got the notification about that other issue in the Eto.OpenTK repo: OpenTK is no longer used in Eto.Veldrid, and should have no connection to the trouble Phil's seeing with the GLX error.

When I first started this Veldrid control for Eto I needed to provide a GL context to the Veldrid library but wasn't sure how to do that, so I implemented it with OpenTK since that's what I knew. I was subsequently made aware of Gtk's built-in GLArea control, allowing for simpler code in our use case, and once I figured out how to use it I removed OpenTK from the codebase.

Unfortunately I must admit I have no insight into the actual problem at hand.

NogginBops commented 3 years ago

Using Gtk's GLArea does indeed sound like the better solution if you where already using Gtk.

I don't have any insight into the GLX error either unfortunately.

philstopford commented 2 years ago

Runs fine on AMD hardware as well, so am discussing this with nVidia support to see if there's a driver bug.