typegpu 0.10.0 → 0.10.2
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/{chunk-BYypO7fO.js → _virtual/_rolldown/runtime.js} +1 -1
- package/builtin.d.ts +50 -0
- package/builtin.js +37 -0
- package/common/fullScreenTriangle.d.ts +26 -0
- package/common/fullScreenTriangle.js +36 -0
- package/common/index.d.ts +2 -3
- package/common/index.js +3 -4
- package/core/buffer/buffer.d.ts +74 -0
- package/core/buffer/buffer.js +197 -0
- package/core/buffer/bufferShorthand.d.ts +48 -0
- package/core/buffer/bufferShorthand.js +49 -0
- package/core/buffer/bufferUsage.d.ts +45 -0
- package/core/buffer/bufferUsage.js +163 -0
- package/core/constant/tgpuConstant.d.ts +28 -0
- package/core/constant/tgpuConstant.js +67 -0
- package/core/declare/tgpuDeclare.d.ts +18 -0
- package/core/declare/tgpuDeclare.js +40 -0
- package/core/function/autoIO.d.ts +37 -0
- package/core/function/autoIO.js +87 -0
- package/core/function/comptime.d.ts +39 -0
- package/core/function/comptime.js +51 -0
- package/core/function/createCallableSchema.js +42 -0
- package/core/function/dualImpl.js +54 -0
- package/core/function/extractArgs.js +204 -0
- package/core/function/fnCore.js +79 -0
- package/core/function/fnTypes.d.ts +34 -0
- package/core/function/ioSchema.d.ts +10 -0
- package/core/function/ioSchema.js +30 -0
- package/core/function/shelllessImpl.d.ts +28 -0
- package/core/function/shelllessImpl.js +23 -0
- package/core/function/templateUtils.js +13 -0
- package/core/function/tgpuComputeFn.d.ts +49 -0
- package/core/function/tgpuComputeFn.js +62 -0
- package/core/function/tgpuFn.d.ts +52 -0
- package/core/function/tgpuFn.js +170 -0
- package/core/function/tgpuFragmentFn.d.ts +68 -0
- package/core/function/tgpuFragmentFn.js +68 -0
- package/core/function/tgpuVertexFn.d.ts +55 -0
- package/core/function/tgpuVertexFn.js +65 -0
- package/core/pipeline/applyPipelineState.js +37 -0
- package/core/pipeline/computePipeline.d.ts +58 -0
- package/core/pipeline/computePipeline.js +226 -0
- package/core/pipeline/connectAttachmentToShader.js +26 -0
- package/core/pipeline/connectTargetsToShader.js +29 -0
- package/core/pipeline/limitsOverflow.js +13 -0
- package/core/pipeline/renderPipeline.d.ts +266 -0
- package/core/pipeline/renderPipeline.js +471 -0
- package/core/pipeline/timeable.d.ts +23 -0
- package/core/pipeline/timeable.js +61 -0
- package/core/pipeline/typeGuards.js +29 -0
- package/core/querySet/querySet.d.ts +22 -0
- package/core/querySet/querySet.js +103 -0
- package/core/rawCodeSnippet/tgpuRawCodeSnippet.d.ts +59 -0
- package/core/rawCodeSnippet/tgpuRawCodeSnippet.js +96 -0
- package/core/resolve/externals.d.ts +10 -0
- package/core/resolve/externals.js +58 -0
- package/core/resolve/namespace.d.ts +38 -0
- package/core/resolve/namespace.js +41 -0
- package/core/resolve/resolveData.js +146 -0
- package/core/resolve/stitch.js +25 -0
- package/core/resolve/tgpuResolve.d.ts +151 -0
- package/core/resolve/tgpuResolve.js +68 -0
- package/core/root/configurableImpl.js +18 -0
- package/core/root/init.d.ts +69 -0
- package/core/root/init.js +457 -0
- package/core/root/rootTypes.d.ts +622 -0
- package/core/sampler/sampler.d.ts +35 -0
- package/core/sampler/sampler.js +116 -0
- package/core/simulate/tgpuSimulate.d.ts +36 -0
- package/core/simulate/tgpuSimulate.js +76 -0
- package/core/slot/accessor.d.ts +13 -0
- package/core/slot/accessor.js +97 -0
- package/core/slot/internalSlots.js +7 -0
- package/core/slot/lazy.d.ts +6 -0
- package/core/slot/lazy.js +42 -0
- package/core/slot/slot.d.ts +6 -0
- package/core/slot/slot.js +40 -0
- package/core/slot/slotTypes.d.ts +92 -0
- package/core/slot/slotTypes.js +21 -0
- package/core/texture/externalTexture.d.ts +12 -0
- package/core/texture/externalTexture.js +48 -0
- package/core/texture/texture.d.ts +118 -0
- package/core/texture/texture.js +312 -0
- package/core/texture/textureFormats.d.ts +29 -0
- package/core/texture/textureFormats.js +99 -0
- package/core/texture/textureProps.d.ts +11 -0
- package/core/texture/textureUtils.js +224 -0
- package/core/texture/usageExtension.d.ts +21 -0
- package/core/texture/usageExtension.js +21 -0
- package/core/unroll/tgpuUnroll.d.ts +13 -0
- package/core/unroll/tgpuUnroll.js +36 -0
- package/core/valueProxyUtils.js +44 -0
- package/core/variable/tgpuVariable.d.ts +38 -0
- package/core/variable/tgpuVariable.js +101 -0
- package/core/vertexLayout/connectAttributesToShader.js +59 -0
- package/core/vertexLayout/vertexAttribute.d.ts +29 -0
- package/core/vertexLayout/vertexLayout.d.ts +19 -0
- package/core/vertexLayout/vertexLayout.js +103 -0
- package/data/alignIO.js +15 -0
- package/data/alignmentOf.d.ts +10 -0
- package/data/alignmentOf.js +88 -0
- package/data/array.d.ts +28 -0
- package/data/array.js +48 -0
- package/data/atomic.d.ts +15 -0
- package/data/atomic.js +25 -0
- package/data/attributes.d.ts +121 -0
- package/data/attributes.js +145 -0
- package/data/autoStruct.d.ts +3 -0
- package/data/autoStruct.js +83 -0
- package/data/compiledIO.js +231 -0
- package/data/dataIO.js +549 -0
- package/data/dataTypes.d.ts +115 -0
- package/data/dataTypes.js +97 -0
- package/data/deepEqual.d.ts +25 -0
- package/data/deepEqual.js +58 -0
- package/data/disarray.d.ts +34 -0
- package/data/disarray.js +52 -0
- package/data/getLongestContiguousPrefix.d.ts +10 -0
- package/data/getLongestContiguousPrefix.js +15 -0
- package/data/index.d.ts +26 -4
- package/data/index.js +27 -7
- package/data/instanceToSchema.d.ts +33 -0
- package/data/isContiguous.d.ts +10 -0
- package/data/isContiguous.js +15 -0
- package/data/matrix.d.ts +126 -0
- package/data/matrix.js +517 -0
- package/data/numberOps.js +24 -0
- package/data/numeric.d.ts +81 -0
- package/data/numeric.js +234 -0
- package/data/offsetUtils.d.ts +33 -0
- package/data/offsetUtils.js +167 -0
- package/data/offsets.js +36 -0
- package/data/partialIO.js +68 -0
- package/data/ptr.d.ts +12 -0
- package/data/ptr.js +46 -0
- package/data/ref.d.ts +37 -0
- package/data/ref.js +96 -0
- package/data/sampler.d.ts +107 -0
- package/data/sampler.js +26 -0
- package/data/schemaCallWrapper.js +32 -0
- package/data/schemaMemoryLayout.js +200 -0
- package/data/sizeOf.d.ts +10 -0
- package/data/sizeOf.js +15 -0
- package/data/snippet.d.ts +26 -0
- package/data/snippet.js +61 -0
- package/data/struct.d.ts +17 -0
- package/data/struct.js +46 -0
- package/data/texture.d.ts +292 -0
- package/{texture-Dg5ybJro.js → data/texture.js} +6 -3
- package/data/unstruct.d.ts +24 -0
- package/data/unstruct.js +43 -0
- package/data/vector.d.ts +191 -0
- package/data/vector.js +247 -0
- package/data/vectorImpl.js +516 -0
- package/data/vectorOps.js +664 -0
- package/data/vertexFormatData.d.ts +190 -0
- package/data/vertexFormatData.js +110 -0
- package/data/wgslTypes.d.ts +896 -0
- package/data/wgslTypes.js +215 -0
- package/errors.d.ts +44 -0
- package/errors.js +128 -0
- package/execMode.js +51 -0
- package/extension.d.ts +11 -0
- package/extension.js +18 -0
- package/getGPUValue.js +9 -0
- package/index.d.ts +40 -243
- package/index.js +19 -6318
- package/indexNamedExports.d.ts +38 -0
- package/mathUtils.js +13 -0
- package/memo.js +22 -0
- package/nameRegistry.d.ts +30 -0
- package/nameRegistry.js +449 -0
- package/package.js +5 -0
- package/package.json +23 -23
- package/resolutionCtx.d.ts +29 -0
- package/resolutionCtx.js +546 -0
- package/shared/env.js +13 -0
- package/shared/generators.js +14 -0
- package/shared/meta.d.ts +39 -0
- package/shared/meta.js +63 -0
- package/shared/repr.d.ts +108 -0
- package/shared/stringify.js +22 -0
- package/shared/symbols.d.ts +61 -0
- package/shared/symbols.js +71 -0
- package/shared/utilityTypes.d.ts +29 -0
- package/shared/utilityTypes.js +7 -0
- package/shared/vertexFormat.d.ts +70 -0
- package/shared/vertexFormat.js +64 -0
- package/std/array.d.ts +7 -0
- package/std/array.js +27 -0
- package/std/atomic.d.ts +19 -0
- package/std/atomic.js +113 -0
- package/std/bitcast.d.ts +10 -0
- package/std/bitcast.js +43 -0
- package/std/boolean.d.ts +127 -0
- package/std/boolean.js +274 -0
- package/std/derivative.d.ts +16 -0
- package/std/derivative.js +89 -0
- package/std/discard.d.ts +6 -0
- package/std/discard.js +16 -0
- package/std/extensions.d.ts +8 -0
- package/std/extensions.js +14 -0
- package/std/index.d.ts +15 -3
- package/std/index.js +16 -5
- package/std/matrix.d.ts +41 -0
- package/std/matrix.js +87 -0
- package/std/numeric.d.ts +254 -0
- package/std/numeric.js +847 -0
- package/std/operators.d.ts +48 -0
- package/std/operators.js +153 -0
- package/std/packing.d.ts +26 -0
- package/std/packing.js +86 -0
- package/std/subgroup.d.ts +47 -0
- package/std/subgroup.js +220 -0
- package/std/texture.d.ts +108 -0
- package/std/texture.js +197 -0
- package/tgpu.js +44 -0
- package/tgpuBindGroupLayout.d.ts +161 -0
- package/tgpuBindGroupLayout.js +271 -0
- package/tgpuUnstable.d.ts +48 -0
- package/tgpuUnstable.js +66 -0
- package/tgsl/accessIndex.js +45 -0
- package/tgsl/accessProp.js +113 -0
- package/tgsl/consoleLog/deserializers.js +117 -0
- package/tgsl/consoleLog/logGenerator.js +86 -0
- package/tgsl/consoleLog/serializers.js +225 -0
- package/tgsl/consoleLog/types.d.ts +54 -0
- package/tgsl/consoleLog/types.js +12 -0
- package/tgsl/conversion.js +200 -0
- package/tgsl/forOfUtils.js +45 -0
- package/tgsl/generationHelpers.d.ts +37 -0
- package/tgsl/generationHelpers.js +67 -0
- package/tgsl/math.js +45 -0
- package/tgsl/shaderGenerator.d.ts +18 -0
- package/tgsl/shellless.d.ts +11 -0
- package/tgsl/shellless.js +53 -0
- package/tgsl/wgslGenerator.js +585 -0
- package/types.d.ts +255 -0
- package/types.js +43 -0
- package/unwrapper.d.ts +27 -0
- package/wgslExtensions.d.ts +5 -0
- package/wgslExtensions.js +18 -0
- package/builtin-ClEnM-Ye.js +0 -818
- package/builtin-ClEnM-Ye.js.map +0 -1
- package/common/index.d.ts.map +0 -1
- package/common/index.js.map +0 -1
- package/data/index.d.ts.map +0 -1
- package/data/index.js.map +0 -1
- package/deepEqual-yZXvaV2C.js +0 -413
- package/deepEqual-yZXvaV2C.js.map +0 -1
- package/extensions-0SFbU9FH.js +0 -2032
- package/extensions-0SFbU9FH.js.map +0 -1
- package/fullScreenTriangle-MdLGaAMR.js +0 -543
- package/fullScreenTriangle-MdLGaAMR.js.map +0 -1
- package/index.d.ts.map +0 -1
- package/index.js.map +0 -1
- package/indexNamedExports-Cdy7USiY.d.ts +0 -5696
- package/indexNamedExports-Cdy7USiY.d.ts.map +0 -1
- package/operators-HTxa_0k9.js +0 -4156
- package/operators-HTxa_0k9.js.map +0 -1
- package/std/index.d.ts.map +0 -1
- package/std/index.js.map +0 -1
- package/texture-Dg5ybJro.js.map +0 -1
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { $internal } from "../../shared/symbols.js";
|
|
2
|
+
import { setName } from "../../shared/meta.js";
|
|
3
|
+
|
|
4
|
+
//#region src/core/querySet/querySet.ts
|
|
5
|
+
function INTERNAL_createQuerySet(group, type, count, rawQuerySet) {
|
|
6
|
+
return new TgpuQuerySetImpl(group, type, count, rawQuerySet);
|
|
7
|
+
}
|
|
8
|
+
function isQuerySet(value) {
|
|
9
|
+
const maybe = value;
|
|
10
|
+
return maybe?.resourceType === "query-set" && !!maybe[$internal];
|
|
11
|
+
}
|
|
12
|
+
var TgpuQuerySetImpl = class {
|
|
13
|
+
resourceType = "query-set";
|
|
14
|
+
#device;
|
|
15
|
+
_querySet = null;
|
|
16
|
+
_ownQuerySet;
|
|
17
|
+
_destroyed = false;
|
|
18
|
+
_available = true;
|
|
19
|
+
_readBuffer = null;
|
|
20
|
+
_resolveBuffer = null;
|
|
21
|
+
constructor(root, type, count, rawQuerySet) {
|
|
22
|
+
this.type = type;
|
|
23
|
+
this.count = count;
|
|
24
|
+
this.rawQuerySet = rawQuerySet;
|
|
25
|
+
this.#device = root.device;
|
|
26
|
+
this._ownQuerySet = !rawQuerySet;
|
|
27
|
+
this._querySet = rawQuerySet || null;
|
|
28
|
+
}
|
|
29
|
+
get querySet() {
|
|
30
|
+
if (this._destroyed) throw new Error("This QuerySet has been destroyed.");
|
|
31
|
+
if (this.rawQuerySet) return this.rawQuerySet;
|
|
32
|
+
if (this._querySet) return this._querySet;
|
|
33
|
+
this._querySet = this.#device.createQuerySet({
|
|
34
|
+
type: this.type,
|
|
35
|
+
count: this.count
|
|
36
|
+
});
|
|
37
|
+
return this._querySet;
|
|
38
|
+
}
|
|
39
|
+
get destroyed() {
|
|
40
|
+
return this._destroyed;
|
|
41
|
+
}
|
|
42
|
+
get available() {
|
|
43
|
+
return this._available;
|
|
44
|
+
}
|
|
45
|
+
get [$internal]() {
|
|
46
|
+
const self = this;
|
|
47
|
+
return {
|
|
48
|
+
get readBuffer() {
|
|
49
|
+
if (!self._readBuffer) self._readBuffer = self.#device.createBuffer({
|
|
50
|
+
size: self.count * BigUint64Array.BYTES_PER_ELEMENT,
|
|
51
|
+
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
|
52
|
+
});
|
|
53
|
+
return self._readBuffer;
|
|
54
|
+
},
|
|
55
|
+
get resolveBuffer() {
|
|
56
|
+
if (!self._resolveBuffer) self._resolveBuffer = self.#device.createBuffer({
|
|
57
|
+
size: self.count * BigUint64Array.BYTES_PER_ELEMENT,
|
|
58
|
+
usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.COPY_SRC
|
|
59
|
+
});
|
|
60
|
+
return self._resolveBuffer;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
$name(label) {
|
|
65
|
+
setName(this, label);
|
|
66
|
+
if (this._querySet) this._querySet.label = label;
|
|
67
|
+
return this;
|
|
68
|
+
}
|
|
69
|
+
resolve() {
|
|
70
|
+
if (this._destroyed) throw new Error("This QuerySet has been destroyed.");
|
|
71
|
+
if (!this._available) throw new Error("This QuerySet is busy resolving or reading.");
|
|
72
|
+
const commandEncoder = this.#device.createCommandEncoder();
|
|
73
|
+
commandEncoder.resolveQuerySet(this.querySet, 0, this.count, this[$internal].resolveBuffer, 0);
|
|
74
|
+
this.#device.queue.submit([commandEncoder.finish()]);
|
|
75
|
+
}
|
|
76
|
+
async read() {
|
|
77
|
+
if (!this._resolveBuffer) throw new Error("QuerySet must be resolved before reading.");
|
|
78
|
+
this._available = false;
|
|
79
|
+
try {
|
|
80
|
+
const commandEncoder = this.#device.createCommandEncoder();
|
|
81
|
+
commandEncoder.copyBufferToBuffer(this[$internal].resolveBuffer, 0, this[$internal].readBuffer, 0, this.count * BigUint64Array.BYTES_PER_ELEMENT);
|
|
82
|
+
this.#device.queue.submit([commandEncoder.finish()]);
|
|
83
|
+
const readBuffer = this[$internal].readBuffer;
|
|
84
|
+
await readBuffer.mapAsync(GPUMapMode.READ);
|
|
85
|
+
const data = new BigUint64Array(readBuffer.getMappedRange().slice());
|
|
86
|
+
readBuffer.unmap();
|
|
87
|
+
return Array.from(data);
|
|
88
|
+
} finally {
|
|
89
|
+
this._available = true;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
destroy() {
|
|
93
|
+
if (this._destroyed) return;
|
|
94
|
+
this._destroyed = true;
|
|
95
|
+
if (this._querySet && this._ownQuerySet) this._querySet.destroy();
|
|
96
|
+
this._readBuffer?.destroy();
|
|
97
|
+
this._resolveBuffer?.destroy();
|
|
98
|
+
this._readBuffer = this._resolveBuffer = null;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
//#endregion
|
|
103
|
+
export { INTERNAL_createQuerySet, isQuerySet };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { $gpuValueOf } from "../../shared/symbols.js";
|
|
2
|
+
import { Origin } from "../../data/snippet.js";
|
|
3
|
+
import { BaseData } from "../../data/wgslTypes.js";
|
|
4
|
+
import { InferGPU } from "../../shared/repr.js";
|
|
5
|
+
import { AnyData } from "../../data/dataTypes.js";
|
|
6
|
+
|
|
7
|
+
//#region src/core/rawCodeSnippet/tgpuRawCodeSnippet.d.ts
|
|
8
|
+
/**
|
|
9
|
+
* Extra declaration that will be included in final WGSL code
|
|
10
|
+
* when resolving objects that use it.
|
|
11
|
+
*/
|
|
12
|
+
interface TgpuRawCodeSnippet<TDataType extends BaseData> {
|
|
13
|
+
$: InferGPU<TDataType>;
|
|
14
|
+
value: InferGPU<TDataType>;
|
|
15
|
+
readonly [$gpuValueOf]: InferGPU<TDataType>;
|
|
16
|
+
$uses(dependencyMap: Record<string, unknown>): this;
|
|
17
|
+
}
|
|
18
|
+
type RawCodeSnippetOrigin = Exclude<Origin, 'function' | 'this-function' | 'argument' | 'constant-ref'>;
|
|
19
|
+
/**
|
|
20
|
+
* An advanced API that creates a typed shader expression which
|
|
21
|
+
* can be injected into the final shader bundle upon use.
|
|
22
|
+
*
|
|
23
|
+
* @param expression The code snippet that will be injected in place of `foo.$`
|
|
24
|
+
* @param type The type of the expression
|
|
25
|
+
* @param [origin='runtime'] Where the value originates from.
|
|
26
|
+
*
|
|
27
|
+
* **-- Which origin to choose?**
|
|
28
|
+
*
|
|
29
|
+
* Usually 'runtime' (the default) is a safe bet, but if you're sure that the expression or
|
|
30
|
+
* computation is constant (either a reference to a constant, a numeric literal,
|
|
31
|
+
* or an operation on constants), then pass 'constant' as it might lead to better
|
|
32
|
+
* optimizations.
|
|
33
|
+
*
|
|
34
|
+
* If what the expression is a direct reference to an existing value (e.g. a uniform, a
|
|
35
|
+
* storage binding, ...), then choose from 'uniform', 'mutable', 'readonly', 'workgroup',
|
|
36
|
+
* 'private' or 'handle' depending on the address space of the referred value.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* // An identifier that we know will be in the
|
|
41
|
+
* // final shader bundle, but we cannot
|
|
42
|
+
* // refer to it in any other way.
|
|
43
|
+
* const existingGlobal = tgpu['~unstable']
|
|
44
|
+
* .rawCodeSnippet('EXISTING_GLOBAL', d.f32, 'constant');
|
|
45
|
+
*
|
|
46
|
+
* const foo = () => {
|
|
47
|
+
* 'use gpu';
|
|
48
|
+
* return existingGlobal.$ * 2;
|
|
49
|
+
* };
|
|
50
|
+
*
|
|
51
|
+
* const wgsl = tgpu.resolve([foo]);
|
|
52
|
+
* // fn foo() -> f32 {
|
|
53
|
+
* // return EXISTING_GLOBAL * 2;
|
|
54
|
+
* // }
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
declare function rawCodeSnippet<TDataType extends AnyData>(expression: string, type: TDataType, origin?: RawCodeSnippetOrigin | undefined): TgpuRawCodeSnippet<TDataType>;
|
|
58
|
+
//#endregion
|
|
59
|
+
export { RawCodeSnippetOrigin, TgpuRawCodeSnippet, rawCodeSnippet };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { $gpuValueOf, $internal, $ownSnippet, $resolve } from "../../shared/symbols.js";
|
|
2
|
+
import { snip } from "../../data/snippet.js";
|
|
3
|
+
import { inCodegenMode } from "../../execMode.js";
|
|
4
|
+
import { valueProxyHandler } from "../valueProxyUtils.js";
|
|
5
|
+
import { applyExternals, replaceExternalsInWgsl } from "../resolve/externals.js";
|
|
6
|
+
|
|
7
|
+
//#region src/core/rawCodeSnippet/tgpuRawCodeSnippet.ts
|
|
8
|
+
/**
|
|
9
|
+
* An advanced API that creates a typed shader expression which
|
|
10
|
+
* can be injected into the final shader bundle upon use.
|
|
11
|
+
*
|
|
12
|
+
* @param expression The code snippet that will be injected in place of `foo.$`
|
|
13
|
+
* @param type The type of the expression
|
|
14
|
+
* @param [origin='runtime'] Where the value originates from.
|
|
15
|
+
*
|
|
16
|
+
* **-- Which origin to choose?**
|
|
17
|
+
*
|
|
18
|
+
* Usually 'runtime' (the default) is a safe bet, but if you're sure that the expression or
|
|
19
|
+
* computation is constant (either a reference to a constant, a numeric literal,
|
|
20
|
+
* or an operation on constants), then pass 'constant' as it might lead to better
|
|
21
|
+
* optimizations.
|
|
22
|
+
*
|
|
23
|
+
* If what the expression is a direct reference to an existing value (e.g. a uniform, a
|
|
24
|
+
* storage binding, ...), then choose from 'uniform', 'mutable', 'readonly', 'workgroup',
|
|
25
|
+
* 'private' or 'handle' depending on the address space of the referred value.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* // An identifier that we know will be in the
|
|
30
|
+
* // final shader bundle, but we cannot
|
|
31
|
+
* // refer to it in any other way.
|
|
32
|
+
* const existingGlobal = tgpu['~unstable']
|
|
33
|
+
* .rawCodeSnippet('EXISTING_GLOBAL', d.f32, 'constant');
|
|
34
|
+
*
|
|
35
|
+
* const foo = () => {
|
|
36
|
+
* 'use gpu';
|
|
37
|
+
* return existingGlobal.$ * 2;
|
|
38
|
+
* };
|
|
39
|
+
*
|
|
40
|
+
* const wgsl = tgpu.resolve([foo]);
|
|
41
|
+
* // fn foo() -> f32 {
|
|
42
|
+
* // return EXISTING_GLOBAL * 2;
|
|
43
|
+
* // }
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
function rawCodeSnippet(expression, type, origin = "runtime") {
|
|
47
|
+
return new TgpuRawCodeSnippetImpl(expression, type, origin);
|
|
48
|
+
}
|
|
49
|
+
var TgpuRawCodeSnippetImpl = class {
|
|
50
|
+
[$internal];
|
|
51
|
+
dataType;
|
|
52
|
+
origin;
|
|
53
|
+
#expression;
|
|
54
|
+
#externalsToApply;
|
|
55
|
+
constructor(expression, type, origin) {
|
|
56
|
+
this[$internal] = true;
|
|
57
|
+
this.dataType = type;
|
|
58
|
+
this.origin = origin;
|
|
59
|
+
this.#expression = expression;
|
|
60
|
+
this.#externalsToApply = [];
|
|
61
|
+
}
|
|
62
|
+
$uses(dependencyMap) {
|
|
63
|
+
this.#externalsToApply.push(dependencyMap);
|
|
64
|
+
return this;
|
|
65
|
+
}
|
|
66
|
+
[$resolve](ctx) {
|
|
67
|
+
const externalMap = {};
|
|
68
|
+
for (const externals of this.#externalsToApply) applyExternals(externalMap, externals);
|
|
69
|
+
return snip(replaceExternalsInWgsl(ctx, externalMap, this.#expression), this.dataType, this.origin);
|
|
70
|
+
}
|
|
71
|
+
toString() {
|
|
72
|
+
return `raw(${String(this.dataType)}): "${this.#expression}"`;
|
|
73
|
+
}
|
|
74
|
+
get [$gpuValueOf]() {
|
|
75
|
+
const dataType = this.dataType;
|
|
76
|
+
const origin = this.origin;
|
|
77
|
+
return new Proxy({
|
|
78
|
+
[$internal]: true,
|
|
79
|
+
get [$ownSnippet]() {
|
|
80
|
+
return snip(this, dataType, origin);
|
|
81
|
+
},
|
|
82
|
+
[$resolve]: (ctx) => ctx.resolve(this),
|
|
83
|
+
toString: () => `raw(${String(this.dataType)}): "${this.#expression}".$`
|
|
84
|
+
}, valueProxyHandler);
|
|
85
|
+
}
|
|
86
|
+
get $() {
|
|
87
|
+
if (!inCodegenMode()) throw new Error("Raw code snippets can only be used on the GPU.");
|
|
88
|
+
return this[$gpuValueOf];
|
|
89
|
+
}
|
|
90
|
+
get value() {
|
|
91
|
+
return this.$;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
//#endregion
|
|
96
|
+
export { rawCodeSnippet };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import "../../types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/core/resolve/externals.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* A key-value mapping where keys represent identifiers within shader code,
|
|
6
|
+
* and values can be any type that can be resolved to a code string.
|
|
7
|
+
*/
|
|
8
|
+
type ExternalMap = Record<string, unknown>;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { ExternalMap };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { getName, hasTinyestMetadata, setName } from "../../shared/meta.js";
|
|
2
|
+
import { isWgslStruct } from "../../data/wgslTypes.js";
|
|
3
|
+
import { isLooseData } from "../../data/dataTypes.js";
|
|
4
|
+
import { isWgsl } from "../../types.js";
|
|
5
|
+
|
|
6
|
+
//#region src/core/resolve/externals.ts
|
|
7
|
+
/**
|
|
8
|
+
* Merges two external maps into one. If a key is present in both maps, the value from the new map is used.
|
|
9
|
+
* If the external value is a namable object, it is given a name if it does not already have one.
|
|
10
|
+
* @param existing - The existing external map.
|
|
11
|
+
* @param newExternals - The new external map.
|
|
12
|
+
*/
|
|
13
|
+
function applyExternals(existing, newExternals) {
|
|
14
|
+
for (const [key, value] of Object.entries(newExternals)) {
|
|
15
|
+
existing[key] = value;
|
|
16
|
+
if (value && (typeof value === "object" || typeof value === "function") && getName(value) === void 0) setName(value, key);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function addArgTypesToExternals(implementation, argTypes, applyExternals) {
|
|
20
|
+
const argTypeNames = [...implementation.matchAll(/:\s*(?<arg>.*?)\s*[,)]/g)].map((found) => found ? found[1] : void 0);
|
|
21
|
+
applyExternals(Object.fromEntries(argTypes.flatMap((argType, i) => {
|
|
22
|
+
const argTypeName = argTypeNames ? argTypeNames[i] : void 0;
|
|
23
|
+
return isWgslStruct(argType) && argTypeName !== void 0 ? [[argTypeName, argType]] : [];
|
|
24
|
+
})));
|
|
25
|
+
}
|
|
26
|
+
function addReturnTypeToExternals(implementation, returnType, applyExternals) {
|
|
27
|
+
const matched = implementation.match(/->\s(?<output>[\w\d_]+)\s{/);
|
|
28
|
+
const outputName = matched ? matched[1]?.trim() : void 0;
|
|
29
|
+
if (isWgslStruct(returnType) && outputName && !/\s/g.test(outputName)) applyExternals({ [outputName]: returnType });
|
|
30
|
+
}
|
|
31
|
+
function identifierRegex(name) {
|
|
32
|
+
return new RegExp(`(?<![\\w\\$_.])${name.replaceAll(".", "\\.").replaceAll("$", "\\$")}(?![\\w\\$_])`, "g");
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Replaces all occurrences of external names in WGSL code with their resolved values.
|
|
36
|
+
* It adds all necessary definitions to the resolution context.
|
|
37
|
+
* @param ctx - The resolution context.
|
|
38
|
+
* @param externalMap - The external map.
|
|
39
|
+
* @param wgsl - The WGSL code.
|
|
40
|
+
*
|
|
41
|
+
* @returns The WGSL code with all external names replaced with their resolved values.
|
|
42
|
+
*/
|
|
43
|
+
function replaceExternalsInWgsl(ctx, externalMap, wgsl) {
|
|
44
|
+
return Object.entries(externalMap).reduce((acc, [externalName, external]) => {
|
|
45
|
+
const externalRegex = identifierRegex(externalName);
|
|
46
|
+
if (wgsl && externalName !== "Out" && externalName !== "In" && !externalRegex.test(wgsl)) console.warn(`The external '${externalName}' wasn't used in the resolved template.`);
|
|
47
|
+
if (isWgsl(external) || isLooseData(external) || hasTinyestMetadata(external)) return acc.replaceAll(externalRegex, ctx.resolve(external).value);
|
|
48
|
+
if (external !== null && typeof external === "object") {
|
|
49
|
+
const foundProperties = [...wgsl.matchAll(new RegExp(`${externalName.replaceAll(".", "\\.").replaceAll("$", "\\$")}\\.(?<prop>.*?)(?![\\w\\$_])`, "g"))].map((found) => found[1]);
|
|
50
|
+
return [...new Set(foundProperties)].reduce((innerAcc, prop) => prop && prop in external ? replaceExternalsInWgsl(ctx, { [`${externalName}.${prop}`]: external[prop] }, innerAcc) : innerAcc, acc);
|
|
51
|
+
}
|
|
52
|
+
console.warn(`During resolution, the external '${externalName}' has been omitted. Only TGPU resources, 'use gpu' functions, primitives, and plain JS objects can be used as externals.`);
|
|
53
|
+
return acc;
|
|
54
|
+
}, wgsl);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//#endregion
|
|
58
|
+
export { addArgTypesToExternals, addReturnTypeToExternals, applyExternals, replaceExternalsInWgsl };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { $internal } from "../../shared/symbols.js";
|
|
2
|
+
import { ResolvedSnippet } from "../../data/snippet.js";
|
|
3
|
+
import { ShelllessRepository } from "../../tgsl/shellless.js";
|
|
4
|
+
import { TgpuLazy, TgpuSlot } from "../slot/slotTypes.js";
|
|
5
|
+
import { NameRegistry } from "../../nameRegistry.js";
|
|
6
|
+
|
|
7
|
+
//#region src/core/resolve/namespace.d.ts
|
|
8
|
+
type SlotToValueMap = Map<TgpuSlot<unknown>, unknown>;
|
|
9
|
+
interface NamespaceInternal {
|
|
10
|
+
readonly nameRegistry: NameRegistry;
|
|
11
|
+
readonly shelllessRepo: ShelllessRepository;
|
|
12
|
+
memoizedResolves: WeakMap<object, {
|
|
13
|
+
slotToValueMap: SlotToValueMap;
|
|
14
|
+
result: ResolvedSnippet;
|
|
15
|
+
}[]>;
|
|
16
|
+
memoizedLazy: WeakMap<TgpuLazy<unknown>, {
|
|
17
|
+
slotToValueMap: SlotToValueMap;
|
|
18
|
+
result: unknown;
|
|
19
|
+
}[]>;
|
|
20
|
+
listeners: { [K in keyof NamespaceEventMap]: Set<(event: NamespaceEventMap[K]) => void> };
|
|
21
|
+
}
|
|
22
|
+
type NamespaceEventMap = {
|
|
23
|
+
name: {
|
|
24
|
+
target: object;
|
|
25
|
+
name: string;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
type DetachListener = () => void;
|
|
29
|
+
interface Namespace {
|
|
30
|
+
readonly [$internal]: NamespaceInternal;
|
|
31
|
+
on<TEvent extends keyof NamespaceEventMap>(event: TEvent, listener: (event: NamespaceEventMap[TEvent]) => void): DetachListener;
|
|
32
|
+
}
|
|
33
|
+
interface NamespaceOptions {
|
|
34
|
+
names?: 'random' | 'strict' | undefined;
|
|
35
|
+
}
|
|
36
|
+
declare function namespace(options?: NamespaceOptions): Namespace;
|
|
37
|
+
//#endregion
|
|
38
|
+
export { Namespace, namespace };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { $internal } from "../../shared/symbols.js";
|
|
2
|
+
import { getName } from "../../shared/meta.js";
|
|
3
|
+
import { RandomNameRegistry, StrictNameRegistry } from "../../nameRegistry.js";
|
|
4
|
+
import { ShelllessRepository } from "../../tgsl/shellless.js";
|
|
5
|
+
|
|
6
|
+
//#region src/core/resolve/namespace.ts
|
|
7
|
+
var NamespaceImpl = class {
|
|
8
|
+
[$internal];
|
|
9
|
+
constructor(nameRegistry) {
|
|
10
|
+
this[$internal] = {
|
|
11
|
+
nameRegistry,
|
|
12
|
+
shelllessRepo: new ShelllessRepository(),
|
|
13
|
+
memoizedResolves: /* @__PURE__ */ new WeakMap(),
|
|
14
|
+
memoizedLazy: /* @__PURE__ */ new WeakMap(),
|
|
15
|
+
listeners: { name: /* @__PURE__ */ new Set() }
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
on(event, listener) {
|
|
19
|
+
if (event === "name") {
|
|
20
|
+
const listeners = this[$internal].listeners.name;
|
|
21
|
+
listeners.add(listener);
|
|
22
|
+
return () => listeners.delete(listener);
|
|
23
|
+
}
|
|
24
|
+
throw new Error(`Unsupported event: ${event}`);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
function getUniqueName(namespace, resource) {
|
|
28
|
+
const name = namespace.nameRegistry.makeUnique(getName(resource), true);
|
|
29
|
+
for (const listener of namespace.listeners.name) listener({
|
|
30
|
+
target: resource,
|
|
31
|
+
name
|
|
32
|
+
});
|
|
33
|
+
return name;
|
|
34
|
+
}
|
|
35
|
+
function namespace(options) {
|
|
36
|
+
const { names = "strict" } = options ?? {};
|
|
37
|
+
return new NamespaceImpl(names === "strict" ? new StrictNameRegistry() : new RandomNameRegistry());
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
//#endregion
|
|
41
|
+
export { getUniqueName, namespace };
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { $internal } from "../../shared/symbols.js";
|
|
2
|
+
import { isLooseData } from "../../data/dataTypes.js";
|
|
3
|
+
import { assertExhaustive } from "../../shared/utilityTypes.js";
|
|
4
|
+
import { formatToWGSLType } from "../../data/vertexFormatData.js";
|
|
5
|
+
import { getAttributesString } from "../../data/attributes.js";
|
|
6
|
+
import { isWgslComparisonSampler, isWgslSampler } from "../../data/sampler.js";
|
|
7
|
+
import { accessModeMap, isWgslStorageTexture, isWgslTexture } from "../../data/texture.js";
|
|
8
|
+
import { isAttribute } from "../vertexLayout/connectAttributesToShader.js";
|
|
9
|
+
|
|
10
|
+
//#region src/core/resolve/resolveData.ts
|
|
11
|
+
/**
|
|
12
|
+
* Schemas for which their `type` property directly
|
|
13
|
+
* translates to the resulting WGSL code.
|
|
14
|
+
*/
|
|
15
|
+
const identityTypes = [
|
|
16
|
+
"bool",
|
|
17
|
+
"f32",
|
|
18
|
+
"f16",
|
|
19
|
+
"i32",
|
|
20
|
+
"u32",
|
|
21
|
+
"vec2f",
|
|
22
|
+
"vec3f",
|
|
23
|
+
"vec4f",
|
|
24
|
+
"vec2h",
|
|
25
|
+
"vec3h",
|
|
26
|
+
"vec4h",
|
|
27
|
+
"vec2i",
|
|
28
|
+
"vec3i",
|
|
29
|
+
"vec4i",
|
|
30
|
+
"vec2u",
|
|
31
|
+
"vec3u",
|
|
32
|
+
"vec4u",
|
|
33
|
+
"vec2<bool>",
|
|
34
|
+
"vec3<bool>",
|
|
35
|
+
"vec4<bool>",
|
|
36
|
+
"mat2x2f",
|
|
37
|
+
"mat3x3f",
|
|
38
|
+
"mat4x4f",
|
|
39
|
+
"texture_external"
|
|
40
|
+
];
|
|
41
|
+
function isIdentityType(data) {
|
|
42
|
+
return identityTypes.includes(data.type);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Resolves a single property of a struct.
|
|
46
|
+
* @param ctx - The resolution context.
|
|
47
|
+
* @param key - The key of the property.
|
|
48
|
+
* @param property - The property itself.
|
|
49
|
+
*
|
|
50
|
+
* @returns The resolved property string.
|
|
51
|
+
*/
|
|
52
|
+
function resolveStructProperty(ctx, [key, property]) {
|
|
53
|
+
return ` ${getAttributesString(property)}${key}: ${ctx.resolve(property).value},\n`;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Resolves a struct and adds its declaration to the resolution context.
|
|
57
|
+
* @param ctx - The resolution context.
|
|
58
|
+
* @param struct - The struct to resolve.
|
|
59
|
+
*
|
|
60
|
+
* @returns The resolved struct name.
|
|
61
|
+
*/
|
|
62
|
+
function resolveStruct(ctx, struct) {
|
|
63
|
+
if (struct[$internal].isAbstruct) throw new Error("Cannot resolve abstract struct types to WGSL.");
|
|
64
|
+
const id = ctx.getUniqueName(struct);
|
|
65
|
+
ctx.addDeclaration(`\
|
|
66
|
+
struct ${id} {
|
|
67
|
+
${Object.entries(struct.propTypes).map((prop) => resolveStructProperty(ctx, prop)).join("")}\
|
|
68
|
+
}`);
|
|
69
|
+
return id;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Resolves an unstruct (struct that does not align data by default) to its struct data counterpart.
|
|
73
|
+
* @param ctx - The resolution context.
|
|
74
|
+
* @param unstruct - The unstruct to resolve.
|
|
75
|
+
*
|
|
76
|
+
* @returns The resolved unstruct name.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```ts
|
|
80
|
+
* resolveUnstruct(ctx, {
|
|
81
|
+
* uv: d.float16x2, // -> d.vec2f after resolution
|
|
82
|
+
* color: d.snorm8x4, -> d.vec4f after resolution
|
|
83
|
+
* });
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
function resolveUnstruct(ctx, unstruct) {
|
|
87
|
+
const id = ctx.getUniqueName(unstruct);
|
|
88
|
+
ctx.addDeclaration(`\
|
|
89
|
+
struct ${id} {
|
|
90
|
+
${Object.entries(unstruct.propTypes).map((prop) => isAttribute(prop[1]) ? resolveStructProperty(ctx, [prop[0], formatToWGSLType[prop[1].format]]) : resolveStructProperty(ctx, prop)).join("")}
|
|
91
|
+
}`);
|
|
92
|
+
return id;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Resolves an array.
|
|
96
|
+
* @param ctx - The resolution context.
|
|
97
|
+
* @param array - The array to resolve.
|
|
98
|
+
*
|
|
99
|
+
* @returns The resolved array name along with its element type and count (if not runtime-sized).
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```ts
|
|
103
|
+
* resolveArray(ctx, d.arrayOf(d.u32, 0)); // 'array<u32>' (not a real pattern, a function is preferred)
|
|
104
|
+
* resolveArray(ctx, d.arrayOf(d.u32, 5)); // 'array<u32, 5>'
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
function resolveArray(ctx, array) {
|
|
108
|
+
const element = ctx.resolve(array.elementType).value;
|
|
109
|
+
return array.elementCount === 0 ? `array<${element}>` : `array<${element}, ${array.elementCount}>`;
|
|
110
|
+
}
|
|
111
|
+
function resolveDisarray(ctx, disarray) {
|
|
112
|
+
const element = ctx.resolve(isAttribute(disarray.elementType) ? formatToWGSLType[disarray.elementType.format] : disarray.elementType).value;
|
|
113
|
+
return disarray.elementCount === 0 ? `array<${element}>` : `array<${element}, ${disarray.elementCount}>`;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Resolves a WGSL data-type schema to a string.
|
|
117
|
+
* @param ctx - The resolution context.
|
|
118
|
+
* @param data - The data-type to resolve.
|
|
119
|
+
*
|
|
120
|
+
* @returns The resolved data-type string.
|
|
121
|
+
*/
|
|
122
|
+
function resolveData(ctx, data) {
|
|
123
|
+
if (isLooseData(data)) {
|
|
124
|
+
if (data.type === "unstruct") return resolveUnstruct(ctx, data);
|
|
125
|
+
if (data.type === "disarray") return resolveDisarray(ctx, data);
|
|
126
|
+
if (data.type === "loose-decorated") return ctx.resolve(isAttribute(data.inner) ? formatToWGSLType[data.inner.format] : data.inner).value;
|
|
127
|
+
return ctx.resolve(formatToWGSLType[data.type]).value;
|
|
128
|
+
}
|
|
129
|
+
if (isIdentityType(data)) return data.type;
|
|
130
|
+
if (data.type === "struct") return resolveStruct(ctx, data);
|
|
131
|
+
if (data.type === "array") return resolveArray(ctx, data);
|
|
132
|
+
if (data.type === "atomic") return `atomic<${resolveData(ctx, data.inner)}>`;
|
|
133
|
+
if (data.type === "decorated") return ctx.resolve(data.inner).value;
|
|
134
|
+
if (data.type === "ptr") {
|
|
135
|
+
if (data.addressSpace === "storage") return `ptr<storage, ${ctx.resolve(data.inner).value}, ${data.access === "read-write" ? "read_write" : data.access}>`;
|
|
136
|
+
return `ptr<${data.addressSpace}, ${ctx.resolve(data.inner).value}>`;
|
|
137
|
+
}
|
|
138
|
+
if (data.type === "abstractInt" || data.type === "abstractFloat" || data.type === "void" || data.type === "u16") throw new Error(`${data.type} has no representation in WGSL`);
|
|
139
|
+
if (isWgslStorageTexture(data)) return `${data.type}<${data.format}, ${accessModeMap[data.access]}>`;
|
|
140
|
+
if (isWgslTexture(data)) return data.type.startsWith("texture_depth") ? data.type : `${data.type}<${data.sampleType.type}>`;
|
|
141
|
+
if (isWgslComparisonSampler(data) || isWgslSampler(data)) return data.type;
|
|
142
|
+
assertExhaustive(data, "resolveData");
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
//#endregion
|
|
146
|
+
export { resolveData };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { isSnippet } from "../../data/snippet.js";
|
|
2
|
+
import { getResolutionCtx } from "../../execMode.js";
|
|
3
|
+
|
|
4
|
+
//#region src/core/resolve/stitch.ts
|
|
5
|
+
/**
|
|
6
|
+
* "The reverse of snipping"
|
|
7
|
+
* Injects resolved snippets into a template string.
|
|
8
|
+
*/
|
|
9
|
+
function stitch(strings, ...snippets) {
|
|
10
|
+
const ctx = getResolutionCtx();
|
|
11
|
+
function resolveSnippet(maybeSnippet) {
|
|
12
|
+
return isSnippet(maybeSnippet) ? ctx.resolve(maybeSnippet.value, maybeSnippet.dataType).value : maybeSnippet;
|
|
13
|
+
}
|
|
14
|
+
let result = "";
|
|
15
|
+
for (let i = 0; i < strings.length; ++i) {
|
|
16
|
+
result += strings[i];
|
|
17
|
+
const snippet = snippets[i];
|
|
18
|
+
if (Array.isArray(snippet)) result += snippet.filter((s) => s !== void 0).map(resolveSnippet).join(", ");
|
|
19
|
+
else if (snippet) result += resolveSnippet(snippet);
|
|
20
|
+
}
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
export { stitch };
|