@shopify/react-native-skia 2.5.1 → 2.5.3
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.
- package/android/CMakeLists.txt +8 -6
- package/android/build.gradle +5 -32
- package/android/cpp/jni/JniWebGPUView.cpp +67 -0
- package/android/cpp/rnskia-android/OpenGLContext.h +9 -2
- package/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h +6 -3
- package/android/cpp/rnskia-android/SkiaPlatformContext.h +26 -0
- package/android/src/main/java/com/shopify/reactnative/skia/RNSkiaPackage.java +4 -1
- package/android/src/main/java/com/shopify/reactnative/skia/WebGPUSurfaceView.java +41 -0
- package/android/src/main/java/com/shopify/reactnative/skia/WebGPUTextureView.java +44 -0
- package/android/src/main/java/com/shopify/reactnative/skia/WebGPUView.java +95 -0
- package/android/src/main/java/com/shopify/reactnative/skia/WebGPUViewAPI.java +14 -0
- package/android/src/main/java/com/shopify/reactnative/skia/WebGPUViewManager.java +58 -0
- package/apple/MetalContext.h +10 -2
- package/apple/MetalWindowContext.h +1 -0
- package/apple/MetalWindowContext.mm +8 -1
- package/apple/RNSkApplePlatformContext.h +2 -1
- package/apple/RNSkApplePlatformContext.mm +6 -4
- package/apple/RNSkUIKit.h +13 -0
- package/apple/SkiaPictureView.mm +3 -0
- package/apple/SkiaPlatformContext.h +20 -0
- package/apple/SkiaPlatformContext.mm +21 -0
- package/apple/WebGPUMetalView.h +12 -0
- package/apple/WebGPUMetalView.mm +93 -0
- package/apple/WebGPUView.h +20 -0
- package/apple/WebGPUView.mm +77 -0
- package/cpp/api/JsiSkImage.h +76 -0
- package/cpp/api/JsiSkSurfaceFactory.h +12 -1
- package/cpp/jsi2/JSIConverter.h +11 -0
- package/cpp/rnskia/RNDawnContext.h +24 -16
- package/cpp/rnskia/RNDawnUtils.h +12 -0
- package/cpp/rnskia/RNSkManager.cpp +11 -4
- package/cpp/rnskia/RNSkPlatformContext.h +3 -1
- package/cpp/rnwgpu/Canvas.h +45 -0
- package/cpp/rnwgpu/PlatformContext.h +18 -0
- package/cpp/rnwgpu/SurfaceRegistry.h +229 -0
- package/cpp/rnwgpu/api/GPUAdapter.cpp +26 -0
- package/cpp/rnwgpu/api/GPUCanvasContext.cpp +64 -0
- package/cpp/rnwgpu/api/GPUCanvasContext.h +65 -0
- package/cpp/rnwgpu/api/GPUDevice.cpp +52 -0
- package/cpp/rnwgpu/api/GPUDevice.h +62 -1
- package/cpp/rnwgpu/api/GPUUncapturedErrorEvent.h +61 -0
- package/cpp/rnwgpu/api/RNWebGPU.h +62 -0
- package/cpp/rnwgpu/api/descriptors/GPUBindGroupEntry.h +4 -0
- package/cpp/rnwgpu/api/descriptors/GPUCanvasConfiguration.h +76 -0
- package/lib/commonjs/external/reanimated/useVideo.js +1 -4
- package/lib/commonjs/external/reanimated/useVideo.js.map +1 -1
- package/lib/commonjs/mock/index.js +1 -0
- package/lib/commonjs/mock/index.js.map +1 -1
- package/lib/commonjs/skia/types/Surface/SurfaceFactory.d.ts +10 -1
- package/lib/commonjs/skia/types/Surface/SurfaceFactory.js +5 -0
- package/lib/commonjs/skia/types/Surface/SurfaceFactory.js.map +1 -1
- package/lib/commonjs/sksg/Container.native.js +4 -0
- package/lib/commonjs/sksg/Container.native.js.map +1 -1
- package/lib/commonjs/sksg/Container.web.js +4 -0
- package/lib/commonjs/sksg/Container.web.js.map +1 -1
- package/lib/commonjs/specs/WebGPUViewNativeComponent.d.ts +8 -0
- package/lib/commonjs/specs/WebGPUViewNativeComponent.js +11 -0
- package/lib/commonjs/specs/WebGPUViewNativeComponent.js.map +1 -0
- package/lib/commonjs/specs/WebGPUViewNativeComponent.web.d.ts +8 -0
- package/lib/commonjs/specs/WebGPUViewNativeComponent.web.js +101 -0
- package/lib/commonjs/specs/WebGPUViewNativeComponent.web.js.map +1 -0
- package/lib/commonjs/specs/utils.d.ts +1 -0
- package/lib/commonjs/specs/utils.js +11 -0
- package/lib/commonjs/specs/utils.js.map +1 -0
- package/lib/commonjs/views/WebGPUCanvas.d.ts +32 -0
- package/lib/commonjs/views/WebGPUCanvas.js +66 -0
- package/lib/commonjs/views/WebGPUCanvas.js.map +1 -0
- package/lib/commonjs/views/WebGPUCanvas.web.d.ts +23 -0
- package/lib/commonjs/views/WebGPUCanvas.web.js +20 -0
- package/lib/commonjs/views/WebGPUCanvas.web.js.map +1 -0
- package/lib/commonjs/views/index.d.ts +1 -0
- package/lib/commonjs/views/index.js +11 -0
- package/lib/commonjs/views/index.js.map +1 -1
- package/lib/module/external/reanimated/useVideo.js +1 -4
- package/lib/module/external/reanimated/useVideo.js.map +1 -1
- package/lib/module/mock/index.js +1 -0
- package/lib/module/mock/index.js.map +1 -1
- package/lib/module/skia/types/Surface/SurfaceFactory.d.ts +10 -1
- package/lib/module/skia/types/Surface/SurfaceFactory.js +4 -1
- package/lib/module/skia/types/Surface/SurfaceFactory.js.map +1 -1
- package/lib/module/sksg/Container.native.js +5 -0
- package/lib/module/sksg/Container.native.js.map +1 -1
- package/lib/module/sksg/Container.web.js +5 -0
- package/lib/module/sksg/Container.web.js.map +1 -1
- package/lib/module/specs/WebGPUViewNativeComponent.d.ts +8 -0
- package/lib/module/specs/WebGPUViewNativeComponent.js +4 -0
- package/lib/module/specs/WebGPUViewNativeComponent.js.map +1 -0
- package/lib/module/specs/WebGPUViewNativeComponent.web.d.ts +8 -0
- package/lib/module/specs/WebGPUViewNativeComponent.web.js +94 -0
- package/lib/module/specs/WebGPUViewNativeComponent.web.js.map +1 -0
- package/lib/module/specs/utils.d.ts +1 -0
- package/lib/module/specs/utils.js +5 -0
- package/lib/module/specs/utils.js.map +1 -0
- package/lib/module/views/WebGPUCanvas.d.ts +32 -0
- package/lib/module/views/WebGPUCanvas.js +57 -0
- package/lib/module/views/WebGPUCanvas.js.map +1 -0
- package/lib/module/views/WebGPUCanvas.web.d.ts +23 -0
- package/lib/module/views/WebGPUCanvas.web.js +12 -0
- package/lib/module/views/WebGPUCanvas.web.js.map +1 -0
- package/lib/module/views/index.d.ts +1 -0
- package/lib/module/views/index.js +1 -0
- package/lib/module/views/index.js.map +1 -1
- package/lib/typescript/lib/commonjs/mock/index.d.ts +1 -0
- package/lib/typescript/lib/commonjs/skia/types/Surface/SurfaceFactory.d.ts +4 -0
- package/lib/typescript/lib/commonjs/specs/WebGPUViewNativeComponent.d.ts +3 -0
- package/lib/typescript/lib/commonjs/specs/WebGPUViewNativeComponent.web.d.ts +3 -0
- package/lib/typescript/lib/commonjs/specs/utils.d.ts +2 -0
- package/lib/typescript/lib/commonjs/views/WebGPUCanvas.d.ts +6 -0
- package/lib/typescript/lib/commonjs/views/WebGPUCanvas.web.d.ts +6 -0
- package/lib/typescript/lib/module/mock/index.d.ts +7 -1
- package/lib/typescript/lib/module/skia/types/Surface/SurfaceFactory.d.ts +4 -1
- package/lib/typescript/lib/module/specs/WebGPUViewNativeComponent.d.ts +2 -0
- package/lib/typescript/lib/module/specs/WebGPUViewNativeComponent.web.d.ts +2 -0
- package/lib/typescript/lib/module/specs/utils.d.ts +1 -0
- package/lib/typescript/lib/module/views/WebGPUCanvas.d.ts +7 -0
- package/lib/typescript/lib/module/views/WebGPUCanvas.web.d.ts +8 -0
- package/lib/typescript/lib/module/views/index.d.ts +1 -0
- package/lib/typescript/src/skia/types/Surface/SurfaceFactory.d.ts +10 -1
- package/lib/typescript/src/specs/WebGPUViewNativeComponent.d.ts +8 -0
- package/lib/typescript/src/specs/WebGPUViewNativeComponent.web.d.ts +8 -0
- package/lib/typescript/src/specs/utils.d.ts +1 -0
- package/lib/typescript/src/views/WebGPUCanvas.d.ts +32 -0
- package/lib/typescript/src/views/WebGPUCanvas.web.d.ts +23 -0
- package/lib/typescript/src/views/index.d.ts +1 -0
- package/package.json +7 -3
- package/react-native-skia.podspec +16 -83
- package/scripts/install-libs.js +131 -0
- package/src/external/reanimated/useVideo.ts +1 -4
- package/src/mock/index.ts +1 -0
- package/src/skia/types/Surface/SurfaceFactory.ts +17 -1
- package/src/sksg/Container.native.ts +3 -0
- package/src/sksg/Container.web.ts +3 -0
- package/src/specs/WebGPUViewNativeComponent.ts +11 -0
- package/src/specs/WebGPUViewNativeComponent.web.ts +108 -0
- package/src/specs/utils.ts +4 -0
- package/src/views/WebGPUCanvas.tsx +109 -0
- package/src/views/WebGPUCanvas.web.tsx +36 -0
- package/src/views/index.ts +1 -0
|
@@ -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
|
|
@@ -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 ®istry = 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
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
+
#include <functional>
|
|
4
|
+
#include <map>
|
|
3
5
|
#include <memory>
|
|
6
|
+
#include <mutex>
|
|
4
7
|
#include <optional>
|
|
5
8
|
#include <string>
|
|
6
9
|
#include <unordered_set>
|
|
7
10
|
#include <utility>
|
|
8
11
|
#include <variant>
|
|
12
|
+
#include <vector>
|
|
9
13
|
|
|
10
14
|
#include "descriptors/Unions.h"
|
|
11
15
|
|
|
@@ -16,6 +20,8 @@
|
|
|
16
20
|
|
|
17
21
|
#include "webgpu/webgpu_cpp.h"
|
|
18
22
|
|
|
23
|
+
#include "GPUUncapturedErrorEvent.h"
|
|
24
|
+
|
|
19
25
|
#include "GPUBindGroup.h"
|
|
20
26
|
#include "GPUBindGroupLayout.h"
|
|
21
27
|
#include "GPUBuffer.h"
|
|
@@ -51,6 +57,39 @@ namespace rnwgpu {
|
|
|
51
57
|
|
|
52
58
|
namespace jsi = facebook::jsi;
|
|
53
59
|
|
|
60
|
+
// Forward declaration
|
|
61
|
+
class GPUDevice;
|
|
62
|
+
|
|
63
|
+
// Static registry to map wgpu::Device handles to GPUDevice instances
|
|
64
|
+
class GPUDeviceRegistry {
|
|
65
|
+
public:
|
|
66
|
+
static GPUDeviceRegistry &getInstance() {
|
|
67
|
+
static GPUDeviceRegistry instance;
|
|
68
|
+
return instance;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
void registerDevice(WGPUDevice handle, GPUDevice *device) {
|
|
72
|
+
std::lock_guard<std::mutex> lock(_mutex);
|
|
73
|
+
_devices[handle] = device;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
void unregisterDevice(WGPUDevice handle) {
|
|
77
|
+
std::lock_guard<std::mutex> lock(_mutex);
|
|
78
|
+
_devices.erase(handle);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
GPUDevice *getDevice(WGPUDevice handle) {
|
|
82
|
+
std::lock_guard<std::mutex> lock(_mutex);
|
|
83
|
+
auto it = _devices.find(handle);
|
|
84
|
+
return it != _devices.end() ? it->second : nullptr;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private:
|
|
88
|
+
GPUDeviceRegistry() = default;
|
|
89
|
+
std::mutex _mutex;
|
|
90
|
+
std::map<WGPUDevice, GPUDevice *> _devices;
|
|
91
|
+
};
|
|
92
|
+
|
|
54
93
|
class GPUDevice : public NativeObject<GPUDevice> {
|
|
55
94
|
public:
|
|
56
95
|
static constexpr const char *CLASS_NAME = "GPUDevice";
|
|
@@ -59,7 +98,15 @@ public:
|
|
|
59
98
|
std::shared_ptr<async::AsyncRunner> async,
|
|
60
99
|
std::string label)
|
|
61
100
|
: NativeObject(CLASS_NAME), _instance(instance), _async(async),
|
|
62
|
-
_label(label) {
|
|
101
|
+
_label(label) {
|
|
102
|
+
// Register this device in the global registry
|
|
103
|
+
GPUDeviceRegistry::getInstance().registerDevice(_instance.Get(), this);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
~GPUDevice() {
|
|
107
|
+
// Unregister from the global registry
|
|
108
|
+
GPUDeviceRegistry::getInstance().unregisterDevice(_instance.Get());
|
|
109
|
+
}
|
|
63
110
|
|
|
64
111
|
public:
|
|
65
112
|
std::string getBrand() { return CLASS_NAME; }
|
|
@@ -105,6 +152,11 @@ public:
|
|
|
105
152
|
void notifyDeviceLost(wgpu::DeviceLostReason reason, std::string message);
|
|
106
153
|
void forceLossForTesting();
|
|
107
154
|
|
|
155
|
+
// Event listener methods
|
|
156
|
+
void addEventListener(std::string type, jsi::Function callback);
|
|
157
|
+
void removeEventListener(std::string type, jsi::Function callback);
|
|
158
|
+
void notifyUncapturedError(GPUErrorVariant error);
|
|
159
|
+
|
|
108
160
|
std::string getLabel() { return _label; }
|
|
109
161
|
void setLabel(const std::string &label) {
|
|
110
162
|
_label = label;
|
|
@@ -155,6 +207,10 @@ public:
|
|
|
155
207
|
&GPUDevice::setLabel);
|
|
156
208
|
installMethod(runtime, prototype, "forceLossForTesting",
|
|
157
209
|
&GPUDevice::forceLossForTesting);
|
|
210
|
+
installMethod(runtime, prototype, "addEventListener",
|
|
211
|
+
&GPUDevice::addEventListener);
|
|
212
|
+
installMethod(runtime, prototype, "removeEventListener",
|
|
213
|
+
&GPUDevice::removeEventListener);
|
|
158
214
|
}
|
|
159
215
|
|
|
160
216
|
inline const wgpu::Device get() { return _instance; }
|
|
@@ -169,6 +225,11 @@ private:
|
|
|
169
225
|
std::shared_ptr<GPUDeviceLostInfo> _lostInfo;
|
|
170
226
|
bool _lostSettled = false;
|
|
171
227
|
std::optional<async::AsyncTaskHandle::ResolveFunction> _lostResolve;
|
|
228
|
+
|
|
229
|
+
// Event listeners storage
|
|
230
|
+
std::mutex _listenersMutex;
|
|
231
|
+
std::map<std::string, std::vector<std::shared_ptr<jsi::Function>>>
|
|
232
|
+
_eventListeners;
|
|
172
233
|
};
|
|
173
234
|
|
|
174
235
|
} // namespace rnwgpu
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <memory>
|
|
4
|
+
#include <string>
|
|
5
|
+
#include <variant>
|
|
6
|
+
|
|
7
|
+
#include "jsi2/NativeObject.h"
|
|
8
|
+
|
|
9
|
+
#include "GPUError.h"
|
|
10
|
+
#include "GPUInternalError.h"
|
|
11
|
+
#include "GPUOutOfMemoryError.h"
|
|
12
|
+
#include "GPUValidationError.h"
|
|
13
|
+
|
|
14
|
+
namespace rnwgpu {
|
|
15
|
+
|
|
16
|
+
namespace jsi = facebook::jsi;
|
|
17
|
+
|
|
18
|
+
using GPUErrorVariant =
|
|
19
|
+
std::variant<std::shared_ptr<GPUValidationError>,
|
|
20
|
+
std::shared_ptr<GPUOutOfMemoryError>,
|
|
21
|
+
std::shared_ptr<GPUInternalError>>;
|
|
22
|
+
|
|
23
|
+
class GPUUncapturedErrorEvent : public NativeObject<GPUUncapturedErrorEvent> {
|
|
24
|
+
public:
|
|
25
|
+
static constexpr const char *CLASS_NAME = "GPUUncapturedErrorEvent";
|
|
26
|
+
|
|
27
|
+
explicit GPUUncapturedErrorEvent(GPUErrorVariant error)
|
|
28
|
+
: NativeObject(CLASS_NAME), _error(std::move(error)) {}
|
|
29
|
+
|
|
30
|
+
GPUErrorVariant getError() { return _error; }
|
|
31
|
+
|
|
32
|
+
static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) {
|
|
33
|
+
installGetter(runtime, prototype, "error",
|
|
34
|
+
&GPUUncapturedErrorEvent::getError);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private:
|
|
38
|
+
GPUErrorVariant _error;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
} // namespace rnwgpu
|
|
42
|
+
|
|
43
|
+
namespace rnwgpu {
|
|
44
|
+
|
|
45
|
+
template <> struct JSIConverter<GPUErrorVariant> {
|
|
46
|
+
static jsi::Value toJSI(jsi::Runtime &runtime, GPUErrorVariant arg) {
|
|
47
|
+
return std::visit(
|
|
48
|
+
[&runtime](auto &&error) -> jsi::Value {
|
|
49
|
+
using T = std::decay_t<decltype(error)>;
|
|
50
|
+
return JSIConverter<T>::toJSI(runtime, error);
|
|
51
|
+
},
|
|
52
|
+
arg);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
static GPUErrorVariant fromJSI(jsi::Runtime &runtime, const jsi::Value &arg,
|
|
56
|
+
bool outOfBounds) {
|
|
57
|
+
throw std::runtime_error("GPUErrorVariant::fromJSI not implemented");
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
} // namespace rnwgpu
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <memory>
|
|
4
|
+
#include <string>
|
|
5
|
+
|
|
6
|
+
#include "jsi2/NativeObject.h"
|
|
7
|
+
|
|
8
|
+
#include "rnwgpu/Canvas.h"
|
|
9
|
+
#include "GPU.h"
|
|
10
|
+
#include "GPUCanvasContext.h"
|
|
11
|
+
#include "rnwgpu/PlatformContext.h"
|
|
12
|
+
|
|
13
|
+
namespace rnwgpu {
|
|
14
|
+
|
|
15
|
+
namespace jsi = facebook::jsi;
|
|
16
|
+
|
|
17
|
+
class RNWebGPU : public NativeObject<RNWebGPU> {
|
|
18
|
+
public:
|
|
19
|
+
static constexpr const char *CLASS_NAME = "RNWebGPU";
|
|
20
|
+
|
|
21
|
+
explicit RNWebGPU(std::shared_ptr<GPU> gpu,
|
|
22
|
+
std::shared_ptr<PlatformContext> platformContext)
|
|
23
|
+
: NativeObject(CLASS_NAME), _gpu(gpu), _platformContext(platformContext) {
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
std::shared_ptr<GPU> getGPU() { return _gpu; }
|
|
27
|
+
|
|
28
|
+
bool getFabric() { return true; }
|
|
29
|
+
|
|
30
|
+
std::shared_ptr<GPUCanvasContext>
|
|
31
|
+
MakeWebGPUCanvasContext(int contextId, float width, float height) {
|
|
32
|
+
auto ctx =
|
|
33
|
+
std::make_shared<GPUCanvasContext>(_gpu, contextId, width, height);
|
|
34
|
+
return ctx;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
std::shared_ptr<Canvas> getNativeSurface(int contextId) {
|
|
38
|
+
auto ®istry = rnwgpu::SurfaceRegistry::getInstance();
|
|
39
|
+
auto info = registry.getSurfaceInfo(contextId);
|
|
40
|
+
if (info == nullptr) {
|
|
41
|
+
return std::make_shared<Canvas>(nullptr, 0, 0);
|
|
42
|
+
}
|
|
43
|
+
auto nativeInfo = info->getNativeInfo();
|
|
44
|
+
return std::make_shared<Canvas>(nativeInfo.nativeSurface, nativeInfo.width,
|
|
45
|
+
nativeInfo.height);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) {
|
|
49
|
+
installGetter(runtime, prototype, "fabric", &RNWebGPU::getFabric);
|
|
50
|
+
installGetter(runtime, prototype, "gpu", &RNWebGPU::getGPU);
|
|
51
|
+
installMethod(runtime, prototype, "getNativeSurface",
|
|
52
|
+
&RNWebGPU::getNativeSurface);
|
|
53
|
+
installMethod(runtime, prototype, "MakeWebGPUCanvasContext",
|
|
54
|
+
&RNWebGPU::MakeWebGPUCanvasContext);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private:
|
|
58
|
+
std::shared_ptr<GPU> _gpu;
|
|
59
|
+
std::shared_ptr<PlatformContext> _platformContext;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
} // namespace rnwgpu
|