Gfx: OpenGL surface via surfman

Created on 28 Jan 2020  Â·  15Comments  Â·  Source: gfx-rs/gfx

Just spoke to @pcwalton about https://github.com/pcwalton/surfman, and I'm wondering if we can use this for implementing the true surfaces on GL context, that don't require GL device. Seems like a direction worth exploring.

The tricky bit is that presenting the shared DXGI surface in WGL seems impossible at the moment (link to an issue missing?). I would be comfortable restricting our GL backend to non-windows platforms, or just reporting that a surface can't be presented to on Windows. We have enough of alternatives there (DX11/DX12/Vulkan), so we should be safe. Most value of OpenGL comes to Linux/Android.

Related to #1304

OpenGL average ready for work feature high

Most helpful comment

As far as I understand it #3151 did a major step in the direction of actually using surfman to manage the surfaces and windowing, but it has a lot of places that might be restricted to single threaded and it is still doing a blit every presentation which may be able to be properly gotten rid of with surfman.

That is something that I think is maybe too far outside of my knowledge to attempt right now. Also, probably more importantly, with the integration with wgpu ( https://github.com/gfx-rs/wgpu/pull/502 ) there are some deficiencies in the gl backend functionally that still need to be addressed ( not that I can address those necessarily either ).

I was thinking of creating a new issue to track the failure points of the GL backend and maybe putting in a message linking to that issue whenever the GL backend panics so that we could start collecting those issues.

All 15 comments

I'm not totally sure where exactly this would fit in. Would you mind clarifying a bit?

Regarding OpenGL on Windows: Right now it should provide the same as Vulkan regarding swapchain/surface separation from devices as they are backed by different GL contexts (e.g in the quad example the wgl path: https://github.com/gfx-rs/gfx/blob/master/examples/quad/main.rs#L114)

I'm not totally sure either. The way I see it that we'd use surfman for creating the surface independently of gfx_backend_gl::Device. Then we'd glue it together with the device at create_swapchain and present on it. This should allow us to work with WSI with the same path we do on other backends.

FWIW I just tried the threads example on a wayland machine but replacing https://github.com/pcwalton/surfman/blob/master/surfman/examples/threads.rs#L98 with Connection::new().unwrap(), which causes the example to hang (without the change it works normally). This would simulate our use-case where the Instance creates at least one pure context.

The documentation seems to kinda imply that this might not work: https://github.com/pcwalton/surfman/blob/master/surfman/src/platform/unix/wayland/surface.rs#L32

Note that the master branch is surfman 0.1, which is only lightly maintained. The new work is surfman 0.2 in the "multi" branch, which is a major overhaul. Once @asajeffrey finishes upgrading Servo to surfman 0.2 (a large task that has taken several weeks due to all the platforms Servo runs on), we will merge surfman 0.2 into master.

@pcwalton does 0.2 changes anything with regards to this limitation?

Surfaces are specific to a given context and cannot be rendered to from any context other than
the one they were created with.

What we really need is to have the surface to be rendered by a different context.

Not on every platform, but on platforms where it's supported, sure.

It's been a few weeks since I experimented with this and my memory is a bit fuzzy, but as I recall the reason for the limitation is WGL. There really isn't a way to make an surface renderable by another context with the WGL API. In theory you can create a DXGI surface and use the NV_GL_DX_interop2 extension to render to it; in practice driver bugs prevent this from working properly. So essentially the reason for this limitation is driver bugs on Windows.

Wonderful, then we are almost there! Let's proceed with GL backend being gated off windows.

On Mar 8, 2020, at 03:06, Patrick Walton notifications@github.com wrote:


Not on every platform, but on platforms where it's supported, sure.

It's been a few weeks since I experimented with this and my memory is a bit fuzzy, but as I recall the reason for the limitation is WGL. There really isn't a way to make an surface renderable by another context with the WGL API. In theory you can create a DXGI surface and use the NV_GL_DX_interop2 extension to render to it; in practice driver bugs prevent this from working properly. So essentially the reason for this limitation is driver bugs on Windows.

—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or unsubscribe.

As far as I understand it #3151 did a major step in the direction of actually using surfman to manage the surfaces and windowing, but it has a lot of places that might be restricted to single threaded and it is still doing a blit every presentation which may be able to be properly gotten rid of with surfman.

That is something that I think is maybe too far outside of my knowledge to attempt right now. Also, probably more importantly, with the integration with wgpu ( https://github.com/gfx-rs/wgpu/pull/502 ) there are some deficiencies in the gl backend functionally that still need to be addressed ( not that I can address those necessarily either ).

I was thinking of creating a new issue to track the failure points of the GL backend and maybe putting in a message linking to that issue whenever the GL backend panics so that we could start collecting those issues.

This sounds like a good way to move forward: either with a meta-issue, or real smaller issues, it's all up to you.
The single-threaded restriction is deserving a seaprate issue, perhaps. I wonder if we can just have a mode, where we mutex lock every access to the device or a queue, so that it's Sync when seen from the outside.

I wonder if we can just have a mode, where we mutex lock every access to the device or a queue, so that it's Sync when seen from the outside.

That might actually be somewhat similar to what It's already doing, it's just that there are Starc's all over the place because of the lack of Send ( is that right? ) implementations and I'm not sure that none of those will panic if actually used in a multi-threaded scenario. I tried to put RwLocks wherever I needed multi-threaded access to anything, but while it works in the examples, I don't actually have verification that it worked like I was thinking from a multi-threaded standpoint. I'd probably need to look at it again, but you're right that should be a separate issue.

Nice! Is there an overview on how it works out so far on the different platforms?

Not yet. :)

So far the surfman backend is only meant for use on Android, Linux, and MacOS. I've only tested it on Linux with X11, though Wayland is also supported. @hecrj was unfortunately having some issues ( https://github.com/servo/surfman/issues/173 ) with surfman, but that appears to be a problem with surfman itself, and not the GL backend.

WGPU is going to be the best way to test the functionality of the GL backend and because there are already a collection of projects built on WGPU, it will give us a lot of opportunity to test it in different situations. Currently a good chunk of the wgpu examples are failing ( https://github.com/gfx-rs/wgpu/issues/450#issuecomment-612514358 ) with it, but the cube and triangle examples are working.

Also of note, on my machine, I did notice that when using surfman and running the gfx quad example, the screen would show black for just a second before appearing while the glutin version would be displaying the quad as soon as the window was on the screen. I'm not sure if that is a real concern or not, but I figured I'd mention it.

@zicklag now I don't understand how and why #3151 worked, given our recent discovery of the lack of sharing in https://github.com/pcwalton/surfman/issues/65 . Do you know?

I'm also no longer sure about the benefit surfman brings to the table, given the problems we encountered, and the fact it still requires a blit to the surface. We were doing the same thing with glutin, which were just missing the proper context sharing, which is already exposed there. So it would be much easier to get that going.

I suspect one difference is that Glutin is based on Winit, and that is precisely what we don't need in the backend. Is that it? (cc @msiglreith )

@zicklag now I don't understand how and why #3151 worked, given our recent discovery of the lack of sharing in pcwalton/surfman#65 . Do you know?

I'm not sure, but I suspect that the context that we crated for the surface that is bound to the window, ended up being the current context for the whole duration of the rendering pass ( if render pass is the right term ). So instead of rendering to a shared context, and doing a blit onto the window's context before presentation, we were just rendering directly to the window's context the whole time. Which would explain why it stopped working when we tried to make sure the context we wanted to be current was the current one on dereference.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

clevijoki picture clevijoki  Â·  3Comments

seivan picture seivan  Â·  4Comments

InMath picture InMath  Â·  5Comments

msiglreith picture msiglreith  Â·  3Comments

norru picture norru  Â·  4Comments