@forgeax/engine-runtime 0.1.23 → 0.1.24

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 (368) hide show
  1. package/README.md +15 -6
  2. package/dist/__tests__/advance-animation-player.cases.unit.test.d.ts +2 -0
  3. package/dist/__tests__/advance-animation-player.cases.unit.test.d.ts.map +1 -0
  4. package/dist/__tests__/asset-registry-aabb.cases.unit.test.d.ts +2 -0
  5. package/dist/__tests__/asset-registry-aabb.cases.unit.test.d.ts.map +1 -0
  6. package/dist/__tests__/asset-registry-bootstrap.cases.unit.test.d.ts +2 -0
  7. package/dist/__tests__/asset-registry-bootstrap.cases.unit.test.d.ts.map +1 -0
  8. package/dist/__tests__/asset-registry-builtin-nineslice.cases.unit.test.d.ts +2 -0
  9. package/dist/__tests__/asset-registry-builtin-nineslice.cases.unit.test.d.ts.map +1 -0
  10. package/dist/__tests__/asset-registry-d9-tile-sampler-soft-warn.cases.unit.test.d.ts +2 -0
  11. package/dist/__tests__/asset-registry-d9-tile-sampler-soft-warn.cases.unit.test.d.ts.map +1 -0
  12. package/dist/__tests__/asset-registry-guid.cases.unit.test.d.ts +2 -0
  13. package/dist/__tests__/asset-registry-guid.cases.unit.test.d.ts.map +1 -0
  14. package/dist/__tests__/asset-registry-material-validate.cases.unit.test.d.ts +2 -0
  15. package/dist/__tests__/asset-registry-material-validate.cases.unit.test.d.ts.map +1 -0
  16. package/dist/__tests__/asset-registry-mesh-fail-fast.cases.unit.test.d.ts +2 -0
  17. package/dist/__tests__/asset-registry-mesh-fail-fast.cases.unit.test.d.ts.map +1 -0
  18. package/dist/__tests__/asset-registry-scene.cases.unit.test.d.ts +2 -0
  19. package/dist/__tests__/asset-registry-scene.cases.unit.test.d.ts.map +1 -0
  20. package/dist/__tests__/asset-registry-sprite-slices-validate.cases.unit.test.d.ts +2 -0
  21. package/dist/__tests__/asset-registry-sprite-slices-validate.cases.unit.test.d.ts.map +1 -0
  22. package/dist/__tests__/asset-renderer-assembly.cases.unit.test.d.ts +2 -0
  23. package/dist/__tests__/asset-renderer-assembly.cases.unit.test.d.ts.map +1 -0
  24. package/dist/__tests__/asset.cases.unit.test.d.ts +2 -0
  25. package/dist/__tests__/asset.cases.unit.test.d.ts.map +1 -0
  26. package/dist/__tests__/bloom-gating.cases.unit.test.d.ts +2 -0
  27. package/dist/__tests__/bloom-gating.cases.unit.test.d.ts.map +1 -0
  28. package/dist/__tests__/builtin-guid-ssot.cases.unit.test.d.ts +2 -0
  29. package/dist/__tests__/builtin-guid-ssot.cases.unit.test.d.ts.map +1 -0
  30. package/dist/__tests__/builtin-pack.cases.unit.test.d.ts +2 -0
  31. package/dist/__tests__/builtin-pack.cases.unit.test.d.ts.map +1 -0
  32. package/dist/__tests__/camera-antialias.cases.unit.test.d.ts +2 -0
  33. package/dist/__tests__/camera-antialias.cases.unit.test.d.ts.map +1 -0
  34. package/dist/__tests__/camera-bloom.cases.unit.test.d.ts +2 -0
  35. package/dist/__tests__/camera-bloom.cases.unit.test.d.ts.map +1 -0
  36. package/dist/__tests__/camera-clear-schema.cases.unit.test.d.ts +2 -0
  37. package/dist/__tests__/camera-clear-schema.cases.unit.test.d.ts.map +1 -0
  38. package/dist/__tests__/camera-ortho.cases.unit.test.d.ts +2 -0
  39. package/dist/__tests__/camera-ortho.cases.unit.test.d.ts.map +1 -0
  40. package/dist/__tests__/cluster-binner.cases.unit.test.d.ts +2 -0
  41. package/dist/__tests__/cluster-binner.cases.unit.test.d.ts.map +1 -0
  42. package/dist/__tests__/create-renderer-fallback-shader-manifest.cases.unit.test.d.ts +2 -0
  43. package/dist/__tests__/create-renderer-fallback-shader-manifest.cases.unit.test.d.ts.map +1 -0
  44. package/dist/__tests__/create-renderer-uniform-fallback.cases.unit.test.d.ts +2 -0
  45. package/dist/__tests__/create-renderer-uniform-fallback.cases.unit.test.d.ts.map +1 -0
  46. package/dist/__tests__/cubemap-upload.cases.unit.test.d.ts +2 -0
  47. package/dist/__tests__/cubemap-upload.cases.unit.test.d.ts.map +1 -0
  48. package/dist/__tests__/dev-import-transport.cases.unit.test.d.ts +2 -0
  49. package/dist/__tests__/dev-import-transport.cases.unit.test.d.ts.map +1 -0
  50. package/dist/__tests__/engine-metrics.cases.unit.test.d.ts +2 -0
  51. package/dist/__tests__/engine-metrics.cases.unit.test.d.ts.map +1 -0
  52. package/dist/__tests__/equirect-projection-error.cases.unit.test.d.ts +2 -0
  53. package/dist/__tests__/equirect-projection-error.cases.unit.test.d.ts.map +1 -0
  54. package/dist/__tests__/font-asset-load.cases.unit.test.d.ts +2 -0
  55. package/dist/__tests__/font-asset-load.cases.unit.test.d.ts.map +1 -0
  56. package/dist/__tests__/fxaa-intermediate-texture.cases.unit.test.d.ts +2 -0
  57. package/dist/__tests__/fxaa-intermediate-texture.cases.unit.test.d.ts.map +1 -0
  58. package/dist/__tests__/fxaa-pipeline.cases.unit.test.d.ts +2 -0
  59. package/dist/__tests__/fxaa-pipeline.cases.unit.test.d.ts.map +1 -0
  60. package/dist/__tests__/gpu-residency.cases.unit.test.d.ts +2 -0
  61. package/dist/__tests__/gpu-residency.cases.unit.test.d.ts.map +1 -0
  62. package/dist/__tests__/gpu-resource-release.cases.unit.test.d.ts +2 -0
  63. package/dist/__tests__/gpu-resource-release.cases.unit.test.d.ts.map +1 -0
  64. package/dist/__tests__/handle-quad.cases.unit.test.d.ts +2 -0
  65. package/dist/__tests__/handle-quad.cases.unit.test.d.ts.map +1 -0
  66. package/dist/__tests__/hdrp-bgl-slots.cases.unit.test.d.ts +2 -0
  67. package/dist/__tests__/hdrp-bgl-slots.cases.unit.test.d.ts.map +1 -0
  68. package/dist/__tests__/hdrp-grid-invalid.cases.unit.test.d.ts +2 -0
  69. package/dist/__tests__/hdrp-grid-invalid.cases.unit.test.d.ts.map +1 -0
  70. package/dist/__tests__/hdrp-index-list-overflow-once.cases.unit.test.d.ts +2 -0
  71. package/dist/__tests__/hdrp-index-list-overflow-once.cases.unit.test.d.ts.map +1 -0
  72. package/dist/__tests__/hdrp-light-budget.cases.unit.test.d.ts +2 -0
  73. package/dist/__tests__/hdrp-light-budget.cases.unit.test.d.ts.map +1 -0
  74. package/dist/__tests__/hdrp-pipeline-asset-config.cases.unit.test.d.ts +2 -0
  75. package/dist/__tests__/hdrp-pipeline-asset-config.cases.unit.test.d.ts.map +1 -0
  76. package/dist/__tests__/helpers/renderer-device-loss-dawn.d.ts +25 -0
  77. package/dist/__tests__/helpers/renderer-device-loss-dawn.d.ts.map +1 -0
  78. package/dist/__tests__/helpers/standard-material-manifest.d.ts +0 -1
  79. package/dist/__tests__/helpers/standard-material-manifest.d.ts.map +1 -1
  80. package/dist/__tests__/ibl-pipeline-cache.cases.unit.test.d.ts +2 -0
  81. package/dist/__tests__/ibl-pipeline-cache.cases.unit.test.d.ts.map +1 -0
  82. package/dist/__tests__/lazy-catalog.cases.unit.test.d.ts +2 -0
  83. package/dist/__tests__/lazy-catalog.cases.unit.test.d.ts.map +1 -0
  84. package/dist/__tests__/load-by-guid-hdr.cases.unit.test.d.ts +2 -0
  85. package/dist/__tests__/load-by-guid-hdr.cases.unit.test.d.ts.map +1 -0
  86. package/dist/__tests__/load-by-guid-prod-material-parent.cases.unit.test.d.ts +2 -0
  87. package/dist/__tests__/load-by-guid-prod-material-parent.cases.unit.test.d.ts.map +1 -0
  88. package/dist/__tests__/load-by-guid-prod.cases.unit.test.d.ts +2 -0
  89. package/dist/__tests__/load-by-guid-prod.cases.unit.test.d.ts.map +1 -0
  90. package/dist/__tests__/loader-registry.cases.unit.test.d.ts +2 -0
  91. package/dist/__tests__/loader-registry.cases.unit.test.d.ts.map +1 -0
  92. package/dist/__tests__/m7-hdrp-demo-shape.cases.unit.test.d.ts +2 -0
  93. package/dist/__tests__/m7-hdrp-demo-shape.cases.unit.test.d.ts.map +1 -0
  94. package/dist/__tests__/mipmap-formula.cases.unit.test.d.ts +2 -0
  95. package/dist/__tests__/mipmap-formula.cases.unit.test.d.ts.map +1 -0
  96. package/dist/__tests__/mipmap-pipeline-cache.cases.unit.test.d.ts +2 -0
  97. package/dist/__tests__/mipmap-pipeline-cache.cases.unit.test.d.ts.map +1 -0
  98. package/dist/__tests__/parse-asset-payload-material.cases.unit.test.d.ts +2 -0
  99. package/dist/__tests__/parse-asset-payload-material.cases.unit.test.d.ts.map +1 -0
  100. package/dist/__tests__/parse-asset-payload-texture.cases.unit.test.d.ts +2 -0
  101. package/dist/__tests__/parse-asset-payload-texture.cases.unit.test.d.ts.map +1 -0
  102. package/dist/__tests__/parse-scene-payload-refs.cases.unit.test.d.ts +2 -0
  103. package/dist/__tests__/parse-scene-payload-refs.cases.unit.test.d.ts.map +1 -0
  104. package/dist/__tests__/pass-selector.cases.unit.test.d.ts +2 -0
  105. package/dist/__tests__/pass-selector.cases.unit.test.d.ts.map +1 -0
  106. package/dist/__tests__/pipeline-builder.cases.unit.test.d.ts +2 -0
  107. package/dist/__tests__/pipeline-builder.cases.unit.test.d.ts.map +1 -0
  108. package/dist/__tests__/pipeline-cache-key-topology.cases.unit.test.d.ts +2 -0
  109. package/dist/__tests__/pipeline-cache-key-topology.cases.unit.test.d.ts.map +1 -0
  110. package/dist/__tests__/pipeline-vertex-stride-branch.cases.unit.test.d.ts +2 -0
  111. package/dist/__tests__/pipeline-vertex-stride-branch.cases.unit.test.d.ts.map +1 -0
  112. package/dist/__tests__/pipeline.cases.unit.test.d.ts +2 -0
  113. package/dist/__tests__/pipeline.cases.unit.test.d.ts.map +1 -0
  114. package/dist/__tests__/post-process-register.cases.unit.test.d.ts +2 -0
  115. package/dist/__tests__/post-process-register.cases.unit.test.d.ts.map +1 -0
  116. package/dist/__tests__/propagate-transforms.cases.unit.test.d.ts +2 -0
  117. package/dist/__tests__/propagate-transforms.cases.unit.test.d.ts.map +1 -0
  118. package/dist/__tests__/record-all-topology.cases.unit.test.d.ts +2 -0
  119. package/dist/__tests__/record-all-topology.cases.unit.test.d.ts.map +1 -0
  120. package/dist/__tests__/record-draw-branch.cases.unit.test.d.ts +2 -0
  121. package/dist/__tests__/record-draw-branch.cases.unit.test.d.ts.map +1 -0
  122. package/dist/__tests__/record-strip-index-format.cases.unit.test.d.ts +2 -0
  123. package/dist/__tests__/record-strip-index-format.cases.unit.test.d.ts.map +1 -0
  124. package/dist/__tests__/register-with-guid-rgba16float.cases.unit.test.d.ts +2 -0
  125. package/dist/__tests__/register-with-guid-rgba16float.cases.unit.test.d.ts.map +1 -0
  126. package/dist/__tests__/render-data.cases.unit.test.d.ts +2 -0
  127. package/dist/__tests__/render-data.cases.unit.test.d.ts.map +1 -0
  128. package/dist/__tests__/render-error-exhaustive.test-d.d.ts.map +1 -1
  129. package/dist/__tests__/render-query-regression.cases.unit.test.d.ts +2 -0
  130. package/dist/__tests__/render-query-regression.cases.unit.test.d.ts.map +1 -0
  131. package/dist/__tests__/render-system-record-submesh.cases.unit.test.d.ts +2 -0
  132. package/dist/__tests__/render-system-record-submesh.cases.unit.test.d.ts.map +1 -0
  133. package/dist/__tests__/render-system-record-warn-once.cases.unit.test.d.ts +2 -0
  134. package/dist/__tests__/render-system-record-warn-once.cases.unit.test.d.ts.map +1 -0
  135. package/dist/__tests__/renderer-device-loss-multi-world.integration.test.d.ts +2 -0
  136. package/dist/__tests__/renderer-device-loss-multi-world.integration.test.d.ts.map +1 -0
  137. package/dist/__tests__/renderer-device-loss-provider-feasibility.dawn.test.d.ts +2 -0
  138. package/dist/__tests__/renderer-device-loss-provider-feasibility.dawn.test.d.ts.map +1 -0
  139. package/dist/__tests__/renderer-device-loss-recovery.dawn.test.d.ts +2 -0
  140. package/dist/__tests__/renderer-device-loss-recovery.dawn.test.d.ts.map +1 -0
  141. package/dist/__tests__/renderer-draw-world.cases.unit.test.d.ts +2 -0
  142. package/dist/__tests__/renderer-draw-world.cases.unit.test.d.ts.map +1 -0
  143. package/dist/__tests__/renderer-recovery-consumer.integration.test.d.ts +2 -0
  144. package/dist/__tests__/renderer-recovery-consumer.integration.test.d.ts.map +1 -0
  145. package/dist/__tests__/renderstate-pipeline-cache.cases.unit.test.d.ts +2 -0
  146. package/dist/__tests__/renderstate-pipeline-cache.cases.unit.test.d.ts.map +1 -0
  147. package/dist/__tests__/resolve-scene-guids.cases.unit.test.d.ts +2 -0
  148. package/dist/__tests__/resolve-scene-guids.cases.unit.test.d.ts.map +1 -0
  149. package/dist/__tests__/shadow-skip-non-triangle.cases.unit.test.d.ts +2 -0
  150. package/dist/__tests__/shadow-skip-non-triangle.cases.unit.test.d.ts.map +1 -0
  151. package/dist/__tests__/skin-errors-kebab-case.cases.unit.test.d.ts +2 -0
  152. package/dist/__tests__/skin-errors-kebab-case.cases.unit.test.d.ts.map +1 -0
  153. package/dist/__tests__/skin-instances-coexist.cases.unit.test.d.ts +2 -0
  154. package/dist/__tests__/skin-instances-coexist.cases.unit.test.d.ts.map +1 -0
  155. package/dist/__tests__/skin-m2-extract-happy.cases.unit.test.d.ts +2 -0
  156. package/dist/__tests__/skin-m2-extract-happy.cases.unit.test.d.ts.map +1 -0
  157. package/dist/__tests__/skin-m2-extract-joint-error.cases.unit.test.d.ts +2 -0
  158. package/dist/__tests__/skin-m2-extract-joint-error.cases.unit.test.d.ts.map +1 -0
  159. package/dist/__tests__/skin-m2-extract-null-assets.cases.unit.test.d.ts +2 -0
  160. package/dist/__tests__/skin-m2-extract-null-assets.cases.unit.test.d.ts.map +1 -0
  161. package/dist/__tests__/skin-m2-extract-skeleton-error.cases.unit.test.d.ts +2 -0
  162. package/dist/__tests__/skin-m2-extract-skeleton-error.cases.unit.test.d.ts.map +1 -0
  163. package/dist/__tests__/skin-m3-record-cache.cases.unit.test.d.ts +2 -0
  164. package/dist/__tests__/skin-m3-record-cache.cases.unit.test.d.ts.map +1 -0
  165. package/dist/__tests__/skin-palette-extract.cases.unit.test.d.ts +2 -0
  166. package/dist/__tests__/skin-palette-extract.cases.unit.test.d.ts.map +1 -0
  167. package/dist/__tests__/skin-pipeline-routing.cases.unit.test.d.ts +2 -0
  168. package/dist/__tests__/skin-pipeline-routing.cases.unit.test.d.ts.map +1 -0
  169. package/dist/__tests__/skin.cases.unit.test.d.ts +2 -0
  170. package/dist/__tests__/skin.cases.unit.test.d.ts.map +1 -0
  171. package/dist/__tests__/skybox-extract.cases.unit.test.d.ts +2 -0
  172. package/dist/__tests__/skybox-extract.cases.unit.test.d.ts.map +1 -0
  173. package/dist/__tests__/skybox-shader-compile.cases.unit.test.d.ts +2 -0
  174. package/dist/__tests__/skybox-shader-compile.cases.unit.test.d.ts.map +1 -0
  175. package/dist/__tests__/skylight-bind-group.cases.unit.test.d.ts +2 -0
  176. package/dist/__tests__/skylight-bind-group.cases.unit.test.d.ts.map +1 -0
  177. package/dist/__tests__/skylight-component.cases.unit.test.d.ts +2 -0
  178. package/dist/__tests__/skylight-component.cases.unit.test.d.ts.map +1 -0
  179. package/dist/__tests__/skylight-fallback-path.cases.unit.test.d.ts +2 -0
  180. package/dist/__tests__/skylight-fallback-path.cases.unit.test.d.ts.map +1 -0
  181. package/dist/__tests__/skylight-pipeline-layout.cases.unit.test.d.ts +2 -0
  182. package/dist/__tests__/skylight-pipeline-layout.cases.unit.test.d.ts.map +1 -0
  183. package/dist/__tests__/skylight-solid-color-extract.cases.unit.test.d.ts +2 -0
  184. package/dist/__tests__/skylight-solid-color-extract.cases.unit.test.d.ts.map +1 -0
  185. package/dist/__tests__/sprite-animation-tick-boundary.cases.unit.test.d.ts +2 -0
  186. package/dist/__tests__/sprite-animation-tick-boundary.cases.unit.test.d.ts.map +1 -0
  187. package/dist/__tests__/sprite-animation-tick-clamp.cases.unit.test.d.ts +2 -0
  188. package/dist/__tests__/sprite-animation-tick-clamp.cases.unit.test.d.ts.map +1 -0
  189. package/dist/__tests__/sprite-animation-tick-frame-duration-negative.cases.unit.test.d.ts +2 -0
  190. package/dist/__tests__/sprite-animation-tick-frame-duration-negative.cases.unit.test.d.ts.map +1 -0
  191. package/dist/__tests__/sprite-animation-tick-frame-duration-zero.cases.unit.test.d.ts +2 -0
  192. package/dist/__tests__/sprite-animation-tick-frame-duration-zero.cases.unit.test.d.ts.map +1 -0
  193. package/dist/__tests__/sprite-animation-tick-loop.cases.unit.test.d.ts +2 -0
  194. package/dist/__tests__/sprite-animation-tick-loop.cases.unit.test.d.ts.map +1 -0
  195. package/dist/__tests__/sprite-animation-tick-override-probe.cases.unit.test.d.ts +2 -0
  196. package/dist/__tests__/sprite-animation-tick-override-probe.cases.unit.test.d.ts.map +1 -0
  197. package/dist/__tests__/sprite-animation-tick-regions-mismatch.cases.unit.test.d.ts +2 -0
  198. package/dist/__tests__/sprite-animation-tick-regions-mismatch.cases.unit.test.d.ts.map +1 -0
  199. package/dist/__tests__/storage-buffer-caps.cases.unit.test.d.ts +2 -0
  200. package/dist/__tests__/storage-buffer-caps.cases.unit.test.d.ts.map +1 -0
  201. package/dist/__tests__/systems.cases.unit.test.d.ts +2 -0
  202. package/dist/__tests__/systems.cases.unit.test.d.ts.map +1 -0
  203. package/dist/__tests__/tonemap-hdr-target.cases.unit.test.d.ts +2 -0
  204. package/dist/__tests__/tonemap-hdr-target.cases.unit.test.d.ts.map +1 -0
  205. package/dist/__tests__/tonemap-pipeline-split.cases.unit.test.d.ts +2 -0
  206. package/dist/__tests__/tonemap-pipeline-split.cases.unit.test.d.ts.map +1 -0
  207. package/dist/__tests__/tonemap.cases.unit.test.d.ts +2 -0
  208. package/dist/__tests__/tonemap.cases.unit.test.d.ts.map +1 -0
  209. package/dist/__tests__/transparent-sort-config-get.cases.unit.test.d.ts +2 -0
  210. package/dist/__tests__/transparent-sort-config-get.cases.unit.test.d.ts.map +1 -0
  211. package/dist/__tests__/transparent-sort-config-set.cases.unit.test.d.ts +2 -0
  212. package/dist/__tests__/transparent-sort-config-set.cases.unit.test.d.ts.map +1 -0
  213. package/dist/__tests__/transparent-sort.cases.unit.test.d.ts +2 -0
  214. package/dist/__tests__/transparent-sort.cases.unit.test.d.ts.map +1 -0
  215. package/dist/__tests__/upload-texture-consistency.cases.unit.test.d.ts +2 -0
  216. package/dist/__tests__/upload-texture-consistency.cases.unit.test.d.ts.map +1 -0
  217. package/dist/__tests__/verify-revisions.cases.unit.test.d.ts +2 -0
  218. package/dist/__tests__/verify-revisions.cases.unit.test.d.ts.map +1 -0
  219. package/dist/__tests__/wire-default-loaders.cases.unit.test.d.ts +2 -0
  220. package/dist/__tests__/wire-default-loaders.cases.unit.test.d.ts.map +1 -0
  221. package/dist/__tests__/zero-camera-clear-fallback.cases.unit.test.d.ts +2 -0
  222. package/dist/__tests__/zero-camera-clear-fallback.cases.unit.test.d.ts.map +1 -0
  223. package/dist/dev-import-transport.d.ts.map +1 -1
  224. package/dist/index.mjs +1 -1
  225. package/dist/index.mjs.map +1 -1
  226. package/package.json +30 -30
  227. package/src/__tests__/advance-animation-player.cases.unit.test.ts +1666 -0
  228. package/src/__tests__/asset-registry-aabb.cases.unit.test.ts +676 -0
  229. package/src/__tests__/asset-registry-bootstrap.cases.unit.test.ts +472 -0
  230. package/src/__tests__/asset-registry-builtin-nineslice.cases.unit.test.ts +481 -0
  231. package/src/__tests__/asset-registry-d9-tile-sampler-soft-warn.cases.unit.test.ts +568 -0
  232. package/src/__tests__/asset-registry-guid.cases.unit.test.ts +500 -0
  233. package/src/__tests__/asset-registry-material-validate.cases.unit.test.ts +756 -0
  234. package/src/__tests__/asset-registry-mesh-fail-fast.cases.unit.test.ts +591 -0
  235. package/src/__tests__/asset-registry-scene.cases.unit.test.ts +501 -0
  236. package/src/__tests__/asset-registry-sprite-slices-validate.cases.unit.test.ts +536 -0
  237. package/src/__tests__/asset-renderer-assembly.cases.unit.test.ts +496 -0
  238. package/src/__tests__/asset.cases.unit.test.ts +439 -0
  239. package/src/__tests__/bind-group-cache-keying.test.ts +6 -2
  240. package/src/__tests__/bloom-gating.cases.unit.test.ts +428 -0
  241. package/src/__tests__/builtin-guid-ssot.cases.unit.test.ts +472 -0
  242. package/src/__tests__/builtin-pack.cases.unit.test.ts +639 -0
  243. package/src/__tests__/builtin-shader-register-e2e.test.ts +1 -1
  244. package/src/__tests__/camera-antialias.cases.unit.test.ts +372 -0
  245. package/src/__tests__/camera-bloom.cases.unit.test.ts +396 -0
  246. package/src/__tests__/camera-clear-schema.cases.unit.test.ts +391 -0
  247. package/src/__tests__/camera-ortho.cases.unit.test.ts +484 -0
  248. package/src/__tests__/cluster-binner.cases.unit.test.ts +817 -0
  249. package/src/__tests__/collect-scene-mount-collapse.test.ts +5 -1
  250. package/src/__tests__/create-renderer-fallback-shader-manifest.cases.unit.test.ts +345 -0
  251. package/src/__tests__/create-renderer-uniform-fallback.cases.unit.test.ts +445 -0
  252. package/src/__tests__/cubemap-upload.cases.unit.test.ts +593 -0
  253. package/src/__tests__/dawn/ibl-precompute-readback.dawn.test.ts +184 -17
  254. package/src/__tests__/dawn/material-alpha.dawn.test.ts +17 -4
  255. package/src/__tests__/derive-bgl-integration.test.ts +8 -8
  256. package/src/__tests__/dev-import-transport.cases.unit.test.ts +503 -0
  257. package/src/__tests__/engine-metrics.cases.unit.test.ts +371 -0
  258. package/src/__tests__/equirect-projection-error.cases.unit.test.ts +416 -0
  259. package/src/__tests__/font-asset-load.cases.unit.test.ts +510 -0
  260. package/src/__tests__/fxaa-intermediate-texture.cases.unit.test.ts +690 -0
  261. package/src/__tests__/fxaa-pipeline.cases.unit.test.ts +546 -0
  262. package/src/__tests__/gpu-residency.cases.unit.test.ts +479 -0
  263. package/src/__tests__/gpu-resource-release.cases.unit.test.ts +929 -0
  264. package/src/__tests__/handle-quad.cases.unit.test.ts +491 -0
  265. package/src/__tests__/hdrp-bgl-slots.cases.unit.test.ts +451 -0
  266. package/src/__tests__/hdrp-grid-invalid.cases.unit.test.ts +408 -0
  267. package/src/__tests__/hdrp-index-list-overflow-once.cases.unit.test.ts +405 -0
  268. package/src/__tests__/hdrp-light-budget.cases.unit.test.ts +483 -0
  269. package/src/__tests__/hdrp-pipeline-asset-config.cases.unit.test.ts +441 -0
  270. package/src/__tests__/helpers/renderer-device-loss-dawn.ts +69 -0
  271. package/src/__tests__/helpers/standard-material-manifest.ts +11 -15
  272. package/src/__tests__/ibl-pipeline-cache.cases.unit.test.ts +415 -0
  273. package/src/__tests__/lazy-catalog.cases.unit.test.ts +848 -0
  274. package/src/__tests__/light-gpu-byte-neutral.unit.test.ts +6 -5
  275. package/src/__tests__/load-by-guid-hdr.cases.unit.test.ts +582 -0
  276. package/src/__tests__/load-by-guid-prod-material-parent.cases.unit.test.ts +1514 -0
  277. package/src/__tests__/load-by-guid-prod.cases.unit.test.ts +557 -0
  278. package/src/__tests__/loader-registry.cases.unit.test.ts +767 -0
  279. package/src/__tests__/m7-hdrp-demo-shape.cases.unit.test.ts +361 -0
  280. package/src/__tests__/material-texture-uv-scale.unit.test.ts +2 -2
  281. package/src/__tests__/materials.unit.test.ts +29 -10
  282. package/src/__tests__/mipmap-formula.cases.unit.test.ts +434 -0
  283. package/src/__tests__/mipmap-pipeline-cache.cases.unit.test.ts +490 -0
  284. package/src/__tests__/parse-asset-payload-material.cases.unit.test.ts +565 -0
  285. package/src/__tests__/parse-asset-payload-texture.cases.unit.test.ts +720 -0
  286. package/src/__tests__/parse-scene-payload-refs.cases.unit.test.ts +767 -0
  287. package/src/__tests__/pass-selector.cases.unit.test.ts +376 -0
  288. package/src/__tests__/pbr-pipeline.unit.test.ts +23 -5
  289. package/src/__tests__/pipeline-builder.cases.unit.test.ts +624 -0
  290. package/src/__tests__/pipeline-cache-key-topology.cases.unit.test.ts +807 -0
  291. package/src/__tests__/pipeline-vertex-stride-branch.cases.unit.test.ts +379 -0
  292. package/src/__tests__/pipeline.cases.unit.test.ts +370 -0
  293. package/src/__tests__/post-process-register.cases.unit.test.ts +405 -0
  294. package/src/__tests__/propagate-transforms.cases.unit.test.ts +502 -0
  295. package/src/__tests__/propagate-transforms.dawn.test.ts +19 -2
  296. package/src/__tests__/record-all-topology.cases.unit.test.ts +608 -0
  297. package/src/__tests__/record-draw-branch.cases.unit.test.ts +621 -0
  298. package/src/__tests__/record-strip-index-format.cases.unit.test.ts +419 -0
  299. package/src/__tests__/register-with-guid-rgba16float.cases.unit.test.ts +469 -0
  300. package/src/__tests__/render-data.cases.unit.test.ts +553 -0
  301. package/src/__tests__/render-error-exhaustive.test-d.ts +1 -0
  302. package/src/__tests__/render-query-regression.cases.unit.test.ts +531 -0
  303. package/src/__tests__/render-system-record-submesh.cases.unit.test.ts +740 -0
  304. package/src/__tests__/render-system-record-warn-once.cases.unit.test.ts +418 -0
  305. package/src/__tests__/render-system-record.test.ts +15 -33
  306. package/src/__tests__/renderer-device-loss-multi-world.integration.test.ts +103 -0
  307. package/src/__tests__/renderer-device-loss-provider-feasibility.dawn.test.ts +124 -0
  308. package/src/__tests__/renderer-device-loss-recovery.dawn.test.ts +50 -0
  309. package/src/__tests__/renderer-draw-world.cases.unit.test.ts +514 -0
  310. package/src/__tests__/renderer-recovery-consumer.integration.test.ts +96 -0
  311. package/src/__tests__/renderstate-pipeline-cache.cases.unit.test.ts +631 -0
  312. package/src/__tests__/resolve-scene-guids.cases.unit.test.ts +1123 -0
  313. package/src/__tests__/shadow-caster-empty-schema.test.ts +1 -1
  314. package/src/__tests__/shadow-fields-observable.dawn.test.ts +2 -2
  315. package/src/__tests__/shadow-m1.dawn.test.ts +1 -1
  316. package/src/__tests__/shadow-skip-non-triangle.cases.unit.test.ts +681 -0
  317. package/src/__tests__/skin-errors-kebab-case.cases.unit.test.ts +475 -0
  318. package/src/__tests__/skin-extract-getarrayview-count.unit.test.ts +5 -4
  319. package/src/__tests__/skin-instances-coexist.cases.unit.test.ts +375 -0
  320. package/src/__tests__/skin-m2-extract-happy.cases.unit.test.ts +592 -0
  321. package/src/__tests__/skin-m2-extract-joint-error.cases.unit.test.ts +619 -0
  322. package/src/__tests__/skin-m2-extract-null-assets.cases.unit.test.ts +569 -0
  323. package/src/__tests__/skin-m2-extract-skeleton-error.cases.unit.test.ts +585 -0
  324. package/src/__tests__/skin-m3-record-cache.cases.unit.test.ts +457 -0
  325. package/src/__tests__/skin-palette-extract.cases.unit.test.ts +635 -0
  326. package/src/__tests__/skin-pipeline-routing.cases.unit.test.ts +411 -0
  327. package/src/__tests__/skin.cases.unit.test.ts +421 -0
  328. package/src/__tests__/skybox-extract.cases.unit.test.ts +511 -0
  329. package/src/__tests__/skybox-shader-compile.cases.unit.test.ts +437 -0
  330. package/src/__tests__/skylight-bind-group.cases.unit.test.ts +642 -0
  331. package/src/__tests__/skylight-component.cases.unit.test.ts +386 -0
  332. package/src/__tests__/skylight-fallback-path.cases.unit.test.ts +566 -0
  333. package/src/__tests__/skylight-lazy-projection.test.ts +35 -20
  334. package/src/__tests__/skylight-pipeline-layout.cases.unit.test.ts +506 -0
  335. package/src/__tests__/skylight-solid-color-extract.cases.unit.test.ts +399 -0
  336. package/src/__tests__/sprite-animation-tick-boundary.cases.unit.test.ts +521 -0
  337. package/src/__tests__/sprite-animation-tick-clamp.cases.unit.test.ts +453 -0
  338. package/src/__tests__/sprite-animation-tick-frame-duration-negative.cases.unit.test.ts +447 -0
  339. package/src/__tests__/sprite-animation-tick-frame-duration-zero.cases.unit.test.ts +395 -0
  340. package/src/__tests__/sprite-animation-tick-loop.cases.unit.test.ts +494 -0
  341. package/src/__tests__/sprite-animation-tick-override-probe.cases.unit.test.ts +439 -0
  342. package/src/__tests__/sprite-animation-tick-regions-mismatch.cases.unit.test.ts +466 -0
  343. package/src/__tests__/sprite-lit-bgl-byte-identical.test.ts +5 -5
  344. package/src/__tests__/sprite-lit-pipeline-cache-key.test.ts +1 -1
  345. package/src/__tests__/ssao-pipelines.test.ts +1 -1
  346. package/src/__tests__/storage-buffer-caps.cases.unit.test.ts +373 -0
  347. package/src/__tests__/systems.cases.unit.test.ts +425 -0
  348. package/src/__tests__/tilemap-chunk-extract.overhang-bounds.test.ts +1 -1
  349. package/src/__tests__/tonemap-hdr-target.cases.unit.test.ts +670 -0
  350. package/src/__tests__/tonemap-pipeline-split.cases.unit.test.ts +867 -0
  351. package/src/__tests__/tonemap.cases.unit.test.ts +446 -0
  352. package/src/__tests__/transparent-sort-config-get.cases.unit.test.ts +395 -0
  353. package/src/__tests__/transparent-sort-config-set.cases.unit.test.ts +424 -0
  354. package/src/__tests__/transparent-sort.cases.unit.test.ts +684 -0
  355. package/src/__tests__/upload-texture-consistency.cases.unit.test.ts +478 -0
  356. package/src/__tests__/verify-revisions.cases.unit.test.ts +619 -0
  357. package/src/__tests__/wire-default-loaders.cases.unit.test.ts +461 -0
  358. package/src/__tests__/zero-camera-clear-fallback.cases.unit.test.ts +374 -0
  359. package/src/dev-import-transport.ts +2 -1
  360. package/dist/__tests__/asset.unit.test.d.ts +0 -2
  361. package/dist/__tests__/asset.unit.test.d.ts.map +0 -1
  362. package/dist/__tests__/pipeline.unit.test.d.ts +0 -2
  363. package/dist/__tests__/pipeline.unit.test.d.ts.map +0 -1
  364. package/dist/__tests__/systems.unit.test.d.ts +0 -2
  365. package/dist/__tests__/systems.unit.test.d.ts.map +0 -1
  366. package/src/__tests__/asset.unit.test.ts +0 -7113
  367. package/src/__tests__/pipeline.unit.test.ts +0 -5279
  368. package/src/__tests__/systems.unit.test.ts +0 -9061
@@ -0,0 +1,124 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ // These are the WebGPU COPY_SRC/COPY_DST bits; Dawn runs without a DOM constant global.
4
+ const COPY_SRC = 0x0004;
5
+ const COPY_DST = 0x0008;
6
+
7
+ type LossObservation = {
8
+ readonly status: 'lost' | 'insufficient-evidence';
9
+ readonly reason?: string;
10
+ readonly message?: string;
11
+ };
12
+
13
+ type FeasibilityEvidence = {
14
+ readonly status: 'available' | 'insufficient-evidence';
15
+ readonly owner: string;
16
+ readonly command: string;
17
+ readonly exitStatus: number;
18
+ readonly submittedWork: boolean;
19
+ readonly rawDeviceObservation: LossObservation;
20
+ readonly missingCapability?: string;
21
+ readonly providerSurface: readonly string[];
22
+ };
23
+
24
+ const observationDeadlineMs = 250;
25
+
26
+ function callableProviderSurface(value: object): string[] {
27
+ return Object.getOwnPropertyNames(value)
28
+ .filter((name) => /loss|crash|reset|recover/i.test(name))
29
+ .filter((name) => typeof (value as Record<string, unknown>)[name] === 'function')
30
+ .sort();
31
+ }
32
+
33
+ async function submitObservableWork(device: GPUDevice): Promise<void> {
34
+ const source = device.createBuffer({
35
+ size: 16,
36
+ usage: COPY_SRC | COPY_DST,
37
+ });
38
+ const destination = device.createBuffer({
39
+ size: 16,
40
+ usage: COPY_SRC | COPY_DST,
41
+ });
42
+ device.queue.writeBuffer(source, 0, new Uint32Array([0xdecafbad, 1, 2, 3]));
43
+ const encoder = device.createCommandEncoder();
44
+ encoder.copyBufferToBuffer(source, 0, destination, 0, 16);
45
+ device.queue.submit([encoder.finish()]);
46
+ await device.queue.onSubmittedWorkDone();
47
+ }
48
+
49
+ async function observeRawLoss(device: GPUDevice): Promise<LossObservation> {
50
+ let timer: ReturnType<typeof setTimeout> | undefined;
51
+ const deadline = new Promise<LossObservation>((resolve) => {
52
+ timer = setTimeout(
53
+ () =>
54
+ resolve({
55
+ status: 'insufficient-evidence',
56
+ message: `raw GPUDevice.lost remained pending for ${observationDeadlineMs}ms`,
57
+ }),
58
+ observationDeadlineMs,
59
+ );
60
+ });
61
+ const loss = device.lost.then((value) => ({
62
+ status: 'lost' as const,
63
+ reason: value.reason,
64
+ message: value.message,
65
+ }));
66
+ const observation = await Promise.race([loss, deadline]);
67
+ if (timer !== undefined) clearTimeout(timer);
68
+ return observation;
69
+ }
70
+
71
+ describe('real Dawn device-loss provider feasibility', () => {
72
+ it('submits real work and reports an auditable provider boundary', async () => {
73
+ const command =
74
+ 'pnpm exec vitest run --project dawn packages/runtime/src/__tests__/renderer-device-loss-provider-feasibility.dawn.test.ts';
75
+ const gpu = globalThis.navigator?.gpu;
76
+ expect(typeof gpu?.requestAdapter).toBe('function');
77
+ if (typeof gpu?.requestAdapter !== 'function') return;
78
+
79
+ const adapter = await gpu.requestAdapter();
80
+ expect(adapter).not.toBeNull();
81
+ if (adapter === null) return;
82
+
83
+ const device = await adapter.requestDevice();
84
+ let submittedWork = false;
85
+ await submitObservableWork(device);
86
+ submittedWork = true;
87
+ const rawDeviceObservation = await observeRawLoss(device);
88
+ const providerSurface = [
89
+ ...callableProviderSurface(gpu),
90
+ ...callableProviderSurface(adapter),
91
+ ...callableProviderSurface(device),
92
+ ];
93
+ const evidence: FeasibilityEvidence =
94
+ rawDeviceObservation.status === 'lost' && rawDeviceObservation.reason !== 'destroyed'
95
+ ? {
96
+ status: 'available',
97
+ owner: 'raw Dawn GPUDevice provider before packages/rhi-webgpu/src/device.ts',
98
+ command,
99
+ exitStatus: 0,
100
+ submittedWork,
101
+ rawDeviceObservation,
102
+ providerSurface,
103
+ }
104
+ : {
105
+ status: 'insufficient-evidence',
106
+ owner: 'raw Dawn GPUDevice provider before packages/rhi-webgpu/src/device.ts',
107
+ command,
108
+ exitStatus: 0,
109
+ submittedWork,
110
+ rawDeviceObservation,
111
+ missingCapability:
112
+ 'No test-visible non-destroyed loss injection method is exposed by the real Dawn GPU, adapter, or device objects',
113
+ providerSurface,
114
+ };
115
+ console.log(`[dawn-loss-feasibility] ${JSON.stringify(evidence)}`);
116
+ expect(evidence.submittedWork).toBe(true);
117
+ expect(['available', 'insufficient-evidence']).toContain(evidence.status);
118
+ if (evidence.status === 'available') {
119
+ expect(evidence.rawDeviceObservation.reason).not.toBe('destroyed');
120
+ } else {
121
+ expect(evidence.missingCapability).toBeTruthy();
122
+ }
123
+ });
124
+ });
@@ -0,0 +1,50 @@
1
+ import { World } from '@forgeax/engine-ecs';
2
+ import { describe, expect, it } from 'vitest';
3
+ import {
4
+ insufficientDawnRecoveryEvidence,
5
+ observeRealLoss,
6
+ submitRealFrame,
7
+ testOnlyLossProvider,
8
+ } from './helpers/renderer-device-loss-dawn';
9
+
10
+ type RecoveryEvidence = ReturnType<typeof insufficientDawnRecoveryEvidence>;
11
+
12
+ describe('real Dawn renderer device-loss recovery', () => {
13
+ it('keeps the dual-world recovery contract honest when provider evidence is absent', async () => {
14
+ const gpu = globalThis.navigator?.gpu;
15
+ expect(typeof gpu?.requestAdapter).toBe('function');
16
+ if (typeof gpu?.requestAdapter !== 'function') return;
17
+ const adapter = await gpu.requestAdapter();
18
+ expect(adapter).not.toBeNull();
19
+ if (adapter === null) return;
20
+ const device = await adapter.requestDevice();
21
+ const firstWorld = new World();
22
+ const secondWorld = new World();
23
+ await submitRealFrame(device);
24
+ const provider = testOnlyLossProvider();
25
+ const rawLoss =
26
+ provider === undefined
27
+ ? undefined
28
+ : await (async () => {
29
+ await provider.injectNonDestroyedLoss?.(device);
30
+ return observeRealLoss(device);
31
+ })();
32
+ let evidence: RecoveryEvidence = insufficientDawnRecoveryEvidence([
33
+ firstWorld.identity,
34
+ secondWorld.identity,
35
+ ]);
36
+ if (provider !== undefined && rawLoss?.reason === 'unknown') {
37
+ evidence = insufficientDawnRecoveryEvidence(
38
+ [firstWorld.identity, secondWorld.identity],
39
+ 'A non-destroyed raw loss was observed, but this fixture does not exercise public Renderer recovery',
40
+ );
41
+ }
42
+ console.log(
43
+ `[dawn-loss-recovery] ${JSON.stringify({ ...evidence, rawLoss: rawLoss ?? 'provider-missing' })}`,
44
+ );
45
+ expect(evidence.submittedWork).toBe(true);
46
+ expect(evidence.worlds).toHaveLength(2);
47
+ expect(evidence.status).toBe('insufficient-evidence');
48
+ expect(evidence.missingCapability).toBeTruthy();
49
+ });
50
+ });
@@ -0,0 +1,514 @@
1
+ // @ts-nocheck — merged file: cross-source node:fs/node:path imports outside @types/node coverage in runtime tsconfig
2
+ // Consolidated by feat-20260609-test-pool-startup-reduction-merge-tiny-test-files
3
+ // biome-ignore-all lint/complexity/noUselessLoneBlockStatements: block-scope isolation between merged source files (consolidation paradigm)
4
+ //
5
+ // Source files (N=33):
6
+ // - packages/runtime/__tests__/create-renderer-fallback.test.ts
7
+ // - packages/runtime/src/__tests__/cluster-binner.test.ts
8
+ // - packages/runtime/src/__tests__/create-renderer-fallback-shader-manifest.test.ts
9
+ // - packages/runtime/src/__tests__/create-renderer-uniform-fallback.test.ts
10
+ // - packages/runtime/src/__tests__/createRenderer.test.ts
11
+ // - packages/runtime/src/__tests__/dispatch-sort.test.ts
12
+ // - packages/runtime/src/__tests__/engine-metrics.test.ts
13
+ // - packages/runtime/src/__tests__/device/gpu-residency-caps-guard.test.ts
14
+ // - packages/runtime/src/__tests__/pass-selector.test.ts
15
+ // - packages/runtime/src/__tests__/pipeline-builder.test.ts
16
+ // - packages/runtime/src/__tests__/pipeline-cache-key-topology.test.ts
17
+ // - packages/runtime/src/__tests__/pipeline-rename-grep-gate.test.ts
18
+ // - packages/runtime/src/__tests__/pipeline-vertex-stride-branch.test.ts
19
+ // - packages/runtime/src/__tests__/post-process-register.test.ts
20
+ // - packages/runtime/src/__tests__/record-all-topology.test.ts
21
+ // - packages/runtime/src/__tests__/record-draw-branch.test.ts
22
+ // - packages/runtime/src/__tests__/record-strip-index-format.test.ts
23
+ // - packages/runtime/src/__tests__/render-query-regression.test.ts
24
+ // - packages/runtime/src/__tests__/renderer-draw-world.test.ts
25
+ // - packages/runtime/src/__tests__/renderer-input-snapshot.test.ts
26
+ // - packages/runtime/src/__tests__/renderer-read-pixels.test.ts
27
+ // - packages/runtime/src/__tests__/renderer-ready.test.ts
28
+ // - packages/runtime/src/__tests__/renderstate-pipeline-cache.test.ts
29
+ // - packages/runtime/src/__tests__/storage-buffer-caps.test.ts
30
+ // - packages/runtime/src/__tests__/device/gpu-residency.test.ts
31
+ // - packages/runtime/src/__tests__/render-data.test.ts
32
+ // - packages/runtime/src/__tests__/hdrp-bgl-slots.test.ts
33
+ // - packages/runtime/src/__tests__/hdrp-caps-gate.test.ts
34
+ // - packages/runtime/src/__tests__/hdrp-grid-invalid.test.ts
35
+ // - packages/runtime/src/__tests__/hdrp-index-list-overflow-once.test.ts
36
+ // - packages/runtime/src/__tests__/hdrp-light-budget.test.ts
37
+ // - packages/runtime/src/__tests__/hdrp-pipeline-asset-config.test.ts
38
+ // - packages/runtime/src/__tests__/m7-hdrp-demo-shape.test.ts
39
+ //
40
+ // Paradigm: each block-scope wraps a source file. ancestorTitles[0] is the
41
+ // source-preserved inner describe (NOT the source filename for these 3 files
42
+ // — recovery path: vitest report ancestorTitles -> grep this file -> upstream
43
+ // `// ─── from <name>.test.ts ───` block separator -> source filename).
44
+ // Top-level imports merged + deduped.
45
+
46
+ import { existsSync, readFileSync } from 'node:fs';
47
+ import { dirname, resolve } from 'node:path';
48
+ import { fileURLToPath } from 'node:url';
49
+ import { HANDLE_CUBE, HANDLE_TRIANGLE, resolveAssetHandle } from '@forgeax/engine-assets-runtime';
50
+ import type { World as WorldType } from '@forgeax/engine-ecs';
51
+ import { defineComponent, World } from '@forgeax/engine-ecs';
52
+ import {
53
+ buildMeshAttributeMapForUvSets,
54
+ createBoxGeometry,
55
+ createConeGeometry,
56
+ createCylinderGeometry,
57
+ createPlaneGeometry,
58
+ createSphereGeometry,
59
+ createTorusGeometry,
60
+ PROCEDURAL_FLOATS_PER_VERTEX,
61
+ } from '@forgeax/engine-geometry';
62
+ import { type Mat4, mat4, type Vec3, vec3 } from '@forgeax/engine-math';
63
+ import type { Renderer as RendererType } from '@forgeax/engine-render';
64
+ import { Camera, MeshFilter, MeshRenderer } from '@forgeax/engine-render';
65
+ import {
66
+ err,
67
+ ok,
68
+ type PipelineLayout,
69
+ type RenderPipeline,
70
+ type Result,
71
+ type RhiCaps,
72
+ type RhiDevice,
73
+ RhiError,
74
+ ok as rhiOk,
75
+ type ShaderModule,
76
+ } from '@forgeax/engine-rhi';
77
+ import {
78
+ acquireCanvasContext as acquireNullCanvasContext,
79
+ createShaderModule as createNullShaderModule,
80
+ RhiNullAdapter,
81
+ } from '@forgeax/engine-rhi-null';
82
+ import { ChildOf, Transform } from '@forgeax/engine-scene';
83
+ import {
84
+ findVariantByKey,
85
+ type MaterialShaderEntry,
86
+ type MaterialShaderManifestEntry,
87
+ type MaterialShaderManifestVariant,
88
+ } from '@forgeax/engine-shader';
89
+ import {
90
+ type AssetError,
91
+ type EquirectAsset,
92
+ type Handle,
93
+ type MaterialRenderState,
94
+ type MeshAsset,
95
+ type PassSelector,
96
+ type PrimitiveTopology,
97
+ type RenderPipelineAsset,
98
+ type TextureAsset,
99
+ toShared,
100
+ } from '@forgeax/engine-types';
101
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
102
+ import {
103
+ bin,
104
+ type ClusterBinError,
105
+ calculateSphereClusterBounds,
106
+ clusterSpaceObjectAabb,
107
+ deriveCullingRadius,
108
+ ndcPositionToCluster,
109
+ viewZToZSlice,
110
+ } from '../../../render/src/cluster-binner';
111
+ import { GpuResidencyCache } from '../../../render/src/device/gpu-residency';
112
+ import { createEngineMetrics } from '../../../render/src/engine-metrics';
113
+ import { assertStorageBufferCap } from '../../../render/src/light-buffer-layout';
114
+ import {
115
+ buildPbrPipelineLayouts,
116
+ buildPbrViewBglEntries,
117
+ type PbrCaps,
118
+ } from '../../../render/src/pbr-pipeline';
119
+ import {
120
+ HdrpInstallError,
121
+ validateClusterGrid,
122
+ } from '../../../render/src/pipeline/standard-pipeline';
123
+ import {
124
+ buildPipelineForMaterialShader,
125
+ type PipelineBuilderContext,
126
+ type PipelineBuilderShaderModuleFactory,
127
+ } from '../../../render/src/pipeline-builder';
128
+ import {
129
+ cacheKeyOf,
130
+ createHdrpBindGroupLayoutDescriptor,
131
+ type PipelineSpec,
132
+ } from '../../../render/src/pipeline-spec';
133
+ import {
134
+ deriveRenderDataCubemap,
135
+ deriveRenderDataMesh,
136
+ deriveRenderDataTexture,
137
+ } from '../../../render/src/render-data';
138
+ import { extractFrame, prepareExtractContext } from '../../../render/src/render-system-extract';
139
+ import { matchPass } from '../../../render/src/systems/pass-selector';
140
+ import { makeMockShaderRegistry } from './helpers/mock-shader-registry';
141
+ import { standardMaterialShaderVariants } from './helpers/standard-material-manifest';
142
+
143
+ function makeExplicitNullRhi(spies: {
144
+ setIndexBuffer: ReturnType<typeof vi.fn>;
145
+ setVertexBuffer: ReturnType<typeof vi.fn>;
146
+ draw: ReturnType<typeof vi.fn>;
147
+ drawIndexed: ReturnType<typeof vi.fn>;
148
+ }): unknown {
149
+ const adapter = new RhiNullAdapter();
150
+ const requestDevice = adapter.requestDevice.bind(adapter);
151
+ adapter.requestDevice = async () => {
152
+ const result = await requestDevice();
153
+ if (result.ok) {
154
+ const device = result.value;
155
+ const createCommandEncoder = device.createCommandEncoder.bind(device);
156
+ device.createCommandEncoder = (desc) => {
157
+ const encoderResult = createCommandEncoder(desc);
158
+ if (!encoderResult.ok) return encoderResult;
159
+ const encoder = encoderResult.value;
160
+ const beginRenderPass = encoder.beginRenderPass.bind(encoder);
161
+ encoder.beginRenderPass = (passDesc) => {
162
+ const pass = beginRenderPass(passDesc);
163
+ const draw = pass.draw.bind(pass);
164
+ const drawIndexed = pass.drawIndexed.bind(pass);
165
+ const setIndexBuffer = pass.setIndexBuffer.bind(pass);
166
+ const setVertexBuffer = pass.setVertexBuffer.bind(pass);
167
+ pass.draw = (...args) => {
168
+ spies.draw(...args);
169
+ draw(...args);
170
+ };
171
+ pass.drawIndexed = (...args) => {
172
+ spies.drawIndexed(...args);
173
+ drawIndexed(...args);
174
+ };
175
+ pass.setIndexBuffer = (...args) => {
176
+ spies.setIndexBuffer(...args);
177
+ setIndexBuffer(...args);
178
+ };
179
+ pass.setVertexBuffer = (...args) => {
180
+ spies.setVertexBuffer(...args);
181
+ setVertexBuffer(...args);
182
+ };
183
+ return pass;
184
+ };
185
+ return { ok: true, value: encoder };
186
+ };
187
+ }
188
+ return result;
189
+ };
190
+ return {
191
+ requestAdapter: async () => ({ ok: true, value: adapter }),
192
+ acquireCanvasContext: acquireNullCanvasContext,
193
+ createShaderModule: (device: unknown, desc: { code: string; label?: string }) =>
194
+ createNullShaderModule(device as never, desc),
195
+ };
196
+ }
197
+
198
+ vi.mock('@forgeax/engine-rhi-wgpu', () => {
199
+ return {
200
+ rhi: {
201
+ requestAdapter: async () => ({
202
+ ok: false,
203
+ error: {
204
+ code: 'adapter-unavailable',
205
+ expected: 'adapter available',
206
+ hint: 'default mock fail',
207
+ },
208
+ }),
209
+ getPreferredCanvasFormat: () => 'bgra8unorm',
210
+ acquireCanvasContext: () => ({
211
+ ok: false,
212
+ error: {
213
+ code: 'webgpu-runtime-error',
214
+ expected: 'context available',
215
+ hint: 'default mock fail',
216
+ },
217
+ }),
218
+ },
219
+ ensureReady: async () => undefined,
220
+ };
221
+ });
222
+
223
+ void [
224
+ Camera,
225
+ ChildOf,
226
+ GpuResidencyCache,
227
+ HANDLE_CUBE,
228
+ HANDLE_TRIANGLE,
229
+ HdrpInstallError,
230
+ MeshFilter,
231
+ MeshRenderer,
232
+ PROCEDURAL_FLOATS_PER_VERTEX,
233
+ RhiError,
234
+ RhiNullAdapter,
235
+ Transform,
236
+ World,
237
+ acquireNullCanvasContext,
238
+ afterEach,
239
+ assertStorageBufferCap,
240
+ beforeEach,
241
+ bin,
242
+ buildMeshAttributeMapForUvSets,
243
+ buildPbrPipelineLayouts,
244
+ buildPbrViewBglEntries,
245
+ buildPipelineForMaterialShader,
246
+ cacheKeyOf,
247
+ calculateSphereClusterBounds,
248
+ clusterSpaceObjectAabb,
249
+ createBoxGeometry,
250
+ createConeGeometry,
251
+ createCylinderGeometry,
252
+ createEngineMetrics,
253
+ createHdrpBindGroupLayoutDescriptor,
254
+ createNullShaderModule,
255
+ createPlaneGeometry,
256
+ createSphereGeometry,
257
+ createTorusGeometry,
258
+ defineComponent,
259
+ deriveCullingRadius,
260
+ deriveRenderDataCubemap,
261
+ deriveRenderDataMesh,
262
+ deriveRenderDataTexture,
263
+ describe,
264
+ dirname,
265
+ err,
266
+ existsSync,
267
+ expect,
268
+ extractFrame,
269
+ fileURLToPath,
270
+ findVariantByKey,
271
+ it,
272
+ makeExplicitNullRhi,
273
+ makeMockShaderRegistry,
274
+ mat4,
275
+ matchPass,
276
+ ndcPositionToCluster,
277
+ ok,
278
+ prepareExtractContext,
279
+ readFileSync,
280
+ resolve,
281
+ resolveAssetHandle,
282
+ rhiOk,
283
+ standardMaterialShaderVariants,
284
+ toShared,
285
+ validateClusterGrid,
286
+ vec3,
287
+ vi,
288
+ viewZToZSlice,
289
+ ];
290
+ type __MergedKeep =
291
+ | AssetError
292
+ | ClusterBinError
293
+ | EquirectAsset
294
+ | Handle
295
+ | Mat4
296
+ | MaterialRenderState
297
+ | MaterialShaderEntry
298
+ | MaterialShaderManifestEntry
299
+ | MaterialShaderManifestVariant
300
+ | MeshAsset
301
+ | PassSelector
302
+ | PbrCaps
303
+ | PipelineBuilderContext
304
+ | PipelineBuilderShaderModuleFactory
305
+ | PipelineLayout
306
+ | PipelineSpec
307
+ | PrimitiveTopology
308
+ | RenderPipeline
309
+ | RenderPipelineAsset
310
+ | RendererType
311
+ | Result
312
+ | RhiCaps
313
+ | RhiDevice
314
+ | ShaderModule
315
+ | TextureAsset
316
+ | Vec3
317
+ | WorldType;
318
+
319
+ {
320
+ // --- from renderer-draw-world.test.ts ---
321
+ const _ENGINE = new URL('../../../render/src/assembly/factory.ts', import.meta.url).href;
322
+ const RENDERER = new URL('../../../render/src/assembly/factory.ts', import.meta.url).href;
323
+
324
+ // ─── Mock helpers ───────────────────────────────────────────────────────────
325
+
326
+ interface MockGL2Context {
327
+ __mockTag: 'webgl2';
328
+ getExtension: () => null;
329
+ getParameter: () => number;
330
+ isContextLost: () => boolean;
331
+ }
332
+
333
+ function makeMockGL2(): MockGL2Context {
334
+ return {
335
+ __mockTag: 'webgl2',
336
+ getExtension: () => null,
337
+ getParameter: () => 1,
338
+ isContextLost: () => false,
339
+ };
340
+ }
341
+
342
+ interface CanvasOptions {
343
+ webgl2: 'context' | 'null';
344
+ webgpu?: 'context' | 'null';
345
+ }
346
+
347
+ function _makeMockCanvas(opts: CanvasOptions): HTMLCanvasElement {
348
+ const canvas = {
349
+ width: 800,
350
+ height: 600,
351
+ getContext(kind: string): unknown {
352
+ if (kind === 'webgl2') {
353
+ return opts.webgl2 === 'context' ? makeMockGL2() : null;
354
+ }
355
+ if (kind === 'webgpu') {
356
+ if (opts.webgpu === 'context') {
357
+ return {
358
+ __mockTag: 'webgpu-canvas-context',
359
+ configure: () => undefined,
360
+ unconfigure: () => undefined,
361
+ getCurrentTexture: () => ({ createView: () => ({}) }),
362
+ };
363
+ }
364
+ return null;
365
+ }
366
+ return null;
367
+ },
368
+ addEventListener: () => undefined,
369
+ removeEventListener: () => undefined,
370
+ } as unknown as HTMLCanvasElement;
371
+ return canvas;
372
+ }
373
+
374
+ function _makeMockGPUDevice(): { device: unknown } {
375
+ const lost = new Promise<unknown>(() => undefined);
376
+ const device = {
377
+ __mockTag: 'gpu-device',
378
+ lost,
379
+ features: new Set(),
380
+ limits: {},
381
+ queue: {
382
+ submit: () => undefined,
383
+ writeBuffer: () => undefined,
384
+ // bug-20260519 AC-03 path: zero-manifest path runs through fallback
385
+ // texture seed (writeTexture) which the legacy 4 cases never reach.
386
+ writeTexture: () => undefined,
387
+ },
388
+ createShaderModule: () => ({
389
+ getCompilationInfo: async () => ({ messages: [] }),
390
+ }),
391
+ createBindGroupLayout: () => ({}),
392
+ createPipelineLayout: () => ({}),
393
+ createRenderPipeline: () => ({}),
394
+ createBindGroup: () => ({}),
395
+ createBuffer: () => ({
396
+ getMappedRange: () => new ArrayBuffer(64),
397
+ unmap: () => undefined,
398
+ }),
399
+ createCommandEncoder: () => ({
400
+ beginRenderPass: () => ({
401
+ setPipeline: () => undefined,
402
+ setVertexBuffer: () => undefined,
403
+ setIndexBuffer: () => undefined,
404
+ setBindGroup: () => undefined,
405
+ draw: () => undefined,
406
+ drawIndexed: () => undefined,
407
+ end: () => undefined,
408
+ }),
409
+ finish: () => ({}),
410
+ }),
411
+ createTexture: () => ({
412
+ createView: () => ({}),
413
+ }),
414
+ createSampler: () => ({}),
415
+ destroy: () => undefined,
416
+ };
417
+ return { device };
418
+ }
419
+
420
+ function _makeMockGPU(deviceObj: unknown): unknown {
421
+ return {
422
+ requestAdapter: async () => ({
423
+ requestDevice: async () => deviceObj,
424
+ }),
425
+ getPreferredCanvasFormat: () => 'bgra8unorm',
426
+ };
427
+ }
428
+
429
+ const baseNavigator = { userAgent: 'mock-engine-test' } as unknown as Navigator;
430
+
431
+ function _buildManifestDataUrl(): string {
432
+ // feat-20260518-pbr-direct-lighting-mvp M5 / w22.9: createRenderer's
433
+ // post-fallback path requires both pbr (`f_schlick(` marker) + unlit
434
+ // entries; seed two minimal stubs (mock device's createShaderModule does
435
+ // not parse WGSL).
436
+ const manifest = {
437
+ schemaVersion: '1.0.0',
438
+ entries: [
439
+ { hash: 'pbr00000', wgsl: '/* pbr stub - calls f_schlick( */', glsl: '', bindings: '' },
440
+ { hash: 'unlit000', wgsl: '/* unlit stub */', glsl: '', bindings: '' },
441
+ {
442
+ hash: 'tonemap0',
443
+ wgsl: '/* tonemap stub - struct TonemapParams { exposure: f32 }; */',
444
+ glsl: '',
445
+ bindings: '',
446
+ },
447
+ ],
448
+ };
449
+ return `data:application/json,${encodeURIComponent(JSON.stringify(manifest))}`;
450
+ }
451
+
452
+ beforeEach(() => {
453
+ vi.stubGlobal('navigator', { ...baseNavigator });
454
+ });
455
+
456
+ afterEach(() => {
457
+ vi.unstubAllGlobals();
458
+ });
459
+
460
+ // ─── Tests ──────────────────────────────────────────────────────────────────
461
+
462
+ describe('Renderer.draw(world) K-4 contract rewrite (D-S11)', () => {
463
+ it('removes the RendererDrawTarget interface from the renderer source file', async () => {
464
+ // Source-level grep gate: the D-S11 + K-4 rewrite removes the
465
+ // RendererDrawTarget interface declaration entirely (charter
466
+ // proposition 5 single PBR main path; no double-shader branching).
467
+ const fsId = 'node:fs';
468
+ const pathId = 'node:path';
469
+ const urlId = 'node:url';
470
+ const fs = (await import(/* @vite-ignore */ fsId)) as {
471
+ readFileSync: (p: string, enc: string) => string;
472
+ };
473
+ const path = (await import(/* @vite-ignore */ pathId)) as {
474
+ resolve: (...parts: string[]) => string;
475
+ dirname: (p: string) => string;
476
+ };
477
+ const url = (await import(/* @vite-ignore */ urlId)) as {
478
+ fileURLToPath: (u: string) => string;
479
+ };
480
+ const here = url.fileURLToPath(import.meta.url);
481
+ const rendererSrc = path.resolve(
482
+ path.dirname(here),
483
+ '..',
484
+ '..',
485
+ '..',
486
+ 'render',
487
+ 'src',
488
+ 'assembly',
489
+ 'webgpu-renderer.ts',
490
+ );
491
+ const text = fs.readFileSync(rendererSrc, 'utf8');
492
+ expect(text).not.toMatch(/interface RendererDrawTarget/);
493
+ expect(text).not.toMatch(/RendererDrawTarget/);
494
+ // Module runtime export must also be absent (already erased by tsc for
495
+ // type-only members; covers `export type` removal at the surface level).
496
+ const mod = (await import(RENDERER)) as Record<string, unknown>;
497
+ expect(mod.RendererDrawTarget).toBeUndefined();
498
+ });
499
+ });
500
+
501
+ // bug-20260519 AC-03: when a world *does* carry a `MeshRenderer` entity but
502
+ // the renderer was created without `shaderManifestUrl`, render-time access
503
+ // to the now-nullable `pipelineState.{unlitPipeline,standardPipeline}` must
504
+ // feat-20260529 D-3: materials without passes are caught at extract stage
505
+ // as `material-no-effective-pass` (the shared MaterialError), before
506
+ // reaching the record-stage pipeline-pick branch. The test's original
507
+ // bug-20260519 AC-03 intent — "zero-manifest renderer fires structured error
508
+ // not crash" — is preserved; the detection point has moved upstream.
509
+ // Original test expected `shader-compile-failed` from the record stage.
510
+ // After D-3, the material registered below has `kind:'material'` +
511
+ // `baseColor` but zero passes — the extract stage
512
+ // walks the parent chain (no parent), finds zero passes, and fires
513
+ // `material-no-effective-pass` with a recovery hint for adding a pass.
514
+ }