typegpu 0.11.8 → 0.12.0

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 (362) hide show
  1. package/builtin.d.ts +51 -53
  2. package/builtin.js +30 -34
  3. package/common/fullScreenTriangle.d.ts +2 -10
  4. package/common/fullScreenTriangle.js +20 -28
  5. package/common/index.d.ts +2 -9
  6. package/common/index.js +3 -12
  7. package/common/writeSoA.d.ts +11 -12
  8. package/common/writeSoA.js +88 -76
  9. package/core/buffer/buffer.d.ts +79 -62
  10. package/core/buffer/buffer.js +279 -205
  11. package/core/buffer/bufferBinding.d.ts +71 -0
  12. package/core/buffer/bufferBinding.js +154 -0
  13. package/core/buffer/bufferUsage.d.ts +14 -45
  14. package/core/buffer/bufferUsage.js +1 -171
  15. package/core/buffer/laidOutBuffer.d.ts +25 -0
  16. package/core/buffer/laidOutBuffer.js +55 -0
  17. package/core/commandEncoder/attachments.d.ts +125 -0
  18. package/core/commandEncoder/attachments.js +29 -0
  19. package/core/commandEncoder/commandEncoder.d.ts +53 -0
  20. package/core/commandEncoder/commandEncoder.js +56 -0
  21. package/core/commandEncoder/computePass.d.ts +58 -0
  22. package/core/commandEncoder/computePass.js +63 -0
  23. package/core/commandEncoder/renderPass.d.ts +121 -0
  24. package/core/commandEncoder/renderPass.js +196 -0
  25. package/core/constant/tgpuConstant.d.ts +26 -26
  26. package/core/constant/tgpuConstant.js +76 -65
  27. package/core/declare/tgpuDeclare.d.ts +3 -6
  28. package/core/declare/tgpuDeclare.js +37 -38
  29. package/core/function/autoIO.d.ts +61 -33
  30. package/core/function/autoIO.js +68 -73
  31. package/core/function/comptime.d.ts +11 -13
  32. package/core/function/comptime.js +60 -52
  33. package/core/function/createCallableSchema.d.ts +16 -0
  34. package/core/function/createCallableSchema.js +50 -40
  35. package/core/function/dualImpl.d.ts +44 -0
  36. package/core/function/dualImpl.js +71 -50
  37. package/core/function/entryInputRouter.d.ts +26 -0
  38. package/core/function/entryInputRouter.js +31 -33
  39. package/core/function/extractArgs.d.ts +38 -0
  40. package/core/function/extractArgs.js +202 -200
  41. package/core/function/fnCore.d.ts +44 -0
  42. package/core/function/fnCore.js +148 -92
  43. package/core/function/fnTypes.d.ts +31 -29
  44. package/core/function/fnTypes.js +1 -0
  45. package/core/function/ioSchema.d.ts +12 -10
  46. package/core/function/ioSchema.js +65 -47
  47. package/core/function/shelllessImpl.d.ts +9 -12
  48. package/core/function/shelllessImpl.js +18 -20
  49. package/core/function/templateUtils.d.ts +2 -0
  50. package/core/function/templateUtils.js +9 -8
  51. package/core/function/tgpuComputeFn.d.ts +26 -28
  52. package/core/function/tgpuComputeFn.js +47 -48
  53. package/core/function/tgpuFn.d.ts +34 -37
  54. package/core/function/tgpuFn.js +179 -153
  55. package/core/function/tgpuFragmentFn.d.ts +52 -53
  56. package/core/function/tgpuFragmentFn.js +63 -56
  57. package/core/function/tgpuVertexFn.d.ts +36 -39
  58. package/core/function/tgpuVertexFn.js +56 -53
  59. package/core/pipeline/computePipeline.d.ts +141 -53
  60. package/core/pipeline/computePipeline.js +291 -225
  61. package/core/pipeline/connectAttachmentToShader.d.ts +4 -0
  62. package/core/pipeline/connectAttachmentToShader.js +25 -22
  63. package/core/pipeline/connectTargetsToShader.d.ts +3 -0
  64. package/core/pipeline/connectTargetsToShader.js +29 -27
  65. package/core/pipeline/drawState.d.ts +52 -0
  66. package/core/pipeline/drawState.js +225 -0
  67. package/core/pipeline/limitsOverflow.d.ts +2 -0
  68. package/core/pipeline/limitsOverflow.js +13 -10
  69. package/core/pipeline/performanceTracker.d.ts +14 -0
  70. package/core/pipeline/performanceTracker.js +34 -0
  71. package/core/pipeline/pipelineUtils.d.ts +18 -0
  72. package/core/pipeline/pipelineUtils.js +54 -25
  73. package/core/pipeline/priors.d.ts +1 -0
  74. package/core/pipeline/priors.js +12 -0
  75. package/core/pipeline/renderPipeline.d.ts +246 -261
  76. package/core/pipeline/renderPipeline.js +487 -480
  77. package/core/pipeline/timeable.d.ts +28 -18
  78. package/core/pipeline/timeable.js +90 -52
  79. package/core/pipeline/typeGuards.d.ts +17 -0
  80. package/core/pipeline/typeGuards.js +52 -22
  81. package/core/querySet/querySet.d.ts +26 -21
  82. package/core/querySet/querySet.js +127 -103
  83. package/core/rawCodeSnippet/tgpuRawCodeSnippet.d.ts +13 -18
  84. package/core/rawCodeSnippet/tgpuRawCodeSnippet.js +90 -93
  85. package/core/resolve/externals.d.ts +25 -7
  86. package/core/resolve/externals.js +79 -62
  87. package/core/resolve/namespace.d.ts +22 -25
  88. package/core/resolve/namespace.js +16 -21
  89. package/core/resolve/resolvableString.d.ts +7 -0
  90. package/core/resolve/resolvableString.js +13 -0
  91. package/core/resolve/resolveData.d.ts +10 -0
  92. package/core/resolve/resolveData.js +162 -121
  93. package/core/resolve/stitch.d.ts +8 -0
  94. package/core/resolve/stitch.js +23 -21
  95. package/core/resolve/tgpuResolve.d.ts +55 -53
  96. package/core/resolve/tgpuResolve.js +106 -55
  97. package/core/root/configurableImpl.d.ts +10 -0
  98. package/core/root/configurableImpl.js +17 -19
  99. package/core/root/init.d.ts +76 -38
  100. package/core/root/init.js +346 -454
  101. package/core/root/rootTypes.d.ts +461 -627
  102. package/core/root/rootTypes.js +1 -0
  103. package/core/sampler/sampler.d.ts +50 -31
  104. package/core/sampler/sampler.js +120 -113
  105. package/core/simulate/tgpuSimulate.d.ts +9 -12
  106. package/core/simulate/tgpuSimulate.js +68 -71
  107. package/core/slot/accessor.d.ts +36 -13
  108. package/core/slot/accessor.js +138 -91
  109. package/core/slot/internalSlots.d.ts +2 -0
  110. package/core/slot/internalSlots.js +1 -6
  111. package/core/slot/lazy.d.ts +2 -6
  112. package/core/slot/lazy.js +71 -39
  113. package/core/slot/slot.d.ts +2 -6
  114. package/core/slot/slot.js +45 -38
  115. package/core/slot/slotTypes.d.ts +78 -80
  116. package/core/slot/slotTypes.js +11 -16
  117. package/core/texture/externalTexture.d.ts +20 -11
  118. package/core/texture/externalTexture.js +46 -46
  119. package/core/texture/texture.d.ts +152 -97
  120. package/core/texture/texture.js +407 -314
  121. package/core/texture/textureFormats.d.ts +42 -23
  122. package/core/texture/textureFormats.js +104 -75
  123. package/core/texture/textureProps.d.ts +7 -10
  124. package/core/texture/textureProps.js +1 -0
  125. package/core/texture/textureUtils.d.ts +8 -0
  126. package/core/texture/textureUtils.js +185 -179
  127. package/core/texture/usageExtension.d.ts +21 -18
  128. package/core/texture/usageExtension.js +13 -17
  129. package/core/unroll/tgpuUnroll.d.ts +20 -19
  130. package/core/unroll/tgpuUnroll.js +82 -91
  131. package/core/valueProxyUtils.d.ts +3 -0
  132. package/core/valueProxyUtils.js +52 -41
  133. package/core/variable/tgpuVariable.d.ts +26 -27
  134. package/core/variable/tgpuVariable.js +93 -96
  135. package/core/vertexLayout/connectAttributesToShader.d.ts +9 -0
  136. package/core/vertexLayout/connectAttributesToShader.js +61 -56
  137. package/core/vertexLayout/vertexAttribute.d.ts +21 -17
  138. package/core/vertexLayout/vertexAttribute.js +1 -0
  139. package/core/vertexLayout/vertexLayout.d.ts +24 -18
  140. package/core/vertexLayout/vertexLayout.js +130 -99
  141. package/core/whitespaces.d.ts +2 -0
  142. package/core/whitespaces.js +16 -0
  143. package/data/alignIO.d.ts +7 -0
  144. package/data/alignIO.js +13 -13
  145. package/data/alignmentOf.d.ts +5 -8
  146. package/data/alignmentOf.js +90 -75
  147. package/data/array.d.ts +6 -9
  148. package/data/array.js +48 -40
  149. package/data/atomic.d.ts +2 -7
  150. package/data/atomic.js +26 -23
  151. package/data/attributes.d.ts +19 -21
  152. package/data/attributes.js +192 -132
  153. package/data/autoStruct.d.ts +36 -3
  154. package/data/autoStruct.js +84 -81
  155. package/data/compiledIO.d.ts +5 -0
  156. package/data/compiledIO.js +231 -214
  157. package/data/dataIO.d.ts +13 -11
  158. package/data/dataIO.js +643 -589
  159. package/data/dataTypes.d.ts +83 -65
  160. package/data/dataTypes.js +66 -68
  161. package/data/deepEqual.d.ts +2 -7
  162. package/data/deepEqual.js +80 -55
  163. package/data/disarray.d.ts +6 -10
  164. package/data/disarray.js +52 -46
  165. package/data/float16Conversion.d.ts +4 -0
  166. package/data/float16Conversion.js +7 -0
  167. package/data/getLongestContiguousPrefix.d.ts +4 -8
  168. package/data/getLongestContiguousPrefix.js +6 -11
  169. package/data/index.d.ts +30 -31
  170. package/data/index.js +39 -172
  171. package/data/instanceToSchema.d.ts +24 -27
  172. package/data/instanceToSchema.js +1 -0
  173. package/data/isContiguous.d.ts +4 -8
  174. package/data/isContiguous.js +6 -11
  175. package/data/matrix.d.ts +21 -21
  176. package/data/matrix.js +513 -505
  177. package/data/numberOps.d.ts +6 -0
  178. package/data/numberOps.js +26 -20
  179. package/data/numeric.d.ts +21 -12
  180. package/data/numeric.js +287 -192
  181. package/data/offsetUtils.d.ts +9 -13
  182. package/data/offsetUtils.js +204 -144
  183. package/data/offsets.d.ts +8 -0
  184. package/data/offsets.js +33 -33
  185. package/data/partialIO.d.ts +13 -8
  186. package/data/partialIO.js +124 -113
  187. package/data/ptr.d.ts +12 -12
  188. package/data/ptr.js +42 -44
  189. package/data/ref.d.ts +40 -27
  190. package/data/ref.js +125 -95
  191. package/data/sampler.d.ts +99 -101
  192. package/data/sampler.js +17 -21
  193. package/data/schemaCallWrapper.d.ts +19 -0
  194. package/data/schemaCallWrapper.js +31 -26
  195. package/data/schemaMemoryLayout.d.ts +8 -0
  196. package/data/schemaMemoryLayout.js +213 -185
  197. package/data/sizeOf.d.ts +4 -8
  198. package/data/sizeOf.js +6 -11
  199. package/data/snippet.d.ts +96 -20
  200. package/data/snippet.js +75 -86
  201. package/data/struct.d.ts +4 -7
  202. package/data/struct.js +51 -39
  203. package/data/texture.d.ts +253 -250
  204. package/data/texture.js +238 -200
  205. package/data/unstruct.d.ts +2 -7
  206. package/data/unstruct.js +43 -37
  207. package/data/vector.d.ts +33 -21
  208. package/data/vector.js +234 -221
  209. package/data/vectorImpl.d.ts +231 -0
  210. package/data/vectorImpl.js +563 -515
  211. package/data/vectorOps.d.ts +63 -0
  212. package/data/vectorOps.js +642 -630
  213. package/data/vertexFormatData.d.ts +181 -184
  214. package/data/vertexFormatData.js +104 -106
  215. package/data/wgslTypes.d.ts +665 -600
  216. package/data/wgslTypes.js +220 -198
  217. package/errors.d.ts +50 -24
  218. package/errors.js +146 -120
  219. package/execMode.d.ts +16 -0
  220. package/execMode.js +47 -40
  221. package/extension.d.ts +13 -8
  222. package/extension.js +10 -16
  223. package/getGPUValue.d.ts +1 -0
  224. package/getGPUValue.js +2 -7
  225. package/index.d.ts +28 -68
  226. package/index.js +8 -28
  227. package/indexNamedExports.d.ts +69 -42
  228. package/indexNamedExports.js +25 -0
  229. package/internal.d.ts +16 -0
  230. package/internal.js +12 -0
  231. package/mathUtils.d.ts +5 -0
  232. package/mathUtils.js +7 -11
  233. package/memo.d.ts +11 -0
  234. package/memo.js +20 -22
  235. package/minify.d.ts +5 -0
  236. package/minify.js +93 -0
  237. package/nameUtils.d.ts +29 -0
  238. package/nameUtils.js +428 -398
  239. package/package.json +9 -3
  240. package/resolutionCtx.d.ts +162 -22
  241. package/resolutionCtx.js +911 -624
  242. package/serial/registry.d.ts +15 -0
  243. package/serial/registry.js +106 -0
  244. package/serial/restore.d.ts +49 -0
  245. package/serial/restore.js +68 -0
  246. package/serial/schema.d.ts +58 -0
  247. package/serial/schema.js +209 -0
  248. package/serial/types.d.ts +5 -0
  249. package/serial/types.js +1 -0
  250. package/shared/env.d.ts +9 -0
  251. package/shared/env.js +9 -12
  252. package/shared/generators.d.ts +4 -0
  253. package/shared/generators.js +10 -12
  254. package/shared/meta.d.ts +29 -14
  255. package/shared/meta.js +71 -55
  256. package/shared/normalizeMetadata.d.ts +32 -27
  257. package/shared/normalizeMetadata.js +23 -36
  258. package/shared/repr.d.ts +73 -55
  259. package/shared/repr.js +1 -0
  260. package/shared/soul.d.ts +17 -0
  261. package/shared/soul.js +1 -0
  262. package/shared/stringify.d.ts +2 -0
  263. package/shared/stringify.js +29 -20
  264. package/shared/symbols.d.ts +26 -20
  265. package/shared/symbols.js +79 -79
  266. package/shared/tseynit.d.ts +2 -0
  267. package/shared/tseynit.js +160 -75
  268. package/shared/utilityTypes.d.ts +30 -14
  269. package/shared/utilityTypes.js +2 -6
  270. package/shared/vertexFormat.d.ts +41 -43
  271. package/shared/vertexFormat.js +59 -62
  272. package/std/array.d.ts +2 -7
  273. package/std/array.js +18 -23
  274. package/std/atomic.d.ts +14 -18
  275. package/std/atomic.js +96 -95
  276. package/std/bitcast.d.ts +193 -10
  277. package/std/bitcast.js +309 -39
  278. package/std/boolean.d.ts +19 -33
  279. package/std/boolean.js +296 -288
  280. package/std/copy.d.ts +2 -7
  281. package/std/copy.js +27 -24
  282. package/std/derivative.d.ts +11 -15
  283. package/std/derivative.js +56 -79
  284. package/std/discard.d.ts +1 -6
  285. package/std/discard.js +7 -14
  286. package/std/environment.d.ts +19 -14
  287. package/std/environment.js +71 -51
  288. package/std/extensions.d.ts +2 -8
  289. package/std/extensions.js +10 -11
  290. package/std/index.d.ts +20 -24
  291. package/std/index.js +32 -187
  292. package/std/matrix.d.ts +6 -12
  293. package/std/matrix.js +60 -69
  294. package/std/numeric.d.ts +143 -146
  295. package/std/numeric.js +858 -749
  296. package/std/operators.d.ts +19 -27
  297. package/std/operators.js +227 -193
  298. package/std/packing.d.ts +5 -11
  299. package/std/packing.js +67 -75
  300. package/std/range.d.ts +6 -11
  301. package/std/range.js +48 -36
  302. package/std/subgroup.d.ts +33 -37
  303. package/std/subgroup.js +180 -217
  304. package/std/texture.d.ts +70 -38
  305. package/std/texture.js +176 -172
  306. package/taskQueue.d.ts +6 -0
  307. package/taskQueue.js +30 -0
  308. package/tgpu.d.ts +16 -0
  309. package/tgpu.js +17 -44
  310. package/tgpuBindGroupLayout.d.ts +132 -152
  311. package/tgpuBindGroupLayout.js +346 -268
  312. package/tgpuLogger.d.ts +34 -0
  313. package/tgpuLogger.js +63 -0
  314. package/tgpuUnstable.d.ts +16 -22
  315. package/tgpuUnstable.js +13 -35
  316. package/tgsl/accessIndex.d.ts +2 -0
  317. package/tgsl/accessIndex.js +76 -33
  318. package/tgsl/accessProp.d.ts +2 -0
  319. package/tgsl/accessProp.js +142 -100
  320. package/tgsl/accessStructProp.d.ts +5 -0
  321. package/tgsl/accessStructProp.js +18 -0
  322. package/tgsl/consoleLog/deserializers.d.ts +13 -0
  323. package/tgsl/consoleLog/deserializers.js +119 -103
  324. package/tgsl/consoleLog/logGenerator.d.ts +21 -0
  325. package/tgsl/consoleLog/logGenerator.js +85 -80
  326. package/tgsl/consoleLog/serializers.d.ts +21 -0
  327. package/tgsl/consoleLog/serializers.js +119 -100
  328. package/tgsl/consoleLog/types.d.ts +40 -39
  329. package/tgsl/consoleLog/types.js +1 -0
  330. package/tgsl/conversion.d.ts +33 -0
  331. package/tgsl/conversion.js +272 -193
  332. package/tgsl/forOfUtils.d.ts +15 -0
  333. package/tgsl/forOfUtils.js +85 -70
  334. package/tgsl/generationHelpers.d.ts +22 -39
  335. package/tgsl/generationHelpers.js +85 -58
  336. package/tgsl/infixDispatch.d.ts +70 -0
  337. package/tgsl/infixDispatch.js +48 -46
  338. package/tgsl/jsPolyfills.d.ts +16 -19
  339. package/tgsl/jsPolyfills.js +44 -42
  340. package/tgsl/makeDereferenceable.d.ts +48 -0
  341. package/tgsl/makeDereferenceable.js +86 -0
  342. package/tgsl/makeResolvable.d.ts +22 -0
  343. package/tgsl/makeResolvable.js +33 -0
  344. package/tgsl/shaderGenerator.d.ts +77 -17
  345. package/tgsl/shaderGenerator.js +1 -0
  346. package/tgsl/shellless.d.ts +6 -9
  347. package/tgsl/shellless.js +73 -43
  348. package/tgsl/wgslGenerator.d.ts +66 -59
  349. package/tgsl/wgslGenerator.js +1344 -747
  350. package/types.d.ts +287 -221
  351. package/types.js +61 -44
  352. package/unwrapper.d.ts +31 -26
  353. package/unwrapper.js +1 -0
  354. package/wgslExtensions.d.ts +3 -5
  355. package/wgslExtensions.js +12 -16
  356. package/_virtual/rolldown_runtime.js +0 -13
  357. package/core/buffer/bufferShorthand.d.ts +0 -50
  358. package/core/buffer/bufferShorthand.js +0 -55
  359. package/core/pipeline/applyPipelineState.js +0 -37
  360. package/package.js +0 -5
  361. package/tgsl/shaderGenerator_members.d.ts +0 -33
  362. 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 "./limitsOverflow.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 };