Open Bug 883517 Opened 11 years ago Updated 2 years ago

[Skia] SkCanvas::flush takes up a lot of time in the refresh driver

Categories

(Core :: Graphics, defect)

x86
macOS
defect

Tracking

()

People

(Reporter: gal, Unassigned)

Details

When the refresh driver creates the layer for a 2d canvas it does Flush() on the skia draw target. Skia queues canvas requests since submitting them to GL is more efficient on bulk. As a result this Flush takes a lot of time in the profile.

I did some experiments with this. With SkDeferredCanvas I can successfully push almost all the computation time into the Flush in the refresh driver. This is good because the actual canvas operations (JS) run faster. Overall frame rate is lower because we submit to the GL hardware later and we are blocking on the GPU being done with the operations.

If I put a flush into AutoPaint in DrawTargetSkia I can successfully eliminate the refresh driver from the profile, but overall frame rate is lower because we do more GL setup stuff in Skia (instead of submitting in bulk).

I think what we want is basically using SkGPipe to send the canvas operations to a different thread like SkDeferredCanvas, however, we want to submit them earlier (so SkGPipe into a regular canvas). In addition we want to do a Flush on a regular basis so ideally by the time the refresh driver comes the GPU is already done. The Flush() in the refresh driver just waits for this new thread to be done processing the entire queue.
A simpler solution is to use SkDeferredCanvas and fire of a runnable to the main thread that holds a weak reference to the CanvasRenderingContext2D and will flush the drawable earlier and from the event loop. Only submit one of these until Flush() was called. EnsureTarget() is probably a good place to submit the runnable, checking that it wasn't submitted before. Peter, want to give this a try? This should improve performance by submitting GPU commands earlier, before we need them (as we do the buffer swap).
Isn't this fairly similar to bug 857895, apart from using SkDeferredCanvas instead of SkPicture?

The idea there was to dispatch commands to the rendering thread every N canvas calls, as well as once the current JS code block finished (RunInStableState).

We then wait for the rendering thread to complete the command queue inside the CanvasLayer's PreTransactionCallback. This is marginally later than the BuildLayer call, depending on how much ThebesLayer painting we do.
If you have a rendering thread, how do you make sure we create the context on that thread? I think our GLContext code doesn't like using contexts on multiple threads.
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.