react-native-wgpu 0.1.4 → 0.1.6
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/README.md +43 -42
- package/android/cpp/AndroidPlatformContext.h +2 -1
- package/cpp/jsi/RNFJSIConverter.h +10 -0
- package/cpp/rnwgpu/SurfaceRegistry.h +1 -2
- package/cpp/rnwgpu/api/Canvas.h +3 -3
- package/cpp/rnwgpu/api/GPUBuffer.h +1 -1
- package/ios/WebGPUView.mm +14 -1
- package/lib/commonjs/Canvas.js.map +1 -1
- package/lib/commonjs/utils.js +2 -2
- package/lib/commonjs/utils.js.map +1 -1
- package/lib/module/Canvas.js.map +1 -1
- package/lib/module/utils.js +2 -2
- package/lib/module/utils.js.map +1 -1
- package/lib/typescript/lib/commonjs/utils.d.ts +1 -1
- package/lib/typescript/lib/commonjs/utils.d.ts.map +1 -1
- package/lib/typescript/lib/module/utils.d.ts +1 -1
- package/lib/typescript/lib/module/utils.d.ts.map +1 -1
- package/lib/typescript/src/Canvas.d.ts +3 -2
- package/lib/typescript/src/Canvas.d.ts.map +1 -1
- package/lib/typescript/src/__tests__/ArrayBuffer.spec.d.ts +2 -0
- package/lib/typescript/src/__tests__/ArrayBuffer.spec.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/Buffer.spec.d.ts +2 -0
- package/lib/typescript/src/__tests__/Buffer.spec.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/ComputeShader.spec.d.ts +2 -0
- package/lib/typescript/src/__tests__/ComputeShader.spec.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/Constants.spec.d.ts +2 -0
- package/lib/typescript/src/__tests__/Constants.spec.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/Device.spec.d.ts +2 -0
- package/lib/typescript/src/__tests__/Device.spec.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/ExternalTexture.spec.d.ts +2 -0
- package/lib/typescript/src/__tests__/ExternalTexture.spec.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/GPU.spec.d.ts +2 -0
- package/lib/typescript/src/__tests__/GPU.spec.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/ImageData.spec.d.ts +2 -0
- package/lib/typescript/src/__tests__/ImageData.spec.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/Shaders.spec.d.ts +2 -0
- package/lib/typescript/src/__tests__/Shaders.spec.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/Texture.spec.d.ts +2 -0
- package/lib/typescript/src/__tests__/Texture.spec.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/components/DrawingContext.d.ts +12 -0
- package/lib/typescript/src/__tests__/components/DrawingContext.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/components/Wireframe/Shaders.d.ts +3 -0
- package/lib/typescript/src/__tests__/components/Wireframe/Shaders.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/components/Wireframe/models.d.ts +29 -0
- package/lib/typescript/src/__tests__/components/Wireframe/models.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/components/Wireframe/utils.d.ts +5 -0
- package/lib/typescript/src/__tests__/components/Wireframe/utils.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/components/cube.d.ts +7 -0
- package/lib/typescript/src/__tests__/components/cube.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/components/meshes/mesh.d.ts +22 -0
- package/lib/typescript/src/__tests__/components/meshes/mesh.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/components/meshes/sphere.d.ts +12 -0
- package/lib/typescript/src/__tests__/components/meshes/sphere.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/components/meshes/stanfordDragon.d.ts +7 -0
- package/lib/typescript/src/__tests__/components/meshes/stanfordDragon.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/components/meshes/stanfordDragonData.d.ts +6 -0
- package/lib/typescript/src/__tests__/components/meshes/stanfordDragonData.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/components/meshes/teapot.d.ts +6 -0
- package/lib/typescript/src/__tests__/components/meshes/teapot.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/components/meshes/utils.d.ts +10 -0
- package/lib/typescript/src/__tests__/components/meshes/utils.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/components/triangle.d.ts +3 -0
- package/lib/typescript/src/__tests__/components/triangle.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/config.d.ts +3 -0
- package/lib/typescript/src/__tests__/config.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/demos/ABuffer.spec.d.ts +2 -0
- package/lib/typescript/src/__tests__/demos/ABuffer.spec.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/demos/Blur.spec.d.ts +2 -0
- package/lib/typescript/src/__tests__/demos/Blur.spec.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/demos/Cube.spec.d.ts +2 -0
- package/lib/typescript/src/__tests__/demos/Cube.spec.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/demos/FractalCube.spec.d.ts +2 -0
- package/lib/typescript/src/__tests__/demos/FractalCube.spec.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/demos/OcclusionQuery.spec.d.ts +2 -0
- package/lib/typescript/src/__tests__/demos/OcclusionQuery.spec.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/demos/RenderBundles.spec.d.ts +2 -0
- package/lib/typescript/src/__tests__/demos/RenderBundles.spec.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/demos/Triangle.spec.d.ts +2 -0
- package/lib/typescript/src/__tests__/demos/Triangle.spec.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/demos/Wireframe.spec.d.ts +2 -0
- package/lib/typescript/src/__tests__/demos/Wireframe.spec.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/globalSetup.d.ts +10 -0
- package/lib/typescript/src/__tests__/globalSetup.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/globalTeardown.d.ts +3 -0
- package/lib/typescript/src/__tests__/globalTeardown.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/setup.d.ts +62 -0
- package/lib/typescript/src/__tests__/setup.d.ts.map +1 -0
- package/lib/typescript/src/utils.d.ts +2 -1
- package/lib/typescript/src/utils.d.ts.map +1 -1
- package/libs/android/arm64-v8a/libwebgpu_dawn.so +0 -0
- package/libs/android/armeabi-v7a/libwebgpu_dawn.so +0 -0
- package/libs/android/x86/libwebgpu_dawn.so +0 -0
- package/libs/android/x86_64/libwebgpu_dawn.so +0 -0
- package/libs/{ios/libwebgpu_dawn.xcframework/ios-arm64 → apple/arm64_iphoneos}/libwebgpu_dawn.a +0 -0
- package/libs/{ios → apple}/arm64_iphonesimulator/libwebgpu_dawn.a +0 -0
- package/libs/{ios/libwebgpu_dawn.xcframework/xros-arm64 → apple/arm64_xros}/libwebgpu_dawn.a +0 -0
- package/libs/{ios → apple}/arm64_xrsimulator/libwebgpu_dawn.a +0 -0
- package/libs/{ios → apple}/libwebgpu_dawn.a +0 -0
- package/libs/apple/libwebgpu_dawn.xcframework/Info.plist +44 -0
- package/libs/{ios/arm64_iphoneos → apple/libwebgpu_dawn.xcframework/ios-arm64}/libwebgpu_dawn.a +0 -0
- package/libs/{ios → apple}/libwebgpu_dawn.xcframework/ios-arm64_x86_64-simulator/libwebgpu_dawn.a +0 -0
- package/libs/apple/libwebgpu_dawn_macosx.xcframework/Info.plist +28 -0
- package/libs/apple/libwebgpu_dawn_macosx.xcframework/macos-arm64_x86_64/libwebgpu_dawn.a +0 -0
- package/libs/{ios/libwebgpu_dawn.xcframework/xros-arm64_x86_64-simulator → apple}/libwebgpu_dawn_visionos.a +0 -0
- package/libs/{ios/libwebgpu_dawn.xcframework → apple/libwebgpu_dawn_visionos.xcframework}/Info.plist +0 -31
- package/libs/{ios/arm64_xros → apple/libwebgpu_dawn_visionos.xcframework/xros-arm64}/libwebgpu_dawn.a +0 -0
- package/libs/{ios → apple/libwebgpu_dawn_visionos.xcframework/xros-arm64_x86_64-simulator}/libwebgpu_dawn_visionos.a +0 -0
- package/libs/apple/universal_macosx/libwebgpu_dawn.a +0 -0
- package/libs/{ios → apple}/x86_64_iphonesimulator/libwebgpu_dawn.a +0 -0
- package/libs/{ios → apple}/x86_64_xrsimulator/libwebgpu_dawn.a +0 -0
- package/package.json +24 -24
- package/src/Canvas.tsx +4 -2
- package/src/__tests__/ArrayBuffer.spec.ts +76 -0
- package/src/__tests__/Buffer.spec.ts +357 -0
- package/src/__tests__/ComputeShader.spec.ts +375 -0
- package/src/__tests__/Constants.spec.ts +91 -0
- package/src/__tests__/Device.spec.ts +35 -0
- package/src/__tests__/ExternalTexture.spec.ts +284 -0
- package/src/__tests__/GPU.spec.ts +229 -0
- package/src/__tests__/ImageData.spec.ts +26 -0
- package/src/__tests__/Shaders.spec.ts +232 -0
- package/src/__tests__/Texture.spec.ts +191 -0
- package/src/__tests__/assets/Di-3d.png +0 -0
- package/src/__tests__/components/DrawingContext.ts +11 -0
- package/src/__tests__/components/Wireframe/Shaders.ts +138 -0
- package/src/__tests__/components/Wireframe/models.ts +113 -0
- package/src/__tests__/components/Wireframe/utils.ts +22 -0
- package/src/__tests__/components/cube.ts +51 -0
- package/src/__tests__/components/meshes/mesh.ts +96 -0
- package/src/__tests__/components/meshes/sphere.ts +103 -0
- package/src/__tests__/components/meshes/stanfordDragon.ts +44 -0
- package/src/__tests__/components/meshes/stanfordDragonData.ts +5 -0
- package/src/__tests__/components/meshes/teapot.ts +13 -0
- package/src/__tests__/components/meshes/utils.ts +235 -0
- package/src/__tests__/components/triangle.ts +17 -0
- package/src/__tests__/config.ts +2 -0
- package/src/__tests__/demos/ABuffer.spec.ts +885 -0
- package/src/__tests__/demos/Blur.spec.ts +397 -0
- package/src/__tests__/demos/Cube.spec.ts +925 -0
- package/src/__tests__/demos/FractalCube.spec.ts +239 -0
- package/src/__tests__/demos/OcclusionQuery.spec.ts +376 -0
- package/src/__tests__/demos/RenderBundles.spec.ts +579 -0
- package/src/__tests__/demos/Triangle.spec.ts +248 -0
- package/src/__tests__/demos/Wireframe.spec.ts +190 -0
- package/src/__tests__/globalSetup.ts +54 -0
- package/src/__tests__/globalTeardown.ts +11 -0
- package/src/__tests__/setup.ts +409 -0
- package/src/__tests__/snapshots/abuffer.png +0 -0
- package/src/__tests__/snapshots/asteroid.png +0 -0
- package/src/__tests__/snapshots/blur.png +0 -0
- package/src/__tests__/snapshots/buffer.png +0 -0
- package/src/__tests__/snapshots/constant-triangle.png +0 -0
- package/src/__tests__/snapshots/cube.png +0 -0
- package/src/__tests__/snapshots/f.png +0 -0
- package/src/__tests__/snapshots/f2.png +0 -0
- package/src/__tests__/snapshots/fractal-cubes.png +0 -0
- package/src/__tests__/snapshots/instanced-cubes.png +0 -0
- package/src/__tests__/snapshots/occlusion-query.png +0 -0
- package/src/__tests__/snapshots/ref.png +0 -0
- package/src/__tests__/snapshots/texture.png +0 -0
- package/src/__tests__/snapshots/textured-cube.png +0 -0
- package/src/__tests__/snapshots/triangle-msaa.png +0 -0
- package/src/__tests__/snapshots/triangle.png +0 -0
- package/src/__tests__/snapshots/two-cube.png +0 -0
- package/src/utils.ts +3 -1
- package/android/gradle.properties +0 -5
- package/react-native-wgpu.podspec +0 -53
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
/* eslint-disable max-len */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
+
/* eslint-disable no-var */
|
|
4
|
+
import fs from "fs";
|
|
5
|
+
import path from "path";
|
|
6
|
+
|
|
7
|
+
import puppeteer from "puppeteer";
|
|
8
|
+
import { PNG } from "pngjs";
|
|
9
|
+
import pixelmatch from "pixelmatch";
|
|
10
|
+
import type { mat4, vec3, mat3 } from "wgpu-matrix";
|
|
11
|
+
import type { Server, WebSocket } from "ws";
|
|
12
|
+
import type { Browser, Page } from "puppeteer";
|
|
13
|
+
|
|
14
|
+
import type { DrawingContext } from "./components/DrawingContext";
|
|
15
|
+
import { cubeVertexArray } from "./components/cube";
|
|
16
|
+
import { redFragWGSL, triangleVertWGSL } from "./components/triangle";
|
|
17
|
+
import { DEBUG, REFERENCE } from "./config";
|
|
18
|
+
|
|
19
|
+
jest.setTimeout(180 * 1000);
|
|
20
|
+
|
|
21
|
+
type TestOS = "ios" | "android" | "web" | "node";
|
|
22
|
+
|
|
23
|
+
declare global {
|
|
24
|
+
var testServer: Server;
|
|
25
|
+
var testClient: WebSocket;
|
|
26
|
+
var testOS: TestOS;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface GPUContext {
|
|
30
|
+
gpu: GPU;
|
|
31
|
+
adapter: GPUAdapter;
|
|
32
|
+
device: GPUDevice;
|
|
33
|
+
shaders: {
|
|
34
|
+
triangleVertWGSL: string;
|
|
35
|
+
redFragWGSL: string;
|
|
36
|
+
};
|
|
37
|
+
urls: {
|
|
38
|
+
fTexture: string;
|
|
39
|
+
};
|
|
40
|
+
assets: {
|
|
41
|
+
cubeVertexArray: Float32Array;
|
|
42
|
+
di3D: ImageData;
|
|
43
|
+
moon: ImageData;
|
|
44
|
+
saturn: ImageData;
|
|
45
|
+
};
|
|
46
|
+
ctx: DrawingContext;
|
|
47
|
+
mat4: typeof mat4;
|
|
48
|
+
vec3: typeof vec3;
|
|
49
|
+
mat3: typeof mat3;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
type Ctx = Record<string, unknown>;
|
|
53
|
+
|
|
54
|
+
type JSONValue =
|
|
55
|
+
| { [key: string]: JSONValue }
|
|
56
|
+
| JSONValue[]
|
|
57
|
+
| number
|
|
58
|
+
| string
|
|
59
|
+
| boolean
|
|
60
|
+
| null;
|
|
61
|
+
|
|
62
|
+
interface TestingClient {
|
|
63
|
+
eval<C = Ctx, R = JSONValue>(
|
|
64
|
+
fn: (ctx: GPUContext & C) => R | Promise<R>,
|
|
65
|
+
ctx?: C,
|
|
66
|
+
): Promise<R>;
|
|
67
|
+
OS: TestOS;
|
|
68
|
+
arch: "paper" | "fabric";
|
|
69
|
+
init(): Promise<void>;
|
|
70
|
+
dispose(): Promise<void>;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export let client: TestingClient;
|
|
74
|
+
|
|
75
|
+
beforeAll(async () => {
|
|
76
|
+
client = REFERENCE ? new ReferenceTestingClient() : new RemoteTestingClient();
|
|
77
|
+
await client.init();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
afterAll(async () => {
|
|
81
|
+
await client.dispose();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
class RemoteTestingClient implements TestingClient {
|
|
85
|
+
readonly OS = global.testOS;
|
|
86
|
+
readonly arch = global.testArch;
|
|
87
|
+
|
|
88
|
+
eval<C = Ctx, R = JSONValue>(
|
|
89
|
+
fn: (ctx: GPUContext & C) => R | Promise<R>,
|
|
90
|
+
context?: C,
|
|
91
|
+
): Promise<R> {
|
|
92
|
+
const ctx = this.prepareContext(context ?? {});
|
|
93
|
+
const body = { code: fn.toString(), ctx };
|
|
94
|
+
return this.handleResponse<R>(JSON.stringify(body));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
private handleResponse<R>(body: string): Promise<R> {
|
|
98
|
+
return new Promise((resolve) => {
|
|
99
|
+
this.client.once("message", (raw: Buffer) => {
|
|
100
|
+
resolve(JSON.parse(raw.toString()));
|
|
101
|
+
});
|
|
102
|
+
this.client.send(body);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
private get client() {
|
|
107
|
+
if (global.testClient === null) {
|
|
108
|
+
throw new Error("Client is not connected. Did you call init?");
|
|
109
|
+
}
|
|
110
|
+
return global.testClient!;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private prepareContext<C extends Ctx>(context?: C): C {
|
|
114
|
+
const ctx: any = {};
|
|
115
|
+
if (context) {
|
|
116
|
+
for (const [key, value] of Object.entries(context)) {
|
|
117
|
+
ctx[key] = value;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return ctx;
|
|
121
|
+
}
|
|
122
|
+
async init() {}
|
|
123
|
+
async dispose() {}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
class ReferenceTestingClient implements TestingClient {
|
|
127
|
+
readonly OS = "web";
|
|
128
|
+
readonly arch = "paper";
|
|
129
|
+
|
|
130
|
+
private browser: Browser | null = null;
|
|
131
|
+
private page: Page | null = null;
|
|
132
|
+
|
|
133
|
+
async eval<C = Ctx, R = JSONValue>(
|
|
134
|
+
fn: (ctx: GPUContext & C) => R | Promise<R>,
|
|
135
|
+
ctx?: C,
|
|
136
|
+
): Promise<R> {
|
|
137
|
+
if (!this.page) {
|
|
138
|
+
throw new Error("RemoteSurface not initialized");
|
|
139
|
+
}
|
|
140
|
+
const fTexturePath = path.join(
|
|
141
|
+
__dirname,
|
|
142
|
+
"../../../../apps/paper/src/assets/f.png",
|
|
143
|
+
);
|
|
144
|
+
const fTextureData = fs.readFileSync(fTexturePath);
|
|
145
|
+
const fTextureBase64 = `data:image/png;base64,${fTextureData.toString("base64")}`;
|
|
146
|
+
const source = `(async function Main(){
|
|
147
|
+
var global = window;
|
|
148
|
+
const r = () => {${fs.readFileSync(path.join(__dirname, "../../../../node_modules/wgpu-matrix/dist/3.x/wgpu-matrix.js"), "utf8")} };
|
|
149
|
+
r();
|
|
150
|
+
const { mat4, vec3, mat3 } = window.wgpuMatrix;
|
|
151
|
+
const { device, adapter, gpu, cubeVertexArray, triangleVertWGSL, redFragWGSL, di3D, saturn, moon } = window;
|
|
152
|
+
class DrawingContext {
|
|
153
|
+
constructor(device, width, height) {
|
|
154
|
+
this.device = device;
|
|
155
|
+
this.width = width;
|
|
156
|
+
this.height = height;
|
|
157
|
+
const bytesPerRow = this.width * 4;
|
|
158
|
+
this.texture = device.createTexture({
|
|
159
|
+
size: [width, height],
|
|
160
|
+
format: gpu.getPreferredCanvasFormat(),
|
|
161
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
|
|
162
|
+
});
|
|
163
|
+
this.buffer = device.createBuffer({
|
|
164
|
+
size: bytesPerRow * this.height,
|
|
165
|
+
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
getCurrentTexture() {
|
|
169
|
+
return this.texture;
|
|
170
|
+
}
|
|
171
|
+
getImageData() {
|
|
172
|
+
const commandEncoder = this.device.createCommandEncoder();
|
|
173
|
+
const bytesPerRow = this.width * 4;
|
|
174
|
+
commandEncoder.copyTextureToBuffer({ texture: this.texture }, { buffer: this.buffer, bytesPerRow }, [this.width, this.height]);
|
|
175
|
+
this.device.queue.submit([commandEncoder.finish()]);
|
|
176
|
+
|
|
177
|
+
return this.buffer.mapAsync(GPUMapMode.READ).then(() => {
|
|
178
|
+
const arrayBuffer = this.buffer.getMappedRange();
|
|
179
|
+
const uint8Array = new Uint8Array(arrayBuffer);
|
|
180
|
+
const data = Array.from(uint8Array);
|
|
181
|
+
this.buffer.unmap();
|
|
182
|
+
return {
|
|
183
|
+
data,
|
|
184
|
+
width: this.width,
|
|
185
|
+
height: this.height,
|
|
186
|
+
format: gpu.getPreferredCanvasFormat(),
|
|
187
|
+
};
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const ctx = new DrawingContext(device, 1024, 1024);
|
|
193
|
+
return (${fn.toString()})({
|
|
194
|
+
device, adapter, gpu,
|
|
195
|
+
urls: {
|
|
196
|
+
fTexture: "${fTextureBase64}"
|
|
197
|
+
},
|
|
198
|
+
assets: {
|
|
199
|
+
cubeVertexArray,
|
|
200
|
+
di3D,
|
|
201
|
+
moon,
|
|
202
|
+
saturn,
|
|
203
|
+
},
|
|
204
|
+
shaders: {
|
|
205
|
+
triangleVertWGSL,
|
|
206
|
+
redFragWGSL,
|
|
207
|
+
},
|
|
208
|
+
ctx,
|
|
209
|
+
mat4,
|
|
210
|
+
vec3,
|
|
211
|
+
mat3,
|
|
212
|
+
...${JSON.stringify(ctx || {})}
|
|
213
|
+
});
|
|
214
|
+
})();`;
|
|
215
|
+
const data = await this.page.evaluate(source);
|
|
216
|
+
return data as R;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
async init() {
|
|
220
|
+
const browser = await puppeteer.launch({
|
|
221
|
+
headless: !DEBUG,
|
|
222
|
+
args: ["--enable-unsafe-webgpu"],
|
|
223
|
+
});
|
|
224
|
+
const page = await browser.newPage();
|
|
225
|
+
page.on("console", (msg) => console.log(msg.text()));
|
|
226
|
+
page.on("pageerror", (error) => {
|
|
227
|
+
console.error(error.message);
|
|
228
|
+
});
|
|
229
|
+
await page
|
|
230
|
+
.goto("chrome://gpu", {
|
|
231
|
+
waitUntil: "networkidle0",
|
|
232
|
+
timeout: 20 * 60 * 1000,
|
|
233
|
+
})
|
|
234
|
+
.catch((e) => console.log(e));
|
|
235
|
+
await page.waitForNetworkIdle();
|
|
236
|
+
const di3D = decodeImage(
|
|
237
|
+
path.join(__dirname, "../../../../apps/paper/src/assets/Di-3d.png"),
|
|
238
|
+
);
|
|
239
|
+
const moon = decodeImage(
|
|
240
|
+
path.join(__dirname, "../../../../apps/paper/src/assets/moon.png"),
|
|
241
|
+
);
|
|
242
|
+
const saturn = decodeImage(
|
|
243
|
+
path.join(__dirname, "../../../../apps/paper/src/assets/saturn.png"),
|
|
244
|
+
);
|
|
245
|
+
await page.evaluate(
|
|
246
|
+
`
|
|
247
|
+
(async () => {
|
|
248
|
+
window.gpu = navigator.gpu;
|
|
249
|
+
if (!gpu) {
|
|
250
|
+
const canvas = document.createElement('canvas');
|
|
251
|
+
const gl = canvas.getContext('webgl');
|
|
252
|
+
throw new Error("WebGPU is not available. WebGL: " + !!(gl && gl instanceof WebGLRenderingContext));
|
|
253
|
+
}
|
|
254
|
+
window.adapter = await gpu.requestAdapter();
|
|
255
|
+
if (!adapter) {
|
|
256
|
+
throw new Error("No adapter");
|
|
257
|
+
}
|
|
258
|
+
window.RNWebGPU = {
|
|
259
|
+
DecodeToUTF8: (data) => {
|
|
260
|
+
return new TextDecoder().decode(data);
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
window.device = await adapter.requestDevice();
|
|
264
|
+
window.cubeVertexArray = new Float32Array(${JSON.stringify(Array.from(cubeVertexArray))});
|
|
265
|
+
window.triangleVertWGSL = \`${triangleVertWGSL}\`;
|
|
266
|
+
window.redFragWGSL = \`${redFragWGSL}\`;
|
|
267
|
+
const rawDi3D = ${JSON.stringify(di3D)};
|
|
268
|
+
window.di3D = new ImageData(
|
|
269
|
+
new Uint8ClampedArray(rawDi3D.data),
|
|
270
|
+
rawDi3D.width,
|
|
271
|
+
rawDi3D.height
|
|
272
|
+
);
|
|
273
|
+
const rawMoon = ${JSON.stringify(moon)};
|
|
274
|
+
window.moon = new ImageData(
|
|
275
|
+
new Uint8ClampedArray(rawMoon.data),
|
|
276
|
+
rawMoon.width,
|
|
277
|
+
rawMoon.height
|
|
278
|
+
);
|
|
279
|
+
const rawSaturn = ${JSON.stringify(saturn)};
|
|
280
|
+
window.saturn = new ImageData(
|
|
281
|
+
new Uint8ClampedArray(rawSaturn.data),
|
|
282
|
+
rawSaturn.width,
|
|
283
|
+
rawSaturn.height
|
|
284
|
+
);
|
|
285
|
+
})();
|
|
286
|
+
`,
|
|
287
|
+
);
|
|
288
|
+
this.browser = browser;
|
|
289
|
+
this.page = page;
|
|
290
|
+
}
|
|
291
|
+
async dispose() {
|
|
292
|
+
if (this.browser && !DEBUG) {
|
|
293
|
+
this.browser.close();
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
interface BitmapData {
|
|
299
|
+
data: number[];
|
|
300
|
+
width: number;
|
|
301
|
+
height: number;
|
|
302
|
+
format: string;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export const encodeImage = (bitmap: BitmapData) => {
|
|
306
|
+
const { width, height, format } = bitmap;
|
|
307
|
+
let data = new Uint8Array(bitmap.data);
|
|
308
|
+
// Convert BGRA to RGBA if necessary
|
|
309
|
+
if (format === "bgra8unorm") {
|
|
310
|
+
data = new Uint8Array(bitmap.data.length);
|
|
311
|
+
for (let i = 0; i < bitmap.data.length; i += 4) {
|
|
312
|
+
data[i] = bitmap.data[i + 2]; // R
|
|
313
|
+
data[i + 1] = bitmap.data[i + 1]; // G
|
|
314
|
+
data[i + 2] = bitmap.data[i]; // B
|
|
315
|
+
data[i + 3] = bitmap.data[i + 3]; // A
|
|
316
|
+
}
|
|
317
|
+
} else if (format !== "rgba8unorm") {
|
|
318
|
+
throw new Error(`Unsupported format ${format}`);
|
|
319
|
+
}
|
|
320
|
+
// Create a new PNG
|
|
321
|
+
const png = new PNG({
|
|
322
|
+
width: width,
|
|
323
|
+
height: height,
|
|
324
|
+
filterType: -1,
|
|
325
|
+
});
|
|
326
|
+
png.data = Buffer.from(data);
|
|
327
|
+
return png;
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
interface CheckImageOptions {
|
|
331
|
+
maxPixelDiff?: number;
|
|
332
|
+
threshold?: number;
|
|
333
|
+
overwrite?: boolean;
|
|
334
|
+
mute?: boolean;
|
|
335
|
+
shouldFail?: boolean;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// On Github Action, the image decoding is slightly different
|
|
339
|
+
// all tests that show the oslo.jpg have small differences but look ok
|
|
340
|
+
const defaultCheckImageOptions = {
|
|
341
|
+
maxPixelDiff: 200,
|
|
342
|
+
threshold: 0.1,
|
|
343
|
+
overwrite: false,
|
|
344
|
+
mute: false,
|
|
345
|
+
shouldFail: false,
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
export const checkImage = (
|
|
349
|
+
toTest: PNG,
|
|
350
|
+
relPath: string,
|
|
351
|
+
opts?: CheckImageOptions,
|
|
352
|
+
) => {
|
|
353
|
+
const options = { ...defaultCheckImageOptions, ...opts };
|
|
354
|
+
const { overwrite, threshold, mute, maxPixelDiff, shouldFail } = options;
|
|
355
|
+
const p = path.resolve(__dirname, relPath);
|
|
356
|
+
if (fs.existsSync(p) && !overwrite) {
|
|
357
|
+
const ref = fs.readFileSync(p);
|
|
358
|
+
const baseline = PNG.sync.read(ref);
|
|
359
|
+
const diffImage = new PNG({
|
|
360
|
+
width: baseline.width,
|
|
361
|
+
height: baseline.height,
|
|
362
|
+
});
|
|
363
|
+
if (baseline.width !== toTest.width || baseline.height !== toTest.height) {
|
|
364
|
+
throw new Error(
|
|
365
|
+
`Image sizes don't match: ${baseline.width}x${baseline.height} vs ${toTest.width}x${toTest.height}`,
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
const diffPixelsCount = pixelmatch(
|
|
369
|
+
baseline.data,
|
|
370
|
+
toTest.data,
|
|
371
|
+
diffImage.data,
|
|
372
|
+
baseline.width,
|
|
373
|
+
baseline.height,
|
|
374
|
+
{ threshold },
|
|
375
|
+
);
|
|
376
|
+
if (!mute) {
|
|
377
|
+
if (diffPixelsCount > maxPixelDiff && !shouldFail) {
|
|
378
|
+
console.log(`${p} didn't match`);
|
|
379
|
+
fs.writeFileSync(`${p}.test.png`, PNG.sync.write(toTest));
|
|
380
|
+
fs.writeFileSync(`${p}-diff-test.png`, PNG.sync.write(diffImage));
|
|
381
|
+
}
|
|
382
|
+
if (shouldFail) {
|
|
383
|
+
expect(diffPixelsCount).not.toBeLessThanOrEqual(maxPixelDiff);
|
|
384
|
+
} else {
|
|
385
|
+
expect(diffPixelsCount).toBeLessThanOrEqual(maxPixelDiff);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return diffPixelsCount;
|
|
389
|
+
} else {
|
|
390
|
+
const buffer = PNG.sync.write(toTest);
|
|
391
|
+
fs.writeFileSync(p, buffer);
|
|
392
|
+
}
|
|
393
|
+
return 0;
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
export const decodeImage = (relPath: string): BitmapData => {
|
|
397
|
+
const p = path.resolve(__dirname, relPath);
|
|
398
|
+
const data = fs.readFileSync(p);
|
|
399
|
+
const png = PNG.sync.read(data);
|
|
400
|
+
|
|
401
|
+
const bitmap: BitmapData = {
|
|
402
|
+
data: Array.from(png.data),
|
|
403
|
+
width: png.width,
|
|
404
|
+
height: png.height,
|
|
405
|
+
format: "rgba8unorm",
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
return bitmap;
|
|
409
|
+
};
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/utils.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { DependencyList } from "react";
|
|
1
2
|
import { useEffect, useRef } from "react";
|
|
2
3
|
|
|
3
4
|
import type { CanvasRef } from "./Canvas";
|
|
@@ -14,6 +15,7 @@ export const warnIfNotHardwareAccelerated = (adapter: GPUAdapter) => {
|
|
|
14
15
|
|
|
15
16
|
export const useCanvasEffect = (
|
|
16
17
|
effect: () => void | Unsubscribe | Promise<void | Unsubscribe>,
|
|
18
|
+
deps: DependencyList = [],
|
|
17
19
|
) => {
|
|
18
20
|
const ref = useRef<CanvasRef>(null);
|
|
19
21
|
const unsubscribe = useRef<Unsubscribe>();
|
|
@@ -35,6 +37,6 @@ export const useCanvasEffect = (
|
|
|
35
37
|
}
|
|
36
38
|
};
|
|
37
39
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
38
|
-
},
|
|
40
|
+
}, deps);
|
|
39
41
|
return ref;
|
|
40
42
|
};
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
require "json"
|
|
2
|
-
|
|
3
|
-
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
-
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
|
|
5
|
-
|
|
6
|
-
Pod::Spec.new do |s|
|
|
7
|
-
s.name = "react-native-wgpu"
|
|
8
|
-
s.version = package["version"]
|
|
9
|
-
s.summary = package["description"]
|
|
10
|
-
s.homepage = package["homepage"]
|
|
11
|
-
s.license = package["license"]
|
|
12
|
-
s.authors = package["author"]
|
|
13
|
-
|
|
14
|
-
s.platforms = { :ios => min_ios_version_supported, :visionos => "1.0" }
|
|
15
|
-
s.source = { :git => "https://github.com/wcandillon/react-native-webgpu.git", :tag => "#{s.version}" }
|
|
16
|
-
|
|
17
|
-
s.source_files = [
|
|
18
|
-
"ios/**/*.{h,c,cc,cpp,m,mm,swift}",
|
|
19
|
-
"cpp/**/*.{h,cpp}"
|
|
20
|
-
]
|
|
21
|
-
|
|
22
|
-
s.ios.vendored_frameworks = [
|
|
23
|
-
'libs/ios/libwebgpu_dawn.xcframework',
|
|
24
|
-
]
|
|
25
|
-
|
|
26
|
-
s.pod_target_xcconfig = {
|
|
27
|
-
'HEADER_SEARCH_PATHS' => '$(PODS_TARGET_SRCROOT)/cpp',
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
# Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
|
|
31
|
-
# See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79.
|
|
32
|
-
if respond_to?(:install_modules_dependencies, true)
|
|
33
|
-
install_modules_dependencies(s)
|
|
34
|
-
else
|
|
35
|
-
s.dependency "React-Core"
|
|
36
|
-
|
|
37
|
-
# Don't install the dependencies when we run `pod install` in the old architecture.
|
|
38
|
-
if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
|
|
39
|
-
s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
|
|
40
|
-
s.pod_target_xcconfig = {
|
|
41
|
-
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
|
|
42
|
-
"OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
|
43
|
-
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
|
|
44
|
-
}
|
|
45
|
-
s.dependency "React-RCTFabric"
|
|
46
|
-
s.dependency "React-Codegen"
|
|
47
|
-
s.dependency "RCT-Folly"
|
|
48
|
-
s.dependency "RCTRequired"
|
|
49
|
-
s.dependency "RCTTypeSafety"
|
|
50
|
-
s.dependency "ReactCommon/turbomodule/core"
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|