Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions .github/workflows/build-dawn.yml
Original file line number Diff line number Diff line change
Expand Up @@ -236,9 +236,9 @@ jobs:
- name: Create XCFramework
run: |
xcodebuild -create-xcframework \
-library libs/apple/iphonesimulator/libwebgpu_dawn.a \
-library artifacts/build-ios-arm64/libwebgpu_dawn.a \
-library artifacts/build-macos-universal/libwebgpu_dawn.a \
-library libs/apple/iphonesimulator/libwebgpu_dawn.a -headers dawn-headers/include \
-library artifacts/build-ios-arm64/libwebgpu_dawn.a -headers dawn-headers/include \
-library artifacts/build-macos-universal/libwebgpu_dawn.a -headers dawn-headers/include \
-output dawn-apple.xcframework

- name: Package Android libraries
Expand All @@ -256,8 +256,13 @@ jobs:
run: |
TAG="${{ needs.prepare-release.outputs.tag_name }}"
tar -czf dawn-android-${TAG}.tar.gz dawn-android
tar -czf dawn-apple-${TAG}.xcframework.tar.gz dawn-apple.xcframework
tar -czf dawn-headers-${TAG}.tar.gz dawn-headers
# Package.swift binaryTarget(url:checksum:) requires a zip archive, not a
# tarball, and `ditto` (unlike `zip`) preserves the xcframework's symlinks
# and resource forks losslessly.
ditto -c -k --sequesterRsrc --keepParent dawn-apple.xcframework dawn-apple-${TAG}.xcframework.zip
swift package compute-checksum dawn-apple-${TAG}.xcframework.zip > dawn-apple-${TAG}.xcframework.zip.checksum.txt
cat dawn-apple-${TAG}.xcframework.zip.checksum.txt

- name: Upload to GitHub release
uses: softprops/action-gh-release@v2
Expand All @@ -267,6 +272,7 @@ jobs:
tag_name: ${{ needs.prepare-release.outputs.tag_name }}
files: |
dawn-android-${{ needs.prepare-release.outputs.tag_name }}.tar.gz
dawn-apple-${{ needs.prepare-release.outputs.tag_name }}.xcframework.tar.gz
dawn-apple-${{ needs.prepare-release.outputs.tag_name }}.xcframework.zip
dawn-apple-${{ needs.prepare-release.outputs.tag_name }}.xcframework.zip.checksum.txt
dawn-headers-${{ needs.prepare-release.outputs.tag_name }}.tar.gz
prerelease: true
36 changes: 36 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,42 @@ jobs:
-disableAutomaticPackageResolution \
build | xcpretty

- name: Install CocoaPods (spm-example)
working-directory: apps/spm-example/ios
env:
RNWGPU_USE_SPM: "1"
run: pod install

# Don't reuse "build" as -derivedDataPath for this app: React Native
# Codegen writes generated headers to apps/spm-example/ios/build/generated/ios,
# and CocoaPods symlinks them from Pods/Headers/Public/ReactCodegen/;
# deriving into the same "build" directory (as the example app step above
# does) deletes those symlink targets on a clean checkout.
#
# PODS_ROOT is deliberately not exported: xcodebuild never sets it, and
# Package.swift has to find the Pods directory from its own location.
# This step is what verifies that fallback.
#
# No -disableAutomaticPackageResolution here (unlike the example app
# build below): react-native-webgpu is a local Swift package added
# directly to the Xcode project (XCLocalSwiftPackageReference), not
# CocoaPods-vendored, and its WebGPUDawn binaryTarget resolves to a
# remote release zip + checksum with nothing cached ahead of time — this
# build's whole point is exercising that download-and-verify step.
- name: Build spm-example for iOS
working-directory: apps/spm-example/ios
run: |
set -o pipefail && xcodebuild \
-workspace SpmExample.xcworkspace \
-scheme SpmExample \
-configuration Debug \
-sdk iphonesimulator \
-destination "generic/platform=iOS Simulator" \
-derivedDataPath spm-build \
COMPILER_INDEX_STORE_ENABLE=NO \
DISABLE_MANUAL_TARGET_ORDER_BUILD_WARNING=YES \
build | xcpretty

- name: Boot iPhone Simulator
run: |
if xcrun simctl list devices booted | grep -q "iPhone"; then
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,8 @@ apps/example/**/Pods
# Ruby
apps/vendor/

# Swift Package Manager
.swiftpm/
Package.resolved

.turbo
20 changes: 20 additions & 0 deletions apps/docs/content/docs/getting-started/installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,26 @@ npm i react-native-webgpu

Please note that this module does not work on the legacy architecture.

## iOS: Swift Package Manager

By default, `react-native-webgpu` links on iOS/macOS through CocoaPods autolinking - no extra setup needed. As an alternative, the package also ships a `Package.swift` and can be linked through Swift Package Manager instead:

1. Set `RNWGPU_USE_SPM=1` before running `pod install` (e.g. `RNWGPU_USE_SPM=1 pod install` from your app's `ios` directory, or export it in your shell). This tells the CocoaPods podspec to skip vendoring the native sources and Dawn binary itself, and only keep the small shim CocoaPods/Codegen still need - otherwise the app would link the native module twice.
2. In Xcode, add a local Swift Package dependency pointing at `node_modules/react-native-webgpu` (where `Package.swift` lives), then add the `react-native-webgpu` product to your app target's "Frameworks, Libraries, and Embedded Content".
3. Keep running `pod install` as usual for everything else - only `react-native-webgpu` itself moves to SPM.

The Swift package reads React Native's headers from the static-library Pods layout (`Pods/Headers/Public`), so it cannot be combined with `use_frameworks!`; `pod install` refuses `RNWGPU_USE_SPM=1` when `USE_FRAMEWORKS` is set. If a Graphite build of `@shopify/react-native-skia` is installed alongside, the manifest also checks that both packages link the same Dawn release and fails package resolution on a mismatch (see [React Native Skia](/docs/integrations/react-native-skia)).

<Callout type="info" title="React Native 0.87 SwiftPM autolinking">
React Native 0.87 introduced SwiftPM autolinking, where a library shipping its own `Package.swift` is linked without CocoaPods and consumes React Native's headers as Swift package products. This manifest does not support that model yet: it still needs the CocoaPods install described above for React Native's headers, so keep CocoaPods for React Native on 0.87+ apps.
</Callout>

`Package.swift`'s `WebGPUDawn` binary target resolves to a prebuilt Dawn `.xcframework` published on GitHub Releases; Xcode downloads and checksum-verifies it the first time it resolves packages.

<Callout type="warn" title="Platform coverage">
The Swift package targets iOS 15.1+ and macOS 11.0+ only - Android and visionOS still require the CocoaPods/Gradle autolinked path. See `apps/spm-example` in the [react-native-webgpu repo](https://github.com/wcandillon/react-native-webgpu) for a working reference project.
</Callout>

## Setup

Once installed, the global `navigator.gpu` API is available - the same entry point as in Chrome or Safari:
Expand Down
3 changes: 2 additions & 1 deletion apps/docs/content/docs/integrations/react-native-skia.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ Both packages follow Chrome/Skia milestones: react-native-webgpu pins the Dawn r

| Milestone | react-native-webgpu | Dawn release tag | `@shopify/react-native-skia` (Graphite `@next`) |
| --- | --- | --- | --- |
| m152 | 0.8.2 | `dawn-chrome-m152` | 2.12.0-next.1 (Graphite `152.0.0`) |
| m154 | *unreleased* | `dawn-chrome-m154` | *unreleased* |
| m152 | 0.8.2 – 0.9.0 | `dawn-chrome-m152` | 2.12.0-next.1 (Graphite `152.0.0`) |
| m150 | 0.7.0 – 0.8.1 | `dawn-chrome-m150` | 2.9.1-next.1 – 2.11.0-next.2 (Graphite `150.0.0`) |

Default (Ganesh) releases of react-native-skia — 2.11.0 at the time of writing — are not part of this pairing: they do not link Dawn, so any version works alongside any version of react-native-webgpu.
Expand Down
4 changes: 4 additions & 0 deletions apps/spm-example/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
root: true,
extends: '@react-native',
};
75 changes: 75 additions & 0 deletions apps/spm-example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# OSX
#
.DS_Store

# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
**/.xcode.env.local

# Android/IntelliJ
#
build/
.idea
.gradle
local.properties
*.iml
*.hprof
.cxx/
*.keystore
!debug.keystore
.kotlin/

# node.js
#
node_modules/
npm-debug.log
yarn-error.log

# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/

**/fastlane/report.xml
**/fastlane/Preview.html
**/fastlane/screenshots
**/fastlane/test_output

# Bundle artifact
*.jsbundle

# Ruby / CocoaPods
**/Pods/
/vendor/bundle/

# Temporary files created by Metro to check the health of the file watcher
.metro-health-check*

# testing
/coverage

# Yarn
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
5 changes: 5 additions & 0 deletions apps/spm-example/.prettierrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
arrowParens: 'avoid',
singleQuote: true,
trailingComma: 'all',
};
1 change: 1 addition & 0 deletions apps/spm-example/.watchmanconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
84 changes: 84 additions & 0 deletions apps/spm-example/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
* Minimal app used to validate react-native-webgpu linked via Swift Package
* Manager (see packages/webgpu/Package.swift) instead of CocoaPods on iOS.
* Renders a plain animated clear color: enough to exercise adapter/device
* request, context configuration, command submission, and present() end to
* end without pulling in the full example app's dependencies.
*
* @format
*/

import { useEffect, useRef } from 'react';
import { StyleSheet, View } from 'react-native';
import { Canvas, type CanvasRef } from 'react-native-webgpu';

function Scene() {
const ref = useRef<CanvasRef>(null);

useEffect(() => {
let stopped = false;
let frame: number;

const start = async () => {
const context = ref.current?.getContext('webgpu');
if (!context) {
frame = requestAnimationFrame(start);
return;
}
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter?.requestDevice();
if (!device) {
return;
}
const format = navigator.gpu.getPreferredCanvasFormat();
context.configure({ device, format, alphaMode: 'opaque' });

const render = (t: number) => {
if (stopped) {
return;
}
const hue = (t / 1000) % 1;
const encoder = device.createCommandEncoder();
const pass = encoder.beginRenderPass({
colorAttachments: [
{
view: context.getCurrentTexture().createView(),
loadOp: 'clear',
storeOp: 'store',
clearValue: { r: hue, g: 1 - hue, b: 0.5, a: 1 },
},
],
});
pass.end();
device.queue.submit([encoder.finish()]);
context.present();
frame = requestAnimationFrame(render);
};
frame = requestAnimationFrame(render);
};

frame = requestAnimationFrame(start);
return () => {
stopped = true;
cancelAnimationFrame(frame);
};
}, []);

return <Canvas ref={ref} style={StyleSheet.absoluteFill} />;
}

function App() {
return (
<View style={styles.container}>
<Scene />
</View>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
},
});

export default App;
16 changes: 16 additions & 0 deletions apps/spm-example/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
source 'https://rubygems.org'

# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
ruby ">= 2.6.10"

# Exclude problematic versions of cocoapods and activesupport that causes build failures.
gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1'
gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0'
gem 'xcodeproj', '< 1.26.0'
gem 'concurrent-ruby', '< 1.3.4'

# Ruby 3.4.0 has removed some libraries from the standard library.
gem 'bigdecimal'
gem 'logger'
gem 'benchmark'
gem 'mutex_m'
Loading
Loading