react-native-wgpu 0.1.8 → 0.1.9
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/cpp/cpp-adapter.cpp +13 -35
- package/android/src/main/java/com/webgpu/WebGPUModule.java +0 -37
- package/android/src/main/java/com/webgpu/WebGPUView.java +0 -1
- package/android/src/main/java/com/webgpu/WebGPUViewPackage.java +1 -1
- package/cpp/rnwgpu/RNWebGPUManager.h +2 -2
- package/cpp/rnwgpu/SurfaceRegistry.h +148 -13
- package/cpp/rnwgpu/api/Canvas.h +15 -15
- package/cpp/rnwgpu/api/GPUCanvasContext.cpp +81 -23
- package/cpp/rnwgpu/api/GPUCanvasContext.h +16 -7
- package/cpp/rnwgpu/api/GPUDevice.cpp +3 -2
- package/cpp/rnwgpu/api/OffscreenSurface.h +49 -0
- package/cpp/rnwgpu/api/RNWebGPU.h +21 -10
- package/ios/MetalView.mm +11 -0
- package/ios/SurfaceUtils.h +2 -0
- package/ios/SurfaceUtils.mm +16 -4
- package/ios/WebGPUModule.mm +8 -25
- package/ios/WebGPUView.mm +9 -6
- package/lib/commonjs/Canvas.js +79 -18
- package/lib/commonjs/Canvas.js.map +1 -1
- package/lib/commonjs/Offscreen.js +3 -0
- package/lib/commonjs/Offscreen.js.map +1 -1
- package/lib/commonjs/utils.js +26 -15
- package/lib/commonjs/utils.js.map +1 -1
- package/lib/module/Canvas.js +80 -19
- package/lib/module/Canvas.js.map +1 -1
- package/lib/module/Offscreen.js +3 -0
- package/lib/module/Offscreen.js.map +1 -1
- package/lib/module/utils.js +25 -15
- package/lib/module/utils.js.map +1 -1
- package/lib/typescript/lib/commonjs/Offscreen.d.ts +1 -0
- package/lib/typescript/lib/commonjs/Offscreen.d.ts.map +1 -1
- package/lib/typescript/lib/commonjs/utils.d.ts +5 -1
- package/lib/typescript/lib/commonjs/utils.d.ts.map +1 -1
- package/lib/typescript/lib/module/Canvas.d.ts.map +1 -1
- package/lib/typescript/lib/module/Offscreen.d.ts +1 -0
- package/lib/typescript/lib/module/Offscreen.d.ts.map +1 -1
- package/lib/typescript/lib/module/utils.d.ts +5 -1
- package/lib/typescript/lib/module/utils.d.ts.map +1 -1
- package/lib/typescript/src/Canvas.d.ts +4 -2
- package/lib/typescript/src/Canvas.d.ts.map +1 -1
- package/lib/typescript/src/Offscreen.d.ts +16 -1
- package/lib/typescript/src/Offscreen.d.ts.map +1 -1
- package/lib/typescript/src/utils.d.ts +6 -3
- package/lib/typescript/src/utils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/Canvas.tsx +99 -35
- package/src/Offscreen.ts +6 -2
- package/src/utils.ts +28 -18
|
@@ -27,52 +27,30 @@ extern "C" JNIEXPORT void JNICALL Java_com_webgpu_WebGPUModule_initializeNative(
|
|
|
27
27
|
platformContext);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
extern "C" JNIEXPORT void JNICALL
|
|
31
|
-
Java_com_webgpu_WebGPUModule_createSurfaceContext(JNIEnv *env, jobject thiz,
|
|
32
|
-
jlong jsRuntime,
|
|
33
|
-
jint contextId) {
|
|
34
|
-
auto canvas = manager->surfacesRegistry.getSurface(contextId);
|
|
35
|
-
if (canvas == nullptr) {
|
|
36
|
-
throw std::runtime_error("Surface haven't configured yet");
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
auto runtime = reinterpret_cast<facebook::jsi::Runtime *>(jsRuntime);
|
|
40
|
-
auto webGPUContextRegistry = runtime->global().getPropertyAsObject(
|
|
41
|
-
*runtime, "__WebGPUContextRegistry");
|
|
42
|
-
if (webGPUContextRegistry.hasProperty(*runtime,
|
|
43
|
-
std::to_string(contextId).c_str())) {
|
|
44
|
-
// Context already exists, just update width/height
|
|
45
|
-
auto prop =
|
|
46
|
-
webGPUContextRegistry
|
|
47
|
-
.getPropertyAsObject(*runtime, std::to_string(contextId).c_str())
|
|
48
|
-
.asHostObject<rnwgpu::Canvas>(*runtime);
|
|
49
|
-
prop->setWidth(canvas->getWidth());
|
|
50
|
-
prop->setHeight(canvas->getHeight());
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
webGPUContextRegistry.setProperty(
|
|
54
|
-
*runtime, std::to_string(contextId).c_str(),
|
|
55
|
-
facebook::jsi::Object::createFromHostObject(*runtime, canvas));
|
|
56
|
-
}
|
|
57
|
-
|
|
58
30
|
extern "C" JNIEXPORT void JNICALL Java_com_webgpu_WebGPUView_onSurfaceChanged(
|
|
59
31
|
JNIEnv *env, jobject thiz, jobject surface, jint contextId, jfloat width,
|
|
60
32
|
jfloat height) {
|
|
61
|
-
|
|
33
|
+
auto ®istry = rnwgpu::SurfaceRegistry::getInstance();
|
|
34
|
+
auto info = registry.getSurface(contextId);
|
|
35
|
+
registry.setSize(contextId, static_cast<int>(width),
|
|
36
|
+
static_cast<int>(height));
|
|
62
37
|
}
|
|
63
38
|
|
|
64
39
|
extern "C" JNIEXPORT void JNICALL Java_com_webgpu_WebGPUView_onSurfaceCreate(
|
|
65
|
-
JNIEnv *env, jobject thiz, jobject
|
|
40
|
+
JNIEnv *env, jobject thiz, jobject jSurface, jint contextId, jfloat width,
|
|
66
41
|
jfloat height) {
|
|
67
|
-
auto window = ANativeWindow_fromSurface(env,
|
|
42
|
+
auto window = ANativeWindow_fromSurface(env, jSurface);
|
|
68
43
|
// ANativeWindow_acquire(window);
|
|
69
|
-
|
|
44
|
+
auto ®istry = rnwgpu::SurfaceRegistry::getInstance();
|
|
45
|
+
registry.createSurface(contextId, window, static_cast<int>(width),
|
|
46
|
+
static_cast<int>(height), manager->_platformContext);
|
|
70
47
|
}
|
|
71
48
|
|
|
72
49
|
extern "C" JNIEXPORT void JNICALL Java_com_webgpu_WebGPUView_onSurfaceDestroy(
|
|
73
50
|
JNIEnv *env, jobject thiz, jint contextId) {
|
|
74
|
-
auto
|
|
51
|
+
auto ®istry = rnwgpu::SurfaceRegistry::getInstance();
|
|
52
|
+
auto canvas = registry.getSurface(contextId);
|
|
75
53
|
ANativeWindow_release(
|
|
76
|
-
reinterpret_cast<ANativeWindow *>(canvas
|
|
77
|
-
|
|
54
|
+
reinterpret_cast<ANativeWindow *>(canvas.nativeSurface));
|
|
55
|
+
registry.removeSurface(contextId);
|
|
78
56
|
}
|
|
@@ -24,9 +24,6 @@ public class WebGPUModule extends NativeWebGPUModuleSpec {
|
|
|
24
24
|
System.loadLibrary("react-native-wgpu"); // Load the C++ library
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
private final Object mContextLock = new Object();
|
|
28
|
-
private final Set<Integer> mSurfaceContextsIds = new HashSet<>();
|
|
29
|
-
|
|
30
27
|
public WebGPUModule(ReactApplicationContext reactContext) {
|
|
31
28
|
super(reactContext);
|
|
32
29
|
// Initialize the C++ module
|
|
@@ -50,38 +47,4 @@ public class WebGPUModule extends NativeWebGPUModuleSpec {
|
|
|
50
47
|
@OptIn(markerClass = FrameworkAPI.class)
|
|
51
48
|
@DoNotStrip
|
|
52
49
|
private native void initializeNative(long jsRuntime, CallInvokerHolderImpl jsInvoker, BlobModule blobModule);
|
|
53
|
-
|
|
54
|
-
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
55
|
-
public boolean createSurfaceContext(double contextId) {
|
|
56
|
-
waitForNativeSurface((int)contextId);
|
|
57
|
-
|
|
58
|
-
ReactApplicationContext context = getReactApplicationContext();
|
|
59
|
-
JavaScriptContextHolder jsContext = context.getJavaScriptContextHolder();
|
|
60
|
-
createSurfaceContext(jsContext.get(), (int)contextId);
|
|
61
|
-
return true;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
@DoNotStrip
|
|
65
|
-
private native void createSurfaceContext(long jsRuntime, int contextId);
|
|
66
|
-
|
|
67
|
-
private void waitForNativeSurface(Integer contextId) {
|
|
68
|
-
synchronized (mContextLock) {
|
|
69
|
-
while (!mSurfaceContextsIds.contains(contextId)) {
|
|
70
|
-
try {
|
|
71
|
-
mContextLock.wait();
|
|
72
|
-
} catch (InterruptedException e) {
|
|
73
|
-
Log.e("RNWebGPU", "Unable to create a context");
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
protected void onSurfaceCreated(Integer contextId) {
|
|
81
|
-
synchronized (mContextLock) {
|
|
82
|
-
mSurfaceContextsIds.add(contextId);
|
|
83
|
-
mContextLock.notifyAll();
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
50
|
}
|
|
@@ -41,7 +41,6 @@ public class WebGPUView extends SurfaceView implements SurfaceHolder.Callback {
|
|
|
41
41
|
float width = getWidth() / density;
|
|
42
42
|
float height = getHeight() / density;
|
|
43
43
|
onSurfaceCreate(holder.getSurface(), mContextId, width, height);
|
|
44
|
-
mModule.onSurfaceCreated(mContextId);
|
|
45
44
|
}
|
|
46
45
|
|
|
47
46
|
@Override
|
|
@@ -21,6 +21,6 @@ public class WebGPUViewPackage implements ReactPackage {
|
|
|
21
21
|
|
|
22
22
|
@Override
|
|
23
23
|
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
|
|
24
|
-
return
|
|
24
|
+
return List.of(new WebGPUModule(reactContext));
|
|
25
25
|
}
|
|
26
26
|
}
|
|
@@ -27,11 +27,11 @@ public:
|
|
|
27
27
|
std::shared_ptr<PlatformContext> platformContext);
|
|
28
28
|
~RNWebGPUManager();
|
|
29
29
|
|
|
30
|
-
SurfaceRegistry surfacesRegistry;
|
|
31
|
-
|
|
32
30
|
private:
|
|
33
31
|
jsi::Runtime *_jsRuntime;
|
|
34
32
|
std::shared_ptr<facebook::react::CallInvoker> _jsCallInvoker;
|
|
33
|
+
|
|
34
|
+
public:
|
|
35
35
|
std::shared_ptr<PlatformContext> _platformContext;
|
|
36
36
|
};
|
|
37
37
|
|
|
@@ -1,33 +1,168 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
3
|
#include <memory>
|
|
4
|
+
#include <shared_mutex>
|
|
4
5
|
#include <unordered_map>
|
|
5
6
|
|
|
6
7
|
#include "webgpu/webgpu_cpp.h"
|
|
7
8
|
|
|
8
|
-
#include "Canvas.h"
|
|
9
|
-
|
|
10
9
|
namespace rnwgpu {
|
|
11
10
|
|
|
11
|
+
struct ISize {
|
|
12
|
+
int width;
|
|
13
|
+
int height;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
struct SurfaceInfo {
|
|
17
|
+
void *nativeSurface = nullptr;
|
|
18
|
+
wgpu::Surface surface;
|
|
19
|
+
int width;
|
|
20
|
+
int height;
|
|
21
|
+
wgpu::Texture texture;
|
|
22
|
+
wgpu::Instance gpu;
|
|
23
|
+
wgpu::SurfaceConfiguration config;
|
|
24
|
+
|
|
25
|
+
void flushTextureToSurface() {
|
|
26
|
+
// 1.a flush texture to the onscreen surface
|
|
27
|
+
if (texture) {
|
|
28
|
+
wgpu::CommandEncoderDescriptor encoderDesc;
|
|
29
|
+
auto device = config.device;
|
|
30
|
+
wgpu::CommandEncoder encoder = device.CreateCommandEncoder(&encoderDesc);
|
|
31
|
+
|
|
32
|
+
wgpu::ImageCopyTexture sourceTexture = {};
|
|
33
|
+
sourceTexture.texture = texture;
|
|
34
|
+
|
|
35
|
+
wgpu::ImageCopyTexture destinationTexture = {};
|
|
36
|
+
wgpu::SurfaceTexture surfaceTexture;
|
|
37
|
+
surface.GetCurrentTexture(&surfaceTexture);
|
|
38
|
+
destinationTexture.texture = surfaceTexture.texture;
|
|
39
|
+
|
|
40
|
+
wgpu::Extent3D size = {sourceTexture.texture.GetWidth(),
|
|
41
|
+
sourceTexture.texture.GetHeight(),
|
|
42
|
+
sourceTexture.texture.GetDepthOrArrayLayers()};
|
|
43
|
+
|
|
44
|
+
encoder.CopyTextureToTexture(&sourceTexture, &destinationTexture, &size);
|
|
45
|
+
|
|
46
|
+
wgpu::CommandBuffer commands = encoder.Finish();
|
|
47
|
+
wgpu::Queue queue = device.GetQueue();
|
|
48
|
+
queue.Submit(1, &commands);
|
|
49
|
+
texture = nullptr;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
12
54
|
class SurfaceRegistry {
|
|
13
|
-
|
|
55
|
+
private:
|
|
56
|
+
std::unordered_map<int, SurfaceInfo> _registry;
|
|
57
|
+
mutable std::shared_mutex _mutex;
|
|
58
|
+
|
|
59
|
+
// Private constructor to prevent instantiation
|
|
60
|
+
SurfaceRegistry() {}
|
|
61
|
+
|
|
62
|
+
void updateSurface(const int contextId, SurfaceInfo &info) {
|
|
63
|
+
auto it = _registry.find(contextId);
|
|
64
|
+
if (it != _registry.end()) {
|
|
65
|
+
it->second = info;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// bool hasOnScreenSurface(const int contextId) const {
|
|
70
|
+
// std::shared_lock<std::shared_mutex> lock(_mutex);
|
|
71
|
+
// auto it = _registry.find(contextId);
|
|
72
|
+
// if (it != _registry.end()) {
|
|
73
|
+
// return it->second.nativeSurface != nullptr;
|
|
74
|
+
// }
|
|
75
|
+
// return false;
|
|
76
|
+
// }
|
|
77
|
+
|
|
78
|
+
bool hasSurfaceInfo(const int contextId) const {
|
|
79
|
+
return _registry.find(contextId) != _registry.end();
|
|
80
|
+
}
|
|
14
81
|
|
|
15
82
|
public:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
83
|
+
// Delete copy constructor and assignment operator
|
|
84
|
+
SurfaceRegistry(const SurfaceRegistry &) = delete;
|
|
85
|
+
SurfaceRegistry &operator=(const SurfaceRegistry &) = delete;
|
|
86
|
+
|
|
87
|
+
// Static method to get the singleton instance
|
|
88
|
+
static SurfaceRegistry &getInstance() {
|
|
89
|
+
static SurfaceRegistry instance;
|
|
90
|
+
return instance;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
void removeSurface(const int contextId) {
|
|
94
|
+
std::unique_lock<std::shared_mutex> lock(_mutex);
|
|
95
|
+
_registry.erase(contextId);
|
|
19
96
|
}
|
|
20
97
|
|
|
21
|
-
std::
|
|
22
|
-
|
|
98
|
+
std::optional<SurfaceInfo> getSurfaceMaybe(const int contextId) {
|
|
99
|
+
std::unique_lock<std::shared_mutex> lock(_mutex);
|
|
100
|
+
auto it = _registry.find(contextId);
|
|
101
|
+
if (it != _registry.end()) {
|
|
102
|
+
return it->second;
|
|
103
|
+
}
|
|
104
|
+
return std::nullopt;
|
|
23
105
|
}
|
|
24
106
|
|
|
25
|
-
|
|
107
|
+
SurfaceInfo getSurface(const int contextId) const {
|
|
108
|
+
auto it = _registry.find(contextId);
|
|
109
|
+
if (it != _registry.end()) {
|
|
110
|
+
return it->second;
|
|
111
|
+
}
|
|
112
|
+
throw std::out_of_range("Surface not found");
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
void setSize(const int contextId, int width, int height) {
|
|
116
|
+
std::unique_lock<std::shared_mutex> lock(_mutex);
|
|
117
|
+
auto it = _registry.find(contextId);
|
|
118
|
+
if (it != _registry.end()) {
|
|
119
|
+
it->second.width = width;
|
|
120
|
+
it->second.height = height;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
void
|
|
125
|
+
configureOffscreenSurface(const int contextId, wgpu::Instance gpu,
|
|
126
|
+
wgpu::Texture texture,
|
|
127
|
+
wgpu::SurfaceConfiguration surfaceConfiguration) {
|
|
128
|
+
SurfaceInfo info;
|
|
129
|
+
info.width = surfaceConfiguration.width;
|
|
130
|
+
info.height = surfaceConfiguration.height;
|
|
131
|
+
info.texture = texture;
|
|
132
|
+
info.gpu = gpu;
|
|
133
|
+
info.config = surfaceConfiguration;
|
|
134
|
+
std::unique_lock<std::shared_mutex> lock(_mutex);
|
|
135
|
+
_registry[contextId] = info;
|
|
136
|
+
}
|
|
26
137
|
|
|
27
|
-
void
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
138
|
+
void createSurface(const int contextId, void *nativeSurface, int width,
|
|
139
|
+
int height,
|
|
140
|
+
std::shared_ptr<PlatformContext> platformContext) {
|
|
141
|
+
std::unique_lock<std::shared_mutex> lock(_mutex);
|
|
142
|
+
// 1. The scene has already be drawn offscreen
|
|
143
|
+
if (hasSurfaceInfo(contextId)) {
|
|
144
|
+
auto info = getSurface(contextId);
|
|
145
|
+
auto surface =
|
|
146
|
+
platformContext->makeSurface(info.gpu, nativeSurface, width, height);
|
|
147
|
+
info.config.usage = info.config.usage | wgpu::TextureUsage::CopyDst;
|
|
148
|
+
surface.Configure(&info.config);
|
|
149
|
+
info.nativeSurface = nativeSurface;
|
|
150
|
+
info.surface = surface;
|
|
151
|
+
info.width = width;
|
|
152
|
+
info.height = height;
|
|
153
|
+
info.flushTextureToSurface();
|
|
154
|
+
surface.Present();
|
|
155
|
+
updateSurface(contextId, info);
|
|
156
|
+
} else {
|
|
157
|
+
// 2. The scene has not been drawn offscreen yet, we will draw onscreen
|
|
158
|
+
// directly
|
|
159
|
+
rnwgpu::SurfaceInfo info;
|
|
160
|
+
info.nativeSurface = nativeSurface;
|
|
161
|
+
info.surface =
|
|
162
|
+
platformContext->makeSurface(info.gpu, nativeSurface, width, height);
|
|
163
|
+
info.width = width;
|
|
164
|
+
info.height = height;
|
|
165
|
+
_registry[contextId] = info;
|
|
31
166
|
}
|
|
32
167
|
}
|
|
33
168
|
};
|
package/cpp/rnwgpu/api/Canvas.h
CHANGED
|
@@ -15,24 +15,24 @@ namespace m = margelo;
|
|
|
15
15
|
|
|
16
16
|
class Canvas : public m::HybridObject {
|
|
17
17
|
public:
|
|
18
|
-
explicit Canvas(void*
|
|
18
|
+
explicit Canvas(void *surface, const int width, const int height)
|
|
19
19
|
: HybridObject("Canvas"), _surface(surface), _width(width),
|
|
20
20
|
_height(height), _clientWidth(width), _clientHeight(height) {}
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
int getWidth() { return _width; }
|
|
23
|
+
int getHeight() { return _height; }
|
|
24
24
|
|
|
25
|
-
void setWidth(const
|
|
26
|
-
void setHeight(const
|
|
25
|
+
void setWidth(const int width) { _width = width; }
|
|
26
|
+
void setHeight(const int height) { _height = height; }
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
int getClientWidth() { return _clientWidth; }
|
|
29
|
+
int getClientHeight() { return _clientHeight; }
|
|
30
30
|
|
|
31
|
-
void setClientWidth(const
|
|
31
|
+
void setClientWidth(const int width) { _clientWidth = width; }
|
|
32
32
|
|
|
33
|
-
void setClientHeight(const
|
|
33
|
+
void setClientHeight(const int height) { _clientHeight = height; }
|
|
34
34
|
|
|
35
|
-
void*
|
|
35
|
+
void *getSurface() { return _surface; }
|
|
36
36
|
|
|
37
37
|
void loadHybridMethods() override {
|
|
38
38
|
registerHybridGetter("surface", &Canvas::getSurface, this);
|
|
@@ -45,11 +45,11 @@ public:
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
private:
|
|
48
|
-
void*
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
void *_surface;
|
|
49
|
+
int _width;
|
|
50
|
+
int _height;
|
|
51
|
+
int _clientWidth;
|
|
52
|
+
int _clientHeight;
|
|
53
53
|
};
|
|
54
54
|
|
|
55
55
|
} // namespace rnwgpu
|
|
@@ -23,41 +23,99 @@ void GPUCanvasContext::configure(
|
|
|
23
23
|
if (!conv(surfaceConfiguration.usage, configuration->usage)) {
|
|
24
24
|
throw std::runtime_error("Error with SurfaceConfiguration");
|
|
25
25
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
auto width = _canvas->getWidth();
|
|
27
|
+
auto height = _canvas->getHeight();
|
|
28
|
+
surfaceConfiguration.width = width;
|
|
29
|
+
surfaceConfiguration.height = height;
|
|
30
|
+
_surfaceConfiguration = surfaceConfiguration;
|
|
31
|
+
// Are we onscreen now?
|
|
32
|
+
auto ®istry = rnwgpu::SurfaceRegistry::getInstance();
|
|
33
|
+
auto infoVal = registry.getSurfaceMaybe(_contextId);
|
|
34
|
+
if (infoVal.has_value()) {
|
|
35
|
+
auto info = infoVal.value();
|
|
36
|
+
if (info.surface) {
|
|
37
|
+
_instance = info.surface;
|
|
38
|
+
_offscreenSurface = nullptr;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (_instance) {
|
|
43
|
+
_instance.Configure(&surfaceConfiguration);
|
|
44
|
+
} else {
|
|
45
|
+
_offscreenSurface->configure(_surfaceConfiguration);
|
|
46
|
+
// Add texture to the surface registry, when the native surface is
|
|
47
|
+
// available, we will copy its content there This only makes sense if the on
|
|
48
|
+
// screen native surface is not available yet
|
|
49
|
+
registry.configureOffscreenSurface(_contextId, _gpu->get(),
|
|
50
|
+
_offscreenSurface->getCurrentTexture(),
|
|
51
|
+
_surfaceConfiguration);
|
|
52
|
+
}
|
|
32
53
|
}
|
|
33
54
|
|
|
34
55
|
void GPUCanvasContext::unconfigure() {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
56
|
+
if (_instance) {
|
|
57
|
+
_instance.Unconfigure();
|
|
58
|
+
} else if (_offscreenSurface) {
|
|
59
|
+
_offscreenSurface = nullptr;
|
|
60
|
+
}
|
|
39
61
|
}
|
|
40
62
|
|
|
41
63
|
std::shared_ptr<GPUTexture> GPUCanvasContext::getCurrentTexture() {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
64
|
+
auto width = _canvas->getWidth();
|
|
65
|
+
auto height = _canvas->getHeight();
|
|
66
|
+
|
|
67
|
+
auto prevWidth = _surfaceConfiguration.width;
|
|
68
|
+
auto prevHeight = _surfaceConfiguration.height;
|
|
69
|
+
auto sizeHasChanged = prevWidth != width || prevHeight != height;
|
|
70
|
+
_surfaceConfiguration.width = width;
|
|
71
|
+
_surfaceConfiguration.height = height;
|
|
72
|
+
// Get onscreen texture
|
|
73
|
+
if (_instance) {
|
|
74
|
+
// Did the surface resize?
|
|
75
|
+
if (sizeHasChanged) {
|
|
76
|
+
_instance.Configure(&_surfaceConfiguration);
|
|
77
|
+
}
|
|
78
|
+
// Get onscreen texture
|
|
79
|
+
wgpu::SurfaceTexture surfaceTexture;
|
|
80
|
+
_instance.GetCurrentTexture(&surfaceTexture);
|
|
81
|
+
auto texture = surfaceTexture.texture;
|
|
82
|
+
if (texture == nullptr) {
|
|
83
|
+
throw std::runtime_error("Couldn't get current texture");
|
|
84
|
+
}
|
|
85
|
+
return std::make_shared<GPUTexture>(texture, "");
|
|
86
|
+
} else {
|
|
87
|
+
// Did the surface resize?
|
|
88
|
+
if (sizeHasChanged) {
|
|
89
|
+
_offscreenSurface->configure(_surfaceConfiguration);
|
|
90
|
+
}
|
|
91
|
+
// Get offscreen texture
|
|
92
|
+
auto tex = _offscreenSurface->getCurrentTexture();
|
|
93
|
+
return std::make_shared<GPUTexture>(tex, "");
|
|
94
|
+
}
|
|
54
95
|
}
|
|
55
96
|
|
|
56
97
|
void GPUCanvasContext::present() {
|
|
57
98
|
#ifdef __APPLE__
|
|
58
99
|
dawn::native::metal::WaitForCommandsToBeScheduled(_device.Get());
|
|
59
100
|
#endif
|
|
60
|
-
|
|
101
|
+
auto ®istry = rnwgpu::SurfaceRegistry::getInstance();
|
|
102
|
+
auto infoVal = registry.getSurfaceMaybe(_contextId);
|
|
103
|
+
if (infoVal.has_value()) {
|
|
104
|
+
auto info = infoVal.value();
|
|
105
|
+
// We are starting a new frame, this is a good time to update the client
|
|
106
|
+
_canvas->setClientWidth(info.width);
|
|
107
|
+
_canvas->setClientHeight(info.height);
|
|
108
|
+
if (_offscreenSurface) {
|
|
109
|
+
// Are we onscreen now?
|
|
110
|
+
if (info.surface) {
|
|
111
|
+
_instance = info.surface;
|
|
112
|
+
_offscreenSurface = nullptr;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (_instance) {
|
|
117
|
+
_instance.Present();
|
|
118
|
+
}
|
|
61
119
|
}
|
|
62
120
|
|
|
63
121
|
} // namespace rnwgpu
|
|
@@ -12,8 +12,10 @@
|
|
|
12
12
|
#include "AsyncRunner.h"
|
|
13
13
|
|
|
14
14
|
#include "Canvas.h"
|
|
15
|
+
#include "GPU.h"
|
|
15
16
|
#include "GPUCanvasConfiguration.h"
|
|
16
17
|
#include "GPUTexture.h"
|
|
18
|
+
#include "OffscreenSurface.h"
|
|
17
19
|
#include "SurfaceRegistry.h"
|
|
18
20
|
|
|
19
21
|
#ifdef __APPLE__
|
|
@@ -38,9 +40,13 @@ namespace m = margelo;
|
|
|
38
40
|
|
|
39
41
|
class GPUCanvasContext : public m::HybridObject {
|
|
40
42
|
public:
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
// TODO: platformContext no necessary here
|
|
44
|
+
GPUCanvasContext(std::shared_ptr<GPU> gpu, int contextId, int width,
|
|
45
|
+
int height)
|
|
46
|
+
: HybridObject("GPUCanvasContext"), _contextId(contextId),
|
|
47
|
+
_gpu(std::move(gpu)) {
|
|
48
|
+
_canvas = std::make_shared<Canvas>(nullptr, width, height);
|
|
49
|
+
_offscreenSurface = std::make_shared<OffscreenSurface>(_canvas);
|
|
44
50
|
}
|
|
45
51
|
|
|
46
52
|
public:
|
|
@@ -65,12 +71,15 @@ public:
|
|
|
65
71
|
void present();
|
|
66
72
|
|
|
67
73
|
private:
|
|
68
|
-
|
|
74
|
+
std::shared_ptr<OffscreenSurface> _offscreenSurface;
|
|
75
|
+
wgpu::Surface _instance = nullptr;
|
|
69
76
|
wgpu::Device _device;
|
|
70
77
|
std::shared_ptr<Canvas> _canvas;
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
78
|
+
int _contextId;
|
|
79
|
+
|
|
80
|
+
std::shared_ptr<GPU> _gpu;
|
|
81
|
+
// TODO: do we need this or can it be stored in the surface registry?
|
|
82
|
+
wgpu::SurfaceConfiguration _surfaceConfiguration;
|
|
74
83
|
};
|
|
75
84
|
|
|
76
85
|
} // namespace rnwgpu
|
|
@@ -70,8 +70,9 @@ std::shared_ptr<GPUShaderModule> GPUDevice::createShaderModule(
|
|
|
70
70
|
wgpu::ShaderModuleWGSLDescriptor wgsl_desc{};
|
|
71
71
|
wgpu::ShaderModuleDescriptor sm_desc{};
|
|
72
72
|
Convertor conv;
|
|
73
|
-
if (!conv(wgsl_desc.code, descriptor->code) ||
|
|
74
|
-
|
|
73
|
+
if (!conv(wgsl_desc.code, descriptor->code) ||
|
|
74
|
+
!conv(sm_desc.label, descriptor->label)) {
|
|
75
|
+
return {};
|
|
75
76
|
}
|
|
76
77
|
sm_desc.nextInChain = &wgsl_desc;
|
|
77
78
|
if (descriptor->code.find('\0') != std::string::npos) {
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "webgpu/webgpu_cpp.h"
|
|
4
|
+
|
|
5
|
+
#include "Canvas.h"
|
|
6
|
+
|
|
7
|
+
namespace rnwgpu {
|
|
8
|
+
|
|
9
|
+
class OffscreenSurface {
|
|
10
|
+
public:
|
|
11
|
+
explicit OffscreenSurface(std::shared_ptr<Canvas> canvas)
|
|
12
|
+
: _canvas(std::move(canvas)) {
|
|
13
|
+
#if defined(__ANDROID__)
|
|
14
|
+
_textureFormat = wgpu::TextureFormat::RGBA8Unorm;
|
|
15
|
+
#else
|
|
16
|
+
_textureFormat = wgpu::TextureFormat::BGRA8Unorm;
|
|
17
|
+
#endif // defined(__ANDROID__)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
void configure(const wgpu::SurfaceConfiguration &config) {
|
|
21
|
+
// Configure the canvas context with the device and format
|
|
22
|
+
_device = config.device;
|
|
23
|
+
|
|
24
|
+
wgpu::TextureDescriptor textureDesc;
|
|
25
|
+
textureDesc.size.width = _canvas->getWidth();
|
|
26
|
+
textureDesc.size.height = _canvas->getHeight();
|
|
27
|
+
textureDesc.format = _textureFormat;
|
|
28
|
+
textureDesc.usage = wgpu::TextureUsage::RenderAttachment |
|
|
29
|
+
wgpu::TextureUsage::CopySrc |
|
|
30
|
+
wgpu::TextureUsage::TextureBinding;
|
|
31
|
+
|
|
32
|
+
_texture = _device.CreateTexture(&textureDesc);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
wgpu::Texture getCurrentTexture() {
|
|
36
|
+
if (!_texture) {
|
|
37
|
+
throw std::runtime_error("Texture is not configured");
|
|
38
|
+
}
|
|
39
|
+
return _texture;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private:
|
|
43
|
+
wgpu::TextureFormat _textureFormat;
|
|
44
|
+
wgpu::Texture _texture = nullptr;
|
|
45
|
+
wgpu::Device _device;
|
|
46
|
+
std::shared_ptr<Canvas> _canvas;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
} // namespace rnwgpu
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
#include <memory>
|
|
4
4
|
#include <string>
|
|
5
5
|
|
|
6
|
+
#include "Canvas.h"
|
|
6
7
|
#include "GPU.h"
|
|
7
8
|
#include "GPUCanvasContext.h"
|
|
8
9
|
#include "ImageBitmap.h"
|
|
@@ -29,17 +30,18 @@ public:
|
|
|
29
30
|
|
|
30
31
|
std::shared_ptr<GPU> getGPU() { return _gpu; }
|
|
31
32
|
|
|
33
|
+
bool getFabric() {
|
|
34
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
35
|
+
return true;
|
|
36
|
+
#else
|
|
37
|
+
return false;
|
|
38
|
+
#endif
|
|
39
|
+
}
|
|
40
|
+
|
|
32
41
|
std::shared_ptr<GPUCanvasContext>
|
|
33
|
-
MakeWebGPUCanvasContext(
|
|
34
|
-
auto
|
|
35
|
-
|
|
36
|
-
auto height = canvas->getHeight();
|
|
37
|
-
auto surface = _platformContext->makeSurface(
|
|
38
|
-
_gpu->get(), reinterpret_cast<void *>(nativeSurface), width, height);
|
|
39
|
-
if (surface == nullptr) {
|
|
40
|
-
throw std::runtime_error("null surface");
|
|
41
|
-
}
|
|
42
|
-
auto ctx = std::make_shared<GPUCanvasContext>(surface, canvas);
|
|
42
|
+
MakeWebGPUCanvasContext(int contextId, float width, float height) {
|
|
43
|
+
auto ctx =
|
|
44
|
+
std::make_shared<GPUCanvasContext>(_gpu, contextId, width, height);
|
|
43
45
|
return ctx;
|
|
44
46
|
}
|
|
45
47
|
|
|
@@ -50,10 +52,19 @@ public:
|
|
|
50
52
|
return imageBitmap;
|
|
51
53
|
}
|
|
52
54
|
|
|
55
|
+
std::shared_ptr<Canvas> getNativeSurface(int contextId) {
|
|
56
|
+
auto ®istry = rnwgpu::SurfaceRegistry::getInstance();
|
|
57
|
+
auto info = registry.getSurface(contextId);
|
|
58
|
+
return std::make_shared<Canvas>(info.nativeSurface, info.width,
|
|
59
|
+
info.height);
|
|
60
|
+
}
|
|
61
|
+
|
|
53
62
|
void loadHybridMethods() override {
|
|
63
|
+
registerHybridGetter("fabric", &RNWebGPU::getFabric, this);
|
|
54
64
|
registerHybridGetter("gpu", &RNWebGPU::getGPU, this);
|
|
55
65
|
registerHybridMethod("createImageBitmap", &RNWebGPU::createImageBitmap,
|
|
56
66
|
this);
|
|
67
|
+
registerHybridMethod("getNativeSurface", &RNWebGPU::getNativeSurface, this);
|
|
57
68
|
registerHybridMethod("MakeWebGPUCanvasContext",
|
|
58
69
|
&RNWebGPU::MakeWebGPUCanvasContext, this);
|
|
59
70
|
}
|