@forgeax/engine-render 0.1.2

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 (1172) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +1019 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/__tests__/analytic-sky-contract.test.d.ts +2 -0
  5. package/dist/__tests__/analytic-sky-contract.test.d.ts.map +1 -0
  6. package/dist/__tests__/analytic-sky-falsify.test.d.ts +2 -0
  7. package/dist/__tests__/analytic-sky-falsify.test.d.ts.map +1 -0
  8. package/dist/__tests__/assets-runtime-handoff.integration.test.d.ts +2 -0
  9. package/dist/__tests__/assets-runtime-handoff.integration.test.d.ts.map +1 -0
  10. package/dist/__tests__/authoring-path.unit.test.d.ts +2 -0
  11. package/dist/__tests__/authoring-path.unit.test.d.ts.map +1 -0
  12. package/dist/__tests__/backend-selection-rhi-capture.test-d.d.ts +2 -0
  13. package/dist/__tests__/backend-selection-rhi-capture.test-d.d.ts.map +1 -0
  14. package/dist/__tests__/backend-selection.integration.test.d.ts +2 -0
  15. package/dist/__tests__/backend-selection.integration.test.d.ts.map +1 -0
  16. package/dist/__tests__/callback-inference.test-d.d.ts +2 -0
  17. package/dist/__tests__/callback-inference.test-d.d.ts.map +1 -0
  18. package/dist/__tests__/camera-temporal.test-d.d.ts +2 -0
  19. package/dist/__tests__/camera-temporal.test-d.d.ts.map +1 -0
  20. package/dist/__tests__/camera-temporal.test.d.ts +2 -0
  21. package/dist/__tests__/camera-temporal.test.d.ts.map +1 -0
  22. package/dist/__tests__/cluster-binner.test.d.ts +2 -0
  23. package/dist/__tests__/cluster-binner.test.d.ts.map +1 -0
  24. package/dist/__tests__/cluster-grid-default-surface.unit.test.d.ts +2 -0
  25. package/dist/__tests__/cluster-grid-default-surface.unit.test.d.ts.map +1 -0
  26. package/dist/__tests__/construct-renderer-identity.unit.test.d.ts +2 -0
  27. package/dist/__tests__/construct-renderer-identity.unit.test.d.ts.map +1 -0
  28. package/dist/__tests__/direct-extract-consumer-contract.test-d.d.ts +2 -0
  29. package/dist/__tests__/direct-extract-consumer-contract.test-d.d.ts.map +1 -0
  30. package/dist/__tests__/direct-light-snapshot.unit.test.d.ts +2 -0
  31. package/dist/__tests__/direct-light-snapshot.unit.test.d.ts.map +1 -0
  32. package/dist/__tests__/directional-shadow-probe-atlas-layout.unit.test.d.ts +2 -0
  33. package/dist/__tests__/directional-shadow-probe-atlas-layout.unit.test.d.ts.map +1 -0
  34. package/dist/__tests__/environment-inspection.test.d.ts +2 -0
  35. package/dist/__tests__/environment-inspection.test.d.ts.map +1 -0
  36. package/dist/__tests__/factory-contract.integration.test.d.ts +2 -0
  37. package/dist/__tests__/factory-contract.integration.test.d.ts.map +1 -0
  38. package/dist/__tests__/fallback-row-stride-surface.unit.test.d.ts +2 -0
  39. package/dist/__tests__/fallback-row-stride-surface.unit.test.d.ts.map +1 -0
  40. package/dist/__tests__/fog-ai-user.fixture.d.ts +2 -0
  41. package/dist/__tests__/fog-ai-user.fixture.d.ts.map +1 -0
  42. package/dist/__tests__/fog-custom-render-feature.fixture.d.ts +16 -0
  43. package/dist/__tests__/fog-custom-render-feature.fixture.d.ts.map +1 -0
  44. package/dist/__tests__/fog-custom-render-feature.integration.test.d.ts +2 -0
  45. package/dist/__tests__/fog-custom-render-feature.integration.test.d.ts.map +1 -0
  46. package/dist/__tests__/fog-inspection.integration.test.d.ts +2 -0
  47. package/dist/__tests__/fog-inspection.integration.test.d.ts.map +1 -0
  48. package/dist/__tests__/fog-owner-state.integration.test.d.ts +2 -0
  49. package/dist/__tests__/fog-owner-state.integration.test.d.ts.map +1 -0
  50. package/dist/__tests__/fog-pipeline-topology.integration.test.d.ts +2 -0
  51. package/dist/__tests__/fog-pipeline-topology.integration.test.d.ts.map +1 -0
  52. package/dist/__tests__/fog-public-surface.integration.test.d.ts +2 -0
  53. package/dist/__tests__/fog-public-surface.integration.test.d.ts.map +1 -0
  54. package/dist/__tests__/fog-ray-contract.integration.test.d.ts +2 -0
  55. package/dist/__tests__/fog-ray-contract.integration.test.d.ts.map +1 -0
  56. package/dist/__tests__/fog-source-absence.integration.test.d.ts +2 -0
  57. package/dist/__tests__/fog-source-absence.integration.test.d.ts.map +1 -0
  58. package/dist/__tests__/fog-temporal.integration.test.d.ts +2 -0
  59. package/dist/__tests__/fog-temporal.integration.test.d.ts.map +1 -0
  60. package/dist/__tests__/frame-chain.unit.test.d.ts +2 -0
  61. package/dist/__tests__/frame-chain.unit.test.d.ts.map +1 -0
  62. package/dist/__tests__/frame-observation.contract.test.d.ts +2 -0
  63. package/dist/__tests__/frame-observation.contract.test.d.ts.map +1 -0
  64. package/dist/__tests__/glyph-text-layout-recovery.unit.test.d.ts +2 -0
  65. package/dist/__tests__/glyph-text-layout-recovery.unit.test.d.ts.map +1 -0
  66. package/dist/__tests__/gpu-driven-indirect-raster-evidence.d.ts +6 -0
  67. package/dist/__tests__/gpu-driven-indirect-raster-evidence.d.ts.map +1 -0
  68. package/dist/__tests__/gpu-driven-indirect-raster.browser.test.d.ts +2 -0
  69. package/dist/__tests__/gpu-driven-indirect-raster.browser.test.d.ts.map +1 -0
  70. package/dist/__tests__/gpu-driven-indirect-raster.dawn.test.d.ts +2 -0
  71. package/dist/__tests__/gpu-driven-indirect-raster.dawn.test.d.ts.map +1 -0
  72. package/dist/__tests__/gpu-driven-production.integration.test.d.ts +2 -0
  73. package/dist/__tests__/gpu-driven-production.integration.test.d.ts.map +1 -0
  74. package/dist/__tests__/gpu-driven-scaling.unit.test.d.ts +2 -0
  75. package/dist/__tests__/gpu-driven-scaling.unit.test.d.ts.map +1 -0
  76. package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts +12 -0
  77. package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts.map +1 -0
  78. package/dist/__tests__/gpu-driven-view-graph.integration.test.d.ts +2 -0
  79. package/dist/__tests__/gpu-driven-view-graph.integration.test.d.ts.map +1 -0
  80. package/dist/__tests__/gpu-driven-view.browser.test.d.ts +2 -0
  81. package/dist/__tests__/gpu-driven-view.browser.test.d.ts.map +1 -0
  82. package/dist/__tests__/gpu-driven-view.dawn.test.d.ts +2 -0
  83. package/dist/__tests__/gpu-driven-view.dawn.test.d.ts.map +1 -0
  84. package/dist/__tests__/gpu-driven-view.unit.test.d.ts +2 -0
  85. package/dist/__tests__/gpu-driven-view.unit.test.d.ts.map +1 -0
  86. package/dist/__tests__/gpu-resource-store-stride.unit.test.d.ts +2 -0
  87. package/dist/__tests__/gpu-resource-store-stride.unit.test.d.ts.map +1 -0
  88. package/dist/__tests__/gpu-scene-field-type-owner.test-d.d.ts +2 -0
  89. package/dist/__tests__/gpu-scene-field-type-owner.test-d.d.ts.map +1 -0
  90. package/dist/__tests__/gpu-scene-render-graph-gpu.d.ts +7 -0
  91. package/dist/__tests__/gpu-scene-render-graph-gpu.d.ts.map +1 -0
  92. package/dist/__tests__/gpu-scene-render-graph.browser.test.d.ts +2 -0
  93. package/dist/__tests__/gpu-scene-render-graph.browser.test.d.ts.map +1 -0
  94. package/dist/__tests__/gpu-scene-render-graph.dawn.test.d.ts +2 -0
  95. package/dist/__tests__/gpu-scene-render-graph.dawn.test.d.ts.map +1 -0
  96. package/dist/__tests__/gpu-scene-schema.unit.test.d.ts +2 -0
  97. package/dist/__tests__/gpu-scene-schema.unit.test.d.ts.map +1 -0
  98. package/dist/__tests__/gpu-scene.dawn.test.d.ts +2 -0
  99. package/dist/__tests__/gpu-scene.dawn.test.d.ts.map +1 -0
  100. package/dist/__tests__/gpu-scene.unit.test.d.ts +2 -0
  101. package/dist/__tests__/gpu-scene.unit.test.d.ts.map +1 -0
  102. package/dist/__tests__/hdrp-pipeline.unit.test.d.ts +2 -0
  103. package/dist/__tests__/hdrp-pipeline.unit.test.d.ts.map +1 -0
  104. package/dist/__tests__/ibl/ibl-fallback.unit.test.d.ts +2 -0
  105. package/dist/__tests__/ibl/ibl-fallback.unit.test.d.ts.map +1 -0
  106. package/dist/__tests__/infinite-grid-no-vertex-probe.unit.test.d.ts +2 -0
  107. package/dist/__tests__/infinite-grid-no-vertex-probe.unit.test.d.ts.map +1 -0
  108. package/dist/__tests__/injection-kind-owner.test-d.d.ts +2 -0
  109. package/dist/__tests__/injection-kind-owner.test-d.d.ts.map +1 -0
  110. package/dist/__tests__/ktx2-basis-gpu-consumer.dawn.test.d.ts +2 -0
  111. package/dist/__tests__/ktx2-basis-gpu-consumer.dawn.test.d.ts.map +1 -0
  112. package/dist/__tests__/light-buffer-layout.unit.test.d.ts +2 -0
  113. package/dist/__tests__/light-buffer-layout.unit.test.d.ts.map +1 -0
  114. package/dist/__tests__/material-contract-inventory.unit.test.d.ts +2 -0
  115. package/dist/__tests__/material-contract-inventory.unit.test.d.ts.map +1 -0
  116. package/dist/__tests__/material-cooked-projection.unit.test.d.ts +2 -0
  117. package/dist/__tests__/material-cooked-projection.unit.test.d.ts.map +1 -0
  118. package/dist/__tests__/material-derived-error-stop-draw.integration.test.d.ts +2 -0
  119. package/dist/__tests__/material-derived-error-stop-draw.integration.test.d.ts.map +1 -0
  120. package/dist/__tests__/material-derived-payload.integration.test.d.ts +2 -0
  121. package/dist/__tests__/material-derived-payload.integration.test.d.ts.map +1 -0
  122. package/dist/__tests__/material-snapshot-mutation.integration.test.d.ts +2 -0
  123. package/dist/__tests__/material-snapshot-mutation.integration.test.d.ts.map +1 -0
  124. package/dist/__tests__/material-static-dynamic-route.unit.test.d.ts +2 -0
  125. package/dist/__tests__/material-static-dynamic-route.unit.test.d.ts.map +1 -0
  126. package/dist/__tests__/material-stride-surface.unit.test.d.ts +2 -0
  127. package/dist/__tests__/material-stride-surface.unit.test.d.ts.map +1 -0
  128. package/dist/__tests__/materials.unit.test.d.ts +2 -0
  129. package/dist/__tests__/materials.unit.test.d.ts.map +1 -0
  130. package/dist/__tests__/mesh-buffer-usage-surface.unit.test.d.ts +2 -0
  131. package/dist/__tests__/mesh-buffer-usage-surface.unit.test.d.ts.map +1 -0
  132. package/dist/__tests__/mesh-material-bindings.unit.test.d.ts +2 -0
  133. package/dist/__tests__/mesh-material-bindings.unit.test.d.ts.map +1 -0
  134. package/dist/__tests__/mesh-stride-surface.unit.test.d.ts +2 -0
  135. package/dist/__tests__/mesh-stride-surface.unit.test.d.ts.map +1 -0
  136. package/dist/__tests__/morph-culling-reentry.dawn.test.d.ts +2 -0
  137. package/dist/__tests__/morph-culling-reentry.dawn.test.d.ts.map +1 -0
  138. package/dist/__tests__/morph-feature-gpu-work.integration.test.d.ts +2 -0
  139. package/dist/__tests__/morph-feature-gpu-work.integration.test.d.ts.map +1 -0
  140. package/dist/__tests__/morph-visual-evidence.integration.test.d.ts +2 -0
  141. package/dist/__tests__/morph-visual-evidence.integration.test.d.ts.map +1 -0
  142. package/dist/__tests__/nineslice-handle-surface.unit.test.d.ts +2 -0
  143. package/dist/__tests__/nineslice-handle-surface.unit.test.d.ts.map +1 -0
  144. package/dist/__tests__/param-schema-projection-census.unit.test.d.ts +2 -0
  145. package/dist/__tests__/param-schema-projection-census.unit.test.d.ts.map +1 -0
  146. package/dist/__tests__/persistent-render-scene.unit.test.d.ts +2 -0
  147. package/dist/__tests__/persistent-render-scene.unit.test.d.ts.map +1 -0
  148. package/dist/__tests__/pipeline-error-policy-owner.unit.test.d.ts +2 -0
  149. package/dist/__tests__/pipeline-error-policy-owner.unit.test.d.ts.map +1 -0
  150. package/dist/__tests__/pipeline-pass-trace.test.d.ts +2 -0
  151. package/dist/__tests__/pipeline-pass-trace.test.d.ts.map +1 -0
  152. package/dist/__tests__/pipeline-stage-owner.test-d.d.ts +2 -0
  153. package/dist/__tests__/pipeline-stage-owner.test-d.d.ts.map +1 -0
  154. package/dist/__tests__/plugin.test.d.ts +2 -0
  155. package/dist/__tests__/plugin.test.d.ts.map +1 -0
  156. package/dist/__tests__/post-process-error-policy-owner.unit.test.d.ts +2 -0
  157. package/dist/__tests__/post-process-error-policy-owner.unit.test.d.ts.map +1 -0
  158. package/dist/__tests__/prepared-buffer-kind-owner.test-d.d.ts +2 -0
  159. package/dist/__tests__/prepared-buffer-kind-owner.test-d.d.ts.map +1 -0
  160. package/dist/__tests__/prepared-graphics-backend-matrix.unit.test.d.ts +2 -0
  161. package/dist/__tests__/prepared-graphics-backend-matrix.unit.test.d.ts.map +1 -0
  162. package/dist/__tests__/prepared-graphics-capability.unit.test.d.ts +2 -0
  163. package/dist/__tests__/prepared-graphics-capability.unit.test.d.ts.map +1 -0
  164. package/dist/__tests__/prepared-graphics-generation.unit.test.d.ts +2 -0
  165. package/dist/__tests__/prepared-graphics-generation.unit.test.d.ts.map +1 -0
  166. package/dist/__tests__/prepared-graphics-lifecycle.unit.test.d.ts +2 -0
  167. package/dist/__tests__/prepared-graphics-lifecycle.unit.test.d.ts.map +1 -0
  168. package/dist/__tests__/prepared-graphics-pipeline-warmup.unit.test.d.ts +2 -0
  169. package/dist/__tests__/prepared-graphics-pipeline-warmup.unit.test.d.ts.map +1 -0
  170. package/dist/__tests__/prepared-graphics-resolver-recording.unit.test.d.ts +2 -0
  171. package/dist/__tests__/prepared-graphics-resolver-recording.unit.test.d.ts.map +1 -0
  172. package/dist/__tests__/prepared-graphics-resolver.unit.test.d.ts +2 -0
  173. package/dist/__tests__/prepared-graphics-resolver.unit.test.d.ts.map +1 -0
  174. package/dist/__tests__/prepared-graphics-snapshot.unit.test.d.ts +2 -0
  175. package/dist/__tests__/prepared-graphics-snapshot.unit.test.d.ts.map +1 -0
  176. package/dist/__tests__/prepared-graphics-store.unit.test.d.ts +2 -0
  177. package/dist/__tests__/prepared-graphics-store.unit.test.d.ts.map +1 -0
  178. package/dist/__tests__/prepared-graphics-validation.unit.test.d.ts +2 -0
  179. package/dist/__tests__/prepared-graphics-validation.unit.test.d.ts.map +1 -0
  180. package/dist/__tests__/profiler-default-off.test.d.ts +2 -0
  181. package/dist/__tests__/profiler-default-off.test.d.ts.map +1 -0
  182. package/dist/__tests__/profiler-phase-catalog.test.d.ts +2 -0
  183. package/dist/__tests__/profiler-phase-catalog.test.d.ts.map +1 -0
  184. package/dist/__tests__/profiler-phase-integration.test.d.ts +2 -0
  185. package/dist/__tests__/profiler-phase-integration.test.d.ts.map +1 -0
  186. package/dist/__tests__/profiler-phase-token.test.d.ts +2 -0
  187. package/dist/__tests__/profiler-phase-token.test.d.ts.map +1 -0
  188. package/dist/__tests__/public-pipeline-id.test-d.d.ts +2 -0
  189. package/dist/__tests__/public-pipeline-id.test-d.d.ts.map +1 -0
  190. package/dist/__tests__/public-surface.test-d.d.ts +2 -0
  191. package/dist/__tests__/public-surface.test-d.d.ts.map +1 -0
  192. package/dist/__tests__/recover-error-policy-owner.unit.test.d.ts +2 -0
  193. package/dist/__tests__/recover-error-policy-owner.unit.test.d.ts.map +1 -0
  194. package/dist/__tests__/render-dispatch-membership.unit.test.d.ts +2 -0
  195. package/dist/__tests__/render-dispatch-membership.unit.test.d.ts.map +1 -0
  196. package/dist/__tests__/render-error-code-owner.test-d.d.ts +2 -0
  197. package/dist/__tests__/render-error-code-owner.test-d.d.ts.map +1 -0
  198. package/dist/__tests__/render-error-detail-ssot.test-d.d.ts +2 -0
  199. package/dist/__tests__/render-error-detail-ssot.test-d.d.ts.map +1 -0
  200. package/dist/__tests__/render-error-exhaustive.test-d.d.ts +2 -0
  201. package/dist/__tests__/render-error-exhaustive.test-d.d.ts.map +1 -0
  202. package/dist/__tests__/render-feature-assembly.test-d.d.ts +2 -0
  203. package/dist/__tests__/render-feature-assembly.test-d.d.ts.map +1 -0
  204. package/dist/__tests__/render-feature-construction.unit.test.d.ts +2 -0
  205. package/dist/__tests__/render-feature-construction.unit.test.d.ts.map +1 -0
  206. package/dist/__tests__/render-feature-context.test-d.d.ts +2 -0
  207. package/dist/__tests__/render-feature-context.test-d.d.ts.map +1 -0
  208. package/dist/__tests__/render-feature-contract.test-d.d.ts +2 -0
  209. package/dist/__tests__/render-feature-contract.test-d.d.ts.map +1 -0
  210. package/dist/__tests__/render-feature-diagnostics.unit.test.d.ts +2 -0
  211. package/dist/__tests__/render-feature-diagnostics.unit.test.d.ts.map +1 -0
  212. package/dist/__tests__/render-feature-docs.unit.test.d.ts +2 -0
  213. package/dist/__tests__/render-feature-docs.unit.test.d.ts.map +1 -0
  214. package/dist/__tests__/render-feature-error-code-owner.test-d.d.ts +2 -0
  215. package/dist/__tests__/render-feature-error-code-owner.test-d.d.ts.map +1 -0
  216. package/dist/__tests__/render-feature-errors.unit.test.d.ts +2 -0
  217. package/dist/__tests__/render-feature-errors.unit.test.d.ts.map +1 -0
  218. package/dist/__tests__/render-feature-gpu-buffer-usage-owner.test-d.d.ts +2 -0
  219. package/dist/__tests__/render-feature-gpu-buffer-usage-owner.test-d.d.ts.map +1 -0
  220. package/dist/__tests__/render-feature-gpu-work.integration.test.d.ts +2 -0
  221. package/dist/__tests__/render-feature-gpu-work.integration.test.d.ts.map +1 -0
  222. package/dist/__tests__/render-feature-graph.integration.test.d.ts +2 -0
  223. package/dist/__tests__/render-feature-graph.integration.test.d.ts.map +1 -0
  224. package/dist/__tests__/render-feature-graphics-staging.unit.test.d.ts +2 -0
  225. package/dist/__tests__/render-feature-graphics-staging.unit.test.d.ts.map +1 -0
  226. package/dist/__tests__/render-feature-order.unit.test.d.ts +2 -0
  227. package/dist/__tests__/render-feature-order.unit.test.d.ts.map +1 -0
  228. package/dist/__tests__/render-feature-prepared-diagnostics.unit.test.d.ts +2 -0
  229. package/dist/__tests__/render-feature-prepared-diagnostics.unit.test.d.ts.map +1 -0
  230. package/dist/__tests__/render-feature-prepared-errors.test-d.d.ts +2 -0
  231. package/dist/__tests__/render-feature-prepared-errors.test-d.d.ts.map +1 -0
  232. package/dist/__tests__/render-feature-prepared-graphics-docs.unit.test.d.ts +2 -0
  233. package/dist/__tests__/render-feature-prepared-graphics-docs.unit.test.d.ts.map +1 -0
  234. package/dist/__tests__/render-feature-prepared-graphics-isolation.unit.test.d.ts +2 -0
  235. package/dist/__tests__/render-feature-prepared-graphics-isolation.unit.test.d.ts.map +1 -0
  236. package/dist/__tests__/render-feature-prepared-graphics-negative.test-d.d.ts +2 -0
  237. package/dist/__tests__/render-feature-prepared-graphics-negative.test-d.d.ts.map +1 -0
  238. package/dist/__tests__/render-feature-prepared-graphics-recording.unit.test.d.ts +2 -0
  239. package/dist/__tests__/render-feature-prepared-graphics-recording.unit.test.d.ts.map +1 -0
  240. package/dist/__tests__/render-feature-prepared-graphics.test-d.d.ts +2 -0
  241. package/dist/__tests__/render-feature-prepared-graphics.test-d.d.ts.map +1 -0
  242. package/dist/__tests__/render-feature-prepared-graphics.unit.test.d.ts +2 -0
  243. package/dist/__tests__/render-feature-prepared-graphics.unit.test.d.ts.map +1 -0
  244. package/dist/__tests__/render-feature-public-surface.test-d.d.ts +2 -0
  245. package/dist/__tests__/render-feature-public-surface.test-d.d.ts.map +1 -0
  246. package/dist/__tests__/render-feature-retry.unit.test.d.ts +2 -0
  247. package/dist/__tests__/render-feature-retry.unit.test.d.ts.map +1 -0
  248. package/dist/__tests__/render-feature-scheduling.unit.test.d.ts +2 -0
  249. package/dist/__tests__/render-feature-scheduling.unit.test.d.ts.map +1 -0
  250. package/dist/__tests__/render-feature-stage-failed-policy-owner.unit.test.d.ts +2 -0
  251. package/dist/__tests__/render-feature-stage-failed-policy-owner.unit.test.d.ts.map +1 -0
  252. package/dist/__tests__/render-feature-stage-fault-recovery.unit.test.d.ts +2 -0
  253. package/dist/__tests__/render-feature-stage-fault-recovery.unit.test.d.ts.map +1 -0
  254. package/dist/__tests__/render-feature-staging.unit.test.d.ts +2 -0
  255. package/dist/__tests__/render-feature-staging.unit.test.d.ts.map +1 -0
  256. package/dist/__tests__/render-feature-visibility-context.test-d.d.ts +2 -0
  257. package/dist/__tests__/render-feature-visibility-context.test-d.d.ts.map +1 -0
  258. package/dist/__tests__/render-feature-visibility-context.unit.test.d.ts +2 -0
  259. package/dist/__tests__/render-feature-visibility-context.unit.test.d.ts.map +1 -0
  260. package/dist/__tests__/render-feature-zero-work.unit.test.d.ts +2 -0
  261. package/dist/__tests__/render-feature-zero-work.unit.test.d.ts.map +1 -0
  262. package/dist/__tests__/render-graph-compute-raster-gpu.d.ts +7 -0
  263. package/dist/__tests__/render-graph-compute-raster-gpu.d.ts.map +1 -0
  264. package/dist/__tests__/render-graph-compute-raster.browser.test.d.ts +2 -0
  265. package/dist/__tests__/render-graph-compute-raster.browser.test.d.ts.map +1 -0
  266. package/dist/__tests__/render-graph-compute-raster.dawn.test.d.ts +2 -0
  267. package/dist/__tests__/render-graph-compute-raster.dawn.test.d.ts.map +1 -0
  268. package/dist/__tests__/render-graph-hzb-gpu.d.ts +7 -0
  269. package/dist/__tests__/render-graph-hzb-gpu.d.ts.map +1 -0
  270. package/dist/__tests__/render-graph-hzb.browser.test.d.ts +2 -0
  271. package/dist/__tests__/render-graph-hzb.browser.test.d.ts.map +1 -0
  272. package/dist/__tests__/render-graph-hzb.dawn.test.d.ts +2 -0
  273. package/dist/__tests__/render-graph-hzb.dawn.test.d.ts.map +1 -0
  274. package/dist/__tests__/render-graph-primitives.unit.test.d.ts +2 -0
  275. package/dist/__tests__/render-graph-primitives.unit.test.d.ts.map +1 -0
  276. package/dist/__tests__/render-graph-storage-indirect-gpu.d.ts +12 -0
  277. package/dist/__tests__/render-graph-storage-indirect-gpu.d.ts.map +1 -0
  278. package/dist/__tests__/render-graph-storage-indirect.browser.test.d.ts +2 -0
  279. package/dist/__tests__/render-graph-storage-indirect.browser.test.d.ts.map +1 -0
  280. package/dist/__tests__/render-graph-storage-indirect.dawn.test.d.ts +2 -0
  281. package/dist/__tests__/render-graph-storage-indirect.dawn.test.d.ts.map +1 -0
  282. package/dist/__tests__/render-scene-projection.unit.test.d.ts +2 -0
  283. package/dist/__tests__/render-scene-projection.unit.test.d.ts.map +1 -0
  284. package/dist/__tests__/renderer-factory-material-contract.unit.test.d.ts +2 -0
  285. package/dist/__tests__/renderer-factory-material-contract.unit.test.d.ts.map +1 -0
  286. package/dist/__tests__/renderer-lifecycle.integration.test.d.ts +2 -0
  287. package/dist/__tests__/renderer-lifecycle.integration.test.d.ts.map +1 -0
  288. package/dist/__tests__/renderer-render-scene-public.test-d.d.ts +2 -0
  289. package/dist/__tests__/renderer-render-scene-public.test-d.d.ts.map +1 -0
  290. package/dist/__tests__/rhi-backend-package-boundary.unit.test.d.ts +2 -0
  291. package/dist/__tests__/rhi-backend-package-boundary.unit.test.d.ts.map +1 -0
  292. package/dist/__tests__/scene-temporal-coverage.unit.test.d.ts +2 -0
  293. package/dist/__tests__/scene-temporal-coverage.unit.test.d.ts.map +1 -0
  294. package/dist/__tests__/scriptable-pack-consumer.test-d.d.ts +2 -0
  295. package/dist/__tests__/scriptable-pack-consumer.test-d.d.ts.map +1 -0
  296. package/dist/__tests__/shader-stage-surface.unit.test.d.ts +2 -0
  297. package/dist/__tests__/shader-stage-surface.unit.test.d.ts.map +1 -0
  298. package/dist/__tests__/ssao-kernel-surface.unit.test.d.ts +2 -0
  299. package/dist/__tests__/ssao-kernel-surface.unit.test.d.ts.map +1 -0
  300. package/dist/__tests__/sun-snapshot-consumers.test.d.ts +2 -0
  301. package/dist/__tests__/sun-snapshot-consumers.test.d.ts.map +1 -0
  302. package/dist/__tests__/surface-backend-kind-owner.test-d.d.ts +2 -0
  303. package/dist/__tests__/surface-backend-kind-owner.test-d.d.ts.map +1 -0
  304. package/dist/__tests__/surface-configuration.unit.test.d.ts +2 -0
  305. package/dist/__tests__/surface-configuration.unit.test.d.ts.map +1 -0
  306. package/dist/__tests__/taa-history-store.unit.test.d.ts +2 -0
  307. package/dist/__tests__/taa-history-store.unit.test.d.ts.map +1 -0
  308. package/dist/__tests__/temporal-frame-transaction.integration.test.d.ts +2 -0
  309. package/dist/__tests__/temporal-frame-transaction.integration.test.d.ts.map +1 -0
  310. package/dist/__tests__/temporal-inspection.unit.test.d.ts +2 -0
  311. package/dist/__tests__/temporal-inspection.unit.test.d.ts.map +1 -0
  312. package/dist/__tests__/texture-usage-surface.unit.test.d.ts +2 -0
  313. package/dist/__tests__/texture-usage-surface.unit.test.d.ts.map +1 -0
  314. package/dist/__tests__/typed-pipeline-topology.unit.test.d.ts +2 -0
  315. package/dist/__tests__/typed-pipeline-topology.unit.test.d.ts.map +1 -0
  316. package/dist/__tests__/urp-pipeline-targets.unit.test.d.ts +2 -0
  317. package/dist/__tests__/urp-pipeline-targets.unit.test.d.ts.map +1 -0
  318. package/dist/__tests__/urp-pipeline.unit.test.d.ts +2 -0
  319. package/dist/__tests__/urp-pipeline.unit.test.d.ts.map +1 -0
  320. package/dist/__tests__/vertex-color-pipeline.unit.test.d.ts +2 -0
  321. package/dist/__tests__/vertex-color-pipeline.unit.test.d.ts.map +1 -0
  322. package/dist/__tests__/vertex-layout-consumer.unit.test.d.ts +2 -0
  323. package/dist/__tests__/vertex-layout-consumer.unit.test.d.ts.map +1 -0
  324. package/dist/__tests__/visibility-diagnostics.integration.test.d.ts +2 -0
  325. package/dist/__tests__/visibility-diagnostics.integration.test.d.ts.map +1 -0
  326. package/dist/__tests__/visibility-extract.integration.test.d.ts +2 -0
  327. package/dist/__tests__/visibility-extract.integration.test.d.ts.map +1 -0
  328. package/dist/__tests__/visibility-extract.perf.test.d.ts +2 -0
  329. package/dist/__tests__/visibility-extract.perf.test.d.ts.map +1 -0
  330. package/dist/__tests__/visibility-feature-dedup.integration.test.d.ts +2 -0
  331. package/dist/__tests__/visibility-feature-dedup.integration.test.d.ts.map +1 -0
  332. package/dist/__tests__/visibility-hidden-report.unit.test.d.ts +2 -0
  333. package/dist/__tests__/visibility-hidden-report.unit.test.d.ts.map +1 -0
  334. package/dist/__tests__/visibility-instances.integration.test.d.ts +2 -0
  335. package/dist/__tests__/visibility-instances.integration.test.d.ts.map +1 -0
  336. package/dist/__tests__/visibility-multi-world.integration.test.d.ts +2 -0
  337. package/dist/__tests__/visibility-multi-world.integration.test.d.ts.map +1 -0
  338. package/dist/__tests__/visibility-producer-matrix.integration.test.d.ts +2 -0
  339. package/dist/__tests__/visibility-producer-matrix.integration.test.d.ts.map +1 -0
  340. package/dist/__tests__/visibility-producer-matrix.unit.test.d.ts +2 -0
  341. package/dist/__tests__/visibility-producer-matrix.unit.test.d.ts.map +1 -0
  342. package/dist/__tests__/visibility-public-surface.test-d.d.ts +2 -0
  343. package/dist/__tests__/visibility-public-surface.test-d.d.ts.map +1 -0
  344. package/dist/__tests__/visibility-resolver.unit.test.d.ts +2 -0
  345. package/dist/__tests__/visibility-resolver.unit.test.d.ts.map +1 -0
  346. package/dist/__tests__/visibility-snapshot-contract.unit.test.d.ts +2 -0
  347. package/dist/__tests__/visibility-snapshot-contract.unit.test.d.ts.map +1 -0
  348. package/dist/__tests__/vocabulary.unit.test.d.ts +2 -0
  349. package/dist/__tests__/vocabulary.unit.test.d.ts.map +1 -0
  350. package/dist/assets/__tests__/asset-decoders.unit.test.d.ts +2 -0
  351. package/dist/assets/__tests__/asset-decoders.unit.test.d.ts.map +1 -0
  352. package/dist/assets/__tests__/mipmap-generator.unit.test.d.ts +2 -0
  353. package/dist/assets/__tests__/mipmap-generator.unit.test.d.ts.map +1 -0
  354. package/dist/assets/__tests__/render-asset-port.unit.test.d.ts +2 -0
  355. package/dist/assets/__tests__/render-asset-port.unit.test.d.ts.map +1 -0
  356. package/dist/assets/__tests__/resolve-render-asset.unit.test.d.ts +2 -0
  357. package/dist/assets/__tests__/resolve-render-asset.unit.test.d.ts.map +1 -0
  358. package/dist/assets/asset-decoders.d.ts +5 -0
  359. package/dist/assets/asset-decoders.d.ts.map +1 -0
  360. package/dist/assets/render-asset-port.d.ts +17 -0
  361. package/dist/assets/render-asset-port.d.ts.map +1 -0
  362. package/dist/assets/resolve-render-asset.d.ts +6 -0
  363. package/dist/assets/resolve-render-asset.d.ts.map +1 -0
  364. package/dist/authoring.d.ts +12 -0
  365. package/dist/authoring.d.ts.map +1 -0
  366. package/dist/authoring.mjs +5 -0
  367. package/dist/authoring.mjs.map +1 -0
  368. package/dist/chunk-33UF5SAO.mjs +7397 -0
  369. package/dist/chunk-33UF5SAO.mjs.map +1 -0
  370. package/dist/chunk-A5QCJSNL.mjs +29913 -0
  371. package/dist/chunk-A5QCJSNL.mjs.map +1 -0
  372. package/dist/chunk-JMSB7AR4.mjs +3 -0
  373. package/dist/chunk-JMSB7AR4.mjs.map +1 -0
  374. package/dist/chunk-LXNGO6AO.mjs +569 -0
  375. package/dist/chunk-LXNGO6AO.mjs.map +1 -0
  376. package/dist/chunk-QRXPSX4X.mjs +659 -0
  377. package/dist/chunk-QRXPSX4X.mjs.map +1 -0
  378. package/dist/chunk-YAKEQPWO.mjs +1439 -0
  379. package/dist/chunk-YAKEQPWO.mjs.map +1 -0
  380. package/dist/cluster-binner.d.ts +152 -0
  381. package/dist/cluster-binner.d.ts.map +1 -0
  382. package/dist/components/__tests__/atmosphere-red.test.d.ts +2 -0
  383. package/dist/components/__tests__/atmosphere-red.test.d.ts.map +1 -0
  384. package/dist/components/__tests__/atmosphere.test.d.ts +2 -0
  385. package/dist/components/__tests__/atmosphere.test.d.ts.map +1 -0
  386. package/dist/components/__tests__/fog.test-d.d.ts +2 -0
  387. package/dist/components/__tests__/fog.test-d.d.ts.map +1 -0
  388. package/dist/components/__tests__/fog.test.d.ts +2 -0
  389. package/dist/components/__tests__/fog.test.d.ts.map +1 -0
  390. package/dist/components/__tests__/schema-parity.unit.test.d.ts +2 -0
  391. package/dist/components/__tests__/schema-parity.unit.test.d.ts.map +1 -0
  392. package/dist/components/__tests__/visibility-schema.unit.test.d.ts +2 -0
  393. package/dist/components/__tests__/visibility-schema.unit.test.d.ts.map +1 -0
  394. package/dist/components/atmosphere.d.ts +18 -0
  395. package/dist/components/atmosphere.d.ts.map +1 -0
  396. package/dist/components/camera.d.ts +311 -0
  397. package/dist/components/camera.d.ts.map +1 -0
  398. package/dist/components/directional-light.d.ts +76 -0
  399. package/dist/components/directional-light.d.ts.map +1 -0
  400. package/dist/components/environment.d.ts +116 -0
  401. package/dist/components/environment.d.ts.map +1 -0
  402. package/dist/components/glyph-text.d.ts +26 -0
  403. package/dist/components/glyph-text.d.ts.map +1 -0
  404. package/dist/components/index.d.ts +22 -0
  405. package/dist/components/index.d.ts.map +1 -0
  406. package/dist/components/instances.d.ts +41 -0
  407. package/dist/components/instances.d.ts.map +1 -0
  408. package/dist/components/layer.d.ts +34 -0
  409. package/dist/components/layer.d.ts.map +1 -0
  410. package/dist/components/light-helpers.d.ts +53 -0
  411. package/dist/components/light-helpers.d.ts.map +1 -0
  412. package/dist/components/mesh-filter.d.ts +24 -0
  413. package/dist/components/mesh-filter.d.ts.map +1 -0
  414. package/dist/components/mesh-renderer.d.ts +33 -0
  415. package/dist/components/mesh-renderer.d.ts.map +1 -0
  416. package/dist/components/point-light-shadow.d.ts +27 -0
  417. package/dist/components/point-light-shadow.d.ts.map +1 -0
  418. package/dist/components/point-light.d.ts +35 -0
  419. package/dist/components/point-light.d.ts.map +1 -0
  420. package/dist/components/post-process-params.d.ts +5 -0
  421. package/dist/components/post-process-params.d.ts.map +1 -0
  422. package/dist/components/scene-instance.d.ts +140 -0
  423. package/dist/components/scene-instance.d.ts.map +1 -0
  424. package/dist/components/sort-key.d.ts +44 -0
  425. package/dist/components/sort-key.d.ts.map +1 -0
  426. package/dist/components/spot-light.d.ts +81 -0
  427. package/dist/components/spot-light.d.ts.map +1 -0
  428. package/dist/components/sprite-animation.d.ts +75 -0
  429. package/dist/components/sprite-animation.d.ts.map +1 -0
  430. package/dist/components/sprite-instances.d.ts +51 -0
  431. package/dist/components/sprite-instances.d.ts.map +1 -0
  432. package/dist/components/sprite-playback-mode.d.ts +37 -0
  433. package/dist/components/sprite-playback-mode.d.ts.map +1 -0
  434. package/dist/components/sprite-region-override.d.ts +47 -0
  435. package/dist/components/sprite-region-override.d.ts.map +1 -0
  436. package/dist/components/tile-layer.d.ts +101 -0
  437. package/dist/components/tile-layer.d.ts.map +1 -0
  438. package/dist/components/tilemap.d.ts +25 -0
  439. package/dist/components/tilemap.d.ts.map +1 -0
  440. package/dist/components/visibility.d.ts +22 -0
  441. package/dist/components/visibility.d.ts.map +1 -0
  442. package/dist/construct-renderer.d.ts +2 -0
  443. package/dist/construct-renderer.d.ts.map +1 -0
  444. package/dist/construct-renderer.mjs +6 -0
  445. package/dist/construct-renderer.mjs.map +1 -0
  446. package/dist/debug-draw-glue.d.ts +56 -0
  447. package/dist/debug-draw-glue.d.ts.map +1 -0
  448. package/dist/deferred-lighting.d.ts +13 -0
  449. package/dist/deferred-lighting.d.ts.map +1 -0
  450. package/dist/dynamic-texture-store.d.ts +42 -0
  451. package/dist/dynamic-texture-store.d.ts.map +1 -0
  452. package/dist/engine-metrics.d.ts +23 -0
  453. package/dist/engine-metrics.d.ts.map +1 -0
  454. package/dist/environment/__tests__/failure-injection.test.d.ts +2 -0
  455. package/dist/environment/__tests__/failure-injection.test.d.ts.map +1 -0
  456. package/dist/environment/__tests__/generation-red.test.d.ts +2 -0
  457. package/dist/environment/__tests__/generation-red.test.d.ts.map +1 -0
  458. package/dist/environment/__tests__/generation.test.d.ts +2 -0
  459. package/dist/environment/__tests__/generation.test.d.ts.map +1 -0
  460. package/dist/environment/__tests__/graph-transaction.test.d.ts +2 -0
  461. package/dist/environment/__tests__/graph-transaction.test.d.ts.map +1 -0
  462. package/dist/environment/__tests__/inspection-red.test.d.ts +2 -0
  463. package/dist/environment/__tests__/inspection-red.test.d.ts.map +1 -0
  464. package/dist/environment/__tests__/lifecycle-evidence.test.d.ts +2 -0
  465. package/dist/environment/__tests__/lifecycle-evidence.test.d.ts.map +1 -0
  466. package/dist/environment/__tests__/pipeline-topology.test.d.ts +2 -0
  467. package/dist/environment/__tests__/pipeline-topology.test.d.ts.map +1 -0
  468. package/dist/environment/__tests__/readiness.test.d.ts +2 -0
  469. package/dist/environment/__tests__/readiness.test.d.ts.map +1 -0
  470. package/dist/environment/__tests__/recovery.test.d.ts +2 -0
  471. package/dist/environment/__tests__/recovery.test.d.ts.map +1 -0
  472. package/dist/environment/__tests__/resize-dispose.test.d.ts +2 -0
  473. package/dist/environment/__tests__/resize-dispose.test.d.ts.map +1 -0
  474. package/dist/environment/__tests__/signature-red.test.d.ts +2 -0
  475. package/dist/environment/__tests__/signature-red.test.d.ts.map +1 -0
  476. package/dist/environment/__tests__/signature.test.d.ts +2 -0
  477. package/dist/environment/__tests__/signature.test.d.ts.map +1 -0
  478. package/dist/environment/descriptors.d.ts +2 -0
  479. package/dist/environment/descriptors.d.ts.map +1 -0
  480. package/dist/environment/extracted-environment.d.ts +53 -0
  481. package/dist/environment/extracted-environment.d.ts.map +1 -0
  482. package/dist/environment/generation.d.ts +62 -0
  483. package/dist/environment/generation.d.ts.map +1 -0
  484. package/dist/environment/gpu-bundle.d.ts +23 -0
  485. package/dist/environment/gpu-bundle.d.ts.map +1 -0
  486. package/dist/environment/graph.d.ts +108 -0
  487. package/dist/environment/graph.d.ts.map +1 -0
  488. package/dist/environment/inspection.d.ts +48 -0
  489. package/dist/environment/inspection.d.ts.map +1 -0
  490. package/dist/environment/lifecycle.d.ts +22 -0
  491. package/dist/environment/lifecycle.d.ts.map +1 -0
  492. package/dist/environment/readiness.d.ts +29 -0
  493. package/dist/environment/readiness.d.ts.map +1 -0
  494. package/dist/environment/signature.d.ts +70 -0
  495. package/dist/environment/signature.d.ts.map +1 -0
  496. package/dist/errors/ecs-validation.d.ts +3 -0
  497. package/dist/errors/ecs-validation.d.ts.map +1 -0
  498. package/dist/errors/index.d.ts +4 -0
  499. package/dist/errors/index.d.ts.map +1 -0
  500. package/dist/errors/recover.d.ts +78 -0
  501. package/dist/errors/recover.d.ts.map +1 -0
  502. package/dist/errors/render.d.ts +633 -0
  503. package/dist/errors/render.d.ts.map +1 -0
  504. package/dist/extract/__tests__/directional-csm-domain.unit.test.d.ts +2 -0
  505. package/dist/extract/__tests__/directional-csm-domain.unit.test.d.ts.map +1 -0
  506. package/dist/extract/__tests__/environment-source.test.d.ts +2 -0
  507. package/dist/extract/__tests__/environment-source.test.d.ts.map +1 -0
  508. package/dist/extract/__tests__/schema-readers.unit.test.d.ts +2 -0
  509. package/dist/extract/__tests__/schema-readers.unit.test.d.ts.map +1 -0
  510. package/dist/extract/directional-csm.d.ts +129 -0
  511. package/dist/extract/directional-csm.d.ts.map +1 -0
  512. package/dist/extract/index.d.ts +5 -0
  513. package/dist/extract/index.d.ts.map +1 -0
  514. package/dist/extract/material-interface.d.ts +56 -0
  515. package/dist/extract/material-interface.d.ts.map +1 -0
  516. package/dist/extract/schema-readers.d.ts +20 -0
  517. package/dist/extract/schema-readers.d.ts.map +1 -0
  518. package/dist/extract/visibility.d.ts +26 -0
  519. package/dist/extract/visibility.d.ts.map +1 -0
  520. package/dist/features/graph-contribution.d.ts +64 -0
  521. package/dist/features/graph-contribution.d.ts.map +1 -0
  522. package/dist/features/host.d.ts +100 -0
  523. package/dist/features/host.d.ts.map +1 -0
  524. package/dist/features/index.d.ts +21 -0
  525. package/dist/features/index.d.ts.map +1 -0
  526. package/dist/features/morph/index.d.ts +3 -0
  527. package/dist/features/morph/index.d.ts.map +1 -0
  528. package/dist/features/morph/morph-bounds.d.ts +42 -0
  529. package/dist/features/morph/morph-bounds.d.ts.map +1 -0
  530. package/dist/features/morph/morph-feature.d.ts +45 -0
  531. package/dist/features/morph/morph-feature.d.ts.map +1 -0
  532. package/dist/features/prepared-gpu-work.d.ts +113 -0
  533. package/dist/features/prepared-gpu-work.d.ts.map +1 -0
  534. package/dist/features/prepared-graphics-store.d.ts +65 -0
  535. package/dist/features/prepared-graphics-store.d.ts.map +1 -0
  536. package/dist/features/prepared-graphics.d.ts +225 -0
  537. package/dist/features/prepared-graphics.d.ts.map +1 -0
  538. package/dist/features/render-graph-compute.d.ts +13 -0
  539. package/dist/features/render-graph-compute.d.ts.map +1 -0
  540. package/dist/features/render-graph-contribution.d.ts +15 -0
  541. package/dist/features/render-graph-contribution.d.ts.map +1 -0
  542. package/dist/features/render-graph-raster.d.ts +34 -0
  543. package/dist/features/render-graph-raster.d.ts.map +1 -0
  544. package/dist/features/render-graph-resources.d.ts +11 -0
  545. package/dist/features/render-graph-resources.d.ts.map +1 -0
  546. package/dist/features/scene-temporal.d.ts +45 -0
  547. package/dist/features/scene-temporal.d.ts.map +1 -0
  548. package/dist/features/taa-resolve.d.ts +21 -0
  549. package/dist/features/taa-resolve.d.ts.map +1 -0
  550. package/dist/features/targets.d.ts +32 -0
  551. package/dist/features/targets.d.ts.map +1 -0
  552. package/dist/features/types.d.ts +247 -0
  553. package/dist/features/types.d.ts.map +1 -0
  554. package/dist/frame-chain.d.ts +14 -0
  555. package/dist/frame-chain.d.ts.map +1 -0
  556. package/dist/fullscreen-post-process-pass.d.ts +178 -0
  557. package/dist/fullscreen-post-process-pass.d.ts.map +1 -0
  558. package/dist/glyph-text-layout-system.d.ts +18 -0
  559. package/dist/glyph-text-layout-system.d.ts.map +1 -0
  560. package/dist/gpu-driven/batch-topology.d.ts +124 -0
  561. package/dist/gpu-driven/batch-topology.d.ts.map +1 -0
  562. package/dist/gpu-driven/production-raster.d.ts +150 -0
  563. package/dist/gpu-driven/production-raster.d.ts.map +1 -0
  564. package/dist/gpu-driven/view-gpu.d.ts +141 -0
  565. package/dist/gpu-driven/view-gpu.d.ts.map +1 -0
  566. package/dist/gpu-driven/view-reference.d.ts +15 -0
  567. package/dist/gpu-driven/view-reference.d.ts.map +1 -0
  568. package/dist/gpu-resource-store.d.ts +294 -0
  569. package/dist/gpu-resource-store.d.ts.map +1 -0
  570. package/dist/gpu-resource.d.ts +73 -0
  571. package/dist/gpu-resource.d.ts.map +1 -0
  572. package/dist/gpu-scene-schema.d.ts +171 -0
  573. package/dist/gpu-scene-schema.d.ts.map +1 -0
  574. package/dist/gpu-scene.d.ts +81 -0
  575. package/dist/gpu-scene.d.ts.map +1 -0
  576. package/dist/gpu-stage.d.ts +4 -0
  577. package/dist/gpu-stage.d.ts.map +1 -0
  578. package/dist/gpu-texture-usage.d.ts +6 -0
  579. package/dist/gpu-texture-usage.d.ts.map +1 -0
  580. package/dist/gpu-usage.d.ts +9 -0
  581. package/dist/gpu-usage.d.ts.map +1 -0
  582. package/dist/hdrp-buffers.d.ts +213 -0
  583. package/dist/hdrp-buffers.d.ts.map +1 -0
  584. package/dist/hdrp-cluster-membership.d.ts +2 -0
  585. package/dist/hdrp-cluster-membership.d.ts.map +1 -0
  586. package/dist/hdrp-pipeline.d.ts +36 -0
  587. package/dist/hdrp-pipeline.d.ts.map +1 -0
  588. package/dist/ibl/IblPipelineCache.d.ts +274 -0
  589. package/dist/ibl/IblPipelineCache.d.ts.map +1 -0
  590. package/dist/ibl/cubemap-projection.d.ts +23 -0
  591. package/dist/ibl/cubemap-projection.d.ts.map +1 -0
  592. package/dist/ibl/face-uniforms.d.ts +65 -0
  593. package/dist/ibl/face-uniforms.d.ts.map +1 -0
  594. package/dist/ibl/skylight-bind-group.d.ts +130 -0
  595. package/dist/ibl/skylight-bind-group.d.ts.map +1 -0
  596. package/dist/index.d.ts +57 -0
  597. package/dist/index.d.ts.map +1 -0
  598. package/dist/index.mjs +5 -0
  599. package/dist/index.mjs.map +1 -0
  600. package/dist/instance-buffer-cache.d.ts +59 -0
  601. package/dist/instance-buffer-cache.d.ts.map +1 -0
  602. package/dist/internal.d.ts +74 -0
  603. package/dist/internal.d.ts.map +1 -0
  604. package/dist/internal.mjs +45 -0
  605. package/dist/internal.mjs.map +1 -0
  606. package/dist/lifecycle.d.ts +28 -0
  607. package/dist/lifecycle.d.ts.map +1 -0
  608. package/dist/light-buffer-layout.d.ts +164 -0
  609. package/dist/light-buffer-layout.d.ts.map +1 -0
  610. package/dist/materials.d.ts +50 -0
  611. package/dist/materials.d.ts.map +1 -0
  612. package/dist/mesh-material-bindings.d.ts +44 -0
  613. package/dist/mesh-material-bindings.d.ts.map +1 -0
  614. package/dist/mesh-update-errors.d.ts +71 -0
  615. package/dist/mesh-update-errors.d.ts.map +1 -0
  616. package/dist/mipmap-generator.d.ts +39 -0
  617. package/dist/mipmap-generator.d.ts.map +1 -0
  618. package/dist/param-schema-projection-census.d.ts +18 -0
  619. package/dist/param-schema-projection-census.d.ts.map +1 -0
  620. package/dist/pbr-pipeline.d.ts +253 -0
  621. package/dist/pbr-pipeline.d.ts.map +1 -0
  622. package/dist/persistent-render-scene.d.ts +158 -0
  623. package/dist/persistent-render-scene.d.ts.map +1 -0
  624. package/dist/pipeline/index.d.ts +11 -0
  625. package/dist/pipeline/index.d.ts.map +1 -0
  626. package/dist/pipeline-builder.d.ts +122 -0
  627. package/dist/pipeline-builder.d.ts.map +1 -0
  628. package/dist/pipeline-errors.d.ts +110 -0
  629. package/dist/pipeline-errors.d.ts.map +1 -0
  630. package/dist/pipeline-spec.d.ts +506 -0
  631. package/dist/pipeline-spec.d.ts.map +1 -0
  632. package/dist/plugin.d.ts +17 -0
  633. package/dist/plugin.d.ts.map +1 -0
  634. package/dist/post-process-errors.d.ts +182 -0
  635. package/dist/post-process-errors.d.ts.map +1 -0
  636. package/dist/prepare/__tests__/schema-readers.unit.test.d.ts +2 -0
  637. package/dist/prepare/__tests__/schema-readers.unit.test.d.ts.map +1 -0
  638. package/dist/prepare/index.d.ts +4 -0
  639. package/dist/prepare/index.d.ts.map +1 -0
  640. package/dist/prepare/prepared-graphics-resolver.d.ts +62 -0
  641. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -0
  642. package/dist/prepare/schema-readers.d.ts +11 -0
  643. package/dist/prepare/schema-readers.d.ts.map +1 -0
  644. package/dist/record/__tests__/environment-record.test.d.ts +2 -0
  645. package/dist/record/__tests__/environment-record.test.d.ts.map +1 -0
  646. package/dist/record/__tests__/frame-targets.unit.test.d.ts +2 -0
  647. package/dist/record/__tests__/frame-targets.unit.test.d.ts.map +1 -0
  648. package/dist/record/__tests__/material-bg-cache.unit.test.d.ts +2 -0
  649. package/dist/record/__tests__/material-bg-cache.unit.test.d.ts.map +1 -0
  650. package/dist/record/__tests__/material-slot-plan.unit.test.d.ts +2 -0
  651. package/dist/record/__tests__/material-slot-plan.unit.test.d.ts.map +1 -0
  652. package/dist/record/__tests__/membership-timing.unit.test.d.ts +2 -0
  653. package/dist/record/__tests__/membership-timing.unit.test.d.ts.map +1 -0
  654. package/dist/record/__tests__/render-submission.integration.test.d.ts +2 -0
  655. package/dist/record/__tests__/render-submission.integration.test.d.ts.map +1 -0
  656. package/dist/record/__tests__/render-submission.perf.test.d.ts +2 -0
  657. package/dist/record/__tests__/render-submission.perf.test.d.ts.map +1 -0
  658. package/dist/record/__tests__/shadow-submit-mode.unit.test.d.ts +2 -0
  659. package/dist/record/__tests__/shadow-submit-mode.unit.test.d.ts.map +1 -0
  660. package/dist/record/__tests__/video-texture-view.unit.test.d.ts +2 -0
  661. package/dist/record/__tests__/video-texture-view.unit.test.d.ts.map +1 -0
  662. package/dist/record/__tests__/view-ubo-layout.unit.test.d.ts +2 -0
  663. package/dist/record/__tests__/view-ubo-layout.unit.test.d.ts.map +1 -0
  664. package/dist/record/frame-lighting.d.ts +187 -0
  665. package/dist/record/frame-lighting.d.ts.map +1 -0
  666. package/dist/record/frame-observation.d.ts +38 -0
  667. package/dist/record/frame-observation.d.ts.map +1 -0
  668. package/dist/record/frame-snapshot.d.ts +429 -0
  669. package/dist/record/frame-snapshot.d.ts.map +1 -0
  670. package/dist/record/frame-targets.d.ts +53 -0
  671. package/dist/record/frame-targets.d.ts.map +1 -0
  672. package/dist/record/frame.d.ts +59 -0
  673. package/dist/record/frame.d.ts.map +1 -0
  674. package/dist/record/helpers.d.ts +101 -0
  675. package/dist/record/helpers.d.ts.map +1 -0
  676. package/dist/record/index.d.ts +15 -0
  677. package/dist/record/index.d.ts.map +1 -0
  678. package/dist/record/main-pass-geometry.d.ts +20 -0
  679. package/dist/record/main-pass-geometry.d.ts.map +1 -0
  680. package/dist/record/main-pass-material.d.ts +173 -0
  681. package/dist/record/main-pass-material.d.ts.map +1 -0
  682. package/dist/record/main-pass-skin.d.ts +46 -0
  683. package/dist/record/main-pass-skin.d.ts.map +1 -0
  684. package/dist/record/main-pass-sprite-draws.d.ts +18 -0
  685. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -0
  686. package/dist/record/main-pass-sprite.d.ts +69 -0
  687. package/dist/record/main-pass-sprite.d.ts.map +1 -0
  688. package/dist/record/main-pass.d.ts +20 -0
  689. package/dist/record/main-pass.d.ts.map +1 -0
  690. package/dist/record/material-payload.d.ts +43 -0
  691. package/dist/record/material-payload.d.ts.map +1 -0
  692. package/dist/record/material-slot-plan.d.ts +26 -0
  693. package/dist/record/material-slot-plan.d.ts.map +1 -0
  694. package/dist/record/membership-timing.d.ts +232 -0
  695. package/dist/record/membership-timing.d.ts.map +1 -0
  696. package/dist/record/mesh-ssbo.d.ts +173 -0
  697. package/dist/record/mesh-ssbo.d.ts.map +1 -0
  698. package/dist/record/shadow-caster-uniform.d.ts +8 -0
  699. package/dist/record/shadow-caster-uniform.d.ts.map +1 -0
  700. package/dist/record/shadow-pass.d.ts +125 -0
  701. package/dist/record/shadow-pass.d.ts.map +1 -0
  702. package/dist/record/shadow-submit-mode.d.ts +66 -0
  703. package/dist/record/shadow-submit-mode.d.ts.map +1 -0
  704. package/dist/record/skybox-post-pass.d.ts +33 -0
  705. package/dist/record/skybox-post-pass.d.ts.map +1 -0
  706. package/dist/record/typed-frame-graph.d.ts +13 -0
  707. package/dist/record/typed-frame-graph.d.ts.map +1 -0
  708. package/dist/record/view-ubo.d.ts +39 -0
  709. package/dist/record/view-ubo.d.ts.map +1 -0
  710. package/dist/render-data.d.ts +143 -0
  711. package/dist/render-data.d.ts.map +1 -0
  712. package/dist/render-dispatch-membership.d.ts +47 -0
  713. package/dist/render-dispatch-membership.d.ts.map +1 -0
  714. package/dist/render-graph-primitives.d.ts +424 -0
  715. package/dist/render-graph-primitives.d.ts.map +1 -0
  716. package/dist/render-pipeline-context.d.ts +289 -0
  717. package/dist/render-pipeline-context.d.ts.map +1 -0
  718. package/dist/render-pipeline-target.d.ts +16 -0
  719. package/dist/render-pipeline-target.d.ts.map +1 -0
  720. package/dist/render-pipeline.d.ts +149 -0
  721. package/dist/render-pipeline.d.ts.map +1 -0
  722. package/dist/render-scene-projection.d.ts +174 -0
  723. package/dist/render-scene-projection.d.ts.map +1 -0
  724. package/dist/render-system-extract.d.ts +1096 -0
  725. package/dist/render-system-extract.d.ts.map +1 -0
  726. package/dist/render-system-fold.d.ts +266 -0
  727. package/dist/render-system-fold.d.ts.map +1 -0
  728. package/dist/render-system.d.ts +814 -0
  729. package/dist/render-system.d.ts.map +1 -0
  730. package/dist/renderer/asset-service.d.ts +10 -0
  731. package/dist/renderer/asset-service.d.ts.map +1 -0
  732. package/dist/renderer/backend-selection.d.ts +26 -0
  733. package/dist/renderer/backend-selection.d.ts.map +1 -0
  734. package/dist/renderer/environment-classify.d.ts +6 -0
  735. package/dist/renderer/environment-classify.d.ts.map +1 -0
  736. package/dist/renderer/environment-error.d.ts +13 -0
  737. package/dist/renderer/environment-error.d.ts.map +1 -0
  738. package/dist/renderer/material/assembly.d.ts +22 -0
  739. package/dist/renderer/material/assembly.d.ts.map +1 -0
  740. package/dist/renderer/material/pipeline-projection.d.ts +91 -0
  741. package/dist/renderer/material/pipeline-projection.d.ts.map +1 -0
  742. package/dist/renderer/renderer-factory.d.ts +283 -0
  743. package/dist/renderer/renderer-factory.d.ts.map +1 -0
  744. package/dist/renderer.d.ts +771 -0
  745. package/dist/renderer.d.ts.map +1 -0
  746. package/dist/scene-instances/post-spawn-resolve-joints.d.ts +33 -0
  747. package/dist/scene-instances/post-spawn-resolve-joints.d.ts.map +1 -0
  748. package/dist/scene-utils/collect-subtree.d.ts +11 -0
  749. package/dist/scene-utils/collect-subtree.d.ts.map +1 -0
  750. package/dist/shadow-atlas.d.ts +117 -0
  751. package/dist/shadow-atlas.d.ts.map +1 -0
  752. package/dist/ssao-buffers.d.ts +31 -0
  753. package/dist/ssao-buffers.d.ts.map +1 -0
  754. package/dist/ssao-config.d.ts +28 -0
  755. package/dist/ssao-config.d.ts.map +1 -0
  756. package/dist/ssao-data.d.ts +34 -0
  757. package/dist/ssao-data.d.ts.map +1 -0
  758. package/dist/surface-format.d.ts +10 -0
  759. package/dist/surface-format.d.ts.map +1 -0
  760. package/dist/systems/active-camera.d.ts +53 -0
  761. package/dist/systems/active-camera.d.ts.map +1 -0
  762. package/dist/systems/pass-selector.d.ts +24 -0
  763. package/dist/systems/pass-selector.d.ts.map +1 -0
  764. package/dist/systems/skin-palette-allocator.d.ts +51 -0
  765. package/dist/systems/skin-palette-allocator.d.ts.map +1 -0
  766. package/dist/systems/transparent-sort-config.d.ts +91 -0
  767. package/dist/systems/transparent-sort-config.d.ts.map +1 -0
  768. package/dist/taa-history-store.d.ts +88 -0
  769. package/dist/taa-history-store.d.ts.map +1 -0
  770. package/dist/temporal-coverage.d.ts +35 -0
  771. package/dist/temporal-coverage.d.ts.map +1 -0
  772. package/dist/temporal-frame-transaction.d.ts +92 -0
  773. package/dist/temporal-frame-transaction.d.ts.map +1 -0
  774. package/dist/temporal-inspection.d.ts +57 -0
  775. package/dist/temporal-inspection.d.ts.map +1 -0
  776. package/dist/temporal-view.d.ts +43 -0
  777. package/dist/temporal-view.d.ts.map +1 -0
  778. package/dist/tilemap/resolve-tileset-runtime.d.ts +23 -0
  779. package/dist/tilemap/resolve-tileset-runtime.d.ts.map +1 -0
  780. package/dist/tilemap-chunk-extract-system.d.ts +142 -0
  781. package/dist/tilemap-chunk-extract-system.d.ts.map +1 -0
  782. package/dist/typed-render-graph-primitives.d.ts +59 -0
  783. package/dist/typed-render-graph-primitives.d.ts.map +1 -0
  784. package/dist/typed-shadow-passes.d.ts +11 -0
  785. package/dist/typed-shadow-passes.d.ts.map +1 -0
  786. package/dist/urp-pipeline.d.ts +4 -0
  787. package/dist/urp-pipeline.d.ts.map +1 -0
  788. package/package.json +94 -0
  789. package/src/__tests__/analytic-sky-contract.test.ts +27 -0
  790. package/src/__tests__/analytic-sky-falsify-carriers.mjs +43 -0
  791. package/src/__tests__/analytic-sky-falsify.test.ts +94 -0
  792. package/src/__tests__/assets-runtime-handoff.integration.test.ts +36 -0
  793. package/src/__tests__/authoring-path.unit.test.ts +14 -0
  794. package/src/__tests__/backend-selection-rhi-capture.test-d.ts +21 -0
  795. package/src/__tests__/backend-selection.integration.test.ts +11 -0
  796. package/src/__tests__/callback-inference.test-d.ts +5 -0
  797. package/src/__tests__/camera-temporal.test-d.ts +8 -0
  798. package/src/__tests__/camera-temporal.test.ts +188 -0
  799. package/src/__tests__/cluster-binner.test.ts +272 -0
  800. package/src/__tests__/cluster-grid-default-surface.unit.test.ts +17 -0
  801. package/src/__tests__/construct-renderer-identity.unit.test.ts +10 -0
  802. package/src/__tests__/direct-extract-consumer-contract.test-d.ts +34 -0
  803. package/src/__tests__/direct-light-snapshot.unit.test.ts +71 -0
  804. package/src/__tests__/directional-shadow-probe-atlas-layout.unit.test.ts +18 -0
  805. package/src/__tests__/environment-inspection.test.ts +45 -0
  806. package/src/__tests__/factory-contract.integration.test.ts +331 -0
  807. package/src/__tests__/fallback-row-stride-surface.unit.test.ts +18 -0
  808. package/src/__tests__/fog-ai-user.fixture.ts +350 -0
  809. package/src/__tests__/fog-custom-render-feature.fixture.ts +33 -0
  810. package/src/__tests__/fog-custom-render-feature.integration.test.ts +76 -0
  811. package/src/__tests__/fog-inspection.integration.test.ts +127 -0
  812. package/src/__tests__/fog-owner-state.integration.test.ts +112 -0
  813. package/src/__tests__/fog-pipeline-topology.integration.test.ts +93 -0
  814. package/src/__tests__/fog-public-surface.integration.test.ts +60 -0
  815. package/src/__tests__/fog-ray-contract.integration.test.ts +73 -0
  816. package/src/__tests__/fog-source-absence.integration.test.ts +51 -0
  817. package/src/__tests__/fog-temporal.integration.test.ts +115 -0
  818. package/src/__tests__/frame-chain.unit.test.ts +26 -0
  819. package/src/__tests__/frame-observation.contract.test.ts +103 -0
  820. package/src/__tests__/glyph-text-layout-recovery.unit.test.ts +172 -0
  821. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +347 -0
  822. package/src/__tests__/gpu-driven-indirect-raster.browser.test.ts +12 -0
  823. package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +16 -0
  824. package/src/__tests__/gpu-driven-production.integration.test.ts +609 -0
  825. package/src/__tests__/gpu-driven-scaling.unit.test.ts +90 -0
  826. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +192 -0
  827. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +128 -0
  828. package/src/__tests__/gpu-driven-view.browser.test.ts +19 -0
  829. package/src/__tests__/gpu-driven-view.dawn.test.ts +17 -0
  830. package/src/__tests__/gpu-driven-view.unit.test.ts +455 -0
  831. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +59 -0
  832. package/src/__tests__/gpu-scene-field-type-owner.test-d.ts +27 -0
  833. package/src/__tests__/gpu-scene-render-graph-gpu.ts +309 -0
  834. package/src/__tests__/gpu-scene-render-graph.browser.test.ts +19 -0
  835. package/src/__tests__/gpu-scene-render-graph.dawn.test.ts +19 -0
  836. package/src/__tests__/gpu-scene-schema.unit.test.ts +16 -0
  837. package/src/__tests__/gpu-scene.dawn.test.ts +209 -0
  838. package/src/__tests__/gpu-scene.unit.test.ts +161 -0
  839. package/src/__tests__/hdrp-pipeline.unit.test.ts +100 -0
  840. package/src/__tests__/ibl/ibl-fallback.unit.test.ts +23 -0
  841. package/src/__tests__/infinite-grid-no-vertex-probe.unit.test.ts +124 -0
  842. package/src/__tests__/injection-kind-owner.test-d.ts +14 -0
  843. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +719 -0
  844. package/src/__tests__/light-buffer-layout.unit.test.ts +85 -0
  845. package/src/__tests__/material-contract-inventory.unit.test.ts +24 -0
  846. package/src/__tests__/material-cooked-projection.unit.test.ts +177 -0
  847. package/src/__tests__/material-derived-error-stop-draw.integration.test.ts +69 -0
  848. package/src/__tests__/material-derived-payload.integration.test.ts +164 -0
  849. package/src/__tests__/material-snapshot-mutation.integration.test.ts +58 -0
  850. package/src/__tests__/material-static-dynamic-route.unit.test.ts +113 -0
  851. package/src/__tests__/material-stride-surface.unit.test.ts +32 -0
  852. package/src/__tests__/materials.unit.test.ts +25 -0
  853. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +107 -0
  854. package/src/__tests__/mesh-material-bindings.unit.test.ts +89 -0
  855. package/src/__tests__/mesh-stride-surface.unit.test.ts +16 -0
  856. package/src/__tests__/morph-culling-reentry.dawn.test.ts +166 -0
  857. package/src/__tests__/morph-feature-gpu-work.integration.test.ts +78 -0
  858. package/src/__tests__/morph-visual-evidence.integration.test.ts +66 -0
  859. package/src/__tests__/nineslice-handle-surface.unit.test.ts +14 -0
  860. package/src/__tests__/param-schema-projection-census.unit.test.ts +40 -0
  861. package/src/__tests__/persistent-render-scene.unit.test.ts +1311 -0
  862. package/src/__tests__/pipeline-error-policy-owner.unit.test.ts +167 -0
  863. package/src/__tests__/pipeline-pass-trace.test.ts +92 -0
  864. package/src/__tests__/pipeline-stage-owner.test-d.ts +13 -0
  865. package/src/__tests__/plugin.test.ts +25 -0
  866. package/src/__tests__/post-process-error-policy-owner.unit.test.ts +208 -0
  867. package/src/__tests__/prepared-buffer-kind-owner.test-d.ts +29 -0
  868. package/src/__tests__/prepared-graphics-backend-matrix.unit.test.ts +129 -0
  869. package/src/__tests__/prepared-graphics-capability.unit.test.ts +140 -0
  870. package/src/__tests__/prepared-graphics-generation.unit.test.ts +175 -0
  871. package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +206 -0
  872. package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +29 -0
  873. package/src/__tests__/prepared-graphics-resolver-recording.unit.test.ts +180 -0
  874. package/src/__tests__/prepared-graphics-resolver.unit.test.ts +287 -0
  875. package/src/__tests__/prepared-graphics-snapshot.unit.test.ts +105 -0
  876. package/src/__tests__/prepared-graphics-store.unit.test.ts +154 -0
  877. package/src/__tests__/prepared-graphics-validation.unit.test.ts +176 -0
  878. package/src/__tests__/profiler-default-off.test.ts +22 -0
  879. package/src/__tests__/profiler-phase-catalog.test.ts +66 -0
  880. package/src/__tests__/profiler-phase-integration.test.ts +70 -0
  881. package/src/__tests__/profiler-phase-token.test.ts +84 -0
  882. package/src/__tests__/public-pipeline-id.test-d.ts +6 -0
  883. package/src/__tests__/public-surface.test-d.ts +32 -0
  884. package/src/__tests__/recover-error-policy-owner.unit.test.ts +127 -0
  885. package/src/__tests__/render-dispatch-membership.unit.test.ts +117 -0
  886. package/src/__tests__/render-error-code-owner.test-d.ts +115 -0
  887. package/src/__tests__/render-error-detail-ssot.test-d.ts +234 -0
  888. package/src/__tests__/render-error-exhaustive.test-d.ts +84 -0
  889. package/src/__tests__/render-feature-assembly.test-d.ts +51 -0
  890. package/src/__tests__/render-feature-construction.unit.test.ts +124 -0
  891. package/src/__tests__/render-feature-context.test-d.ts +81 -0
  892. package/src/__tests__/render-feature-contract.test-d.ts +58 -0
  893. package/src/__tests__/render-feature-diagnostics.unit.test.ts +151 -0
  894. package/src/__tests__/render-feature-docs.unit.test.ts +88 -0
  895. package/src/__tests__/render-feature-error-code-owner.test-d.ts +27 -0
  896. package/src/__tests__/render-feature-errors.unit.test.ts +47 -0
  897. package/src/__tests__/render-feature-gpu-buffer-usage-owner.test-d.ts +46 -0
  898. package/src/__tests__/render-feature-gpu-work.integration.test.ts +377 -0
  899. package/src/__tests__/render-feature-graph.integration.test.ts +205 -0
  900. package/src/__tests__/render-feature-graphics-staging.unit.test.ts +200 -0
  901. package/src/__tests__/render-feature-order.unit.test.ts +66 -0
  902. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +101 -0
  903. package/src/__tests__/render-feature-prepared-errors.test-d.ts +82 -0
  904. package/src/__tests__/render-feature-prepared-graphics-docs.unit.test.ts +141 -0
  905. package/src/__tests__/render-feature-prepared-graphics-isolation.unit.test.ts +122 -0
  906. package/src/__tests__/render-feature-prepared-graphics-negative.test-d.ts +59 -0
  907. package/src/__tests__/render-feature-prepared-graphics-recording.unit.test.ts +107 -0
  908. package/src/__tests__/render-feature-prepared-graphics.test-d.ts +96 -0
  909. package/src/__tests__/render-feature-prepared-graphics.unit.test.ts +121 -0
  910. package/src/__tests__/render-feature-public-surface.test-d.ts +75 -0
  911. package/src/__tests__/render-feature-retry.unit.test.ts +128 -0
  912. package/src/__tests__/render-feature-scheduling.unit.test.ts +122 -0
  913. package/src/__tests__/render-feature-stage-failed-policy-owner.unit.test.ts +146 -0
  914. package/src/__tests__/render-feature-stage-fault-recovery.unit.test.ts +236 -0
  915. package/src/__tests__/render-feature-staging.unit.test.ts +94 -0
  916. package/src/__tests__/render-feature-visibility-context.test-d.ts +38 -0
  917. package/src/__tests__/render-feature-visibility-context.unit.test.ts +38 -0
  918. package/src/__tests__/render-feature-zero-work.unit.test.ts +82 -0
  919. package/src/__tests__/render-graph-compute-raster-gpu.ts +342 -0
  920. package/src/__tests__/render-graph-compute-raster.browser.test.ts +16 -0
  921. package/src/__tests__/render-graph-compute-raster.dawn.test.ts +22 -0
  922. package/src/__tests__/render-graph-hzb-gpu.ts +239 -0
  923. package/src/__tests__/render-graph-hzb.browser.test.ts +16 -0
  924. package/src/__tests__/render-graph-hzb.dawn.test.ts +23 -0
  925. package/src/__tests__/render-graph-primitives.unit.test.ts +22 -0
  926. package/src/__tests__/render-graph-storage-indirect-gpu.ts +162 -0
  927. package/src/__tests__/render-graph-storage-indirect.browser.test.ts +21 -0
  928. package/src/__tests__/render-graph-storage-indirect.dawn.test.ts +28 -0
  929. package/src/__tests__/render-scene-projection.unit.test.ts +206 -0
  930. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +125 -0
  931. package/src/__tests__/renderer-lifecycle.integration.test.ts +10 -0
  932. package/src/__tests__/renderer-render-scene-public.test-d.ts +27 -0
  933. package/src/__tests__/rhi-backend-package-boundary.unit.test.ts +11 -0
  934. package/src/__tests__/scene-temporal-coverage.unit.test.ts +259 -0
  935. package/src/__tests__/scriptable-pack-consumer.test-d.ts +14 -0
  936. package/src/__tests__/shader-stage-surface.unit.test.ts +38 -0
  937. package/src/__tests__/ssao-kernel-surface.unit.test.ts +15 -0
  938. package/src/__tests__/sun-snapshot-consumers.test.ts +35 -0
  939. package/src/__tests__/surface-backend-kind-owner.test-d.ts +42 -0
  940. package/src/__tests__/surface-configuration.unit.test.ts +92 -0
  941. package/src/__tests__/taa-history-store.unit.test.ts +196 -0
  942. package/src/__tests__/temporal-frame-transaction.integration.test.ts +537 -0
  943. package/src/__tests__/temporal-inspection.unit.test.ts +138 -0
  944. package/src/__tests__/texture-usage-surface.unit.test.ts +61 -0
  945. package/src/__tests__/typed-pipeline-topology.unit.test.ts +389 -0
  946. package/src/__tests__/urp-pipeline-targets.unit.test.ts +52 -0
  947. package/src/__tests__/urp-pipeline.unit.test.ts +14 -0
  948. package/src/__tests__/vertex-color-pipeline.unit.test.ts +124 -0
  949. package/src/__tests__/vertex-layout-consumer.unit.test.ts +25 -0
  950. package/src/__tests__/visibility-diagnostics.integration.test.ts +66 -0
  951. package/src/__tests__/visibility-extract.integration.test.ts +89 -0
  952. package/src/__tests__/visibility-extract.perf.test.ts +96 -0
  953. package/src/__tests__/visibility-feature-dedup.integration.test.ts +57 -0
  954. package/src/__tests__/visibility-hidden-report.unit.test.ts +37 -0
  955. package/src/__tests__/visibility-instances.integration.test.ts +50 -0
  956. package/src/__tests__/visibility-multi-world.integration.test.ts +54 -0
  957. package/src/__tests__/visibility-producer-matrix.integration.test.ts +191 -0
  958. package/src/__tests__/visibility-producer-matrix.unit.test.ts +96 -0
  959. package/src/__tests__/visibility-public-surface.test-d.ts +26 -0
  960. package/src/__tests__/visibility-resolver.unit.test.ts +84 -0
  961. package/src/__tests__/visibility-snapshot-contract.unit.test.ts +59 -0
  962. package/src/__tests__/vocabulary.unit.test.ts +21 -0
  963. package/src/assets/__tests__/asset-decoders.unit.test.ts +92 -0
  964. package/src/assets/__tests__/mipmap-generator.unit.test.ts +52 -0
  965. package/src/assets/__tests__/render-asset-port.unit.test.ts +54 -0
  966. package/src/assets/__tests__/resolve-render-asset.unit.test.ts +47 -0
  967. package/src/assets/asset-decoders.ts +158 -0
  968. package/src/assets/render-asset-port.ts +44 -0
  969. package/src/assets/resolve-render-asset.ts +13 -0
  970. package/src/authoring.ts +24 -0
  971. package/src/cluster-binner.ts +700 -0
  972. package/src/components/__tests__/atmosphere-red.test.ts +51 -0
  973. package/src/components/__tests__/atmosphere.test.ts +79 -0
  974. package/src/components/__tests__/fog.test-d.ts +49 -0
  975. package/src/components/__tests__/fog.test.ts +60 -0
  976. package/src/components/__tests__/schema-parity.unit.test.ts +25 -0
  977. package/src/components/__tests__/visibility-schema.unit.test.ts +35 -0
  978. package/src/components/atmosphere.ts +64 -0
  979. package/src/components/camera.ts +512 -0
  980. package/src/components/directional-light.ts +120 -0
  981. package/src/components/environment.ts +206 -0
  982. package/src/components/glyph-text.ts +63 -0
  983. package/src/components/index.ts +49 -0
  984. package/src/components/instances.ts +207 -0
  985. package/src/components/layer.ts +69 -0
  986. package/src/components/light-helpers.ts +188 -0
  987. package/src/components/mesh-filter.ts +59 -0
  988. package/src/components/mesh-renderer.ts +61 -0
  989. package/src/components/point-light-shadow.ts +43 -0
  990. package/src/components/point-light.ts +65 -0
  991. package/src/components/post-process-params.ts +35 -0
  992. package/src/components/scene-instance.ts +193 -0
  993. package/src/components/sort-key.ts +75 -0
  994. package/src/components/spot-light.ts +124 -0
  995. package/src/components/sprite-animation.ts +169 -0
  996. package/src/components/sprite-instances.ts +179 -0
  997. package/src/components/sprite-playback-mode.ts +73 -0
  998. package/src/components/sprite-region-override.ts +106 -0
  999. package/src/components/tile-layer.ts +161 -0
  1000. package/src/components/tilemap.ts +48 -0
  1001. package/src/components/visibility.ts +53 -0
  1002. package/src/construct-renderer.ts +4 -0
  1003. package/src/debug-draw-glue.ts +169 -0
  1004. package/src/deferred-lighting.ts +92 -0
  1005. package/src/dynamic-texture-store.ts +111 -0
  1006. package/src/engine-metrics.ts +89 -0
  1007. package/src/environment/README.md +76 -0
  1008. package/src/environment/__tests__/failure-injection.test.ts +50 -0
  1009. package/src/environment/__tests__/generation-red.test.ts +64 -0
  1010. package/src/environment/__tests__/generation.test.ts +37 -0
  1011. package/src/environment/__tests__/graph-transaction.test.ts +85 -0
  1012. package/src/environment/__tests__/inspection-red.test.ts +53 -0
  1013. package/src/environment/__tests__/lifecycle-evidence.test.ts +40 -0
  1014. package/src/environment/__tests__/pipeline-topology.test.ts +33 -0
  1015. package/src/environment/__tests__/readiness.test.ts +42 -0
  1016. package/src/environment/__tests__/recovery.test.ts +62 -0
  1017. package/src/environment/__tests__/resize-dispose.test.ts +30 -0
  1018. package/src/environment/__tests__/signature-red.test.ts +45 -0
  1019. package/src/environment/__tests__/signature.test.ts +60 -0
  1020. package/src/environment/descriptors.ts +7 -0
  1021. package/src/environment/extracted-environment.ts +239 -0
  1022. package/src/environment/generation.ts +158 -0
  1023. package/src/environment/gpu-bundle.ts +144 -0
  1024. package/src/environment/graph.ts +588 -0
  1025. package/src/environment/inspection.ts +107 -0
  1026. package/src/environment/lifecycle.ts +124 -0
  1027. package/src/environment/readiness.ts +76 -0
  1028. package/src/environment/signature.ts +185 -0
  1029. package/src/errors/ecs-validation.ts +16 -0
  1030. package/src/errors/index.ts +3 -0
  1031. package/src/errors/recover.ts +119 -0
  1032. package/src/errors/render.ts +1244 -0
  1033. package/src/extract/__tests__/directional-csm-domain.unit.test.ts +391 -0
  1034. package/src/extract/__tests__/environment-source.test.ts +105 -0
  1035. package/src/extract/__tests__/schema-readers.unit.test.ts +16 -0
  1036. package/src/extract/directional-csm.ts +959 -0
  1037. package/src/extract/index.ts +10 -0
  1038. package/src/extract/material-interface.ts +604 -0
  1039. package/src/extract/schema-readers.ts +27 -0
  1040. package/src/extract/visibility.ts +120 -0
  1041. package/src/features/graph-contribution.ts +577 -0
  1042. package/src/features/host.ts +1097 -0
  1043. package/src/features/index.ts +100 -0
  1044. package/src/features/morph/index.ts +24 -0
  1045. package/src/features/morph/morph-bounds.ts +123 -0
  1046. package/src/features/morph/morph-feature.ts +287 -0
  1047. package/src/features/prepared-gpu-work.ts +902 -0
  1048. package/src/features/prepared-graphics-store.ts +435 -0
  1049. package/src/features/prepared-graphics.ts +479 -0
  1050. package/src/features/render-graph-compute.ts +60 -0
  1051. package/src/features/render-graph-contribution.ts +95 -0
  1052. package/src/features/render-graph-raster.ts +308 -0
  1053. package/src/features/render-graph-resources.ts +36 -0
  1054. package/src/features/scene-temporal.ts +274 -0
  1055. package/src/features/taa-resolve.ts +244 -0
  1056. package/src/features/targets.ts +83 -0
  1057. package/src/features/types.ts +291 -0
  1058. package/src/frame-chain.ts +21 -0
  1059. package/src/fullscreen-post-process-pass.ts +406 -0
  1060. package/src/glyph-text-layout-system.ts +447 -0
  1061. package/src/gpu-driven/batch-topology.ts +423 -0
  1062. package/src/gpu-driven/production-raster.ts +1705 -0
  1063. package/src/gpu-driven/view-gpu.ts +849 -0
  1064. package/src/gpu-driven/view-reference.ts +110 -0
  1065. package/src/gpu-resource-store.ts +1921 -0
  1066. package/src/gpu-resource.ts +159 -0
  1067. package/src/gpu-scene-schema.ts +224 -0
  1068. package/src/gpu-scene.ts +855 -0
  1069. package/src/gpu-stage.ts +9 -0
  1070. package/src/gpu-texture-usage.ts +12 -0
  1071. package/src/gpu-usage.ts +14 -0
  1072. package/src/hdrp-buffers.ts +689 -0
  1073. package/src/hdrp-cluster-membership.ts +70 -0
  1074. package/src/hdrp-pipeline.ts +525 -0
  1075. package/src/ibl/IblPipelineCache.ts +1246 -0
  1076. package/src/ibl/cubemap-projection.ts +60 -0
  1077. package/src/ibl/face-uniforms.ts +150 -0
  1078. package/src/ibl/skylight-bind-group.ts +513 -0
  1079. package/src/index.ts +271 -0
  1080. package/src/instance-buffer-cache.ts +123 -0
  1081. package/src/internal.ts +88 -0
  1082. package/src/lifecycle.ts +123 -0
  1083. package/src/light-buffer-layout.ts +346 -0
  1084. package/src/materials.ts +236 -0
  1085. package/src/mesh-material-bindings.ts +104 -0
  1086. package/src/mesh-update-errors.ts +113 -0
  1087. package/src/mipmap-generator.ts +244 -0
  1088. package/src/param-schema-projection-census.ts +73 -0
  1089. package/src/pbr-pipeline.ts +749 -0
  1090. package/src/persistent-render-scene.ts +1752 -0
  1091. package/src/pipeline/index.ts +40 -0
  1092. package/src/pipeline-builder.ts +386 -0
  1093. package/src/pipeline-errors.ts +172 -0
  1094. package/src/pipeline-spec.ts +1768 -0
  1095. package/src/plugin.ts +137 -0
  1096. package/src/post-process-errors.ts +304 -0
  1097. package/src/prepare/__tests__/schema-readers.unit.test.ts +16 -0
  1098. package/src/prepare/index.ts +8 -0
  1099. package/src/prepare/prepared-graphics-resolver.ts +455 -0
  1100. package/src/prepare/schema-readers.ts +20 -0
  1101. package/src/record/__tests__/environment-record.test.ts +35 -0
  1102. package/src/record/__tests__/frame-targets.unit.test.ts +54 -0
  1103. package/src/record/__tests__/material-bg-cache.unit.test.ts +41 -0
  1104. package/src/record/__tests__/material-slot-plan.unit.test.ts +76 -0
  1105. package/src/record/__tests__/membership-timing.unit.test.ts +524 -0
  1106. package/src/record/__tests__/render-submission.integration.test.ts +76 -0
  1107. package/src/record/__tests__/render-submission.perf.test.ts +141 -0
  1108. package/src/record/__tests__/shadow-submit-mode.unit.test.ts +88 -0
  1109. package/src/record/__tests__/video-texture-view.unit.test.ts +90 -0
  1110. package/src/record/__tests__/view-ubo-layout.unit.test.ts +101 -0
  1111. package/src/record/frame-lighting.ts +1183 -0
  1112. package/src/record/frame-observation.ts +122 -0
  1113. package/src/record/frame-snapshot.ts +515 -0
  1114. package/src/record/frame-targets.ts +372 -0
  1115. package/src/record/frame.ts +1874 -0
  1116. package/src/record/helpers.ts +289 -0
  1117. package/src/record/index.ts +15 -0
  1118. package/src/record/main-pass-geometry.ts +1014 -0
  1119. package/src/record/main-pass-material.ts +716 -0
  1120. package/src/record/main-pass-skin.ts +51 -0
  1121. package/src/record/main-pass-sprite-draws.ts +1056 -0
  1122. package/src/record/main-pass-sprite.ts +166 -0
  1123. package/src/record/main-pass.ts +588 -0
  1124. package/src/record/material-payload.ts +292 -0
  1125. package/src/record/material-slot-plan.ts +68 -0
  1126. package/src/record/membership-timing.ts +1012 -0
  1127. package/src/record/mesh-ssbo.ts +406 -0
  1128. package/src/record/shadow-caster-uniform.ts +37 -0
  1129. package/src/record/shadow-pass.ts +2387 -0
  1130. package/src/record/shadow-submit-mode.ts +277 -0
  1131. package/src/record/skybox-post-pass.ts +594 -0
  1132. package/src/record/typed-frame-graph.ts +499 -0
  1133. package/src/record/view-ubo.ts +206 -0
  1134. package/src/render-data.ts +385 -0
  1135. package/src/render-dispatch-membership.ts +155 -0
  1136. package/src/render-graph-primitives.ts +1586 -0
  1137. package/src/render-pipeline-context.ts +332 -0
  1138. package/src/render-pipeline-target.ts +96 -0
  1139. package/src/render-pipeline.ts +343 -0
  1140. package/src/render-scene-projection.ts +1738 -0
  1141. package/src/render-system-extract.ts +5203 -0
  1142. package/src/render-system-fold.ts +531 -0
  1143. package/src/render-system.ts +3258 -0
  1144. package/src/renderer/asset-service.ts +32 -0
  1145. package/src/renderer/backend-selection.ts +121 -0
  1146. package/src/renderer/environment-classify.ts +30 -0
  1147. package/src/renderer/environment-error.ts +19 -0
  1148. package/src/renderer/material/assembly.ts +53 -0
  1149. package/src/renderer/material/pipeline-projection.ts +140 -0
  1150. package/src/renderer/renderer-factory.ts +9062 -0
  1151. package/src/renderer.ts +940 -0
  1152. package/src/scene-instances/post-spawn-resolve-joints.ts +168 -0
  1153. package/src/scene-utils/collect-subtree.ts +40 -0
  1154. package/src/shadow-atlas.ts +244 -0
  1155. package/src/ssao-buffers.ts +175 -0
  1156. package/src/ssao-config.ts +61 -0
  1157. package/src/ssao-data.ts +106 -0
  1158. package/src/surface-format.ts +37 -0
  1159. package/src/systems/active-camera.ts +116 -0
  1160. package/src/systems/pass-selector.ts +49 -0
  1161. package/src/systems/skin-palette-allocator.ts +294 -0
  1162. package/src/systems/transparent-sort-config.ts +211 -0
  1163. package/src/taa-history-store.ts +429 -0
  1164. package/src/temporal-coverage.ts +106 -0
  1165. package/src/temporal-frame-transaction.ts +301 -0
  1166. package/src/temporal-inspection.ts +194 -0
  1167. package/src/temporal-view.ts +174 -0
  1168. package/src/tilemap/resolve-tileset-runtime.ts +72 -0
  1169. package/src/tilemap-chunk-extract-system.ts +1307 -0
  1170. package/src/typed-render-graph-primitives.ts +530 -0
  1171. package/src/typed-shadow-passes.ts +195 -0
  1172. package/src/urp-pipeline.ts +340 -0
@@ -0,0 +1,1752 @@
1
+ import type { Component, EntityHandle, World } from '@forgeax/engine-ecs';
2
+ import { Disabled } from '@forgeax/engine-ecs';
3
+ import { createWorldProjection, type WorldProjection } from '@forgeax/engine-ecs/projection';
4
+ import { box3, frustum, mat4 } from '@forgeax/engine-math';
5
+ import type { RhiDevice, RhiError } from '@forgeax/engine-rhi';
6
+ import { ChildOf, MorphWeights, Transform } from '@forgeax/engine-scene';
7
+ import { Skin } from '@forgeax/engine-skinning';
8
+ import {
9
+ Camera,
10
+ DirectionalLight,
11
+ Fog,
12
+ Instances,
13
+ Layer,
14
+ MeshFilter,
15
+ MeshRenderer,
16
+ PointLight,
17
+ PointLightShadow,
18
+ PostProcessParams,
19
+ SkyboxBackground,
20
+ Skylight,
21
+ SpotLight,
22
+ SpriteInstances,
23
+ SpriteRegionOverride,
24
+ Visibility,
25
+ } from './components';
26
+ import {
27
+ type CsmCameraData,
28
+ computeDirectionalCsm,
29
+ type DirectionalCsmCandidateBroadphase,
30
+ } from './extract/directional-csm';
31
+ import {
32
+ BatchTopology,
33
+ type BatchTopologyInspection,
34
+ type SubmissionPlan,
35
+ } from './gpu-driven/batch-topology';
36
+ import { GpuScene, type GpuSceneInspection } from './gpu-scene';
37
+ import {
38
+ buildRenderCandidateDomain,
39
+ buildRenderCandidateIdentityIndex,
40
+ type RenderCandidateDomain,
41
+ renderCandidateCsmCandidates,
42
+ reuseRenderCandidateDomain,
43
+ } from './render-dispatch-membership';
44
+ import type {
45
+ RenderSceneApplyResult,
46
+ RenderSceneOperation,
47
+ RenderSceneSubmissionDelta,
48
+ } from './render-scene-projection';
49
+ import { RenderSceneProjection } from './render-scene-projection';
50
+ import type {
51
+ CameraSnapshot,
52
+ DispatchEntry,
53
+ ExtractedFrame,
54
+ FogSelection,
55
+ FogSnapshot,
56
+ RenderableSnapshot,
57
+ } from './render-system-extract';
58
+ import { sortDispatchByQueue } from './render-system-extract';
59
+ import { ACTIVE_CAMERA_KEY } from './systems/active-camera';
60
+
61
+ export type RenderSceneResyncReason =
62
+ | 'attach'
63
+ | 'asset-catalog-changed'
64
+ | 'shared-ref-changed'
65
+ | 'journal-overflow'
66
+ | 'unsupported-change'
67
+ | 'non-rigid-lane'
68
+ | 'explicit-invalidate';
69
+
70
+ export type PersistentFogFailureCode = 'fog-owner-conflict' | 'fog-parameters-invalid';
71
+
72
+ export interface PersistentFogInspection {
73
+ readonly enabled: boolean;
74
+ readonly resourceOwner: number | undefined;
75
+ readonly entity: number | undefined;
76
+ readonly revision: number | undefined;
77
+ readonly reactive: boolean;
78
+ readonly failure: PersistentFogFailureCode | undefined;
79
+ }
80
+
81
+ export interface PersistentFogFailure {
82
+ readonly code: PersistentFogFailureCode;
83
+ readonly resourceOwner: number;
84
+ }
85
+
86
+ export interface PersistentRenderSceneInspection {
87
+ readonly worldEntitiesScanned: number;
88
+ readonly fullRebuilds: number;
89
+ readonly noChangeFrames: number;
90
+ readonly deltaFrames: number;
91
+ readonly transformUpdates: number;
92
+ readonly materialUpdates: number;
93
+ readonly instanceUpdates: number;
94
+ readonly cameraUpdates: number;
95
+ readonly resourceUpdates: number;
96
+ /** Number of journal entities admitted to the local topology reconciler. */
97
+ readonly topologyEntitiesReconciled: number;
98
+ /** Number of identity-addressed production render extractions requested. */
99
+ readonly singleEntityExtractions: number;
100
+ readonly removals: number;
101
+ readonly lastResyncReason: RenderSceneResyncReason | undefined;
102
+ /** @internal M0 attribution for a rebuild that otherwise only says unsupported-change. */
103
+ readonly lastResyncDetail: string | undefined;
104
+ readonly cursor: number | undefined;
105
+ readonly projectionRecords: number;
106
+ readonly spatialIndex: import('./render-scene-projection').SpatialIndexInspection | undefined;
107
+ readonly topology: BatchTopologyInspection;
108
+ readonly gpu:
109
+ | { readonly status: 'inactive' }
110
+ | { readonly status: 'unsupported'; readonly reason: 'storage-buffer-unavailable' }
111
+ | ({ readonly status: 'resident' } & GpuSceneInspection)
112
+ | { readonly status: 'rebuild-pending' }
113
+ | { readonly status: 'error' };
114
+ readonly fog: PersistentFogInspection;
115
+ }
116
+
117
+ export interface PersistentRenderSceneOptions {
118
+ readonly getDevice?: (() => RhiDevice) | undefined;
119
+ readonly onGpuError?: ((error: RhiError) => void) | undefined;
120
+ /** @internal Collect complete per-candidate CSM decisions for debug capture. */
121
+ readonly collectShadowDebugCandidates?: (() => boolean) | undefined;
122
+ }
123
+
124
+ /**
125
+ * Complete facts produced by the render-domain admission owner for one ECS
126
+ * entity. Dispatch entries use the local candidate index from that extraction;
127
+ * PersistentRenderScene rebases them onto its slot-owned candidate domain.
128
+ */
129
+ export interface PersistentRenderableExtraction {
130
+ readonly snapshot: RenderableSnapshot;
131
+ readonly candidateDispatch: readonly DispatchEntry[];
132
+ }
133
+
134
+ export interface PersistentGpuDrivenState {
135
+ readonly scene: GpuScene;
136
+ readonly plan: SubmissionPlan;
137
+ readonly slots: readonly import('./render-scene-projection').RenderSceneProjectionSlot[];
138
+ /**
139
+ * The same projection that owns `slots` and the spatial index. Visibility
140
+ * must query this owner; a revision number copied into GpuScene is only
141
+ * diagnostic metadata and cannot select a candidate domain by itself.
142
+ */
143
+ /** Present for the production owner; optional keeps older test doubles honest. */
144
+ readonly projection?: RenderSceneProjection;
145
+ }
146
+
147
+ type PersistentGpuSceneInspection = PersistentRenderSceneInspection['gpu'];
148
+
149
+ interface PersistentWorldEntry {
150
+ readonly worldId: number;
151
+ readonly projection: RenderSceneProjection;
152
+ readonly topology: BatchTopology;
153
+ candidateFrame: ExtractedFrame;
154
+ visibleFrame: ExtractedFrame;
155
+ readonly changeProjection: WorldProjection;
156
+ cursor: number;
157
+ catalogEpoch: number;
158
+ sharedRefEpoch: number;
159
+ activeCameraEpoch: number;
160
+ cameraEntities: ReadonlySet<EntityHandle>;
161
+ readonly rigidOnly: boolean;
162
+ gpuDrivenCoverageKey: string | undefined;
163
+ gpuDrivenOwnsAll: boolean;
164
+ }
165
+
166
+ interface PersistentCompositionEntry {
167
+ readonly token: object;
168
+ readonly worlds: readonly World[];
169
+ readonly worldIds: readonly number[];
170
+ readonly cameraOwner: number;
171
+ readonly resourceOwner: number;
172
+ readonly projection: RenderSceneProjection;
173
+ readonly topology: BatchTopology;
174
+ readonly changeProjections: readonly WorldProjection[];
175
+ candidateFrame: ExtractedFrame;
176
+ visibleFrame: ExtractedFrame;
177
+ readonly cursors: number[];
178
+ readonly sharedRefEpochs: number[];
179
+ readonly cameraEntities: readonly ReadonlySet<EntityHandle>[];
180
+ catalogEpoch: number;
181
+ readonly rigidOnly: boolean;
182
+ gpuDrivenCoverageKey: string | undefined;
183
+ gpuDrivenOwnsAll: boolean;
184
+ }
185
+
186
+ const RENDER_RELEVANT_COMPONENTS = [
187
+ Transform,
188
+ ChildOf,
189
+ MeshFilter,
190
+ MeshRenderer,
191
+ Instances,
192
+ SpriteInstances,
193
+ SpriteRegionOverride,
194
+ Skin,
195
+ MorphWeights,
196
+ Layer,
197
+ Visibility,
198
+ Disabled,
199
+ Camera,
200
+ DirectionalLight,
201
+ PointLight,
202
+ PointLightShadow,
203
+ SpotLight,
204
+ Skylight,
205
+ Fog,
206
+ SkyboxBackground,
207
+ PostProcessParams,
208
+ ] as const;
209
+ const RENDER_RELEVANT_COMPONENT_SET = new Set<Component>(RENDER_RELEVANT_COMPONENTS);
210
+
211
+ const NON_RENDERABLE_TRANSFORM_CONSUMERS = [
212
+ Camera,
213
+ DirectionalLight,
214
+ PointLight,
215
+ SpotLight,
216
+ ] as const;
217
+
218
+ function cameraFrusta(cameras: readonly CameraSnapshot[]): readonly Float32Array[] {
219
+ const planes: Float32Array[] = [];
220
+ for (const camera of cameras) {
221
+ if (
222
+ (camera.projection === 'perspective' && (camera.fov <= 0 || camera.aspect <= 0)) ||
223
+ camera.near >= camera.far
224
+ ) {
225
+ planes.push(new Float32Array(0));
226
+ continue;
227
+ }
228
+ const projection = mat4.create();
229
+ if (camera.projection === 'orthographic') {
230
+ mat4.orthographic(
231
+ projection,
232
+ camera.orthoLeft,
233
+ camera.orthoRight,
234
+ camera.orthoBottom,
235
+ camera.orthoTop,
236
+ camera.near,
237
+ camera.far,
238
+ );
239
+ } else {
240
+ mat4.perspective(projection, camera.fov, camera.aspect, camera.near, camera.far);
241
+ }
242
+ const view = mat4.create();
243
+ mat4.invert(view, camera.world as unknown as mat4.Mat4Like);
244
+ const viewProjection = mat4.create();
245
+ mat4.multiply(viewProjection, projection, view);
246
+ const cameraPlanes = frustum.create();
247
+ frustum.fromViewProjection(cameraPlanes, viewProjection);
248
+ planes.push(cameraPlanes);
249
+ }
250
+ return planes;
251
+ }
252
+
253
+ function candidateBroadphaseForProjection(
254
+ projection: RenderSceneProjection,
255
+ candidateDomain: RenderCandidateDomain,
256
+ ): DirectionalCsmCandidateBroadphase {
257
+ return (worldAabb) =>
258
+ projection.querySpatialIndex(worldAabb).hits.flatMap((hit) => {
259
+ const candidateIndex = candidateDomain.indexByIdentity.get(`${hit.worldId}:${hit.entityKey}`);
260
+ return candidateIndex === undefined ? [] : [candidateIndex];
261
+ });
262
+ }
263
+
264
+ function rebaseCandidateDomain(
265
+ frame: ExtractedFrame,
266
+ candidates: readonly RenderableSnapshot[],
267
+ patch?: {
268
+ readonly worldId: number;
269
+ readonly dispatch: readonly DispatchEntry[];
270
+ readonly replaceIdentities: ReadonlySet<string>;
271
+ },
272
+ ): ExtractedFrame {
273
+ const previousCandidates =
274
+ frame.candidateDomain?.renderables ?? frame.candidateRenderables ?? frame.renderables;
275
+ const previousDispatch =
276
+ frame.candidateDomain?.dispatch ?? frame.candidateDispatch ?? frame.dispatch;
277
+ const previousDomain =
278
+ frame.candidateDomain ?? buildRenderCandidateDomain(previousCandidates, previousDispatch);
279
+ const candidateDomainUnchanged =
280
+ previousCandidates.length === candidates.length &&
281
+ previousCandidates.every(
282
+ (candidate, candidateIndex) =>
283
+ candidate === candidates[candidateIndex] &&
284
+ (candidate.candidateIndex === undefined || candidate.candidateIndex === candidateIndex),
285
+ );
286
+ if (candidateDomainUnchanged && frame.candidateDomain !== undefined) {
287
+ // Camera-only refreshes must not manufacture a new candidate array, index
288
+ // map, dispatch array, or membership Set when the domain is unchanged.
289
+ return frame;
290
+ }
291
+ const candidateRenderables = candidates.map((candidate, candidateIndex) =>
292
+ candidate.candidateIndex === candidateIndex ? candidate : { ...candidate, candidateIndex },
293
+ );
294
+ const nextIndexByIdentity = buildRenderCandidateIdentityIndex(candidateRenderables);
295
+
296
+ const candidateDispatch = previousDomain.dispatch.flatMap((entry) => {
297
+ const previousCandidate = previousCandidates[entry.renderableIndex];
298
+ if (previousCandidate === undefined) return [];
299
+ if (
300
+ patch?.replaceIdentities.has(
301
+ `${previousCandidate.worldId}:${previousCandidate.entityKey}`,
302
+ ) === true
303
+ ) {
304
+ return [];
305
+ }
306
+ const candidateIndex = nextIndexByIdentity.get(
307
+ `${previousCandidate.worldId}:${previousCandidate.entityKey}`,
308
+ );
309
+ return candidateIndex === undefined ? [] : [{ ...entry, renderableIndex: candidateIndex }];
310
+ });
311
+ if (patch !== undefined) {
312
+ for (const entry of patch.dispatch) {
313
+ const candidateIndex = nextIndexByIdentity.get(`${patch.worldId}:${entry.entityIndex}`);
314
+ if (candidateIndex === undefined) continue;
315
+ candidateDispatch.push({ ...entry, renderableIndex: candidateIndex });
316
+ }
317
+ }
318
+ const candidateDomain = buildRenderCandidateDomain(
319
+ candidateRenderables,
320
+ sortDispatchByQueue(candidateDispatch),
321
+ nextIndexByIdentity,
322
+ );
323
+
324
+ return {
325
+ ...frame,
326
+ candidateRenderables: candidateDomain.renderables,
327
+ candidateDispatch: candidateDomain.dispatch,
328
+ candidateDispatchMembership: candidateDomain.membership,
329
+ candidateDomain,
330
+ };
331
+ }
332
+
333
+ function cullPersistentFrame(
334
+ frame: ExtractedFrame,
335
+ candidates: readonly RenderableSnapshot[],
336
+ collectShadowDebugCandidates = false,
337
+ projection?: RenderSceneProjection,
338
+ ): ExtractedFrame {
339
+ const planes = cameraFrusta(frame.cameras);
340
+ const candidateSnapshots =
341
+ frame.candidateDomain?.renderables ?? frame.candidateRenderables ?? candidates;
342
+ const candidateDispatch =
343
+ frame.candidateDomain?.dispatch ?? frame.candidateDispatch ?? frame.dispatch;
344
+ const candidateDomain = reuseRenderCandidateDomain(
345
+ candidateSnapshots,
346
+ candidateDispatch,
347
+ frame.candidateDomain,
348
+ );
349
+ const mainVisible = new Set<number>();
350
+ let total = 0;
351
+ let culled = 0;
352
+
353
+ for (let index = 0; index < candidateSnapshots.length; index += 1) {
354
+ const candidate = candidateSnapshots[index];
355
+ if (candidate === undefined) continue;
356
+ let isVisible = true;
357
+ if (candidate.localAabb !== undefined) {
358
+ total += 1;
359
+ const worldAabb = box3.create();
360
+ box3.transformBox3(
361
+ worldAabb,
362
+ candidate.localAabb,
363
+ candidate.transform.world as unknown as Parameters<typeof box3.transformBox3>[2],
364
+ );
365
+ isVisible = planes.length === 0;
366
+ for (const cameraPlanes of planes) {
367
+ if (
368
+ cameraPlanes.length === 0 ||
369
+ frustum.intersectsBox(cameraPlanes as frustum.Frustum, worldAabb as box3.Box3Like)
370
+ ) {
371
+ isVisible = true;
372
+ break;
373
+ }
374
+ }
375
+ }
376
+ if (!isVisible) {
377
+ culled += 1;
378
+ continue;
379
+ }
380
+ mainVisible.add(index);
381
+ }
382
+
383
+ const camera = frame.cameras[0];
384
+ const csmConfig = frame.lights.directionalCsmConfig;
385
+ const csmDirection = frame.lights.directionalCsmDirection;
386
+ const csmCamera: CsmCameraData | undefined =
387
+ camera === undefined
388
+ ? undefined
389
+ : {
390
+ world: camera.world,
391
+ fov: camera.fov,
392
+ aspect: camera.aspect,
393
+ near: camera.near,
394
+ far: camera.far,
395
+ projection: camera.projection,
396
+ orthoLeft: camera.orthoLeft,
397
+ orthoRight: camera.orthoRight,
398
+ orthoBottom: camera.orthoBottom,
399
+ orthoTop: camera.orthoTop,
400
+ };
401
+ const candidateDispatchMembership = candidateDomain.membership;
402
+ const recomputedCsm =
403
+ csmConfig !== undefined && csmDirection !== undefined
404
+ ? computeDirectionalCsm(
405
+ csmDirection,
406
+ { ...csmConfig, collectCandidateDecisions: collectShadowDebugCandidates },
407
+ csmCamera,
408
+ renderCandidateCsmCandidates(candidateDomain),
409
+ projection === undefined
410
+ ? undefined
411
+ : candidateBroadphaseForProjection(projection, candidateDomain),
412
+ )
413
+ : undefined;
414
+ const csm = recomputedCsm ?? frame.lights.directionalCsm;
415
+ if (csm !== undefined) {
416
+ for (const cascade of csm.cascades) {
417
+ for (const index of cascade.casterRenderableIndices) {
418
+ // Keep the candidate index stable across main-view culling.
419
+ if (index >= 0) mainVisible.add(index);
420
+ }
421
+ }
422
+ }
423
+
424
+ const unionIndices = [...mainVisible].sort((left, right) => left - right);
425
+ const projectedIndex = new Int32Array(candidateSnapshots.length);
426
+ projectedIndex.fill(-1);
427
+ const visible: RenderableSnapshot[] = [];
428
+ for (const candidateIndex of unionIndices) {
429
+ const candidate = candidateSnapshots[candidateIndex];
430
+ if (candidate === undefined) continue;
431
+ projectedIndex[candidateIndex] = visible.length;
432
+ visible.push(candidate);
433
+ }
434
+
435
+ const dispatch: DispatchEntry[] = [];
436
+ for (const entry of candidateDispatch) {
437
+ const renderableIndex = projectedIndex[entry.renderableIndex];
438
+ if (renderableIndex === undefined || renderableIndex < 0) continue;
439
+ dispatch.push({ ...entry, renderableIndex });
440
+ }
441
+ const finalizedCsm = csm;
442
+ const nextLights =
443
+ finalizedCsm === undefined
444
+ ? frame.lights
445
+ : {
446
+ ...frame.lights,
447
+ // The CSM plan owns receiver matrices and cascade volumes. Camera
448
+ // refresh can first produce a no-candidate fit; once the candidate
449
+ // domain is available here, publish every light field from the same
450
+ // finalized plan so four-view visibility and the View UBO cannot use
451
+ // different cascade spaces.
452
+ lightViewProj: finalizedCsm.lightViewProj,
453
+ splitPlanes: finalizedCsm.splitPlanes,
454
+ cascadeCount: finalizedCsm.cascadeCount,
455
+ cascadeBlend: finalizedCsm.cascadeBlend,
456
+ shadowMapSize: finalizedCsm.shadowMapSize,
457
+ directionalCsm: finalizedCsm,
458
+ cascades: finalizedCsm.cascades,
459
+ };
460
+ return {
461
+ ...frame,
462
+ renderables: visible,
463
+ dispatch,
464
+ candidateRenderables: candidateDomain.renderables,
465
+ candidateDispatch: candidateDomain.dispatch,
466
+ candidateDispatchMembership,
467
+ candidateDomain,
468
+ lights: nextLights,
469
+ frustumStats: { culled, total },
470
+ };
471
+ }
472
+
473
+ /** Persistent single-World rigid scene used by the renderer's ordinary path. */
474
+ export class PersistentRenderScene {
475
+ private readonly entries = new WeakMap<World, PersistentWorldEntry>();
476
+ private readonly worldIds = new WeakMap<World, number>();
477
+ private readonly worldsById = new Map<number, World>();
478
+ private nextWorldId = 0;
479
+ private fullRebuilds = 0;
480
+ private worldEntitiesScanned = 0;
481
+ private noChangeFrames = 0;
482
+ private deltaFrames = 0;
483
+ private transformUpdates = 0;
484
+ private materialUpdates = 0;
485
+ private instanceUpdates = 0;
486
+ private cameraUpdates = 0;
487
+ private resourceUpdates = 0;
488
+ private topologyEntitiesReconciled = 0;
489
+ private singleEntityExtractions = 0;
490
+ private removals = 0;
491
+ private lastResyncReason: RenderSceneResyncReason | undefined;
492
+ private lastResyncDetail: string | undefined;
493
+ private lastWorld: World | undefined;
494
+ private composition: PersistentCompositionEntry | undefined;
495
+ private gpuScene: GpuScene | undefined;
496
+ private gpuOwner: object | undefined;
497
+ private gpuDevice: RhiDevice | undefined;
498
+ private gpuStatus: 'inactive' | 'unsupported' | 'resident' | 'rebuild-pending' | 'error' =
499
+ 'inactive';
500
+ private fogCandidate: FogSelection | undefined;
501
+ private fogLastKnownGood: FogSelection | undefined;
502
+ private fogFailure: PersistentFogFailureCode | undefined;
503
+ private fogFailureOwner: number | undefined;
504
+ private fogReactive = false;
505
+
506
+ constructor(private readonly options: PersistentRenderSceneOptions = {}) {}
507
+
508
+ readonly worldForRenderId = (worldId: number): World | undefined => this.worldsById.get(worldId);
509
+
510
+ extract(
511
+ world: World,
512
+ catalogEpoch: number,
513
+ buildCandidateFrame: () => ExtractedFrame,
514
+ refreshMaterial?: (
515
+ snapshot: RenderableSnapshot,
516
+ materialHandle: number,
517
+ ) => RenderableSnapshot | undefined,
518
+ refreshCameras?: (frame: ExtractedFrame) => ExtractedFrame,
519
+ gpuDrivenCoverageKey?: string,
520
+ refreshPostProcessParams?: (frame: ExtractedFrame) => ExtractedFrame,
521
+ refreshLights?: (frame: ExtractedFrame) => ExtractedFrame,
522
+ refreshRenderable?: (
523
+ entity: EntityHandle,
524
+ currentFrame: ExtractedFrame,
525
+ ) => PersistentRenderableExtraction | undefined,
526
+ ): ExtractedFrame {
527
+ this.worldEntitiesScanned = 0;
528
+ this.lastWorld = world;
529
+ this.attachWorld(world);
530
+ const entry = this.entries.get(world);
531
+ if (entry === undefined) {
532
+ return this.rebuild(world, catalogEpoch, buildCandidateFrame, 'attach');
533
+ }
534
+ if (entry.catalogEpoch !== catalogEpoch) {
535
+ return this.rebuild(world, catalogEpoch, buildCandidateFrame, 'asset-catalog-changed');
536
+ }
537
+ const sharedRefChanges = world.sharedRefs.readChangesSince(entry.sharedRefEpoch);
538
+ if (sharedRefChanges.status === 'overflow') {
539
+ return this.rebuild(world, catalogEpoch, buildCandidateFrame, 'shared-ref-changed');
540
+ }
541
+
542
+ const changes = entry.changeProjection.poll();
543
+ if (changes.status === 'rebuild') {
544
+ return this.rebuild(world, catalogEpoch, buildCandidateFrame, 'journal-overflow');
545
+ }
546
+ const refreshedBySlot = new Map<number, RenderableSnapshot>();
547
+ for (const change of sharedRefChanges.records) {
548
+ const affected = entry.projection.slotsForMaterial(change.handle);
549
+ if (affected.length > 0 && refreshMaterial === undefined) {
550
+ return this.rebuild(world, catalogEpoch, buildCandidateFrame, 'shared-ref-changed');
551
+ }
552
+ for (const slot of affected) {
553
+ const current = refreshedBySlot.get(slot.slot) ?? slot.snapshot;
554
+ const refreshed = refreshMaterial?.(current, change.handle);
555
+ if (refreshed === undefined) {
556
+ return this.rebuild(world, catalogEpoch, buildCandidateFrame, 'shared-ref-changed');
557
+ }
558
+ refreshedBySlot.set(slot.slot, refreshed);
559
+ }
560
+ }
561
+ const materialOperations: RenderSceneOperation[] = [...refreshedBySlot.entries()].map(
562
+ ([slot, snapshot]) => {
563
+ const liveSlot = entry.projection.slotByIndex(slot);
564
+ return {
565
+ kind: 'create',
566
+ snapshot,
567
+ ...(liveSlot === undefined ? {} : { expectedGeneration: liveSlot.generation }),
568
+ };
569
+ },
570
+ );
571
+ let postProcessParamsChanged = false;
572
+ let lightsChanged = false;
573
+ const activeCameraEpoch = world.getResourceChange(ACTIVE_CAMERA_KEY)?.changed ?? 0;
574
+ let cameraChanged = activeCameraEpoch !== entry.activeCameraEpoch;
575
+ if (
576
+ !entry.rigidOnly &&
577
+ (changes.changes.length > 0 || materialOperations.length > 0 || cameraChanged)
578
+ ) {
579
+ return this.rebuild(world, catalogEpoch, buildCandidateFrame, 'non-rigid-lane');
580
+ }
581
+ if (changes.changes.length === 0 && materialOperations.length === 0 && !cameraChanged) {
582
+ entry.cursor = changes.cursor;
583
+ entry.sharedRefEpoch = sharedRefChanges.cursor;
584
+ this.noChangeFrames += 1;
585
+ this.syncGpu(world, entry.projection);
586
+ return entry.visibleFrame;
587
+ }
588
+
589
+ const derivedTransforms = new Set<EntityHandle>();
590
+ const removedRenderables = new Set<EntityHandle>();
591
+ const instanceOperations: RenderSceneOperation[] = [];
592
+ const topologyEntities = new Set<EntityHandle>();
593
+ const topologyDispatch: DispatchEntry[] = [];
594
+ const topologyIdentities = new Set<string>();
595
+ for (const record of changes.changes) {
596
+ if (record.kind === 'derived-component-changed' && record.component === Transform) {
597
+ derivedTransforms.add(record.entity as EntityHandle);
598
+ }
599
+ }
600
+ for (const record of changes.changes) {
601
+ const authoredTransform =
602
+ record.kind === 'component-changed' && record.component === Transform;
603
+ const derivedTransform =
604
+ record.kind === 'derived-component-changed' && record.component === Transform;
605
+ const wasCamera = entry.cameraEntities.has(record.entity as EntityHandle);
606
+ const isCamera = world.hasComponent(record.entity as EntityHandle, Camera);
607
+ if (
608
+ record.component === Camera ||
609
+ ((authoredTransform || derivedTransform) && (wasCamera || isCamera))
610
+ ) {
611
+ cameraChanged = true;
612
+ continue;
613
+ }
614
+ if (record.component === PostProcessParams && record.kind !== 'entity-removed') {
615
+ if (refreshPostProcessParams === undefined) {
616
+ return this.rebuild(
617
+ world,
618
+ catalogEpoch,
619
+ buildCandidateFrame,
620
+ 'unsupported-change',
621
+ 'post-process-refresh-unavailable',
622
+ );
623
+ }
624
+ // PostProcessParams is a resource-owner input, not a render-domain
625
+ // slot. Refresh its compact map without invalidating the candidate,
626
+ // dispatch, topology, or GPU scene owner.
627
+ postProcessParamsChanged = true;
628
+ continue;
629
+ }
630
+ if (record.kind === 'entity-removed' && wasCamera) {
631
+ cameraChanged = true;
632
+ if (refreshLights !== undefined) lightsChanged = true;
633
+ if (entry.projection.has(entry.worldId, record.entity)) {
634
+ removedRenderables.add(record.entity as EntityHandle);
635
+ }
636
+ continue;
637
+ }
638
+ if (record.kind === 'entity-removed') {
639
+ if (refreshLights !== undefined) lightsChanged = true;
640
+ if (entry.projection.has(entry.worldId, record.entity)) {
641
+ removedRenderables.add(record.entity as EntityHandle);
642
+ }
643
+ continue;
644
+ }
645
+ if (
646
+ record.component === DirectionalLight ||
647
+ record.component === PointLight ||
648
+ record.component === PointLightShadow ||
649
+ record.component === SpotLight ||
650
+ record.component === Skylight ||
651
+ record.component === Fog ||
652
+ record.component === SkyboxBackground
653
+ ) {
654
+ if (refreshLights === undefined) {
655
+ return this.rebuild(
656
+ world,
657
+ catalogEpoch,
658
+ buildCandidateFrame,
659
+ 'unsupported-change',
660
+ `light-refresh-unavailable:${record.kind}:${record.componentId}:${record.entity}`,
661
+ );
662
+ }
663
+ // Light and shadow components feed compact extracted resources. A
664
+ // mutation there must not invalidate render-domain slots, dispatch,
665
+ // candidate membership, topology, or the GPU scene owner.
666
+ lightsChanged = true;
667
+ continue;
668
+ }
669
+ if (derivedTransform) continue;
670
+ if (authoredTransform && derivedTransforms.has(record.entity as EntityHandle)) continue;
671
+ if (record.component === Instances && entry.projection.has(entry.worldId, record.entity)) {
672
+ const current = entry.projection.snapshot(entry.worldId, record.entity);
673
+ if (current === undefined) continue;
674
+ const instances = world.get(record.entity, Instances);
675
+ const transforms = instances.ok ? instances.value.transforms : undefined;
676
+ if (transforms === undefined) {
677
+ const { instances: _instances, ...withoutInstances } = current;
678
+ const liveRecord = entry.projection.record(entry.worldId, record.entity);
679
+ instanceOperations.push({
680
+ kind: 'create',
681
+ snapshot: withoutInstances,
682
+ ...(liveRecord === undefined ? {} : { expectedGeneration: liveRecord.generation }),
683
+ });
684
+ continue;
685
+ }
686
+ if (transforms.length % 16 !== 0) {
687
+ return this.rebuild(
688
+ world,
689
+ catalogEpoch,
690
+ buildCandidateFrame,
691
+ 'unsupported-change',
692
+ `instance-transform-length:${record.entity}:${transforms.length}`,
693
+ );
694
+ }
695
+ const liveRecord = entry.projection.record(entry.worldId, record.entity);
696
+ instanceOperations.push({
697
+ kind: 'create',
698
+ snapshot: {
699
+ ...current,
700
+ instances: {
701
+ transforms: new Float32Array(transforms),
702
+ instanceCount: Math.max(1, transforms.length / 16),
703
+ cacheKey: record.entity,
704
+ archVersion: (current.instances?.archVersion ?? 0) + 1,
705
+ },
706
+ },
707
+ ...(liveRecord === undefined ? {} : { expectedGeneration: liveRecord.generation }),
708
+ });
709
+ continue;
710
+ }
711
+ if (record.component !== undefined && !RENDER_RELEVANT_COMPONENT_SET.has(record.component)) {
712
+ continue;
713
+ }
714
+ if (
715
+ refreshRenderable !== undefined &&
716
+ record.component !== ChildOf &&
717
+ record.component !== Visibility &&
718
+ record.component !== Skin
719
+ ) {
720
+ // Reconcile the final entity state once after all journal records have
721
+ // been classified. This is the generic admission path for a new or
722
+ // materially changed renderable; hierarchy, inherited visibility, and
723
+ // skin changes stay on their existing conservative lanes.
724
+ topologyEntities.add(record.entity as EntityHandle);
725
+ continue;
726
+ }
727
+ return this.rebuild(
728
+ world,
729
+ catalogEpoch,
730
+ buildCandidateFrame,
731
+ 'unsupported-change',
732
+ `change-record:${record.kind}:${record.componentId ?? 'none'}:${record.entity}`,
733
+ );
734
+ }
735
+
736
+ const operations: RenderSceneOperation[] = [
737
+ ...materialOperations,
738
+ ...instanceOperations.filter((operation) => {
739
+ return !(
740
+ operation.kind === 'create' &&
741
+ topologyEntities.has(operation.snapshot.entityKey as EntityHandle)
742
+ );
743
+ }),
744
+ ...[...removedRenderables].map((entity): RenderSceneOperation => {
745
+ const liveRecord = entry.projection.record(entry.worldId, entity);
746
+ return {
747
+ kind: 'remove',
748
+ worldId: entry.worldId,
749
+ entityKey: entity,
750
+ ...(liveRecord === undefined ? {} : { expectedGeneration: liveRecord.generation }),
751
+ };
752
+ }),
753
+ ];
754
+ let transformOperationCount = 0;
755
+ for (const entity of derivedTransforms) {
756
+ if (topologyEntities.has(entity)) continue;
757
+ // A FixedUpdate can derive Transform and despawn the same entity before
758
+ // the render projection polls its journal. The entity-removed record is
759
+ // already authoritative for the projection; do not turn that stale
760
+ // derived record into a full rebuild or read a component that no longer
761
+ // exists.
762
+ if (removedRenderables.has(entity)) continue;
763
+ if (!entry.projection.has(entry.worldId, entity)) {
764
+ if (entry.cameraEntities.has(entity) || world.hasComponent(entity, Camera)) continue;
765
+ if (
766
+ NON_RENDERABLE_TRANSFORM_CONSUMERS.some((component) =>
767
+ world.hasComponent(entity, component),
768
+ )
769
+ ) {
770
+ if (refreshLights === undefined) {
771
+ return this.rebuild(
772
+ world,
773
+ catalogEpoch,
774
+ buildCandidateFrame,
775
+ 'unsupported-change',
776
+ `non-renderable-transform-consumer:${entity}`,
777
+ );
778
+ }
779
+ lightsChanged = true;
780
+ continue;
781
+ }
782
+ continue;
783
+ }
784
+ const transform = world.get(entity, Transform);
785
+ if (!transform.ok) {
786
+ return this.rebuild(
787
+ world,
788
+ catalogEpoch,
789
+ buildCandidateFrame,
790
+ 'unsupported-change',
791
+ `derived-transform-unavailable:${entity}`,
792
+ );
793
+ }
794
+ const liveRecord = entry.projection.record(entry.worldId, entity);
795
+ operations.push({
796
+ kind: 'update-transform',
797
+ worldId: entry.worldId,
798
+ entityKey: entity,
799
+ world: new Float32Array(transform.value.world),
800
+ ...(liveRecord === undefined ? {} : { expectedGeneration: liveRecord.generation }),
801
+ });
802
+ transformOperationCount += 1;
803
+ }
804
+ if (refreshRenderable !== undefined) {
805
+ this.topologyEntitiesReconciled += topologyEntities.size;
806
+ for (const entity of topologyEntities) {
807
+ const liveRecord = entry.projection.record(entry.worldId, entity);
808
+ topologyIdentities.add(`${entry.worldId}:${entity}`);
809
+ const hasRenderableComponents =
810
+ world.hasComponent(entity, Transform) &&
811
+ world.hasComponent(entity, MeshFilter) &&
812
+ world.hasComponent(entity, MeshRenderer) &&
813
+ !world.hasComponent(entity, Disabled);
814
+ const extracted = hasRenderableComponents
815
+ ? (() => {
816
+ this.singleEntityExtractions += 1;
817
+ return refreshRenderable(entity, entry.candidateFrame);
818
+ })()
819
+ : undefined;
820
+ if (extracted === undefined) {
821
+ if (liveRecord !== undefined && !removedRenderables.has(entity)) {
822
+ operations.push({
823
+ kind: 'remove',
824
+ worldId: entry.worldId,
825
+ entityKey: entity,
826
+ expectedGeneration: liveRecord.generation,
827
+ });
828
+ }
829
+ continue;
830
+ }
831
+ const snapshot =
832
+ extracted.snapshot.worldId === entry.worldId
833
+ ? extracted.snapshot
834
+ : { ...extracted.snapshot, worldId: entry.worldId };
835
+ operations.push({
836
+ kind: 'create',
837
+ snapshot,
838
+ ...(liveRecord === undefined ? {} : { expectedGeneration: liveRecord.generation }),
839
+ });
840
+ topologyDispatch.push(...extracted.candidateDispatch);
841
+ }
842
+ }
843
+ // A stale derived Transform record can discover that the Transform column
844
+ // disappeared after the initial operation list was assembled. Materialize
845
+ // that late remove before the projection apply; otherwise the diagnostic
846
+ // set says "removed" while the retained slot remains live for one frame.
847
+ const removeOperations = new Set(
848
+ operations.flatMap((operation) =>
849
+ operation.kind === 'remove' ? [`${operation.worldId}:${operation.entityKey}`] : [],
850
+ ),
851
+ );
852
+ for (const entity of removedRenderables) {
853
+ const liveRecord = entry.projection.record(entry.worldId, entity);
854
+ const identity = `${entry.worldId}:${entity}`;
855
+ if (liveRecord === undefined || removeOperations.has(identity)) continue;
856
+ operations.push({
857
+ kind: 'remove',
858
+ worldId: entry.worldId,
859
+ entityKey: entity,
860
+ expectedGeneration: liveRecord.generation,
861
+ });
862
+ removeOperations.add(identity);
863
+ }
864
+ if (operations.length === 0 && !cameraChanged && !postProcessParamsChanged && !lightsChanged) {
865
+ entry.cursor = changes.cursor;
866
+ entry.sharedRefEpoch = sharedRefChanges.cursor;
867
+ this.noChangeFrames += 1;
868
+ this.syncGpu(world, entry.projection);
869
+ return entry.visibleFrame;
870
+ }
871
+ if (operations.length > 0) {
872
+ const delta = entry.projection.apply(operations);
873
+ entry.topology.apply(delta);
874
+ this.syncGpu(world, entry.projection, delta);
875
+ const candidates = entry.projection.materialize();
876
+ const rebased = rebaseCandidateDomain(
877
+ entry.candidateFrame,
878
+ candidates,
879
+ topologyEntities.size === 0
880
+ ? undefined
881
+ : {
882
+ worldId: entry.worldId,
883
+ dispatch: topologyDispatch,
884
+ replaceIdentities: topologyIdentities,
885
+ },
886
+ );
887
+ entry.candidateFrame = { ...rebased, renderables: [...candidates] };
888
+ } else {
889
+ this.syncGpu(world, entry.projection);
890
+ }
891
+ if (cameraChanged) {
892
+ if (refreshCameras === undefined) {
893
+ return this.rebuild(
894
+ world,
895
+ catalogEpoch,
896
+ buildCandidateFrame,
897
+ 'unsupported-change',
898
+ 'camera-refresh-unavailable',
899
+ );
900
+ }
901
+ const candidates = entry.projection.materialize();
902
+ const refreshed = rebaseCandidateDomain(refreshCameras(entry.candidateFrame), candidates);
903
+ entry.candidateFrame = { ...refreshed, renderables: [...candidates] };
904
+ entry.cameraEntities = this.cameraEntities(world);
905
+ entry.activeCameraEpoch = activeCameraEpoch;
906
+ this.cameraUpdates += 1;
907
+ }
908
+ if (postProcessParamsChanged && refreshPostProcessParams !== undefined) {
909
+ // Refresh candidate and visible frames separately because the latter is
910
+ // the cull projection of the former and may be returned without a cull
911
+ // pass when this is the only changed lane.
912
+ entry.candidateFrame = refreshPostProcessParams(entry.candidateFrame);
913
+ entry.visibleFrame = refreshPostProcessParams(entry.visibleFrame);
914
+ }
915
+ if (lightsChanged && refreshLights !== undefined) {
916
+ // Refresh candidate and visible frames separately so a light-only
917
+ // update preserves the existing visible projection while publishing
918
+ // the new light/CSM/point-shadow snapshot to both frame owners.
919
+ entry.candidateFrame = refreshLights(entry.candidateFrame);
920
+ entry.visibleFrame = refreshLights(entry.visibleFrame);
921
+ }
922
+ if (postProcessParamsChanged || lightsChanged) this.resourceUpdates += 1;
923
+ if (operations.length > 0 || cameraChanged) {
924
+ const candidates = entry.projection.materialize();
925
+ entry.visibleFrame =
926
+ operations.length === 0 &&
927
+ cameraChanged &&
928
+ entry.gpuDrivenOwnsAll &&
929
+ entry.gpuDrivenCoverageKey === gpuDrivenCoverageKey
930
+ ? entry.candidateFrame
931
+ : cullPersistentFrame(
932
+ entry.candidateFrame,
933
+ candidates,
934
+ this.options.collectShadowDebugCandidates?.() === true,
935
+ entry.projection,
936
+ );
937
+ }
938
+ entry.cursor = changes.cursor;
939
+ entry.sharedRefEpoch = sharedRefChanges.cursor;
940
+ this.deltaFrames += 1;
941
+ this.transformUpdates += transformOperationCount;
942
+ this.materialUpdates += materialOperations.length;
943
+ this.instanceUpdates += instanceOperations.length;
944
+ this.removals += removedRenderables.size;
945
+ return entry.visibleFrame;
946
+ }
947
+
948
+ extractComposition(
949
+ worlds: readonly World[],
950
+ owner: { readonly cameraOwner: number; readonly resourceOwner: number },
951
+ catalogEpoch: number,
952
+ buildCandidateFrame: () => ExtractedFrame,
953
+ refreshRenderable?: (
954
+ world: World,
955
+ worldId: number,
956
+ entity: EntityHandle,
957
+ currentFrame: ExtractedFrame,
958
+ ) => PersistentRenderableExtraction | undefined,
959
+ ): ExtractedFrame {
960
+ this.worldEntitiesScanned = 0;
961
+ const worldIds = worlds.map((world) => this.attachWorld(world));
962
+ const entry = this.composition;
963
+ if (
964
+ entry === undefined ||
965
+ entry.catalogEpoch !== catalogEpoch ||
966
+ entry.cameraOwner !== owner.cameraOwner ||
967
+ entry.resourceOwner !== owner.resourceOwner ||
968
+ entry.worlds.length !== worlds.length ||
969
+ entry.worlds.some((world, index) => world !== worlds[index]) ||
970
+ entry.worldIds.some((worldId, index) => worldId !== worldIds[index])
971
+ ) {
972
+ return this.rebuildComposition(worlds, worldIds, owner, catalogEpoch, buildCandidateFrame);
973
+ }
974
+ if (!entry.rigidOnly) {
975
+ return this.rebuildComposition(worlds, worldIds, owner, catalogEpoch, buildCandidateFrame);
976
+ }
977
+
978
+ const operations: RenderSceneOperation[] = [];
979
+ const topologyEntities = new Map<
980
+ string,
981
+ { readonly world: World; readonly worldId: number; readonly entity: EntityHandle }
982
+ >();
983
+ const topologyDispatchByWorld = new Map<number, DispatchEntry[]>();
984
+ const topologyIdentitiesByWorld = new Map<number, Set<string>>();
985
+ const removalIdentities = new Set<string>();
986
+ let transformOperationCount = 0;
987
+ let removalOperationCount = 0;
988
+ let requiresRebuild = false;
989
+ for (let worldId = 0; worldId < worlds.length; worldId += 1) {
990
+ const world = worlds[worldId];
991
+ if (world === undefined) continue;
992
+ const renderWorldId = entry.worldIds[worldId];
993
+ if (renderWorldId === undefined) {
994
+ requiresRebuild = true;
995
+ break;
996
+ }
997
+ const changeProjection = entry.changeProjections[worldId];
998
+ if (changeProjection === undefined) {
999
+ requiresRebuild = true;
1000
+ break;
1001
+ }
1002
+ const changes = changeProjection.poll();
1003
+ const shared = world.sharedRefs.readChangesSince(entry.sharedRefEpochs[worldId] ?? 0);
1004
+ if (changes.status === 'rebuild' || shared.status === 'overflow') {
1005
+ requiresRebuild = true;
1006
+ break;
1007
+ }
1008
+ if (shared.records.length > 0) {
1009
+ requiresRebuild = true;
1010
+ break;
1011
+ }
1012
+ const derivedTransforms = new Set<EntityHandle>();
1013
+ for (const record of changes.changes) {
1014
+ if (record.kind === 'derived-component-changed' && record.component === Transform) {
1015
+ derivedTransforms.add(record.entity as EntityHandle);
1016
+ }
1017
+ }
1018
+ for (const record of changes.changes) {
1019
+ if (
1020
+ record.kind !== 'entity-removed' &&
1021
+ record.component !== undefined &&
1022
+ !RENDER_RELEVANT_COMPONENT_SET.has(record.component)
1023
+ ) {
1024
+ continue;
1025
+ }
1026
+ const authoredTransform =
1027
+ record.kind === 'component-changed' && record.component === Transform;
1028
+ const derivedTransform =
1029
+ record.kind === 'derived-component-changed' && record.component === Transform;
1030
+ if (derivedTransform) continue;
1031
+ if (authoredTransform && derivedTransforms.has(record.entity as EntityHandle)) continue;
1032
+ const entity = record.entity as EntityHandle;
1033
+ const identity = `${renderWorldId}:${entity}`;
1034
+ const wasCamera = entry.cameraEntities[worldId]?.has(entity) === true;
1035
+ if (record.kind === 'entity-removed') {
1036
+ // Camera/light/resource removal changes the composed frame-level
1037
+ // owner. Keep that path conservative; ordinary renderable removal
1038
+ // can be addressed directly by the projection owner.
1039
+ if (wasCamera || !entry.projection.has(renderWorldId, entity)) {
1040
+ if (wasCamera) requiresRebuild = true;
1041
+ continue;
1042
+ }
1043
+ if (!removalIdentities.has(identity)) {
1044
+ const liveRecord = entry.projection.record(renderWorldId, entity);
1045
+ operations.push({
1046
+ kind: 'remove',
1047
+ worldId: renderWorldId,
1048
+ entityKey: entity,
1049
+ ...(liveRecord === undefined ? {} : { expectedGeneration: liveRecord.generation }),
1050
+ });
1051
+ removalIdentities.add(identity);
1052
+ removalOperationCount += 1;
1053
+ }
1054
+ continue;
1055
+ }
1056
+ if (
1057
+ record.component === Camera ||
1058
+ record.component === DirectionalLight ||
1059
+ record.component === PointLight ||
1060
+ record.component === PointLightShadow ||
1061
+ record.component === SpotLight ||
1062
+ record.component === Skylight ||
1063
+ record.component === Fog ||
1064
+ record.component === SkyboxBackground ||
1065
+ record.component === PostProcessParams ||
1066
+ wasCamera
1067
+ ) {
1068
+ requiresRebuild = true;
1069
+ break;
1070
+ }
1071
+ if (
1072
+ (authoredTransform || record.component === Transform) &&
1073
+ entry.projection.has(renderWorldId, entity)
1074
+ ) {
1075
+ const transform = world.get(record.entity, Transform);
1076
+ if (!transform.ok) {
1077
+ requiresRebuild = true;
1078
+ break;
1079
+ }
1080
+ const liveRecord = entry.projection.record(renderWorldId, entity);
1081
+ operations.push({
1082
+ kind: 'update-transform',
1083
+ worldId: renderWorldId,
1084
+ entityKey: record.entity,
1085
+ world: new Float32Array(transform.value.world),
1086
+ ...(liveRecord === undefined ? {} : { expectedGeneration: liveRecord.generation }),
1087
+ });
1088
+ transformOperationCount += 1;
1089
+ continue;
1090
+ }
1091
+ if (
1092
+ refreshRenderable !== undefined &&
1093
+ record.component !== ChildOf &&
1094
+ record.component !== Visibility &&
1095
+ record.component !== Skin
1096
+ ) {
1097
+ topologyEntities.set(identity, { world, worldId: renderWorldId, entity });
1098
+ continue;
1099
+ }
1100
+ requiresRebuild = true;
1101
+ break;
1102
+ }
1103
+ if (!requiresRebuild) {
1104
+ for (const entity of derivedTransforms) {
1105
+ const identity = `${renderWorldId}:${entity}`;
1106
+ if (topologyEntities.has(identity)) continue;
1107
+ if (entry.projection.has(renderWorldId, entity)) {
1108
+ const transform = world.get(entity, Transform);
1109
+ if (!transform.ok) {
1110
+ requiresRebuild = true;
1111
+ break;
1112
+ }
1113
+ const liveRecord = entry.projection.record(renderWorldId, entity);
1114
+ operations.push({
1115
+ kind: 'update-transform',
1116
+ worldId: renderWorldId,
1117
+ entityKey: entity,
1118
+ world: new Float32Array(transform.value.world),
1119
+ ...(liveRecord === undefined ? {} : { expectedGeneration: liveRecord.generation }),
1120
+ });
1121
+ transformOperationCount += 1;
1122
+ continue;
1123
+ }
1124
+ if (
1125
+ NON_RENDERABLE_TRANSFORM_CONSUMERS.some((component) =>
1126
+ world.hasComponent(entity, component),
1127
+ )
1128
+ ) {
1129
+ requiresRebuild = true;
1130
+ break;
1131
+ }
1132
+ }
1133
+ }
1134
+ if (requiresRebuild) break;
1135
+ entry.cursors[worldId] = changes.cursor;
1136
+ entry.sharedRefEpochs[worldId] = shared.cursor;
1137
+ }
1138
+ if (requiresRebuild) {
1139
+ return this.rebuildComposition(worlds, worldIds, owner, catalogEpoch, buildCandidateFrame);
1140
+ }
1141
+ if (refreshRenderable !== undefined && topologyEntities.size > 0) {
1142
+ this.topologyEntitiesReconciled += topologyEntities.size;
1143
+ for (const { world, worldId, entity } of topologyEntities.values()) {
1144
+ const identity = `${worldId}:${entity}`;
1145
+ const identities = topologyIdentitiesByWorld.get(worldId) ?? new Set<string>();
1146
+ identities.add(identity);
1147
+ topologyIdentitiesByWorld.set(worldId, identities);
1148
+ const hasRenderableComponents =
1149
+ world.hasComponent(entity, Transform) &&
1150
+ world.hasComponent(entity, MeshFilter) &&
1151
+ world.hasComponent(entity, MeshRenderer) &&
1152
+ !world.hasComponent(entity, Disabled);
1153
+ const extracted = hasRenderableComponents
1154
+ ? (() => {
1155
+ this.singleEntityExtractions += 1;
1156
+ return refreshRenderable(world, worldId, entity, entry.candidateFrame);
1157
+ })()
1158
+ : undefined;
1159
+ const liveRecord = entry.projection.record(worldId, entity);
1160
+ if (extracted === undefined) {
1161
+ if (liveRecord !== undefined && !removalIdentities.has(identity)) {
1162
+ operations.push({
1163
+ kind: 'remove',
1164
+ worldId,
1165
+ entityKey: entity,
1166
+ expectedGeneration: liveRecord.generation,
1167
+ });
1168
+ removalIdentities.add(identity);
1169
+ removalOperationCount += 1;
1170
+ }
1171
+ continue;
1172
+ }
1173
+ const snapshot =
1174
+ extracted.snapshot.worldId === worldId
1175
+ ? extracted.snapshot
1176
+ : { ...extracted.snapshot, worldId };
1177
+ operations.push({
1178
+ kind: 'create',
1179
+ snapshot,
1180
+ ...(liveRecord === undefined ? {} : { expectedGeneration: liveRecord.generation }),
1181
+ });
1182
+ const dispatch = topologyDispatchByWorld.get(worldId) ?? [];
1183
+ dispatch.push(...extracted.candidateDispatch);
1184
+ topologyDispatchByWorld.set(worldId, dispatch);
1185
+ }
1186
+ }
1187
+ if (topologyEntities.size > 0) {
1188
+ const topologyIdentitySet = new Set(topologyEntities.keys());
1189
+ for (let index = operations.length - 1; index >= 0; index -= 1) {
1190
+ const operation = operations[index];
1191
+ if (
1192
+ operation?.kind === 'update-transform' &&
1193
+ topologyIdentitySet.has(`${operation.worldId}:${operation.entityKey}`)
1194
+ ) {
1195
+ operations.splice(index, 1);
1196
+ }
1197
+ }
1198
+ }
1199
+ if (operations.length === 0) {
1200
+ this.noChangeFrames += 1;
1201
+ this.syncGpuOwner(entry.token, entry.projection);
1202
+ return entry.visibleFrame;
1203
+ }
1204
+ const delta = entry.projection.apply(operations);
1205
+ entry.topology.apply(delta);
1206
+ this.syncGpuOwner(entry.token, entry.projection, delta);
1207
+ const candidates = entry.projection.materialize();
1208
+ let rebased = entry.candidateFrame;
1209
+ for (const [worldId, dispatch] of topologyDispatchByWorld) {
1210
+ rebased = rebaseCandidateDomain(rebased, candidates, {
1211
+ worldId,
1212
+ dispatch,
1213
+ replaceIdentities: topologyIdentitiesByWorld.get(worldId) ?? new Set<string>(),
1214
+ });
1215
+ }
1216
+ if (topologyDispatchByWorld.size === 0 && topologyEntities.size > 0) {
1217
+ for (const [worldId, replaceIdentities] of topologyIdentitiesByWorld) {
1218
+ rebased = rebaseCandidateDomain(rebased, candidates, {
1219
+ worldId,
1220
+ dispatch: [],
1221
+ replaceIdentities,
1222
+ });
1223
+ }
1224
+ }
1225
+ entry.candidateFrame = { ...rebased, renderables: [...candidates] };
1226
+ entry.visibleFrame = cullPersistentFrame(
1227
+ entry.candidateFrame,
1228
+ candidates,
1229
+ this.options.collectShadowDebugCandidates?.() === true,
1230
+ entry.projection,
1231
+ );
1232
+ this.deltaFrames += 1;
1233
+ this.transformUpdates += transformOperationCount;
1234
+ this.removals += removalOperationCount;
1235
+ return entry.visibleFrame;
1236
+ }
1237
+
1238
+ invalidate(world?: World): void {
1239
+ if (world !== undefined) this.entries.delete(world);
1240
+ else if (this.lastWorld !== undefined) this.entries.delete(this.lastWorld);
1241
+ this.composition = undefined;
1242
+ this.lastResyncReason = 'explicit-invalidate';
1243
+ this.lastResyncDetail = undefined;
1244
+ }
1245
+
1246
+ setGpuDrivenCoverage(world: World, key: string, ownsAll: boolean): void {
1247
+ const entry = this.entries.get(world);
1248
+ if (entry === undefined) return;
1249
+ entry.gpuDrivenCoverageKey = key;
1250
+ entry.gpuDrivenOwnsAll = ownsAll;
1251
+ }
1252
+
1253
+ setCompositionGpuDrivenCoverage(key: string, ownsAll: boolean): void {
1254
+ const entry = this.composition;
1255
+ if (entry === undefined) return;
1256
+ entry.gpuDrivenCoverageKey = key;
1257
+ entry.gpuDrivenOwnsAll = ownsAll;
1258
+ }
1259
+
1260
+ detach(world: World): void {
1261
+ const detachedEntry = this.entries.get(world);
1262
+ detachedEntry?.projection.reset([]);
1263
+ this.entries.delete(world);
1264
+ const worldId = this.worldIds.get(world);
1265
+ if (worldId !== undefined) {
1266
+ this.worldIds.delete(world);
1267
+ this.worldsById.delete(worldId);
1268
+ }
1269
+ const detachedComposition = this.composition?.worlds.includes(world)
1270
+ ? this.composition
1271
+ : undefined;
1272
+ if (detachedComposition !== undefined) this.composition = undefined;
1273
+ if (this.fogLastKnownGood?.resourceOwner === worldId) {
1274
+ this.fogCandidate = undefined;
1275
+ this.fogLastKnownGood = undefined;
1276
+ this.fogFailure = undefined;
1277
+ this.fogFailureOwner = undefined;
1278
+ this.fogReactive = false;
1279
+ }
1280
+ if (this.lastWorld === world) this.lastWorld = undefined;
1281
+ if (this.gpuOwner !== world && this.gpuOwner !== detachedComposition?.token) return;
1282
+ this.gpuScene?.dispose();
1283
+ this.gpuScene = undefined;
1284
+ this.gpuOwner = undefined;
1285
+ this.gpuDevice = undefined;
1286
+ this.gpuStatus = 'inactive';
1287
+ }
1288
+
1289
+ /** Drop only device-owned tables; the CPU projection remains the recovery authority. */
1290
+ resetGpuForRecover(): void {
1291
+ if (this.lastWorld !== undefined) {
1292
+ const entry = this.entries.get(this.lastWorld);
1293
+ if (entry !== undefined) entry.gpuDrivenOwnsAll = false;
1294
+ }
1295
+ if (this.composition !== undefined) this.composition.gpuDrivenOwnsAll = false;
1296
+ this.gpuScene = undefined;
1297
+ this.gpuOwner = undefined;
1298
+ this.gpuDevice = undefined;
1299
+ this.gpuStatus = this.options.getDevice === undefined ? 'inactive' : 'rebuild-pending';
1300
+ }
1301
+
1302
+ dispose(): void {
1303
+ this.gpuScene?.dispose();
1304
+ this.gpuScene = undefined;
1305
+ this.gpuOwner = undefined;
1306
+ this.gpuDevice = undefined;
1307
+ this.gpuStatus = 'inactive';
1308
+ this.composition = undefined;
1309
+ this.fogCandidate = undefined;
1310
+ this.fogLastKnownGood = undefined;
1311
+ this.fogFailure = undefined;
1312
+ this.fogFailureOwner = undefined;
1313
+ this.fogReactive = false;
1314
+ }
1315
+
1316
+ inspect(world = this.lastWorld): PersistentRenderSceneInspection {
1317
+ const entry = (world === undefined ? undefined : this.entries.get(world)) ?? this.composition;
1318
+ return {
1319
+ worldEntitiesScanned: this.worldEntitiesScanned,
1320
+ fullRebuilds: this.fullRebuilds,
1321
+ noChangeFrames: this.noChangeFrames,
1322
+ deltaFrames: this.deltaFrames,
1323
+ transformUpdates: this.transformUpdates,
1324
+ materialUpdates: this.materialUpdates,
1325
+ instanceUpdates: this.instanceUpdates,
1326
+ cameraUpdates: this.cameraUpdates,
1327
+ resourceUpdates: this.resourceUpdates,
1328
+ topologyEntitiesReconciled: this.topologyEntitiesReconciled,
1329
+ singleEntityExtractions: this.singleEntityExtractions,
1330
+ removals: this.removals,
1331
+ lastResyncReason: this.lastResyncReason,
1332
+ lastResyncDetail: this.lastResyncDetail,
1333
+ cursor: 'cursor' in (entry ?? {}) ? (entry as PersistentWorldEntry).cursor : undefined,
1334
+ projectionRecords: entry?.projection.inspect().current.length ?? 0,
1335
+ spatialIndex: entry?.projection.inspect().spatialIndex,
1336
+ topology:
1337
+ entry?.topology.inspect() ??
1338
+ ({
1339
+ revision: 0,
1340
+ batchCount: 0,
1341
+ candidateCount: 0,
1342
+ rebuilds: 0,
1343
+ patches: 0,
1344
+ ineligible: 0,
1345
+ } satisfies BatchTopologyInspection),
1346
+ gpu: this.inspectGpu(),
1347
+ fog: this.inspectFog(),
1348
+ };
1349
+ }
1350
+
1351
+ /** Stage a resource-owner Fog candidate; publication waits for submit. */
1352
+ stageFogCandidate(candidate: FogSelection): void {
1353
+ this.fogCandidate = candidate;
1354
+ this.fogFailure = undefined;
1355
+ this.fogFailureOwner = undefined;
1356
+ this.fogReactive = false;
1357
+ }
1358
+
1359
+ /** Return the accepted Fog payload for failed-candidate frame reuse. */
1360
+ fogSnapshot(): FogSnapshot | undefined {
1361
+ return this.fogLastKnownGood?.snapshot;
1362
+ }
1363
+
1364
+ /** Retain the previous accepted Fog when extraction or validation fails. */
1365
+ stageFogFailure(failure: PersistentFogFailure): void {
1366
+ this.fogCandidate = undefined;
1367
+ this.fogFailure = failure.code;
1368
+ this.fogFailureOwner = failure.resourceOwner;
1369
+ this.fogReactive = false;
1370
+ }
1371
+
1372
+ /** Drop an unsubmitted candidate without mutating the accepted snapshot. */
1373
+ discardFogCandidate(): void {
1374
+ this.fogCandidate = undefined;
1375
+ this.fogReactive = false;
1376
+ }
1377
+
1378
+ /** Commit the staged Fog candidate at the existing successful-submit seam. */
1379
+ stageFogSubmission(): void {
1380
+ const candidate = this.fogCandidate;
1381
+ if (candidate === undefined) return;
1382
+ const previous = this.fogLastKnownGood;
1383
+ this.fogReactive =
1384
+ previous === undefined || previous.snapshot?.revision !== candidate.snapshot?.revision;
1385
+ this.fogLastKnownGood = candidate;
1386
+ this.fogCandidate = undefined;
1387
+ this.fogFailure = undefined;
1388
+ this.fogFailureOwner = undefined;
1389
+ }
1390
+
1391
+ private inspectFog(): PersistentFogInspection {
1392
+ const accepted = this.fogLastKnownGood;
1393
+ return {
1394
+ enabled: accepted?.snapshot !== undefined,
1395
+ resourceOwner: accepted?.resourceOwner ?? this.fogFailureOwner,
1396
+ entity: accepted?.entity as number | undefined,
1397
+ revision: accepted?.snapshot?.revision,
1398
+ reactive: this.fogReactive,
1399
+ failure: this.fogFailure,
1400
+ };
1401
+ }
1402
+
1403
+ gpuDrivenState(world = this.lastWorld): PersistentGpuDrivenState | undefined {
1404
+ if (world === undefined || world !== this.gpuOwner || this.gpuScene === undefined) {
1405
+ return undefined;
1406
+ }
1407
+ const entry = this.entries.get(world);
1408
+ if (entry === undefined) return undefined;
1409
+ return {
1410
+ scene: this.gpuScene,
1411
+ plan: entry.topology.plan(),
1412
+ slots: entry.projection.slotsSnapshot(),
1413
+ projection: entry.projection,
1414
+ };
1415
+ }
1416
+
1417
+ compositionGpuDrivenState(): PersistentGpuDrivenState | undefined {
1418
+ const entry = this.composition;
1419
+ if (entry === undefined || this.gpuOwner !== entry.token || this.gpuScene === undefined) {
1420
+ return undefined;
1421
+ }
1422
+ return {
1423
+ scene: this.gpuScene,
1424
+ plan: entry.topology.plan(),
1425
+ slots: entry.projection.slotsSnapshot(),
1426
+ projection: entry.projection,
1427
+ };
1428
+ }
1429
+
1430
+ temporalProjection(worlds: readonly World[]): RenderSceneProjection | undefined {
1431
+ if (worlds.length === 1) {
1432
+ const world = worlds[0];
1433
+ return world === undefined ? undefined : this.entries.get(world)?.projection;
1434
+ }
1435
+ const composition = this.composition;
1436
+ if (
1437
+ composition === undefined ||
1438
+ composition.worlds.length !== worlds.length ||
1439
+ composition.worlds.some((world, index) => world !== worlds[index])
1440
+ ) {
1441
+ return undefined;
1442
+ }
1443
+ return composition.projection;
1444
+ }
1445
+
1446
+ stageTemporalSubmission(delta: RenderSceneSubmissionDelta): void {
1447
+ this.gpuScene?.stageSubmitted(delta);
1448
+ this.stageFogSubmission();
1449
+ }
1450
+
1451
+ private inspectGpu(): PersistentGpuSceneInspection {
1452
+ if (this.gpuStatus === 'resident' && this.gpuScene !== undefined) {
1453
+ return { status: 'resident', ...this.gpuScene.inspect() };
1454
+ }
1455
+ if (this.gpuStatus === 'unsupported') {
1456
+ return { status: 'unsupported', reason: 'storage-buffer-unavailable' };
1457
+ }
1458
+ if (this.gpuStatus === 'rebuild-pending') return { status: 'rebuild-pending' };
1459
+ if (this.gpuStatus === 'error') return { status: 'error' };
1460
+ return { status: 'inactive' };
1461
+ }
1462
+
1463
+ private rebuild(
1464
+ world: World,
1465
+ catalogEpoch: number,
1466
+ buildCandidateFrame: () => ExtractedFrame,
1467
+ reason: RenderSceneResyncReason,
1468
+ detail?: string,
1469
+ ): ExtractedFrame {
1470
+ const worldId = this.attachWorld(world);
1471
+ const previousEntry = this.entries.get(world);
1472
+ const sourceCandidateFrame = this.remapWorldIds(buildCandidateFrame(), [worldId]);
1473
+ const projectionCandidates =
1474
+ sourceCandidateFrame.candidateRenderables ?? sourceCandidateFrame.renderables;
1475
+ this.worldEntitiesScanned = projectionCandidates.length;
1476
+ const projection = previousEntry?.projection ?? new RenderSceneProjection();
1477
+ if (previousEntry === undefined) projection.reset(projectionCandidates);
1478
+ else projection.replaceCurrent(projectionCandidates);
1479
+ const topology = new BatchTopology();
1480
+ topology.rebuild(projection.slotsSnapshot());
1481
+ const candidates = projection.materialize();
1482
+ const candidateFrame = {
1483
+ ...rebaseCandidateDomain(sourceCandidateFrame, candidates),
1484
+ renderables: [...candidates],
1485
+ };
1486
+ const visibleFrame = cullPersistentFrame(
1487
+ candidateFrame,
1488
+ candidates,
1489
+ this.options.collectShadowDebugCandidates?.() === true,
1490
+ projection,
1491
+ );
1492
+ const changeProjection = createWorldProjection(world, {
1493
+ components: RENDER_RELEVANT_COMPONENTS,
1494
+ });
1495
+ this.entries.set(world, {
1496
+ worldId,
1497
+ projection,
1498
+ topology,
1499
+ candidateFrame,
1500
+ visibleFrame,
1501
+ changeProjection,
1502
+ cursor: changeProjection.cursor,
1503
+ catalogEpoch,
1504
+ sharedRefEpoch: world.sharedRefs.getMutationEpoch(),
1505
+ activeCameraEpoch: world.getResourceChange(ACTIVE_CAMERA_KEY)?.changed ?? 0,
1506
+ cameraEntities: this.cameraEntities(world),
1507
+ rigidOnly: candidates.every(
1508
+ (renderable) => renderable.skin === undefined && renderable.morphWeights === undefined,
1509
+ ),
1510
+ gpuDrivenCoverageKey: undefined,
1511
+ gpuDrivenOwnsAll: false,
1512
+ });
1513
+ this.syncGpu(world, projection, undefined, true);
1514
+ this.fullRebuilds += 1;
1515
+ this.lastResyncReason = reason;
1516
+ this.lastResyncDetail = detail;
1517
+ return visibleFrame;
1518
+ }
1519
+
1520
+ private rebuildComposition(
1521
+ worlds: readonly World[],
1522
+ worldIds: readonly number[],
1523
+ owner: { readonly cameraOwner: number; readonly resourceOwner: number },
1524
+ catalogEpoch: number,
1525
+ buildCandidateFrame: () => ExtractedFrame,
1526
+ ): ExtractedFrame {
1527
+ const previousComposition = this.composition;
1528
+ const canReuseProjection =
1529
+ previousComposition !== undefined &&
1530
+ previousComposition.cameraOwner === owner.cameraOwner &&
1531
+ previousComposition.resourceOwner === owner.resourceOwner &&
1532
+ previousComposition.worlds.length === worlds.length &&
1533
+ previousComposition.worlds.every((world, index) => world === worlds[index]) &&
1534
+ previousComposition.worldIds.every((worldId, index) => worldId === worldIds[index]);
1535
+ const sourceCandidateFrame = this.remapWorldIds(buildCandidateFrame(), worldIds);
1536
+ const projectionCandidates =
1537
+ sourceCandidateFrame.candidateRenderables ?? sourceCandidateFrame.renderables;
1538
+ this.worldEntitiesScanned = projectionCandidates.length;
1539
+ const projection = canReuseProjection
1540
+ ? previousComposition.projection
1541
+ : new RenderSceneProjection();
1542
+ if (canReuseProjection) projection.replaceCurrent(projectionCandidates);
1543
+ else projection.reset(projectionCandidates);
1544
+ const topology = new BatchTopology();
1545
+ topology.rebuild(projection.slotsSnapshot());
1546
+ const candidates = projection.materialize();
1547
+ const candidateFrame = {
1548
+ ...rebaseCandidateDomain(sourceCandidateFrame, candidates),
1549
+ renderables: [...candidates],
1550
+ };
1551
+ const visibleFrame = cullPersistentFrame(
1552
+ candidateFrame,
1553
+ candidates,
1554
+ this.options.collectShadowDebugCandidates?.() === true,
1555
+ projection,
1556
+ );
1557
+ const token = {};
1558
+ const changeProjections = worlds.map((world) =>
1559
+ createWorldProjection(world, { components: RENDER_RELEVANT_COMPONENTS }),
1560
+ );
1561
+ const entry: PersistentCompositionEntry = {
1562
+ token,
1563
+ worlds: [...worlds],
1564
+ worldIds: [...worldIds],
1565
+ cameraOwner: owner.cameraOwner,
1566
+ resourceOwner: owner.resourceOwner,
1567
+ projection,
1568
+ topology,
1569
+ candidateFrame,
1570
+ visibleFrame,
1571
+ changeProjections,
1572
+ cursors: changeProjections.map((projection) => projection.cursor),
1573
+ sharedRefEpochs: worlds.map((world) => world.sharedRefs.getMutationEpoch()),
1574
+ cameraEntities: worlds.map((world) => this.cameraEntities(world)),
1575
+ catalogEpoch,
1576
+ rigidOnly: candidates.every(
1577
+ (renderable) => renderable.skin === undefined && renderable.morphWeights === undefined,
1578
+ ),
1579
+ gpuDrivenCoverageKey: undefined,
1580
+ gpuDrivenOwnsAll: false,
1581
+ };
1582
+ this.composition = entry;
1583
+ this.syncGpuOwner(token, projection, undefined, true);
1584
+ this.fullRebuilds += 1;
1585
+ this.lastResyncReason = 'attach';
1586
+ return visibleFrame;
1587
+ }
1588
+
1589
+ private syncGpu(
1590
+ world: World,
1591
+ projection: RenderSceneProjection,
1592
+ delta?: RenderSceneApplyResult,
1593
+ full = false,
1594
+ ): void {
1595
+ this.syncGpuOwner(world, projection, delta, full);
1596
+ }
1597
+
1598
+ private syncGpuOwner(
1599
+ owner: object,
1600
+ projection: RenderSceneProjection,
1601
+ delta?: RenderSceneApplyResult,
1602
+ full = false,
1603
+ ): void {
1604
+ const acquired = this.acquireGpuScene(owner, projection);
1605
+ if (acquired === undefined || acquired.rebuilt) return;
1606
+ const result = full
1607
+ ? acquired.scene.rebuild(projection)
1608
+ : delta === undefined
1609
+ ? acquired.scene.sync(projection, {
1610
+ created: 0,
1611
+ updated: 0,
1612
+ removed: 0,
1613
+ recreated: 0,
1614
+ ignoredLateUpdates: 0,
1615
+ createdSlots: [],
1616
+ updatedSlots: [],
1617
+ removedSlots: [],
1618
+ recreatedSlots: [],
1619
+ factDeltas: [],
1620
+ diagnostics: [],
1621
+ })
1622
+ : acquired.scene.sync(projection, delta);
1623
+ if (!result.ok) this.failGpu(result.error);
1624
+ }
1625
+
1626
+ private acquireGpuScene(
1627
+ owner: object,
1628
+ projection: RenderSceneProjection,
1629
+ ): { readonly scene: GpuScene; readonly rebuilt: boolean } | undefined {
1630
+ const getDevice = this.options.getDevice;
1631
+ if (getDevice === undefined) return undefined;
1632
+ const device = getDevice();
1633
+ if (this.gpuDevice !== undefined && this.gpuDevice !== device) {
1634
+ this.gpuScene = undefined;
1635
+ this.gpuOwner = undefined;
1636
+ this.gpuStatus = 'rebuild-pending';
1637
+ }
1638
+ if (this.gpuStatus === 'error' && this.gpuDevice === device) return undefined;
1639
+ if (this.gpuStatus === 'unsupported' && this.gpuDevice === device) return undefined;
1640
+ if (this.gpuScene !== undefined && this.gpuOwner === owner) {
1641
+ return { scene: this.gpuScene, rebuilt: false };
1642
+ }
1643
+ if (this.gpuScene !== undefined) this.gpuScene.dispose();
1644
+ this.gpuScene = undefined;
1645
+ this.gpuOwner = undefined;
1646
+ this.gpuDevice = device;
1647
+ const created = GpuScene.create(device, Math.max(256, projection.inspect().slotCapacity));
1648
+ if (!created.ok) {
1649
+ this.failGpu(created.error);
1650
+ return undefined;
1651
+ }
1652
+ if (created.value.status === 'unavailable') {
1653
+ this.gpuStatus = 'unsupported';
1654
+ return undefined;
1655
+ }
1656
+ const scene = created.value.scene;
1657
+ const rebuilt = scene.rebuild(projection);
1658
+ if (!rebuilt.ok) {
1659
+ scene.dispose();
1660
+ this.failGpu(rebuilt.error);
1661
+ return undefined;
1662
+ }
1663
+ this.gpuScene = scene;
1664
+ this.gpuOwner = owner;
1665
+ this.gpuStatus = 'resident';
1666
+ return { scene, rebuilt: true };
1667
+ }
1668
+
1669
+ private failGpu(error: RhiError): void {
1670
+ this.gpuScene?.dispose();
1671
+ this.gpuScene = undefined;
1672
+ this.gpuOwner = undefined;
1673
+ this.gpuStatus = 'error';
1674
+ this.options.onGpuError?.(error);
1675
+ }
1676
+
1677
+ private cameraEntities(world: World): ReadonlySet<EntityHandle> {
1678
+ const entities = new Set<EntityHandle>();
1679
+ for (const row of world.query({ read: [Camera], with: [Transform] }).unwrap()) {
1680
+ entities.add(row.entity as EntityHandle);
1681
+ }
1682
+ return entities;
1683
+ }
1684
+
1685
+ private attachWorld(world: World): number {
1686
+ const attached = this.worldIds.get(world);
1687
+ if (attached !== undefined) return attached;
1688
+ if (this.nextWorldId >= 0x20_0000) {
1689
+ throw new RangeError('renderer exhausted the 21-bit WorldRenderId space');
1690
+ }
1691
+ const worldId = this.nextWorldId;
1692
+ this.nextWorldId += 1;
1693
+ this.worldIds.set(world, worldId);
1694
+ this.worldsById.set(worldId, world);
1695
+ return worldId;
1696
+ }
1697
+
1698
+ private remapWorldIds(frame: ExtractedFrame, worldIds: readonly number[]): ExtractedFrame {
1699
+ let changed = false;
1700
+ const cameras = frame.cameras.map((camera) => {
1701
+ const worldId = worldIds[camera.worldId];
1702
+ if (worldId === undefined) {
1703
+ throw new RangeError(`camera references unattached world index ${camera.worldId}`);
1704
+ }
1705
+ if (worldId === camera.worldId) return camera;
1706
+ changed = true;
1707
+ return { ...camera, worldId };
1708
+ });
1709
+ const renderables = frame.renderables.map((renderable) => {
1710
+ const worldId = worldIds[renderable.worldId];
1711
+ if (worldId === undefined) {
1712
+ throw new RangeError(`renderable references unattached world index ${renderable.worldId}`);
1713
+ }
1714
+ if (worldId === renderable.worldId) return renderable;
1715
+ changed = true;
1716
+ return { ...renderable, worldId };
1717
+ });
1718
+ const sourceCandidateRenderables =
1719
+ frame.candidateDomain?.renderables ?? frame.candidateRenderables;
1720
+ const candidateRenderables = sourceCandidateRenderables?.map((renderable) => {
1721
+ const worldId = worldIds[renderable.worldId];
1722
+ if (worldId === undefined) {
1723
+ throw new RangeError(`candidate references unattached world index ${renderable.worldId}`);
1724
+ }
1725
+ if (worldId === renderable.worldId) return renderable;
1726
+ changed = true;
1727
+ return { ...renderable, worldId };
1728
+ });
1729
+ if (!changed) return frame;
1730
+ if (frame.candidateDomain === undefined || candidateRenderables === undefined) {
1731
+ return {
1732
+ ...frame,
1733
+ cameras,
1734
+ renderables,
1735
+ ...(candidateRenderables === undefined ? {} : { candidateRenderables }),
1736
+ };
1737
+ }
1738
+ const candidateDomain = buildRenderCandidateDomain(
1739
+ candidateRenderables,
1740
+ frame.candidateDomain.dispatch,
1741
+ );
1742
+ return {
1743
+ ...frame,
1744
+ cameras,
1745
+ renderables,
1746
+ candidateRenderables: candidateDomain.renderables,
1747
+ candidateDispatch: candidateDomain.dispatch,
1748
+ candidateDispatchMembership: candidateDomain.membership,
1749
+ candidateDomain,
1750
+ };
1751
+ }
1752
+ }