webgpu-computed 0.0.5 → 0.0.7

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 CHANGED
@@ -12,6 +12,7 @@ A simplified WebGPU computing library that encapsulates tedious initialization a
12
12
  - 🔧 Support for complex data structures (vectors, matrices)
13
13
  - ⚡ High-performance GPU computing
14
14
  - 📚 Built-in common WGSL functions
15
+ - ✅ Support node
15
16
 
16
17
  ## Installation
17
18
 
@@ -19,23 +20,6 @@ A simplified WebGPU computing library that encapsulates tedious initialization a
19
20
  npm install webgpu-computed
20
21
  ```
21
22
 
22
- ## Node.js Environment Configuration
23
-
24
- You can install the webgpu package
25
-
26
- ```bash
27
- npm install webgpu
28
- ```
29
-
30
- Then initialize the environment
31
-
32
- ```js
33
- import { create, globals } from 'webgpu'
34
-
35
- Object.assign(globalThis, globals)
36
- const navigator = { gpu: create([]) }
37
- ```
38
-
39
23
  ## Quick Start
40
24
 
41
25
  ### 1. Initialize WebGPU
@@ -47,6 +31,8 @@ import { GpuComputed } from 'webgpu-computed';
47
31
 
48
32
  // Initialize WebGPU
49
33
  await GpuComputed.init();
34
+ //After using the node environment, please call:
35
+ //GpuComputed.destroy()
50
36
  ```
51
37
 
52
38
  ### 2. Perform Simple Computation
package/README.zh-CN.md CHANGED
@@ -9,6 +9,7 @@
9
9
  - 🔧 支持复杂数据结构(向量、矩阵)
10
10
  - ⚡ 高性能 GPU 计算
11
11
  - 📚 内置常用 WGSL 函数
12
+ - ✅ 支持Node
12
13
 
13
14
  ## 安装
14
15
 
@@ -16,19 +17,6 @@
16
17
  npm install webgpu-computed
17
18
  ```
18
19
 
19
- ## node 环境配置
20
- 可安装webgpu包
21
- ```bash
22
- npm install webgpu
23
- ```
24
- 然后初始化环境
25
- ```js
26
- import { create, globals } from 'webgpu'
27
-
28
- Object.assign(globalThis, globals)
29
- const navigator = { gpu: create([]) }
30
- ```
31
-
32
20
  ## 快速开始
33
21
 
34
22
  ### 1. 初始化 WebGPU
@@ -40,6 +28,8 @@ import { GpuComputed } from 'webgpu-computed';
40
28
 
41
29
  // 初始化 WebGPU
42
30
  await GpuComputed.init();
31
+ // node 环境使用完请调用:
32
+ // GpuComputed.destroy()
43
33
  ```
44
34
 
45
35
  ### 2. 执行简单计算
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webgpu-computed",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "description": "对webgpu的封装,处理了繁琐的前置工作,只关注wgsl本身逻辑",
5
5
  "main": "./src/index.js",
6
6
  "scripts": {
@@ -9,6 +9,13 @@
9
9
  "keywords": [
10
10
  "webgpu", "computed", "web", "js"
11
11
  ],
12
+ "dependencies": {
13
+ "webgpu": "^0.3.8"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/xiaguochuqiu/webgpu-computed.git"
18
+ },
12
19
  "author": "夏过初秋",
13
20
  "license": "ISC"
14
21
  }
package/src/index.d.ts CHANGED
@@ -13,6 +13,7 @@ declare type BufferType = {
13
13
  export declare class GpuComputed {
14
14
  constructor();
15
15
  static init(): Promise<void>;
16
+ static destroy(): void;
16
17
  getDevice(): Promise<{
17
18
  adapter: GPUAdapter;
18
19
  device: GPUDevice;
package/src/index.js CHANGED
@@ -1,11 +1,22 @@
1
- const m = {
1
+ async function P(v, r = !0) {
2
+ if (typeof global < "u" && typeof require < "u")
3
+ return require(v);
4
+ {
5
+ let e = await import(
6
+ /* @vite-ignore */
7
+ v
8
+ );
9
+ return r && (e = e.default), e;
10
+ }
11
+ }
12
+ const w = {
2
13
  f32: 1,
3
14
  vec2: 2,
4
15
  vec3: 3,
5
16
  vec4: 4,
6
17
  mat3x3: 12,
7
18
  mat4x4: 16
8
- }, w = {
19
+ }, h = {
9
20
  f32: 1,
10
21
  vec2: 2,
11
22
  vec3: 4,
@@ -13,33 +24,42 @@ const m = {
13
24
  mat3x3: 4,
14
25
  mat4x4: 4
15
26
  };
16
- function P(A, c) {
17
- const o = w[c];
18
- return (o - A % o) % o;
27
+ function B(v, r) {
28
+ const e = h[r];
29
+ return (e - v % e) % e;
19
30
  }
20
- let b = null, v = null;
21
- class h {
31
+ let y = null, m = null;
32
+ class A {
22
33
  constructor() {
23
34
  }
24
35
  static async init() {
25
- if (!navigator.gpu) throw new Error("该环境不支持webgpu");
26
- if (b = await navigator.gpu.requestAdapter({}), !b) throw new Error("获取适配器失败");
27
- if (v = await b.requestDevice(), !b) throw new Error("获取设备失败");
36
+ if (!(y && m)) {
37
+ if (typeof globalThis < "u" && typeof window > "u") {
38
+ const { create: r, globals: e } = await P("webgpu", !1);
39
+ Object.assign(globalThis, e), globalThis.navigator || (globalThis.navigator = {}), Object.assign(globalThis.navigator, { gpu: r([]) });
40
+ }
41
+ if (!navigator.gpu) throw new Error("该环境不支持webgpu");
42
+ if (y || (y = await navigator.gpu.requestAdapter({})), !y) throw new Error("获取适配器失败");
43
+ if (m = await y.requestDevice(), !y) throw new Error("获取设备失败");
44
+ }
45
+ }
46
+ static destroy() {
47
+ m && m.destroy(), m = null;
28
48
  }
29
49
  async getDevice() {
30
- if (!b || !v) throw new Error("webgpu未初始化或不可用");
31
- return { adapter: b, device: v };
50
+ if (!y || !m) throw new Error("webgpu未初始化或不可用");
51
+ return { adapter: y, device: m };
32
52
  }
33
- async createPipeline(c, o) {
34
- const { device: r } = await this.getDevice(), n = Object.keys(o).map((f, s) => {
35
- const a = o[f], i = new Float32Array(Array.isArray(a) ? a : a.buffer), e = r.createBuffer({
36
- size: i.byteLength,
53
+ async createPipeline(r, e) {
54
+ const { device: o } = await this.getDevice(), a = Object.keys(e).map((f, s) => {
55
+ const i = e[f], u = new Float32Array(Array.isArray(i) ? i : i.buffer), t = o.createBuffer({
56
+ size: u.byteLength,
37
57
  usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE
38
58
  });
39
- return r.queue.writeBuffer(e, 0, i), {
59
+ return o.queue.writeBuffer(t, 0, u), {
40
60
  name: f,
41
- buffer: e,
42
- float32Array: i,
61
+ buffer: t,
62
+ float32Array: u,
43
63
  groupLayoutItem: {
44
64
  binding: s,
45
65
  // 绑定到组里的0号位插槽
@@ -51,134 +71,134 @@ class h {
51
71
  },
52
72
  groupItem: {
53
73
  binding: s,
54
- resource: { buffer: e }
74
+ resource: { buffer: t }
55
75
  }
56
76
  };
57
- }), l = r.createBindGroupLayout({
58
- entries: n.map((f) => f.groupLayoutItem)
59
- }), g = r.createBindGroup({
77
+ }), l = o.createBindGroupLayout({
78
+ entries: a.map((f) => f.groupLayoutItem)
79
+ }), g = o.createBindGroup({
60
80
  layout: l,
61
- entries: n.map((f) => f.groupItem)
81
+ entries: a.map((f) => f.groupItem)
62
82
  });
63
- return { pipeline: r.createComputePipeline({
64
- layout: r.createPipelineLayout({
83
+ return { pipeline: o.createComputePipeline({
84
+ layout: o.createPipelineLayout({
65
85
  bindGroupLayouts: [l]
66
86
  }),
67
87
  compute: {
68
- module: r.createShaderModule({ code: c, label: "" }),
88
+ module: o.createShaderModule({ code: r, label: "" }),
69
89
  entryPoint: "main"
70
90
  }
71
- }), group: g, device: r, bufferInfoList: n };
91
+ }), group: g, device: o, bufferInfoList: a };
72
92
  }
73
- buildCode(c, o, r) {
93
+ buildCode(r, e, o) {
74
94
  const {
75
- workgroupSize: n = [32, 1, 1],
95
+ workgroupSize: a = [32, 1, 1],
76
96
  globalInvocationIdName: l = "grid",
77
97
  workgroupIndexName: g = "index"
78
- } = r ?? {}, y = (e) => e && e[0].toUpperCase() + e.slice(1), f = Object.keys(c).map((e) => {
79
- const p = c[e];
80
- return Array.isArray(p) ? void 0 : `struct ${y(e)}Struct { ${p.layout.map((t) => `${t.name}: ${t.type === "f32" ? "f32" : `${t.type}<f32>`}`).join(",")} };`;
81
- }).filter((e) => !!e).join(`
82
- `), s = Object.keys(c).map((e, p) => {
83
- const u = c[e], t = "read_write";
84
- return Array.isArray(u) ? `@group(0) @binding(${p}) var<storage, ${t}> ${e}: array<f32>;` : `@group(0) @binding(${p}) var<storage, ${t}> ${e}: array<${y(e)}Struct>;`;
98
+ } = o ?? {}, d = (t) => t && t[0].toUpperCase() + t.slice(1), f = Object.keys(r).map((t) => {
99
+ const p = r[t];
100
+ return Array.isArray(p) ? void 0 : `struct ${d(t)}Struct { ${p.layout.map((n) => `${n.name}: ${n.type === "f32" ? "f32" : `${n.type}<f32>`}`).join(",")} };`;
101
+ }).filter((t) => !!t).join(`
102
+ `), s = Object.keys(r).map((t, p) => {
103
+ const c = r[t], n = "read_write";
104
+ return Array.isArray(c) ? `@group(0) @binding(${p}) var<storage, ${n}> ${t}: array<f32>;` : `@group(0) @binding(${p}) var<storage, ${n}> ${t}: array<${d(t)}Struct>;`;
85
105
  }).join(`
86
- `), a = l;
106
+ `), i = l;
87
107
  return (
88
108
  /*wgsl*/
89
109
  `
90
110
  ${f}
91
111
  ${s}
92
112
 
93
- ${r?.beforeCodes?.join(" ") ?? ""}
113
+ ${o?.beforeCodes?.join(" ") ?? ""}
94
114
 
95
- @compute @workgroup_size(${n.join(",")})
96
- fn main(@builtin(global_invocation_id) ${a}: vec3<u32>) {
97
- var ${g} = ${a}.x;
98
- ${o}
115
+ @compute @workgroup_size(${a.join(",")})
116
+ fn main(@builtin(global_invocation_id) ${i}: vec3<u32>) {
117
+ var ${g} = ${i}.x;
118
+ ${e}
99
119
  }
100
120
  `
101
121
  );
102
122
  }
103
- buildBuffer(c, o, r) {
104
- if (!Array.isArray(c) || c.length === 0)
123
+ buildBuffer(r, e, o) {
124
+ if (!Array.isArray(r) || r.length === 0)
105
125
  throw new Error("数据必须是非空数组");
106
- if (o || (o = Object.keys(c[0])), r || (r = o.map((s) => {
107
- const a = c[0][s];
108
- if (Array.isArray(a)) {
109
- for (const i of ["vec2", "vec3", "vec4", "mat3x3", "mat4x4"])
110
- if (m[i] === a.length) return i;
111
- throw new Error(`${s} 不支持的数组长度 ${a.length}`);
126
+ if (e || (e = Object.keys(r[0])), o || (o = e.map((s) => {
127
+ const i = r[0][s];
128
+ if (Array.isArray(i)) {
129
+ for (const u of ["vec2", "vec3", "vec4", "mat3x3", "mat4x4"])
130
+ if (w[u] === i.length) return u;
131
+ throw new Error(`${s} 不支持的数组长度 ${i.length}`);
112
132
  }
113
- if (typeof a == "number") return "f32";
133
+ if (typeof i == "number") return "f32";
114
134
  throw new Error(`${s} 不支持的类型`);
115
- })), o.length !== r.length) throw new Error("keys 与 types 长度不一致");
116
- let n = 0;
117
- const l = o.map((s, a) => {
118
- const i = r[a];
119
- n += P(n, i);
120
- const e = {
135
+ })), e.length !== o.length) throw new Error("keys 与 types 长度不一致");
136
+ let a = 0;
137
+ const l = e.map((s, i) => {
138
+ const u = o[i];
139
+ a += B(a, u);
140
+ const t = {
121
141
  name: s,
122
- type: i,
123
- offset: n,
124
- size: m[i]
142
+ type: u,
143
+ offset: a,
144
+ size: w[u]
125
145
  };
126
- return n += m[i], e;
127
- }), g = Math.max(...r.map((s) => w[s])), y = n + (g - n % g) % g, f = new Array(y * c.length).fill(0);
128
- return c.forEach((s, a) => {
129
- const i = a * y;
130
- l.forEach(({ name: e, offset: p, size: u }) => {
131
- let t = s[e];
132
- Array.isArray(t) || (t = [t]);
133
- for (let d = 0; d < u; d++)
134
- f[i + p + d] = Number(t[d] ?? 0);
146
+ return a += w[u], t;
147
+ }), g = Math.max(...o.map((s) => h[s])), d = a + (g - a % g) % g, f = new Array(d * r.length).fill(0);
148
+ return r.forEach((s, i) => {
149
+ const u = i * d;
150
+ l.forEach(({ name: t, offset: p, size: c }) => {
151
+ let n = s[t];
152
+ Array.isArray(n) || (n = [n]);
153
+ for (let b = 0; b < c; b++)
154
+ f[u + p + b] = Number(n[b] ?? 0);
135
155
  });
136
156
  }), {
137
157
  buffer: f,
138
- stride: y,
158
+ stride: d,
139
159
  layout: l,
140
- count: c.length
160
+ count: r.length
141
161
  };
142
162
  }
143
- async computed(c) {
144
- let { code: o, data: r, ...n } = c;
145
- const l = Object.keys(r).reduce((u, t) => {
146
- const d = r[t];
147
- if (typeof d[0] == "number") u[t] = d;
163
+ async computed(r) {
164
+ let { code: e, data: o, ...a } = r;
165
+ const l = Object.keys(o).reduce((c, n) => {
166
+ const b = o[n];
167
+ if (typeof b[0] == "number") c[n] = b;
148
168
  else {
149
- const $ = this.buildBuffer(d);
150
- u[t] = $;
169
+ const $ = this.buildBuffer(b);
170
+ c[n] = $;
151
171
  }
152
- return u;
172
+ return c;
153
173
  }, {});
154
- o = this.buildCode(l, o, n);
155
- const { pipeline: g, group: y, device: f, bufferInfoList: s } = await this.createPipeline(o, l), a = f.createCommandEncoder(), i = a.beginComputePass();
156
- i.setPipeline(g), i.setBindGroup(0, y), i.dispatchWorkgroups(n.workgroupCount[0], n.workgroupCount[1], n.workgroupCount[2]), i.end();
157
- const e = s?.map((u) => {
158
- if (n.synchronize?.includes(u.name)) {
159
- const t = f.createBuffer({
160
- size: u.float32Array.byteLength,
174
+ e = this.buildCode(l, e, a);
175
+ const { pipeline: g, group: d, device: f, bufferInfoList: s } = await this.createPipeline(e, l), i = f.createCommandEncoder(), u = i.beginComputePass();
176
+ u.setPipeline(g), u.setBindGroup(0, d), u.dispatchWorkgroups(a.workgroupCount[0], a.workgroupCount[1], a.workgroupCount[2]), u.end();
177
+ const t = s?.map((c) => {
178
+ if (a.synchronize?.includes(c.name)) {
179
+ const n = f.createBuffer({
180
+ size: c.float32Array.byteLength,
161
181
  usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST
162
182
  });
163
- return a.copyBufferToBuffer(u.buffer, 0, t, 0, t.size), { buffer: t, name: u.name };
183
+ return i.copyBufferToBuffer(c.buffer, 0, n, 0, n.size), { buffer: n, name: c.name };
164
184
  }
165
- }).filter((u) => !!u);
166
- f.queue.submit([a.finish()]), await f.queue.onSubmittedWorkDone();
185
+ }).filter((c) => !!c);
186
+ f.queue.submit([i.finish()]), await f.queue.onSubmittedWorkDone();
167
187
  const p = await Promise.all(
168
- e.map(async (u) => {
169
- await u.buffer.mapAsync(GPUMapMode.READ);
170
- const t = u.buffer.getMappedRange();
171
- return [...new Float32Array(t)];
188
+ t.map(async (c) => {
189
+ await c.buffer.mapAsync(GPUMapMode.READ);
190
+ const n = c.buffer.getMappedRange();
191
+ return [...new Float32Array(n)];
172
192
  })
173
193
  );
174
- return n?.onSuccess && n.onSuccess({ code: o, bufferInfoList: s, results: p }), p;
194
+ return a?.onSuccess && a.onSuccess({ code: e, bufferInfoList: s, results: p }), p;
175
195
  }
176
196
  static instance;
177
197
  static get computed() {
178
- return this.instance || (this.instance = new h()), this.instance.computed.bind(this.instance);
198
+ return this.instance || (this.instance = new A()), this.instance.computed.bind(this.instance);
179
199
  }
180
200
  }
181
- const B = Object.freeze({
201
+ const q = Object.freeze({
182
202
  quat_rotate: (
183
203
  /* wgsl */
184
204
  `
@@ -212,6 +232,6 @@ const B = Object.freeze({
212
232
  )
213
233
  });
214
234
  export {
215
- h as GpuComputed,
216
- B as WGSL_Fun
235
+ A as GpuComputed,
236
+ q as WGSL_Fun
217
237
  };