typegpu 0.10.1 → 0.11.0-rc.1

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 (273) hide show
  1. package/_virtual/_rolldown/runtime.js +13 -0
  2. package/builtin.d.ts +50 -0
  3. package/builtin.js +35 -0
  4. package/common/fullScreenTriangle.d.ts +22 -0
  5. package/common/fullScreenTriangle.js +34 -0
  6. package/common/index.d.ts +4 -4
  7. package/common/index.js +8 -7
  8. package/common/writeSoA.d.ts +16 -0
  9. package/common/writeSoA.js +90 -0
  10. package/core/buffer/buffer.d.ts +79 -0
  11. package/core/buffer/buffer.js +246 -0
  12. package/core/buffer/bufferShorthand.d.ts +48 -0
  13. package/core/buffer/bufferShorthand.js +53 -0
  14. package/core/buffer/bufferUsage.d.ts +43 -0
  15. package/core/buffer/bufferUsage.js +165 -0
  16. package/core/constant/tgpuConstant.d.ts +29 -0
  17. package/core/constant/tgpuConstant.js +68 -0
  18. package/core/declare/tgpuDeclare.d.ts +18 -0
  19. package/core/declare/tgpuDeclare.js +39 -0
  20. package/core/function/autoIO.d.ts +38 -0
  21. package/core/function/autoIO.js +85 -0
  22. package/core/function/comptime.d.ts +39 -0
  23. package/core/function/comptime.js +49 -0
  24. package/core/function/createCallableSchema.js +40 -0
  25. package/core/function/dualImpl.js +52 -0
  26. package/core/function/entryInputRouter.js +39 -0
  27. package/core/function/extractArgs.js +204 -0
  28. package/core/function/fnCore.js +90 -0
  29. package/core/function/fnTypes.d.ts +40 -0
  30. package/core/function/ioSchema.d.ts +10 -0
  31. package/core/function/ioSchema.js +51 -0
  32. package/core/function/shelllessImpl.d.ts +28 -0
  33. package/core/function/shelllessImpl.js +21 -0
  34. package/core/function/templateUtils.js +12 -0
  35. package/core/function/tgpuComputeFn.d.ts +48 -0
  36. package/core/function/tgpuComputeFn.js +55 -0
  37. package/core/function/tgpuFn.d.ts +52 -0
  38. package/core/function/tgpuFn.js +168 -0
  39. package/core/function/tgpuFragmentFn.d.ts +72 -0
  40. package/core/function/tgpuFragmentFn.js +63 -0
  41. package/core/function/tgpuVertexFn.d.ts +59 -0
  42. package/core/function/tgpuVertexFn.js +59 -0
  43. package/core/pipeline/applyPipelineState.js +35 -0
  44. package/core/pipeline/computePipeline.d.ts +54 -0
  45. package/core/pipeline/computePipeline.js +227 -0
  46. package/core/pipeline/connectAttachmentToShader.js +24 -0
  47. package/core/pipeline/connectTargetsToShader.js +27 -0
  48. package/core/pipeline/limitsOverflow.js +12 -0
  49. package/core/pipeline/pipelineUtils.js +29 -0
  50. package/core/pipeline/renderPipeline.d.ts +284 -0
  51. package/core/pipeline/renderPipeline.js +489 -0
  52. package/core/pipeline/timeable.d.ts +20 -0
  53. package/core/pipeline/timeable.js +55 -0
  54. package/core/pipeline/typeGuards.js +27 -0
  55. package/core/querySet/querySet.d.ts +20 -0
  56. package/core/querySet/querySet.js +104 -0
  57. package/core/rawCodeSnippet/tgpuRawCodeSnippet.d.ts +59 -0
  58. package/core/rawCodeSnippet/tgpuRawCodeSnippet.js +94 -0
  59. package/core/resolve/externals.d.ts +8 -0
  60. package/core/resolve/externals.js +56 -0
  61. package/core/resolve/namespace.d.ts +38 -0
  62. package/core/resolve/namespace.js +39 -0
  63. package/core/resolve/resolveData.js +144 -0
  64. package/core/resolve/stitch.js +23 -0
  65. package/core/resolve/tgpuResolve.d.ts +153 -0
  66. package/core/resolve/tgpuResolve.js +66 -0
  67. package/core/root/configurableImpl.js +17 -0
  68. package/core/root/init.d.ts +64 -0
  69. package/core/root/init.js +464 -0
  70. package/core/root/rootTypes.d.ts +642 -0
  71. package/core/sampler/sampler.d.ts +31 -0
  72. package/core/sampler/sampler.js +116 -0
  73. package/core/simulate/tgpuSimulate.d.ts +36 -0
  74. package/core/simulate/tgpuSimulate.js +74 -0
  75. package/core/slot/accessor.d.ts +9 -0
  76. package/core/slot/accessor.js +95 -0
  77. package/core/slot/internalSlots.js +5 -0
  78. package/core/slot/lazy.d.ts +6 -0
  79. package/core/slot/lazy.js +40 -0
  80. package/core/slot/slot.d.ts +6 -0
  81. package/core/slot/slot.js +39 -0
  82. package/core/slot/slotTypes.d.ts +92 -0
  83. package/core/slot/slotTypes.js +19 -0
  84. package/core/texture/externalTexture.d.ts +6 -0
  85. package/core/texture/externalTexture.js +47 -0
  86. package/core/texture/texture.d.ts +114 -0
  87. package/core/texture/texture.js +314 -0
  88. package/core/texture/textureFormats.d.ts +29 -0
  89. package/core/texture/textureFormats.js +97 -0
  90. package/core/texture/textureProps.d.ts +11 -0
  91. package/core/texture/textureUtils.js +222 -0
  92. package/core/texture/usageExtension.d.ts +21 -0
  93. package/core/texture/usageExtension.js +19 -0
  94. package/core/unroll/tgpuUnroll.d.ts +68 -0
  95. package/core/unroll/tgpuUnroll.js +94 -0
  96. package/core/valueProxyUtils.js +42 -0
  97. package/core/variable/tgpuVariable.d.ts +38 -0
  98. package/core/variable/tgpuVariable.js +99 -0
  99. package/core/vertexLayout/connectAttributesToShader.js +57 -0
  100. package/core/vertexLayout/vertexAttribute.d.ts +29 -0
  101. package/core/vertexLayout/vertexLayout.d.ts +19 -0
  102. package/core/vertexLayout/vertexLayout.js +103 -0
  103. package/data/alignIO.js +14 -0
  104. package/data/alignmentOf.d.ts +9 -0
  105. package/data/alignmentOf.js +86 -0
  106. package/data/array.d.ts +26 -0
  107. package/data/array.js +46 -0
  108. package/data/atomic.d.ts +15 -0
  109. package/data/atomic.js +24 -0
  110. package/data/attributes.d.ts +121 -0
  111. package/data/attributes.js +145 -0
  112. package/data/autoStruct.d.ts +1 -0
  113. package/data/autoStruct.js +81 -0
  114. package/data/compiledIO.js +228 -0
  115. package/data/dataIO.js +556 -0
  116. package/data/dataTypes.d.ts +115 -0
  117. package/data/dataTypes.js +100 -0
  118. package/data/deepEqual.d.ts +25 -0
  119. package/data/deepEqual.js +56 -0
  120. package/data/disarray.d.ts +32 -0
  121. package/data/disarray.js +50 -0
  122. package/data/getLongestContiguousPrefix.d.ts +9 -0
  123. package/data/getLongestContiguousPrefix.js +13 -0
  124. package/data/index.d.ts +26 -4
  125. package/data/index.js +36 -9
  126. package/data/instanceToSchema.d.ts +33 -0
  127. package/data/isContiguous.d.ts +9 -0
  128. package/data/isContiguous.js +13 -0
  129. package/data/matrix.d.ts +124 -0
  130. package/data/matrix.js +531 -0
  131. package/data/numberOps.js +23 -0
  132. package/data/numeric.d.ts +81 -0
  133. package/data/numeric.js +221 -0
  134. package/data/offsetUtils.d.ts +33 -0
  135. package/data/offsetUtils.js +165 -0
  136. package/data/offsets.js +34 -0
  137. package/data/partialIO.js +113 -0
  138. package/data/ptr.d.ts +11 -0
  139. package/data/ptr.js +44 -0
  140. package/data/ref.d.ts +34 -0
  141. package/data/ref.js +94 -0
  142. package/data/sampler.d.ts +107 -0
  143. package/data/sampler.js +24 -0
  144. package/data/schemaCallWrapper.js +30 -0
  145. package/data/schemaMemoryLayout.js +198 -0
  146. package/data/sizeOf.d.ts +9 -0
  147. package/data/sizeOf.js +13 -0
  148. package/data/snippet.d.ts +26 -0
  149. package/data/snippet.js +70 -0
  150. package/data/struct.d.ts +17 -0
  151. package/data/struct.js +44 -0
  152. package/data/texture.d.ts +292 -0
  153. package/{texture-BagDrrks.js → data/texture.js} +6 -5
  154. package/data/unstruct.d.ts +24 -0
  155. package/data/unstruct.js +41 -0
  156. package/data/vector.d.ts +191 -0
  157. package/data/vector.js +239 -0
  158. package/data/vectorImpl.js +515 -0
  159. package/data/vectorOps.js +681 -0
  160. package/data/vertexFormatData.d.ts +190 -0
  161. package/data/vertexFormatData.js +109 -0
  162. package/data/wgslTypes.d.ts +924 -0
  163. package/data/wgslTypes.js +222 -0
  164. package/errors.d.ts +44 -0
  165. package/errors.js +131 -0
  166. package/execMode.js +49 -0
  167. package/extension.d.ts +11 -0
  168. package/extension.js +16 -0
  169. package/getGPUValue.js +7 -0
  170. package/index.d.ts +42 -243
  171. package/index.js +21 -6320
  172. package/indexNamedExports.d.ts +40 -0
  173. package/mathUtils.js +12 -0
  174. package/memo.js +22 -0
  175. package/nameRegistry.d.ts +30 -0
  176. package/nameRegistry.js +447 -0
  177. package/package.js +4 -0
  178. package/package.json +26 -26
  179. package/resolutionCtx.d.ts +19 -0
  180. package/resolutionCtx.js +612 -0
  181. package/shared/env.js +12 -0
  182. package/shared/generators.js +13 -0
  183. package/shared/meta.d.ts +39 -0
  184. package/shared/meta.js +61 -0
  185. package/shared/repr.d.ts +138 -0
  186. package/shared/stringify.js +20 -0
  187. package/shared/symbols.d.ts +70 -0
  188. package/shared/symbols.js +48 -0
  189. package/shared/utilityTypes.d.ts +33 -0
  190. package/shared/utilityTypes.js +6 -0
  191. package/shared/vertexFormat.d.ts +70 -0
  192. package/shared/vertexFormat.js +63 -0
  193. package/std/array.d.ts +7 -0
  194. package/std/array.js +25 -0
  195. package/std/atomic.d.ts +19 -0
  196. package/std/atomic.js +111 -0
  197. package/std/bitcast.d.ts +10 -0
  198. package/std/bitcast.js +41 -0
  199. package/std/boolean.d.ts +141 -0
  200. package/std/boolean.js +299 -0
  201. package/std/derivative.d.ts +16 -0
  202. package/std/derivative.js +87 -0
  203. package/std/discard.d.ts +6 -0
  204. package/std/discard.js +14 -0
  205. package/std/extensions.d.ts +6 -0
  206. package/std/extensions.js +12 -0
  207. package/std/index.d.ts +17 -4
  208. package/std/index.js +21 -7
  209. package/std/matrix.d.ts +41 -0
  210. package/std/matrix.js +85 -0
  211. package/std/numeric.d.ts +200 -0
  212. package/std/numeric.js +845 -0
  213. package/std/operators.d.ts +56 -0
  214. package/std/operators.js +227 -0
  215. package/std/packing.d.ts +26 -0
  216. package/std/packing.js +84 -0
  217. package/std/range.d.ts +24 -0
  218. package/std/range.js +38 -0
  219. package/std/subgroup.d.ts +47 -0
  220. package/std/subgroup.js +218 -0
  221. package/std/texture.d.ts +117 -0
  222. package/std/texture.js +207 -0
  223. package/tgpu.js +42 -0
  224. package/tgpuBindGroupLayout.d.ts +161 -0
  225. package/tgpuBindGroupLayout.js +272 -0
  226. package/tgpuUnstable.d.ts +48 -0
  227. package/tgpuUnstable.js +64 -0
  228. package/tgsl/accessIndex.js +43 -0
  229. package/tgsl/accessProp.js +115 -0
  230. package/tgsl/consoleLog/deserializers.js +115 -0
  231. package/tgsl/consoleLog/logGenerator.js +84 -0
  232. package/tgsl/consoleLog/serializers.js +223 -0
  233. package/tgsl/consoleLog/types.d.ts +52 -0
  234. package/tgsl/consoleLog/types.js +11 -0
  235. package/tgsl/conversion.js +198 -0
  236. package/tgsl/forOfUtils.js +71 -0
  237. package/tgsl/generationHelpers.d.ts +37 -0
  238. package/tgsl/generationHelpers.js +67 -0
  239. package/tgsl/math.js +43 -0
  240. package/tgsl/shaderGenerator.d.ts +20 -0
  241. package/tgsl/shaderGenerator_members.d.ts +2 -0
  242. package/tgsl/shaderGenerator_members.js +6 -0
  243. package/tgsl/shellless.d.ts +11 -0
  244. package/tgsl/shellless.js +46 -0
  245. package/tgsl/wgslGenerator.d.ts +36 -0
  246. package/tgsl/wgslGenerator.js +639 -0
  247. package/types.d.ts +265 -0
  248. package/types.js +43 -0
  249. package/unwrapper.d.ts +27 -0
  250. package/wgslExtensions.d.ts +5 -0
  251. package/wgslExtensions.js +17 -0
  252. package/builtin-DdtWpk2t.js +0 -818
  253. package/builtin-DdtWpk2t.js.map +0 -1
  254. package/chunk-BYypO7fO.js +0 -18
  255. package/common/index.d.ts.map +0 -1
  256. package/common/index.js.map +0 -1
  257. package/data/index.d.ts.map +0 -1
  258. package/data/index.js.map +0 -1
  259. package/deepEqual-DQxK4vdp.js +0 -413
  260. package/deepEqual-DQxK4vdp.js.map +0 -1
  261. package/extensions-DIVuAfBM.js +0 -2032
  262. package/extensions-DIVuAfBM.js.map +0 -1
  263. package/fullScreenTriangle-CfFyQd_0.js +0 -543
  264. package/fullScreenTriangle-CfFyQd_0.js.map +0 -1
  265. package/index.d.ts.map +0 -1
  266. package/index.js.map +0 -1
  267. package/indexNamedExports-oL6tyaJ9.d.ts +0 -5697
  268. package/indexNamedExports-oL6tyaJ9.d.ts.map +0 -1
  269. package/operators-d-PMVTo7.js +0 -4158
  270. package/operators-d-PMVTo7.js.map +0 -1
  271. package/std/index.d.ts.map +0 -1
  272. package/std/index.js.map +0 -1
  273. package/texture-BagDrrks.js.map +0 -1
@@ -0,0 +1,222 @@
1
+ import { getEffectiveSampleTypes, getTextureFormatInfo } from "./textureFormats.js";
2
+ //#region src/core/texture/textureUtils.ts
3
+ function getImageSourceDimensions(source) {
4
+ const { videoWidth, videoHeight } = source;
5
+ if (videoWidth && videoHeight) return {
6
+ width: videoWidth,
7
+ height: videoHeight
8
+ };
9
+ const { naturalWidth, naturalHeight } = source;
10
+ if (naturalWidth && naturalHeight) return {
11
+ width: naturalWidth,
12
+ height: naturalHeight
13
+ };
14
+ const { codedWidth, codedHeight } = source;
15
+ if (codedWidth && codedHeight) return {
16
+ width: codedWidth,
17
+ height: codedHeight
18
+ };
19
+ const { width, height } = source;
20
+ if (width && height) return {
21
+ width,
22
+ height
23
+ };
24
+ throw new Error("Cannot determine dimensions of the provided image source.");
25
+ }
26
+ const FULLSCREEN_VERTEX_SHADER = `
27
+ struct VertexOutput {
28
+ @builtin(position) pos: vec4f,
29
+ @location(0) uv: vec2f,
30
+ }
31
+
32
+ @vertex
33
+ fn vs_main(@builtin(vertex_index) i: u32) -> VertexOutput {
34
+ const pos = array(vec2f(-1, -1), vec2f(3, -1), vec2f(-1, 3));
35
+ const uv = array(vec2f(0, 1), vec2f(2, 1), vec2f(0, -1));
36
+ return VertexOutput(vec4f(pos[i], 0, 1), uv[i]);
37
+ }`;
38
+ const SAMPLE_FRAGMENT_SHADER = `
39
+ @group(0) @binding(0) var src: texture_2d<f32>;
40
+ @group(0) @binding(1) var samp: sampler;
41
+
42
+ @fragment
43
+ fn fs_main(@location(0) uv: vec2f) -> @location(0) vec4f {
44
+ return textureSample(src, samp, uv);
45
+ }`;
46
+ const GATHER_FRAGMENT_SHADER = `
47
+ @group(0) @binding(0) var src: texture_2d<f32>;
48
+ @group(0) @binding(1) var samp: sampler;
49
+
50
+ @fragment
51
+ fn fs_main(@location(0) uv: vec2f) -> @location(0) vec4f {
52
+ let r = textureGather(0, src, samp, uv);
53
+ let g = textureGather(1, src, samp, uv);
54
+ let b = textureGather(2, src, samp, uv);
55
+ let a = textureGather(3, src, samp, uv);
56
+ return vec4f(dot(r, vec4f(0.25)), dot(g, vec4f(0.25)), dot(b, vec4f(0.25)), dot(a, vec4f(0.25)));
57
+ }`;
58
+ const blitCache = /* @__PURE__ */ new WeakMap();
59
+ function getOrCreateDeviceCache(device) {
60
+ let cache = blitCache.get(device);
61
+ if (!cache) {
62
+ cache = {
63
+ vertexModule: device.createShaderModule({ code: FULLSCREEN_VERTEX_SHADER }),
64
+ filterableResources: /* @__PURE__ */ new Map(),
65
+ layoutResources: /* @__PURE__ */ new Map()
66
+ };
67
+ blitCache.set(device, cache);
68
+ }
69
+ return cache;
70
+ }
71
+ function getBlitResources(device, filterable, sampleType) {
72
+ const cache = getOrCreateDeviceCache(device);
73
+ let filterableRes = cache.filterableResources.get(filterable);
74
+ if (!filterableRes) {
75
+ filterableRes = {
76
+ fragmentModule: device.createShaderModule({ code: filterable ? SAMPLE_FRAGMENT_SHADER : GATHER_FRAGMENT_SHADER }),
77
+ sampler: device.createSampler(filterable ? {
78
+ magFilter: "linear",
79
+ minFilter: "linear"
80
+ } : {})
81
+ };
82
+ cache.filterableResources.set(filterable, filterableRes);
83
+ }
84
+ const layoutKey = `${filterable}:${sampleType}`;
85
+ let layoutRes = cache.layoutResources.get(layoutKey);
86
+ if (!layoutRes) {
87
+ const bindGroupLayout = device.createBindGroupLayout({ entries: [{
88
+ binding: 0,
89
+ visibility: GPUShaderStage.FRAGMENT,
90
+ texture: { sampleType }
91
+ }, {
92
+ binding: 1,
93
+ visibility: GPUShaderStage.FRAGMENT,
94
+ sampler: { type: filterable ? "filtering" : "non-filtering" }
95
+ }] });
96
+ layoutRes = {
97
+ bindGroupLayout,
98
+ pipelineLayout: device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayout] })
99
+ };
100
+ cache.layoutResources.set(layoutKey, layoutRes);
101
+ }
102
+ return {
103
+ vertexModule: cache.vertexModule,
104
+ ...filterableRes,
105
+ ...layoutRes
106
+ };
107
+ }
108
+ function blit(options) {
109
+ const { device, source, destination, format, filterable, sampleType } = options;
110
+ const resources = getBlitResources(device, filterable, sampleType);
111
+ const pipeline = device.createRenderPipeline({
112
+ layout: resources.pipelineLayout,
113
+ vertex: { module: resources.vertexModule },
114
+ fragment: {
115
+ module: resources.fragmentModule,
116
+ targets: [{ format }]
117
+ },
118
+ primitive: { topology: "triangle-list" }
119
+ });
120
+ const bindGroup = device.createBindGroup({
121
+ layout: resources.bindGroupLayout,
122
+ entries: [{
123
+ binding: 0,
124
+ resource: source
125
+ }, {
126
+ binding: 1,
127
+ resource: resources.sampler
128
+ }]
129
+ });
130
+ const ownEncoder = !options.encoder;
131
+ const encoder = options.encoder ?? device.createCommandEncoder();
132
+ const pass = encoder.beginRenderPass({ colorAttachments: [{
133
+ view: destination,
134
+ loadOp: "clear",
135
+ storeOp: "store"
136
+ }] });
137
+ pass.setPipeline(pipeline);
138
+ pass.setBindGroup(0, bindGroup);
139
+ pass.draw(3);
140
+ pass.end();
141
+ if (ownEncoder) device.queue.submit([encoder.finish()]);
142
+ }
143
+ function clearTextureUtilsCache(device) {
144
+ blitCache.delete(device);
145
+ }
146
+ function validateBlitFormat(device, format, operation) {
147
+ const info = getTextureFormatInfo(format);
148
+ const effectiveSampleTypes = getEffectiveSampleTypes(device, format);
149
+ const isFloat = effectiveSampleTypes.includes("float");
150
+ const isUnfilterableFloat = effectiveSampleTypes.includes("unfilterable-float");
151
+ if (!isFloat && !isUnfilterableFloat) throw new Error(`Cannot ${operation} for format '${format}': only float formats are supported.`);
152
+ if (!info.canRenderAttachment) throw new Error(`Cannot ${operation} for format '${format}': format does not support render attachments.`);
153
+ return {
154
+ filterable: isFloat,
155
+ sampleType: isFloat ? "float" : "unfilterable-float"
156
+ };
157
+ }
158
+ function generateTextureMipmaps(device, texture, baseMipLevel = 0, mipLevels) {
159
+ if (texture.dimension !== "2d") throw new Error("Mipmap generation only supports 2D textures.");
160
+ const { filterable, sampleType } = validateBlitFormat(device, texture.format, "generate mipmaps");
161
+ const levels = mipLevels ?? texture.mipLevelCount - baseMipLevel;
162
+ for (let layer = 0; layer < texture.depthOrArrayLayers; layer++) for (let mip = baseMipLevel; mip < baseMipLevel + levels - 1; mip++) {
163
+ const viewOptions = (level) => ({
164
+ dimension: "2d",
165
+ baseMipLevel: level,
166
+ mipLevelCount: 1,
167
+ baseArrayLayer: layer,
168
+ arrayLayerCount: 1
169
+ });
170
+ blit({
171
+ device,
172
+ source: texture.createView(viewOptions(mip)),
173
+ destination: texture.createView(viewOptions(mip + 1)),
174
+ format: texture.format,
175
+ filterable,
176
+ sampleType
177
+ });
178
+ }
179
+ }
180
+ function resampleImage(device, targetTexture, image, layer = 0) {
181
+ if (targetTexture.dimension !== "2d") throw new Error("Resampling only supports 2D textures.");
182
+ const { filterable } = validateBlitFormat(device, targetTexture.format, "resample");
183
+ const { width, height } = getImageSourceDimensions(image);
184
+ const inputTexture = device.createTexture({
185
+ size: [width, height],
186
+ format: "rgba8unorm",
187
+ usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT
188
+ });
189
+ device.queue.copyExternalImageToTexture({ source: image }, { texture: inputTexture }, [width, height]);
190
+ const renderTexture = device.createTexture({
191
+ size: [targetTexture.width, targetTexture.height],
192
+ format: targetTexture.format,
193
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC
194
+ });
195
+ const encoder = device.createCommandEncoder();
196
+ blit({
197
+ device,
198
+ source: inputTexture.createView(),
199
+ destination: renderTexture.createView(),
200
+ format: targetTexture.format,
201
+ filterable,
202
+ sampleType: "float",
203
+ encoder
204
+ });
205
+ encoder.copyTextureToTexture({ texture: renderTexture }, {
206
+ texture: targetTexture,
207
+ origin: {
208
+ x: 0,
209
+ y: 0,
210
+ z: layer
211
+ }
212
+ }, {
213
+ width: targetTexture.width,
214
+ height: targetTexture.height,
215
+ depthOrArrayLayers: 1
216
+ });
217
+ device.queue.submit([encoder.finish()]);
218
+ inputTexture.destroy();
219
+ renderTexture.destroy();
220
+ }
221
+ //#endregion
222
+ export { clearTextureUtilsCache, generateTextureMipmaps, getImageSourceDimensions, resampleImage };
@@ -0,0 +1,21 @@
1
+ import { StorageFlag } from "../../extension.js";
2
+ import { TextureProps } from "./textureProps.js";
3
+ import { StorageTextureFormats } from "./textureFormats.js";
4
+
5
+ //#region src/core/texture/usageExtension.d.ts
6
+ interface SampledFlag {
7
+ usableAsSampled: true;
8
+ }
9
+ interface RenderFlag {
10
+ usableAsRender: true;
11
+ }
12
+ type LiteralToExtensionMap = {
13
+ storage: StorageFlag;
14
+ sampled: SampledFlag;
15
+ render: RenderFlag;
16
+ };
17
+ type AllowedUsages<TProps extends TextureProps> = 'sampled' | 'render' | (TProps['format'] extends StorageTextureFormats ? 'storage' : never);
18
+ declare function isUsableAsSampled<T>(value: T): value is T & SampledFlag;
19
+ declare function isUsableAsRender<T>(value: T): value is T & RenderFlag;
20
+ //#endregion
21
+ export { AllowedUsages, LiteralToExtensionMap, RenderFlag, SampledFlag, isUsableAsRender, isUsableAsSampled };
@@ -0,0 +1,19 @@
1
+ import { getName } from "../../shared/meta.js";
2
+ //#region src/core/texture/usageExtension.ts
3
+ function isUsableAsSampled(value) {
4
+ return !!value?.usableAsSampled;
5
+ }
6
+ function isUsableAsRender(value) {
7
+ return !!value?.usableAsRender;
8
+ }
9
+ /**
10
+ * @category Errors
11
+ */
12
+ var NotSampledError = class NotSampledError extends Error {
13
+ constructor(value) {
14
+ super(`Resource '${getName(value) ?? "<unnamed>"}' cannot be bound as 'sampled'. Use .$usage('sampled') to allow it.`);
15
+ Object.setPrototypeOf(this, NotSampledError.prototype);
16
+ }
17
+ };
18
+ //#endregion
19
+ export { NotSampledError, isUsableAsRender, isUsableAsSampled };
@@ -0,0 +1,68 @@
1
+ import { $internal } from "../../shared/symbols.js";
2
+ import { GPUCallable } from "../../types.js";
3
+
4
+ //#region src/core/unroll/tgpuUnroll.d.ts
5
+ /**
6
+ * Marks an iterable to be unrolled by the shader generator when used in a for loop.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * const neighborOffsets = [d.vec2i(0, 1), d.vec2i(0, -1), d.vec2i(1, 0), d.vec2i(-1, 0)];
11
+ *
12
+ * // Unrolls into 4 blocks of code, one for each offset.
13
+ * for (const offset of tgpu.unroll(neighborOffsets)) {
14
+ * // ...
15
+ * }
16
+ * ```
17
+ *
18
+ * If you'd like to unroll over a range of numbers, use `tgpu.unroll(std.range(n))`.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * // (...)
23
+ * const FBM_OCTAVES = 3;
24
+ *
25
+ * function fbm(pos: d.v3f): number {
26
+ * 'use gpu';
27
+ * let sum = d.f32();
28
+ *
29
+ * // i = 0, 1, 2
30
+ * for (const i of tgpu.unroll(std.range(FBM_OCTAVES))) {
31
+ * sum +=
32
+ * noise3d(pos * (CLOUD_FREQUENCY * FBM_LACUNARITY ** i)) *
33
+ * (CLOUD_AMPLITUDE * FBM_PERSISTENCE ** i);
34
+ * }
35
+ *
36
+ * return sum;
37
+ * }
38
+ *
39
+ * ```
40
+ *
41
+ * Generates:
42
+ *
43
+ * ```wgsl
44
+ * // (...)
45
+ *
46
+ * fn fbm(pos: vec3f) -> f32 {
47
+ * var sum = 0f;
48
+ * // unrolled iteration #0
49
+ * {
50
+ * sum += noise3d(pos * 1.4f) * 1f;
51
+ * }
52
+ * // unrolled iteration #1
53
+ * {
54
+ * sum += noise3d(pos * 2.8f) * 0.5f;
55
+ * }
56
+ * // unrolled iteration #2
57
+ * {
58
+ * sum += noise3d(pos * 5.6f) * 0.25f;
59
+ * }
60
+ * return sum;
61
+ * }
62
+ * ```
63
+ */
64
+ declare const unroll: (<T extends Iterable<unknown>>(iterable: T) => T) & GPUCallable & {
65
+ [$internal]: true;
66
+ };
67
+ //#endregion
68
+ export { unroll };
@@ -0,0 +1,94 @@
1
+ import { $gpuCallable, $internal, $resolve } from "../../shared/symbols.js";
2
+ import { setName } from "../../shared/meta.js";
3
+ import { snip } from "../../data/snippet.js";
4
+ import { stitch } from "../resolve/stitch.js";
5
+ //#region src/core/unroll/tgpuUnroll.ts
6
+ /**
7
+ * The result of calling `tgpu.unroll(...)`. The code responsible for
8
+ * generating shader code can check if the value of a snippet is
9
+ * an instance of `UnrollableIterable`, and act accordingly.
10
+ */
11
+ var UnrollableIterable = class {
12
+ [$internal] = true;
13
+ snippet;
14
+ constructor(snippet) {
15
+ this.snippet = snippet;
16
+ }
17
+ [$resolve](_ctx) {
18
+ return snip(stitch`${this.snippet}`, this.snippet.dataType, this.snippet.origin);
19
+ }
20
+ };
21
+ /**
22
+ * Marks an iterable to be unrolled by the shader generator when used in a for loop.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * const neighborOffsets = [d.vec2i(0, 1), d.vec2i(0, -1), d.vec2i(1, 0), d.vec2i(-1, 0)];
27
+ *
28
+ * // Unrolls into 4 blocks of code, one for each offset.
29
+ * for (const offset of tgpu.unroll(neighborOffsets)) {
30
+ * // ...
31
+ * }
32
+ * ```
33
+ *
34
+ * If you'd like to unroll over a range of numbers, use `tgpu.unroll(std.range(n))`.
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * // (...)
39
+ * const FBM_OCTAVES = 3;
40
+ *
41
+ * function fbm(pos: d.v3f): number {
42
+ * 'use gpu';
43
+ * let sum = d.f32();
44
+ *
45
+ * // i = 0, 1, 2
46
+ * for (const i of tgpu.unroll(std.range(FBM_OCTAVES))) {
47
+ * sum +=
48
+ * noise3d(pos * (CLOUD_FREQUENCY * FBM_LACUNARITY ** i)) *
49
+ * (CLOUD_AMPLITUDE * FBM_PERSISTENCE ** i);
50
+ * }
51
+ *
52
+ * return sum;
53
+ * }
54
+ *
55
+ * ```
56
+ *
57
+ * Generates:
58
+ *
59
+ * ```wgsl
60
+ * // (...)
61
+ *
62
+ * fn fbm(pos: vec3f) -> f32 {
63
+ * var sum = 0f;
64
+ * // unrolled iteration #0
65
+ * {
66
+ * sum += noise3d(pos * 1.4f) * 1f;
67
+ * }
68
+ * // unrolled iteration #1
69
+ * {
70
+ * sum += noise3d(pos * 2.8f) * 0.5f;
71
+ * }
72
+ * // unrolled iteration #2
73
+ * {
74
+ * sum += noise3d(pos * 5.6f) * 0.25f;
75
+ * }
76
+ * return sum;
77
+ * }
78
+ * ```
79
+ */
80
+ const unroll = (() => {
81
+ function jsImpl(iterable) {
82
+ return iterable;
83
+ }
84
+ const impl = jsImpl;
85
+ setName(impl, "unroll");
86
+ impl.toString = () => "unroll";
87
+ impl[$internal] = true;
88
+ impl[$gpuCallable] = { call(_ctx, [value]) {
89
+ return snip(new UnrollableIterable(value), value.dataType, value.origin);
90
+ } };
91
+ return impl;
92
+ })();
93
+ //#endregion
94
+ export { UnrollableIterable, unroll };
@@ -0,0 +1,42 @@
1
+ import { $internal, $ownSnippet, $resolve } from "../shared/symbols.js";
2
+ import { getOwnSnippet } from "../types.js";
3
+ import { getGPUValue } from "../getGPUValue.js";
4
+ import { accessProp } from "../tgsl/accessProp.js";
5
+ import { accessIndex } from "../tgsl/accessIndex.js";
6
+ //#region src/core/valueProxyUtils.ts
7
+ const valueProxyHandler = { get(target, prop) {
8
+ if (prop in target) return Reflect.get(target, prop);
9
+ if (prop === "toString" || prop === Symbol.toStringTag || prop === Symbol.toPrimitive) return () => target.toString();
10
+ if (typeof prop === "symbol") return;
11
+ const targetSnippet = getOwnSnippet(target);
12
+ const index = Number(prop);
13
+ if (!Number.isNaN(index)) {
14
+ const accessed = accessIndex(targetSnippet, index);
15
+ if (!accessed) return;
16
+ return new Proxy({
17
+ [$internal]: true,
18
+ [$resolve]: (ctx) => ctx.resolve(accessed.value, accessed.dataType),
19
+ [$ownSnippet]: accessed,
20
+ toString: () => `${String(target)}[${prop}]`
21
+ }, valueProxyHandler);
22
+ }
23
+ const accessed = accessProp(targetSnippet, String(prop));
24
+ if (!accessed) return;
25
+ return new Proxy({
26
+ [$internal]: true,
27
+ [$resolve]: (ctx) => ctx.resolve(accessed.value, accessed.dataType),
28
+ [$ownSnippet]: accessed,
29
+ toString: () => `${String(target)}.${prop}`
30
+ }, valueProxyHandler);
31
+ } };
32
+ function getGpuValueRecursively(value) {
33
+ let unwrapped = value;
34
+ while (true) {
35
+ const gpuValue = getGPUValue(unwrapped);
36
+ if (!gpuValue) break;
37
+ unwrapped = gpuValue;
38
+ }
39
+ return unwrapped;
40
+ }
41
+ //#endregion
42
+ export { getGpuValueRecursively, valueProxyHandler };
@@ -0,0 +1,38 @@
1
+ import { TgpuNamable } from "../../shared/meta.js";
2
+ import { $gpuValueOf, $internal } from "../../shared/symbols.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/variable/tgpuVariable.d.ts
8
+ type VariableScope = 'private' | 'workgroup';
9
+ interface TgpuVar<TScope extends VariableScope = VariableScope, TDataType extends BaseData = BaseData> extends TgpuNamable {
10
+ readonly resourceType: 'var';
11
+ readonly [$gpuValueOf]: InferGPU<TDataType>;
12
+ /**
13
+ * @deprecated Use `.$` instead, works the same way.
14
+ */
15
+ value: InferGPU<TDataType>;
16
+ $: InferGPU<TDataType>;
17
+ readonly [$internal]: {
18
+ /** Makes it differentiable on the type level. Does not exist at runtime. */dataType?: TDataType; /** Makes it differentiable on the type level. Does not exist at runtime. */
19
+ scope?: TScope;
20
+ };
21
+ }
22
+ /**
23
+ * Defines a variable scoped to each entry function (private).
24
+ *
25
+ * @param dataType The schema of the held data's type
26
+ * @param initialValue If not provided, the variable will be initialized to the dataType's "zero-value".
27
+ */
28
+ declare function privateVar<TDataType extends AnyData>(dataType: TDataType, initialValue?: InferGPU<TDataType>): TgpuVar<'private', TDataType>;
29
+ /**
30
+ * Defines a variable scoped to the whole workgroup, shared between entry functions
31
+ * of the same invocation.
32
+ *
33
+ * @param dataType The schema of the held data's type
34
+ */
35
+ declare function workgroupVar<TDataType extends AnyData>(dataType: TDataType): TgpuVar<'workgroup', TDataType>;
36
+ declare function isVariable(value: unknown): value is TgpuVar;
37
+ //#endregion
38
+ export { TgpuVar, VariableScope, isVariable, privateVar, workgroupVar };
@@ -0,0 +1,99 @@
1
+ import { $gpuValueOf, $internal, $ownSnippet, $resolve } from "../../shared/symbols.js";
2
+ import { getName, setName } from "../../shared/meta.js";
3
+ import { isNaturallyEphemeral } from "../../data/wgslTypes.js";
4
+ import { snip } from "../../data/snippet.js";
5
+ import { IllegalVarAccessError } from "../../errors.js";
6
+ import { getExecMode, isInsideTgpuFn } from "../../execMode.js";
7
+ import { assertExhaustive } from "../../shared/utilityTypes.js";
8
+ import { valueProxyHandler } from "../valueProxyUtils.js";
9
+ //#region src/core/variable/tgpuVariable.ts
10
+ /**
11
+ * Defines a variable scoped to each entry function (private).
12
+ *
13
+ * @param dataType The schema of the held data's type
14
+ * @param initialValue If not provided, the variable will be initialized to the dataType's "zero-value".
15
+ */
16
+ function privateVar(dataType, initialValue) {
17
+ return new TgpuVarImpl("private", dataType, initialValue);
18
+ }
19
+ /**
20
+ * Defines a variable scoped to the whole workgroup, shared between entry functions
21
+ * of the same invocation.
22
+ *
23
+ * @param dataType The schema of the held data's type
24
+ */
25
+ function workgroupVar(dataType) {
26
+ return new TgpuVarImpl("workgroup", dataType);
27
+ }
28
+ function isVariable(value) {
29
+ return value instanceof TgpuVarImpl;
30
+ }
31
+ var TgpuVarImpl = class {
32
+ [$internal] = {};
33
+ resourceType;
34
+ #scope;
35
+ #dataType;
36
+ #initialValue;
37
+ constructor(scope, dataType, initialValue) {
38
+ this.resourceType = "var";
39
+ this.#scope = scope;
40
+ this.#dataType = dataType;
41
+ this.#initialValue = initialValue;
42
+ }
43
+ [$resolve](ctx) {
44
+ const id = ctx.getUniqueName(this);
45
+ const pre = `var<${this.#scope}> ${id}: ${ctx.resolve(this.#dataType).value}`;
46
+ if (this.#initialValue) ctx.addDeclaration(`${pre} = ${ctx.resolve(this.#initialValue, this.#dataType).value};`);
47
+ else ctx.addDeclaration(`${pre};`);
48
+ return snip(id, this.#dataType, isNaturallyEphemeral(this.#dataType) ? "runtime" : this.#scope);
49
+ }
50
+ $name(label) {
51
+ setName(this, label);
52
+ return this;
53
+ }
54
+ toString() {
55
+ return `var:${getName(this) ?? "<unnamed>"}`;
56
+ }
57
+ get [$gpuValueOf]() {
58
+ const dataType = this.#dataType;
59
+ const origin = isNaturallyEphemeral(dataType) ? "runtime" : this.#scope;
60
+ return new Proxy({
61
+ [$internal]: true,
62
+ get [$ownSnippet]() {
63
+ return snip(this, dataType, origin);
64
+ },
65
+ [$resolve]: (ctx) => ctx.resolve(this),
66
+ toString: () => `var:${getName(this) ?? "<unnamed>"}.$`
67
+ }, valueProxyHandler);
68
+ }
69
+ get $() {
70
+ const mode = getExecMode();
71
+ const insideTgpuFn = isInsideTgpuFn();
72
+ if (mode.type === "normal") throw new IllegalVarAccessError(insideTgpuFn ? `Cannot access variable '${getName(this) ?? "<unnamed>"}'. TypeGPU functions that depends on GPU resources need to be part of a compute dispatch, draw call or simulation` : "TypeGPU variables are inaccessible during normal JS execution. If you wanted to simulate GPU behavior, try `tgpu.simulate()`");
73
+ if (mode.type === "codegen") return this[$gpuValueOf];
74
+ if (mode.type === "simulate") {
75
+ if (!mode.vars[this.#scope].has(this)) mode.vars[this.#scope].set(this, this.#initialValue);
76
+ return mode.vars[this.#scope].get(this);
77
+ }
78
+ return assertExhaustive(mode, "tgpuVariable.ts#TgpuVarImpl/$");
79
+ }
80
+ set $(value) {
81
+ const mode = getExecMode();
82
+ const insideTgpuFn = isInsideTgpuFn();
83
+ if (mode.type === "normal") throw new IllegalVarAccessError(insideTgpuFn ? `Cannot access ${String(this)}. TypeGPU functions that depends on GPU resources need to be part of a compute dispatch, draw call or simulation` : "TypeGPU variables are inaccessible during normal JS execution. If you wanted to simulate GPU behavior, try `tgpu.simulate()`");
84
+ if (mode.type === "codegen") throw new Error("Unreachable tgpuVariable.ts#TgpuVarImpl/$");
85
+ if (mode.type === "simulate") {
86
+ mode.vars[this.#scope].set(this, value);
87
+ return;
88
+ }
89
+ assertExhaustive(mode, "tgpuVariable.ts#TgpuVarImpl/$");
90
+ }
91
+ get value() {
92
+ return this.$;
93
+ }
94
+ set value(v) {
95
+ this.$ = v;
96
+ }
97
+ };
98
+ //#endregion
99
+ export { isVariable, privateVar, workgroupVar };
@@ -0,0 +1,57 @@
1
+ import { getCustomLocation, isData } from "../../data/dataTypes.js";
2
+ import { isBuiltin } from "../../data/attributes.js";
3
+ //#region src/core/vertexLayout/connectAttributesToShader.ts
4
+ function isAttribute(value) {
5
+ return typeof value?.format === "string";
6
+ }
7
+ function connectAttributesToShader(shaderInputLayout, attributes) {
8
+ const usedVertexLayouts = [];
9
+ if (isData(shaderInputLayout)) {
10
+ if (!isAttribute(attributes)) throw new Error("Shader expected a single attribute, not a record of attributes to be passed in.");
11
+ usedVertexLayouts.push(attributes._layout);
12
+ return {
13
+ usedVertexLayouts,
14
+ bufferDefinitions: [{
15
+ arrayStride: attributes._layout.stride,
16
+ stepMode: attributes._layout.stepMode,
17
+ attributes: [{
18
+ format: attributes.format,
19
+ offset: attributes.offset,
20
+ shaderLocation: getCustomLocation(shaderInputLayout) ?? 0
21
+ }]
22
+ }]
23
+ };
24
+ }
25
+ const bufferDefinitions = [];
26
+ const layoutToAttribListMap = /* @__PURE__ */ new WeakMap();
27
+ let nextShaderLocation = 0;
28
+ for (const [key, member] of Object.entries(shaderInputLayout)) {
29
+ if (isBuiltin(member)) continue;
30
+ const matchingAttribute = attributes[key];
31
+ if (!matchingAttribute) throw new Error(`An attribute by the name of '${key}' was not provided to the shader.`);
32
+ const layout = matchingAttribute._layout;
33
+ let attribList = layoutToAttribListMap.get(layout);
34
+ if (!attribList) {
35
+ usedVertexLayouts.push(layout);
36
+ attribList = [];
37
+ bufferDefinitions.push({
38
+ arrayStride: layout.stride,
39
+ stepMode: layout.stepMode,
40
+ attributes: attribList
41
+ });
42
+ layoutToAttribListMap.set(layout, attribList);
43
+ }
44
+ nextShaderLocation = getCustomLocation(member) ?? nextShaderLocation;
45
+ attribList.push({
46
+ format: matchingAttribute.format,
47
+ offset: matchingAttribute.offset,
48
+ shaderLocation: nextShaderLocation++
49
+ });
50
+ }
51
+ return {
52
+ usedVertexLayouts,
53
+ bufferDefinitions
54
+ };
55
+ }
56
+ //#endregion
57
+ export { connectAttributesToShader, isAttribute };