Closed Bug 1625070 Opened 5 years ago Closed 4 years ago

[X11][WebRender] Linux partial present

Categories

(Core :: Graphics: WebRender, enhancement, P5)

Desktop
Linux
enhancement

Tracking

()

RESOLVED FIXED
mozilla80
Tracking Status
firefox80 --- wontfix
firefox81 --- wontfix
firefox82 --- wontfix
firefox83 --- fixed

People

(Reporter: sotaro, Assigned: nical)

References

(Blocks 2 open bugs)

Details

Attachments

(3 files)

X11 version of Bug 1620076.

See Also: → 1620076

It seems that we could use glxCopySubBufferMESA() for it.

Blocks: wr-linux

FTR again, if someone with an better understanding of the code than me would give bug 1474281 a go, we could (hopefully quite easily) implement bug 788319 and therefore use EGL_KHR_swap_buffers_with_damage on X11, Wayland and Android.

Please wontfix GLX. EGL/X11 is required for bug 1580166 (see bug 1010527 comment 32 and bug 1619523). surfman also switched to EGL on X11.

Priority: -- → P5
Status: NEW → RESOLVED
Closed: 5 years ago
Resolution: --- → DUPLICATE
See Also: 1620076

Jan, can we reopen this and mark it as dependent on bug 1620076, bug 788319 and https://gitlab.freedesktop.org/mesa/mesa/-/issues/3030? bug 1620076 alone won't be enough for X11 while it is for Wayland.

Flags: needinfo?(jan)

Yes, thank you! :)

Status: RESOLVED → REOPENED
Depends on: 1620076, linux-egl
Flags: needinfo?(jan)
OS: Unspecified → Linux
Hardware: Unspecified → Desktop
Resolution: DUPLICATE → ---
Status: REOPENED → NEW

Nico, are you aware that stransky is actively working on bug 788319 (or bug 1640048, which already implements almost everything needed) as it's needed for bug 1619523? I don't think it makes sense to invest much time into the GLX backend - the EGL backend gives us partial damage in a proper manner for free (as it's shared with Wayland/Android).

Edit: most importantly bug 1580166 has already landed - it's necessary to get good WebGL performance without readbacks)
Edit2: that means with bug 1640048 applied you should already get partial damage support when using the nvidia proprietary driver. Mesa drivers are blocked by https://gitlab.freedesktop.org/mesa/mesa/-/issues/3030
edit3: also, glxCopySubBufferMESA is obviously not supported on the nvidia driver - and mesa drivers benefit the most from the switch to EGL because of the dmabuf work.

Flags: needinfo?(nical.bugzilla)
Depends on: 1648872, 1640048
No longer depends on: linux-egl

Nico, are you aware that stransky is actively working on bug 788319

I wasn't sure whether there was active work towards using EGL instead of GLX. My goal in this hacky portotype was to see if a simple change could yield some short term wins (but I am leaning towads "probably not") and help ship wr on linux+x11 quickly.

I'm definitely in favor of using EGL, but we'll probably want to get webrender enabled for some linux user before it happens.

--

I did a very quick and dirty integration of glxCopySubBuffer in https://phabricator.services.mozilla.com/D81868 to see how it works. The documentation is scarse:

 void glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable,
				    int x, int y, int width, int height );

    may be used to copy a rectangular region of the back color buffer to
    the front color buffer.  This can be used to quickly repaint 3D windows
    in response to expose events when the back color buffer cannot be
    damaged by other windows.

    <x> and <y> indicates the lower-left corner of the region to copy and
    <width> and <height> indicate the size in pixels.  Coordinate (0,0)
    corresponds to the lower-left pixel of the window, like glReadPixels.

    If dpy and drawable are the display and drawable for the calling
    thread's current context, glXCopySubBufferMESA performs an
    implicit glFlush before it returns.  Subsequent OpenGL commands
    may be issued immediately after calling glXCopySubBufferMESA, but
    are not executed until the copy is completed.

This seems to imply a model where we don't swap between buffers, we'd only copy from the back buffer to a persistent front buffer for the window (implying some sort of double buffering, wouldn't work with triple buffering or other types of swapchain)?
If we invalidate the whole window this would mean an extra copy entirely compared to swapbuffer. It's unclear whether we can we mix swap buffer and copysubbuffer depending on the amount of damage.
I am not 100% sure I understand the part about "when the back color buffer cannot be damaged by other windows". I'm assuming that we don't need to worry when the window has its own surface as opposed to rendering directly into the screen as was customary in the earlier days of x11.

Testing this out I get some glitches, for example after scrolling, in a way that looks like glxCopySubBuffer does pretty much what the documentation says without enforcing double buffering. To make it work I suppose we would need to present with double buffering.

An alternative is to use the buffer age extension but having frame building and the renderer on separate threads makes this a bit error prone and ugly.

It looks like EGL has a cleaner API for this, split in two independent pieces: buffer_age to avoid re-rendering content and EGL_KHR_swap_buffers_with_damage to tell the window manager which parts were invalidated and reduce compositor overhead.

Flags: needinfo?(nical.bugzilla)

bug 1640048 waits for a review over a month now.

Oh, you have edited your comment while I was typing. Sorry for writing the same.

(In reply to Nicolas Silva [:nical] from comment #9)

I'm definitely in favor of using EGL, but we'll probably want to get webrender enabled for some linux user before it happens.

VAAPI is a killer feature and the VAAPI/DMABUF/EGL/X11 WIP already works fine. 🙈 (bug 1580166 comment 7)
Users have been quite sad that it was Wayland-only so far.

Exciting! It's likely we'll ship the first wave of webrender on linux via x11 nonetheless because it has had more testing and we'd like to start doing that soon. We can forget about partial present through GLX and get it via egl when it's landed, one less thing to do.

(In reply to Nicolas Silva [:nical] from comment #9)

It looks like EGL has a cleaner API for this, split in two independent pieces: buffer_age to avoid re-rendering content and EGL_KHR_swap_buffers_with_damage to tell the window manager which parts were invalidated and reduce compositor overhead.

Indeed and that's how it was implemented for the EGL backend in bug 1620076 - so what we need here is really only:

  • switch to the EGL backend on X11 - stransky took that over and is working on it now
  • fix remaining issues with partial present and turn it on by default, tracked in bug 1648799 and bug 1640710 - that's were we could need some help by the gfx team / you :) It would also benefit Android and Win8 AFAIK.
Depends on: 1648799
Blocks: 1647073
Depends on: 1650583

(In reply to Nicolas Silva [:nical] from comment #9)

Testing this out I get some glitches, for example after scrolling, in a way that looks like glxCopySubBuffer does pretty much what the documentation says without enforcing double buffering. To make it work I suppose we would need to present with double buffering.

I believe there are two issues with your patch:

  1. mGL->SwapBuffers(); is always called, sometimes twice in a row;
  2. missing coordinate translation (see RenderCompositorEGL::EndFrame() for the example).

I've attached a fixed version. Could you take a look please?

Flags: needinfo?(nical.bugzilla)

Thanks Rinat, your version indeed works quite a bit better. I'll look into making sure it only runs where the extension is available, and landing it preffed off. After a bit of testing we'll see if we put it in the MVP since it's a low hanging fruit.

Flags: needinfo?(nical.bugzilla)

(In reply to Nicolas Silva [:nical] from comment #16)

<...> and landing it preffed off. After a bit of testing we'll see if we put it in the MVP since it's a low hanging fruit.

That's exactly what I wanted you to consider. Thanks!
As for the pref, there is probably no need for it: gfx::gfxVars::WebRenderMaxPartialPresentRects() can be used for that, just like it's done in RenderCompositorEGL.

I've also got some approximate power consumption estimation (PkgWatt metric from turbostat). With that patch it goes from ~2.3 W to ~1.8 W on a page with nothing but a 128x128 GIF animation, so it really gains something.

Assignee: nobody → nical.bugzilla
Attachment #9160676 - Attachment description: Bug 1625070 - Hack glxCopySubBuffer to see if it works. → Bug 1625070 - Use glxCopySubBufferMESA when available if partial present and WebRender are enabled on GLX.
Status: NEW → ASSIGNED

(In reply to Robert Mader [:rmader] from comment #8)

edit3: also, glxCopySubBufferMESA is obviously not supported on the nvidia driver - and mesa drivers benefit the most from the switch to EGL because of the dmabuf work.

While NVIDIA drivers have no string "GLX_MESA_copy_sub_buffer" inside them, their libGL.so.1.7.0 exports glXCopySubBufferMESA symbol.

Currently I have no access to a machine which has NVIDIA as a primary video adapter, so I'm not sure if it works. But it may work. After all, it's a 20-year old tech. Perhaps it was added at some point, but without mentioning it in the supported extensions list.

Thanks for fixing the patch!
Proprietary Nvidia should better not be part of the initial MVP.

  • On Gnome desktops it is still affected by broken rendering when resuming from standby.
  • On non-Gnome desktops, it additionally causes noticeable performance problems until users manually enable "Force Composition Pipeline" in Nvidia X Server settings. Even glxgears is affected by that.
  • Of course it would be nice if it supported this GLX extension.
  • Proprietary Nvidia supports EGL_EXT_buffer_age and EGL_KHR_swap_buffers_with_damage. bug 1650583 blocks us from using EGL there. Surfman had the same problem and there are two approaches: Either "Avoid calling eglMakeCurrent prior to creating a window surface" or "create a 1x1 pbuffer dummy surface and make current against that when you want to unlock your main surface".

(In reply to Rinat from comment #18)

While NVIDIA drivers have no string "GLX_MESA_copy_sub_buffer" inside them, their libGL.so.1.7.0 exports glXCopySubBufferMESA symbol.

Currently I have no access to a machine which has NVIDIA as a primary video adapter, so I'm not sure if it works. But it may work. After all, it's a 20-year old tech. Perhaps it was added at some point, but without mentioning it in the supported extensions list.

Oh, that's good to know, thanks. I still hope to get the EGL backend into shape soon, but given that EGL_KHR_swap_buffers_with_damage on X11 has not even landed in mesa it's probably a good idea to start the MVP with this.

Pushed by nsilva@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/74a508f9bac4 Use glxCopySubBufferMESA when available if partial present and WebRender are enabled on GLX. r=jgilbert

Currently I have no access to a machine which has NVIDIA as a primary video adapter, so I'm not sure if it works. But it may work.

The extension doesn't work on my nvidia desktop (proprietary drivers). Calling glXCopySubBufferMESA symbol does nothing as far as I can tell (if I skip checking that the extension is supported).

Oh, that's good to know, thanks. I still hope to get the EGL backend into shape soon,

EGL is still very much the way forward.

(In reply to Nicolas Silva [:nical] from comment #22)

The extension doesn't work on my nvidia desktop (proprietary drivers). Calling glXCopySubBufferMESA symbol does nothing as far as I can tell (if I skip checking that the extension is supported).

That explains why it wasn't mentioned in the list of supported extensions.

EGL is still very much the way forward.

By the way, are EGL-partial-present-related extensions working on NVIDIA's proprietary driver?

(In reply to Rinat from comment #24)

By the way, are EGL-partial-present-related extensions working on NVIDIA's proprietary driver?

Unfortunately we couldn't test that with FF so far because of bug 1650583 and bug 1648872 :(

Gnome XWayland, Debian Testing, Radeon RX480
With steps from bug 1648872 comment 0 I can confirm that GLX partial present works with build from comment 21:
mozregression --repo autoland --launch 74a508f9bac4 --pref gfx.webrender.all:true gfx.webrender.max-partial-present-rects:1

(In reply to Robert Mader [:rmader] from comment #25)

Unfortunately we couldn't test that with FF so far because of bug 1650583 and bug 1648872 :(

The only thing that really blocks from testing it, is the physical absence of a machine with NVIDIA adapter. :)

Simple test would consist of creating GL context, glClear() with all-red color, buffer swap, then glClear() with all-green color, partial present of some rectangle. If in result one can see a green box on a red background, then partial present works.

(In reply to Jan Andre Ikenmeyer [:darkspirit] from comment #26)

Gnome XWayland, Debian Testing, Radeon RX480
With steps from bug 1648872 comment 0 I can confirm that GLX partial present works with build from comment 21:
mozregression --repo autoland --launch 74a508f9bac4 --pref gfx.webrender.all:true gfx.webrender.max-partial-present-rects:1

This is good to hear as it suggest X11 is not affected by bug 1648872 and maybe points into a direction I speculated about in bug 1617002 comment 1 - will check.

(In reply to Rinat from comment #27)

(In reply to Robert Mader [:rmader] from comment #25)

Unfortunately we couldn't test that with FF so far because of bug 1650583 and bug 1648872 :(

The only thing that really blocks from testing it, is the physical absence of a machine with NVIDIA adapter. :)

Same here :)

Simple test would consist of creating GL context, glClear() with all-red color, buffer swap, then glClear() with all-green color, partial present of some rectangle. If in result one can see a green box on a red background, then partial present works.

Indeed, although I'd recommed to also validate with some external tool like e.g. Mutter as described in bug 1648872 comment 0 - so we can be sure that WMs / compostitors really get the right info.

Flags: needinfo?(nical.bugzilla)

(In reply to Rinat from comment #27)

The only thing that really blocks from testing it, is the physical absence of a machine with NVIDIA adapter. :)

Err only understood you now - right :)
Don't have one here, will you give it a try?

Yes, SwapBuffersWithDamageKHR is supported by proprietary Nvidia (GTX1060) on X11 and it works:

https://github.com/rust-windowing/glutin/blob/master/glutin_examples/examples/damage.rs
As expected, only the bottom-left corner gets invalidated if nothing else has to be invalidated.

git clone https://github.com/rust-windowing/glutin
cd glutin
nano glutin_examples/examples/damage.rs

change
ContextBuilder::new().build_windowed(wb, &el).unwrap();
to
ContextBuilder::new().with_gl(glutin::GlRequest::Specific(glutin::Api::OpenGlEs, (3, 1))).build_windowed(wb, &el).unwrap();
to use GLES/EGL

cargo run --example damage

Pushed by nsilva@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/39c56dc3d469 Use glxCopySubBufferMESA when available if partial present and WebRender are enabled on GLX. r=jgilbert

(In reply to Robert Mader [:rmader] from comment #29)

(In reply to Rinat from comment #27)

The only thing that really blocks from testing it, is the physical absence of a machine with NVIDIA adapter. :)

Err only understood you now - right :)
Don't have one here, will you give it a try?

I don't have any available unfortunately, so couldn't check myself.
There is an eGPU enclosure, but I failed to pass-through GPU from it to a VM. Looks like NVIDIA driver actively refuses to support VMs.

Status: ASSIGNED → RESOLVED
Closed: 5 years ago4 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla80

(In reply to Rinat from comment #27)

Simple test would consist of creating GL context, glClear() with all-red color, buffer swap, then glClear() with all-green color, partial present of some rectangle. If in result one can see a green box on a red background, then partial present works.

Temporary got a cloud VM with NVIDIA GPU attached, and tried exactly that. Can confirm that glXCopySubBufferMESA() has no visible effects when running on NVIDIA proprietary driver.

I just got a ping from Michel Dänzer (xorg/mesa dev) that glXCopySubBufferMESA() is somewhat buggy in his experience. So it might turn out we need to wait for EGL_KHR_swap_buffers_with_damage on X11 support and the EGL switch to really turn this on :/ - but lets wait a bit for some testing.

Edit: he just commented, see bug 1648799 comment 5

This landed preffed off so the bug isn't fixed quite yet.

I just got a ping from Michel Dänzer (xorg/mesa dev) that glXCopySubBufferMESA() is somewhat buggy in his experience.

Ok thanks, that's good to know. well let's keep it preffed off an reevaluate if we find that performance/power usage is unacceptable.

Status: RESOLVED → REOPENED
Resolution: FIXED → ---
See Also: → 1617002
No longer blocks: wr-linux-mvp
Depends on: 1656472
Depends on: 1656533

EGL_KHR_swap_buffers_with_damage support for X11 has now been merged to upstream Mesa (so it'll be in mesa 20.3). Backport to mesa 20.2 branch is still pending.

No longer depends on: 1650583

egl/x11 support for EGL_KHR_swap_buffers_with_damage has now been merged to mesa 20.2 branch, and is available in mesa 20.2.0-rc4 (and later).

https://lists.freedesktop.org/archives/mesa-dev/2020-September/224608.html

Blocks: 1648799
No longer depends on: 1648799
No longer depends on: wr-non-os-compositor

mesa 20.2.0 has been released recently, and it includes egl/x11 support for "EGL_KHR_swap_buffers_with_damage".

With bug 1656533 fixed, I think this can also be declared fixed.

On to bug 1648799!

Status: REOPENED → RESOLVED
Closed: 4 years ago4 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: