typegpu 0.11.9 → 0.12.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 (366) hide show
  1. package/bin.mjs +28 -6
  2. package/builtin.d.ts +51 -53
  3. package/builtin.js +30 -34
  4. package/common/fullScreenTriangle.d.ts +2 -10
  5. package/common/fullScreenTriangle.js +20 -28
  6. package/common/index.d.ts +2 -9
  7. package/common/index.js +3 -12
  8. package/common/writeSoA.d.ts +11 -12
  9. package/common/writeSoA.js +88 -76
  10. package/core/buffer/buffer.d.ts +79 -62
  11. package/core/buffer/buffer.js +283 -205
  12. package/core/buffer/bufferBinding.d.ts +71 -0
  13. package/core/buffer/bufferBinding.js +154 -0
  14. package/core/buffer/bufferUsage.d.ts +14 -45
  15. package/core/buffer/bufferUsage.js +1 -171
  16. package/core/buffer/laidOutBuffer.d.ts +25 -0
  17. package/core/buffer/laidOutBuffer.js +55 -0
  18. package/core/commandEncoder/attachments.d.ts +125 -0
  19. package/core/commandEncoder/attachments.js +29 -0
  20. package/core/commandEncoder/commandEncoder.d.ts +53 -0
  21. package/core/commandEncoder/commandEncoder.js +56 -0
  22. package/core/commandEncoder/computePass.d.ts +58 -0
  23. package/core/commandEncoder/computePass.js +63 -0
  24. package/core/commandEncoder/renderPass.d.ts +121 -0
  25. package/core/commandEncoder/renderPass.js +196 -0
  26. package/core/constant/tgpuConstant.d.ts +26 -26
  27. package/core/constant/tgpuConstant.js +76 -65
  28. package/core/declare/tgpuDeclare.d.ts +3 -6
  29. package/core/declare/tgpuDeclare.js +36 -36
  30. package/core/function/autoIO.d.ts +61 -33
  31. package/core/function/autoIO.js +68 -73
  32. package/core/function/comptime.d.ts +11 -13
  33. package/core/function/comptime.js +60 -52
  34. package/core/function/createCallableSchema.d.ts +16 -0
  35. package/core/function/createCallableSchema.js +50 -40
  36. package/core/function/dualImpl.d.ts +44 -0
  37. package/core/function/dualImpl.js +71 -50
  38. package/core/function/entryInputRouter.d.ts +26 -0
  39. package/core/function/entryInputRouter.js +31 -33
  40. package/core/function/extractArgs.d.ts +38 -0
  41. package/core/function/extractArgs.js +202 -200
  42. package/core/function/fnCore.d.ts +44 -5
  43. package/core/function/fnCore.js +148 -93
  44. package/core/function/fnTypes.d.ts +31 -29
  45. package/core/function/fnTypes.js +1 -0
  46. package/core/function/ioSchema.d.ts +12 -10
  47. package/core/function/ioSchema.js +65 -47
  48. package/core/function/shelllessImpl.d.ts +9 -12
  49. package/core/function/shelllessImpl.js +17 -22
  50. package/core/function/templateUtils.d.ts +2 -0
  51. package/core/function/templateUtils.js +9 -8
  52. package/core/function/tgpuComputeFn.d.ts +26 -28
  53. package/core/function/tgpuComputeFn.js +47 -48
  54. package/core/function/tgpuFn.d.ts +34 -37
  55. package/core/function/tgpuFn.js +179 -153
  56. package/core/function/tgpuFragmentFn.d.ts +52 -53
  57. package/core/function/tgpuFragmentFn.js +63 -56
  58. package/core/function/tgpuVertexFn.d.ts +36 -39
  59. package/core/function/tgpuVertexFn.js +56 -53
  60. package/core/pipeline/computePipeline.d.ts +141 -53
  61. package/core/pipeline/computePipeline.js +291 -225
  62. package/core/pipeline/connectAttachmentToShader.d.ts +4 -0
  63. package/core/pipeline/connectAttachmentToShader.js +25 -22
  64. package/core/pipeline/connectTargetsToShader.d.ts +3 -0
  65. package/core/pipeline/connectTargetsToShader.js +29 -27
  66. package/core/pipeline/drawState.d.ts +52 -0
  67. package/core/pipeline/drawState.js +225 -0
  68. package/core/pipeline/performanceTracker.d.ts +14 -0
  69. package/core/pipeline/performanceTracker.js +34 -0
  70. package/core/pipeline/pipelineUtils.d.ts +18 -0
  71. package/core/pipeline/pipelineUtils.js +54 -25
  72. package/core/pipeline/priors.d.ts +1 -0
  73. package/core/pipeline/priors.js +12 -0
  74. package/core/pipeline/renderPipeline.d.ts +246 -261
  75. package/core/pipeline/renderPipeline.js +487 -480
  76. package/core/pipeline/timeable.d.ts +28 -18
  77. package/core/pipeline/timeable.js +90 -52
  78. package/core/pipeline/typeGuards.d.ts +17 -0
  79. package/core/pipeline/typeGuards.js +52 -22
  80. package/core/pipeline/webgpuLimitations.d.ts +10 -0
  81. package/core/pipeline/webgpuLimitations.js +81 -0
  82. package/core/querySet/querySet.d.ts +26 -21
  83. package/core/querySet/querySet.js +127 -103
  84. package/core/rawCodeSnippet/tgpuRawCodeSnippet.d.ts +13 -18
  85. package/core/rawCodeSnippet/tgpuRawCodeSnippet.js +89 -90
  86. package/core/resolve/externals.d.ts +25 -8
  87. package/core/resolve/externals.js +78 -54
  88. package/core/resolve/namespace.d.ts +22 -25
  89. package/core/resolve/namespace.js +16 -21
  90. package/core/resolve/resolvableString.d.ts +7 -0
  91. package/core/resolve/resolvableString.js +13 -0
  92. package/core/resolve/resolveData.d.ts +10 -0
  93. package/core/resolve/resolveData.js +162 -121
  94. package/core/resolve/stitch.d.ts +8 -0
  95. package/core/resolve/stitch.js +23 -21
  96. package/core/resolve/tgpuResolve.d.ts +55 -53
  97. package/core/resolve/tgpuResolve.js +106 -53
  98. package/core/root/configurableImpl.d.ts +10 -0
  99. package/core/root/configurableImpl.js +17 -19
  100. package/core/root/init.d.ts +76 -38
  101. package/core/root/init.js +346 -455
  102. package/core/root/rootTypes.d.ts +461 -636
  103. package/core/root/rootTypes.js +1 -0
  104. package/core/sampler/sampler.d.ts +50 -31
  105. package/core/sampler/sampler.js +120 -113
  106. package/core/simulate/tgpuSimulate.d.ts +9 -12
  107. package/core/simulate/tgpuSimulate.js +68 -71
  108. package/core/slot/accessor.d.ts +36 -13
  109. package/core/slot/accessor.js +138 -91
  110. package/core/slot/internalSlots.d.ts +2 -0
  111. package/core/slot/internalSlots.js +1 -6
  112. package/core/slot/lazy.d.ts +2 -6
  113. package/core/slot/lazy.js +71 -39
  114. package/core/slot/slot.d.ts +2 -6
  115. package/core/slot/slot.js +45 -38
  116. package/core/slot/slotTypes.d.ts +78 -80
  117. package/core/slot/slotTypes.js +11 -16
  118. package/core/texture/externalTexture.d.ts +20 -11
  119. package/core/texture/externalTexture.js +46 -46
  120. package/core/texture/texture.d.ts +152 -97
  121. package/core/texture/texture.js +407 -314
  122. package/core/texture/textureFormats.d.ts +42 -23
  123. package/core/texture/textureFormats.js +104 -75
  124. package/core/texture/textureProps.d.ts +7 -10
  125. package/core/texture/textureProps.js +1 -0
  126. package/core/texture/textureUtils.d.ts +8 -0
  127. package/core/texture/textureUtils.js +185 -179
  128. package/core/texture/usageExtension.d.ts +21 -18
  129. package/core/texture/usageExtension.js +13 -17
  130. package/core/unroll/tgpuUnroll.d.ts +20 -19
  131. package/core/unroll/tgpuUnroll.js +82 -91
  132. package/core/valueProxyUtils.d.ts +3 -0
  133. package/core/valueProxyUtils.js +52 -41
  134. package/core/variable/tgpuVariable.d.ts +26 -27
  135. package/core/variable/tgpuVariable.js +93 -96
  136. package/core/vertexLayout/connectAttributesToShader.d.ts +9 -0
  137. package/core/vertexLayout/connectAttributesToShader.js +61 -56
  138. package/core/vertexLayout/vertexAttribute.d.ts +21 -17
  139. package/core/vertexLayout/vertexAttribute.js +1 -0
  140. package/core/vertexLayout/vertexLayout.d.ts +24 -18
  141. package/core/vertexLayout/vertexLayout.js +130 -99
  142. package/core/whitespaces.d.ts +2 -0
  143. package/core/whitespaces.js +16 -0
  144. package/data/alignIO.d.ts +7 -0
  145. package/data/alignIO.js +13 -13
  146. package/data/alignmentOf.d.ts +5 -8
  147. package/data/alignmentOf.js +90 -75
  148. package/data/array.d.ts +17 -9
  149. package/data/array.js +57 -40
  150. package/data/atomic.d.ts +2 -7
  151. package/data/atomic.js +26 -23
  152. package/data/attributes.d.ts +19 -21
  153. package/data/attributes.js +192 -132
  154. package/data/autoStruct.d.ts +36 -3
  155. package/data/autoStruct.js +84 -81
  156. package/data/compiledIO.d.ts +5 -0
  157. package/data/compiledIO.js +231 -215
  158. package/data/dataIO.d.ts +13 -11
  159. package/data/dataIO.js +643 -589
  160. package/data/dataTypes.d.ts +83 -65
  161. package/data/dataTypes.js +66 -68
  162. package/data/deepEqual.d.ts +2 -7
  163. package/data/deepEqual.js +80 -55
  164. package/data/disarray.d.ts +6 -10
  165. package/data/disarray.js +52 -46
  166. package/data/float16Conversion.d.ts +4 -0
  167. package/data/float16Conversion.js +7 -0
  168. package/data/generalizeFn.d.ts +25 -0
  169. package/data/generalizeFn.js +89 -0
  170. package/data/getLongestContiguousPrefix.d.ts +4 -8
  171. package/data/getLongestContiguousPrefix.js +6 -11
  172. package/data/index.d.ts +30 -31
  173. package/data/index.js +39 -172
  174. package/data/instanceToSchema.d.ts +24 -27
  175. package/data/instanceToSchema.js +1 -0
  176. package/data/isContiguous.d.ts +4 -8
  177. package/data/isContiguous.js +6 -11
  178. package/data/matrix.d.ts +21 -21
  179. package/data/matrix.js +513 -505
  180. package/data/numberOps.d.ts +5 -0
  181. package/data/numberOps.js +21 -21
  182. package/data/numeric.d.ts +21 -12
  183. package/data/numeric.js +287 -197
  184. package/data/offsetUtils.d.ts +9 -13
  185. package/data/offsetUtils.js +204 -144
  186. package/data/offsets.d.ts +8 -0
  187. package/data/offsets.js +33 -33
  188. package/data/partialIO.d.ts +13 -8
  189. package/data/partialIO.js +124 -113
  190. package/data/ptr.d.ts +12 -12
  191. package/data/ptr.js +42 -44
  192. package/data/ref.d.ts +40 -27
  193. package/data/ref.js +125 -95
  194. package/data/sampler.d.ts +99 -101
  195. package/data/sampler.js +17 -21
  196. package/data/schemaCallWrapper.d.ts +19 -0
  197. package/data/schemaCallWrapper.js +31 -26
  198. package/data/schemaMemoryLayout.d.ts +8 -0
  199. package/data/schemaMemoryLayout.js +213 -185
  200. package/data/sizeOf.d.ts +4 -8
  201. package/data/sizeOf.js +6 -11
  202. package/data/snippet.d.ts +96 -20
  203. package/data/snippet.js +75 -86
  204. package/data/struct.d.ts +4 -7
  205. package/data/struct.js +51 -39
  206. package/data/texture.d.ts +253 -250
  207. package/data/texture.js +238 -200
  208. package/data/unstruct.d.ts +2 -7
  209. package/data/unstruct.js +43 -37
  210. package/data/vector.d.ts +33 -21
  211. package/data/vector.js +234 -221
  212. package/data/vectorImpl.d.ts +231 -0
  213. package/data/vectorImpl.js +563 -515
  214. package/data/vectorOps.d.ts +25 -0
  215. package/data/vectorOps.js +118 -669
  216. package/data/vertexFormatData.d.ts +181 -184
  217. package/data/vertexFormatData.js +104 -106
  218. package/data/wgslTypes.d.ts +665 -600
  219. package/data/wgslTypes.js +220 -198
  220. package/errors.d.ts +50 -24
  221. package/errors.js +146 -126
  222. package/execMode.d.ts +16 -0
  223. package/execMode.js +47 -40
  224. package/extension.d.ts +13 -8
  225. package/extension.js +10 -16
  226. package/getGPUValue.d.ts +1 -0
  227. package/getGPUValue.js +2 -7
  228. package/index.d.ts +28 -68
  229. package/index.js +8 -28
  230. package/indexNamedExports.d.ts +69 -42
  231. package/indexNamedExports.js +25 -0
  232. package/internal.d.ts +16 -0
  233. package/internal.js +12 -0
  234. package/mathUtils.d.ts +5 -0
  235. package/mathUtils.js +7 -11
  236. package/memo.d.ts +11 -0
  237. package/memo.js +20 -22
  238. package/minify.d.ts +5 -0
  239. package/minify.js +93 -0
  240. package/nameUtils.d.ts +29 -0
  241. package/nameUtils.js +427 -394
  242. package/package.json +5 -1
  243. package/resolutionCtx.d.ts +162 -22
  244. package/resolutionCtx.js +911 -629
  245. package/serial/registry.d.ts +15 -0
  246. package/serial/registry.js +106 -0
  247. package/serial/restore.d.ts +49 -0
  248. package/serial/restore.js +68 -0
  249. package/serial/schema.d.ts +58 -0
  250. package/serial/schema.js +209 -0
  251. package/serial/types.d.ts +5 -0
  252. package/serial/types.js +1 -0
  253. package/shared/env.d.ts +9 -0
  254. package/shared/env.js +9 -12
  255. package/shared/generators.d.ts +4 -0
  256. package/shared/generators.js +10 -12
  257. package/shared/meta.d.ts +29 -14
  258. package/shared/meta.js +71 -55
  259. package/shared/normalizeMetadata.d.ts +32 -27
  260. package/shared/normalizeMetadata.js +23 -36
  261. package/shared/repr.d.ts +73 -55
  262. package/shared/repr.js +1 -0
  263. package/shared/soul.d.ts +17 -0
  264. package/shared/soul.js +1 -0
  265. package/shared/stringify.d.ts +2 -0
  266. package/shared/stringify.js +29 -20
  267. package/shared/symbols.d.ts +26 -20
  268. package/shared/symbols.js +79 -79
  269. package/shared/tseynit.d.ts +2 -0
  270. package/shared/tseynit.js +160 -75
  271. package/shared/utilityTypes.d.ts +30 -14
  272. package/shared/utilityTypes.js +2 -6
  273. package/shared/vertexFormat.d.ts +41 -43
  274. package/shared/vertexFormat.js +59 -62
  275. package/std/array.d.ts +2 -7
  276. package/std/array.js +18 -23
  277. package/std/atomic.d.ts +14 -18
  278. package/std/atomic.js +96 -95
  279. package/std/bitcast.d.ts +193 -10
  280. package/std/bitcast.js +309 -39
  281. package/std/boolean.d.ts +19 -33
  282. package/std/boolean.js +296 -292
  283. package/std/copy.d.ts +2 -7
  284. package/std/copy.js +27 -24
  285. package/std/derivative.d.ts +11 -15
  286. package/std/derivative.js +56 -79
  287. package/std/discard.d.ts +1 -6
  288. package/std/discard.js +7 -14
  289. package/std/environment.d.ts +19 -14
  290. package/std/environment.js +71 -51
  291. package/std/extensions.d.ts +2 -8
  292. package/std/extensions.js +10 -11
  293. package/std/index.d.ts +20 -24
  294. package/std/index.js +32 -187
  295. package/std/matrix.d.ts +6 -12
  296. package/std/matrix.js +60 -69
  297. package/std/numeric.d.ts +150 -146
  298. package/std/numeric.js +771 -727
  299. package/std/operators.d.ts +19 -27
  300. package/std/operators.js +195 -194
  301. package/std/packing.d.ts +5 -11
  302. package/std/packing.js +67 -75
  303. package/std/range.d.ts +6 -11
  304. package/std/range.js +48 -36
  305. package/std/subgroup.d.ts +33 -37
  306. package/std/subgroup.js +180 -217
  307. package/std/texture.d.ts +70 -38
  308. package/std/texture.js +176 -172
  309. package/taskQueue.d.ts +6 -0
  310. package/taskQueue.js +30 -0
  311. package/tgpu.d.ts +16 -0
  312. package/tgpu.js +17 -44
  313. package/tgpuBindGroupLayout.d.ts +132 -152
  314. package/tgpuBindGroupLayout.js +346 -268
  315. package/tgpuLogger.d.ts +34 -0
  316. package/tgpuLogger.js +64 -0
  317. package/tgpuUnstable.d.ts +16 -22
  318. package/tgpuUnstable.js +13 -35
  319. package/tgsl/accessIndex.d.ts +2 -0
  320. package/tgsl/accessIndex.js +76 -33
  321. package/tgsl/accessProp.d.ts +2 -0
  322. package/tgsl/accessProp.js +142 -101
  323. package/tgsl/accessStructProp.d.ts +5 -0
  324. package/tgsl/accessStructProp.js +13 -15
  325. package/tgsl/consoleLog/deserializers.d.ts +13 -0
  326. package/tgsl/consoleLog/deserializers.js +119 -103
  327. package/tgsl/consoleLog/logGenerator.d.ts +21 -0
  328. package/tgsl/consoleLog/logGenerator.js +85 -80
  329. package/tgsl/consoleLog/serializers.d.ts +21 -0
  330. package/tgsl/consoleLog/serializers.js +119 -100
  331. package/tgsl/consoleLog/types.d.ts +40 -39
  332. package/tgsl/consoleLog/types.js +1 -0
  333. package/tgsl/conversion.d.ts +33 -0
  334. package/tgsl/conversion.js +271 -216
  335. package/tgsl/forOfUtils.d.ts +15 -0
  336. package/tgsl/forOfUtils.js +85 -70
  337. package/tgsl/generationHelpers.d.ts +22 -39
  338. package/tgsl/generationHelpers.js +85 -58
  339. package/tgsl/infixDispatch.d.ts +70 -0
  340. package/tgsl/infixDispatch.js +48 -46
  341. package/tgsl/jsPolyfills.d.ts +16 -19
  342. package/tgsl/jsPolyfills.js +44 -42
  343. package/tgsl/makeDereferenceable.d.ts +48 -0
  344. package/tgsl/makeDereferenceable.js +86 -0
  345. package/tgsl/makeResolvable.d.ts +22 -0
  346. package/tgsl/makeResolvable.js +33 -0
  347. package/tgsl/shaderGenerator.d.ts +77 -17
  348. package/tgsl/shaderGenerator.js +1 -0
  349. package/tgsl/shellless.d.ts +6 -9
  350. package/tgsl/shellless.js +73 -43
  351. package/tgsl/wgslGenerator.d.ts +66 -59
  352. package/tgsl/wgslGenerator.js +1345 -760
  353. package/types.d.ts +287 -222
  354. package/types.js +61 -44
  355. package/unwrapper.d.ts +31 -26
  356. package/unwrapper.js +1 -0
  357. package/wgslExtensions.d.ts +3 -5
  358. package/wgslExtensions.js +12 -16
  359. package/_virtual/rolldown_runtime.js +0 -13
  360. package/core/buffer/bufferShorthand.d.ts +0 -50
  361. package/core/buffer/bufferShorthand.js +0 -55
  362. package/core/pipeline/applyPipelineState.js +0 -37
  363. package/core/pipeline/limitsOverflow.js +0 -13
  364. package/package.js +0 -5
  365. package/tgsl/shaderGenerator_members.d.ts +0 -33
  366. package/tgsl/shaderGenerator_members.js +0 -12
@@ -1,491 +1,498 @@
1
- import { $getNameForward, $internal, $resolve } from "../../shared/symbols.js";
2
- import { Void, isWgslData } from "../../data/wgslTypes.js";
3
- import { PERF, getName, setName } from "../../shared/meta.js";
1
+ import { isBuiltin } from "../../data/attributes.js";
4
2
  import { getCustomLocation } from "../../data/dataTypes.js";
3
+ import { sizeOf } from "../../data/sizeOf.js";
5
4
  import { snip } from "../../data/snippet.js";
6
- import { isGPUBuffer } from "../../types.js";
7
5
  import { formatToWGSLType } from "../../data/vertexFormatData.js";
8
- import { sizeOf } from "../../data/sizeOf.js";
9
- import { isBuiltin } from "../../data/attributes.js";
10
- import { isTexture, isTextureView } from "../texture/texture.js";
11
- import { isBindGroup, isBindGroupLayout } from "../../tgpuBindGroupLayout.js";
12
- import { connectAttributesToShader } from "../vertexLayout/connectAttributesToShader.js";
6
+ import { isWgslData, Void, } from "../../data/wgslTypes.js";
7
+ import { invariant } from "../../errors.js";
13
8
  import { resolve } from "../../resolutionCtx.js";
14
- import { isGPUCommandEncoder, isGPURenderBundleEncoder, isGPURenderPassEncoder } from "./typeGuards.js";
9
+ import { getName, PERF, setName } from "../../shared/meta.js";
10
+ import { $getNameForward, $internal, $resolve, $soul } from "../../shared/symbols.js";
11
+ import { isBindGroup, isBindGroupLayout, } from "../../tgpuBindGroupLayout.js";
12
+ import { isGPUBuffer } from "../../types.js";
13
+ import { wgslEnableExtensions, wgslEnableExtensionToFeatureName } from "../../wgslExtensions.js";
14
+ import { AutoFragmentFn, AutoVertexFn, } from "../function/autoIO.js";
15
15
  import { namespace } from "../resolve/namespace.js";
16
- import { applyBindGroups, applyVertexBuffers } from "./applyPipelineState.js";
17
- import { logDataFromGPU } from "../../tgsl/consoleLog/deserializers.js";
18
- import { wgslEnableExtensionToFeatureName, wgslEnableExtensions } from "../../wgslExtensions.js";
19
- import { resolveIndirectOffset } from "./pipelineUtils.js";
20
- import { createWithPerformanceCallback, createWithTimestampWrites, setupTimestampWrites, triggerPerformanceCallback } from "./timeable.js";
21
- import { AutoFragmentFn, AutoVertexFn } from "../function/autoIO.js";
16
+ import { connectAttributesToShader } from "../vertexLayout/connectAttributesToShader.js";
22
17
  import { isVertexLayout } from "../vertexLayout/vertexLayout.js";
23
18
  import { connectAttachmentToShader } from "./connectAttachmentToShader.js";
24
19
  import { connectTargetsToShader } from "./connectTargetsToShader.js";
25
-
26
- //#region src/core/pipeline/renderPipeline.ts
27
- const DRAW_INDIRECT_SIZE = 16;
28
- const DRAW_INDEXED_INDIRECT_SIZE = 20;
29
- function INTERNAL_createRenderPipeline(options) {
30
- return new TgpuRenderPipelineImpl(new RenderPipelineCore(options), {});
20
+ import { INTERNAL_adoptCommandEncoder, INTERNAL_createCommandEncoder, } from "../commandEncoder/commandEncoder.js";
21
+ import { INTERNAL_adoptRenderCommands, } from "../commandEncoder/renderPass.js";
22
+ import { emitRenderDraw, finalizeOwnEncoder, requireIndexBuffer } from "./drawState.js";
23
+ import { isGPUCommandEncoder, isGPURenderBundleEncoder, isGPURenderPassEncoder, isTgpuCommandEncoder, isTgpuRenderCommands, } from "./typeGuards.js";
24
+ import { createWithPerformanceCallback, createWithTimestampWrites, } from "./timeable.js";
25
+ import { nonTransferablePriorsOf } from "./priors.js";
26
+ import {} from "../../data/offsetUtils.js";
27
+ import { warnIfOverflow } from "./webgpuLimitations.js";
28
+ import { collectBindGroupPairs, collectVertexBufferPairs, DRAW_INDEXED_INDIRECT_SIZE, DRAW_INDIRECT_SIZE, resolveIndirectOffset, restoreTimestampPriors, } from "./pipelineUtils.js";
29
+ import { NullPerformanceTracker, PerformanceTrackerImpl, } from "./performanceTracker.js";
30
+ import { logger } from "../../tgpuLogger.js";
31
+ export function INTERNAL_createRenderPipeline(options) {
32
+ return new TgpuRenderPipelineImpl(new RenderPipelineCore(options), {});
31
33
  }
32
- const _lastAppliedRender = /* @__PURE__ */ new WeakMap();
33
- var TgpuRenderPipelineImpl = class TgpuRenderPipelineImpl {
34
- [$internal];
35
- resourceType = "render-pipeline";
36
- [$getNameForward];
37
- hasIndexBuffer = false;
38
- constructor(core, priors) {
39
- this[$internal] = {
40
- core,
41
- priors,
42
- root: core.options.root
43
- };
44
- this[$getNameForward] = core;
45
- }
46
- [$resolve](ctx) {
47
- return ctx.resolve(this[$internal].core);
48
- }
49
- toString() {
50
- return `renderPipeline:${getName(this) ?? "<unnamed>"}`;
51
- }
52
- $name(label) {
53
- setName(this, label);
54
- return this;
55
- }
56
- with(first, resource) {
57
- const internals = this[$internal];
58
- if (isGPURenderPassEncoder(first) || isGPURenderBundleEncoder(first)) return new TgpuRenderPipelineImpl(internals.core, {
59
- ...internals.priors,
60
- externalRenderEncoder: first,
61
- externalEncoder: void 0
62
- });
63
- if (isGPUCommandEncoder(first)) return new TgpuRenderPipelineImpl(internals.core, {
64
- ...internals.priors,
65
- externalEncoder: first,
66
- externalRenderEncoder: void 0
67
- });
68
- if (isBindGroup(first)) return new TgpuRenderPipelineImpl(internals.core, {
69
- ...internals.priors,
70
- bindGroupLayoutMap: new Map([...internals.priors.bindGroupLayoutMap ?? [], [first.layout, first]])
71
- });
72
- if (isBindGroupLayout(first)) return new TgpuRenderPipelineImpl(internals.core, {
73
- ...internals.priors,
74
- bindGroupLayoutMap: new Map([...internals.priors.bindGroupLayoutMap ?? [], [first, resource]])
75
- });
76
- if (isVertexLayout(first)) return new TgpuRenderPipelineImpl(internals.core, {
77
- ...internals.priors,
78
- vertexLayoutMap: new Map([...internals.priors.vertexLayoutMap ?? [], [first, resource]])
79
- });
80
- throw new Error("Unsupported value passed into .with()");
81
- }
82
- withPerformanceCallback(callback) {
83
- const internals = this[$internal];
84
- if (internals.priors.timestampWrites) return new TgpuRenderPipelineImpl(internals.core, {
85
- ...internals.priors,
86
- performanceCallback: callback
87
- });
88
- const querySet = internals.core.performanceCallbackQuerySet;
89
- if (!querySet) {
90
- console.warn("Performance callback cannot be used because the timestamp-query feature is not enabled on the root.");
91
- return this;
92
- }
93
- const newPriors = createWithPerformanceCallback(internals.priors, callback, querySet);
94
- return new TgpuRenderPipelineImpl(internals.core, newPriors);
95
- }
96
- withTimestampWrites(options) {
97
- const internals = this[$internal];
98
- const newPriors = createWithTimestampWrites(internals.priors, options, internals.core.options.root);
99
- return new TgpuRenderPipelineImpl(internals.core, newPriors);
100
- }
101
- withColorAttachment(attachment) {
102
- const internals = this[$internal];
103
- return new TgpuRenderPipelineImpl(internals.core, {
104
- ...internals.priors,
105
- colorAttachment: attachment
106
- });
107
- }
108
- withDepthStencilAttachment(attachment) {
109
- const internals = this[$internal];
110
- return new TgpuRenderPipelineImpl(internals.core, {
111
- ...internals.priors,
112
- depthStencilAttachment: attachment
113
- });
114
- }
115
- withStencilReference(reference) {
116
- const internals = this[$internal];
117
- return new TgpuRenderPipelineImpl(internals.core, {
118
- ...internals.priors,
119
- stencilReference: reference
120
- });
121
- }
122
- withIndexBuffer(buffer, indexFormatOrOffset, offsetElementsOrSizeBytes, sizeElementsOrUndefined) {
123
- const internals = this[$internal];
124
- if (isGPUBuffer(buffer)) {
125
- if (typeof indexFormatOrOffset !== "string") throw new Error("If a GPUBuffer is passed, indexFormat must be provided.");
126
- return new TgpuRenderPipelineImpl(internals.core, {
127
- ...internals.priors,
128
- indexBuffer: {
129
- buffer,
130
- indexFormat: indexFormatOrOffset,
131
- offsetBytes: offsetElementsOrSizeBytes,
132
- sizeBytes: sizeElementsOrUndefined
133
- }
134
- });
135
- }
136
- const dataTypeToIndexFormat = {
137
- u32: "uint32",
138
- u16: "uint16"
139
- };
140
- const elementType = buffer.dataType.elementType;
141
- return new TgpuRenderPipelineImpl(internals.core, {
142
- ...internals.priors,
143
- indexBuffer: {
144
- buffer,
145
- indexFormat: dataTypeToIndexFormat[elementType.type],
146
- offsetBytes: indexFormatOrOffset !== void 0 ? indexFormatOrOffset * sizeOf(elementType) : void 0,
147
- sizeBytes: sizeElementsOrUndefined !== void 0 ? sizeElementsOrUndefined * sizeOf(elementType) : void 0
148
- }
149
- });
150
- }
151
- _createRenderPass(encoder) {
152
- const internals = this[$internal];
153
- const { root, descriptor } = internals.core.options;
154
- const memo = internals.core.unwrap();
155
- const colorAttachments = descriptor.fragment ? connectAttachmentToShader(descriptor.fragment?.shell?.returnType ?? memo.fragmentOut, internals.priors.colorAttachment ?? {}).map((_attachment) => {
156
- const attachment = {
157
- loadOp: "clear",
158
- storeOp: "store",
159
- ..._attachment
160
- };
161
- if (isTexture(attachment.view)) attachment.view = root.unwrap(attachment.view).createView();
162
- else if (isTextureView(attachment.view)) attachment.view = root.unwrap(attachment.view);
163
- else if (isGPUCanvasContext(attachment.view)) attachment.view = attachment.view.getCurrentTexture().createView();
164
- if (isTexture(attachment.resolveTarget)) attachment.resolveTarget = root.unwrap(attachment.resolveTarget).createView();
165
- else if (isTextureView(attachment.resolveTarget)) attachment.resolveTarget = root.unwrap(attachment.resolveTarget);
166
- else if (isGPUCanvasContext(attachment.resolveTarget)) attachment.resolveTarget = attachment.resolveTarget.getCurrentTexture().createView();
167
- return attachment;
168
- }) : [];
169
- const renderPassDescriptor = {
170
- label: getName(internals.core) ?? "<unnamed>",
171
- colorAttachments,
172
- ...setupTimestampWrites(internals.priors, root)
173
- };
174
- const depthStencil = internals.priors.depthStencilAttachment;
175
- if (depthStencil !== void 0) {
176
- const view = isTexture(depthStencil.view) ? root.unwrap(depthStencil.view).createView() : isTextureView(depthStencil.view) ? root.unwrap(depthStencil.view) : depthStencil.view;
177
- renderPassDescriptor.depthStencilAttachment = {
178
- ...depthStencil,
179
- view
180
- };
181
- }
182
- return encoder.beginRenderPass(renderPassDescriptor);
183
- }
184
- _applyRenderState(encoder) {
185
- const internals = this[$internal];
186
- const memo = internals.core.unwrap();
187
- const { root } = internals.core.options;
188
- encoder.setPipeline(memo.pipeline);
189
- applyBindGroups(encoder, root, memo.usedBindGroupLayouts, memo.catchall, (layout) => internals.priors.bindGroupLayoutMap?.get(layout));
190
- applyVertexBuffers(encoder, root, memo.usedVertexLayouts, (layout) => {
191
- const buffer = internals.priors.vertexLayoutMap?.get(layout);
192
- return buffer ? { buffer } : void 0;
193
- });
194
- if (internals.priors.stencilReference !== void 0 && "setStencilReference" in encoder) encoder.setStencilReference(internals.priors.stencilReference);
195
- }
196
- _setIndexBuffer(encoder) {
197
- const internals = this[$internal];
198
- const { root } = internals.core.options;
199
- if (!internals.priors.indexBuffer) throw new Error("No index buffer set for this render pipeline.");
200
- const { buffer, indexFormat, offsetBytes, sizeBytes } = internals.priors.indexBuffer;
201
- if (isGPUBuffer(buffer)) encoder.setIndexBuffer(buffer, indexFormat, offsetBytes, sizeBytes);
202
- else encoder.setIndexBuffer(root.unwrap(buffer), indexFormat, offsetBytes, sizeBytes);
203
- }
204
- draw(vertexCount, instanceCount, firstVertex, firstInstance) {
205
- const internals = this[$internal];
206
- const { root } = internals.core.options;
207
- if (internals.priors.externalRenderEncoder) {
208
- if (_lastAppliedRender.get(internals.priors.externalRenderEncoder) !== this) {
209
- this._applyRenderState(internals.priors.externalRenderEncoder);
210
- _lastAppliedRender.set(internals.priors.externalRenderEncoder, this);
211
- }
212
- internals.priors.externalRenderEncoder.draw(vertexCount, instanceCount, firstVertex, firstInstance);
213
- return;
214
- }
215
- if (internals.priors.externalEncoder) {
216
- const pass$1 = this._createRenderPass(internals.priors.externalEncoder);
217
- this._applyRenderState(pass$1);
218
- pass$1.draw(vertexCount, instanceCount, firstVertex, firstInstance);
219
- pass$1.end();
220
- return;
221
- }
222
- const { logResources } = internals.core.unwrap();
223
- const commandEncoder = root.device.createCommandEncoder();
224
- const pass = this._createRenderPass(commandEncoder);
225
- this._applyRenderState(pass);
226
- pass.draw(vertexCount, instanceCount, firstVertex, firstInstance);
227
- pass.end();
228
- root.device.queue.submit([commandEncoder.finish()]);
229
- if (logResources) logDataFromGPU(logResources);
230
- if (internals.priors.performanceCallback) triggerPerformanceCallback({
231
- root,
232
- priors: internals.priors
233
- });
234
- }
235
- drawIndexed(indexCount, instanceCount, firstIndex, baseVertex, firstInstance) {
236
- const internals = this[$internal];
237
- const { root } = internals.core.options;
238
- if (internals.priors.externalRenderEncoder) {
239
- if (_lastAppliedRender.get(internals.priors.externalRenderEncoder) !== this) {
240
- this._applyRenderState(internals.priors.externalRenderEncoder);
241
- this._setIndexBuffer(internals.priors.externalRenderEncoder);
242
- _lastAppliedRender.set(internals.priors.externalRenderEncoder, this);
243
- }
244
- internals.priors.externalRenderEncoder.drawIndexed(indexCount, instanceCount, firstIndex, baseVertex, firstInstance);
245
- return;
246
- }
247
- if (internals.priors.externalEncoder) {
248
- const pass$1 = this._createRenderPass(internals.priors.externalEncoder);
249
- this._applyRenderState(pass$1);
250
- this._setIndexBuffer(pass$1);
251
- pass$1.drawIndexed(indexCount, instanceCount, firstIndex, baseVertex, firstInstance);
252
- pass$1.end();
253
- return;
254
- }
255
- const { logResources } = internals.core.unwrap();
256
- const commandEncoder = root.device.createCommandEncoder();
257
- const pass = this._createRenderPass(commandEncoder);
258
- this._applyRenderState(pass);
259
- this._setIndexBuffer(pass);
260
- pass.drawIndexed(indexCount, instanceCount, firstIndex, baseVertex, firstInstance);
261
- pass.end();
262
- root.device.queue.submit([commandEncoder.finish()]);
263
- if (logResources) logDataFromGPU(logResources);
264
- if (internals.priors.performanceCallback) triggerPerformanceCallback({
265
- root,
266
- priors: internals.priors
267
- });
268
- }
269
- drawIndirect(indirectBuffer, indirectOffset) {
270
- const internals = this[$internal];
271
- const { root } = internals.core.options;
272
- const rawBuffer = isGPUBuffer(indirectBuffer) ? indirectBuffer : indirectBuffer.buffer;
273
- const offset = resolveIndirectOffset(indirectBuffer, indirectOffset, DRAW_INDIRECT_SIZE, "drawIndirect");
274
- if (internals.priors.externalRenderEncoder) {
275
- if (_lastAppliedRender.get(internals.priors.externalRenderEncoder) !== this) {
276
- this._applyRenderState(internals.priors.externalRenderEncoder);
277
- _lastAppliedRender.set(internals.priors.externalRenderEncoder, this);
278
- }
279
- internals.priors.externalRenderEncoder.drawIndirect(rawBuffer, offset);
280
- return;
281
- }
282
- if (internals.priors.externalEncoder) {
283
- const pass$1 = this._createRenderPass(internals.priors.externalEncoder);
284
- this._applyRenderState(pass$1);
285
- pass$1.drawIndirect(rawBuffer, offset);
286
- pass$1.end();
287
- return;
288
- }
289
- const { logResources } = internals.core.unwrap();
290
- const commandEncoder = root.device.createCommandEncoder();
291
- const pass = this._createRenderPass(commandEncoder);
292
- this._applyRenderState(pass);
293
- pass.drawIndirect(rawBuffer, offset);
294
- pass.end();
295
- root.device.queue.submit([commandEncoder.finish()]);
296
- if (logResources) logDataFromGPU(logResources);
297
- if (internals.priors.performanceCallback) triggerPerformanceCallback({
298
- root,
299
- priors: internals.priors
300
- });
301
- }
302
- drawIndexedIndirect(indirectBuffer, indirectOffset) {
303
- const internals = this[$internal];
304
- const { root } = internals.core.options;
305
- const rawBuffer = isGPUBuffer(indirectBuffer) ? indirectBuffer : root.unwrap(indirectBuffer);
306
- const offset = resolveIndirectOffset(indirectBuffer, indirectOffset, DRAW_INDEXED_INDIRECT_SIZE, "drawIndexedIndirect");
307
- if (internals.priors.externalRenderEncoder) {
308
- if (_lastAppliedRender.get(internals.priors.externalRenderEncoder) !== this) {
309
- this._applyRenderState(internals.priors.externalRenderEncoder);
310
- this._setIndexBuffer(internals.priors.externalRenderEncoder);
311
- _lastAppliedRender.set(internals.priors.externalRenderEncoder, this);
312
- }
313
- internals.priors.externalRenderEncoder.drawIndexedIndirect(rawBuffer, offset);
314
- return;
315
- }
316
- if (internals.priors.externalEncoder) {
317
- const pass$1 = this._createRenderPass(internals.priors.externalEncoder);
318
- this._applyRenderState(pass$1);
319
- this._setIndexBuffer(pass$1);
320
- pass$1.drawIndexedIndirect(rawBuffer, offset);
321
- pass$1.end();
322
- return;
323
- }
324
- const { logResources } = internals.core.unwrap();
325
- const commandEncoder = root.device.createCommandEncoder();
326
- const pass = this._createRenderPass(commandEncoder);
327
- this._applyRenderState(pass);
328
- this._setIndexBuffer(pass);
329
- pass.drawIndexedIndirect(rawBuffer, offset);
330
- pass.end();
331
- root.device.queue.submit([commandEncoder.finish()]);
332
- if (logResources) logDataFromGPU(logResources);
333
- if (internals.priors.performanceCallback) triggerPerformanceCallback({
334
- root,
335
- priors: internals.priors
336
- });
337
- }
338
- };
339
- var RenderPipelineCore = class {
340
- [$internal] = true;
341
- options;
342
- _memo;
343
- #latestAutoVertexIn;
344
- #latestAutoFragmentOut;
345
- #performanceCallbackQuerySet;
346
- constructor(options) {
347
- this.options = options;
348
- }
349
- [$resolve](ctx) {
350
- const { slotBindings } = this.options;
351
- const { vertex, fragment, attribs = {} } = this.options.descriptor;
352
- this.#latestAutoVertexIn = void 0;
353
- this.#latestAutoFragmentOut = void 0;
354
- const locations = matchUpVaryingLocations(vertex?.shell?.out, fragment?.shell?.in, getName(vertex) ?? "<unnamed>", getName(fragment) ?? "<unnamed>");
355
- return ctx.withVaryingLocations(locations, () => ctx.withSlots(slotBindings, () => {
356
- let vertexOut;
357
- if (typeof vertex === "function") {
358
- const autoFn = new AutoVertexFn(vertex, Object.fromEntries(Object.entries(attribs).map(([key, value]) => [key, formatToWGSLType[value.format]])), locations);
359
- ctx.resolve(autoFn);
360
- this.#latestAutoVertexIn = autoFn.autoIn.completeStruct.propTypes;
361
- vertexOut = autoFn.autoOut.completeStruct;
362
- } else vertexOut = ctx.resolve(vertex).dataType;
363
- if (fragment) if (typeof fragment === "function") {
364
- const varyings = Object.fromEntries(Object.entries(vertexOut.propTypes).filter(([, dataType]) => !isBuiltin(dataType)));
365
- this.#latestAutoFragmentOut = ctx.resolve(new AutoFragmentFn(fragment, varyings, locations)).dataType;
366
- } else ctx.resolve(fragment);
367
- return snip("", Void, "runtime");
368
- }));
369
- }
370
- toString() {
371
- return "renderPipelineCore";
372
- }
373
- get performanceCallbackQuerySet() {
374
- if (!this.options.root.enabledFeatures.has("timestamp-query")) return;
375
- return this.#performanceCallbackQuerySet ??= this.options.root.createQuerySet("timestamp", 2);
376
- }
377
- unwrap() {
378
- if (this._memo !== void 0) return this._memo;
379
- const { root, descriptor: tgpuDescriptor } = this.options;
380
- const device = root.device;
381
- const enableExtensions = wgslEnableExtensions.filter((extension) => root.enabledFeatures.has(wgslEnableExtensionToFeatureName[extension]));
382
- let resolutionResult;
383
- let resolveMeasure;
384
- const ns = namespace({ names: root.nameRegistrySetting });
385
- if (PERF?.enabled) {
386
- const resolveStart = performance.mark("typegpu:resolution:start");
387
- resolutionResult = resolve(this, {
388
- namespace: ns,
389
- enableExtensions,
390
- shaderGenerator: root.shaderGenerator,
391
- root
392
- });
393
- resolveMeasure = performance.measure("typegpu:resolution", { start: resolveStart.name });
394
- } else resolutionResult = resolve(this, {
395
- namespace: ns,
396
- enableExtensions,
397
- shaderGenerator: root.shaderGenerator,
398
- root
399
- });
400
- const { code, usedBindGroupLayouts, catchall, logResources } = resolutionResult;
401
- if (catchall !== void 0) usedBindGroupLayouts[catchall[0]]?.$name(`${getName(this) ?? "<unnamed>"} - Automatic Bind Group & Layout`);
402
- const module = device.createShaderModule({
403
- label: `${getName(this) ?? "<unnamed>"} - Shader`,
404
- code
405
- });
406
- const { vertex, fragment, attribs = {}, targets } = this.options.descriptor;
407
- const connectedAttribs = connectAttributesToShader(vertex?.shell?.in ?? this.#latestAutoVertexIn ?? {}, attribs);
408
- const fragmentOut = fragment?.shell?.returnType ?? this.#latestAutoFragmentOut;
409
- const connectedTargets = fragmentOut ? connectTargetsToShader(fragmentOut, targets) : [null];
410
- const descriptor = {
411
- layout: device.createPipelineLayout({
412
- label: `${getName(this) ?? "<unnamed>"} - Pipeline Layout`,
413
- bindGroupLayouts: usedBindGroupLayouts.map((l) => root.unwrap(l))
414
- }),
415
- vertex: {
416
- module,
417
- buffers: connectedAttribs.bufferDefinitions
418
- }
419
- };
420
- const label = getName(this);
421
- if (label !== void 0) descriptor.label = label;
422
- if (tgpuDescriptor.fragment) descriptor.fragment = {
423
- module,
424
- targets: connectedTargets
425
- };
426
- if (tgpuDescriptor.primitive) if (isWgslData(tgpuDescriptor.primitive.stripIndexFormat)) descriptor.primitive = {
427
- ...tgpuDescriptor.primitive,
428
- stripIndexFormat: {
429
- u32: "uint32",
430
- u16: "uint16"
431
- }[tgpuDescriptor.primitive.stripIndexFormat.type]
432
- };
433
- else descriptor.primitive = tgpuDescriptor.primitive;
434
- if (tgpuDescriptor.depthStencil) descriptor.depthStencil = tgpuDescriptor.depthStencil;
435
- if (tgpuDescriptor.multisample) descriptor.multisample = tgpuDescriptor.multisample;
436
- this._memo = {
437
- pipeline: device.createRenderPipeline(descriptor),
438
- usedBindGroupLayouts,
439
- catchall,
440
- logResources,
441
- usedVertexLayouts: connectedAttribs.usedVertexLayouts,
442
- fragmentOut: this.#latestAutoFragmentOut
443
- };
444
- if (PERF?.enabled) (async () => {
445
- const start = performance.mark("typegpu:compile-start");
446
- await device.queue.onSubmittedWorkDone();
447
- const compileMeasure = performance.measure("typegpu:compiled", { start: start.name });
448
- PERF?.record("resolution", {
449
- resolveDuration: resolveMeasure?.duration,
450
- compileDuration: compileMeasure.duration,
451
- wgslSize: code.length
452
- });
453
- })();
454
- return this._memo;
455
- }
456
- };
457
- /**
458
- * Assumes vertexOut and fragmentIn are matching when it comes to the keys, that is fragmentIn's keyset is a subset of vertexOut's
459
- * Logs a warning, when they don't match in terms of custom locations
460
- */
461
- function matchUpVaryingLocations(vertexOut = {}, fragmentIn = {}, vertexFnName, fragmentFnName) {
462
- const locations = {};
463
- const usedLocations = /* @__PURE__ */ new Set();
464
- function saveLocation(key, location) {
465
- locations[key] = location;
466
- usedLocations.add(location);
467
- }
468
- for (const [key, value] of Object.entries(vertexOut)) {
469
- const customLocation = getCustomLocation(value);
470
- if (customLocation !== void 0) saveLocation(key, customLocation);
471
- }
472
- for (const [key, value] of Object.entries(fragmentIn)) {
473
- const customLocation = getCustomLocation(value);
474
- if (customLocation === void 0) continue;
475
- if (locations[key] === void 0) saveLocation(key, customLocation);
476
- else if (locations[key] !== customLocation) console.warn(`Mismatched location between vertexFn (${vertexFnName}) output (${locations[key]}) and fragmentFn (${fragmentFnName}) input (${customLocation}) for the key "${key}", using the location set on vertex output.`);
477
- }
478
- let nextLocation = 0;
479
- for (const key of Object.keys(vertexOut ?? {})) {
480
- if (isBuiltin(vertexOut[key]) || locations[key] !== void 0) continue;
481
- while (usedLocations.has(nextLocation)) nextLocation++;
482
- saveLocation(key, nextLocation);
483
- }
484
- return locations;
34
+ export function INTERNAL_restoreRenderPipeline(soul, ctx) {
35
+ invariant(soul.raw, 'A render pipeline soul is only complete once materialized.');
36
+ const root = ctx.getRoot(soul.device);
37
+ const core = RenderPipelineCore.precompiled(root, {
38
+ pipeline: soul.raw,
39
+ usedBindGroupLayouts: soul.usedBindGroupLayouts ?? [],
40
+ // The catchall group is already one of `bindGroups`, keyed by the layout it was resolved with
41
+ catchall: undefined,
42
+ logResources: undefined,
43
+ usedVertexLayouts: soul.usedVertexLayouts ?? [],
44
+ fragmentOut: soul.fragmentOut,
45
+ });
46
+ const pipeline = new TgpuRenderPipelineImpl(core, {
47
+ bindGroupLayoutMap: new Map(soul.bindGroups),
48
+ vertexLayoutMap: new Map(soul.vertexBuffers),
49
+ indexBuffer: soul.indexBuffer,
50
+ stencilReference: soul.stencilReference,
51
+ });
52
+ return restoreTimestampPriors(pipeline, soul);
485
53
  }
486
- function isGPUCanvasContext(value) {
487
- return typeof value?.getCurrentTexture === "function";
54
+ class TgpuRenderPipelineImpl {
55
+ [$internal];
56
+ [$soul];
57
+ resourceType = 'render-pipeline';
58
+ [$getNameForward];
59
+ constructor(core, priors) {
60
+ this[$soul] = {
61
+ type: 'render-pipeline',
62
+ device: core.options.root.device,
63
+ raw: undefined,
64
+ label: undefined,
65
+ };
66
+ this[$internal] = {
67
+ core,
68
+ priors,
69
+ root: core.options.root,
70
+ materialize: () => {
71
+ const soul = this[$soul];
72
+ if (!soul.raw) {
73
+ const memo = core.unwrap();
74
+ soul.raw = memo.pipeline;
75
+ soul.usedBindGroupLayouts = memo.usedBindGroupLayouts;
76
+ soul.usedVertexLayouts = memo.usedVertexLayouts;
77
+ soul.fragmentOut = memo.fragmentOut;
78
+ soul.bindGroups = collectBindGroupPairs(memo.usedBindGroupLayouts, memo.catchall, priors.bindGroupLayoutMap);
79
+ soul.vertexBuffers = collectVertexBufferPairs(memo.usedVertexLayouts, priors.vertexLayoutMap);
80
+ soul.indexBuffer = priors.indexBuffer;
81
+ soul.stencilReference = priors.stencilReference;
82
+ soul.timestampWrites = priors.timestampWrites;
83
+ soul.performanceCallback = priors.performanceCallback;
84
+ soul.nonTransferablePriors = nonTransferablePriorsOf(priors);
85
+ }
86
+ return soul.raw;
87
+ },
88
+ };
89
+ this[$getNameForward] = core;
90
+ }
91
+ [$resolve](ctx) {
92
+ return ctx.resolve(this[$internal].core);
93
+ }
94
+ toString() {
95
+ return `renderPipeline:${getName(this) ?? '<unnamed>'}`;
96
+ }
97
+ $name(label) {
98
+ setName(this, label);
99
+ return this;
100
+ }
101
+ #withPriors(patch) {
102
+ const { core, priors } = this[$internal];
103
+ return new TgpuRenderPipelineImpl(core, { ...priors, ...patch });
104
+ }
105
+ with(first, resource) {
106
+ const internals = this[$internal];
107
+ if (isTgpuRenderCommands(first)) {
108
+ return this.#withPriors({ pass: first, encoder: undefined });
109
+ }
110
+ if (isTgpuCommandEncoder(first)) {
111
+ return this.#withPriors({ pass: undefined, encoder: first });
112
+ }
113
+ if (isGPURenderPassEncoder(first) || isGPURenderBundleEncoder(first)) {
114
+ return this.#withPriors({
115
+ pass: INTERNAL_adoptRenderCommands(internals.root, first),
116
+ encoder: undefined,
117
+ });
118
+ }
119
+ if (isGPUCommandEncoder(first)) {
120
+ return this.#withPriors({
121
+ pass: undefined,
122
+ encoder: INTERNAL_adoptCommandEncoder(internals.root, first),
123
+ });
124
+ }
125
+ if (isBindGroup(first) || isBindGroupLayout(first)) {
126
+ const [layout, group] = isBindGroup(first)
127
+ ? [first.layout, first]
128
+ : [first, resource];
129
+ return this.#withPriors({
130
+ bindGroupLayoutMap: new Map([
131
+ ...(internals.priors.bindGroupLayoutMap ?? []),
132
+ [layout, group],
133
+ ]),
134
+ });
135
+ }
136
+ if (isVertexLayout(first)) {
137
+ return this.#withPriors({
138
+ vertexLayoutMap: new Map([
139
+ ...(internals.priors.vertexLayoutMap ?? []),
140
+ [first, resource],
141
+ ]),
142
+ });
143
+ }
144
+ throw new Error('Unsupported value passed into .with()');
145
+ }
146
+ withPerformanceCallback(callback) {
147
+ const internals = this[$internal];
148
+ if (internals.priors.timestampWrites) {
149
+ return this.#withPriors({ performanceCallback: callback });
150
+ }
151
+ const querySet = internals.core.performanceCallbackQuerySet;
152
+ if (!querySet) {
153
+ logger.warn('webgpu-feature-missing', 'Performance callback cannot be used because the timestamp-query feature is not enabled on the root.');
154
+ return this;
155
+ }
156
+ return this.#withPriors(createWithPerformanceCallback(internals.priors, callback, querySet));
157
+ }
158
+ withTimestampWrites(options) {
159
+ const internals = this[$internal];
160
+ return this.#withPriors(createWithTimestampWrites(internals.priors, options, internals.root));
161
+ }
162
+ withColorAttachment(attachment) {
163
+ return this.#withPriors({ colorAttachment: attachment });
164
+ }
165
+ withDepthStencilAttachment(attachment) {
166
+ return this.#withPriors({ depthStencilAttachment: attachment });
167
+ }
168
+ withStencilReference(reference) {
169
+ return this.#withPriors({ stencilReference: reference });
170
+ }
171
+ withIndexBuffer(buffer, indexFormatOrOffset, offsetElementsOrSizeBytes, sizeElementsOrUndefined) {
172
+ if (isGPUBuffer(buffer)) {
173
+ if (typeof indexFormatOrOffset !== 'string') {
174
+ throw new Error('If a GPUBuffer is passed, indexFormat must be provided.');
175
+ }
176
+ return this.#withPriors({
177
+ indexBuffer: {
178
+ buffer,
179
+ indexFormat: indexFormatOrOffset,
180
+ offsetBytes: offsetElementsOrSizeBytes,
181
+ sizeBytes: sizeElementsOrUndefined,
182
+ },
183
+ });
184
+ }
185
+ const dataTypeToIndexFormat = {
186
+ u32: 'uint32',
187
+ u16: 'uint16',
188
+ };
189
+ const elementType = buffer.dataType.elementType;
190
+ return this.#withPriors({
191
+ indexBuffer: {
192
+ buffer,
193
+ indexFormat: dataTypeToIndexFormat[elementType.type],
194
+ offsetBytes: indexFormatOrOffset !== undefined
195
+ ? indexFormatOrOffset * sizeOf(elementType)
196
+ : undefined,
197
+ sizeBytes: sizeElementsOrUndefined !== undefined
198
+ ? sizeElementsOrUndefined * sizeOf(elementType)
199
+ : undefined,
200
+ },
201
+ });
202
+ }
203
+ initAsync() {
204
+ return this[$internal].core.initAsync();
205
+ }
206
+ initSync() {
207
+ this[$internal].core.initSync();
208
+ }
209
+ get hasIndexBuffer() {
210
+ return this[$internal].priors.indexBuffer !== undefined;
211
+ }
212
+ #ownPassDescriptor() {
213
+ const { core, priors } = this[$internal];
214
+ const { fragmentOut } = core.unwrap();
215
+ return {
216
+ label: getName(core) ?? '<unnamed>',
217
+ colorAttachments: fragmentOut
218
+ ? connectAttachmentToShader(fragmentOut, priors.colorAttachment ?? {})
219
+ : [],
220
+ depthStencilAttachment: priors.depthStencilAttachment,
221
+ timestampWrites: priors.timestampWrites,
222
+ };
223
+ }
224
+ #execute(usesIndexBuffer, emit) {
225
+ const { core, priors, root } = this[$internal];
226
+ if (priors.pass) {
227
+ emitRenderDraw(root, priors.pass[$internal], this, usesIndexBuffer, emit);
228
+ return;
229
+ }
230
+ // checked up front so a rejected draw never leaves a half-recorded pass behind
231
+ if (usesIndexBuffer) {
232
+ requireIndexBuffer(priors.indexBuffer);
233
+ }
234
+ const encoder = priors.encoder ?? INTERNAL_createCommandEncoder(root);
235
+ const pass = encoder.beginRenderPass(this.#ownPassDescriptor());
236
+ emitRenderDraw(root, pass[$internal], this, usesIndexBuffer, emit, /* ownsPass */ true);
237
+ pass.end();
238
+ finalizeOwnEncoder(encoder, core, core.unwrap().logResources, priors);
239
+ }
240
+ draw(vertexCount, instanceCount, firstVertex, firstInstance) {
241
+ this.#execute(false, (rawPass) => rawPass.draw(vertexCount, instanceCount, firstVertex, firstInstance));
242
+ }
243
+ drawIndexed(indexCount, instanceCount, firstIndex, baseVertex, firstInstance) {
244
+ this.#execute(true, (rawPass) => rawPass.drawIndexed(indexCount, instanceCount, firstIndex, baseVertex, firstInstance));
245
+ }
246
+ drawIndirect(indirectBuffer, indirectOffset) {
247
+ const rawBuffer = isGPUBuffer(indirectBuffer) ? indirectBuffer : indirectBuffer.buffer;
248
+ const offset = resolveIndirectOffset(indirectBuffer, indirectOffset, DRAW_INDIRECT_SIZE, 'drawIndirect');
249
+ this.#execute(false, (rawPass) => rawPass.drawIndirect(rawBuffer, offset));
250
+ }
251
+ drawIndexedIndirect(indirectBuffer, indirectOffset) {
252
+ const rawBuffer = isGPUBuffer(indirectBuffer) ? indirectBuffer : indirectBuffer.buffer;
253
+ const offset = resolveIndirectOffset(indirectBuffer, indirectOffset, DRAW_INDEXED_INDIRECT_SIZE, 'drawIndexedIndirect');
254
+ this.#execute(true, (rawPass) => rawPass.drawIndexedIndirect(rawBuffer, offset));
255
+ }
256
+ }
257
+ class RenderPipelineCore {
258
+ [$internal] = true;
259
+ options;
260
+ #performanceTracker;
261
+ #initAsyncPromise;
262
+ #memo;
263
+ #latestAutoVertexIn;
264
+ #latestAutoFragmentOut;
265
+ #performanceCallbackQuerySet;
266
+ constructor(options) {
267
+ this.options = options;
268
+ this.#performanceTracker = PERF?.enabled
269
+ ? new PerformanceTrackerImpl()
270
+ : new NullPerformanceTracker();
271
+ }
272
+ static precompiled(root, memo) {
273
+ const core = new RenderPipelineCore({
274
+ root,
275
+ slotBindings: [],
276
+ descriptor: undefined,
277
+ });
278
+ core.#memo = memo;
279
+ return core;
280
+ }
281
+ [$resolve](ctx) {
282
+ const { slotBindings } = this.options;
283
+ const { vertex, fragment, attribs = {} } = this.options.descriptor ?? {};
284
+ if (!vertex) {
285
+ return snip('', Void, /* origin */ 'runtime');
286
+ }
287
+ this.#latestAutoVertexIn = undefined;
288
+ this.#latestAutoFragmentOut = undefined;
289
+ const locations = matchUpVaryingLocations(vertex?.shell?.out, fragment?.shell?.in, getName(vertex) ?? '<unnamed>', getName(fragment) ?? '<unnamed>');
290
+ return ctx.withVaryingLocations(locations, () => ctx.withSlots(slotBindings, () => {
291
+ let vertexOut;
292
+ if (typeof vertex === 'function') {
293
+ const defaultAttribData = Object.fromEntries(Object.entries(attribs).map(([key, value]) => [
294
+ key,
295
+ formatToWGSLType[value.format],
296
+ ]));
297
+ const autoFn = new AutoVertexFn(vertex, defaultAttribData, locations);
298
+ ctx.resolve(autoFn);
299
+ this.#latestAutoVertexIn = autoFn.autoIn.completeStruct.propTypes;
300
+ vertexOut = autoFn.autoOut.completeStruct;
301
+ }
302
+ else {
303
+ vertexOut = ctx.resolve(vertex).dataType;
304
+ }
305
+ if (fragment) {
306
+ if (typeof fragment === 'function') {
307
+ const varyings = Object.fromEntries(Object.entries(vertexOut.propTypes).filter(([, dataType]) => !isBuiltin(dataType)));
308
+ const fragOut = ctx.resolve(new AutoFragmentFn(fragment, varyings, locations));
309
+ this.#latestAutoFragmentOut = fragOut.dataType;
310
+ }
311
+ else {
312
+ ctx.resolve(fragment);
313
+ }
314
+ }
315
+ return snip('', Void, /* origin */ 'runtime');
316
+ }));
317
+ }
318
+ toString() {
319
+ return 'renderPipelineCore';
320
+ }
321
+ get performanceCallbackQuerySet() {
322
+ if (!this.options.root.enabledFeatures.has('timestamp-query')) {
323
+ return undefined;
324
+ }
325
+ return (this.#performanceCallbackQuerySet ??= this.options.root.createQuerySet('timestamp', 2));
326
+ }
327
+ initAsync() {
328
+ if (this.#memo !== undefined) {
329
+ // the pipeline was already resolved & compiled
330
+ return Promise.resolve();
331
+ }
332
+ if (this.#initAsyncPromise === undefined) {
333
+ // the pipeline did not start resolution & compilation
334
+ const device = this.options.root.device;
335
+ const { resolutionResult, descriptor, connectedAttribs, fragmentOut } = this.resolveAndCreateShaderModule();
336
+ const { usedBindGroupLayouts, catchall, logResources } = resolutionResult;
337
+ this.#initAsyncPromise = device
338
+ .createRenderPipelineAsync(descriptor)
339
+ .then((pipeline) => {
340
+ this.#memo = {
341
+ pipeline,
342
+ usedBindGroupLayouts,
343
+ catchall,
344
+ logResources,
345
+ usedVertexLayouts: connectedAttribs.usedVertexLayouts,
346
+ fragmentOut,
347
+ };
348
+ this.#performanceTracker.measureCompile(device);
349
+ })
350
+ .finally(() => {
351
+ this.#initAsyncPromise = undefined;
352
+ });
353
+ }
354
+ return this.#initAsyncPromise;
355
+ }
356
+ initSync() {
357
+ if (this.#memo !== undefined) {
358
+ return;
359
+ }
360
+ if (this.#initAsyncPromise !== undefined) {
361
+ throw new Error("'pipeline.initAsync()' was called and is not yet resolved.");
362
+ }
363
+ const device = this.options.root.device;
364
+ const { resolutionResult, descriptor, connectedAttribs, fragmentOut } = this.resolveAndCreateShaderModule();
365
+ const { usedBindGroupLayouts, catchall, logResources } = resolutionResult;
366
+ this.#memo = {
367
+ pipeline: device.createRenderPipeline(descriptor),
368
+ usedBindGroupLayouts,
369
+ catchall,
370
+ logResources,
371
+ usedVertexLayouts: connectedAttribs.usedVertexLayouts,
372
+ fragmentOut,
373
+ };
374
+ this.#performanceTracker.measureCompile(device);
375
+ }
376
+ unwrap() {
377
+ this.initSync();
378
+ return this.#memo;
379
+ }
380
+ resolveAndCreateShaderModule() {
381
+ const { root, descriptor: tgpuDescriptor } = this.options;
382
+ if (!tgpuDescriptor) {
383
+ throw new Error('Precompiled pipelines are never resolved again.');
384
+ }
385
+ const device = root.device;
386
+ const enableExtensions = wgslEnableExtensions.filter((extension) => root.enabledFeatures.has(wgslEnableExtensionToFeatureName[extension]));
387
+ // Resolving code
388
+ const ns = namespace({ names: root.nameRegistrySetting });
389
+ const resolutionResult = this.#performanceTracker.measureResolve(() => resolve(this, {
390
+ namespace: ns,
391
+ minify: root.minify,
392
+ enableExtensions,
393
+ shaderGenerator: root.shaderGeneratorClass ? new root.shaderGeneratorClass() : undefined,
394
+ root,
395
+ }));
396
+ const { code, usedBindGroupLayouts, catchall } = resolutionResult;
397
+ if (catchall !== undefined) {
398
+ usedBindGroupLayouts[catchall[0]]?.$name(`${getName(this) ?? '<unnamed>'} - Automatic Bind Group & Layout`);
399
+ }
400
+ warnIfOverflow(usedBindGroupLayouts, device.limits);
401
+ const module = device.createShaderModule({
402
+ label: `${getName(this) ?? '<unnamed>'} - Shader`,
403
+ code,
404
+ });
405
+ const { vertex, fragment, attribs = {}, targets } = tgpuDescriptor;
406
+ const connectedAttribs = connectAttributesToShader(vertex?.shell?.in ?? this.#latestAutoVertexIn ?? {}, attribs);
407
+ // If the fragment output is a single builtin, then this.#latestAutoFragmentOut doesn't
408
+ // retain that information, that's why we use that here and fallback to this.#latestAutoFragmentOut.
409
+ // One other reason is that if the shelled fragment has already been resolved in this namespace,
410
+ // then this.#latestAutoFragmentOut will be undefined.
411
+ const fragmentOut = fragment?.shell?.returnType ?? this.#latestAutoFragmentOut;
412
+ const connectedTargets = fragmentOut ? connectTargetsToShader(fragmentOut, targets) : [null];
413
+ const descriptor = {
414
+ layout: device.createPipelineLayout({
415
+ label: `${getName(this) ?? '<unnamed>'} - Pipeline Layout`,
416
+ bindGroupLayouts: usedBindGroupLayouts.map((l) => root.unwrap(l)),
417
+ }),
418
+ vertex: {
419
+ module,
420
+ buffers: connectedAttribs.bufferDefinitions,
421
+ },
422
+ };
423
+ const label = getName(this);
424
+ if (label !== undefined) {
425
+ descriptor.label = label;
426
+ }
427
+ if (tgpuDescriptor.fragment) {
428
+ descriptor.fragment = {
429
+ module,
430
+ targets: connectedTargets,
431
+ };
432
+ }
433
+ if (tgpuDescriptor.primitive) {
434
+ if (isWgslData(tgpuDescriptor.primitive.stripIndexFormat)) {
435
+ descriptor.primitive = {
436
+ ...tgpuDescriptor.primitive,
437
+ stripIndexFormat: {
438
+ u32: 'uint32',
439
+ u16: 'uint16',
440
+ }[tgpuDescriptor.primitive.stripIndexFormat.type],
441
+ };
442
+ }
443
+ else {
444
+ descriptor.primitive = tgpuDescriptor.primitive;
445
+ }
446
+ }
447
+ if (tgpuDescriptor.depthStencil) {
448
+ descriptor.depthStencil = tgpuDescriptor.depthStencil;
449
+ }
450
+ if (tgpuDescriptor.multisample) {
451
+ descriptor.multisample = tgpuDescriptor.multisample;
452
+ }
453
+ return { resolutionResult, descriptor, connectedAttribs, fragmentOut };
454
+ }
455
+ }
456
+ /**
457
+ * Assumes vertexOut and fragmentIn are matching when it comes to the keys, that is fragmentIn's keyset is a subset of vertexOut's
458
+ * Logs a warning, when they don't match in terms of custom locations
459
+ */
460
+ export function matchUpVaryingLocations(vertexOut = {}, fragmentIn = {}, vertexFnName, fragmentFnName) {
461
+ const locations = {};
462
+ const usedLocations = new Set();
463
+ function saveLocation(key, location) {
464
+ locations[key] = location;
465
+ usedLocations.add(location);
466
+ }
467
+ // respect custom locations and pair up vertex and fragment varying with the same key
468
+ for (const [key, value] of Object.entries(vertexOut)) {
469
+ const customLocation = getCustomLocation(value);
470
+ if (customLocation !== undefined) {
471
+ saveLocation(key, customLocation);
472
+ }
473
+ }
474
+ for (const [key, value] of Object.entries(fragmentIn)) {
475
+ const customLocation = getCustomLocation(value);
476
+ if (customLocation === undefined) {
477
+ continue;
478
+ }
479
+ if (locations[key] === undefined) {
480
+ saveLocation(key, customLocation);
481
+ }
482
+ else if (locations[key] !== customLocation) {
483
+ logger.warn('locations-mismatched', `Mismatched location between vertexFn (${vertexFnName}) output (${locations[key]}) and fragmentFn (${fragmentFnName}) input (${customLocation}) for the key "${key}", using the location set on vertex output.`);
484
+ }
485
+ }
486
+ // automatically assign remaining locations to the rest
487
+ let nextLocation = 0;
488
+ for (const key of Object.keys(vertexOut ?? {})) {
489
+ if (isBuiltin(vertexOut[key]) || locations[key] !== undefined) {
490
+ continue;
491
+ }
492
+ while (usedLocations.has(nextLocation)) {
493
+ nextLocation++;
494
+ }
495
+ saveLocation(key, nextLocation);
496
+ }
497
+ return locations;
488
498
  }
489
-
490
- //#endregion
491
- export { INTERNAL_createRenderPipeline };