@carbonenginejs/runtime-resource 0.10.0 → 0.11.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 (254) hide show
  1. package/dist/format/effect/effectPermutationGraph.js +257 -0
  2. package/dist/format/effect/effectPermutationGraph.js.map +1 -0
  3. package/dist/format/effect/effectReflectionPackage.js +636 -0
  4. package/dist/format/effect/effectReflectionPackage.js.map +1 -0
  5. package/dist/format/effect/sha256.js +114 -0
  6. package/dist/format/effect/sha256.js.map +1 -0
  7. package/dist/formats/dxbc/CjsDxbcFormat.js +142 -0
  8. package/dist/formats/dxbc/CjsDxbcFormat.js.map +1 -0
  9. package/dist/formats/dxbc/core/DxbcReader.js +266 -0
  10. package/dist/formats/dxbc/core/DxbcReader.js.map +1 -0
  11. package/dist/formats/dxbc/core/container.js +169 -0
  12. package/dist/formats/dxbc/core/container.js.map +1 -0
  13. package/dist/formats/dxbc/core/decoder.js +789 -0
  14. package/dist/formats/dxbc/core/decoder.js.map +1 -0
  15. package/dist/formats/dxbc/core/errors.js +19 -0
  16. package/dist/formats/dxbc/core/errors.js.map +1 -0
  17. package/dist/formats/dxbc/core/helpers.js +220 -0
  18. package/dist/formats/dxbc/core/helpers.js.map +1 -0
  19. package/dist/formats/dxbc/core/opcodes.js +45 -0
  20. package/dist/formats/dxbc/core/opcodes.js.map +1 -0
  21. package/dist/formats/dxbc/core/program.js +91 -0
  22. package/dist/formats/dxbc/core/program.js.map +1 -0
  23. package/dist/formats/dxbc/core/signature.js +172 -0
  24. package/dist/formats/dxbc/core/signature.js.map +1 -0
  25. package/dist/formats/dxbc/index.js +2 -0
  26. package/dist/formats/dxbc/index.js.map +1 -0
  27. package/dist/formats/hlsl/CjsHlslFormat.js +254 -0
  28. package/dist/formats/hlsl/CjsHlslFormat.js.map +1 -0
  29. package/dist/formats/hlsl/core/HlslBinaryUtils.js +15 -0
  30. package/dist/formats/hlsl/core/HlslBinaryUtils.js.map +1 -0
  31. package/dist/formats/hlsl/core/HlslEffectReadError.js +19 -0
  32. package/dist/formats/hlsl/core/HlslEffectReadError.js.map +1 -0
  33. package/dist/formats/hlsl/core/HlslEffectStateManager.js +130 -0
  34. package/dist/formats/hlsl/core/HlslEffectStateManager.js.map +1 -0
  35. package/dist/formats/hlsl/core/HlslReader.js +266 -0
  36. package/dist/formats/hlsl/core/HlslReader.js.map +1 -0
  37. package/dist/formats/hlsl/core/HlslRenderStateSetup.js +37 -0
  38. package/dist/formats/hlsl/core/HlslRenderStateSetup.js.map +1 -0
  39. package/dist/formats/hlsl/core/HlslResourceSetDescription.js +94 -0
  40. package/dist/formats/hlsl/core/HlslResourceSetDescription.js.map +1 -0
  41. package/dist/formats/hlsl/core/HlslShaderBytecode.js +44 -0
  42. package/dist/formats/hlsl/core/HlslShaderBytecode.js.map +1 -0
  43. package/dist/formats/hlsl/core/analysis.js +51 -0
  44. package/dist/formats/hlsl/core/analysis.js.map +1 -0
  45. package/dist/formats/hlsl/core/helpers.js +270 -0
  46. package/dist/formats/hlsl/core/helpers.js.map +1 -0
  47. package/dist/formats/hlsl/core/json.js +284 -0
  48. package/dist/formats/hlsl/core/json.js.map +1 -0
  49. package/dist/formats/hlsl/core/metadata.js +327 -0
  50. package/dist/formats/hlsl/core/metadata.js.map +1 -0
  51. package/dist/formats/hlsl/core/portableReflection.js +848 -0
  52. package/dist/formats/hlsl/core/portableReflection.js.map +1 -0
  53. package/dist/formats/hlsl/core/render-states.js +280 -0
  54. package/dist/formats/hlsl/core/render-states.js.map +1 -0
  55. package/dist/formats/hlsl/core/tr2/HlslRenderContextEnum.js +43 -0
  56. package/dist/formats/hlsl/core/tr2/HlslRenderContextEnum.js.map +1 -0
  57. package/dist/formats/hlsl/core/tr2/resources/HlslEffectRes.js +294 -0
  58. package/dist/formats/hlsl/core/tr2/resources/HlslEffectRes.js.map +1 -0
  59. package/dist/formats/hlsl/core/tr2/resources/HlslShaderPermutation.js +33 -0
  60. package/dist/formats/hlsl/core/tr2/resources/HlslShaderPermutation.js.map +1 -0
  61. package/dist/formats/hlsl/core/tr2/shader/HlslEffectBindingManifest.js +416 -0
  62. package/dist/formats/hlsl/core/tr2/shader/HlslEffectBindingManifest.js.map +1 -0
  63. package/dist/formats/hlsl/core/tr2/shader/HlslEffectConstant.js +40 -0
  64. package/dist/formats/hlsl/core/tr2/shader/HlslEffectConstant.js.map +1 -0
  65. package/dist/formats/hlsl/core/tr2/shader/HlslEffectDescription.js +742 -0
  66. package/dist/formats/hlsl/core/tr2/shader/HlslEffectDescription.js.map +1 -0
  67. package/dist/formats/hlsl/core/tr2/shader/HlslEffectLibrary.js +52 -0
  68. package/dist/formats/hlsl/core/tr2/shader/HlslEffectLibrary.js.map +1 -0
  69. package/dist/formats/hlsl/core/tr2/shader/HlslEffectParameterAnnotation.js +38 -0
  70. package/dist/formats/hlsl/core/tr2/shader/HlslEffectParameterAnnotation.js.map +1 -0
  71. package/dist/formats/hlsl/core/tr2/shader/HlslEffectResource.js +50 -0
  72. package/dist/formats/hlsl/core/tr2/shader/HlslEffectResource.js.map +1 -0
  73. package/dist/formats/hlsl/core/tr2/shader/HlslEffectStageInput.js +86 -0
  74. package/dist/formats/hlsl/core/tr2/shader/HlslEffectStageInput.js.map +1 -0
  75. package/dist/formats/hlsl/core/tr2/shader/HlslEffectTechnique.js +31 -0
  76. package/dist/formats/hlsl/core/tr2/shader/HlslEffectTechnique.js.map +1 -0
  77. package/dist/formats/hlsl/core/tr2/shader/HlslPass.js +42 -0
  78. package/dist/formats/hlsl/core/tr2/shader/HlslPass.js.map +1 -0
  79. package/dist/formats/hlsl/core/tr2/shader/HlslSamplerDescription.js +55 -0
  80. package/dist/formats/hlsl/core/tr2/shader/HlslSamplerDescription.js.map +1 -0
  81. package/dist/formats/hlsl/core/tr2/shader/HlslSamplerSetup.js +29 -0
  82. package/dist/formats/hlsl/core/tr2/shader/HlslSamplerSetup.js.map +1 -0
  83. package/dist/formats/hlsl/core/tr2/shader/HlslShader.js +220 -0
  84. package/dist/formats/hlsl/core/tr2/shader/HlslShader.js.map +1 -0
  85. package/dist/formats/hlsl/core/tr2/shader/HlslShaderOption.js +30 -0
  86. package/dist/formats/hlsl/core/tr2/shader/HlslShaderOption.js.map +1 -0
  87. package/dist/formats/hlsl/index.js +2 -0
  88. package/dist/formats/hlsl/index.js.map +1 -0
  89. package/dist/formats/hlsl/portable.js +2 -0
  90. package/dist/formats/hlsl/portable.js.map +1 -0
  91. package/dist/formats/index.js +4 -0
  92. package/dist/formats/index.js.map +1 -1
  93. package/dist/formats/webgl/CjsWebglFormat.js +221 -0
  94. package/dist/formats/webgl/CjsWebglFormat.js.map +1 -0
  95. package/dist/formats/webgl/core/cewg/CewgPackage.js +339 -0
  96. package/dist/formats/webgl/core/cewg/CewgPackage.js.map +1 -0
  97. package/dist/formats/webgl/core/cewg/CewgPackageBuilder.js +104 -0
  98. package/dist/formats/webgl/core/cewg/CewgPackageBuilder.js.map +1 -0
  99. package/dist/formats/webgl/core/cewg/binary.js +101 -0
  100. package/dist/formats/webgl/core/cewg/binary.js.map +1 -0
  101. package/dist/formats/webgl/core/cewgCompleteness.js +81 -0
  102. package/dist/formats/webgl/core/cewgCompleteness.js.map +1 -0
  103. package/dist/formats/webgl/core/effectPackage.js +789 -0
  104. package/dist/formats/webgl/core/effectPackage.js.map +1 -0
  105. package/dist/formats/webgl/core/effectPackageValidation.js +331 -0
  106. package/dist/formats/webgl/core/effectPackageValidation.js.map +1 -0
  107. package/dist/formats/webgl/core/errors.js +27 -0
  108. package/dist/formats/webgl/core/errors.js.map +1 -0
  109. package/dist/formats/webgl/core/glsl/DxbcGlslEmitter.js +2678 -0
  110. package/dist/formats/webgl/core/glsl/DxbcGlslEmitter.js.map +1 -0
  111. package/dist/formats/webgl/core/glsl/DxbcGlslHelpers.js +89 -0
  112. package/dist/formats/webgl/core/glsl/DxbcGlslHelpers.js.map +1 -0
  113. package/dist/formats/webgl/core/glsl/DxbcGlslOperandFormatter.js +428 -0
  114. package/dist/formats/webgl/core/glsl/DxbcGlslOperandFormatter.js.map +1 -0
  115. package/dist/formats/webgl/core/helpers.js +306 -0
  116. package/dist/formats/webgl/core/helpers.js.map +1 -0
  117. package/dist/formats/webgl/index.js +2 -0
  118. package/dist/formats/webgl/index.js.map +1 -0
  119. package/dist/formats/webgpu/CjsWebgpuFormat.js +376 -0
  120. package/dist/formats/webgpu/CjsWebgpuFormat.js.map +1 -0
  121. package/dist/formats/webgpu/core/cewgpu/CewgpuPackage.js +415 -0
  122. package/dist/formats/webgpu/core/cewgpu/CewgpuPackage.js.map +1 -0
  123. package/dist/formats/webgpu/core/cewgpu/CewgpuPackageBuilder.js +100 -0
  124. package/dist/formats/webgpu/core/cewgpu/CewgpuPackageBuilder.js.map +1 -0
  125. package/dist/formats/webgpu/core/cewgpu/binary.js +93 -0
  126. package/dist/formats/webgpu/core/cewgpu/binary.js.map +1 -0
  127. package/dist/formats/webgpu/core/cewgpu/tags.js +17 -0
  128. package/dist/formats/webgpu/core/cewgpu/tags.js.map +1 -0
  129. package/dist/formats/webgpu/core/effectAnalysis.js +82 -0
  130. package/dist/formats/webgpu/core/effectAnalysis.js.map +1 -0
  131. package/dist/formats/webgpu/core/effectBackendBodySet.js +305 -0
  132. package/dist/formats/webgpu/core/effectBackendBodySet.js.map +1 -0
  133. package/dist/formats/webgpu/core/effectPackageValidation.js +1078 -0
  134. package/dist/formats/webgpu/core/effectPackageValidation.js.map +1 -0
  135. package/dist/formats/webgpu/core/errors.js +20 -0
  136. package/dist/formats/webgpu/core/errors.js.map +1 -0
  137. package/dist/formats/webgpu/core/helpers.js +448 -0
  138. package/dist/formats/webgpu/core/helpers.js.map +1 -0
  139. package/dist/formats/webgpu/core/ir/analyzeRegisterValues.js +223 -0
  140. package/dist/formats/webgpu/core/ir/analyzeRegisterValues.js.map +1 -0
  141. package/dist/formats/webgpu/core/ir/buildControlFlow.js +220 -0
  142. package/dist/formats/webgpu/core/ir/buildControlFlow.js.map +1 -0
  143. package/dist/formats/webgpu/core/ir/indexableTemps.js +137 -0
  144. package/dist/formats/webgpu/core/ir/indexableTemps.js.map +1 -0
  145. package/dist/formats/webgpu/core/ir/inferValueTypes.js +454 -0
  146. package/dist/formats/webgpu/core/ir/inferValueTypes.js.map +1 -0
  147. package/dist/formats/webgpu/core/ir/lowerDxbcToIr.js +494 -0
  148. package/dist/formats/webgpu/core/ir/lowerDxbcToIr.js.map +1 -0
  149. package/dist/formats/webgpu/core/ir/resolveRegisterFlow.js +177 -0
  150. package/dist/formats/webgpu/core/ir/resolveRegisterFlow.js.map +1 -0
  151. package/dist/formats/webgpu/core/ir/sourceLanes.js +61 -0
  152. package/dist/formats/webgpu/core/ir/sourceLanes.js.map +1 -0
  153. package/dist/formats/webgpu/core/packageEffect.js +300 -0
  154. package/dist/formats/webgpu/core/packageEffect.js.map +1 -0
  155. package/dist/formats/webgpu/core/packageEffectSelection.js +164 -0
  156. package/dist/formats/webgpu/core/packageEffectSelection.js.map +1 -0
  157. package/dist/formats/webgpu/core/packageMetadata.js +8 -0
  158. package/dist/formats/webgpu/core/packageMetadata.js.map +1 -0
  159. package/dist/formats/webgpu/core/schema.js +4 -0
  160. package/dist/formats/webgpu/core/schema.js.map +1 -0
  161. package/dist/formats/webgpu/core/wgsl/buildResourceTransformPlan.js +275 -0
  162. package/dist/formats/webgpu/core/wgsl/buildResourceTransformPlan.js.map +1 -0
  163. package/dist/formats/webgpu/core/wgsl/buildWgslBindingPlan.js +182 -0
  164. package/dist/formats/webgpu/core/wgsl/buildWgslBindingPlan.js.map +1 -0
  165. package/dist/formats/webgpu/core/wgsl/buildWgslSet.js +324 -0
  166. package/dist/formats/webgpu/core/wgsl/buildWgslSet.js.map +1 -0
  167. package/dist/formats/webgpu/core/wgsl/emitWgsl.js +356 -0
  168. package/dist/formats/webgpu/core/wgsl/emitWgsl.js.map +1 -0
  169. package/dist/formats/webgpu/core/wgsl/hoistEscapingValues.js +77 -0
  170. package/dist/formats/webgpu/core/wgsl/hoistEscapingValues.js.map +1 -0
  171. package/dist/formats/webgpu/core/wgsl/lowerBindingLayout.js +451 -0
  172. package/dist/formats/webgpu/core/wgsl/lowerBindingLayout.js.map +1 -0
  173. package/dist/formats/webgpu/core/wgsl/lowerComputeProgram.js +754 -0
  174. package/dist/formats/webgpu/core/wgsl/lowerComputeProgram.js.map +1 -0
  175. package/dist/formats/webgpu/core/wgsl/lowerCreateHistogramsComputeProgram.js +457 -0
  176. package/dist/formats/webgpu/core/wgsl/lowerCreateHistogramsComputeProgram.js.map +1 -0
  177. package/dist/formats/webgpu/core/wgsl/lowerFragmentProgram.js +1572 -0
  178. package/dist/formats/webgpu/core/wgsl/lowerFragmentProgram.js.map +1 -0
  179. package/dist/formats/webgpu/core/wgsl/lowerMergeHistogramsComputeProgram.js +659 -0
  180. package/dist/formats/webgpu/core/wgsl/lowerMergeHistogramsComputeProgram.js.map +1 -0
  181. package/dist/formats/webgpu/core/wgsl/lowerParticleClearComputePrograms.js +734 -0
  182. package/dist/formats/webgpu/core/wgsl/lowerParticleClearComputePrograms.js.map +1 -0
  183. package/dist/formats/webgpu/core/wgsl/lowerParticleEmitComputeProgram.js +583 -0
  184. package/dist/formats/webgpu/core/wgsl/lowerParticleEmitComputeProgram.js.map +1 -0
  185. package/dist/formats/webgpu/core/wgsl/lowerSkinVerticesComputeProgram.js +621 -0
  186. package/dist/formats/webgpu/core/wgsl/lowerSkinVerticesComputeProgram.js.map +1 -0
  187. package/dist/formats/webgpu/core/wgsl/lowerSortComputeProgram.js +824 -0
  188. package/dist/formats/webgpu/core/wgsl/lowerSortComputeProgram.js.map +1 -0
  189. package/dist/formats/webgpu/core/wgsl/lowerSortInnerComputeProgram.js +697 -0
  190. package/dist/formats/webgpu/core/wgsl/lowerSortInnerComputeProgram.js.map +1 -0
  191. package/dist/formats/webgpu/core/wgsl/lowerSortStepComputeProgram.js +559 -0
  192. package/dist/formats/webgpu/core/wgsl/lowerSortStepComputeProgram.js.map +1 -0
  193. package/dist/formats/webgpu/core/wgsl/lowerVertexProgram.js +1328 -0
  194. package/dist/formats/webgpu/core/wgsl/lowerVertexProgram.js.map +1 -0
  195. package/dist/formats/webgpu/core/wgsl/particleEmitSemanticDigest.js +110 -0
  196. package/dist/formats/webgpu/core/wgsl/particleEmitSemanticDigest.js.map +1 -0
  197. package/dist/formats/webgpu/core/wgsl/precisionControls.js +55 -0
  198. package/dist/formats/webgpu/core/wgsl/precisionControls.js.map +1 -0
  199. package/dist/formats/webgpu/core/wgsl/selectionPlans.js +758 -0
  200. package/dist/formats/webgpu/core/wgsl/selectionPlans.js.map +1 -0
  201. package/dist/formats/webgpu/core/wgsl/uniformity.js +78 -0
  202. package/dist/formats/webgpu/core/wgsl/uniformity.js.map +1 -0
  203. package/dist/formats/webgpu/core/wgsl/validateExactComputeIr.js +196 -0
  204. package/dist/formats/webgpu/core/wgsl/validateExactComputeIr.js.map +1 -0
  205. package/dist/formats/webgpu/core/wgsl/validateHandleOperand.js +37 -0
  206. package/dist/formats/webgpu/core/wgsl/validateHandleOperand.js.map +1 -0
  207. package/dist/formats/webgpu/index.js +2 -0
  208. package/dist/formats/webgpu/index.js.map +1 -0
  209. package/dist/resource/shader/Tr2EffectRes.js +159 -150
  210. package/dist/resource/shader/Tr2EffectRes.js.map +1 -1
  211. package/dist/resource/shader/Tr2MaterialArea.js +23 -28
  212. package/dist/resource/shader/Tr2MaterialArea.js.map +1 -1
  213. package/dist/resource/shader/Tr2MaterialMesh.js +21 -27
  214. package/dist/resource/shader/Tr2MaterialMesh.js.map +1 -1
  215. package/dist/resource/shader/Tr2MaterialRes.js +24 -29
  216. package/dist/resource/shader/Tr2MaterialRes.js.map +1 -1
  217. package/dist/resource/shader/Tr2Shader.js +45 -39
  218. package/dist/resource/shader/Tr2Shader.js.map +1 -1
  219. package/dist/resource/shader/Tr2ShaderPermutation.js +30 -32
  220. package/dist/resource/shader/Tr2ShaderPermutation.js.map +1 -1
  221. package/dist/resource/shader/reflection/Tr2EffectConstant.js +113 -78
  222. package/dist/resource/shader/reflection/Tr2EffectConstant.js.map +1 -1
  223. package/dist/resource/shader/reflection/Tr2EffectDefine.js +17 -23
  224. package/dist/resource/shader/reflection/Tr2EffectDefine.js.map +1 -1
  225. package/dist/resource/shader/reflection/Tr2EffectDescription.js +23 -29
  226. package/dist/resource/shader/reflection/Tr2EffectDescription.js.map +1 -1
  227. package/dist/resource/shader/reflection/Tr2EffectLibrary.js +44 -40
  228. package/dist/resource/shader/reflection/Tr2EffectLibrary.js.map +1 -1
  229. package/dist/resource/shader/reflection/Tr2EffectParameterAnnotation.js +82 -86
  230. package/dist/resource/shader/reflection/Tr2EffectParameterAnnotation.js.map +1 -1
  231. package/dist/resource/shader/reflection/Tr2EffectResource.js +55 -61
  232. package/dist/resource/shader/reflection/Tr2EffectResource.js.map +1 -1
  233. package/dist/resource/shader/reflection/Tr2EffectStageInput.js +49 -45
  234. package/dist/resource/shader/reflection/Tr2EffectStageInput.js.map +1 -1
  235. package/dist/resource/shader/reflection/Tr2EffectTechnique.js +25 -30
  236. package/dist/resource/shader/reflection/Tr2EffectTechnique.js.map +1 -1
  237. package/dist/resource/shader/reflection/Tr2Pass.js +30 -32
  238. package/dist/resource/shader/reflection/Tr2Pass.js.map +1 -1
  239. package/dist/resource/shader/sampler/Tr2SamplerSetup.js +21 -26
  240. package/dist/resource/shader/sampler/Tr2SamplerSetup.js.map +1 -1
  241. package/docs/formats/README.md +4 -0
  242. package/docs/formats/provenance.md +11 -3
  243. package/docs/reference/classes/formats.md +440 -0
  244. package/format-notices/dxbc/LICENSE +21 -0
  245. package/format-notices/dxbc/NOTICE +20 -0
  246. package/format-notices/hlsl/LICENSE +21 -0
  247. package/format-notices/hlsl/NOTICE +25 -0
  248. package/format-notices/webgl/LICENSE +21 -0
  249. package/format-notices/webgl/NOTICE +35 -0
  250. package/format-notices/webgpu/LICENSE +21 -0
  251. package/format-notices/webgpu/NOTICE +31 -0
  252. package/package.json +6 -1
  253. package/dist/resource/shader/portableValidation.js +0 -461
  254. package/dist/resource/shader/portableValidation.js.map +0 -1
@@ -0,0 +1,223 @@
1
+ import { fixedSourceLanes } from './sourceLanes.js';
2
+ import { validateIndexableTempOperand } from './indexableTemps.js';
3
+
4
+ const COMPONENTS = ["x", "y", "z", "w"];
5
+ const REGISTER_FILES = new Set(["temp", "input", "output", "indexable_temp", "input_primitive_id", "output_depth", "output_coverage", "input_control_point", "output_control_point", "input_patch_constant", "input_domain_point", "output_control_point_id", "input_fork_instance_id", "input_join_instance_id", "input_thread_id", "input_thread_group_id", "input_thread_id_in_group", "input_coverage_mask", "input_thread_id_in_group_flattened", "input_gs_instance_id", "output_depth_greater_equal", "output_depth_less_equal"]);
6
+ const WRITABLE_FILES = new Set(["temp", "output", "indexable_temp", "output_depth", "output_coverage", "output_control_point", "output_depth_greater_equal", "output_depth_less_equal"]);
7
+ const NO_DESTINATION = new Set(["break", "breakc", "call", "callc", "case", "continue", "continuec", "cut", "default", "discard", "else", "emit", "emit_then_cut", "endif", "endloop", "endswitch", "if", "label", "loop", "nop", "ret", "retc", "switch", "sync", "store_uav_typed", "store_raw", "store_structured", "atomic_and", "atomic_or", "atomic_xor", "atomic_cmp_store", "atomic_iadd", "atomic_imax", "atomic_imin", "atomic_umax", "atomic_umin"]);
8
+ const DUAL_DESTINATION = new Set(["sincos", "imul", "umul", "udiv", "swapc"]);
9
+ const FULL_SOURCE_LANES = new Set(["ld", "ld_ms", "resinfo"]);
10
+ function operandComponents(operand, destination = false, activeComponents = null) {
11
+ if (destination) {
12
+ if (operand.mask) return COMPONENTS.filter(component => operand.mask.includes(component));
13
+ if (operand.componentCount === 1) return ["x"];
14
+ return COMPONENTS.slice();
15
+ }
16
+ if (operand.swizzle) {
17
+ return activeComponents ? activeComponents.map(component => operand.swizzle[COMPONENTS.indexOf(component)]) : Array.from(operand.swizzle);
18
+ }
19
+ if (operand.selected) return activeComponents ? activeComponents.map(() => operand.selected) : [operand.selected];
20
+ if (operand.mask) return COMPONENTS.filter(component => operand.mask.includes(component));
21
+ if (operand.componentCount === 1) return ["x"];
22
+ return activeComponents ? activeComponents.slice() : COMPONENTS.slice();
23
+ }
24
+ function registerKey(program, operand, role) {
25
+ if (!REGISTER_FILES.has(operand.typeName)) return null;
26
+ if (operand.typeName === "indexable_temp") {
27
+ return validateIndexableTempOperand(program, operand, role)?.key || null;
28
+ }
29
+ const indices = (operand.indices || []).map(index => {
30
+ const immediate = index.values?.join(":") || "";
31
+ return index.relative ? `${immediate}+relative` : immediate;
32
+ });
33
+ return `${operand.typeName}[${indices.join(",")}]`;
34
+ }
35
+
36
+ /**
37
+ * Classifies decoded instruction operands as register sources or destinations.
38
+ *
39
+ * @param {object} instruction Decoded instruction.
40
+ * @returns {Array<{operand: object, role: string}>} Ordered operand roles.
41
+ */
42
+ function operandRoles(instruction) {
43
+ const operands = instruction.operands || [];
44
+ if (NO_DESTINATION.has(instruction.opcodeName)) {
45
+ return operands.map(operand => ({
46
+ operand,
47
+ role: "source"
48
+ }));
49
+ }
50
+ if (DUAL_DESTINATION.has(instruction.opcodeName)) {
51
+ return operands.map((operand, index) => ({
52
+ operand,
53
+ role: index < 2 ? "destination" : "source"
54
+ }));
55
+ }
56
+ return operands.map((operand, index) => ({
57
+ operand,
58
+ role: index === 0 && WRITABLE_FILES.has(operand.typeName) ? "destination" : "source"
59
+ }));
60
+ }
61
+ function valueRef(value, component) {
62
+ return {
63
+ valueId: value.id,
64
+ component
65
+ };
66
+ }
67
+ function ensureComponent(state, values, register, component, blockId) {
68
+ let components = state.get(register);
69
+ if (!components) {
70
+ components = new Map();
71
+ state.set(register, components);
72
+ }
73
+ if (!components.has(component)) {
74
+ const value = {
75
+ kind: "register-value",
76
+ id: `value${values.length}`,
77
+ origin: "block-input",
78
+ blockId,
79
+ instructionIndex: null,
80
+ register,
81
+ writeMask: component,
82
+ previous: null
83
+ };
84
+ values.push(value);
85
+ components.set(component, valueRef(value, component));
86
+ }
87
+ return components.get(component);
88
+ }
89
+ function analyzeBlock(program, block, values) {
90
+ const state = new Map();
91
+ const inputIds = new Set();
92
+ for (const instructionIndex of block.instructionIndices) {
93
+ const instruction = program.instructions[instructionIndex];
94
+ const roles = operandRoles(instruction);
95
+ const destinationComponents = Array.from(new Set(roles.filter(entry => entry.role === "destination" && entry.operand.typeName !== "null").flatMap(entry => operandComponents(entry.operand, true))));
96
+ const activeSourceComponents = destinationComponents.length && !FULL_SOURCE_LANES.has(instruction.opcodeName) ? destinationComponents : null;
97
+ const reads = [];
98
+ const writes = [];
99
+ for (let operandIndex = 0; operandIndex < roles.length; operandIndex += 1) {
100
+ const {
101
+ operand,
102
+ role
103
+ } = roles[operandIndex];
104
+ if (role !== "source") continue;
105
+ const register = registerKey(program, operand, "source");
106
+ if (!register) continue;
107
+ const components = operandComponents(operand, false, fixedSourceLanes(instruction, operandIndex, program) || activeSourceComponents);
108
+ const refs = components.map(component => ensureComponent(state, values, register, component, block.id));
109
+ for (const ref of refs) {
110
+ const value = values.find(entry => entry.id === ref.valueId);
111
+ if (value?.origin === "block-input") inputIds.add(value.id);
112
+ }
113
+ reads.push({
114
+ kind: "register-read",
115
+ operandIndex,
116
+ register,
117
+ components,
118
+ refs
119
+ });
120
+ }
121
+ for (let operandIndex = 0; operandIndex < roles.length; operandIndex += 1) {
122
+ const {
123
+ operand
124
+ } = roles[operandIndex];
125
+ const indices = operand.indices || [];
126
+ for (let dimension = 0; dimension < indices.length; dimension += 1) {
127
+ const relative = indices[dimension].relative;
128
+ if (!relative) continue;
129
+ const register = registerKey(program, relative, "source");
130
+ if (!register) throw new Error("Shader IR relative index uses an unsupported register file");
131
+ const components = operandComponents(relative, false);
132
+ if (components.length !== 1) throw new Error("Shader IR relative index requires one scalar component");
133
+ const refs = components.map(component => ensureComponent(state, values, register, component, block.id));
134
+ for (const ref of refs) {
135
+ const value = values.find(entry => entry.id === ref.valueId);
136
+ if (value?.origin === "block-input") inputIds.add(value.id);
137
+ }
138
+ reads.push({
139
+ kind: "index-read",
140
+ operandIndex,
141
+ dimension,
142
+ register,
143
+ components,
144
+ refs
145
+ });
146
+ }
147
+ }
148
+ for (let operandIndex = 0; operandIndex < roles.length; operandIndex += 1) {
149
+ const {
150
+ operand,
151
+ role
152
+ } = roles[operandIndex];
153
+ if (role !== "destination" || operand.typeName === "null") continue;
154
+ const register = registerKey(program, operand, "destination");
155
+ if (!register) continue;
156
+ const mask = operandComponents(operand, true);
157
+ const previous = {};
158
+ for (const component of COMPONENTS) {
159
+ if (!mask.includes(component)) {
160
+ previous[component] = ensureComponent(state, values, register, component, block.id);
161
+ }
162
+ }
163
+ const value = {
164
+ kind: "register-value",
165
+ id: `value${values.length}`,
166
+ origin: "instruction-write",
167
+ blockId: block.id,
168
+ instructionIndex,
169
+ register,
170
+ writeMask: mask.join(""),
171
+ previous: Object.keys(previous).length ? previous : null
172
+ };
173
+ values.push(value);
174
+ let components = state.get(register);
175
+ if (!components) {
176
+ components = new Map();
177
+ state.set(register, components);
178
+ }
179
+ for (const component of mask) components.set(component, valueRef(value, component));
180
+ const result = {};
181
+ for (const component of COMPONENTS) {
182
+ result[component] = components.get(component) || ensureComponent(state, values, register, component, block.id);
183
+ }
184
+ writes.push({
185
+ kind: "register-write",
186
+ operandIndex,
187
+ register,
188
+ mask: mask.join(""),
189
+ valueId: value.id,
190
+ previous: value.previous,
191
+ result
192
+ });
193
+ }
194
+ instruction.dataflow = {
195
+ reads,
196
+ writes
197
+ };
198
+ }
199
+ block.inputValueIds = Array.from(inputIds);
200
+ block.outputValues = Array.from(state.entries()).flatMap(([register, components]) => Array.from(components.entries()).map(([component, ref]) => ({
201
+ register,
202
+ component,
203
+ ref
204
+ }))).sort((a, b) => a.register.localeCompare(b.register) || a.component.localeCompare(b.component));
205
+ }
206
+
207
+ /**
208
+ * Adds block-local register versions, masked-write reconstruction records,
209
+ * and deterministic block-exit state. A later pass resolves the conservative
210
+ * block inputs through CFG predecessors.
211
+ *
212
+ * @param {object} program Mutable shader IR under construction.
213
+ * @returns {object} The same program.
214
+ */
215
+ function analyzeRegisterValues(program) {
216
+ const values = [];
217
+ for (const block of program.blocks) analyzeBlock(program, block, values);
218
+ program.values = values;
219
+ return program;
220
+ }
221
+
222
+ export { analyzeRegisterValues, operandRoles };
223
+ //# sourceMappingURL=analyzeRegisterValues.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyzeRegisterValues.js","sources":["../../../../../../src/formats/webgpu/core/ir/analyzeRegisterValues.js"],"sourcesContent":["import { fixedSourceLanes } from \"./sourceLanes.js\";\nimport { validateIndexableTempOperand } from \"./indexableTemps.js\";\n\nconst COMPONENTS = [ \"x\", \"y\", \"z\", \"w\" ];\n\nconst REGISTER_FILES = new Set([\n \"temp\", \"input\", \"output\", \"indexable_temp\", \"input_primitive_id\",\n \"output_depth\", \"output_coverage\", \"input_control_point\",\n \"output_control_point\", \"input_patch_constant\", \"input_domain_point\",\n \"output_control_point_id\", \"input_fork_instance_id\", \"input_join_instance_id\",\n \"input_thread_id\", \"input_thread_group_id\", \"input_thread_id_in_group\",\n \"input_coverage_mask\", \"input_thread_id_in_group_flattened\",\n \"input_gs_instance_id\", \"output_depth_greater_equal\", \"output_depth_less_equal\"\n]);\n\nconst WRITABLE_FILES = new Set([\n \"temp\", \"output\", \"indexable_temp\", \"output_depth\", \"output_coverage\",\n \"output_control_point\", \"output_depth_greater_equal\", \"output_depth_less_equal\"\n]);\n\nconst NO_DESTINATION = new Set([\n \"break\", \"breakc\", \"call\", \"callc\", \"case\", \"continue\", \"continuec\",\n \"cut\", \"default\", \"discard\", \"else\", \"emit\", \"emit_then_cut\", \"endif\",\n \"endloop\", \"endswitch\", \"if\", \"label\", \"loop\", \"nop\", \"ret\", \"retc\",\n \"switch\", \"sync\", \"store_uav_typed\", \"store_raw\", \"store_structured\",\n \"atomic_and\", \"atomic_or\", \"atomic_xor\", \"atomic_cmp_store\", \"atomic_iadd\",\n \"atomic_imax\", \"atomic_imin\", \"atomic_umax\", \"atomic_umin\"\n]);\n\nconst DUAL_DESTINATION = new Set([ \"sincos\", \"imul\", \"umul\", \"udiv\", \"swapc\" ]);\nconst FULL_SOURCE_LANES = new Set([\n \"ld\", \"ld_ms\", \"resinfo\"\n]);\n\nfunction operandComponents(operand, destination = false, activeComponents = null)\n{\n if (destination)\n {\n if (operand.mask) return COMPONENTS.filter((component) => operand.mask.includes(component));\n if (operand.componentCount === 1) return [ \"x\" ];\n return COMPONENTS.slice();\n }\n if (operand.swizzle)\n {\n return activeComponents\n ? activeComponents.map((component) => operand.swizzle[COMPONENTS.indexOf(component)])\n : Array.from(operand.swizzle);\n }\n if (operand.selected) return activeComponents ? activeComponents.map(() => operand.selected) : [ operand.selected ];\n if (operand.mask) return COMPONENTS.filter((component) => operand.mask.includes(component));\n if (operand.componentCount === 1) return [ \"x\" ];\n return activeComponents ? activeComponents.slice() : COMPONENTS.slice();\n}\n\nfunction registerKey(program, operand, role)\n{\n if (!REGISTER_FILES.has(operand.typeName)) return null;\n if (operand.typeName === \"indexable_temp\")\n {\n return validateIndexableTempOperand(program, operand, role)?.key || null;\n }\n const indices = (operand.indices || []).map((index) =>\n {\n const immediate = index.values?.join(\":\") || \"\";\n return index.relative ? `${immediate}+relative` : immediate;\n });\n return `${operand.typeName}[${indices.join(\",\")}]`;\n}\n\n/**\n * Classifies decoded instruction operands as register sources or destinations.\n *\n * @param {object} instruction Decoded instruction.\n * @returns {Array<{operand: object, role: string}>} Ordered operand roles.\n */\nexport function operandRoles(instruction)\n{\n const operands = instruction.operands || [];\n if (NO_DESTINATION.has(instruction.opcodeName))\n {\n return operands.map((operand) => ({ operand, role: \"source\" }));\n }\n if (DUAL_DESTINATION.has(instruction.opcodeName))\n {\n return operands.map((operand, index) => ({ operand, role: index < 2 ? \"destination\" : \"source\" }));\n }\n return operands.map((operand, index) => ({\n operand,\n role: index === 0 && WRITABLE_FILES.has(operand.typeName) ? \"destination\" : \"source\"\n }));\n}\n\nfunction valueRef(value, component)\n{\n return { valueId: value.id, component };\n}\n\nfunction ensureComponent(state, values, register, component, blockId)\n{\n let components = state.get(register);\n if (!components)\n {\n components = new Map();\n state.set(register, components);\n }\n if (!components.has(component))\n {\n const value = {\n kind: \"register-value\",\n id: `value${values.length}`,\n origin: \"block-input\",\n blockId,\n instructionIndex: null,\n register,\n writeMask: component,\n previous: null\n };\n values.push(value);\n components.set(component, valueRef(value, component));\n }\n return components.get(component);\n}\n\nfunction analyzeBlock(program, block, values)\n{\n const state = new Map();\n const inputIds = new Set();\n for (const instructionIndex of block.instructionIndices)\n {\n const instruction = program.instructions[instructionIndex];\n const roles = operandRoles(instruction);\n const destinationComponents = Array.from(new Set(roles\n .filter((entry) => entry.role === \"destination\" && entry.operand.typeName !== \"null\")\n .flatMap((entry) => operandComponents(entry.operand, true))));\n const activeSourceComponents = destinationComponents.length && !FULL_SOURCE_LANES.has(instruction.opcodeName)\n ? destinationComponents\n : null;\n const reads = [];\n const writes = [];\n\n for (let operandIndex = 0; operandIndex < roles.length; operandIndex += 1)\n {\n const { operand, role } = roles[operandIndex];\n if (role !== \"source\") continue;\n const register = registerKey(program, operand, \"source\");\n if (!register) continue;\n const components = operandComponents(\n operand,\n false,\n fixedSourceLanes(instruction, operandIndex, program) || activeSourceComponents);\n const refs = components.map((component) => ensureComponent(state, values, register, component, block.id));\n for (const ref of refs)\n {\n const value = values.find((entry) => entry.id === ref.valueId);\n if (value?.origin === \"block-input\") inputIds.add(value.id);\n }\n reads.push({ kind: \"register-read\", operandIndex, register, components, refs });\n }\n\n for (let operandIndex = 0; operandIndex < roles.length; operandIndex += 1)\n {\n const { operand } = roles[operandIndex];\n const indices = operand.indices || [];\n for (let dimension = 0; dimension < indices.length; dimension += 1)\n {\n const relative = indices[dimension].relative;\n if (!relative) continue;\n const register = registerKey(program, relative, \"source\");\n if (!register) throw new Error(\"Shader IR relative index uses an unsupported register file\");\n const components = operandComponents(relative, false);\n if (components.length !== 1) throw new Error(\"Shader IR relative index requires one scalar component\");\n const refs = components.map((component) => ensureComponent(state, values, register, component, block.id));\n for (const ref of refs)\n {\n const value = values.find((entry) => entry.id === ref.valueId);\n if (value?.origin === \"block-input\") inputIds.add(value.id);\n }\n reads.push({ kind: \"index-read\", operandIndex, dimension, register, components, refs });\n }\n }\n\n for (let operandIndex = 0; operandIndex < roles.length; operandIndex += 1)\n {\n const { operand, role } = roles[operandIndex];\n if (role !== \"destination\" || operand.typeName === \"null\") continue;\n const register = registerKey(program, operand, \"destination\");\n if (!register) continue;\n const mask = operandComponents(operand, true);\n const previous = {};\n for (const component of COMPONENTS)\n {\n if (!mask.includes(component))\n {\n previous[component] = ensureComponent(state, values, register, component, block.id);\n }\n }\n const value = {\n kind: \"register-value\",\n id: `value${values.length}`,\n origin: \"instruction-write\",\n blockId: block.id,\n instructionIndex,\n register,\n writeMask: mask.join(\"\"),\n previous: Object.keys(previous).length ? previous : null\n };\n values.push(value);\n let components = state.get(register);\n if (!components)\n {\n components = new Map();\n state.set(register, components);\n }\n for (const component of mask) components.set(component, valueRef(value, component));\n const result = {};\n for (const component of COMPONENTS)\n {\n result[component] = components.get(component) || ensureComponent(state, values, register, component, block.id);\n }\n writes.push({\n kind: \"register-write\",\n operandIndex,\n register,\n mask: mask.join(\"\"),\n valueId: value.id,\n previous: value.previous,\n result\n });\n }\n instruction.dataflow = { reads, writes };\n }\n block.inputValueIds = Array.from(inputIds);\n block.outputValues = Array.from(state.entries())\n .flatMap(([ register, components ]) => Array.from(components.entries())\n .map(([ component, ref ]) => ({ register, component, ref })))\n .sort((a, b) => a.register.localeCompare(b.register) || a.component.localeCompare(b.component));\n}\n\n/**\n * Adds block-local register versions, masked-write reconstruction records,\n * and deterministic block-exit state. A later pass resolves the conservative\n * block inputs through CFG predecessors.\n *\n * @param {object} program Mutable shader IR under construction.\n * @returns {object} The same program.\n */\nexport function analyzeRegisterValues(program)\n{\n const values = [];\n for (const block of program.blocks) analyzeBlock(program, block, values);\n program.values = values;\n return program;\n}\n"],"names":["COMPONENTS","REGISTER_FILES","Set","WRITABLE_FILES","NO_DESTINATION","DUAL_DESTINATION","FULL_SOURCE_LANES","operandComponents","operand","destination","activeComponents","mask","filter","component","includes","componentCount","slice","swizzle","map","indexOf","Array","from","selected","registerKey","program","role","has","typeName","validateIndexableTempOperand","key","indices","index","immediate","values","join","relative","operandRoles","instruction","operands","opcodeName","valueRef","value","valueId","id","ensureComponent","state","register","blockId","components","get","Map","set","kind","length","origin","instructionIndex","writeMask","previous","push","analyzeBlock","block","inputIds","instructionIndices","instructions","roles","destinationComponents","entry","flatMap","activeSourceComponents","reads","writes","operandIndex","fixedSourceLanes","refs","ref","find","add","dimension","Error","Object","keys","result","dataflow","inputValueIds","outputValues","entries","sort","a","b","localeCompare","analyzeRegisterValues","blocks"],"mappings":"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"}
@@ -0,0 +1,220 @@
1
+ const CONDITIONAL_EXITS = new Set(["retc", "discard"]);
2
+ const TERMINAL_EXITS = new Set(["ret", "abort"]);
3
+ const UNSUPPORTED_FLOW = new Set(["call", "callc", "label", "interface_call"]);
4
+ function collectRegions(instructions) {
5
+ const regions = [];
6
+ const stack = [];
7
+ const requireTop = (kind, opcode, index) => {
8
+ const region = stack.at(-1);
9
+ if (!region || region.kind !== kind) {
10
+ throw new Error(`Shader IR has mismatched ${opcode} at instruction ${index}`);
11
+ }
12
+ return region;
13
+ };
14
+ for (const instruction of instructions) {
15
+ const index = instruction.index;
16
+ switch (instruction.opcodeName) {
17
+ case "if":
18
+ stack.push({
19
+ kind: "selection",
20
+ startInstruction: index,
21
+ elseInstruction: null
22
+ });
23
+ break;
24
+ case "else":
25
+ {
26
+ const region = requireTop("selection", "else", index);
27
+ if (region.elseInstruction !== null) throw new Error(`Shader IR has duplicate else at instruction ${index}`);
28
+ region.elseInstruction = index;
29
+ break;
30
+ }
31
+ case "endif":
32
+ {
33
+ const region = requireTop("selection", "endif", index);
34
+ stack.pop();
35
+ region.endInstruction = index;
36
+ regions.push(region);
37
+ break;
38
+ }
39
+ case "loop":
40
+ stack.push({
41
+ kind: "loop",
42
+ startInstruction: index
43
+ });
44
+ break;
45
+ case "endloop":
46
+ {
47
+ const region = requireTop("loop", "endloop", index);
48
+ stack.pop();
49
+ region.endInstruction = index;
50
+ regions.push(region);
51
+ break;
52
+ }
53
+ case "switch":
54
+ stack.push({
55
+ kind: "switch",
56
+ startInstruction: index,
57
+ caseInstructions: [],
58
+ defaultInstruction: null
59
+ });
60
+ break;
61
+ case "case":
62
+ {
63
+ const region = requireTop("switch", "case", index);
64
+ region.caseInstructions.push(index);
65
+ break;
66
+ }
67
+ case "default":
68
+ {
69
+ const region = requireTop("switch", "default", index);
70
+ if (region.defaultInstruction !== null) throw new Error(`Shader IR has duplicate default at instruction ${index}`);
71
+ region.defaultInstruction = index;
72
+ break;
73
+ }
74
+ case "endswitch":
75
+ {
76
+ const region = requireTop("switch", "endswitch", index);
77
+ stack.pop();
78
+ region.endInstruction = index;
79
+ regions.push(region);
80
+ break;
81
+ }
82
+ }
83
+ }
84
+ if (stack.length) {
85
+ throw new Error("Shader IR contains an unterminated structured control-flow region");
86
+ }
87
+ return regions.sort((a, b) => a.startInstruction - b.startInstruction);
88
+ }
89
+ function containingRegion(regions, instructionIndex, kinds) {
90
+ return regions.filter(region => kinds.has(region.kind) && region.startInstruction < instructionIndex && instructionIndex < region.endInstruction).sort((a, b) => b.startInstruction - a.startInstruction)[0] || null;
91
+ }
92
+ function addEdge(from, to, kind) {
93
+ if (!to) return;
94
+ if (!from.successors.some(edge => edge.blockId === to.id && edge.kind === kind)) {
95
+ from.successors.push({
96
+ blockId: to.id,
97
+ kind
98
+ });
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Adds structured CFG edges without attempting register SSA construction.
104
+ * Join blocks receive merge-site metadata consumed by the later SSA pass.
105
+ *
106
+ * @param {object} program Mutable shader IR under construction.
107
+ * @returns {object} The same program.
108
+ */
109
+ function buildControlFlow(program) {
110
+ const {
111
+ blocks,
112
+ instructions
113
+ } = program;
114
+ const unsupported = instructions.find(instruction => UNSUPPORTED_FLOW.has(instruction.opcodeName));
115
+ if (unsupported) {
116
+ throw new Error(`Shader IR does not yet support ${unsupported.opcodeName} control flow at instruction ${unsupported.index}`);
117
+ }
118
+ const regions = collectRegions(instructions);
119
+ const blockAtInstruction = new Map();
120
+ const blockById = new Map(blocks.map(block => [block.id, block]));
121
+ for (const block of blocks) {
122
+ block.successors = [];
123
+ block.predecessors = [];
124
+ block.exits = [];
125
+ block.mergeSite = null;
126
+ for (const index of block.instructionIndices) blockAtInstruction.set(index, block);
127
+ }
128
+ const blockAfterInstruction = index => blockAtInstruction.get(index + 1) || null;
129
+ const regionStartingAt = new Map(regions.map(region => [region.startInstruction, region]));
130
+ const elseRegion = new Map(regions.filter(region => region.kind === "selection" && region.elseInstruction !== null).map(region => [region.elseInstruction, region]));
131
+ for (const block of blocks) {
132
+ const last = instructions[block.endInstruction];
133
+ const next = blocks[block.index + 1] || null;
134
+ const opcode = last.opcodeName;
135
+ const region = regionStartingAt.get(last.index);
136
+ if (opcode === "if") {
137
+ const trueTarget = region.elseInstruction === next?.startInstruction ? blockAtInstruction.get(region.endInstruction) : next;
138
+ addEdge(block, trueTarget, "selection-true");
139
+ const falseInstruction = region.elseInstruction ?? region.endInstruction;
140
+ addEdge(block, blockAtInstruction.get(falseInstruction), "selection-false");
141
+ } else if (opcode === "switch") {
142
+ for (const caseInstruction of region.caseInstructions) {
143
+ addEdge(block, blockAtInstruction.get(caseInstruction), "switch-case");
144
+ }
145
+ const fallback = region.defaultInstruction ?? region.endInstruction;
146
+ addEdge(block, blockAtInstruction.get(fallback), region.defaultInstruction === null ? "switch-no-match" : "switch-default");
147
+ } else if (opcode === "break" || opcode === "breakc") {
148
+ const owner = containingRegion(regions, last.index, new Set(["loop", "switch"]));
149
+ if (!owner) throw new Error(`Shader IR has ${opcode} outside loop or switch at instruction ${last.index}`);
150
+ const target = blockAfterInstruction(owner.endInstruction);
151
+ if (target) addEdge(block, target, "break");else block.exits.push("break");
152
+ if (opcode === "breakc") addEdge(block, next, "condition-false");
153
+ } else if (opcode === "continue" || opcode === "continuec") {
154
+ const owner = containingRegion(regions, last.index, new Set(["loop"]));
155
+ if (!owner) throw new Error(`Shader IR has ${opcode} outside loop at instruction ${last.index}`);
156
+ addEdge(block, blockAtInstruction.get(owner.endInstruction), "continue");
157
+ if (opcode === "continuec") addEdge(block, next, "condition-false");
158
+ } else if (opcode === "endloop") {
159
+ const owner = regions.find(entry => entry.kind === "loop" && entry.endInstruction === last.index);
160
+ addEdge(block, blockAtInstruction.get(owner.startInstruction), "loop-back");
161
+ } else if (TERMINAL_EXITS.has(opcode)) {
162
+ block.exits.push(opcode === "abort" ? "abort" : "return");
163
+ } else if (CONDITIONAL_EXITS.has(opcode)) {
164
+ block.exits.push(opcode === "discard" ? "discard" : "return");
165
+ addEdge(block, next, "condition-false");
166
+ } else {
167
+ const upcomingElse = next ? elseRegion.get(next.startInstruction) : null;
168
+ if (upcomingElse) {
169
+ addEdge(block, blockAtInstruction.get(upcomingElse.endInstruction), "selection-merge");
170
+ } else {
171
+ addEdge(block, next, opcode === "loop" ? "loop-body" : "fallthrough");
172
+ }
173
+ }
174
+ }
175
+ for (const block of blocks) {
176
+ for (const edge of block.successors) {
177
+ blockById.get(edge.blockId).predecessors.push({
178
+ blockId: block.id,
179
+ kind: edge.kind
180
+ });
181
+ }
182
+ }
183
+ const reachable = new Set();
184
+ const pending = blocks.length ? [blocks[0]] : [];
185
+ while (pending.length) {
186
+ const block = pending.shift();
187
+ if (reachable.has(block.id)) continue;
188
+ reachable.add(block.id);
189
+ for (const edge of block.successors) pending.push(blockById.get(edge.blockId));
190
+ }
191
+ for (const block of blocks) block.reachable = reachable.has(block.id);
192
+ for (const block of blocks) {
193
+ const predecessorBlockIds = Array.from(new Set(block.predecessors.map(edge => edge.blockId))).filter(id => block.reachable && blockById.get(id).reachable);
194
+ const includesEntry = block.id === blocks[0]?.id;
195
+ if (predecessorBlockIds.length > 1 || includesEntry && predecessorBlockIds.length > 0) {
196
+ block.mergeSite = {
197
+ kind: "control-flow-merge-site",
198
+ id: `merge:${block.id}`,
199
+ predecessorBlockIds,
200
+ includesEntry,
201
+ requiresRegisterMerge: true
202
+ };
203
+ }
204
+ }
205
+ program.controlFlow = {
206
+ kind: "control-flow-graph",
207
+ entryBlockId: blocks[0]?.id || null,
208
+ edgeCount: blocks.reduce((total, block) => total + block.successors.length, 0),
209
+ reachableBlockIds: blocks.filter(block => block.reachable).map(block => block.id),
210
+ unreachableBlockIds: blocks.filter(block => !block.reachable).map(block => block.id),
211
+ regions: regions.map((region, index) => ({
212
+ id: `region${index}`,
213
+ ...region
214
+ }))
215
+ };
216
+ return program;
217
+ }
218
+
219
+ export { buildControlFlow };
220
+ //# sourceMappingURL=buildControlFlow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildControlFlow.js","sources":["../../../../../../src/formats/webgpu/core/ir/buildControlFlow.js"],"sourcesContent":["const CONDITIONAL_EXITS = new Set([ \"retc\", \"discard\" ]);\nconst TERMINAL_EXITS = new Set([ \"ret\", \"abort\" ]);\nconst UNSUPPORTED_FLOW = new Set([ \"call\", \"callc\", \"label\", \"interface_call\" ]);\n\nfunction collectRegions(instructions)\n{\n const regions = [];\n const stack = [];\n\n const requireTop = (kind, opcode, index) =>\n {\n const region = stack.at(-1);\n if (!region || region.kind !== kind)\n {\n throw new Error(`Shader IR has mismatched ${opcode} at instruction ${index}`);\n }\n return region;\n };\n\n for (const instruction of instructions)\n {\n const index = instruction.index;\n switch (instruction.opcodeName)\n {\n case \"if\":\n stack.push({ kind: \"selection\", startInstruction: index, elseInstruction: null });\n break;\n case \"else\":\n {\n const region = requireTop(\"selection\", \"else\", index);\n if (region.elseInstruction !== null) throw new Error(`Shader IR has duplicate else at instruction ${index}`);\n region.elseInstruction = index;\n break;\n }\n case \"endif\":\n {\n const region = requireTop(\"selection\", \"endif\", index);\n stack.pop();\n region.endInstruction = index;\n regions.push(region);\n break;\n }\n case \"loop\":\n stack.push({ kind: \"loop\", startInstruction: index });\n break;\n case \"endloop\":\n {\n const region = requireTop(\"loop\", \"endloop\", index);\n stack.pop();\n region.endInstruction = index;\n regions.push(region);\n break;\n }\n case \"switch\":\n stack.push({ kind: \"switch\", startInstruction: index, caseInstructions: [], defaultInstruction: null });\n break;\n case \"case\":\n {\n const region = requireTop(\"switch\", \"case\", index);\n region.caseInstructions.push(index);\n break;\n }\n case \"default\":\n {\n const region = requireTop(\"switch\", \"default\", index);\n if (region.defaultInstruction !== null) throw new Error(`Shader IR has duplicate default at instruction ${index}`);\n region.defaultInstruction = index;\n break;\n }\n case \"endswitch\":\n {\n const region = requireTop(\"switch\", \"endswitch\", index);\n stack.pop();\n region.endInstruction = index;\n regions.push(region);\n break;\n }\n default:\n break;\n }\n }\n\n if (stack.length)\n {\n throw new Error(\"Shader IR contains an unterminated structured control-flow region\");\n }\n return regions.sort((a, b) => a.startInstruction - b.startInstruction);\n}\n\nfunction containingRegion(regions, instructionIndex, kinds)\n{\n return regions\n .filter((region) => kinds.has(region.kind)\n && region.startInstruction < instructionIndex\n && instructionIndex < region.endInstruction)\n .sort((a, b) => b.startInstruction - a.startInstruction)[0] || null;\n}\n\nfunction addEdge(from, to, kind)\n{\n if (!to) return;\n if (!from.successors.some((edge) => edge.blockId === to.id && edge.kind === kind))\n {\n from.successors.push({ blockId: to.id, kind });\n }\n}\n\n/**\n * Adds structured CFG edges without attempting register SSA construction.\n * Join blocks receive merge-site metadata consumed by the later SSA pass.\n *\n * @param {object} program Mutable shader IR under construction.\n * @returns {object} The same program.\n */\nexport function buildControlFlow(program)\n{\n const { blocks, instructions } = program;\n const unsupported = instructions.find((instruction) => UNSUPPORTED_FLOW.has(instruction.opcodeName));\n if (unsupported)\n {\n throw new Error(`Shader IR does not yet support ${unsupported.opcodeName} control flow at instruction ${unsupported.index}`);\n }\n const regions = collectRegions(instructions);\n const blockAtInstruction = new Map();\n const blockById = new Map(blocks.map((block) => [ block.id, block ]));\n for (const block of blocks)\n {\n block.successors = [];\n block.predecessors = [];\n block.exits = [];\n block.mergeSite = null;\n for (const index of block.instructionIndices) blockAtInstruction.set(index, block);\n }\n\n const blockAfterInstruction = (index) => blockAtInstruction.get(index + 1) || null;\n const regionStartingAt = new Map(regions.map((region) => [ region.startInstruction, region ]));\n const elseRegion = new Map(regions\n .filter((region) => region.kind === \"selection\" && region.elseInstruction !== null)\n .map((region) => [ region.elseInstruction, region ]));\n\n for (const block of blocks)\n {\n const last = instructions[block.endInstruction];\n const next = blocks[block.index + 1] || null;\n const opcode = last.opcodeName;\n const region = regionStartingAt.get(last.index);\n\n if (opcode === \"if\")\n {\n const trueTarget = region.elseInstruction === next?.startInstruction\n ? blockAtInstruction.get(region.endInstruction)\n : next;\n addEdge(block, trueTarget, \"selection-true\");\n const falseInstruction = region.elseInstruction ?? region.endInstruction;\n addEdge(block, blockAtInstruction.get(falseInstruction), \"selection-false\");\n }\n else if (opcode === \"switch\")\n {\n for (const caseInstruction of region.caseInstructions)\n {\n addEdge(block, blockAtInstruction.get(caseInstruction), \"switch-case\");\n }\n const fallback = region.defaultInstruction ?? region.endInstruction;\n addEdge(block, blockAtInstruction.get(fallback), region.defaultInstruction === null ? \"switch-no-match\" : \"switch-default\");\n }\n else if (opcode === \"break\" || opcode === \"breakc\")\n {\n const owner = containingRegion(regions, last.index, new Set([ \"loop\", \"switch\" ]));\n if (!owner) throw new Error(`Shader IR has ${opcode} outside loop or switch at instruction ${last.index}`);\n const target = blockAfterInstruction(owner.endInstruction);\n if (target) addEdge(block, target, \"break\");\n else block.exits.push(\"break\");\n if (opcode === \"breakc\") addEdge(block, next, \"condition-false\");\n }\n else if (opcode === \"continue\" || opcode === \"continuec\")\n {\n const owner = containingRegion(regions, last.index, new Set([ \"loop\" ]));\n if (!owner) throw new Error(`Shader IR has ${opcode} outside loop at instruction ${last.index}`);\n addEdge(block, blockAtInstruction.get(owner.endInstruction), \"continue\");\n if (opcode === \"continuec\") addEdge(block, next, \"condition-false\");\n }\n else if (opcode === \"endloop\")\n {\n const owner = regions.find((entry) => entry.kind === \"loop\" && entry.endInstruction === last.index);\n addEdge(block, blockAtInstruction.get(owner.startInstruction), \"loop-back\");\n }\n else if (TERMINAL_EXITS.has(opcode))\n {\n block.exits.push(opcode === \"abort\" ? \"abort\" : \"return\");\n }\n else if (CONDITIONAL_EXITS.has(opcode))\n {\n block.exits.push(opcode === \"discard\" ? \"discard\" : \"return\");\n addEdge(block, next, \"condition-false\");\n }\n else\n {\n const upcomingElse = next ? elseRegion.get(next.startInstruction) : null;\n if (upcomingElse)\n {\n addEdge(block, blockAtInstruction.get(upcomingElse.endInstruction), \"selection-merge\");\n }\n else\n {\n addEdge(block, next, opcode === \"loop\" ? \"loop-body\" : \"fallthrough\");\n }\n }\n }\n\n for (const block of blocks)\n {\n for (const edge of block.successors)\n {\n blockById.get(edge.blockId).predecessors.push({ blockId: block.id, kind: edge.kind });\n }\n }\n\n const reachable = new Set();\n const pending = blocks.length ? [ blocks[0] ] : [];\n while (pending.length)\n {\n const block = pending.shift();\n if (reachable.has(block.id)) continue;\n reachable.add(block.id);\n for (const edge of block.successors) pending.push(blockById.get(edge.blockId));\n }\n for (const block of blocks) block.reachable = reachable.has(block.id);\n for (const block of blocks)\n {\n const predecessorBlockIds = Array.from(new Set(block.predecessors.map((edge) => edge.blockId)))\n .filter((id) => block.reachable && blockById.get(id).reachable);\n const includesEntry = block.id === blocks[0]?.id;\n if (predecessorBlockIds.length > 1 || (includesEntry && predecessorBlockIds.length > 0))\n {\n block.mergeSite = {\n kind: \"control-flow-merge-site\",\n id: `merge:${block.id}`,\n predecessorBlockIds,\n includesEntry,\n requiresRegisterMerge: true\n };\n }\n }\n\n program.controlFlow = {\n kind: \"control-flow-graph\",\n entryBlockId: blocks[0]?.id || null,\n edgeCount: blocks.reduce((total, block) => total + block.successors.length, 0),\n reachableBlockIds: blocks.filter((block) => block.reachable).map((block) => block.id),\n unreachableBlockIds: blocks.filter((block) => !block.reachable).map((block) => block.id),\n regions: regions.map((region, index) => ({ id: `region${index}`, ...region }))\n };\n return program;\n}\n"],"names":["CONDITIONAL_EXITS","Set","TERMINAL_EXITS","UNSUPPORTED_FLOW","collectRegions","instructions","regions","stack","requireTop","kind","opcode","index","region","at","Error","instruction","opcodeName","push","startInstruction","elseInstruction","pop","endInstruction","caseInstructions","defaultInstruction","length","sort","a","b","containingRegion","instructionIndex","kinds","filter","has","addEdge","from","to","successors","some","edge","blockId","id","buildControlFlow","program","blocks","unsupported","find","blockAtInstruction","Map","blockById","map","block","predecessors","exits","mergeSite","instructionIndices","set","blockAfterInstruction","get","regionStartingAt","elseRegion","last","next","trueTarget","falseInstruction","caseInstruction","fallback","owner","target","entry","upcomingElse","reachable","pending","shift","add","predecessorBlockIds","Array","includesEntry","requiresRegisterMerge","controlFlow","entryBlockId","edgeCount","reduce","total","reachableBlockIds","unreachableBlockIds"],"mappings":"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"}