@forgeax/engine-runtime 0.1.3 → 0.1.6

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 (606) hide show
  1. package/README.md +49 -83
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/__tests__/animation-graph-collect-roundtrip.test.d.ts +2 -0
  4. package/dist/__tests__/animation-graph-collect-roundtrip.test.d.ts.map +1 -0
  5. package/dist/__tests__/animation-graph-serialize.unit.test.d.ts +2 -0
  6. package/dist/__tests__/animation-graph-serialize.unit.test.d.ts.map +1 -0
  7. package/dist/__tests__/asset-brand-and-name-retirement.test.d.ts +2 -0
  8. package/dist/__tests__/asset-brand-and-name-retirement.test.d.ts.map +1 -0
  9. package/dist/__tests__/asset-error-exhaustive.test-d.d.ts +11 -0
  10. package/dist/__tests__/asset-error-exhaustive.test-d.d.ts.map +1 -0
  11. package/dist/__tests__/asset-registry-guid-reverse.test.d.ts +2 -0
  12. package/dist/__tests__/asset-registry-guid-reverse.test.d.ts.map +1 -0
  13. package/dist/__tests__/asset-registry-hdr-equirect.test.d.ts +2 -0
  14. package/dist/__tests__/asset-registry-hdr-equirect.test.d.ts.map +1 -0
  15. package/dist/__tests__/asset-registry-mesh-pack-payload.dawn.test.d.ts +2 -0
  16. package/dist/__tests__/asset-registry-mesh-pack-payload.dawn.test.d.ts.map +1 -0
  17. package/dist/__tests__/asset-registry-mounts.test.d.ts +2 -0
  18. package/dist/__tests__/asset-registry-mounts.test.d.ts.map +1 -0
  19. package/dist/__tests__/asset-registry.browser.test.d.ts +2 -0
  20. package/dist/__tests__/asset-registry.browser.test.d.ts.map +1 -0
  21. package/dist/__tests__/asset-registry.dawn.test.d.ts +2 -0
  22. package/dist/__tests__/asset-registry.dawn.test.d.ts.map +1 -0
  23. package/dist/__tests__/asset-registry.listCatalog.test.d.ts +2 -0
  24. package/dist/__tests__/asset-registry.listCatalog.test.d.ts.map +1 -0
  25. package/dist/__tests__/asset-registry.mesh-bin.test.d.ts +2 -0
  26. package/dist/__tests__/asset-registry.mesh-bin.test.d.ts.map +1 -0
  27. package/dist/__tests__/asset-registry.pack-cache.test.d.ts +2 -0
  28. package/dist/__tests__/asset-registry.pack-cache.test.d.ts.map +1 -0
  29. package/dist/__tests__/asset-registry.raw-container-failfast.test.d.ts +2 -0
  30. package/dist/__tests__/asset-registry.raw-container-failfast.test.d.ts.map +1 -0
  31. package/dist/__tests__/asset-registry.recursive.spec.d.ts +2 -0
  32. package/dist/__tests__/asset-registry.recursive.spec.d.ts.map +1 -0
  33. package/dist/__tests__/asset-registry.unit.test.d.ts +2 -0
  34. package/dist/__tests__/asset-registry.unit.test.d.ts.map +1 -0
  35. package/dist/__tests__/asset.unit.test.d.ts +2 -0
  36. package/dist/__tests__/asset.unit.test.d.ts.map +1 -0
  37. package/dist/__tests__/audio-load-by-guid.unit.test.d.ts +2 -0
  38. package/dist/__tests__/audio-load-by-guid.unit.test.d.ts.map +1 -0
  39. package/dist/__tests__/backend-selection.integration.test.d.ts +2 -0
  40. package/dist/__tests__/backend-selection.integration.test.d.ts.map +1 -0
  41. package/dist/__tests__/basis-catalog-dispatch.integration.test.d.ts +2 -0
  42. package/dist/__tests__/basis-catalog-dispatch.integration.test.d.ts.map +1 -0
  43. package/dist/__tests__/builtin-asset-registry.unit.test.d.ts +2 -0
  44. package/dist/__tests__/builtin-asset-registry.unit.test.d.ts.map +1 -0
  45. package/dist/__tests__/collect-scene-asset.test.d.ts +1 -2
  46. package/dist/__tests__/collect-scene-asset.test.d.ts.map +1 -1
  47. package/dist/__tests__/collect-scene-mount-collapse.test.d.ts +2 -0
  48. package/dist/__tests__/collect-scene-mount-collapse.test.d.ts.map +1 -0
  49. package/dist/__tests__/collect-transient-roundtrip.test.d.ts +1 -1
  50. package/dist/__tests__/collect-transient-roundtrip.test.d.ts.map +1 -1
  51. package/dist/__tests__/collect-transient-skip.test.d.ts +1 -2
  52. package/dist/__tests__/collect-transient-skip.test.d.ts.map +1 -1
  53. package/dist/__tests__/compressed-texture-physical-extent.integration.test.d.ts +2 -0
  54. package/dist/__tests__/compressed-texture-physical-extent.integration.test.d.ts.map +1 -0
  55. package/dist/__tests__/dawn/mesh-update-dawn.test.d.ts +2 -0
  56. package/dist/__tests__/dawn/mesh-update-dawn.test.d.ts.map +1 -0
  57. package/dist/__tests__/dawn/upload-texture.dawn.test.d.ts +2 -0
  58. package/dist/__tests__/dawn/upload-texture.dawn.test.d.ts.map +1 -0
  59. package/dist/__tests__/draw-published.d.ts +2 -2
  60. package/dist/__tests__/draw-published.d.ts.map +1 -1
  61. package/dist/__tests__/dynamic-texture-store.unit.test.d.ts +2 -0
  62. package/dist/__tests__/dynamic-texture-store.unit.test.d.ts.map +1 -0
  63. package/dist/__tests__/errors.unit.test.d.ts +2 -0
  64. package/dist/__tests__/errors.unit.test.d.ts.map +1 -0
  65. package/dist/__tests__/extract-skin-mismatch.unit.test.d.ts +2 -0
  66. package/dist/__tests__/extract-skin-mismatch.unit.test.d.ts.map +1 -0
  67. package/dist/__tests__/fetch-binary-decompress.test.d.ts +2 -0
  68. package/dist/__tests__/fetch-binary-decompress.test.d.ts.map +1 -0
  69. package/dist/__tests__/four-path-compression.integration.test.d.ts +2 -0
  70. package/dist/__tests__/four-path-compression.integration.test.d.ts.map +1 -0
  71. package/dist/__tests__/fullscreen-feature-host.dawn.test.d.ts +2 -0
  72. package/dist/__tests__/fullscreen-feature-host.dawn.test.d.ts.map +1 -0
  73. package/dist/__tests__/guid-for-asset.unit.test.d.ts +2 -0
  74. package/dist/__tests__/guid-for-asset.unit.test.d.ts.map +1 -0
  75. package/dist/__tests__/handle-migration.test.d.ts +2 -0
  76. package/dist/__tests__/handle-migration.test.d.ts.map +1 -0
  77. package/dist/__tests__/helpers/register-runtime-components.d.ts.map +1 -1
  78. package/dist/__tests__/host-custom-kind-contract.test-d.d.ts +2 -0
  79. package/dist/__tests__/host-custom-kind-contract.test-d.d.ts.map +1 -0
  80. package/dist/__tests__/host-custom-kind-contract.test.d.ts +2 -0
  81. package/dist/__tests__/host-custom-kind-contract.test.d.ts.map +1 -0
  82. package/dist/__tests__/inspect-name.test.d.ts +2 -0
  83. package/dist/__tests__/inspect-name.test.d.ts.map +1 -0
  84. package/dist/__tests__/instantiate-mount-deferred-wiring.test.d.ts +2 -0
  85. package/dist/__tests__/instantiate-mount-deferred-wiring.test.d.ts.map +1 -0
  86. package/dist/__tests__/loadbyguid-payload.unit.test.d.ts +2 -0
  87. package/dist/__tests__/loadbyguid-payload.unit.test.d.ts.map +1 -0
  88. package/dist/__tests__/loadbyguid-texture-intern.unit.test.d.ts +2 -0
  89. package/dist/__tests__/loadbyguid-texture-intern.unit.test.d.ts.map +1 -0
  90. package/dist/__tests__/loader-extract-graceful.test.d.ts +2 -0
  91. package/dist/__tests__/loader-extract-graceful.test.d.ts.map +1 -0
  92. package/dist/__tests__/loader-name-survival.test.d.ts +2 -0
  93. package/dist/__tests__/loader-name-survival.test.d.ts.map +1 -0
  94. package/dist/__tests__/mesh-bin-contract.test.d.ts +2 -0
  95. package/dist/__tests__/mesh-bin-contract.test.d.ts.map +1 -0
  96. package/dist/__tests__/mesh-bin-skin-roundtrip.unit.test.d.ts +2 -0
  97. package/dist/__tests__/mesh-bin-skin-roundtrip.unit.test.d.ts.map +1 -0
  98. package/dist/__tests__/mesh-bin.test.d.ts +2 -0
  99. package/dist/__tests__/mesh-bin.test.d.ts.map +1 -0
  100. package/dist/__tests__/mesh-loader-skin-contract.unit.test.d.ts +2 -0
  101. package/dist/__tests__/mesh-loader-skin-contract.unit.test.d.ts.map +1 -0
  102. package/dist/__tests__/new-kind-refs-contract.test.d.ts +2 -0
  103. package/dist/__tests__/new-kind-refs-contract.test.d.ts.map +1 -0
  104. package/dist/__tests__/package-promotion.test.d.ts +2 -0
  105. package/dist/__tests__/package-promotion.test.d.ts.map +1 -0
  106. package/dist/__tests__/package-rename.test.d.ts +2 -0
  107. package/dist/__tests__/package-rename.test.d.ts.map +1 -0
  108. package/dist/__tests__/recover-error-exhaustive.test-d.d.ts +1 -1
  109. package/dist/__tests__/recover-error-exhaustive.test-d.d.ts.map +1 -1
  110. package/dist/__tests__/render-error-exhaustive.test-d.d.ts +1 -1
  111. package/dist/__tests__/render-error-exhaustive.test-d.d.ts.map +1 -1
  112. package/dist/__tests__/render-feature-prepared-graphics.fixture.d.ts +10 -0
  113. package/dist/__tests__/render-feature-prepared-graphics.fixture.d.ts.map +1 -0
  114. package/dist/__tests__/render-system-extract.unit.test.d.ts +2 -0
  115. package/dist/__tests__/render-system-extract.unit.test.d.ts.map +1 -0
  116. package/dist/__tests__/renderer-test-utils.d.ts +10 -0
  117. package/dist/__tests__/renderer-test-utils.d.ts.map +1 -0
  118. package/dist/__tests__/renderer.test-d.d.ts +2 -0
  119. package/dist/__tests__/renderer.test-d.d.ts.map +1 -0
  120. package/dist/__tests__/resolve-asset-handle-err.test.d.ts +2 -0
  121. package/dist/__tests__/resolve-asset-handle-err.test.d.ts.map +1 -0
  122. package/dist/__tests__/resolve-asset-handle.unit.test.d.ts +2 -0
  123. package/dist/__tests__/resolve-asset-handle.unit.test.d.ts.map +1 -0
  124. package/dist/__tests__/resolveName-fallback.test.d.ts +2 -0
  125. package/dist/__tests__/resolveName-fallback.test.d.ts.map +1 -0
  126. package/dist/__tests__/resolveName-null-package.test.d.ts +2 -0
  127. package/dist/__tests__/resolveName-null-package.test.d.ts.map +1 -0
  128. package/dist/__tests__/resolveName-unified-entry.test.d.ts +2 -0
  129. package/dist/__tests__/resolveName-unified-entry.test.d.ts.map +1 -0
  130. package/dist/__tests__/resolveName.test.d.ts +2 -0
  131. package/dist/__tests__/resolveName.test.d.ts.map +1 -0
  132. package/dist/__tests__/roots-to-scene-asset.test.d.ts +1 -1
  133. package/dist/__tests__/roots-to-scene-asset.test.d.ts.map +1 -1
  134. package/dist/__tests__/roundtrip-primitive.test.d.ts +2 -0
  135. package/dist/__tests__/roundtrip-primitive.test.d.ts.map +1 -0
  136. package/dist/__tests__/scene-bare-guid-refs-instantiate.test.d.ts +2 -0
  137. package/dist/__tests__/scene-bare-guid-refs-instantiate.test.d.ts.map +1 -0
  138. package/dist/__tests__/scene-instance-authoring.integration.test.d.ts +2 -0
  139. package/dist/__tests__/scene-instance-authoring.integration.test.d.ts.map +1 -0
  140. package/dist/__tests__/scene-mount-fixed-point.test.d.ts +2 -0
  141. package/dist/__tests__/scene-mount-fixed-point.test.d.ts.map +1 -0
  142. package/dist/__tests__/scene-mount-roundtrip.test.d.ts +2 -0
  143. package/dist/__tests__/scene-mount-roundtrip.test.d.ts.map +1 -0
  144. package/dist/__tests__/scene-mount-wrapper-roundtrip.test.d.ts +2 -0
  145. package/dist/__tests__/scene-mount-wrapper-roundtrip.test.d.ts.map +1 -0
  146. package/dist/__tests__/scene-sugar-instantiate.test.d.ts +2 -0
  147. package/dist/__tests__/scene-sugar-instantiate.test.d.ts.map +1 -0
  148. package/dist/__tests__/serialize-mounts-roundtrip.test.d.ts +2 -0
  149. package/dist/__tests__/serialize-mounts-roundtrip.test.d.ts.map +1 -0
  150. package/dist/__tests__/serialize-scene-asset.test.d.ts +1 -1
  151. package/dist/__tests__/serialize-scene-asset.test.d.ts.map +1 -1
  152. package/dist/__tests__/template-game-default-api-contract.test.d.ts +2 -0
  153. package/dist/__tests__/template-game-default-api-contract.test.d.ts.map +1 -0
  154. package/dist/__tests__/tileset-asset-validate.test.d.ts +2 -0
  155. package/dist/__tests__/tileset-asset-validate.test.d.ts.map +1 -0
  156. package/dist/__tests__/transcode-fallback.unit.test.d.ts +2 -0
  157. package/dist/__tests__/transcode-fallback.unit.test.d.ts.map +1 -0
  158. package/dist/__tests__/transient-runtime-behavior.test.d.ts +2 -0
  159. package/dist/__tests__/transient-runtime-behavior.test.d.ts.map +1 -0
  160. package/dist/__tests__/video-loader-consumption.test.d.ts +2 -0
  161. package/dist/__tests__/video-loader-consumption.test.d.ts.map +1 -0
  162. package/dist/__tests__/video-loader-smoke.dawn.test.d.ts +2 -0
  163. package/dist/__tests__/video-loader-smoke.dawn.test.d.ts.map +1 -0
  164. package/dist/backend-selection.d.ts +13 -0
  165. package/dist/backend-selection.d.ts.map +1 -0
  166. package/dist/collect-scene-asset.d.ts +3 -3
  167. package/dist/collect-scene-asset.d.ts.map +1 -1
  168. package/dist/createRenderer.d.ts +14 -2
  169. package/dist/createRenderer.d.ts.map +1 -1
  170. package/dist/errors/environment.d.ts +1 -1
  171. package/dist/errors/environment.d.ts.map +1 -1
  172. package/dist/index.d.ts +19 -81
  173. package/dist/index.d.ts.map +1 -1
  174. package/dist/index.mjs +105 -108
  175. package/dist/index.mjs.map +1 -1
  176. package/dist/renderer-host.d.ts +9 -0
  177. package/dist/renderer-host.d.ts.map +1 -0
  178. package/dist/renderer-host.mjs +62 -0
  179. package/dist/renderer-host.mjs.map +1 -0
  180. package/dist/scene-instances/index.d.ts +2 -0
  181. package/dist/scene-instances/index.d.ts.map +1 -0
  182. package/dist/scene-utils/mount-override-fold.d.ts +1 -2
  183. package/dist/scene-utils/mount-override-fold.d.ts.map +1 -1
  184. package/dist/systems/sprite-animation-tick.d.ts +1 -1
  185. package/dist/systems/sprite-animation-tick.d.ts.map +1 -1
  186. package/dist/systems/transparent-sort.d.ts +1 -2
  187. package/dist/systems/transparent-sort.d.ts.map +1 -1
  188. package/dist/tilemap-register-validate.d.ts.map +1 -1
  189. package/package.json +34 -33
  190. package/src/__tests__/active-camera.unit.test.ts +19 -9
  191. package/src/__tests__/animation-graph-collect-roundtrip.test.ts +213 -0
  192. package/src/__tests__/animation-graph-serialize.unit.test.ts +171 -0
  193. package/src/__tests__/append-injection.test.ts +1 -1
  194. package/src/__tests__/asset-brand-and-name-retirement.test.ts +102 -0
  195. package/src/__tests__/asset-error-exhaustive.test-d.ts +62 -0
  196. package/src/__tests__/asset-registry-guid-reverse.test.ts +575 -0
  197. package/src/__tests__/asset-registry-hdr-equirect.test.ts +78 -0
  198. package/src/__tests__/asset-registry-mesh-pack-payload.dawn.test.ts +232 -0
  199. package/src/__tests__/asset-registry-mounts.test.ts +806 -0
  200. package/src/__tests__/asset-registry.browser.test.ts +81 -0
  201. package/src/__tests__/asset-registry.dawn.test.ts +94 -0
  202. package/src/__tests__/asset-registry.listCatalog.test.ts +170 -0
  203. package/src/__tests__/asset-registry.mesh-bin.test.ts +316 -0
  204. package/src/__tests__/asset-registry.pack-cache.test.ts +969 -0
  205. package/src/__tests__/asset-registry.raw-container-failfast.test.ts +225 -0
  206. package/src/__tests__/asset-registry.recursive.spec.ts +1397 -0
  207. package/src/__tests__/asset-registry.unit.test.ts +1030 -0
  208. package/src/__tests__/asset.unit.test.ts +7107 -0
  209. package/src/__tests__/audio-load-by-guid.unit.test.ts +126 -0
  210. package/src/__tests__/backend-selection.integration.test.ts +11 -0
  211. package/src/__tests__/basis-catalog-dispatch.integration.test.ts +320 -0
  212. package/src/__tests__/bind-group-cache-keying.test.ts +4 -4
  213. package/src/__tests__/block-upload-math.unit.test.ts +2 -2
  214. package/src/__tests__/builtin-asset-registry.unit.test.ts +112 -0
  215. package/src/__tests__/builtin-shader-register-e2e.test.ts +1 -1
  216. package/src/__tests__/cache-false-eviction.test.ts +2 -1
  217. package/src/__tests__/cache-isolation-matrix.test.ts +2 -1
  218. package/src/__tests__/camera-clear-snapshot-equivalence.unit.test.ts +5 -6
  219. package/src/__tests__/clamp-to-last.e2e.browser.test.ts +29 -19
  220. package/src/__tests__/collect-scene-asset.test.ts +49 -52
  221. package/src/__tests__/collect-scene-mount-collapse.test.ts +391 -0
  222. package/src/__tests__/collect-subtree.unit.test.ts +1 -2
  223. package/src/__tests__/collect-transient-children-absent.test.ts +24 -10
  224. package/src/__tests__/collect-transient-roundtrip.test.ts +44 -20
  225. package/src/__tests__/collect-transient-skip.test.ts +24 -13
  226. package/src/__tests__/components.test-d.ts +1 -6
  227. package/src/__tests__/components.unit.test.ts +20 -19
  228. package/src/__tests__/composite-skybox-cross-world.browser.test.ts +59 -27
  229. package/src/__tests__/compressed-texture-physical-extent.integration.test.ts +139 -0
  230. package/src/__tests__/create-renderer-assembly.integration.test.ts +42 -29
  231. package/src/__tests__/createRenderer-dispose.test.ts +35 -402
  232. package/src/__tests__/createRenderer.browser-no-webgpu.test.ts +25 -30
  233. package/src/__tests__/createRenderer.unit.test.ts +1 -1
  234. package/src/__tests__/dawn/hello-sprite-nineslice-section.dawn.test.ts +27 -63
  235. package/src/__tests__/dawn/ibl-precompute-readback.dawn.test.ts +56 -47
  236. package/src/__tests__/dawn/instances-per-instance-pbr.dawn.test.ts +49 -29
  237. package/src/__tests__/dawn/instances-shadow.dawn.test.ts +26 -15
  238. package/src/__tests__/dawn/instances-uniform-fallback.dawn.test.ts +13 -14
  239. package/src/__tests__/dawn/material-alpha.dawn.test.ts +23 -31
  240. package/src/__tests__/dawn/material-cooked-fixture.dawn.test.ts +0 -18
  241. package/src/__tests__/dawn/{mesh-update.dawn.test.ts → mesh-update-dawn.test.ts} +42 -134
  242. package/src/__tests__/dawn/mipmap-srgb-linear.dawn.test.ts +14 -7
  243. package/src/__tests__/dawn/per-entity-material-texture-isolation.dawn.test.ts +16 -28
  244. package/src/__tests__/dawn/sprite-nineslice-mesh-bind.dawn.test.ts +23 -39
  245. package/src/__tests__/dawn/upload-texture.dawn.test.ts +198 -0
  246. package/src/__tests__/dawn/user-handle-mesh-render.dawn.test.ts +12 -14
  247. package/src/__tests__/dawn/user-mesh-upload.dawn.test.ts +27 -22
  248. package/src/__tests__/dawn/zero-manifest-mesh-fail.dawn.test.ts +25 -28
  249. package/src/__tests__/dawn/zero-manifest-ready.dawn.test.ts +10 -11
  250. package/src/__tests__/demo-sortscope-migration.unit.test.ts +5 -5
  251. package/src/__tests__/derive-bgl-integration.test.ts +34 -44
  252. package/src/__tests__/derive-render-data-skin.unit.test.ts +1 -1
  253. package/src/__tests__/draw-published.ts +11 -4
  254. package/src/__tests__/dynamic-texture-store.unit.test.ts +190 -0
  255. package/src/__tests__/equirect-bc6h.integration.test.ts +144 -21
  256. package/src/__tests__/errors.unit.test.ts +1203 -0
  257. package/src/__tests__/extract-frames-graceful-degradation.test.ts +3 -7
  258. package/src/__tests__/extract-frames-merge.test.ts +35 -22
  259. package/src/__tests__/extract-record-no-hardcoded-texture-fields.test.ts +5 -16
  260. package/src/__tests__/extract-skin-mismatch.unit.test.ts +322 -0
  261. package/src/__tests__/fetch-binary-decompress.test.ts +356 -0
  262. package/src/__tests__/four-path-compression.integration.test.ts +395 -0
  263. package/src/__tests__/frame-targets-shadow-regression.unit.test.ts +1 -1
  264. package/src/__tests__/fullscreen-feature-host.dawn.test.ts +80 -0
  265. package/src/__tests__/fullscreen-post-bgl-depth.test.ts +4 -2
  266. package/src/__tests__/fullscreen-post-depth-params-arity.test.ts +3 -3
  267. package/src/__tests__/fullscreen-post-process-pass.dawn.test.ts +39 -23
  268. package/src/__tests__/fullscreen-post-process-pass.unit.test.ts +4 -2
  269. package/src/__tests__/fxaa-pixel-diff.dawn.test.ts +28 -17
  270. package/src/__tests__/fxaa-validation-and-resize.dawn.test.ts +29 -18
  271. package/src/__tests__/fxaa-zero-overhead.dawn.test.ts +16 -12
  272. package/src/__tests__/geometry.unit.test.ts +525 -159
  273. package/src/__tests__/glyph-tilemap-worldid.test.ts +1 -1
  274. package/src/__tests__/gpu-resource-cow-survivor.test.ts +6 -4
  275. package/src/__tests__/guid-for-asset.unit.test.ts +102 -0
  276. package/src/__tests__/handle-migration.test.ts +136 -0
  277. package/src/__tests__/helpers/register-runtime-components.ts +4 -2
  278. package/src/__tests__/helpers/register-scene-components.ts +1 -1
  279. package/src/__tests__/host-custom-kind-contract.test-d.ts +47 -0
  280. package/src/__tests__/host-custom-kind-contract.test.ts +578 -0
  281. package/src/__tests__/inspect-name.test.ts +139 -0
  282. package/src/__tests__/instances.test-d.ts +1 -1
  283. package/src/__tests__/instantiate-mount-deferred-wiring.test.ts +112 -0
  284. package/src/__tests__/light-casters-9-light.browser.test.ts +73 -76
  285. package/src/__tests__/light-gpu-byte-neutral.unit.test.ts +7 -10
  286. package/src/__tests__/light-snapshot.test-d.ts +2 -2
  287. package/src/__tests__/lights-vec-negative.unit.test.ts +1 -1
  288. package/src/__tests__/lights.unit.test.ts +16 -500
  289. package/src/__tests__/loadbyguid-payload.unit.test.ts +117 -0
  290. package/src/__tests__/loadbyguid-texture-intern.unit.test.ts +213 -0
  291. package/src/__tests__/loader-extract-graceful.test.ts +146 -0
  292. package/src/__tests__/loader-name-survival.test.ts +213 -0
  293. package/src/__tests__/m3-vec-negative.unit.test.ts +3 -2
  294. package/src/__tests__/material-texture-uv-scale.unit.test.ts +101 -31
  295. package/src/__tests__/materials.unit.test.ts +10 -27
  296. package/src/__tests__/mesh-bin-contract.test.ts +28 -0
  297. package/src/__tests__/mesh-bin-skin-roundtrip.unit.test.ts +149 -0
  298. package/src/__tests__/mesh-bin.test.ts +38 -0
  299. package/src/__tests__/mesh-loader-skin-contract.unit.test.ts +120 -0
  300. package/src/__tests__/mesh-ssbo-grow.unit.test.ts +3 -3
  301. package/src/__tests__/mip-gate.unit.test.ts +1 -1
  302. package/src/__tests__/msaa-sprite-pixel-diff.dawn.test.ts +29 -68
  303. package/src/__tests__/new-kind-refs-contract.test.ts +132 -0
  304. package/src/__tests__/node-shims.d.ts +4 -6
  305. package/src/__tests__/package-promotion.test.ts +88 -0
  306. package/src/__tests__/package-rename.test.ts +103 -0
  307. package/src/__tests__/pass-selector.unit.test.ts +2 -2
  308. package/src/__tests__/pbr-pipeline.unit.test.ts +14 -21
  309. package/src/__tests__/pipeline-builder-msaa.unit.test.ts +6 -9
  310. package/src/__tests__/pipeline-cache-keying.unit.test.ts +6 -9
  311. package/src/__tests__/pipeline-spec.test.ts +16 -177
  312. package/src/__tests__/pipeline.unit.test.ts +154 -1693
  313. package/src/__tests__/point-light-shadow.dawn.test.ts +33 -42
  314. package/src/__tests__/point-light-shadow.unit.test.ts +19 -60
  315. package/src/__tests__/post-process-error-codes.unit.test.ts +4 -1
  316. package/src/__tests__/post-process-params-component.unit.test.ts +1 -1
  317. package/src/__tests__/post-process-params-extract.unit.test.ts +2 -5
  318. package/src/__tests__/postprocess-camera-consistency.test.ts +4 -7
  319. package/src/__tests__/profiler-assembly.integration.test.ts +1 -1
  320. package/src/__tests__/propagate-transforms.dawn.test.ts +12 -11
  321. package/src/__tests__/record-worldid-isolation.test.ts +7 -29
  322. package/src/__tests__/recover-error-exhaustive.test-d.ts +1 -1
  323. package/src/__tests__/render-error-exhaustive.test-d.ts +81 -71
  324. package/src/__tests__/render-feature-assembly.test-d.ts +20 -9
  325. package/src/__tests__/render-feature-prepared-graphics-docs.unit.test.ts +8 -6
  326. package/src/__tests__/render-feature-prepared-graphics.browser.test.ts +60 -558
  327. package/src/__tests__/render-feature-prepared-graphics.dawn.test.ts +57 -544
  328. package/src/__tests__/render-feature-prepared-graphics.fixture.ts +104 -0
  329. package/src/__tests__/render-feature-prepared-graphics.integration.test.ts +40 -248
  330. package/src/__tests__/render-feature-prepared-graphics.regression.integration.test.ts +83 -340
  331. package/src/__tests__/render-feature-recover.integration.test.ts +9 -49
  332. package/src/__tests__/render-feature-runtime-surface.test-d.ts +17 -20
  333. package/src/__tests__/render-schema-consumer.integration.test.ts +20 -13
  334. package/src/__tests__/render-schema-owner-boundary.unit.test.ts +2 -6
  335. package/src/__tests__/render-system-cross-world-overlay-queue.test.ts +5 -5
  336. package/src/__tests__/render-system-extract-dispatch-ordering.test.ts +16 -31
  337. package/src/__tests__/render-system-extract.test.ts +36 -51
  338. package/src/__tests__/render-system-extract.unit.test.ts +360 -0
  339. package/src/__tests__/render-system-fold-bucket.unit.test.ts +3 -5
  340. package/src/__tests__/render-system-fold-fallback.unit.test.ts +6 -3
  341. package/src/__tests__/render-system-fold-material.unit.test.ts +3 -5
  342. package/src/__tests__/render-system-fold-metrics.unit.test.ts +5 -5
  343. package/src/__tests__/render-system-fold-modegate.unit.test.ts +6 -6
  344. package/src/__tests__/render-system-fold.dawn.test.ts +7 -5
  345. package/src/__tests__/render-system-mega.test.ts +292 -190
  346. package/src/__tests__/render-system-owner-split-contract.test.ts +10 -32
  347. package/src/__tests__/render-system-record-multi-material-textureview.test.ts +59 -45
  348. package/src/__tests__/render-system-record-per-submesh-transparency.test.ts +23 -29
  349. package/src/__tests__/render-system-record.test.ts +398 -235
  350. package/src/__tests__/render-system-record.unit.test.ts +25 -26
  351. package/src/__tests__/render-system-skin-bg.unit.test.ts +8 -12
  352. package/src/__tests__/renderer-consumer.test-d.ts +16 -3
  353. package/src/__tests__/renderer-health.unit.test.ts +26 -916
  354. package/src/__tests__/renderer-lifecycle.integration.test.ts +19 -6
  355. package/src/__tests__/renderer-recover.unit.test.ts +49 -1069
  356. package/src/__tests__/renderer-result.test-d.ts +19 -9
  357. package/src/__tests__/renderer-surface.unit.test.ts +3 -5
  358. package/src/__tests__/renderer-test-utils.ts +56 -0
  359. package/src/__tests__/renderer.test-d.ts +59 -0
  360. package/src/__tests__/resolve-asset-handle-err.test.ts +111 -0
  361. package/src/__tests__/resolve-asset-handle.unit.test.ts +64 -0
  362. package/src/__tests__/resolve-depth-only-view.test.ts +1 -1
  363. package/src/__tests__/resolveName-fallback.test.ts +64 -0
  364. package/src/__tests__/resolveName-null-package.test.ts +38 -0
  365. package/src/__tests__/resolveName-unified-entry.test.ts +65 -0
  366. package/src/__tests__/resolveName.test.ts +64 -0
  367. package/src/__tests__/rhi-null-command-flow.unit.test.ts +43 -261
  368. package/src/__tests__/rhi-null-renderer-lifecycle.unit.test.ts +41 -169
  369. package/src/__tests__/roots-to-scene-asset.test.ts +199 -93
  370. package/src/__tests__/roundtrip-primitive.test.ts +351 -0
  371. package/src/__tests__/scene-bare-guid-refs-instantiate.test.ts +123 -0
  372. package/src/__tests__/scene-equirect-roundtrip.test.ts +103 -16
  373. package/src/__tests__/scene-instance-authoring.integration.test.ts +8 -0
  374. package/src/__tests__/scene-instance-bridge.integration.test.ts +1 -1
  375. package/src/__tests__/scene-instance-component.test.ts +1 -1
  376. package/src/__tests__/scene-mount-fixed-point.test.ts +257 -0
  377. package/src/__tests__/scene-mount-roundtrip.test.ts +987 -0
  378. package/src/__tests__/scene-mount-wrapper-roundtrip.test.ts +202 -0
  379. package/src/__tests__/scene-sugar-instantiate.test.ts +324 -0
  380. package/src/__tests__/serialize-mounts-roundtrip.test.ts +533 -0
  381. package/src/__tests__/serialize-scene-asset.test.ts +219 -22
  382. package/src/__tests__/shadow-caster-empty-schema.test.ts +3 -3
  383. package/src/__tests__/shadow-csm-cascade-loadop.test.ts +37 -17
  384. package/src/__tests__/shadow-csm-component.test.ts +3 -5
  385. package/src/__tests__/shadow-csm-extract.test.ts +2 -100
  386. package/src/__tests__/shadow-csm-orthoz.test.ts +2 -16
  387. package/src/__tests__/shadow-csm-runtime-vary.dawn.test.ts +19 -14
  388. package/src/__tests__/shadow-csm-tile-consistency.test.ts +32 -26
  389. package/src/__tests__/shadow-csm-ubo.dawn.test.ts +8 -49
  390. package/src/__tests__/shadow-csm-ubo.test.ts +3 -25
  391. package/src/__tests__/shadow-csm-viewport.browser.test.ts +1 -1
  392. package/src/__tests__/shadow-fields-observable.dawn.test.ts +67 -56
  393. package/src/__tests__/shadow-m1.dawn.test.ts +8 -9
  394. package/src/__tests__/shadow-mesh-ssbo-order.test.ts +11 -27
  395. package/src/__tests__/skin-errors.unit.test.ts +1 -1
  396. package/src/__tests__/skin-extract-getarrayview-count.unit.test.ts +7 -5
  397. package/src/__tests__/skylight-lazy-projection.test.ts +36 -15
  398. package/src/__tests__/sparse-tag-scene-roundtrip.test.ts +5 -5
  399. package/src/__tests__/sprite-cullmode-flip.dawn.test.ts +47 -64
  400. package/src/__tests__/sprite-lit-bgl-byte-identical.test.ts +12 -11
  401. package/src/__tests__/sprite-lit-extract-branch.test.ts +1 -1
  402. package/src/__tests__/sprite-lit-pipeline-cache-key.test.ts +1 -1
  403. package/src/__tests__/ssao-bgl.test.ts +16 -9
  404. package/src/__tests__/ssao-buffers.test.ts +2 -2
  405. package/src/__tests__/ssao-data.test.ts +2 -2
  406. package/src/__tests__/ssao-errors.test.ts +1 -1
  407. package/src/__tests__/ssao-passes.test.ts +64 -392
  408. package/src/__tests__/ssao-pipelines.test.ts +1 -1
  409. package/src/__tests__/ssao-uniform-layout.test.ts +8 -6
  410. package/src/__tests__/stencil-outline-pixel.dawn.test.ts +25 -17
  411. package/src/__tests__/swap-chain-format.unit.test.ts +5 -7
  412. package/src/__tests__/systems.unit.test.ts +536 -1326
  413. package/src/__tests__/template-game-default-api-contract.test.ts +362 -0
  414. package/src/__tests__/text.unit.test.ts +56 -33
  415. package/src/__tests__/tilemap-childed-despawn.test.ts +8 -14
  416. package/src/__tests__/tilemap-chunk-extract.overhang-bounds.test.ts +8 -12
  417. package/src/__tests__/tilemap-chunk-extract.propagate-order.test.ts +2 -1
  418. package/src/__tests__/tilemap-chunk-extract.test.ts +13 -17
  419. package/src/__tests__/tilemap-dirty-rebuild.test.ts +7 -11
  420. package/src/__tests__/tilemap-material-cache.test.ts +8 -13
  421. package/src/__tests__/tilemap-multi-atlas.test.ts +12 -32
  422. package/src/__tests__/tilemap-owner-boundary.unit.test.ts +5 -2
  423. package/src/__tests__/tilemap-region-pack.test.ts +8 -12
  424. package/src/__tests__/tilemap-spawn-flip-pivot.test.ts +8 -12
  425. package/src/__tests__/tilemap-uv-inset.test.ts +11 -14
  426. package/src/__tests__/tilemap-validate.test.ts +1 -1
  427. package/src/__tests__/tileset-asset-validate.test.ts +638 -0
  428. package/src/__tests__/transcode-fallback.unit.test.ts +207 -0
  429. package/src/__tests__/transform-hierarchy-pixel-diff.dawn.test.ts +36 -28
  430. package/src/__tests__/transient-fields-collect.test.ts +28 -21
  431. package/src/__tests__/transient-runtime-behavior.test.ts +227 -0
  432. package/src/__tests__/transparent-sort-tilemap-sprite-interleave.test.ts +4 -4
  433. package/src/__tests__/variant-selection.unit.test.ts +1 -1
  434. package/src/__tests__/video-extract-bindgroup.dawn.test.ts +89 -136
  435. package/src/__tests__/video-loader-consumption.test.ts +86 -0
  436. package/src/__tests__/video-loader-smoke.dawn.test.ts +60 -0
  437. package/src/__tests__/view-ubo-layout.browser.test.ts +0 -22
  438. package/src/__tests__/world-entity-key.test.ts +1 -1
  439. package/src/__tests__/world-scene-despawn.test.ts +1 -1
  440. package/src/__tests__/world-scene-instantiate.test.ts +2 -36
  441. package/src/__tests__/world-scene-nested.test.ts +1 -1
  442. package/src/__tests__/world-scene-override.test.ts +1 -1
  443. package/src/backend-selection.ts +69 -0
  444. package/src/collect-scene-asset.ts +28 -23
  445. package/src/components/__tests__/camera.test-d.ts +1 -1
  446. package/src/components/__tests__/camera.test.ts +1 -1
  447. package/src/components/__tests__/sprite-animation.test-d.ts +2 -2
  448. package/src/components/__tests__/tile-layer.test-d.ts +1 -1
  449. package/src/components/__tests__/tile-layer.unit.test.ts +2 -2
  450. package/src/createRenderer.ts +24 -36
  451. package/src/errors/environment.ts +1 -1
  452. package/src/index.ts +47 -113
  453. package/src/renderer-host.ts +33 -0
  454. package/src/scene-instances/__tests__/post-spawn-resolve-joints.unit.test.ts +1 -1
  455. package/src/scene-instances/index.ts +4 -0
  456. package/src/scene-utils/mount-override-fold.ts +3 -7
  457. package/src/systems/__tests__/transparent-sort.bench.ts +3 -3
  458. package/src/systems/sprite-animation-tick.ts +1 -1
  459. package/src/systems/transparent-sort.ts +38 -38
  460. package/src/tilemap-register-validate.ts +4 -4
  461. package/dist/__tests__/bind-group-cache-binding.test.d.ts +0 -2
  462. package/dist/__tests__/bind-group-cache-binding.test.d.ts.map +0 -1
  463. package/dist/__tests__/bind-group-cache-frame.test.d.ts +0 -2
  464. package/dist/__tests__/bind-group-cache-frame.test.d.ts.map +0 -1
  465. package/dist/__tests__/dawn/mesh-update.dawn.test.d.ts +0 -2
  466. package/dist/__tests__/dawn/mesh-update.dawn.test.d.ts.map +0 -1
  467. package/dist/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.d.ts +0 -2
  468. package/dist/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.d.ts.map +0 -1
  469. package/dist/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.d.ts +0 -2
  470. package/dist/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.d.ts.map +0 -1
  471. package/dist/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.d.ts +0 -2
  472. package/dist/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.d.ts.map +0 -1
  473. package/dist/__tests__/dispatch-fullscreen-pass-params.unit.test.d.ts +0 -2
  474. package/dist/__tests__/dispatch-fullscreen-pass-params.unit.test.d.ts.map +0 -1
  475. package/dist/__tests__/fog-producer-manifest.d.ts +0 -131
  476. package/dist/__tests__/fog-producer-manifest.d.ts.map +0 -1
  477. package/dist/__tests__/fog-producer-pixel-probe.d.ts +0 -42
  478. package/dist/__tests__/fog-producer-pixel-probe.d.ts.map +0 -1
  479. package/dist/__tests__/fog-producer-pixel.browser.test.d.ts +0 -2
  480. package/dist/__tests__/fog-producer-pixel.browser.test.d.ts.map +0 -1
  481. package/dist/__tests__/fog-producer-pixel.dawn.test.d.ts +0 -2
  482. package/dist/__tests__/fog-producer-pixel.dawn.test.d.ts.map +0 -1
  483. package/dist/__tests__/fog-producer-real-fixture.d.ts +0 -5
  484. package/dist/__tests__/fog-producer-real-fixture.d.ts.map +0 -1
  485. package/dist/__tests__/fog-producer-vfx-effect.d.ts +0 -3
  486. package/dist/__tests__/fog-producer-vfx-effect.d.ts.map +0 -1
  487. package/dist/__tests__/fog-scene-asset.integration.test.d.ts +0 -2
  488. package/dist/__tests__/fog-scene-asset.integration.test.d.ts.map +0 -1
  489. package/dist/__tests__/gpu-resource-store-cubemap-status.test.d.ts +0 -2
  490. package/dist/__tests__/gpu-resource-store-cubemap-status.test.d.ts.map +0 -1
  491. package/dist/__tests__/gpu-resource.test.d.ts +0 -2
  492. package/dist/__tests__/gpu-resource.test.d.ts.map +0 -1
  493. package/dist/__tests__/hdrp-bgl-slots.browser.test.d.ts +0 -2
  494. package/dist/__tests__/hdrp-bgl-slots.browser.test.d.ts.map +0 -1
  495. package/dist/__tests__/hdrp-buffers.unit.test.d.ts +0 -2
  496. package/dist/__tests__/hdrp-buffers.unit.test.d.ts.map +0 -1
  497. package/dist/__tests__/hdrp-execute-filter.unit.test.d.ts +0 -2
  498. package/dist/__tests__/hdrp-execute-filter.unit.test.d.ts.map +0 -1
  499. package/dist/__tests__/hdrp-gbuffer-attachments.browser.test.d.ts +0 -2
  500. package/dist/__tests__/hdrp-gbuffer-attachments.browser.test.d.ts.map +0 -1
  501. package/dist/__tests__/hdrp-pipeline-asset-type.test-d.d.ts +0 -2
  502. package/dist/__tests__/hdrp-pipeline-asset-type.test-d.d.ts.map +0 -1
  503. package/dist/__tests__/hdrp-ssao-boundary.test.d.ts +0 -2
  504. package/dist/__tests__/hdrp-ssao-boundary.test.d.ts.map +0 -1
  505. package/dist/__tests__/hdrp-ssao-falsification.test.d.ts +0 -2
  506. package/dist/__tests__/hdrp-ssao-falsification.test.d.ts.map +0 -1
  507. package/dist/__tests__/helpers/primitive-world.d.ts +0 -8
  508. package/dist/__tests__/helpers/primitive-world.d.ts.map +0 -1
  509. package/dist/__tests__/helpers/render-asset-port.d.ts +0 -15
  510. package/dist/__tests__/helpers/render-asset-port.d.ts.map +0 -1
  511. package/dist/__tests__/helpers/scene-asset-port.d.ts +0 -9
  512. package/dist/__tests__/helpers/scene-asset-port.d.ts.map +0 -1
  513. package/dist/__tests__/material-derived-coordinates.integration.test.d.ts +0 -2
  514. package/dist/__tests__/material-derived-coordinates.integration.test.d.ts.map +0 -1
  515. package/dist/__tests__/pipeline-layout-selection.test.d.ts +0 -2
  516. package/dist/__tests__/pipeline-layout-selection.test.d.ts.map +0 -1
  517. package/dist/__tests__/post-process-reads-narrowing.test-d.d.ts +0 -2
  518. package/dist/__tests__/post-process-reads-narrowing.test-d.d.ts.map +0 -1
  519. package/dist/__tests__/post-process-register-roundtrip.dawn.test.d.ts +0 -2
  520. package/dist/__tests__/post-process-register-roundtrip.dawn.test.d.ts.map +0 -1
  521. package/dist/__tests__/render-feature-zero-feature.browser.test.d.ts +0 -2
  522. package/dist/__tests__/render-feature-zero-feature.browser.test.d.ts.map +0 -1
  523. package/dist/__tests__/render-pipeline-trivial.dawn.test.d.ts +0 -2
  524. package/dist/__tests__/render-pipeline-trivial.dawn.test.d.ts.map +0 -1
  525. package/dist/__tests__/shadow-csm-caster-membership.test.d.ts +0 -2
  526. package/dist/__tests__/shadow-csm-caster-membership.test.d.ts.map +0 -1
  527. package/dist/__tests__/shadow-csm-pssm.test.d.ts +0 -2
  528. package/dist/__tests__/shadow-csm-pssm.test.d.ts.map +0 -1
  529. package/dist/__tests__/shadow-csm-temporal.browser.test.d.ts +0 -2
  530. package/dist/__tests__/shadow-csm-temporal.browser.test.d.ts.map +0 -1
  531. package/dist/__tests__/shadow-csm-viewport.test.d.ts +0 -2
  532. package/dist/__tests__/shadow-csm-viewport.test.d.ts.map +0 -1
  533. package/dist/__tests__/shadow-m2.dawn.test.d.ts +0 -2
  534. package/dist/__tests__/shadow-m2.dawn.test.d.ts.map +0 -1
  535. package/dist/__tests__/shadow-m3-calibrate-run.dawn.test.d.ts +0 -2
  536. package/dist/__tests__/shadow-m3-calibrate-run.dawn.test.d.ts.map +0 -1
  537. package/dist/__tests__/shadow-m3-calibrate.d.ts +0 -83
  538. package/dist/__tests__/shadow-m3-calibrate.d.ts.map +0 -1
  539. package/dist/__tests__/shadow-m3.dawn.test.d.ts +0 -2
  540. package/dist/__tests__/shadow-m3.dawn.test.d.ts.map +0 -1
  541. package/dist/__tests__/shadow-probe-control-flow.dawn.test.d.ts +0 -2
  542. package/dist/__tests__/shadow-probe-control-flow.dawn.test.d.ts.map +0 -1
  543. package/dist/__tests__/shadow-quality-metrics.dawn.test.d.ts +0 -2
  544. package/dist/__tests__/shadow-quality-metrics.dawn.test.d.ts.map +0 -1
  545. package/dist/__tests__/temporal-off-path.unit.test.d.ts +0 -2
  546. package/dist/__tests__/temporal-off-path.unit.test.d.ts.map +0 -1
  547. package/dist/__tests__/video-cache-regression.unit.test.d.ts +0 -2
  548. package/dist/__tests__/video-cache-regression.unit.test.d.ts.map +0 -1
  549. package/dist/asset-kind.d.ts +0 -4
  550. package/dist/asset-kind.d.ts.map +0 -1
  551. package/dist/errors/sprite-animation.d.ts +0 -3
  552. package/dist/errors/sprite-animation.d.ts.map +0 -1
  553. package/dist/scene-asset-port.d.ts +0 -17
  554. package/dist/scene-asset-port.d.ts.map +0 -1
  555. package/dist/scene-collect-errors.d.ts +0 -22
  556. package/dist/scene-collect-errors.d.ts.map +0 -1
  557. package/dist/shadow-m3-calibrate.d.ts +0 -40
  558. package/dist/shadow-m3-calibrate.d.ts.map +0 -1
  559. package/src/__tests__/bind-group-cache-binding.test.ts +0 -2513
  560. package/src/__tests__/bind-group-cache-frame.test.ts +0 -1511
  561. package/src/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.ts +0 -204
  562. package/src/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.ts +0 -297
  563. package/src/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.ts +0 -271
  564. package/src/__tests__/dispatch-fullscreen-pass-params.unit.test.ts +0 -321
  565. package/src/__tests__/fog-producer-manifest.ts +0 -162
  566. package/src/__tests__/fog-producer-pixel-probe.ts +0 -263
  567. package/src/__tests__/fog-producer-pixel.browser.test.ts +0 -26
  568. package/src/__tests__/fog-producer-pixel.dawn.test.ts +0 -55
  569. package/src/__tests__/fog-producer-real-fixture.ts +0 -805
  570. package/src/__tests__/fog-producer-vfx-effect.ts +0 -272
  571. package/src/__tests__/fog-scene-asset.integration.test.ts +0 -123
  572. package/src/__tests__/gpu-resource-store-cubemap-status.test.ts +0 -207
  573. package/src/__tests__/gpu-resource.test.ts +0 -1206
  574. package/src/__tests__/hdrp-bgl-slots.browser.test.ts +0 -50
  575. package/src/__tests__/hdrp-buffers.unit.test.ts +0 -70
  576. package/src/__tests__/hdrp-execute-filter.unit.test.ts +0 -200
  577. package/src/__tests__/hdrp-gbuffer-attachments.browser.test.ts +0 -64
  578. package/src/__tests__/hdrp-pipeline-asset-type.test-d.ts +0 -139
  579. package/src/__tests__/hdrp-ssao-boundary.test.ts +0 -237
  580. package/src/__tests__/hdrp-ssao-falsification.test.ts +0 -289
  581. package/src/__tests__/helpers/primitive-world.ts +0 -91
  582. package/src/__tests__/helpers/render-asset-port.ts +0 -65
  583. package/src/__tests__/helpers/scene-asset-port.ts +0 -23
  584. package/src/__tests__/material-derived-coordinates.integration.test.ts +0 -100
  585. package/src/__tests__/pipeline-layout-selection.test.ts +0 -298
  586. package/src/__tests__/post-process-reads-narrowing.test-d.ts +0 -52
  587. package/src/__tests__/post-process-register-roundtrip.dawn.test.ts +0 -230
  588. package/src/__tests__/render-feature-zero-feature.browser.test.ts +0 -152
  589. package/src/__tests__/render-pipeline-trivial.dawn.test.ts +0 -525
  590. package/src/__tests__/shadow-csm-caster-membership.test.ts +0 -232
  591. package/src/__tests__/shadow-csm-pssm.test.ts +0 -142
  592. package/src/__tests__/shadow-csm-temporal.browser.test.ts +0 -145
  593. package/src/__tests__/shadow-csm-viewport.test.ts +0 -74
  594. package/src/__tests__/shadow-m2.dawn.test.ts +0 -394
  595. package/src/__tests__/shadow-m3-calibrate-run.dawn.test.ts +0 -248
  596. package/src/__tests__/shadow-m3-calibrate.ts +0 -203
  597. package/src/__tests__/shadow-m3.dawn.test.ts +0 -288
  598. package/src/__tests__/shadow-probe-control-flow.dawn.test.ts +0 -264
  599. package/src/__tests__/shadow-quality-metrics.dawn.test.ts +0 -324
  600. package/src/__tests__/temporal-off-path.unit.test.ts +0 -69
  601. package/src/__tests__/video-cache-regression.unit.test.ts +0 -186
  602. package/src/asset-kind.ts +0 -7
  603. package/src/errors/sprite-animation.ts +0 -5
  604. package/src/scene-asset-port.ts +0 -32
  605. package/src/scene-collect-errors.ts +0 -30
  606. package/src/shadow-m3-calibrate.ts +0 -171
@@ -1,525 +0,0 @@
1
- // render-pipeline-trivial.dawn.test.ts
2
- // feat-20260601-customizable-render-pipeline-seam-and-dogfood-rend M2 / w11.
3
- //
4
- // Structured dawn-node smoke for the customizable render-pipeline seam. This single test
5
- // file is BOTH the AC-02 (register + install + run a trivial custom pipeline 300 frames,
6
- // 0 RhiError) AND the AC-03 (install two RenderPipelineAssets sharing ONE logic id but
7
- // differing only in config.passCount, observe perFramePassNames differ + a graph rebuild --
8
- // the genuine one-logic-N-configs proof that config is threaded into buildGraph and is
9
- // NON-no-op; feat-20260601 verify round 2 fixed the seam that formerly dropped config) AND
10
- // the AC-08 proof: the trivial pipeline's buildGraph / execute closures take a `RenderPipelineContext`
11
- // argument and reference ONLY its documented fields. A `ctx.internals` access does NOT
12
- // type-check (the kitchen-sink is gone) - that compile error is the load-bearing AC-08
13
- // oracle, asserted statically below via an `@ts-expect-error` line.
14
- //
15
- // Follows the fxaa-zero-overhead.dawn.test.ts pattern for canvas mock + device capture.
16
-
17
- import { World } from '@forgeax/engine-ecs';
18
- import { createPrimitiveMesh } from '@forgeax/engine-geometry';
19
- import type { RenderPipeline, RenderPipelineContext } from '@forgeax/engine-render/internal';
20
- import { Camera, MeshFilter, MeshRenderer } from '@forgeax/engine-render/internal';
21
- import { Transform } from '@forgeax/engine-scene';
22
- import type { RenderPipelineAsset } from '@forgeax/engine-types';
23
- import { describe, expect, it } from 'vitest';
24
- import { createRenderer } from '../index';
25
- import { drawPublished } from './draw-published';
26
-
27
- const WIDTH = 256;
28
- const HEIGHT = 256;
29
-
30
- const TEXTURE_USAGE_COPY_SRC = 0x01;
31
- const TEXTURE_USAGE_RENDER_ATTACHMENT = 0x10;
32
-
33
- const ENGINE_MANIFEST = await (async () => {
34
- const { buildEngineShaderManifest } = await import('@forgeax/engine-vite-plugin-shader');
35
- return buildEngineShaderManifest();
36
- })();
37
- const ENGINE_MANIFEST_URL = `data:application/json,${encodeURIComponent(
38
- JSON.stringify(ENGINE_MANIFEST),
39
- )}`;
40
-
41
- /**
42
- * Build the trivial custom RenderPipeline. ONE logic id; its topology is sized at
43
- * `buildGraph` time by `data.config?.passCount` (the install-time `RenderPipelineAsset.config`
44
- * threaded through the pipeline seam, feat-20260601 verify round 2). Two `RenderPipelineAsset`s
45
- * sharing this one logic id but differing only in `config.passCount` install to observably
46
- * different `perFramePassNames` (AC-03, one-logic-N-configs).
47
- *
48
- * `data.config?.passCount ?? 1` is the read: missing config defaults to a single pass so a
49
- * config-less install still produces a non-empty frame (AC-02).
50
- *
51
- * AC-08 evidence: every closure below takes a `RenderPipelineContext` and reaches ONLY its
52
- * documented fields (`ctx.encoder`, `ctx.view`, `ctx.runtime.device`, `ctx.frameState`). It
53
- * CANNOT reach `ctx.internals` - that is a compile error (the `@ts-expect-error` test at the
54
- * bottom of this file pins that). Pass 0 clears the swap-chain view to a distinctive green
55
- * so the produced frame is observably non-empty (AC-02); passes 1..N-1 are no-ops. The
56
- * config-driven pass count drives `perFramePassNames` (AC-03).
57
- */
58
- function makeTrivialPipeline(): RenderPipeline {
59
- return {
60
- build({ graph, contributeFeatures }, topology) {
61
- const passCount = topology.config?.passCount ?? 1;
62
- const surface = graph.importTexture(
63
- 'custom-surface',
64
- {
65
- format: topology.surface.storageFormat,
66
- size: 'surface',
67
- usage: TEXTURE_USAGE_COPY_SRC | TEXTURE_USAGE_RENDER_ATTACHMENT,
68
- viewFormats:
69
- topology.surface.storageFormat === topology.surface.viewFormat
70
- ? []
71
- : [topology.surface.viewFormat],
72
- },
73
- (frame) => frame.currentTexture,
74
- );
75
- if (!surface.ok) return surface;
76
- const surfaceView = graph.importView(
77
- surface.value,
78
- { label: 'custom-surface.view', format: topology.surface.viewFormat },
79
- (frame) => frame.view,
80
- );
81
- if (!surfaceView.ok) return surfaceView;
82
- for (let i = 0; i < passCount; i++) {
83
- const added = graph.addRasterPass(`custom-pass-${i}`, {
84
- accesses: [{ resource: surfaceView.value, usage: 'color-attachment' }],
85
- colorAttachments: [
86
- {
87
- view: surfaceView.value,
88
- clearValue: { r: 0, g: 0.6, b: 0, a: 1 },
89
- loadOp: i === 0 ? 'clear' : 'load',
90
- storeOp: 'store',
91
- },
92
- ],
93
- encode: () => undefined,
94
- });
95
- if (!added.ok) return added;
96
- }
97
- return contributeFeatures([]);
98
- },
99
- };
100
- }
101
-
102
- interface DawnHarness {
103
- renderer: Awaited<ReturnType<typeof createRenderer>>;
104
- device: GPUDevice;
105
- renderTarget: GPUTexture;
106
- }
107
-
108
- async function bootDawn(): Promise<DawnHarness | null> {
109
- const dawnAvailable = typeof globalThis.navigator?.gpu?.requestAdapter === 'function';
110
- if (!dawnAvailable) {
111
- throw new Error('dawn-node navigator.gpu not injected; vitest.setup-webgpu.ts regressed');
112
- }
113
- let sharedDevice: GPUDevice | undefined;
114
- const originalRequestAdapter = globalThis.navigator.gpu.requestAdapter.bind(
115
- globalThis.navigator.gpu,
116
- );
117
- globalThis.navigator.gpu.requestAdapter = async (opts) => {
118
- const rawAdapter = await originalRequestAdapter(opts);
119
- if (rawAdapter === null) return rawAdapter;
120
- const originalRequestDevice = rawAdapter.requestDevice.bind(rawAdapter);
121
- rawAdapter.requestDevice = async (desc) => {
122
- const dev = await originalRequestDevice(desc);
123
- if (sharedDevice === undefined) sharedDevice = dev;
124
- return dev;
125
- };
126
- return rawAdapter;
127
- };
128
-
129
- let renderTarget: GPUTexture | undefined;
130
- const ensureRenderTarget = (device: GPUDevice, format: GPUTextureFormat): GPUTexture => {
131
- if (renderTarget !== undefined) return renderTarget;
132
- renderTarget = device.createTexture({
133
- size: { width: WIDTH, height: HEIGHT, depthOrArrayLayers: 1 },
134
- format,
135
- usage: TEXTURE_USAGE_RENDER_ATTACHMENT | TEXTURE_USAGE_COPY_SRC,
136
- viewFormats: ['rgba8unorm-srgb'],
137
- });
138
- return renderTarget;
139
- };
140
- const mockCanvas = {
141
- width: WIDTH,
142
- height: HEIGHT,
143
- getContext(kind: string): unknown {
144
- if (kind !== 'webgpu') return null;
145
- return {
146
- configure(desc: { device: GPUDevice; format?: GPUTextureFormat }) {
147
- ensureRenderTarget(desc.device, desc.format ?? 'rgba8unorm');
148
- },
149
- unconfigure() {},
150
- getCurrentTexture(): GPUTexture {
151
- if (renderTarget === undefined) {
152
- if (sharedDevice === undefined)
153
- throw new Error('render target requested before device captured');
154
- return ensureRenderTarget(sharedDevice, 'rgba8unorm');
155
- }
156
- return renderTarget;
157
- },
158
- };
159
- },
160
- addEventListener() {},
161
- removeEventListener() {},
162
- } as unknown as HTMLCanvasElement;
163
-
164
- let renderer: Awaited<ReturnType<typeof createRenderer>>;
165
- try {
166
- renderer = await createRenderer(mockCanvas, {}, { shaderManifestUrl: ENGINE_MANIFEST_URL });
167
- } finally {
168
- globalThis.navigator.gpu.requestAdapter = originalRequestAdapter;
169
- }
170
- expect(renderer.backend).toBe('webgpu');
171
- const ready = await renderer.ready;
172
- expect(ready.ok).toBe(true);
173
- if (!ready.ok) return null;
174
- if (sharedDevice === undefined) {
175
- throw new Error('dawn device never captured through requestDevice shim');
176
- }
177
- // Create the swap-chain render target eagerly. The mock canvas creates it lazily inside
178
- // getCurrentTexture(), which the first renderer.draw() triggers - but bootDawn returns
179
- // before any draw, so without this eager creation renderTarget stays undefined and the
180
- // harness would (formerly) return null, making the AC-02/AC-03 tests no-op (vacuous green).
181
- const target = ensureRenderTarget(sharedDevice, 'rgba8unorm');
182
- return { renderer, device: sharedDevice, renderTarget: target };
183
- }
184
-
185
- function spawnCubeScene(world: World): void {
186
- const cubeHandle = world.internSharedRef('MeshAsset', createPrimitiveMesh('cube').unwrap());
187
- world.spawn(
188
- {
189
- component: Transform,
190
- data: {
191
- pos: [0, 0, 0],
192
- quat: [0, 0, 0, 1],
193
- scale: [1, 1, 1],
194
- },
195
- },
196
- { component: MeshFilter, data: { assetHandle: cubeHandle } },
197
- { component: MeshRenderer, data: {} },
198
- );
199
- world.spawn(
200
- {
201
- component: Transform,
202
- data: {
203
- pos: [0, 0, 3],
204
- quat: [0, 0, 0, 1],
205
- scale: [1, 1, 1],
206
- },
207
- },
208
- { component: Camera, data: { fov: Math.PI / 4, aspect: 1, near: 0.1, far: 100 } },
209
- );
210
- }
211
-
212
- describe('feat-20260601 M2 w11: customizable render pipeline (dawn)', () => {
213
- it('AC-02: register + install a trivial custom pipeline, draw 300 frames, 0 RhiError', async () => {
214
- const harness = await bootDawn();
215
- if (harness === null) return;
216
- const { renderer, device } = harness;
217
-
218
- let rhiErrors = 0;
219
- renderer.onError(() => {
220
- rhiErrors++;
221
- });
222
-
223
- renderer.registerPipeline('test::trivial', makeTrivialPipeline());
224
- const installed = renderer.installPipeline({
225
- kind: 'render-pipeline',
226
- pipelineId: 'test::trivial',
227
- config: { passCount: 1 },
228
- });
229
- expect(installed.ok).toBe(true);
230
-
231
- const world = new World();
232
- spawnCubeScene(world);
233
-
234
- for (let f = 0; f < 300; f++) {
235
- const drawn = drawPublished(renderer, world);
236
- expect(drawn.ok).toBe(true);
237
- }
238
- await device.queue.onSubmittedWorkDone();
239
-
240
- // AC-02: zero structured RhiError across 300 frames.
241
- expect(rhiErrors).toBe(0);
242
- // AC-02 non-empty frame proof: the custom pipeline drove the per-frame graph and the
243
- // declared pass set is present (falsification anchor: a buildGraph -> null returns an
244
- // empty perFramePassNames array, which would fail this assertion).
245
- expect(renderer.perFramePassNames).toEqual(['custom-pass-0']);
246
- });
247
-
248
- it('AC-03: ONE logic id + two configs (passCount 1 vs 2) rebuilds the graph + changes perFramePassNames', async () => {
249
- const harness = await bootDawn();
250
- if (harness === null) return;
251
- const { renderer, device } = harness;
252
-
253
- let rhiErrors = 0;
254
- renderer.onError(() => {
255
- rhiErrors++;
256
- });
257
-
258
- // ONE logic id. The config-driven difference is genuine (not faked by two closures): the
259
- // trivial pipeline's buildGraph reads `data.config?.passCount` (the install-time config
260
- // threaded through the seam). Two assets share this single logic id and differ ONLY in
261
- // config.passCount.
262
- renderer.registerPipeline('test::trivial', makeTrivialPipeline());
263
-
264
- const assetA: RenderPipelineAsset = {
265
- kind: 'render-pipeline',
266
- pipelineId: 'test::trivial',
267
- config: { passCount: 1 },
268
- };
269
- const assetB: RenderPipelineAsset = {
270
- kind: 'render-pipeline',
271
- pipelineId: 'test::trivial',
272
- config: { passCount: 2 },
273
- };
274
-
275
- const world = new World();
276
- spawnCubeScene(world);
277
-
278
- // Install A (config.passCount=1) + draw -> one custom pass.
279
- expect(renderer.installPipeline(assetA).ok).toBe(true);
280
- expect(drawPublished(renderer, world).ok).toBe(true);
281
- const passesAfterA = [...renderer.perFramePassNames];
282
-
283
- // Install B (same logic id, config.passCount=2) + draw -> the install bumps the
284
- // install-epoch brand-number, forcing a rebuild; buildGraph then reads the new
285
- // config and declares two passes. This is the falsifiable proof that config is NON-no-op:
286
- // if installPipeline dropped config (the verify-round-1 defect) passesAfterB would equal
287
- // passesAfterA and the assertion below would fail.
288
- expect(renderer.installPipeline(assetB).ok).toBe(true);
289
- expect(drawPublished(renderer, world).ok).toBe(true);
290
- const passesAfterB = [...renderer.perFramePassNames];
291
-
292
- await device.queue.onSubmittedWorkDone();
293
-
294
- // AC-03 (a)+(b): same logic id, the graph rebuilt (different pass set) and the
295
- // config-driven pass count is observable through perFramePassNames.
296
- expect(passesAfterA).toEqual(['custom-pass-0']);
297
- expect(passesAfterB).toEqual(['custom-pass-0', 'custom-pass-1']);
298
- expect(passesAfterA).not.toEqual(passesAfterB);
299
- // AC-03 (c): 0 RhiError across both installs + draws.
300
- expect(rhiErrors).toBe(0);
301
- });
302
-
303
- it('AC-08: a custom pipeline closure cannot reach ctx.internals (compile-time oracle)', () => {
304
- // The load-bearing AC-08 proof is static: the kitchen-sink `internals` field is GONE
305
- // from RenderPipelineContext. The line below MUST fail to type-check; if a future
306
- // change re-adds `internals` to the public ctx, the `@ts-expect-error` becomes unused
307
- // and tsc fails the build - turning this into a falsifiable guard.
308
- const probe = (ctx: RenderPipelineContext): unknown =>
309
- // @ts-expect-error - ctx.internals is intentionally unreachable (AC-08 oracle)
310
- ctx.internals;
311
- // The clean named surfaces ARE reachable (no error expected).
312
- const probeClean = (ctx: RenderPipelineContext): unknown => [
313
- ctx.assets,
314
- ctx.store,
315
- ctx.pipelineState,
316
- ctx.runtime,
317
- ];
318
- expect(typeof probe).toBe('function');
319
- expect(typeof probeClean).toBe('function');
320
- });
321
-
322
- // feat-20260604-resource-owning-render-graph-and-fullscreen-postpr M3 / w17:
323
- // AC-11 (addScenePass primitive) + AC-17 (end-to-end scene -> graph-owned RT
324
- // -> fullscreen post-process readback). The trivial pipeline above only clears
325
- // the swap-chain; below proves `g.addColorTarget` + `g.addScenePass` +
326
- // `g.addFullscreenPass` form the public vocabulary an AI user pipeline uses.
327
- //
328
- // The urp pipeline is exercised through createRenderer's default
329
- // install — one frame with a non-empty scene must read back non-clear pixels
330
- // through every pass (geometry, tonemap, fxaa). Without addScenePass /
331
- // addFullscreenPass actually drawing the scene into the graph-owned RT and
332
- // composing into the swap-chain, the readback would equal the clear colour —
333
- // which the falsify test below asserts when no scene is spawned.
334
- it('AC-11/17: urp addScenePass + addFullscreenPass renders scene non-empty', async () => {
335
- const harness = await bootDawn();
336
- if (harness === null) return;
337
- const { renderer, device, renderTarget } = harness;
338
-
339
- let rhiErrors = 0;
340
- renderer.onError(() => {
341
- rhiErrors++;
342
- });
343
-
344
- const world = new World();
345
- spawnCubeScene(world);
346
-
347
- // Drive a single frame through the default pipeline (forgeax::urp),
348
- // which after M3 is rewritten on top of addColorTarget / addScenePass /
349
- // addFullscreenPass. The end-to-end signature is observable through pixel
350
- // readback + perFramePassNames.
351
- expect(drawPublished(renderer, world).ok).toBe(true);
352
- await device.queue.onSubmittedWorkDone();
353
-
354
- // AC-15 / R-PERFPASS: the urp pass names are preserved post-rewrite.
355
- // perFramePassNames is the machine-readable proof that buildGraph still
356
- // declares the canonical chain after switching to the public vocabulary.
357
- //
358
- // feat-20260613-csm M6 / w22: the legacy 'shadow' pass is now N
359
- // independent 'shadowCascade<i>' passes (one per cascade tile in the
360
- // atlas, D-4). Without DirectionalLight with castShadow the urp falls back to
361
- // cascadeCount=1 -> a single 'shadowCascade0' pass.
362
- //
363
- // Point-shadow work and bloom passes are topology-owned: zero point
364
- // shadows and bloom=off do not declare dead GPU passes. The spot atlas is
365
- // still cleared once because the main View binding always samples it.
366
- const expectedPassNames = [
367
- 'directional-shadow-reset',
368
- 'shadowCascade0',
369
- 'directional-shadow-observation',
370
- 'spot-shadow',
371
- 'skybox',
372
- 'main',
373
- 'linear-hdr-observation',
374
- 'output',
375
- 'debug-overlay',
376
- ];
377
- const passNames = renderer.perFramePassNames;
378
- expect(passNames).toHaveLength(expectedPassNames.length);
379
- expect(passNames).toEqual(expect.arrayContaining(expectedPassNames));
380
- const passIndex = (name: string) => passNames.indexOf(name);
381
- expect(passIndex('directional-shadow-reset')).toBeLessThan(passIndex('shadowCascade0'));
382
- expect(passIndex('shadowCascade0')).toBeLessThan(passIndex('directional-shadow-observation'));
383
- expect(passIndex('directional-shadow-observation')).toBeLessThan(passIndex('main'));
384
-
385
- // AC-17: read back the swap-chain texture. The cube scene clears to
386
- // (0.06, 0.06, 0.08) and renders an unlit cube + camera; the readback must
387
- // contain at least one pixel that differs from the clear colour. If
388
- // addScenePass / addFullscreenPass were no-ops (the falsifiable case), the
389
- // entire readback would equal the clear colour and this assertion would
390
- // fail.
391
- const bytesPerRow = Math.ceil((WIDTH * 4) / 256) * 256;
392
- const readback = device.createBuffer({
393
- size: bytesPerRow * HEIGHT,
394
- usage: 0x09, // GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST
395
- });
396
- const cmd = device.createCommandEncoder();
397
- cmd.copyTextureToBuffer(
398
- { texture: renderTarget, mipLevel: 0, origin: { x: 0, y: 0, z: 0 } },
399
- { buffer: readback, bytesPerRow, rowsPerImage: HEIGHT },
400
- { width: WIDTH, height: HEIGHT, depthOrArrayLayers: 1 },
401
- );
402
- device.queue.submit([cmd.finish()]);
403
- await readback.mapAsync(1); // GPUMapMode.READ
404
- const view = new Uint8Array(readback.getMappedRange().slice(0));
405
- readback.unmap();
406
- readback.destroy();
407
-
408
- // Clear colour (0.06, 0.06, 0.08, 1.0) → sRGB-encoded ~ (69, 69, 80) in
409
- // bgra8unorm-srgb. Find pixels whose channel sum differs from clear by >40
410
- // (a comfortable threshold for tonemap/fxaa rounding while still proving
411
- // the scene drew non-clear content).
412
- const CLEAR_B = 80;
413
- const CLEAR_G = 69;
414
- const CLEAR_R = 69;
415
- let nonClearPixels = 0;
416
- for (let y = 0; y < HEIGHT; y++) {
417
- for (let x = 0; x < WIDTH; x++) {
418
- const off = y * bytesPerRow + x * 4;
419
- const b = view[off];
420
- const g = view[off + 1];
421
- const r = view[off + 2];
422
- if (b === undefined || g === undefined || r === undefined) continue;
423
- const delta = Math.abs(b - CLEAR_B) + Math.abs(g - CLEAR_G) + Math.abs(r - CLEAR_R);
424
- if (delta > 40) nonClearPixels++;
425
- }
426
- }
427
- // AC-17 readback assertion: at least 1% of pixels must differ from the
428
- // clear colour (a cube + camera fills ~15-30% of the frame; 1% is a very
429
- // conservative lower bound that still proves the chain end-to-end).
430
- expect(nonClearPixels).toBeGreaterThan(WIDTH * HEIGHT * 0.01);
431
- expect(rhiErrors).toBe(0);
432
- });
433
-
434
- it('AC-17 falsify: empty scene reads back clear colour (proves end-to-end has discriminating power)', async () => {
435
- // Falsification anchor for the AC-17 readback above. If the previous test
436
- // passed only because of leftover GPU state or a dawn quirk (not because
437
- // addScenePass actually drew the scene), this test would also see
438
- // non-clear pixels — it doesn't, because spawning no renderables means
439
- // every pass clears or no-ops, leaving the swap-chain at the clear colour.
440
- const harness = await bootDawn();
441
- if (harness === null) return;
442
- const { renderer, device, renderTarget } = harness;
443
-
444
- let rhiErrors = 0;
445
- renderer.onError(() => {
446
- rhiErrors++;
447
- });
448
-
449
- const world = new World();
450
- // Camera only; NO MeshFilter / MeshRenderer (no draw calls in scene pass).
451
- world.spawn(
452
- {
453
- component: Transform,
454
- data: {
455
- pos: [0, 0, 3],
456
- quat: [0, 0, 0, 1],
457
- scale: [1, 1, 1],
458
- },
459
- },
460
- // feat-20260608 sibling-collateral: clearColor moved off RendererOptions
461
- // to the Camera schema (one inline array<f32,4> column as of
462
- // feat-20260709 M3); explicit values keep this falsify discriminator
463
- // stable across the surface-trim cut.
464
- {
465
- component: Camera,
466
- data: {
467
- fov: Math.PI / 4,
468
- aspect: 1,
469
- near: 0.1,
470
- far: 100,
471
- clearColor: [69 / 255, 69 / 255, 80 / 255, 1],
472
- },
473
- },
474
- );
475
-
476
- expect(drawPublished(renderer, world).ok).toBe(true);
477
- await device.queue.onSubmittedWorkDone();
478
-
479
- const bytesPerRow = Math.ceil((WIDTH * 4) / 256) * 256;
480
- const readback = device.createBuffer({
481
- size: bytesPerRow * HEIGHT,
482
- usage: 0x09, // GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST
483
- });
484
- const cmd = device.createCommandEncoder();
485
- cmd.copyTextureToBuffer(
486
- { texture: renderTarget, mipLevel: 0, origin: { x: 0, y: 0, z: 0 } },
487
- { buffer: readback, bytesPerRow, rowsPerImage: HEIGHT },
488
- { width: WIDTH, height: HEIGHT, depthOrArrayLayers: 1 },
489
- );
490
- device.queue.submit([cmd.finish()]);
491
- await readback.mapAsync(1); // GPUMapMode.READ
492
- const view = new Uint8Array(readback.getMappedRange().slice(0));
493
- readback.unmap();
494
- readback.destroy();
495
-
496
- // With NO renderables, every pixel should be the clear colour — proving
497
- // the AC-17 readback test has discriminating power: a regression that
498
- // dropped scene-draw entirely would surface as "the AC-17 test sees the
499
- // same clear-only output this test sees".
500
- // feat-20260608 sibling-collateral: clear color is gamma-encoded by the
501
- // srgb output view (bgra8unorm-srgb view over bgra8unorm storage), so
502
- // clearR=clearG=69/255 (=0.27 linear) reads back as ~142 (=0.557 in srgb
503
- // encoding); clearB=80/255 (=0.314 linear) reads back as ~152.
504
- const CLEAR_B = 152;
505
- const CLEAR_G = 142;
506
- const CLEAR_R = 142;
507
- let nonClearPixels = 0;
508
- for (let y = 0; y < HEIGHT; y++) {
509
- for (let x = 0; x < WIDTH; x++) {
510
- const off = y * bytesPerRow + x * 4;
511
- const b = view[off];
512
- const g = view[off + 1];
513
- const r = view[off + 2];
514
- if (b === undefined || g === undefined || r === undefined) continue;
515
- const delta = Math.abs(b - CLEAR_B) + Math.abs(g - CLEAR_G) + Math.abs(r - CLEAR_R);
516
- if (delta > 40) nonClearPixels++;
517
- }
518
- }
519
- // Conservative bound: <0.5% of pixels may stray from the clear colour
520
- // (FXAA edge softening across the 0-pixel boundary, etc.). The difference
521
- // with AC-17 above (>1% non-clear) is the discriminating signal.
522
- expect(nonClearPixels).toBeLessThan(WIDTH * HEIGHT * 0.005);
523
- expect(rhiErrors).toBe(0);
524
- });
525
- });