Skip to content

feat: Enable GPU Canvas for Rive dashboards on Android - #267

Merged
wpmed92 merged 2 commits into
softwiredtech:mainfrom
Prag-designs:enable-gpu-canvas
Oct 26, 2026
Merged

wpmed92 merged 2 commits into
softwiredtech:mainfrom
Prag-designs:enable-gpu-canvas

Conversation

@Prag-designs

Copy link
Copy Markdown
Contributor

Summary

  • Create the Android Rive worker with rememberDeferredRiveWorker(), the GPU Canvas capable worker, so dashboards that draw with GPU Canvas (a script-drawn canvas finished by a WGSL shader) render that layer instead of only showing their native fallback.
  • Bump rive-android from 11.14.1 to 11.14.3. 11.14.2 fixes GPU Canvas content rendering black on Android (rive-android#474).
  • Opt in to @ExperimentalDeferredRendering, which Rive requires for this entry point.

Why

Rive files that use GPU Canvas need a deferred worker to draw. With the plain worker they run, but the GPU layer does not render and only the native copy of the dashboard shows. This is the one switch dashboard authors cannot flip from inside the .riv.

Notes for review

  • rememberDeferredRiveWorker() has no OrNull variant. If the worker cannot be created it throws RiveInitializationException instead of calling onError. Compose does not allow try/catch around composables, so I did not wrap it. Happy to change this if you prefer another fallback.
  • Rive says the deferred renderer does not improve rendering performance yet. Dashboards that do not use GPU Canvas should look the same, but I have not compared frame times.
  • iOS is not changed. The app uses the older RiveViewModel API. GPU Canvas on iOS is Worker(enableGPUCanvas: true) in rive-ios's newer concurrency API, which is a bigger port. Happy to do that as a separate PR.

Validation

  • Not built locally (no Java or Android SDK on my machine). Relying on the Android build check on this PR.
  • Device testing is pending.

Use a deferred Rive worker so dashboards that draw with GPU Canvas (WGSL shaders over a script-drawn canvas) render instead of falling back to their native copy. Bump rive-android 11.14.1 to 11.14.3, which includes the fix for GPU Canvas rendering black on Android (11.14.2).
@Prag-designs

Copy link
Copy Markdown
Contributor Author

Device test on a OnePlus 12R (Android). I built this branch locally with JDK 17 and Android SDK 36 (assembleDebug succeeds) and installed it next to the Play Store app under a different application id.

What I did: loaded a contest dashboard that uses GPU Canvas (a script-drawn canvas finished by a WGSL shader) through Settings > Developer > Load Rive File, with the Demo data source, then tapped Drive.

What I saw:

  • The GPU layer renders: shader-poured liquid fills with bubbles, bloom, and the glowing speed limit sign. When I tried the same file earlier today in the Play Store build (plain worker), it only showed the flat native fallback.
  • It animates live. The two frames below are about 6 seconds apart (78 to 53 km/h, and the liquid has moved).
  • No crash in logcat and the app stayed alive.

Frame 1

Frame 2

Not tested yet: iOS (unchanged in this PR), a real car connection, other dashboards for regressions, and frame times.

@wpmed92

wpmed92 commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Thanks @Prag-designs this is cool! My only concern is the potential for crash. Can we make it so that the new Rive context only activates if we toggle it in developer settings?
Or think of any other clean way to do this, but the idea is to only use this new deferred creation if the Rive app actually needs it.
Maybe the dash app manifest would be the right place to declare shader usage then check that and go the deffered route, but in the “normal” case just do it the old way.

The deferred Rive worker is now behind a Developer settings switch, "GPU Canvas for Rive (experimental)", off by default. With the switch off, RiveDashView uses the standard worker exactly as before. With it on, Rive dashboards render on the deferred worker so GPU Canvas (WGSL) content shows. The setting is read when the dashboard opens.
@Prag-designs

Copy link
Copy Markdown
Contributor Author

Thanks @wpmed92, done in 28576cd. The deferred worker is now opt-in: Settings > Developer has a new switch, "GPU Canvas for Rive (experimental)", off by default.

  • Off (default): RiveDashView creates the worker exactly as before (rememberRiveWorkerOrNull, same error handling), so the normal path is unchanged.
  • On: Rive dashboards use rememberDeferredRiveWorker(), which GPU Canvas content needs. The setting is read when the dashboard opens.

I went with the developer switch rather than a manifest flag to keep the change small and easy to remove. If you'd prefer the manifest route later (a dash app declares that it uses GPU Canvas and the app picks the worker from that), I'm happy to do a follow-up.

Tested on a OnePlus 12R (Android 16) with a debug build of this branch installed next to the Play Store app, Demo data source:

  • Switch off: a GPU Canvas dashboard shows its native fallback and runs normally. No crash.
  • Switch on: the same dashboard renders its WGSL layer live. No crash.
  • assembleDebug and testDebugUnitTest pass locally.

@wpmed92
wpmed92 merged commit 657dcee into softwiredtech:main Oct 26, 2026
2 checks passed
@wpmed92

wpmed92 commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

Thanks @Prag-designs great work!

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.

2 participants