@forgeax/engine-render 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1172) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +1019 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/__tests__/analytic-sky-contract.test.d.ts +2 -0
  5. package/dist/__tests__/analytic-sky-contract.test.d.ts.map +1 -0
  6. package/dist/__tests__/analytic-sky-falsify.test.d.ts +2 -0
  7. package/dist/__tests__/analytic-sky-falsify.test.d.ts.map +1 -0
  8. package/dist/__tests__/assets-runtime-handoff.integration.test.d.ts +2 -0
  9. package/dist/__tests__/assets-runtime-handoff.integration.test.d.ts.map +1 -0
  10. package/dist/__tests__/authoring-path.unit.test.d.ts +2 -0
  11. package/dist/__tests__/authoring-path.unit.test.d.ts.map +1 -0
  12. package/dist/__tests__/backend-selection-rhi-capture.test-d.d.ts +2 -0
  13. package/dist/__tests__/backend-selection-rhi-capture.test-d.d.ts.map +1 -0
  14. package/dist/__tests__/backend-selection.integration.test.d.ts +2 -0
  15. package/dist/__tests__/backend-selection.integration.test.d.ts.map +1 -0
  16. package/dist/__tests__/callback-inference.test-d.d.ts +2 -0
  17. package/dist/__tests__/callback-inference.test-d.d.ts.map +1 -0
  18. package/dist/__tests__/camera-temporal.test-d.d.ts +2 -0
  19. package/dist/__tests__/camera-temporal.test-d.d.ts.map +1 -0
  20. package/dist/__tests__/camera-temporal.test.d.ts +2 -0
  21. package/dist/__tests__/camera-temporal.test.d.ts.map +1 -0
  22. package/dist/__tests__/cluster-binner.test.d.ts +2 -0
  23. package/dist/__tests__/cluster-binner.test.d.ts.map +1 -0
  24. package/dist/__tests__/cluster-grid-default-surface.unit.test.d.ts +2 -0
  25. package/dist/__tests__/cluster-grid-default-surface.unit.test.d.ts.map +1 -0
  26. package/dist/__tests__/construct-renderer-identity.unit.test.d.ts +2 -0
  27. package/dist/__tests__/construct-renderer-identity.unit.test.d.ts.map +1 -0
  28. package/dist/__tests__/direct-extract-consumer-contract.test-d.d.ts +2 -0
  29. package/dist/__tests__/direct-extract-consumer-contract.test-d.d.ts.map +1 -0
  30. package/dist/__tests__/direct-light-snapshot.unit.test.d.ts +2 -0
  31. package/dist/__tests__/direct-light-snapshot.unit.test.d.ts.map +1 -0
  32. package/dist/__tests__/directional-shadow-probe-atlas-layout.unit.test.d.ts +2 -0
  33. package/dist/__tests__/directional-shadow-probe-atlas-layout.unit.test.d.ts.map +1 -0
  34. package/dist/__tests__/environment-inspection.test.d.ts +2 -0
  35. package/dist/__tests__/environment-inspection.test.d.ts.map +1 -0
  36. package/dist/__tests__/factory-contract.integration.test.d.ts +2 -0
  37. package/dist/__tests__/factory-contract.integration.test.d.ts.map +1 -0
  38. package/dist/__tests__/fallback-row-stride-surface.unit.test.d.ts +2 -0
  39. package/dist/__tests__/fallback-row-stride-surface.unit.test.d.ts.map +1 -0
  40. package/dist/__tests__/fog-ai-user.fixture.d.ts +2 -0
  41. package/dist/__tests__/fog-ai-user.fixture.d.ts.map +1 -0
  42. package/dist/__tests__/fog-custom-render-feature.fixture.d.ts +16 -0
  43. package/dist/__tests__/fog-custom-render-feature.fixture.d.ts.map +1 -0
  44. package/dist/__tests__/fog-custom-render-feature.integration.test.d.ts +2 -0
  45. package/dist/__tests__/fog-custom-render-feature.integration.test.d.ts.map +1 -0
  46. package/dist/__tests__/fog-inspection.integration.test.d.ts +2 -0
  47. package/dist/__tests__/fog-inspection.integration.test.d.ts.map +1 -0
  48. package/dist/__tests__/fog-owner-state.integration.test.d.ts +2 -0
  49. package/dist/__tests__/fog-owner-state.integration.test.d.ts.map +1 -0
  50. package/dist/__tests__/fog-pipeline-topology.integration.test.d.ts +2 -0
  51. package/dist/__tests__/fog-pipeline-topology.integration.test.d.ts.map +1 -0
  52. package/dist/__tests__/fog-public-surface.integration.test.d.ts +2 -0
  53. package/dist/__tests__/fog-public-surface.integration.test.d.ts.map +1 -0
  54. package/dist/__tests__/fog-ray-contract.integration.test.d.ts +2 -0
  55. package/dist/__tests__/fog-ray-contract.integration.test.d.ts.map +1 -0
  56. package/dist/__tests__/fog-source-absence.integration.test.d.ts +2 -0
  57. package/dist/__tests__/fog-source-absence.integration.test.d.ts.map +1 -0
  58. package/dist/__tests__/fog-temporal.integration.test.d.ts +2 -0
  59. package/dist/__tests__/fog-temporal.integration.test.d.ts.map +1 -0
  60. package/dist/__tests__/frame-chain.unit.test.d.ts +2 -0
  61. package/dist/__tests__/frame-chain.unit.test.d.ts.map +1 -0
  62. package/dist/__tests__/frame-observation.contract.test.d.ts +2 -0
  63. package/dist/__tests__/frame-observation.contract.test.d.ts.map +1 -0
  64. package/dist/__tests__/glyph-text-layout-recovery.unit.test.d.ts +2 -0
  65. package/dist/__tests__/glyph-text-layout-recovery.unit.test.d.ts.map +1 -0
  66. package/dist/__tests__/gpu-driven-indirect-raster-evidence.d.ts +6 -0
  67. package/dist/__tests__/gpu-driven-indirect-raster-evidence.d.ts.map +1 -0
  68. package/dist/__tests__/gpu-driven-indirect-raster.browser.test.d.ts +2 -0
  69. package/dist/__tests__/gpu-driven-indirect-raster.browser.test.d.ts.map +1 -0
  70. package/dist/__tests__/gpu-driven-indirect-raster.dawn.test.d.ts +2 -0
  71. package/dist/__tests__/gpu-driven-indirect-raster.dawn.test.d.ts.map +1 -0
  72. package/dist/__tests__/gpu-driven-production.integration.test.d.ts +2 -0
  73. package/dist/__tests__/gpu-driven-production.integration.test.d.ts.map +1 -0
  74. package/dist/__tests__/gpu-driven-scaling.unit.test.d.ts +2 -0
  75. package/dist/__tests__/gpu-driven-scaling.unit.test.d.ts.map +1 -0
  76. package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts +12 -0
  77. package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts.map +1 -0
  78. package/dist/__tests__/gpu-driven-view-graph.integration.test.d.ts +2 -0
  79. package/dist/__tests__/gpu-driven-view-graph.integration.test.d.ts.map +1 -0
  80. package/dist/__tests__/gpu-driven-view.browser.test.d.ts +2 -0
  81. package/dist/__tests__/gpu-driven-view.browser.test.d.ts.map +1 -0
  82. package/dist/__tests__/gpu-driven-view.dawn.test.d.ts +2 -0
  83. package/dist/__tests__/gpu-driven-view.dawn.test.d.ts.map +1 -0
  84. package/dist/__tests__/gpu-driven-view.unit.test.d.ts +2 -0
  85. package/dist/__tests__/gpu-driven-view.unit.test.d.ts.map +1 -0
  86. package/dist/__tests__/gpu-resource-store-stride.unit.test.d.ts +2 -0
  87. package/dist/__tests__/gpu-resource-store-stride.unit.test.d.ts.map +1 -0
  88. package/dist/__tests__/gpu-scene-field-type-owner.test-d.d.ts +2 -0
  89. package/dist/__tests__/gpu-scene-field-type-owner.test-d.d.ts.map +1 -0
  90. package/dist/__tests__/gpu-scene-render-graph-gpu.d.ts +7 -0
  91. package/dist/__tests__/gpu-scene-render-graph-gpu.d.ts.map +1 -0
  92. package/dist/__tests__/gpu-scene-render-graph.browser.test.d.ts +2 -0
  93. package/dist/__tests__/gpu-scene-render-graph.browser.test.d.ts.map +1 -0
  94. package/dist/__tests__/gpu-scene-render-graph.dawn.test.d.ts +2 -0
  95. package/dist/__tests__/gpu-scene-render-graph.dawn.test.d.ts.map +1 -0
  96. package/dist/__tests__/gpu-scene-schema.unit.test.d.ts +2 -0
  97. package/dist/__tests__/gpu-scene-schema.unit.test.d.ts.map +1 -0
  98. package/dist/__tests__/gpu-scene.dawn.test.d.ts +2 -0
  99. package/dist/__tests__/gpu-scene.dawn.test.d.ts.map +1 -0
  100. package/dist/__tests__/gpu-scene.unit.test.d.ts +2 -0
  101. package/dist/__tests__/gpu-scene.unit.test.d.ts.map +1 -0
  102. package/dist/__tests__/hdrp-pipeline.unit.test.d.ts +2 -0
  103. package/dist/__tests__/hdrp-pipeline.unit.test.d.ts.map +1 -0
  104. package/dist/__tests__/ibl/ibl-fallback.unit.test.d.ts +2 -0
  105. package/dist/__tests__/ibl/ibl-fallback.unit.test.d.ts.map +1 -0
  106. package/dist/__tests__/infinite-grid-no-vertex-probe.unit.test.d.ts +2 -0
  107. package/dist/__tests__/infinite-grid-no-vertex-probe.unit.test.d.ts.map +1 -0
  108. package/dist/__tests__/injection-kind-owner.test-d.d.ts +2 -0
  109. package/dist/__tests__/injection-kind-owner.test-d.d.ts.map +1 -0
  110. package/dist/__tests__/ktx2-basis-gpu-consumer.dawn.test.d.ts +2 -0
  111. package/dist/__tests__/ktx2-basis-gpu-consumer.dawn.test.d.ts.map +1 -0
  112. package/dist/__tests__/light-buffer-layout.unit.test.d.ts +2 -0
  113. package/dist/__tests__/light-buffer-layout.unit.test.d.ts.map +1 -0
  114. package/dist/__tests__/material-contract-inventory.unit.test.d.ts +2 -0
  115. package/dist/__tests__/material-contract-inventory.unit.test.d.ts.map +1 -0
  116. package/dist/__tests__/material-cooked-projection.unit.test.d.ts +2 -0
  117. package/dist/__tests__/material-cooked-projection.unit.test.d.ts.map +1 -0
  118. package/dist/__tests__/material-derived-error-stop-draw.integration.test.d.ts +2 -0
  119. package/dist/__tests__/material-derived-error-stop-draw.integration.test.d.ts.map +1 -0
  120. package/dist/__tests__/material-derived-payload.integration.test.d.ts +2 -0
  121. package/dist/__tests__/material-derived-payload.integration.test.d.ts.map +1 -0
  122. package/dist/__tests__/material-snapshot-mutation.integration.test.d.ts +2 -0
  123. package/dist/__tests__/material-snapshot-mutation.integration.test.d.ts.map +1 -0
  124. package/dist/__tests__/material-static-dynamic-route.unit.test.d.ts +2 -0
  125. package/dist/__tests__/material-static-dynamic-route.unit.test.d.ts.map +1 -0
  126. package/dist/__tests__/material-stride-surface.unit.test.d.ts +2 -0
  127. package/dist/__tests__/material-stride-surface.unit.test.d.ts.map +1 -0
  128. package/dist/__tests__/materials.unit.test.d.ts +2 -0
  129. package/dist/__tests__/materials.unit.test.d.ts.map +1 -0
  130. package/dist/__tests__/mesh-buffer-usage-surface.unit.test.d.ts +2 -0
  131. package/dist/__tests__/mesh-buffer-usage-surface.unit.test.d.ts.map +1 -0
  132. package/dist/__tests__/mesh-material-bindings.unit.test.d.ts +2 -0
  133. package/dist/__tests__/mesh-material-bindings.unit.test.d.ts.map +1 -0
  134. package/dist/__tests__/mesh-stride-surface.unit.test.d.ts +2 -0
  135. package/dist/__tests__/mesh-stride-surface.unit.test.d.ts.map +1 -0
  136. package/dist/__tests__/morph-culling-reentry.dawn.test.d.ts +2 -0
  137. package/dist/__tests__/morph-culling-reentry.dawn.test.d.ts.map +1 -0
  138. package/dist/__tests__/morph-feature-gpu-work.integration.test.d.ts +2 -0
  139. package/dist/__tests__/morph-feature-gpu-work.integration.test.d.ts.map +1 -0
  140. package/dist/__tests__/morph-visual-evidence.integration.test.d.ts +2 -0
  141. package/dist/__tests__/morph-visual-evidence.integration.test.d.ts.map +1 -0
  142. package/dist/__tests__/nineslice-handle-surface.unit.test.d.ts +2 -0
  143. package/dist/__tests__/nineslice-handle-surface.unit.test.d.ts.map +1 -0
  144. package/dist/__tests__/param-schema-projection-census.unit.test.d.ts +2 -0
  145. package/dist/__tests__/param-schema-projection-census.unit.test.d.ts.map +1 -0
  146. package/dist/__tests__/persistent-render-scene.unit.test.d.ts +2 -0
  147. package/dist/__tests__/persistent-render-scene.unit.test.d.ts.map +1 -0
  148. package/dist/__tests__/pipeline-error-policy-owner.unit.test.d.ts +2 -0
  149. package/dist/__tests__/pipeline-error-policy-owner.unit.test.d.ts.map +1 -0
  150. package/dist/__tests__/pipeline-pass-trace.test.d.ts +2 -0
  151. package/dist/__tests__/pipeline-pass-trace.test.d.ts.map +1 -0
  152. package/dist/__tests__/pipeline-stage-owner.test-d.d.ts +2 -0
  153. package/dist/__tests__/pipeline-stage-owner.test-d.d.ts.map +1 -0
  154. package/dist/__tests__/plugin.test.d.ts +2 -0
  155. package/dist/__tests__/plugin.test.d.ts.map +1 -0
  156. package/dist/__tests__/post-process-error-policy-owner.unit.test.d.ts +2 -0
  157. package/dist/__tests__/post-process-error-policy-owner.unit.test.d.ts.map +1 -0
  158. package/dist/__tests__/prepared-buffer-kind-owner.test-d.d.ts +2 -0
  159. package/dist/__tests__/prepared-buffer-kind-owner.test-d.d.ts.map +1 -0
  160. package/dist/__tests__/prepared-graphics-backend-matrix.unit.test.d.ts +2 -0
  161. package/dist/__tests__/prepared-graphics-backend-matrix.unit.test.d.ts.map +1 -0
  162. package/dist/__tests__/prepared-graphics-capability.unit.test.d.ts +2 -0
  163. package/dist/__tests__/prepared-graphics-capability.unit.test.d.ts.map +1 -0
  164. package/dist/__tests__/prepared-graphics-generation.unit.test.d.ts +2 -0
  165. package/dist/__tests__/prepared-graphics-generation.unit.test.d.ts.map +1 -0
  166. package/dist/__tests__/prepared-graphics-lifecycle.unit.test.d.ts +2 -0
  167. package/dist/__tests__/prepared-graphics-lifecycle.unit.test.d.ts.map +1 -0
  168. package/dist/__tests__/prepared-graphics-pipeline-warmup.unit.test.d.ts +2 -0
  169. package/dist/__tests__/prepared-graphics-pipeline-warmup.unit.test.d.ts.map +1 -0
  170. package/dist/__tests__/prepared-graphics-resolver-recording.unit.test.d.ts +2 -0
  171. package/dist/__tests__/prepared-graphics-resolver-recording.unit.test.d.ts.map +1 -0
  172. package/dist/__tests__/prepared-graphics-resolver.unit.test.d.ts +2 -0
  173. package/dist/__tests__/prepared-graphics-resolver.unit.test.d.ts.map +1 -0
  174. package/dist/__tests__/prepared-graphics-snapshot.unit.test.d.ts +2 -0
  175. package/dist/__tests__/prepared-graphics-snapshot.unit.test.d.ts.map +1 -0
  176. package/dist/__tests__/prepared-graphics-store.unit.test.d.ts +2 -0
  177. package/dist/__tests__/prepared-graphics-store.unit.test.d.ts.map +1 -0
  178. package/dist/__tests__/prepared-graphics-validation.unit.test.d.ts +2 -0
  179. package/dist/__tests__/prepared-graphics-validation.unit.test.d.ts.map +1 -0
  180. package/dist/__tests__/profiler-default-off.test.d.ts +2 -0
  181. package/dist/__tests__/profiler-default-off.test.d.ts.map +1 -0
  182. package/dist/__tests__/profiler-phase-catalog.test.d.ts +2 -0
  183. package/dist/__tests__/profiler-phase-catalog.test.d.ts.map +1 -0
  184. package/dist/__tests__/profiler-phase-integration.test.d.ts +2 -0
  185. package/dist/__tests__/profiler-phase-integration.test.d.ts.map +1 -0
  186. package/dist/__tests__/profiler-phase-token.test.d.ts +2 -0
  187. package/dist/__tests__/profiler-phase-token.test.d.ts.map +1 -0
  188. package/dist/__tests__/public-pipeline-id.test-d.d.ts +2 -0
  189. package/dist/__tests__/public-pipeline-id.test-d.d.ts.map +1 -0
  190. package/dist/__tests__/public-surface.test-d.d.ts +2 -0
  191. package/dist/__tests__/public-surface.test-d.d.ts.map +1 -0
  192. package/dist/__tests__/recover-error-policy-owner.unit.test.d.ts +2 -0
  193. package/dist/__tests__/recover-error-policy-owner.unit.test.d.ts.map +1 -0
  194. package/dist/__tests__/render-dispatch-membership.unit.test.d.ts +2 -0
  195. package/dist/__tests__/render-dispatch-membership.unit.test.d.ts.map +1 -0
  196. package/dist/__tests__/render-error-code-owner.test-d.d.ts +2 -0
  197. package/dist/__tests__/render-error-code-owner.test-d.d.ts.map +1 -0
  198. package/dist/__tests__/render-error-detail-ssot.test-d.d.ts +2 -0
  199. package/dist/__tests__/render-error-detail-ssot.test-d.d.ts.map +1 -0
  200. package/dist/__tests__/render-error-exhaustive.test-d.d.ts +2 -0
  201. package/dist/__tests__/render-error-exhaustive.test-d.d.ts.map +1 -0
  202. package/dist/__tests__/render-feature-assembly.test-d.d.ts +2 -0
  203. package/dist/__tests__/render-feature-assembly.test-d.d.ts.map +1 -0
  204. package/dist/__tests__/render-feature-construction.unit.test.d.ts +2 -0
  205. package/dist/__tests__/render-feature-construction.unit.test.d.ts.map +1 -0
  206. package/dist/__tests__/render-feature-context.test-d.d.ts +2 -0
  207. package/dist/__tests__/render-feature-context.test-d.d.ts.map +1 -0
  208. package/dist/__tests__/render-feature-contract.test-d.d.ts +2 -0
  209. package/dist/__tests__/render-feature-contract.test-d.d.ts.map +1 -0
  210. package/dist/__tests__/render-feature-diagnostics.unit.test.d.ts +2 -0
  211. package/dist/__tests__/render-feature-diagnostics.unit.test.d.ts.map +1 -0
  212. package/dist/__tests__/render-feature-docs.unit.test.d.ts +2 -0
  213. package/dist/__tests__/render-feature-docs.unit.test.d.ts.map +1 -0
  214. package/dist/__tests__/render-feature-error-code-owner.test-d.d.ts +2 -0
  215. package/dist/__tests__/render-feature-error-code-owner.test-d.d.ts.map +1 -0
  216. package/dist/__tests__/render-feature-errors.unit.test.d.ts +2 -0
  217. package/dist/__tests__/render-feature-errors.unit.test.d.ts.map +1 -0
  218. package/dist/__tests__/render-feature-gpu-buffer-usage-owner.test-d.d.ts +2 -0
  219. package/dist/__tests__/render-feature-gpu-buffer-usage-owner.test-d.d.ts.map +1 -0
  220. package/dist/__tests__/render-feature-gpu-work.integration.test.d.ts +2 -0
  221. package/dist/__tests__/render-feature-gpu-work.integration.test.d.ts.map +1 -0
  222. package/dist/__tests__/render-feature-graph.integration.test.d.ts +2 -0
  223. package/dist/__tests__/render-feature-graph.integration.test.d.ts.map +1 -0
  224. package/dist/__tests__/render-feature-graphics-staging.unit.test.d.ts +2 -0
  225. package/dist/__tests__/render-feature-graphics-staging.unit.test.d.ts.map +1 -0
  226. package/dist/__tests__/render-feature-order.unit.test.d.ts +2 -0
  227. package/dist/__tests__/render-feature-order.unit.test.d.ts.map +1 -0
  228. package/dist/__tests__/render-feature-prepared-diagnostics.unit.test.d.ts +2 -0
  229. package/dist/__tests__/render-feature-prepared-diagnostics.unit.test.d.ts.map +1 -0
  230. package/dist/__tests__/render-feature-prepared-errors.test-d.d.ts +2 -0
  231. package/dist/__tests__/render-feature-prepared-errors.test-d.d.ts.map +1 -0
  232. package/dist/__tests__/render-feature-prepared-graphics-docs.unit.test.d.ts +2 -0
  233. package/dist/__tests__/render-feature-prepared-graphics-docs.unit.test.d.ts.map +1 -0
  234. package/dist/__tests__/render-feature-prepared-graphics-isolation.unit.test.d.ts +2 -0
  235. package/dist/__tests__/render-feature-prepared-graphics-isolation.unit.test.d.ts.map +1 -0
  236. package/dist/__tests__/render-feature-prepared-graphics-negative.test-d.d.ts +2 -0
  237. package/dist/__tests__/render-feature-prepared-graphics-negative.test-d.d.ts.map +1 -0
  238. package/dist/__tests__/render-feature-prepared-graphics-recording.unit.test.d.ts +2 -0
  239. package/dist/__tests__/render-feature-prepared-graphics-recording.unit.test.d.ts.map +1 -0
  240. package/dist/__tests__/render-feature-prepared-graphics.test-d.d.ts +2 -0
  241. package/dist/__tests__/render-feature-prepared-graphics.test-d.d.ts.map +1 -0
  242. package/dist/__tests__/render-feature-prepared-graphics.unit.test.d.ts +2 -0
  243. package/dist/__tests__/render-feature-prepared-graphics.unit.test.d.ts.map +1 -0
  244. package/dist/__tests__/render-feature-public-surface.test-d.d.ts +2 -0
  245. package/dist/__tests__/render-feature-public-surface.test-d.d.ts.map +1 -0
  246. package/dist/__tests__/render-feature-retry.unit.test.d.ts +2 -0
  247. package/dist/__tests__/render-feature-retry.unit.test.d.ts.map +1 -0
  248. package/dist/__tests__/render-feature-scheduling.unit.test.d.ts +2 -0
  249. package/dist/__tests__/render-feature-scheduling.unit.test.d.ts.map +1 -0
  250. package/dist/__tests__/render-feature-stage-failed-policy-owner.unit.test.d.ts +2 -0
  251. package/dist/__tests__/render-feature-stage-failed-policy-owner.unit.test.d.ts.map +1 -0
  252. package/dist/__tests__/render-feature-stage-fault-recovery.unit.test.d.ts +2 -0
  253. package/dist/__tests__/render-feature-stage-fault-recovery.unit.test.d.ts.map +1 -0
  254. package/dist/__tests__/render-feature-staging.unit.test.d.ts +2 -0
  255. package/dist/__tests__/render-feature-staging.unit.test.d.ts.map +1 -0
  256. package/dist/__tests__/render-feature-visibility-context.test-d.d.ts +2 -0
  257. package/dist/__tests__/render-feature-visibility-context.test-d.d.ts.map +1 -0
  258. package/dist/__tests__/render-feature-visibility-context.unit.test.d.ts +2 -0
  259. package/dist/__tests__/render-feature-visibility-context.unit.test.d.ts.map +1 -0
  260. package/dist/__tests__/render-feature-zero-work.unit.test.d.ts +2 -0
  261. package/dist/__tests__/render-feature-zero-work.unit.test.d.ts.map +1 -0
  262. package/dist/__tests__/render-graph-compute-raster-gpu.d.ts +7 -0
  263. package/dist/__tests__/render-graph-compute-raster-gpu.d.ts.map +1 -0
  264. package/dist/__tests__/render-graph-compute-raster.browser.test.d.ts +2 -0
  265. package/dist/__tests__/render-graph-compute-raster.browser.test.d.ts.map +1 -0
  266. package/dist/__tests__/render-graph-compute-raster.dawn.test.d.ts +2 -0
  267. package/dist/__tests__/render-graph-compute-raster.dawn.test.d.ts.map +1 -0
  268. package/dist/__tests__/render-graph-hzb-gpu.d.ts +7 -0
  269. package/dist/__tests__/render-graph-hzb-gpu.d.ts.map +1 -0
  270. package/dist/__tests__/render-graph-hzb.browser.test.d.ts +2 -0
  271. package/dist/__tests__/render-graph-hzb.browser.test.d.ts.map +1 -0
  272. package/dist/__tests__/render-graph-hzb.dawn.test.d.ts +2 -0
  273. package/dist/__tests__/render-graph-hzb.dawn.test.d.ts.map +1 -0
  274. package/dist/__tests__/render-graph-primitives.unit.test.d.ts +2 -0
  275. package/dist/__tests__/render-graph-primitives.unit.test.d.ts.map +1 -0
  276. package/dist/__tests__/render-graph-storage-indirect-gpu.d.ts +12 -0
  277. package/dist/__tests__/render-graph-storage-indirect-gpu.d.ts.map +1 -0
  278. package/dist/__tests__/render-graph-storage-indirect.browser.test.d.ts +2 -0
  279. package/dist/__tests__/render-graph-storage-indirect.browser.test.d.ts.map +1 -0
  280. package/dist/__tests__/render-graph-storage-indirect.dawn.test.d.ts +2 -0
  281. package/dist/__tests__/render-graph-storage-indirect.dawn.test.d.ts.map +1 -0
  282. package/dist/__tests__/render-scene-projection.unit.test.d.ts +2 -0
  283. package/dist/__tests__/render-scene-projection.unit.test.d.ts.map +1 -0
  284. package/dist/__tests__/renderer-factory-material-contract.unit.test.d.ts +2 -0
  285. package/dist/__tests__/renderer-factory-material-contract.unit.test.d.ts.map +1 -0
  286. package/dist/__tests__/renderer-lifecycle.integration.test.d.ts +2 -0
  287. package/dist/__tests__/renderer-lifecycle.integration.test.d.ts.map +1 -0
  288. package/dist/__tests__/renderer-render-scene-public.test-d.d.ts +2 -0
  289. package/dist/__tests__/renderer-render-scene-public.test-d.d.ts.map +1 -0
  290. package/dist/__tests__/rhi-backend-package-boundary.unit.test.d.ts +2 -0
  291. package/dist/__tests__/rhi-backend-package-boundary.unit.test.d.ts.map +1 -0
  292. package/dist/__tests__/scene-temporal-coverage.unit.test.d.ts +2 -0
  293. package/dist/__tests__/scene-temporal-coverage.unit.test.d.ts.map +1 -0
  294. package/dist/__tests__/scriptable-pack-consumer.test-d.d.ts +2 -0
  295. package/dist/__tests__/scriptable-pack-consumer.test-d.d.ts.map +1 -0
  296. package/dist/__tests__/shader-stage-surface.unit.test.d.ts +2 -0
  297. package/dist/__tests__/shader-stage-surface.unit.test.d.ts.map +1 -0
  298. package/dist/__tests__/ssao-kernel-surface.unit.test.d.ts +2 -0
  299. package/dist/__tests__/ssao-kernel-surface.unit.test.d.ts.map +1 -0
  300. package/dist/__tests__/sun-snapshot-consumers.test.d.ts +2 -0
  301. package/dist/__tests__/sun-snapshot-consumers.test.d.ts.map +1 -0
  302. package/dist/__tests__/surface-backend-kind-owner.test-d.d.ts +2 -0
  303. package/dist/__tests__/surface-backend-kind-owner.test-d.d.ts.map +1 -0
  304. package/dist/__tests__/surface-configuration.unit.test.d.ts +2 -0
  305. package/dist/__tests__/surface-configuration.unit.test.d.ts.map +1 -0
  306. package/dist/__tests__/taa-history-store.unit.test.d.ts +2 -0
  307. package/dist/__tests__/taa-history-store.unit.test.d.ts.map +1 -0
  308. package/dist/__tests__/temporal-frame-transaction.integration.test.d.ts +2 -0
  309. package/dist/__tests__/temporal-frame-transaction.integration.test.d.ts.map +1 -0
  310. package/dist/__tests__/temporal-inspection.unit.test.d.ts +2 -0
  311. package/dist/__tests__/temporal-inspection.unit.test.d.ts.map +1 -0
  312. package/dist/__tests__/texture-usage-surface.unit.test.d.ts +2 -0
  313. package/dist/__tests__/texture-usage-surface.unit.test.d.ts.map +1 -0
  314. package/dist/__tests__/typed-pipeline-topology.unit.test.d.ts +2 -0
  315. package/dist/__tests__/typed-pipeline-topology.unit.test.d.ts.map +1 -0
  316. package/dist/__tests__/urp-pipeline-targets.unit.test.d.ts +2 -0
  317. package/dist/__tests__/urp-pipeline-targets.unit.test.d.ts.map +1 -0
  318. package/dist/__tests__/urp-pipeline.unit.test.d.ts +2 -0
  319. package/dist/__tests__/urp-pipeline.unit.test.d.ts.map +1 -0
  320. package/dist/__tests__/vertex-color-pipeline.unit.test.d.ts +2 -0
  321. package/dist/__tests__/vertex-color-pipeline.unit.test.d.ts.map +1 -0
  322. package/dist/__tests__/vertex-layout-consumer.unit.test.d.ts +2 -0
  323. package/dist/__tests__/vertex-layout-consumer.unit.test.d.ts.map +1 -0
  324. package/dist/__tests__/visibility-diagnostics.integration.test.d.ts +2 -0
  325. package/dist/__tests__/visibility-diagnostics.integration.test.d.ts.map +1 -0
  326. package/dist/__tests__/visibility-extract.integration.test.d.ts +2 -0
  327. package/dist/__tests__/visibility-extract.integration.test.d.ts.map +1 -0
  328. package/dist/__tests__/visibility-extract.perf.test.d.ts +2 -0
  329. package/dist/__tests__/visibility-extract.perf.test.d.ts.map +1 -0
  330. package/dist/__tests__/visibility-feature-dedup.integration.test.d.ts +2 -0
  331. package/dist/__tests__/visibility-feature-dedup.integration.test.d.ts.map +1 -0
  332. package/dist/__tests__/visibility-hidden-report.unit.test.d.ts +2 -0
  333. package/dist/__tests__/visibility-hidden-report.unit.test.d.ts.map +1 -0
  334. package/dist/__tests__/visibility-instances.integration.test.d.ts +2 -0
  335. package/dist/__tests__/visibility-instances.integration.test.d.ts.map +1 -0
  336. package/dist/__tests__/visibility-multi-world.integration.test.d.ts +2 -0
  337. package/dist/__tests__/visibility-multi-world.integration.test.d.ts.map +1 -0
  338. package/dist/__tests__/visibility-producer-matrix.integration.test.d.ts +2 -0
  339. package/dist/__tests__/visibility-producer-matrix.integration.test.d.ts.map +1 -0
  340. package/dist/__tests__/visibility-producer-matrix.unit.test.d.ts +2 -0
  341. package/dist/__tests__/visibility-producer-matrix.unit.test.d.ts.map +1 -0
  342. package/dist/__tests__/visibility-public-surface.test-d.d.ts +2 -0
  343. package/dist/__tests__/visibility-public-surface.test-d.d.ts.map +1 -0
  344. package/dist/__tests__/visibility-resolver.unit.test.d.ts +2 -0
  345. package/dist/__tests__/visibility-resolver.unit.test.d.ts.map +1 -0
  346. package/dist/__tests__/visibility-snapshot-contract.unit.test.d.ts +2 -0
  347. package/dist/__tests__/visibility-snapshot-contract.unit.test.d.ts.map +1 -0
  348. package/dist/__tests__/vocabulary.unit.test.d.ts +2 -0
  349. package/dist/__tests__/vocabulary.unit.test.d.ts.map +1 -0
  350. package/dist/assets/__tests__/asset-decoders.unit.test.d.ts +2 -0
  351. package/dist/assets/__tests__/asset-decoders.unit.test.d.ts.map +1 -0
  352. package/dist/assets/__tests__/mipmap-generator.unit.test.d.ts +2 -0
  353. package/dist/assets/__tests__/mipmap-generator.unit.test.d.ts.map +1 -0
  354. package/dist/assets/__tests__/render-asset-port.unit.test.d.ts +2 -0
  355. package/dist/assets/__tests__/render-asset-port.unit.test.d.ts.map +1 -0
  356. package/dist/assets/__tests__/resolve-render-asset.unit.test.d.ts +2 -0
  357. package/dist/assets/__tests__/resolve-render-asset.unit.test.d.ts.map +1 -0
  358. package/dist/assets/asset-decoders.d.ts +5 -0
  359. package/dist/assets/asset-decoders.d.ts.map +1 -0
  360. package/dist/assets/render-asset-port.d.ts +17 -0
  361. package/dist/assets/render-asset-port.d.ts.map +1 -0
  362. package/dist/assets/resolve-render-asset.d.ts +6 -0
  363. package/dist/assets/resolve-render-asset.d.ts.map +1 -0
  364. package/dist/authoring.d.ts +12 -0
  365. package/dist/authoring.d.ts.map +1 -0
  366. package/dist/authoring.mjs +5 -0
  367. package/dist/authoring.mjs.map +1 -0
  368. package/dist/chunk-33UF5SAO.mjs +7397 -0
  369. package/dist/chunk-33UF5SAO.mjs.map +1 -0
  370. package/dist/chunk-A5QCJSNL.mjs +29913 -0
  371. package/dist/chunk-A5QCJSNL.mjs.map +1 -0
  372. package/dist/chunk-JMSB7AR4.mjs +3 -0
  373. package/dist/chunk-JMSB7AR4.mjs.map +1 -0
  374. package/dist/chunk-LXNGO6AO.mjs +569 -0
  375. package/dist/chunk-LXNGO6AO.mjs.map +1 -0
  376. package/dist/chunk-QRXPSX4X.mjs +659 -0
  377. package/dist/chunk-QRXPSX4X.mjs.map +1 -0
  378. package/dist/chunk-YAKEQPWO.mjs +1439 -0
  379. package/dist/chunk-YAKEQPWO.mjs.map +1 -0
  380. package/dist/cluster-binner.d.ts +152 -0
  381. package/dist/cluster-binner.d.ts.map +1 -0
  382. package/dist/components/__tests__/atmosphere-red.test.d.ts +2 -0
  383. package/dist/components/__tests__/atmosphere-red.test.d.ts.map +1 -0
  384. package/dist/components/__tests__/atmosphere.test.d.ts +2 -0
  385. package/dist/components/__tests__/atmosphere.test.d.ts.map +1 -0
  386. package/dist/components/__tests__/fog.test-d.d.ts +2 -0
  387. package/dist/components/__tests__/fog.test-d.d.ts.map +1 -0
  388. package/dist/components/__tests__/fog.test.d.ts +2 -0
  389. package/dist/components/__tests__/fog.test.d.ts.map +1 -0
  390. package/dist/components/__tests__/schema-parity.unit.test.d.ts +2 -0
  391. package/dist/components/__tests__/schema-parity.unit.test.d.ts.map +1 -0
  392. package/dist/components/__tests__/visibility-schema.unit.test.d.ts +2 -0
  393. package/dist/components/__tests__/visibility-schema.unit.test.d.ts.map +1 -0
  394. package/dist/components/atmosphere.d.ts +18 -0
  395. package/dist/components/atmosphere.d.ts.map +1 -0
  396. package/dist/components/camera.d.ts +311 -0
  397. package/dist/components/camera.d.ts.map +1 -0
  398. package/dist/components/directional-light.d.ts +76 -0
  399. package/dist/components/directional-light.d.ts.map +1 -0
  400. package/dist/components/environment.d.ts +116 -0
  401. package/dist/components/environment.d.ts.map +1 -0
  402. package/dist/components/glyph-text.d.ts +26 -0
  403. package/dist/components/glyph-text.d.ts.map +1 -0
  404. package/dist/components/index.d.ts +22 -0
  405. package/dist/components/index.d.ts.map +1 -0
  406. package/dist/components/instances.d.ts +41 -0
  407. package/dist/components/instances.d.ts.map +1 -0
  408. package/dist/components/layer.d.ts +34 -0
  409. package/dist/components/layer.d.ts.map +1 -0
  410. package/dist/components/light-helpers.d.ts +53 -0
  411. package/dist/components/light-helpers.d.ts.map +1 -0
  412. package/dist/components/mesh-filter.d.ts +24 -0
  413. package/dist/components/mesh-filter.d.ts.map +1 -0
  414. package/dist/components/mesh-renderer.d.ts +33 -0
  415. package/dist/components/mesh-renderer.d.ts.map +1 -0
  416. package/dist/components/point-light-shadow.d.ts +27 -0
  417. package/dist/components/point-light-shadow.d.ts.map +1 -0
  418. package/dist/components/point-light.d.ts +35 -0
  419. package/dist/components/point-light.d.ts.map +1 -0
  420. package/dist/components/post-process-params.d.ts +5 -0
  421. package/dist/components/post-process-params.d.ts.map +1 -0
  422. package/dist/components/scene-instance.d.ts +140 -0
  423. package/dist/components/scene-instance.d.ts.map +1 -0
  424. package/dist/components/sort-key.d.ts +44 -0
  425. package/dist/components/sort-key.d.ts.map +1 -0
  426. package/dist/components/spot-light.d.ts +81 -0
  427. package/dist/components/spot-light.d.ts.map +1 -0
  428. package/dist/components/sprite-animation.d.ts +75 -0
  429. package/dist/components/sprite-animation.d.ts.map +1 -0
  430. package/dist/components/sprite-instances.d.ts +51 -0
  431. package/dist/components/sprite-instances.d.ts.map +1 -0
  432. package/dist/components/sprite-playback-mode.d.ts +37 -0
  433. package/dist/components/sprite-playback-mode.d.ts.map +1 -0
  434. package/dist/components/sprite-region-override.d.ts +47 -0
  435. package/dist/components/sprite-region-override.d.ts.map +1 -0
  436. package/dist/components/tile-layer.d.ts +101 -0
  437. package/dist/components/tile-layer.d.ts.map +1 -0
  438. package/dist/components/tilemap.d.ts +25 -0
  439. package/dist/components/tilemap.d.ts.map +1 -0
  440. package/dist/components/visibility.d.ts +22 -0
  441. package/dist/components/visibility.d.ts.map +1 -0
  442. package/dist/construct-renderer.d.ts +2 -0
  443. package/dist/construct-renderer.d.ts.map +1 -0
  444. package/dist/construct-renderer.mjs +6 -0
  445. package/dist/construct-renderer.mjs.map +1 -0
  446. package/dist/debug-draw-glue.d.ts +56 -0
  447. package/dist/debug-draw-glue.d.ts.map +1 -0
  448. package/dist/deferred-lighting.d.ts +13 -0
  449. package/dist/deferred-lighting.d.ts.map +1 -0
  450. package/dist/dynamic-texture-store.d.ts +42 -0
  451. package/dist/dynamic-texture-store.d.ts.map +1 -0
  452. package/dist/engine-metrics.d.ts +23 -0
  453. package/dist/engine-metrics.d.ts.map +1 -0
  454. package/dist/environment/__tests__/failure-injection.test.d.ts +2 -0
  455. package/dist/environment/__tests__/failure-injection.test.d.ts.map +1 -0
  456. package/dist/environment/__tests__/generation-red.test.d.ts +2 -0
  457. package/dist/environment/__tests__/generation-red.test.d.ts.map +1 -0
  458. package/dist/environment/__tests__/generation.test.d.ts +2 -0
  459. package/dist/environment/__tests__/generation.test.d.ts.map +1 -0
  460. package/dist/environment/__tests__/graph-transaction.test.d.ts +2 -0
  461. package/dist/environment/__tests__/graph-transaction.test.d.ts.map +1 -0
  462. package/dist/environment/__tests__/inspection-red.test.d.ts +2 -0
  463. package/dist/environment/__tests__/inspection-red.test.d.ts.map +1 -0
  464. package/dist/environment/__tests__/lifecycle-evidence.test.d.ts +2 -0
  465. package/dist/environment/__tests__/lifecycle-evidence.test.d.ts.map +1 -0
  466. package/dist/environment/__tests__/pipeline-topology.test.d.ts +2 -0
  467. package/dist/environment/__tests__/pipeline-topology.test.d.ts.map +1 -0
  468. package/dist/environment/__tests__/readiness.test.d.ts +2 -0
  469. package/dist/environment/__tests__/readiness.test.d.ts.map +1 -0
  470. package/dist/environment/__tests__/recovery.test.d.ts +2 -0
  471. package/dist/environment/__tests__/recovery.test.d.ts.map +1 -0
  472. package/dist/environment/__tests__/resize-dispose.test.d.ts +2 -0
  473. package/dist/environment/__tests__/resize-dispose.test.d.ts.map +1 -0
  474. package/dist/environment/__tests__/signature-red.test.d.ts +2 -0
  475. package/dist/environment/__tests__/signature-red.test.d.ts.map +1 -0
  476. package/dist/environment/__tests__/signature.test.d.ts +2 -0
  477. package/dist/environment/__tests__/signature.test.d.ts.map +1 -0
  478. package/dist/environment/descriptors.d.ts +2 -0
  479. package/dist/environment/descriptors.d.ts.map +1 -0
  480. package/dist/environment/extracted-environment.d.ts +53 -0
  481. package/dist/environment/extracted-environment.d.ts.map +1 -0
  482. package/dist/environment/generation.d.ts +62 -0
  483. package/dist/environment/generation.d.ts.map +1 -0
  484. package/dist/environment/gpu-bundle.d.ts +23 -0
  485. package/dist/environment/gpu-bundle.d.ts.map +1 -0
  486. package/dist/environment/graph.d.ts +108 -0
  487. package/dist/environment/graph.d.ts.map +1 -0
  488. package/dist/environment/inspection.d.ts +48 -0
  489. package/dist/environment/inspection.d.ts.map +1 -0
  490. package/dist/environment/lifecycle.d.ts +22 -0
  491. package/dist/environment/lifecycle.d.ts.map +1 -0
  492. package/dist/environment/readiness.d.ts +29 -0
  493. package/dist/environment/readiness.d.ts.map +1 -0
  494. package/dist/environment/signature.d.ts +70 -0
  495. package/dist/environment/signature.d.ts.map +1 -0
  496. package/dist/errors/ecs-validation.d.ts +3 -0
  497. package/dist/errors/ecs-validation.d.ts.map +1 -0
  498. package/dist/errors/index.d.ts +4 -0
  499. package/dist/errors/index.d.ts.map +1 -0
  500. package/dist/errors/recover.d.ts +78 -0
  501. package/dist/errors/recover.d.ts.map +1 -0
  502. package/dist/errors/render.d.ts +633 -0
  503. package/dist/errors/render.d.ts.map +1 -0
  504. package/dist/extract/__tests__/directional-csm-domain.unit.test.d.ts +2 -0
  505. package/dist/extract/__tests__/directional-csm-domain.unit.test.d.ts.map +1 -0
  506. package/dist/extract/__tests__/environment-source.test.d.ts +2 -0
  507. package/dist/extract/__tests__/environment-source.test.d.ts.map +1 -0
  508. package/dist/extract/__tests__/schema-readers.unit.test.d.ts +2 -0
  509. package/dist/extract/__tests__/schema-readers.unit.test.d.ts.map +1 -0
  510. package/dist/extract/directional-csm.d.ts +129 -0
  511. package/dist/extract/directional-csm.d.ts.map +1 -0
  512. package/dist/extract/index.d.ts +5 -0
  513. package/dist/extract/index.d.ts.map +1 -0
  514. package/dist/extract/material-interface.d.ts +56 -0
  515. package/dist/extract/material-interface.d.ts.map +1 -0
  516. package/dist/extract/schema-readers.d.ts +20 -0
  517. package/dist/extract/schema-readers.d.ts.map +1 -0
  518. package/dist/extract/visibility.d.ts +26 -0
  519. package/dist/extract/visibility.d.ts.map +1 -0
  520. package/dist/features/graph-contribution.d.ts +64 -0
  521. package/dist/features/graph-contribution.d.ts.map +1 -0
  522. package/dist/features/host.d.ts +100 -0
  523. package/dist/features/host.d.ts.map +1 -0
  524. package/dist/features/index.d.ts +21 -0
  525. package/dist/features/index.d.ts.map +1 -0
  526. package/dist/features/morph/index.d.ts +3 -0
  527. package/dist/features/morph/index.d.ts.map +1 -0
  528. package/dist/features/morph/morph-bounds.d.ts +42 -0
  529. package/dist/features/morph/morph-bounds.d.ts.map +1 -0
  530. package/dist/features/morph/morph-feature.d.ts +45 -0
  531. package/dist/features/morph/morph-feature.d.ts.map +1 -0
  532. package/dist/features/prepared-gpu-work.d.ts +113 -0
  533. package/dist/features/prepared-gpu-work.d.ts.map +1 -0
  534. package/dist/features/prepared-graphics-store.d.ts +65 -0
  535. package/dist/features/prepared-graphics-store.d.ts.map +1 -0
  536. package/dist/features/prepared-graphics.d.ts +225 -0
  537. package/dist/features/prepared-graphics.d.ts.map +1 -0
  538. package/dist/features/render-graph-compute.d.ts +13 -0
  539. package/dist/features/render-graph-compute.d.ts.map +1 -0
  540. package/dist/features/render-graph-contribution.d.ts +15 -0
  541. package/dist/features/render-graph-contribution.d.ts.map +1 -0
  542. package/dist/features/render-graph-raster.d.ts +34 -0
  543. package/dist/features/render-graph-raster.d.ts.map +1 -0
  544. package/dist/features/render-graph-resources.d.ts +11 -0
  545. package/dist/features/render-graph-resources.d.ts.map +1 -0
  546. package/dist/features/scene-temporal.d.ts +45 -0
  547. package/dist/features/scene-temporal.d.ts.map +1 -0
  548. package/dist/features/taa-resolve.d.ts +21 -0
  549. package/dist/features/taa-resolve.d.ts.map +1 -0
  550. package/dist/features/targets.d.ts +32 -0
  551. package/dist/features/targets.d.ts.map +1 -0
  552. package/dist/features/types.d.ts +247 -0
  553. package/dist/features/types.d.ts.map +1 -0
  554. package/dist/frame-chain.d.ts +14 -0
  555. package/dist/frame-chain.d.ts.map +1 -0
  556. package/dist/fullscreen-post-process-pass.d.ts +178 -0
  557. package/dist/fullscreen-post-process-pass.d.ts.map +1 -0
  558. package/dist/glyph-text-layout-system.d.ts +18 -0
  559. package/dist/glyph-text-layout-system.d.ts.map +1 -0
  560. package/dist/gpu-driven/batch-topology.d.ts +124 -0
  561. package/dist/gpu-driven/batch-topology.d.ts.map +1 -0
  562. package/dist/gpu-driven/production-raster.d.ts +150 -0
  563. package/dist/gpu-driven/production-raster.d.ts.map +1 -0
  564. package/dist/gpu-driven/view-gpu.d.ts +141 -0
  565. package/dist/gpu-driven/view-gpu.d.ts.map +1 -0
  566. package/dist/gpu-driven/view-reference.d.ts +15 -0
  567. package/dist/gpu-driven/view-reference.d.ts.map +1 -0
  568. package/dist/gpu-resource-store.d.ts +294 -0
  569. package/dist/gpu-resource-store.d.ts.map +1 -0
  570. package/dist/gpu-resource.d.ts +73 -0
  571. package/dist/gpu-resource.d.ts.map +1 -0
  572. package/dist/gpu-scene-schema.d.ts +171 -0
  573. package/dist/gpu-scene-schema.d.ts.map +1 -0
  574. package/dist/gpu-scene.d.ts +81 -0
  575. package/dist/gpu-scene.d.ts.map +1 -0
  576. package/dist/gpu-stage.d.ts +4 -0
  577. package/dist/gpu-stage.d.ts.map +1 -0
  578. package/dist/gpu-texture-usage.d.ts +6 -0
  579. package/dist/gpu-texture-usage.d.ts.map +1 -0
  580. package/dist/gpu-usage.d.ts +9 -0
  581. package/dist/gpu-usage.d.ts.map +1 -0
  582. package/dist/hdrp-buffers.d.ts +213 -0
  583. package/dist/hdrp-buffers.d.ts.map +1 -0
  584. package/dist/hdrp-cluster-membership.d.ts +2 -0
  585. package/dist/hdrp-cluster-membership.d.ts.map +1 -0
  586. package/dist/hdrp-pipeline.d.ts +36 -0
  587. package/dist/hdrp-pipeline.d.ts.map +1 -0
  588. package/dist/ibl/IblPipelineCache.d.ts +274 -0
  589. package/dist/ibl/IblPipelineCache.d.ts.map +1 -0
  590. package/dist/ibl/cubemap-projection.d.ts +23 -0
  591. package/dist/ibl/cubemap-projection.d.ts.map +1 -0
  592. package/dist/ibl/face-uniforms.d.ts +65 -0
  593. package/dist/ibl/face-uniforms.d.ts.map +1 -0
  594. package/dist/ibl/skylight-bind-group.d.ts +130 -0
  595. package/dist/ibl/skylight-bind-group.d.ts.map +1 -0
  596. package/dist/index.d.ts +57 -0
  597. package/dist/index.d.ts.map +1 -0
  598. package/dist/index.mjs +5 -0
  599. package/dist/index.mjs.map +1 -0
  600. package/dist/instance-buffer-cache.d.ts +59 -0
  601. package/dist/instance-buffer-cache.d.ts.map +1 -0
  602. package/dist/internal.d.ts +74 -0
  603. package/dist/internal.d.ts.map +1 -0
  604. package/dist/internal.mjs +45 -0
  605. package/dist/internal.mjs.map +1 -0
  606. package/dist/lifecycle.d.ts +28 -0
  607. package/dist/lifecycle.d.ts.map +1 -0
  608. package/dist/light-buffer-layout.d.ts +164 -0
  609. package/dist/light-buffer-layout.d.ts.map +1 -0
  610. package/dist/materials.d.ts +50 -0
  611. package/dist/materials.d.ts.map +1 -0
  612. package/dist/mesh-material-bindings.d.ts +44 -0
  613. package/dist/mesh-material-bindings.d.ts.map +1 -0
  614. package/dist/mesh-update-errors.d.ts +71 -0
  615. package/dist/mesh-update-errors.d.ts.map +1 -0
  616. package/dist/mipmap-generator.d.ts +39 -0
  617. package/dist/mipmap-generator.d.ts.map +1 -0
  618. package/dist/param-schema-projection-census.d.ts +18 -0
  619. package/dist/param-schema-projection-census.d.ts.map +1 -0
  620. package/dist/pbr-pipeline.d.ts +253 -0
  621. package/dist/pbr-pipeline.d.ts.map +1 -0
  622. package/dist/persistent-render-scene.d.ts +158 -0
  623. package/dist/persistent-render-scene.d.ts.map +1 -0
  624. package/dist/pipeline/index.d.ts +11 -0
  625. package/dist/pipeline/index.d.ts.map +1 -0
  626. package/dist/pipeline-builder.d.ts +122 -0
  627. package/dist/pipeline-builder.d.ts.map +1 -0
  628. package/dist/pipeline-errors.d.ts +110 -0
  629. package/dist/pipeline-errors.d.ts.map +1 -0
  630. package/dist/pipeline-spec.d.ts +506 -0
  631. package/dist/pipeline-spec.d.ts.map +1 -0
  632. package/dist/plugin.d.ts +17 -0
  633. package/dist/plugin.d.ts.map +1 -0
  634. package/dist/post-process-errors.d.ts +182 -0
  635. package/dist/post-process-errors.d.ts.map +1 -0
  636. package/dist/prepare/__tests__/schema-readers.unit.test.d.ts +2 -0
  637. package/dist/prepare/__tests__/schema-readers.unit.test.d.ts.map +1 -0
  638. package/dist/prepare/index.d.ts +4 -0
  639. package/dist/prepare/index.d.ts.map +1 -0
  640. package/dist/prepare/prepared-graphics-resolver.d.ts +62 -0
  641. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -0
  642. package/dist/prepare/schema-readers.d.ts +11 -0
  643. package/dist/prepare/schema-readers.d.ts.map +1 -0
  644. package/dist/record/__tests__/environment-record.test.d.ts +2 -0
  645. package/dist/record/__tests__/environment-record.test.d.ts.map +1 -0
  646. package/dist/record/__tests__/frame-targets.unit.test.d.ts +2 -0
  647. package/dist/record/__tests__/frame-targets.unit.test.d.ts.map +1 -0
  648. package/dist/record/__tests__/material-bg-cache.unit.test.d.ts +2 -0
  649. package/dist/record/__tests__/material-bg-cache.unit.test.d.ts.map +1 -0
  650. package/dist/record/__tests__/material-slot-plan.unit.test.d.ts +2 -0
  651. package/dist/record/__tests__/material-slot-plan.unit.test.d.ts.map +1 -0
  652. package/dist/record/__tests__/membership-timing.unit.test.d.ts +2 -0
  653. package/dist/record/__tests__/membership-timing.unit.test.d.ts.map +1 -0
  654. package/dist/record/__tests__/render-submission.integration.test.d.ts +2 -0
  655. package/dist/record/__tests__/render-submission.integration.test.d.ts.map +1 -0
  656. package/dist/record/__tests__/render-submission.perf.test.d.ts +2 -0
  657. package/dist/record/__tests__/render-submission.perf.test.d.ts.map +1 -0
  658. package/dist/record/__tests__/shadow-submit-mode.unit.test.d.ts +2 -0
  659. package/dist/record/__tests__/shadow-submit-mode.unit.test.d.ts.map +1 -0
  660. package/dist/record/__tests__/video-texture-view.unit.test.d.ts +2 -0
  661. package/dist/record/__tests__/video-texture-view.unit.test.d.ts.map +1 -0
  662. package/dist/record/__tests__/view-ubo-layout.unit.test.d.ts +2 -0
  663. package/dist/record/__tests__/view-ubo-layout.unit.test.d.ts.map +1 -0
  664. package/dist/record/frame-lighting.d.ts +187 -0
  665. package/dist/record/frame-lighting.d.ts.map +1 -0
  666. package/dist/record/frame-observation.d.ts +38 -0
  667. package/dist/record/frame-observation.d.ts.map +1 -0
  668. package/dist/record/frame-snapshot.d.ts +429 -0
  669. package/dist/record/frame-snapshot.d.ts.map +1 -0
  670. package/dist/record/frame-targets.d.ts +53 -0
  671. package/dist/record/frame-targets.d.ts.map +1 -0
  672. package/dist/record/frame.d.ts +59 -0
  673. package/dist/record/frame.d.ts.map +1 -0
  674. package/dist/record/helpers.d.ts +101 -0
  675. package/dist/record/helpers.d.ts.map +1 -0
  676. package/dist/record/index.d.ts +15 -0
  677. package/dist/record/index.d.ts.map +1 -0
  678. package/dist/record/main-pass-geometry.d.ts +20 -0
  679. package/dist/record/main-pass-geometry.d.ts.map +1 -0
  680. package/dist/record/main-pass-material.d.ts +173 -0
  681. package/dist/record/main-pass-material.d.ts.map +1 -0
  682. package/dist/record/main-pass-skin.d.ts +46 -0
  683. package/dist/record/main-pass-skin.d.ts.map +1 -0
  684. package/dist/record/main-pass-sprite-draws.d.ts +18 -0
  685. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -0
  686. package/dist/record/main-pass-sprite.d.ts +69 -0
  687. package/dist/record/main-pass-sprite.d.ts.map +1 -0
  688. package/dist/record/main-pass.d.ts +20 -0
  689. package/dist/record/main-pass.d.ts.map +1 -0
  690. package/dist/record/material-payload.d.ts +43 -0
  691. package/dist/record/material-payload.d.ts.map +1 -0
  692. package/dist/record/material-slot-plan.d.ts +26 -0
  693. package/dist/record/material-slot-plan.d.ts.map +1 -0
  694. package/dist/record/membership-timing.d.ts +232 -0
  695. package/dist/record/membership-timing.d.ts.map +1 -0
  696. package/dist/record/mesh-ssbo.d.ts +173 -0
  697. package/dist/record/mesh-ssbo.d.ts.map +1 -0
  698. package/dist/record/shadow-caster-uniform.d.ts +8 -0
  699. package/dist/record/shadow-caster-uniform.d.ts.map +1 -0
  700. package/dist/record/shadow-pass.d.ts +125 -0
  701. package/dist/record/shadow-pass.d.ts.map +1 -0
  702. package/dist/record/shadow-submit-mode.d.ts +66 -0
  703. package/dist/record/shadow-submit-mode.d.ts.map +1 -0
  704. package/dist/record/skybox-post-pass.d.ts +33 -0
  705. package/dist/record/skybox-post-pass.d.ts.map +1 -0
  706. package/dist/record/typed-frame-graph.d.ts +13 -0
  707. package/dist/record/typed-frame-graph.d.ts.map +1 -0
  708. package/dist/record/view-ubo.d.ts +39 -0
  709. package/dist/record/view-ubo.d.ts.map +1 -0
  710. package/dist/render-data.d.ts +143 -0
  711. package/dist/render-data.d.ts.map +1 -0
  712. package/dist/render-dispatch-membership.d.ts +47 -0
  713. package/dist/render-dispatch-membership.d.ts.map +1 -0
  714. package/dist/render-graph-primitives.d.ts +424 -0
  715. package/dist/render-graph-primitives.d.ts.map +1 -0
  716. package/dist/render-pipeline-context.d.ts +289 -0
  717. package/dist/render-pipeline-context.d.ts.map +1 -0
  718. package/dist/render-pipeline-target.d.ts +16 -0
  719. package/dist/render-pipeline-target.d.ts.map +1 -0
  720. package/dist/render-pipeline.d.ts +149 -0
  721. package/dist/render-pipeline.d.ts.map +1 -0
  722. package/dist/render-scene-projection.d.ts +174 -0
  723. package/dist/render-scene-projection.d.ts.map +1 -0
  724. package/dist/render-system-extract.d.ts +1096 -0
  725. package/dist/render-system-extract.d.ts.map +1 -0
  726. package/dist/render-system-fold.d.ts +266 -0
  727. package/dist/render-system-fold.d.ts.map +1 -0
  728. package/dist/render-system.d.ts +814 -0
  729. package/dist/render-system.d.ts.map +1 -0
  730. package/dist/renderer/asset-service.d.ts +10 -0
  731. package/dist/renderer/asset-service.d.ts.map +1 -0
  732. package/dist/renderer/backend-selection.d.ts +26 -0
  733. package/dist/renderer/backend-selection.d.ts.map +1 -0
  734. package/dist/renderer/environment-classify.d.ts +6 -0
  735. package/dist/renderer/environment-classify.d.ts.map +1 -0
  736. package/dist/renderer/environment-error.d.ts +13 -0
  737. package/dist/renderer/environment-error.d.ts.map +1 -0
  738. package/dist/renderer/material/assembly.d.ts +22 -0
  739. package/dist/renderer/material/assembly.d.ts.map +1 -0
  740. package/dist/renderer/material/pipeline-projection.d.ts +91 -0
  741. package/dist/renderer/material/pipeline-projection.d.ts.map +1 -0
  742. package/dist/renderer/renderer-factory.d.ts +283 -0
  743. package/dist/renderer/renderer-factory.d.ts.map +1 -0
  744. package/dist/renderer.d.ts +771 -0
  745. package/dist/renderer.d.ts.map +1 -0
  746. package/dist/scene-instances/post-spawn-resolve-joints.d.ts +33 -0
  747. package/dist/scene-instances/post-spawn-resolve-joints.d.ts.map +1 -0
  748. package/dist/scene-utils/collect-subtree.d.ts +11 -0
  749. package/dist/scene-utils/collect-subtree.d.ts.map +1 -0
  750. package/dist/shadow-atlas.d.ts +117 -0
  751. package/dist/shadow-atlas.d.ts.map +1 -0
  752. package/dist/ssao-buffers.d.ts +31 -0
  753. package/dist/ssao-buffers.d.ts.map +1 -0
  754. package/dist/ssao-config.d.ts +28 -0
  755. package/dist/ssao-config.d.ts.map +1 -0
  756. package/dist/ssao-data.d.ts +34 -0
  757. package/dist/ssao-data.d.ts.map +1 -0
  758. package/dist/surface-format.d.ts +10 -0
  759. package/dist/surface-format.d.ts.map +1 -0
  760. package/dist/systems/active-camera.d.ts +53 -0
  761. package/dist/systems/active-camera.d.ts.map +1 -0
  762. package/dist/systems/pass-selector.d.ts +24 -0
  763. package/dist/systems/pass-selector.d.ts.map +1 -0
  764. package/dist/systems/skin-palette-allocator.d.ts +51 -0
  765. package/dist/systems/skin-palette-allocator.d.ts.map +1 -0
  766. package/dist/systems/transparent-sort-config.d.ts +91 -0
  767. package/dist/systems/transparent-sort-config.d.ts.map +1 -0
  768. package/dist/taa-history-store.d.ts +88 -0
  769. package/dist/taa-history-store.d.ts.map +1 -0
  770. package/dist/temporal-coverage.d.ts +35 -0
  771. package/dist/temporal-coverage.d.ts.map +1 -0
  772. package/dist/temporal-frame-transaction.d.ts +92 -0
  773. package/dist/temporal-frame-transaction.d.ts.map +1 -0
  774. package/dist/temporal-inspection.d.ts +57 -0
  775. package/dist/temporal-inspection.d.ts.map +1 -0
  776. package/dist/temporal-view.d.ts +43 -0
  777. package/dist/temporal-view.d.ts.map +1 -0
  778. package/dist/tilemap/resolve-tileset-runtime.d.ts +23 -0
  779. package/dist/tilemap/resolve-tileset-runtime.d.ts.map +1 -0
  780. package/dist/tilemap-chunk-extract-system.d.ts +142 -0
  781. package/dist/tilemap-chunk-extract-system.d.ts.map +1 -0
  782. package/dist/typed-render-graph-primitives.d.ts +59 -0
  783. package/dist/typed-render-graph-primitives.d.ts.map +1 -0
  784. package/dist/typed-shadow-passes.d.ts +11 -0
  785. package/dist/typed-shadow-passes.d.ts.map +1 -0
  786. package/dist/urp-pipeline.d.ts +4 -0
  787. package/dist/urp-pipeline.d.ts.map +1 -0
  788. package/package.json +94 -0
  789. package/src/__tests__/analytic-sky-contract.test.ts +27 -0
  790. package/src/__tests__/analytic-sky-falsify-carriers.mjs +43 -0
  791. package/src/__tests__/analytic-sky-falsify.test.ts +94 -0
  792. package/src/__tests__/assets-runtime-handoff.integration.test.ts +36 -0
  793. package/src/__tests__/authoring-path.unit.test.ts +14 -0
  794. package/src/__tests__/backend-selection-rhi-capture.test-d.ts +21 -0
  795. package/src/__tests__/backend-selection.integration.test.ts +11 -0
  796. package/src/__tests__/callback-inference.test-d.ts +5 -0
  797. package/src/__tests__/camera-temporal.test-d.ts +8 -0
  798. package/src/__tests__/camera-temporal.test.ts +188 -0
  799. package/src/__tests__/cluster-binner.test.ts +272 -0
  800. package/src/__tests__/cluster-grid-default-surface.unit.test.ts +17 -0
  801. package/src/__tests__/construct-renderer-identity.unit.test.ts +10 -0
  802. package/src/__tests__/direct-extract-consumer-contract.test-d.ts +34 -0
  803. package/src/__tests__/direct-light-snapshot.unit.test.ts +71 -0
  804. package/src/__tests__/directional-shadow-probe-atlas-layout.unit.test.ts +18 -0
  805. package/src/__tests__/environment-inspection.test.ts +45 -0
  806. package/src/__tests__/factory-contract.integration.test.ts +331 -0
  807. package/src/__tests__/fallback-row-stride-surface.unit.test.ts +18 -0
  808. package/src/__tests__/fog-ai-user.fixture.ts +350 -0
  809. package/src/__tests__/fog-custom-render-feature.fixture.ts +33 -0
  810. package/src/__tests__/fog-custom-render-feature.integration.test.ts +76 -0
  811. package/src/__tests__/fog-inspection.integration.test.ts +127 -0
  812. package/src/__tests__/fog-owner-state.integration.test.ts +112 -0
  813. package/src/__tests__/fog-pipeline-topology.integration.test.ts +93 -0
  814. package/src/__tests__/fog-public-surface.integration.test.ts +60 -0
  815. package/src/__tests__/fog-ray-contract.integration.test.ts +73 -0
  816. package/src/__tests__/fog-source-absence.integration.test.ts +51 -0
  817. package/src/__tests__/fog-temporal.integration.test.ts +115 -0
  818. package/src/__tests__/frame-chain.unit.test.ts +26 -0
  819. package/src/__tests__/frame-observation.contract.test.ts +103 -0
  820. package/src/__tests__/glyph-text-layout-recovery.unit.test.ts +172 -0
  821. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +347 -0
  822. package/src/__tests__/gpu-driven-indirect-raster.browser.test.ts +12 -0
  823. package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +16 -0
  824. package/src/__tests__/gpu-driven-production.integration.test.ts +609 -0
  825. package/src/__tests__/gpu-driven-scaling.unit.test.ts +90 -0
  826. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +192 -0
  827. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +128 -0
  828. package/src/__tests__/gpu-driven-view.browser.test.ts +19 -0
  829. package/src/__tests__/gpu-driven-view.dawn.test.ts +17 -0
  830. package/src/__tests__/gpu-driven-view.unit.test.ts +455 -0
  831. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +59 -0
  832. package/src/__tests__/gpu-scene-field-type-owner.test-d.ts +27 -0
  833. package/src/__tests__/gpu-scene-render-graph-gpu.ts +309 -0
  834. package/src/__tests__/gpu-scene-render-graph.browser.test.ts +19 -0
  835. package/src/__tests__/gpu-scene-render-graph.dawn.test.ts +19 -0
  836. package/src/__tests__/gpu-scene-schema.unit.test.ts +16 -0
  837. package/src/__tests__/gpu-scene.dawn.test.ts +209 -0
  838. package/src/__tests__/gpu-scene.unit.test.ts +161 -0
  839. package/src/__tests__/hdrp-pipeline.unit.test.ts +100 -0
  840. package/src/__tests__/ibl/ibl-fallback.unit.test.ts +23 -0
  841. package/src/__tests__/infinite-grid-no-vertex-probe.unit.test.ts +124 -0
  842. package/src/__tests__/injection-kind-owner.test-d.ts +14 -0
  843. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +719 -0
  844. package/src/__tests__/light-buffer-layout.unit.test.ts +85 -0
  845. package/src/__tests__/material-contract-inventory.unit.test.ts +24 -0
  846. package/src/__tests__/material-cooked-projection.unit.test.ts +177 -0
  847. package/src/__tests__/material-derived-error-stop-draw.integration.test.ts +69 -0
  848. package/src/__tests__/material-derived-payload.integration.test.ts +164 -0
  849. package/src/__tests__/material-snapshot-mutation.integration.test.ts +58 -0
  850. package/src/__tests__/material-static-dynamic-route.unit.test.ts +113 -0
  851. package/src/__tests__/material-stride-surface.unit.test.ts +32 -0
  852. package/src/__tests__/materials.unit.test.ts +25 -0
  853. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +107 -0
  854. package/src/__tests__/mesh-material-bindings.unit.test.ts +89 -0
  855. package/src/__tests__/mesh-stride-surface.unit.test.ts +16 -0
  856. package/src/__tests__/morph-culling-reentry.dawn.test.ts +166 -0
  857. package/src/__tests__/morph-feature-gpu-work.integration.test.ts +78 -0
  858. package/src/__tests__/morph-visual-evidence.integration.test.ts +66 -0
  859. package/src/__tests__/nineslice-handle-surface.unit.test.ts +14 -0
  860. package/src/__tests__/param-schema-projection-census.unit.test.ts +40 -0
  861. package/src/__tests__/persistent-render-scene.unit.test.ts +1311 -0
  862. package/src/__tests__/pipeline-error-policy-owner.unit.test.ts +167 -0
  863. package/src/__tests__/pipeline-pass-trace.test.ts +92 -0
  864. package/src/__tests__/pipeline-stage-owner.test-d.ts +13 -0
  865. package/src/__tests__/plugin.test.ts +25 -0
  866. package/src/__tests__/post-process-error-policy-owner.unit.test.ts +208 -0
  867. package/src/__tests__/prepared-buffer-kind-owner.test-d.ts +29 -0
  868. package/src/__tests__/prepared-graphics-backend-matrix.unit.test.ts +129 -0
  869. package/src/__tests__/prepared-graphics-capability.unit.test.ts +140 -0
  870. package/src/__tests__/prepared-graphics-generation.unit.test.ts +175 -0
  871. package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +206 -0
  872. package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +29 -0
  873. package/src/__tests__/prepared-graphics-resolver-recording.unit.test.ts +180 -0
  874. package/src/__tests__/prepared-graphics-resolver.unit.test.ts +287 -0
  875. package/src/__tests__/prepared-graphics-snapshot.unit.test.ts +105 -0
  876. package/src/__tests__/prepared-graphics-store.unit.test.ts +154 -0
  877. package/src/__tests__/prepared-graphics-validation.unit.test.ts +176 -0
  878. package/src/__tests__/profiler-default-off.test.ts +22 -0
  879. package/src/__tests__/profiler-phase-catalog.test.ts +66 -0
  880. package/src/__tests__/profiler-phase-integration.test.ts +70 -0
  881. package/src/__tests__/profiler-phase-token.test.ts +84 -0
  882. package/src/__tests__/public-pipeline-id.test-d.ts +6 -0
  883. package/src/__tests__/public-surface.test-d.ts +32 -0
  884. package/src/__tests__/recover-error-policy-owner.unit.test.ts +127 -0
  885. package/src/__tests__/render-dispatch-membership.unit.test.ts +117 -0
  886. package/src/__tests__/render-error-code-owner.test-d.ts +115 -0
  887. package/src/__tests__/render-error-detail-ssot.test-d.ts +234 -0
  888. package/src/__tests__/render-error-exhaustive.test-d.ts +84 -0
  889. package/src/__tests__/render-feature-assembly.test-d.ts +51 -0
  890. package/src/__tests__/render-feature-construction.unit.test.ts +124 -0
  891. package/src/__tests__/render-feature-context.test-d.ts +81 -0
  892. package/src/__tests__/render-feature-contract.test-d.ts +58 -0
  893. package/src/__tests__/render-feature-diagnostics.unit.test.ts +151 -0
  894. package/src/__tests__/render-feature-docs.unit.test.ts +88 -0
  895. package/src/__tests__/render-feature-error-code-owner.test-d.ts +27 -0
  896. package/src/__tests__/render-feature-errors.unit.test.ts +47 -0
  897. package/src/__tests__/render-feature-gpu-buffer-usage-owner.test-d.ts +46 -0
  898. package/src/__tests__/render-feature-gpu-work.integration.test.ts +377 -0
  899. package/src/__tests__/render-feature-graph.integration.test.ts +205 -0
  900. package/src/__tests__/render-feature-graphics-staging.unit.test.ts +200 -0
  901. package/src/__tests__/render-feature-order.unit.test.ts +66 -0
  902. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +101 -0
  903. package/src/__tests__/render-feature-prepared-errors.test-d.ts +82 -0
  904. package/src/__tests__/render-feature-prepared-graphics-docs.unit.test.ts +141 -0
  905. package/src/__tests__/render-feature-prepared-graphics-isolation.unit.test.ts +122 -0
  906. package/src/__tests__/render-feature-prepared-graphics-negative.test-d.ts +59 -0
  907. package/src/__tests__/render-feature-prepared-graphics-recording.unit.test.ts +107 -0
  908. package/src/__tests__/render-feature-prepared-graphics.test-d.ts +96 -0
  909. package/src/__tests__/render-feature-prepared-graphics.unit.test.ts +121 -0
  910. package/src/__tests__/render-feature-public-surface.test-d.ts +75 -0
  911. package/src/__tests__/render-feature-retry.unit.test.ts +128 -0
  912. package/src/__tests__/render-feature-scheduling.unit.test.ts +122 -0
  913. package/src/__tests__/render-feature-stage-failed-policy-owner.unit.test.ts +146 -0
  914. package/src/__tests__/render-feature-stage-fault-recovery.unit.test.ts +236 -0
  915. package/src/__tests__/render-feature-staging.unit.test.ts +94 -0
  916. package/src/__tests__/render-feature-visibility-context.test-d.ts +38 -0
  917. package/src/__tests__/render-feature-visibility-context.unit.test.ts +38 -0
  918. package/src/__tests__/render-feature-zero-work.unit.test.ts +82 -0
  919. package/src/__tests__/render-graph-compute-raster-gpu.ts +342 -0
  920. package/src/__tests__/render-graph-compute-raster.browser.test.ts +16 -0
  921. package/src/__tests__/render-graph-compute-raster.dawn.test.ts +22 -0
  922. package/src/__tests__/render-graph-hzb-gpu.ts +239 -0
  923. package/src/__tests__/render-graph-hzb.browser.test.ts +16 -0
  924. package/src/__tests__/render-graph-hzb.dawn.test.ts +23 -0
  925. package/src/__tests__/render-graph-primitives.unit.test.ts +22 -0
  926. package/src/__tests__/render-graph-storage-indirect-gpu.ts +162 -0
  927. package/src/__tests__/render-graph-storage-indirect.browser.test.ts +21 -0
  928. package/src/__tests__/render-graph-storage-indirect.dawn.test.ts +28 -0
  929. package/src/__tests__/render-scene-projection.unit.test.ts +206 -0
  930. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +125 -0
  931. package/src/__tests__/renderer-lifecycle.integration.test.ts +10 -0
  932. package/src/__tests__/renderer-render-scene-public.test-d.ts +27 -0
  933. package/src/__tests__/rhi-backend-package-boundary.unit.test.ts +11 -0
  934. package/src/__tests__/scene-temporal-coverage.unit.test.ts +259 -0
  935. package/src/__tests__/scriptable-pack-consumer.test-d.ts +14 -0
  936. package/src/__tests__/shader-stage-surface.unit.test.ts +38 -0
  937. package/src/__tests__/ssao-kernel-surface.unit.test.ts +15 -0
  938. package/src/__tests__/sun-snapshot-consumers.test.ts +35 -0
  939. package/src/__tests__/surface-backend-kind-owner.test-d.ts +42 -0
  940. package/src/__tests__/surface-configuration.unit.test.ts +92 -0
  941. package/src/__tests__/taa-history-store.unit.test.ts +196 -0
  942. package/src/__tests__/temporal-frame-transaction.integration.test.ts +537 -0
  943. package/src/__tests__/temporal-inspection.unit.test.ts +138 -0
  944. package/src/__tests__/texture-usage-surface.unit.test.ts +61 -0
  945. package/src/__tests__/typed-pipeline-topology.unit.test.ts +389 -0
  946. package/src/__tests__/urp-pipeline-targets.unit.test.ts +52 -0
  947. package/src/__tests__/urp-pipeline.unit.test.ts +14 -0
  948. package/src/__tests__/vertex-color-pipeline.unit.test.ts +124 -0
  949. package/src/__tests__/vertex-layout-consumer.unit.test.ts +25 -0
  950. package/src/__tests__/visibility-diagnostics.integration.test.ts +66 -0
  951. package/src/__tests__/visibility-extract.integration.test.ts +89 -0
  952. package/src/__tests__/visibility-extract.perf.test.ts +96 -0
  953. package/src/__tests__/visibility-feature-dedup.integration.test.ts +57 -0
  954. package/src/__tests__/visibility-hidden-report.unit.test.ts +37 -0
  955. package/src/__tests__/visibility-instances.integration.test.ts +50 -0
  956. package/src/__tests__/visibility-multi-world.integration.test.ts +54 -0
  957. package/src/__tests__/visibility-producer-matrix.integration.test.ts +191 -0
  958. package/src/__tests__/visibility-producer-matrix.unit.test.ts +96 -0
  959. package/src/__tests__/visibility-public-surface.test-d.ts +26 -0
  960. package/src/__tests__/visibility-resolver.unit.test.ts +84 -0
  961. package/src/__tests__/visibility-snapshot-contract.unit.test.ts +59 -0
  962. package/src/__tests__/vocabulary.unit.test.ts +21 -0
  963. package/src/assets/__tests__/asset-decoders.unit.test.ts +92 -0
  964. package/src/assets/__tests__/mipmap-generator.unit.test.ts +52 -0
  965. package/src/assets/__tests__/render-asset-port.unit.test.ts +54 -0
  966. package/src/assets/__tests__/resolve-render-asset.unit.test.ts +47 -0
  967. package/src/assets/asset-decoders.ts +158 -0
  968. package/src/assets/render-asset-port.ts +44 -0
  969. package/src/assets/resolve-render-asset.ts +13 -0
  970. package/src/authoring.ts +24 -0
  971. package/src/cluster-binner.ts +700 -0
  972. package/src/components/__tests__/atmosphere-red.test.ts +51 -0
  973. package/src/components/__tests__/atmosphere.test.ts +79 -0
  974. package/src/components/__tests__/fog.test-d.ts +49 -0
  975. package/src/components/__tests__/fog.test.ts +60 -0
  976. package/src/components/__tests__/schema-parity.unit.test.ts +25 -0
  977. package/src/components/__tests__/visibility-schema.unit.test.ts +35 -0
  978. package/src/components/atmosphere.ts +64 -0
  979. package/src/components/camera.ts +512 -0
  980. package/src/components/directional-light.ts +120 -0
  981. package/src/components/environment.ts +206 -0
  982. package/src/components/glyph-text.ts +63 -0
  983. package/src/components/index.ts +49 -0
  984. package/src/components/instances.ts +207 -0
  985. package/src/components/layer.ts +69 -0
  986. package/src/components/light-helpers.ts +188 -0
  987. package/src/components/mesh-filter.ts +59 -0
  988. package/src/components/mesh-renderer.ts +61 -0
  989. package/src/components/point-light-shadow.ts +43 -0
  990. package/src/components/point-light.ts +65 -0
  991. package/src/components/post-process-params.ts +35 -0
  992. package/src/components/scene-instance.ts +193 -0
  993. package/src/components/sort-key.ts +75 -0
  994. package/src/components/spot-light.ts +124 -0
  995. package/src/components/sprite-animation.ts +169 -0
  996. package/src/components/sprite-instances.ts +179 -0
  997. package/src/components/sprite-playback-mode.ts +73 -0
  998. package/src/components/sprite-region-override.ts +106 -0
  999. package/src/components/tile-layer.ts +161 -0
  1000. package/src/components/tilemap.ts +48 -0
  1001. package/src/components/visibility.ts +53 -0
  1002. package/src/construct-renderer.ts +4 -0
  1003. package/src/debug-draw-glue.ts +169 -0
  1004. package/src/deferred-lighting.ts +92 -0
  1005. package/src/dynamic-texture-store.ts +111 -0
  1006. package/src/engine-metrics.ts +89 -0
  1007. package/src/environment/README.md +76 -0
  1008. package/src/environment/__tests__/failure-injection.test.ts +50 -0
  1009. package/src/environment/__tests__/generation-red.test.ts +64 -0
  1010. package/src/environment/__tests__/generation.test.ts +37 -0
  1011. package/src/environment/__tests__/graph-transaction.test.ts +85 -0
  1012. package/src/environment/__tests__/inspection-red.test.ts +53 -0
  1013. package/src/environment/__tests__/lifecycle-evidence.test.ts +40 -0
  1014. package/src/environment/__tests__/pipeline-topology.test.ts +33 -0
  1015. package/src/environment/__tests__/readiness.test.ts +42 -0
  1016. package/src/environment/__tests__/recovery.test.ts +62 -0
  1017. package/src/environment/__tests__/resize-dispose.test.ts +30 -0
  1018. package/src/environment/__tests__/signature-red.test.ts +45 -0
  1019. package/src/environment/__tests__/signature.test.ts +60 -0
  1020. package/src/environment/descriptors.ts +7 -0
  1021. package/src/environment/extracted-environment.ts +239 -0
  1022. package/src/environment/generation.ts +158 -0
  1023. package/src/environment/gpu-bundle.ts +144 -0
  1024. package/src/environment/graph.ts +588 -0
  1025. package/src/environment/inspection.ts +107 -0
  1026. package/src/environment/lifecycle.ts +124 -0
  1027. package/src/environment/readiness.ts +76 -0
  1028. package/src/environment/signature.ts +185 -0
  1029. package/src/errors/ecs-validation.ts +16 -0
  1030. package/src/errors/index.ts +3 -0
  1031. package/src/errors/recover.ts +119 -0
  1032. package/src/errors/render.ts +1244 -0
  1033. package/src/extract/__tests__/directional-csm-domain.unit.test.ts +391 -0
  1034. package/src/extract/__tests__/environment-source.test.ts +105 -0
  1035. package/src/extract/__tests__/schema-readers.unit.test.ts +16 -0
  1036. package/src/extract/directional-csm.ts +959 -0
  1037. package/src/extract/index.ts +10 -0
  1038. package/src/extract/material-interface.ts +604 -0
  1039. package/src/extract/schema-readers.ts +27 -0
  1040. package/src/extract/visibility.ts +120 -0
  1041. package/src/features/graph-contribution.ts +577 -0
  1042. package/src/features/host.ts +1097 -0
  1043. package/src/features/index.ts +100 -0
  1044. package/src/features/morph/index.ts +24 -0
  1045. package/src/features/morph/morph-bounds.ts +123 -0
  1046. package/src/features/morph/morph-feature.ts +287 -0
  1047. package/src/features/prepared-gpu-work.ts +902 -0
  1048. package/src/features/prepared-graphics-store.ts +435 -0
  1049. package/src/features/prepared-graphics.ts +479 -0
  1050. package/src/features/render-graph-compute.ts +60 -0
  1051. package/src/features/render-graph-contribution.ts +95 -0
  1052. package/src/features/render-graph-raster.ts +308 -0
  1053. package/src/features/render-graph-resources.ts +36 -0
  1054. package/src/features/scene-temporal.ts +274 -0
  1055. package/src/features/taa-resolve.ts +244 -0
  1056. package/src/features/targets.ts +83 -0
  1057. package/src/features/types.ts +291 -0
  1058. package/src/frame-chain.ts +21 -0
  1059. package/src/fullscreen-post-process-pass.ts +406 -0
  1060. package/src/glyph-text-layout-system.ts +447 -0
  1061. package/src/gpu-driven/batch-topology.ts +423 -0
  1062. package/src/gpu-driven/production-raster.ts +1705 -0
  1063. package/src/gpu-driven/view-gpu.ts +849 -0
  1064. package/src/gpu-driven/view-reference.ts +110 -0
  1065. package/src/gpu-resource-store.ts +1921 -0
  1066. package/src/gpu-resource.ts +159 -0
  1067. package/src/gpu-scene-schema.ts +224 -0
  1068. package/src/gpu-scene.ts +855 -0
  1069. package/src/gpu-stage.ts +9 -0
  1070. package/src/gpu-texture-usage.ts +12 -0
  1071. package/src/gpu-usage.ts +14 -0
  1072. package/src/hdrp-buffers.ts +689 -0
  1073. package/src/hdrp-cluster-membership.ts +70 -0
  1074. package/src/hdrp-pipeline.ts +525 -0
  1075. package/src/ibl/IblPipelineCache.ts +1246 -0
  1076. package/src/ibl/cubemap-projection.ts +60 -0
  1077. package/src/ibl/face-uniforms.ts +150 -0
  1078. package/src/ibl/skylight-bind-group.ts +513 -0
  1079. package/src/index.ts +271 -0
  1080. package/src/instance-buffer-cache.ts +123 -0
  1081. package/src/internal.ts +88 -0
  1082. package/src/lifecycle.ts +123 -0
  1083. package/src/light-buffer-layout.ts +346 -0
  1084. package/src/materials.ts +236 -0
  1085. package/src/mesh-material-bindings.ts +104 -0
  1086. package/src/mesh-update-errors.ts +113 -0
  1087. package/src/mipmap-generator.ts +244 -0
  1088. package/src/param-schema-projection-census.ts +73 -0
  1089. package/src/pbr-pipeline.ts +749 -0
  1090. package/src/persistent-render-scene.ts +1752 -0
  1091. package/src/pipeline/index.ts +40 -0
  1092. package/src/pipeline-builder.ts +386 -0
  1093. package/src/pipeline-errors.ts +172 -0
  1094. package/src/pipeline-spec.ts +1768 -0
  1095. package/src/plugin.ts +137 -0
  1096. package/src/post-process-errors.ts +304 -0
  1097. package/src/prepare/__tests__/schema-readers.unit.test.ts +16 -0
  1098. package/src/prepare/index.ts +8 -0
  1099. package/src/prepare/prepared-graphics-resolver.ts +455 -0
  1100. package/src/prepare/schema-readers.ts +20 -0
  1101. package/src/record/__tests__/environment-record.test.ts +35 -0
  1102. package/src/record/__tests__/frame-targets.unit.test.ts +54 -0
  1103. package/src/record/__tests__/material-bg-cache.unit.test.ts +41 -0
  1104. package/src/record/__tests__/material-slot-plan.unit.test.ts +76 -0
  1105. package/src/record/__tests__/membership-timing.unit.test.ts +524 -0
  1106. package/src/record/__tests__/render-submission.integration.test.ts +76 -0
  1107. package/src/record/__tests__/render-submission.perf.test.ts +141 -0
  1108. package/src/record/__tests__/shadow-submit-mode.unit.test.ts +88 -0
  1109. package/src/record/__tests__/video-texture-view.unit.test.ts +90 -0
  1110. package/src/record/__tests__/view-ubo-layout.unit.test.ts +101 -0
  1111. package/src/record/frame-lighting.ts +1183 -0
  1112. package/src/record/frame-observation.ts +122 -0
  1113. package/src/record/frame-snapshot.ts +515 -0
  1114. package/src/record/frame-targets.ts +372 -0
  1115. package/src/record/frame.ts +1874 -0
  1116. package/src/record/helpers.ts +289 -0
  1117. package/src/record/index.ts +15 -0
  1118. package/src/record/main-pass-geometry.ts +1014 -0
  1119. package/src/record/main-pass-material.ts +716 -0
  1120. package/src/record/main-pass-skin.ts +51 -0
  1121. package/src/record/main-pass-sprite-draws.ts +1056 -0
  1122. package/src/record/main-pass-sprite.ts +166 -0
  1123. package/src/record/main-pass.ts +588 -0
  1124. package/src/record/material-payload.ts +292 -0
  1125. package/src/record/material-slot-plan.ts +68 -0
  1126. package/src/record/membership-timing.ts +1012 -0
  1127. package/src/record/mesh-ssbo.ts +406 -0
  1128. package/src/record/shadow-caster-uniform.ts +37 -0
  1129. package/src/record/shadow-pass.ts +2387 -0
  1130. package/src/record/shadow-submit-mode.ts +277 -0
  1131. package/src/record/skybox-post-pass.ts +594 -0
  1132. package/src/record/typed-frame-graph.ts +499 -0
  1133. package/src/record/view-ubo.ts +206 -0
  1134. package/src/render-data.ts +385 -0
  1135. package/src/render-dispatch-membership.ts +155 -0
  1136. package/src/render-graph-primitives.ts +1586 -0
  1137. package/src/render-pipeline-context.ts +332 -0
  1138. package/src/render-pipeline-target.ts +96 -0
  1139. package/src/render-pipeline.ts +343 -0
  1140. package/src/render-scene-projection.ts +1738 -0
  1141. package/src/render-system-extract.ts +5203 -0
  1142. package/src/render-system-fold.ts +531 -0
  1143. package/src/render-system.ts +3258 -0
  1144. package/src/renderer/asset-service.ts +32 -0
  1145. package/src/renderer/backend-selection.ts +121 -0
  1146. package/src/renderer/environment-classify.ts +30 -0
  1147. package/src/renderer/environment-error.ts +19 -0
  1148. package/src/renderer/material/assembly.ts +53 -0
  1149. package/src/renderer/material/pipeline-projection.ts +140 -0
  1150. package/src/renderer/renderer-factory.ts +9062 -0
  1151. package/src/renderer.ts +940 -0
  1152. package/src/scene-instances/post-spawn-resolve-joints.ts +168 -0
  1153. package/src/scene-utils/collect-subtree.ts +40 -0
  1154. package/src/shadow-atlas.ts +244 -0
  1155. package/src/ssao-buffers.ts +175 -0
  1156. package/src/ssao-config.ts +61 -0
  1157. package/src/ssao-data.ts +106 -0
  1158. package/src/surface-format.ts +37 -0
  1159. package/src/systems/active-camera.ts +116 -0
  1160. package/src/systems/pass-selector.ts +49 -0
  1161. package/src/systems/skin-palette-allocator.ts +294 -0
  1162. package/src/systems/transparent-sort-config.ts +211 -0
  1163. package/src/taa-history-store.ts +429 -0
  1164. package/src/temporal-coverage.ts +106 -0
  1165. package/src/temporal-frame-transaction.ts +301 -0
  1166. package/src/temporal-inspection.ts +194 -0
  1167. package/src/temporal-view.ts +174 -0
  1168. package/src/tilemap/resolve-tileset-runtime.ts +72 -0
  1169. package/src/tilemap-chunk-extract-system.ts +1307 -0
  1170. package/src/typed-render-graph-primitives.ts +530 -0
  1171. package/src/typed-shadow-passes.ts +195 -0
  1172. package/src/urp-pipeline.ts +340 -0
@@ -0,0 +1,1705 @@
1
+ import { frustum, mat4 } from '@forgeax/engine-math';
2
+ import type {
3
+ GraphAccess,
4
+ GraphBuffer,
5
+ GraphResourceResolver,
6
+ RenderGraphBuilder,
7
+ RenderGraphError,
8
+ } from '@forgeax/engine-render-graph';
9
+ import type {
10
+ BindGroup,
11
+ BindGroupLayout,
12
+ RenderPipeline,
13
+ Result,
14
+ RhiDevice,
15
+ ShaderModule,
16
+ } from '@forgeax/engine-rhi';
17
+ import { err, ok, RhiError } from '@forgeax/engine-rhi';
18
+ import { type MaterialRenderState, RenderQueue } from '@forgeax/engine-types';
19
+ import { GPU_SCENE_WGSL } from '../gpu-scene-schema';
20
+ import {
21
+ GPU_BUFFER_USAGE_COPY_DST,
22
+ GPU_BUFFER_USAGE_INDEX,
23
+ GPU_BUFFER_USAGE_UNIFORM,
24
+ GPU_BUFFER_USAGE_VERTEX,
25
+ } from '../gpu-usage';
26
+ import type { PersistentGpuDrivenState } from '../persistent-render-scene';
27
+ import type { PipelineBuilderShaderModuleFactory } from '../pipeline-builder';
28
+ import { type RasterItemKey, rasterItemKey } from '../record';
29
+ import type {
30
+ RenderPipelineFrame,
31
+ RenderPipelineGpuDrivenProjection,
32
+ RenderPipelineGpuDrivenShadowProjection,
33
+ } from '../render-pipeline';
34
+ import type { MeshGpuHandles } from '../render-system';
35
+ import {
36
+ buildRenderVisibilityViewDescriptors,
37
+ type CameraSnapshot,
38
+ type ExtractedFrame,
39
+ type RenderableSnapshot,
40
+ } from '../render-system-extract';
41
+ import {
42
+ buildBatchAlignedSubmission,
43
+ buildSubmissionCandidateMembership,
44
+ type GpuDrivenBatch,
45
+ type GpuDrivenCandidate,
46
+ type SubmissionCandidateMembership,
47
+ type SubmissionPlan,
48
+ } from './batch-topology';
49
+ import {
50
+ type CpuMultiViewVisibilityResult,
51
+ type CpuVisibilityCandidate,
52
+ executeCpuMultiViewVisibility,
53
+ GpuDrivenView,
54
+ } from './view-gpu';
55
+
56
+ const VERTEX_STAGE = 0x1;
57
+ const FRAGMENT_STAGE = 0x2;
58
+ const EMPTY_RESOURCE_CLASS = JSON.stringify({ textures: [], samplers: [], video: [] });
59
+
60
+ function supportsRigidGpuDrivenProjection(mesh: MeshGpuHandles): boolean {
61
+ const attributes = mesh.layoutProjection.attributes;
62
+ const required = ['position', 'normal', 'uv', 'tangent'] as const;
63
+ return (
64
+ attributes.length === required.length &&
65
+ attributes.every((attribute, index) => attribute.key === required[index])
66
+ );
67
+ }
68
+
69
+ export const GPU_DRIVEN_RIGID_UNLIT_WGSL = /* wgsl */ `
70
+ ${GPU_SCENE_WGSL}
71
+
72
+ struct ViewData {
73
+ slots: array<vec4<f32>, 49>,
74
+ };
75
+
76
+ @group(0) @binding(0) var<uniform> view: ViewData;
77
+ @group(1) @binding(0) var<storage, read> primitives: array<GpuScenePrimitive>;
78
+ @group(1) @binding(1) var<storage, read> instances: array<GpuSceneInstance>;
79
+ @group(1) @binding(2) var<storage, read> materials: array<GpuSceneMaterial>;
80
+ @group(1) @binding(3) var<storage, read> visibleItems: array<vec2<u32>>;
81
+ @group(1) @binding(4) var<storage, read> transforms: array<GpuSceneTransform>;
82
+
83
+ struct VertexInput {
84
+ @location(0) position: vec3<f32>,
85
+ };
86
+
87
+ struct VertexOutput {
88
+ @builtin(position) position: vec4<f32>,
89
+ @location(0) color: vec4<f32>,
90
+ };
91
+
92
+ @vertex
93
+ fn vs_main(input: VertexInput, @builtin(instance_index) instanceIndex: u32) -> VertexOutput {
94
+ let viewProjection = mat4x4<f32>(view.slots[0], view.slots[1], view.slots[2], view.slots[3]);
95
+ let visible = visibleItems[instanceIndex];
96
+ let sceneInstance = instances[visible.x];
97
+ let primitiveIndex = sceneInstance.primitiveIndex;
98
+ let primitive = primitives[primitiveIndex];
99
+ let material = materials[visible.y];
100
+ var output: VertexOutput;
101
+ let world = transforms[primitive.transformIndex].currentWorld * transforms[sceneInstance.transformIndex].currentWorld;
102
+ output.position = viewProjection * world * vec4<f32>(input.position, 1.0);
103
+ output.color = material.params0;
104
+ return output;
105
+ }
106
+
107
+ @fragment
108
+ fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
109
+ return input.color;
110
+ }
111
+ `;
112
+
113
+ /**
114
+ * Depth-only shadow raster companion for the shared GPU Scene visibility
115
+ * buffers. It deliberately has no material-dependent fragment stage: alpha
116
+ * test and custom ShadowCaster variants stay on the CPU contract until their
117
+ * own batch shader is available. Opaque casters use the same primitive,
118
+ * instance, transform and compact-visible tables as the main view.
119
+ */
120
+ export const GPU_DRIVEN_SHADOW_WGSL = /* wgsl */ `
121
+ ${GPU_SCENE_WGSL}
122
+
123
+ struct ShadowBatch {
124
+ lightViewProj: mat4x4<f32>,
125
+ visibleBase: u32,
126
+ pad0: u32,
127
+ pad1: u32,
128
+ pad2: u32,
129
+ };
130
+
131
+ @group(2) @binding(0) var<storage, read> primitives: array<GpuScenePrimitive>;
132
+ @group(2) @binding(1) var<storage, read> instances: array<GpuSceneInstance>;
133
+ @group(2) @binding(2) var<storage, read> transforms: array<GpuSceneTransform>;
134
+ @group(2) @binding(3) var<storage, read> visibleItems: array<vec2<u32>>;
135
+ @group(2) @binding(4) var<uniform> shadowBatch: ShadowBatch;
136
+
137
+ struct VertexInput {
138
+ @location(0) position: vec3<f32>,
139
+ };
140
+
141
+ @vertex
142
+ fn vs_main(input: VertexInput, @builtin(instance_index) instanceIndex: u32) -> @builtin(position) vec4<f32> {
143
+ let visible = visibleItems[shadowBatch.visibleBase + instanceIndex];
144
+ let sceneInstance = instances[visible.x];
145
+ let primitive = primitives[sceneInstance.primitiveIndex];
146
+ let world = transforms[primitive.transformIndex].currentWorld *
147
+ transforms[sceneInstance.transformIndex].currentWorld;
148
+ return shadowBatch.lightViewProj * world * vec4<f32>(input.position, 1.0);
149
+ }
150
+ `;
151
+
152
+ interface PreparedBatch {
153
+ readonly batch: GpuDrivenBatch;
154
+ readonly mesh: MeshGpuHandles;
155
+ readonly renderState: MaterialRenderState | undefined;
156
+ }
157
+
158
+ interface ProjectedBatch extends PreparedBatch {
159
+ readonly bindings: BindGroup;
160
+ readonly pipeline: RenderPipeline;
161
+ readonly vertex: GraphBuffer;
162
+ readonly index?: GraphBuffer;
163
+ }
164
+
165
+ function bufferBinding(
166
+ buffer: import('@forgeax/engine-rhi').Buffer,
167
+ offset?: number,
168
+ size?: number,
169
+ ) {
170
+ return {
171
+ kind: 'buffer' as const,
172
+ value: {
173
+ buffer,
174
+ ...(offset === undefined ? {} : { offset }),
175
+ ...(size === undefined ? {} : { size }),
176
+ },
177
+ };
178
+ }
179
+
180
+ function activeFrustum(camera: CameraSnapshot): Float32Array {
181
+ const projection = mat4.create();
182
+ if (camera.projection === 'orthographic') {
183
+ mat4.orthographic(
184
+ projection,
185
+ camera.orthoLeft,
186
+ camera.orthoRight,
187
+ camera.orthoBottom,
188
+ camera.orthoTop,
189
+ camera.near,
190
+ camera.far,
191
+ );
192
+ } else {
193
+ mat4.perspective(projection, camera.fov, camera.aspect, camera.near, camera.far);
194
+ }
195
+ const view = mat4.invert(mat4.create(), camera.world);
196
+ return frustum.fromViewProjection(
197
+ frustum.create(),
198
+ mat4.multiply(mat4.create(), projection, view),
199
+ );
200
+ }
201
+
202
+ export type GpuDrivenRasterEligibilityReason =
203
+ | 'missing-local-bounds-capability-lane'
204
+ | 'skinned-capability-lane'
205
+ | 'sprite-capability-lane'
206
+ | 'not-geometry-queue'
207
+ | 'unsafe-ordering'
208
+ | 'pbr-capability-lane'
209
+ | 'alpha-test-capability-lane'
210
+ | 'resource-bindings-capability-lane'
211
+ | 'transparent';
212
+
213
+ export interface GpuDrivenRasterEligibility {
214
+ readonly eligible: boolean;
215
+ readonly reason: GpuDrivenRasterEligibilityReason | undefined;
216
+ }
217
+
218
+ /**
219
+ * The current shader remains a deliberately narrow capability lane. Semantic
220
+ * batch keys still retain PBR/alpha/resource/double-sided identity so those
221
+ * objects can share the CPU/shadow contract without being misreported as
222
+ * rigid-unlit GPU-owned raster work.
223
+ */
224
+ export function gpuDrivenRasterEligibility(
225
+ snapshot: RenderableSnapshot,
226
+ batch: GpuDrivenBatch,
227
+ ): GpuDrivenRasterEligibility {
228
+ const material = snapshot.materials[batch.key.materialSlot] ?? snapshot.material;
229
+ const shader = material.materialShaderId ?? 'forgeax::default-unlit';
230
+ if (snapshot.localAabb === undefined) {
231
+ return { eligible: false, reason: 'missing-local-bounds-capability-lane' };
232
+ }
233
+ if (snapshot.skin !== undefined) return { eligible: false, reason: 'skinned-capability-lane' };
234
+ if (snapshot.spriteInstances !== undefined) {
235
+ return { eligible: false, reason: 'sprite-capability-lane' };
236
+ }
237
+ if (batch.key.queue !== RenderQueue.Geometry) {
238
+ return { eligible: false, reason: 'not-geometry-queue' };
239
+ }
240
+ if (!orderSafe(material.renderState)) return { eligible: false, reason: 'unsafe-ordering' };
241
+ if (batch.key.pbr || shader !== 'forgeax::default-unlit') {
242
+ return { eligible: false, reason: 'pbr-capability-lane' };
243
+ }
244
+ if (batch.key.alphaTest) return { eligible: false, reason: 'alpha-test-capability-lane' };
245
+ if (
246
+ batch.key.materialResourceClass !== EMPTY_RESOURCE_CLASS ||
247
+ material.baseColorTexture !== undefined
248
+ ) {
249
+ return { eligible: false, reason: 'resource-bindings-capability-lane' };
250
+ }
251
+ if (material.transparent === true) return { eligible: false, reason: 'transparent' };
252
+ return { eligible: true, reason: undefined };
253
+ }
254
+
255
+ function productionEligible(snapshot: RenderableSnapshot, batch: GpuDrivenBatch): boolean {
256
+ return gpuDrivenRasterEligibility(snapshot, batch).eligible;
257
+ }
258
+
259
+ function sameNumberArray(left: readonly number[], right: readonly number[]): boolean {
260
+ if (left.length !== right.length) return false;
261
+ for (let index = 0; index < left.length; index += 1) {
262
+ if (left[index] !== right[index]) return false;
263
+ }
264
+ return true;
265
+ }
266
+
267
+ function orderSafe(renderState: MaterialRenderState | undefined): boolean {
268
+ if (renderState === undefined) return true;
269
+ return (
270
+ renderState.blend === undefined &&
271
+ renderState.depthWriteEnabled !== false &&
272
+ renderState.depthCompare !== 'always' &&
273
+ renderState.stencil === undefined &&
274
+ renderState.stencilReadMask === undefined &&
275
+ renderState.stencilWriteMask === undefined
276
+ );
277
+ }
278
+
279
+ function meshSupportsBatch(mesh: MeshGpuHandles, batch: GpuDrivenBatch): boolean {
280
+ if (!supportsRigidGpuDrivenProjection(mesh)) return false;
281
+ return batch.key.drawKind === 'indexed'
282
+ ? mesh.indexed && mesh.indexBuffer !== null
283
+ : !mesh.indexed;
284
+ }
285
+
286
+ function filteredPlan(
287
+ source: SubmissionPlan,
288
+ slots: PersistentGpuDrivenState['slots'],
289
+ meshes: ReadonlyMap<number, MeshGpuHandles>,
290
+ ): {
291
+ readonly plan: SubmissionPlan;
292
+ readonly shadowPlan: SubmissionPlan;
293
+ readonly batches: readonly PreparedBatch[];
294
+ readonly itemKeys: ReadonlySet<RasterItemKey>;
295
+ readonly forwardItemKeys: ReadonlySet<RasterItemKey>;
296
+ } {
297
+ const slotByPrimitive = new Map(slots.map((slot) => [slot.slot, slot] as const));
298
+ const itemKeys = new Set<RasterItemKey>();
299
+ const forwardItemKeys = new Set<RasterItemKey>();
300
+ let hasEarlierQueue = false;
301
+ for (const slot of slots) {
302
+ for (const draw of slot.snapshot.gpuDrivenDraws ?? []) {
303
+ const key = rasterItemKey(
304
+ slot.snapshot.worldId,
305
+ slot.snapshot.entityKey,
306
+ draw.submeshIndex,
307
+ draw.passIndex,
308
+ );
309
+ if (draw.queue === RenderQueue.Geometry) forwardItemKeys.add(key);
310
+ if (draw.queue < RenderQueue.Geometry) hasEarlierQueue = true;
311
+ }
312
+ }
313
+ const candidatesByBatch = new Map<number, readonly GpuDrivenCandidate[]>();
314
+ const shadowCandidatesByBatch = new Map<number, readonly GpuDrivenCandidate[]>();
315
+ const meshByBatch = new Map<number, MeshGpuHandles>();
316
+ const renderStateByBatch = new Map<number, MaterialRenderState | undefined>();
317
+ for (const batch of source.batches) {
318
+ const shadowCandidates = batch.candidates.filter(
319
+ (candidate) => slotByPrimitive.has(candidate.primitiveIndex) && batch.key.shadowCaster,
320
+ );
321
+ if (shadowCandidates.length > 0) {
322
+ shadowCandidatesByBatch.set(batch.batchId, Object.freeze(shadowCandidates));
323
+ }
324
+ const candidates = batch.candidates.filter((candidate) => {
325
+ const slot = slotByPrimitive.get(candidate.primitiveIndex);
326
+ if (slot === undefined || !productionEligible(slot.snapshot, batch)) return false;
327
+ const mesh = meshes.get(slot.snapshot.assetHandle);
328
+ if (mesh === undefined || !meshSupportsBatch(mesh, batch)) return false;
329
+ const draw = slot.snapshot.gpuDrivenDraws?.[candidate.drawItemIndex];
330
+ if (draw === undefined) return false;
331
+ itemKeys.add(
332
+ rasterItemKey(
333
+ slot.snapshot.worldId,
334
+ slot.snapshot.entityKey,
335
+ draw.submeshIndex,
336
+ draw.passIndex,
337
+ ),
338
+ );
339
+ return true;
340
+ });
341
+ if (candidates.length === 0) continue;
342
+ const first = slotByPrimitive.get(candidates[0]?.primitiveIndex ?? -1);
343
+ const mesh = first === undefined ? undefined : meshes.get(first.snapshot.assetHandle);
344
+ if (mesh === undefined || first === undefined) continue;
345
+ candidatesByBatch.set(batch.batchId, Object.freeze(candidates));
346
+ meshByBatch.set(batch.batchId, mesh);
347
+ const material = first.snapshot.materials[batch.key.materialSlot] ?? first.snapshot.material;
348
+ renderStateByBatch.set(batch.batchId, material.renderState);
349
+ }
350
+ const sourceShadowPlan = buildBatchAlignedSubmission(source, shadowCandidatesByBatch);
351
+ // The typed graph encodes the GPU Geometry lane before CPU recording in the
352
+ // same raster pass. If an earlier queue or an ineligible Geometry item is
353
+ // present, publishing only a subset would change stable queue order. Fail
354
+ // closed for the whole GPU lane and let the CPU path own every item.
355
+ if (hasEarlierQueue || itemKeys.size !== forwardItemKeys.size) {
356
+ return {
357
+ plan: Object.freeze({
358
+ revision: source.revision,
359
+ batches: Object.freeze([]),
360
+ candidateCount: 0,
361
+ visibleCapacity: 0,
362
+ }),
363
+ shadowPlan: sourceShadowPlan,
364
+ batches: Object.freeze([]),
365
+ itemKeys: new Set<RasterItemKey>(),
366
+ forwardItemKeys,
367
+ };
368
+ }
369
+ const plan = buildBatchAlignedSubmission(source, candidatesByBatch);
370
+ const batches: PreparedBatch[] = [];
371
+ for (const batch of plan.batches) {
372
+ const mesh = meshByBatch.get(batch.batchId);
373
+ if (mesh === undefined) continue;
374
+ batches.push({
375
+ batch,
376
+ mesh,
377
+ renderState: renderStateByBatch.get(batch.batchId),
378
+ });
379
+ }
380
+ return {
381
+ plan,
382
+ // Shadow topology is intentionally derived from the unfiltered source
383
+ // plan. The rigid-unlit forward capability lane must not remove PBR,
384
+ // alpha-test, or double-sided casters from the ShadowCaster pool.
385
+ shadowPlan: sourceShadowPlan,
386
+ batches: Object.freeze(batches),
387
+ itemKeys,
388
+ forwardItemKeys,
389
+ };
390
+ }
391
+
392
+ function filterShadowSubmissionBySlots(
393
+ source: SubmissionPlan,
394
+ shadowCasterSlotIndices: ReadonlySet<number> | undefined,
395
+ ): SubmissionPlan {
396
+ if (shadowCasterSlotIndices === undefined) return source;
397
+ const candidatesByBatch = new Map<number, readonly GpuDrivenCandidate[]>();
398
+ for (const batch of source.batches) {
399
+ const candidates = batch.candidates.filter((candidate) =>
400
+ shadowCasterSlotIndices.has(candidate.primitiveIndex),
401
+ );
402
+ if (candidates.length > 0) {
403
+ candidatesByBatch.set(batch.batchId, Object.freeze(candidates));
404
+ }
405
+ }
406
+ return buildBatchAlignedSubmission(source, candidatesByBatch);
407
+ }
408
+
409
+ type FilteredProductionPlan = ReturnType<typeof filteredPlan>;
410
+
411
+ export interface GpuDrivenProductionInspection {
412
+ readonly gpuOwnedSnapshotsMaterialized: number;
413
+ readonly filteredPlanBuilds: number;
414
+ readonly gpuOwnedItemCount: number;
415
+ readonly candidateUploadBytes: number;
416
+ readonly batchUploadBytes: number;
417
+ readonly viewConstantsUploadBytes: number;
418
+ readonly batchBindGroupCreates: number;
419
+ readonly viewBindGroupCreates: number;
420
+ readonly topologyRevision: number | undefined;
421
+ readonly validatedGpuOwnedRows: number;
422
+ readonly cpuFallbackDrawItems: number;
423
+ readonly cpuVisibility: CpuMultiViewVisibilityResult | undefined;
424
+ readonly shadowBatchCount: number;
425
+ readonly shadowCandidateCount: number;
426
+ readonly shadowDrawCount: number;
427
+ readonly faults: readonly GpuDrivenVisibilityFault[];
428
+ }
429
+
430
+ export type GpuDrivenVisibilityFaultCode =
431
+ | 'visibility-overflow'
432
+ | 'gpu-capability-unavailable'
433
+ | 'gpu-scene-fact-unavailable'
434
+ | 'device-recovery-required'
435
+ | 'gpu-resource-failed';
436
+
437
+ export interface GpuDrivenVisibilityFault {
438
+ readonly code: GpuDrivenVisibilityFaultCode;
439
+ readonly viewId: string;
440
+ readonly revision: number;
441
+ readonly fallback: 'cpu-batch-contract' | 'scene-rebuild';
442
+ readonly detail: string;
443
+ }
444
+
445
+ class GpuDrivenRigidRaster {
446
+ private readonly pipelines = new Map<string, RenderPipeline>();
447
+
448
+ private constructor(
449
+ private readonly device: RhiDevice,
450
+ private readonly layout: BindGroupLayout,
451
+ private readonly pipelineLayout: import('@forgeax/engine-rhi').PipelineLayout,
452
+ private readonly module: ShaderModule,
453
+ ) {}
454
+
455
+ static create(input: {
456
+ readonly device: RhiDevice;
457
+ readonly shaderModuleFactory: PipelineBuilderShaderModuleFactory;
458
+ readonly viewBindGroupLayout: BindGroupLayout;
459
+ }): Result<GpuDrivenRigidRaster, RhiError> {
460
+ const layout = input.device.createBindGroupLayout({
461
+ label: 'gpu-driven-rigid-raster-bgl',
462
+ entries: [
463
+ { binding: 0, visibility: VERTEX_STAGE, buffer: { type: 'read-only-storage' } },
464
+ {
465
+ binding: 1,
466
+ visibility: VERTEX_STAGE,
467
+ buffer: { type: 'read-only-storage' },
468
+ },
469
+ {
470
+ binding: 2,
471
+ visibility: VERTEX_STAGE | FRAGMENT_STAGE,
472
+ buffer: { type: 'read-only-storage' },
473
+ },
474
+ { binding: 3, visibility: VERTEX_STAGE, buffer: { type: 'read-only-storage' } },
475
+ { binding: 4, visibility: VERTEX_STAGE, buffer: { type: 'read-only-storage' } },
476
+ ],
477
+ });
478
+ if (!layout.ok) return layout;
479
+ const pipelineLayout = input.device.createPipelineLayout({
480
+ label: 'gpu-driven-rigid-raster-pl',
481
+ bindGroupLayouts: [input.viewBindGroupLayout, layout.value],
482
+ });
483
+ if (!pipelineLayout.ok) return pipelineLayout;
484
+ const module = input.shaderModuleFactory.createShaderModule({
485
+ label: 'gpu-driven-rigid-unlit',
486
+ code: GPU_DRIVEN_RIGID_UNLIT_WGSL,
487
+ });
488
+ if (!module.ok) return module;
489
+ return ok(
490
+ new GpuDrivenRigidRaster(input.device, layout.value, pipelineLayout.value, module.value),
491
+ );
492
+ }
493
+
494
+ pipeline(
495
+ format: string,
496
+ sampleCount: 1 | 4,
497
+ vertexStride: number,
498
+ topology: GpuDrivenBatch['key']['topology'],
499
+ stripIndexFormat: 'uint16' | 'uint32' | undefined,
500
+ renderState: MaterialRenderState | undefined,
501
+ ): Result<RenderPipeline, RhiError> {
502
+ const key = `${format}|${sampleCount}|${vertexStride}|${topology}|${stripIndexFormat ?? ''}|${JSON.stringify(renderState ?? null)}`;
503
+ const cached = this.pipelines.get(key);
504
+ if (cached !== undefined) return ok(cached);
505
+ const created = this.device.createRenderPipeline({
506
+ label: `gpu-driven-rigid-unlit.${key}`,
507
+ layout: this.pipelineLayout as unknown as GPUPipelineLayout,
508
+ vertex: {
509
+ module: this.module as unknown as GPUShaderModule,
510
+ entryPoint: 'vs_main',
511
+ buffers: [
512
+ {
513
+ arrayStride: vertexStride,
514
+ stepMode: 'vertex',
515
+ attributes: [{ shaderLocation: 0, offset: 0, format: 'float32x3' }],
516
+ },
517
+ ],
518
+ },
519
+ fragment: {
520
+ module: this.module as unknown as GPUShaderModule,
521
+ entryPoint: 'fs_main',
522
+ targets: [
523
+ {
524
+ format: format as GPUTextureFormat,
525
+ ...(renderState?.blend === undefined ? {} : { blend: renderState.blend }),
526
+ },
527
+ ],
528
+ },
529
+ primitive: {
530
+ topology: topology as GPUPrimitiveTopology,
531
+ cullMode: renderState?.cullMode ?? 'back',
532
+ frontFace: renderState?.frontFace ?? 'ccw',
533
+ ...(stripIndexFormat === undefined ? {} : { stripIndexFormat }),
534
+ },
535
+ depthStencil: {
536
+ format: 'depth24plus-stencil8',
537
+ depthWriteEnabled: renderState?.depthWriteEnabled ?? true,
538
+ depthCompare: renderState?.depthCompare ?? 'less',
539
+ ...(renderState?.stencil === undefined
540
+ ? {}
541
+ : {
542
+ stencilFront: renderState.stencil,
543
+ stencilBack: renderState.stencil,
544
+ stencilReadMask: renderState.stencilReadMask,
545
+ stencilWriteMask: renderState.stencilWriteMask,
546
+ }),
547
+ },
548
+ ...(sampleCount === 4
549
+ ? {
550
+ multisample: {
551
+ count: 4,
552
+ alphaToCoverageEnabled: renderState?.alphaToCoverageEnabled ?? false,
553
+ },
554
+ }
555
+ : {}),
556
+ });
557
+ if (!created.ok) return created;
558
+ this.pipelines.set(key, created.value);
559
+ return created;
560
+ }
561
+
562
+ bindGroup(
563
+ scene: PersistentGpuDrivenState['scene'],
564
+ view: GpuDrivenView,
565
+ batch: GpuDrivenBatch,
566
+ ): Result<BindGroup, RhiError> {
567
+ const visible = view.visibleBuffer;
568
+ if (visible === undefined) {
569
+ return err(
570
+ new RhiError({
571
+ code: 'internal-error',
572
+ expected: 'GPU-driven view buffers exist after a successful view update',
573
+ hint: 'prepare the GPU-driven view before projecting its raster batches',
574
+ }),
575
+ );
576
+ }
577
+ return this.device.createBindGroup({
578
+ label: `gpu-driven-rigid-batch-${batch.batchId}`,
579
+ layout: this.layout,
580
+ entries: [
581
+ { binding: 0, resource: bufferBinding(scene.primitiveBuffer) },
582
+ { binding: 1, resource: bufferBinding(scene.instanceBuffer) },
583
+ { binding: 2, resource: bufferBinding(scene.materialBuffer) },
584
+ {
585
+ binding: 3,
586
+ resource: bufferBinding(visible, batch.visibleBase * 8, batch.visibleCapacity * 8),
587
+ },
588
+ {
589
+ binding: 4,
590
+ resource: bufferBinding(scene.transformBuffer),
591
+ },
592
+ ],
593
+ });
594
+ }
595
+ }
596
+
597
+ interface PreparedShadowBatch {
598
+ readonly batch: GpuDrivenBatch;
599
+ readonly mesh: MeshGpuHandles;
600
+ readonly pipeline: RenderPipeline;
601
+ readonly uniformOffset: number;
602
+ }
603
+
604
+ interface PreparedShadowView {
605
+ readonly cascadeIndex: number;
606
+ readonly view: GpuDrivenView;
607
+ readonly plan: SubmissionPlan;
608
+ readonly batches: readonly PreparedShadowBatch[];
609
+ readonly bindGroup: BindGroup;
610
+ readonly graphLabel: string;
611
+ readonly graphResources?: import('./view-gpu').GpuDrivenViewGraphResources;
612
+ }
613
+
614
+ class GpuDrivenShadowRaster {
615
+ private readonly pipelines = new Map<string, RenderPipeline>();
616
+ private readonly uniformBuffers = new Set<import('@forgeax/engine-rhi').Buffer>();
617
+ private readonly uniformByCascade = new Map<number, import('@forgeax/engine-rhi').Buffer>();
618
+ private readonly uniformCapacities = new Map<number, number>();
619
+
620
+ private constructor(
621
+ private readonly device: RhiDevice,
622
+ private readonly layout: BindGroupLayout,
623
+ private readonly pipelineLayout: import('@forgeax/engine-rhi').PipelineLayout,
624
+ private readonly module: ShaderModule,
625
+ ) {}
626
+
627
+ static create(input: {
628
+ readonly device: RhiDevice;
629
+ readonly shaderModuleFactory: PipelineBuilderShaderModuleFactory;
630
+ readonly viewBindGroupLayout: BindGroupLayout;
631
+ readonly materialBindGroupLayout: BindGroupLayout;
632
+ }): Result<GpuDrivenShadowRaster, RhiError> {
633
+ const layout = input.device.createBindGroupLayout({
634
+ label: 'gpu-driven-shadow-raster-bgl',
635
+ entries: [
636
+ { binding: 0, visibility: VERTEX_STAGE, buffer: { type: 'read-only-storage' } },
637
+ { binding: 1, visibility: VERTEX_STAGE, buffer: { type: 'read-only-storage' } },
638
+ { binding: 2, visibility: VERTEX_STAGE, buffer: { type: 'read-only-storage' } },
639
+ { binding: 3, visibility: VERTEX_STAGE, buffer: { type: 'read-only-storage' } },
640
+ {
641
+ binding: 4,
642
+ visibility: VERTEX_STAGE,
643
+ buffer: { type: 'uniform', hasDynamicOffset: true },
644
+ },
645
+ ],
646
+ });
647
+ if (!layout.ok) return layout;
648
+ const pipelineLayout = input.device.createPipelineLayout({
649
+ label: 'gpu-driven-shadow-raster-pl',
650
+ bindGroupLayouts: [input.viewBindGroupLayout, input.materialBindGroupLayout, layout.value],
651
+ });
652
+ if (!pipelineLayout.ok) return pipelineLayout;
653
+ const module = input.shaderModuleFactory.createShaderModule({
654
+ label: 'gpu-driven-shadow-raster',
655
+ code: GPU_DRIVEN_SHADOW_WGSL,
656
+ });
657
+ if (!module.ok) return module;
658
+ return ok(
659
+ new GpuDrivenShadowRaster(input.device, layout.value, pipelineLayout.value, module.value),
660
+ );
661
+ }
662
+
663
+ prepareView(input: {
664
+ readonly cascadeIndex: number;
665
+ readonly scene: PersistentGpuDrivenState['scene'];
666
+ readonly view: GpuDrivenView;
667
+ readonly plan: SubmissionPlan;
668
+ readonly lightViewProj: Float32Array;
669
+ readonly meshes: ReadonlyMap<number, MeshGpuHandles>;
670
+ readonly graphLabel: string;
671
+ }): Result<PreparedShadowView | undefined, RhiError> {
672
+ const eligibleBatches: Array<{
673
+ readonly batch: GpuDrivenBatch;
674
+ readonly mesh: MeshGpuHandles;
675
+ }> = [];
676
+ for (const batch of input.plan.batches) {
677
+ // The GPU shadow shader is the opaque rigid capability lane. Alpha-test,
678
+ // custom material shadow shaders, non-rigid geometry and line/point
679
+ // topology remain on the same batch-aligned CPU fallback contract.
680
+ if (batch.key.alphaTest) continue;
681
+ if (batch.key.topology !== 'triangle-list' && batch.key.topology !== 'triangle-strip') {
682
+ continue;
683
+ }
684
+ const mesh = input.meshes.get(batch.key.assetHandle);
685
+ if (mesh === undefined || !supportsRigidGpuDrivenProjection(mesh)) continue;
686
+ if (batch.key.drawKind === 'indexed' && (!mesh.indexed || mesh.indexBuffer === null)) {
687
+ continue;
688
+ }
689
+ if (batch.key.drawKind === 'non-indexed' && mesh.indexed) continue;
690
+ eligibleBatches.push({ batch, mesh });
691
+ }
692
+ if (eligibleBatches.length === 0 || input.view.visibleBuffer === undefined)
693
+ return ok(undefined);
694
+
695
+ const requiredBytes = Math.max(256, eligibleBatches.length * 256);
696
+ let uniformBuffer = this.uniformByCascade.get(input.cascadeIndex);
697
+ const currentCapacity = this.uniformCapacities.get(input.cascadeIndex) ?? 0;
698
+ if (uniformBuffer === undefined || currentCapacity < requiredBytes) {
699
+ const created = this.device.createBuffer({
700
+ label: `gpu-driven-shadow-cascade-${input.cascadeIndex}-uniforms`,
701
+ size: requiredBytes,
702
+ usage: GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST,
703
+ mappedAtCreation: false,
704
+ });
705
+ if (!created.ok) return created;
706
+ uniformBuffer = created.value;
707
+ this.uniformBuffers.add(uniformBuffer);
708
+ this.uniformByCascade.set(input.cascadeIndex, uniformBuffer);
709
+ this.uniformCapacities.set(input.cascadeIndex, requiredBytes);
710
+ }
711
+ const payload = new Uint8Array(requiredBytes);
712
+ for (let index = 0; index < eligibleBatches.length; index += 1) {
713
+ const item = eligibleBatches[index];
714
+ if (item === undefined) continue;
715
+ const offset = index * 256;
716
+ new Float32Array(payload.buffer, offset, 16).set(input.lightViewProj.subarray(0, 16));
717
+ new DataView(payload.buffer).setUint32(offset + 64, item.batch.visibleBase, true);
718
+ }
719
+ const write = this.device.queue.writeBuffer(uniformBuffer, 0, payload);
720
+ if (!write.ok) return write;
721
+ const visible = input.view.visibleBuffer;
722
+ const binding = this.device.createBindGroup({
723
+ label: `gpu-driven-shadow-cascade-${input.cascadeIndex}-bg`,
724
+ layout: this.layout,
725
+ entries: [
726
+ { binding: 0, resource: bufferBinding(input.scene.primitiveBuffer) },
727
+ { binding: 1, resource: bufferBinding(input.scene.instanceBuffer) },
728
+ { binding: 2, resource: bufferBinding(input.scene.transformBuffer) },
729
+ { binding: 3, resource: bufferBinding(visible) },
730
+ {
731
+ binding: 4,
732
+ resource: {
733
+ kind: 'buffer',
734
+ value: { buffer: uniformBuffer, offset: 0, size: 80 },
735
+ },
736
+ },
737
+ ],
738
+ });
739
+ if (!binding.ok) return binding;
740
+ const batches: PreparedShadowBatch[] = [];
741
+ for (let index = 0; index < eligibleBatches.length; index += 1) {
742
+ const item = eligibleBatches[index];
743
+ if (item === undefined) continue;
744
+ const pipeline = this.pipeline(item.mesh, item.batch);
745
+ if (!pipeline.ok) return pipeline;
746
+ batches.push({
747
+ batch: item.batch,
748
+ mesh: item.mesh,
749
+ pipeline: pipeline.value,
750
+ uniformOffset: index * 256,
751
+ });
752
+ }
753
+ return ok({
754
+ cascadeIndex: input.cascadeIndex,
755
+ view: input.view,
756
+ plan: input.plan,
757
+ batches: Object.freeze(batches),
758
+ bindGroup: binding.value,
759
+ graphLabel: input.graphLabel,
760
+ });
761
+ }
762
+
763
+ encode(
764
+ prepared: PreparedShadowView,
765
+ resources: GraphResourceResolver,
766
+ graphResources: import('./view-gpu').GpuDrivenViewGraphResources,
767
+ pass: import('@forgeax/engine-rhi').RhiRenderPassEncoder,
768
+ ): void {
769
+ const indirect = resources.buffer(graphResources.indirect);
770
+ if (!indirect.ok) throw indirect.error;
771
+ let currentPipeline: RenderPipeline | undefined;
772
+ let currentVertex: import('@forgeax/engine-rhi').Buffer | undefined;
773
+ let currentIndex: import('@forgeax/engine-rhi').Buffer | undefined;
774
+ for (const batch of prepared.batches) {
775
+ if (currentPipeline !== batch.pipeline) {
776
+ pass.setPipeline(batch.pipeline);
777
+ currentPipeline = batch.pipeline;
778
+ }
779
+ pass.setBindGroup(2, prepared.bindGroup, [batch.uniformOffset]);
780
+ if (currentVertex !== batch.mesh.vertexBuffer.handle) {
781
+ pass.setVertexBuffer(0, batch.mesh.vertexBuffer.handle);
782
+ currentVertex = batch.mesh.vertexBuffer.handle;
783
+ }
784
+ if (batch.mesh.indexBuffer !== null && batch.mesh.indexed) {
785
+ if (currentIndex !== batch.mesh.indexBuffer.handle) {
786
+ pass.setIndexBuffer(batch.mesh.indexBuffer.handle, batch.mesh.indexFormat);
787
+ currentIndex = batch.mesh.indexBuffer.handle;
788
+ }
789
+ pass.drawIndexedIndirect(indirect.value, batch.batch.indirectOffset);
790
+ } else {
791
+ pass.drawIndirect(indirect.value, batch.batch.indirectOffset);
792
+ }
793
+ }
794
+ }
795
+
796
+ dispose(): void {
797
+ for (const buffer of this.uniformBuffers) this.device.destroyBuffer(buffer);
798
+ this.uniformBuffers.clear();
799
+ this.uniformByCascade.clear();
800
+ this.uniformCapacities.clear();
801
+ this.pipelines.clear();
802
+ }
803
+
804
+ private pipeline(mesh: MeshGpuHandles, batch: GpuDrivenBatch): Result<RenderPipeline, RhiError> {
805
+ const stripIndexFormat =
806
+ batch.key.drawKind === 'indexed' && batch.key.topology === 'triangle-strip'
807
+ ? mesh.indexFormat
808
+ : undefined;
809
+ const key = `${batch.key.topology}|${stripIndexFormat ?? ''}|${batch.key.doubleSided ? 'none' : 'back'}`;
810
+ const cached = this.pipelines.get(key);
811
+ if (cached !== undefined) return ok(cached);
812
+ const created = this.device.createRenderPipeline({
813
+ label: `gpu-driven-shadow-${key}`,
814
+ layout: this.pipelineLayout as unknown as GPUPipelineLayout,
815
+ vertex: {
816
+ module: this.module as unknown as GPUShaderModule,
817
+ entryPoint: 'vs_main',
818
+ buffers: [
819
+ {
820
+ arrayStride: 48,
821
+ stepMode: 'vertex',
822
+ attributes: [{ shaderLocation: 0, offset: 0, format: 'float32x3' }],
823
+ },
824
+ ],
825
+ },
826
+ primitive: {
827
+ topology: batch.key.topology as GPUPrimitiveTopology,
828
+ cullMode: batch.key.doubleSided ? 'none' : 'back',
829
+ frontFace: 'ccw',
830
+ ...(stripIndexFormat === undefined ? {} : { stripIndexFormat }),
831
+ },
832
+ depthStencil: {
833
+ format: 'depth32float',
834
+ depthWriteEnabled: true,
835
+ depthCompare: 'less',
836
+ },
837
+ });
838
+ if (!created.ok) return created;
839
+ this.pipelines.set(key, created.value);
840
+ return created;
841
+ }
842
+ }
843
+
844
+ export interface PreparedGpuDrivenFrame {
845
+ readonly topologySignature: string;
846
+ readonly ownedItemKeys: ReadonlySet<RasterItemKey>;
847
+ readonly ownsAllForwardItems: boolean;
848
+ /** Batch-aligned ShadowCaster candidates from the same topology revision. */
849
+ readonly shadowSubmission: SubmissionPlan;
850
+ project(
851
+ graph: RenderGraphBuilder<RenderPipelineFrame>,
852
+ format: string,
853
+ sampleCount: 1 | 4,
854
+ ): Result<RenderPipelineGpuDrivenProjection, RenderGraphError | RhiError>;
855
+ }
856
+
857
+ /**
858
+ * Per-view production submission. The batch-aligned plan owns candidate
859
+ * membership; candidateIndexByStableId is a one-way adapter for the existing
860
+ * direct RHI draw encoder and must not be used to generate another view list.
861
+ */
862
+ export interface MultiViewProductionSubmission {
863
+ readonly source: 'multi-view-indirect';
864
+ readonly viewId: string;
865
+ readonly kind: 'main' | 'cascade';
866
+ readonly cascadeIndex: number | undefined;
867
+ readonly volumeRevision: number | undefined;
868
+ readonly spatialIndexRevision: number | undefined;
869
+ readonly overflow: boolean;
870
+ readonly plan: SubmissionPlan;
871
+ readonly candidateIndexByStableId: ReadonlyMap<number, number>;
872
+ /** Immutable candidate membership adapter shared by CPU shadow fallback and observation. */
873
+ readonly candidateIndices: ReadonlySet<number>;
874
+ readonly faults: readonly GpuDrivenVisibilityFault[];
875
+ }
876
+
877
+ export class GpuDrivenProduction {
878
+ private view: GpuDrivenView | undefined;
879
+ private raster: GpuDrivenRigidRaster | undefined;
880
+ private shadowRaster: GpuDrivenShadowRaster | undefined;
881
+ private readonly shadowViews = new Map<number, GpuDrivenView>();
882
+ private preparedShadowViews: readonly PreparedShadowView[] = [];
883
+ private readonly sceneIdentities = new WeakMap<object, number>();
884
+ private nextSceneIdentity = 1;
885
+ private filteredCache:
886
+ | {
887
+ readonly source: SubmissionPlan;
888
+ readonly meshResidencyEpoch: number;
889
+ readonly value: FilteredProductionPlan;
890
+ }
891
+ | undefined;
892
+ private gpuOwnedSnapshotsMaterialized = 0;
893
+ private filteredPlanBuilds = 0;
894
+ private gpuOwnedItemCount = 0;
895
+ private batchBindGroupCreates = 0;
896
+ private validatedGpuOwnedRows = 0;
897
+ private cpuFallbackDrawItems = 0;
898
+ private cpuVisibility: CpuMultiViewVisibilityResult | undefined;
899
+ /** Candidate-domain ShadowCaster membership projected onto persistent slots. */
900
+ private shadowCasterSlotIndices: ReadonlySet<number> | undefined;
901
+ private visibilityViews: readonly import('../render-system-extract').RenderVisibilityViewDescriptor[] =
902
+ [];
903
+ private shadowSubmission: SubmissionPlan | undefined;
904
+ private readonly shadowPlanCache = new Map<
905
+ string,
906
+ {
907
+ readonly source: SubmissionPlan;
908
+ readonly stableIds: readonly number[];
909
+ readonly generations: readonly number[];
910
+ readonly plan: SubmissionPlan;
911
+ }
912
+ >();
913
+ /**
914
+ * Reverse index for the immutable shadow topology. Cascade views provide
915
+ * stable slot ids, so rebuilding a view plan should walk the selected view
916
+ * domain instead of filtering every source candidate for every cascade.
917
+ */
918
+ private shadowCandidateMembership: SubmissionCandidateMembership | undefined;
919
+ private faults: readonly GpuDrivenVisibilityFault[] = [];
920
+ private signatureCache:
921
+ | {
922
+ readonly filtered: FilteredProductionPlan;
923
+ readonly sceneIdentity: number;
924
+ readonly viewResourceGeneration: number;
925
+ readonly meshResidencyEpoch: number;
926
+ readonly value: string;
927
+ }
928
+ | undefined;
929
+
930
+ constructor(
931
+ private readonly device: RhiDevice,
932
+ private readonly shaderModuleFactory: PipelineBuilderShaderModuleFactory,
933
+ ) {}
934
+
935
+ prepareCpuVisibility(input: {
936
+ readonly scene: PersistentGpuDrivenState | undefined;
937
+ readonly frame: ExtractedFrame;
938
+ readonly camera: CameraSnapshot | undefined;
939
+ }): CpuMultiViewVisibilityResult | undefined {
940
+ this.faults = [];
941
+ if (input.scene === undefined) {
942
+ this.cpuVisibility = undefined;
943
+ this.visibilityViews = [];
944
+ this.shadowCasterSlotIndices = undefined;
945
+ this.shadowPlanCache.clear();
946
+ this.shadowCandidateMembership = undefined;
947
+ return undefined;
948
+ }
949
+ const descriptors = buildRenderVisibilityViewDescriptors({
950
+ camera: input.camera,
951
+ directionalCsm: input.frame.lights.directionalCsm,
952
+ spatialIndexRevision: input.scene.scene.inspect().spatialIndex?.revision,
953
+ });
954
+ const batchBySlot = new Map<
955
+ number,
956
+ { readonly batchId: number; readonly instanceOrdinal: number }
957
+ >();
958
+ const capacityByBatch = new Map<number, number>();
959
+ for (const batch of input.scene.plan.batches) {
960
+ capacityByBatch.set(batch.batchId, batch.visibleCapacity);
961
+ for (const candidate of batch.candidates) {
962
+ if (!batchBySlot.has(candidate.primitiveIndex)) {
963
+ batchBySlot.set(candidate.primitiveIndex, {
964
+ batchId: batch.batchId,
965
+ instanceOrdinal: candidate.instanceOrdinal,
966
+ });
967
+ }
968
+ }
969
+ }
970
+ const candidateDomain = input.frame.candidateDomain;
971
+ const needsCandidateIdentityFallback =
972
+ candidateDomain !== undefined ||
973
+ input.scene.slots.some((slot) => slot.snapshot.candidateIndex === undefined);
974
+ let candidateIndexByIdentity: ReadonlyMap<string, number> = new Map<string, number>();
975
+ if (needsCandidateIdentityFallback) {
976
+ if (candidateDomain !== undefined) {
977
+ // The persistent candidate domain is the only owner that remains
978
+ // correct after projection removals compact the candidate array. A
979
+ // projection slot may still carry the old snapshot candidateIndex;
980
+ // never let that stale producer hint override the domain join.
981
+ candidateIndexByIdentity = candidateDomain.indexByIdentity;
982
+ } else {
983
+ const fallback = new Map<string, number>();
984
+ for (let index = 0; index < (input.frame.candidateRenderables?.length ?? 0); index += 1) {
985
+ const candidate = input.frame.candidateRenderables?.[index];
986
+ if (candidate !== undefined) {
987
+ fallback.set(`${candidate.worldId}:${candidate.entityKey}`, index);
988
+ }
989
+ }
990
+ candidateIndexByIdentity = fallback;
991
+ }
992
+ }
993
+ const candidatesBySlot = new Map<number, CpuVisibilityCandidate>();
994
+ const shadowCasterCandidateIndices =
995
+ input.frame.candidateDomain?.membership.shadowCasterCandidateIndices ??
996
+ input.frame.candidateDispatchMembership?.shadowCasterCandidateIndices;
997
+ const shadowCasterSlotIndices =
998
+ shadowCasterCandidateIndices === undefined ? undefined : new Set<number>();
999
+ for (const slot of input.scene.slots) {
1000
+ const batch = batchBySlot.get(slot.slot);
1001
+ const worldAabb =
1002
+ slot.fact.bounds.status === 'present' ? slot.fact.bounds.worldAabb : undefined;
1003
+ const candidateIndex =
1004
+ candidateDomain === undefined
1005
+ ? (slot.snapshot.candidateIndex ??
1006
+ candidateIndexByIdentity.get(`${slot.worldId}:${slot.entityKey}`))
1007
+ : candidateIndexByIdentity.get(`${slot.worldId}:${slot.entityKey}`);
1008
+ const dispatchShadowCaster =
1009
+ shadowCasterCandidateIndices === undefined ||
1010
+ candidateIndex === undefined ||
1011
+ shadowCasterCandidateIndices.has(candidateIndex);
1012
+ if (
1013
+ dispatchShadowCaster &&
1014
+ slot.fact.casterEligibility !== 'ineligible' &&
1015
+ shadowCasterSlotIndices !== undefined
1016
+ ) {
1017
+ shadowCasterSlotIndices.add(slot.slot);
1018
+ }
1019
+ candidatesBySlot.set(slot.slot, {
1020
+ stableId: slot.slot,
1021
+ generation: slot.generation,
1022
+ candidateIndex,
1023
+ worldAabb,
1024
+ // Unknown authoring facts remain conservative. Only an explicit
1025
+ // ineligible fact may remove a candidate from a shadow view.
1026
+ casterEligible: slot.fact.casterEligibility !== 'ineligible' && dispatchShadowCaster,
1027
+ batchId: batch?.batchId,
1028
+ instanceOrdinal: batch?.instanceOrdinal,
1029
+ });
1030
+ }
1031
+ this.shadowCasterSlotIndices =
1032
+ shadowCasterSlotIndices === undefined
1033
+ ? undefined
1034
+ : (Object.freeze(shadowCasterSlotIndices) as ReadonlySet<number>);
1035
+ const candidatesByView = new Map<string, readonly CpuVisibilityCandidate[]>();
1036
+ const candidateUnion = new Map<number, CpuVisibilityCandidate>();
1037
+ for (const view of descriptors) {
1038
+ const hits =
1039
+ view.broadphaseWorldAabb === undefined || input.scene.projection === undefined
1040
+ ? input.scene.slots
1041
+ : input.scene.projection.querySpatialIndex(view.broadphaseWorldAabb).hits;
1042
+ const domain: CpuVisibilityCandidate[] = [];
1043
+ for (const hit of hits) {
1044
+ const candidate = candidatesBySlot.get(hit.slot);
1045
+ if (candidate === undefined) continue;
1046
+ domain.push(candidate);
1047
+ candidateUnion.set(candidate.stableId, candidate);
1048
+ }
1049
+ candidatesByView.set(view.viewId, Object.freeze(domain));
1050
+ }
1051
+ const candidates = [...candidateUnion.values()];
1052
+ // Main visibility is independent from the GPU batch domain. Keep its
1053
+ // compact array large enough for non-GPU renderables in the broadphase
1054
+ // domain, otherwise a valid CPU-only object would be reported as an
1055
+ // artificial visibility overflow.
1056
+ const capacity = Math.max(1, input.scene.plan.visibleCapacity, candidates.length);
1057
+ const capacityByView = new Map(descriptors.map((view) => [view.viewId, capacity] as const));
1058
+ this.visibilityViews = descriptors;
1059
+ this.cpuVisibility = executeCpuMultiViewVisibility({
1060
+ views: descriptors,
1061
+ candidates,
1062
+ candidatesByView,
1063
+ capacityByView,
1064
+ capacityByBatch,
1065
+ });
1066
+ return this.cpuVisibility;
1067
+ }
1068
+
1069
+ prepare(input: {
1070
+ readonly scene: PersistentGpuDrivenState | undefined;
1071
+ readonly camera: CameraSnapshot;
1072
+ readonly meshes: ReadonlyMap<number, MeshGpuHandles>;
1073
+ readonly viewBindGroupLayout: BindGroupLayout;
1074
+ readonly materialBindGroupLayout?: BindGroupLayout;
1075
+ readonly meshResidencyEpoch: number;
1076
+ readonly hdrp: boolean;
1077
+ }): Result<PreparedGpuDrivenFrame | undefined, RhiError> {
1078
+ this.gpuOwnedSnapshotsMaterialized = 0;
1079
+ this.filteredPlanBuilds = 0;
1080
+ this.batchBindGroupCreates = 0;
1081
+ this.validatedGpuOwnedRows = 0;
1082
+ this.cpuFallbackDrawItems = 0;
1083
+ this.shadowSubmission = undefined;
1084
+ this.shadowCandidateMembership = undefined;
1085
+ this.preparedShadowViews = [];
1086
+ if (input.scene === undefined) {
1087
+ this.gpuOwnedItemCount = 0;
1088
+ return ok(undefined);
1089
+ }
1090
+ const scene = input.scene;
1091
+ let filtered = this.filteredCache?.value;
1092
+ if (
1093
+ filtered === undefined ||
1094
+ this.filteredCache?.source !== scene.plan ||
1095
+ this.filteredCache.meshResidencyEpoch !== input.meshResidencyEpoch
1096
+ ) {
1097
+ filtered = filteredPlan(scene.plan, scene.slots, input.meshes);
1098
+ this.filteredCache = {
1099
+ source: scene.plan,
1100
+ meshResidencyEpoch: input.meshResidencyEpoch,
1101
+ value: filtered,
1102
+ };
1103
+ this.gpuOwnedSnapshotsMaterialized = scene.slots.length;
1104
+ this.filteredPlanBuilds = 1;
1105
+ }
1106
+ this.gpuOwnedItemCount = filtered.itemKeys.size;
1107
+ const shadowSubmission = filterShadowSubmissionBySlots(
1108
+ filtered.shadowPlan,
1109
+ this.shadowCasterSlotIndices,
1110
+ );
1111
+ this.shadowSubmission = shadowSubmission;
1112
+ if (
1113
+ input.hdrp ||
1114
+ !this.device.caps.compute ||
1115
+ !this.device.caps.storageBuffer ||
1116
+ !this.device.caps.indirectDrawing ||
1117
+ (filtered.batches.length === 0 && shadowSubmission.batches.length === 0)
1118
+ ) {
1119
+ if (shadowSubmission.candidateCount > 0) {
1120
+ this.addFault({
1121
+ code: 'gpu-capability-unavailable',
1122
+ viewId: 'all',
1123
+ revision: shadowSubmission.revision,
1124
+ fallback: 'cpu-batch-contract',
1125
+ detail: input.hdrp
1126
+ ? 'HDRP production raster does not expose the rigid shadow capability lane'
1127
+ : 'compute, storage-buffer, indirect-drawing, or forward batch capability is unavailable',
1128
+ });
1129
+ }
1130
+ return ok(undefined);
1131
+ }
1132
+ if (this.view === undefined) {
1133
+ const created = GpuDrivenView.create({
1134
+ device: this.device,
1135
+ shaderModuleFactory: this.shaderModuleFactory,
1136
+ });
1137
+ if (!created.ok) {
1138
+ this.addRhiFault(created.error, 'all', filtered.plan.revision);
1139
+ return created;
1140
+ }
1141
+ this.view = created.value;
1142
+ }
1143
+ if (this.raster === undefined) {
1144
+ const created = GpuDrivenRigidRaster.create({
1145
+ device: this.device,
1146
+ shaderModuleFactory: this.shaderModuleFactory,
1147
+ viewBindGroupLayout: input.viewBindGroupLayout,
1148
+ });
1149
+ if (!created.ok) {
1150
+ this.addRhiFault(created.error, 'all', filtered.plan.revision);
1151
+ return created;
1152
+ }
1153
+ this.raster = created.value;
1154
+ }
1155
+ if (this.shadowRaster === undefined && input.materialBindGroupLayout !== undefined) {
1156
+ const created = GpuDrivenShadowRaster.create({
1157
+ device: this.device,
1158
+ shaderModuleFactory: this.shaderModuleFactory,
1159
+ viewBindGroupLayout: input.viewBindGroupLayout,
1160
+ materialBindGroupLayout: input.materialBindGroupLayout,
1161
+ });
1162
+ if (!created.ok) {
1163
+ this.addRhiFault(created.error, 'all', shadowSubmission.revision);
1164
+ } else {
1165
+ this.shadowRaster = created.value;
1166
+ }
1167
+ }
1168
+ const updated = this.view.update(filtered.plan, scene.scene, activeFrustum(input.camera));
1169
+ if (!updated.ok) {
1170
+ this.addRhiFault(updated.error, 'main', filtered.plan.revision);
1171
+ return updated;
1172
+ }
1173
+ const shadowPrepared = this.prepareShadowViews(scene, shadowSubmission, input.meshes);
1174
+ if (!shadowPrepared.ok) {
1175
+ this.addRhiFault(shadowPrepared.error, 'all', shadowSubmission.revision);
1176
+ return shadowPrepared;
1177
+ }
1178
+ const view = this.view;
1179
+ const raster = this.raster;
1180
+ const sceneIdentity = this.sceneIdentity(scene.scene);
1181
+ const viewInspection = view.inspect();
1182
+ let signature = this.signatureCache?.value;
1183
+ if (
1184
+ signature === undefined ||
1185
+ this.signatureCache?.filtered !== filtered ||
1186
+ this.signatureCache.sceneIdentity !== sceneIdentity ||
1187
+ this.signatureCache.viewResourceGeneration !== viewInspection.resourceGeneration ||
1188
+ this.signatureCache.meshResidencyEpoch !== input.meshResidencyEpoch
1189
+ ) {
1190
+ signature = JSON.stringify({
1191
+ sceneIdentity,
1192
+ revision: filtered.plan.revision,
1193
+ meshResidencyEpoch: input.meshResidencyEpoch,
1194
+ viewResourceGeneration: viewInspection.resourceGeneration,
1195
+ batches: filtered.batches.map(({ batch, mesh }) => [
1196
+ batch.batchId,
1197
+ batch.generation,
1198
+ batch.visibleBase,
1199
+ batch.candidates.map((candidate) => [
1200
+ candidate.primitiveIndex,
1201
+ candidate.generation,
1202
+ candidate.instanceOrdinal,
1203
+ ]),
1204
+ mesh.vboBytes,
1205
+ mesh.iboBytes,
1206
+ mesh.indexFormat,
1207
+ mesh.layoutProjection.digest,
1208
+ ]),
1209
+ capacities: [
1210
+ viewInspection.candidateCapacity,
1211
+ viewInspection.batchCapacity,
1212
+ viewInspection.indirectCapacity,
1213
+ ],
1214
+ });
1215
+ this.signatureCache = {
1216
+ filtered,
1217
+ sceneIdentity,
1218
+ viewResourceGeneration: viewInspection.resourceGeneration,
1219
+ meshResidencyEpoch: input.meshResidencyEpoch,
1220
+ value: signature,
1221
+ };
1222
+ }
1223
+ return ok({
1224
+ topologySignature: signature,
1225
+ ownedItemKeys: filtered.itemKeys,
1226
+ ownsAllForwardItems:
1227
+ filtered.forwardItemKeys.size > 0 &&
1228
+ [...filtered.forwardItemKeys].every((key) => filtered.itemKeys.has(key)),
1229
+ shadowSubmission,
1230
+ project: (graph, format, sampleCount) => {
1231
+ const outputs = view.addPasses(graph);
1232
+ if (!outputs.ok) return outputs;
1233
+ const projected: ProjectedBatch[] = [];
1234
+ const accesses: GraphAccess[] = [
1235
+ { resource: outputs.value.primitive, usage: 'storage-read' },
1236
+ { resource: outputs.value.instance, usage: 'storage-read' },
1237
+ { resource: outputs.value.material, usage: 'storage-read' },
1238
+ { resource: outputs.value.visible, usage: 'storage-read' },
1239
+ { resource: outputs.value.transform, usage: 'storage-read' },
1240
+ { resource: outputs.value.indirect, usage: 'indirect-read' },
1241
+ ];
1242
+ const meshBuffers = new Map<
1243
+ number,
1244
+ { readonly vertex: GraphBuffer; readonly index?: GraphBuffer }
1245
+ >();
1246
+ for (const prepared of filtered.batches) {
1247
+ let buffers = meshBuffers.get(prepared.batch.key.assetHandle);
1248
+ if (buffers === undefined) {
1249
+ const vertex = graph.importBuffer(
1250
+ `gpu-driven.mesh.${prepared.batch.key.assetHandle}.vertex`,
1251
+ {
1252
+ size: prepared.mesh.vboBytes,
1253
+ usage: GPU_BUFFER_USAGE_VERTEX | GPU_BUFFER_USAGE_COPY_DST,
1254
+ },
1255
+ () => prepared.mesh.vertexBuffer.handle,
1256
+ );
1257
+ if (!vertex.ok) return vertex;
1258
+ let index: GraphBuffer | undefined;
1259
+ const indexHandle = prepared.mesh.indexBuffer;
1260
+ if (indexHandle !== null) {
1261
+ const imported = graph.importBuffer(
1262
+ `gpu-driven.mesh.${prepared.batch.key.assetHandle}.index`,
1263
+ {
1264
+ size: prepared.mesh.iboBytes,
1265
+ usage: GPU_BUFFER_USAGE_INDEX | GPU_BUFFER_USAGE_COPY_DST,
1266
+ },
1267
+ () => indexHandle.handle,
1268
+ );
1269
+ if (!imported.ok) return imported;
1270
+ index = imported.value;
1271
+ }
1272
+ buffers = { vertex: vertex.value, ...(index === undefined ? {} : { index }) };
1273
+ meshBuffers.set(prepared.batch.key.assetHandle, buffers);
1274
+ accesses.push({ resource: buffers.vertex, usage: 'vertex-read' });
1275
+ if (buffers.index !== undefined) {
1276
+ accesses.push({ resource: buffers.index, usage: 'index-read' });
1277
+ }
1278
+ }
1279
+ const pipeline = raster.pipeline(
1280
+ format,
1281
+ sampleCount,
1282
+ prepared.mesh.layoutProjection.arrayStride,
1283
+ prepared.batch.key.topology,
1284
+ prepared.batch.key.drawKind === 'indexed' &&
1285
+ (prepared.batch.key.topology === 'line-strip' ||
1286
+ prepared.batch.key.topology === 'triangle-strip')
1287
+ ? prepared.mesh.indexFormat
1288
+ : undefined,
1289
+ prepared.renderState,
1290
+ );
1291
+ if (!pipeline.ok) return pipeline;
1292
+ const bindings = raster.bindGroup(scene.scene, view, prepared.batch);
1293
+ if (!bindings.ok) return bindings;
1294
+ this.batchBindGroupCreates += 1;
1295
+ projected.push({
1296
+ ...prepared,
1297
+ ...buffers,
1298
+ pipeline: pipeline.value,
1299
+ bindings: bindings.value,
1300
+ });
1301
+ }
1302
+ const shadow: RenderPipelineGpuDrivenShadowProjection[] = [];
1303
+ const shadowRaster = this.shadowRaster;
1304
+ if (shadowRaster !== undefined) {
1305
+ for (const prepared of this.preparedShadowViews) {
1306
+ const shadowOutputs = prepared.view.addPasses(graph, prepared.graphLabel);
1307
+ if (!shadowOutputs.ok) return shadowOutputs;
1308
+ const shadowAccesses: GraphAccess[] = [
1309
+ { resource: shadowOutputs.value.primitive, usage: 'storage-read' },
1310
+ { resource: shadowOutputs.value.instance, usage: 'storage-read' },
1311
+ { resource: shadowOutputs.value.transform, usage: 'storage-read' },
1312
+ { resource: shadowOutputs.value.visible, usage: 'storage-read' },
1313
+ { resource: shadowOutputs.value.indirect, usage: 'indirect-read' },
1314
+ ];
1315
+ const meshBuffers = new Map<
1316
+ number,
1317
+ { readonly vertex: GraphBuffer; readonly index?: GraphBuffer }
1318
+ >();
1319
+ for (const batch of prepared.batches) {
1320
+ let buffers = meshBuffers.get(batch.batch.key.assetHandle);
1321
+ if (buffers === undefined) {
1322
+ const vertex = graph.importBuffer(
1323
+ `${prepared.graphLabel}.mesh.${batch.batch.key.assetHandle}.vertex`,
1324
+ {
1325
+ size: batch.mesh.vboBytes,
1326
+ usage: GPU_BUFFER_USAGE_VERTEX | GPU_BUFFER_USAGE_COPY_DST,
1327
+ },
1328
+ () => batch.mesh.vertexBuffer.handle,
1329
+ );
1330
+ if (!vertex.ok) return vertex;
1331
+ let index: GraphBuffer | undefined;
1332
+ if (batch.mesh.indexBuffer !== null) {
1333
+ const imported = graph.importBuffer(
1334
+ `${prepared.graphLabel}.mesh.${batch.batch.key.assetHandle}.index`,
1335
+ {
1336
+ size: batch.mesh.iboBytes,
1337
+ usage: GPU_BUFFER_USAGE_INDEX | GPU_BUFFER_USAGE_COPY_DST,
1338
+ },
1339
+ () => batch.mesh.indexBuffer?.handle as import('@forgeax/engine-rhi').Buffer,
1340
+ );
1341
+ if (!imported.ok) return imported;
1342
+ index = imported.value;
1343
+ }
1344
+ buffers = { vertex: vertex.value, ...(index === undefined ? {} : { index }) };
1345
+ meshBuffers.set(batch.batch.key.assetHandle, buffers);
1346
+ shadowAccesses.push({ resource: buffers.vertex, usage: 'vertex-read' });
1347
+ if (buffers.index !== undefined) {
1348
+ shadowAccesses.push({ resource: buffers.index, usage: 'index-read' });
1349
+ }
1350
+ }
1351
+ }
1352
+ shadow.push({
1353
+ cascadeIndex: prepared.cascadeIndex,
1354
+ accesses: Object.freeze(shadowAccesses),
1355
+ batchCount: prepared.batches.length,
1356
+ encode: (pass, resources) =>
1357
+ shadowRaster.encode(prepared, resources, shadowOutputs.value, pass),
1358
+ });
1359
+ }
1360
+ }
1361
+ return ok({
1362
+ accesses,
1363
+ shadow: Object.freeze(shadow),
1364
+ encode: (viewBindGroup, pass, resources: GraphResourceResolver) => {
1365
+ pass.setBindGroup(0, viewBindGroup);
1366
+ let currentPipeline: RenderPipeline | undefined;
1367
+ let currentVertex: GraphBuffer | undefined;
1368
+ let currentIndex: GraphBuffer | undefined;
1369
+ for (const batch of projected) {
1370
+ if (currentPipeline !== batch.pipeline) {
1371
+ pass.setPipeline(batch.pipeline);
1372
+ currentPipeline = batch.pipeline;
1373
+ }
1374
+ pass.setBindGroup(1, batch.bindings);
1375
+ if (currentVertex !== batch.vertex) {
1376
+ const vertex = resources.buffer(batch.vertex);
1377
+ if (!vertex.ok) throw vertex.error;
1378
+ pass.setVertexBuffer(0, vertex.value);
1379
+ currentVertex = batch.vertex;
1380
+ }
1381
+ if (batch.index !== undefined && currentIndex !== batch.index) {
1382
+ const index = resources.buffer(batch.index);
1383
+ if (!index.ok) throw index.error;
1384
+ pass.setIndexBuffer(index.value, batch.mesh.indexFormat);
1385
+ currentIndex = batch.index;
1386
+ }
1387
+ const indirect = resources.buffer(outputs.value.indirect);
1388
+ if (!indirect.ok) throw indirect.error;
1389
+ if (batch.batch.key.drawKind === 'indexed') {
1390
+ pass.drawIndexedIndirect(indirect.value, batch.batch.indirectOffset);
1391
+ } else {
1392
+ pass.drawIndirect(indirect.value, batch.batch.indirectOffset);
1393
+ }
1394
+ }
1395
+ },
1396
+ });
1397
+ },
1398
+ });
1399
+ }
1400
+
1401
+ /**
1402
+ * Intersect the four-view visibility result with the shared ShadowCaster
1403
+ * topology. This is the only production candidate-to-submission join; CPU
1404
+ * fallback devices consume the same immutable plans as indirect-capable
1405
+ * devices.
1406
+ */
1407
+ multiViewSubmissions(): readonly MultiViewProductionSubmission[] {
1408
+ if (this.cpuVisibility === undefined || this.shadowSubmission === undefined) {
1409
+ return [];
1410
+ }
1411
+ const shadowSubmission = this.shadowSubmission;
1412
+ return Object.freeze(
1413
+ this.cpuVisibility.views.map((view) => {
1414
+ const candidateIndexByStableId = new Map<number, number>();
1415
+ for (const candidate of view.compactVisible) {
1416
+ if (candidate.candidateIndex !== undefined) {
1417
+ candidateIndexByStableId.set(candidate.stableId, candidate.candidateIndex);
1418
+ }
1419
+ }
1420
+ const plan = this.shadowSubmissionForView(shadowSubmission, view);
1421
+ const candidateIndices = new Set<number>();
1422
+ for (const batch of plan.batches) {
1423
+ for (const candidate of batch.candidates) {
1424
+ const candidateIndex = candidateIndexByStableId.get(candidate.primitiveIndex);
1425
+ if (candidateIndex !== undefined) candidateIndices.add(candidateIndex);
1426
+ }
1427
+ }
1428
+ return Object.freeze({
1429
+ source: 'multi-view-indirect' as const,
1430
+ viewId: view.viewId,
1431
+ kind: view.kind,
1432
+ cascadeIndex: view.cascadeIndex,
1433
+ volumeRevision: view.volumeRevision,
1434
+ spatialIndexRevision: view.spatialIndexRevision,
1435
+ overflow: view.overflow,
1436
+ plan,
1437
+ candidateIndexByStableId,
1438
+ candidateIndices,
1439
+ faults: Object.freeze(
1440
+ this.faults.filter((fault) => fault.viewId === 'all' || fault.viewId === view.viewId),
1441
+ ),
1442
+ });
1443
+ }),
1444
+ );
1445
+ }
1446
+
1447
+ private prepareShadowViews(
1448
+ scene: PersistentGpuDrivenState,
1449
+ shadowSource: SubmissionPlan,
1450
+ meshes: ReadonlyMap<number, MeshGpuHandles>,
1451
+ ): Result<void, RhiError> {
1452
+ this.preparedShadowViews = [];
1453
+ if (this.shadowRaster === undefined || this.cpuVisibility === undefined) return ok(undefined);
1454
+ const slotByPrimitive = new Map(scene.slots.map((slot) => [slot.slot, slot] as const));
1455
+ const descriptorByView = new Map(
1456
+ this.visibilityViews.map((view) => [view.viewId, view] as const),
1457
+ );
1458
+ const prepared: PreparedShadowView[] = [];
1459
+ for (const viewResult of this.cpuVisibility.views) {
1460
+ if (viewResult.kind !== 'cascade' || viewResult.cascadeIndex === undefined) continue;
1461
+ const descriptor = descriptorByView.get(viewResult.viewId);
1462
+ if (
1463
+ descriptor === undefined ||
1464
+ descriptor.lightViewProj === undefined ||
1465
+ descriptor.planes.length < 24 ||
1466
+ viewResult.overflow
1467
+ ) {
1468
+ if (viewResult.overflow) {
1469
+ this.addFault({
1470
+ code: 'visibility-overflow',
1471
+ viewId: viewResult.viewId,
1472
+ revision: shadowSource.revision,
1473
+ fallback: 'cpu-batch-contract',
1474
+ detail:
1475
+ 'compact visibility capacity was exceeded; the complete CPU batch contract remains authoritative',
1476
+ });
1477
+ } else if (descriptor === undefined || descriptor.lightViewProj === undefined) {
1478
+ this.addFault({
1479
+ code: 'gpu-resource-failed',
1480
+ viewId: viewResult.viewId,
1481
+ revision: shadowSource.revision,
1482
+ fallback: 'cpu-batch-contract',
1483
+ detail: 'cascade volume did not publish a canonical raster matrix',
1484
+ });
1485
+ }
1486
+ continue;
1487
+ }
1488
+ const plan = this.shadowSubmissionForView(shadowSource, viewResult);
1489
+ if (plan.batches.length === 0) continue;
1490
+ let gpuSafe = true;
1491
+ for (const batch of plan.batches) {
1492
+ const mesh = meshes.get(batch.key.assetHandle);
1493
+ if (
1494
+ batch.key.alphaTest ||
1495
+ (batch.key.materialClass !== 'forgeax::default-unlit' &&
1496
+ batch.key.materialClass !== 'forgeax::default-standard-pbr') ||
1497
+ mesh === undefined ||
1498
+ !supportsRigidGpuDrivenProjection(mesh) ||
1499
+ (batch.key.topology !== 'triangle-list' && batch.key.topology !== 'triangle-strip') ||
1500
+ (batch.key.drawKind === 'indexed' && (!mesh.indexed || mesh.indexBuffer === null)) ||
1501
+ (batch.key.drawKind === 'non-indexed' && mesh.indexed)
1502
+ ) {
1503
+ gpuSafe = false;
1504
+ break;
1505
+ }
1506
+ for (const candidate of batch.candidates) {
1507
+ const slot = slotByPrimitive.get(candidate.primitiveIndex);
1508
+ if (
1509
+ slot === undefined ||
1510
+ slot.fact.bounds.status !== 'present' ||
1511
+ slot.snapshot.gpuDrivenDraws === undefined
1512
+ ) {
1513
+ gpuSafe = false;
1514
+ break;
1515
+ }
1516
+ }
1517
+ if (!gpuSafe) break;
1518
+ }
1519
+ if (!gpuSafe) {
1520
+ this.addFault({
1521
+ code: 'gpu-scene-fact-unavailable',
1522
+ viewId: viewResult.viewId,
1523
+ revision: shadowSource.revision,
1524
+ fallback: 'cpu-batch-contract',
1525
+ detail:
1526
+ 'one or more casters lack bounded GPU Scene facts required by the exact shadow cull',
1527
+ });
1528
+ continue;
1529
+ }
1530
+ let view = this.shadowViews.get(viewResult.cascadeIndex);
1531
+ if (view === undefined) {
1532
+ const created = GpuDrivenView.create({
1533
+ device: this.device,
1534
+ shaderModuleFactory: this.shaderModuleFactory,
1535
+ });
1536
+ if (!created.ok) {
1537
+ this.addRhiFault(created.error, viewResult.viewId, shadowSource.revision);
1538
+ continue;
1539
+ }
1540
+ view = created.value;
1541
+ this.shadowViews.set(viewResult.cascadeIndex, view);
1542
+ }
1543
+ const updated = view.update(plan, scene.scene, descriptor.planes);
1544
+ if (!updated.ok) {
1545
+ this.addRhiFault(updated.error, viewResult.viewId, shadowSource.revision);
1546
+ continue;
1547
+ }
1548
+ const shadowView = this.shadowRaster.prepareView({
1549
+ cascadeIndex: viewResult.cascadeIndex,
1550
+ scene: scene.scene,
1551
+ view,
1552
+ plan,
1553
+ lightViewProj: descriptor.lightViewProj,
1554
+ meshes,
1555
+ graphLabel: `gpu-driven.shadow.cascade-${viewResult.cascadeIndex}`,
1556
+ });
1557
+ if (!shadowView.ok) {
1558
+ this.addRhiFault(shadowView.error, viewResult.viewId, shadowSource.revision);
1559
+ continue;
1560
+ }
1561
+ if (shadowView.value !== undefined) prepared.push(shadowView.value);
1562
+ }
1563
+ this.preparedShadowViews = Object.freeze(prepared);
1564
+ return ok(undefined);
1565
+ }
1566
+
1567
+ private shadowSubmissionForView(
1568
+ shadowSubmission: SubmissionPlan,
1569
+ view: CpuMultiViewVisibilityResult['views'][number],
1570
+ ): SubmissionPlan {
1571
+ const cached = this.shadowPlanCache.get(view.viewId);
1572
+ const stableIds = view.compactVisible.map((candidate) => candidate.stableId);
1573
+ const generations = view.compactVisible.map((candidate) => candidate.generation);
1574
+ if (
1575
+ cached !== undefined &&
1576
+ cached.source === shadowSubmission &&
1577
+ sameNumberArray(cached.stableIds, stableIds) &&
1578
+ sameNumberArray(cached.generations, generations)
1579
+ ) {
1580
+ return cached.plan;
1581
+ }
1582
+ let reverse = this.shadowCandidateMembership;
1583
+ if (reverse?.source !== shadowSubmission) {
1584
+ reverse = buildSubmissionCandidateMembership(shadowSubmission);
1585
+ this.shadowCandidateMembership = reverse;
1586
+ }
1587
+ const candidatesByBatch = new Map<number, GpuDrivenCandidate[]>();
1588
+ // compactVisible is stable-id ordered because the CPU visibility owner
1589
+ // sorts its candidate domain once. Appending each slot's source-order
1590
+ // candidates therefore preserves the old deterministic order while
1591
+ // changing the join from O(all shadow candidates per cascade) to
1592
+ // O(selected candidates).
1593
+ for (const visible of view.compactVisible) {
1594
+ const entries = reverse.byPrimitiveIndex.get(visible.stableId);
1595
+ if (entries === undefined) continue;
1596
+ for (const entry of entries) {
1597
+ if (entry.candidate.generation !== visible.generation) continue;
1598
+ const candidates = candidatesByBatch.get(entry.batchId) ?? [];
1599
+ candidates.push(entry.candidate);
1600
+ candidatesByBatch.set(entry.batchId, candidates);
1601
+ }
1602
+ }
1603
+ const frozenCandidatesByBatch = new Map<number, readonly GpuDrivenCandidate[]>();
1604
+ for (const [batchId, candidates] of candidatesByBatch) {
1605
+ frozenCandidatesByBatch.set(batchId, Object.freeze(candidates));
1606
+ }
1607
+ const plan = buildBatchAlignedSubmission(shadowSubmission, frozenCandidatesByBatch);
1608
+ this.shadowPlanCache.set(view.viewId, {
1609
+ source: shadowSubmission,
1610
+ stableIds: Object.freeze(stableIds),
1611
+ generations: Object.freeze(generations),
1612
+ plan,
1613
+ });
1614
+ return plan;
1615
+ }
1616
+
1617
+ dispose(): void {
1618
+ this.view?.dispose();
1619
+ for (const view of this.shadowViews.values()) view.dispose();
1620
+ this.shadowViews.clear();
1621
+ this.shadowRaster?.dispose();
1622
+ this.view = undefined;
1623
+ this.raster = undefined;
1624
+ this.shadowRaster = undefined;
1625
+ this.preparedShadowViews = [];
1626
+ this.filteredCache = undefined;
1627
+ this.signatureCache = undefined;
1628
+ this.cpuVisibility = undefined;
1629
+ this.shadowCasterSlotIndices = undefined;
1630
+ this.shadowSubmission = undefined;
1631
+ this.shadowPlanCache.clear();
1632
+ this.shadowCandidateMembership = undefined;
1633
+ }
1634
+
1635
+ inspect(): GpuDrivenProductionInspection {
1636
+ const view = this.view?.inspect();
1637
+ return {
1638
+ gpuOwnedSnapshotsMaterialized: this.gpuOwnedSnapshotsMaterialized,
1639
+ filteredPlanBuilds: this.filteredPlanBuilds,
1640
+ gpuOwnedItemCount: this.gpuOwnedItemCount,
1641
+ candidateUploadBytes: view?.candidateUploadBytes ?? 0,
1642
+ batchUploadBytes: view?.batchUploadBytes ?? 0,
1643
+ viewConstantsUploadBytes: view?.viewConstantsUploadBytes ?? 0,
1644
+ batchBindGroupCreates: this.batchBindGroupCreates,
1645
+ viewBindGroupCreates: view?.bindGroupCreates ?? 0,
1646
+ topologyRevision: view?.topologyRevision,
1647
+ validatedGpuOwnedRows: this.validatedGpuOwnedRows,
1648
+ cpuFallbackDrawItems: this.cpuFallbackDrawItems,
1649
+ cpuVisibility: this.cpuVisibility,
1650
+ shadowBatchCount: this.shadowSubmission?.batches.length ?? 0,
1651
+ shadowCandidateCount: this.shadowSubmission?.candidateCount ?? 0,
1652
+ shadowDrawCount: this.preparedShadowViews.reduce(
1653
+ (total, prepared) => total + prepared.batches.length,
1654
+ 0,
1655
+ ),
1656
+ faults: this.faults,
1657
+ };
1658
+ }
1659
+
1660
+ recordCpuValidation(
1661
+ validated: readonly { readonly source: RenderableSnapshot }[],
1662
+ gpuOwned: ReadonlySet<RasterItemKey>,
1663
+ ): void {
1664
+ let cpuFallbackItems = 0;
1665
+ for (const row of validated) {
1666
+ for (const draw of row.source.gpuDrivenDraws ?? []) {
1667
+ const key = rasterItemKey(
1668
+ row.source.worldId,
1669
+ row.source.entityKey,
1670
+ draw.submeshIndex,
1671
+ draw.passIndex,
1672
+ );
1673
+ if (!gpuOwned.has(key)) cpuFallbackItems += 1;
1674
+ }
1675
+ }
1676
+ this.cpuFallbackDrawItems = cpuFallbackItems;
1677
+ // Validation remains a renderable/mesh-residency phase. Ownership is
1678
+ // published only for item keys, so no validated row is GPU-owned.
1679
+ this.validatedGpuOwnedRows = 0;
1680
+ }
1681
+
1682
+ private sceneIdentity(scene: object): number {
1683
+ const existing = this.sceneIdentities.get(scene);
1684
+ if (existing !== undefined) return existing;
1685
+ const identity = this.nextSceneIdentity;
1686
+ this.nextSceneIdentity += 1;
1687
+ this.sceneIdentities.set(scene, identity);
1688
+ return identity;
1689
+ }
1690
+
1691
+ private addFault(fault: GpuDrivenVisibilityFault): void {
1692
+ this.faults = Object.freeze([...this.faults, Object.freeze(fault)]);
1693
+ }
1694
+
1695
+ private addRhiFault(error: RhiError, viewId: string, revision: number): void {
1696
+ const requiresRecovery = error.code === 'device-lost' || error.code === 'oom';
1697
+ this.addFault({
1698
+ code: requiresRecovery ? 'device-recovery-required' : 'gpu-resource-failed',
1699
+ viewId,
1700
+ revision,
1701
+ fallback: requiresRecovery ? 'scene-rebuild' : 'cpu-batch-contract',
1702
+ detail: `${error.code}: ${error.message}`,
1703
+ });
1704
+ }
1705
+ }