react-native-webgpu 0.15.2 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/android/CMakeLists.txt +5 -0
  2. package/android/build.gradle +11 -1
  3. package/android/cpp/cpp-adapter.cpp +109 -11
  4. package/android/src/main/java/com/webgpu/SurfaceFrameRateVote.java +97 -85
  5. package/android/src/main/java/com/webgpu/WebGPUView.java +97 -42
  6. package/apple/ApplePlatformContext.h +1 -0
  7. package/cpp/jsi/JSICache.cpp +2 -0
  8. package/cpp/jsi/NativeObject.h +81 -17
  9. package/cpp/rnwgpu/RNWebGPUManager.cpp +51 -41
  10. package/cpp/rnwgpu/RNWebGPUManager.h +10 -0
  11. package/cpp/rnwgpu/SurfaceRegistry.h +4 -4
  12. package/cpp/rnwgpu/api/GPUDevice.cpp +96 -0
  13. package/cpp/rnwgpu/api/GPUDevice.h +22 -0
  14. package/cpp/rnwgpu/api/GPUError.h +1 -0
  15. package/cpp/rnwgpu/api/GPUExtent2D.h +56 -0
  16. package/cpp/rnwgpu/api/GPUExternalTexture.cpp +32 -408
  17. package/cpp/rnwgpu/api/GPUExternalTexture.h +12 -37
  18. package/cpp/rnwgpu/api/GPUInternalError.h +1 -0
  19. package/cpp/rnwgpu/api/GPUNativeBufferExternalTexture.h +60 -0
  20. package/cpp/rnwgpu/api/GPUNativeBufferTexture.h +52 -0
  21. package/cpp/rnwgpu/api/GPUNativeBufferWrapper.cpp +144 -0
  22. package/cpp/rnwgpu/api/GPUNativeBufferWrapper.h +143 -0
  23. package/cpp/rnwgpu/api/GPUOutOfMemoryError.h +1 -0
  24. package/cpp/rnwgpu/api/GPUQueue.h +1 -0
  25. package/cpp/rnwgpu/api/GPUSharedFence.h +1 -0
  26. package/cpp/rnwgpu/api/GPUSharedTextureMemory.cpp +12 -44
  27. package/cpp/rnwgpu/api/GPUSharedTextureMemory.h +1 -0
  28. package/cpp/rnwgpu/api/GPUUncapturedErrorEvent.h +1 -0
  29. package/cpp/rnwgpu/api/GPUValidationError.h +1 -0
  30. package/cpp/rnwgpu/api/NativeFrameImport.cpp +638 -0
  31. package/cpp/rnwgpu/api/NativeFrameImport.h +86 -0
  32. package/cpp/rnwgpu/api/VideoFrame.h +21 -7
  33. package/cpp/rnwgpu/api/descriptors/GPUExternalTextureDescriptor.h +153 -1
  34. package/cpp/rnwgpu/api/descriptors/GPUNativeBufferTextureDescriptor.h +55 -0
  35. package/cpp/rnwgpu/async/RuntimeContext.cpp +1 -0
  36. package/lib/commonjs/Canvas.js +51 -0
  37. package/lib/commonjs/Canvas.js.map +1 -1
  38. package/lib/commonjs/external/reanimated/registerWebGPUForReanimated.js.map +1 -1
  39. package/lib/commonjs/index.js.map +1 -1
  40. package/lib/commonjs/install.js +26 -7
  41. package/lib/commonjs/install.js.map +1 -1
  42. package/lib/module/Canvas.js +51 -0
  43. package/lib/module/Canvas.js.map +1 -1
  44. package/lib/module/external/reanimated/registerWebGPUForReanimated.js.map +1 -1
  45. package/lib/module/index.js.map +1 -1
  46. package/lib/module/install.js +26 -7
  47. package/lib/module/install.js.map +1 -1
  48. package/lib/typescript/lib/commonjs/Canvas.d.ts.map +1 -1
  49. package/lib/typescript/lib/commonjs/install.d.ts +10 -7
  50. package/lib/typescript/lib/commonjs/install.d.ts.map +1 -1
  51. package/lib/typescript/lib/module/Canvas.d.ts.map +1 -1
  52. package/lib/typescript/lib/module/install.d.ts.map +1 -1
  53. package/lib/typescript/src/Canvas.d.ts +20 -35
  54. package/lib/typescript/src/Canvas.d.ts.map +1 -1
  55. package/lib/typescript/src/external/reanimated/registerWebGPUForReanimated.d.ts +1 -0
  56. package/lib/typescript/src/external/reanimated/registerWebGPUForReanimated.d.ts.map +1 -1
  57. package/lib/typescript/src/index.d.ts +4 -2
  58. package/lib/typescript/src/index.d.ts.map +1 -1
  59. package/lib/typescript/src/install.d.ts +10 -7
  60. package/lib/typescript/src/install.d.ts.map +1 -1
  61. package/lib/typescript/src/types.d.ts +34 -1
  62. package/lib/typescript/src/types.d.ts.map +1 -1
  63. package/package.json +6 -5
  64. package/plugin/build/index.js +2 -1
  65. package/plugin/build/setMinSdkVersion.d.ts +9 -0
  66. package/plugin/build/setMinSdkVersion.js +25 -0
  67. package/plugin/build/withMinSdkVersion.d.ts +11 -0
  68. package/plugin/build/withMinSdkVersion.js +20 -0
  69. package/src/Canvas.tsx +74 -40
  70. package/src/external/reanimated/registerWebGPUForReanimated.ts +4 -0
  71. package/src/index.tsx +24 -0
  72. package/src/install.ts +26 -7
  73. package/src/types.ts +98 -1
@@ -2,6 +2,7 @@ package com.webgpu;
2
2
 
3
3
  import android.content.Context;
4
4
  import android.os.Build;
5
+ import android.util.Log;
5
6
  import android.view.Surface;
6
7
  import android.view.View;
7
8
 
@@ -10,6 +11,7 @@ import com.facebook.react.uimanager.ThemedReactContext;
10
11
  import com.facebook.react.views.view.ReactViewGroup;
11
12
 
12
13
  public class WebGPUView extends ReactViewGroup implements WebGPUAPI {
14
+ private static final String TAG = "WebGPUView";
13
15
 
14
16
  // Backing view kinds, see updateView().
15
17
  private static final int KIND_SURFACE_VIEW = 0;
@@ -17,16 +19,22 @@ public class WebGPUView extends ReactViewGroup implements WebGPUAPI {
17
19
  private static final int KIND_HARDWARE_BUFFER_VIEW = 2;
18
20
 
19
21
  private int mContextId;
22
+ // Props. opaque is applied in place, and so is zOrderOnTop where Android
23
+ // allows it (see setZOrderOnTop); surfaceType is read once, when the
24
+ // backing view is created (see updateView()).
20
25
  private boolean mOpaque = true;
21
26
  private String mSurfaceType = "auto";
22
27
  private boolean mZOrderOnTop = false;
23
- private int mAppliedKind = -1;
24
- private boolean mAppliedZOrderOnTop;
25
28
  private WebGPUModule mModule;
29
+ // The backing view, created by the first prop transaction and kept, with
30
+ // the kind it was created with. The kind is -1 until then: it is what
31
+ // tells a mounted canvas apart.
26
32
  private View mView = null;
33
+ private int mKind = -1;
27
34
  // Only a SurfaceView votes: a TextureView or HardwareBufferView is
28
35
  // composited into the window, which votes for it.
29
- private final SurfaceFrameRateVote mFrameRateVote = new SurfaceFrameRateVote(this);
36
+ private final SurfaceFrameRateVote mFrameRateVote = new SurfaceFrameRateVote(
37
+ this, idleAfterNanos -> releaseFrameRateVoteIfIdle(mContextId, idleAfterNanos));
30
38
 
31
39
  WebGPUView(Context context) {
32
40
  super(context);
@@ -54,12 +62,52 @@ public class WebGPUView extends ReactViewGroup implements WebGPUAPI {
54
62
  mOpaque = value;
55
63
  }
56
64
 
65
+ // The backing view is chosen from the props of the first transaction and
66
+ // kept (see updateView()). React calls a setter again only when its prop
67
+ // changed, so a call on a mounted canvas is a change: the setters below
68
+ // apply it in place where the view can take it, else they ignore it and
69
+ // say so (a canvas that needs another backing view is remounted, with a
70
+ // new key). The JS side warns about the same changes in development (see
71
+ // Canvas.tsx), mirroring these rules.
72
+
57
73
  public void setSurfaceType(String value) {
74
+ if (mKind != -1) {
75
+ warnIgnoredOnceMounted("android.surfaceType");
76
+ return;
77
+ }
58
78
  mSurfaceType = value;
59
79
  }
60
80
 
61
81
  public void setZOrderOnTop(boolean value) {
82
+ if (mKind == -1) {
83
+ mZOrderOnTop = value;
84
+ return;
85
+ }
86
+ // Only a SurfaceView has a z-order of its own: elsewhere the prop never
87
+ // applied, and the change is moot.
88
+ if (mKind != KIND_SURFACE_VIEW) {
89
+ return;
90
+ }
91
+ if (!zOrderChangesInPlace()) {
92
+ warnIgnoredOnceMounted("android.zOrderOnTop");
93
+ return;
94
+ }
62
95
  mZOrderOnTop = value;
96
+ ((WebGPUSurfaceView) mView).setZOrderOnTop(value);
97
+ }
98
+
99
+ private void warnIgnoredOnceMounted(String prop) {
100
+ Log.w(TAG, "Ignoring a change of " + prop + " on a mounted canvas: the backing view"
101
+ + " is chosen when the canvas mounts. Remount the canvas (give it a new key)"
102
+ + " to change it.");
103
+ }
104
+
105
+ // SurfaceView.setZOrderOnTop() moves a live surface since Android 11, for
106
+ // an app targeting it; before that, the surface reads it when it is
107
+ // created (see updateView()).
108
+ private boolean zOrderChangesInPlace() {
109
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
110
+ && getContext().getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R;
63
111
  }
64
112
 
65
113
  // Resolve the backing view from the props. "auto" picks SurfaceView for an
@@ -83,41 +131,44 @@ public class WebGPUView extends ReactViewGroup implements WebGPUAPI {
83
131
  }
84
132
 
85
133
  // Apply the complete prop transaction once, after contextId and all rendering
86
- // options have arrived. Only a change of backing view (or of zOrderOnTop,
87
- // which a SurfaceView must know before it attaches) replaces the child;
88
- // opacity is applied in place.
134
+ // options have arrived. The first one creates the backing view, which is
135
+ // then kept: a SurfaceView must know its z-order before it attaches (before
136
+ // Android 11), and replacing a backing view on screen hands the canvas from
137
+ // one view to another, which no release of Android does without a frame of
138
+ // nothing, or of black, in between (the two views are composited by
139
+ // different frames). A canvas that needs another backing view is remounted
140
+ // instead. Later transactions apply the opacity in place (the setters decide
141
+ // what else is taken); WebGPUHardwareBufferView always composites with
142
+ // alpha, so there it is a no-op.
89
143
  public void updateView() {
144
+ if (mKind != -1) {
145
+ if (mKind == KIND_TEXTURE_VIEW) {
146
+ ((WebGPUTextureView) mView).setOpaque(mOpaque);
147
+ } else if (mKind == KIND_SURFACE_VIEW) {
148
+ ((WebGPUSurfaceView) mView).setOpaque(mOpaque);
149
+ }
150
+ return;
151
+ }
90
152
  int kind = resolveKind();
91
153
  boolean zOrderOnTop = kind == KIND_SURFACE_VIEW && mZOrderOnTop;
92
- if (mView == null || kind != mAppliedKind || zOrderOnTop != mAppliedZOrderOnTop) {
93
- if (mView != null) {
94
- removeView(mView);
95
- }
96
- mAppliedKind = kind;
97
- mAppliedZOrderOnTop = zOrderOnTop;
98
- Context ctx = getContext();
99
- switch (kind) {
100
- case KIND_HARDWARE_BUFFER_VIEW:
101
- mView = new WebGPUHardwareBufferView(ctx, this);
102
- break;
103
- case KIND_TEXTURE_VIEW:
104
- mView = new WebGPUTextureView(ctx, this, mOpaque);
105
- break;
106
- default:
107
- mView = new WebGPUSurfaceView(ctx, this, zOrderOnTop, mOpaque);
108
- break;
109
- }
110
- addView(mView);
111
- // ReactViewGroup.requestLayout() is a deliberate no-op, so addView outside
112
- // the layout pass never lays the child out; do it by hand or the new view
113
- // stays 0x0 and never gets a surface.
114
- layoutChild();
115
- } else if (kind == KIND_TEXTURE_VIEW) {
116
- ((WebGPUTextureView) mView).setOpaque(mOpaque);
117
- } else if (kind == KIND_SURFACE_VIEW) {
118
- ((WebGPUSurfaceView) mView).setOpaque(mOpaque);
154
+ mKind = kind;
155
+ Context ctx = getContext();
156
+ switch (kind) {
157
+ case KIND_HARDWARE_BUFFER_VIEW:
158
+ mView = new WebGPUHardwareBufferView(ctx, this);
159
+ break;
160
+ case KIND_TEXTURE_VIEW:
161
+ mView = new WebGPUTextureView(ctx, this, mOpaque);
162
+ break;
163
+ default:
164
+ mView = new WebGPUSurfaceView(ctx, this, zOrderOnTop, mOpaque);
165
+ break;
119
166
  }
120
- // WebGPUHardwareBufferView always composites with alpha; opacity is a no-op.
167
+ addView(mView);
168
+ // ReactViewGroup.requestLayout() is a deliberate no-op, so addView outside
169
+ // the layout pass never lays the child out; do it by hand or the new view
170
+ // stays 0x0 and never gets a surface.
171
+ layoutChild();
121
172
  }
122
173
 
123
174
  private void layoutChild() {
@@ -137,7 +188,7 @@ public class WebGPUView extends ReactViewGroup implements WebGPUAPI {
137
188
  float density = getResources().getDisplayMetrics().density;
138
189
  float width = getWidth() / density;
139
190
  float height = getHeight() / density;
140
- boolean votesFrameRate = mAppliedKind == KIND_SURFACE_VIEW;
191
+ boolean votesFrameRate = mKind == KIND_SURFACE_VIEW;
141
192
  if (votesFrameRate) {
142
193
  mFrameRateVote.attach(surface);
143
194
  }
@@ -160,12 +211,12 @@ public class WebGPUView extends ReactViewGroup implements WebGPUAPI {
160
211
  }
161
212
 
162
213
  /**
163
- * Called from native (SurfaceInfo::presentFrame) on the thread that
164
- * presented a frame to the surface, only for a SurfaceView.
214
+ * Called from native (AnimationReporter in cpp-adapter.cpp) on the thread
215
+ * that presents to the surface, once per animation, only for a SurfaceView.
165
216
  */
166
217
  @DoNotStrip
167
- void onFramePresented() {
168
- mFrameRateVote.onFramePresented();
218
+ void onAnimating() {
219
+ mFrameRateVote.onAnimating();
169
220
  }
170
221
 
171
222
  @Override
@@ -182,15 +233,15 @@ public class WebGPUView extends ReactViewGroup implements WebGPUAPI {
182
233
  onViewDestroyed(mContextId);
183
234
  }
184
235
 
185
- // reportPresents asks native to call onFramePresented() for each frame
186
- // presented to this surface.
236
+ // reportAnimation asks native to call onAnimating() when frames start being
237
+ // presented to this surface back to back.
187
238
  @DoNotStrip
188
239
  private native void onSurfaceCreate(
189
240
  Surface surface,
190
241
  int contextId,
191
242
  float width,
192
243
  float height,
193
- boolean reportPresents
244
+ boolean reportAnimation
194
245
  );
195
246
 
196
247
  @DoNotStrip
@@ -207,4 +258,8 @@ public class WebGPUView extends ReactViewGroup implements WebGPUAPI {
207
258
  @DoNotStrip
208
259
  private native void onViewDestroyed(int contextId);
209
260
 
261
+ // See SurfaceFrameRateVote.AnimationSource.
262
+ @DoNotStrip
263
+ private native long releaseFrameRateVoteIfIdle(int contextId, long idleAfterNanos);
264
+
210
265
  }
@@ -2,6 +2,7 @@
2
2
 
3
3
  #include "PlatformContext.h"
4
4
  #include <functional>
5
+ #include <memory>
5
6
  #include <string>
6
7
 
7
8
  namespace rnwgpu {
@@ -2,8 +2,10 @@
2
2
 
3
3
  #include <algorithm>
4
4
  #include <iterator>
5
+ #include <memory>
5
6
  #include <stdexcept>
6
7
  #include <string>
8
+ #include <unordered_map>
7
9
  #include <utility>
8
10
 
9
11
  namespace rnwgpu {
@@ -14,6 +14,7 @@
14
14
  #include <typeindex>
15
15
  #include <unordered_map>
16
16
  #include <utility>
17
+ #include <vector>
17
18
 
18
19
  #include "EnforceRange.h"
19
20
  #include "JSICache.h"
@@ -178,6 +179,14 @@ private:
178
179
  * getters and Proxy traps of unrelated objects never run.
179
180
  * - box(value): wraps the object into a BoxedWebGPUObject, branded with its
180
181
  * class name, for unbox() on the target runtime.
182
+ * - installConstructors(): installs the constructor of every WebGPU class on
183
+ * the calling runtime, skipping the ones already there, so `instanceof`
184
+ * works against any class on that runtime, including classes no object of
185
+ * which was ever created there or crossed into it (unboxing installs only
186
+ * the class of the object that crosses). installWebGPU() calls it. The
187
+ * class list belongs to the API layer (RNWebGPUManager::installConstructors)
188
+ * and is handed in at construction: every API class includes this header,
189
+ * which therefore cannot include them back.
181
190
  *
182
191
  * One instance is installed on the main runtime as
183
192
  * globalThis.__webgpuWorkletHelpers and captured by the serializer's
@@ -188,8 +197,26 @@ private:
188
197
  */
189
198
  class WebGPUWorkletHelpers : public jsi::HostObject {
190
199
  public:
200
+ using InstallConstructors = void (*)(jsi::Runtime &);
201
+
202
+ explicit WebGPUWorkletHelpers(InstallConstructors installConstructors)
203
+ : _installConstructors(installConstructors) {}
204
+
191
205
  jsi::Value get(jsi::Runtime &runtime, const jsi::PropNameID &name) override {
192
206
  auto propName = name.utf8(runtime);
207
+ if (propName == "installConstructors") {
208
+ auto install = _installConstructors;
209
+ return jsi::Function::createFromHostFunction(
210
+ runtime, name, 0,
211
+ [install](jsi::Runtime &rt, const jsi::Value & /*thisVal*/,
212
+ const jsi::Value * /*args*/,
213
+ size_t /*count*/) -> jsi::Value {
214
+ if (install != nullptr) {
215
+ install(rt);
216
+ }
217
+ return jsi::Value::undefined();
218
+ });
219
+ }
193
220
  if (propName == "isNativeObject") {
194
221
  return jsi::Function::createFromHostFunction(
195
222
  runtime, name, 1,
@@ -229,11 +256,15 @@ public:
229
256
  std::vector<jsi::PropNameID>
230
257
  getPropertyNames(jsi::Runtime &runtime) override {
231
258
  std::vector<jsi::PropNameID> names;
232
- names.reserve(2);
259
+ names.reserve(3);
233
260
  names.push_back(jsi::PropNameID::forUtf8(runtime, "isNativeObject"));
234
261
  names.push_back(jsi::PropNameID::forUtf8(runtime, "box"));
262
+ names.push_back(jsi::PropNameID::forUtf8(runtime, "installConstructors"));
235
263
  return names;
236
264
  }
265
+
266
+ private:
267
+ InstallConstructors _installConstructors;
237
268
  };
238
269
 
239
270
  /**
@@ -377,6 +408,9 @@ public:
377
408
  * The constructor throws if called directly (these objects are only
378
409
  * created internally by the native code).
379
410
  *
411
+ * Idempotent per runtime: once the global exists there, later calls return
412
+ * without touching it, so the constructor object keeps its identity.
413
+ *
380
414
  * Also registers this class with NativeObjectRegistry so that
381
415
  * BoxedWebGPUObject::unbox() can rebuild its objects on secondary runtimes.
382
416
  */
@@ -393,10 +427,9 @@ public:
393
427
  if (instance == nullptr) {
394
428
  throw jsi::JSError(rt, "Invalid boxed native object state");
395
429
  }
396
- // The constructor makes `instanceof` work on this runtime too.
397
- if (!rt.global().hasProperty(rt, Derived::CLASS_NAME)) {
398
- Derived::installConstructor(rt);
399
- }
430
+ // The constructor makes `instanceof` work on this runtime too
431
+ // (a no-op once it is installed there).
432
+ Derived::installConstructor(rt);
400
433
  // Unboxing hands back the wrapper cached for the target runtime,
401
434
  // creating it on first use. Keep the runtime the object was
402
435
  // originally created on: async native code (GPUDevice error/lost
@@ -414,6 +447,14 @@ public:
414
447
 
415
448
  installPrototype(runtime);
416
449
 
450
+ // Once per runtime. installWebGPU() runs this at the top of every worklet
451
+ // invocation, and reinstalling would replace the global with a new
452
+ // function object each time (`const C = GPUBuffer; C === GPUBuffer`
453
+ // would be false).
454
+ if (runtime.global().hasProperty(runtime, Derived::CLASS_NAME)) {
455
+ return;
456
+ }
457
+
417
458
  auto *prototype = getCachedPrototype(runtime);
418
459
  if (prototype == nullptr) {
419
460
  return;
@@ -640,19 +681,26 @@ protected:
640
681
  rt, std::move(result));
641
682
  }
642
683
  });
684
+ defineGetter(runtime, prototype, name, getterFunc);
685
+ }
643
686
 
644
- // Use Object.defineProperty to create a proper getter
645
- auto objectCtor = runtime.global().getPropertyAsObject(runtime, "Object");
646
- auto defineProperty =
647
- objectCtor.getPropertyAsFunction(runtime, "defineProperty");
648
-
649
- jsi::Object descriptor(runtime);
650
- descriptor.setProperty(runtime, "get", getterFunc);
651
- descriptor.setProperty(runtime, "enumerable", true);
652
- descriptor.setProperty(runtime, "configurable", true);
653
-
654
- defineProperty.call(runtime, prototype,
655
- jsi::String::createFromUtf8(runtime, name), descriptor);
687
+ /**
688
+ * Install a getter whose native implementation builds the JS value itself,
689
+ * from the calling jsi::Runtime: for values no JSIConverter produces (null
690
+ * or a BigInt, say).
691
+ */
692
+ static void installGetter(jsi::Runtime &runtime, jsi::Object &prototype,
693
+ const char *name,
694
+ jsi::Value (Derived::*getter)(jsi::Runtime &)) {
695
+ auto getterFunc = jsi::Function::createFromHostFunction(
696
+ runtime, jsi::PropNameID::forUtf8(runtime, std::string("get_") + name),
697
+ 0,
698
+ [getter](jsi::Runtime &rt, const jsi::Value &thisVal,
699
+ const jsi::Value *args, size_t count) -> jsi::Value {
700
+ auto native = Derived::fromValue(rt, thisVal);
701
+ return (native.get()->*getter)(rt);
702
+ });
703
+ defineGetter(runtime, prototype, name, getterFunc);
656
704
  }
657
705
 
658
706
  /**
@@ -757,6 +805,22 @@ protected:
757
805
  }
758
806
 
759
807
  private:
808
+ // Use Object.defineProperty to create a proper getter
809
+ static void defineGetter(jsi::Runtime &runtime, jsi::Object &prototype,
810
+ const char *name, const jsi::Function &getterFunc) {
811
+ auto objectCtor = runtime.global().getPropertyAsObject(runtime, "Object");
812
+ auto defineProperty =
813
+ objectCtor.getPropertyAsFunction(runtime, "defineProperty");
814
+
815
+ jsi::Object descriptor(runtime);
816
+ descriptor.setProperty(runtime, "get", getterFunc);
817
+ descriptor.setProperty(runtime, "enumerable", true);
818
+ descriptor.setProperty(runtime, "configurable", true);
819
+
820
+ defineProperty.call(runtime, prototype,
821
+ jsi::String::createFromUtf8(runtime, name), descriptor);
822
+ }
823
+
760
824
  // Helper to call a method that takes the calling jsi::Runtime as its first
761
825
  // parameter, with JSI argument conversion for the rest and JSI conversion of
762
826
  // the result.
@@ -22,6 +22,8 @@
22
22
  #include "GPUError.h"
23
23
  #include "GPUExternalTexture.h"
24
24
  #include "GPUInternalError.h"
25
+ #include "GPUNativeBufferExternalTexture.h"
26
+ #include "GPUNativeBufferTexture.h"
25
27
  #include "GPUOutOfMemoryError.h"
26
28
  #include "GPUPipelineLayout.h"
27
29
  #include "GPUQuerySet.h"
@@ -85,43 +87,7 @@ RNWebGPUManager::RNWebGPUManager(
85
87
  RNWebGPU::create(*_jsRuntime, rnWebGPU));
86
88
 
87
89
  // Install constructors for instanceof support
88
- GPU::installConstructor(*_jsRuntime);
89
- GPUAdapter::installConstructor(*_jsRuntime);
90
- GPUAdapterInfo::installConstructor(*_jsRuntime);
91
- GPUBindGroup::installConstructor(*_jsRuntime);
92
- GPUBindGroupLayout::installConstructor(*_jsRuntime);
93
- GPUBuffer::installConstructor(*_jsRuntime);
94
- GPUCanvasContext::installConstructor(*_jsRuntime);
95
- GPUCommandBuffer::installConstructor(*_jsRuntime);
96
- GPUCommandEncoder::installConstructor(*_jsRuntime);
97
- GPUCompilationInfo::installConstructor(*_jsRuntime);
98
- GPUCompilationMessage::installConstructor(*_jsRuntime);
99
- GPUComputePassEncoder::installConstructor(*_jsRuntime);
100
- GPUComputePipeline::installConstructor(*_jsRuntime);
101
- GPUDevice::installConstructor(*_jsRuntime);
102
- GPUDeviceLostInfo::installConstructor(*_jsRuntime);
103
- GPUError::installConstructor(*_jsRuntime);
104
- GPUExternalTexture::installConstructor(*_jsRuntime);
105
- GPUInternalError::installConstructor(*_jsRuntime);
106
- GPUOutOfMemoryError::installConstructor(*_jsRuntime);
107
- GPUValidationError::installConstructor(*_jsRuntime);
108
- GPUUncapturedErrorEvent::installConstructor(*_jsRuntime);
109
- GPUPipelineLayout::installConstructor(*_jsRuntime);
110
- GPUQuerySet::installConstructor(*_jsRuntime);
111
- GPUQueue::installConstructor(*_jsRuntime);
112
- GPURenderBundle::installConstructor(*_jsRuntime);
113
- GPURenderBundleEncoder::installConstructor(*_jsRuntime);
114
- GPURenderPassEncoder::installConstructor(*_jsRuntime);
115
- GPURenderPipeline::installConstructor(*_jsRuntime);
116
- GPUSampler::installConstructor(*_jsRuntime);
117
- GPUSharedFence::installConstructor(*_jsRuntime);
118
- GPUSharedTextureMemory::installConstructor(*_jsRuntime);
119
- GPUShaderModule::installConstructor(*_jsRuntime);
120
- GPUSupportedLimits::installConstructor(*_jsRuntime);
121
- GPUTexture::installConstructor(*_jsRuntime);
122
- GPUTextureView::installConstructor(*_jsRuntime);
123
- VideoFrame::installConstructor(*_jsRuntime);
124
- VideoPlayer::installConstructor(*_jsRuntime);
90
+ installConstructors(*_jsRuntime);
125
91
 
126
92
  // Install constant objects as plain JS objects with own properties
127
93
  _jsRuntime->global().setProperty(*_jsRuntime, "GPUBufferUsage",
@@ -140,14 +106,58 @@ RNWebGPUManager::RNWebGPUManager(
140
106
  installWebGPUWorkletHelpers(*_jsRuntime);
141
107
  }
142
108
 
109
+ void RNWebGPUManager::installConstructors(jsi::Runtime &runtime) {
110
+ GPU::installConstructor(runtime);
111
+ GPUAdapter::installConstructor(runtime);
112
+ GPUAdapterInfo::installConstructor(runtime);
113
+ GPUBindGroup::installConstructor(runtime);
114
+ GPUBindGroupLayout::installConstructor(runtime);
115
+ GPUBuffer::installConstructor(runtime);
116
+ GPUCanvasContext::installConstructor(runtime);
117
+ GPUCommandBuffer::installConstructor(runtime);
118
+ GPUCommandEncoder::installConstructor(runtime);
119
+ GPUCompilationInfo::installConstructor(runtime);
120
+ GPUCompilationMessage::installConstructor(runtime);
121
+ GPUComputePassEncoder::installConstructor(runtime);
122
+ GPUComputePipeline::installConstructor(runtime);
123
+ GPUDevice::installConstructor(runtime);
124
+ GPUDeviceLostInfo::installConstructor(runtime);
125
+ GPUError::installConstructor(runtime);
126
+ GPUExternalTexture::installConstructor(runtime);
127
+ GPUNativeBufferExternalTexture::installConstructor(runtime);
128
+ GPUNativeBufferTexture::installConstructor(runtime);
129
+ GPUInternalError::installConstructor(runtime);
130
+ GPUOutOfMemoryError::installConstructor(runtime);
131
+ GPUValidationError::installConstructor(runtime);
132
+ GPUUncapturedErrorEvent::installConstructor(runtime);
133
+ GPUPipelineLayout::installConstructor(runtime);
134
+ GPUQuerySet::installConstructor(runtime);
135
+ GPUQueue::installConstructor(runtime);
136
+ GPURenderBundle::installConstructor(runtime);
137
+ GPURenderBundleEncoder::installConstructor(runtime);
138
+ GPURenderPassEncoder::installConstructor(runtime);
139
+ GPURenderPipeline::installConstructor(runtime);
140
+ GPUSampler::installConstructor(runtime);
141
+ GPUSharedFence::installConstructor(runtime);
142
+ GPUSharedTextureMemory::installConstructor(runtime);
143
+ GPUShaderModule::installConstructor(runtime);
144
+ GPUSupportedLimits::installConstructor(runtime);
145
+ GPUTexture::installConstructor(runtime);
146
+ GPUTextureView::installConstructor(runtime);
147
+ VideoFrame::installConstructor(runtime);
148
+ VideoPlayer::installConstructor(runtime);
149
+ }
150
+
143
151
  void RNWebGPUManager::installWebGPUWorkletHelpers(jsi::Runtime &runtime) {
144
- // The serializer worklets capture this object by closure; worklets passes a
145
- // HostObject to every runtime by reference, so installing it here, on the
146
- // main runtime, is enough (see WebGPUWorkletHelpers).
152
+ // The serializer worklets and installWebGPU() capture this object by
153
+ // closure; worklets passes a HostObject to every runtime by reference, so
154
+ // installing it here, on the main runtime, is enough (see
155
+ // WebGPUWorkletHelpers).
147
156
  runtime.global().setProperty(
148
157
  runtime, "__webgpuWorkletHelpers",
149
158
  jsi::Object::createFromHostObject(
150
- runtime, std::make_shared<WebGPUWorkletHelpers>()));
159
+ runtime, std::make_shared<WebGPUWorkletHelpers>(
160
+ &RNWebGPUManager::installConstructors)));
151
161
  }
152
162
 
153
163
  void RNWebGPUManager::flushPendingSurfaceTransition(
@@ -35,6 +35,16 @@ public:
35
35
  */
36
36
  static void installWebGPUWorkletHelpers(jsi::Runtime &runtime);
37
37
 
38
+ /**
39
+ * Installs the constructor of every WebGPU API class on `runtime` (see
40
+ * NativeObject::installConstructor), skipping the ones already there. Runs
41
+ * on the main runtime at startup and, through
42
+ * __webgpuWorkletHelpers.installConstructors(), on every runtime that calls
43
+ * installWebGPU(). RNWebGPU itself is not part of it: that global is the
44
+ * module instance, main runtime only.
45
+ */
46
+ static void installConstructors(jsi::Runtime &runtime);
47
+
38
48
  /**
39
49
  * Applies a surface attach latched by the platform UI thread (see
40
50
  * SurfaceInfo::applyPendingAttach) from the JS thread. Surface attaches are
@@ -59,7 +59,7 @@ struct Size {
59
59
  using NativeSurfaceReleaser = std::function<void(void *)>;
60
60
 
61
61
  #if defined(__ANDROID__)
62
- // --- AHB-pool presentation mode (WebGPUHardwareBufferView)
62
+ // --- AHB-pool presentation mode (WebGPUNativeBufferView)
63
63
  // -----------------------------
64
64
  //
65
65
  // A third presentation backend (besides the on-screen wgpu::Surface swapchain
@@ -71,7 +71,7 @@ using NativeSurfaceReleaser = std::function<void(void *)>;
71
71
  // like the swapchain, so the canvas texture always matches the app's other
72
72
  // attachments (e.g. its depth texture).
73
73
 
74
- #define RNWGPU_LOG_TAG "WebGPUHardwareBufferView"
74
+ #define RNWGPU_LOG_TAG "WebGPUNativeBufferView"
75
75
  // Failure / anomaly reporting only (never per-frame).
76
76
  #define RNWGPU_POOL_WARN(...) \
77
77
  __android_log_print(ANDROID_LOG_WARN, RNWGPU_LOG_TAG, __VA_ARGS__)
@@ -435,7 +435,7 @@ public:
435
435
  bool hasNativeSurface() {
436
436
  std::shared_lock<std::shared_mutex> lock(_mutex);
437
437
  #if defined(__ANDROID__)
438
- // A WebGPUHardwareBufferView in pool mode owns presentation the same way a
438
+ // A WebGPUNativeBufferView in pool mode owns presentation the same way a
439
439
  // surface-backed view does, and retires the entry on its own teardown.
440
440
  if (_poolMode.load()) {
441
441
  return true;
@@ -725,7 +725,7 @@ private:
725
725
  {
726
726
  std::unique_lock<std::shared_mutex> lock(_mutex);
727
727
  #if defined(__ANDROID__)
728
- // Leaving pool mode (the WebGPUHardwareBufferView detached): drop the
728
+ // Leaving pool mode (the WebGPUNativeBufferView detached): drop the
729
729
  // pool. A configured context keeps rendering into the offscreen
730
730
  // fallback, exactly like the surface path.
731
731
  if (_poolMode.load()) {