typegpu 0.12.5 → 0.12.6

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 (69) hide show
  1. package/common/index.d.ts +1 -0
  2. package/common/index.js +1 -0
  3. package/common/writeChannels.d.ts +31 -0
  4. package/common/writeChannels.js +32 -0
  5. package/core/commandEncoder/computePass.d.ts +13 -0
  6. package/core/commandEncoder/computePass.js +5 -2
  7. package/core/commandEncoder/renderPass.d.ts +18 -4
  8. package/core/commandEncoder/renderPass.js +6 -2
  9. package/core/declare/tgpuDeclare.d.ts +11 -0
  10. package/core/declare/tgpuDeclare.js +1 -1
  11. package/core/immediate/immediateVar.d.ts +52 -0
  12. package/core/immediate/immediateVar.js +149 -0
  13. package/core/pipeline/computePipeline.d.ts +17 -0
  14. package/core/pipeline/computePipeline.js +23 -9
  15. package/core/pipeline/drawState.d.ts +8 -4
  16. package/core/pipeline/drawState.js +41 -51
  17. package/core/pipeline/priors.js +1 -0
  18. package/core/pipeline/renderPipeline.d.ts +18 -1
  19. package/core/pipeline/renderPipeline.js +15 -1
  20. package/core/root/init.js +3 -0
  21. package/core/root/rootTypes.d.ts +11 -0
  22. package/core/slot/slotTypes.d.ts +2 -1
  23. package/core/texture/texture.d.ts +20 -14
  24. package/core/texture/texture.js +70 -65
  25. package/core/texture/textureUtils.d.ts +3 -6
  26. package/core/texture/textureUtils.js +142 -165
  27. package/core/texture/textureWrite.d.ts +61 -0
  28. package/core/texture/textureWrite.js +59 -0
  29. package/data/dataIO.d.ts +2 -2
  30. package/data/snippet.d.ts +5 -1
  31. package/data/snippet.js +1 -0
  32. package/data/wgslTypes.d.ts +1 -1
  33. package/errors.d.ts +7 -0
  34. package/errors.js +15 -0
  35. package/indexNamedExports.d.ts +5 -2
  36. package/indexNamedExports.js +2 -1
  37. package/internal.d.ts +1 -1
  38. package/internal.js +1 -1
  39. package/package.json +2 -2
  40. package/resolutionCtx.d.ts +5 -0
  41. package/resolutionCtx.js +11 -0
  42. package/serial/restore.d.ts +3 -1
  43. package/serial/restore.js +2 -0
  44. package/shared/meta.js +1 -1
  45. package/shared/symbols.js +1 -1
  46. package/shared/tseynit.d.ts +1 -0
  47. package/shared/tseynit.js +39 -7
  48. package/std/atomic.d.ts +13 -0
  49. package/std/atomic.js +63 -29
  50. package/std/derivative.js +14 -9
  51. package/std/index.d.ts +4 -4
  52. package/std/index.js +5 -5
  53. package/std/numeric.d.ts +5 -1
  54. package/std/numeric.js +3 -3
  55. package/std/packing.d.ts +61 -1
  56. package/std/packing.js +214 -25
  57. package/std/subgroup.d.ts +4 -0
  58. package/std/subgroup.js +34 -0
  59. package/std/texture.d.ts +13 -0
  60. package/std/texture.js +48 -0
  61. package/tgpuUnstable.d.ts +1 -0
  62. package/tgpuUnstable.js +1 -0
  63. package/tgsl/conversion.d.ts +2 -0
  64. package/tgsl/conversion.js +3 -0
  65. package/tgsl/shaderGenerator.d.ts +1 -1
  66. package/tgsl/wgslGenerator.d.ts +5 -0
  67. package/tgsl/wgslGenerator.js +218 -50
  68. package/types.d.ts +9 -1
  69. package/types.js +5 -0
@@ -5,6 +5,7 @@ import type { IndexFlag, TgpuBuffer, VertexFlag } from '../buffer/buffer.ts';
5
5
  import type { TgpuCommandEncoder } from '../commandEncoder/commandEncoder.ts';
6
6
  import type { ComputePassInternals } from '../commandEncoder/computePass.ts';
7
7
  import type { RenderPassInternals } from '../commandEncoder/renderPass.ts';
8
+ import { ImmediatePassState } from '../immediate/immediateVar.ts';
8
9
  import type { ExperimentalTgpuRoot } from '../root/rootTypes.ts';
9
10
  import type { TgpuVertexLayout } from '../vertexLayout/vertexLayout.ts';
10
11
  import type { TgpuComputePipeline } from './computePipeline.ts';
@@ -24,6 +25,7 @@ export interface IndexBufferEntry {
24
25
  export declare class RenderDrawState {
25
26
  readonly bindGroups: Map<TgpuBindGroupLayout<Record<string, import("../../tgpuBindGroupLayout.ts").TgpuLayoutEntry | null>>, TgpuBindGroup | GPUBindGroup>;
26
27
  readonly vertexBuffers: Map<TgpuVertexLayout<import("../../data/wgslTypes.ts").WgslArray<BaseData> | import("../../data/dataTypes.ts").Disarray<BaseData>>, VertexBufferEntry>;
28
+ readonly immediates: ImmediatePassState;
27
29
  currentPipeline: TgpuRenderPipeline | undefined;
28
30
  indexBuffer: IndexBufferEntry | undefined;
29
31
  stencilReference: GPUStencilValue | undefined;
@@ -35,15 +37,17 @@ export declare class RenderDrawState {
35
37
  }
36
38
  export declare class ComputeDrawState {
37
39
  readonly bindGroups: Map<TgpuBindGroupLayout<Record<string, import("../../tgpuBindGroupLayout.ts").TgpuLayoutEntry | null>>, TgpuBindGroup | GPUBindGroup>;
40
+ readonly immediates: ImmediatePassState;
38
41
  currentPipeline: TgpuComputePipeline | undefined;
39
42
  version: number;
40
43
  rawAccessed: boolean;
41
44
  }
42
45
  export declare function recordBindGroup(state: RenderDrawState | ComputeDrawState, first: TgpuBindGroup | TgpuBindGroupLayout, bindGroup: TgpuBindGroup | GPUBindGroup | undefined): void;
43
- /** Writes the pipeline and its bound resources into pass state; later set* calls overwrite them */
44
- export declare function stampRenderPipeline(state: RenderDrawState, pipeline: TgpuRenderPipeline): void;
45
- /** The compute counterpart of {@link stampRenderPipeline} */
46
- export declare function stampComputePipeline(state: ComputeDrawState, pipeline: TgpuComputePipeline): void;
46
+ /** Makes the pipeline current; its held state is resolved at draw time, below what the pass holds */
47
+ export declare function selectPipeline<TPipeline>(state: {
48
+ currentPipeline: TPipeline | undefined;
49
+ version: number;
50
+ }, pipeline: TPipeline): void;
47
51
  export declare function requireIndexBuffer(indexBuffer: IndexBufferEntry | undefined): void;
48
52
  export declare function finalizeOwnEncoder(encoder: TgpuCommandEncoder, core: object, logResources: LogResources | undefined, priors: TimestampWritesPriors & {
49
53
  readonly encoder?: TgpuCommandEncoder | undefined;
@@ -4,10 +4,12 @@ import { logger } from "../../tgpuLogger.js";
4
4
  import { isBindGroup, } from "../../tgpuBindGroupLayout.js";
5
5
  import { logDataFromGPU } from "../../tgsl/consoleLog/deserializers.js";
6
6
  import { isBuffer } from "../../types.js";
7
+ import { ImmediatePassState } from "../immediate/immediateVar.js";
7
8
  import { queueTimestampResolve } from "./timeable.js";
8
9
  export class RenderDrawState {
9
10
  bindGroups = new Map();
10
11
  vertexBuffers = new Map();
12
+ immediates = new ImmediatePassState();
11
13
  currentPipeline;
12
14
  indexBuffer;
13
15
  stencilReference;
@@ -19,6 +21,7 @@ export class RenderDrawState {
19
21
  }
20
22
  export class ComputeDrawState {
21
23
  bindGroups = new Map();
24
+ immediates = new ImmediatePassState();
22
25
  currentPipeline;
23
26
  version = 0;
24
27
  rawAccessed = false;
@@ -32,38 +35,12 @@ export function recordBindGroup(state, first, bindGroup) {
32
35
  }
33
36
  state.version++;
34
37
  }
35
- /** Writes the pipeline and its bound resources into pass state; later set* calls overwrite them */
36
- export function stampRenderPipeline(state, pipeline) {
37
- const { priors } = pipeline[$internal];
38
- state.currentPipeline = pipeline;
39
- if (priors.bindGroupLayoutMap) {
40
- for (const [layout, group] of priors.bindGroupLayoutMap) {
41
- state.bindGroups.set(layout, group);
42
- }
43
- }
44
- if (priors.vertexLayoutMap) {
45
- for (const [layout, buffer] of priors.vertexLayoutMap) {
46
- state.vertexBuffers.set(layout, { buffer, offset: undefined, size: undefined });
47
- }
48
- }
49
- if (priors.indexBuffer) {
50
- state.indexBuffer = priors.indexBuffer;
51
- }
52
- if (priors.stencilReference !== undefined) {
53
- state.stencilReference = priors.stencilReference;
54
- }
55
- state.version++;
56
- }
57
- /** The compute counterpart of {@link stampRenderPipeline} */
58
- export function stampComputePipeline(state, pipeline) {
59
- const { priors } = pipeline[$internal];
60
- state.currentPipeline = pipeline;
61
- if (priors.bindGroupLayoutMap) {
62
- for (const [layout, group] of priors.bindGroupLayoutMap) {
63
- state.bindGroups.set(layout, group);
64
- }
38
+ /** Makes the pipeline current; its held state is resolved at draw time, below what the pass holds */
39
+ export function selectPipeline(state, pipeline) {
40
+ if (state.currentPipeline !== pipeline) {
41
+ state.currentPipeline = pipeline;
42
+ state.version++;
65
43
  }
66
- state.version++;
67
44
  }
68
45
  function applyIndexBuffer(encoder, root, entry) {
69
46
  const { buffer, indexFormat, offsetBytes, sizeBytes } = entry;
@@ -117,25 +94,36 @@ function applyVertexBuffers(encoder, root, usedVertexLayouts, resolveVertexBuffe
117
94
  }
118
95
  }
119
96
  function applyRenderPipelineState(encoder, root, pipeline, passState) {
120
- const memo = pipeline[$internal].core.unwrap();
97
+ const { core, priors } = pipeline[$internal];
98
+ const memo = core.unwrap();
121
99
  encoder.setPipeline(memo.pipeline);
122
- applyBindGroups(encoder, root, memo.usedBindGroupLayouts, memo.catchall, (layout) => passState.bindGroups.get(layout));
123
- applyVertexBuffers(encoder, root, memo.usedVertexLayouts, (vertexLayout) => passState.vertexBuffers.get(vertexLayout));
124
- if (passState.indexBuffer !== undefined) {
125
- applyIndexBuffer(encoder, root, passState.indexBuffer);
126
- }
127
- if (typeof encoder.setStencilReference === 'function' &&
128
- passState.stencilReference !== undefined) {
129
- if (passState.rawAccessed || passState.stencilReference !== passState.appliedStencilReference) {
130
- encoder.setStencilReference(passState.stencilReference);
131
- passState.appliedStencilReference = passState.stencilReference;
100
+ applyBindGroups(encoder, root, memo.usedBindGroupLayouts, memo.catchall, (layout) => passState.bindGroups.get(layout) ?? priors.bindGroupLayoutMap?.get(layout));
101
+ applyVertexBuffers(encoder, root, memo.usedVertexLayouts, (vertexLayout) => {
102
+ const passEntry = passState.vertexBuffers.get(vertexLayout);
103
+ if (passEntry !== undefined) {
104
+ return passEntry;
105
+ }
106
+ const buffer = priors.vertexLayoutMap?.get(vertexLayout);
107
+ return buffer !== undefined ? { buffer } : undefined;
108
+ });
109
+ const indexBuffer = passState.indexBuffer ?? priors.indexBuffer;
110
+ if (indexBuffer !== undefined) {
111
+ applyIndexBuffer(encoder, root, indexBuffer);
112
+ }
113
+ if (typeof encoder.setStencilReference === 'function') {
114
+ const stencilReference = passState.stencilReference ?? priors.stencilReference ?? 0;
115
+ const dirty = passState.rawAccessed || stencilReference !== passState.appliedStencilReference;
116
+ if (dirty) {
117
+ encoder.setStencilReference(stencilReference);
118
+ passState.appliedStencilReference = stencilReference;
132
119
  }
133
120
  }
134
121
  }
135
122
  function applyComputePipelineState(encoder, root, pipeline, passState) {
136
- const memo = pipeline[$internal].core.unwrap();
123
+ const { core, priors } = pipeline[$internal];
124
+ const memo = core.unwrap();
137
125
  encoder.setPipeline(memo.pipeline);
138
- applyBindGroups(encoder, root, memo.usedBindGroupLayouts, memo.catchall, (layout) => passState.bindGroups.get(layout));
126
+ applyBindGroups(encoder, root, memo.usedBindGroupLayouts, memo.catchall, (layout) => passState.bindGroups.get(layout) ?? priors.bindGroupLayoutMap?.get(layout));
139
127
  }
140
128
  export function requireIndexBuffer(indexBuffer) {
141
129
  if (!indexBuffer) {
@@ -191,11 +179,9 @@ function reportIgnoredPriors(core, owner, hasTimestampWrites, logResources, pass
191
179
  export function emitRenderDraw(root, passInternals, pipeline, usesIndexBuffer, emit, ownsPass = false) {
192
180
  const { state, rawPass } = passInternals;
193
181
  const { core, priors } = pipeline[$internal];
194
- if (state.currentPipeline !== pipeline) {
195
- stampRenderPipeline(state, pipeline);
196
- }
182
+ selectPipeline(state, pipeline);
197
183
  if (usesIndexBuffer) {
198
- requireIndexBuffer(state.indexBuffer);
184
+ requireIndexBuffer(state.indexBuffer ?? priors.indexBuffer);
199
185
  }
200
186
  const memo = core.unwrap();
201
187
  if (!ownsPass) {
@@ -205,14 +191,15 @@ export function emitRenderDraw(root, passInternals, pipeline, usesIndexBuffer, e
205
191
  applyRenderPipelineState(rawPass, root, pipeline, state);
206
192
  passInternals.appliedVersion = state.version;
207
193
  }
194
+ if (memo.usedImmediate !== undefined) {
195
+ state.immediates.write(rawPass, memo.usedImmediate, priors.immediatesMap, !state.rawAccessed);
196
+ }
208
197
  emit(rawPass);
209
198
  }
210
199
  export function emitComputeDispatch(root, passInternals, pipeline, emit, ownsPass = false) {
211
200
  const { state, rawPass } = passInternals;
212
201
  const { core, priors } = pipeline[$internal];
213
- if (state.currentPipeline !== pipeline) {
214
- stampComputePipeline(state, pipeline);
215
- }
202
+ selectPipeline(state, pipeline);
216
203
  const memo = core.unwrap();
217
204
  if (!ownsPass) {
218
205
  reportIgnoredPriors(core, passInternals.owner, !!priors.timestampWrites, memo.logResources, 'compute');
@@ -221,5 +208,8 @@ export function emitComputeDispatch(root, passInternals, pipeline, emit, ownsPas
221
208
  applyComputePipelineState(rawPass, root, pipeline, state);
222
209
  passInternals.appliedVersion = state.version;
223
210
  }
211
+ if (memo.usedImmediate !== undefined) {
212
+ state.immediates.write(rawPass, memo.usedImmediate, priors.immediatesMap, !state.rawAccessed);
213
+ }
224
214
  emit(rawPass);
225
215
  }
@@ -1,6 +1,7 @@
1
1
  // GPU objects like query sets cross runtimes as shareable host objects, performanceCallback crosses only if it is a worklet
2
2
  const TRANSFERABLE_PRIORS = new Set([
3
3
  'bindGroupLayoutMap',
4
+ 'immediatesMap',
4
5
  'vertexLayoutMap',
5
6
  'indexBuffer',
6
7
  'stencilReference',
@@ -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, type WgslStruct } from '../../data/wgslTypes.ts';
6
+ import { type AnyVecInstance, type AnyWgslData, type BaseData, type U16, type U32, type v4f, Void, type WgslArray, type WgslStruct } 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';
@@ -19,6 +20,7 @@ import type { TgpuSlot } from '../slot/slotTypes.ts';
19
20
  import { type TgpuVertexLayout } from '../vertexLayout/vertexLayout.ts';
20
21
  import { type TgpuCommandEncoder } from '../commandEncoder/commandEncoder.ts';
21
22
  import type { ColorAttachment, DepthStencilAttachment } from '../commandEncoder/attachments.ts';
23
+ import { type ImmediateSnapshot, type TgpuImmediateVar } from '../immediate/immediateVar.ts';
22
24
  import { type TgpuRenderCommands } from '../commandEncoder/renderPass.ts';
23
25
  import { type Timeable, type TimestampWritesPriors } from './timeable.ts';
24
26
  import { type PrimitiveOffsetInfo } from '../../data/offsetUtils.ts';
@@ -34,6 +36,8 @@ export interface TgpuRenderPipelineSoul extends TgpuDeviceOwningSoul<'render-pip
34
36
  usedVertexLayouts?: TgpuVertexLayout[] | undefined;
35
37
  fragmentOut?: BaseData | undefined;
36
38
  bindGroups?: [TgpuBindGroupLayout, TgpuBindGroup | GPUBindGroup][] | undefined;
39
+ usedImmediate?: TgpuImmediateVar | undefined;
40
+ immediates?: [TgpuImmediateVar, ImmediateSnapshot][] | undefined;
37
41
  vertexBuffers?: [TgpuVertexLayout, (TgpuBuffer<BaseData> & VertexFlag) | GPUBuffer][] | undefined;
38
42
  indexBuffer?: {
39
43
  buffer: (TgpuBuffer<BaseData> & IndexFlag) | GPUBuffer;
@@ -76,6 +80,16 @@ export interface TgpuRenderPipeline<in Targets = never> extends TgpuNamable, Sel
76
80
  with<Entries extends Record<string, TgpuLayoutEntry | null>>(bindGroupLayout: TgpuBindGroupLayout<Entries>, bindGroup: TgpuBindGroup<Entries>): this;
77
81
  with(bindGroupLayout: TgpuBindGroupLayout, bindGroup: GPUBindGroup): this;
78
82
  with(bindGroup: TgpuBindGroup): this;
83
+ /**
84
+ * Provides a value for the given immediate variable, applied on draw like
85
+ * the rest of the pipeline-held state and overridden by `pass.setImmediates`.
86
+ * The value is captured (copied) at call time; mutating it afterwards has
87
+ * no effect.
88
+ *
89
+ * Passing an `ArrayBuffer` or typed array skips serialization entirely; the bytes
90
+ * are copied verbatim and the caller guarantees they match the schema's layout.
91
+ */
92
+ with<T extends AnyWgslData>(immediate: TgpuImmediateVar<T>, value: InferInput<T> | ArrayBuffer | ArrayBufferView): this;
79
93
  /**
80
94
  * Directs subsequent draw calls into the given render pass or render bundle
81
95
  * encoder, letting multiple pipelines share one pass (and one submission).
@@ -199,6 +213,7 @@ type TgpuRenderPipelinePriors = {
199
213
  readonly pass?: TgpuRenderCommands | undefined;
200
214
  /** An encoder the pipeline records its own passes into, but does not submit */
201
215
  readonly encoder?: TgpuCommandEncoder | undefined;
216
+ readonly immediatesMap?: Map<TgpuImmediateVar, ImmediateSnapshot> | undefined;
202
217
  } & TimestampWritesPriors;
203
218
  type Memo = {
204
219
  pipeline: GPURenderPipeline;
@@ -207,6 +222,7 @@ type Memo = {
207
222
  logResources: LogResources | undefined;
208
223
  usedVertexLayouts: TgpuVertexLayout[];
209
224
  fragmentOut: BaseData | undefined;
225
+ usedImmediate: TgpuImmediateVar | undefined;
210
226
  };
211
227
  declare class TgpuRenderPipelineImpl implements TgpuRenderPipeline {
212
228
  #private;
@@ -223,6 +239,7 @@ declare class TgpuRenderPipelineImpl implements TgpuRenderPipeline {
223
239
  with(bindGroupLayout: TgpuBindGroupLayout, bindGroup: GPUBindGroup): this;
224
240
  with(bindGroup: TgpuBindGroup): this;
225
241
  with<TData extends WgslArray | Disarray>(vertexLayout: TgpuVertexLayout<TData>, buffer: GPUBuffer): this;
242
+ with<T extends AnyWgslData>(immediate: TgpuImmediateVar<T>, value: InferInput<T> | ArrayBuffer | ArrayBufferView): this;
226
243
  with(pass: TgpuRenderCommands): this;
227
244
  with(encoder: TgpuCommandEncoder): this;
228
245
  with(encoder: GPUCommandEncoder): this;
@@ -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";
@@ -42,9 +43,11 @@ export function INTERNAL_restoreRenderPipeline(soul, ctx) {
42
43
  logResources: undefined,
43
44
  usedVertexLayouts: soul.usedVertexLayouts ?? [],
44
45
  fragmentOut: soul.fragmentOut,
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,
@@ -76,6 +79,8 @@ class TgpuRenderPipelineImpl {
76
79
  soul.usedVertexLayouts = memo.usedVertexLayouts;
77
80
  soul.fragmentOut = memo.fragmentOut;
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) {
@@ -347,6 +357,7 @@ class RenderPipelineCore {
347
357
  logResources,
348
358
  usedVertexLayouts: connectedAttribs.usedVertexLayouts,
349
359
  fragmentOut,
360
+ usedImmediate: resolutionResult.usedImmediate,
350
361
  };
351
362
  this.#performanceTracker.measureCompile(device);
352
363
  })
@@ -373,6 +384,7 @@ class RenderPipelineCore {
373
384
  logResources,
374
385
  usedVertexLayouts: connectedAttribs.usedVertexLayouts,
375
386
  fragmentOut,
387
+ usedImmediate: resolutionResult.usedImmediate,
376
388
  };
377
389
  this.#performanceTracker.measureCompile(device);
378
390
  }
@@ -396,11 +408,12 @@ class RenderPipelineCore {
396
408
  shaderGenerator: root.shaderGeneratorClass ? new root.shaderGeneratorClass() : undefined,
397
409
  root,
398
410
  }));
399
- const { code, usedBindGroupLayouts, catchall } = resolutionResult;
411
+ const { code, usedBindGroupLayouts, catchall, usedImmediate } = resolutionResult;
400
412
  if (catchall !== undefined) {
401
413
  usedBindGroupLayouts[catchall[0]]?.$name(`${getName(this) ?? '<unnamed>'} - Automatic Bind Group & Layout`);
402
414
  }
403
415
  warnIfOverflow(usedBindGroupLayouts, device.limits);
416
+ const immediateSize = usedImmediate ? validateImmediateUsage(usedImmediate, root) : 0;
404
417
  const module = device.createShaderModule({
405
418
  label: `${getName(this) ?? '<unnamed>'} - Shader`,
406
419
  code,
@@ -417,6 +430,7 @@ class RenderPipelineCore {
417
430
  layout: device.createPipelineLayout({
418
431
  label: `${getName(this) ?? '<unnamed>'} - Pipeline Layout`,
419
432
  bindGroupLayouts: usedBindGroupLayouts.map((l) => root.unwrap(l)),
433
+ immediateSize,
420
434
  }),
421
435
  vertex: {
422
436
  module,
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
  }
@@ -418,6 +418,17 @@ export interface TgpuRoot extends Unwrapper, WithBinding {
418
418
  * @returns A set of strings representing the enabled features.
419
419
  */
420
420
  get enabledFeatures(): ReadonlySet<GPUFeatureName>;
421
+ /**
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>;
421
432
  /**
422
433
  * Destroys all underlying resources (i.e. buffers...) created through this root object.
423
434
  * If the object is created via `tgpu.init` instead of `tgpu.initFromDevice`,
@@ -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 ExternalImageSource = HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | ImageBitmap | ImageData | OffscreenCanvas | VideoFrame;
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
- write(source: ExternalImageSource | ExternalImageSource[], options?: TextureWriteOptions): void;
129
- write(source: ArrayBuffer | TypedArray | DataView, mipLevel?: number): void;
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 {};