Skip to content

feat: expose GPU Canvas (3D) on iOS and Android - #381

Merged
mfazekas merged 9 commits into
mainfrom
claude/gpu-canvas-beta-android-ios-7ccb40
Oct 5, 2026
Merged

mfazekas merged 9 commits into
mainfrom
claude/gpu-canvas-beta-android-ios-7ccb40

Conversation

@mfazekas

@mfazekas mfazekas commented Sep 10, 2026 •

Copy link
Copy Markdown
Collaborator

Exposes GPU Canvas (required for 3D content) on the new runtime as RiveRuntime.setGPUCanvasEnabled(true) / isGPUCanvasEnabled(). It needs rive-ios 6.25.0+ and rive-android 11.12.0+, which main already pins (6.28.0 / 11.12.1). The setting is process-wide and must be set before the first Rive file loads; a later call logs a warning and is ignored. No-op on the legacy runtime.

iOS uses Worker(configuration: .init(enableGPUCanvas:)). Android uses rive-android's experimental deferred renderer, whose CommandQueue.createDeferred is Kotlin-internal, so DeferredRiveWorker.kt resolves it by reflection; if the rive-android in use has no such entry point the worker is created without GPU Canvas and a warning is logged.

While testing 11.12.0 this found rive-app/rive-android#470 (debug-build abort when reading a nonexistent boolean property, fixed in 11.12.1); the harness test now covers nested misses too.

Example page demos/GPUCanvasDemo.tsx renders ore.riv (rive-android's sample, MIT). Verified on both platforms: harness green (iOS 29/29, Android 29/29), the 3D scene renders with the flag and is black without it. Docs in docs/runtime-backends.md.

@mfazekas
mfazekas force-pushed the claude/gpu-canvas-beta-android-ios-7ccb40 branch from d935add to 808c6a6 Compare September 21, 2026 18:51
@mfazekas
mfazekas added this pull request to stack #384 September 22, 2026 08:23
@mfazekas
mfazekas removed this pull request from stack #384 September 22, 2026 16:01
HayesGordon
HayesGordon previously approved these changes Sep 23, 2026

@HayesGordon HayesGordon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM!

@mfazekas
mfazekas force-pushed the claude/gpu-canvas-beta-android-ios-7ccb40 branch 2 times, most recently from 02a5b8f to 137750a Compare September 24, 2026 02:32
@mfazekas
mfazekas force-pushed the claude/gpu-canvas-beta-android-ios-7ccb40 branch from 137750a to c40d615 Compare September 28, 2026 04:31
mfazekas added a commit that referenced this pull request Sep 29, 2026
Bumps the pinned native runtimes to the newest releases we can consume:
rive-android 11.9.1 → 11.12.1 and rive-ios 6.23.1 → 6.26.0. rive-ios
6.27.0 is tagged on GitHub but was never pushed to CocoaPods trunk,
which tops out at 6.26.0, so the podspec can't use it yet.

11.12.1 is also the first safe rive-android pin after 11.9.1:
11.10.0–11.12.0 abort debuggable apps under CheckJNI when a nonexistent
boolean view-model property is read (rive-android#470, fixed in
11.12.1). 11.11.0 deprecates the legacy `app.rive.runtime.kotlin` API
the legacy backend uses, and 11.12 adds more 12.0 deprecations on the
new API; both are compile warnings only, nothing is removed. The only
other change is the rive-ios source link in `RiveRuntimeLogger.swift`,
repointed at the same lines in 6.26.0.

Verified locally, both backends on both platforms (iPhone 17 simulator,
Pixel 6 emulator):

1. New backend: iOS 29/29 suites, 209 tests; Android 29/29, 209 tests.
2. Legacy backend: iOS 29/29, 201 passed + 8 skipped; Android 29/29, 201
passed + 8 skipped.

#381 pins the same versions, so it will rebase cleanly once this lands.
The 0.4.x counterpart is a separate PR against `release-v0.4`.

Also switches release-please from beta prereleases to a final release
pinned at `0.5.0`, so the release PR after this merges is 0.5.0 and
publishes to npm `latest`. `release-as` has to be removed once 0.5.0 is
out.
@mfazekas
mfazekas enabled auto-merge (squash) October 1, 2026 13:02
@mfazekas
mfazekas force-pushed the claude/gpu-canvas-beta-android-ios-7ccb40 branch from e5fd81e to 2ee96bb Compare October 2, 2026 14:54
Both are the first releases that ship GPU Canvas (rive-ios 6.25.0,
rive-android 11.12.0). rive-android 11.10+ also surfaces an upstream bug:
reading a nonexistent boolean property aborts debuggable apps with
"JNI DETECTED ERROR: unexpected jboolean value" because rive-runtime's
listViewModelPropertyValue handler still sends a value message with an
uninitialized union member after reporting the not-found error. As a
mitigation, boolean reads on instances with known ViewModel metadata are
validated against the property list before touching the native getter.
… + Android)

Adds RiveRuntime.setGPUCanvasEnabled()/isGPUCanvasEnabled(). The setting
is process-wide and fixed once the shared render worker exists, like
setAndroidRenderBackend; both now live in RiveWorkerConfig per source set.
iOS maps to Worker(configuration: .init(enableGPUCanvas:)); Android maps to
rive-android's experimental deferred renderer, reached through a Java shim
because CommandQueue.createDeferred is Kotlin-internal. No-op on the legacy
runtime. Adds the ore.riv GPU Canvas demo page and docs.
Walks the path via ViewModelInstance.create(Reference(parent)) and
getViewModelName() so nested and view-obtained instances are covered by
the rive-app/rive-android#470 guard too, and caches the result per path.
Adds nested-miss cases to the harness test.
11.12.1 fixes rive-app/rive-android#470 in the runtime (a failed property
read no longer sends a value message), so the metadata guard in
HybridViewModelInstance is gone; the nested-miss harness cases stay as the
regression check. Also adds the generated ore.riv.d.ts the lint job
requires.
…th a warning

CommandQueue.createDeferred is Kotlin-internal, so the GPU Canvas worker was
reached through a Java shim that named the mangled method at compile time.
A rive-android without that exact symbol (older override, or an upstream
rename) broke the build. Look it up reflectively instead, accepting either
the mangled or a plain createDeferred; when it is missing the worker is
created without GPU Canvas, RiveLog warns, and isGPUCanvasEnabled() turns
false.
The status was read once before the file loaded, so on a native SDK without
the deferred worker the page said "enabled" over a black scene and, after a
reload, blamed a prior file load. Re-check the flag once the file has loaded
and distinguish "request ignored" from "not available in this SDK".
createWorker() resolves the requested options, tries the deferred worker,
falls back with a warning, and commits the options the worker was actually
built with, so HybridRiveFileFactory no longer stitches those steps together
and a failed construction leaves the options open for a retry. Also drops
the isAccessible toggle in DeferredRiveWorker: the mangled entry point is
public in bytecode.
…erred worker

The docs named `RiveWorker.createDeferred()` as if it were public API and did
not say that an older `RiveRuntimeIOSVersion` fails to compile. Also trims the
DeferredRiveWorker comment to what the lookup does.
@mfazekas
mfazekas force-pushed the claude/gpu-canvas-beta-android-ios-7ccb40 branch from 2ee96bb to d46c41c Compare October 5, 2026 11:57
@mfazekas
mfazekas requested a review from HayesGordon October 5, 2026 11:57
@mfazekas
mfazekas merged commit d9439a9 into main Oct 5, 2026
15 checks passed
@mfazekas
mfazekas deleted the claude/gpu-canvas-beta-android-ios-7ccb40 branch October 5, 2026 15:23
mfazekas pushed a commit that referenced this pull request Oct 6, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.5.3](v0.5.2...v0.5.3)
(2026-10-05)


### Features

* expose GPU Canvas (3D) on iOS and Android
([#381](#381))
([d9439a9](d9439a9))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
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