webgpu-computed 0.0.8 → 0.0.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.
Files changed (3) hide show
  1. package/README.en.md +496 -0
  2. package/README.md +497 -0
  3. package/package.json +1 -1
package/README.en.md ADDED
@@ -0,0 +1,496 @@
1
+ # webgpu-computed
2
+
3
+ 🌐 Other language versions:
4
+ - [简体中文](./README.md)
5
+
6
+ A simplified WebGPU computing library that encapsulates tedious initialization and buffer management, allowing developers to focus on WGSL shader logic.
7
+
8
+ ## Features
9
+
10
+ - 🚀 Simplified WebGPU initialization
11
+ - 📦 Automatic buffer management and layout calculation
12
+ - 🔧 Support for complex data structures (vectors, matrices)
13
+ - ⚡ High-performance GPU computing
14
+ - 📚 Built-in common WGSL functions
15
+ - ✅ Support for Node.js environment
16
+ - 🛠️ TypeScript support
17
+ - 📖 Detailed English documentation and examples
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ npm install webgpu-computed
23
+ ```
24
+
25
+ ## Quick Start
26
+
27
+ ### 1. Initialize WebGPU
28
+
29
+ Before using any computing features, you need to initialize the WebGPU environment:
30
+
31
+ ```javascript
32
+ import { GpuComputed } from 'webgpu-computed';
33
+
34
+ // Initialize WebGPU
35
+ await GpuComputed.init();
36
+
37
+ // After using in Node.js environment, please call:
38
+ // GpuComputed.destroy()
39
+ ```
40
+
41
+ ### 2. Perform Simple Computation
42
+
43
+ Here is a simple vector addition example:
44
+
45
+ ```javascript
46
+ import { GpuComputed } from 'webgpu-computed';
47
+
48
+ // Prepare data
49
+ const data = {
50
+ inputA: [1.0, 2.0, 3.0, 4.0],
51
+ inputB: [0.5, 1.5, 2.5, 3.5],
52
+ output: new Array(4).fill(0) // Output buffer
53
+ };
54
+
55
+ // WGSL computation code
56
+ const code = `
57
+ output[index] = inputA[index] + inputB[index];
58
+ `;
59
+
60
+ // Execute computation
61
+ GpuComputed.computed({
62
+ code,
63
+ data,
64
+ synchronize: ["output"], // Fields to return
65
+ workgroupCount: [1] // Number of workgroups
66
+ }).then(results => {
67
+ console.log(results); // [[1.5, 3.5, 5.5, 7.5]]
68
+ })
69
+ ```
70
+
71
+ ### 3. Using Complex Data Structures
72
+
73
+ The library supports vector and matrix types:
74
+
75
+ ```javascript
76
+ const data = {
77
+ positions: [
78
+ { pos: [1.0, 2.0, 3.0], vel: [0.1, 0.2, 0.3] },
79
+ { pos: [4.0, 5.0, 6.0], vel: [0.4, 0.5, 0.6] }
80
+ ],
81
+ output: new Array(2).fill({ pos: [0,0,0], vel: [0,0,0] })
82
+ };
83
+
84
+ const code = `
85
+ output[index].pos = positions[index].pos + positions[index].vel;
86
+ output[index].vel = positions[index].vel * 2.0;
87
+ `;
88
+
89
+ // Execute computation
90
+ GpuComputed.computed({
91
+ code,
92
+ data,
93
+ synchronize: ["output"], // Fields to return
94
+ workgroupCount: [1] // Number of workgroups
95
+ }).then(results => {
96
+ console.log(results); // [[1.100000023841858,2.200000047683716,3.299999952316284,0,0.20000000298023224,0.4000000059604645,0.6000000238418579,0,4.400000095367432,5.5,6.599999904632568,0,0.800000011920929,1,1.2000000476837158,0]]
97
+ })
98
+ ```
99
+
100
+ ### 4. Manually Create GpuComputed Instance
101
+
102
+ If you need more fine-grained control, you can directly create a GpuComputed instance:
103
+
104
+ ```javascript
105
+ import { GpuComputed } from 'webgpu-computed';
106
+
107
+ // 1. Define data template
108
+ const template = {
109
+ inputA: [] as number[],
110
+ inputB: [] as number[],
111
+ output: [] as number[]
112
+ };
113
+
114
+ // 2. Create instance
115
+ const gpuComputed = new GpuComputed(template, {
116
+ code: `
117
+ output[index] = inputA[index] + inputB[index];
118
+ `,
119
+ workgroupSize: [32, 1, 1] // Optional: custom workgroup size
120
+ });
121
+
122
+ // 3. Initialize pipeline
123
+ await gpuComputed.initPipeline();
124
+
125
+ // 4. Prepare data
126
+ const data = {
127
+ inputA: [1.0, 2.0, 3.0, 4.0],
128
+ inputB: [0.5, 1.5, 2.5, 3.5],
129
+ output: new Array(4).fill(0)
130
+ };
131
+
132
+ // 5. Create bind group
133
+ const bindGroup = gpuComputed.createBindGroup(data);
134
+
135
+ // 6. Execute computation
136
+ const results = await gpuComputed.computed(bindGroup, [1], ['output']);
137
+
138
+ console.log(results[0]); // [1.5, 3.5, 5.5, 7.5]
139
+ ```
140
+
141
+ #### Using Struct Data
142
+
143
+ ```javascript
144
+ // Define struct template
145
+ const structTemplate = {
146
+ particles: {
147
+ layout: [
148
+ { name: 'position', type: 'vec3' },
149
+ { name: 'velocity', type: 'vec3' },
150
+ { name: 'mass', type: 'f32' }
151
+ ]
152
+ },
153
+ output: {
154
+ layout: [
155
+ { name: 'position', type: 'vec3' },
156
+ { name: 'velocity', type: 'vec3' },
157
+ { name: 'mass', type: 'f32' }
158
+ ]
159
+ }
160
+ };
161
+
162
+ const gpuComputed = new GpuComputed(structTemplate, {
163
+ code: `
164
+ output[index].position = particles[index].position + particles[index].velocity;
165
+ output[index].velocity = particles[index].velocity * 2.0;
166
+ output[index].mass = particles[index].mass * 1.5;
167
+ `
168
+ });
169
+
170
+ await gpuComputed.initPipeline();
171
+
172
+ const data = {
173
+ particles: [
174
+ { position: [1, 2, 3], velocity: [0.1, 0.2, 0.3], mass: 1.0 },
175
+ { position: [4, 5, 6], velocity: [0.4, 0.5, 0.6], mass: 2.0 }
176
+ ],
177
+ output: [
178
+ { position: [0, 0, 0], velocity: [0, 0, 0], mass: 0 },
179
+ { position: [0, 0, 0], velocity: [0, 0, 0], mass: 0 }
180
+ ]
181
+ };
182
+
183
+ const bindGroup = gpuComputed.createBindGroup(data);
184
+ const results = await gpuComputed.computed(bindGroup, [1], ['output']);
185
+
186
+ console.log(results[0]); // Mapped data
187
+ ```
188
+
189
+ #### Data Mapping
190
+
191
+ When using structs, you can use the `dataMap` method to map results back to the original structure:
192
+
193
+ ```javascript
194
+ const mappedData = gpuComputed.dataMap(results[0], 'output');
195
+ console.log(mappedData); // Returns structured object array
196
+ ```
197
+
198
+ ## API Reference
199
+
200
+ ### GpuComputed Class
201
+
202
+ #### Static Methods
203
+
204
+ ##### `GpuComputed.init()`
205
+
206
+ Initializes the WebGPU environment. Must be called before using other features.
207
+
208
+ **Returns**: `Promise<void>`
209
+
210
+ **Throws**: If the browser does not support WebGPU or fails to obtain adapter/device
211
+
212
+ ##### `GpuComputed.computed(options)`
213
+
214
+ Executes a GPU computation task.
215
+
216
+ **Parameters**:
217
+
218
+ - `code` (string): WGSL computation code
219
+ - `data` (object): Input/output data object
220
+ - `workgroupCount` (array): Number of workgroups [x, y?, z?]
221
+ - `workgroupSize` (array, optional): Workgroup size, default [32, 1, 1]
222
+ - `globalInvocationIdName` (string, optional): Global invocation ID variable name, default "grid"
223
+ - `workgroupIndexName` (string, optional): Workgroup index variable name, default "index"
224
+ - `synchronize` (array, optional): Array of buffer names to synchronize back to CPU
225
+ - `beforeCodes` (array, optional): WGSL code snippets before the computation function
226
+ - `onSuccess` (function, optional): Success callback function
227
+
228
+ **Returns**: `Promise<Array<Float32Array>>` - Data from synchronized buffers
229
+
230
+ ### Data Types
231
+
232
+ Supports the following WGSL types:
233
+
234
+ - `f32`: Single-precision float
235
+ - `vec2`: 2D vector
236
+ - `vec3`: 3D vector
237
+ - `vec4`: 4D vector
238
+ - `mat3x3`: 3x3 matrix
239
+ - `mat4x4`: 4x4 matrix
240
+
241
+ ### Built-in WGSL Functions
242
+
243
+ The library provides some commonly used WGSL helper functions:
244
+
245
+ #### Quaternion Rotation
246
+
247
+ ```wgsl
248
+ fn quat_rotate(q: vec4<f32>, v: vec3<f32>) -> vec3<f32>
249
+ ```
250
+
251
+ Usage example:
252
+
253
+ ```javascript
254
+ import { WGSL_Fun } from 'webgpu-computed';
255
+
256
+ await GpuComputed.computed({
257
+ code: "",
258
+ data: {....},
259
+ beforeCodes:[WGSL_Fun.quat_rotate]
260
+ })
261
+ ```
262
+
263
+ #### Point in OBB Detection
264
+
265
+ ```wgsl
266
+ fn point_in_obb(point: vec3<f32>, center: vec3<f32>, halfSize: vec3<f32>, quat: vec4<f32>) -> bool
267
+ ```
268
+
269
+ ## Advanced Usage
270
+
271
+ ### Custom Workgroup Configuration
272
+
273
+ ```javascript
274
+ await GpuComputed.computed({
275
+ code: '...',
276
+ data: {...},
277
+ workgroupCount: [4, 4], // 16 workgroups
278
+ workgroupSize: [16, 16], // 256 threads per workgroup
279
+ });
280
+ ```
281
+
282
+ ### Synchronizing Data Back to CPU
283
+
284
+ ```javascript
285
+ const results = await GpuComputed.computed({
286
+ code: '...',
287
+ data: {...},
288
+ synchronize: ['output'], // Specify buffers to synchronize
289
+ workgroupCount: [1]
290
+ });
291
+
292
+ // results contains synchronized data
293
+ ```
294
+
295
+ ### Callback Function
296
+
297
+ ```javascript
298
+ await GpuComputed.computed({
299
+ code: '...',
300
+ data: {...},
301
+ workgroupCount: [1],
302
+ onSuccess: ({ gpuComputed, group, results }) => {
303
+ console.log('Computation completed', results);
304
+ }
305
+ });
306
+ ```
307
+
308
+ ## Example Project
309
+
310
+ ```js
311
+ import { GpuComputed } from "webgpu-computed"
312
+ import * as WGSL_Fun from "webgpu-computed"
313
+
314
+ // 1. Initialize WebGPU
315
+ console.log('Initializing WebGPU...');
316
+ await GpuComputed.init();
317
+ console.log('WebGPU initialized successfully');
318
+
319
+ // 2. Simple array computation example
320
+ console.log('\n=== Simple Array Computation ===');
321
+ const simpleData = {
322
+ inputA: [1.0, 2.0, 3.0, 4.0],
323
+ inputB: [0.5, 1.5, 2.5, 3.5],
324
+ output: new Array(4).fill(0)
325
+ };
326
+
327
+ const simpleCode = `
328
+ output[index] = inputA[index] + inputB[index];
329
+ `;
330
+
331
+ const simpleResults = await GpuComputed.computed({
332
+ code: simpleCode,
333
+ data: simpleData,
334
+ workgroupCount: [1],
335
+ synchronize: ['output']
336
+ });
337
+
338
+ console.log('Simple computation result:', simpleResults[0]); // [1.5, 3.5, 5.5, 7.5]
339
+
340
+ // 3. Complex data structure example (struct)
341
+ console.log('\n=== Complex Data Structure Computation ===');
342
+ const complexData = {
343
+ particles: [
344
+ { position: [1.0, 2.0, 3.0], velocity: [0.1, 0.2, 0.3], mass: 1.0 },
345
+ { position: [4.0, 5.0, 6.0], velocity: [0.4, 0.5, 0.6], mass: 2.0 }
346
+ ],
347
+ output: [
348
+ { position: [0, 0, 0], velocity: [0, 0, 0], mass: 0 },
349
+ { position: [0, 0, 0], velocity: [0, 0, 0], mass: 0 }
350
+ ]
351
+ };
352
+
353
+ const complexCode = `
354
+ output[index].position = particles[index].position + particles[index].velocity;
355
+ output[index].velocity = particles[index].velocity * 2.0;
356
+ output[index].mass = particles[index].mass * 1.5;
357
+ `;
358
+
359
+ const complexResults = await GpuComputed.computed({
360
+ code: complexCode,
361
+ data: complexData,
362
+ workgroupCount: [1],
363
+ synchronize: ['output']
364
+ });
365
+
366
+ console.log('Complex computation result:', complexResults[0]);
367
+
368
+ // 4. Using built-in WGSL functions example
369
+ console.log('\n=== Using Built-in WGSL Functions ===');
370
+ const wgslFunData = {
371
+ points: [
372
+ {
373
+ x: 1.0, y: 0.0, z: 0.0
374
+ },
375
+ {
376
+ x: 0.0, y: 1.0, z: 0.0
377
+ },
378
+ {
379
+ x: -1.0, y: 0.0, z: 0.0
380
+ }
381
+ ],
382
+ obbCenter: [0.0, 0.0, 0.0],
383
+ obbHalfSize: [2.0, 2.0, 2.0],
384
+ obbRotation: [0.0, 0.0, 0.0, 1.0], // Unit quaternion, no rotation
385
+ results: new Array(3).fill(0)
386
+ };
387
+
388
+ const wgslFunCode = `
389
+ let point = vec3(points[index].x, points[index].y, points[index].z);
390
+ let center = vec3<f32>(obbCenter[0], obbCenter[1], obbCenter[2]);
391
+ let halfSize = vec3<f32>(obbHalfSize[0], obbHalfSize[1], obbHalfSize[2]);
392
+ let quat = vec4<f32>(obbRotation[0], obbRotation[1], obbRotation[2], obbRotation[3]);
393
+
394
+ if (point_in_obb(point, center, halfSize, quat)) {
395
+ results[index] = 1.0;
396
+ } else {
397
+ results[index] = 0.0;
398
+ }
399
+ `;
400
+
401
+ const wgslFunResults = await GpuComputed.computed({
402
+ code: wgslFunCode,
403
+ data: wgslFunData,
404
+ workgroupCount: [1],
405
+ beforeCodes: [WGSL_Fun.quat_rotate, WGSL_Fun.point_in_obb, /** Add your own function code */],
406
+ synchronize: ['results']
407
+ });
408
+
409
+ console.log('OBB detection result:', wgslFunResults[0]); // [1, 1, 1] All points are inside the OBB
410
+
411
+ // 5. Custom workgroup configuration example
412
+ console.log('\n=== Custom Workgroup Configuration ===');
413
+ const largeData = {
414
+ largeArray: new Array(1024).fill(0).map((_, i) => i * 1.0),
415
+ output: new Array(1024).fill(0)
416
+ };
417
+
418
+ const largeCode = `
419
+ output[index] = largeArray[index] * 2.0;
420
+ `;
421
+
422
+ const largeResults = await GpuComputed.computed({
423
+ code: largeCode,
424
+ data: largeData,
425
+ workgroupCount: [32], // 32 workgroups
426
+ workgroupSize: [32, 1, 1], // 32 threads per workgroup, total 1024 threads
427
+ synchronize: ['output']
428
+ });
429
+
430
+ console.log('Large array computation result (first 10):', largeResults[0].slice(0, 10));
431
+
432
+ // 6. Using callback function example
433
+ console.log('\n=== Using Callback Function ===');
434
+ const callbackData = {
435
+ values: [10.0, 20.0, 30.0],
436
+ squares: new Array(3).fill(0)
437
+ };
438
+
439
+ const callbackCode = `
440
+ squares[index] = values[index] * values[index];
441
+ `;
442
+
443
+ await GpuComputed.computed({
444
+ code: callbackCode,
445
+ data: callbackData,
446
+ workgroupCount: [1],
447
+ synchronize: ['squares'],
448
+ onSuccess: ({ gpuComputed, group, results }) => {
449
+ console.log('Callback triggered, square computation result:', results[0]); // [100, 400, 900]
450
+ }
451
+ });
452
+
453
+ // 7. Multi-dimensional workgroup example
454
+ console.log('\n=== Multi-dimensional Workgroup ===');
455
+ const matrixData = {
456
+ matrixA: new Array(16).fill(0).map((_, i) => i * 1.0),
457
+ matrixB: new Array(16).fill(0).map((_, i) => (i + 1) * 1.0),
458
+ result: new Array(16).fill(0)
459
+ };
460
+
461
+ const matrixCode = `
462
+ let x = index % 4u;
463
+ let y = index / 4u;
464
+ let idx = y * 4u + x;
465
+ result[idx] = matrixA[idx] + matrixB[idx];
466
+ `;
467
+
468
+ const matrixResults = await GpuComputed.computed({
469
+ code: matrixCode,
470
+ data: matrixData,
471
+ workgroupCount: [4, 4], // 4x4 workgroup grid
472
+ workgroupSize: [1, 1, 1], // 1 thread per workgroup
473
+ synchronize: ['result']
474
+ });
475
+
476
+ console.log('Matrix computation result:', matrixResults[0]);
477
+
478
+ console.log('\nAll feature examples completed!');
479
+ ```
480
+
481
+ ## Browser Support
482
+
483
+ - Chrome 113+
484
+ - Edge 113+
485
+ - Firefox (partial support)
486
+ - Safari (partial support)
487
+
488
+ Ensure the browser supports the WebGPU API.
489
+
490
+ ## Contributing
491
+
492
+ Welcome to submit Issues and Pull Requests!
493
+
494
+ ## License
495
+
496
+ ISC License
package/README.md ADDED
@@ -0,0 +1,497 @@
1
+ # webgpu-computed
2
+
3
+ 🌐 其他语言版本:
4
+ - [English](./README.en.md)
5
+
6
+ 一个简化的 WebGPU 计算库,封装了繁琐的初始化和缓冲区管理,让开发者专注于 WGSL 着色器逻辑。
7
+
8
+ ## 特性
9
+
10
+ - 🚀 简化的 WebGPU 初始化
11
+ - 📦 自动缓冲区管理和布局计算
12
+ - 🔧 支持复杂数据结构(向量、矩阵)
13
+ - ⚡ 高性能 GPU 计算
14
+ - 📚 内置常用 WGSL 函数
15
+ - ✅ 支持 Node.js 环境
16
+ - 🛠️ TypeScript 支持
17
+ - 📖 详细的中文文档和示例
18
+
19
+ ## 安装
20
+
21
+ ```bash
22
+ npm install webgpu-computed
23
+ ```
24
+
25
+ ## 快速开始
26
+
27
+ ### 1. 初始化 WebGPU
28
+
29
+ 在使用任何计算功能之前,需要初始化 WebGPU 环境:
30
+
31
+ ```javascript
32
+ import { GpuComputed } from 'webgpu-computed';
33
+
34
+ // 初始化 WebGPU
35
+ await GpuComputed.init();
36
+
37
+ // 在 Node.js 环境中使用后,请调用:
38
+ // GpuComputed.destroy()
39
+ ```
40
+
41
+ ### 2. 执行简单计算
42
+
43
+ 以下是一个简单的向量加法示例:
44
+
45
+ ```javascript
46
+ import { GpuComputed } from 'webgpu-computed';
47
+
48
+ // 准备数据
49
+ const data = {
50
+ inputA: [1.0, 2.0, 3.0, 4.0],
51
+ inputB: [0.5, 1.5, 2.5, 3.5],
52
+ output: new Array(4).fill(0) // 输出缓冲区
53
+ };
54
+
55
+ // WGSL 计算代码
56
+ const code = `
57
+ output[index] = inputA[index] + inputB[index];
58
+ `;
59
+
60
+ // 执行计算
61
+ GpuComputed.computed({
62
+ code,
63
+ data,
64
+ synchronize: ["output"], // 需要返回的数据字段
65
+ workgroupCount: [1] // 工作组数量
66
+ }).then(results => {
67
+ console.log(results); // [[1.5, 3.5, 5.5, 7.5]]
68
+ })
69
+ ```
70
+
71
+ ### 3. 使用复杂数据结构
72
+
73
+ 该库支持向量和矩阵类型:
74
+
75
+ ```javascript
76
+ const data = {
77
+ positions: [
78
+ { pos: [1.0, 2.0, 3.0], vel: [0.1, 0.2, 0.3] },
79
+ { pos: [4.0, 5.0, 6.0], vel: [0.4, 0.5, 0.6] }
80
+ ],
81
+ output: new Array(2).fill({ pos: [0,0,0], vel: [0,0,0] })
82
+ };
83
+
84
+ const code = `
85
+ output[index].pos = positions[index].pos + positions[index].vel;
86
+ output[index].vel = positions[index].vel * 2.0;
87
+ `;
88
+
89
+ // 执行计算
90
+ GpuComputed.computed({
91
+ code,
92
+ data,
93
+ synchronize: ["output"], // 需要返回的数据字段
94
+ workgroupCount: [1] // 工作组数量
95
+ }).then(results => {
96
+ console.log(results); // [[1.100000023841858,2.200000047683716,3.299999952316284,0,0.20000000298023224,0.4000000059604645,0.6000000238418579,0,4.400000095367432,5.5,6.599999904632568,0,0.800000011920929,1,1.2000000476837158,0]]
97
+ })
98
+ ```
99
+
100
+ ### 4. 手动创建 GpuComputed 实例
101
+
102
+ 如果您需要更精细的控制,可以直接创建 GpuComputed 实例:
103
+
104
+ ```javascript
105
+ import { GpuComputed } from 'webgpu-computed';
106
+
107
+ // 1. 定义数据模板
108
+ const template = {
109
+ inputA: [] as number[],
110
+ inputB: [] as number[],
111
+ output: [] as number[]
112
+ };
113
+
114
+ // 2. 创建实例
115
+ const gpuComputed = new GpuComputed(template, {
116
+ code: `
117
+ output[index] = inputA[index] + inputB[index];
118
+ `,
119
+ workgroupSize: [32, 1, 1] // 可选:自定义工作组大小
120
+ });
121
+
122
+ // 3. 初始化管线
123
+ await gpuComputed.initPipeline();
124
+
125
+ // 4. 准备数据
126
+ const data = {
127
+ inputA: [1.0, 2.0, 3.0, 4.0],
128
+ inputB: [0.5, 1.5, 2.5, 3.5],
129
+ output: new Array(4).fill(0)
130
+ };
131
+
132
+ // 5. 创建绑定组
133
+ const bindGroup = gpuComputed.createBindGroup(data);
134
+
135
+ // 6. 执行计算
136
+ const results = await gpuComputed.computed(bindGroup, [1], ['output']);
137
+
138
+ console.log(results[0]); // [1.5, 3.5, 5.5, 7.5]
139
+ ```
140
+
141
+ #### 使用结构体数据
142
+
143
+ ```javascript
144
+ // 定义结构体模板
145
+ const structTemplate = {
146
+ particles: {
147
+ layout: [
148
+ { name: 'position', type: 'vec3' },
149
+ { name: 'velocity', type: 'vec3' },
150
+ { name: 'mass', type: 'f32' }
151
+ ]
152
+ },
153
+ output: {
154
+ layout: [
155
+ { name: 'position', type: 'vec3' },
156
+ { name: 'velocity', type: 'vec3' },
157
+ { name: 'mass', type: 'f32' }
158
+ ]
159
+ }
160
+ };
161
+
162
+ const gpuComputed = new GpuComputed(structTemplate, {
163
+ code: `
164
+ output[index].position = particles[index].position + particles[index].velocity;
165
+ output[index].velocity = particles[index].velocity * 2.0;
166
+ output[index].mass = particles[index].mass * 1.5;
167
+ `
168
+ });
169
+
170
+ await gpuComputed.initPipeline();
171
+
172
+ const data = {
173
+ particles: [
174
+ { position: [1, 2, 3], velocity: [0.1, 0.2, 0.3], mass: 1.0 },
175
+ { position: [4, 5, 6], velocity: [0.4, 0.5, 0.6], mass: 2.0 }
176
+ ],
177
+ output: [
178
+ { position: [0, 0, 0], velocity: [0, 0, 0], mass: 0 },
179
+ { position: [0, 0, 0], velocity: [0, 0, 0], mass: 0 }
180
+ ]
181
+ };
182
+
183
+ const bindGroup = gpuComputed.createBindGroup(data);
184
+ const results = await gpuComputed.computed(bindGroup, [1], ['output']);
185
+
186
+ console.log(results[0]); // 映射后的数据
187
+ ```
188
+
189
+ #### 数据映射
190
+
191
+ 当使用结构体时,可以使用 `dataMap` 方法将结果映射回原始结构:
192
+
193
+ ```javascript
194
+ const mappedData = gpuComputed.dataMap(results[0], 'output');
195
+ console.log(mappedData); // 返回结构化的对象数组
196
+ ```
197
+
198
+ ## API 参考
199
+
200
+ ### GpuComputed 类
201
+
202
+ #### 静态方法
203
+
204
+ ##### `GpuComputed.init()`
205
+
206
+ 初始化 WebGPU 环境。必须在使用其他功能之前调用。
207
+
208
+ **返回值**: `Promise<void>`
209
+
210
+ **抛出异常**: 如果浏览器不支持 WebGPU 或获取适配器/设备失败
211
+
212
+ ##### `GpuComputed.computed(options)`
213
+
214
+ 执行 GPU 计算任务。
215
+
216
+ **参数**:
217
+
218
+ - `code` (string): WGSL 计算代码
219
+ - `data` (object): 输入/输出数据对象
220
+ - `workgroupCount` (array): 工作组数量 [x, y?, z?]
221
+ - `workgroupSize` (array, 可选): 工作组大小,默认 [32, 1, 1]
222
+ - `globalInvocationIdName` (string, 可选): 全局调用 ID 变量名,默认 "grid"
223
+ - `workgroupIndexName` (string, 可选): 工作组索引变量名,默认 "index"
224
+ - `synchronize` (array, 可选): 需要同步回 CPU 的缓冲区名称数组
225
+ - `beforeCodes` (array, 可选): 计算函数之前的 WGSL 代码片段
226
+ - `onSuccess` (function, 可选): 成功回调函数
227
+
228
+ **返回值**: `Promise<Array<Float32Array>>` - 同步缓冲区的数据
229
+
230
+ ### 数据类型
231
+
232
+ 支持以下 WGSL 类型:
233
+
234
+ - `f32`: 单精度浮点数
235
+ - `vec2`: 2D 向量
236
+ - `vec3`: 3D 向量
237
+ - `vec4`: 4D 向量
238
+ - `mat3x3`: 3x3 矩阵
239
+ - `mat4x4`: 4x4 矩阵
240
+
241
+ ### 内置 WGSL 函数
242
+
243
+ 该库提供了一些常用的 WGSL 辅助函数:
244
+
245
+ #### 四元数旋转
246
+
247
+ ```wgsl
248
+ fn quat_rotate(q: vec4<f32>, v: vec3<f32>) -> vec3<f32>
249
+ ```
250
+
251
+ 使用示例:
252
+
253
+ ```javascript
254
+ import { WGSL_Fun } from 'webgpu-computed';
255
+
256
+ await GpuComputed.computed({
257
+ code: "",
258
+ data: {....},
259
+ beforeCodes:[WGSL_Fun.quat_rotate]
260
+ })
261
+ ```
262
+
263
+ #### 点在 OBB 中的检测
264
+
265
+ ```wgsl
266
+ fn point_in_obb(point: vec3<f32>, center: vec3<f32>, halfSize: vec3<f32>, quat: vec4<f32>) -> bool
267
+ ```
268
+
269
+ ## 高级用法
270
+
271
+ ### 自定义工作组配置
272
+
273
+ ```javascript
274
+ await GpuComputed.computed({
275
+ code: '...',
276
+ data: {...},
277
+ workgroupCount: [4, 4], // 16 个工作组
278
+ workgroupSize: [16, 16], // 每个工作组 256 个线程
279
+ });
280
+ ```
281
+
282
+ ### 将数据同步回 CPU
283
+
284
+ ```javascript
285
+ const results = await GpuComputed.computed({
286
+ code: '...',
287
+ data: {...},
288
+ synchronize: ['output'], // 指定要同步的缓冲区
289
+ workgroupCount: [1]
290
+ });
291
+
292
+ // results 包含同步的数据
293
+ ```
294
+
295
+ ### 回调函数
296
+
297
+ ```javascript
298
+ await GpuComputed.computed({
299
+ code: '...',
300
+ data: {...},
301
+ workgroupCount: [1],
302
+ onSuccess: ({ code, bufferInfoList, results }) => {
303
+ console.log('计算完成', results);
304
+ }
305
+ });
306
+ ```
307
+
308
+ ## 示例项目
309
+
310
+ ```js
311
+ import { GpuComputed } from "webgpu-computed"
312
+ import * as WGSL_Fun from "webgpu-computed"
313
+
314
+ // 1. 初始化 WebGPU
315
+ console.log('初始化 WebGPU...');
316
+ await GpuComputed.init();
317
+ console.log('WebGPU 初始化成功');
318
+
319
+ // 2. 简单数组计算示例
320
+ console.log('\n=== 简单数组计算 ===');
321
+ const simpleData = {
322
+ inputA: [1.0, 2.0, 3.0, 4.0],
323
+ inputB: [0.5, 1.5, 2.5, 3.5],
324
+ output: new Array(4).fill(0)
325
+ };
326
+
327
+ const simpleCode = `
328
+ output[index] = inputA[index] + inputB[index];
329
+ `;
330
+
331
+ const simpleResults = await GpuComputed.computed({
332
+ code: simpleCode,
333
+ data: simpleData,
334
+ workgroupCount: [1],
335
+ synchronize: ['output']
336
+ });
337
+
338
+ console.log('简单计算结果:', simpleResults[0]); // [1.5, 3.5, 5.5, 7.5]
339
+
340
+ // 3. 复杂数据结构示例(结构体)
341
+ console.log('\n=== 复杂数据结构计算 ===');
342
+ const complexData = {
343
+ particles: [
344
+ { position: [1.0, 2.0, 3.0], velocity: [0.1, 0.2, 0.3], mass: 1.0 },
345
+ { position: [4.0, 5.0, 6.0], velocity: [0.4, 0.5, 0.6], mass: 2.0 }
346
+ ],
347
+ output: [
348
+ { position: [0, 0, 0], velocity: [0, 0, 0], mass: 0 },
349
+ { position: [0, 0, 0], velocity: [0, 0, 0], mass: 0 }
350
+ ]
351
+ };
352
+
353
+ const complexCode = `
354
+ output[index].position = particles[index].position + particles[index].velocity;
355
+ output[index].velocity = particles[index].velocity * 2.0;
356
+ output[index].mass = particles[index].mass * 1.5;
357
+ `;
358
+
359
+ const complexResults = await GpuComputed.computed({
360
+ code: complexCode,
361
+ data: complexData,
362
+ workgroupCount: [1],
363
+ synchronize: ['output']
364
+ });
365
+
366
+ console.log('复杂计算结果:', complexResults[0]);
367
+
368
+ // 4. 使用内置 WGSL 函数示例
369
+ console.log('\n=== 使用内置 WGSL 函数 ===');
370
+ const wgslFunData = {
371
+ points: [
372
+ {
373
+ x: 1.0, y: 0.0, z: 0.0
374
+ },
375
+ {
376
+ x: 0.0, y: 1.0, z: 0.0
377
+ },
378
+ {
379
+ x: -1.0, y: 0.0, z: 0.0
380
+ }
381
+ ],
382
+ obbCenter: [0.0, 0.0, 0.0],
383
+ obbHalfSize: [2.0, 2.0, 2.0],
384
+ obbRotation: [0.0, 0.0, 0.0, 1.0], // 单位四元数,无旋转
385
+ results: new Array(3).fill(0)
386
+ };
387
+
388
+ const wgslFunCode = `
389
+ let point = vec3(points[index].x, points[index].y, points[index].z);
390
+ let center = vec3<f32>(obbCenter[0], obbCenter[1], obbCenter[2]);
391
+ let halfSize = vec3<f32>(obbHalfSize[0], obbHalfSize[1], obbHalfSize[2]);
392
+ let quat = vec4<f32>(obbRotation[0], obbRotation[1], obbRotation[2], obbRotation[3]);
393
+
394
+ if (point_in_obb(point, center, halfSize, quat)) {
395
+ results[index] = 1.0;
396
+ } else {
397
+ results[index] = 0.0;
398
+ }
399
+ `;
400
+
401
+ const wgslFunResults = await GpuComputed.computed({
402
+ code: wgslFunCode,
403
+ data: wgslFunData,
404
+ workgroupCount: [1],
405
+ beforeCodes: [WGSL_Fun.quat_rotate, WGSL_Fun.point_in_obb, /** 可添加自己的函数代码 */],
406
+ synchronize: ['results']
407
+ });
408
+
409
+ console.log('OBB 检测结果:', wgslFunResults[0]); // [1, 1, 1] 所有点都在 OBB 内
410
+
411
+ // 5. 自定义工作组配置示例
412
+ console.log('\n=== 自定义工作组配置 ===');
413
+ const largeData = {
414
+ largeArray: new Array(1024).fill(0).map((_, i) => i * 1.0),
415
+ output: new Array(1024).fill(0)
416
+ };
417
+
418
+ const largeCode = `
419
+ output[index] = largeArray[index] * 2.0;
420
+ `;
421
+
422
+ const largeResults = await GpuComputed.computed({
423
+ code: largeCode,
424
+ data: largeData,
425
+ workgroupCount: [32], // 32 个工作组
426
+ workgroupSize: [32, 1, 1], // 每个工作组 32 个线程,总共 1024 个线程
427
+ synchronize: ['output']
428
+ });
429
+
430
+ console.log('大数组计算结果 (前 10 个):', largeResults[0].slice(0, 10));
431
+
432
+ // 6. 使用回调函数示例
433
+ console.log('\n=== 使用回调函数 ===');
434
+ const callbackData = {
435
+ values: [10.0, 20.0, 30.0],
436
+ squares: new Array(3).fill(0)
437
+ };
438
+
439
+ const callbackCode = `
440
+ squares[index] = values[index] * values[index];
441
+ `;
442
+
443
+ await GpuComputed.computed({
444
+ code: callbackCode,
445
+ data: callbackData,
446
+ workgroupCount: [1],
447
+ synchronize: ['squares'],
448
+ onSuccess: ({ code, bufferInfoList, results }) => {
449
+ console.log('回调触发,平方计算结果:', results[0]); // [100, 400, 900]
450
+ }
451
+ });
452
+
453
+ // 7. 多维工作组示例
454
+ console.log('\n=== 多维工作组 ===');
455
+ const matrixData = {
456
+ matrixA: new Array(16).fill(0).map((_, i) => i * 1.0),
457
+ matrixB: new Array(16).fill(0).map((_, i) => (i + 1) * 1.0),
458
+ result: new Array(16).fill(0)
459
+ };
460
+
461
+ const matrixCode = `
462
+ let x = index % 4u;
463
+ let y = index / 4u;
464
+ let idx = y * 4u + x;
465
+ result[idx] = matrixA[idx] + matrixB[idx];
466
+ `;
467
+
468
+ const matrixResults = await GpuComputed.computed({
469
+ code: matrixCode,
470
+ data: matrixData,
471
+ workgroupCount: [4, 4], // 4x4 工作组网格
472
+ workgroupSize: [1, 1, 1], // 每个工作组 1 个线程
473
+ synchronize: ['result']
474
+ });
475
+
476
+ console.log('矩阵计算结果:', matrixResults[0]);
477
+
478
+ console.log('\n所有功能示例完成!');
479
+ ```
480
+
481
+ ## 浏览器支持
482
+
483
+ - Chrome 113+
484
+ - Edge 113+
485
+ - Firefox (部分支持)
486
+ - Safari (部分支持)
487
+
488
+ 确保浏览器支持 WebGPU API。
489
+
490
+ ## 贡献
491
+
492
+ 欢迎提交 Issue 和 Pull Request!
493
+
494
+ ## 许可证
495
+
496
+ ISC License
497
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webgpu-computed",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "description": "对webgpu的封装,处理了繁琐的前置工作,只关注wgsl本身逻辑",
5
5
  "main": "./src/index.js",
6
6
  "scripts": {