@forgeax/engine-render 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 (918) hide show
  1. package/README.md +130 -641
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/__tests__/device-scope-lifecycle.unit.test.d.ts +2 -0
  4. package/dist/__tests__/device-scope-lifecycle.unit.test.d.ts.map +1 -0
  5. package/dist/__tests__/device-scope-stale-matrix.unit.test.d.ts +2 -0
  6. package/dist/__tests__/device-scope-stale-matrix.unit.test.d.ts.map +1 -0
  7. package/dist/__tests__/fullscreen-feature-plan.unit.test.d.ts +2 -0
  8. package/dist/__tests__/fullscreen-feature-plan.unit.test.d.ts.map +1 -0
  9. package/dist/__tests__/gpu-driven-indirect-raster-evidence.d.ts.map +1 -1
  10. package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts +6 -0
  11. package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts.map +1 -1
  12. package/dist/{gpu-driven/view-reference.d.ts → __tests__/gpu-driven-view-reference.d.ts} +4 -4
  13. package/dist/__tests__/gpu-driven-view-reference.d.ts.map +1 -0
  14. package/dist/__tests__/gpu-scene-render-graph-gpu.d.ts.map +1 -1
  15. package/dist/__tests__/ibl/face-uniforms.unit.test.d.ts +2 -0
  16. package/dist/__tests__/ibl/face-uniforms.unit.test.d.ts.map +1 -0
  17. package/dist/__tests__/morph-feature-plan.unit.test.d.ts +2 -0
  18. package/dist/__tests__/morph-feature-plan.unit.test.d.ts.map +1 -0
  19. package/dist/__tests__/render-feature-plan.test-d.d.ts +2 -0
  20. package/dist/__tests__/render-feature-plan.test-d.d.ts.map +1 -0
  21. package/dist/__tests__/render-feature-plan.unit.test.d.ts +2 -0
  22. package/dist/__tests__/render-feature-plan.unit.test.d.ts.map +1 -0
  23. package/dist/__tests__/ssao-config.unit.test.d.ts +2 -0
  24. package/dist/__tests__/ssao-config.unit.test.d.ts.map +1 -0
  25. package/dist/__tests__/standard-clustered-pipeline.unit.test.d.ts +2 -0
  26. package/dist/__tests__/standard-clustered-pipeline.unit.test.d.ts.map +1 -0
  27. package/dist/__tests__/standard-descriptors.test-d.d.ts +2 -0
  28. package/dist/__tests__/standard-descriptors.test-d.d.ts.map +1 -0
  29. package/dist/__tests__/standard-pipeline.dawn.test.d.ts +2 -0
  30. package/dist/__tests__/standard-pipeline.dawn.test.d.ts.map +1 -0
  31. package/dist/__tests__/standard-pipeline.integration.test.d.ts +2 -0
  32. package/dist/__tests__/standard-pipeline.integration.test.d.ts.map +1 -0
  33. package/dist/__tests__/standard-profile-oracle.unit.test.d.ts +2 -0
  34. package/dist/__tests__/standard-profile-oracle.unit.test.d.ts.map +1 -0
  35. package/dist/__tests__/visibility-resource-short-circuit.unit.test.d.ts +2 -0
  36. package/dist/__tests__/visibility-resource-short-circuit.unit.test.d.ts.map +1 -0
  37. package/dist/{renderer/backend-selection.d.ts → assembly/backend-contract.d.ts} +15 -4
  38. package/dist/assembly/backend-contract.d.ts.map +1 -0
  39. package/dist/assembly/factory.d.ts +207 -0
  40. package/dist/assembly/factory.d.ts.map +1 -0
  41. package/dist/assembly/host-contract.d.ts +84 -0
  42. package/dist/assembly/host-contract.d.ts.map +1 -0
  43. package/dist/{renderer → assembly}/material/assembly.d.ts +1 -2
  44. package/dist/{renderer → assembly}/material/assembly.d.ts.map +1 -1
  45. package/dist/assembly/material/pipeline-projection.d.ts +30 -0
  46. package/dist/assembly/material/pipeline-projection.d.ts.map +1 -0
  47. package/dist/authoring.d.ts +10 -11
  48. package/dist/authoring.d.ts.map +1 -1
  49. package/dist/authoring.mjs +25 -3
  50. package/dist/authoring.mjs.map +1 -1
  51. package/dist/chunk-CQXZC5XI.mjs +182 -0
  52. package/dist/chunk-CQXZC5XI.mjs.map +1 -0
  53. package/dist/chunk-QC4VW3XJ.mjs +79 -0
  54. package/dist/chunk-QC4VW3XJ.mjs.map +1 -0
  55. package/dist/chunk-SCRSAK5B.mjs +480 -0
  56. package/dist/chunk-SCRSAK5B.mjs.map +1 -0
  57. package/dist/components/__tests__/schema-contract.unit.test.d.ts +2 -0
  58. package/dist/components/__tests__/schema-contract.unit.test.d.ts.map +1 -0
  59. package/dist/components/glyph-text.d.ts +1 -1
  60. package/dist/components/glyph-text.d.ts.map +1 -1
  61. package/dist/components/index.d.ts +2 -2
  62. package/dist/components/index.d.ts.map +1 -1
  63. package/dist/components/instances.d.ts +1 -1
  64. package/dist/components/instances.d.ts.map +1 -1
  65. package/dist/components/light-helpers.d.ts +1 -1
  66. package/dist/components/light-helpers.d.ts.map +1 -1
  67. package/dist/components/mesh-filter.d.ts +7 -7
  68. package/dist/components/mesh-filter.d.ts.map +1 -1
  69. package/dist/components/scene-instance.d.ts +11 -11
  70. package/dist/components/skybox-background.d.ts +56 -0
  71. package/dist/components/skybox-background.d.ts.map +1 -0
  72. package/dist/components/skylight.d.ts +55 -0
  73. package/dist/components/skylight.d.ts.map +1 -0
  74. package/dist/components/sprite-animation.d.ts +2 -3
  75. package/dist/components/sprite-animation.d.ts.map +1 -1
  76. package/dist/components/sprite-instances.d.ts +1 -1
  77. package/dist/components/sprite-playback-mode.d.ts +6 -1
  78. package/dist/components/sprite-playback-mode.d.ts.map +1 -1
  79. package/dist/components/sprite-region-override.d.ts +2 -3
  80. package/dist/components/sprite-region-override.d.ts.map +1 -1
  81. package/dist/components/tile-layer.d.ts +5 -0
  82. package/dist/components/tile-layer.d.ts.map +1 -1
  83. package/dist/construct-renderer.d.ts +18 -1
  84. package/dist/construct-renderer.d.ts.map +1 -1
  85. package/dist/construct-renderer.mjs +27008 -4
  86. package/dist/construct-renderer.mjs.map +1 -1
  87. package/dist/debug-draw-glue.d.ts +2 -53
  88. package/dist/debug-draw-glue.d.ts.map +1 -1
  89. package/dist/device/device-scope.d.ts +83 -0
  90. package/dist/device/device-scope.d.ts.map +1 -0
  91. package/dist/{gpu-resource-store.d.ts → device/gpu-residency.d.ts} +91 -48
  92. package/dist/device/gpu-residency.d.ts.map +1 -0
  93. package/dist/device/resource-types.d.ts +8 -0
  94. package/dist/device/resource-types.d.ts.map +1 -0
  95. package/dist/engine-metrics.d.ts +2 -2
  96. package/dist/engine-metrics.d.ts.map +1 -1
  97. package/dist/errors/recover.d.ts +28 -1
  98. package/dist/errors/recover.d.ts.map +1 -1
  99. package/dist/errors/render.d.ts +249 -258
  100. package/dist/errors/render.d.ts.map +1 -1
  101. package/dist/features/fullscreen.d.ts +19 -0
  102. package/dist/features/fullscreen.d.ts.map +1 -0
  103. package/dist/features/host.d.ts +32 -26
  104. package/dist/features/host.d.ts.map +1 -1
  105. package/dist/features/morph/morph-feature.d.ts +39 -5
  106. package/dist/features/morph/morph-feature.d.ts.map +1 -1
  107. package/dist/features/plan.d.ts +182 -0
  108. package/dist/features/plan.d.ts.map +1 -0
  109. package/dist/features/prepared-gpu-work.d.ts +21 -17
  110. package/dist/features/prepared-gpu-work.d.ts.map +1 -1
  111. package/dist/features/prepared-graphics-store.d.ts +2 -1
  112. package/dist/features/prepared-graphics-store.d.ts.map +1 -1
  113. package/dist/features/prepared-graphics.d.ts +11 -21
  114. package/dist/features/prepared-graphics.d.ts.map +1 -1
  115. package/dist/features/render-graph-compute.d.ts +2 -2
  116. package/dist/features/render-graph-compute.d.ts.map +1 -1
  117. package/dist/features/render-graph-contribution.d.ts +4 -7
  118. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  119. package/dist/features/render-graph-raster.d.ts +2 -2
  120. package/dist/features/render-graph-raster.d.ts.map +1 -1
  121. package/dist/features/render-graph-resources.d.ts +6 -6
  122. package/dist/features/render-graph-resources.d.ts.map +1 -1
  123. package/dist/features/targets.d.ts +5 -5
  124. package/dist/features/targets.d.ts.map +1 -1
  125. package/dist/features/types.d.ts +11 -190
  126. package/dist/features/types.d.ts.map +1 -1
  127. package/dist/features/vocabulary.d.ts +14 -0
  128. package/dist/features/vocabulary.d.ts.map +1 -0
  129. package/dist/fullscreen-post-process-pass.d.ts +4 -25
  130. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  131. package/dist/glyph-text-layout-system.d.ts +3 -2
  132. package/dist/glyph-text-layout-system.d.ts.map +1 -1
  133. package/dist/gpu-driven/batch-topology.d.ts +6 -75
  134. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  135. package/dist/gpu-driven/production-raster.d.ts +13 -112
  136. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  137. package/dist/gpu-driven/view-gpu.d.ts +10 -66
  138. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  139. package/dist/gpu-resource.d.ts +3 -3
  140. package/dist/gpu-scene-schema.d.ts +1 -94
  141. package/dist/gpu-scene-schema.d.ts.map +1 -1
  142. package/dist/gpu-scene.d.ts +7 -33
  143. package/dist/gpu-scene.d.ts.map +1 -1
  144. package/dist/hdrp-buffers.d.ts +3 -53
  145. package/dist/hdrp-buffers.d.ts.map +1 -1
  146. package/dist/ibl/IblPipelineCache.d.ts +74 -180
  147. package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
  148. package/dist/ibl/skylight-bind-group.d.ts +1 -1
  149. package/dist/index.d.ts +13 -43
  150. package/dist/index.d.ts.map +1 -1
  151. package/dist/index.mjs +165 -3
  152. package/dist/index.mjs.map +1 -1
  153. package/dist/inspection-types.d.ts +69 -0
  154. package/dist/inspection-types.d.ts.map +1 -0
  155. package/dist/instance-buffer-cache.d.ts +1 -4
  156. package/dist/instance-buffer-cache.d.ts.map +1 -1
  157. package/dist/internal.d.ts +1 -73
  158. package/dist/internal.d.ts.map +1 -1
  159. package/dist/internal.mjs +1 -43
  160. package/dist/internal.mjs.map +1 -1
  161. package/dist/lifecycle.d.ts +36 -2
  162. package/dist/lifecycle.d.ts.map +1 -1
  163. package/dist/materials.d.ts +0 -3
  164. package/dist/materials.d.ts.map +1 -1
  165. package/dist/mesh-material-bindings.d.ts +0 -1
  166. package/dist/mesh-material-bindings.d.ts.map +1 -1
  167. package/dist/pbr-pipeline.d.ts +75 -29
  168. package/dist/pbr-pipeline.d.ts.map +1 -1
  169. package/dist/pipeline/standard-forward-lane.d.ts +5 -0
  170. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -0
  171. package/dist/pipeline/standard-pipeline.d.ts +31 -0
  172. package/dist/pipeline/standard-pipeline.d.ts.map +1 -0
  173. package/dist/pipeline/standard-profile.d.ts +40 -0
  174. package/dist/pipeline/standard-profile.d.ts.map +1 -0
  175. package/dist/pipeline-builder.d.ts +3 -3
  176. package/dist/pipeline-builder.d.ts.map +1 -1
  177. package/dist/pipeline-spec-types.d.ts +24 -0
  178. package/dist/pipeline-spec-types.d.ts.map +1 -0
  179. package/dist/pipeline-spec.d.ts +16 -155
  180. package/dist/pipeline-spec.d.ts.map +1 -1
  181. package/dist/plugin.d.ts +1 -14
  182. package/dist/plugin.d.ts.map +1 -1
  183. package/dist/post-process-errors.d.ts +18 -18
  184. package/dist/post-process-errors.d.ts.map +1 -1
  185. package/dist/prepare/prepared-graphics-resolver.d.ts +2 -5
  186. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  187. package/dist/record/__tests__/typed-frame-graph-plan.unit.test.d.ts +2 -0
  188. package/dist/record/__tests__/typed-frame-graph-plan.unit.test.d.ts.map +1 -0
  189. package/dist/record/frame-lighting.d.ts +7 -73
  190. package/dist/record/frame-lighting.d.ts.map +1 -1
  191. package/dist/record/frame-snapshot.d.ts +44 -44
  192. package/dist/record/frame-snapshot.d.ts.map +1 -1
  193. package/dist/record/frame-targets.d.ts +5 -38
  194. package/dist/record/frame-targets.d.ts.map +1 -1
  195. package/dist/record/frame.d.ts +64 -52
  196. package/dist/record/frame.d.ts.map +1 -1
  197. package/dist/record/helpers.d.ts +3 -2
  198. package/dist/record/helpers.d.ts.map +1 -1
  199. package/dist/record/main-pass-geometry.d.ts +5 -4
  200. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  201. package/dist/record/main-pass-material.d.ts +90 -59
  202. package/dist/record/main-pass-material.d.ts.map +1 -1
  203. package/dist/record/main-pass-sprite-draws.d.ts +28 -3
  204. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  205. package/dist/record/main-pass.d.ts +1 -1
  206. package/dist/record/main-pass.d.ts.map +1 -1
  207. package/dist/record/mesh-ssbo.d.ts +276 -3
  208. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  209. package/dist/record/render-context.d.ts +235 -0
  210. package/dist/record/render-context.d.ts.map +1 -0
  211. package/dist/record/shadow-pass.d.ts +15 -88
  212. package/dist/record/shadow-pass.d.ts.map +1 -1
  213. package/dist/record/skybox-post-pass.d.ts +1 -1
  214. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  215. package/dist/record/typed-frame-graph.d.ts +29 -7
  216. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  217. package/dist/record/view-ubo.d.ts +3 -3
  218. package/dist/record/view-ubo.d.ts.map +1 -1
  219. package/dist/render-contract.d.ts +416 -0
  220. package/dist/render-contract.d.ts.map +1 -0
  221. package/dist/render-data.d.ts.map +1 -1
  222. package/dist/render-graph-primitives.d.ts +14 -362
  223. package/dist/render-graph-primitives.d.ts.map +1 -1
  224. package/dist/render-pipeline.d.ts +25 -64
  225. package/dist/render-pipeline.d.ts.map +1 -1
  226. package/dist/render-system-extract.d.ts +107 -338
  227. package/dist/render-system-extract.d.ts.map +1 -1
  228. package/dist/render-system.d.ts +21 -713
  229. package/dist/render-system.d.ts.map +1 -1
  230. package/dist/scene/render-scene-types.d.ts +58 -0
  231. package/dist/scene/render-scene-types.d.ts.map +1 -0
  232. package/dist/scene/render-scene.d.ts +105 -0
  233. package/dist/scene/render-scene.d.ts.map +1 -0
  234. package/dist/scene-instances/post-spawn-resolve-joints.d.ts +2 -5
  235. package/dist/scene-instances/post-spawn-resolve-joints.d.ts.map +1 -1
  236. package/dist/ssao-buffers.d.ts +22 -3
  237. package/dist/ssao-buffers.d.ts.map +1 -1
  238. package/dist/systems/skin-palette-allocator.d.ts +2 -4
  239. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  240. package/dist/systems/skin-palette-types.d.ts +14 -0
  241. package/dist/systems/skin-palette-types.d.ts.map +1 -0
  242. package/dist/systems/transparent-sort-config.d.ts +23 -2
  243. package/dist/systems/transparent-sort-config.d.ts.map +1 -1
  244. package/dist/tilemap-chunk-extract-system.d.ts +4 -3
  245. package/dist/tilemap-chunk-extract-system.d.ts.map +1 -1
  246. package/dist/typed-render-graph-primitives.d.ts +2 -4
  247. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  248. package/dist/typed-shadow-passes.d.ts +3 -3
  249. package/dist/typed-shadow-passes.d.ts.map +1 -1
  250. package/package.json +23 -23
  251. package/src/__tests__/backend-selection-rhi-capture.test-d.ts +1 -1
  252. package/src/__tests__/callback-inference.test-d.ts +6 -3
  253. package/src/__tests__/cluster-grid-default-surface.unit.test.ts +7 -4
  254. package/src/__tests__/construct-renderer-identity.unit.test.ts +15 -2
  255. package/src/__tests__/device-scope-lifecycle.unit.test.ts +151 -0
  256. package/src/__tests__/device-scope-stale-matrix.unit.test.ts +42 -0
  257. package/src/__tests__/direct-extract-consumer-contract.test-d.ts +8 -19
  258. package/src/__tests__/direct-light-snapshot.unit.test.ts +3 -13
  259. package/src/__tests__/factory-contract.integration.test.ts +158 -209
  260. package/src/__tests__/fallback-row-stride-surface.unit.test.ts +1 -4
  261. package/src/__tests__/frame-observation.contract.test.ts +17 -8
  262. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +32 -0
  263. package/src/__tests__/glyph-text-layout-recovery.unit.test.ts +6 -11
  264. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +9 -16
  265. package/src/__tests__/gpu-driven-production.integration.test.ts +32 -205
  266. package/src/__tests__/gpu-driven-scaling.unit.test.ts +4 -7
  267. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +87 -8
  268. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +170 -8
  269. package/src/{gpu-driven/view-reference.ts → __tests__/gpu-driven-view-reference.ts} +4 -3
  270. package/src/__tests__/gpu-driven-view.browser.test.ts +12 -1
  271. package/src/__tests__/gpu-driven-view.dawn.test.ts +12 -1
  272. package/src/__tests__/gpu-driven-view.unit.test.ts +11 -267
  273. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +3 -3
  274. package/src/__tests__/gpu-scene-render-graph-gpu.ts +2 -3
  275. package/src/__tests__/gpu-scene.dawn.test.ts +2 -6
  276. package/src/__tests__/gpu-scene.unit.test.ts +10 -24
  277. package/src/__tests__/ibl/face-uniforms.unit.test.ts +46 -0
  278. package/src/__tests__/infinite-grid-no-vertex-probe.unit.test.ts +34 -66
  279. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +14 -5
  280. package/src/__tests__/light-buffer-layout.unit.test.ts +4 -49
  281. package/src/__tests__/material-cooked-projection.unit.test.ts +2 -51
  282. package/src/__tests__/material-snapshot-mutation.integration.test.ts +10 -15
  283. package/src/__tests__/material-static-dynamic-route.unit.test.ts +4 -23
  284. package/src/__tests__/material-stride-surface.unit.test.ts +2 -2
  285. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +7 -8
  286. package/src/__tests__/morph-culling-reentry.dawn.test.ts +29 -38
  287. package/src/__tests__/morph-feature-gpu-work.integration.test.ts +45 -43
  288. package/src/__tests__/morph-feature-plan.unit.test.ts +53 -0
  289. package/src/__tests__/morph-visual-evidence.integration.test.ts +47 -33
  290. package/src/__tests__/nineslice-handle-surface.unit.test.ts +11 -6
  291. package/src/__tests__/post-process-error-policy-owner.unit.test.ts +6 -13
  292. package/src/__tests__/prepared-graphics-capability.unit.test.ts +6 -81
  293. package/src/__tests__/prepared-graphics-generation.unit.test.ts +3 -17
  294. package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +6 -74
  295. package/src/__tests__/prepared-graphics-resolver.unit.test.ts +1 -3
  296. package/src/__tests__/prepared-graphics-snapshot.unit.test.ts +2 -2
  297. package/src/__tests__/profiler-default-off.test.ts +1 -1
  298. package/src/__tests__/profiler-phase-catalog.test.ts +2 -2
  299. package/src/__tests__/profiler-phase-integration.test.ts +5 -13
  300. package/src/__tests__/profiler-phase-token.test.ts +3 -8
  301. package/src/__tests__/public-surface.test-d.ts +65 -3
  302. package/src/__tests__/recover-error-policy-owner.unit.test.ts +1 -21
  303. package/src/__tests__/render-error-code-owner.test-d.ts +18 -23
  304. package/src/__tests__/render-error-detail-ssot.test-d.ts +0 -95
  305. package/src/__tests__/render-error-exhaustive.test-d.ts +8 -1
  306. package/src/__tests__/render-feature-assembly.test-d.ts +8 -16
  307. package/src/__tests__/render-feature-context.test-d.ts +16 -40
  308. package/src/__tests__/render-feature-contract.test-d.ts +9 -18
  309. package/src/__tests__/render-feature-diagnostics.unit.test.ts +6 -8
  310. package/src/__tests__/render-feature-docs.unit.test.ts +8 -7
  311. package/src/__tests__/render-feature-gpu-work.integration.test.ts +14 -75
  312. package/src/__tests__/render-feature-plan.test-d.ts +161 -0
  313. package/src/__tests__/render-feature-plan.unit.test.ts +170 -0
  314. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +8 -19
  315. package/src/__tests__/render-feature-prepared-errors.test-d.ts +3 -6
  316. package/src/__tests__/render-feature-prepared-graphics-docs.unit.test.ts +10 -71
  317. package/src/__tests__/render-feature-prepared-graphics-isolation.unit.test.ts +11 -61
  318. package/src/__tests__/render-feature-prepared-graphics-negative.test-d.ts +20 -43
  319. package/src/__tests__/render-feature-prepared-graphics.test-d.ts +56 -78
  320. package/src/__tests__/render-feature-public-surface.test-d.ts +6 -24
  321. package/src/__tests__/render-feature-retry.unit.test.ts +7 -48
  322. package/src/__tests__/render-feature-scheduling.unit.test.ts +15 -27
  323. package/src/__tests__/render-feature-stage-failed-policy-owner.unit.test.ts +0 -9
  324. package/src/__tests__/render-feature-stage-fault-recovery.unit.test.ts +19 -109
  325. package/src/__tests__/render-feature-visibility-context.test-d.ts +1 -6
  326. package/src/__tests__/render-feature-visibility-context.unit.test.ts +1 -2
  327. package/src/__tests__/render-feature-zero-work.unit.test.ts +14 -20
  328. package/src/__tests__/render-scene-projection.unit.test.ts +73 -111
  329. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +46 -50
  330. package/src/__tests__/renderer-lifecycle.integration.test.ts +49 -1
  331. package/src/__tests__/shader-stage-surface.unit.test.ts +14 -9
  332. package/src/__tests__/ssao-config.unit.test.ts +36 -0
  333. package/src/__tests__/ssao-kernel-surface.unit.test.ts +4 -5
  334. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +28 -0
  335. package/src/__tests__/standard-descriptors.test-d.ts +22 -0
  336. package/src/__tests__/standard-pipeline.dawn.test.ts +61 -0
  337. package/src/__tests__/standard-pipeline.integration.test.ts +124 -0
  338. package/src/__tests__/standard-profile-oracle.unit.test.ts +62 -0
  339. package/src/__tests__/surface-configuration.unit.test.ts +1 -2
  340. package/src/__tests__/texture-usage-surface.unit.test.ts +3 -6
  341. package/src/__tests__/typed-pipeline-topology.unit.test.ts +40 -206
  342. package/src/__tests__/urp-pipeline-targets.unit.test.ts +1 -11
  343. package/src/__tests__/urp-pipeline.unit.test.ts +2 -2
  344. package/src/__tests__/vertex-color-pipeline.unit.test.ts +10 -2
  345. package/src/__tests__/vertex-layout-consumer.unit.test.ts +1 -1
  346. package/src/__tests__/visibility-diagnostics.integration.test.ts +7 -11
  347. package/src/__tests__/visibility-extract.integration.test.ts +20 -11
  348. package/src/__tests__/visibility-extract.perf.test.ts +66 -32
  349. package/src/__tests__/visibility-feature-dedup.integration.test.ts +2 -4
  350. package/src/__tests__/visibility-hidden-report.unit.test.ts +1 -2
  351. package/src/__tests__/visibility-instances.integration.test.ts +7 -11
  352. package/src/__tests__/visibility-multi-world.integration.test.ts +38 -6
  353. package/src/__tests__/visibility-producer-matrix.integration.test.ts +18 -41
  354. package/src/__tests__/visibility-public-surface.test-d.ts +10 -9
  355. package/src/__tests__/visibility-resolver.unit.test.ts +2 -1
  356. package/src/__tests__/visibility-resource-short-circuit.unit.test.ts +80 -0
  357. package/src/__tests__/visibility-snapshot-contract.unit.test.ts +2 -1
  358. package/src/__tests__/vocabulary.unit.test.ts +1 -1
  359. package/src/assembly/backend-contract.ts +57 -0
  360. package/src/{renderer/renderer-factory.ts → assembly/factory.ts} +1709 -2693
  361. package/src/assembly/host-contract.ts +101 -0
  362. package/src/{renderer → assembly}/material/assembly.ts +1 -3
  363. package/src/assembly/material/pipeline-projection.ts +63 -0
  364. package/src/authoring.ts +14 -22
  365. package/src/components/__tests__/schema-contract.unit.test.ts +10 -0
  366. package/src/components/glyph-text.ts +3 -2
  367. package/src/components/index.ts +7 -9
  368. package/src/components/instances.ts +4 -5
  369. package/src/components/light-helpers.ts +1 -1
  370. package/src/components/mesh-filter.ts +11 -10
  371. package/src/components/post-process-params.ts +3 -3
  372. package/src/components/scene-instance.ts +12 -12
  373. package/src/components/skybox-background.ts +103 -0
  374. package/src/components/{environment.ts → skylight.ts} +2 -111
  375. package/src/components/sprite-animation.ts +3 -4
  376. package/src/components/sprite-instances.ts +2 -2
  377. package/src/components/sprite-playback-mode.ts +7 -1
  378. package/src/components/sprite-region-override.ts +2 -3
  379. package/src/components/tile-layer.ts +8 -2
  380. package/src/construct-renderer.ts +67 -4
  381. package/src/debug-draw-glue.ts +8 -129
  382. package/src/device/device-scope.ts +306 -0
  383. package/src/{gpu-resource-store.ts → device/gpu-residency.ts} +540 -639
  384. package/src/device/resource-types.ts +20 -0
  385. package/src/engine-metrics.ts +12 -19
  386. package/src/errors/recover.ts +45 -3
  387. package/src/errors/render.ts +357 -460
  388. package/src/features/fullscreen.ts +46 -0
  389. package/src/features/host.ts +575 -309
  390. package/src/features/morph/morph-feature.ts +195 -105
  391. package/src/features/plan.ts +447 -0
  392. package/src/features/prepared-gpu-work.ts +72 -15
  393. package/src/features/prepared-graphics-store.ts +20 -6
  394. package/src/features/prepared-graphics.ts +12 -71
  395. package/src/features/render-graph-compute.ts +14 -5
  396. package/src/features/render-graph-contribution.ts +43 -63
  397. package/src/features/render-graph-raster.ts +11 -6
  398. package/src/features/render-graph-resources.ts +25 -23
  399. package/src/features/targets.ts +8 -21
  400. package/src/features/types.ts +39 -227
  401. package/src/features/vocabulary.ts +24 -0
  402. package/src/fullscreen-post-process-pass.ts +14 -57
  403. package/src/glyph-text-layout-system.ts +70 -96
  404. package/src/gpu-driven/batch-topology.ts +24 -202
  405. package/src/gpu-driven/production-raster.ts +93 -1108
  406. package/src/gpu-driven/view-gpu.ts +46 -192
  407. package/src/gpu-resource.ts +4 -4
  408. package/src/gpu-scene-schema.ts +11 -99
  409. package/src/gpu-scene.ts +231 -364
  410. package/src/hdrp-buffers.ts +12 -221
  411. package/src/ibl/IblPipelineCache.ts +471 -711
  412. package/src/ibl/skylight-bind-group.ts +4 -4
  413. package/src/index.ts +58 -217
  414. package/src/inspection-types.ts +76 -0
  415. package/src/instance-buffer-cache.ts +1 -29
  416. package/src/internal.ts +6 -85
  417. package/src/lifecycle.ts +64 -19
  418. package/src/materials.ts +7 -29
  419. package/src/mesh-material-bindings.ts +0 -1
  420. package/src/pbr-pipeline.ts +434 -53
  421. package/src/{urp-pipeline.ts → pipeline/standard-forward-lane.ts} +38 -149
  422. package/src/{hdrp-pipeline.ts → pipeline/standard-pipeline.ts} +221 -191
  423. package/src/pipeline/standard-profile.ts +65 -0
  424. package/src/pipeline-builder.ts +60 -64
  425. package/src/pipeline-spec-types.ts +28 -0
  426. package/src/pipeline-spec.ts +72 -609
  427. package/src/plugin.ts +3 -75
  428. package/src/post-process-errors.ts +31 -33
  429. package/src/prepare/prepared-graphics-resolver.ts +5 -4
  430. package/src/record/__tests__/material-slot-plan.unit.test.ts +1 -33
  431. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +41 -0
  432. package/src/record/__tests__/video-texture-view.unit.test.ts +1 -1
  433. package/src/record/frame-lighting.ts +74 -195
  434. package/src/record/frame-snapshot.ts +45 -60
  435. package/src/record/frame-targets.ts +8 -243
  436. package/src/record/frame.ts +509 -796
  437. package/src/record/helpers.ts +6 -11
  438. package/src/record/main-pass-geometry.ts +106 -147
  439. package/src/record/main-pass-material.ts +517 -190
  440. package/src/record/main-pass-sprite-draws.ts +198 -117
  441. package/src/record/main-pass.ts +162 -143
  442. package/src/record/mesh-ssbo.ts +517 -38
  443. package/src/record/render-context.ts +364 -0
  444. package/src/record/shadow-pass.ts +138 -1838
  445. package/src/record/skybox-post-pass.ts +12 -14
  446. package/src/record/typed-frame-graph.ts +215 -254
  447. package/src/record/view-ubo.ts +6 -37
  448. package/src/render-contract.ts +571 -0
  449. package/src/render-data.ts +3 -3
  450. package/src/render-graph-primitives.ts +76 -851
  451. package/src/render-pipeline.ts +104 -188
  452. package/src/render-system-extract.ts +1048 -1729
  453. package/src/render-system.ts +330 -1957
  454. package/src/scene/render-scene-types.ts +64 -0
  455. package/src/scene/render-scene.ts +1032 -0
  456. package/src/scene-instances/post-spawn-resolve-joints.ts +4 -7
  457. package/src/ssao-buffers.ts +167 -8
  458. package/src/systems/skin-palette-allocator.ts +21 -64
  459. package/src/systems/skin-palette-types.ts +14 -0
  460. package/src/systems/transparent-sort-config.ts +25 -3
  461. package/src/tilemap-chunk-extract-system.ts +53 -70
  462. package/src/typed-render-graph-primitives.ts +35 -24
  463. package/src/typed-shadow-passes.ts +26 -56
  464. package/dist/__tests__/analytic-sky-contract.test.d.ts +0 -2
  465. package/dist/__tests__/analytic-sky-contract.test.d.ts.map +0 -1
  466. package/dist/__tests__/analytic-sky-falsify.test.d.ts +0 -2
  467. package/dist/__tests__/analytic-sky-falsify.test.d.ts.map +0 -1
  468. package/dist/__tests__/assets-runtime-handoff.integration.test.d.ts +0 -2
  469. package/dist/__tests__/assets-runtime-handoff.integration.test.d.ts.map +0 -1
  470. package/dist/__tests__/backend-selection.integration.test.d.ts +0 -2
  471. package/dist/__tests__/backend-selection.integration.test.d.ts.map +0 -1
  472. package/dist/__tests__/camera-temporal.test-d.d.ts +0 -2
  473. package/dist/__tests__/camera-temporal.test-d.d.ts.map +0 -1
  474. package/dist/__tests__/camera-temporal.test.d.ts +0 -2
  475. package/dist/__tests__/camera-temporal.test.d.ts.map +0 -1
  476. package/dist/__tests__/directional-shadow-probe-atlas-layout.unit.test.d.ts +0 -2
  477. package/dist/__tests__/directional-shadow-probe-atlas-layout.unit.test.d.ts.map +0 -1
  478. package/dist/__tests__/environment-inspection.test.d.ts +0 -2
  479. package/dist/__tests__/environment-inspection.test.d.ts.map +0 -1
  480. package/dist/__tests__/fog-ai-user.fixture.d.ts +0 -2
  481. package/dist/__tests__/fog-ai-user.fixture.d.ts.map +0 -1
  482. package/dist/__tests__/fog-custom-render-feature.fixture.d.ts +0 -16
  483. package/dist/__tests__/fog-custom-render-feature.fixture.d.ts.map +0 -1
  484. package/dist/__tests__/fog-custom-render-feature.integration.test.d.ts +0 -2
  485. package/dist/__tests__/fog-custom-render-feature.integration.test.d.ts.map +0 -1
  486. package/dist/__tests__/fog-inspection.integration.test.d.ts +0 -2
  487. package/dist/__tests__/fog-inspection.integration.test.d.ts.map +0 -1
  488. package/dist/__tests__/fog-owner-state.integration.test.d.ts +0 -2
  489. package/dist/__tests__/fog-owner-state.integration.test.d.ts.map +0 -1
  490. package/dist/__tests__/fog-pipeline-topology.integration.test.d.ts +0 -2
  491. package/dist/__tests__/fog-pipeline-topology.integration.test.d.ts.map +0 -1
  492. package/dist/__tests__/fog-public-surface.integration.test.d.ts +0 -2
  493. package/dist/__tests__/fog-public-surface.integration.test.d.ts.map +0 -1
  494. package/dist/__tests__/fog-ray-contract.integration.test.d.ts +0 -2
  495. package/dist/__tests__/fog-ray-contract.integration.test.d.ts.map +0 -1
  496. package/dist/__tests__/fog-source-absence.integration.test.d.ts +0 -2
  497. package/dist/__tests__/fog-source-absence.integration.test.d.ts.map +0 -1
  498. package/dist/__tests__/fog-temporal.integration.test.d.ts +0 -2
  499. package/dist/__tests__/fog-temporal.integration.test.d.ts.map +0 -1
  500. package/dist/__tests__/frame-chain.unit.test.d.ts +0 -2
  501. package/dist/__tests__/frame-chain.unit.test.d.ts.map +0 -1
  502. package/dist/__tests__/gpu-scene-field-type-owner.test-d.d.ts +0 -2
  503. package/dist/__tests__/gpu-scene-field-type-owner.test-d.d.ts.map +0 -1
  504. package/dist/__tests__/hdrp-pipeline.unit.test.d.ts +0 -2
  505. package/dist/__tests__/hdrp-pipeline.unit.test.d.ts.map +0 -1
  506. package/dist/__tests__/ibl/ibl-fallback.unit.test.d.ts +0 -2
  507. package/dist/__tests__/ibl/ibl-fallback.unit.test.d.ts.map +0 -1
  508. package/dist/__tests__/material-derived-error-stop-draw.integration.test.d.ts +0 -2
  509. package/dist/__tests__/material-derived-error-stop-draw.integration.test.d.ts.map +0 -1
  510. package/dist/__tests__/material-derived-payload.integration.test.d.ts +0 -2
  511. package/dist/__tests__/material-derived-payload.integration.test.d.ts.map +0 -1
  512. package/dist/__tests__/materials.unit.test.d.ts +0 -2
  513. package/dist/__tests__/materials.unit.test.d.ts.map +0 -1
  514. package/dist/__tests__/param-schema-projection-census.unit.test.d.ts +0 -2
  515. package/dist/__tests__/param-schema-projection-census.unit.test.d.ts.map +0 -1
  516. package/dist/__tests__/persistent-render-scene.unit.test.d.ts +0 -2
  517. package/dist/__tests__/persistent-render-scene.unit.test.d.ts.map +0 -1
  518. package/dist/__tests__/pipeline-error-policy-owner.unit.test.d.ts +0 -2
  519. package/dist/__tests__/pipeline-error-policy-owner.unit.test.d.ts.map +0 -1
  520. package/dist/__tests__/pipeline-pass-trace.test.d.ts +0 -2
  521. package/dist/__tests__/pipeline-pass-trace.test.d.ts.map +0 -1
  522. package/dist/__tests__/pipeline-stage-owner.test-d.d.ts +0 -2
  523. package/dist/__tests__/pipeline-stage-owner.test-d.d.ts.map +0 -1
  524. package/dist/__tests__/plugin.test.d.ts +0 -2
  525. package/dist/__tests__/plugin.test.d.ts.map +0 -1
  526. package/dist/__tests__/prepared-graphics-backend-matrix.unit.test.d.ts +0 -2
  527. package/dist/__tests__/prepared-graphics-backend-matrix.unit.test.d.ts.map +0 -1
  528. package/dist/__tests__/prepared-graphics-resolver-recording.unit.test.d.ts +0 -2
  529. package/dist/__tests__/prepared-graphics-resolver-recording.unit.test.d.ts.map +0 -1
  530. package/dist/__tests__/public-pipeline-id.test-d.d.ts +0 -2
  531. package/dist/__tests__/public-pipeline-id.test-d.d.ts.map +0 -1
  532. package/dist/__tests__/render-dispatch-membership.unit.test.d.ts +0 -2
  533. package/dist/__tests__/render-dispatch-membership.unit.test.d.ts.map +0 -1
  534. package/dist/__tests__/render-feature-construction.unit.test.d.ts +0 -2
  535. package/dist/__tests__/render-feature-construction.unit.test.d.ts.map +0 -1
  536. package/dist/__tests__/render-feature-error-code-owner.test-d.d.ts +0 -2
  537. package/dist/__tests__/render-feature-error-code-owner.test-d.d.ts.map +0 -1
  538. package/dist/__tests__/render-feature-gpu-buffer-usage-owner.test-d.d.ts +0 -2
  539. package/dist/__tests__/render-feature-gpu-buffer-usage-owner.test-d.d.ts.map +0 -1
  540. package/dist/__tests__/render-feature-graph.integration.test.d.ts +0 -2
  541. package/dist/__tests__/render-feature-graph.integration.test.d.ts.map +0 -1
  542. package/dist/__tests__/render-feature-graphics-staging.unit.test.d.ts +0 -2
  543. package/dist/__tests__/render-feature-graphics-staging.unit.test.d.ts.map +0 -1
  544. package/dist/__tests__/render-feature-order.unit.test.d.ts +0 -2
  545. package/dist/__tests__/render-feature-order.unit.test.d.ts.map +0 -1
  546. package/dist/__tests__/render-feature-prepared-graphics-recording.unit.test.d.ts +0 -2
  547. package/dist/__tests__/render-feature-prepared-graphics-recording.unit.test.d.ts.map +0 -1
  548. package/dist/__tests__/render-feature-staging.unit.test.d.ts +0 -2
  549. package/dist/__tests__/render-feature-staging.unit.test.d.ts.map +0 -1
  550. package/dist/__tests__/renderer-render-scene-public.test-d.d.ts +0 -2
  551. package/dist/__tests__/renderer-render-scene-public.test-d.d.ts.map +0 -1
  552. package/dist/__tests__/scene-temporal-coverage.unit.test.d.ts +0 -2
  553. package/dist/__tests__/scene-temporal-coverage.unit.test.d.ts.map +0 -1
  554. package/dist/__tests__/sun-snapshot-consumers.test.d.ts +0 -2
  555. package/dist/__tests__/sun-snapshot-consumers.test.d.ts.map +0 -1
  556. package/dist/__tests__/surface-backend-kind-owner.test-d.d.ts +0 -2
  557. package/dist/__tests__/surface-backend-kind-owner.test-d.d.ts.map +0 -1
  558. package/dist/__tests__/taa-history-store.unit.test.d.ts +0 -2
  559. package/dist/__tests__/taa-history-store.unit.test.d.ts.map +0 -1
  560. package/dist/__tests__/temporal-frame-transaction.integration.test.d.ts +0 -2
  561. package/dist/__tests__/temporal-frame-transaction.integration.test.d.ts.map +0 -1
  562. package/dist/__tests__/temporal-inspection.unit.test.d.ts +0 -2
  563. package/dist/__tests__/temporal-inspection.unit.test.d.ts.map +0 -1
  564. package/dist/assets/__tests__/asset-decoders.unit.test.d.ts +0 -2
  565. package/dist/assets/__tests__/asset-decoders.unit.test.d.ts.map +0 -1
  566. package/dist/assets/__tests__/mipmap-generator.unit.test.d.ts +0 -2
  567. package/dist/assets/__tests__/mipmap-generator.unit.test.d.ts.map +0 -1
  568. package/dist/assets/__tests__/render-asset-port.unit.test.d.ts +0 -2
  569. package/dist/assets/__tests__/render-asset-port.unit.test.d.ts.map +0 -1
  570. package/dist/assets/__tests__/resolve-render-asset.unit.test.d.ts +0 -2
  571. package/dist/assets/__tests__/resolve-render-asset.unit.test.d.ts.map +0 -1
  572. package/dist/chunk-33UF5SAO.mjs +0 -7397
  573. package/dist/chunk-33UF5SAO.mjs.map +0 -1
  574. package/dist/chunk-A5QCJSNL.mjs +0 -29913
  575. package/dist/chunk-A5QCJSNL.mjs.map +0 -1
  576. package/dist/chunk-JMSB7AR4.mjs +0 -3
  577. package/dist/chunk-JMSB7AR4.mjs.map +0 -1
  578. package/dist/chunk-LXNGO6AO.mjs +0 -569
  579. package/dist/chunk-LXNGO6AO.mjs.map +0 -1
  580. package/dist/chunk-QRXPSX4X.mjs +0 -659
  581. package/dist/chunk-QRXPSX4X.mjs.map +0 -1
  582. package/dist/chunk-YAKEQPWO.mjs +0 -1439
  583. package/dist/chunk-YAKEQPWO.mjs.map +0 -1
  584. package/dist/components/__tests__/atmosphere-red.test.d.ts +0 -2
  585. package/dist/components/__tests__/atmosphere-red.test.d.ts.map +0 -1
  586. package/dist/components/__tests__/atmosphere.test.d.ts +0 -2
  587. package/dist/components/__tests__/atmosphere.test.d.ts.map +0 -1
  588. package/dist/components/__tests__/fog.test-d.d.ts +0 -2
  589. package/dist/components/__tests__/fog.test-d.d.ts.map +0 -1
  590. package/dist/components/__tests__/fog.test.d.ts +0 -2
  591. package/dist/components/__tests__/fog.test.d.ts.map +0 -1
  592. package/dist/components/atmosphere.d.ts +0 -18
  593. package/dist/components/atmosphere.d.ts.map +0 -1
  594. package/dist/components/environment.d.ts +0 -116
  595. package/dist/components/environment.d.ts.map +0 -1
  596. package/dist/deferred-lighting.d.ts +0 -13
  597. package/dist/deferred-lighting.d.ts.map +0 -1
  598. package/dist/dynamic-texture-store.d.ts +0 -42
  599. package/dist/dynamic-texture-store.d.ts.map +0 -1
  600. package/dist/environment/__tests__/failure-injection.test.d.ts +0 -2
  601. package/dist/environment/__tests__/failure-injection.test.d.ts.map +0 -1
  602. package/dist/environment/__tests__/generation-red.test.d.ts +0 -2
  603. package/dist/environment/__tests__/generation-red.test.d.ts.map +0 -1
  604. package/dist/environment/__tests__/generation.test.d.ts +0 -2
  605. package/dist/environment/__tests__/generation.test.d.ts.map +0 -1
  606. package/dist/environment/__tests__/graph-transaction.test.d.ts +0 -2
  607. package/dist/environment/__tests__/graph-transaction.test.d.ts.map +0 -1
  608. package/dist/environment/__tests__/inspection-red.test.d.ts +0 -2
  609. package/dist/environment/__tests__/inspection-red.test.d.ts.map +0 -1
  610. package/dist/environment/__tests__/lifecycle-evidence.test.d.ts +0 -2
  611. package/dist/environment/__tests__/lifecycle-evidence.test.d.ts.map +0 -1
  612. package/dist/environment/__tests__/pipeline-topology.test.d.ts +0 -2
  613. package/dist/environment/__tests__/pipeline-topology.test.d.ts.map +0 -1
  614. package/dist/environment/__tests__/readiness.test.d.ts +0 -2
  615. package/dist/environment/__tests__/readiness.test.d.ts.map +0 -1
  616. package/dist/environment/__tests__/recovery.test.d.ts +0 -2
  617. package/dist/environment/__tests__/recovery.test.d.ts.map +0 -1
  618. package/dist/environment/__tests__/resize-dispose.test.d.ts +0 -2
  619. package/dist/environment/__tests__/resize-dispose.test.d.ts.map +0 -1
  620. package/dist/environment/__tests__/signature-red.test.d.ts +0 -2
  621. package/dist/environment/__tests__/signature-red.test.d.ts.map +0 -1
  622. package/dist/environment/__tests__/signature.test.d.ts +0 -2
  623. package/dist/environment/__tests__/signature.test.d.ts.map +0 -1
  624. package/dist/environment/descriptors.d.ts +0 -2
  625. package/dist/environment/descriptors.d.ts.map +0 -1
  626. package/dist/environment/extracted-environment.d.ts +0 -53
  627. package/dist/environment/extracted-environment.d.ts.map +0 -1
  628. package/dist/environment/generation.d.ts +0 -62
  629. package/dist/environment/generation.d.ts.map +0 -1
  630. package/dist/environment/gpu-bundle.d.ts +0 -23
  631. package/dist/environment/gpu-bundle.d.ts.map +0 -1
  632. package/dist/environment/graph.d.ts +0 -108
  633. package/dist/environment/graph.d.ts.map +0 -1
  634. package/dist/environment/inspection.d.ts +0 -48
  635. package/dist/environment/inspection.d.ts.map +0 -1
  636. package/dist/environment/lifecycle.d.ts +0 -22
  637. package/dist/environment/lifecycle.d.ts.map +0 -1
  638. package/dist/environment/readiness.d.ts +0 -29
  639. package/dist/environment/readiness.d.ts.map +0 -1
  640. package/dist/environment/signature.d.ts +0 -70
  641. package/dist/environment/signature.d.ts.map +0 -1
  642. package/dist/extract/__tests__/directional-csm-domain.unit.test.d.ts +0 -2
  643. package/dist/extract/__tests__/directional-csm-domain.unit.test.d.ts.map +0 -1
  644. package/dist/extract/__tests__/environment-source.test.d.ts +0 -2
  645. package/dist/extract/__tests__/environment-source.test.d.ts.map +0 -1
  646. package/dist/extract/__tests__/schema-readers.unit.test.d.ts +0 -2
  647. package/dist/extract/__tests__/schema-readers.unit.test.d.ts.map +0 -1
  648. package/dist/extract/directional-csm.d.ts +0 -129
  649. package/dist/extract/directional-csm.d.ts.map +0 -1
  650. package/dist/extract/index.d.ts +0 -5
  651. package/dist/extract/index.d.ts.map +0 -1
  652. package/dist/extract/material-interface.d.ts +0 -56
  653. package/dist/extract/material-interface.d.ts.map +0 -1
  654. package/dist/extract/schema-readers.d.ts +0 -20
  655. package/dist/extract/schema-readers.d.ts.map +0 -1
  656. package/dist/features/graph-contribution.d.ts +0 -64
  657. package/dist/features/graph-contribution.d.ts.map +0 -1
  658. package/dist/features/index.d.ts +0 -21
  659. package/dist/features/index.d.ts.map +0 -1
  660. package/dist/features/morph/index.d.ts +0 -3
  661. package/dist/features/morph/index.d.ts.map +0 -1
  662. package/dist/features/morph/morph-bounds.d.ts +0 -42
  663. package/dist/features/morph/morph-bounds.d.ts.map +0 -1
  664. package/dist/features/scene-temporal.d.ts +0 -45
  665. package/dist/features/scene-temporal.d.ts.map +0 -1
  666. package/dist/features/taa-resolve.d.ts +0 -21
  667. package/dist/features/taa-resolve.d.ts.map +0 -1
  668. package/dist/frame-chain.d.ts +0 -14
  669. package/dist/frame-chain.d.ts.map +0 -1
  670. package/dist/gpu-driven/view-reference.d.ts.map +0 -1
  671. package/dist/gpu-resource-store.d.ts.map +0 -1
  672. package/dist/hdrp-cluster-membership.d.ts +0 -2
  673. package/dist/hdrp-cluster-membership.d.ts.map +0 -1
  674. package/dist/hdrp-pipeline.d.ts +0 -36
  675. package/dist/hdrp-pipeline.d.ts.map +0 -1
  676. package/dist/ibl/cubemap-projection.d.ts +0 -23
  677. package/dist/ibl/cubemap-projection.d.ts.map +0 -1
  678. package/dist/ibl/face-uniforms.d.ts +0 -65
  679. package/dist/ibl/face-uniforms.d.ts.map +0 -1
  680. package/dist/mesh-update-errors.d.ts +0 -71
  681. package/dist/mesh-update-errors.d.ts.map +0 -1
  682. package/dist/mipmap-generator.d.ts +0 -39
  683. package/dist/mipmap-generator.d.ts.map +0 -1
  684. package/dist/param-schema-projection-census.d.ts +0 -18
  685. package/dist/param-schema-projection-census.d.ts.map +0 -1
  686. package/dist/persistent-render-scene.d.ts +0 -158
  687. package/dist/persistent-render-scene.d.ts.map +0 -1
  688. package/dist/pipeline/index.d.ts +0 -11
  689. package/dist/pipeline/index.d.ts.map +0 -1
  690. package/dist/pipeline-errors.d.ts +0 -110
  691. package/dist/pipeline-errors.d.ts.map +0 -1
  692. package/dist/prepare/__tests__/schema-readers.unit.test.d.ts +0 -2
  693. package/dist/prepare/__tests__/schema-readers.unit.test.d.ts.map +0 -1
  694. package/dist/prepare/index.d.ts +0 -4
  695. package/dist/prepare/index.d.ts.map +0 -1
  696. package/dist/prepare/schema-readers.d.ts +0 -11
  697. package/dist/prepare/schema-readers.d.ts.map +0 -1
  698. package/dist/record/__tests__/environment-record.test.d.ts +0 -2
  699. package/dist/record/__tests__/environment-record.test.d.ts.map +0 -1
  700. package/dist/record/__tests__/frame-targets.unit.test.d.ts +0 -2
  701. package/dist/record/__tests__/frame-targets.unit.test.d.ts.map +0 -1
  702. package/dist/record/__tests__/membership-timing.unit.test.d.ts +0 -2
  703. package/dist/record/__tests__/membership-timing.unit.test.d.ts.map +0 -1
  704. package/dist/record/__tests__/render-submission.integration.test.d.ts +0 -2
  705. package/dist/record/__tests__/render-submission.integration.test.d.ts.map +0 -1
  706. package/dist/record/__tests__/render-submission.perf.test.d.ts +0 -2
  707. package/dist/record/__tests__/render-submission.perf.test.d.ts.map +0 -1
  708. package/dist/record/__tests__/shadow-submit-mode.unit.test.d.ts +0 -2
  709. package/dist/record/__tests__/shadow-submit-mode.unit.test.d.ts.map +0 -1
  710. package/dist/record/__tests__/view-ubo-layout.unit.test.d.ts +0 -2
  711. package/dist/record/__tests__/view-ubo-layout.unit.test.d.ts.map +0 -1
  712. package/dist/record/frame-observation.d.ts +0 -38
  713. package/dist/record/frame-observation.d.ts.map +0 -1
  714. package/dist/record/index.d.ts +0 -15
  715. package/dist/record/index.d.ts.map +0 -1
  716. package/dist/record/main-pass-skin.d.ts +0 -46
  717. package/dist/record/main-pass-skin.d.ts.map +0 -1
  718. package/dist/record/main-pass-sprite.d.ts +0 -69
  719. package/dist/record/main-pass-sprite.d.ts.map +0 -1
  720. package/dist/record/material-payload.d.ts +0 -43
  721. package/dist/record/material-payload.d.ts.map +0 -1
  722. package/dist/record/material-slot-plan.d.ts +0 -26
  723. package/dist/record/material-slot-plan.d.ts.map +0 -1
  724. package/dist/record/membership-timing.d.ts +0 -232
  725. package/dist/record/membership-timing.d.ts.map +0 -1
  726. package/dist/record/shadow-caster-uniform.d.ts +0 -8
  727. package/dist/record/shadow-caster-uniform.d.ts.map +0 -1
  728. package/dist/record/shadow-submit-mode.d.ts +0 -66
  729. package/dist/record/shadow-submit-mode.d.ts.map +0 -1
  730. package/dist/render-dispatch-membership.d.ts +0 -47
  731. package/dist/render-dispatch-membership.d.ts.map +0 -1
  732. package/dist/render-pipeline-context.d.ts +0 -289
  733. package/dist/render-pipeline-context.d.ts.map +0 -1
  734. package/dist/render-pipeline-target.d.ts +0 -16
  735. package/dist/render-pipeline-target.d.ts.map +0 -1
  736. package/dist/render-scene-projection.d.ts +0 -174
  737. package/dist/render-scene-projection.d.ts.map +0 -1
  738. package/dist/render-system-fold.d.ts +0 -266
  739. package/dist/render-system-fold.d.ts.map +0 -1
  740. package/dist/renderer/asset-service.d.ts +0 -10
  741. package/dist/renderer/asset-service.d.ts.map +0 -1
  742. package/dist/renderer/backend-selection.d.ts.map +0 -1
  743. package/dist/renderer/environment-classify.d.ts +0 -6
  744. package/dist/renderer/environment-classify.d.ts.map +0 -1
  745. package/dist/renderer/environment-error.d.ts +0 -13
  746. package/dist/renderer/environment-error.d.ts.map +0 -1
  747. package/dist/renderer/material/pipeline-projection.d.ts +0 -91
  748. package/dist/renderer/material/pipeline-projection.d.ts.map +0 -1
  749. package/dist/renderer/renderer-factory.d.ts +0 -283
  750. package/dist/renderer/renderer-factory.d.ts.map +0 -1
  751. package/dist/renderer.d.ts +0 -771
  752. package/dist/renderer.d.ts.map +0 -1
  753. package/dist/scene-utils/collect-subtree.d.ts +0 -11
  754. package/dist/scene-utils/collect-subtree.d.ts.map +0 -1
  755. package/dist/ssao-data.d.ts +0 -34
  756. package/dist/ssao-data.d.ts.map +0 -1
  757. package/dist/surface-format.d.ts +0 -10
  758. package/dist/surface-format.d.ts.map +0 -1
  759. package/dist/taa-history-store.d.ts +0 -88
  760. package/dist/taa-history-store.d.ts.map +0 -1
  761. package/dist/temporal-coverage.d.ts +0 -35
  762. package/dist/temporal-coverage.d.ts.map +0 -1
  763. package/dist/temporal-frame-transaction.d.ts +0 -92
  764. package/dist/temporal-frame-transaction.d.ts.map +0 -1
  765. package/dist/temporal-inspection.d.ts +0 -57
  766. package/dist/temporal-inspection.d.ts.map +0 -1
  767. package/dist/temporal-view.d.ts +0 -43
  768. package/dist/temporal-view.d.ts.map +0 -1
  769. package/dist/tilemap/resolve-tileset-runtime.d.ts +0 -23
  770. package/dist/tilemap/resolve-tileset-runtime.d.ts.map +0 -1
  771. package/dist/urp-pipeline.d.ts +0 -4
  772. package/dist/urp-pipeline.d.ts.map +0 -1
  773. package/src/__tests__/analytic-sky-contract.test.ts +0 -27
  774. package/src/__tests__/analytic-sky-falsify-carriers.mjs +0 -43
  775. package/src/__tests__/analytic-sky-falsify.test.ts +0 -94
  776. package/src/__tests__/assets-runtime-handoff.integration.test.ts +0 -36
  777. package/src/__tests__/backend-selection.integration.test.ts +0 -11
  778. package/src/__tests__/camera-temporal.test-d.ts +0 -8
  779. package/src/__tests__/camera-temporal.test.ts +0 -188
  780. package/src/__tests__/directional-shadow-probe-atlas-layout.unit.test.ts +0 -18
  781. package/src/__tests__/environment-inspection.test.ts +0 -45
  782. package/src/__tests__/fog-ai-user.fixture.ts +0 -350
  783. package/src/__tests__/fog-custom-render-feature.fixture.ts +0 -33
  784. package/src/__tests__/fog-custom-render-feature.integration.test.ts +0 -76
  785. package/src/__tests__/fog-inspection.integration.test.ts +0 -127
  786. package/src/__tests__/fog-owner-state.integration.test.ts +0 -112
  787. package/src/__tests__/fog-pipeline-topology.integration.test.ts +0 -93
  788. package/src/__tests__/fog-public-surface.integration.test.ts +0 -60
  789. package/src/__tests__/fog-ray-contract.integration.test.ts +0 -73
  790. package/src/__tests__/fog-source-absence.integration.test.ts +0 -51
  791. package/src/__tests__/fog-temporal.integration.test.ts +0 -115
  792. package/src/__tests__/frame-chain.unit.test.ts +0 -26
  793. package/src/__tests__/gpu-scene-field-type-owner.test-d.ts +0 -27
  794. package/src/__tests__/hdrp-pipeline.unit.test.ts +0 -100
  795. package/src/__tests__/ibl/ibl-fallback.unit.test.ts +0 -23
  796. package/src/__tests__/material-derived-error-stop-draw.integration.test.ts +0 -69
  797. package/src/__tests__/material-derived-payload.integration.test.ts +0 -164
  798. package/src/__tests__/materials.unit.test.ts +0 -25
  799. package/src/__tests__/param-schema-projection-census.unit.test.ts +0 -40
  800. package/src/__tests__/persistent-render-scene.unit.test.ts +0 -1311
  801. package/src/__tests__/pipeline-error-policy-owner.unit.test.ts +0 -167
  802. package/src/__tests__/pipeline-pass-trace.test.ts +0 -92
  803. package/src/__tests__/pipeline-stage-owner.test-d.ts +0 -13
  804. package/src/__tests__/plugin.test.ts +0 -25
  805. package/src/__tests__/prepared-graphics-backend-matrix.unit.test.ts +0 -129
  806. package/src/__tests__/prepared-graphics-resolver-recording.unit.test.ts +0 -180
  807. package/src/__tests__/public-pipeline-id.test-d.ts +0 -6
  808. package/src/__tests__/render-dispatch-membership.unit.test.ts +0 -117
  809. package/src/__tests__/render-feature-construction.unit.test.ts +0 -124
  810. package/src/__tests__/render-feature-error-code-owner.test-d.ts +0 -27
  811. package/src/__tests__/render-feature-gpu-buffer-usage-owner.test-d.ts +0 -46
  812. package/src/__tests__/render-feature-graph.integration.test.ts +0 -205
  813. package/src/__tests__/render-feature-graphics-staging.unit.test.ts +0 -200
  814. package/src/__tests__/render-feature-order.unit.test.ts +0 -66
  815. package/src/__tests__/render-feature-prepared-graphics-recording.unit.test.ts +0 -107
  816. package/src/__tests__/render-feature-staging.unit.test.ts +0 -94
  817. package/src/__tests__/renderer-render-scene-public.test-d.ts +0 -27
  818. package/src/__tests__/scene-temporal-coverage.unit.test.ts +0 -259
  819. package/src/__tests__/sun-snapshot-consumers.test.ts +0 -35
  820. package/src/__tests__/surface-backend-kind-owner.test-d.ts +0 -42
  821. package/src/__tests__/taa-history-store.unit.test.ts +0 -196
  822. package/src/__tests__/temporal-frame-transaction.integration.test.ts +0 -537
  823. package/src/__tests__/temporal-inspection.unit.test.ts +0 -138
  824. package/src/assets/__tests__/asset-decoders.unit.test.ts +0 -92
  825. package/src/assets/__tests__/mipmap-generator.unit.test.ts +0 -52
  826. package/src/assets/__tests__/render-asset-port.unit.test.ts +0 -54
  827. package/src/assets/__tests__/resolve-render-asset.unit.test.ts +0 -47
  828. package/src/components/__tests__/atmosphere-red.test.ts +0 -51
  829. package/src/components/__tests__/atmosphere.test.ts +0 -79
  830. package/src/components/__tests__/fog.test-d.ts +0 -49
  831. package/src/components/__tests__/fog.test.ts +0 -60
  832. package/src/components/atmosphere.ts +0 -64
  833. package/src/deferred-lighting.ts +0 -92
  834. package/src/dynamic-texture-store.ts +0 -111
  835. package/src/environment/README.md +0 -76
  836. package/src/environment/__tests__/failure-injection.test.ts +0 -50
  837. package/src/environment/__tests__/generation-red.test.ts +0 -64
  838. package/src/environment/__tests__/generation.test.ts +0 -37
  839. package/src/environment/__tests__/graph-transaction.test.ts +0 -85
  840. package/src/environment/__tests__/inspection-red.test.ts +0 -53
  841. package/src/environment/__tests__/lifecycle-evidence.test.ts +0 -40
  842. package/src/environment/__tests__/pipeline-topology.test.ts +0 -33
  843. package/src/environment/__tests__/readiness.test.ts +0 -42
  844. package/src/environment/__tests__/recovery.test.ts +0 -62
  845. package/src/environment/__tests__/resize-dispose.test.ts +0 -30
  846. package/src/environment/__tests__/signature-red.test.ts +0 -45
  847. package/src/environment/__tests__/signature.test.ts +0 -60
  848. package/src/environment/descriptors.ts +0 -7
  849. package/src/environment/extracted-environment.ts +0 -239
  850. package/src/environment/generation.ts +0 -158
  851. package/src/environment/gpu-bundle.ts +0 -144
  852. package/src/environment/graph.ts +0 -588
  853. package/src/environment/inspection.ts +0 -107
  854. package/src/environment/lifecycle.ts +0 -124
  855. package/src/environment/readiness.ts +0 -76
  856. package/src/environment/signature.ts +0 -185
  857. package/src/extract/__tests__/directional-csm-domain.unit.test.ts +0 -391
  858. package/src/extract/__tests__/environment-source.test.ts +0 -105
  859. package/src/extract/__tests__/schema-readers.unit.test.ts +0 -16
  860. package/src/extract/directional-csm.ts +0 -959
  861. package/src/extract/index.ts +0 -10
  862. package/src/extract/material-interface.ts +0 -604
  863. package/src/extract/schema-readers.ts +0 -27
  864. package/src/features/graph-contribution.ts +0 -577
  865. package/src/features/index.ts +0 -100
  866. package/src/features/morph/index.ts +0 -24
  867. package/src/features/morph/morph-bounds.ts +0 -123
  868. package/src/features/scene-temporal.ts +0 -274
  869. package/src/features/taa-resolve.ts +0 -244
  870. package/src/frame-chain.ts +0 -21
  871. package/src/hdrp-cluster-membership.ts +0 -70
  872. package/src/ibl/cubemap-projection.ts +0 -60
  873. package/src/ibl/face-uniforms.ts +0 -150
  874. package/src/mesh-update-errors.ts +0 -113
  875. package/src/mipmap-generator.ts +0 -244
  876. package/src/param-schema-projection-census.ts +0 -73
  877. package/src/persistent-render-scene.ts +0 -1752
  878. package/src/pipeline/index.ts +0 -40
  879. package/src/pipeline-errors.ts +0 -172
  880. package/src/prepare/__tests__/schema-readers.unit.test.ts +0 -16
  881. package/src/prepare/index.ts +0 -8
  882. package/src/prepare/schema-readers.ts +0 -20
  883. package/src/record/__tests__/environment-record.test.ts +0 -35
  884. package/src/record/__tests__/frame-targets.unit.test.ts +0 -54
  885. package/src/record/__tests__/membership-timing.unit.test.ts +0 -524
  886. package/src/record/__tests__/render-submission.integration.test.ts +0 -76
  887. package/src/record/__tests__/render-submission.perf.test.ts +0 -141
  888. package/src/record/__tests__/shadow-submit-mode.unit.test.ts +0 -88
  889. package/src/record/__tests__/view-ubo-layout.unit.test.ts +0 -101
  890. package/src/record/frame-observation.ts +0 -122
  891. package/src/record/index.ts +0 -15
  892. package/src/record/main-pass-skin.ts +0 -51
  893. package/src/record/main-pass-sprite.ts +0 -166
  894. package/src/record/material-payload.ts +0 -292
  895. package/src/record/material-slot-plan.ts +0 -68
  896. package/src/record/membership-timing.ts +0 -1012
  897. package/src/record/shadow-caster-uniform.ts +0 -37
  898. package/src/record/shadow-submit-mode.ts +0 -277
  899. package/src/render-dispatch-membership.ts +0 -155
  900. package/src/render-pipeline-context.ts +0 -332
  901. package/src/render-pipeline-target.ts +0 -96
  902. package/src/render-scene-projection.ts +0 -1738
  903. package/src/render-system-fold.ts +0 -531
  904. package/src/renderer/asset-service.ts +0 -32
  905. package/src/renderer/backend-selection.ts +0 -121
  906. package/src/renderer/environment-classify.ts +0 -30
  907. package/src/renderer/environment-error.ts +0 -19
  908. package/src/renderer/material/pipeline-projection.ts +0 -140
  909. package/src/renderer.ts +0 -940
  910. package/src/scene-utils/collect-subtree.ts +0 -40
  911. package/src/ssao-data.ts +0 -106
  912. package/src/surface-format.ts +0 -37
  913. package/src/taa-history-store.ts +0 -429
  914. package/src/temporal-coverage.ts +0 -106
  915. package/src/temporal-frame-transaction.ts +0 -301
  916. package/src/temporal-inspection.ts +0 -194
  917. package/src/temporal-view.ts +0 -174
  918. package/src/tilemap/resolve-tileset-runtime.ts +0 -72
@@ -1,1311 +0,0 @@
1
- import { Disabled, defineComponent, type EntityHandle, World } from '@forgeax/engine-ecs';
2
- import { vec3 } from '@forgeax/engine-math';
3
- import { RhiNullCommandEncoder, RhiNullDevice, RhiNullQueue } from '@forgeax/engine-rhi-null';
4
- import { ChildOf, MorphWeights, propagateTransforms, Transform } from '@forgeax/engine-scene';
5
- import { toShared } from '@forgeax/engine-types';
6
- import { describe, expect, it } from 'vitest';
7
- import {
8
- Camera,
9
- Instances,
10
- MeshFilter,
11
- MeshRenderer,
12
- PointLight,
13
- PostProcessParams,
14
- } from '../components';
15
- import { PersistentRenderScene } from '../persistent-render-scene';
16
- import type {
17
- CameraSnapshot,
18
- DispatchEntry,
19
- ExtractedFrame,
20
- GpuDrivenDrawSnapshot,
21
- MaterialSnapshot,
22
- RenderableSnapshot,
23
- } from '../render-system-extract';
24
- import {
25
- extractCameraSnapshots,
26
- refreshExtractedFrameCameras,
27
- refreshExtractedFrameLights,
28
- } from '../render-system-extract';
29
- import { temporalViewId } from '../temporal-view';
30
-
31
- const material = {} as MaterialSnapshot;
32
- const GameplayState = defineComponent('PersistentRenderSceneGameplayStateTest', {
33
- value: { type: 'f32', default: 0 },
34
- });
35
-
36
- function renderable(
37
- entityKey: number,
38
- world: Float32Array,
39
- materialSnapshot: MaterialSnapshot = material,
40
- ): RenderableSnapshot {
41
- return {
42
- assetHandle: 1,
43
- transform: { world: new Float32Array(world) },
44
- material: materialSnapshot,
45
- materials: [materialSnapshot],
46
- materialBindingSources: ['engine-default'],
47
- worldId: 0,
48
- entityKey,
49
- };
50
- }
51
-
52
- function frame(...snapshots: RenderableSnapshot[]): ExtractedFrame {
53
- return {
54
- cameras: [],
55
- lights: {
56
- directional: undefined,
57
- directionalCount: 0,
58
- point: [],
59
- spot: [],
60
- lightViewProj: undefined,
61
- splitPlanes: undefined,
62
- cascadeCount: undefined,
63
- cascadeBlend: undefined,
64
- shadowMapSize: undefined,
65
- depthBias: undefined,
66
- normalBias: undefined,
67
- pcfKernelSize: undefined,
68
- pointShadow: [],
69
- directionalCsmConfig: undefined,
70
- directionalCsmDirection: undefined,
71
- },
72
- renderables: snapshots,
73
- dispatch: [],
74
- environment: { kind: 'none', worldId: 0, skylightCount: 0, skyboxCount: 0 },
75
- frustumStats: { culled: 0, total: 0 },
76
- visibilityStats: { explicitlyHidden: 0 },
77
- postProcessParams: new Map(),
78
- visibilitySnapshots: [],
79
- featureVisibilitySnapshots: [],
80
- hiddenEntityReports: [],
81
- };
82
- }
83
-
84
- function csmCamera(world: Float32Array): CameraSnapshot {
85
- return {
86
- worldId: 0,
87
- entityKey: 0,
88
- world,
89
- position: vec3.create(world[12] ?? 0, world[13] ?? 0, world[14] ?? 0),
90
- fov: Math.PI / 3,
91
- aspect: 1,
92
- near: 0.1,
93
- far: 100,
94
- projection: 'perspective',
95
- orthoLeft: -1,
96
- orthoRight: 1,
97
- orthoBottom: -1,
98
- orthoTop: 1,
99
- tonemap: 'none',
100
- exposure: 1,
101
- whitePoint: 1,
102
- antialias: 'none',
103
- historyVersion: 0,
104
- bloom: 'off',
105
- bloomThreshold: 1,
106
- bloomIntensity: 0,
107
- bloomBlurRadius: 1,
108
- clearColor: [0, 0, 0, 1],
109
- };
110
- }
111
-
112
- function csmCandidateFrame(
113
- candidate: RenderableSnapshot,
114
- cameraWorld: Float32Array,
115
- ): ExtractedFrame {
116
- const base = frame(candidate);
117
- const shadowDispatch = [
118
- {
119
- entityIndex: candidate.entityKey,
120
- materialHandle: 0,
121
- renderableIndex: 0,
122
- passIndex: 0,
123
- queue: 2000,
124
- layer: 0,
125
- tags: { LightMode: 'ShadowCaster' },
126
- renderState: undefined,
127
- defines: undefined,
128
- vertexEntry: 'vs_main',
129
- fragmentEntry: undefined,
130
- materialShaderId: 'forgeax::default-shadow-caster',
131
- paramSnapshot: {},
132
- },
133
- ] satisfies DispatchEntry[];
134
- return {
135
- ...base,
136
- cameras: [csmCamera(cameraWorld)],
137
- dispatch: shadowDispatch,
138
- candidateRenderables: [candidate],
139
- candidateDispatch: shadowDispatch,
140
- lights: {
141
- ...base.lights,
142
- directionalCount: 1,
143
- cascadeCount: 2,
144
- cascadeBlend: 0.25,
145
- shadowMapSize: 512,
146
- directionalCsmConfig: {
147
- cascadeCount: 2,
148
- splitLambda: 0.5,
149
- cascadeBlend: 0.25,
150
- mapSize: 512,
151
- shadowDistance: 40,
152
- pcfKernelSize: 3,
153
- },
154
- directionalCsmDirection: vec3.create(0.4, -0.8, 0.2),
155
- },
156
- };
157
- }
158
-
159
- function compositionFrame(
160
- entries: readonly { readonly entity: EntityHandle; readonly worldId: number }[],
161
- ): ExtractedFrame {
162
- const first = entries[0];
163
- if (first === undefined) throw new Error('compositionFrame requires at least one renderable');
164
- const result = frame(renderable(first.entity, new Float32Array(16)));
165
- return {
166
- ...result,
167
- renderables: entries.map(({ entity, worldId }) => ({
168
- ...renderable(entity, new Float32Array(16)),
169
- worldId,
170
- })),
171
- };
172
- }
173
-
174
- describe('PersistentRenderScene', () => {
175
- it('does no World traversal on no-change and drains one transform delta without rebuilding', () => {
176
- const world = new World();
177
- const entity = world.spawn({ component: Transform, data: { pos: [1, 0, 0] } }).unwrap();
178
- propagateTransforms(world).unwrap();
179
- const persistent = new PersistentRenderScene();
180
- let builds = 0;
181
- const build = () => {
182
- builds += 1;
183
- return frame(renderable(entity, world.get(entity, Transform).unwrap().world));
184
- };
185
-
186
- const initial = persistent.extract(world, 0, build);
187
- const unchanged = persistent.extract(world, 0, build);
188
- expect(unchanged).toBe(initial);
189
- expect(builds).toBe(1);
190
-
191
- world.set(entity, Transform, { pos: [9, 0, 0] }).unwrap();
192
- propagateTransforms(world).unwrap();
193
- const updated = persistent.extract(world, 0, build);
194
-
195
- expect(builds).toBe(1);
196
- expect(updated.renderables[0]?.transform.world[12]).toBe(9);
197
- expect(persistent.inspect()).toMatchObject({
198
- fullRebuilds: 1,
199
- noChangeFrames: 1,
200
- deltaFrames: 1,
201
- transformUpdates: 1,
202
- projectionRecords: 1,
203
- });
204
- });
205
-
206
- it('retains submitted temporal authority for an unchanged non-rigid projection', () => {
207
- const world = new World();
208
- const entity = world
209
- .spawn(
210
- { component: Transform, data: {} },
211
- { component: MorphWeights, data: { weights: new Float32Array([0]) } },
212
- )
213
- .unwrap();
214
- propagateTransforms(world).unwrap();
215
- const persistent = new PersistentRenderScene();
216
- let builds = 0;
217
- const build = () => {
218
- builds += 1;
219
- return frame({
220
- ...renderable(entity, world.get(entity, Transform).unwrap().world),
221
- morphWeights: new Float32Array(world.get(entity, MorphWeights).unwrap().weights),
222
- });
223
- };
224
-
225
- const initial = persistent.extract(world, 0, build);
226
- const projection = persistent.temporalProjection([world]);
227
- expect(projection).toBeDefined();
228
- if (projection === undefined) return;
229
- projection.commitSubmission(projection.captureSubmission(initial.renderables));
230
-
231
- const unchanged = persistent.extract(world, 0, build);
232
- const temporal = projection.withTemporal(
233
- unchanged.renderables[0] as RenderableSnapshot,
234
- ).temporal;
235
-
236
- expect(unchanged).toBe(initial);
237
- expect(builds).toBe(1);
238
- expect(temporal).toMatchObject({
239
- previousSource: 'last-submitted',
240
- previousEpoch: 1,
241
- reactive: false,
242
- reactiveReasons: [],
243
- });
244
- expect(persistent.inspect()).toMatchObject({
245
- fullRebuilds: 1,
246
- noChangeFrames: 1,
247
- projectionRecords: 1,
248
- });
249
- });
250
-
251
- it('admits a component-added renderable through one entity extraction and topology patch', () => {
252
- const world = new World();
253
- const first = world
254
- .spawn(
255
- { component: Transform, data: {} },
256
- { component: MeshFilter, data: { assetHandle: toShared<'MeshAsset'>(0) } },
257
- { component: MeshRenderer, data: {} },
258
- )
259
- .unwrap();
260
- propagateTransforms(world).unwrap();
261
- const persistent = new PersistentRenderScene();
262
- const gpuDraw = {
263
- submeshIndex: 0,
264
- passIndex: 0,
265
- queue: 2000,
266
- kind: 'indexed' as const,
267
- first: 0,
268
- count: 36,
269
- baseVertex: 0,
270
- materialSlot: 0,
271
- topology: 'triangle-list',
272
- pipelineClass: 'opaque-pbr',
273
- materialResourceClass: 'plain',
274
- } satisfies GpuDrivenDrawSnapshot;
275
- let builds = 0;
276
- const build = () => {
277
- builds += 1;
278
- return frame({
279
- ...renderable(first, world.get(first, Transform).unwrap().world),
280
- gpuDrivenDraws: [gpuDraw],
281
- });
282
- };
283
-
284
- persistent.extract(world, 0, build);
285
- const second = world
286
- .spawn(
287
- { component: Transform, data: { pos: [2, 0, 0] } },
288
- { component: MeshFilter, data: { assetHandle: toShared<'MeshAsset'>(0) } },
289
- { component: MeshRenderer, data: {} },
290
- )
291
- .unwrap();
292
- propagateTransforms(world).unwrap();
293
- const shadowDispatch = {
294
- entityIndex: second,
295
- materialHandle: 0,
296
- renderableIndex: 0,
297
- passIndex: 0,
298
- queue: 2000,
299
- layer: 0,
300
- tags: { LightMode: 'ShadowCaster' },
301
- renderState: undefined,
302
- defines: undefined,
303
- vertexEntry: 'vs_main',
304
- fragmentEntry: undefined,
305
- materialShaderId: 'forgeax::default-shadow-caster',
306
- paramSnapshot: {},
307
- } satisfies DispatchEntry;
308
- const updated = persistent.extract(
309
- world,
310
- 0,
311
- build,
312
- undefined,
313
- undefined,
314
- undefined,
315
- undefined,
316
- undefined,
317
- (entity) =>
318
- entity === second
319
- ? {
320
- snapshot: {
321
- ...renderable(second, world.get(second, Transform).unwrap().world),
322
- gpuDrivenDraws: [gpuDraw],
323
- },
324
- candidateDispatch: [shadowDispatch],
325
- }
326
- : undefined,
327
- );
328
-
329
- expect(builds).toBe(1);
330
- expect(updated.candidateRenderables?.map((candidate) => candidate.entityKey)).toEqual([
331
- first,
332
- second,
333
- ]);
334
- expect(updated.candidateDispatch?.map((entry) => entry.entityIndex)).toEqual([second]);
335
- expect(updated.candidateDispatch?.[0]?.renderableIndex).toBe(1);
336
- expect(persistent.inspect()).toMatchObject({
337
- fullRebuilds: 1,
338
- deltaFrames: 1,
339
- projectionRecords: 2,
340
- });
341
- expect(persistent.inspect().topology.patches).toBeGreaterThan(0);
342
- });
343
-
344
- it('patches ordinary topology in a multi-World composition without a full rebuild', () => {
345
- const firstWorld = new World();
346
- const secondWorld = new World();
347
- const first = firstWorld.spawn({ component: Transform, data: {} }).unwrap();
348
- const second = secondWorld.spawn({ component: Transform, data: {} }).unwrap();
349
- propagateTransforms(firstWorld).unwrap();
350
- propagateTransforms(secondWorld).unwrap();
351
- const persistent = new PersistentRenderScene();
352
- const gpuDraw = {
353
- submeshIndex: 0,
354
- passIndex: 0,
355
- queue: 2000,
356
- kind: 'indexed' as const,
357
- first: 0,
358
- count: 36,
359
- baseVertex: 0,
360
- materialSlot: 0,
361
- topology: 'triangle-list',
362
- pipelineClass: 'opaque-pbr',
363
- materialResourceClass: 'plain',
364
- } satisfies GpuDrivenDrawSnapshot;
365
- let builds = 0;
366
- const build = () => {
367
- builds += 1;
368
- return {
369
- ...compositionFrame([{ entity: first, worldId: 0 }]),
370
- renderables: [
371
- {
372
- ...renderable(first, firstWorld.get(first, Transform).unwrap().world),
373
- worldId: 0,
374
- gpuDrivenDraws: [gpuDraw],
375
- },
376
- ],
377
- };
378
- };
379
- const refresh = (
380
- world: World,
381
- worldId: number,
382
- entity: EntityHandle,
383
- _current: ExtractedFrame,
384
- ) =>
385
- world === secondWorld && entity === second
386
- ? {
387
- snapshot: {
388
- ...renderable(second, world.get(second, Transform).unwrap().world),
389
- worldId,
390
- gpuDrivenDraws: [gpuDraw],
391
- },
392
- candidateDispatch: [
393
- {
394
- entityIndex: second,
395
- materialHandle: 0,
396
- renderableIndex: 0,
397
- passIndex: 0,
398
- queue: 2000,
399
- layer: 0,
400
- tags: { LightMode: 'ShadowCaster' },
401
- renderState: undefined,
402
- defines: undefined,
403
- vertexEntry: 'vs_main',
404
- fragmentEntry: undefined,
405
- materialShaderId: 'forgeax::default-shadow-caster',
406
- paramSnapshot: {},
407
- } satisfies DispatchEntry,
408
- ],
409
- }
410
- : undefined;
411
-
412
- persistent.extractComposition(
413
- [firstWorld, secondWorld],
414
- { cameraOwner: 0, resourceOwner: 0 },
415
- 0,
416
- build,
417
- refresh,
418
- );
419
- secondWorld
420
- .addComponent(second, {
421
- component: MeshFilter,
422
- data: { assetHandle: toShared<'MeshAsset'>(0) },
423
- })
424
- .unwrap();
425
- secondWorld.addComponent(second, { component: MeshRenderer, data: {} }).unwrap();
426
- propagateTransforms(secondWorld).unwrap();
427
-
428
- const updated = persistent.extractComposition(
429
- [firstWorld, secondWorld],
430
- { cameraOwner: 0, resourceOwner: 0 },
431
- 0,
432
- build,
433
- refresh,
434
- );
435
-
436
- expect(builds).toBe(1);
437
- expect(updated.candidateRenderables?.map((candidate) => candidate.entityKey)).toEqual([
438
- first,
439
- second,
440
- ]);
441
- expect(updated.candidateDispatch?.map((entry) => entry.entityIndex)).toEqual([second]);
442
- expect(updated.candidateDispatch?.[0]?.renderableIndex).toBe(1);
443
- expect(persistent.inspect()).toMatchObject({
444
- fullRebuilds: 1,
445
- deltaFrames: 1,
446
- topologyEntitiesReconciled: 1,
447
- singleEntityExtractions: 1,
448
- projectionRecords: 2,
449
- });
450
- expect(persistent.inspect().topology.patches).toBeGreaterThan(0);
451
- });
452
-
453
- it('rebuilds on an asset epoch change', () => {
454
- const world = new World();
455
- const entity = world.spawn({ component: Transform, data: {} }).unwrap();
456
- propagateTransforms(world).unwrap();
457
- const persistent = new PersistentRenderScene();
458
- let builds = 0;
459
- const build = () => {
460
- builds += 1;
461
- return frame(renderable(entity, world.get(entity, Transform).unwrap().world));
462
- };
463
-
464
- persistent.extract(world, 0, build);
465
- persistent.extract(world, 1, build);
466
-
467
- expect(builds).toBe(2);
468
- expect(persistent.inspect().lastResyncReason).toBe('asset-catalog-changed');
469
- });
470
-
471
- it('refreshes camera state and CSM inputs without rebuilding the render projection', () => {
472
- const world = new World();
473
- const rendered = world.spawn({ component: Transform, data: {} }).unwrap();
474
- const camera = world
475
- .spawn(
476
- { component: Transform, data: { pos: [0, 0, 5] } },
477
- { component: Camera, data: { fov: Math.PI / 4, aspect: 1, near: 0.1, far: 100 } },
478
- )
479
- .unwrap();
480
- propagateTransforms(world).unwrap();
481
- const persistent = new PersistentRenderScene();
482
- let builds = 0;
483
- const build = () => {
484
- builds += 1;
485
- return frame(renderable(rendered, world.get(rendered, Transform).unwrap().world));
486
- };
487
- const refresh = (current: ExtractedFrame) => refreshExtractedFrameCameras(world, current);
488
-
489
- persistent.extract(world, 0, build, undefined, refresh);
490
- world.set(camera, Transform, { pos: [3, 0, 5] }).unwrap();
491
- propagateTransforms(world).unwrap();
492
- const moved = persistent.extract(world, 0, build, undefined, refresh);
493
-
494
- expect(builds).toBe(1);
495
- expect(moved.cameras[0]?.world[12]).toBe(3);
496
- expect(persistent.inspect()).toMatchObject({
497
- fullRebuilds: 1,
498
- cameraUpdates: 1,
499
- deltaFrames: 1,
500
- projectionRecords: 1,
501
- });
502
- });
503
-
504
- it('changes camera view identity after a World attachment generation is replaced', () => {
505
- const world = new World();
506
- world
507
- .spawn(
508
- { component: Transform, data: {} },
509
- { component: Camera, data: { fov: Math.PI / 4, aspect: 1, near: 0.1, far: 100 } },
510
- )
511
- .unwrap();
512
- const persistent = new PersistentRenderScene();
513
- const build = () => ({ ...frame(), cameras: extractCameraSnapshots(world) });
514
-
515
- const first = persistent.extract(world, 0, build).cameras[0];
516
- persistent.detach(world);
517
- const second = persistent.extract(world, 0, build).cameras[0];
518
-
519
- expect(first).toBeDefined();
520
- expect(second).toBeDefined();
521
- expect(first?.entityKey).toBe(second?.entityKey);
522
- expect(first?.worldId).not.toBe(second?.worldId);
523
- expect(temporalViewId(first?.worldId ?? -1, first?.entityKey ?? -1)).not.toBe(
524
- temporalViewId(second?.worldId ?? -1, second?.entityKey ?? -1),
525
- );
526
- });
527
-
528
- it('refreshes post-process resource data without rebuilding the render domain', () => {
529
- const world = new World();
530
- const rendered = world.spawn({ component: Transform, data: {} }).unwrap();
531
- const paramsEntity = world
532
- .spawn({
533
- component: PostProcessParams,
534
- data: { shader: 'test::motion-blur', data: new Uint8Array([1, 2, 3, 4]) },
535
- })
536
- .unwrap();
537
- propagateTransforms(world).unwrap();
538
- const persistent = new PersistentRenderScene();
539
- let builds = 0;
540
- const build = () => {
541
- builds += 1;
542
- return {
543
- ...frame(renderable(rendered, world.get(rendered, Transform).unwrap().world)),
544
- postProcessParams: new Map([
545
- ['test::motion-blur', world.get(paramsEntity, PostProcessParams).unwrap().data],
546
- ]),
547
- };
548
- };
549
- const refresh = (current: ExtractedFrame) => ({
550
- ...current,
551
- postProcessParams: new Map([
552
- ['test::motion-blur', world.get(paramsEntity, PostProcessParams).unwrap().data],
553
- ]),
554
- });
555
-
556
- persistent.extract(world, 0, build, undefined, undefined, undefined, refresh);
557
- world
558
- .set(paramsEntity, PostProcessParams, {
559
- data: new Uint8Array([5, 6, 7, 8]),
560
- })
561
- .unwrap();
562
- const updated = persistent.extract(world, 0, build, undefined, undefined, undefined, refresh);
563
-
564
- expect(builds).toBe(1);
565
- expect([...(updated.postProcessParams.get('test::motion-blur') ?? [])]).toEqual([5, 6, 7, 8]);
566
- expect(persistent.inspect()).toMatchObject({
567
- fullRebuilds: 1,
568
- deltaFrames: 1,
569
- resourceUpdates: 1,
570
- projectionRecords: 1,
571
- });
572
- });
573
-
574
- it('refreshes light resources without rebuilding the render domain', () => {
575
- const world = new World();
576
- const rendered = world.spawn({ component: Transform, data: {} }).unwrap();
577
- const light = world
578
- .spawn(
579
- { component: Transform, data: { pos: [1, 2, 3] } },
580
- { component: PointLight, data: { intensity: 2, range: 8 } },
581
- )
582
- .unwrap();
583
- propagateTransforms(world).unwrap();
584
- const persistent = new PersistentRenderScene();
585
- let builds = 0;
586
- const build = () => {
587
- builds += 1;
588
- return frame(renderable(rendered, world.get(rendered, Transform).unwrap().world));
589
- };
590
- const refresh = (current: ExtractedFrame) => refreshExtractedFrameLights(world, current);
591
-
592
- persistent.extract(world, 0, build, undefined, undefined, undefined, undefined, refresh);
593
- world.set(light, PointLight, { intensity: 6 }).unwrap();
594
- const updated = persistent.extract(
595
- world,
596
- 0,
597
- build,
598
- undefined,
599
- undefined,
600
- undefined,
601
- undefined,
602
- refresh,
603
- );
604
-
605
- expect(builds).toBe(1);
606
- expect(updated.lights.point[0]?.intensity).toBe(6);
607
- expect(updated.lights.point[0]?.position).toEqual(vec3.create(1, 2, 3));
608
- expect(persistent.inspect()).toMatchObject({
609
- fullRebuilds: 1,
610
- deltaFrames: 1,
611
- resourceUpdates: 1,
612
- projectionRecords: 1,
613
- });
614
- });
615
-
616
- it('publishes camera-refresh CSM matrices from the same candidate-aware plan', () => {
617
- const world = new World();
618
- const caster = world.spawn({ component: Transform, data: { pos: [0, 20, -8] } }).unwrap();
619
- const camera = world
620
- .spawn(
621
- { component: Transform, data: { pos: [0, 0, 5] } },
622
- { component: Camera, data: { fov: Math.PI / 3, aspect: 1, near: 0.1, far: 100 } },
623
- )
624
- .unwrap();
625
- propagateTransforms(world).unwrap();
626
-
627
- const casterWorld = new Float32Array(world.get(caster, Transform).unwrap().world);
628
- const casterSnapshot: RenderableSnapshot = {
629
- ...renderable(caster, casterWorld),
630
- localAabb: new Float32Array([-1, -1, -1, 1, 1, 1]),
631
- candidateIndex: 0,
632
- };
633
- const cameraWorld = () => new Float32Array(world.get(camera, Transform).unwrap().world);
634
- const build = () => csmCandidateFrame(casterSnapshot, cameraWorld());
635
- const refresh = (current: ExtractedFrame) => refreshExtractedFrameCameras(world, current);
636
- const persistent = new PersistentRenderScene();
637
-
638
- persistent.extract(world, 0, build, undefined, refresh);
639
- world.set(camera, Transform, { pos: [1, 0, 5] }).unwrap();
640
- propagateTransforms(world).unwrap();
641
- const moved = persistent.extract(world, 0, build, undefined, refresh);
642
- const plan = moved.lights.directionalCsm;
643
- expect(plan).toBeDefined();
644
- expect(plan?.cascades[0]?.casterRenderableIndices).toContain(0);
645
- expect(moved.lights.lightViewProj).toBeDefined();
646
- if (plan === undefined || moved.lights.lightViewProj === undefined) return;
647
-
648
- for (let index = 0; index < plan.cascades.length; index += 1) {
649
- expect(Array.from(plan.cascades[index]?.lightViewProj ?? [])).toEqual(
650
- Array.from(moved.lights.lightViewProj[index] ?? []),
651
- );
652
- }
653
- expect(Array.from(plan.splitPlanes)).toEqual(Array.from(moved.lights.splitPlanes ?? []));
654
- expect(moved.lights.cascadeCount).toBe(plan.cascadeCount);
655
- expect(moved.lights.cascadeBlend).toBe(plan.cascadeBlend);
656
- expect(moved.lights.shadowMapSize).toBe(plan.shadowMapSize);
657
- expect(moved.lights.lightViewProj).toBe(plan.lightViewProj);
658
- expect(moved.lights.splitPlanes).toBe(plan.splitPlanes);
659
- expect(moved.lights.cascades).toBe(plan.cascades);
660
- });
661
-
662
- it('reuses the dispatch membership owner across camera-only persistent culls', () => {
663
- const world = new World();
664
- const caster = world.spawn({ component: Transform, data: { pos: [0, 20, -8] } }).unwrap();
665
- const camera = world
666
- .spawn(
667
- { component: Transform, data: { pos: [0, 0, 5] } },
668
- { component: Camera, data: { fov: Math.PI / 3, aspect: 1, near: 0.1, far: 100 } },
669
- )
670
- .unwrap();
671
- propagateTransforms(world).unwrap();
672
-
673
- const casterSnapshot: RenderableSnapshot = {
674
- ...renderable(caster, new Float32Array(world.get(caster, Transform).unwrap().world)),
675
- localAabb: new Float32Array([-1, -1, -1, 1, 1, 1]),
676
- candidateIndex: 0,
677
- };
678
- const build = () =>
679
- csmCandidateFrame(
680
- casterSnapshot,
681
- new Float32Array(world.get(camera, Transform).unwrap().world),
682
- );
683
- const refresh = (current: ExtractedFrame) => refreshExtractedFrameCameras(world, current);
684
- const persistent = new PersistentRenderScene();
685
-
686
- const initial = persistent.extract(world, 0, build, undefined, refresh);
687
- expect(initial.candidateDispatchMembership).toBeDefined();
688
- const candidateDispatch = initial.candidateDispatch;
689
- const candidateDispatchMembership = initial.candidateDispatchMembership;
690
- const candidateDomain = initial.candidateDomain;
691
-
692
- expect(initial.candidateRenderables).toBe(candidateDomain?.renderables);
693
- expect(candidateDispatch).toBe(candidateDomain?.dispatch);
694
-
695
- world.set(camera, Transform, { pos: [1, 0, 5] }).unwrap();
696
- propagateTransforms(world).unwrap();
697
- const moved = persistent.extract(world, 0, build, undefined, refresh);
698
-
699
- expect(moved.candidateDispatch).toBe(candidateDispatch);
700
- expect(moved.candidateDispatchMembership).toBe(candidateDispatchMembership);
701
- expect(moved.candidateDomain).toBe(candidateDomain);
702
- expect(moved.candidateRenderables).toBe(candidateDomain?.renderables);
703
- expect(moved.candidateDispatchMembership?.shadowCasterCandidateIndices.has(0)).toBe(true);
704
- });
705
-
706
- it('remaps candidate-domain identity when attaching a nonzero World render id', () => {
707
- const identity = new Float32Array(16);
708
- identity[0] = 1;
709
- identity[5] = 1;
710
- identity[10] = 1;
711
- identity[15] = 1;
712
- const persistent = new PersistentRenderScene();
713
-
714
- persistent.extract(new World(), 0, () => csmCandidateFrame(renderable(1, identity), identity));
715
-
716
- const secondWorld = new World();
717
- const attached = persistent.extract(secondWorld, 0, () =>
718
- csmCandidateFrame(renderable(2, identity), identity),
719
- );
720
-
721
- expect(attached.candidateDomain?.renderables[0]?.worldId).toBe(1);
722
- expect(attached.candidateDomain?.indexByIdentity.get('1:2')).toBe(0);
723
- expect(
724
- attached.lights.directionalCsm?.cascades.some((cascade) =>
725
- Array.from(cascade.casterRenderableIndices).includes(0),
726
- ),
727
- ).toBe(true);
728
- });
729
-
730
- it('rebases candidate identity, dispatch, and CSM membership after delta removal', () => {
731
- const world = new World();
732
- const first = world.spawn({ component: Transform, data: { pos: [0, 0, -5] } }).unwrap();
733
- const second = world.spawn({ component: Transform, data: { pos: [2, 0, -6] } }).unwrap();
734
- const third = world.spawn({ component: Transform, data: { pos: [-2, 0, -7] } }).unwrap();
735
- const camera = world
736
- .spawn(
737
- { component: Transform, data: { pos: [0, 0, 5] } },
738
- { component: Camera, data: { fov: Math.PI / 3, aspect: 1, near: 0.1, far: 100 } },
739
- )
740
- .unwrap();
741
- propagateTransforms(world).unwrap();
742
-
743
- const entities = [first, second, third] as const;
744
- const build = () => {
745
- const base = frame();
746
- const candidates = entities.map((entity, candidateIndex) => ({
747
- ...renderable(entity, world.get(entity, Transform).unwrap().world),
748
- localAabb: new Float32Array([-1, -1, -1, 1, 1, 1]),
749
- candidateIndex,
750
- }));
751
- const candidateDispatch = candidates.map(
752
- (candidate, renderableIndex) =>
753
- ({
754
- entityIndex: candidate.entityKey,
755
- materialHandle: 0,
756
- renderableIndex,
757
- passIndex: 0,
758
- queue: 2000,
759
- layer: 0,
760
- tags: { LightMode: 'ShadowCaster' },
761
- renderState: undefined,
762
- defines: undefined,
763
- vertexEntry: 'vs_main',
764
- fragmentEntry: undefined,
765
- materialShaderId: 'forgeax::default-shadow-caster',
766
- paramSnapshot: {},
767
- }) satisfies DispatchEntry,
768
- );
769
- return {
770
- ...base,
771
- cameras: [csmCamera(new Float32Array(world.get(camera, Transform).unwrap().world))],
772
- renderables: candidates,
773
- dispatch: candidateDispatch,
774
- candidateRenderables: candidates,
775
- candidateDispatch,
776
- lights: {
777
- ...base.lights,
778
- directionalCount: 1,
779
- cascadeCount: 2,
780
- cascadeBlend: 0.25,
781
- shadowMapSize: 512,
782
- directionalCsmConfig: {
783
- cascadeCount: 2,
784
- splitLambda: 0.5,
785
- cascadeBlend: 0.25,
786
- mapSize: 512,
787
- shadowDistance: 40,
788
- pcfKernelSize: 3,
789
- },
790
- directionalCsmDirection: vec3.create(0.4, -0.8, 0.2),
791
- },
792
- };
793
- };
794
-
795
- const persistent = new PersistentRenderScene();
796
- persistent.extract(world, 0, build);
797
- world.despawn(first).unwrap();
798
- const projected = persistent.extract(world, 0, build);
799
-
800
- expect(projected.candidateRenderables?.map((candidate) => candidate.entityKey)).toEqual([
801
- second,
802
- third,
803
- ]);
804
- expect(projected.candidateRenderables?.map((candidate) => candidate.candidateIndex)).toEqual([
805
- 0, 1,
806
- ]);
807
- expect(projected.candidateDispatch?.map((entry) => entry.entityIndex)).toEqual([second, third]);
808
- expect(projected.candidateDispatch?.map((entry) => entry.renderableIndex)).toEqual([0, 1]);
809
- expect(projected.renderables.map((candidate) => candidate.entityKey)).not.toContain(first);
810
-
811
- const casterIndices = new Set(
812
- projected.lights.directionalCsm?.cascades.flatMap((cascade) => [
813
- ...cascade.casterRenderableIndices,
814
- ]),
815
- );
816
- expect(casterIndices).toEqual(new Set([0, 1]));
817
- expect(casterIndices).not.toContain(2);
818
- });
819
-
820
- it('skips CPU camera culling only while production coverage matches', () => {
821
- const world = new World();
822
- const rendered = world.spawn({ component: Transform, data: { pos: [100, 0, 0] } }).unwrap();
823
- const camera = world
824
- .spawn(
825
- { component: Transform, data: { pos: [0, 0, 5] } },
826
- { component: Camera, data: { fov: Math.PI / 4, aspect: 1, near: 0.1, far: 100 } },
827
- )
828
- .unwrap();
829
- propagateTransforms(world).unwrap();
830
- const persistent = new PersistentRenderScene();
831
- const build = () =>
832
- frame({
833
- ...renderable(rendered, world.get(rendered, Transform).unwrap().world),
834
- localAabb: new Float32Array([-0.5, -0.5, -0.5, 0.5, 0.5, 0.5]),
835
- gpuDrivenDraws: [
836
- {
837
- submeshIndex: 0,
838
- passIndex: 0,
839
- queue: 2000,
840
- kind: 'indexed',
841
- first: 0,
842
- count: 36,
843
- baseVertex: 0,
844
- materialSlot: 0,
845
- topology: 'triangle-list',
846
- pipelineClass: 'opaque-pbr',
847
- materialResourceClass: 'plain',
848
- },
849
- ],
850
- });
851
- const refresh = (current: ExtractedFrame) => refreshExtractedFrameCameras(world, current);
852
-
853
- persistent.extract(world, 0, build, undefined, refresh, '0:urp');
854
- expect(persistent.inspect().topology.ineligible).toBe(0);
855
-
856
- world.set(camera, Transform, { pos: [1, 0, 5] }).unwrap();
857
- propagateTransforms(world).unwrap();
858
- const fallback = persistent.extract(world, 0, build, undefined, refresh, '0:urp');
859
- expect(fallback).toMatchObject({ frustumStats: { culled: 1, total: 1 } });
860
- expect(fallback.renderables).toHaveLength(0);
861
-
862
- persistent.setGpuDrivenCoverage(world, '0:urp', true);
863
- world.set(camera, Transform, { pos: [2, 0, 5] }).unwrap();
864
- propagateTransforms(world).unwrap();
865
- const owned = persistent.extract(world, 0, build, undefined, refresh, '0:urp');
866
- expect(owned.renderables).toHaveLength(1);
867
-
868
- world.set(camera, Transform, { pos: [3, 0, 5] }).unwrap();
869
- propagateTransforms(world).unwrap();
870
- const invalidated = persistent.extract(world, 0, build, undefined, refresh, '1:urp');
871
- expect(invalidated).toMatchObject({ frustumStats: { culled: 1, total: 1 } });
872
- expect(invalidated.renderables).toHaveLength(0);
873
- });
874
-
875
- it('refreshes only renderables that reference an explicitly changed shared payload', () => {
876
- const world = new World();
877
- const entity = world.spawn({ component: Transform, data: {} }).unwrap();
878
- const handle = world.allocSharedRef<'MaterialAsset', { value: number }>('MaterialAsset', {
879
- value: 1,
880
- });
881
- propagateTransforms(world).unwrap();
882
- const persistent = new PersistentRenderScene();
883
- const initialMaterial = {
884
- baseColor: new Float32Array([1, 0, 0]),
885
- metallic: 0,
886
- roughness: 1,
887
- materialHandle: Number(handle),
888
- } as MaterialSnapshot;
889
- let builds = 0;
890
- const build = () => {
891
- builds += 1;
892
- return frame(
893
- renderable(entity, world.get(entity, Transform).unwrap().world, initialMaterial),
894
- );
895
- };
896
-
897
- persistent.extract(world, 0, build);
898
- const resolved = world.sharedRefs.resolve<'MaterialAsset', { value: number }>(handle).unwrap();
899
- resolved.value = 2;
900
- world.sharedRefs.markChanged(handle).unwrap();
901
- const updated = persistent.extract(world, 0, build, (snapshot) => {
902
- const nextMaterial = {
903
- ...snapshot.material,
904
- baseColor: new Float32Array([0, 1, 0]),
905
- } as MaterialSnapshot;
906
- return { ...snapshot, material: nextMaterial, materials: [nextMaterial] };
907
- });
908
-
909
- expect(builds).toBe(1);
910
- expect(updated.renderables[0]?.material.baseColor[1]).toBe(1);
911
- expect(persistent.inspect()).toMatchObject({
912
- fullRebuilds: 1,
913
- deltaFrames: 1,
914
- materialUpdates: 1,
915
- });
916
- });
917
-
918
- it('refreshes an ordinary instance range without rebuilding the World projection', () => {
919
- const first = new Float32Array(16);
920
- first[0] = 1;
921
- first[5] = 1;
922
- first[10] = 1;
923
- first[15] = 1;
924
- const second = new Float32Array(first);
925
- second[12] = 2;
926
- const world = new World();
927
- const entity = world
928
- .spawn(
929
- { component: Transform, data: {} },
930
- { component: Instances, data: { transforms: first } },
931
- )
932
- .unwrap();
933
- propagateTransforms(world).unwrap();
934
- const persistent = new PersistentRenderScene();
935
- let builds = 0;
936
- const build = () => {
937
- builds += 1;
938
- return frame({
939
- ...renderable(entity, world.get(entity, Transform).unwrap().world),
940
- instances: {
941
- transforms: new Float32Array(world.get(entity, Instances).unwrap().transforms),
942
- instanceCount: 1,
943
- cacheKey: entity,
944
- archVersion: 1,
945
- },
946
- });
947
- };
948
-
949
- persistent.extract(world, 0, build);
950
- world.set(entity, Instances, { transforms: new Float32Array([...first, ...second]) }).unwrap();
951
- const updated = persistent.extract(world, 0, build);
952
-
953
- expect(builds).toBe(1);
954
- expect(updated.renderables[0]?.instances?.instanceCount).toBe(2);
955
- expect(updated.renderables[0]?.instances?.transforms[28]).toBe(2);
956
- expect(persistent.inspect()).toMatchObject({
957
- fullRebuilds: 1,
958
- deltaFrames: 1,
959
- instanceUpdates: 1,
960
- });
961
- });
962
-
963
- it('ignores unrelated gameplay component changes', () => {
964
- const world = new World();
965
- const entity = world
966
- .spawn({ component: Transform, data: {} }, { component: GameplayState, data: { value: 1 } })
967
- .unwrap();
968
- propagateTransforms(world).unwrap();
969
- const persistent = new PersistentRenderScene();
970
- let builds = 0;
971
- const build = () => {
972
- builds += 1;
973
- return frame(renderable(entity, world.get(entity, Transform).unwrap().world));
974
- };
975
-
976
- const initial = persistent.extract(world, 0, build);
977
- world.set(entity, GameplayState, { value: 2 }).unwrap();
978
- const unchanged = persistent.extract(world, 0, build);
979
-
980
- expect(unchanged).toBe(initial);
981
- expect(builds).toBe(1);
982
- expect(persistent.inspect()).toMatchObject({
983
- noChangeFrames: 1,
984
- deltaFrames: 0,
985
- worldEntitiesScanned: 0,
986
- });
987
- });
988
-
989
- it('rebuilds the persistent candidate when Disabled is added', () => {
990
- const world = new World();
991
- const entity = world.spawn({ component: Transform, data: {} }).unwrap();
992
- propagateTransforms(world).unwrap();
993
- const persistent = new PersistentRenderScene();
994
- let builds = 0;
995
- const build = () => {
996
- builds += 1;
997
- return world.hasComponent(entity, Disabled)
998
- ? frame()
999
- : frame(renderable(entity, world.get(entity, Transform).unwrap().world));
1000
- };
1001
-
1002
- const active = persistent.extract(world, 0, build);
1003
- world.addComponent(entity, { component: Disabled, data: {} }).unwrap();
1004
- const disabled = persistent.extract(world, 0, build);
1005
-
1006
- expect(active.renderables).toHaveLength(1);
1007
- expect(disabled.renderables).toHaveLength(0);
1008
- expect(builds).toBe(2);
1009
- expect(persistent.inspect()).toMatchObject({
1010
- fullRebuilds: 2,
1011
- lastResyncReason: 'unsupported-change',
1012
- projectionRecords: 0,
1013
- });
1014
- });
1015
-
1016
- it('rebuilds the persistent candidate when Disabled is removed', () => {
1017
- const world = new World();
1018
- const entity = world
1019
- .spawn({ component: Transform, data: {} }, { component: Disabled, data: {} })
1020
- .unwrap();
1021
- propagateTransforms(world).unwrap();
1022
- const persistent = new PersistentRenderScene();
1023
- let builds = 0;
1024
- const build = () => {
1025
- builds += 1;
1026
- return world.hasComponent(entity, Disabled)
1027
- ? frame()
1028
- : frame(renderable(entity, world.get(entity, Transform).unwrap().world));
1029
- };
1030
-
1031
- const disabled = persistent.extract(world, 0, build);
1032
- world.removeComponent(entity, Disabled).unwrap();
1033
- const restored = persistent.extract(world, 0, build);
1034
-
1035
- expect(disabled.renderables).toHaveLength(0);
1036
- expect(restored.renderables).toHaveLength(1);
1037
- expect(builds).toBe(2);
1038
- expect(persistent.inspect()).toMatchObject({
1039
- fullRebuilds: 2,
1040
- lastResyncReason: 'unsupported-change',
1041
- projectionRecords: 1,
1042
- });
1043
- });
1044
-
1045
- it('shares Disabled structural invalidation with the single-World composition path', () => {
1046
- const world = new World();
1047
- const entity = world.spawn({ component: Transform, data: {} }).unwrap();
1048
- propagateTransforms(world).unwrap();
1049
- const persistent = new PersistentRenderScene();
1050
- let builds = 0;
1051
- const build = () => {
1052
- builds += 1;
1053
- return world.hasComponent(entity, Disabled)
1054
- ? frame()
1055
- : frame(renderable(entity, world.get(entity, Transform).unwrap().world));
1056
- };
1057
- const owner = { cameraOwner: 0, resourceOwner: 0 };
1058
-
1059
- const active = persistent.extractComposition([world], owner, 0, build);
1060
- world.addComponent(entity, { component: Disabled, data: {} }).unwrap();
1061
- const disabled = persistent.extractComposition([world], owner, 0, build);
1062
- world.removeComponent(entity, Disabled).unwrap();
1063
- const restored = persistent.extractComposition([world], owner, 0, build);
1064
-
1065
- expect(active.renderables).toHaveLength(1);
1066
- expect(disabled.renderables).toHaveLength(0);
1067
- expect(restored.renderables).toHaveLength(1);
1068
- expect(builds).toBe(3);
1069
- expect(persistent.inspect()).toMatchObject({
1070
- fullRebuilds: 3,
1071
- lastResyncReason: 'attach',
1072
- projectionRecords: 1,
1073
- });
1074
- });
1075
-
1076
- it('projects entity deletion without a full extract rebuild', () => {
1077
- const world = new World();
1078
- const first = world.spawn({ component: Transform, data: {} }).unwrap();
1079
- const second = world.spawn({ component: Transform, data: { pos: [1, 0, 0] } }).unwrap();
1080
- propagateTransforms(world).unwrap();
1081
- const persistent = new PersistentRenderScene();
1082
- let builds = 0;
1083
- const build = (): ExtractedFrame => {
1084
- builds += 1;
1085
- const initial = frame(renderable(first, world.get(first, Transform).unwrap().world));
1086
- return {
1087
- ...initial,
1088
- renderables: [
1089
- initial.renderables[0] as RenderableSnapshot,
1090
- renderable(second, world.get(second, Transform).unwrap().world),
1091
- ],
1092
- };
1093
- };
1094
-
1095
- persistent.extract(world, 0, build);
1096
- world.despawn(second).unwrap();
1097
- const projected = persistent.extract(world, 0, build);
1098
-
1099
- expect(builds).toBe(1);
1100
- expect(projected.renderables.map((snapshot) => snapshot.entityKey)).toEqual([first]);
1101
- expect(persistent.inspect()).toMatchObject({
1102
- fullRebuilds: 1,
1103
- deltaFrames: 1,
1104
- projectionRecords: 1,
1105
- });
1106
- });
1107
-
1108
- it('does not rebuild when a stale derived transform is followed by entity removal', () => {
1109
- const world = new World();
1110
- const first = world.spawn({ component: Transform, data: {} }).unwrap();
1111
- const removed = world.spawn({ component: Transform, data: { pos: [1, 0, 0] } }).unwrap();
1112
- propagateTransforms(world).unwrap();
1113
- const persistent = new PersistentRenderScene();
1114
- let builds = 0;
1115
- const build = (): ExtractedFrame => {
1116
- builds += 1;
1117
- const snapshots = [renderable(first, world.get(first, Transform).unwrap().world)];
1118
- if (world.hasComponent(removed, Transform)) {
1119
- snapshots.push(renderable(removed, world.get(removed, Transform).unwrap().world));
1120
- }
1121
- return frame(...snapshots);
1122
- };
1123
-
1124
- persistent.extract(world, 0, build);
1125
- world.set(removed, Transform, { pos: [2, 0, 0] }).unwrap();
1126
- propagateTransforms(world).unwrap();
1127
- world.despawn(removed).unwrap();
1128
- const projected = persistent.extract(world, 0, build);
1129
-
1130
- expect(builds).toBe(1);
1131
- expect(projected.renderables.map((snapshot) => snapshot.entityKey)).toEqual([first]);
1132
- expect(persistent.inspect()).toMatchObject({
1133
- fullRebuilds: 1,
1134
- deltaFrames: 1,
1135
- projectionRecords: 1,
1136
- });
1137
- });
1138
-
1139
- it('ignores transform changes on entities outside the render projection', () => {
1140
- const world = new World();
1141
- const rendered = world.spawn({ component: Transform, data: {} }).unwrap();
1142
- const gameplayOnly = world.spawn({ component: Transform, data: {} }).unwrap();
1143
- propagateTransforms(world).unwrap();
1144
- const persistent = new PersistentRenderScene();
1145
- let builds = 0;
1146
- const build = () => {
1147
- builds += 1;
1148
- return frame(renderable(rendered, world.get(rendered, Transform).unwrap().world));
1149
- };
1150
-
1151
- const initial = persistent.extract(world, 0, build);
1152
- world.set(gameplayOnly, Transform, { pos: [5, 0, 0] }).unwrap();
1153
- propagateTransforms(world).unwrap();
1154
- const unchanged = persistent.extract(world, 0, build);
1155
-
1156
- expect(unchanged).toBe(initial);
1157
- expect(builds).toBe(1);
1158
- });
1159
-
1160
- it('reconciles hierarchy faults and same-process repair even when propagation reports an error', () => {
1161
- const world = new World();
1162
- const parent = world.spawn({ component: Transform, data: { pos: [4, 0, 0] } }).unwrap();
1163
- const child = world
1164
- .spawn(
1165
- { component: Transform, data: { pos: [1, 0, 0] } },
1166
- { component: ChildOf, data: { parent } },
1167
- )
1168
- .unwrap();
1169
- propagateTransforms(world).unwrap();
1170
- const persistent = new PersistentRenderScene();
1171
- let builds = 0;
1172
- const build = () => {
1173
- builds += 1;
1174
- return frame(renderable(child, world.get(child, Transform).unwrap().world));
1175
- };
1176
-
1177
- persistent.extract(world, 0, build);
1178
- expect(world.get(child, Transform).unwrap().world[12]).toBe(5);
1179
-
1180
- world.set(child, ChildOf, { parent: 0xfffffffe as EntityHandle }).unwrap();
1181
- expect(propagateTransforms(world).ok).toBe(false);
1182
- const fault = persistent.extract(world, 0, build);
1183
- expect(fault.renderables[0]?.transform.world[12]).toBe(1);
1184
-
1185
- world.set(child, ChildOf, { parent }).unwrap();
1186
- propagateTransforms(world).unwrap();
1187
- const repaired = persistent.extract(world, 0, build);
1188
- expect(repaired.renderables[0]?.transform.world[12]).toBe(5);
1189
- expect(builds).toBe(3);
1190
- expect(persistent.inspect()).toMatchObject({
1191
- fullRebuilds: 3,
1192
- lastResyncReason: 'unsupported-change',
1193
- });
1194
- });
1195
-
1196
- it('rebuilds lost GPU tables from the retained CPU projection without traversing World', () => {
1197
- const world = new World();
1198
- const entity = world.spawn({ component: Transform, data: {} }).unwrap();
1199
- propagateTransforms(world).unwrap();
1200
- let device = new RhiNullDevice(
1201
- new RhiNullQueue(),
1202
- (bookkeeper, ownedDevice) => new RhiNullCommandEncoder(bookkeeper, ownedDevice),
1203
- );
1204
- const persistent = new PersistentRenderScene({ getDevice: () => device });
1205
- let builds = 0;
1206
- const build = () => {
1207
- builds += 1;
1208
- return frame(renderable(entity, world.get(entity, Transform).unwrap().world));
1209
- };
1210
-
1211
- persistent.extract(world, 0, build);
1212
- expect(persistent.inspect().gpu).toMatchObject({ status: 'resident', fullRebuilds: 1 });
1213
-
1214
- persistent.resetGpuForRecover();
1215
- device = new RhiNullDevice(
1216
- new RhiNullQueue(),
1217
- (bookkeeper, ownedDevice) => new RhiNullCommandEncoder(bookkeeper, ownedDevice),
1218
- );
1219
- persistent.extract(world, 0, build);
1220
-
1221
- expect(builds).toBe(1);
1222
- expect(persistent.inspect()).toMatchObject({
1223
- fullRebuilds: 1,
1224
- noChangeFrames: 1,
1225
- projectionRecords: 1,
1226
- gpu: { status: 'resident', fullRebuilds: 1 },
1227
- });
1228
- });
1229
-
1230
- it('releases CPU and GPU state when a World detaches', () => {
1231
- const world = new World();
1232
- const entity = world.spawn({ component: Transform, data: {} }).unwrap();
1233
- propagateTransforms(world).unwrap();
1234
- const device = new RhiNullDevice(
1235
- new RhiNullQueue(),
1236
- (bookkeeper, ownedDevice) => new RhiNullCommandEncoder(bookkeeper, ownedDevice),
1237
- );
1238
- const persistent = new PersistentRenderScene({ getDevice: () => device });
1239
- let builds = 0;
1240
- const build = () => {
1241
- builds += 1;
1242
- return frame(renderable(entity, world.get(entity, Transform).unwrap().world));
1243
- };
1244
-
1245
- persistent.extract(world, 0, build);
1246
- persistent.detach(world);
1247
-
1248
- expect(persistent.inspect()).toMatchObject({
1249
- projectionRecords: 0,
1250
- gpu: { status: 'inactive' },
1251
- });
1252
- persistent.extract(world, 0, build);
1253
- expect(builds).toBe(2);
1254
- });
1255
-
1256
- it('keeps renderer-local WorldRenderId stable when composition order changes', () => {
1257
- const firstWorld = new World();
1258
- const secondWorld = new World();
1259
- const firstEntity = firstWorld.spawn({ component: Transform, data: {} }).unwrap();
1260
- const secondEntity = secondWorld.spawn({ component: Transform, data: {} }).unwrap();
1261
- propagateTransforms(firstWorld).unwrap();
1262
- propagateTransforms(secondWorld).unwrap();
1263
- const persistent = new PersistentRenderScene();
1264
-
1265
- const initial = persistent.extractComposition(
1266
- [firstWorld, secondWorld],
1267
- { cameraOwner: 0, resourceOwner: 0 },
1268
- 0,
1269
- () =>
1270
- compositionFrame([
1271
- { entity: firstEntity, worldId: 0 },
1272
- { entity: secondEntity, worldId: 1 },
1273
- ]),
1274
- );
1275
- const firstWorldId = initial.renderables[0]?.worldId;
1276
- const secondWorldId = initial.renderables[1]?.worldId;
1277
-
1278
- const reordered = persistent.extractComposition(
1279
- [secondWorld, firstWorld],
1280
- { cameraOwner: 0, resourceOwner: 0 },
1281
- 0,
1282
- () =>
1283
- compositionFrame([
1284
- { entity: secondEntity, worldId: 0 },
1285
- { entity: firstEntity, worldId: 1 },
1286
- ]),
1287
- );
1288
-
1289
- expect(firstWorldId).toBeDefined();
1290
- expect(secondWorldId).toBeDefined();
1291
- expect(firstWorldId).not.toBe(secondWorldId);
1292
- expect(reordered.renderables[0]?.worldId).toBe(secondWorldId);
1293
- expect(reordered.renderables[1]?.worldId).toBe(firstWorldId);
1294
- });
1295
-
1296
- it('retires WorldRenderId when a World detaches before the same object reattaches', () => {
1297
- const world = new World();
1298
- const entity = world.spawn({ component: Transform, data: {} }).unwrap();
1299
- propagateTransforms(world).unwrap();
1300
- const persistent = new PersistentRenderScene();
1301
- const build = () => frame(renderable(entity, world.get(entity, Transform).unwrap().world));
1302
-
1303
- const initialWorldId = persistent.extract(world, 0, build).renderables[0]?.worldId;
1304
- persistent.detach(world);
1305
- const reattachedWorldId = persistent.extract(world, 0, build).renderables[0]?.worldId;
1306
-
1307
- expect(initialWorldId).toBeDefined();
1308
- expect(reattachedWorldId).toBeDefined();
1309
- expect(reattachedWorldId).not.toBe(initialWorldId);
1310
- });
1311
- });