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.
- 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/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/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/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 +18 -1
- package/core/pipeline/renderPipeline.js +15 -1
- package/core/root/init.js +3 -0
- package/core/root/rootTypes.d.ts +11 -0
- package/core/slot/slotTypes.d.ts +2 -1
- package/core/texture/texture.d.ts +20 -14
- package/core/texture/texture.js +70 -65
- 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/dataIO.d.ts +2 -2
- package/data/snippet.d.ts +5 -1
- package/data/snippet.js +1 -0
- package/data/wgslTypes.d.ts +1 -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 +1 -1
- package/internal.js +1 -1
- 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 +39 -7
- package/std/atomic.d.ts +13 -0
- package/std/atomic.js +63 -29
- 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/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 +13 -0
- package/std/texture.js +48 -0
- package/tgpuUnstable.d.ts +1 -0
- package/tgpuUnstable.js +1 -0
- package/tgsl/conversion.d.ts +2 -0
- package/tgsl/conversion.js +3 -0
- package/tgsl/shaderGenerator.d.ts +1 -1
- package/tgsl/wgslGenerator.d.ts +5 -0
- package/tgsl/wgslGenerator.js +218 -50
- package/types.d.ts +9 -1
- 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
|
-
/**
|
|
44
|
-
export declare function
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
/**
|
|
36
|
-
export function
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
|
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) =>
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
}
|
package/core/pipeline/priors.js
CHANGED
|
@@ -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
|
}
|
package/core/root/rootTypes.d.ts
CHANGED
|
@@ -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`,
|
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 {};
|