react-native-webgpu 0.6.0 → 0.6.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.
- package/android/cpp/cpp-adapter.cpp +35 -13
- package/android/src/main/java/com/webgpu/WebGPUAHBView.java +2 -2
- package/android/src/main/java/com/webgpu/WebGPUAPI.java +7 -2
- package/android/src/main/java/com/webgpu/WebGPUSurfaceView.java +3 -1
- package/android/src/main/java/com/webgpu/WebGPUTextureView.java +11 -7
- package/android/src/main/java/com/webgpu/WebGPUView.java +10 -7
- package/android/src/main/java/com/webgpu/WebGPUViewManager.java +6 -0
- package/apple/MetalView.mm +33 -8
- package/cpp/rnwgpu/RNWebGPUManager.cpp +14 -1
- package/cpp/rnwgpu/RNWebGPUManager.h +9 -0
- package/cpp/rnwgpu/SurfaceRegistry.h +469 -131
- package/cpp/rnwgpu/api/GPUAdapter.cpp +10 -3
- package/cpp/rnwgpu/api/GPUAdapter.h +5 -4
- package/cpp/rnwgpu/api/GPUBuffer.cpp +12 -2
- package/cpp/rnwgpu/api/GPUBuffer.h +3 -2
- package/cpp/rnwgpu/api/GPUCanvasContext.cpp +33 -19
- package/cpp/rnwgpu/api/GPUCanvasContext.h +3 -1
- package/cpp/rnwgpu/api/GPUDevice.cpp +32 -17
- package/cpp/rnwgpu/api/GPUDevice.h +9 -7
- package/cpp/rnwgpu/api/GPUQueue.cpp +6 -2
- package/cpp/rnwgpu/api/GPUQueue.h +3 -3
- package/cpp/rnwgpu/api/GPUShaderModule.cpp +7 -2
- package/cpp/rnwgpu/api/GPUShaderModule.h +3 -3
- package/cpp/rnwgpu/api/RNWebGPU.h +22 -1
- package/cpp/rnwgpu/async/RuntimeContext.h +9 -2
- package/lib/commonjs/Canvas.js +10 -0
- package/lib/commonjs/Canvas.js.map +1 -1
- package/lib/commonjs/WebPolyfillGPUModule.js +2 -0
- package/lib/commonjs/WebPolyfillGPUModule.js.map +1 -1
- package/lib/module/Canvas.js +11 -1
- package/lib/module/Canvas.js.map +1 -1
- package/lib/module/WebPolyfillGPUModule.js +2 -0
- package/lib/module/WebPolyfillGPUModule.js.map +1 -1
- package/lib/typescript/lib/commonjs/Canvas.d.ts.map +1 -1
- package/lib/typescript/lib/module/Canvas.d.ts.map +1 -1
- package/lib/typescript/src/Canvas.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +2 -6
- package/src/Canvas.tsx +11 -1
- package/src/WebPolyfillGPUModule.ts +2 -0
- package/src/index.tsx +3 -0
- package/android/src/main/java/com/webgpu/WebGPUBaseView.java +0 -61
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
namespace rnwgpu {
|
|
24
24
|
|
|
25
25
|
async::AsyncTaskHandle GPUAdapter::requestDevice(
|
|
26
|
+
jsi::Runtime &runtime,
|
|
26
27
|
std::optional<std::shared_ptr<GPUDeviceDescriptor>> descriptor) {
|
|
27
28
|
// Enable the react-native-wgpu "native-texture" umbrella by default, mirroring
|
|
28
29
|
// the web where importExternalTexture is core and needs no feature request.
|
|
@@ -135,9 +136,15 @@ async::AsyncTaskHandle GPUAdapter::requestDevice(
|
|
|
135
136
|
descriptor.has_value() ? descriptor.value()->label.value_or("") : "";
|
|
136
137
|
|
|
137
138
|
auto creationRuntime = getCreationRuntime();
|
|
138
|
-
|
|
139
|
+
// Post to the CALLING runtime's context so the promise settles on the
|
|
140
|
+
// thread that requested it (see GPUBuffer::mapAsync). The GPUDevice is also
|
|
141
|
+
// bound to this context, honoring the contract that a device belongs to the
|
|
142
|
+
// runtime that requested it.
|
|
143
|
+
auto context =
|
|
144
|
+
async::RuntimeContext::getOrCreate(runtime, _async->instance());
|
|
145
|
+
return context->postTask(
|
|
139
146
|
[this, aDescriptor, descriptor, label = std::move(label),
|
|
140
|
-
deviceLostBinding,
|
|
147
|
+
deviceLostBinding, context,
|
|
141
148
|
creationRuntime](const async::AsyncTaskHandle::ResolveFunction &resolve,
|
|
142
149
|
const async::AsyncTaskHandle::RejectFunction &reject) {
|
|
143
150
|
// Build a local mutable copy so we can chain Dawn's device toggles.
|
|
@@ -193,7 +200,7 @@ async::AsyncTaskHandle GPUAdapter::requestDevice(
|
|
|
193
200
|
}
|
|
194
201
|
_instance.RequestDevice(
|
|
195
202
|
&deviceDesc, wgpu::CallbackMode::AllowProcessEvents,
|
|
196
|
-
[context
|
|
203
|
+
[context, resolve, reject, label, creationRuntime,
|
|
197
204
|
deviceLostBinding](wgpu::RequestDeviceStatus status,
|
|
198
205
|
wgpu::Device device, wgpu::StringView message) {
|
|
199
206
|
if (message.length) {
|
|
@@ -33,8 +33,9 @@ public:
|
|
|
33
33
|
public:
|
|
34
34
|
std::string getBrand() { return CLASS_NAME; }
|
|
35
35
|
|
|
36
|
-
async::AsyncTaskHandle
|
|
37
|
-
|
|
36
|
+
async::AsyncTaskHandle requestDevice(
|
|
37
|
+
jsi::Runtime &runtime,
|
|
38
|
+
std::optional<std::shared_ptr<GPUDeviceDescriptor>> descriptor);
|
|
38
39
|
|
|
39
40
|
std::unordered_set<std::string> getFeatures();
|
|
40
41
|
std::shared_ptr<GPUSupportedLimits> getLimits();
|
|
@@ -42,8 +43,8 @@ public:
|
|
|
42
43
|
|
|
43
44
|
static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) {
|
|
44
45
|
installGetter(runtime, prototype, "__brand", &GPUAdapter::getBrand);
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
installMethodWithRuntime(runtime, prototype, "requestDevice",
|
|
47
|
+
&GPUAdapter::requestDevice);
|
|
47
48
|
installGetter(runtime, prototype, "features", &GPUAdapter::getFeatures);
|
|
48
49
|
installGetter(runtime, prototype, "limits", &GPUAdapter::getLimits);
|
|
49
50
|
installGetter(runtime, prototype, "info", &GPUAdapter::getInfo);
|
|
@@ -37,7 +37,8 @@ GPUBuffer::getMappedRange(std::optional<size_t> o, std::optional<size_t> size) {
|
|
|
37
37
|
|
|
38
38
|
void GPUBuffer::destroy() { _instance.Destroy(); }
|
|
39
39
|
|
|
40
|
-
async::AsyncTaskHandle GPUBuffer::mapAsync(
|
|
40
|
+
async::AsyncTaskHandle GPUBuffer::mapAsync(jsi::Runtime &runtime,
|
|
41
|
+
uint64_t modeIn,
|
|
41
42
|
std::optional<uint64_t> offset,
|
|
42
43
|
std::optional<uint64_t> size) {
|
|
43
44
|
Convertor conv;
|
|
@@ -51,7 +52,16 @@ async::AsyncTaskHandle GPUBuffer::mapAsync(uint64_t modeIn,
|
|
|
51
52
|
auto bufferHandle = _instance;
|
|
52
53
|
uint64_t resolvedOffset = offset.value_or(0);
|
|
53
54
|
|
|
54
|
-
|
|
55
|
+
// Post to the CALLING runtime's context, not the one captured at buffer
|
|
56
|
+
// creation (_async): the buffer may have been created on another runtime and
|
|
57
|
+
// boxed across (e.g. device created on the main JS runtime, mapAsync called
|
|
58
|
+
// from a worklet). The returned Promise lives on the calling runtime, so it
|
|
59
|
+
// must be settled from that runtime's own thread — and postTask itself
|
|
60
|
+
// schedules the pump through its context's runtime (setTimeout), which is
|
|
61
|
+
// only safe for the runtime we are currently executing on.
|
|
62
|
+
auto context =
|
|
63
|
+
async::RuntimeContext::getOrCreate(runtime, _async->instance());
|
|
64
|
+
return context->postTask(
|
|
55
65
|
[bufferHandle, mode, resolvedOffset,
|
|
56
66
|
rangeSize](const async::AsyncTaskHandle::ResolveFunction &resolve,
|
|
57
67
|
const async::AsyncTaskHandle::RejectFunction &reject) {
|
|
@@ -33,7 +33,7 @@ public:
|
|
|
33
33
|
public:
|
|
34
34
|
std::string getBrand() { return CLASS_NAME; }
|
|
35
35
|
|
|
36
|
-
async::AsyncTaskHandle mapAsync(uint64_t modeIn,
|
|
36
|
+
async::AsyncTaskHandle mapAsync(jsi::Runtime &runtime, uint64_t modeIn,
|
|
37
37
|
std::optional<uint64_t> offset,
|
|
38
38
|
std::optional<uint64_t> size);
|
|
39
39
|
std::shared_ptr<ArrayBuffer> getMappedRange(std::optional<size_t> offset,
|
|
@@ -53,7 +53,8 @@ public:
|
|
|
53
53
|
|
|
54
54
|
static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) {
|
|
55
55
|
installGetter(runtime, prototype, "__brand", &GPUBuffer::getBrand);
|
|
56
|
-
|
|
56
|
+
installMethodWithRuntime(runtime, prototype, "mapAsync",
|
|
57
|
+
&GPUBuffer::mapAsync);
|
|
57
58
|
installMethod(runtime, prototype, "getMappedRange",
|
|
58
59
|
&GPUBuffer::getMappedRange);
|
|
59
60
|
installMethod(runtime, prototype, "unmap", &GPUBuffer::unmap);
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
#include "GPUCanvasContext.h"
|
|
2
2
|
#include "Convertors.h"
|
|
3
3
|
#include "RNWebGPUManager.h"
|
|
4
|
+
#include <algorithm>
|
|
4
5
|
#include <memory>
|
|
6
|
+
#include <utility>
|
|
7
|
+
#include <vector>
|
|
5
8
|
|
|
6
9
|
namespace rnwgpu {
|
|
7
10
|
|
|
@@ -10,37 +13,50 @@ void GPUCanvasContext::configure(
|
|
|
10
13
|
Convertor conv;
|
|
11
14
|
wgpu::SurfaceConfiguration surfaceConfiguration;
|
|
12
15
|
surfaceConfiguration.device = configuration->device->get();
|
|
13
|
-
if (configuration->viewFormats.has_value()) {
|
|
14
|
-
if (!conv(surfaceConfiguration.viewFormats,
|
|
15
|
-
surfaceConfiguration.viewFormatCount,
|
|
16
|
-
configuration->viewFormats.value())) {
|
|
17
|
-
throw std::runtime_error("Error with SurfaceConfiguration");
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
16
|
if (!conv(surfaceConfiguration.usage, configuration->usage) ||
|
|
21
17
|
!conv(surfaceConfiguration.format, configuration->format)) {
|
|
22
18
|
throw std::runtime_error("Error with SurfaceConfiguration");
|
|
23
19
|
}
|
|
20
|
+
// viewFormats are deep-copied into SurfaceInfo (which outlives this call);
|
|
21
|
+
// Convertor-allocated arrays would dangle.
|
|
22
|
+
std::vector<wgpu::TextureFormat> viewFormats;
|
|
23
|
+
if (configuration->viewFormats.has_value()) {
|
|
24
|
+
viewFormats = configuration->viewFormats.value();
|
|
25
|
+
}
|
|
24
26
|
|
|
25
27
|
#ifdef __APPLE__
|
|
26
28
|
surfaceConfiguration.alphaMode = configuration->alphaMode;
|
|
27
29
|
#endif
|
|
28
30
|
surfaceConfiguration.presentMode = wgpu::PresentMode::Fifo;
|
|
29
|
-
_surfaceInfo->configure(surfaceConfiguration);
|
|
31
|
+
_surfaceInfo->configure(surfaceConfiguration, std::move(viewFormats));
|
|
30
32
|
}
|
|
31
33
|
|
|
32
|
-
void GPUCanvasContext::unconfigure() {}
|
|
34
|
+
void GPUCanvasContext::unconfigure() { _surfaceInfo->unconfigure(); }
|
|
33
35
|
|
|
34
36
|
std::shared_ptr<GPUTexture> GPUCanvasContext::getCurrentTexture() {
|
|
37
|
+
if (!_surfaceInfo->isConfigured()) {
|
|
38
|
+
// Web parity: on the web this is an InvalidStateError, not a crash.
|
|
39
|
+
throw std::runtime_error(
|
|
40
|
+
"[WebGPU] getCurrentTexture() called on a canvas context that is not "
|
|
41
|
+
"configured; call context.configure() first");
|
|
42
|
+
}
|
|
43
|
+
// The drawing buffer tracks canvas.width/height (like on the web); resize it
|
|
44
|
+
// lazily when they changed. Sizes are clamped to 1 so a canvas that has not
|
|
45
|
+
// been laid out yet (0x0) keeps working.
|
|
35
46
|
auto prevSize = _surfaceInfo->getConfig();
|
|
36
|
-
auto width = _canvas->getWidth();
|
|
37
|
-
auto height = _canvas->getHeight();
|
|
38
|
-
auto sizeHasChanged = prevSize.width != width ||
|
|
47
|
+
auto width = std::max(1, _canvas->getWidth());
|
|
48
|
+
auto height = std::max(1, _canvas->getHeight());
|
|
49
|
+
auto sizeHasChanged = prevSize.width != static_cast<uint32_t>(width) ||
|
|
50
|
+
prevSize.height != static_cast<uint32_t>(height);
|
|
39
51
|
if (sizeHasChanged) {
|
|
40
52
|
_surfaceInfo->reconfigure(width, height);
|
|
41
53
|
}
|
|
42
54
|
|
|
43
55
|
auto texture = _surfaceInfo->getCurrentTexture();
|
|
56
|
+
if (texture == nullptr) {
|
|
57
|
+
throw std::runtime_error(
|
|
58
|
+
"[WebGPU] getCurrentTexture() failed to acquire a texture");
|
|
59
|
+
}
|
|
44
60
|
|
|
45
61
|
auto size = _surfaceInfo->getSize();
|
|
46
62
|
_canvas->setClientWidth(size.width);
|
|
@@ -52,13 +68,11 @@ std::shared_ptr<GPUTexture> GPUCanvasContext::getCurrentTexture() {
|
|
|
52
68
|
}
|
|
53
69
|
|
|
54
70
|
void GPUCanvasContext::present() {
|
|
55
|
-
//
|
|
56
|
-
//
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
_surfaceInfo->presentFrame();
|
|
61
|
-
}
|
|
71
|
+
// presentFrame() is the end-of-frame boundary: it presents when this frame's
|
|
72
|
+
// texture was acquired from the on-screen surface (offscreen and dropped
|
|
73
|
+
// frames are skipped), clears the frame state, and adopts any surface that
|
|
74
|
+
// attached while the frame was in flight.
|
|
75
|
+
_surfaceInfo->presentFrame();
|
|
62
76
|
}
|
|
63
77
|
|
|
64
78
|
} // namespace rnwgpu
|
|
@@ -57,7 +57,9 @@ public:
|
|
|
57
57
|
std::shared_ptr<GPUTexture> getCurrentTexture();
|
|
58
58
|
// Present is explicit on every runtime (main JS, Reanimated UI, and dedicated
|
|
59
59
|
// worklet runtimes). It runs synchronously on the calling thread, preserving
|
|
60
|
-
// Dawn surface thread-affinity; offscreen
|
|
60
|
+
// Dawn surface thread-affinity; frames rendered offscreen (no surface
|
|
61
|
+
// attached) are skipped. It is also the end-of-frame boundary at which a
|
|
62
|
+
// newly attached native surface is adopted (see SurfaceInfo).
|
|
61
63
|
void present();
|
|
62
64
|
|
|
63
65
|
private:
|
|
@@ -348,6 +348,7 @@ std::shared_ptr<GPUSharedFence> GPUDevice::importSharedFence(
|
|
|
348
348
|
}
|
|
349
349
|
|
|
350
350
|
async::AsyncTaskHandle GPUDevice::createComputePipelineAsync(
|
|
351
|
+
jsi::Runtime &runtime,
|
|
351
352
|
std::shared_ptr<GPUComputePipelineDescriptor> descriptor) {
|
|
352
353
|
wgpu::ComputePipelineDescriptor desc{};
|
|
353
354
|
Convertor conv;
|
|
@@ -360,12 +361,16 @@ async::AsyncTaskHandle GPUDevice::createComputePipelineAsync(
|
|
|
360
361
|
descriptor->label.has_value() ? descriptor->label.value() : "");
|
|
361
362
|
auto pipelineHolder = std::make_shared<GPUComputePipeline>(nullptr, label);
|
|
362
363
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
364
|
+
// Post to the CALLING runtime's context so the promise settles on the
|
|
365
|
+
// thread that requested it (see GPUBuffer::mapAsync).
|
|
366
|
+
auto context =
|
|
367
|
+
async::RuntimeContext::getOrCreate(runtime, _async->instance());
|
|
368
|
+
return context->postTask([device = _instance, desc, descriptor,
|
|
369
|
+
pipelineHolder](
|
|
370
|
+
const async::AsyncTaskHandle::ResolveFunction
|
|
371
|
+
&resolve,
|
|
372
|
+
const async::AsyncTaskHandle::RejectFunction
|
|
373
|
+
&reject) {
|
|
369
374
|
(void)descriptor;
|
|
370
375
|
device.CreateComputePipelineAsync(
|
|
371
376
|
&desc, wgpu::CallbackMode::AllowProcessEvents,
|
|
@@ -389,6 +394,7 @@ async::AsyncTaskHandle GPUDevice::createComputePipelineAsync(
|
|
|
389
394
|
}
|
|
390
395
|
|
|
391
396
|
async::AsyncTaskHandle GPUDevice::createRenderPipelineAsync(
|
|
397
|
+
jsi::Runtime &runtime,
|
|
392
398
|
std::shared_ptr<GPURenderPipelineDescriptor> descriptor) {
|
|
393
399
|
wgpu::RenderPipelineDescriptor desc{};
|
|
394
400
|
Convertor conv;
|
|
@@ -402,12 +408,16 @@ async::AsyncTaskHandle GPUDevice::createRenderPipelineAsync(
|
|
|
402
408
|
descriptor->label.has_value() ? descriptor->label.value() : "");
|
|
403
409
|
auto pipelineHolder = std::make_shared<GPURenderPipeline>(nullptr, label);
|
|
404
410
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
+
// Post to the CALLING runtime's context so the promise settles on the
|
|
412
|
+
// thread that requested it (see GPUBuffer::mapAsync).
|
|
413
|
+
auto context =
|
|
414
|
+
async::RuntimeContext::getOrCreate(runtime, _async->instance());
|
|
415
|
+
return context->postTask([device = _instance, desc, descriptor,
|
|
416
|
+
pipelineHolder](
|
|
417
|
+
const async::AsyncTaskHandle::ResolveFunction
|
|
418
|
+
&resolve,
|
|
419
|
+
const async::AsyncTaskHandle::RejectFunction
|
|
420
|
+
&reject) {
|
|
411
421
|
(void)descriptor;
|
|
412
422
|
device.CreateRenderPipelineAsync(
|
|
413
423
|
&desc, wgpu::CallbackMode::AllowProcessEvents,
|
|
@@ -433,13 +443,18 @@ void GPUDevice::pushErrorScope(wgpu::ErrorFilter filter) {
|
|
|
433
443
|
_instance.PushErrorScope(filter);
|
|
434
444
|
}
|
|
435
445
|
|
|
436
|
-
async::AsyncTaskHandle GPUDevice::popErrorScope() {
|
|
446
|
+
async::AsyncTaskHandle GPUDevice::popErrorScope(jsi::Runtime &runtime) {
|
|
437
447
|
auto device = _instance;
|
|
438
448
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
449
|
+
// Post to the CALLING runtime's context so the promise settles on the
|
|
450
|
+
// thread that requested it (see GPUBuffer::mapAsync).
|
|
451
|
+
auto context =
|
|
452
|
+
async::RuntimeContext::getOrCreate(runtime, _async->instance());
|
|
453
|
+
return context->postTask([device](
|
|
454
|
+
const async::AsyncTaskHandle::ResolveFunction
|
|
455
|
+
&resolve,
|
|
456
|
+
const async::AsyncTaskHandle::RejectFunction
|
|
457
|
+
&reject) {
|
|
443
458
|
device.PopErrorScope(
|
|
444
459
|
wgpu::CallbackMode::AllowProcessEvents,
|
|
445
460
|
[resolve, reject](wgpu::PopErrorScopeStatus status,
|
|
@@ -136,8 +136,10 @@ public:
|
|
|
136
136
|
std::shared_ptr<GPURenderPipeline>
|
|
137
137
|
createRenderPipeline(std::shared_ptr<GPURenderPipelineDescriptor> descriptor);
|
|
138
138
|
async::AsyncTaskHandle createComputePipelineAsync(
|
|
139
|
+
jsi::Runtime &runtime,
|
|
139
140
|
std::shared_ptr<GPUComputePipelineDescriptor> descriptor);
|
|
140
141
|
async::AsyncTaskHandle createRenderPipelineAsync(
|
|
142
|
+
jsi::Runtime &runtime,
|
|
141
143
|
std::shared_ptr<GPURenderPipelineDescriptor> descriptor);
|
|
142
144
|
std::shared_ptr<GPUCommandEncoder> createCommandEncoder(
|
|
143
145
|
std::optional<std::shared_ptr<GPUCommandEncoderDescriptor>> descriptor);
|
|
@@ -146,7 +148,7 @@ public:
|
|
|
146
148
|
std::shared_ptr<GPUQuerySet>
|
|
147
149
|
createQuerySet(std::shared_ptr<GPUQuerySetDescriptor> descriptor);
|
|
148
150
|
void pushErrorScope(wgpu::ErrorFilter filter);
|
|
149
|
-
async::AsyncTaskHandle popErrorScope();
|
|
151
|
+
async::AsyncTaskHandle popErrorScope(jsi::Runtime &runtime);
|
|
150
152
|
|
|
151
153
|
std::unordered_set<std::string> getFeatures();
|
|
152
154
|
std::shared_ptr<GPUSupportedLimits> getLimits();
|
|
@@ -192,10 +194,10 @@ public:
|
|
|
192
194
|
&GPUDevice::createComputePipeline);
|
|
193
195
|
installMethod(runtime, prototype, "createRenderPipeline",
|
|
194
196
|
&GPUDevice::createRenderPipeline);
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
197
|
+
installMethodWithRuntime(runtime, prototype, "createComputePipelineAsync",
|
|
198
|
+
&GPUDevice::createComputePipelineAsync);
|
|
199
|
+
installMethodWithRuntime(runtime, prototype, "createRenderPipelineAsync",
|
|
200
|
+
&GPUDevice::createRenderPipelineAsync);
|
|
199
201
|
installMethod(runtime, prototype, "createCommandEncoder",
|
|
200
202
|
&GPUDevice::createCommandEncoder);
|
|
201
203
|
installMethod(runtime, prototype, "createRenderBundleEncoder",
|
|
@@ -204,8 +206,8 @@ public:
|
|
|
204
206
|
&GPUDevice::createQuerySet);
|
|
205
207
|
installMethod(runtime, prototype, "pushErrorScope",
|
|
206
208
|
&GPUDevice::pushErrorScope);
|
|
207
|
-
|
|
208
|
-
|
|
209
|
+
installMethodWithRuntime(runtime, prototype, "popErrorScope",
|
|
210
|
+
&GPUDevice::popErrorScope);
|
|
209
211
|
installGetter(runtime, prototype, "features", &GPUDevice::getFeatures);
|
|
210
212
|
installGetter(runtime, prototype, "limits", &GPUDevice::getLimits);
|
|
211
213
|
installGetter(runtime, prototype, "queue", &GPUDevice::getQueue);
|
|
@@ -78,9 +78,13 @@ void GPUQueue::writeBuffer(std::shared_ptr<GPUBuffer> buffer,
|
|
|
78
78
|
static_cast<size_t>(size64));
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
async::AsyncTaskHandle GPUQueue::onSubmittedWorkDone() {
|
|
81
|
+
async::AsyncTaskHandle GPUQueue::onSubmittedWorkDone(jsi::Runtime &runtime) {
|
|
82
82
|
auto queue = _instance;
|
|
83
|
-
|
|
83
|
+
// Post to the CALLING runtime's context so the promise settles on the
|
|
84
|
+
// thread that requested it (see GPUBuffer::mapAsync).
|
|
85
|
+
auto context =
|
|
86
|
+
async::RuntimeContext::getOrCreate(runtime, _async->instance());
|
|
87
|
+
return context->postTask(
|
|
84
88
|
[queue](const async::AsyncTaskHandle::ResolveFunction &resolve,
|
|
85
89
|
const async::AsyncTaskHandle::RejectFunction &reject) {
|
|
86
90
|
queue.OnSubmittedWorkDone(
|
|
@@ -37,7 +37,7 @@ public:
|
|
|
37
37
|
std::string getBrand() { return CLASS_NAME; }
|
|
38
38
|
|
|
39
39
|
void submit(std::vector<std::shared_ptr<GPUCommandBuffer>> commandBuffers);
|
|
40
|
-
async::AsyncTaskHandle onSubmittedWorkDone();
|
|
40
|
+
async::AsyncTaskHandle onSubmittedWorkDone(jsi::Runtime &runtime);
|
|
41
41
|
void writeBuffer(std::shared_ptr<GPUBuffer> buffer, uint64_t bufferOffset,
|
|
42
42
|
std::shared_ptr<ArrayBuffer> data,
|
|
43
43
|
std::optional<uint64_t> dataOffsetElements,
|
|
@@ -60,8 +60,8 @@ public:
|
|
|
60
60
|
static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) {
|
|
61
61
|
installGetter(runtime, prototype, "__brand", &GPUQueue::getBrand);
|
|
62
62
|
installMethod(runtime, prototype, "submit", &GPUQueue::submit);
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
installMethodWithRuntime(runtime, prototype, "onSubmittedWorkDone",
|
|
64
|
+
&GPUQueue::onSubmittedWorkDone);
|
|
65
65
|
installMethod(runtime, prototype, "writeBuffer", &GPUQueue::writeBuffer);
|
|
66
66
|
installMethod(runtime, prototype, "writeTexture", &GPUQueue::writeTexture);
|
|
67
67
|
installMethod(runtime, prototype, "copyExternalImageToTexture",
|
|
@@ -7,10 +7,15 @@
|
|
|
7
7
|
|
|
8
8
|
namespace rnwgpu {
|
|
9
9
|
|
|
10
|
-
async::AsyncTaskHandle
|
|
10
|
+
async::AsyncTaskHandle
|
|
11
|
+
GPUShaderModule::getCompilationInfo(jsi::Runtime &runtime) {
|
|
11
12
|
auto module = _instance;
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
// Post to the CALLING runtime's context so the promise settles on the
|
|
15
|
+
// thread that requested it (see GPUBuffer::mapAsync).
|
|
16
|
+
auto context =
|
|
17
|
+
async::RuntimeContext::getOrCreate(runtime, _async->instance());
|
|
18
|
+
return context->postTask(
|
|
14
19
|
[module](const async::AsyncTaskHandle::ResolveFunction &resolve,
|
|
15
20
|
const async::AsyncTaskHandle::RejectFunction &reject) {
|
|
16
21
|
auto result = std::make_shared<GPUCompilationInfo>();
|
|
@@ -31,7 +31,7 @@ public:
|
|
|
31
31
|
public:
|
|
32
32
|
std::string getBrand() { return CLASS_NAME; }
|
|
33
33
|
|
|
34
|
-
async::AsyncTaskHandle getCompilationInfo();
|
|
34
|
+
async::AsyncTaskHandle getCompilationInfo(jsi::Runtime &runtime);
|
|
35
35
|
|
|
36
36
|
std::string getLabel() { return _label; }
|
|
37
37
|
void setLabel(const std::string &label) {
|
|
@@ -41,8 +41,8 @@ public:
|
|
|
41
41
|
|
|
42
42
|
static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) {
|
|
43
43
|
installGetter(runtime, prototype, "__brand", &GPUShaderModule::getBrand);
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
installMethodWithRuntime(runtime, prototype, "getCompilationInfo",
|
|
45
|
+
&GPUShaderModule::getCompilationInfo);
|
|
46
46
|
installGetterSetter(runtime, prototype, "label", &GPUShaderModule::getLabel,
|
|
47
47
|
&GPUShaderModule::setLabel);
|
|
48
48
|
}
|
|
@@ -173,7 +173,8 @@ public:
|
|
|
173
173
|
return std::make_shared<VideoFrame>(std::move(frame));
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
std::shared_ptr<VideoFrame> createTestVideoFrame(double width,
|
|
176
|
+
std::shared_ptr<VideoFrame> createTestVideoFrame(double width,
|
|
177
|
+
double height) {
|
|
177
178
|
auto frame = _platformContext->createTestVideoFrame(
|
|
178
179
|
static_cast<uint32_t>(width), static_cast<uint32_t>(height));
|
|
179
180
|
return std::make_shared<VideoFrame>(std::move(frame));
|
|
@@ -211,6 +212,24 @@ public:
|
|
|
211
212
|
nativeInfo.height);
|
|
212
213
|
}
|
|
213
214
|
|
|
215
|
+
// Retires a canvas context from the JS side (Canvas unmount cleanup).
|
|
216
|
+
// Registry entries have two owners, split by whether a native surface is
|
|
217
|
+
// attached:
|
|
218
|
+
// - A native view currently owns a surface (or one is pending): its own
|
|
219
|
+
// teardown (MetalView dealloc / WebGPUViewManager.onDropViewInstance)
|
|
220
|
+
// removes the entry. Skipping here keeps React StrictMode safe: its
|
|
221
|
+
// simulated unmount re-runs JS effects without unmounting native views,
|
|
222
|
+
// and removing the entry then would orphan the still-attached surface.
|
|
223
|
+
// - No native surface: the JS side is the last owner and removes the entry.
|
|
224
|
+
// The check-and-erase runs atomically under the registry lock
|
|
225
|
+
// (removeSurfaceInfoIfDetached), serialized against the UI thread's
|
|
226
|
+
// find-or-create + attach (SurfaceRegistry::attachSurface), so a concurrent
|
|
227
|
+
// attach can never be orphaned by this removal.
|
|
228
|
+
void destroyContext(int contextId) {
|
|
229
|
+
auto ®istry = rnwgpu::SurfaceRegistry::getInstance();
|
|
230
|
+
registry.removeSurfaceInfoIfDetached(contextId);
|
|
231
|
+
}
|
|
232
|
+
|
|
214
233
|
static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) {
|
|
215
234
|
installGetter(runtime, prototype, "fabric", &RNWebGPU::getFabric);
|
|
216
235
|
installGetter(runtime, prototype, "gpu", &RNWebGPU::getGPU);
|
|
@@ -218,6 +237,8 @@ public:
|
|
|
218
237
|
&RNWebGPU::createImageBitmap);
|
|
219
238
|
installMethod(runtime, prototype, "getNativeSurface",
|
|
220
239
|
&RNWebGPU::getNativeSurface);
|
|
240
|
+
installMethod(runtime, prototype, "destroyContext",
|
|
241
|
+
&RNWebGPU::destroyContext);
|
|
221
242
|
installMethod(runtime, prototype, "MakeWebGPUCanvasContext",
|
|
222
243
|
&RNWebGPU::MakeWebGPUCanvasContext);
|
|
223
244
|
installMethod(runtime, prototype, "loadVideoFrame",
|
|
@@ -56,8 +56,15 @@ namespace rnwgpu::async {
|
|
|
56
56
|
* ProcessEvents on one instance is not guaranteed reentrant.
|
|
57
57
|
*
|
|
58
58
|
* Threading contract: a RuntimeContext must only be pumped from the runtime it
|
|
59
|
-
* was created for.
|
|
60
|
-
*
|
|
59
|
+
* was created for. Request/response async entry points (mapAsync,
|
|
60
|
+
* onSubmittedWorkDone, popErrorScope, createComputePipelineAsync,
|
|
61
|
+
* createRenderPipelineAsync, getCompilationInfo, requestAdapter,
|
|
62
|
+
* requestDevice) must NOT use a context captured when the object was created —
|
|
63
|
+
* the object may have been boxed across to another runtime. They resolve the
|
|
64
|
+
* CALLING runtime's context via getOrCreate(runtime, instance) so the promise
|
|
65
|
+
* is settled on the thread it was created on. Spontaneous events (device.lost,
|
|
66
|
+
* uncapturederror) remain bound to the device's own context (best-effort, main
|
|
67
|
+
* runtime only; see the class doc above).
|
|
61
68
|
*/
|
|
62
69
|
class RuntimeContext : public std::enable_shared_from_this<RuntimeContext> {
|
|
63
70
|
public:
|
package/lib/commonjs/Canvas.js
CHANGED
|
@@ -21,6 +21,16 @@ const Canvas = ({
|
|
|
21
21
|
}) => {
|
|
22
22
|
const viewRef = (0, _react.useRef)(null);
|
|
23
23
|
const [contextId, _] = (0, _react.useState)(() => generateContextId());
|
|
24
|
+
// Retire the native registry entry for this contextId on unmount. When a
|
|
25
|
+
// native surface is still attached, this is a no-op and the native view's
|
|
26
|
+
// own teardown retires the entry instead — which keeps StrictMode's
|
|
27
|
+
// simulated unmount (which re-runs effects without unmounting native views)
|
|
28
|
+
// from orphaning a live surface.
|
|
29
|
+
(0, _react.useEffect)(() => {
|
|
30
|
+
return () => {
|
|
31
|
+
RNWebGPU.destroyContext(contextId);
|
|
32
|
+
};
|
|
33
|
+
}, [contextId]);
|
|
24
34
|
(0, _react.useImperativeHandle)(ref, () => ({
|
|
25
35
|
getContextId: () => contextId,
|
|
26
36
|
getNativeSurface: () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_WebGPUViewNativeComponent","_interopRequireDefault","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","_extends","assign","bind","arguments","length","apply","CONTEXT_COUNTER","generateContextId","Canvas","transparent","ref","props","viewRef","useRef","contextId","_","useState","useImperativeHandle","getContextId","getNativeSurface","
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_WebGPUViewNativeComponent","_interopRequireDefault","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","_extends","assign","bind","arguments","length","apply","CONTEXT_COUNTER","generateContextId","Canvas","transparent","ref","props","viewRef","useRef","contextId","_","useState","useEffect","RNWebGPU","destroyContext","useImperativeHandle","getContextId","getNativeSurface","getContext","contextName","Error","current","view","size","getBoundingClientRect","unstable_getBoundingClientRect","MakeWebGPUCanvasContext","width","height","createElement","View","collapsable","style","flex","exports"],"sourceRoot":"../../src","sources":["Canvas.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -43,6 +43,8 @@ function makeWebGPUCanvasContext(contextId, width, height) {
|
|
|
43
43
|
window.RNWebGPU = {
|
|
44
44
|
getNativeSurface,
|
|
45
45
|
MakeWebGPUCanvasContext: makeWebGPUCanvasContext,
|
|
46
|
+
// On web the browser owns the canvas/context lifecycle; nothing to retire.
|
|
47
|
+
destroyContext: _contextId => {},
|
|
46
48
|
fabric
|
|
47
49
|
};
|
|
48
50
|
//# sourceMappingURL=WebPolyfillGPUModule.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_utils","require","fabric","getNativeSurface","contextId","canvas","document","getElementById","contextIdToId","height","width","getBoundingClientRect","surface","BigInt","clientHeight","clientWidth","addEventListener","bind","removeEventListener","dispatchEvent","setPointerCapture","releasePointerCapture","makeWebGPUCanvasContext","dpr","window","devicePixelRatio","pixelWidth","toString","pixelHeight","getAttribute","setAttribute","context","getContext","Object","assign","present","RNWebGPU","MakeWebGPUCanvasContext"],"sourceRoot":"../../src","sources":["WebPolyfillGPUModule.ts"],"mappings":";;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAEA,MAAMC,MAAM,GAAG,IAAI;AAEnB,SAASC,gBAAgBA,CAACC,SAAiB,EAAE;EAC3C,MAAMC,MAAM,GAAGC,QAAQ,CAACC,cAAc,CACpC,IAAAC,oBAAa,EAACJ,SAAS,CACzB,CAAsB;EAEtB,MAAM;IAAEK,MAAM;IAAEC;EAAM,CAAC,GAAGL,MAAM,CAACM,qBAAqB,CAAC,CAAE;EAEzD,OAAO;IACLC,OAAO,EAAEC,MAAM,CAACT,SAAS,CAAC;IAC1BK,MAAM;IACNC,KAAK;IACLI,YAAY,EAAEL,MAAM;IACpBM,WAAW,EAAEL,KAAK;IAClB;IACAM,gBAAgB,EAAEX,MAAM,CAACW,gBAAgB,CAACC,IAAI,CAACZ,MAAM,CAAC;IACtDa,mBAAmB,EAAEb,MAAM,CAACa,mBAAmB,CAACD,IAAI,CAACZ,MAAM,CAAC;IAC5Dc,aAAa,EAAEd,MAAM,CAACc,aAAa,CAACF,IAAI,CAACZ,MAAM,CAAC;IAChDe,iBAAiB,EAAEf,MAAM,CAACe,iBAAiB,CAACH,IAAI,CAACZ,MAAM,CAAC;IACxDgB,qBAAqB,EAAEhB,MAAM,CAACgB,qBAAqB,CAACJ,IAAI,CAACZ,MAAM;EACjE,CAAC;AACH;AAEA,SAASiB,uBAAuBA,CAC9BlB,SAAiB,EACjBM,KAAa,EACbD,MAAc,EACd;EACA,MAAMJ,MAAM,GAAGC,QAAQ,CAACC,cAAc,CACpC,IAAAC,oBAAa,EAACJ,SAAS,CACzB,CAAsB;EAEtB,MAAMmB,GAAG,GAAGC,MAAM,CAACC,gBAAgB,IAAI,CAAC;EACxC,MAAMC,UAAU,GAAG,CAAChB,KAAK,GAAGa,GAAG,EAAEI,QAAQ,CAAC,CAAC;EAC3C,MAAMC,WAAW,GAAG,CAACnB,MAAM,GAAGc,GAAG,EAAEI,QAAQ,CAAC,CAAC;EAE7C,IACEtB,MAAM,CAACwB,YAAY,CAAC,OAAO,CAAC,KAAKH,UAAU,IAC3CrB,MAAM,CAACwB,YAAY,CAAC,QAAQ,CAAC,KAAKD,WAAW,EAC7C;IACAvB,MAAM,CAACyB,YAAY,CAAC,OAAO,EAAEJ,UAAU,CAAC;IACxCrB,MAAM,CAACyB,YAAY,CAAC,QAAQ,EAAEF,WAAW,CAAC;EAC5C;EAEA,MAAMG,OAAO,GAAG1B,MAAM,CAAC2B,UAAU,CAAC,QAAQ,CAAE;EAC5C;EACA;EACA,OAAOC,MAAM,CAACC,MAAM,CAACH,OAAO,EAAE;IAAEI,OAAO,EAAEA,CAAA,KAAM,CAAC;EAAE,CAAC,CAAC;AACtD;;AAEA;AACAX,MAAM,CAACY,QAAQ,GAAG;EAChBjC,gBAAgB;EAChBkC,uBAAuB,EAAEf,uBAAuB;
|
|
1
|
+
{"version":3,"names":["_utils","require","fabric","getNativeSurface","contextId","canvas","document","getElementById","contextIdToId","height","width","getBoundingClientRect","surface","BigInt","clientHeight","clientWidth","addEventListener","bind","removeEventListener","dispatchEvent","setPointerCapture","releasePointerCapture","makeWebGPUCanvasContext","dpr","window","devicePixelRatio","pixelWidth","toString","pixelHeight","getAttribute","setAttribute","context","getContext","Object","assign","present","RNWebGPU","MakeWebGPUCanvasContext","destroyContext","_contextId"],"sourceRoot":"../../src","sources":["WebPolyfillGPUModule.ts"],"mappings":";;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAEA,MAAMC,MAAM,GAAG,IAAI;AAEnB,SAASC,gBAAgBA,CAACC,SAAiB,EAAE;EAC3C,MAAMC,MAAM,GAAGC,QAAQ,CAACC,cAAc,CACpC,IAAAC,oBAAa,EAACJ,SAAS,CACzB,CAAsB;EAEtB,MAAM;IAAEK,MAAM;IAAEC;EAAM,CAAC,GAAGL,MAAM,CAACM,qBAAqB,CAAC,CAAE;EAEzD,OAAO;IACLC,OAAO,EAAEC,MAAM,CAACT,SAAS,CAAC;IAC1BK,MAAM;IACNC,KAAK;IACLI,YAAY,EAAEL,MAAM;IACpBM,WAAW,EAAEL,KAAK;IAClB;IACAM,gBAAgB,EAAEX,MAAM,CAACW,gBAAgB,CAACC,IAAI,CAACZ,MAAM,CAAC;IACtDa,mBAAmB,EAAEb,MAAM,CAACa,mBAAmB,CAACD,IAAI,CAACZ,MAAM,CAAC;IAC5Dc,aAAa,EAAEd,MAAM,CAACc,aAAa,CAACF,IAAI,CAACZ,MAAM,CAAC;IAChDe,iBAAiB,EAAEf,MAAM,CAACe,iBAAiB,CAACH,IAAI,CAACZ,MAAM,CAAC;IACxDgB,qBAAqB,EAAEhB,MAAM,CAACgB,qBAAqB,CAACJ,IAAI,CAACZ,MAAM;EACjE,CAAC;AACH;AAEA,SAASiB,uBAAuBA,CAC9BlB,SAAiB,EACjBM,KAAa,EACbD,MAAc,EACd;EACA,MAAMJ,MAAM,GAAGC,QAAQ,CAACC,cAAc,CACpC,IAAAC,oBAAa,EAACJ,SAAS,CACzB,CAAsB;EAEtB,MAAMmB,GAAG,GAAGC,MAAM,CAACC,gBAAgB,IAAI,CAAC;EACxC,MAAMC,UAAU,GAAG,CAAChB,KAAK,GAAGa,GAAG,EAAEI,QAAQ,CAAC,CAAC;EAC3C,MAAMC,WAAW,GAAG,CAACnB,MAAM,GAAGc,GAAG,EAAEI,QAAQ,CAAC,CAAC;EAE7C,IACEtB,MAAM,CAACwB,YAAY,CAAC,OAAO,CAAC,KAAKH,UAAU,IAC3CrB,MAAM,CAACwB,YAAY,CAAC,QAAQ,CAAC,KAAKD,WAAW,EAC7C;IACAvB,MAAM,CAACyB,YAAY,CAAC,OAAO,EAAEJ,UAAU,CAAC;IACxCrB,MAAM,CAACyB,YAAY,CAAC,QAAQ,EAAEF,WAAW,CAAC;EAC5C;EAEA,MAAMG,OAAO,GAAG1B,MAAM,CAAC2B,UAAU,CAAC,QAAQ,CAAE;EAC5C;EACA;EACA,OAAOC,MAAM,CAACC,MAAM,CAACH,OAAO,EAAE;IAAEI,OAAO,EAAEA,CAAA,KAAM,CAAC;EAAE,CAAC,CAAC;AACtD;;AAEA;AACAX,MAAM,CAACY,QAAQ,GAAG;EAChBjC,gBAAgB;EAChBkC,uBAAuB,EAAEf,uBAAuB;EAChD;EACAgB,cAAc,EAAGC,UAAkB,IAAK,CAAC,CAAC;EAC1CrC;AACF,CAAC","ignoreList":[]}
|
package/lib/module/Canvas.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
2
|
-
import React, { useImperativeHandle, useRef, useState } from "react";
|
|
2
|
+
import React, { useEffect, useImperativeHandle, useRef, useState } from "react";
|
|
3
3
|
import { View } from "react-native";
|
|
4
4
|
import WebGPUNativeView from "./WebGPUViewNativeComponent";
|
|
5
5
|
let CONTEXT_COUNTER = 1;
|
|
@@ -13,6 +13,16 @@ export const Canvas = ({
|
|
|
13
13
|
}) => {
|
|
14
14
|
const viewRef = useRef(null);
|
|
15
15
|
const [contextId, _] = useState(() => generateContextId());
|
|
16
|
+
// Retire the native registry entry for this contextId on unmount. When a
|
|
17
|
+
// native surface is still attached, this is a no-op and the native view's
|
|
18
|
+
// own teardown retires the entry instead — which keeps StrictMode's
|
|
19
|
+
// simulated unmount (which re-runs effects without unmounting native views)
|
|
20
|
+
// from orphaning a live surface.
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
return () => {
|
|
23
|
+
RNWebGPU.destroyContext(contextId);
|
|
24
|
+
};
|
|
25
|
+
}, [contextId]);
|
|
16
26
|
useImperativeHandle(ref, () => ({
|
|
17
27
|
getContextId: () => contextId,
|
|
18
28
|
getNativeSurface: () => {
|
package/lib/module/Canvas.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","useImperativeHandle","useRef","useState","View","WebGPUNativeView","CONTEXT_COUNTER","generateContextId","Canvas","transparent","ref","props","viewRef","contextId","_","
|
|
1
|
+
{"version":3,"names":["React","useEffect","useImperativeHandle","useRef","useState","View","WebGPUNativeView","CONTEXT_COUNTER","generateContextId","Canvas","transparent","ref","props","viewRef","contextId","_","RNWebGPU","destroyContext","getContextId","getNativeSurface","getContext","contextName","Error","current","view","size","getBoundingClientRect","unstable_getBoundingClientRect","MakeWebGPUCanvasContext","width","height","createElement","_extends","collapsable","style","flex"],"sourceRoot":"../../src","sources":["Canvas.tsx"],"mappings":";AAAA,OAAOA,KAAK,IAAIC,SAAS,EAAEC,mBAAmB,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,OAAO;AAE/E,SAASC,IAAI,QAAQ,cAAc;AAEnC,OAAOC,gBAAgB,MAAM,6BAA6B;AAE1D,IAAIC,eAAe,GAAG,CAAC;AACvB,SAASC,iBAAiBA,CAAA,EAAG;EAC3B,OAAOD,eAAe,EAAE;AAC1B;AA2CA,OAAO,MAAME,MAAM,GAAGA,CAAC;EAAEC,WAAW;EAAEC,GAAG;EAAE,GAAGC;AAAmB,CAAC,KAAK;EACrE,MAAMC,OAAO,GAAGV,MAAM,CAAC,IAAI,CAAC;EAC5B,MAAM,CAACW,SAAS,EAAEC,CAAC,CAAC,GAAGX,QAAQ,CAAC,MAAMI,iBAAiB,CAAC,CAAC,CAAC;EAC1D;EACA;EACA;EACA;EACA;EACAP,SAAS,CAAC,MAAM;IACd,OAAO,MAAM;MACXe,QAAQ,CAACC,cAAc,CAACH,SAAS,CAAC;IACpC,CAAC;EACH,CAAC,EAAE,CAACA,SAAS,CAAC,CAAC;EACfZ,mBAAmB,CAACS,GAAG,EAAE,OAAO;IAC9BO,YAAY,EAAEA,CAAA,KAAMJ,SAAS;IAC7BK,gBAAgB,EAAEA,CAAA,KAAM;MACtB,OAAOH,QAAQ,CAACG,gBAAgB,CAACL,SAAS,CAAC;IAC7C,CAAC;IACDM,UAAUA,CAACC,WAAqB,EAA0B;MACxD,IAAIA,WAAW,KAAK,QAAQ,EAAE;QAC5B,MAAM,IAAIC,KAAK,CAAC,iCAAiCD,WAAW,EAAE,CAAC;MACjE;MACA,IAAI,CAACR,OAAO,CAACU,OAAO,EAAE;QACpB,MAAM,IAAID,KAAK,CAAC,0CAA0C,CAAC;MAC7D;MACA;MACA;MACA,MAAME,IAAI,GAAGX,OAAO,CAACU,OAAc;MACnC,MAAME,IAAI,GACR,uBAAuB,IAAID,IAAI,GAC3BA,IAAI,CAACE,qBAAqB,CAAC,CAAC,GAC5BF,IAAI,CAACG,8BAA8B,CAAC,CAAC;MAC3C,OAAOX,QAAQ,CAACY,uBAAuB,CACrCd,SAAS,EACTW,IAAI,CAACI,KAAK,EACVJ,IAAI,CAACK,MACP,CAAC;IACH;EACF,CAAC,CAAC,CAAC;EAEH,oBACE9B,KAAA,CAAA+B,aAAA,CAAC1B,IAAI,EAAA2B,QAAA;IAACC,WAAW,EAAE,KAAM;IAACtB,GAAG,EAAEE;EAAQ,GAAKD,KAAK,gBAC/CZ,KAAA,CAAA+B,aAAA,CAACzB,gBAAgB;IACf4B,KAAK,EAAE;MAAEC,IAAI,EAAE;IAAE,CAAE;IACnBrB,SAAS,EAAEA,SAAU;IACrBJ,WAAW,EAAE,CAAC,CAACA;EAAY,CAC5B,CACG,CAAC;AAEX,CAAC","ignoreList":[]}
|
|
@@ -41,6 +41,8 @@ function makeWebGPUCanvasContext(contextId, width, height) {
|
|
|
41
41
|
window.RNWebGPU = {
|
|
42
42
|
getNativeSurface,
|
|
43
43
|
MakeWebGPUCanvasContext: makeWebGPUCanvasContext,
|
|
44
|
+
// On web the browser owns the canvas/context lifecycle; nothing to retire.
|
|
45
|
+
destroyContext: _contextId => {},
|
|
44
46
|
fabric
|
|
45
47
|
};
|
|
46
48
|
//# sourceMappingURL=WebPolyfillGPUModule.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["contextIdToId","fabric","getNativeSurface","contextId","canvas","document","getElementById","height","width","getBoundingClientRect","surface","BigInt","clientHeight","clientWidth","addEventListener","bind","removeEventListener","dispatchEvent","setPointerCapture","releasePointerCapture","makeWebGPUCanvasContext","dpr","window","devicePixelRatio","pixelWidth","toString","pixelHeight","getAttribute","setAttribute","context","getContext","Object","assign","present","RNWebGPU","MakeWebGPUCanvasContext"],"sourceRoot":"../../src","sources":["WebPolyfillGPUModule.ts"],"mappings":"AAAA,SAASA,aAAa,QAAQ,SAAS;AAEvC,MAAMC,MAAM,GAAG,IAAI;AAEnB,SAASC,gBAAgBA,CAACC,SAAiB,EAAE;EAC3C,MAAMC,MAAM,GAAGC,QAAQ,CAACC,cAAc,CACpCN,aAAa,CAACG,SAAS,CACzB,CAAsB;EAEtB,MAAM;IAAEI,MAAM;IAAEC;EAAM,CAAC,GAAGJ,MAAM,CAACK,qBAAqB,CAAC,CAAE;EAEzD,OAAO;IACLC,OAAO,EAAEC,MAAM,CAACR,SAAS,CAAC;IAC1BI,MAAM;IACNC,KAAK;IACLI,YAAY,EAAEL,MAAM;IACpBM,WAAW,EAAEL,KAAK;IAClB;IACAM,gBAAgB,EAAEV,MAAM,CAACU,gBAAgB,CAACC,IAAI,CAACX,MAAM,CAAC;IACtDY,mBAAmB,EAAEZ,MAAM,CAACY,mBAAmB,CAACD,IAAI,CAACX,MAAM,CAAC;IAC5Da,aAAa,EAAEb,MAAM,CAACa,aAAa,CAACF,IAAI,CAACX,MAAM,CAAC;IAChDc,iBAAiB,EAAEd,MAAM,CAACc,iBAAiB,CAACH,IAAI,CAACX,MAAM,CAAC;IACxDe,qBAAqB,EAAEf,MAAM,CAACe,qBAAqB,CAACJ,IAAI,CAACX,MAAM;EACjE,CAAC;AACH;AAEA,SAASgB,uBAAuBA,CAC9BjB,SAAiB,EACjBK,KAAa,EACbD,MAAc,EACd;EACA,MAAMH,MAAM,GAAGC,QAAQ,CAACC,cAAc,CACpCN,aAAa,CAACG,SAAS,CACzB,CAAsB;EAEtB,MAAMkB,GAAG,GAAGC,MAAM,CAACC,gBAAgB,IAAI,CAAC;EACxC,MAAMC,UAAU,GAAG,CAAChB,KAAK,GAAGa,GAAG,EAAEI,QAAQ,CAAC,CAAC;EAC3C,MAAMC,WAAW,GAAG,CAACnB,MAAM,GAAGc,GAAG,EAAEI,QAAQ,CAAC,CAAC;EAE7C,IACErB,MAAM,CAACuB,YAAY,CAAC,OAAO,CAAC,KAAKH,UAAU,IAC3CpB,MAAM,CAACuB,YAAY,CAAC,QAAQ,CAAC,KAAKD,WAAW,EAC7C;IACAtB,MAAM,CAACwB,YAAY,CAAC,OAAO,EAAEJ,UAAU,CAAC;IACxCpB,MAAM,CAACwB,YAAY,CAAC,QAAQ,EAAEF,WAAW,CAAC;EAC5C;EAEA,MAAMG,OAAO,GAAGzB,MAAM,CAAC0B,UAAU,CAAC,QAAQ,CAAE;EAC5C;EACA;EACA,OAAOC,MAAM,CAACC,MAAM,CAACH,OAAO,EAAE;IAAEI,OAAO,EAAEA,CAAA,KAAM,CAAC;EAAE,CAAC,CAAC;AACtD;;AAEA;AACAX,MAAM,CAACY,QAAQ,GAAG;EAChBhC,gBAAgB;EAChBiC,uBAAuB,EAAEf,uBAAuB;
|
|
1
|
+
{"version":3,"names":["contextIdToId","fabric","getNativeSurface","contextId","canvas","document","getElementById","height","width","getBoundingClientRect","surface","BigInt","clientHeight","clientWidth","addEventListener","bind","removeEventListener","dispatchEvent","setPointerCapture","releasePointerCapture","makeWebGPUCanvasContext","dpr","window","devicePixelRatio","pixelWidth","toString","pixelHeight","getAttribute","setAttribute","context","getContext","Object","assign","present","RNWebGPU","MakeWebGPUCanvasContext","destroyContext","_contextId"],"sourceRoot":"../../src","sources":["WebPolyfillGPUModule.ts"],"mappings":"AAAA,SAASA,aAAa,QAAQ,SAAS;AAEvC,MAAMC,MAAM,GAAG,IAAI;AAEnB,SAASC,gBAAgBA,CAACC,SAAiB,EAAE;EAC3C,MAAMC,MAAM,GAAGC,QAAQ,CAACC,cAAc,CACpCN,aAAa,CAACG,SAAS,CACzB,CAAsB;EAEtB,MAAM;IAAEI,MAAM;IAAEC;EAAM,CAAC,GAAGJ,MAAM,CAACK,qBAAqB,CAAC,CAAE;EAEzD,OAAO;IACLC,OAAO,EAAEC,MAAM,CAACR,SAAS,CAAC;IAC1BI,MAAM;IACNC,KAAK;IACLI,YAAY,EAAEL,MAAM;IACpBM,WAAW,EAAEL,KAAK;IAClB;IACAM,gBAAgB,EAAEV,MAAM,CAACU,gBAAgB,CAACC,IAAI,CAACX,MAAM,CAAC;IACtDY,mBAAmB,EAAEZ,MAAM,CAACY,mBAAmB,CAACD,IAAI,CAACX,MAAM,CAAC;IAC5Da,aAAa,EAAEb,MAAM,CAACa,aAAa,CAACF,IAAI,CAACX,MAAM,CAAC;IAChDc,iBAAiB,EAAEd,MAAM,CAACc,iBAAiB,CAACH,IAAI,CAACX,MAAM,CAAC;IACxDe,qBAAqB,EAAEf,MAAM,CAACe,qBAAqB,CAACJ,IAAI,CAACX,MAAM;EACjE,CAAC;AACH;AAEA,SAASgB,uBAAuBA,CAC9BjB,SAAiB,EACjBK,KAAa,EACbD,MAAc,EACd;EACA,MAAMH,MAAM,GAAGC,QAAQ,CAACC,cAAc,CACpCN,aAAa,CAACG,SAAS,CACzB,CAAsB;EAEtB,MAAMkB,GAAG,GAAGC,MAAM,CAACC,gBAAgB,IAAI,CAAC;EACxC,MAAMC,UAAU,GAAG,CAAChB,KAAK,GAAGa,GAAG,EAAEI,QAAQ,CAAC,CAAC;EAC3C,MAAMC,WAAW,GAAG,CAACnB,MAAM,GAAGc,GAAG,EAAEI,QAAQ,CAAC,CAAC;EAE7C,IACErB,MAAM,CAACuB,YAAY,CAAC,OAAO,CAAC,KAAKH,UAAU,IAC3CpB,MAAM,CAACuB,YAAY,CAAC,QAAQ,CAAC,KAAKD,WAAW,EAC7C;IACAtB,MAAM,CAACwB,YAAY,CAAC,OAAO,EAAEJ,UAAU,CAAC;IACxCpB,MAAM,CAACwB,YAAY,CAAC,QAAQ,EAAEF,WAAW,CAAC;EAC5C;EAEA,MAAMG,OAAO,GAAGzB,MAAM,CAAC0B,UAAU,CAAC,QAAQ,CAAE;EAC5C;EACA;EACA,OAAOC,MAAM,CAACC,MAAM,CAACH,OAAO,EAAE;IAAEI,OAAO,EAAEA,CAAA,KAAM,CAAC;EAAE,CAAC,CAAC;AACtD;;AAEA;AACAX,MAAM,CAACY,QAAQ,GAAG;EAChBhC,gBAAgB;EAChBiC,uBAAuB,EAAEf,uBAAuB;EAChD;EACAgB,cAAc,EAAGC,UAAkB,IAAK,CAAC,CAAC;EAC1CpC;AACF,CAAC","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Canvas.d.ts","sourceRoot":"","sources":["../../../commonjs/Canvas.js"],"names":[],"mappings":";AAgBA;;;;
|
|
1
|
+
{"version":3,"file":"Canvas.d.ts","sourceRoot":"","sources":["../../../commonjs/Canvas.js"],"names":[],"mappings":";AAgBA;;;;QA8CC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Canvas.d.ts","sourceRoot":"","sources":["../../../module/Canvas.js"],"names":[],"mappings":"AAQO;;;;
|
|
1
|
+
{"version":3,"file":"Canvas.d.ts","sourceRoot":"","sources":["../../../module/Canvas.js"],"names":[],"mappings":"AAQO;;;;2DA8CN;qBApDoB,cAAc;kBADqC,OAAO"}
|