Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🏎 Background Thread Skia Rendering #254

Merged
merged 16 commits into from
Mar 16, 2022
Merged

🏎 Background Thread Skia Rendering #254

merged 16 commits into from
Mar 16, 2022

Conversation

chrfalch
Copy link
Contributor

This PR implements support for rendering on a separate background thread. The new rendering pipeline is as the following:

  • Each Skia View is notified on vsync on the main thread
  • On each vsync update we check if there are any pending repaint requests for a given view (a Value was changed, a command was sent to repaint, mouse events etc.)
  • If there is a repaint request waiting, we’ll schedule a call to the Javascript draw method for that specific view on the JS thread.
  • The JS thread calls repaint, and instead of repainting to the underlying hardware it repaints on a “virtual” canvas using a Skia class called SkPicture - which can record drawing commands and replay them on a another surface / canvas.
  • A message is then dispatched to the render thread (which is a separate thread only doing Skia rendering) - with the SkPicture created on the JS thread
  • The render thread will render the SkPicture on the GPU surface / canvas in the background.

In addition this PR also includes a few optimisations found when profiling rendering:

  • The JsiHostObject class now contains optimisations and explicit declarations to make sure property/function lookups are as fast as possible.

chrfalch added 10 commits March 8, 2022 16:22
The rendering pipeline is now as follows:

- On the main thread the app is notified that the screen will refresh
- If any pending redraw requests exists, a draw operation is sent to the JS thread and executed
- The draw request performs the drawing operations that are defined in Javascript code. These operations are recorded using the SkPictureRecorder class
- The resulting SkPicture is passed to the render thread (separate single responsibility thread)
- The GPU backends on Android/iOS will play back the drawing commands in the SkPicture using a canvas connected to the GPU surface in either Metal or OpenGL.
Can be used to optimize the reconciler to be as fast as possible compared to pure JS rendering using a SkiaView.

Not sure if this screen will be kept - but it is super convinient for testing. In pure JS / SkiaView mode it renders over 2000 colored rects in 6ms spent in the JS thread and 2ms spent in the GPU/render thread.
To avoid using queues on iOS (they are a bit hard to understand, especially which / what threads they're using etc)
Now we're searching for property get first - since it is most often called.

Also added some typing and made sure that we don't copy the prop/func maps.
Fixes memory growth on iOS Simulator since all Metal resources are released after use.
@chrfalch chrfalch changed the title Feature/render thread 🚤 Feature/render thread Mar 14, 2022
@chrfalch chrfalch changed the title 🚤 Feature/render thread 🏎 Feature/render thread Mar 14, 2022
@chrfalch chrfalch changed the title 🏎 Feature/render thread 🏎 Background Thread Skia Rendering Mar 14, 2022
wcandillon
wcandillon previously approved these changes Mar 15, 2022
Copy link
Contributor

@wcandillon wcandillon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great. I'm pretty excited about this new feature. Pretty straightforward.

My only question is: could/should the SkPicture be available to be used in makeImageSnapshot if needed?

@chrfalch
Copy link
Contributor Author

Looks great. I'm pretty excited about this new feature. Pretty straightforward.

Thanks :)

My only question is: could/should the SkPicture be available to be used in makeImageSnapshot if needed?

I don't think it is necessary, since when making snapshots we're able to draw directly onto a raster surface (bitmap data), so there is no need to take the route through SkPicture I think. If we find issues with the DisplacementMap that can be solved by using a more centralised route I'm of course all in :)

@wcandillon wcandillon dismissed their stale review March 15, 2022 14:54

I may have detected a regression. Investigating now.

@wcandillon wcandillon self-requested a review March 15, 2022 14:59
@wcandillon
Copy link
Contributor

Not a big deal but sometimes on start this is the debug state.
Untitled

@chrfalch
Copy link
Contributor Author

Not a big deal but sometimes on start this is the debug state.
Untitled

Fixed :) :)

@chrfalch chrfalch merged commit c29738e into main Mar 16, 2022
@chrfalch chrfalch deleted the feature/render-thread branch March 16, 2022 14:01
@vladimirevstratov
Copy link

Nice, will test it now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants