@forgeax/engine-render 0.0.0-dev.8d955ade1c79

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 (891) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +647 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/__tests__/authoring-path.unit.test.d.ts +2 -0
  5. package/dist/__tests__/authoring-path.unit.test.d.ts.map +1 -0
  6. package/dist/__tests__/backend-selection-rhi-capture.test-d.d.ts +2 -0
  7. package/dist/__tests__/backend-selection-rhi-capture.test-d.d.ts.map +1 -0
  8. package/dist/__tests__/callback-inference.test-d.d.ts +2 -0
  9. package/dist/__tests__/callback-inference.test-d.d.ts.map +1 -0
  10. package/dist/__tests__/cluster-binner.test.d.ts +2 -0
  11. package/dist/__tests__/cluster-binner.test.d.ts.map +1 -0
  12. package/dist/__tests__/cluster-grid-default-surface.unit.test.d.ts +2 -0
  13. package/dist/__tests__/cluster-grid-default-surface.unit.test.d.ts.map +1 -0
  14. package/dist/__tests__/construct-renderer-identity.unit.test.d.ts +2 -0
  15. package/dist/__tests__/construct-renderer-identity.unit.test.d.ts.map +1 -0
  16. package/dist/__tests__/device-scope-lifecycle.unit.test.d.ts +2 -0
  17. package/dist/__tests__/device-scope-lifecycle.unit.test.d.ts.map +1 -0
  18. package/dist/__tests__/device-scope-stale-matrix.unit.test.d.ts +2 -0
  19. package/dist/__tests__/device-scope-stale-matrix.unit.test.d.ts.map +1 -0
  20. package/dist/__tests__/direct-extract-consumer-contract.test-d.d.ts +2 -0
  21. package/dist/__tests__/direct-extract-consumer-contract.test-d.d.ts.map +1 -0
  22. package/dist/__tests__/direct-light-snapshot.unit.test.d.ts +2 -0
  23. package/dist/__tests__/direct-light-snapshot.unit.test.d.ts.map +1 -0
  24. package/dist/__tests__/factory-contract.integration.test.d.ts +2 -0
  25. package/dist/__tests__/factory-contract.integration.test.d.ts.map +1 -0
  26. package/dist/__tests__/fallback-row-stride-surface.unit.test.d.ts +2 -0
  27. package/dist/__tests__/fallback-row-stride-surface.unit.test.d.ts.map +1 -0
  28. package/dist/__tests__/frame-observation.contract.test.d.ts +2 -0
  29. package/dist/__tests__/frame-observation.contract.test.d.ts.map +1 -0
  30. package/dist/__tests__/fullscreen-feature-plan.unit.test.d.ts +2 -0
  31. package/dist/__tests__/fullscreen-feature-plan.unit.test.d.ts.map +1 -0
  32. package/dist/__tests__/glyph-text-layout-recovery.unit.test.d.ts +2 -0
  33. package/dist/__tests__/glyph-text-layout-recovery.unit.test.d.ts.map +1 -0
  34. package/dist/__tests__/gpu-driven-indirect-raster-evidence.d.ts +6 -0
  35. package/dist/__tests__/gpu-driven-indirect-raster-evidence.d.ts.map +1 -0
  36. package/dist/__tests__/gpu-driven-indirect-raster.browser.test.d.ts +2 -0
  37. package/dist/__tests__/gpu-driven-indirect-raster.browser.test.d.ts.map +1 -0
  38. package/dist/__tests__/gpu-driven-indirect-raster.dawn.test.d.ts +2 -0
  39. package/dist/__tests__/gpu-driven-indirect-raster.dawn.test.d.ts.map +1 -0
  40. package/dist/__tests__/gpu-driven-production.integration.test.d.ts +2 -0
  41. package/dist/__tests__/gpu-driven-production.integration.test.d.ts.map +1 -0
  42. package/dist/__tests__/gpu-driven-scaling.unit.test.d.ts +2 -0
  43. package/dist/__tests__/gpu-driven-scaling.unit.test.d.ts.map +1 -0
  44. package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts +18 -0
  45. package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts.map +1 -0
  46. package/dist/__tests__/gpu-driven-view-graph.integration.test.d.ts +2 -0
  47. package/dist/__tests__/gpu-driven-view-graph.integration.test.d.ts.map +1 -0
  48. package/dist/__tests__/gpu-driven-view-reference.d.ts +15 -0
  49. package/dist/__tests__/gpu-driven-view-reference.d.ts.map +1 -0
  50. package/dist/__tests__/gpu-driven-view.browser.test.d.ts +2 -0
  51. package/dist/__tests__/gpu-driven-view.browser.test.d.ts.map +1 -0
  52. package/dist/__tests__/gpu-driven-view.dawn.test.d.ts +2 -0
  53. package/dist/__tests__/gpu-driven-view.dawn.test.d.ts.map +1 -0
  54. package/dist/__tests__/gpu-driven-view.unit.test.d.ts +2 -0
  55. package/dist/__tests__/gpu-driven-view.unit.test.d.ts.map +1 -0
  56. package/dist/__tests__/gpu-resource-store-stride.unit.test.d.ts +2 -0
  57. package/dist/__tests__/gpu-resource-store-stride.unit.test.d.ts.map +1 -0
  58. package/dist/__tests__/gpu-scene-render-graph-gpu.d.ts +7 -0
  59. package/dist/__tests__/gpu-scene-render-graph-gpu.d.ts.map +1 -0
  60. package/dist/__tests__/gpu-scene-render-graph.browser.test.d.ts +2 -0
  61. package/dist/__tests__/gpu-scene-render-graph.browser.test.d.ts.map +1 -0
  62. package/dist/__tests__/gpu-scene-render-graph.dawn.test.d.ts +2 -0
  63. package/dist/__tests__/gpu-scene-render-graph.dawn.test.d.ts.map +1 -0
  64. package/dist/__tests__/gpu-scene-schema.unit.test.d.ts +2 -0
  65. package/dist/__tests__/gpu-scene-schema.unit.test.d.ts.map +1 -0
  66. package/dist/__tests__/gpu-scene.dawn.test.d.ts +2 -0
  67. package/dist/__tests__/gpu-scene.dawn.test.d.ts.map +1 -0
  68. package/dist/__tests__/gpu-scene.unit.test.d.ts +2 -0
  69. package/dist/__tests__/gpu-scene.unit.test.d.ts.map +1 -0
  70. package/dist/__tests__/ibl/face-uniforms.unit.test.d.ts +2 -0
  71. package/dist/__tests__/ibl/face-uniforms.unit.test.d.ts.map +1 -0
  72. package/dist/__tests__/infinite-grid-no-vertex-probe.unit.test.d.ts +2 -0
  73. package/dist/__tests__/infinite-grid-no-vertex-probe.unit.test.d.ts.map +1 -0
  74. package/dist/__tests__/injection-kind-owner.test-d.d.ts +2 -0
  75. package/dist/__tests__/injection-kind-owner.test-d.d.ts.map +1 -0
  76. package/dist/__tests__/ktx2-basis-gpu-consumer.dawn.test.d.ts +2 -0
  77. package/dist/__tests__/ktx2-basis-gpu-consumer.dawn.test.d.ts.map +1 -0
  78. package/dist/__tests__/light-buffer-layout.unit.test.d.ts +2 -0
  79. package/dist/__tests__/light-buffer-layout.unit.test.d.ts.map +1 -0
  80. package/dist/__tests__/material-contract-inventory.unit.test.d.ts +2 -0
  81. package/dist/__tests__/material-contract-inventory.unit.test.d.ts.map +1 -0
  82. package/dist/__tests__/material-cooked-projection.unit.test.d.ts +2 -0
  83. package/dist/__tests__/material-cooked-projection.unit.test.d.ts.map +1 -0
  84. package/dist/__tests__/material-snapshot-mutation.integration.test.d.ts +2 -0
  85. package/dist/__tests__/material-snapshot-mutation.integration.test.d.ts.map +1 -0
  86. package/dist/__tests__/material-static-dynamic-route.unit.test.d.ts +2 -0
  87. package/dist/__tests__/material-static-dynamic-route.unit.test.d.ts.map +1 -0
  88. package/dist/__tests__/material-stride-surface.unit.test.d.ts +2 -0
  89. package/dist/__tests__/material-stride-surface.unit.test.d.ts.map +1 -0
  90. package/dist/__tests__/mesh-buffer-usage-surface.unit.test.d.ts +2 -0
  91. package/dist/__tests__/mesh-buffer-usage-surface.unit.test.d.ts.map +1 -0
  92. package/dist/__tests__/mesh-material-bindings.unit.test.d.ts +2 -0
  93. package/dist/__tests__/mesh-material-bindings.unit.test.d.ts.map +1 -0
  94. package/dist/__tests__/mesh-stride-surface.unit.test.d.ts +2 -0
  95. package/dist/__tests__/mesh-stride-surface.unit.test.d.ts.map +1 -0
  96. package/dist/__tests__/morph-culling-reentry.dawn.test.d.ts +2 -0
  97. package/dist/__tests__/morph-culling-reentry.dawn.test.d.ts.map +1 -0
  98. package/dist/__tests__/morph-feature-gpu-work.integration.test.d.ts +2 -0
  99. package/dist/__tests__/morph-feature-gpu-work.integration.test.d.ts.map +1 -0
  100. package/dist/__tests__/morph-feature-plan.unit.test.d.ts +2 -0
  101. package/dist/__tests__/morph-feature-plan.unit.test.d.ts.map +1 -0
  102. package/dist/__tests__/morph-visual-evidence.integration.test.d.ts +2 -0
  103. package/dist/__tests__/morph-visual-evidence.integration.test.d.ts.map +1 -0
  104. package/dist/__tests__/nineslice-handle-surface.unit.test.d.ts +2 -0
  105. package/dist/__tests__/nineslice-handle-surface.unit.test.d.ts.map +1 -0
  106. package/dist/__tests__/post-process-error-policy-owner.unit.test.d.ts +2 -0
  107. package/dist/__tests__/post-process-error-policy-owner.unit.test.d.ts.map +1 -0
  108. package/dist/__tests__/prepared-buffer-kind-owner.test-d.d.ts +2 -0
  109. package/dist/__tests__/prepared-buffer-kind-owner.test-d.d.ts.map +1 -0
  110. package/dist/__tests__/prepared-graphics-capability.unit.test.d.ts +2 -0
  111. package/dist/__tests__/prepared-graphics-capability.unit.test.d.ts.map +1 -0
  112. package/dist/__tests__/prepared-graphics-generation.unit.test.d.ts +2 -0
  113. package/dist/__tests__/prepared-graphics-generation.unit.test.d.ts.map +1 -0
  114. package/dist/__tests__/prepared-graphics-lifecycle.unit.test.d.ts +2 -0
  115. package/dist/__tests__/prepared-graphics-lifecycle.unit.test.d.ts.map +1 -0
  116. package/dist/__tests__/prepared-graphics-pipeline-warmup.unit.test.d.ts +2 -0
  117. package/dist/__tests__/prepared-graphics-pipeline-warmup.unit.test.d.ts.map +1 -0
  118. package/dist/__tests__/prepared-graphics-resolver.unit.test.d.ts +2 -0
  119. package/dist/__tests__/prepared-graphics-resolver.unit.test.d.ts.map +1 -0
  120. package/dist/__tests__/prepared-graphics-snapshot.unit.test.d.ts +2 -0
  121. package/dist/__tests__/prepared-graphics-snapshot.unit.test.d.ts.map +1 -0
  122. package/dist/__tests__/prepared-graphics-store.unit.test.d.ts +2 -0
  123. package/dist/__tests__/prepared-graphics-store.unit.test.d.ts.map +1 -0
  124. package/dist/__tests__/prepared-graphics-validation.unit.test.d.ts +2 -0
  125. package/dist/__tests__/prepared-graphics-validation.unit.test.d.ts.map +1 -0
  126. package/dist/__tests__/profiler-default-off.test.d.ts +2 -0
  127. package/dist/__tests__/profiler-default-off.test.d.ts.map +1 -0
  128. package/dist/__tests__/profiler-phase-catalog.test.d.ts +2 -0
  129. package/dist/__tests__/profiler-phase-catalog.test.d.ts.map +1 -0
  130. package/dist/__tests__/profiler-phase-integration.test.d.ts +2 -0
  131. package/dist/__tests__/profiler-phase-integration.test.d.ts.map +1 -0
  132. package/dist/__tests__/profiler-phase-token.test.d.ts +2 -0
  133. package/dist/__tests__/profiler-phase-token.test.d.ts.map +1 -0
  134. package/dist/__tests__/public-surface.test-d.d.ts +2 -0
  135. package/dist/__tests__/public-surface.test-d.d.ts.map +1 -0
  136. package/dist/__tests__/recover-error-policy-owner.unit.test.d.ts +2 -0
  137. package/dist/__tests__/recover-error-policy-owner.unit.test.d.ts.map +1 -0
  138. package/dist/__tests__/render-error-code-owner.test-d.d.ts +2 -0
  139. package/dist/__tests__/render-error-code-owner.test-d.d.ts.map +1 -0
  140. package/dist/__tests__/render-error-detail-ssot.test-d.d.ts +2 -0
  141. package/dist/__tests__/render-error-detail-ssot.test-d.d.ts.map +1 -0
  142. package/dist/__tests__/render-error-exhaustive.test-d.d.ts +2 -0
  143. package/dist/__tests__/render-error-exhaustive.test-d.d.ts.map +1 -0
  144. package/dist/__tests__/render-feature-assembly.test-d.d.ts +2 -0
  145. package/dist/__tests__/render-feature-assembly.test-d.d.ts.map +1 -0
  146. package/dist/__tests__/render-feature-context.test-d.d.ts +2 -0
  147. package/dist/__tests__/render-feature-context.test-d.d.ts.map +1 -0
  148. package/dist/__tests__/render-feature-contract.test-d.d.ts +2 -0
  149. package/dist/__tests__/render-feature-contract.test-d.d.ts.map +1 -0
  150. package/dist/__tests__/render-feature-diagnostics.unit.test.d.ts +2 -0
  151. package/dist/__tests__/render-feature-diagnostics.unit.test.d.ts.map +1 -0
  152. package/dist/__tests__/render-feature-docs.unit.test.d.ts +2 -0
  153. package/dist/__tests__/render-feature-docs.unit.test.d.ts.map +1 -0
  154. package/dist/__tests__/render-feature-errors.unit.test.d.ts +2 -0
  155. package/dist/__tests__/render-feature-errors.unit.test.d.ts.map +1 -0
  156. package/dist/__tests__/render-feature-gpu-work.integration.test.d.ts +2 -0
  157. package/dist/__tests__/render-feature-gpu-work.integration.test.d.ts.map +1 -0
  158. package/dist/__tests__/render-feature-plan.test-d.d.ts +2 -0
  159. package/dist/__tests__/render-feature-plan.test-d.d.ts.map +1 -0
  160. package/dist/__tests__/render-feature-plan.unit.test.d.ts +2 -0
  161. package/dist/__tests__/render-feature-plan.unit.test.d.ts.map +1 -0
  162. package/dist/__tests__/render-feature-prepared-diagnostics.unit.test.d.ts +2 -0
  163. package/dist/__tests__/render-feature-prepared-diagnostics.unit.test.d.ts.map +1 -0
  164. package/dist/__tests__/render-feature-prepared-errors.test-d.d.ts +2 -0
  165. package/dist/__tests__/render-feature-prepared-errors.test-d.d.ts.map +1 -0
  166. package/dist/__tests__/render-feature-prepared-graphics-docs.unit.test.d.ts +2 -0
  167. package/dist/__tests__/render-feature-prepared-graphics-docs.unit.test.d.ts.map +1 -0
  168. package/dist/__tests__/render-feature-prepared-graphics-isolation.unit.test.d.ts +2 -0
  169. package/dist/__tests__/render-feature-prepared-graphics-isolation.unit.test.d.ts.map +1 -0
  170. package/dist/__tests__/render-feature-prepared-graphics-negative.test-d.d.ts +2 -0
  171. package/dist/__tests__/render-feature-prepared-graphics-negative.test-d.d.ts.map +1 -0
  172. package/dist/__tests__/render-feature-prepared-graphics.test-d.d.ts +2 -0
  173. package/dist/__tests__/render-feature-prepared-graphics.test-d.d.ts.map +1 -0
  174. package/dist/__tests__/render-feature-prepared-graphics.unit.test.d.ts +2 -0
  175. package/dist/__tests__/render-feature-prepared-graphics.unit.test.d.ts.map +1 -0
  176. package/dist/__tests__/render-feature-public-surface.test-d.d.ts +2 -0
  177. package/dist/__tests__/render-feature-public-surface.test-d.d.ts.map +1 -0
  178. package/dist/__tests__/render-feature-retry.unit.test.d.ts +2 -0
  179. package/dist/__tests__/render-feature-retry.unit.test.d.ts.map +1 -0
  180. package/dist/__tests__/render-feature-scheduling.unit.test.d.ts +2 -0
  181. package/dist/__tests__/render-feature-scheduling.unit.test.d.ts.map +1 -0
  182. package/dist/__tests__/render-feature-stage-failed-policy-owner.unit.test.d.ts +2 -0
  183. package/dist/__tests__/render-feature-stage-failed-policy-owner.unit.test.d.ts.map +1 -0
  184. package/dist/__tests__/render-feature-stage-fault-recovery.unit.test.d.ts +2 -0
  185. package/dist/__tests__/render-feature-stage-fault-recovery.unit.test.d.ts.map +1 -0
  186. package/dist/__tests__/render-feature-visibility-context.test-d.d.ts +2 -0
  187. package/dist/__tests__/render-feature-visibility-context.test-d.d.ts.map +1 -0
  188. package/dist/__tests__/render-feature-visibility-context.unit.test.d.ts +2 -0
  189. package/dist/__tests__/render-feature-visibility-context.unit.test.d.ts.map +1 -0
  190. package/dist/__tests__/render-feature-zero-work.unit.test.d.ts +2 -0
  191. package/dist/__tests__/render-feature-zero-work.unit.test.d.ts.map +1 -0
  192. package/dist/__tests__/render-graph-compute-raster-gpu.d.ts +7 -0
  193. package/dist/__tests__/render-graph-compute-raster-gpu.d.ts.map +1 -0
  194. package/dist/__tests__/render-graph-compute-raster.browser.test.d.ts +2 -0
  195. package/dist/__tests__/render-graph-compute-raster.browser.test.d.ts.map +1 -0
  196. package/dist/__tests__/render-graph-compute-raster.dawn.test.d.ts +2 -0
  197. package/dist/__tests__/render-graph-compute-raster.dawn.test.d.ts.map +1 -0
  198. package/dist/__tests__/render-graph-hzb-gpu.d.ts +7 -0
  199. package/dist/__tests__/render-graph-hzb-gpu.d.ts.map +1 -0
  200. package/dist/__tests__/render-graph-hzb.browser.test.d.ts +2 -0
  201. package/dist/__tests__/render-graph-hzb.browser.test.d.ts.map +1 -0
  202. package/dist/__tests__/render-graph-hzb.dawn.test.d.ts +2 -0
  203. package/dist/__tests__/render-graph-hzb.dawn.test.d.ts.map +1 -0
  204. package/dist/__tests__/render-graph-primitives.unit.test.d.ts +2 -0
  205. package/dist/__tests__/render-graph-primitives.unit.test.d.ts.map +1 -0
  206. package/dist/__tests__/render-graph-storage-indirect-gpu.d.ts +12 -0
  207. package/dist/__tests__/render-graph-storage-indirect-gpu.d.ts.map +1 -0
  208. package/dist/__tests__/render-graph-storage-indirect.browser.test.d.ts +2 -0
  209. package/dist/__tests__/render-graph-storage-indirect.browser.test.d.ts.map +1 -0
  210. package/dist/__tests__/render-graph-storage-indirect.dawn.test.d.ts +2 -0
  211. package/dist/__tests__/render-graph-storage-indirect.dawn.test.d.ts.map +1 -0
  212. package/dist/__tests__/render-scene-projection.unit.test.d.ts +2 -0
  213. package/dist/__tests__/render-scene-projection.unit.test.d.ts.map +1 -0
  214. package/dist/__tests__/renderer-factory-material-contract.unit.test.d.ts +2 -0
  215. package/dist/__tests__/renderer-factory-material-contract.unit.test.d.ts.map +1 -0
  216. package/dist/__tests__/renderer-lifecycle.integration.test.d.ts +2 -0
  217. package/dist/__tests__/renderer-lifecycle.integration.test.d.ts.map +1 -0
  218. package/dist/__tests__/rhi-backend-package-boundary.unit.test.d.ts +2 -0
  219. package/dist/__tests__/rhi-backend-package-boundary.unit.test.d.ts.map +1 -0
  220. package/dist/__tests__/scriptable-pack-consumer.test-d.d.ts +2 -0
  221. package/dist/__tests__/scriptable-pack-consumer.test-d.d.ts.map +1 -0
  222. package/dist/__tests__/shader-stage-surface.unit.test.d.ts +2 -0
  223. package/dist/__tests__/shader-stage-surface.unit.test.d.ts.map +1 -0
  224. package/dist/__tests__/ssao-config.unit.test.d.ts +2 -0
  225. package/dist/__tests__/ssao-config.unit.test.d.ts.map +1 -0
  226. package/dist/__tests__/ssao-kernel-surface.unit.test.d.ts +2 -0
  227. package/dist/__tests__/ssao-kernel-surface.unit.test.d.ts.map +1 -0
  228. package/dist/__tests__/standard-clustered-pipeline.unit.test.d.ts +2 -0
  229. package/dist/__tests__/standard-clustered-pipeline.unit.test.d.ts.map +1 -0
  230. package/dist/__tests__/standard-descriptors.test-d.d.ts +2 -0
  231. package/dist/__tests__/standard-descriptors.test-d.d.ts.map +1 -0
  232. package/dist/__tests__/standard-pipeline.dawn.test.d.ts +2 -0
  233. package/dist/__tests__/standard-pipeline.dawn.test.d.ts.map +1 -0
  234. package/dist/__tests__/standard-pipeline.integration.test.d.ts +2 -0
  235. package/dist/__tests__/standard-pipeline.integration.test.d.ts.map +1 -0
  236. package/dist/__tests__/standard-profile-oracle.unit.test.d.ts +2 -0
  237. package/dist/__tests__/standard-profile-oracle.unit.test.d.ts.map +1 -0
  238. package/dist/__tests__/surface-configuration.unit.test.d.ts +2 -0
  239. package/dist/__tests__/surface-configuration.unit.test.d.ts.map +1 -0
  240. package/dist/__tests__/texture-usage-surface.unit.test.d.ts +2 -0
  241. package/dist/__tests__/texture-usage-surface.unit.test.d.ts.map +1 -0
  242. package/dist/__tests__/typed-pipeline-topology.unit.test.d.ts +2 -0
  243. package/dist/__tests__/typed-pipeline-topology.unit.test.d.ts.map +1 -0
  244. package/dist/__tests__/urp-pipeline-targets.unit.test.d.ts +2 -0
  245. package/dist/__tests__/urp-pipeline-targets.unit.test.d.ts.map +1 -0
  246. package/dist/__tests__/urp-pipeline.unit.test.d.ts +2 -0
  247. package/dist/__tests__/urp-pipeline.unit.test.d.ts.map +1 -0
  248. package/dist/__tests__/vertex-color-pipeline.unit.test.d.ts +2 -0
  249. package/dist/__tests__/vertex-color-pipeline.unit.test.d.ts.map +1 -0
  250. package/dist/__tests__/vertex-layout-consumer.unit.test.d.ts +2 -0
  251. package/dist/__tests__/vertex-layout-consumer.unit.test.d.ts.map +1 -0
  252. package/dist/__tests__/visibility-diagnostics.integration.test.d.ts +2 -0
  253. package/dist/__tests__/visibility-diagnostics.integration.test.d.ts.map +1 -0
  254. package/dist/__tests__/visibility-extract.integration.test.d.ts +2 -0
  255. package/dist/__tests__/visibility-extract.integration.test.d.ts.map +1 -0
  256. package/dist/__tests__/visibility-extract.perf.test.d.ts +2 -0
  257. package/dist/__tests__/visibility-extract.perf.test.d.ts.map +1 -0
  258. package/dist/__tests__/visibility-feature-dedup.integration.test.d.ts +2 -0
  259. package/dist/__tests__/visibility-feature-dedup.integration.test.d.ts.map +1 -0
  260. package/dist/__tests__/visibility-hidden-report.unit.test.d.ts +2 -0
  261. package/dist/__tests__/visibility-hidden-report.unit.test.d.ts.map +1 -0
  262. package/dist/__tests__/visibility-instances.integration.test.d.ts +2 -0
  263. package/dist/__tests__/visibility-instances.integration.test.d.ts.map +1 -0
  264. package/dist/__tests__/visibility-multi-world.integration.test.d.ts +2 -0
  265. package/dist/__tests__/visibility-multi-world.integration.test.d.ts.map +1 -0
  266. package/dist/__tests__/visibility-producer-matrix.integration.test.d.ts +2 -0
  267. package/dist/__tests__/visibility-producer-matrix.integration.test.d.ts.map +1 -0
  268. package/dist/__tests__/visibility-producer-matrix.unit.test.d.ts +2 -0
  269. package/dist/__tests__/visibility-producer-matrix.unit.test.d.ts.map +1 -0
  270. package/dist/__tests__/visibility-public-surface.test-d.d.ts +2 -0
  271. package/dist/__tests__/visibility-public-surface.test-d.d.ts.map +1 -0
  272. package/dist/__tests__/visibility-resolver.unit.test.d.ts +2 -0
  273. package/dist/__tests__/visibility-resolver.unit.test.d.ts.map +1 -0
  274. package/dist/__tests__/visibility-resource-short-circuit.unit.test.d.ts +2 -0
  275. package/dist/__tests__/visibility-resource-short-circuit.unit.test.d.ts.map +1 -0
  276. package/dist/__tests__/visibility-snapshot-contract.unit.test.d.ts +2 -0
  277. package/dist/__tests__/visibility-snapshot-contract.unit.test.d.ts.map +1 -0
  278. package/dist/__tests__/vocabulary.unit.test.d.ts +2 -0
  279. package/dist/__tests__/vocabulary.unit.test.d.ts.map +1 -0
  280. package/dist/assembly/backend-contract.d.ts +37 -0
  281. package/dist/assembly/backend-contract.d.ts.map +1 -0
  282. package/dist/assembly/factory.d.ts +207 -0
  283. package/dist/assembly/factory.d.ts.map +1 -0
  284. package/dist/assembly/host-contract.d.ts +84 -0
  285. package/dist/assembly/host-contract.d.ts.map +1 -0
  286. package/dist/assembly/material/assembly.d.ts +21 -0
  287. package/dist/assembly/material/assembly.d.ts.map +1 -0
  288. package/dist/assembly/material/pipeline-projection.d.ts +30 -0
  289. package/dist/assembly/material/pipeline-projection.d.ts.map +1 -0
  290. package/dist/assets/asset-decoders.d.ts +5 -0
  291. package/dist/assets/asset-decoders.d.ts.map +1 -0
  292. package/dist/assets/render-asset-port.d.ts +17 -0
  293. package/dist/assets/render-asset-port.d.ts.map +1 -0
  294. package/dist/assets/resolve-render-asset.d.ts +6 -0
  295. package/dist/assets/resolve-render-asset.d.ts.map +1 -0
  296. package/dist/authoring.d.ts +12 -0
  297. package/dist/authoring.d.ts.map +1 -0
  298. package/dist/authoring.mjs +27 -0
  299. package/dist/authoring.mjs.map +1 -0
  300. package/dist/chunk-CQXZC5XI.mjs +182 -0
  301. package/dist/chunk-CQXZC5XI.mjs.map +1 -0
  302. package/dist/chunk-HCOGPHKS.mjs +93 -0
  303. package/dist/chunk-HCOGPHKS.mjs.map +1 -0
  304. package/dist/chunk-YEJIUW7D.mjs +1152 -0
  305. package/dist/chunk-YEJIUW7D.mjs.map +1 -0
  306. package/dist/cluster-binner.d.ts +152 -0
  307. package/dist/cluster-binner.d.ts.map +1 -0
  308. package/dist/components/__tests__/points-lines-admission.unit.test.d.ts +2 -0
  309. package/dist/components/__tests__/points-lines-admission.unit.test.d.ts.map +1 -0
  310. package/dist/components/__tests__/points-lines-schema.unit.test.d.ts +2 -0
  311. package/dist/components/__tests__/points-lines-schema.unit.test.d.ts.map +1 -0
  312. package/dist/components/__tests__/schema-contract.unit.test.d.ts +2 -0
  313. package/dist/components/__tests__/schema-contract.unit.test.d.ts.map +1 -0
  314. package/dist/components/__tests__/schema-parity.unit.test.d.ts +2 -0
  315. package/dist/components/__tests__/schema-parity.unit.test.d.ts.map +1 -0
  316. package/dist/components/__tests__/visibility-schema.unit.test.d.ts +2 -0
  317. package/dist/components/__tests__/visibility-schema.unit.test.d.ts.map +1 -0
  318. package/dist/components/camera.d.ts +311 -0
  319. package/dist/components/camera.d.ts.map +1 -0
  320. package/dist/components/directional-light.d.ts +76 -0
  321. package/dist/components/directional-light.d.ts.map +1 -0
  322. package/dist/components/glyph-text.d.ts +26 -0
  323. package/dist/components/glyph-text.d.ts.map +1 -0
  324. package/dist/components/index.d.ts +24 -0
  325. package/dist/components/index.d.ts.map +1 -0
  326. package/dist/components/instances.d.ts +41 -0
  327. package/dist/components/instances.d.ts.map +1 -0
  328. package/dist/components/layer.d.ts +34 -0
  329. package/dist/components/layer.d.ts.map +1 -0
  330. package/dist/components/light-helpers.d.ts +53 -0
  331. package/dist/components/light-helpers.d.ts.map +1 -0
  332. package/dist/components/lines.d.ts +5 -0
  333. package/dist/components/lines.d.ts.map +1 -0
  334. package/dist/components/mesh-filter.d.ts +24 -0
  335. package/dist/components/mesh-filter.d.ts.map +1 -0
  336. package/dist/components/mesh-renderer.d.ts +33 -0
  337. package/dist/components/mesh-renderer.d.ts.map +1 -0
  338. package/dist/components/point-light-shadow.d.ts +27 -0
  339. package/dist/components/point-light-shadow.d.ts.map +1 -0
  340. package/dist/components/point-light.d.ts +35 -0
  341. package/dist/components/point-light.d.ts.map +1 -0
  342. package/dist/components/points.d.ts +15 -0
  343. package/dist/components/points.d.ts.map +1 -0
  344. package/dist/components/post-process-params.d.ts +5 -0
  345. package/dist/components/post-process-params.d.ts.map +1 -0
  346. package/dist/components/scene-instance.d.ts +140 -0
  347. package/dist/components/scene-instance.d.ts.map +1 -0
  348. package/dist/components/skybox-background.d.ts +56 -0
  349. package/dist/components/skybox-background.d.ts.map +1 -0
  350. package/dist/components/skylight.d.ts +55 -0
  351. package/dist/components/skylight.d.ts.map +1 -0
  352. package/dist/components/sort-key.d.ts +44 -0
  353. package/dist/components/sort-key.d.ts.map +1 -0
  354. package/dist/components/spot-light.d.ts +81 -0
  355. package/dist/components/spot-light.d.ts.map +1 -0
  356. package/dist/components/sprite-animation.d.ts +74 -0
  357. package/dist/components/sprite-animation.d.ts.map +1 -0
  358. package/dist/components/sprite-instances.d.ts +51 -0
  359. package/dist/components/sprite-instances.d.ts.map +1 -0
  360. package/dist/components/sprite-playback-mode.d.ts +42 -0
  361. package/dist/components/sprite-playback-mode.d.ts.map +1 -0
  362. package/dist/components/sprite-region-override.d.ts +46 -0
  363. package/dist/components/sprite-region-override.d.ts.map +1 -0
  364. package/dist/components/tile-layer.d.ts +106 -0
  365. package/dist/components/tile-layer.d.ts.map +1 -0
  366. package/dist/components/tilemap.d.ts +25 -0
  367. package/dist/components/tilemap.d.ts.map +1 -0
  368. package/dist/components/visibility.d.ts +22 -0
  369. package/dist/components/visibility.d.ts.map +1 -0
  370. package/dist/construct-renderer.d.ts +19 -0
  371. package/dist/construct-renderer.d.ts.map +1 -0
  372. package/dist/construct-renderer.mjs +27462 -0
  373. package/dist/construct-renderer.mjs.map +1 -0
  374. package/dist/debug-draw-glue.d.ts +5 -0
  375. package/dist/debug-draw-glue.d.ts.map +1 -0
  376. package/dist/device/device-scope.d.ts +83 -0
  377. package/dist/device/device-scope.d.ts.map +1 -0
  378. package/dist/device/gpu-residency.d.ts +337 -0
  379. package/dist/device/gpu-residency.d.ts.map +1 -0
  380. package/dist/device/resource-types.d.ts +8 -0
  381. package/dist/device/resource-types.d.ts.map +1 -0
  382. package/dist/engine-metrics.d.ts +23 -0
  383. package/dist/engine-metrics.d.ts.map +1 -0
  384. package/dist/errors/ecs-validation.d.ts +3 -0
  385. package/dist/errors/ecs-validation.d.ts.map +1 -0
  386. package/dist/errors/index.d.ts +4 -0
  387. package/dist/errors/index.d.ts.map +1 -0
  388. package/dist/errors/recover.d.ts +105 -0
  389. package/dist/errors/recover.d.ts.map +1 -0
  390. package/dist/errors/render.d.ts +705 -0
  391. package/dist/errors/render.d.ts.map +1 -0
  392. package/dist/extract/visibility.d.ts +26 -0
  393. package/dist/extract/visibility.d.ts.map +1 -0
  394. package/dist/features/fullscreen.d.ts +19 -0
  395. package/dist/features/fullscreen.d.ts.map +1 -0
  396. package/dist/features/host.d.ts +106 -0
  397. package/dist/features/host.d.ts.map +1 -0
  398. package/dist/features/morph/morph-feature.d.ts +79 -0
  399. package/dist/features/morph/morph-feature.d.ts.map +1 -0
  400. package/dist/features/plan.d.ts +182 -0
  401. package/dist/features/plan.d.ts.map +1 -0
  402. package/dist/features/prepared-gpu-work.d.ts +117 -0
  403. package/dist/features/prepared-gpu-work.d.ts.map +1 -0
  404. package/dist/features/prepared-graphics-store.d.ts +66 -0
  405. package/dist/features/prepared-graphics-store.d.ts.map +1 -0
  406. package/dist/features/prepared-graphics.d.ts +215 -0
  407. package/dist/features/prepared-graphics.d.ts.map +1 -0
  408. package/dist/features/render-graph-compute.d.ts +13 -0
  409. package/dist/features/render-graph-compute.d.ts.map +1 -0
  410. package/dist/features/render-graph-contribution.d.ts +12 -0
  411. package/dist/features/render-graph-contribution.d.ts.map +1 -0
  412. package/dist/features/render-graph-raster.d.ts +38 -0
  413. package/dist/features/render-graph-raster.d.ts.map +1 -0
  414. package/dist/features/render-graph-resources.d.ts +11 -0
  415. package/dist/features/render-graph-resources.d.ts.map +1 -0
  416. package/dist/features/targets.d.ts +32 -0
  417. package/dist/features/targets.d.ts.map +1 -0
  418. package/dist/features/types.d.ts +68 -0
  419. package/dist/features/types.d.ts.map +1 -0
  420. package/dist/features/vocabulary.d.ts +14 -0
  421. package/dist/features/vocabulary.d.ts.map +1 -0
  422. package/dist/fullscreen-post-process-pass.d.ts +157 -0
  423. package/dist/fullscreen-post-process-pass.d.ts.map +1 -0
  424. package/dist/glyph-text-layout-system.d.ts +19 -0
  425. package/dist/glyph-text-layout-system.d.ts.map +1 -0
  426. package/dist/gpu-driven/batch-topology.d.ts +55 -0
  427. package/dist/gpu-driven/batch-topology.d.ts.map +1 -0
  428. package/dist/gpu-driven/production-raster.d.ts +51 -0
  429. package/dist/gpu-driven/production-raster.d.ts.map +1 -0
  430. package/dist/gpu-driven/view-gpu.d.ts +85 -0
  431. package/dist/gpu-driven/view-gpu.d.ts.map +1 -0
  432. package/dist/gpu-resource.d.ts +73 -0
  433. package/dist/gpu-resource.d.ts.map +1 -0
  434. package/dist/gpu-scene-schema.d.ts +78 -0
  435. package/dist/gpu-scene-schema.d.ts.map +1 -0
  436. package/dist/gpu-scene.d.ts +55 -0
  437. package/dist/gpu-scene.d.ts.map +1 -0
  438. package/dist/gpu-stage.d.ts +4 -0
  439. package/dist/gpu-stage.d.ts.map +1 -0
  440. package/dist/gpu-texture-usage.d.ts +6 -0
  441. package/dist/gpu-texture-usage.d.ts.map +1 -0
  442. package/dist/gpu-usage.d.ts +9 -0
  443. package/dist/gpu-usage.d.ts.map +1 -0
  444. package/dist/hdrp-buffers.d.ts +163 -0
  445. package/dist/hdrp-buffers.d.ts.map +1 -0
  446. package/dist/ibl/IblPipelineCache.d.ts +168 -0
  447. package/dist/ibl/IblPipelineCache.d.ts.map +1 -0
  448. package/dist/ibl/skylight-bind-group.d.ts +130 -0
  449. package/dist/ibl/skylight-bind-group.d.ts.map +1 -0
  450. package/dist/index.d.ts +31 -0
  451. package/dist/index.d.ts.map +1 -0
  452. package/dist/index.mjs +169 -0
  453. package/dist/index.mjs.map +1 -0
  454. package/dist/inspection-types.d.ts +72 -0
  455. package/dist/inspection-types.d.ts.map +1 -0
  456. package/dist/instance-buffer-cache.d.ts +56 -0
  457. package/dist/instance-buffer-cache.d.ts.map +1 -0
  458. package/dist/internal.d.ts +2 -0
  459. package/dist/internal.d.ts.map +1 -0
  460. package/dist/internal.mjs +3 -0
  461. package/dist/internal.mjs.map +1 -0
  462. package/dist/lifecycle.d.ts +62 -0
  463. package/dist/lifecycle.d.ts.map +1 -0
  464. package/dist/light-buffer-layout.d.ts +164 -0
  465. package/dist/light-buffer-layout.d.ts.map +1 -0
  466. package/dist/materials.d.ts +47 -0
  467. package/dist/materials.d.ts.map +1 -0
  468. package/dist/mesh-material-bindings.d.ts +43 -0
  469. package/dist/mesh-material-bindings.d.ts.map +1 -0
  470. package/dist/pbr-pipeline.d.ts +301 -0
  471. package/dist/pbr-pipeline.d.ts.map +1 -0
  472. package/dist/pipeline/standard-forward-lane.d.ts +5 -0
  473. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -0
  474. package/dist/pipeline/standard-pipeline.d.ts +31 -0
  475. package/dist/pipeline/standard-pipeline.d.ts.map +1 -0
  476. package/dist/pipeline/standard-profile.d.ts +40 -0
  477. package/dist/pipeline/standard-profile.d.ts.map +1 -0
  478. package/dist/pipeline-builder.d.ts +122 -0
  479. package/dist/pipeline-builder.d.ts.map +1 -0
  480. package/dist/pipeline-spec-types.d.ts +24 -0
  481. package/dist/pipeline-spec-types.d.ts.map +1 -0
  482. package/dist/pipeline-spec.d.ts +367 -0
  483. package/dist/pipeline-spec.d.ts.map +1 -0
  484. package/dist/plugin.d.ts +4 -0
  485. package/dist/plugin.d.ts.map +1 -0
  486. package/dist/points-lines/__tests__/bounds.unit.test.d.ts +2 -0
  487. package/dist/points-lines/__tests__/bounds.unit.test.d.ts.map +1 -0
  488. package/dist/points-lines/__tests__/cache-recovery.unit.test.d.ts +2 -0
  489. package/dist/points-lines/__tests__/cache-recovery.unit.test.d.ts.map +1 -0
  490. package/dist/points-lines/__tests__/inspection-lanes.integration.test.d.ts +2 -0
  491. package/dist/points-lines/__tests__/inspection-lanes.integration.test.d.ts.map +1 -0
  492. package/dist/points-lines/__tests__/inspection.unit.test.d.ts +2 -0
  493. package/dist/points-lines/__tests__/inspection.unit.test.d.ts.map +1 -0
  494. package/dist/points-lines/__tests__/lane-structural.integration.test.d.ts +2 -0
  495. package/dist/points-lines/__tests__/lane-structural.integration.test.d.ts.map +1 -0
  496. package/dist/points-lines/__tests__/points-lines.bench.d.ts +2 -0
  497. package/dist/points-lines/__tests__/points-lines.bench.d.ts.map +1 -0
  498. package/dist/points-lines/__tests__/raster-lane.integration.test.d.ts +2 -0
  499. package/dist/points-lines/__tests__/raster-lane.integration.test.d.ts.map +1 -0
  500. package/dist/points-lines/__tests__/snapshot.unit.test.d.ts +2 -0
  501. package/dist/points-lines/__tests__/snapshot.unit.test.d.ts.map +1 -0
  502. package/dist/points-lines/__tests__/view-ubo.unit.test.d.ts +2 -0
  503. package/dist/points-lines/__tests__/view-ubo.unit.test.d.ts.map +1 -0
  504. package/dist/points-lines/admission.d.ts +36 -0
  505. package/dist/points-lines/admission.d.ts.map +1 -0
  506. package/dist/points-lines/bounds.d.ts +8 -0
  507. package/dist/points-lines/bounds.d.ts.map +1 -0
  508. package/dist/points-lines/expansion-cache.d.ts +28 -0
  509. package/dist/points-lines/expansion-cache.d.ts.map +1 -0
  510. package/dist/points-lines/inspection.d.ts +53 -0
  511. package/dist/points-lines/inspection.d.ts.map +1 -0
  512. package/dist/points-lines/prepare.d.ts +67 -0
  513. package/dist/points-lines/prepare.d.ts.map +1 -0
  514. package/dist/points-lines/record.d.ts +60 -0
  515. package/dist/points-lines/record.d.ts.map +1 -0
  516. package/dist/points-lines/snapshot.d.ts +49 -0
  517. package/dist/points-lines/snapshot.d.ts.map +1 -0
  518. package/dist/post-process-errors.d.ts +182 -0
  519. package/dist/post-process-errors.d.ts.map +1 -0
  520. package/dist/prepare/prepared-graphics-resolver.d.ts +59 -0
  521. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -0
  522. package/dist/record/__tests__/material-bg-cache.unit.test.d.ts +2 -0
  523. package/dist/record/__tests__/material-bg-cache.unit.test.d.ts.map +1 -0
  524. package/dist/record/__tests__/material-slot-plan.unit.test.d.ts +2 -0
  525. package/dist/record/__tests__/material-slot-plan.unit.test.d.ts.map +1 -0
  526. package/dist/record/__tests__/typed-frame-graph-plan.unit.test.d.ts +2 -0
  527. package/dist/record/__tests__/typed-frame-graph-plan.unit.test.d.ts.map +1 -0
  528. package/dist/record/__tests__/video-texture-view.unit.test.d.ts +2 -0
  529. package/dist/record/__tests__/video-texture-view.unit.test.d.ts.map +1 -0
  530. package/dist/record/frame-lighting.d.ts +121 -0
  531. package/dist/record/frame-lighting.d.ts.map +1 -0
  532. package/dist/record/frame-snapshot.d.ts +429 -0
  533. package/dist/record/frame-snapshot.d.ts.map +1 -0
  534. package/dist/record/frame-targets.d.ts +20 -0
  535. package/dist/record/frame-targets.d.ts.map +1 -0
  536. package/dist/record/frame.d.ts +71 -0
  537. package/dist/record/frame.d.ts.map +1 -0
  538. package/dist/record/helpers.d.ts +102 -0
  539. package/dist/record/helpers.d.ts.map +1 -0
  540. package/dist/record/main-pass-geometry.d.ts +28 -0
  541. package/dist/record/main-pass-geometry.d.ts.map +1 -0
  542. package/dist/record/main-pass-material.d.ts +204 -0
  543. package/dist/record/main-pass-material.d.ts.map +1 -0
  544. package/dist/record/main-pass-sprite-draws.d.ts +43 -0
  545. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -0
  546. package/dist/record/main-pass.d.ts +20 -0
  547. package/dist/record/main-pass.d.ts.map +1 -0
  548. package/dist/record/mesh-ssbo.d.ts +446 -0
  549. package/dist/record/mesh-ssbo.d.ts.map +1 -0
  550. package/dist/record/render-context.d.ts +252 -0
  551. package/dist/record/render-context.d.ts.map +1 -0
  552. package/dist/record/shadow-pass.d.ts +52 -0
  553. package/dist/record/shadow-pass.d.ts.map +1 -0
  554. package/dist/record/skybox-post-pass.d.ts +33 -0
  555. package/dist/record/skybox-post-pass.d.ts.map +1 -0
  556. package/dist/record/typed-frame-graph.d.ts +35 -0
  557. package/dist/record/typed-frame-graph.d.ts.map +1 -0
  558. package/dist/record/view-ubo.d.ts +45 -0
  559. package/dist/record/view-ubo.d.ts.map +1 -0
  560. package/dist/render-contract.d.ts +424 -0
  561. package/dist/render-contract.d.ts.map +1 -0
  562. package/dist/render-data.d.ts +143 -0
  563. package/dist/render-data.d.ts.map +1 -0
  564. package/dist/render-graph-primitives.d.ts +76 -0
  565. package/dist/render-graph-primitives.d.ts.map +1 -0
  566. package/dist/render-pipeline.d.ts +110 -0
  567. package/dist/render-pipeline.d.ts.map +1 -0
  568. package/dist/render-system-extract.d.ts +868 -0
  569. package/dist/render-system-extract.d.ts.map +1 -0
  570. package/dist/render-system.d.ts +125 -0
  571. package/dist/render-system.d.ts.map +1 -0
  572. package/dist/scene/render-scene-types.d.ts +61 -0
  573. package/dist/scene/render-scene-types.d.ts.map +1 -0
  574. package/dist/scene/render-scene.d.ts +112 -0
  575. package/dist/scene/render-scene.d.ts.map +1 -0
  576. package/dist/scene-instances/post-spawn-resolve-joints.d.ts +30 -0
  577. package/dist/scene-instances/post-spawn-resolve-joints.d.ts.map +1 -0
  578. package/dist/shadow-atlas.d.ts +117 -0
  579. package/dist/shadow-atlas.d.ts.map +1 -0
  580. package/dist/ssao-buffers.d.ts +50 -0
  581. package/dist/ssao-buffers.d.ts.map +1 -0
  582. package/dist/ssao-config.d.ts +28 -0
  583. package/dist/ssao-config.d.ts.map +1 -0
  584. package/dist/systems/active-camera.d.ts +53 -0
  585. package/dist/systems/active-camera.d.ts.map +1 -0
  586. package/dist/systems/pass-selector.d.ts +24 -0
  587. package/dist/systems/pass-selector.d.ts.map +1 -0
  588. package/dist/systems/skin-palette-allocator.d.ts +49 -0
  589. package/dist/systems/skin-palette-allocator.d.ts.map +1 -0
  590. package/dist/systems/skin-palette-types.d.ts +14 -0
  591. package/dist/systems/skin-palette-types.d.ts.map +1 -0
  592. package/dist/systems/transparent-sort-config.d.ts +112 -0
  593. package/dist/systems/transparent-sort-config.d.ts.map +1 -0
  594. package/dist/tilemap-chunk-extract-system.d.ts +143 -0
  595. package/dist/tilemap-chunk-extract-system.d.ts.map +1 -0
  596. package/dist/typed-render-graph-primitives.d.ts +57 -0
  597. package/dist/typed-render-graph-primitives.d.ts.map +1 -0
  598. package/dist/typed-shadow-passes.d.ts +11 -0
  599. package/dist/typed-shadow-passes.d.ts.map +1 -0
  600. package/package.json +94 -0
  601. package/src/__tests__/authoring-path.unit.test.ts +23 -0
  602. package/src/__tests__/backend-selection-rhi-capture.test-d.ts +21 -0
  603. package/src/__tests__/callback-inference.test-d.ts +8 -0
  604. package/src/__tests__/cluster-binner.test.ts +272 -0
  605. package/src/__tests__/cluster-grid-default-surface.unit.test.ts +20 -0
  606. package/src/__tests__/construct-renderer-identity.unit.test.ts +23 -0
  607. package/src/__tests__/device-scope-lifecycle.unit.test.ts +151 -0
  608. package/src/__tests__/device-scope-stale-matrix.unit.test.ts +42 -0
  609. package/src/__tests__/direct-extract-consumer-contract.test-d.ts +23 -0
  610. package/src/__tests__/direct-light-snapshot.unit.test.ts +61 -0
  611. package/src/__tests__/factory-contract.integration.test.ts +280 -0
  612. package/src/__tests__/fallback-row-stride-surface.unit.test.ts +15 -0
  613. package/src/__tests__/frame-observation.contract.test.ts +112 -0
  614. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +32 -0
  615. package/src/__tests__/glyph-text-layout-recovery.unit.test.ts +167 -0
  616. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +350 -0
  617. package/src/__tests__/gpu-driven-indirect-raster.browser.test.ts +12 -0
  618. package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +16 -0
  619. package/src/__tests__/gpu-driven-production.integration.test.ts +436 -0
  620. package/src/__tests__/gpu-driven-scaling.unit.test.ts +87 -0
  621. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +271 -0
  622. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +290 -0
  623. package/src/__tests__/gpu-driven-view-reference.ts +111 -0
  624. package/src/__tests__/gpu-driven-view.browser.test.ts +30 -0
  625. package/src/__tests__/gpu-driven-view.dawn.test.ts +28 -0
  626. package/src/__tests__/gpu-driven-view.unit.test.ts +199 -0
  627. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +59 -0
  628. package/src/__tests__/gpu-scene-render-graph-gpu.ts +308 -0
  629. package/src/__tests__/gpu-scene-render-graph.browser.test.ts +19 -0
  630. package/src/__tests__/gpu-scene-render-graph.dawn.test.ts +19 -0
  631. package/src/__tests__/gpu-scene-schema.unit.test.ts +16 -0
  632. package/src/__tests__/gpu-scene.dawn.test.ts +205 -0
  633. package/src/__tests__/gpu-scene.unit.test.ts +147 -0
  634. package/src/__tests__/ibl/face-uniforms.unit.test.ts +46 -0
  635. package/src/__tests__/infinite-grid-no-vertex-probe.unit.test.ts +92 -0
  636. package/src/__tests__/injection-kind-owner.test-d.ts +14 -0
  637. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +728 -0
  638. package/src/__tests__/light-buffer-layout.unit.test.ts +40 -0
  639. package/src/__tests__/material-contract-inventory.unit.test.ts +24 -0
  640. package/src/__tests__/material-cooked-projection.unit.test.ts +150 -0
  641. package/src/__tests__/material-snapshot-mutation.integration.test.ts +53 -0
  642. package/src/__tests__/material-static-dynamic-route.unit.test.ts +94 -0
  643. package/src/__tests__/material-stride-surface.unit.test.ts +32 -0
  644. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +106 -0
  645. package/src/__tests__/mesh-material-bindings.unit.test.ts +89 -0
  646. package/src/__tests__/mesh-stride-surface.unit.test.ts +16 -0
  647. package/src/__tests__/morph-culling-reentry.dawn.test.ts +157 -0
  648. package/src/__tests__/morph-feature-gpu-work.integration.test.ts +80 -0
  649. package/src/__tests__/morph-feature-plan.unit.test.ts +53 -0
  650. package/src/__tests__/morph-visual-evidence.integration.test.ts +80 -0
  651. package/src/__tests__/nineslice-handle-surface.unit.test.ts +19 -0
  652. package/src/__tests__/post-process-error-policy-owner.unit.test.ts +201 -0
  653. package/src/__tests__/prepared-buffer-kind-owner.test-d.ts +29 -0
  654. package/src/__tests__/prepared-graphics-capability.unit.test.ts +65 -0
  655. package/src/__tests__/prepared-graphics-generation.unit.test.ts +161 -0
  656. package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +138 -0
  657. package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +29 -0
  658. package/src/__tests__/prepared-graphics-resolver.unit.test.ts +285 -0
  659. package/src/__tests__/prepared-graphics-snapshot.unit.test.ts +105 -0
  660. package/src/__tests__/prepared-graphics-store.unit.test.ts +154 -0
  661. package/src/__tests__/prepared-graphics-validation.unit.test.ts +176 -0
  662. package/src/__tests__/profiler-default-off.test.ts +22 -0
  663. package/src/__tests__/profiler-phase-catalog.test.ts +66 -0
  664. package/src/__tests__/profiler-phase-integration.test.ts +62 -0
  665. package/src/__tests__/profiler-phase-token.test.ts +79 -0
  666. package/src/__tests__/public-surface.test-d.ts +94 -0
  667. package/src/__tests__/recover-error-policy-owner.unit.test.ts +107 -0
  668. package/src/__tests__/render-error-code-owner.test-d.ts +116 -0
  669. package/src/__tests__/render-error-detail-ssot.test-d.ts +139 -0
  670. package/src/__tests__/render-error-exhaustive.test-d.ts +110 -0
  671. package/src/__tests__/render-feature-assembly.test-d.ts +43 -0
  672. package/src/__tests__/render-feature-context.test-d.ts +57 -0
  673. package/src/__tests__/render-feature-contract.test-d.ts +49 -0
  674. package/src/__tests__/render-feature-diagnostics.unit.test.ts +149 -0
  675. package/src/__tests__/render-feature-docs.unit.test.ts +89 -0
  676. package/src/__tests__/render-feature-errors.unit.test.ts +47 -0
  677. package/src/__tests__/render-feature-gpu-work.integration.test.ts +316 -0
  678. package/src/__tests__/render-feature-plan.test-d.ts +161 -0
  679. package/src/__tests__/render-feature-plan.unit.test.ts +170 -0
  680. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +90 -0
  681. package/src/__tests__/render-feature-prepared-errors.test-d.ts +79 -0
  682. package/src/__tests__/render-feature-prepared-graphics-docs.unit.test.ts +80 -0
  683. package/src/__tests__/render-feature-prepared-graphics-isolation.unit.test.ts +72 -0
  684. package/src/__tests__/render-feature-prepared-graphics-negative.test-d.ts +36 -0
  685. package/src/__tests__/render-feature-prepared-graphics.test-d.ts +74 -0
  686. package/src/__tests__/render-feature-prepared-graphics.unit.test.ts +121 -0
  687. package/src/__tests__/render-feature-public-surface.test-d.ts +57 -0
  688. package/src/__tests__/render-feature-retry.unit.test.ts +87 -0
  689. package/src/__tests__/render-feature-scheduling.unit.test.ts +110 -0
  690. package/src/__tests__/render-feature-stage-failed-policy-owner.unit.test.ts +137 -0
  691. package/src/__tests__/render-feature-stage-fault-recovery.unit.test.ts +146 -0
  692. package/src/__tests__/render-feature-visibility-context.test-d.ts +33 -0
  693. package/src/__tests__/render-feature-visibility-context.unit.test.ts +37 -0
  694. package/src/__tests__/render-feature-zero-work.unit.test.ts +76 -0
  695. package/src/__tests__/render-graph-compute-raster-gpu.ts +342 -0
  696. package/src/__tests__/render-graph-compute-raster.browser.test.ts +16 -0
  697. package/src/__tests__/render-graph-compute-raster.dawn.test.ts +22 -0
  698. package/src/__tests__/render-graph-hzb-gpu.ts +239 -0
  699. package/src/__tests__/render-graph-hzb.browser.test.ts +16 -0
  700. package/src/__tests__/render-graph-hzb.dawn.test.ts +23 -0
  701. package/src/__tests__/render-graph-primitives.unit.test.ts +22 -0
  702. package/src/__tests__/render-graph-storage-indirect-gpu.ts +162 -0
  703. package/src/__tests__/render-graph-storage-indirect.browser.test.ts +21 -0
  704. package/src/__tests__/render-graph-storage-indirect.dawn.test.ts +28 -0
  705. package/src/__tests__/render-scene-projection.unit.test.ts +168 -0
  706. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +121 -0
  707. package/src/__tests__/renderer-lifecycle.integration.test.ts +58 -0
  708. package/src/__tests__/rhi-backend-package-boundary.unit.test.ts +11 -0
  709. package/src/__tests__/scriptable-pack-consumer.test-d.ts +14 -0
  710. package/src/__tests__/shader-stage-surface.unit.test.ts +43 -0
  711. package/src/__tests__/ssao-config.unit.test.ts +36 -0
  712. package/src/__tests__/ssao-kernel-surface.unit.test.ts +14 -0
  713. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +28 -0
  714. package/src/__tests__/standard-descriptors.test-d.ts +22 -0
  715. package/src/__tests__/standard-pipeline.dawn.test.ts +61 -0
  716. package/src/__tests__/standard-pipeline.integration.test.ts +124 -0
  717. package/src/__tests__/standard-profile-oracle.unit.test.ts +62 -0
  718. package/src/__tests__/surface-configuration.unit.test.ts +91 -0
  719. package/src/__tests__/texture-usage-surface.unit.test.ts +58 -0
  720. package/src/__tests__/typed-pipeline-topology.unit.test.ts +223 -0
  721. package/src/__tests__/urp-pipeline-targets.unit.test.ts +42 -0
  722. package/src/__tests__/urp-pipeline.unit.test.ts +14 -0
  723. package/src/__tests__/vertex-color-pipeline.unit.test.ts +132 -0
  724. package/src/__tests__/vertex-layout-consumer.unit.test.ts +25 -0
  725. package/src/__tests__/visibility-diagnostics.integration.test.ts +62 -0
  726. package/src/__tests__/visibility-extract.integration.test.ts +98 -0
  727. package/src/__tests__/visibility-extract.perf.test.ts +130 -0
  728. package/src/__tests__/visibility-feature-dedup.integration.test.ts +55 -0
  729. package/src/__tests__/visibility-hidden-report.unit.test.ts +36 -0
  730. package/src/__tests__/visibility-instances.integration.test.ts +46 -0
  731. package/src/__tests__/visibility-multi-world.integration.test.ts +86 -0
  732. package/src/__tests__/visibility-producer-matrix.integration.test.ts +168 -0
  733. package/src/__tests__/visibility-producer-matrix.unit.test.ts +96 -0
  734. package/src/__tests__/visibility-public-surface.test-d.ts +27 -0
  735. package/src/__tests__/visibility-resolver.unit.test.ts +85 -0
  736. package/src/__tests__/visibility-resource-short-circuit.unit.test.ts +80 -0
  737. package/src/__tests__/visibility-snapshot-contract.unit.test.ts +60 -0
  738. package/src/__tests__/vocabulary.unit.test.ts +21 -0
  739. package/src/assembly/backend-contract.ts +57 -0
  740. package/src/assembly/factory.ts +8130 -0
  741. package/src/assembly/host-contract.ts +101 -0
  742. package/src/assembly/material/assembly.ts +48 -0
  743. package/src/assembly/material/pipeline-projection.ts +63 -0
  744. package/src/assets/asset-decoders.ts +158 -0
  745. package/src/assets/render-asset-port.ts +44 -0
  746. package/src/assets/resolve-render-asset.ts +13 -0
  747. package/src/authoring.ts +17 -0
  748. package/src/cluster-binner.ts +700 -0
  749. package/src/components/__tests__/points-lines-admission.unit.test.ts +219 -0
  750. package/src/components/__tests__/points-lines-schema.unit.test.ts +56 -0
  751. package/src/components/__tests__/schema-contract.unit.test.ts +10 -0
  752. package/src/components/__tests__/schema-parity.unit.test.ts +25 -0
  753. package/src/components/__tests__/visibility-schema.unit.test.ts +35 -0
  754. package/src/components/camera.ts +512 -0
  755. package/src/components/directional-light.ts +120 -0
  756. package/src/components/glyph-text.ts +64 -0
  757. package/src/components/index.ts +54 -0
  758. package/src/components/instances.ts +206 -0
  759. package/src/components/layer.ts +69 -0
  760. package/src/components/light-helpers.ts +188 -0
  761. package/src/components/lines.ts +18 -0
  762. package/src/components/mesh-filter.ts +60 -0
  763. package/src/components/mesh-renderer.ts +61 -0
  764. package/src/components/point-light-shadow.ts +43 -0
  765. package/src/components/point-light.ts +65 -0
  766. package/src/components/points.ts +40 -0
  767. package/src/components/post-process-params.ts +35 -0
  768. package/src/components/scene-instance.ts +193 -0
  769. package/src/components/skybox-background.ts +103 -0
  770. package/src/components/skylight.ts +97 -0
  771. package/src/components/sort-key.ts +75 -0
  772. package/src/components/spot-light.ts +124 -0
  773. package/src/components/sprite-animation.ts +168 -0
  774. package/src/components/sprite-instances.ts +179 -0
  775. package/src/components/sprite-playback-mode.ts +79 -0
  776. package/src/components/sprite-region-override.ts +105 -0
  777. package/src/components/tile-layer.ts +167 -0
  778. package/src/components/tilemap.ts +48 -0
  779. package/src/components/visibility.ts +53 -0
  780. package/src/construct-renderer.ts +67 -0
  781. package/src/debug-draw-glue.ts +48 -0
  782. package/src/device/device-scope.ts +306 -0
  783. package/src/device/gpu-residency.ts +1822 -0
  784. package/src/device/resource-types.ts +20 -0
  785. package/src/engine-metrics.ts +82 -0
  786. package/src/errors/ecs-validation.ts +16 -0
  787. package/src/errors/index.ts +3 -0
  788. package/src/errors/recover.ts +161 -0
  789. package/src/errors/render.ts +1284 -0
  790. package/src/extract/visibility.ts +120 -0
  791. package/src/features/fullscreen.ts +46 -0
  792. package/src/features/host.ts +1363 -0
  793. package/src/features/morph/morph-feature.ts +377 -0
  794. package/src/features/plan.ts +447 -0
  795. package/src/features/prepared-gpu-work.ts +959 -0
  796. package/src/features/prepared-graphics-store.ts +449 -0
  797. package/src/features/prepared-graphics.ts +420 -0
  798. package/src/features/render-graph-compute.ts +69 -0
  799. package/src/features/render-graph-contribution.ts +75 -0
  800. package/src/features/render-graph-raster.ts +332 -0
  801. package/src/features/render-graph-resources.ts +38 -0
  802. package/src/features/targets.ts +70 -0
  803. package/src/features/types.ts +103 -0
  804. package/src/features/vocabulary.ts +24 -0
  805. package/src/fullscreen-post-process-pass.ts +363 -0
  806. package/src/glyph-text-layout-system.ts +421 -0
  807. package/src/gpu-driven/batch-topology.ts +245 -0
  808. package/src/gpu-driven/production-raster.ts +695 -0
  809. package/src/gpu-driven/view-gpu.ts +703 -0
  810. package/src/gpu-resource.ts +159 -0
  811. package/src/gpu-scene-schema.ts +136 -0
  812. package/src/gpu-scene.ts +722 -0
  813. package/src/gpu-stage.ts +9 -0
  814. package/src/gpu-texture-usage.ts +12 -0
  815. package/src/gpu-usage.ts +14 -0
  816. package/src/hdrp-buffers.ts +480 -0
  817. package/src/ibl/IblPipelineCache.ts +1006 -0
  818. package/src/ibl/skylight-bind-group.ts +513 -0
  819. package/src/index.ts +129 -0
  820. package/src/inspection-types.ts +80 -0
  821. package/src/instance-buffer-cache.ts +95 -0
  822. package/src/internal.ts +9 -0
  823. package/src/lifecycle.ts +168 -0
  824. package/src/light-buffer-layout.ts +346 -0
  825. package/src/materials.ts +214 -0
  826. package/src/mesh-material-bindings.ts +103 -0
  827. package/src/pbr-pipeline.ts +1137 -0
  828. package/src/pipeline/standard-forward-lane.ts +229 -0
  829. package/src/pipeline/standard-pipeline.ts +555 -0
  830. package/src/pipeline/standard-profile.ts +65 -0
  831. package/src/pipeline-builder.ts +382 -0
  832. package/src/pipeline-spec-types.ts +28 -0
  833. package/src/pipeline-spec.ts +1231 -0
  834. package/src/plugin.ts +69 -0
  835. package/src/points-lines/__tests__/bounds.unit.test.ts +21 -0
  836. package/src/points-lines/__tests__/cache-recovery.unit.test.ts +157 -0
  837. package/src/points-lines/__tests__/inspection-lanes.integration.test.ts +146 -0
  838. package/src/points-lines/__tests__/inspection.unit.test.ts +173 -0
  839. package/src/points-lines/__tests__/lane-structural.integration.test.ts +122 -0
  840. package/src/points-lines/__tests__/points-lines.bench.ts +400 -0
  841. package/src/points-lines/__tests__/raster-lane.integration.test.ts +44 -0
  842. package/src/points-lines/__tests__/snapshot.unit.test.ts +101 -0
  843. package/src/points-lines/__tests__/view-ubo.unit.test.ts +73 -0
  844. package/src/points-lines/admission.ts +238 -0
  845. package/src/points-lines/bounds.ts +23 -0
  846. package/src/points-lines/expansion-cache.ts +215 -0
  847. package/src/points-lines/inspection.ts +97 -0
  848. package/src/points-lines/prepare.ts +177 -0
  849. package/src/points-lines/record.ts +125 -0
  850. package/src/points-lines/snapshot.ts +130 -0
  851. package/src/post-process-errors.ts +302 -0
  852. package/src/prepare/prepared-graphics-resolver.ts +456 -0
  853. package/src/record/__tests__/material-bg-cache.unit.test.ts +41 -0
  854. package/src/record/__tests__/material-slot-plan.unit.test.ts +44 -0
  855. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +41 -0
  856. package/src/record/__tests__/video-texture-view.unit.test.ts +90 -0
  857. package/src/record/frame-lighting.ts +1074 -0
  858. package/src/record/frame-snapshot.ts +500 -0
  859. package/src/record/frame-targets.ts +137 -0
  860. package/src/record/frame.ts +1598 -0
  861. package/src/record/helpers.ts +284 -0
  862. package/src/record/main-pass-geometry.ts +1065 -0
  863. package/src/record/main-pass-material.ts +1043 -0
  864. package/src/record/main-pass-sprite-draws.ts +1137 -0
  865. package/src/record/main-pass.ts +610 -0
  866. package/src/record/mesh-ssbo.ts +885 -0
  867. package/src/record/render-context.ts +384 -0
  868. package/src/record/shadow-pass.ts +698 -0
  869. package/src/record/skybox-post-pass.ts +593 -0
  870. package/src/record/typed-frame-graph.ts +461 -0
  871. package/src/record/view-ubo.ts +222 -0
  872. package/src/render-contract.ts +582 -0
  873. package/src/render-data.ts +385 -0
  874. package/src/render-graph-primitives.ts +811 -0
  875. package/src/render-pipeline.ts +259 -0
  876. package/src/render-system-extract.ts +4585 -0
  877. package/src/render-system.ts +1933 -0
  878. package/src/scene/render-scene-types.ts +67 -0
  879. package/src/scene/render-scene.ts +1087 -0
  880. package/src/scene-instances/post-spawn-resolve-joints.ts +165 -0
  881. package/src/shadow-atlas.ts +244 -0
  882. package/src/ssao-buffers.ts +334 -0
  883. package/src/ssao-config.ts +61 -0
  884. package/src/systems/active-camera.ts +116 -0
  885. package/src/systems/pass-selector.ts +49 -0
  886. package/src/systems/skin-palette-allocator.ts +251 -0
  887. package/src/systems/skin-palette-types.ts +14 -0
  888. package/src/systems/transparent-sort-config.ts +233 -0
  889. package/src/tilemap-chunk-extract-system.ts +1290 -0
  890. package/src/typed-render-graph-primitives.ts +541 -0
  891. package/src/typed-shadow-passes.ts +165 -0
@@ -0,0 +1,1363 @@
1
+ import type { EntityHandle } from '@forgeax/engine-ecs';
2
+ import type { RhiCaps, TextureFormat } from '@forgeax/engine-rhi';
3
+ import { err, ok, type Result } from '@forgeax/engine-types';
4
+ import {
5
+ type RenderError,
6
+ RenderFeatureCapabilityMissingError,
7
+ RenderFeaturePreparationFailedError,
8
+ RenderFeatureRegistrationConflictError,
9
+ RenderFeatureStageFailedError,
10
+ } from '../errors/render';
11
+ import type { PostProcessShaderEntry } from '../fullscreen-post-process-pass';
12
+ import type {
13
+ PreparedGraphicsReference,
14
+ PreparedGraphicsResolvedSnapshot,
15
+ PreparedGraphicsResolver,
16
+ PreparedGraphicsResourceLease,
17
+ } from '../prepare/prepared-graphics-resolver';
18
+ import {
19
+ freezeRenderFeaturePlan,
20
+ type RenderFeatureLogicalTarget,
21
+ type RenderFeaturePassDeclaration,
22
+ type RenderFeaturePlan,
23
+ type RenderFeaturePlannedFrame,
24
+ type RenderFeatureResourceDeclaration,
25
+ renderFeaturePlanSignature,
26
+ } from './plan';
27
+ import type {
28
+ RenderFeatureGpuBindingsRef,
29
+ RenderFeatureGpuBufferRef,
30
+ RenderFeatureGpuComputePassDescriptor,
31
+ RenderFeatureGpuPrepareSession,
32
+ RenderFeatureGpuProgramRef,
33
+ RenderFeatureGpuWorkOwner,
34
+ } from './prepared-gpu-work';
35
+ import {
36
+ type RenderFeatureGraphicsPassDescriptor,
37
+ type RenderFeatureGraphicsPrepare,
38
+ type RenderFeaturePreparedGraphicsState,
39
+ type RenderFeaturePreparedRef,
40
+ validateRenderFeatureGraphicsPass,
41
+ } from './prepared-graphics';
42
+ import {
43
+ createPreparedGraphicsStore,
44
+ type PreparedGraphicsStore,
45
+ type PreparedGraphicsTransaction,
46
+ } from './prepared-graphics-store';
47
+ import type {
48
+ RenderFeature,
49
+ RenderFeatureCapabilityKey,
50
+ RenderFeatureCleanupFailure,
51
+ RenderFeatureDiagnostics,
52
+ RenderFeatureErrorDescriptor,
53
+ RenderFeatureExtractContext,
54
+ RenderFeatureHiddenEntityReport,
55
+ RenderFeatureRecoverInput,
56
+ RenderFeatureStatus,
57
+ RenderFeatureTargetHandle,
58
+ RenderFeatureWorldVisibilitySnapshot,
59
+ } from './types';
60
+
61
+ const planExecutionProjections = new WeakMap<
62
+ RenderFeaturePlannedFrame,
63
+ RenderFeaturePlanExecution
64
+ >();
65
+
66
+ export interface RenderFeaturePlanExecutionPass {
67
+ readonly featureIdentity: string;
68
+ readonly order: number;
69
+ readonly name: string;
70
+ readonly graphics?: RenderFeatureGraphicsPassDescriptor;
71
+ readonly graphicsState?: RenderFeaturePreparedGraphicsState;
72
+ readonly gpuCompute?: RenderFeatureGpuComputePassDescriptor;
73
+ readonly resolvedGraphics?: PreparedGraphicsResolvedSnapshot;
74
+ readonly resolvedGpuCompute?: import('./prepared-gpu-work').RenderFeatureResolvedGpuComputePass;
75
+ }
76
+
77
+ /** Host-owned device projection of one frozen plan; graph access is derived later. */
78
+ export interface RenderFeaturePlanExecution {
79
+ readonly featureIdentity: string;
80
+ readonly order: number;
81
+ readonly passes: readonly RenderFeaturePlanExecutionPass[];
82
+ }
83
+
84
+ /** @internal Typed-graph adapter for the host-owned projection of a validated plan. */
85
+ export function getRenderFeaturePlanExecutionProjection(
86
+ planned: RenderFeaturePlannedFrame,
87
+ ): RenderFeaturePlanExecution | undefined {
88
+ return planExecutionProjections.get(planned);
89
+ }
90
+
91
+ export interface RenderFeatureStageEvent {
92
+ readonly featureIdentity: string;
93
+ readonly order: number;
94
+ readonly stage: 'extract' | 'plan';
95
+ }
96
+
97
+ export interface RenderFeatureFrameInput {
98
+ readonly worlds: readonly import('@forgeax/engine-ecs').World[];
99
+ readonly owner: number;
100
+ readonly frameNumber: number;
101
+ readonly visibilitySnapshots?: readonly RenderFeatureWorldVisibilitySnapshot[];
102
+ readonly hiddenEntityReports?: readonly RenderFeatureHiddenEntityReport[];
103
+ /** Active-pipeline logical targets available to producer-owned features. */
104
+ readonly targets?: readonly RenderFeatureTargetHandle[];
105
+ readonly generation?: number;
106
+ readonly caps: Readonly<RhiCaps>;
107
+ readonly createPreparedGraphicsResolver?: (
108
+ input: RenderFeaturePreparedGraphicsResolverInput,
109
+ ) => PreparedGraphicsResolver;
110
+ /** Single renderer-owned GPU preparation owner for all feature sessions. */
111
+ readonly gpuWork?: RenderFeatureGpuWorkOwner;
112
+ }
113
+
114
+ export interface RenderFeaturePreparedGraphicsResolverInput {
115
+ readonly featureIdentity: string;
116
+ readonly order: number;
117
+ readonly generation: number;
118
+ readonly transaction: PreparedGraphicsTransaction;
119
+ readonly fullscreenEffects: ReadonlyMap<string, PostProcessShaderEntry>;
120
+ readonly lookup: (
121
+ reference: import('./prepared-graphics').RenderFeaturePreparedRef,
122
+ ) => import('./prepared-graphics-store').PreparedGraphicsItem | undefined;
123
+ }
124
+
125
+ export interface RenderFeatureFrameResult {
126
+ readonly stageEvents: readonly RenderFeatureStageEvent[];
127
+ readonly errors: readonly RenderError[];
128
+ readonly plans: readonly RenderFeaturePlannedFrame[];
129
+ readonly fullscreenEffects: ReadonlyMap<string, PostProcessShaderEntry>;
130
+ readonly preparedResourceBatches: readonly RenderFeaturePreparedResourceBatch[];
131
+ readonly hiddenEntityReports: readonly RenderFeatureHiddenEntityReport[];
132
+ }
133
+
134
+ export interface RenderFeatureHost {
135
+ readonly size: number;
136
+ readonly features: readonly RenderFeature<unknown>[];
137
+ readonly preparedGeneration: number;
138
+ /** Install a producer after renderer creation; same object identity is idempotent. */
139
+ install(feature: RenderFeature<unknown>): Result<void, RenderError>;
140
+ /** Remove one installed producer and release every resource it owns. */
141
+ uninstall(feature: RenderFeature<unknown>): Result<void, RenderError>;
142
+ advancePreparedGeneration(): number;
143
+ setStatus(
144
+ identity: string,
145
+ status: RenderFeatureStatus,
146
+ latestError?: RenderFeatureErrorDescriptor,
147
+ ): Result<void, RenderError>;
148
+ /** Record a failure from active-graph execution against its owning slot. */
149
+ recordError(identity: string, error: RenderError): RenderError;
150
+ beginPreparedFrame(identity: string, generation: number): PreparedGraphicsTransaction | undefined;
151
+ retainPreparedGraphics(
152
+ identity: string,
153
+ leases: readonly PreparedGraphicsResourceLease[],
154
+ ): Result<RenderFeaturePreparedResourceBatch, RenderError>;
155
+ /** Mark batches used by the just-recorded frame as protected by queue work. */
156
+ markPreparedGraphicsSubmitted(batches: readonly RenderFeaturePreparedResourceBatch[]): void;
157
+ /** Release completed batches, or all batches that were never submitted. */
158
+ retirePreparedGraphics(
159
+ batches?: readonly RenderFeaturePreparedResourceBatch[],
160
+ ): Result<void, RenderError>;
161
+ /** Release submitted batches when queue completion rejects and cannot prove completion. */
162
+ recoverPreparedGraphics(
163
+ batches: readonly RenderFeaturePreparedResourceBatch[],
164
+ ): Result<void, RenderError>;
165
+ recover(input: RenderFeatureRecoverInput): Result<void, RenderError>;
166
+ diagnostics(): readonly RenderFeatureDiagnostics[];
167
+ /** Subscribe to lifecycle projection changes; unchanged active frames are silent. */
168
+ subscribeDiagnostics(listener: () => void): () => void;
169
+ dispose(): Result<void, RenderError>;
170
+ }
171
+
172
+ export interface RenderFeaturePreparedResourceBatch {
173
+ release(): Result<void, RenderError>;
174
+ }
175
+
176
+ /**
177
+ * Resolve a submitted batch from queue completion without conflating promise
178
+ * rejection with retirement failures. Rejection is treated as lost completion
179
+ * evidence, so the host releases only batches still marked submitted.
180
+ */
181
+ export function settlePreparedGraphicsCompletion(
182
+ host: RenderFeatureHost,
183
+ batches: readonly RenderFeaturePreparedResourceBatch[],
184
+ completion: PromiseLike<unknown>,
185
+ onError: (error: unknown) => void,
186
+ ): void {
187
+ const run = (operation: () => Result<void, RenderError>): void => {
188
+ try {
189
+ const result = operation();
190
+ if (!result.ok) onError(result.error);
191
+ } catch (error) {
192
+ onError(error);
193
+ }
194
+ };
195
+
196
+ void completion.then(
197
+ () => run(() => host.retirePreparedGraphics(batches)),
198
+ () => run(() => host.recoverPreparedGraphics(batches)),
199
+ );
200
+ }
201
+
202
+ interface FeatureSlot {
203
+ readonly feature: RenderFeature<unknown>;
204
+ order: number;
205
+ readonly preparedResourceBatches: Set<RenderFeaturePreparedResourceBatch>;
206
+ readonly preparedStore: PreparedGraphicsStore;
207
+ status: RenderFeatureStatus;
208
+ latestError: RenderFeatureErrorDescriptor | undefined;
209
+ }
210
+
211
+ function freezeError(error: RenderFeatureErrorDescriptor): RenderFeatureErrorDescriptor {
212
+ const detail = { ...error.detail } as RenderFeatureErrorDescriptor['detail'];
213
+ if ('cleanupFailures' in detail && detail.cleanupFailures !== undefined) {
214
+ (detail as { cleanupFailures: readonly RenderFeatureCleanupFailure[] }).cleanupFailures =
215
+ Object.freeze([...detail.cleanupFailures]);
216
+ }
217
+ return Object.freeze({
218
+ code: error.code,
219
+ expected: error.expected,
220
+ hint: error.hint,
221
+ detail: Object.freeze(detail),
222
+ }) as RenderFeatureErrorDescriptor;
223
+ }
224
+
225
+ function freezeDiagnostics(slot: FeatureSlot): RenderFeatureDiagnostics {
226
+ return Object.freeze({
227
+ identity: slot.feature.identity,
228
+ order: slot.order,
229
+ status: slot.status,
230
+ latestError: slot.latestError === undefined ? undefined : freezeError(slot.latestError),
231
+ });
232
+ }
233
+
234
+ function findSlot(slots: readonly FeatureSlot[], identity: string): FeatureSlot | undefined {
235
+ return slots.find((slot) => slot.feature.identity === identity);
236
+ }
237
+
238
+ function registrationConflict(
239
+ featureIdentity: string,
240
+ order: number,
241
+ conflictingOrder: number,
242
+ ): RenderFeatureRegistrationConflictError {
243
+ return new RenderFeatureRegistrationConflictError(featureIdentity, order, conflictingOrder);
244
+ }
245
+
246
+ function unknownFeatureError(
247
+ identity: string,
248
+ stage: 'recover' | 'dispose',
249
+ ): RenderFeatureStageFailedError {
250
+ return new RenderFeatureStageFailedError(identity, -1, stage, 'registration');
251
+ }
252
+
253
+ function missingCapability(
254
+ feature: RenderFeature<unknown>,
255
+ caps: Readonly<RhiCaps>,
256
+ ): RenderFeatureCapabilityKey | undefined {
257
+ return feature.requiredCapabilities?.find((capability) => caps[capability] !== true);
258
+ }
259
+
260
+ function createPreparedGraphicsPrepare(
261
+ transaction: PreparedGraphicsTransaction,
262
+ ): RenderFeatureGraphicsPrepare {
263
+ return {
264
+ preparePipeline: (name, descriptor) => transaction.prepare('pipeline', name, descriptor),
265
+ prepareBindings: (name, descriptor) => transaction.prepare('bindings', name, descriptor),
266
+ prepareVertexData: (name, descriptor) => transaction.prepare('vertex-data', name, descriptor),
267
+ prepareIndexData: (name, descriptor) => transaction.prepare('index-data', name, descriptor),
268
+ };
269
+ }
270
+
271
+ function preparedGraphicsReferences(
272
+ descriptor: import('./prepared-graphics').RenderFeatureGraphicsPassDescriptor,
273
+ ): readonly PreparedGraphicsReference[] {
274
+ return descriptor.draws.flatMap((draw) => [
275
+ draw.pipeline,
276
+ ...draw.bindings,
277
+ ...draw.vertexData.map((vertex) => vertex.resource),
278
+ ...(draw.indexData === undefined ? [] : [draw.indexData.resource]),
279
+ ]);
280
+ }
281
+
282
+ function resolveGraphicsSnapshot(
283
+ resolver: PreparedGraphicsResolver,
284
+ descriptor: import('./prepared-graphics').RenderFeatureGraphicsPassDescriptor,
285
+ generation: number,
286
+ ): Result<PreparedGraphicsResolvedSnapshot, RenderError> {
287
+ const resources = new Map<
288
+ object,
289
+ import('../prepare/prepared-graphics-resolver').PreparedGraphicsResolvedResource
290
+ >();
291
+ for (const reference of preparedGraphicsReferences(descriptor)) {
292
+ if (resources.has(reference)) continue;
293
+ const resolved = resolver.resolve(reference);
294
+ if (!resolved.ok) return resolved;
295
+ resources.set(reference, resolved.value);
296
+ }
297
+ return ok({
298
+ generation,
299
+ leases: resolver.leases,
300
+ resolve: (reference) => resources.get(reference),
301
+ ...(resolver.resolveGpuBuffer === undefined
302
+ ? {}
303
+ : { resolveGpuBuffer: resolver.resolveGpuBuffer }),
304
+ });
305
+ }
306
+
307
+ function graphicsValidator(
308
+ identity: string,
309
+ transaction: PreparedGraphicsTransaction,
310
+ capabilityAvailable: boolean,
311
+ ): (
312
+ descriptor: RenderFeatureGraphicsPassDescriptor,
313
+ resources: readonly { readonly name: string }[],
314
+ ) => Result<RenderFeaturePreparedGraphicsState, RenderError> {
315
+ return (descriptor, resources) => {
316
+ const attachments = [
317
+ ...descriptor.attachments.colors
318
+ .filter(
319
+ (attachment) =>
320
+ typeof attachment.resource !== 'string' ||
321
+ attachment.resource === 'swapchain' ||
322
+ resources.some((resource) => resource.name === `${identity}::${attachment.resource}`),
323
+ )
324
+ .map((attachment) => ({ resource: attachment.resource, format: attachment.format })),
325
+ ...(descriptor.attachments.depthStencil === undefined
326
+ ? []
327
+ : resources.some(
328
+ (resource) =>
329
+ resource.name === `${identity}::${descriptor.attachments.depthStencil?.resource}`,
330
+ ) || typeof descriptor.attachments.depthStencil.resource !== 'string'
331
+ ? [
332
+ {
333
+ resource: descriptor.attachments.depthStencil.resource,
334
+ format: descriptor.attachments.depthStencil.format,
335
+ },
336
+ ]
337
+ : []),
338
+ ];
339
+ const state = transaction.graphicsState(capabilityAvailable, attachments);
340
+ const validated = validateRenderFeatureGraphicsPass(identity, descriptor, state);
341
+ return validated.ok ? ok(state) : validated;
342
+ };
343
+ }
344
+
345
+ function asFeatureError(
346
+ error: unknown,
347
+ identity: string,
348
+ order: number,
349
+ stage: 'extract' | 'plan',
350
+ ): RenderError {
351
+ if (error instanceof Error && typeof (error as Partial<RenderError>).code === 'string') {
352
+ return error as RenderError;
353
+ }
354
+ return new RenderFeatureStageFailedError(identity, order, stage, 'next-frame');
355
+ }
356
+
357
+ function featureErrorForSlot(slot: FeatureSlot, error: RenderError): RenderError {
358
+ switch (error.code) {
359
+ case 'render-feature-registration-conflict':
360
+ case 'render-feature-stage-failed':
361
+ case 'render-feature-capability-missing':
362
+ case 'render-feature-pass-order-conflict':
363
+ case 'render-feature-preparation-failed':
364
+ case 'render-feature-prepared-state-mismatch':
365
+ case 'render-feature-draw-recording-failed':
366
+ return error.detail.featureIdentity === slot.feature.identity
367
+ ? error
368
+ : new RenderFeatureStageFailedError(
369
+ slot.feature.identity,
370
+ slot.order,
371
+ 'plan',
372
+ 'next-frame',
373
+ );
374
+ default:
375
+ return new RenderFeatureStageFailedError(
376
+ slot.feature.identity,
377
+ slot.order,
378
+ 'plan',
379
+ 'next-frame',
380
+ );
381
+ }
382
+ }
383
+
384
+ function errorDescriptor(error: RenderError): RenderFeatureErrorDescriptor {
385
+ switch (error.code) {
386
+ case 'render-feature-registration-conflict':
387
+ case 'render-feature-stage-failed':
388
+ case 'render-feature-capability-missing':
389
+ case 'render-feature-pass-order-conflict':
390
+ case 'render-feature-preparation-failed':
391
+ case 'render-feature-prepared-state-mismatch':
392
+ case 'render-feature-draw-recording-failed':
393
+ return {
394
+ code: error.code,
395
+ expected: error.expected,
396
+ hint: error.hint,
397
+ detail: { ...error.detail },
398
+ } as RenderFeatureErrorDescriptor;
399
+ default:
400
+ return {
401
+ code: 'render-feature-stage-failed',
402
+ expected: error.expected,
403
+ hint: error.hint,
404
+ detail: {
405
+ featureIdentity: 'unknown',
406
+ order: -1,
407
+ stage: 'plan',
408
+ recovery: 'next-frame',
409
+ },
410
+ };
411
+ }
412
+ }
413
+
414
+ function recordFailure(
415
+ slot: FeatureSlot,
416
+ stage: 'extract' | 'plan',
417
+ failure: unknown,
418
+ errors: RenderError[],
419
+ ): void {
420
+ const error = asFeatureError(failure, slot.feature.identity, slot.order, stage);
421
+ errors.push(error);
422
+ slot.status = 'failed';
423
+ slot.latestError = errorDescriptor(error);
424
+ }
425
+
426
+ function logicalTargets(
427
+ targets: readonly RenderFeatureTargetHandle[],
428
+ ): readonly RenderFeatureLogicalTarget[] {
429
+ return Object.freeze(
430
+ targets.map((target) => ({
431
+ name: target.kind === 'scene-color' ? 'color' : 'depth',
432
+ kind: target.kind === 'scene-color' ? ('color' as const) : ('depth' as const),
433
+ format: target.format,
434
+ sampleCount: target.sampleCount,
435
+ })),
436
+ );
437
+ }
438
+
439
+ interface PreparedPlanResources {
440
+ readonly computePrograms: ReadonlyMap<string, RenderFeatureGpuProgramRef>;
441
+ readonly graphicsPrograms: ReadonlyMap<string, RenderFeaturePreparedRef<'pipeline'>>;
442
+ readonly buffers: ReadonlyMap<string, RenderFeatureGpuBufferRef>;
443
+ readonly computeBindings: ReadonlyMap<string, RenderFeatureGpuBindingsRef>;
444
+ readonly graphicsBindings: ReadonlyMap<string, RenderFeaturePreparedRef<'bindings'>>;
445
+ readonly vertexData: ReadonlyMap<string, RenderFeaturePreparedRef<'vertex-data'>>;
446
+ readonly indexData: ReadonlyMap<string, RenderFeaturePreparedRef<'index-data'>>;
447
+ }
448
+
449
+ function planFailure(slot: FeatureSlot): RenderFeatureStageFailedError {
450
+ return new RenderFeatureStageFailedError(slot.feature.identity, slot.order, 'plan', 'next-frame');
451
+ }
452
+
453
+ function targetHandle(
454
+ name: string,
455
+ targets: readonly RenderFeatureTargetHandle[],
456
+ ): string | RenderFeatureTargetHandle | undefined {
457
+ if (name === 'swapchain') return 'swapchain';
458
+ return targets.find(
459
+ (target) =>
460
+ (name === 'color' && target.kind === 'scene-color') ||
461
+ (name === 'depth' && target.kind === 'scene-depth'),
462
+ );
463
+ }
464
+
465
+ function targetFormat(
466
+ name: string,
467
+ targets: readonly RenderFeatureLogicalTarget[],
468
+ fallback: string | undefined,
469
+ ): TextureFormat | undefined {
470
+ const target = targets.find((candidate) => candidate.name === name);
471
+ return (target?.format ?? fallback) as TextureFormat | undefined;
472
+ }
473
+
474
+ function preparePlanResources(
475
+ slot: FeatureSlot,
476
+ plan: RenderFeaturePlan,
477
+ graphics: RenderFeatureGraphicsPrepare,
478
+ gpu: RenderFeatureGpuPrepareSession | undefined,
479
+ targets: readonly RenderFeatureTargetHandle[],
480
+ ): Result<PreparedPlanResources, RenderError> {
481
+ const computePrograms = new Map<string, RenderFeatureGpuProgramRef>();
482
+ const graphicsPrograms = new Map<string, RenderFeaturePreparedRef<'pipeline'>>();
483
+ const buffers = new Map<string, RenderFeatureGpuBufferRef>();
484
+ const computeBindings = new Map<string, RenderFeatureGpuBindingsRef>();
485
+ const graphicsBindings = new Map<string, RenderFeaturePreparedRef<'bindings'>>();
486
+ const vertexData = new Map<string, RenderFeaturePreparedRef<'vertex-data'>>();
487
+ const indexData = new Map<string, RenderFeaturePreparedRef<'index-data'>>();
488
+ const byKind = <Kind extends RenderFeatureResourceDeclaration['kind']>(kind: Kind) =>
489
+ plan.resources.filter(
490
+ (resource): resource is Extract<RenderFeatureResourceDeclaration, { readonly kind: Kind }> =>
491
+ resource.kind === kind,
492
+ );
493
+
494
+ if (
495
+ gpu === undefined &&
496
+ plan.resources.some((resource) =>
497
+ ['compute-program', 'buffer', 'compute-bindings'].includes(resource.kind),
498
+ )
499
+ ) {
500
+ return err(planFailure(slot));
501
+ }
502
+ for (const resource of byKind('compute-program')) {
503
+ const prepared = gpu?.prepareProgram(resource.name, resource.program);
504
+ if (prepared === undefined) return err(planFailure(slot));
505
+ if (!prepared.ok) return prepared;
506
+ computePrograms.set(resource.name, prepared.value);
507
+ }
508
+ for (const resource of byKind('graphics-program')) {
509
+ const prepared = graphics.preparePipeline(resource.name, resource.program);
510
+ if (!prepared.ok) return prepared;
511
+ graphicsPrograms.set(resource.name, prepared.value);
512
+ }
513
+ for (const resource of byKind('buffer')) {
514
+ const prepared = gpu?.prepareBuffer(resource.name, {
515
+ size: resource.size,
516
+ usage: resource.usage,
517
+ ...(resource.data === undefined ? {} : { data: resource.data }),
518
+ });
519
+ if (prepared === undefined) return err(planFailure(slot));
520
+ if (!prepared.ok) return prepared;
521
+ buffers.set(resource.name, prepared.value);
522
+ }
523
+ for (const resource of byKind('compute-bindings')) {
524
+ const program = computePrograms.get(resource.program);
525
+ const entries = resource.entries.map((entry) => ({
526
+ binding: entry.binding,
527
+ buffer: buffers.get(entry.resource),
528
+ }));
529
+ if (program === undefined || entries.some((entry) => entry.buffer === undefined)) {
530
+ return err(planFailure(slot));
531
+ }
532
+ const prepared = gpu?.prepareBindings(resource.name, {
533
+ program,
534
+ entries: entries.map((entry) => ({
535
+ binding: entry.binding,
536
+ buffer: entry.buffer as RenderFeatureGpuBufferRef,
537
+ })),
538
+ });
539
+ if (prepared === undefined) return err(planFailure(slot));
540
+ if (!prepared.ok) return prepared;
541
+ computeBindings.set(resource.name, prepared.value);
542
+ }
543
+ for (const resource of byKind('graphics-bindings')) {
544
+ const program = graphicsPrograms.get(resource.program);
545
+ if (program === undefined) return err(planFailure(slot));
546
+ const values: Record<string, unknown> = { ...resource.values };
547
+ for (const [key, targetName] of Object.entries(resource.logicalTargets ?? {})) {
548
+ const target = targetHandle(targetName, targets);
549
+ if (target === undefined || typeof target === 'string') return err(planFailure(slot));
550
+ values[key] = target;
551
+ }
552
+ const prepared = graphics.prepareBindings(resource.name, { pipeline: program, values });
553
+ if (!prepared.ok) return prepared;
554
+ graphicsBindings.set(resource.name, prepared.value);
555
+ }
556
+ for (const resource of byKind('vertex-data')) {
557
+ const descriptor =
558
+ resource.buffer === undefined
559
+ ? { layout: resource.layout, data: resource.data }
560
+ : { layout: resource.layout, buffer: buffers.get(resource.buffer) };
561
+ if ('buffer' in descriptor && descriptor.buffer === undefined) return err(planFailure(slot));
562
+ const prepared = graphics.prepareVertexData(
563
+ resource.name,
564
+ descriptor as import('./prepared-graphics').RenderFeatureVertexDataDescriptor,
565
+ );
566
+ if (!prepared.ok) return prepared;
567
+ vertexData.set(resource.name, prepared.value);
568
+ }
569
+ for (const resource of byKind('index-data')) {
570
+ const descriptor =
571
+ resource.buffer === undefined
572
+ ? { format: resource.format, data: resource.data }
573
+ : { format: resource.format, buffer: buffers.get(resource.buffer) };
574
+ if ('buffer' in descriptor && descriptor.buffer === undefined) return err(planFailure(slot));
575
+ const prepared = graphics.prepareIndexData(
576
+ resource.name,
577
+ descriptor as import('./prepared-graphics').RenderFeatureIndexDataDescriptor,
578
+ );
579
+ if (!prepared.ok) return prepared;
580
+ indexData.set(resource.name, prepared.value);
581
+ }
582
+ return ok({
583
+ computePrograms,
584
+ graphicsPrograms,
585
+ buffers,
586
+ computeBindings,
587
+ graphicsBindings,
588
+ vertexData,
589
+ indexData,
590
+ });
591
+ }
592
+
593
+ function projectDraw(
594
+ slot: FeatureSlot,
595
+ draw: Extract<RenderFeaturePassDeclaration, { readonly kind: 'raster' }>['draws'][number],
596
+ prepared: PreparedPlanResources,
597
+ ): Result<import('./prepared-graphics').RenderFeatureDrawRecord, RenderError> {
598
+ const pipeline = prepared.graphicsPrograms.get(draw.program);
599
+ const bindings = draw.bindings.map((name) => prepared.graphicsBindings.get(name));
600
+ const vertexData = draw.vertexData.map((entry) => ({
601
+ slot: entry.slot,
602
+ resource: prepared.vertexData.get(entry.resource),
603
+ }));
604
+ const indexData =
605
+ draw.indexData === undefined
606
+ ? undefined
607
+ : {
608
+ resource: prepared.indexData.get(draw.indexData.resource),
609
+ format: draw.indexData.format,
610
+ };
611
+ if (
612
+ pipeline === undefined ||
613
+ bindings.some((binding) => binding === undefined) ||
614
+ vertexData.some((vertex) => vertex.resource === undefined) ||
615
+ (indexData !== undefined && indexData.resource === undefined)
616
+ ) {
617
+ return err(planFailure(slot));
618
+ }
619
+ const common = {
620
+ pipeline,
621
+ bindings: bindings as readonly RenderFeaturePreparedRef<'bindings'>[],
622
+ vertexData: vertexData as readonly {
623
+ readonly slot: number;
624
+ readonly resource: RenderFeaturePreparedRef<'vertex-data'>;
625
+ }[],
626
+ ...(draw.vertexLayout === undefined ? {} : { vertexLayout: draw.vertexLayout }),
627
+ };
628
+ switch (draw.draw.kind) {
629
+ case 'draw':
630
+ return ok({
631
+ kind: 'draw',
632
+ ...common,
633
+ ...(indexData === undefined
634
+ ? {}
635
+ : {
636
+ indexData: {
637
+ resource: indexData.resource as RenderFeaturePreparedRef<'index-data'>,
638
+ format: indexData.format,
639
+ },
640
+ }),
641
+ command: {
642
+ vertexCount: draw.draw.vertexCount,
643
+ instanceCount: draw.draw.instanceCount,
644
+ ...(draw.draw.firstVertex === undefined ? {} : { firstVertex: draw.draw.firstVertex }),
645
+ ...(draw.draw.firstInstance === undefined
646
+ ? {}
647
+ : { firstInstance: draw.draw.firstInstance }),
648
+ },
649
+ });
650
+ case 'draw-indexed':
651
+ return ok({
652
+ kind: 'draw-indexed',
653
+ ...common,
654
+ indexData:
655
+ indexData === undefined
656
+ ? undefined
657
+ : {
658
+ resource: indexData.resource as RenderFeaturePreparedRef<'index-data'>,
659
+ format: indexData.format,
660
+ },
661
+ command: {
662
+ indexCount: draw.draw.indexCount,
663
+ instanceCount: draw.draw.instanceCount,
664
+ ...(draw.draw.firstIndex === undefined ? {} : { firstIndex: draw.draw.firstIndex }),
665
+ ...(draw.draw.baseVertex === undefined ? {} : { baseVertex: draw.draw.baseVertex }),
666
+ ...(draw.draw.firstInstance === undefined
667
+ ? {}
668
+ : { firstInstance: draw.draw.firstInstance }),
669
+ },
670
+ });
671
+ case 'draw-indirect':
672
+ case 'draw-indexed-indirect': {
673
+ const buffer = prepared.buffers.get(draw.draw.resource);
674
+ if (buffer === undefined) return err(planFailure(slot));
675
+ const command = {
676
+ buffer,
677
+ ...(draw.draw.offset === undefined ? {} : { offset: draw.draw.offset }),
678
+ };
679
+ if (draw.draw.kind === 'draw-indexed-indirect') {
680
+ return ok({
681
+ kind: 'draw-indexed-indirect',
682
+ ...common,
683
+ indexData:
684
+ indexData === undefined
685
+ ? undefined
686
+ : {
687
+ resource: indexData.resource as RenderFeaturePreparedRef<'index-data'>,
688
+ format: indexData.format,
689
+ },
690
+ command,
691
+ });
692
+ }
693
+ return ok({
694
+ kind: 'draw-indirect',
695
+ ...common,
696
+ ...(indexData === undefined
697
+ ? {}
698
+ : {
699
+ indexData: {
700
+ resource: indexData.resource as RenderFeaturePreparedRef<'index-data'>,
701
+ format: indexData.format,
702
+ },
703
+ }),
704
+ command,
705
+ });
706
+ }
707
+ }
708
+ }
709
+
710
+ function projectPlanPasses(
711
+ slot: FeatureSlot,
712
+ plan: RenderFeaturePlan,
713
+ prepared: PreparedPlanResources,
714
+ gpu: RenderFeatureGpuPrepareSession | undefined,
715
+ targets: readonly RenderFeatureTargetHandle[],
716
+ validateGraphics: (
717
+ descriptor: RenderFeatureGraphicsPassDescriptor,
718
+ resources: readonly { readonly name: string }[],
719
+ ) => Result<RenderFeaturePreparedGraphicsState, RenderError>,
720
+ resolveGraphics?: (
721
+ descriptor: RenderFeatureGraphicsPassDescriptor,
722
+ ) => Result<PreparedGraphicsResolvedSnapshot, RenderError> | undefined,
723
+ ): Result<RenderFeaturePlanExecution, RenderError> {
724
+ const logical = logicalTargets(targets);
725
+ const projected: RenderFeaturePlanExecutionPass[] = [];
726
+ for (const pass of plan.passes) {
727
+ if (pass.kind === 'compute') {
728
+ const program = prepared.computePrograms.get(pass.program);
729
+ const bindings = prepared.computeBindings.get(pass.bindings);
730
+ if (program === undefined || bindings === undefined) return err(planFailure(slot));
731
+ const descriptor: RenderFeatureGpuComputePassDescriptor = {
732
+ program,
733
+ bindings,
734
+ dispatches: pass.dispatches.map((dispatch) =>
735
+ dispatch.kind === 'direct'
736
+ ? {
737
+ entryPoint: dispatch.entryPoint,
738
+ bindings,
739
+ workgroups: dispatch.workgroups,
740
+ }
741
+ : {
742
+ entryPoint: dispatch.entryPoint,
743
+ bindings,
744
+ indirect: {
745
+ buffer: prepared.buffers.get(dispatch.resource) as RenderFeatureGpuBufferRef,
746
+ offset: dispatch.offset,
747
+ },
748
+ },
749
+ ),
750
+ };
751
+ if (
752
+ descriptor.dispatches.some(
753
+ (dispatch) => dispatch.indirect !== undefined && dispatch.indirect.buffer === undefined,
754
+ )
755
+ ) {
756
+ return err(planFailure(slot));
757
+ }
758
+ const resolved = gpu?.resolveComputePass(slot.feature.identity, descriptor);
759
+ if (resolved === undefined) return err(planFailure(slot));
760
+ if (!resolved.ok) return resolved;
761
+ projected.push({
762
+ featureIdentity: slot.feature.identity,
763
+ order: slot.order,
764
+ name: pass.name,
765
+ gpuCompute: descriptor,
766
+ resolvedGpuCompute: resolved.value,
767
+ });
768
+ continue;
769
+ }
770
+
771
+ const draws: import('./prepared-graphics').RenderFeatureDrawRecord[] = [];
772
+ for (const draw of pass.draws) {
773
+ const projected = projectDraw(slot, draw, prepared);
774
+ if (!projected.ok) return projected;
775
+ draws.push(projected.value);
776
+ }
777
+ const fallbackFormat = (() => {
778
+ const firstProgram = prepared.graphicsPrograms.get(pass.draws[0]?.program ?? '');
779
+ const declaration = plan.resources.find(
780
+ (resource) =>
781
+ resource.kind === 'graphics-program' &&
782
+ prepared.graphicsPrograms.get(resource.name) === firstProgram,
783
+ );
784
+ return declaration?.kind === 'graphics-program'
785
+ ? declaration.program.colorFormats[0]
786
+ : undefined;
787
+ })();
788
+ const colors = pass.colorAttachments.map((attachment) => ({
789
+ resource: targetHandle(attachment.target, targets),
790
+ format: targetFormat(attachment.target, logical, fallbackFormat),
791
+ loadOp: attachment.loadOp,
792
+ storeOp: attachment.storeOp,
793
+ }));
794
+ const depth =
795
+ pass.depthStencilAttachment === undefined
796
+ ? undefined
797
+ : {
798
+ resource: targetHandle(pass.depthStencilAttachment.target, targets),
799
+ format: targetFormat(pass.depthStencilAttachment.target, logical, undefined),
800
+ depthLoadOp: pass.depthStencilAttachment.depthLoadOp,
801
+ depthStoreOp: pass.depthStencilAttachment.depthStoreOp,
802
+ };
803
+ const sampledTargets = (pass.sampledTargets ?? []).map((name) => targetHandle(name, targets));
804
+ if (
805
+ colors.some(
806
+ (attachment) => attachment.resource === undefined || attachment.format === undefined,
807
+ ) ||
808
+ (depth !== undefined && (depth.resource === undefined || depth.format === undefined)) ||
809
+ sampledTargets.some((target) => target === undefined || typeof target === 'string')
810
+ ) {
811
+ return err(planFailure(slot));
812
+ }
813
+ const attachments: RenderFeatureGraphicsPassDescriptor['attachments'] =
814
+ depth === undefined
815
+ ? { colors: colors as RenderFeatureGraphicsPassDescriptor['attachments']['colors'] }
816
+ : {
817
+ colors: colors as RenderFeatureGraphicsPassDescriptor['attachments']['colors'],
818
+ depthStencil: depth as NonNullable<
819
+ RenderFeatureGraphicsPassDescriptor['attachments']['depthStencil']
820
+ >,
821
+ };
822
+ const descriptor: RenderFeatureGraphicsPassDescriptor = {
823
+ attachments,
824
+ ...(sampledTargets.length === 0
825
+ ? {}
826
+ : {
827
+ sampledTargets: sampledTargets as readonly RenderFeatureTargetHandle[],
828
+ }),
829
+ draws,
830
+ };
831
+ const graphicsState = validateGraphics(descriptor, []);
832
+ if (!graphicsState.ok) return graphicsState;
833
+ const resolved = resolveGraphics?.(descriptor);
834
+ if (
835
+ resolved !== undefined &&
836
+ !resolved.ok &&
837
+ resolved.error instanceof RenderFeaturePreparationFailedError &&
838
+ resolved.error.detail.reason === 'pipeline-pending'
839
+ ) {
840
+ continue;
841
+ }
842
+ if (resolved !== undefined && !resolved.ok) return resolved;
843
+ projected.push({
844
+ featureIdentity: slot.feature.identity,
845
+ order: slot.order,
846
+ name: pass.name,
847
+ graphics: descriptor,
848
+ graphicsState: graphicsState.value,
849
+ ...(resolved?.ok === true ? { resolvedGraphics: resolved.value } : {}),
850
+ });
851
+ }
852
+ return ok({
853
+ featureIdentity: slot.feature.identity,
854
+ order: slot.order,
855
+ passes: Object.freeze(projected),
856
+ });
857
+ }
858
+
859
+ function invokeStage<T>(
860
+ slot: FeatureSlot,
861
+ stage: RenderFeatureStageEvent['stage'],
862
+ action: () => Result<T, RenderError>,
863
+ stageEvents: RenderFeatureStageEvent[],
864
+ errors: RenderError[],
865
+ ): Result<T, RenderError> {
866
+ const identity = slot.feature.identity;
867
+ stageEvents.push({ featureIdentity: identity, order: slot.order, stage });
868
+ try {
869
+ const result = action();
870
+ if (result.ok) return result;
871
+ recordFailure(slot, stage, result.error, errors);
872
+ return err(result.error);
873
+ } catch (failure) {
874
+ recordFailure(slot, stage, failure, errors);
875
+ return err(errors[errors.length - 1] as RenderError);
876
+ }
877
+ }
878
+
879
+ class FeatureHostImpl implements RenderFeatureHost {
880
+ private disposed = false;
881
+ private generation = 0;
882
+ private lastRecoveryFrame: number | undefined;
883
+ private readonly diagnosticsListeners = new Set<() => void>();
884
+ private readonly preparedBatchStates = new WeakMap<
885
+ RenderFeaturePreparedResourceBatch,
886
+ 'unsubmitted' | 'submitted'
887
+ >();
888
+
889
+ constructor(private readonly slots: FeatureSlot[]) {}
890
+
891
+ get size(): number {
892
+ return this.slots.length;
893
+ }
894
+
895
+ get preparedGeneration(): number {
896
+ return this.generation;
897
+ }
898
+
899
+ get features(): readonly RenderFeature<unknown>[] {
900
+ return this.slots.map((slot) => slot.feature);
901
+ }
902
+
903
+ private publishDiagnosticsChanged(): void {
904
+ for (const listener of this.diagnosticsListeners) {
905
+ try {
906
+ listener();
907
+ } catch {
908
+ // Diagnostics are a projection of renderer state. An observer failure
909
+ // must not alter an already-applied feature lifecycle transition.
910
+ }
911
+ }
912
+ }
913
+
914
+ install(feature: RenderFeature<unknown>): Result<void, RenderError> {
915
+ if (this.disposed) return err(unknownFeatureError(feature.identity, 'dispose'));
916
+ const existingOrder = this.slots.findIndex(
917
+ (slot) => slot.feature.identity === feature.identity,
918
+ );
919
+ if (existingOrder >= 0) {
920
+ const existing = this.slots[existingOrder];
921
+ if (existing?.feature === feature) return ok(undefined);
922
+ return err(registrationConflict(feature.identity, this.slots.length, existingOrder));
923
+ }
924
+ this.slots.push({
925
+ feature,
926
+ order: this.slots.length,
927
+ preparedResourceBatches: new Set(),
928
+ preparedStore: createPreparedGraphicsStore(),
929
+ status: 'active',
930
+ latestError: undefined,
931
+ });
932
+ this.publishDiagnosticsChanged();
933
+ return ok(undefined);
934
+ }
935
+
936
+ uninstall(feature: RenderFeature<unknown>): Result<void, RenderError> {
937
+ if (this.disposed) return err(unknownFeatureError(feature.identity, 'dispose'));
938
+ const index = this.slots.findIndex((slot) => slot.feature === feature);
939
+ if (index < 0) return ok(undefined);
940
+ const slot = this.slots[index];
941
+ if (slot === undefined) return ok(undefined);
942
+
943
+ let firstError: RenderError | undefined;
944
+ for (const batch of slot.preparedResourceBatches) {
945
+ const result = batch.release();
946
+ if (!result.ok && firstError === undefined) firstError = result.error;
947
+ }
948
+ slot.status = 'disposed';
949
+ this.slots.splice(index, 1);
950
+ for (const [order, remaining] of this.slots.entries()) remaining.order = order;
951
+ this.publishDiagnosticsChanged();
952
+ return firstError === undefined ? ok(undefined) : err(firstError);
953
+ }
954
+
955
+ advancePreparedGeneration(): number {
956
+ if (this.disposed) return this.generation;
957
+ this.generation += 1;
958
+ for (const slot of this.slots) {
959
+ slot.preparedStore.invalidate(slot.feature.identity, this.generation);
960
+ }
961
+ this.lastRecoveryFrame = undefined;
962
+ return this.generation;
963
+ }
964
+
965
+ setStatus(
966
+ identity: string,
967
+ status: RenderFeatureStatus,
968
+ latestError?: RenderFeatureErrorDescriptor,
969
+ ): Result<void, RenderError> {
970
+ const slot = findSlot(this.slots, identity);
971
+ if (slot === undefined || this.disposed || slot.status === 'disposed') {
972
+ return err(unknownFeatureError(identity, 'recover'));
973
+ }
974
+ if (slot.status === status && slot.latestError === undefined && latestError === undefined) {
975
+ return ok(undefined);
976
+ }
977
+ slot.status = status;
978
+ slot.latestError = latestError === undefined ? undefined : freezeError(latestError);
979
+ this.publishDiagnosticsChanged();
980
+ return ok(undefined);
981
+ }
982
+
983
+ recordError(identity: string, error: RenderError): RenderError {
984
+ const slot = findSlot(this.slots, identity);
985
+ if (slot === undefined || this.disposed || slot.status === 'disposed') return error;
986
+ const owned = featureErrorForSlot(slot, error);
987
+ slot.status = 'failed';
988
+ slot.latestError = errorDescriptor(owned);
989
+ this.publishDiagnosticsChanged();
990
+ return owned;
991
+ }
992
+
993
+ beginPreparedFrame(
994
+ identity: string,
995
+ generation: number,
996
+ ): PreparedGraphicsTransaction | undefined {
997
+ const slot = findSlot(this.slots, identity);
998
+ if (slot === undefined || this.disposed || slot.status === 'disposed') return undefined;
999
+ if (generation > this.generation) this.generation = generation;
1000
+ return slot.preparedStore.beginFrame(identity, this.generation);
1001
+ }
1002
+
1003
+ retainPreparedGraphics(
1004
+ identity: string,
1005
+ leases: readonly PreparedGraphicsResourceLease[],
1006
+ ): Result<RenderFeaturePreparedResourceBatch, RenderError> {
1007
+ const slot = findSlot(this.slots, identity);
1008
+ if (slot === undefined || this.disposed || slot.status === 'disposed') {
1009
+ return err(unknownFeatureError(identity, 'dispose'));
1010
+ }
1011
+ if (leases.length === 0) {
1012
+ return ok({ release: () => ok(undefined) });
1013
+ }
1014
+ let released = false;
1015
+ let batch!: RenderFeaturePreparedResourceBatch;
1016
+ batch = {
1017
+ release: () => {
1018
+ if (released) return ok(undefined);
1019
+ released = true;
1020
+ this.preparedBatchStates.delete(batch);
1021
+ slot.preparedResourceBatches.delete(batch);
1022
+ let firstError: RenderError | undefined;
1023
+ for (const lease of leases) {
1024
+ const result = lease.release();
1025
+ if (!result.ok && firstError === undefined) firstError = result.error;
1026
+ }
1027
+ return firstError === undefined ? ok(undefined) : err(firstError);
1028
+ },
1029
+ };
1030
+ this.preparedBatchStates.set(batch, 'unsubmitted');
1031
+ slot.preparedResourceBatches.add(batch);
1032
+ return ok(batch);
1033
+ }
1034
+
1035
+ markPreparedGraphicsSubmitted(batches: readonly RenderFeaturePreparedResourceBatch[]): void {
1036
+ for (const batch of batches) {
1037
+ if (this.preparedBatchStates.get(batch) === 'unsubmitted') {
1038
+ this.preparedBatchStates.set(batch, 'submitted');
1039
+ }
1040
+ }
1041
+ }
1042
+
1043
+ retirePreparedGraphics(
1044
+ batches?: readonly RenderFeaturePreparedResourceBatch[],
1045
+ ): Result<void, RenderError> {
1046
+ const owned = batches ?? this.slots.flatMap((slot) => [...slot.preparedResourceBatches]);
1047
+ let firstError: RenderError | undefined;
1048
+ for (const batch of owned) {
1049
+ const state = this.preparedBatchStates.get(batch);
1050
+ if (state === undefined || (batches === undefined && state === 'submitted')) continue;
1051
+ if (batches !== undefined && state !== 'submitted') continue;
1052
+ const result = batch.release();
1053
+ if (!result.ok && firstError === undefined) firstError = result.error;
1054
+ }
1055
+ return firstError === undefined ? ok(undefined) : err(firstError);
1056
+ }
1057
+
1058
+ recoverPreparedGraphics(
1059
+ batches: readonly RenderFeaturePreparedResourceBatch[],
1060
+ ): Result<void, RenderError> {
1061
+ let firstError: RenderError | undefined;
1062
+ for (const batch of batches) {
1063
+ if (this.preparedBatchStates.get(batch) !== 'submitted') continue;
1064
+ const result = batch.release();
1065
+ if (!result.ok && firstError === undefined) firstError = result.error;
1066
+ }
1067
+ return firstError === undefined ? ok(undefined) : err(firstError);
1068
+ }
1069
+
1070
+ recover(input: RenderFeatureRecoverInput): Result<void, RenderError> {
1071
+ if (this.disposed) return err(unknownFeatureError('render-feature-host', 'recover'));
1072
+ if (this.lastRecoveryFrame === input.frameNumber) return ok(undefined);
1073
+ const retired = this.retirePreparedGraphics();
1074
+ this.advancePreparedGeneration();
1075
+ this.lastRecoveryFrame = input.frameNumber;
1076
+ let firstError: RenderError | undefined = retired.ok ? undefined : retired.error;
1077
+ let diagnosticsChanged = false;
1078
+ for (const slot of this.slots) {
1079
+ if (slot.status === 'disposed') continue;
1080
+ const missing = missingCapability(slot.feature, input.caps);
1081
+ if (missing !== undefined) {
1082
+ const error = new RenderFeatureCapabilityMissingError(
1083
+ slot.feature.identity,
1084
+ slot.order,
1085
+ missing,
1086
+ );
1087
+ slot.status = 'disabled';
1088
+ slot.latestError = errorDescriptor(error);
1089
+ diagnosticsChanged = true;
1090
+ if (firstError === undefined) firstError = error;
1091
+ continue;
1092
+ }
1093
+ if (slot.status !== 'active' || slot.latestError !== undefined) {
1094
+ slot.status = 'active';
1095
+ slot.latestError = undefined;
1096
+ diagnosticsChanged = true;
1097
+ }
1098
+ }
1099
+ if (diagnosticsChanged) this.publishDiagnosticsChanged();
1100
+ return firstError === undefined ? ok(undefined) : err(firstError);
1101
+ }
1102
+
1103
+ diagnostics(): readonly RenderFeatureDiagnostics[] {
1104
+ return Object.freeze(this.slots.map(freezeDiagnostics));
1105
+ }
1106
+
1107
+ subscribeDiagnostics(listener: () => void): () => void {
1108
+ this.diagnosticsListeners.add(listener);
1109
+ return () => this.diagnosticsListeners.delete(listener);
1110
+ }
1111
+
1112
+ dispose(): Result<void, RenderError> {
1113
+ if (this.disposed) return ok(undefined);
1114
+ this.disposed = true;
1115
+
1116
+ const retired = this.retirePreparedGraphics();
1117
+ const firstError: RenderError | undefined = retired.ok ? undefined : retired.error;
1118
+ for (const slot of this.slots) {
1119
+ slot.status = 'disposed';
1120
+ }
1121
+ this.publishDiagnosticsChanged();
1122
+ this.diagnosticsListeners.clear();
1123
+
1124
+ return firstError === undefined ? ok(undefined) : err(firstError);
1125
+ }
1126
+ }
1127
+
1128
+ /** Build and project the mandatory plan once for every active feature. */
1129
+ export function runRenderFeatureFrame(
1130
+ host: RenderFeatureHost,
1131
+ input: RenderFeatureFrameInput,
1132
+ ): RenderFeatureFrameResult {
1133
+ const stageEvents: RenderFeatureStageEvent[] = [];
1134
+ const errors: RenderError[] = [];
1135
+ const plans: RenderFeaturePlannedFrame[] = [];
1136
+ const fullscreenEffects = new Map<string, PostProcessShaderEntry>();
1137
+ const preparedResourceBatches: RenderFeaturePreparedResourceBatch[] = [];
1138
+ const hiddenEntityReports: RenderFeatureHiddenEntityReport[] = [
1139
+ ...(input.hiddenEntityReports ?? []),
1140
+ ];
1141
+
1142
+ const diagnostics = host.diagnostics();
1143
+ for (const [order, feature] of host.features.entries()) {
1144
+ const diagnostic = diagnostics[order];
1145
+ if (diagnostic?.status === 'disabled' || diagnostic?.status === 'disposed') continue;
1146
+ const missing = missingCapability(feature, input.caps);
1147
+ if (missing !== undefined) {
1148
+ const capabilityError = new RenderFeatureCapabilityMissingError(
1149
+ feature.identity,
1150
+ order,
1151
+ missing,
1152
+ );
1153
+ errors.push(capabilityError);
1154
+ host.setStatus(feature.identity, 'disabled', errorDescriptor(capabilityError));
1155
+ continue;
1156
+ }
1157
+ const slot: FeatureSlot = {
1158
+ feature,
1159
+ order,
1160
+ preparedResourceBatches: new Set(),
1161
+ preparedStore: createPreparedGraphicsStore(),
1162
+ status: 'active',
1163
+ latestError: undefined,
1164
+ };
1165
+ const identity = slot.feature.identity;
1166
+ const transaction = host.beginPreparedFrame(identity, input.generation ?? 0);
1167
+ if (transaction === undefined) continue;
1168
+ const graphics = createPreparedGraphicsPrepare(transaction);
1169
+ const gpu: RenderFeatureGpuPrepareSession | undefined = input.gpuWork?.beginFeature(
1170
+ identity,
1171
+ input.generation ?? 0,
1172
+ );
1173
+ const featureHiddenEntityReports: RenderFeatureHiddenEntityReport[] = [];
1174
+ const extractContext = {
1175
+ worlds: input.worlds,
1176
+ owner: input.owner,
1177
+ frameNumber: input.frameNumber,
1178
+ reportHiddenEntity: (report) => featureHiddenEntityReports.push(report),
1179
+ ...(input.visibilitySnapshots === undefined
1180
+ ? {}
1181
+ : { visibilitySnapshots: input.visibilitySnapshots }),
1182
+ } satisfies RenderFeatureExtractContext;
1183
+ const extracted = invokeStage(
1184
+ slot,
1185
+ 'extract',
1186
+ () => slot.feature.extract(extractContext),
1187
+ stageEvents,
1188
+ errors,
1189
+ );
1190
+ if (!extracted.ok) {
1191
+ transaction.abort();
1192
+ host.setStatus(identity, 'failed', slot.latestError);
1193
+ continue;
1194
+ }
1195
+
1196
+ const targets = logicalTargets(input.targets ?? []);
1197
+ const declared = invokeStage(
1198
+ slot,
1199
+ 'plan',
1200
+ () =>
1201
+ feature.plan(extracted.value, {
1202
+ caps: input.caps,
1203
+ frame: { frameNumber: input.frameNumber },
1204
+ generation: transaction.generation,
1205
+ targets,
1206
+ }),
1207
+ stageEvents,
1208
+ errors,
1209
+ );
1210
+ if (!declared.ok) {
1211
+ transaction.abort();
1212
+ host.setStatus(identity, 'failed', slot.latestError);
1213
+ continue;
1214
+ }
1215
+ const frozen = freezeRenderFeaturePlan(identity, declared.value, targets);
1216
+ if (!frozen.ok) {
1217
+ recordFailure(slot, 'plan', frozen.error, errors);
1218
+ transaction.abort();
1219
+ host.setStatus(identity, 'failed', slot.latestError);
1220
+ continue;
1221
+ }
1222
+ const plannedFrame: RenderFeaturePlannedFrame = Object.freeze({
1223
+ featureIdentity: identity,
1224
+ generation: transaction.generation,
1225
+ signature: renderFeaturePlanSignature(frozen.value),
1226
+ plan: frozen.value,
1227
+ });
1228
+ for (const resource of frozen.value.resources) {
1229
+ if (resource.kind !== 'fullscreen-program') continue;
1230
+ fullscreenEffects.set(identity, {
1231
+ source: resource.source,
1232
+ ...(resource.reads === undefined ? {} : { reads: resource.reads }),
1233
+ ...(resource.params === undefined ? {} : { params: resource.params }),
1234
+ });
1235
+ }
1236
+ const prepared = preparePlanResources(slot, frozen.value, graphics, gpu, input.targets ?? []);
1237
+ if (!prepared.ok) {
1238
+ recordFailure(slot, 'plan', prepared.error, errors);
1239
+ transaction.abort();
1240
+ host.setStatus(identity, 'failed', slot.latestError);
1241
+ continue;
1242
+ }
1243
+ const validateGraphics = graphicsValidator(identity, transaction, true);
1244
+
1245
+ const resolverInput: RenderFeaturePreparedGraphicsResolverInput = {
1246
+ featureIdentity: identity,
1247
+ order,
1248
+ generation: transaction.generation,
1249
+ transaction,
1250
+ fullscreenEffects,
1251
+ lookup: (reference) =>
1252
+ [...transaction.overlayItems(), ...transaction.committedItems()].find(
1253
+ (item) => item.reference === reference,
1254
+ ),
1255
+ };
1256
+ const resolver = input.createPreparedGraphicsResolver?.(resolverInput);
1257
+ const resolveGraphics =
1258
+ resolver === undefined
1259
+ ? undefined
1260
+ : (descriptor: import('./prepared-graphics').RenderFeatureGraphicsPassDescriptor) => {
1261
+ const resolved = resolveGraphicsSnapshot(resolver, descriptor, transaction.generation);
1262
+ if (!resolved.ok) resolver.release();
1263
+ return resolved;
1264
+ };
1265
+ const releaseResolver = (): void => {
1266
+ if (resolver !== undefined) resolver.release();
1267
+ };
1268
+ const projected = projectPlanPasses(
1269
+ slot,
1270
+ frozen.value,
1271
+ prepared.value,
1272
+ gpu,
1273
+ input.targets ?? [],
1274
+ validateGraphics,
1275
+ resolveGraphics,
1276
+ );
1277
+ if (!projected.ok) {
1278
+ recordFailure(slot, 'plan', projected.error, errors);
1279
+ transaction.abort();
1280
+ releaseResolver();
1281
+ host.setStatus(identity, 'failed', slot.latestError);
1282
+ continue;
1283
+ }
1284
+ const preparedCommit = transaction.commit();
1285
+ if (!preparedCommit.ok) {
1286
+ recordFailure(slot, 'plan', preparedCommit.error, errors);
1287
+ releaseResolver();
1288
+ host.setStatus(identity, 'failed', slot.latestError);
1289
+ continue;
1290
+ }
1291
+ const leases = [
1292
+ ...new Set(projected.value.passes.flatMap((pass) => pass.resolvedGraphics?.leases ?? [])),
1293
+ ...(gpu?.retireUntouched() ?? []),
1294
+ ];
1295
+ const retained = host.retainPreparedGraphics(identity, leases);
1296
+ if (!retained.ok) {
1297
+ recordFailure(slot, 'plan', retained.error, errors);
1298
+ releaseResolver();
1299
+ host.setStatus(identity, 'failed', slot.latestError);
1300
+ continue;
1301
+ }
1302
+ planExecutionProjections.set(plannedFrame, projected.value);
1303
+ plans.push(plannedFrame);
1304
+ if (leases.length > 0) preparedResourceBatches.push(retained.value);
1305
+ hiddenEntityReports.push(...featureHiddenEntityReports);
1306
+ host.setStatus(identity, 'active');
1307
+ }
1308
+
1309
+ return {
1310
+ stageEvents,
1311
+ errors,
1312
+ plans,
1313
+ fullscreenEffects,
1314
+ preparedResourceBatches,
1315
+ hiddenEntityReports: mergeHiddenEntityReports(hiddenEntityReports),
1316
+ };
1317
+ }
1318
+
1319
+ function mergeHiddenEntityReports(
1320
+ reports: readonly RenderFeatureHiddenEntityReport[],
1321
+ ): readonly RenderFeatureHiddenEntityReport[] {
1322
+ const entitiesByWorld = new WeakMap<object, Set<EntityHandle>>();
1323
+ const merged: RenderFeatureHiddenEntityReport[] = [];
1324
+ for (const report of reports) {
1325
+ let entities = entitiesByWorld.get(report.world);
1326
+ if (entities === undefined) {
1327
+ entities = new Set<EntityHandle>();
1328
+ entitiesByWorld.set(report.world, entities);
1329
+ }
1330
+ if (entities.has(report.entity)) continue;
1331
+ entities.add(report.entity);
1332
+ merged.push(report);
1333
+ }
1334
+ return Object.freeze(merged);
1335
+ }
1336
+
1337
+ /**
1338
+ * Validate identities before creating typed slots or accepting resources.
1339
+ * Registration order is the input order and is never sorted by feature kind.
1340
+ */
1341
+ export function createRenderFeatureHost(
1342
+ features: readonly RenderFeature<unknown>[],
1343
+ _caps?: Readonly<RhiCaps>,
1344
+ ): Result<RenderFeatureHost, RenderError> {
1345
+ const identities = new Map<string, number>();
1346
+ for (const [order, feature] of features.entries()) {
1347
+ const conflictingOrder = identities.get(feature.identity);
1348
+ if (conflictingOrder !== undefined) {
1349
+ return err(registrationConflict(feature.identity, order, conflictingOrder));
1350
+ }
1351
+ identities.set(feature.identity, order);
1352
+ }
1353
+
1354
+ const slots: FeatureSlot[] = features.map((feature, order) => ({
1355
+ feature,
1356
+ order,
1357
+ preparedResourceBatches: new Set(),
1358
+ preparedStore: createPreparedGraphicsStore(),
1359
+ status: 'active',
1360
+ latestError: undefined,
1361
+ }));
1362
+ return ok(new FeatureHostImpl(slots));
1363
+ }