Open Bug 1903611 Opened 11 months ago Updated 6 months ago

Firefox draws inefficently on large canvas

Categories

(Core :: Graphics: Canvas2D, defect, P3)

Firefox 127
defect

Tracking

()

People

(Reporter: samuel, Assigned: lsalzman)

Details

Attachments

(9 files)

Attached file test.html

Steps to reproduce:

Use a large canvas, and continuously make small changes to a small part of it. Or open test.html in Firefox on Windows.

Actual results:

The rotation of the triangle is laggy, and the CPU and GPU usage is very high.

If decreasing the size of the canvas in test.html to 500x500, things are a lot smoother.

Expected results:

The rotation should be smooth, and the resource usage shouldn't be high. The size of the canvas shouldn't matter this much.

Resource usage in Windows when using test.html (large canvas)

Resource usage in Windows when using test.html, but with a 500x500 canvas instead.

Attached image chrome_large_canvas.png

Resource usage when using Chrome instead, test.html (large canvas)

Attached image chrome_small_canvas.png

Resource usage when using Chrome, test.html, but with a 500x500 canvas instead

As seen in the attached screenshots, In Google Chrome, the difference in resource usage differs very little when using a 4k canvas vs using a 500x500 canvas. The visible rotation smoothness is also the same in Chrome, no matter if the canvas is large or small.

The Bugbug bot thinks this bug should belong to the 'Core::Graphics' component, and is moving the bug to that component. Please correct in case you think the bot is wrong.

Component: Untriaged → Graphics
Product: Firefox → Core

Hi Samuel,
Can you type "about:support" in the address bar if your Firefox browser, and copy-paste its contents here.

Flags: needinfo?(samuel)

Samuel, can you also capture a performance profile following the steps here (use the "Graphics" preset in the profiler UI) : https://profiler.firefox.com/docs/#/./guide-getting-started

Attached file about:support

The about:support info, and the performance profile is available above. I didn't check any of the "Include hidden..." boxes when uploading the performance profile.

Flags: needinfo?(samuel)

This shows a lot of time spent in the Renderer Thread.

CC :nical and :gw.

Status: UNCONFIRMED → NEW
Ever confirmed: true

I'm not sure why CompositorEndFrame is taking that long, I assume it's waiting for D2D to finish rasterizing, but why would D2D run that slowly?

Blocks: gfx-triage
Severity: -- → S3

My guess is that the canvas being this large causes issues on some models of Intel iGPU. I can repro this on an Intel 11900H (Tiger Lake) laptop, which shows the same issue where Firefox is janky and Chrome is smooth - unless of course I have both showing this, then Chrome is a bit janky as well, which would be consistent with the iGPU being overworked.

It's not clear to me if this size of canvas exceeds a hardware limit (which would seem peculiar to me, but I don't know the internals of Direct2D).

Per discussion in triage, an optimization that could be implemented for simple canvases like this is calculating an invalidation rect rather than redrawing the entire bitmap every frame, so it would be drawing way less pixels, it's possible that Chrome is already doing so, if so adding another such triangle in the bottom right corner may cause slowness in Chrome on the same GPU.

Component: Graphics → Graphics: Canvas2D
Flags: needinfo?(samuel)

Lee, do we have ideas on how to make this better? I think Intel is merely the most affected platform.

Flags: needinfo?(lsalzman)
Flags: needinfo?(lsalzman)
Flags: needinfo?(samuel)
Priority: -- → P3

It is pretty clear that Firefox is simply waiting on D2D here, we may be doing an unnecessary copy, we may be rendering more pixels than necessary (potential optimization of the invalidation rect).

One follow-up we can do is toggle gfx.canvas.accelerated and see if that helps as it may tease apart the question of memory bandwidth vs unnecessary copies and such.

Sotaro, it seems like we just may be stalling on composition here somehow, at least based on the profile the user submitted. Any ideas what the problem might be?

Flags: needinfo?(sotaro.ikeda.g)

With Intel GPU Win PC and the STR of comment 0, when perf gfx.webrender.debug.dcomp-redraw-regions = true, entire Firefox window showed redraw. It did not happen with NVIDIA GPU Win PC and AMD GPU Win PC. From it, Intel GPU seems to use more GPU power to redraw.

At first, I wondered if WEBRENDER_SCISSORED_CACHE_CLEARS might be related, since it is blocked with Intel GPU. But pref gfx.webrender.scissored-cache-clears.force-enabled = true did not affect to the entire window redraw.
https://searchfox.org/mozilla-central/rev/1d4c27f9f166ce6e967fb0e8c8d6e0795dbbd12e/widget/windows/GfxInfo.cpp#1884

Somehow, the entire window's redraw did not happen with WebGL Aquarium with Intel GPU Win PC.

:gw, do you have any ideas why the entire window redraw of comment 19 happens with Intel GPU Win PC and with the STR of comment 0?

Flags: needinfo?(gwatson)

The patch skips DrawTargetD2D1::CopySurface() and WebRender's canvas rendering by changing CanvasTranslator::PushRemoteTexture().

Assignee: nobody → sotaro.ikeda.g

With Attachment 9420934 [details] [diff], GPU usage during the STR of comment 0 was reduced significantly with Win11 PC with Intel GPU. From it, the followings consumes a lot of GPU power.

[2] might be related to comment 19 and comment 20.

Flags: needinfo?(sotaro.ikeda.g)
Assignee: sotaro.ikeda.g → nobody

No, I can't think why that would differ between GPU vendors, unless one is running without DC enabled and using partial present, which I assume isn't the case here?

Flags: needinfo?(gwatson)

All tests in comment 19 used with DC native compositor.

Sorry, my check in comment 19 was not enough. The following only happened with one Win11 laptop with Intel Gen12 GPU.

Somehow, the entire window's redraw did not happen with WebGL Aquarium with Intel GPU Win PC.

With another laptops with intel GPUs, whole window redraw happened both with the STR of comment 0 and with WebGL Aquarium .

And even with NVIDIA GPUs Win laptop that uses intel display adapter, the whole window flickering happened with both use cases. then I am going to think that the whole window redraw of comment 19 might be related to DC Surfaces usage with intel display adapter.

When I set pref gfx.webrender.compositor = false, GPU usage was reduced significantly on Win PCs with Intel GPUs. Intel display adapter might not be efficient with multiple DC Surfaces.

Lee, what can we do to move this forward?

Flags: needinfo?(lsalzman)

(In reply to Bob Hood [:bhood] from comment #26)

Lee, what can we do to move this forward?

This might be helped by bug 1910138 which will use a different compositing path via WebGL. Sotaro seems to have identified that the bottleneck is in the remote texture compositing path, which would no longer be used once we get bug 1910138 going again.

Flags: needinfo?(lsalzman)
No longer blocks: gfx-triage
Assignee: nobody → lsalzman

We suspect this bug is vague, but there are two paths of improvement here:

  1. Switching to DTWebgl by disabling d2d seems to improve preformance in this case, possibly due to sync/completion issues in our d2d backend/compositing.
  2. Adding damage-rect partial-present support, when we can tell that only a small portion of a canvas has been drawn to. I think this is possible for (simple cases in?) canvas2d, but a less exact form is possible for webgl as well.

This bug sounds like it will be satisfied with just #1. Eventually we will likely want #2, and it's probably possible to make a decent testcase for this already, but we may want to do that in a different bug.

Assigned, P3, the strategies in comment 28 lay out a path forward. Taking this out of triage.

No longer blocks: gfx-triage
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: