typegpu 0.12.5 → 0.12.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/common/index.d.ts +1 -0
- package/common/index.js +1 -0
- package/common/writeChannels.d.ts +31 -0
- package/common/writeChannels.js +32 -0
- package/common/writeSoA.js +16 -0
- package/core/buffer/buffer.js +47 -11
- package/core/commandEncoder/attachments.js +5 -2
- package/core/commandEncoder/computePass.d.ts +13 -0
- package/core/commandEncoder/computePass.js +5 -2
- package/core/commandEncoder/renderPass.d.ts +18 -4
- package/core/commandEncoder/renderPass.js +6 -2
- package/core/declare/tgpuDeclare.d.ts +11 -0
- package/core/declare/tgpuDeclare.js +1 -1
- package/core/function/autoIO.js +4 -2
- package/core/function/ioSchema.d.ts +7 -2
- package/core/function/ioSchema.js +41 -15
- package/core/function/tgpuFragmentFn.d.ts +1 -1
- package/core/function/tgpuFragmentFn.js +2 -1
- package/core/function/tgpuVertexFn.js +2 -1
- package/core/immediate/immediateVar.d.ts +52 -0
- package/core/immediate/immediateVar.js +149 -0
- package/core/pipeline/computePipeline.d.ts +17 -0
- package/core/pipeline/computePipeline.js +23 -9
- package/core/pipeline/connectAttachmentToShader.d.ts +2 -2
- package/core/pipeline/connectAttachmentToShader.js +16 -21
- package/core/pipeline/connectTargetsToShader.d.ts +5 -1
- package/core/pipeline/connectTargetsToShader.js +23 -18
- package/core/pipeline/drawState.d.ts +8 -4
- package/core/pipeline/drawState.js +41 -51
- package/core/pipeline/priors.js +1 -0
- package/core/pipeline/renderPipeline.d.ts +22 -4
- package/core/pipeline/renderPipeline.js +25 -13
- package/core/resolve/namespace.js +2 -2
- package/core/root/init.js +3 -0
- package/core/root/rootTypes.d.ts +17 -2
- package/core/slot/accessor.d.ts +1 -1
- package/core/slot/accessor.js +72 -5
- package/core/slot/slotTypes.d.ts +2 -1
- package/core/texture/texture.d.ts +20 -14
- package/core/texture/texture.js +78 -69
- package/core/texture/textureUtils.d.ts +3 -6
- package/core/texture/textureUtils.js +142 -165
- package/core/texture/textureWrite.d.ts +61 -0
- package/core/texture/textureWrite.js +59 -0
- package/data/autoStruct.d.ts +1 -1
- package/data/autoStruct.js +8 -4
- package/data/dataIO.d.ts +2 -2
- package/data/deepEqual.js +19 -9
- package/data/matrix.js +10 -3
- package/data/partialIO.d.ts +8 -1
- package/data/partialIO.js +36 -19
- package/data/ref.js +2 -2
- package/data/snippet.d.ts +11 -5
- package/data/snippet.js +9 -4
- package/data/wgslTypes.d.ts +4 -1
- package/errors.d.ts +7 -0
- package/errors.js +15 -0
- package/indexNamedExports.d.ts +5 -2
- package/indexNamedExports.js +2 -1
- package/internal.d.ts +2 -1
- package/internal.js +1 -1
- package/nameUtils.d.ts +7 -0
- package/nameUtils.js +60 -0
- package/package.json +2 -2
- package/resolutionCtx.d.ts +5 -0
- package/resolutionCtx.js +11 -0
- package/serial/restore.d.ts +3 -1
- package/serial/restore.js +2 -0
- package/shared/meta.js +1 -1
- package/shared/symbols.js +1 -1
- package/shared/tseynit.d.ts +1 -0
- package/shared/tseynit.js +80 -44
- package/std/atomic.d.ts +13 -0
- package/std/atomic.js +63 -29
- package/std/boolean.js +9 -10
- package/std/derivative.js +14 -9
- package/std/index.d.ts +4 -4
- package/std/index.js +5 -5
- package/std/numeric.d.ts +5 -1
- package/std/numeric.js +3 -3
- package/std/operators.js +9 -4
- package/std/packing.d.ts +61 -1
- package/std/packing.js +214 -25
- package/std/subgroup.d.ts +4 -0
- package/std/subgroup.js +34 -0
- package/std/texture.d.ts +15 -2
- package/std/texture.js +48 -0
- package/tgpuUnstable.d.ts +1 -0
- package/tgpuUnstable.js +1 -0
- package/tgsl/accessIndex.js +19 -23
- package/tgsl/conversion.d.ts +2 -0
- package/tgsl/conversion.js +3 -0
- package/tgsl/forOfUtils.js +6 -6
- package/tgsl/generationHelpers.js +2 -2
- package/tgsl/shaderGenerator.d.ts +1 -1
- package/tgsl/wgslGenerator.d.ts +5 -0
- package/tgsl/wgslGenerator.js +288 -58
- package/types.d.ts +9 -1
- package/types.js +5 -0
|
@@ -3,8 +3,9 @@ import type { IndexFlag, IndirectFlag, TgpuBuffer, VertexFlag } from '../buffer/
|
|
|
3
3
|
import type { TgpuQuerySet } from '../querySet/querySet.ts';
|
|
4
4
|
import { type Disarray, type UndecorateRecord } from '../../data/dataTypes.ts';
|
|
5
5
|
import { type ResolvedSnippet } from '../../data/snippet.ts';
|
|
6
|
-
import { type AnyVecInstance, type BaseData, type U16, type U32, type v4f, Void, type WgslArray
|
|
6
|
+
import { type AnyVecInstance, type AnyWgslData, type BaseData, type U16, type U32, type v4f, Void, type WgslArray } from '../../data/wgslTypes.ts';
|
|
7
7
|
import type { TgpuNamable } from '../../shared/meta.ts';
|
|
8
|
+
import type { InferInput } from '../../shared/repr.ts';
|
|
8
9
|
import type { TgpuDeviceOwningSoul } from '../../shared/soul.ts';
|
|
9
10
|
import { $getNameForward, $internal, $resolve, $soul } from '../../shared/symbols.ts';
|
|
10
11
|
import type { AnyVertexAttribs } from '../../shared/vertexFormat.ts';
|
|
@@ -17,8 +18,10 @@ import type { TgpuVertexFn } from '../function/tgpuVertexFn.ts';
|
|
|
17
18
|
import type { ExperimentalTgpuRoot } from '../root/rootTypes.ts';
|
|
18
19
|
import type { TgpuSlot } from '../slot/slotTypes.ts';
|
|
19
20
|
import { type TgpuVertexLayout } from '../vertexLayout/vertexLayout.ts';
|
|
21
|
+
import { type ConnectedTarget } from './connectTargetsToShader.ts';
|
|
20
22
|
import { type TgpuCommandEncoder } from '../commandEncoder/commandEncoder.ts';
|
|
21
23
|
import type { ColorAttachment, DepthStencilAttachment } from '../commandEncoder/attachments.ts';
|
|
24
|
+
import { type ImmediateSnapshot, type TgpuImmediateVar } from '../immediate/immediateVar.ts';
|
|
22
25
|
import { type TgpuRenderCommands } from '../commandEncoder/renderPass.ts';
|
|
23
26
|
import { type Timeable, type TimestampWritesPriors } from './timeable.ts';
|
|
24
27
|
import { type PrimitiveOffsetInfo } from '../../data/offsetUtils.ts';
|
|
@@ -32,8 +35,10 @@ export interface RenderPipelineInternals {
|
|
|
32
35
|
export interface TgpuRenderPipelineSoul extends TgpuDeviceOwningSoul<'render-pipeline', GPURenderPipeline> {
|
|
33
36
|
usedBindGroupLayouts?: TgpuBindGroupLayout[] | undefined;
|
|
34
37
|
usedVertexLayouts?: TgpuVertexLayout[] | undefined;
|
|
35
|
-
|
|
38
|
+
connectedTargets?: (ConnectedTarget | null)[] | undefined;
|
|
36
39
|
bindGroups?: [TgpuBindGroupLayout, TgpuBindGroup | GPUBindGroup][] | undefined;
|
|
40
|
+
usedImmediate?: TgpuImmediateVar | undefined;
|
|
41
|
+
immediates?: [TgpuImmediateVar, ImmediateSnapshot][] | undefined;
|
|
37
42
|
vertexBuffers?: [TgpuVertexLayout, (TgpuBuffer<BaseData> & VertexFlag) | GPUBuffer][] | undefined;
|
|
38
43
|
indexBuffer?: {
|
|
39
44
|
buffer: (TgpuBuffer<BaseData> & IndexFlag) | GPUBuffer;
|
|
@@ -76,6 +81,16 @@ export interface TgpuRenderPipeline<in Targets = never> extends TgpuNamable, Sel
|
|
|
76
81
|
with<Entries extends Record<string, TgpuLayoutEntry | null>>(bindGroupLayout: TgpuBindGroupLayout<Entries>, bindGroup: TgpuBindGroup<Entries>): this;
|
|
77
82
|
with(bindGroupLayout: TgpuBindGroupLayout, bindGroup: GPUBindGroup): this;
|
|
78
83
|
with(bindGroup: TgpuBindGroup): this;
|
|
84
|
+
/**
|
|
85
|
+
* Provides a value for the given immediate variable, applied on draw like
|
|
86
|
+
* the rest of the pipeline-held state and overridden by `pass.setImmediates`.
|
|
87
|
+
* The value is captured (copied) at call time; mutating it afterwards has
|
|
88
|
+
* no effect.
|
|
89
|
+
*
|
|
90
|
+
* Passing an `ArrayBuffer` or typed array skips serialization entirely; the bytes
|
|
91
|
+
* are copied verbatim and the caller guarantees they match the schema's layout.
|
|
92
|
+
*/
|
|
93
|
+
with<T extends AnyWgslData>(immediate: TgpuImmediateVar<T>, value: InferInput<T> | ArrayBuffer | ArrayBufferView): this;
|
|
79
94
|
/**
|
|
80
95
|
* Directs subsequent draw calls into the given render pass or render bundle
|
|
81
96
|
* encoder, letting multiple pipelines share one pass (and one submission).
|
|
@@ -199,6 +214,7 @@ type TgpuRenderPipelinePriors = {
|
|
|
199
214
|
readonly pass?: TgpuRenderCommands | undefined;
|
|
200
215
|
/** An encoder the pipeline records its own passes into, but does not submit */
|
|
201
216
|
readonly encoder?: TgpuCommandEncoder | undefined;
|
|
217
|
+
readonly immediatesMap?: Map<TgpuImmediateVar, ImmediateSnapshot> | undefined;
|
|
202
218
|
} & TimestampWritesPriors;
|
|
203
219
|
type Memo = {
|
|
204
220
|
pipeline: GPURenderPipeline;
|
|
@@ -206,7 +222,8 @@ type Memo = {
|
|
|
206
222
|
catchall: [number, TgpuBindGroup] | undefined;
|
|
207
223
|
logResources: LogResources | undefined;
|
|
208
224
|
usedVertexLayouts: TgpuVertexLayout[];
|
|
209
|
-
|
|
225
|
+
connectedTargets: (ConnectedTarget | null)[] | undefined;
|
|
226
|
+
usedImmediate: TgpuImmediateVar | undefined;
|
|
210
227
|
};
|
|
211
228
|
declare class TgpuRenderPipelineImpl implements TgpuRenderPipeline {
|
|
212
229
|
#private;
|
|
@@ -223,6 +240,7 @@ declare class TgpuRenderPipelineImpl implements TgpuRenderPipeline {
|
|
|
223
240
|
with(bindGroupLayout: TgpuBindGroupLayout, bindGroup: GPUBindGroup): this;
|
|
224
241
|
with(bindGroup: TgpuBindGroup): this;
|
|
225
242
|
with<TData extends WgslArray | Disarray>(vertexLayout: TgpuVertexLayout<TData>, buffer: GPUBuffer): this;
|
|
243
|
+
with<T extends AnyWgslData>(immediate: TgpuImmediateVar<T>, value: InferInput<T> | ArrayBuffer | ArrayBufferView): this;
|
|
226
244
|
with(pass: TgpuRenderCommands): this;
|
|
227
245
|
with(encoder: TgpuCommandEncoder): this;
|
|
228
246
|
with(encoder: GPUCommandEncoder): this;
|
|
@@ -263,8 +281,8 @@ declare class RenderPipelineCore implements SelfResolvable {
|
|
|
263
281
|
resolveAndCreateShaderModule(): {
|
|
264
282
|
resolutionResult: import("../../resolutionCtx.ts").ResolutionResult;
|
|
265
283
|
descriptor: GPURenderPipelineDescriptor;
|
|
284
|
+
connectedTargets: (ConnectedTarget | null)[];
|
|
266
285
|
connectedAttribs: import("../vertexLayout/connectAttributesToShader.ts").ConnectAttributesToShaderResult;
|
|
267
|
-
fragmentOut: WgslStruct<import("../function/ioSchema.ts").WithLocations<Record<string, BaseData>>>;
|
|
268
286
|
};
|
|
269
287
|
}
|
|
270
288
|
/**
|
|
@@ -18,6 +18,7 @@ import { isVertexLayout } from "../vertexLayout/vertexLayout.js";
|
|
|
18
18
|
import { connectAttachmentToShader } from "./connectAttachmentToShader.js";
|
|
19
19
|
import { connectTargetsToShader } from "./connectTargetsToShader.js";
|
|
20
20
|
import { INTERNAL_adoptCommandEncoder, INTERNAL_createCommandEncoder, } from "../commandEncoder/commandEncoder.js";
|
|
21
|
+
import { createImmediateSnapshot, isImmediateVar, validateImmediateUsage, } from "../immediate/immediateVar.js";
|
|
21
22
|
import { INTERNAL_adoptRenderCommands, } from "../commandEncoder/renderPass.js";
|
|
22
23
|
import { emitRenderDraw, finalizeOwnEncoder, requireIndexBuffer } from "./drawState.js";
|
|
23
24
|
import { isGPUCommandEncoder, isGPURenderBundleEncoder, isGPURenderPassEncoder, isTgpuCommandEncoder, isTgpuRenderCommands, } from "./typeGuards.js";
|
|
@@ -41,10 +42,12 @@ export function INTERNAL_restoreRenderPipeline(soul, ctx) {
|
|
|
41
42
|
catchall: undefined,
|
|
42
43
|
logResources: undefined,
|
|
43
44
|
usedVertexLayouts: soul.usedVertexLayouts ?? [],
|
|
44
|
-
|
|
45
|
+
connectedTargets: soul.connectedTargets,
|
|
46
|
+
usedImmediate: soul.usedImmediate,
|
|
45
47
|
});
|
|
46
48
|
const pipeline = new TgpuRenderPipelineImpl(core, {
|
|
47
49
|
bindGroupLayoutMap: new Map(soul.bindGroups),
|
|
50
|
+
immediatesMap: new Map(soul.immediates),
|
|
48
51
|
vertexLayoutMap: new Map(soul.vertexBuffers),
|
|
49
52
|
indexBuffer: soul.indexBuffer,
|
|
50
53
|
stencilReference: soul.stencilReference,
|
|
@@ -74,8 +77,10 @@ class TgpuRenderPipelineImpl {
|
|
|
74
77
|
soul.raw = memo.pipeline;
|
|
75
78
|
soul.usedBindGroupLayouts = memo.usedBindGroupLayouts;
|
|
76
79
|
soul.usedVertexLayouts = memo.usedVertexLayouts;
|
|
77
|
-
soul.
|
|
80
|
+
soul.connectedTargets = memo.connectedTargets;
|
|
78
81
|
soul.bindGroups = collectBindGroupPairs(memo.usedBindGroupLayouts, memo.catchall, priors.bindGroupLayoutMap);
|
|
82
|
+
soul.usedImmediate = memo.usedImmediate;
|
|
83
|
+
soul.immediates = [...(priors.immediatesMap ?? [])];
|
|
79
84
|
soul.vertexBuffers = collectVertexBufferPairs(memo.usedVertexLayouts, priors.vertexLayoutMap);
|
|
80
85
|
soul.indexBuffer = priors.indexBuffer;
|
|
81
86
|
soul.stencilReference = priors.stencilReference;
|
|
@@ -141,6 +146,11 @@ class TgpuRenderPipelineImpl {
|
|
|
141
146
|
]),
|
|
142
147
|
});
|
|
143
148
|
}
|
|
149
|
+
if (isImmediateVar(first)) {
|
|
150
|
+
return this.#withPriors({
|
|
151
|
+
immediatesMap: new Map(internals.priors.immediatesMap).set(first, createImmediateSnapshot(first, resource)),
|
|
152
|
+
});
|
|
153
|
+
}
|
|
144
154
|
throw new Error('Unsupported value passed into .with()');
|
|
145
155
|
}
|
|
146
156
|
pipe(transform) {
|
|
@@ -214,12 +224,10 @@ class TgpuRenderPipelineImpl {
|
|
|
214
224
|
}
|
|
215
225
|
#ownPassDescriptor() {
|
|
216
226
|
const { core, priors } = this[$internal];
|
|
217
|
-
const {
|
|
227
|
+
const { connectedTargets } = core.unwrap();
|
|
218
228
|
return {
|
|
219
229
|
label: getName(core) ?? '<unnamed>',
|
|
220
|
-
colorAttachments:
|
|
221
|
-
? connectAttachmentToShader(fragmentOut, priors.colorAttachment ?? {})
|
|
222
|
-
: [],
|
|
230
|
+
colorAttachments: connectAttachmentToShader(connectedTargets, priors.colorAttachment ?? {}),
|
|
223
231
|
depthStencilAttachment: priors.depthStencilAttachment,
|
|
224
232
|
timestampWrites: priors.timestampWrites,
|
|
225
233
|
};
|
|
@@ -335,7 +343,7 @@ class RenderPipelineCore {
|
|
|
335
343
|
if (this.#initAsyncPromise === undefined) {
|
|
336
344
|
// the pipeline did not start resolution & compilation
|
|
337
345
|
const device = this.options.root.device;
|
|
338
|
-
const { resolutionResult, descriptor,
|
|
346
|
+
const { resolutionResult, descriptor, connectedTargets, connectedAttribs } = this.resolveAndCreateShaderModule();
|
|
339
347
|
const { usedBindGroupLayouts, catchall, logResources } = resolutionResult;
|
|
340
348
|
this.#initAsyncPromise = device
|
|
341
349
|
.createRenderPipelineAsync(descriptor)
|
|
@@ -346,7 +354,8 @@ class RenderPipelineCore {
|
|
|
346
354
|
catchall,
|
|
347
355
|
logResources,
|
|
348
356
|
usedVertexLayouts: connectedAttribs.usedVertexLayouts,
|
|
349
|
-
|
|
357
|
+
connectedTargets,
|
|
358
|
+
usedImmediate: resolutionResult.usedImmediate,
|
|
350
359
|
};
|
|
351
360
|
this.#performanceTracker.measureCompile(device);
|
|
352
361
|
})
|
|
@@ -364,7 +373,7 @@ class RenderPipelineCore {
|
|
|
364
373
|
throw new Error("'pipeline.initAsync()' was called and is not yet resolved.");
|
|
365
374
|
}
|
|
366
375
|
const device = this.options.root.device;
|
|
367
|
-
const { resolutionResult, descriptor,
|
|
376
|
+
const { resolutionResult, descriptor, connectedTargets, connectedAttribs } = this.resolveAndCreateShaderModule();
|
|
368
377
|
const { usedBindGroupLayouts, catchall, logResources } = resolutionResult;
|
|
369
378
|
this.#memo = {
|
|
370
379
|
pipeline: device.createRenderPipeline(descriptor),
|
|
@@ -372,7 +381,8 @@ class RenderPipelineCore {
|
|
|
372
381
|
catchall,
|
|
373
382
|
logResources,
|
|
374
383
|
usedVertexLayouts: connectedAttribs.usedVertexLayouts,
|
|
375
|
-
|
|
384
|
+
connectedTargets,
|
|
385
|
+
usedImmediate: resolutionResult.usedImmediate,
|
|
376
386
|
};
|
|
377
387
|
this.#performanceTracker.measureCompile(device);
|
|
378
388
|
}
|
|
@@ -396,11 +406,12 @@ class RenderPipelineCore {
|
|
|
396
406
|
shaderGenerator: root.shaderGeneratorClass ? new root.shaderGeneratorClass() : undefined,
|
|
397
407
|
root,
|
|
398
408
|
}));
|
|
399
|
-
const { code, usedBindGroupLayouts, catchall } = resolutionResult;
|
|
409
|
+
const { code, usedBindGroupLayouts, catchall, usedImmediate } = resolutionResult;
|
|
400
410
|
if (catchall !== undefined) {
|
|
401
411
|
usedBindGroupLayouts[catchall[0]]?.$name(`${getName(this) ?? '<unnamed>'} - Automatic Bind Group & Layout`);
|
|
402
412
|
}
|
|
403
413
|
warnIfOverflow(usedBindGroupLayouts, device.limits);
|
|
414
|
+
const immediateSize = usedImmediate ? validateImmediateUsage(usedImmediate, root) : 0;
|
|
404
415
|
const module = device.createShaderModule({
|
|
405
416
|
label: `${getName(this) ?? '<unnamed>'} - Shader`,
|
|
406
417
|
code,
|
|
@@ -417,6 +428,7 @@ class RenderPipelineCore {
|
|
|
417
428
|
layout: device.createPipelineLayout({
|
|
418
429
|
label: `${getName(this) ?? '<unnamed>'} - Pipeline Layout`,
|
|
419
430
|
bindGroupLayouts: usedBindGroupLayouts.map((l) => root.unwrap(l)),
|
|
431
|
+
immediateSize,
|
|
420
432
|
}),
|
|
421
433
|
vertex: {
|
|
422
434
|
module,
|
|
@@ -430,7 +442,7 @@ class RenderPipelineCore {
|
|
|
430
442
|
if (tgpuDescriptor.fragment) {
|
|
431
443
|
descriptor.fragment = {
|
|
432
444
|
module,
|
|
433
|
-
targets: connectedTargets,
|
|
445
|
+
targets: connectedTargets.map((target) => (target ? target.target : null)),
|
|
434
446
|
};
|
|
435
447
|
}
|
|
436
448
|
if (tgpuDescriptor.primitive) {
|
|
@@ -453,7 +465,7 @@ class RenderPipelineCore {
|
|
|
453
465
|
if (tgpuDescriptor.multisample) {
|
|
454
466
|
descriptor.multisample = tgpuDescriptor.multisample;
|
|
455
467
|
}
|
|
456
|
-
return { resolutionResult, descriptor,
|
|
468
|
+
return { resolutionResult, descriptor, connectedTargets, connectedAttribs };
|
|
457
469
|
}
|
|
458
470
|
}
|
|
459
471
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { bannedTokens, builtins } from "../../nameUtils.js";
|
|
1
|
+
import { bannedTokens, builtins, templateEnumerants } from "../../nameUtils.js";
|
|
2
2
|
import { $internal } from "../../shared/symbols.js";
|
|
3
3
|
import { ShelllessRepository } from "../../tgsl/shellless.js";
|
|
4
4
|
class NamespaceImpl {
|
|
@@ -6,7 +6,7 @@ class NamespaceImpl {
|
|
|
6
6
|
constructor(strategy) {
|
|
7
7
|
this[$internal] = {
|
|
8
8
|
strategy,
|
|
9
|
-
takenGlobalIdentifiers: new Set([...bannedTokens, ...builtins]),
|
|
9
|
+
takenGlobalIdentifiers: new Set([...bannedTokens, ...builtins, ...templateEnumerants]),
|
|
10
10
|
shelllessRepo: new ShelllessRepository(),
|
|
11
11
|
memoizedResolves: new WeakMap(),
|
|
12
12
|
memoizedLazy: new WeakMap(),
|
package/core/root/init.js
CHANGED
|
@@ -214,6 +214,9 @@ class TgpuRootImpl extends WithBindingImpl {
|
|
|
214
214
|
get minify() {
|
|
215
215
|
return this[$soul].minify;
|
|
216
216
|
}
|
|
217
|
+
get enabledWgslLanguageFeatures() {
|
|
218
|
+
return navigator.gpu?.wgslLanguageFeatures ?? new Set();
|
|
219
|
+
}
|
|
217
220
|
createBuffer(typeSchema, initialOrBuffer) {
|
|
218
221
|
return INTERNAL_createBuffer(this, typeSchema, initialOrBuffer);
|
|
219
222
|
}
|
package/core/root/rootTypes.d.ts
CHANGED
|
@@ -419,9 +419,24 @@ export interface TgpuRoot extends Unwrapper, WithBinding {
|
|
|
419
419
|
*/
|
|
420
420
|
get enabledFeatures(): ReadonlySet<GPUFeatureName>;
|
|
421
421
|
/**
|
|
422
|
-
*
|
|
422
|
+
* Retrieves a read-only list of WGSL language extensions supported in the
|
|
423
|
+
* current environment (`navigator.gpu.wgslLanguageFeatures`).
|
|
424
|
+
* Returns an empty set when WebGPU is unavailable.
|
|
425
|
+
*
|
|
426
|
+
* @example
|
|
427
|
+
* ```ts
|
|
428
|
+
* const canUseImmediates = root.enabledWgslLanguageFeatures.has('immediate_address_space');
|
|
429
|
+
* ```
|
|
430
|
+
*/
|
|
431
|
+
get enabledWgslLanguageFeatures(): ReadonlySet<string>;
|
|
432
|
+
/**
|
|
433
|
+
* Releases internal resource caches (e.g. utility texture pipelines),
|
|
434
|
+
* letting the GC reclaim them.
|
|
435
|
+
*
|
|
436
|
+
* Buffers, textures and other resources created through the root are NOT destroyed.
|
|
437
|
+
*
|
|
423
438
|
* If the object is created via `tgpu.init` instead of `tgpu.initFromDevice`,
|
|
424
|
-
*
|
|
439
|
+
* destroys the underlying WebGPU device as well.
|
|
425
440
|
*/
|
|
426
441
|
destroy(): void;
|
|
427
442
|
'~unstable': Pick<ExperimentalTgpuRoot, 'createCommandEncoder' | 'createComparisonSampler' | 'createGuardedComputePipeline' | 'createRenderBundleEncoder' | 'createSampler' | 'createTexture' | 'nameRegistrySetting' | 'shaderGeneratorClass' | 'pipe' | 'with'>;
|
package/core/slot/accessor.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type AnyData } from '../../data/dataTypes.ts';
|
|
2
|
-
import type
|
|
2
|
+
import { type BaseData } from '../../data/wgslTypes.ts';
|
|
3
3
|
import type { InferGPU } from '../../shared/repr.ts';
|
|
4
4
|
import { $getNameForward, $gpuValueOf, $internal, $resolve, $soul } from '../../shared/symbols.ts';
|
|
5
5
|
import type { UnwrapRuntimeConstructor } from '../../tgpuBindGroupLayout.ts';
|
package/core/slot/accessor.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import { isData } from "../../data/dataTypes.js";
|
|
1
|
+
import { isData, undecorate } from "../../data/dataTypes.js";
|
|
2
2
|
import { schemaCallWrapper } from "../../data/schemaCallWrapper.js";
|
|
3
3
|
import { isSnippet, snip } from "../../data/snippet.js";
|
|
4
|
+
import { deepEqual } from "../../data/deepEqual.js";
|
|
5
|
+
import { arrayOf } from "../../data/array.js";
|
|
6
|
+
import { UnknownData } from "../../data/dataTypes.js";
|
|
7
|
+
import { isAbstract, isWgslArray } from "../../data/wgslTypes.js";
|
|
4
8
|
import { getResolutionCtx } from "../../execMode.js";
|
|
5
9
|
import { makeDereferenceable } from "../../tgsl/makeDereferenceable.js";
|
|
6
10
|
import { makeResolvable } from "../../tgsl/makeResolvable.js";
|
|
@@ -19,10 +23,65 @@ export function mutableAccessor(schemaOrConstructor, defaultValue) {
|
|
|
19
23
|
// --------------
|
|
20
24
|
// Implementation
|
|
21
25
|
// --------------
|
|
26
|
+
/**
|
|
27
|
+
* Accessors typed with a runtime-sized array schema (e.g. `d.arrayOf(d.f32)`) accept
|
|
28
|
+
* any array of that element type. If the provided JS value has a concrete length, we
|
|
29
|
+
* use a statically-sized schema so that the generated code can take advantage of it.
|
|
30
|
+
*/
|
|
31
|
+
function concretizeSchema(accessorSchema, value) {
|
|
32
|
+
if (isWgslArray(accessorSchema) && accessorSchema.elementCount === 0 && Array.isArray(value)) {
|
|
33
|
+
if (value.length === 0) {
|
|
34
|
+
throw new Error(`Cannot use empty array as an accessor value. Empty arrays aren't representable in shader code.`);
|
|
35
|
+
}
|
|
36
|
+
return arrayOf(accessorSchema.elementType, value.length);
|
|
37
|
+
}
|
|
38
|
+
return accessorSchema;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Origins of values that can be assigned to (or are handles, like storage textures).
|
|
42
|
+
* Accessors can only refer to module-scope resources, so function-scope origins
|
|
43
|
+
* ('function', 'local-def') are never provided to them.
|
|
44
|
+
*/
|
|
45
|
+
const mutableOrigins = new Set(['mutable', 'workgroup', 'private', 'handle']);
|
|
46
|
+
/**
|
|
47
|
+
* Whether a value of type `providedType` can be used in place of `accessorSchema` without
|
|
48
|
+
* any conversion. Runtime-sized array schemas accept arrays of any length with a matching element type.
|
|
49
|
+
*/
|
|
50
|
+
function matchesSchema(accessorSchema, providedType) {
|
|
51
|
+
if (providedType === UnknownData) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
const expected = undecorate(accessorSchema);
|
|
55
|
+
const provided = undecorate(providedType);
|
|
56
|
+
if (isWgslArray(expected) && expected.elementCount === 0 && isWgslArray(provided)) {
|
|
57
|
+
return deepEqual(expected.elementType, provided.elementType);
|
|
58
|
+
}
|
|
59
|
+
return deepEqual(expected, provided);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Values with a concrete WGSL type (buffers, variables, GPU functions, ...) are used as-is,
|
|
63
|
+
* so they have to match the accessor's schema exactly. Mutable accessors are also assigned to,
|
|
64
|
+
* so the provided value has to be mutable.
|
|
65
|
+
*/
|
|
66
|
+
function validateAccessorSnippet(accessor, snippet) {
|
|
67
|
+
const isMutable = accessor.resourceType === 'mutable-accessor';
|
|
68
|
+
const description = `${isMutable ? 'mutable accessor' : 'accessor'} '${getName(accessor) ?? '<unnamed>'}'`;
|
|
69
|
+
if (isMutable && !mutableOrigins.has(snippet.origin)) {
|
|
70
|
+
throw new Error(`Values provided to ${description} must be mutable (e.g. mutable buffers, private or workgroup variables), got a value with origin '${snippet.origin}'. Use tgpu.accessor for read-only access.`);
|
|
71
|
+
}
|
|
72
|
+
if (!matchesSchema(accessor.schema, snippet.dataType)) {
|
|
73
|
+
throw new Error(`Value of type '${String(snippet.dataType)}' does not match the schema of ${description}: '${String(accessor.schema)}'.`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
22
76
|
/**
|
|
23
77
|
* @returns A snippet representing the accessor.
|
|
24
78
|
*/
|
|
25
79
|
function createAccessorSnippet(accessor) {
|
|
80
|
+
const snippet = createUnvalidatedAccessorSnippet(accessor);
|
|
81
|
+
validateAccessorSnippet(accessor, snippet);
|
|
82
|
+
return snippet;
|
|
83
|
+
}
|
|
84
|
+
function createUnvalidatedAccessorSnippet(accessor) {
|
|
26
85
|
// oxlint-disable-next-line typescript/no-non-null-assertion -- it's there
|
|
27
86
|
const ctx = getResolutionCtx();
|
|
28
87
|
let value = getGpuValueRecursively(ctx.unwrap(accessor.slot));
|
|
@@ -35,23 +94,31 @@ function createAccessorSnippet(accessor) {
|
|
|
35
94
|
if (isSnippet(value)) {
|
|
36
95
|
value = value.value;
|
|
37
96
|
}
|
|
97
|
+
value = getGpuValueRecursively(value);
|
|
38
98
|
}
|
|
39
99
|
const ownSnippet = getOwnSnippet(value);
|
|
40
100
|
if (ownSnippet) {
|
|
41
101
|
return ownSnippet;
|
|
42
102
|
}
|
|
43
103
|
if (isGPUCallable(value)) {
|
|
44
|
-
|
|
104
|
+
const result = value[$gpuCallable].call(ctx, []);
|
|
105
|
+
if (result.dataType !== UnknownData && !isAbstract(result.dataType)) {
|
|
106
|
+
return result;
|
|
107
|
+
}
|
|
108
|
+
// The result is a plain JS value (e.g. an array literal or a number returned from
|
|
109
|
+
// `tgpu.comptime`), so we treat it the same way as a directly provided JS value.
|
|
110
|
+
value = result.value;
|
|
45
111
|
}
|
|
46
112
|
if (isTgpuFn(value) || hasTinyestMetadata(value)) {
|
|
47
113
|
const fn = ctx.resolve(value);
|
|
48
|
-
return ctx.withResetIndentLevel(() => snip(`${fn.value}()`,
|
|
114
|
+
return ctx.withResetIndentLevel(() => snip(`${fn.value}()`, fn.dataType, /* origin */ 'runtime', fn.possibleSideEffects));
|
|
49
115
|
}
|
|
50
116
|
ctx.pushMode(new NormalState());
|
|
51
117
|
try {
|
|
118
|
+
const schema = concretizeSchema(accessor.schema, value);
|
|
52
119
|
// Doing a deep copy each time so that we don't have to deal with refs
|
|
53
|
-
const cloned = schemaCallWrapper(
|
|
54
|
-
return snip(cloned,
|
|
120
|
+
const cloned = schemaCallWrapper(schema, value);
|
|
121
|
+
return snip(cloned, schema, 'constant', /* possibleSideEffects */ false);
|
|
55
122
|
}
|
|
56
123
|
finally {
|
|
57
124
|
ctx.popMode('normal');
|
package/core/slot/slotTypes.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { $gpuValueOf, $internal, $providing, $soul } from '../../shared/symbols.
|
|
|
7
7
|
import type { UnwrapRuntimeConstructor } from '../../tgpuBindGroupLayout.ts';
|
|
8
8
|
import type { TgpuBufferBinding } from '../buffer/bufferBinding.ts';
|
|
9
9
|
import type { TgpuConst } from '../constant/tgpuConstant.ts';
|
|
10
|
+
import type { TgpuImmediateVar } from '../immediate/immediateVar.ts';
|
|
10
11
|
import type { Withable } from '../root/rootTypes.ts';
|
|
11
12
|
import type { TgpuTextureView } from '../texture/texture.ts';
|
|
12
13
|
import type { TgpuVar, VariableScope } from '../variable/tgpuVariable.ts';
|
|
@@ -51,7 +52,7 @@ export interface TgpuAccessor<T extends BaseData = BaseData> extends TgpuNamable
|
|
|
51
52
|
readonly $: InferGPU<T>;
|
|
52
53
|
toString(): string;
|
|
53
54
|
}
|
|
54
|
-
type DataAccessorIn<T extends BaseData> = (() => DataAccessorIn<T>) | TgpuBufferBinding<T> | TgpuVar<VariableScope, T> | TgpuConst<T> | Infer<T>;
|
|
55
|
+
type DataAccessorIn<T extends BaseData> = (() => DataAccessorIn<T>) | TgpuBufferBinding<T> | TgpuVar<VariableScope, T> | TgpuConst<T> | TgpuImmediateVar<T> | Infer<T>;
|
|
55
56
|
type TextureAccessorIn<T extends WgslTexture | WgslStorageTexture> = (() => TextureAccessorIn<T>) | Infer<T> | TgpuTextureView<T>;
|
|
56
57
|
export declare namespace TgpuAccessor {
|
|
57
58
|
type In<T extends BaseData | ((count: number) => BaseData)> = UnwrapRuntimeConstructor<T> extends WgslTexture | WgslStorageTexture ? TextureAccessorIn<UnwrapRuntimeConstructor<T>> : DataAccessorIn<UnwrapRuntimeConstructor<T>>;
|
|
@@ -13,6 +13,7 @@ import type { ResolutionCtx, SelfResolvable } from '../../types.ts';
|
|
|
13
13
|
import type { ExperimentalTgpuRoot } from '../root/rootTypes.ts';
|
|
14
14
|
import type { TextureProps } from './textureProps.ts';
|
|
15
15
|
import type { AllowedUsages, LiteralToExtensionMap, RenderFlag, SampledFlag } from './usageExtension.ts';
|
|
16
|
+
import { type TextureBlobWriteOptions, type TextureCopyOptions, type TextureRawWriteOptions, type TextureWriteOptions } from './textureWrite.ts';
|
|
16
17
|
export type TextureInternals = {
|
|
17
18
|
root: ExperimentalTgpuRoot;
|
|
18
19
|
materialize(): GPUTexture;
|
|
@@ -38,17 +39,7 @@ type TextureViewInternals = {
|
|
|
38
39
|
readonly aspect?: GPUTextureAspect | undefined;
|
|
39
40
|
};
|
|
40
41
|
export type TexelData = Vec4u | Vec4i | Vec4f;
|
|
41
|
-
export type
|
|
42
|
-
export type TextureWriteFit = 'stretch';
|
|
43
|
-
export type TextureWriteOptions = {
|
|
44
|
-
/**
|
|
45
|
-
* How to handle a source whose dimensions do not match the texture.
|
|
46
|
-
*
|
|
47
|
-
* By default, mismatched writes throw. Use `'stretch'` to resample the
|
|
48
|
-
* source to the texture's dimensions.
|
|
49
|
-
*/
|
|
50
|
-
fit?: TextureWriteFit;
|
|
51
|
-
};
|
|
42
|
+
export type { TextureBlobWriteOptions, TextureChannel, TextureCopyOptions, TextureRawWriteOptions, TextureWriteFit, TextureWriteOptions, } from './textureWrite.ts';
|
|
52
43
|
type TgpuTextureViewDescriptor = {
|
|
53
44
|
/**
|
|
54
45
|
* Which {@link GPUTextureAspect | aspect(s)} of the texture are accessible to the texture view.
|
|
@@ -106,6 +97,12 @@ type CopyCompatibleTexture<T extends TextureProps> = TgpuTexture<{
|
|
|
106
97
|
format: T['format'];
|
|
107
98
|
sampleCount?: T['sampleCount'];
|
|
108
99
|
}>;
|
|
100
|
+
type FormatCompatibleTexture<T extends TextureProps> = TgpuTexture<{
|
|
101
|
+
size: readonly number[];
|
|
102
|
+
format: T['format'];
|
|
103
|
+
dimension?: TextureProps['dimension'];
|
|
104
|
+
sampleCount?: T['sampleCount'];
|
|
105
|
+
}>;
|
|
109
106
|
export interface TgpuTexture<TProps extends TextureProps = any> extends TgpuNamable {
|
|
110
107
|
readonly [$internal]: TextureInternals;
|
|
111
108
|
readonly [$soul]: TgpuTextureSoul<TProps>;
|
|
@@ -123,11 +120,21 @@ export interface TgpuTexture<TProps extends TextureProps = any> extends TgpuNama
|
|
|
123
120
|
sampleType?: T['sampleType'] extends F32 ? 'float' | 'unfilterable-float' : never;
|
|
124
121
|
}): TgpuTextureView<T>;
|
|
125
122
|
createView<T extends WgslStorageTexture>(schema: ValidateTextureViewSchema<this, T>, viewDescriptor?: TgpuTextureViewDescriptor): TgpuTextureView<T>;
|
|
123
|
+
/** Clears the texture to zeros */
|
|
126
124
|
clear(mipLevel?: number | 'all'): void;
|
|
125
|
+
/** Clears the texture to `color`. Requires the `'render'` usage flag */
|
|
126
|
+
clear(color: readonly [number, number, number, number], mipLevel?: number | 'all'): void;
|
|
127
127
|
generateMipmaps(baseMipLevel?: number, mipLevels?: number): void;
|
|
128
|
-
|
|
129
|
-
write(source:
|
|
128
|
+
/** Writes image sources to the texture, one per array layer. Requires the `'render'` usage flag */
|
|
129
|
+
write(source: GPUCopyExternalImageSource | GPUCopyExternalImageSource[], options?: TextureWriteOptions): void;
|
|
130
|
+
/** Writes raw texel data to the texture */
|
|
131
|
+
write(source: ArrayBuffer | TypedArray | DataView, options?: number | TextureRawWriteOptions): void;
|
|
132
|
+
/** Decodes an image blob and writes it to the texture. Requires the `'render'` usage flag */
|
|
133
|
+
writeAsync(source: Blob, options?: TextureBlobWriteOptions): Promise<void>;
|
|
134
|
+
/** Copies the contents of a texture with a matching size and format */
|
|
130
135
|
copyFrom<T extends CopyCompatibleTexture<TProps>>(source: T): void;
|
|
136
|
+
/** Copies a region between textures of the same format */
|
|
137
|
+
copyFrom<T extends FormatCompatibleTexture<TProps>>(source: T, options: TextureCopyOptions): void;
|
|
131
138
|
destroy(): void;
|
|
132
139
|
}
|
|
133
140
|
export interface TgpuTextureView<TSchema extends WgslStorageTexture | WgslTexture = WgslStorageTexture | WgslTexture> extends TgpuNamable {
|
|
@@ -170,4 +177,3 @@ export declare class TgpuTextureRenderViewImpl implements TgpuTextureRenderView
|
|
|
170
177
|
constructor(baseTexture: TgpuTexture, descriptor?: TgpuTextureViewDescriptor);
|
|
171
178
|
get descriptor(): TgpuTextureViewDescriptor;
|
|
172
179
|
}
|
|
173
|
-
export {};
|