@shopify/react-native-skia 2.5.2 → 2.5.4

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 (121) hide show
  1. package/android/CMakeLists.txt +11 -0
  2. package/android/cpp/jni/JniWebGPUView.cpp +67 -0
  3. package/android/cpp/rnskia-android/SkiaPlatformContext.h +26 -0
  4. package/android/src/main/java/com/shopify/reactnative/skia/RNSkiaPackage.java +4 -1
  5. package/android/src/main/java/com/shopify/reactnative/skia/WebGPUSurfaceView.java +41 -0
  6. package/android/src/main/java/com/shopify/reactnative/skia/WebGPUTextureView.java +44 -0
  7. package/android/src/main/java/com/shopify/reactnative/skia/WebGPUView.java +95 -0
  8. package/android/src/main/java/com/shopify/reactnative/skia/WebGPUViewAPI.java +14 -0
  9. package/android/src/main/java/com/shopify/reactnative/skia/WebGPUViewManager.java +58 -0
  10. package/apple/RNSkUIKit.h +13 -0
  11. package/apple/SkiaPlatformContext.h +20 -0
  12. package/apple/SkiaPlatformContext.mm +21 -0
  13. package/apple/WebGPUMetalView.h +12 -0
  14. package/apple/WebGPUMetalView.mm +93 -0
  15. package/apple/WebGPUView.h +20 -0
  16. package/apple/WebGPUView.mm +77 -0
  17. package/cpp/jsi2/JSIConverter.h +11 -0
  18. package/cpp/rnskia/RNDawnContext.h +2 -2
  19. package/cpp/rnskia/RNDawnWindowContext.h +3 -0
  20. package/cpp/rnskia/RNSkManager.cpp +11 -4
  21. package/cpp/rnwgpu/Canvas.h +50 -0
  22. package/cpp/rnwgpu/PlatformContext.h +18 -0
  23. package/cpp/rnwgpu/SurfaceRegistry.h +229 -0
  24. package/cpp/rnwgpu/api/GPU.cpp +12 -0
  25. package/cpp/rnwgpu/api/GPUAdapter.cpp +26 -0
  26. package/cpp/rnwgpu/api/GPUCanvasContext.cpp +64 -0
  27. package/cpp/rnwgpu/api/GPUCanvasContext.h +65 -0
  28. package/cpp/rnwgpu/api/GPUDevice.cpp +52 -0
  29. package/cpp/rnwgpu/api/GPUDevice.h +62 -1
  30. package/cpp/rnwgpu/api/GPUQueue.cpp +1 -1
  31. package/cpp/rnwgpu/api/GPUUncapturedErrorEvent.h +61 -0
  32. package/cpp/rnwgpu/api/RNWebGPU.h +62 -0
  33. package/cpp/rnwgpu/api/descriptors/GPUBindGroupEntry.h +4 -0
  34. package/cpp/rnwgpu/api/descriptors/GPUCanvasConfiguration.h +76 -0
  35. package/lib/commonjs/external/reanimated/useVideo.js +1 -4
  36. package/lib/commonjs/external/reanimated/useVideo.js.map +1 -1
  37. package/lib/commonjs/mock/index.js +1 -0
  38. package/lib/commonjs/mock/index.js.map +1 -1
  39. package/lib/commonjs/skia/types/Surface/SurfaceFactory.js.map +1 -1
  40. package/lib/commonjs/sksg/Container.native.js +4 -0
  41. package/lib/commonjs/sksg/Container.native.js.map +1 -1
  42. package/lib/commonjs/sksg/Container.web.js +4 -0
  43. package/lib/commonjs/sksg/Container.web.js.map +1 -1
  44. package/lib/commonjs/specs/WebGPUViewNativeComponent.d.ts +8 -0
  45. package/lib/commonjs/specs/WebGPUViewNativeComponent.js +11 -0
  46. package/lib/commonjs/specs/WebGPUViewNativeComponent.js.map +1 -0
  47. package/lib/commonjs/specs/WebGPUViewNativeComponent.web.d.ts +8 -0
  48. package/lib/commonjs/specs/WebGPUViewNativeComponent.web.js +101 -0
  49. package/lib/commonjs/specs/WebGPUViewNativeComponent.web.js.map +1 -0
  50. package/lib/commonjs/specs/utils.d.ts +1 -0
  51. package/lib/commonjs/specs/utils.js +11 -0
  52. package/lib/commonjs/specs/utils.js.map +1 -0
  53. package/lib/commonjs/views/WebGPUCanvas.d.ts +32 -0
  54. package/lib/commonjs/views/WebGPUCanvas.js +66 -0
  55. package/lib/commonjs/views/WebGPUCanvas.js.map +1 -0
  56. package/lib/commonjs/views/WebGPUCanvas.web.d.ts +23 -0
  57. package/lib/commonjs/views/WebGPUCanvas.web.js +20 -0
  58. package/lib/commonjs/views/WebGPUCanvas.web.js.map +1 -0
  59. package/lib/commonjs/views/index.d.ts +1 -0
  60. package/lib/commonjs/views/index.js +11 -0
  61. package/lib/commonjs/views/index.js.map +1 -1
  62. package/lib/module/external/reanimated/useVideo.js +1 -4
  63. package/lib/module/external/reanimated/useVideo.js.map +1 -1
  64. package/lib/module/mock/index.js +1 -0
  65. package/lib/module/mock/index.js.map +1 -1
  66. package/lib/module/skia/types/Surface/SurfaceFactory.js.map +1 -1
  67. package/lib/module/sksg/Container.native.js +5 -0
  68. package/lib/module/sksg/Container.native.js.map +1 -1
  69. package/lib/module/sksg/Container.web.js +5 -0
  70. package/lib/module/sksg/Container.web.js.map +1 -1
  71. package/lib/module/specs/WebGPUViewNativeComponent.d.ts +8 -0
  72. package/lib/module/specs/WebGPUViewNativeComponent.js +4 -0
  73. package/lib/module/specs/WebGPUViewNativeComponent.js.map +1 -0
  74. package/lib/module/specs/WebGPUViewNativeComponent.web.d.ts +8 -0
  75. package/lib/module/specs/WebGPUViewNativeComponent.web.js +94 -0
  76. package/lib/module/specs/WebGPUViewNativeComponent.web.js.map +1 -0
  77. package/lib/module/specs/utils.d.ts +1 -0
  78. package/lib/module/specs/utils.js +5 -0
  79. package/lib/module/specs/utils.js.map +1 -0
  80. package/lib/module/views/WebGPUCanvas.d.ts +32 -0
  81. package/lib/module/views/WebGPUCanvas.js +57 -0
  82. package/lib/module/views/WebGPUCanvas.js.map +1 -0
  83. package/lib/module/views/WebGPUCanvas.web.d.ts +23 -0
  84. package/lib/module/views/WebGPUCanvas.web.js +12 -0
  85. package/lib/module/views/WebGPUCanvas.web.js.map +1 -0
  86. package/lib/module/views/index.d.ts +1 -0
  87. package/lib/module/views/index.js +1 -0
  88. package/lib/module/views/index.js.map +1 -1
  89. package/lib/typescript/lib/commonjs/mock/index.d.ts +1 -0
  90. package/lib/typescript/lib/commonjs/specs/WebGPUViewNativeComponent.d.ts +3 -0
  91. package/lib/typescript/lib/commonjs/specs/WebGPUViewNativeComponent.web.d.ts +3 -0
  92. package/lib/typescript/lib/commonjs/specs/utils.d.ts +2 -0
  93. package/lib/typescript/lib/commonjs/views/WebGPUCanvas.d.ts +6 -0
  94. package/lib/typescript/lib/commonjs/views/WebGPUCanvas.web.d.ts +6 -0
  95. package/lib/typescript/lib/module/mock/index.d.ts +3 -1
  96. package/lib/typescript/lib/module/specs/WebGPUViewNativeComponent.d.ts +2 -0
  97. package/lib/typescript/lib/module/specs/WebGPUViewNativeComponent.web.d.ts +2 -0
  98. package/lib/typescript/lib/module/specs/utils.d.ts +1 -0
  99. package/lib/typescript/lib/module/views/WebGPUCanvas.d.ts +7 -0
  100. package/lib/typescript/lib/module/views/WebGPUCanvas.web.d.ts +8 -0
  101. package/lib/typescript/lib/module/views/index.d.ts +1 -0
  102. package/lib/typescript/src/specs/WebGPUViewNativeComponent.d.ts +8 -0
  103. package/lib/typescript/src/specs/WebGPUViewNativeComponent.web.d.ts +8 -0
  104. package/lib/typescript/src/specs/utils.d.ts +1 -0
  105. package/lib/typescript/src/views/WebGPUCanvas.d.ts +32 -0
  106. package/lib/typescript/src/views/WebGPUCanvas.web.d.ts +23 -0
  107. package/lib/typescript/src/views/index.d.ts +1 -0
  108. package/package.json +3 -2
  109. package/react-native-skia.podspec +3 -0
  110. package/scripts/install-libs.js +24 -32
  111. package/src/external/reanimated/useVideo.ts +1 -4
  112. package/src/mock/index.ts +1 -0
  113. package/src/skia/types/Surface/SurfaceFactory.ts +5 -1
  114. package/src/sksg/Container.native.ts +3 -0
  115. package/src/sksg/Container.web.ts +3 -0
  116. package/src/specs/WebGPUViewNativeComponent.ts +11 -0
  117. package/src/specs/WebGPUViewNativeComponent.web.ts +108 -0
  118. package/src/specs/utils.ts +4 -0
  119. package/src/views/WebGPUCanvas.tsx +109 -0
  120. package/src/views/WebGPUCanvas.web.tsx +36 -0
  121. package/src/views/index.ts +1 -0
@@ -297,11 +297,11 @@ public:
297
297
  // 1. Create Surface
298
298
  wgpu::SurfaceDescriptor surfaceDescriptor;
299
299
  #ifdef __APPLE__
300
- wgpu::SurfaceDescriptorFromMetalLayer metalSurfaceDesc;
300
+ wgpu::SurfaceSourceMetalLayer metalSurfaceDesc;
301
301
  metalSurfaceDesc.layer = window;
302
302
  surfaceDescriptor.nextInChain = &metalSurfaceDesc;
303
303
  #else
304
- wgpu::SurfaceDescriptorFromAndroidNativeWindow androidSurfaceDesc;
304
+ wgpu::SurfaceSourceAndroidNativeWindow androidSurfaceDesc;
305
305
  androidSurfaceDesc.window = window;
306
306
  surfaceDescriptor.nextInChain = &androidSurfaceDesc;
307
307
  #endif
@@ -34,6 +34,9 @@ public:
34
34
  wgpu::SurfaceTexture surfaceTexture;
35
35
  _surface.GetCurrentTexture(&surfaceTexture);
36
36
  auto texture = surfaceTexture.texture;
37
+ if (!texture) {
38
+ return nullptr;
39
+ }
37
40
  skgpu::graphite::DawnTextureInfo info(
38
41
  /*sampleCount=*/1, skgpu::Mipmapped::kNo,
39
42
  DawnUtils::PreferredTextureFormat, texture.GetUsage(),
@@ -14,6 +14,8 @@
14
14
  #ifdef SK_GRAPHITE
15
15
  #include "RNDawnContext.h"
16
16
  #include "rnwgpu/api/GPU.h"
17
+ #include "rnwgpu/api/GPUUncapturedErrorEvent.h"
18
+ #include "rnwgpu/api/RNWebGPU.h"
17
19
  #include "rnwgpu/api/descriptors/GPUBufferUsage.h"
18
20
  #include "rnwgpu/api/descriptors/GPUColorWrite.h"
19
21
  #include "rnwgpu/api/descriptors/GPUMapMode.h"
@@ -73,8 +75,9 @@ void RNSkManager::installBindings() {
73
75
  jsi::Object::createFromHostObject(*_jsRuntime, _viewApi));
74
76
 
75
77
  #ifdef SK_GRAPHITE
76
- // Install WebGPU GPU constructor
78
+ // Install WebGPU constructors
77
79
  rnwgpu::GPU::installConstructor(*_jsRuntime);
80
+ rnwgpu::GPUUncapturedErrorEvent::installConstructor(*_jsRuntime);
78
81
  // Create and expose navigator.gpu using DawnContext's instance
79
82
  auto &dawnContext = DawnContext::getInstance();
80
83
  auto gpu =
@@ -103,9 +106,13 @@ void RNSkManager::installBindings() {
103
106
  rnwgpu::GPUMapMode::create(*_jsRuntime));
104
107
  _jsRuntime->global().setProperty(*_jsRuntime, "GPUShaderStage",
105
108
  rnwgpu::GPUShaderStage::create(*_jsRuntime));
106
- _jsRuntime->global().setProperty(
107
- *_jsRuntime, "GPUTextureUsage",
108
- rnwgpu::GPUTextureUsage::create(*_jsRuntime));
109
+ _jsRuntime->global().setProperty(*_jsRuntime, "GPUTextureUsage",
110
+ rnwgpu::GPUTextureUsage::create(*_jsRuntime));
111
+
112
+ // Install RNWebGPU global object for WebGPU Canvas support
113
+ auto rnWebGPU = std::make_shared<rnwgpu::RNWebGPU>(gpu, nullptr);
114
+ _jsRuntime->global().setProperty(*_jsRuntime, "RNWebGPU",
115
+ rnwgpu::RNWebGPU::create(*_jsRuntime, rnWebGPU));
109
116
  #endif
110
117
  }
111
118
  } // namespace RNSkia
@@ -0,0 +1,50 @@
1
+ #pragma once
2
+
3
+ #include <memory>
4
+
5
+ #include "jsi2/NativeObject.h"
6
+
7
+ namespace rnwgpu {
8
+
9
+ namespace jsi = facebook::jsi;
10
+
11
+ class Canvas : public NativeObject<Canvas> {
12
+ public:
13
+ static constexpr const char *CLASS_NAME = "Canvas";
14
+
15
+ Canvas(void *nativeSurface, int width, int height)
16
+ : NativeObject(CLASS_NAME), _nativeSurface(nativeSurface), _width(width),
17
+ _height(height), _clientWidth(width), _clientHeight(height) {}
18
+
19
+ void *getNativeSurface() { return _nativeSurface; }
20
+
21
+ int getWidth() { return _width; }
22
+ int getHeight() { return _height; }
23
+
24
+ void setWidth(int width) { _width = width; }
25
+ void setHeight(int height) { _height = height; }
26
+
27
+ int getClientWidth() { return _clientWidth; }
28
+ int getClientHeight() { return _clientHeight; }
29
+
30
+ void setClientWidth(int width) { _clientWidth = width; }
31
+ void setClientHeight(int height) { _clientHeight = height; }
32
+
33
+ static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) {
34
+ installGetterSetter(runtime, prototype, "width", &Canvas::getWidth,
35
+ &Canvas::setWidth);
36
+ installGetterSetter(runtime, prototype, "height", &Canvas::getHeight,
37
+ &Canvas::setHeight);
38
+ installGetter(runtime, prototype, "clientWidth", &Canvas::getClientWidth);
39
+ installGetter(runtime, prototype, "clientHeight", &Canvas::getClientHeight);
40
+ }
41
+
42
+ private:
43
+ void *_nativeSurface;
44
+ int _width;
45
+ int _height;
46
+ int _clientWidth;
47
+ int _clientHeight;
48
+ };
49
+
50
+ } // namespace rnwgpu
@@ -0,0 +1,18 @@
1
+ #pragma once
2
+
3
+ #include <memory>
4
+
5
+ #include "webgpu/webgpu_cpp.h"
6
+
7
+ namespace rnwgpu {
8
+
9
+ class PlatformContext {
10
+ public:
11
+ PlatformContext() = default;
12
+ virtual ~PlatformContext() = default;
13
+
14
+ virtual wgpu::Surface makeSurface(wgpu::Instance instance, void *surface,
15
+ int width, int height) = 0;
16
+ };
17
+
18
+ } // namespace rnwgpu
@@ -0,0 +1,229 @@
1
+ #pragma once
2
+
3
+ #include <memory>
4
+ #include <shared_mutex>
5
+ #include <unordered_map>
6
+ #include <utility>
7
+
8
+ #include "webgpu/webgpu_cpp.h"
9
+
10
+ namespace rnwgpu {
11
+
12
+ struct NativeInfo {
13
+ void *nativeSurface;
14
+ int width;
15
+ int height;
16
+ };
17
+
18
+ struct Size {
19
+ int width;
20
+ int height;
21
+ };
22
+
23
+ class SurfaceInfo {
24
+ public:
25
+ SurfaceInfo(wgpu::Instance gpu, int width, int height)
26
+ : gpu(std::move(gpu)), width(width), height(height) {}
27
+
28
+ ~SurfaceInfo() { surface = nullptr; }
29
+
30
+ void reconfigure(int newWidth, int newHeight) {
31
+ std::unique_lock<std::shared_mutex> lock(_mutex);
32
+ config.width = newWidth;
33
+ config.height = newHeight;
34
+ _configure();
35
+ }
36
+
37
+ void configure(wgpu::SurfaceConfiguration &newConfig) {
38
+ std::unique_lock<std::shared_mutex> lock(_mutex);
39
+ config = newConfig;
40
+ config.width = width;
41
+ config.height = height;
42
+ config.presentMode = wgpu::PresentMode::Fifo;
43
+ _configure();
44
+ }
45
+
46
+ void unconfigure() {
47
+ std::unique_lock<std::shared_mutex> lock(_mutex);
48
+ if (surface) {
49
+ surface.Unconfigure();
50
+ } else {
51
+ texture = nullptr;
52
+ }
53
+ }
54
+
55
+ void *switchToOffscreen() {
56
+ std::unique_lock<std::shared_mutex> lock(_mutex);
57
+ // We only do this if the onscreen surface is configured.
58
+ auto isConfigured = config.device != nullptr;
59
+ if (isConfigured) {
60
+ wgpu::TextureDescriptor textureDesc;
61
+ textureDesc.usage = wgpu::TextureUsage::RenderAttachment |
62
+ wgpu::TextureUsage::CopySrc |
63
+ wgpu::TextureUsage::TextureBinding;
64
+ textureDesc.format = config.format;
65
+ textureDesc.size.width = config.width;
66
+ textureDesc.size.height = config.height;
67
+ texture = config.device.CreateTexture(&textureDesc);
68
+ }
69
+ surface = nullptr;
70
+ return nativeSurface;
71
+ }
72
+
73
+ void switchToOnscreen(void *newNativeSurface, wgpu::Surface newSurface) {
74
+ std::unique_lock<std::shared_mutex> lock(_mutex);
75
+ nativeSurface = newNativeSurface;
76
+ surface = std::move(newSurface);
77
+ // If we are comming from an offscreen context, we need to configure the new
78
+ // surface
79
+ if (texture != nullptr) {
80
+ config.usage = config.usage | wgpu::TextureUsage::CopyDst;
81
+ _configure();
82
+ // We flush the offscreen texture to the onscreen one
83
+ wgpu::CommandEncoderDescriptor encoderDesc;
84
+ auto device = config.device;
85
+ wgpu::CommandEncoder encoder = device.CreateCommandEncoder(&encoderDesc);
86
+
87
+ wgpu::TexelCopyTextureInfo sourceTexture = {};
88
+ sourceTexture.texture = texture;
89
+
90
+ wgpu::TexelCopyTextureInfo destinationTexture = {};
91
+ wgpu::SurfaceTexture surfaceTexture;
92
+ surface.GetCurrentTexture(&surfaceTexture);
93
+ destinationTexture.texture = surfaceTexture.texture;
94
+
95
+ wgpu::Extent3D size = {sourceTexture.texture.GetWidth(),
96
+ sourceTexture.texture.GetHeight(),
97
+ sourceTexture.texture.GetDepthOrArrayLayers()};
98
+
99
+ encoder.CopyTextureToTexture(&sourceTexture, &destinationTexture, &size);
100
+
101
+ wgpu::CommandBuffer commands = encoder.Finish();
102
+ wgpu::Queue queue = device.GetQueue();
103
+ queue.Submit(1, &commands);
104
+ surface.Present();
105
+ texture = nullptr;
106
+ }
107
+ }
108
+
109
+ void resize(int newWidth, int newHeight) {
110
+ std::unique_lock<std::shared_mutex> lock(_mutex);
111
+ width = newWidth;
112
+ height = newHeight;
113
+ }
114
+
115
+ void present() {
116
+ std::unique_lock<std::shared_mutex> lock(_mutex);
117
+ if (surface) {
118
+ surface.Present();
119
+ }
120
+ }
121
+
122
+ wgpu::Texture getCurrentTexture() {
123
+ std::shared_lock<std::shared_mutex> lock(_mutex);
124
+ if (surface) {
125
+ wgpu::SurfaceTexture surfaceTexture;
126
+ surface.GetCurrentTexture(&surfaceTexture);
127
+ return surfaceTexture.texture;
128
+ } else {
129
+ return texture;
130
+ }
131
+ }
132
+
133
+ NativeInfo getNativeInfo() {
134
+ std::shared_lock<std::shared_mutex> lock(_mutex);
135
+ return {.nativeSurface = nativeSurface, .width = width, .height = height};
136
+ }
137
+
138
+ Size getSize() {
139
+ std::shared_lock<std::shared_mutex> lock(_mutex);
140
+ return {.width = width, .height = height};
141
+ }
142
+
143
+ wgpu::SurfaceConfiguration getConfig() {
144
+ std::shared_lock<std::shared_mutex> lock(_mutex);
145
+ return config;
146
+ }
147
+
148
+ wgpu::Device getDevice() {
149
+ std::shared_lock<std::shared_mutex> lock(_mutex);
150
+ return config.device;
151
+ }
152
+
153
+ private:
154
+ void _configure() {
155
+ if (surface) {
156
+ surface.Configure(&config);
157
+ } else {
158
+ wgpu::TextureDescriptor textureDesc;
159
+ textureDesc.format = config.format;
160
+ textureDesc.size.width = config.width;
161
+ textureDesc.size.height = config.height;
162
+ textureDesc.usage = wgpu::TextureUsage::RenderAttachment |
163
+ wgpu::TextureUsage::CopySrc |
164
+ wgpu::TextureUsage::TextureBinding;
165
+ texture = config.device.CreateTexture(&textureDesc);
166
+ }
167
+ }
168
+
169
+ mutable std::shared_mutex _mutex;
170
+ void *nativeSurface = nullptr;
171
+ wgpu::Surface surface = nullptr;
172
+ wgpu::Texture texture = nullptr;
173
+ wgpu::Instance gpu;
174
+ wgpu::SurfaceConfiguration config;
175
+ int width;
176
+ int height;
177
+ };
178
+
179
+ class SurfaceRegistry {
180
+ public:
181
+ static SurfaceRegistry &getInstance() {
182
+ static SurfaceRegistry instance;
183
+ return instance;
184
+ }
185
+
186
+ SurfaceRegistry(const SurfaceRegistry &) = delete;
187
+ SurfaceRegistry &operator=(const SurfaceRegistry &) = delete;
188
+
189
+ std::shared_ptr<SurfaceInfo> getSurfaceInfo(int id) {
190
+ std::shared_lock<std::shared_mutex> lock(_mutex);
191
+ auto it = _registry.find(id);
192
+ if (it != _registry.end()) {
193
+ return it->second;
194
+ }
195
+ return nullptr;
196
+ }
197
+
198
+ void removeSurfaceInfo(int id) {
199
+ std::unique_lock<std::shared_mutex> lock(_mutex);
200
+ _registry.erase(id);
201
+ }
202
+
203
+ std::shared_ptr<SurfaceInfo> addSurfaceInfo(int id, wgpu::Instance gpu,
204
+ int width, int height) {
205
+ std::unique_lock<std::shared_mutex> lock(_mutex);
206
+ auto info = std::make_shared<SurfaceInfo>(gpu, width, height);
207
+ _registry[id] = info;
208
+ return info;
209
+ }
210
+
211
+ std::shared_ptr<SurfaceInfo>
212
+ getSurfaceInfoOrCreate(int id, wgpu::Instance gpu, int width, int height) {
213
+ std::unique_lock<std::shared_mutex> lock(_mutex);
214
+ auto it = _registry.find(id);
215
+ if (it != _registry.end()) {
216
+ return it->second;
217
+ }
218
+ auto info = std::make_shared<SurfaceInfo>(gpu, width, height);
219
+ _registry[id] = info;
220
+ return info;
221
+ }
222
+
223
+ private:
224
+ SurfaceRegistry() = default;
225
+ mutable std::shared_mutex _mutex;
226
+ std::unordered_map<int, std::shared_ptr<SurfaceInfo>> _registry;
227
+ };
228
+
229
+ } // namespace rnwgpu
@@ -88,6 +88,18 @@ std::unordered_set<std::string> GPU::getWgslLanguageFeatures() {
88
88
  case wgpu::WGSLLanguageFeatureName::PointerCompositeAccess:
89
89
  name = "pointer_composite_access";
90
90
  break;
91
+ case wgpu::WGSLLanguageFeatureName::UniformBufferStandardLayout:
92
+ name = "uniform_buffer_standard_layout";
93
+ break;
94
+ case wgpu::WGSLLanguageFeatureName::SubgroupId:
95
+ name = "subgroup_id";
96
+ break;
97
+ case wgpu::WGSLLanguageFeatureName::FragmentDepth:
98
+ name = "fragment_depth";
99
+ break;
100
+ case wgpu::WGSLLanguageFeatureName::ImmediateAddressSpace:
101
+ name = "immediate_address_space";
102
+ break;
91
103
  case wgpu::WGSLLanguageFeatureName::ChromiumTestingUnimplemented:
92
104
  name = "chromium_testing_unimplemented";
93
105
  break;
@@ -10,6 +10,9 @@
10
10
  #include "Convertors.h"
11
11
 
12
12
  #include "GPUFeatures.h"
13
+ #include "GPUInternalError.h"
14
+ #include "GPUOutOfMemoryError.h"
15
+ #include "GPUValidationError.h"
13
16
  #include "jsi2/JSIConverter.h"
14
17
 
15
18
  namespace rnwgpu {
@@ -73,6 +76,29 @@ async::AsyncTaskHandle GPUAdapter::requestDevice(
73
76
  std::string(message.data, message.length)
74
77
  : "no message";
75
78
  fprintf(stderr, "%s", fullMessage.c_str());
79
+
80
+ // Look up the GPUDevice from the registry and notify it
81
+ auto *gpuDevice = GPUDeviceRegistry::getInstance().getDevice(device.Get());
82
+ if (gpuDevice != nullptr) {
83
+ std::string messageStr =
84
+ message.length > 0 ? std::string(message.data, message.length) : "";
85
+
86
+ GPUErrorVariant error;
87
+ switch (type) {
88
+ case wgpu::ErrorType::Validation:
89
+ error = std::make_shared<GPUValidationError>(messageStr);
90
+ break;
91
+ case wgpu::ErrorType::OutOfMemory:
92
+ error = std::make_shared<GPUOutOfMemoryError>(messageStr);
93
+ break;
94
+ case wgpu::ErrorType::Internal:
95
+ case wgpu::ErrorType::Unknown:
96
+ default:
97
+ error = std::make_shared<GPUInternalError>(messageStr);
98
+ break;
99
+ }
100
+ gpuDevice->notifyUncapturedError(std::move(error));
101
+ }
76
102
  });
77
103
  std::string label =
78
104
  descriptor.has_value() ? descriptor.value()->label.value_or("") : "";
@@ -0,0 +1,64 @@
1
+ #include "GPUCanvasContext.h"
2
+ #include "Convertors.h"
3
+ #include <memory>
4
+
5
+ #ifdef __APPLE__
6
+ namespace dawn::native::metal {
7
+
8
+ void WaitForCommandsToBeScheduled(WGPUDevice device);
9
+
10
+ }
11
+ #endif
12
+
13
+ namespace rnwgpu {
14
+
15
+ void GPUCanvasContext::configure(
16
+ std::shared_ptr<GPUCanvasConfiguration> configuration) {
17
+ Convertor conv;
18
+ wgpu::SurfaceConfiguration surfaceConfiguration;
19
+ surfaceConfiguration.device = configuration->device->get();
20
+ if (configuration->viewFormats.has_value()) {
21
+ if (!conv(surfaceConfiguration.viewFormats,
22
+ surfaceConfiguration.viewFormatCount,
23
+ configuration->viewFormats.value())) {
24
+ throw std::runtime_error("Error with SurfaceConfiguration");
25
+ }
26
+ }
27
+ if (!conv(surfaceConfiguration.usage, configuration->usage) ||
28
+ !conv(surfaceConfiguration.format, configuration->format)) {
29
+ throw std::runtime_error("Error with SurfaceConfiguration");
30
+ }
31
+
32
+ #ifdef __APPLE__
33
+ surfaceConfiguration.alphaMode = configuration->alphaMode;
34
+ #endif
35
+ surfaceConfiguration.presentMode = wgpu::PresentMode::Fifo;
36
+ _surfaceInfo->configure(surfaceConfiguration);
37
+ }
38
+
39
+ void GPUCanvasContext::unconfigure() {}
40
+
41
+ std::shared_ptr<GPUTexture> GPUCanvasContext::getCurrentTexture() {
42
+ auto prevSize = _surfaceInfo->getConfig();
43
+ auto width = _canvas->getWidth();
44
+ auto height = _canvas->getHeight();
45
+ auto sizeHasChanged = prevSize.width != width || prevSize.height != height;
46
+ if (sizeHasChanged) {
47
+ _surfaceInfo->reconfigure(width, height);
48
+ }
49
+ auto texture = _surfaceInfo->getCurrentTexture();
50
+ return std::make_shared<GPUTexture>(texture, "");
51
+ }
52
+
53
+ void GPUCanvasContext::present() {
54
+ #ifdef __APPLE__
55
+ dawn::native::metal::WaitForCommandsToBeScheduled(
56
+ _surfaceInfo->getDevice().Get());
57
+ #endif
58
+ auto size = _surfaceInfo->getSize();
59
+ _canvas->setClientWidth(size.width);
60
+ _canvas->setClientHeight(size.height);
61
+ _surfaceInfo->present();
62
+ }
63
+
64
+ } // namespace rnwgpu
@@ -0,0 +1,65 @@
1
+ #pragma once
2
+
3
+ #include <memory>
4
+ #include <string>
5
+ #include <utility>
6
+
7
+ #include "descriptors/Unions.h"
8
+
9
+ #include "webgpu/webgpu_cpp.h"
10
+
11
+ #include "jsi2/NativeObject.h"
12
+
13
+ #include "rnwgpu/Canvas.h"
14
+ #include "GPU.h"
15
+ #include "descriptors/GPUCanvasConfiguration.h"
16
+ #include "GPUTexture.h"
17
+ #include "rnwgpu/SurfaceRegistry.h"
18
+
19
+ namespace rnwgpu {
20
+
21
+ namespace jsi = facebook::jsi;
22
+
23
+ class GPUCanvasContext : public NativeObject<GPUCanvasContext> {
24
+ public:
25
+ static constexpr const char *CLASS_NAME = "GPUCanvasContext";
26
+
27
+ GPUCanvasContext(std::shared_ptr<GPU> gpu, int contextId, int width,
28
+ int height)
29
+ : NativeObject(CLASS_NAME), _gpu(std::move(gpu)) {
30
+ _canvas = std::make_shared<Canvas>(nullptr, width, height);
31
+ auto &registry = rnwgpu::SurfaceRegistry::getInstance();
32
+ _surfaceInfo =
33
+ registry.getSurfaceInfoOrCreate(contextId, _gpu->get(), width, height);
34
+ }
35
+
36
+ public:
37
+ std::string getBrand() { return CLASS_NAME; }
38
+
39
+ std::shared_ptr<Canvas> getCanvas() { return _canvas; }
40
+
41
+ static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) {
42
+ installGetter(runtime, prototype, "__brand", &GPUCanvasContext::getBrand);
43
+ installGetter(runtime, prototype, "canvas", &GPUCanvasContext::getCanvas);
44
+ installMethod(runtime, prototype, "configure",
45
+ &GPUCanvasContext::configure);
46
+ installMethod(runtime, prototype, "unconfigure",
47
+ &GPUCanvasContext::unconfigure);
48
+ installMethod(runtime, prototype, "getCurrentTexture",
49
+ &GPUCanvasContext::getCurrentTexture);
50
+ installMethod(runtime, prototype, "present", &GPUCanvasContext::present);
51
+ }
52
+
53
+ inline const wgpu::Surface get() { return nullptr; }
54
+ void configure(std::shared_ptr<GPUCanvasConfiguration> configuration);
55
+ void unconfigure();
56
+ std::shared_ptr<GPUTexture> getCurrentTexture();
57
+ void present();
58
+
59
+ private:
60
+ std::shared_ptr<Canvas> _canvas;
61
+ std::shared_ptr<SurfaceInfo> _surfaceInfo;
62
+ std::shared_ptr<GPU> _gpu;
63
+ };
64
+
65
+ } // namespace rnwgpu
@@ -431,4 +431,56 @@ async::AsyncTaskHandle GPUDevice::getLost() {
431
431
  _lostHandle = handle;
432
432
  return handle;
433
433
  }
434
+ void GPUDevice::addEventListener(std::string type, jsi::Function callback) {
435
+ std::lock_guard<std::mutex> lock(_listenersMutex);
436
+ auto sharedCallback = std::make_shared<jsi::Function>(std::move(callback));
437
+ _eventListeners[type].push_back(sharedCallback);
438
+ }
439
+
440
+ void GPUDevice::removeEventListener(std::string type, jsi::Function callback) {
441
+ std::lock_guard<std::mutex> lock(_listenersMutex);
442
+ auto it = _eventListeners.find(type);
443
+ if (it != _eventListeners.end()) {
444
+ auto &listeners = it->second;
445
+ // Remove the last listener of this type (simple approach since we can't
446
+ // easily compare jsi::Function objects)
447
+ if (!listeners.empty()) {
448
+ listeners.pop_back();
449
+ }
450
+ }
451
+ }
452
+
453
+ void GPUDevice::notifyUncapturedError(GPUErrorVariant error) {
454
+ auto runtime = getCreationRuntime();
455
+ if (runtime == nullptr) {
456
+ return;
457
+ }
458
+
459
+ std::vector<std::shared_ptr<jsi::Function>> listeners;
460
+ {
461
+ std::lock_guard<std::mutex> lock(_listenersMutex);
462
+ auto it = _eventListeners.find("uncapturederror");
463
+ if (it != _eventListeners.end()) {
464
+ listeners = it->second;
465
+ }
466
+ }
467
+
468
+ if (listeners.empty()) {
469
+ return;
470
+ }
471
+
472
+ // Create the event object
473
+ auto event = std::make_shared<GPUUncapturedErrorEvent>(std::move(error));
474
+ auto eventValue = GPUUncapturedErrorEvent::create(*runtime, event);
475
+
476
+ // Call all listeners
477
+ for (const auto &listener : listeners) {
478
+ try {
479
+ listener->call(*runtime, eventValue);
480
+ } catch (const std::exception &e) {
481
+ fprintf(stderr, "Error in uncapturederror listener: %s\n", e.what());
482
+ }
483
+ }
484
+ }
485
+
434
486
  } // namespace rnwgpu