react-native-webgpu 0.14.2 → 0.15.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 (108) hide show
  1. package/android/cpp/AndroidColorSpace.h +107 -0
  2. package/android/cpp/AndroidPlatformContext.h +100 -9
  3. package/android/cpp/AndroidVideoPlayer.h +46 -1
  4. package/android/cpp/cpp-adapter.cpp +53 -1
  5. package/android/src/main/java/com/webgpu/SyncFences.java +88 -0
  6. package/android/src/main/java/com/webgpu/ViewSnapshot.java +66 -23
  7. package/android/src/main/java/com/webgpu/WebGPUModule.java +69 -5
  8. package/android/src/main/java/com/webgpu/WebGPUVideoPlayer.java +109 -0
  9. package/apple/ApplePlatformContext.h +5 -5
  10. package/apple/ApplePlatformContext.mm +301 -90
  11. package/apple/AppleVideoPlayer.mm +68 -35
  12. package/cpp/dawn/common/ExternalTextureParams.h +67 -0
  13. package/cpp/rnwgpu/PlatformContext.h +71 -16
  14. package/cpp/rnwgpu/api/GPUAdapter.cpp +35 -0
  15. package/cpp/rnwgpu/api/GPUExternalTexture.cpp +172 -156
  16. package/cpp/rnwgpu/api/GPUExternalTexture.h +2 -19
  17. package/cpp/rnwgpu/api/GPUQueue.cpp +101 -3
  18. package/cpp/rnwgpu/api/RNWebGPU.h +9 -3
  19. package/cpp/rnwgpu/api/VideoFrameBlit.h +39 -24
  20. package/cpp/rnwgpu/api/descriptors/GPUDrawElementImageSource.h +7 -0
  21. package/cpp/rnwgpu/api/descriptors/GPUExternalTextureDescriptor.h +10 -3
  22. package/lib/commonjs/Canvas.js +32 -5
  23. package/lib/commonjs/Canvas.js.map +1 -1
  24. package/lib/commonjs/WebPolyfillGPUModule.js +6 -3
  25. package/lib/commonjs/WebPolyfillGPUModule.js.map +1 -1
  26. package/lib/commonjs/constants.js +6 -3
  27. package/lib/commonjs/constants.js.map +1 -1
  28. package/lib/commonjs/index.js +1 -0
  29. package/lib/commonjs/index.js.map +1 -1
  30. package/lib/commonjs/install.js +9 -22
  31. package/lib/commonjs/install.js.map +1 -1
  32. package/lib/commonjs/main/index.js +8 -7
  33. package/lib/commonjs/main/index.js.map +1 -1
  34. package/lib/commonjs/main/index.web.js +1 -1
  35. package/lib/commonjs/main/installNative.js +20 -0
  36. package/lib/commonjs/main/installNative.js.map +1 -0
  37. package/lib/commonjs/main/installNative.web.js +4 -0
  38. package/lib/commonjs/main/installNative.web.js.map +1 -0
  39. package/lib/commonjs/mock.js +60 -13
  40. package/lib/commonjs/mock.js.map +1 -1
  41. package/lib/module/Canvas.js +33 -6
  42. package/lib/module/Canvas.js.map +1 -1
  43. package/lib/module/WebPolyfillGPUModule.js +6 -3
  44. package/lib/module/WebPolyfillGPUModule.js.map +1 -1
  45. package/lib/module/constants.js +6 -3
  46. package/lib/module/constants.js.map +1 -1
  47. package/lib/module/index.js +8 -1
  48. package/lib/module/index.js.map +1 -1
  49. package/lib/module/install.js +8 -20
  50. package/lib/module/install.js.map +1 -1
  51. package/lib/module/main/index.js +6 -7
  52. package/lib/module/main/index.js.map +1 -1
  53. package/lib/module/main/index.web.js +1 -1
  54. package/lib/module/main/index.web.js.map +1 -1
  55. package/lib/module/main/installNative.js +18 -0
  56. package/lib/module/main/installNative.js.map +1 -0
  57. package/lib/module/main/installNative.web.js +6 -0
  58. package/lib/module/main/installNative.web.js.map +1 -0
  59. package/lib/module/mock.js +55 -1
  60. package/lib/module/mock.js.map +1 -1
  61. package/lib/typescript/lib/commonjs/Canvas.d.ts.map +1 -1
  62. package/lib/typescript/lib/commonjs/install.d.ts +41 -3
  63. package/lib/typescript/lib/commonjs/install.d.ts.map +1 -1
  64. package/lib/typescript/lib/commonjs/main/installNative.d.ts +2 -0
  65. package/lib/typescript/lib/commonjs/main/installNative.d.ts.map +1 -0
  66. package/lib/typescript/lib/commonjs/main/installNative.web.d.ts +2 -0
  67. package/lib/typescript/lib/commonjs/main/installNative.web.d.ts.map +1 -0
  68. package/lib/typescript/lib/commonjs/mock.d.ts +39 -0
  69. package/lib/typescript/lib/commonjs/mock.d.ts.map +1 -1
  70. package/lib/typescript/lib/module/Canvas.d.ts.map +1 -1
  71. package/lib/typescript/lib/module/install.d.ts +0 -1
  72. package/lib/typescript/lib/module/install.d.ts.map +1 -1
  73. package/lib/typescript/lib/module/main/installNative.d.ts +2 -0
  74. package/lib/typescript/lib/module/main/installNative.d.ts.map +1 -0
  75. package/lib/typescript/lib/module/main/installNative.web.d.ts +2 -0
  76. package/lib/typescript/lib/module/main/installNative.web.d.ts.map +1 -0
  77. package/lib/typescript/lib/module/mock.d.ts +39 -1
  78. package/lib/typescript/lib/module/mock.d.ts.map +1 -1
  79. package/lib/typescript/src/Canvas.d.ts.map +1 -1
  80. package/lib/typescript/src/constants.d.ts.map +1 -1
  81. package/lib/typescript/src/index.d.ts +2 -2
  82. package/lib/typescript/src/index.d.ts.map +1 -1
  83. package/lib/typescript/src/install.d.ts +0 -5
  84. package/lib/typescript/src/install.d.ts.map +1 -1
  85. package/lib/typescript/src/main/index.d.ts +1 -0
  86. package/lib/typescript/src/main/index.d.ts.map +1 -1
  87. package/lib/typescript/src/main/index.web.d.ts +1 -1
  88. package/lib/typescript/src/main/index.web.d.ts.map +1 -1
  89. package/lib/typescript/src/main/installNative.d.ts +2 -0
  90. package/lib/typescript/src/main/installNative.d.ts.map +1 -0
  91. package/lib/typescript/src/main/installNative.web.d.ts +2 -0
  92. package/lib/typescript/src/main/installNative.web.d.ts.map +1 -0
  93. package/lib/typescript/src/mock.d.ts +5 -1
  94. package/lib/typescript/src/mock.d.ts.map +1 -1
  95. package/lib/typescript/src/types.d.ts +1 -0
  96. package/lib/typescript/src/types.d.ts.map +1 -1
  97. package/package.json +1 -1
  98. package/src/Canvas.tsx +44 -28
  99. package/src/WebPolyfillGPUModule.ts +3 -1
  100. package/src/constants.ts +6 -3
  101. package/src/index.tsx +18 -10
  102. package/src/install.ts +9 -18
  103. package/src/main/index.tsx +7 -10
  104. package/src/main/index.web.tsx +1 -1
  105. package/src/main/installNative.ts +20 -0
  106. package/src/main/installNative.web.ts +5 -0
  107. package/src/mock.ts +60 -1
  108. package/src/types.ts +6 -0
@@ -0,0 +1,67 @@
1
+ // Copyright 2026 The Dawn & Tint Authors
2
+ //
3
+ // Redistribution and use in source and binary forms, with or without
4
+ // modification, are permitted provided that the following conditions are met:
5
+ //
6
+ // 1. Redistributions of source code must retain the above copyright notice, this
7
+ // list of conditions and the following disclaimer.
8
+ //
9
+ // 2. Redistributions in binary form must reproduce the above copyright notice,
10
+ // this list of conditions and the following disclaimer in the documentation
11
+ // and/or other materials provided with the distribution.
12
+ //
13
+ // 3. Neither the name of the copyright holder nor the names of its
14
+ // contributors may be used to endorse or promote products derived from
15
+ // this software without specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21
+ // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
+ // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23
+ // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24
+ // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25
+ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
+ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+
28
+ // DAWN_VENDORED_EXTERNAL_TEXTURE_PARAMS
29
+ //
30
+ // Vendored from Dawn's src/dawn/common/ExternalTextureParams.h, unchanged. The
31
+ // functions it declares are compiled into the Dawn binaries that
32
+ // react-native-webgpu-dawn ships (libwebgpu_dawn.so, libwebgpu_dawn.a), which
33
+ // export them, but the package only ships Dawn's public headers. The copy is
34
+ // pinned to the Dawn commit of the package in scripts/check-dawn.ts: on a Dawn
35
+ // bump, diff it against the new commit's file and re-sync it.
36
+
37
+ #ifndef SRC_DAWN_COMMON_EXTERNALTEXTUREPARAMS_H_
38
+ #define SRC_DAWN_COMMON_EXTERNALTEXTUREPARAMS_H_
39
+
40
+ #include <webgpu/webgpu_cpp.h>
41
+
42
+ #include <array>
43
+
44
+ namespace dawn {
45
+
46
+ // Color space parameters that can be passed to an ExternalTexture.
47
+ struct ExternalTextureColorSpaceParams {
48
+ // Stored row-major to save uniform buffer space. (so one full row after another)
49
+ // TODO(https://crbug.com/496604550): That's an implementation detail that should not be exposed
50
+ // in the API, Dawn can transpose internally.
51
+ std::array<float, 12> yuvToRgbConversionMatrix{};
52
+ std::array<float, 7> srcTransferFunction = {};
53
+ std::array<float, 7> dstTransferFunction = {}; // Really the inverse transfer function.
54
+ // Stored column major to match WGSL. (so one full column after another)
55
+ std::array<float, 9> gamutConversionMatrix{};
56
+ };
57
+
58
+ // Helper function to make parameters for an ExternalTextureDescriptor
59
+ wgpu::Status ComputeExternalTextureParams(const wgpu::ColorSpaceDawn& srcColorSpace,
60
+ wgpu::PredefinedColorSpace dstColorSpace,
61
+ ExternalTextureColorSpaceParams* out);
62
+
63
+ ExternalTextureColorSpaceParams GetNoopColorSpaceParams();
64
+
65
+ } // namespace dawn
66
+
67
+ #endif // SRC_DAWN_COMMON_EXTERNALTEXTUREPARAMS_H_
@@ -3,6 +3,7 @@
3
3
  #include <functional>
4
4
  #include <memory>
5
5
  #include <mutex>
6
+ #include <optional>
6
7
  #include <span>
7
8
  #include <string>
8
9
  #include <utility>
@@ -36,6 +37,20 @@ enum class VideoPixelFormat {
36
37
  NV12,
37
38
  };
38
39
 
40
+ // The color space of a YUV frame, as its producer reports it: the YCbCr matrix
41
+ // and range that encode the samples, and the primaries and transfer function of
42
+ // the RGB they encode. Each member is optional: what the producer does not know
43
+ // (a camera buffer carries no color metadata, a container may record only some
44
+ // of it) is resolved at import time (GPUExternalTexture::Create) from the
45
+ // buffer and the platform's norm. Dawn converts the samples to RGB in the
46
+ // destination color space while sampling the external texture.
47
+ struct VideoFrameColorSpace {
48
+ std::optional<wgpu::ColorSpacePrimariesDawn> primaries;
49
+ std::optional<wgpu::ColorSpaceTransferDawn> transfer;
50
+ std::optional<wgpu::ColorSpaceYCbCrRangeDawn> range;
51
+ std::optional<wgpu::ColorSpaceYCbCrMatrixDawn> matrix;
52
+ };
53
+
39
54
  // A native handle to a video frame that can be imported into a
40
55
  // GPUSharedTextureMemory.
41
56
  //
@@ -50,14 +65,33 @@ struct VideoFrameHandle {
50
65
  uint32_t width = 0;
51
66
  uint32_t height = 0;
52
67
  VideoPixelFormat pixelFormat = VideoPixelFormat::BGRA8;
53
- // 3x4 row-major matrix mapping [Y, U, V, 1] → linear [R, G, B]. Pre-computed
54
- // at decode time from CVPixelBuffer attachments (kCVImageBufferYCbCrMatrixKey
55
- // + range), with a BT.709 limited-range default. Only meaningful when
56
- // pixelFormat == NV12.
57
- float yuvToRgbMatrix[12] = {};
68
+ // The color space of the samples. Only meaningful when pixelFormat == NV12:
69
+ // from the CVPixelBuffer attachments on Apple platforms, from the Image's
70
+ // data space (API 33) or the container's color info on Android.
71
+ VideoFrameColorSpace colorSpace;
72
+ // Android: the acquire fence of the frame as a sync file descriptor, or -1.
73
+ // The producer (video decoder, camera) may still be writing the buffer when
74
+ // the consumer gets it; the GPU work that reads the frame waits on this fence
75
+ // (imported as a shared-fence-sync-fd into BeginAccess). Owned by the handle:
76
+ // the deleter closes it. Importing it into Dawn duplicates it, so the frame
77
+ // can be imported more than once.
78
+ int acquireFenceFd = -1;
58
79
  std::function<void()> deleter;
59
80
  };
60
81
 
82
+ // The samples of the NV12 test frame of createTestVideoFrame: pure red and
83
+ // pure green in BT.709 limited range (Y 16..235, Cb/Cr 16..240), so the frame
84
+ // converts back to exactly those colors in sRGB. Shared by both platforms so
85
+ // the e2e spec sees the same frame on each.
86
+ namespace test_yuv_frame {
87
+ constexpr uint8_t kRedY = 63;
88
+ constexpr uint8_t kRedCb = 102;
89
+ constexpr uint8_t kRedCr = 240;
90
+ constexpr uint8_t kGreenY = 173;
91
+ constexpr uint8_t kGreenCb = 42;
92
+ constexpr uint8_t kGreenCr = 26;
93
+ } // namespace test_yuv_frame
94
+
61
95
  // Platform-implemented video source that hands out fresh IOSurface /
62
96
  // AHardwareBuffer-backed frames as a video plays, with the playback controls
63
97
  // of an HTMLMediaElement (times in seconds).
@@ -110,6 +144,16 @@ struct ViewSnapshotRequest {
110
144
  double sourceHeight = 0;
111
145
  uint32_t width = 0;
112
146
  uint32_t height = 0;
147
+ // Whether the caller can draw a GPU frame (a VideoFrameHandle) into the
148
+ // destination itself. A platform that renders the view into a GPU buffer
149
+ // then hands that buffer over instead of reading the pixels back.
150
+ bool allowFrame = false;
151
+ // iOS: whether to flush pending layout and layer changes before drawing
152
+ // (drawViewHierarchyInRect's afterScreenUpdates), so a snapshot taken right
153
+ // after a state change reflects it; false draws the last committed frame
154
+ // without that round trip. Android renders the views' current display
155
+ // lists either way.
156
+ bool afterScreenUpdates = true;
113
157
  };
114
158
 
115
159
  class PlatformContext {
@@ -129,17 +173,24 @@ public:
129
173
  return currentSlot();
130
174
  }
131
175
 
132
- // Rasterize a native view into CPU pixels (see ViewSnapshotRequest). The
133
- // implementation hops to the platform UI thread, so this is asynchronous:
134
- // exactly one of onSuccess / onError is invoked, from an arbitrary thread
176
+ // Rasterize a native view (see ViewSnapshotRequest). The implementation hops
177
+ // to the platform UI thread, so this is asynchronous: exactly one of
178
+ // onPixels / onFrame / onError is invoked, from an arbitrary thread
135
179
  // (typically the UI thread). Callers must not touch JSI in the callbacks.
136
180
  //
137
- // The returned ImageData is tightly packed (no row padding), 4 bytes per
138
- // pixel, `format` is rgba8unorm or bgra8unorm depending on what the platform
139
- // rasterizer produces natively, and `premultiplied` reports its alpha
140
- // representation.
181
+ // onPixels receives the view as CPU pixels: tightly packed (no row
182
+ // padding), 4 bytes per pixel, `format` rgba8unorm or bgra8unorm depending
183
+ // on what the platform rasterizer produces natively, and `premultiplied`
184
+ // reporting its alpha representation.
185
+ //
186
+ // onFrame, only when the request allows it, receives the GPU buffer the
187
+ // platform rendered the view into (Android 13 and above: the
188
+ // HardwareRenderer's AHardwareBuffer, with the fence that signals when the
189
+ // drawing is done), as an RGBA frame of premultiplied pixels. The receiver
190
+ // owns the frame and releases it through its deleter.
141
191
  virtual void snapshotView(const ViewSnapshotRequest &request,
142
- std::function<void(ImageData)> onSuccess,
192
+ std::function<void(ImageData)> onPixels,
193
+ std::function<void(VideoFrameHandle)> onFrame,
143
194
  std::function<void(std::string)> onError) = 0;
144
195
 
145
196
  virtual ImageData createImageBitmap(std::string blobId, double offset,
@@ -167,9 +218,13 @@ public:
167
218
 
168
219
  // Create a synthetic, GPU-shareable IOSurface/AHardwareBuffer filled with a
169
220
  // generated test pattern. Avoids the need to bundle a video asset for the
170
- // SharedTextureMemory example.
171
- virtual VideoFrameHandle createTestVideoFrame(uint32_t width,
172
- uint32_t height) = 0;
221
+ // SharedTextureMemory example. BGRA8 is an RGB gradient; NV12 is a biplanar
222
+ // YUV frame, BT.709 limited range, red on the left half and green on the
223
+ // right, which exercises the color conversion of importExternalTexture.
224
+ // Throws a message containing "unsupported" where the platform cannot
225
+ // allocate or fill the YUV layout (Android before API 29).
226
+ virtual VideoFrameHandle createTestVideoFrame(uint32_t width, uint32_t height,
227
+ VideoPixelFormat format) = 0;
173
228
 
174
229
  // Open a video file at `path` for playback. The returned player yields
175
230
  // IOSurface / AHardwareBuffer-backed frames via copyLatestFrame().
@@ -12,6 +12,9 @@
12
12
  #ifdef __APPLE__
13
13
  #include <TargetConditionals.h>
14
14
  #endif
15
+ #ifdef __ANDROID__
16
+ #include <android/log.h>
17
+ #endif
15
18
 
16
19
  #include "Convertors.h"
17
20
 
@@ -158,7 +161,14 @@ async::AsyncTaskHandle GPUAdapter::requestDevice(
158
161
  message.length > 0 ? std::string(message.data, message.length) : "";
159
162
  std::string fullMessage =
160
163
  msg.length() > 0 ? std::string(errorType) + ": " + msg : "no message";
164
+ #ifdef __ANDROID__
165
+ // stderr goes nowhere in an Android app; logcat is where the message can
166
+ // be read (and where CI collects it).
167
+ __android_log_print(ANDROID_LOG_ERROR, "WebGPU", "Uncaptured error: %s",
168
+ fullMessage.c_str());
169
+ #else
161
170
  fprintf(stderr, "%s\n", fullMessage.c_str());
171
+ #endif
162
172
 
163
173
  // Look up the GPUDevice from the registry and notify it
164
174
  if (auto gpuDevice = GPUDevice::lookupDevice(device.Get())) {
@@ -224,6 +234,31 @@ async::AsyncTaskHandle GPUAdapter::requestDevice(
224
234
  disabledToggles.push_back(name);
225
235
  }
226
236
  }
237
+ #endif
238
+ #if defined(__ANDROID__)
239
+ // Dawn checks the memory a VkImage needs for an imported
240
+ // AHardwareBuffer against the allocation size the driver reports for
241
+ // the buffer, and some drivers report it wrong: Dawn itself skips the
242
+ // check on Samsung, Qualcomm and Huawei drivers
243
+ // (https://crbug.com/333424893). The emulator (gfxstream) reports 0
244
+ // for the buffers HWUI draws into, which rejects every view snapshot
245
+ // and SurfaceControl import there, so skip it on all of Android unless
246
+ // the caller disables the toggle. Dawn drops unknown toggle names, so a
247
+ // build without this toggle is unaffected.
248
+ static const char *const kAndroidEnabledToggles[] = {
249
+ "ignore_imported_ahardwarebuffer_vulkan_image_size"};
250
+ for (const char *name : kAndroidEnabledToggles) {
251
+ const auto named = [name](const char *t) {
252
+ return std::strcmp(t, name) == 0;
253
+ };
254
+ const bool explicitlyDisabled = std::any_of(
255
+ disabledToggles.begin(), disabledToggles.end(), named);
256
+ const bool alreadyEnabled =
257
+ std::any_of(enabledToggles.begin(), enabledToggles.end(), named);
258
+ if (!explicitlyDisabled && !alreadyEnabled) {
259
+ enabledToggles.push_back(name);
260
+ }
261
+ }
227
262
  #endif
228
263
  if (!enabledToggles.empty() || !disabledToggles.empty()) {
229
264
  toggles.enabledToggleCount = enabledToggles.size();