webgpu-computed 0.0.18 → 0.0.19

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webgpu-computed",
3
- "version": "0.0.18",
3
+ "version": "0.0.19",
4
4
  "description": "对webgpu的封装,处理了繁琐的前置工作,只关注wgsl本身逻辑",
5
5
  "main": "./src/index.js",
6
6
  "scripts": {
package/src/index.js CHANGED
@@ -48,20 +48,20 @@ function U(f) {
48
48
  throw new Error(`${c} 不支持的类型`);
49
49
  });
50
50
  if (e.length !== r.length) throw new Error("keys 与 types 长度不一致");
51
- let s = 0;
51
+ let i = 0;
52
52
  const u = e.map((c, l) => {
53
53
  const y = r[l];
54
- s += _(s, y);
54
+ i += _(i, y);
55
55
  const a = {
56
56
  name: c,
57
57
  type: y,
58
- offset: s,
58
+ offset: i,
59
59
  size: $[y]
60
60
  };
61
- return s += $[y], a;
61
+ return i += $[y], a;
62
62
  }), t = Math.max(...r.map((c) => E[c]));
63
63
  return {
64
- stride: s + (t - s % t) % t,
64
+ stride: i + (t - i % t) % t,
65
65
  layout: u
66
66
  };
67
67
  }
@@ -107,7 +107,7 @@ class T {
107
107
  t.forEach((c) => {
108
108
  n += _(n, c.type), c.offset = n, c.size = $[c.type], n += c.size;
109
109
  });
110
- }, s = (t) => {
110
+ }, i = (t) => {
111
111
  r(t.layout);
112
112
  const n = t.layout[t.layout.length - 1], c = n.offset + n.size;
113
113
  let l = 1;
@@ -116,7 +116,7 @@ class T {
116
116
  };
117
117
  Object.keys(e).forEach((t) => {
118
118
  const n = e[t];
119
- m(n) ? r(n) : B(n) ? s(n) : Array.isArray(n) && typeof n[0] == "number" && (e[t] = new Float32Array());
119
+ m(n) ? r(n) : B(n) ? i(n) : Array.isArray(n) && typeof n[0] == "number" && (e[t] = new Float32Array());
120
120
  });
121
121
  }
122
122
  /** 获取Gpu设备
@@ -132,8 +132,8 @@ class T {
132
132
  async initPipeline() {
133
133
  if (!this.template) throw new Error("初始化计算管线错误,未找到可用数据模版");
134
134
  await T.init();
135
- const e = this.template, { device: r } = await this.getDevice(), s = [], u = [], t = [];
136
- this.device = r, Object.keys(e).forEach((i, d) => {
135
+ const e = this.template, { device: r } = await this.getDevice(), i = [], u = [], t = [];
136
+ this.device = r, Object.keys(e).forEach((s, d) => {
137
137
  if (t.push({
138
138
  binding: d,
139
139
  // 绑定到组里的0号位插槽
@@ -142,15 +142,15 @@ class T {
142
142
  buffer: {
143
143
  type: "storage"
144
144
  }
145
- }), m(e[i])) {
146
- const g = e[i], h = g.map((b) => `${b.name}:${b.type === "f32" ? "f32" : b.type + "<f32>"}`).join(","), v = `${S(i)}Struct`;
147
- s.push(`struct ${S(i)}Struct {${h}};`), u.push(`@group(0) @binding(${d}) var<storage, read_write> ${i}: ${v};`);
148
- } else if (B(e[i])) {
149
- const g = e[i], h = g.layout.map((b) => `${b.name}:${b.type === "f32" ? "f32" : b.type + "<f32>"}`).join(","), v = `${S(i)}Struct`;
150
- s.push(`struct ${v} {${h}};`), u.push(`@group(0) @binding(${d}) var<storage, read_write> ${i}: array<${v}>;`);
151
- } else if (ArrayBuffer.isView(e[i]) && !(e[i] instanceof DataView)) {
152
- const g = e[i], h = q(g);
153
- g instanceof D ? u.push(`@group(0) @binding(${d}) var<storage, read_write> ${i}: array<atomic<${h}>>;`) : u.push(`@group(0) @binding(${d}) var<storage, read_write> ${i}: array<${h}>;`);
145
+ }), m(e[s])) {
146
+ const g = e[s], h = g.map((b) => `${b.name}:${b.type === "f32" ? "f32" : b.type + "<f32>"}`).join(","), v = `${S(s)}Struct`;
147
+ i.push(`struct ${S(s)}Struct {${h}};`), u.push(`@group(0) @binding(${d}) var<storage, read_write> ${s}: ${v};`);
148
+ } else if (B(e[s])) {
149
+ const g = e[s], h = g.layout.map((b) => `${b.name}:${b.type === "f32" ? "f32" : b.type + "<f32>"}`).join(","), v = `${S(s)}Struct`;
150
+ i.push(`struct ${v} {${h}};`), u.push(`@group(0) @binding(${d}) var<storage, read_write> ${s}: array<${v}>;`);
151
+ } else if (ArrayBuffer.isView(e[s]) && !(e[s] instanceof DataView)) {
152
+ const g = e[s], h = q(g);
153
+ g instanceof D ? u.push(`@group(0) @binding(${d}) var<storage, read_write> ${s}: array<atomic<${h}>>;`) : u.push(`@group(0) @binding(${d}) var<storage, read_write> ${s}: array<${h}>;`);
154
154
  }
155
155
  });
156
156
  const {
@@ -162,7 +162,7 @@ class T {
162
162
  } = this.option ?? {}, o = (
163
163
  /*wgsl*/
164
164
  `
165
- ${s.join("")}
165
+ ${i.join("")}
166
166
  ${u.join("")}
167
167
  ${n.join(" ") ?? ""}
168
168
 
@@ -196,28 +196,28 @@ ${u.join("")}
196
196
  createBindGroup(e, r) {
197
197
  if (!this.template) throw new Error("创建buffer组错误,未找到可用数据模版");
198
198
  if (!this.device) throw new Error("创建buffer组错误,未找到可用的gpu设备,请确保初始化完计算管线");
199
- const s = this.device, u = this.template, t = [], n = r?.buffers?.reduce((a, o) => (a.set(o.name, o.buffer), a), /* @__PURE__ */ new Map());
200
- function c(a, o, p = 0, i) {
199
+ const i = this.device, u = this.template, t = [], n = r?.buffers?.reduce((a, o) => (a.set(o.name, o.buffer), a), /* @__PURE__ */ new Map());
200
+ function c(a, o, p = 0, s) {
201
201
  if (ArrayBuffer.isView(a) || Array.isArray(a)) return a;
202
- if (!i) {
202
+ if (!s) {
203
203
  const d = o[o.length - 1], g = d.offset + d.size;
204
204
  let h = 1;
205
205
  for (const v of o) h = Math.max(h, E[v.type]);
206
- i = i ?? new Float32Array(P(g, h)).fill(0);
206
+ s = s ?? new Float32Array(P(g, h)).fill(0);
207
207
  }
208
208
  return o.forEach((d) => {
209
209
  let g = a[d.name];
210
210
  Array.isArray(g) || (g = [g]);
211
211
  for (let h = 0; h < d.size; h++)
212
- i[p + d.offset + h] = Number(g[h] ?? 0);
213
- }), i;
212
+ s[p + d.offset + h] = Number(g[h] ?? 0);
213
+ }), s;
214
214
  }
215
215
  function l(a, o) {
216
216
  if (ArrayBuffer.isView(a) || typeof a[0] == "number") return a;
217
217
  const p = new Float32Array(o.stride * a.length).fill(0);
218
- return a.forEach((i, d) => {
218
+ return a.forEach((s, d) => {
219
219
  const g = d * o.stride;
220
- c(i, o.layout, g, p);
220
+ c(s, o.layout, g, p);
221
221
  }), p;
222
222
  }
223
223
  return Object.keys(u).forEach((a) => {
@@ -227,17 +227,17 @@ ${u.join("")}
227
227
  throw new Error(`传入的数据中,不存在${a}字段`);
228
228
  }
229
229
  const o = u[a], p = e[a];
230
- let i = [];
231
- m(o) ? i = c(p, o) : B(o) ? i = l(p, o) : (Array.isArray(p) || ArrayBuffer.isView(p)) && (i = p);
230
+ let s = [];
231
+ m(o) ? s = c(p, o) : B(o) ? s = l(p, o) : (Array.isArray(p) || ArrayBuffer.isView(p)) && (s = p);
232
232
  let d = null;
233
- if (o instanceof Float32Array ? d = new Float32Array(i) : o instanceof Uint32Array ? d = new Uint32Array(i) : o instanceof Int32Array ? d = new Int32Array(i) : d = new Float32Array(i), !d) throw new Error("不支持的数组类型" + o);
234
- const g = s.createBuffer({
233
+ if (o instanceof Float32Array ? d = new Float32Array(s) : o instanceof Uint32Array ? d = new Uint32Array(s) : o instanceof Int32Array ? d = new Int32Array(s) : d = new Float32Array(s), !d) throw new Error("不支持的数组类型" + o);
234
+ const g = i.createBuffer({
235
235
  size: d.byteLength,
236
236
  usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE
237
237
  });
238
- s.queue.writeBuffer(g, 0, d), t.push({ name: a, buffer: g });
238
+ i.queue.writeBuffer(g, 0, d), t.push({ name: a, buffer: g });
239
239
  }), {
240
- group: s.createBindGroup({
240
+ group: i.createBindGroup({
241
241
  layout: this.groupLayout,
242
242
  entries: t.map((a, o) => ({
243
243
  binding: o,
@@ -254,10 +254,10 @@ ${u.join("")}
254
254
  dataMap(e, r) {
255
255
  if (!(r in this.template)) throw new Error("未找到数据字段:" + r);
256
256
  if (B(this.template[r])) {
257
- const s = this.template[r], u = e.length / s.stride, t = [];
257
+ const i = this.template[r], u = e.length / i.stride, t = [];
258
258
  for (let n = 0; n < u; n++) {
259
- const c = n * s.stride, l = {};
260
- s.layout.forEach((y) => {
259
+ const c = n * i.stride, l = {};
260
+ i.layout.forEach((y) => {
261
261
  const a = e.slice(c + y.offset, c + y.offset + y.size);
262
262
  l[y.name] = a.length === 1 ? a[0] : [...a];
263
263
  }), t.push(l);
@@ -265,8 +265,8 @@ ${u.join("")}
265
265
  return t;
266
266
  }
267
267
  if (m(this.template[r])) {
268
- const s = this.template[r], u = {};
269
- return s.forEach((t) => {
268
+ const i = this.template[r], u = {};
269
+ return i.forEach((t) => {
270
270
  const n = e.slice(t.offset, t.offset + t.size);
271
271
  u[t.name] = n.length === 1 ? n[0] : [...n];
272
272
  }), u;
@@ -279,12 +279,12 @@ ${u.join("")}
279
279
  * @param synchronize 需要同步的数据字段
280
280
  * @returns
281
281
  */
282
- async computed(e, r, s = []) {
282
+ async computed(e, r, i = []) {
283
283
  if (!this.pipeline) throw new Error("未找到可用计算管线,请确保计算管线已经创建成功");
284
284
  const u = this.device, t = this.pipeline, n = u.createCommandEncoder(), c = n.beginComputePass();
285
285
  c.setPipeline(t), c.setBindGroup(0, e.group), c.dispatchWorkgroups(r[0], r[1], r[2]), c.end();
286
286
  const l = e.buffers?.map((o) => {
287
- if (s?.includes(o.name)) {
287
+ if (i?.includes(o.name)) {
288
288
  const p = u.createBuffer({
289
289
  size: o.buffer.size,
290
290
  usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST
@@ -298,23 +298,23 @@ ${u.join("")}
298
298
  l.map(async (o) => {
299
299
  await o.buffer.mapAsync(GPUMapMode.READ);
300
300
  const p = o.buffer.getMappedRange();
301
- let i = null;
302
- this.template[o.name] instanceof Float32Array ? i = new Float32Array(p) : this.template[o.name] instanceof Uint32Array ? i = new Uint32Array(p) : this.template[o.name] instanceof Int32Array ? i = new Int32Array(p) : i = new Float32Array(p), y.set(o.name, i);
301
+ let s = null;
302
+ this.template[o.name] instanceof Float32Array ? s = new Float32Array(p) : this.template[o.name] instanceof Uint32Array ? s = new Uint32Array(p) : this.template[o.name] instanceof Int32Array ? s = new Int32Array(p) : s = new Float32Array(p), y.set(o.name, s);
303
303
  })
304
- ), s.map((o) => y.get(o));
304
+ ), i.map((o) => y.get(o));
305
305
  }
306
306
  /** 初始化gpu设备
307
307
  * @returns
308
308
  */
309
- static async init() {
309
+ static async init(e = {}) {
310
310
  if (!(w && A)) {
311
311
  if (typeof globalThis < "u" && typeof window > "u") {
312
- const { create: e, globals: r } = await z("webgpu", !1);
313
- Object.assign(globalThis, r), globalThis.navigator || (globalThis.navigator = {}), Object.assign(globalThis.navigator, { gpu: e([]) });
312
+ const { create: r, globals: i } = await z("webgpu", !1);
313
+ Object.assign(globalThis, i), globalThis.navigator || (globalThis.navigator = {}), Object.assign(globalThis.navigator, { gpu: r([]) });
314
314
  }
315
315
  if (!navigator.gpu) throw new Error("该环境不支持webgpu");
316
- if (w || (w = await navigator.gpu.requestAdapter({})), !w) throw new Error("获取适配器失败");
317
- if (A = await w.requestDevice(), !w) throw new Error("获取设备失败");
316
+ if (w || (w = await navigator.gpu.requestAdapter(e)), !w) throw new Error("获取适配器失败");
317
+ if (A = await w.requestDevice(e), !w) throw new Error("获取设备失败");
318
318
  }
319
319
  }
320
320
  /** 注销gpu设备
@@ -326,20 +326,20 @@ ${u.join("")}
326
326
  * @param data
327
327
  */
328
328
  static buildBufferTypeByData(e) {
329
- return Object.keys(e).reduce((s, u) => {
329
+ return Object.keys(e).reduce((i, u) => {
330
330
  let t = e[u];
331
331
  if (Array.isArray(t) && typeof t[0] == "number" && (t = new Float32Array()), Array.isArray(t))
332
332
  if (typeof t[0] == "object" || t.length) {
333
333
  const n = U(t[0]);
334
- s[u] = n;
334
+ i[u] = n;
335
335
  } else console.log(`字段:${u}, 不支持该值对应数据类型或数组为空`);
336
336
  else if (ArrayBuffer.isView(t) && !(t instanceof DataView))
337
- s[u] = t;
337
+ i[u] = t;
338
338
  else if (typeof t == "object") {
339
339
  const n = U(t);
340
- s[u] = n.layout;
340
+ i[u] = n.layout;
341
341
  } else console.log(`字段:${u}, 不支持的数据类型`);
342
- return s;
342
+ return i;
343
343
  }, {});
344
344
  }
345
345
  /** 通过数据创建
@@ -347,8 +347,8 @@ ${u.join("")}
347
347
  * @returns
348
348
  */
349
349
  static async fromByData(e) {
350
- let { data: r, ...s } = e;
351
- const u = this.buildBufferTypeByData(r), t = new T(u, s);
350
+ let { data: r, ...i } = e;
351
+ const u = this.buildBufferTypeByData(r), t = new T(u, i);
352
352
  return await t.initPipeline(), t;
353
353
  }
354
354
  /** 快捷计算方法
@@ -356,9 +356,9 @@ ${u.join("")}
356
356
  * @returns
357
357
  */
358
358
  static async computed(e) {
359
- let { data: r, map: s = !1, workgroupCount: u, synchronize: t, onSuccess: n, ...c } = e;
359
+ let { data: r, map: i = !1, workgroupCount: u, synchronize: t, onSuccess: n, ...c } = e;
360
360
  const l = await this.fromByData({ data: r, ...c }), y = l.createBindGroup(r), a = await l.computed(y, u, t);
361
- return n && n({ gpuComputed: l, group: y, results: a }), s ? a.map((o, p) => l.dataMap(o, t[p])) : a;
361
+ return n && n({ gpuComputed: l, group: y, results: a }), i ? a.map((o, p) => l.dataMap(o, t[p])) : a;
362
362
  }
363
363
  }
364
364
  const M = (
@@ -26,6 +26,15 @@ interface IStructArray {
26
26
  layout: IStruct;
27
27
  }
28
28
  type BufferDataType = Record<string, (number[]) | ArrayBufferView | IStruct | IStructArray>;
29
+ type InitOption = {
30
+ featureLevel?: string;
31
+ powerPreference?: GPUPowerPreference;
32
+ forceFallbackAdapter?: boolean;
33
+ xrCompatible?: boolean;
34
+ requiredFeatures?: Iterable<GPUFeatureName>;
35
+ requiredLimits?: Record<string, GPUSize64 | undefined>;
36
+ defaultQueue?: GPUQueueDescriptor;
37
+ };
29
38
  export declare class AtomicUint32Array extends Uint32Array {
30
39
  }
31
40
  export declare class GpuComputed {
@@ -85,7 +94,7 @@ export declare class GpuComputed {
85
94
  /** 初始化gpu设备
86
95
  * @returns
87
96
  */
88
- static init(): Promise<void>;
97
+ static init(opt?: InitOption): Promise<void>;
89
98
  /** 注销gpu设备
90
99
  */
91
100
  static destroy(): void;