@tapez/core 0.0.0-alpha.2 → 0.0.0-alpha.4
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 +33 -0
- package/dist/index.d.ts +389 -21
- package/dist/index.js +556 -30
- package/dist/index.js.map +1 -1
- package/package.json +7 -5
- package/dist/array.d.ts +0 -26
- package/dist/array.d.ts.map +0 -1
- package/dist/array.js +0 -30
- package/dist/array.js.map +0 -1
- package/dist/bind-helpers.d.ts +0 -36
- package/dist/bind-helpers.d.ts.map +0 -1
- package/dist/bind-helpers.js +0 -44
- package/dist/bind-helpers.js.map +0 -1
- package/dist/const.d.ts +0 -26
- package/dist/const.d.ts.map +0 -1
- package/dist/const.js +0 -43
- package/dist/const.js.map +0 -1
- package/dist/gpu-buffer-utils.d.ts +0 -40
- package/dist/gpu-buffer-utils.d.ts.map +0 -1
- package/dist/gpu-buffer-utils.js +0 -105
- package/dist/gpu-buffer-utils.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/layout.d.ts +0 -36
- package/dist/layout.d.ts.map +0 -1
- package/dist/layout.js +0 -39
- package/dist/layout.js.map +0 -1
- package/dist/matrix.d.ts +0 -20
- package/dist/matrix.d.ts.map +0 -1
- package/dist/matrix.js +0 -25
- package/dist/matrix.js.map +0 -1
- package/dist/schemas.d.ts +0 -61
- package/dist/schemas.d.ts.map +0 -1
- package/dist/schemas.js +0 -85
- package/dist/schemas.js.map +0 -1
- package/dist/struct.d.ts +0 -47
- package/dist/struct.d.ts.map +0 -1
- package/dist/struct.js +0 -81
- package/dist/struct.js.map +0 -1
- package/dist/typed-buffer.d.ts +0 -117
- package/dist/typed-buffer.d.ts.map +0 -1
- package/dist/typed-buffer.js +0 -273
- package/dist/typed-buffer.js.map +0 -1
- package/dist/types.d.ts +0 -33
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -23
- package/dist/types.js.map +0 -1
- package/dist/vectors.d.ts +0 -26
- package/dist/vectors.d.ts.map +0 -1
- package/dist/vectors.js +0 -44
- package/dist/vectors.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,31 +1,557 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
1
|
+
// src/types.ts
|
|
2
|
+
function scalar(wgslType, arrayKind) {
|
|
3
|
+
return Object.freeze({ kind: "scalar", wgslType, byteSize: 4, alignment: 4, arrayKind });
|
|
4
|
+
}
|
|
5
|
+
var f32 = scalar("f32", "f32");
|
|
6
|
+
var u32 = scalar("u32", "u32");
|
|
7
|
+
var i32 = scalar("i32", "i32");
|
|
8
|
+
function atomic(inner) {
|
|
9
|
+
return Object.freeze({
|
|
10
|
+
kind: "atomic",
|
|
11
|
+
wgslType: `atomic<${inner.wgslType}>`,
|
|
12
|
+
byteSize: inner.byteSize,
|
|
13
|
+
alignment: inner.alignment,
|
|
14
|
+
inner,
|
|
15
|
+
arrayKind: inner.arrayKind
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// src/vectors.ts
|
|
20
|
+
function vec(components, componentType) {
|
|
21
|
+
const suffix = componentType.wgslType[0];
|
|
22
|
+
const wgslType = `vec${components}<${componentType.wgslType}>`;
|
|
23
|
+
let byteSize;
|
|
24
|
+
let alignment;
|
|
25
|
+
switch (components) {
|
|
26
|
+
case 2:
|
|
27
|
+
byteSize = 8;
|
|
28
|
+
alignment = 8;
|
|
29
|
+
break;
|
|
30
|
+
case 3:
|
|
31
|
+
byteSize = 12;
|
|
32
|
+
alignment = 16;
|
|
33
|
+
break;
|
|
34
|
+
case 4:
|
|
35
|
+
byteSize = 16;
|
|
36
|
+
alignment = 16;
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
return Object.freeze({ kind: "vector", wgslType, byteSize, alignment, components, componentType });
|
|
40
|
+
}
|
|
41
|
+
var vec2f = vec(2, f32);
|
|
42
|
+
var vec3f = vec(3, f32);
|
|
43
|
+
var vec4f = vec(4, f32);
|
|
44
|
+
var vec2u = vec(2, u32);
|
|
45
|
+
var vec3u = vec(3, u32);
|
|
46
|
+
var vec4u = vec(4, u32);
|
|
47
|
+
var vec2i = vec(2, i32);
|
|
48
|
+
var vec3i = vec(3, i32);
|
|
49
|
+
var vec4i = vec(4, i32);
|
|
50
|
+
|
|
51
|
+
// src/matrix.ts
|
|
52
|
+
function mat(cols, rows, byteSize, alignment) {
|
|
53
|
+
return Object.freeze({
|
|
54
|
+
kind: "matrix",
|
|
55
|
+
wgslType: `mat${cols}x${rows}<f32>`,
|
|
56
|
+
byteSize,
|
|
57
|
+
alignment,
|
|
58
|
+
columns: cols,
|
|
59
|
+
rows
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
var mat2x2f = mat(2, 2, 16, 8);
|
|
63
|
+
var mat3x3f = mat(3, 3, 48, 16);
|
|
64
|
+
var mat4x4f = mat(4, 4, 64, 16);
|
|
65
|
+
|
|
66
|
+
// src/layout.ts
|
|
67
|
+
function roundUp(alignment, offset) {
|
|
68
|
+
return Math.ceil(offset / alignment) * alignment;
|
|
69
|
+
}
|
|
70
|
+
function computeStructLayout(fields) {
|
|
71
|
+
const layouts = [];
|
|
72
|
+
const offsets = {};
|
|
73
|
+
let offset = 0;
|
|
74
|
+
let maxAlignment = 1;
|
|
75
|
+
for (const { name, type } of fields) {
|
|
76
|
+
offset = roundUp(type.alignment, offset);
|
|
77
|
+
layouts.push({ name, type, offset });
|
|
78
|
+
offsets[name] = offset;
|
|
79
|
+
offset += type.byteSize;
|
|
80
|
+
if (type.alignment > maxAlignment) {
|
|
81
|
+
maxAlignment = type.alignment;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const byteSize = roundUp(maxAlignment, offset);
|
|
85
|
+
return { fields: layouts, byteSize, alignment: maxAlignment, offsets };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// src/struct.ts
|
|
89
|
+
function struct(name, fields) {
|
|
90
|
+
const fieldOrder = Object.keys(fields);
|
|
91
|
+
const fieldEntries = fieldOrder.map((k) => {
|
|
92
|
+
const t = fields[k];
|
|
93
|
+
if (!t) throw new Error(`struct ${name}: missing field type for "${k}"`);
|
|
94
|
+
return { name: k, type: t };
|
|
95
|
+
});
|
|
96
|
+
const layout = computeStructLayout(fieldEntries);
|
|
97
|
+
const offsets = {};
|
|
98
|
+
for (const k of fieldOrder) {
|
|
99
|
+
const off = layout.offsets[k];
|
|
100
|
+
if (off === void 0) throw new Error(`struct ${name}: missing offset for "${k}"`);
|
|
101
|
+
offsets[k] = off;
|
|
102
|
+
}
|
|
103
|
+
const result = {
|
|
104
|
+
kind: "struct",
|
|
105
|
+
wgslType: name,
|
|
106
|
+
name,
|
|
107
|
+
byteSize: layout.byteSize,
|
|
108
|
+
alignment: layout.alignment,
|
|
109
|
+
fields,
|
|
110
|
+
offsets,
|
|
111
|
+
fieldOrder,
|
|
112
|
+
layout,
|
|
113
|
+
toWGSL() {
|
|
114
|
+
return structToWGSL(result);
|
|
115
|
+
},
|
|
116
|
+
withAtomics(atomicName, atomicFields) {
|
|
117
|
+
const atomicSet = new Set(atomicFields);
|
|
118
|
+
const newFields = {};
|
|
119
|
+
for (const k of fieldOrder) {
|
|
120
|
+
const fieldType = fields[k];
|
|
121
|
+
if (!fieldType) throw new Error(`withAtomics: missing field "${k}"`);
|
|
122
|
+
if (atomicSet.has(k)) {
|
|
123
|
+
if (fieldType.kind !== "scalar") {
|
|
124
|
+
throw new Error(`withAtomics: field "${k}" is not a scalar (got ${fieldType.kind})`);
|
|
125
|
+
}
|
|
126
|
+
newFields[k] = atomic(fieldType);
|
|
127
|
+
} else {
|
|
128
|
+
newFields[k] = fieldType;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return struct(atomicName, newFields);
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
return Object.freeze(result);
|
|
135
|
+
}
|
|
136
|
+
function structToWGSL(s) {
|
|
137
|
+
const lines = s.layout.fields.map((f) => ` ${f.name}: ${f.type.wgslType},`);
|
|
138
|
+
return `struct ${s.name} {
|
|
139
|
+
${lines.join("\n")}
|
|
140
|
+
}`;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// src/array.ts
|
|
144
|
+
function arrayOf(elementType, count) {
|
|
145
|
+
const stride = roundUp(elementType.alignment, elementType.byteSize);
|
|
146
|
+
const byteSize = count * stride;
|
|
147
|
+
const alignment = elementType.alignment;
|
|
148
|
+
return Object.freeze({
|
|
149
|
+
kind: "array",
|
|
150
|
+
wgslType: `array<${elementType.wgslType}, ${count}>`,
|
|
151
|
+
byteSize,
|
|
152
|
+
alignment,
|
|
153
|
+
elementType,
|
|
154
|
+
count,
|
|
155
|
+
stride
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// src/const.ts
|
|
160
|
+
function constant(name, type, value) {
|
|
161
|
+
return Object.freeze({
|
|
162
|
+
kind: "const",
|
|
163
|
+
name,
|
|
164
|
+
type,
|
|
165
|
+
value,
|
|
166
|
+
toWGSL() {
|
|
167
|
+
return constToWGSL(name, type, value);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
function constToWGSL(name, type, value) {
|
|
172
|
+
let literal;
|
|
173
|
+
switch (type.arrayKind) {
|
|
174
|
+
case "f32":
|
|
175
|
+
literal = Number.isInteger(value) ? `${value}.0` : `${value}`;
|
|
176
|
+
break;
|
|
177
|
+
case "u32":
|
|
178
|
+
literal = `${value >>> 0}u`;
|
|
179
|
+
break;
|
|
180
|
+
case "i32":
|
|
181
|
+
literal = `${value | 0}i`;
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
184
|
+
return `const ${name}: ${type.wgslType} = ${literal};`;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// src/gpu-buffer-utils.ts
|
|
188
|
+
var ZERO_U32_4_BUFFER = new ArrayBuffer(16);
|
|
189
|
+
var INDIRECT_INIT_6_BUFFER = new ArrayBuffer(16);
|
|
190
|
+
new Uint32Array(INDIRECT_INIT_6_BUFFER).set([6, 0, 0, 0]);
|
|
191
|
+
var UniformBuffer = class {
|
|
192
|
+
buffer;
|
|
193
|
+
scratch;
|
|
194
|
+
u32;
|
|
195
|
+
i32;
|
|
196
|
+
f32;
|
|
197
|
+
byteSize;
|
|
198
|
+
constructor(device, label, byteSize, usage) {
|
|
199
|
+
if (byteSize <= 0) {
|
|
200
|
+
throw new Error(`UniformBuffer size must be positive, got ${byteSize}`);
|
|
201
|
+
}
|
|
202
|
+
if (byteSize % 4 !== 0) {
|
|
203
|
+
throw new Error(`UniformBuffer size must be 4-byte aligned, got ${byteSize}`);
|
|
204
|
+
}
|
|
205
|
+
this.byteSize = byteSize;
|
|
206
|
+
this.buffer = device.createBuffer({
|
|
207
|
+
label,
|
|
208
|
+
size: byteSize,
|
|
209
|
+
usage: usage ?? GPUBufferUsage.UNIFORM | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
|
|
210
|
+
});
|
|
211
|
+
this.scratch = new ArrayBuffer(byteSize);
|
|
212
|
+
this.u32 = new Uint32Array(this.scratch);
|
|
213
|
+
this.i32 = new Int32Array(this.scratch);
|
|
214
|
+
this.f32 = new Float32Array(this.scratch);
|
|
215
|
+
}
|
|
216
|
+
write(queue, offsetBytes = 0) {
|
|
217
|
+
queue.writeBuffer(this.buffer, offsetBytes, this.scratch);
|
|
218
|
+
}
|
|
219
|
+
destroy() {
|
|
220
|
+
this.buffer.destroy();
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
var DirtyUniformBuffer = class extends UniformBuffer {
|
|
224
|
+
_dirty = true;
|
|
225
|
+
/** Set a u32 value at index, marks dirty only if value changed */
|
|
226
|
+
setU32(i, v) {
|
|
227
|
+
if (this.u32[i] !== v) {
|
|
228
|
+
this.u32[i] = v;
|
|
229
|
+
this._dirty = true;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/** Set an i32 value at index, marks dirty only if value changed */
|
|
233
|
+
setI32(i, v) {
|
|
234
|
+
if (this.i32[i] !== v) {
|
|
235
|
+
this.i32[i] = v;
|
|
236
|
+
this._dirty = true;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/** Set an f32 value at index, marks dirty only if value changed */
|
|
240
|
+
setF32(i, v) {
|
|
241
|
+
if (this.f32[i] !== v) {
|
|
242
|
+
this.f32[i] = v;
|
|
243
|
+
this._dirty = true;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
/** Force dirty state (use when external factors require re-upload) */
|
|
247
|
+
markDirty() {
|
|
248
|
+
this._dirty = true;
|
|
249
|
+
}
|
|
250
|
+
/** Returns true if any values have changed since last write */
|
|
251
|
+
get isDirty() {
|
|
252
|
+
return this._dirty;
|
|
253
|
+
}
|
|
254
|
+
/** Upload to GPU only if dirty, then clear dirty flag */
|
|
255
|
+
writeIfDirty(queue, offsetBytes = 0) {
|
|
256
|
+
if (!this._dirty) return;
|
|
257
|
+
this.write(queue, offsetBytes);
|
|
258
|
+
this._dirty = false;
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
// src/typed-buffer.ts
|
|
263
|
+
var TypedBuffer = class _TypedBuffer {
|
|
264
|
+
/** The underlying DirtyUniformBuffer (provides typed array views: .f32, .u32, .i32) */
|
|
265
|
+
raw;
|
|
266
|
+
/** The tapez type this buffer was created from */
|
|
267
|
+
type;
|
|
268
|
+
/**
|
|
269
|
+
* Named field setters. Only available for struct types.
|
|
270
|
+
* For non-struct buffers this is an empty object.
|
|
271
|
+
*/
|
|
272
|
+
set;
|
|
273
|
+
/**
|
|
274
|
+
* Named field getters. Only available for struct types.
|
|
275
|
+
* For non-struct buffers this is an empty object.
|
|
276
|
+
*/
|
|
277
|
+
get;
|
|
278
|
+
constructor(raw, type) {
|
|
279
|
+
this.raw = raw;
|
|
280
|
+
this.type = type;
|
|
281
|
+
if (type.kind === "struct") {
|
|
282
|
+
const struct2 = type;
|
|
283
|
+
this.set = buildSetters(raw, struct2);
|
|
284
|
+
this.get = buildGetters(raw, struct2);
|
|
285
|
+
} else {
|
|
286
|
+
this.set = {};
|
|
287
|
+
this.get = {};
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
/** The raw GPUBuffer — for texture/sampler bind group entries only */
|
|
291
|
+
get buffer() {
|
|
292
|
+
return this.raw.buffer;
|
|
293
|
+
}
|
|
294
|
+
/** Total byte size of the buffer */
|
|
295
|
+
get byteSize() {
|
|
296
|
+
return this.raw.byteSize;
|
|
297
|
+
}
|
|
298
|
+
/** Whether any values have changed since last write */
|
|
299
|
+
get isDirty() {
|
|
300
|
+
return this.raw.isDirty;
|
|
301
|
+
}
|
|
302
|
+
/** Force dirty state (for external invalidation) */
|
|
303
|
+
markDirty() {
|
|
304
|
+
this.raw.markDirty();
|
|
305
|
+
}
|
|
306
|
+
/** Upload to GPU only if dirty, then clear dirty flag */
|
|
307
|
+
writeIfDirty(queue) {
|
|
308
|
+
this.raw.writeIfDirty(queue);
|
|
309
|
+
}
|
|
310
|
+
/** Upload to GPU unconditionally */
|
|
311
|
+
write(queue) {
|
|
312
|
+
this.raw.write(queue);
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Bulk set multiple struct fields at once.
|
|
316
|
+
* Only available for struct-typed buffers.
|
|
317
|
+
*/
|
|
318
|
+
writeFields(values) {
|
|
319
|
+
for (const key in values) {
|
|
320
|
+
if (Object.prototype.hasOwnProperty.call(values, key)) {
|
|
321
|
+
const setter = this.set[key];
|
|
322
|
+
if (setter) setter(values[key]);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
/** Destroy the underlying GPU buffer */
|
|
327
|
+
destroy() {
|
|
328
|
+
this.raw.destroy();
|
|
329
|
+
}
|
|
330
|
+
// ---------------------------------------------------------------------------
|
|
331
|
+
// WebGPU API wrappers — so entity code never touches .buffer directly
|
|
332
|
+
// ---------------------------------------------------------------------------
|
|
333
|
+
/** Write raw data to this buffer via queue.writeBuffer */
|
|
334
|
+
writeRaw(queue, data, bufferOffset = 0, dataOffset, size) {
|
|
335
|
+
queue.writeBuffer(this.raw.buffer, bufferOffset, data, dataOffset, size);
|
|
336
|
+
}
|
|
337
|
+
/** Copy data from this buffer to another TypedBuffer */
|
|
338
|
+
copyTo(encoder, dest, srcOffset = 0, dstOffset = 0, size) {
|
|
339
|
+
encoder.copyBufferToBuffer(this.raw.buffer, srcOffset, dest.raw.buffer, dstOffset, size ?? this.raw.byteSize);
|
|
340
|
+
}
|
|
341
|
+
/** Copy data from another TypedBuffer into this buffer */
|
|
342
|
+
copyFrom(encoder, src, srcOffset = 0, dstOffset = 0, size) {
|
|
343
|
+
encoder.copyBufferToBuffer(src.raw.buffer, srcOffset, this.raw.buffer, dstOffset, size ?? src.raw.byteSize);
|
|
344
|
+
}
|
|
345
|
+
/** Use this buffer for drawIndirect */
|
|
346
|
+
drawIndirect(pass, offset = 0) {
|
|
347
|
+
pass.drawIndirect(this.raw.buffer, offset);
|
|
348
|
+
}
|
|
349
|
+
/** Use this buffer for dispatchWorkgroupsIndirect */
|
|
350
|
+
dispatchIndirect(pass, offset = 0) {
|
|
351
|
+
pass.dispatchWorkgroupsIndirect(this.raw.buffer, offset);
|
|
352
|
+
}
|
|
353
|
+
/** Map buffer for reading (for readback buffers). Returns the mapped ArrayBuffer. */
|
|
354
|
+
async mapRead() {
|
|
355
|
+
await this.raw.buffer.mapAsync(GPUMapMode.READ);
|
|
356
|
+
return this.raw.buffer.getMappedRange();
|
|
357
|
+
}
|
|
358
|
+
/** Unmap a previously mapped buffer */
|
|
359
|
+
unmap() {
|
|
360
|
+
this.raw.buffer.unmap();
|
|
361
|
+
}
|
|
362
|
+
// ---------------------------------------------------------------------------
|
|
363
|
+
// Factory methods
|
|
364
|
+
// ---------------------------------------------------------------------------
|
|
365
|
+
/** Create a buffer with explicit usage flags. Accepts any TapezType. */
|
|
366
|
+
static create(device, type, label, usage) {
|
|
367
|
+
const raw = new DirtyUniformBuffer(device, label, type.byteSize, usage | GPUBufferUsage.COPY_DST);
|
|
368
|
+
return new _TypedBuffer(raw, type);
|
|
369
|
+
}
|
|
370
|
+
/** Create a uniform buffer (UNIFORM | STORAGE | COPY_DST) */
|
|
371
|
+
static createUniform(device, type, label) {
|
|
372
|
+
return _TypedBuffer.create(
|
|
373
|
+
device,
|
|
374
|
+
type,
|
|
375
|
+
label,
|
|
376
|
+
GPUBufferUsage.UNIFORM | GPUBufferUsage.STORAGE
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
/** Create a storage buffer (STORAGE | COPY_DST). Pass extraFlags for COPY_SRC etc. */
|
|
380
|
+
static createStorage(device, type, label, extraFlags = 0) {
|
|
381
|
+
return _TypedBuffer.create(
|
|
382
|
+
device,
|
|
383
|
+
type,
|
|
384
|
+
label,
|
|
385
|
+
GPUBufferUsage.STORAGE | extraFlags
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
/** Create an indirect draw/dispatch buffer (INDIRECT | STORAGE | COPY_DST) */
|
|
389
|
+
static createIndirect(device, type, label) {
|
|
390
|
+
return _TypedBuffer.create(
|
|
391
|
+
device,
|
|
392
|
+
type,
|
|
393
|
+
label,
|
|
394
|
+
GPUBufferUsage.INDIRECT | GPUBufferUsage.STORAGE
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
/** Create a readback buffer (MAP_READ | COPY_DST). For GPU→CPU data transfer. */
|
|
398
|
+
static createReadback(device, type, label) {
|
|
399
|
+
return _TypedBuffer.create(
|
|
400
|
+
device,
|
|
401
|
+
type,
|
|
402
|
+
label,
|
|
403
|
+
GPUBufferUsage.MAP_READ
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
function buildSetters(raw, schema) {
|
|
408
|
+
const setters = {};
|
|
409
|
+
for (const field of schema.layout.fields) {
|
|
410
|
+
setters[field.name] = createSetter(raw, field);
|
|
411
|
+
}
|
|
412
|
+
return setters;
|
|
413
|
+
}
|
|
414
|
+
function buildGetters(raw, schema) {
|
|
415
|
+
const getters = {};
|
|
416
|
+
for (const field of schema.layout.fields) {
|
|
417
|
+
getters[field.name] = createGetter(raw, field);
|
|
418
|
+
}
|
|
419
|
+
return getters;
|
|
420
|
+
}
|
|
421
|
+
function createSetter(raw, field) {
|
|
422
|
+
const type = field.type;
|
|
423
|
+
const byteOffset = field.offset;
|
|
424
|
+
switch (type.kind) {
|
|
425
|
+
case "scalar":
|
|
426
|
+
case "atomic": {
|
|
427
|
+
const index = byteOffset / 4;
|
|
428
|
+
const arrayKind = type.kind === "atomic" ? type.arrayKind : type.arrayKind;
|
|
429
|
+
switch (arrayKind) {
|
|
430
|
+
case "f32":
|
|
431
|
+
return (v) => raw.setF32(index, v);
|
|
432
|
+
case "u32":
|
|
433
|
+
return (v) => raw.setU32(index, v);
|
|
434
|
+
case "i32":
|
|
435
|
+
return (v) => raw.setI32(index, v);
|
|
436
|
+
}
|
|
437
|
+
break;
|
|
438
|
+
}
|
|
439
|
+
case "vector": {
|
|
440
|
+
const vec2 = type;
|
|
441
|
+
const startIndex = byteOffset / 4;
|
|
442
|
+
const count = vec2.components;
|
|
443
|
+
const arrayKind = vec2.componentType.arrayKind;
|
|
444
|
+
switch (arrayKind) {
|
|
445
|
+
case "f32":
|
|
446
|
+
return (v) => {
|
|
447
|
+
const arr = v;
|
|
448
|
+
for (let i = 0; i < count; i++) raw.setF32(startIndex + i, arr[i]);
|
|
449
|
+
};
|
|
450
|
+
case "u32":
|
|
451
|
+
return (v) => {
|
|
452
|
+
const arr = v;
|
|
453
|
+
for (let i = 0; i < count; i++) raw.setU32(startIndex + i, arr[i]);
|
|
454
|
+
};
|
|
455
|
+
case "i32":
|
|
456
|
+
return (v) => {
|
|
457
|
+
const arr = v;
|
|
458
|
+
for (let i = 0; i < count; i++) raw.setI32(startIndex + i, arr[i]);
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
break;
|
|
462
|
+
}
|
|
463
|
+
case "matrix": {
|
|
464
|
+
const startIndex = byteOffset / 4;
|
|
465
|
+
const floatCount = type.byteSize / 4;
|
|
466
|
+
return (v) => {
|
|
467
|
+
const arr = v;
|
|
468
|
+
for (let i = 0; i < floatCount; i++) raw.setF32(startIndex + i, arr[i]);
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
default:
|
|
472
|
+
return () => {
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
function createGetter(raw, field) {
|
|
477
|
+
const type = field.type;
|
|
478
|
+
const byteOffset = field.offset;
|
|
479
|
+
switch (type.kind) {
|
|
480
|
+
case "scalar":
|
|
481
|
+
case "atomic": {
|
|
482
|
+
const index = byteOffset / 4;
|
|
483
|
+
const arrayKind = type.kind === "atomic" ? type.arrayKind : type.arrayKind;
|
|
484
|
+
switch (arrayKind) {
|
|
485
|
+
case "f32":
|
|
486
|
+
return () => raw.f32[index];
|
|
487
|
+
case "u32":
|
|
488
|
+
return () => raw.u32[index];
|
|
489
|
+
case "i32":
|
|
490
|
+
return () => raw.i32[index];
|
|
491
|
+
}
|
|
492
|
+
break;
|
|
493
|
+
}
|
|
494
|
+
case "vector": {
|
|
495
|
+
const vec2 = type;
|
|
496
|
+
const startIndex = byteOffset / 4;
|
|
497
|
+
const count = vec2.components;
|
|
498
|
+
const arrayKind = vec2.componentType.arrayKind;
|
|
499
|
+
switch (arrayKind) {
|
|
500
|
+
case "f32":
|
|
501
|
+
return () => Array.from(raw.f32.subarray(startIndex, startIndex + count));
|
|
502
|
+
case "u32":
|
|
503
|
+
return () => Array.from(raw.u32.subarray(startIndex, startIndex + count));
|
|
504
|
+
case "i32":
|
|
505
|
+
return () => Array.from(raw.i32.subarray(startIndex, startIndex + count));
|
|
506
|
+
}
|
|
507
|
+
break;
|
|
508
|
+
}
|
|
509
|
+
case "matrix": {
|
|
510
|
+
const startIndex = byteOffset / 4;
|
|
511
|
+
const floatCount = type.byteSize / 4;
|
|
512
|
+
return () => Array.from(raw.f32.subarray(startIndex, startIndex + floatCount));
|
|
513
|
+
}
|
|
514
|
+
default:
|
|
515
|
+
return () => void 0;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// src/bind-helpers.ts
|
|
520
|
+
function uniformEntry(binding, visibility) {
|
|
521
|
+
return { binding, visibility, buffer: { type: "uniform" } };
|
|
522
|
+
}
|
|
523
|
+
function storageEntry(binding, visibility, type = "storage") {
|
|
524
|
+
return { binding, visibility, buffer: { type } };
|
|
525
|
+
}
|
|
526
|
+
function bufferEntry(binding, buf) {
|
|
527
|
+
const gpuBuffer = "buffer" in buf && typeof buf.byteSize === "number" ? buf.buffer : buf;
|
|
528
|
+
return { binding, resource: { buffer: gpuBuffer } };
|
|
529
|
+
}
|
|
530
|
+
export {
|
|
531
|
+
TypedBuffer,
|
|
532
|
+
arrayOf,
|
|
533
|
+
atomic,
|
|
534
|
+
bufferEntry,
|
|
535
|
+
computeStructLayout,
|
|
536
|
+
constant as const,
|
|
537
|
+
f32,
|
|
538
|
+
i32,
|
|
539
|
+
mat2x2f,
|
|
540
|
+
mat3x3f,
|
|
541
|
+
mat4x4f,
|
|
542
|
+
roundUp,
|
|
543
|
+
storageEntry,
|
|
544
|
+
struct,
|
|
545
|
+
u32,
|
|
546
|
+
uniformEntry,
|
|
547
|
+
vec2f,
|
|
548
|
+
vec2i,
|
|
549
|
+
vec2u,
|
|
550
|
+
vec3f,
|
|
551
|
+
vec3i,
|
|
552
|
+
vec3u,
|
|
553
|
+
vec4f,
|
|
554
|
+
vec4i,
|
|
555
|
+
vec4u
|
|
556
|
+
};
|
|
31
557
|
//# sourceMappingURL=index.js.map
|