@forgeax/engine-render 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (918) hide show
  1. package/README.md +130 -641
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/__tests__/device-scope-lifecycle.unit.test.d.ts +2 -0
  4. package/dist/__tests__/device-scope-lifecycle.unit.test.d.ts.map +1 -0
  5. package/dist/__tests__/device-scope-stale-matrix.unit.test.d.ts +2 -0
  6. package/dist/__tests__/device-scope-stale-matrix.unit.test.d.ts.map +1 -0
  7. package/dist/__tests__/fullscreen-feature-plan.unit.test.d.ts +2 -0
  8. package/dist/__tests__/fullscreen-feature-plan.unit.test.d.ts.map +1 -0
  9. package/dist/__tests__/gpu-driven-indirect-raster-evidence.d.ts.map +1 -1
  10. package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts +6 -0
  11. package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts.map +1 -1
  12. package/dist/{gpu-driven/view-reference.d.ts → __tests__/gpu-driven-view-reference.d.ts} +4 -4
  13. package/dist/__tests__/gpu-driven-view-reference.d.ts.map +1 -0
  14. package/dist/__tests__/gpu-scene-render-graph-gpu.d.ts.map +1 -1
  15. package/dist/__tests__/ibl/face-uniforms.unit.test.d.ts +2 -0
  16. package/dist/__tests__/ibl/face-uniforms.unit.test.d.ts.map +1 -0
  17. package/dist/__tests__/morph-feature-plan.unit.test.d.ts +2 -0
  18. package/dist/__tests__/morph-feature-plan.unit.test.d.ts.map +1 -0
  19. package/dist/__tests__/render-feature-plan.test-d.d.ts +2 -0
  20. package/dist/__tests__/render-feature-plan.test-d.d.ts.map +1 -0
  21. package/dist/__tests__/render-feature-plan.unit.test.d.ts +2 -0
  22. package/dist/__tests__/render-feature-plan.unit.test.d.ts.map +1 -0
  23. package/dist/__tests__/ssao-config.unit.test.d.ts +2 -0
  24. package/dist/__tests__/ssao-config.unit.test.d.ts.map +1 -0
  25. package/dist/__tests__/standard-clustered-pipeline.unit.test.d.ts +2 -0
  26. package/dist/__tests__/standard-clustered-pipeline.unit.test.d.ts.map +1 -0
  27. package/dist/__tests__/standard-descriptors.test-d.d.ts +2 -0
  28. package/dist/__tests__/standard-descriptors.test-d.d.ts.map +1 -0
  29. package/dist/__tests__/standard-pipeline.dawn.test.d.ts +2 -0
  30. package/dist/__tests__/standard-pipeline.dawn.test.d.ts.map +1 -0
  31. package/dist/__tests__/standard-pipeline.integration.test.d.ts +2 -0
  32. package/dist/__tests__/standard-pipeline.integration.test.d.ts.map +1 -0
  33. package/dist/__tests__/standard-profile-oracle.unit.test.d.ts +2 -0
  34. package/dist/__tests__/standard-profile-oracle.unit.test.d.ts.map +1 -0
  35. package/dist/__tests__/visibility-resource-short-circuit.unit.test.d.ts +2 -0
  36. package/dist/__tests__/visibility-resource-short-circuit.unit.test.d.ts.map +1 -0
  37. package/dist/{renderer/backend-selection.d.ts → assembly/backend-contract.d.ts} +15 -4
  38. package/dist/assembly/backend-contract.d.ts.map +1 -0
  39. package/dist/assembly/factory.d.ts +207 -0
  40. package/dist/assembly/factory.d.ts.map +1 -0
  41. package/dist/assembly/host-contract.d.ts +84 -0
  42. package/dist/assembly/host-contract.d.ts.map +1 -0
  43. package/dist/{renderer → assembly}/material/assembly.d.ts +0 -1
  44. package/dist/{renderer → assembly}/material/assembly.d.ts.map +1 -1
  45. package/dist/assembly/material/pipeline-projection.d.ts +30 -0
  46. package/dist/assembly/material/pipeline-projection.d.ts.map +1 -0
  47. package/dist/authoring.d.ts +10 -11
  48. package/dist/authoring.d.ts.map +1 -1
  49. package/dist/authoring.mjs +25 -3
  50. package/dist/authoring.mjs.map +1 -1
  51. package/dist/chunk-CQXZC5XI.mjs +182 -0
  52. package/dist/chunk-CQXZC5XI.mjs.map +1 -0
  53. package/dist/chunk-QC4VW3XJ.mjs +79 -0
  54. package/dist/chunk-QC4VW3XJ.mjs.map +1 -0
  55. package/dist/chunk-SCRSAK5B.mjs +480 -0
  56. package/dist/chunk-SCRSAK5B.mjs.map +1 -0
  57. package/dist/components/__tests__/schema-contract.unit.test.d.ts +2 -0
  58. package/dist/components/__tests__/schema-contract.unit.test.d.ts.map +1 -0
  59. package/dist/components/glyph-text.d.ts +1 -1
  60. package/dist/components/glyph-text.d.ts.map +1 -1
  61. package/dist/components/index.d.ts +2 -2
  62. package/dist/components/index.d.ts.map +1 -1
  63. package/dist/components/instances.d.ts +1 -1
  64. package/dist/components/instances.d.ts.map +1 -1
  65. package/dist/components/light-helpers.d.ts +1 -1
  66. package/dist/components/light-helpers.d.ts.map +1 -1
  67. package/dist/components/mesh-filter.d.ts +7 -7
  68. package/dist/components/mesh-filter.d.ts.map +1 -1
  69. package/dist/components/scene-instance.d.ts +11 -11
  70. package/dist/components/skybox-background.d.ts +56 -0
  71. package/dist/components/skybox-background.d.ts.map +1 -0
  72. package/dist/components/skylight.d.ts +55 -0
  73. package/dist/components/skylight.d.ts.map +1 -0
  74. package/dist/components/sprite-animation.d.ts +2 -3
  75. package/dist/components/sprite-animation.d.ts.map +1 -1
  76. package/dist/components/sprite-instances.d.ts +1 -1
  77. package/dist/components/sprite-playback-mode.d.ts +6 -1
  78. package/dist/components/sprite-playback-mode.d.ts.map +1 -1
  79. package/dist/components/sprite-region-override.d.ts +2 -3
  80. package/dist/components/sprite-region-override.d.ts.map +1 -1
  81. package/dist/components/tile-layer.d.ts +5 -0
  82. package/dist/components/tile-layer.d.ts.map +1 -1
  83. package/dist/construct-renderer.d.ts +18 -1
  84. package/dist/construct-renderer.d.ts.map +1 -1
  85. package/dist/construct-renderer.mjs +27008 -4
  86. package/dist/construct-renderer.mjs.map +1 -1
  87. package/dist/debug-draw-glue.d.ts +2 -53
  88. package/dist/debug-draw-glue.d.ts.map +1 -1
  89. package/dist/device/device-scope.d.ts +83 -0
  90. package/dist/device/device-scope.d.ts.map +1 -0
  91. package/dist/{gpu-resource-store.d.ts → device/gpu-residency.d.ts} +91 -48
  92. package/dist/device/gpu-residency.d.ts.map +1 -0
  93. package/dist/device/resource-types.d.ts +8 -0
  94. package/dist/device/resource-types.d.ts.map +1 -0
  95. package/dist/engine-metrics.d.ts +2 -2
  96. package/dist/engine-metrics.d.ts.map +1 -1
  97. package/dist/errors/recover.d.ts +28 -1
  98. package/dist/errors/recover.d.ts.map +1 -1
  99. package/dist/errors/render.d.ts +249 -258
  100. package/dist/errors/render.d.ts.map +1 -1
  101. package/dist/features/fullscreen.d.ts +19 -0
  102. package/dist/features/fullscreen.d.ts.map +1 -0
  103. package/dist/features/host.d.ts +32 -26
  104. package/dist/features/host.d.ts.map +1 -1
  105. package/dist/features/morph/morph-feature.d.ts +39 -5
  106. package/dist/features/morph/morph-feature.d.ts.map +1 -1
  107. package/dist/features/plan.d.ts +182 -0
  108. package/dist/features/plan.d.ts.map +1 -0
  109. package/dist/features/prepared-gpu-work.d.ts +21 -17
  110. package/dist/features/prepared-gpu-work.d.ts.map +1 -1
  111. package/dist/features/prepared-graphics-store.d.ts +2 -1
  112. package/dist/features/prepared-graphics-store.d.ts.map +1 -1
  113. package/dist/features/prepared-graphics.d.ts +11 -21
  114. package/dist/features/prepared-graphics.d.ts.map +1 -1
  115. package/dist/features/render-graph-compute.d.ts +2 -2
  116. package/dist/features/render-graph-compute.d.ts.map +1 -1
  117. package/dist/features/render-graph-contribution.d.ts +4 -7
  118. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  119. package/dist/features/render-graph-raster.d.ts +2 -2
  120. package/dist/features/render-graph-raster.d.ts.map +1 -1
  121. package/dist/features/render-graph-resources.d.ts +6 -6
  122. package/dist/features/render-graph-resources.d.ts.map +1 -1
  123. package/dist/features/targets.d.ts +5 -5
  124. package/dist/features/targets.d.ts.map +1 -1
  125. package/dist/features/types.d.ts +11 -190
  126. package/dist/features/types.d.ts.map +1 -1
  127. package/dist/features/vocabulary.d.ts +14 -0
  128. package/dist/features/vocabulary.d.ts.map +1 -0
  129. package/dist/fullscreen-post-process-pass.d.ts +4 -25
  130. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  131. package/dist/glyph-text-layout-system.d.ts +3 -2
  132. package/dist/glyph-text-layout-system.d.ts.map +1 -1
  133. package/dist/gpu-driven/batch-topology.d.ts +6 -75
  134. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  135. package/dist/gpu-driven/production-raster.d.ts +13 -112
  136. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  137. package/dist/gpu-driven/view-gpu.d.ts +10 -66
  138. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  139. package/dist/gpu-resource.d.ts +3 -3
  140. package/dist/gpu-scene-schema.d.ts +1 -94
  141. package/dist/gpu-scene-schema.d.ts.map +1 -1
  142. package/dist/gpu-scene.d.ts +7 -33
  143. package/dist/gpu-scene.d.ts.map +1 -1
  144. package/dist/hdrp-buffers.d.ts +3 -53
  145. package/dist/hdrp-buffers.d.ts.map +1 -1
  146. package/dist/ibl/IblPipelineCache.d.ts +74 -180
  147. package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
  148. package/dist/ibl/skylight-bind-group.d.ts +1 -1
  149. package/dist/index.d.ts +13 -43
  150. package/dist/index.d.ts.map +1 -1
  151. package/dist/index.mjs +165 -3
  152. package/dist/index.mjs.map +1 -1
  153. package/dist/inspection-types.d.ts +69 -0
  154. package/dist/inspection-types.d.ts.map +1 -0
  155. package/dist/instance-buffer-cache.d.ts +1 -4
  156. package/dist/instance-buffer-cache.d.ts.map +1 -1
  157. package/dist/internal.d.ts +1 -73
  158. package/dist/internal.d.ts.map +1 -1
  159. package/dist/internal.mjs +1 -43
  160. package/dist/internal.mjs.map +1 -1
  161. package/dist/lifecycle.d.ts +36 -2
  162. package/dist/lifecycle.d.ts.map +1 -1
  163. package/dist/materials.d.ts +0 -3
  164. package/dist/materials.d.ts.map +1 -1
  165. package/dist/mesh-material-bindings.d.ts +0 -1
  166. package/dist/mesh-material-bindings.d.ts.map +1 -1
  167. package/dist/pbr-pipeline.d.ts +75 -29
  168. package/dist/pbr-pipeline.d.ts.map +1 -1
  169. package/dist/pipeline/standard-forward-lane.d.ts +5 -0
  170. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -0
  171. package/dist/pipeline/standard-pipeline.d.ts +31 -0
  172. package/dist/pipeline/standard-pipeline.d.ts.map +1 -0
  173. package/dist/pipeline/standard-profile.d.ts +40 -0
  174. package/dist/pipeline/standard-profile.d.ts.map +1 -0
  175. package/dist/pipeline-builder.d.ts +3 -3
  176. package/dist/pipeline-builder.d.ts.map +1 -1
  177. package/dist/pipeline-spec-types.d.ts +24 -0
  178. package/dist/pipeline-spec-types.d.ts.map +1 -0
  179. package/dist/pipeline-spec.d.ts +16 -155
  180. package/dist/pipeline-spec.d.ts.map +1 -1
  181. package/dist/plugin.d.ts +1 -14
  182. package/dist/plugin.d.ts.map +1 -1
  183. package/dist/post-process-errors.d.ts +18 -18
  184. package/dist/post-process-errors.d.ts.map +1 -1
  185. package/dist/prepare/prepared-graphics-resolver.d.ts +2 -5
  186. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  187. package/dist/record/__tests__/typed-frame-graph-plan.unit.test.d.ts +2 -0
  188. package/dist/record/__tests__/typed-frame-graph-plan.unit.test.d.ts.map +1 -0
  189. package/dist/record/frame-lighting.d.ts +7 -73
  190. package/dist/record/frame-lighting.d.ts.map +1 -1
  191. package/dist/record/frame-snapshot.d.ts +44 -44
  192. package/dist/record/frame-snapshot.d.ts.map +1 -1
  193. package/dist/record/frame-targets.d.ts +5 -38
  194. package/dist/record/frame-targets.d.ts.map +1 -1
  195. package/dist/record/frame.d.ts +64 -52
  196. package/dist/record/frame.d.ts.map +1 -1
  197. package/dist/record/helpers.d.ts +3 -2
  198. package/dist/record/helpers.d.ts.map +1 -1
  199. package/dist/record/main-pass-geometry.d.ts +5 -4
  200. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  201. package/dist/record/main-pass-material.d.ts +90 -59
  202. package/dist/record/main-pass-material.d.ts.map +1 -1
  203. package/dist/record/main-pass-sprite-draws.d.ts +28 -3
  204. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  205. package/dist/record/main-pass.d.ts +1 -1
  206. package/dist/record/main-pass.d.ts.map +1 -1
  207. package/dist/record/mesh-ssbo.d.ts +276 -3
  208. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  209. package/dist/record/render-context.d.ts +235 -0
  210. package/dist/record/render-context.d.ts.map +1 -0
  211. package/dist/record/shadow-pass.d.ts +15 -88
  212. package/dist/record/shadow-pass.d.ts.map +1 -1
  213. package/dist/record/skybox-post-pass.d.ts +1 -1
  214. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  215. package/dist/record/typed-frame-graph.d.ts +29 -7
  216. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  217. package/dist/record/view-ubo.d.ts +3 -3
  218. package/dist/record/view-ubo.d.ts.map +1 -1
  219. package/dist/render-contract.d.ts +416 -0
  220. package/dist/render-contract.d.ts.map +1 -0
  221. package/dist/render-data.d.ts.map +1 -1
  222. package/dist/render-graph-primitives.d.ts +14 -362
  223. package/dist/render-graph-primitives.d.ts.map +1 -1
  224. package/dist/render-pipeline.d.ts +25 -64
  225. package/dist/render-pipeline.d.ts.map +1 -1
  226. package/dist/render-system-extract.d.ts +107 -338
  227. package/dist/render-system-extract.d.ts.map +1 -1
  228. package/dist/render-system.d.ts +21 -713
  229. package/dist/render-system.d.ts.map +1 -1
  230. package/dist/scene/render-scene-types.d.ts +58 -0
  231. package/dist/scene/render-scene-types.d.ts.map +1 -0
  232. package/dist/scene/render-scene.d.ts +105 -0
  233. package/dist/scene/render-scene.d.ts.map +1 -0
  234. package/dist/scene-instances/post-spawn-resolve-joints.d.ts +2 -5
  235. package/dist/scene-instances/post-spawn-resolve-joints.d.ts.map +1 -1
  236. package/dist/ssao-buffers.d.ts +22 -3
  237. package/dist/ssao-buffers.d.ts.map +1 -1
  238. package/dist/systems/skin-palette-allocator.d.ts +2 -4
  239. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  240. package/dist/systems/skin-palette-types.d.ts +14 -0
  241. package/dist/systems/skin-palette-types.d.ts.map +1 -0
  242. package/dist/systems/transparent-sort-config.d.ts +23 -2
  243. package/dist/systems/transparent-sort-config.d.ts.map +1 -1
  244. package/dist/tilemap-chunk-extract-system.d.ts +4 -3
  245. package/dist/tilemap-chunk-extract-system.d.ts.map +1 -1
  246. package/dist/typed-render-graph-primitives.d.ts +2 -4
  247. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  248. package/dist/typed-shadow-passes.d.ts +3 -3
  249. package/dist/typed-shadow-passes.d.ts.map +1 -1
  250. package/package.json +23 -23
  251. package/src/__tests__/backend-selection-rhi-capture.test-d.ts +1 -1
  252. package/src/__tests__/callback-inference.test-d.ts +6 -3
  253. package/src/__tests__/cluster-grid-default-surface.unit.test.ts +7 -4
  254. package/src/__tests__/construct-renderer-identity.unit.test.ts +15 -2
  255. package/src/__tests__/device-scope-lifecycle.unit.test.ts +151 -0
  256. package/src/__tests__/device-scope-stale-matrix.unit.test.ts +42 -0
  257. package/src/__tests__/direct-extract-consumer-contract.test-d.ts +8 -19
  258. package/src/__tests__/direct-light-snapshot.unit.test.ts +3 -13
  259. package/src/__tests__/factory-contract.integration.test.ts +158 -209
  260. package/src/__tests__/fallback-row-stride-surface.unit.test.ts +1 -4
  261. package/src/__tests__/frame-observation.contract.test.ts +17 -8
  262. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +32 -0
  263. package/src/__tests__/glyph-text-layout-recovery.unit.test.ts +6 -11
  264. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +9 -16
  265. package/src/__tests__/gpu-driven-production.integration.test.ts +32 -205
  266. package/src/__tests__/gpu-driven-scaling.unit.test.ts +4 -7
  267. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +87 -8
  268. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +170 -8
  269. package/src/{gpu-driven/view-reference.ts → __tests__/gpu-driven-view-reference.ts} +4 -3
  270. package/src/__tests__/gpu-driven-view.browser.test.ts +12 -1
  271. package/src/__tests__/gpu-driven-view.dawn.test.ts +12 -1
  272. package/src/__tests__/gpu-driven-view.unit.test.ts +11 -267
  273. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +3 -3
  274. package/src/__tests__/gpu-scene-render-graph-gpu.ts +2 -3
  275. package/src/__tests__/gpu-scene.dawn.test.ts +2 -6
  276. package/src/__tests__/gpu-scene.unit.test.ts +10 -24
  277. package/src/__tests__/ibl/face-uniforms.unit.test.ts +46 -0
  278. package/src/__tests__/infinite-grid-no-vertex-probe.unit.test.ts +34 -66
  279. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +14 -5
  280. package/src/__tests__/light-buffer-layout.unit.test.ts +4 -49
  281. package/src/__tests__/material-cooked-projection.unit.test.ts +2 -51
  282. package/src/__tests__/material-snapshot-mutation.integration.test.ts +10 -15
  283. package/src/__tests__/material-static-dynamic-route.unit.test.ts +4 -23
  284. package/src/__tests__/material-stride-surface.unit.test.ts +2 -2
  285. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +7 -8
  286. package/src/__tests__/morph-culling-reentry.dawn.test.ts +29 -38
  287. package/src/__tests__/morph-feature-gpu-work.integration.test.ts +45 -43
  288. package/src/__tests__/morph-feature-plan.unit.test.ts +53 -0
  289. package/src/__tests__/morph-visual-evidence.integration.test.ts +47 -33
  290. package/src/__tests__/nineslice-handle-surface.unit.test.ts +11 -6
  291. package/src/__tests__/post-process-error-policy-owner.unit.test.ts +6 -13
  292. package/src/__tests__/prepared-graphics-capability.unit.test.ts +6 -81
  293. package/src/__tests__/prepared-graphics-generation.unit.test.ts +3 -17
  294. package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +6 -74
  295. package/src/__tests__/prepared-graphics-resolver.unit.test.ts +1 -3
  296. package/src/__tests__/prepared-graphics-snapshot.unit.test.ts +2 -2
  297. package/src/__tests__/profiler-default-off.test.ts +1 -1
  298. package/src/__tests__/profiler-phase-catalog.test.ts +2 -2
  299. package/src/__tests__/profiler-phase-integration.test.ts +5 -13
  300. package/src/__tests__/profiler-phase-token.test.ts +3 -8
  301. package/src/__tests__/public-surface.test-d.ts +65 -3
  302. package/src/__tests__/recover-error-policy-owner.unit.test.ts +1 -21
  303. package/src/__tests__/render-error-code-owner.test-d.ts +18 -23
  304. package/src/__tests__/render-error-detail-ssot.test-d.ts +0 -95
  305. package/src/__tests__/render-error-exhaustive.test-d.ts +8 -1
  306. package/src/__tests__/render-feature-assembly.test-d.ts +8 -16
  307. package/src/__tests__/render-feature-context.test-d.ts +16 -40
  308. package/src/__tests__/render-feature-contract.test-d.ts +9 -18
  309. package/src/__tests__/render-feature-diagnostics.unit.test.ts +6 -8
  310. package/src/__tests__/render-feature-docs.unit.test.ts +8 -7
  311. package/src/__tests__/render-feature-gpu-work.integration.test.ts +14 -75
  312. package/src/__tests__/render-feature-plan.test-d.ts +161 -0
  313. package/src/__tests__/render-feature-plan.unit.test.ts +170 -0
  314. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +8 -19
  315. package/src/__tests__/render-feature-prepared-errors.test-d.ts +3 -6
  316. package/src/__tests__/render-feature-prepared-graphics-docs.unit.test.ts +10 -71
  317. package/src/__tests__/render-feature-prepared-graphics-isolation.unit.test.ts +11 -61
  318. package/src/__tests__/render-feature-prepared-graphics-negative.test-d.ts +20 -43
  319. package/src/__tests__/render-feature-prepared-graphics.test-d.ts +56 -78
  320. package/src/__tests__/render-feature-public-surface.test-d.ts +6 -24
  321. package/src/__tests__/render-feature-retry.unit.test.ts +7 -48
  322. package/src/__tests__/render-feature-scheduling.unit.test.ts +15 -27
  323. package/src/__tests__/render-feature-stage-failed-policy-owner.unit.test.ts +0 -9
  324. package/src/__tests__/render-feature-stage-fault-recovery.unit.test.ts +19 -109
  325. package/src/__tests__/render-feature-visibility-context.test-d.ts +1 -6
  326. package/src/__tests__/render-feature-visibility-context.unit.test.ts +1 -2
  327. package/src/__tests__/render-feature-zero-work.unit.test.ts +14 -20
  328. package/src/__tests__/render-scene-projection.unit.test.ts +73 -111
  329. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +44 -95
  330. package/src/__tests__/renderer-lifecycle.integration.test.ts +49 -1
  331. package/src/__tests__/shader-stage-surface.unit.test.ts +14 -9
  332. package/src/__tests__/ssao-config.unit.test.ts +36 -0
  333. package/src/__tests__/ssao-kernel-surface.unit.test.ts +4 -5
  334. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +28 -0
  335. package/src/__tests__/standard-descriptors.test-d.ts +22 -0
  336. package/src/__tests__/standard-pipeline.dawn.test.ts +61 -0
  337. package/src/__tests__/standard-pipeline.integration.test.ts +124 -0
  338. package/src/__tests__/standard-profile-oracle.unit.test.ts +62 -0
  339. package/src/__tests__/surface-configuration.unit.test.ts +1 -2
  340. package/src/__tests__/texture-usage-surface.unit.test.ts +3 -6
  341. package/src/__tests__/typed-pipeline-topology.unit.test.ts +40 -206
  342. package/src/__tests__/urp-pipeline-targets.unit.test.ts +1 -11
  343. package/src/__tests__/urp-pipeline.unit.test.ts +2 -2
  344. package/src/__tests__/vertex-color-pipeline.unit.test.ts +10 -2
  345. package/src/__tests__/vertex-layout-consumer.unit.test.ts +1 -1
  346. package/src/__tests__/visibility-diagnostics.integration.test.ts +7 -11
  347. package/src/__tests__/visibility-extract.integration.test.ts +20 -11
  348. package/src/__tests__/visibility-extract.perf.test.ts +66 -32
  349. package/src/__tests__/visibility-feature-dedup.integration.test.ts +2 -4
  350. package/src/__tests__/visibility-hidden-report.unit.test.ts +1 -2
  351. package/src/__tests__/visibility-instances.integration.test.ts +7 -11
  352. package/src/__tests__/visibility-multi-world.integration.test.ts +38 -6
  353. package/src/__tests__/visibility-producer-matrix.integration.test.ts +18 -41
  354. package/src/__tests__/visibility-public-surface.test-d.ts +10 -9
  355. package/src/__tests__/visibility-resolver.unit.test.ts +2 -1
  356. package/src/__tests__/visibility-resource-short-circuit.unit.test.ts +80 -0
  357. package/src/__tests__/visibility-snapshot-contract.unit.test.ts +2 -1
  358. package/src/__tests__/vocabulary.unit.test.ts +1 -1
  359. package/src/assembly/backend-contract.ts +57 -0
  360. package/src/{renderer/renderer-factory.ts → assembly/factory.ts} +1663 -2690
  361. package/src/assembly/host-contract.ts +101 -0
  362. package/src/{renderer → assembly}/material/assembly.ts +0 -2
  363. package/src/assembly/material/pipeline-projection.ts +63 -0
  364. package/src/authoring.ts +14 -22
  365. package/src/components/__tests__/schema-contract.unit.test.ts +10 -0
  366. package/src/components/glyph-text.ts +3 -2
  367. package/src/components/index.ts +7 -9
  368. package/src/components/instances.ts +4 -5
  369. package/src/components/light-helpers.ts +1 -1
  370. package/src/components/mesh-filter.ts +11 -10
  371. package/src/components/post-process-params.ts +3 -3
  372. package/src/components/scene-instance.ts +12 -12
  373. package/src/components/skybox-background.ts +103 -0
  374. package/src/components/{environment.ts → skylight.ts} +2 -110
  375. package/src/components/sprite-animation.ts +3 -4
  376. package/src/components/sprite-instances.ts +2 -2
  377. package/src/components/sprite-playback-mode.ts +7 -1
  378. package/src/components/sprite-region-override.ts +2 -3
  379. package/src/components/tile-layer.ts +8 -2
  380. package/src/construct-renderer.ts +67 -4
  381. package/src/debug-draw-glue.ts +8 -129
  382. package/src/device/device-scope.ts +306 -0
  383. package/src/{gpu-resource-store.ts → device/gpu-residency.ts} +540 -639
  384. package/src/device/resource-types.ts +20 -0
  385. package/src/engine-metrics.ts +12 -19
  386. package/src/errors/recover.ts +45 -3
  387. package/src/errors/render.ts +357 -460
  388. package/src/features/fullscreen.ts +46 -0
  389. package/src/features/host.ts +575 -309
  390. package/src/features/morph/morph-feature.ts +195 -105
  391. package/src/features/plan.ts +447 -0
  392. package/src/features/prepared-gpu-work.ts +72 -15
  393. package/src/features/prepared-graphics-store.ts +20 -6
  394. package/src/features/prepared-graphics.ts +12 -71
  395. package/src/features/render-graph-compute.ts +14 -5
  396. package/src/features/render-graph-contribution.ts +43 -63
  397. package/src/features/render-graph-raster.ts +11 -6
  398. package/src/features/render-graph-resources.ts +25 -23
  399. package/src/features/targets.ts +8 -21
  400. package/src/features/types.ts +39 -227
  401. package/src/features/vocabulary.ts +24 -0
  402. package/src/fullscreen-post-process-pass.ts +14 -57
  403. package/src/glyph-text-layout-system.ts +70 -96
  404. package/src/gpu-driven/batch-topology.ts +24 -202
  405. package/src/gpu-driven/production-raster.ts +93 -1108
  406. package/src/gpu-driven/view-gpu.ts +46 -192
  407. package/src/gpu-resource.ts +4 -4
  408. package/src/gpu-scene-schema.ts +11 -99
  409. package/src/gpu-scene.ts +231 -364
  410. package/src/hdrp-buffers.ts +12 -221
  411. package/src/ibl/IblPipelineCache.ts +471 -711
  412. package/src/ibl/skylight-bind-group.ts +4 -4
  413. package/src/index.ts +58 -217
  414. package/src/inspection-types.ts +76 -0
  415. package/src/instance-buffer-cache.ts +1 -29
  416. package/src/internal.ts +6 -85
  417. package/src/lifecycle.ts +64 -19
  418. package/src/materials.ts +7 -29
  419. package/src/mesh-material-bindings.ts +0 -1
  420. package/src/pbr-pipeline.ts +434 -53
  421. package/src/{urp-pipeline.ts → pipeline/standard-forward-lane.ts} +38 -149
  422. package/src/{hdrp-pipeline.ts → pipeline/standard-pipeline.ts} +221 -191
  423. package/src/pipeline/standard-profile.ts +65 -0
  424. package/src/pipeline-builder.ts +60 -64
  425. package/src/pipeline-spec-types.ts +28 -0
  426. package/src/pipeline-spec.ts +72 -609
  427. package/src/plugin.ts +3 -75
  428. package/src/post-process-errors.ts +31 -33
  429. package/src/prepare/prepared-graphics-resolver.ts +5 -4
  430. package/src/record/__tests__/material-slot-plan.unit.test.ts +1 -33
  431. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +41 -0
  432. package/src/record/__tests__/video-texture-view.unit.test.ts +1 -1
  433. package/src/record/frame-lighting.ts +74 -195
  434. package/src/record/frame-snapshot.ts +45 -60
  435. package/src/record/frame-targets.ts +8 -243
  436. package/src/record/frame.ts +509 -796
  437. package/src/record/helpers.ts +6 -11
  438. package/src/record/main-pass-geometry.ts +106 -147
  439. package/src/record/main-pass-material.ts +517 -190
  440. package/src/record/main-pass-sprite-draws.ts +198 -117
  441. package/src/record/main-pass.ts +162 -143
  442. package/src/record/mesh-ssbo.ts +517 -38
  443. package/src/record/render-context.ts +364 -0
  444. package/src/record/shadow-pass.ts +138 -1838
  445. package/src/record/skybox-post-pass.ts +12 -14
  446. package/src/record/typed-frame-graph.ts +215 -254
  447. package/src/record/view-ubo.ts +6 -37
  448. package/src/render-contract.ts +571 -0
  449. package/src/render-data.ts +3 -3
  450. package/src/render-graph-primitives.ts +76 -851
  451. package/src/render-pipeline.ts +104 -188
  452. package/src/render-system-extract.ts +1048 -1729
  453. package/src/render-system.ts +330 -1957
  454. package/src/scene/render-scene-types.ts +64 -0
  455. package/src/scene/render-scene.ts +1032 -0
  456. package/src/scene-instances/post-spawn-resolve-joints.ts +4 -7
  457. package/src/ssao-buffers.ts +167 -8
  458. package/src/systems/skin-palette-allocator.ts +21 -64
  459. package/src/systems/skin-palette-types.ts +14 -0
  460. package/src/systems/transparent-sort-config.ts +25 -3
  461. package/src/tilemap-chunk-extract-system.ts +53 -70
  462. package/src/typed-render-graph-primitives.ts +35 -24
  463. package/src/typed-shadow-passes.ts +26 -56
  464. package/dist/__tests__/analytic-sky-contract.test.d.ts +0 -2
  465. package/dist/__tests__/analytic-sky-contract.test.d.ts.map +0 -1
  466. package/dist/__tests__/analytic-sky-falsify.test.d.ts +0 -2
  467. package/dist/__tests__/analytic-sky-falsify.test.d.ts.map +0 -1
  468. package/dist/__tests__/assets-runtime-handoff.integration.test.d.ts +0 -2
  469. package/dist/__tests__/assets-runtime-handoff.integration.test.d.ts.map +0 -1
  470. package/dist/__tests__/backend-selection.integration.test.d.ts +0 -2
  471. package/dist/__tests__/backend-selection.integration.test.d.ts.map +0 -1
  472. package/dist/__tests__/camera-temporal.test-d.d.ts +0 -2
  473. package/dist/__tests__/camera-temporal.test-d.d.ts.map +0 -1
  474. package/dist/__tests__/camera-temporal.test.d.ts +0 -2
  475. package/dist/__tests__/camera-temporal.test.d.ts.map +0 -1
  476. package/dist/__tests__/directional-shadow-probe-atlas-layout.unit.test.d.ts +0 -2
  477. package/dist/__tests__/directional-shadow-probe-atlas-layout.unit.test.d.ts.map +0 -1
  478. package/dist/__tests__/environment-inspection.test.d.ts +0 -2
  479. package/dist/__tests__/environment-inspection.test.d.ts.map +0 -1
  480. package/dist/__tests__/fog-ai-user.fixture.d.ts +0 -2
  481. package/dist/__tests__/fog-ai-user.fixture.d.ts.map +0 -1
  482. package/dist/__tests__/fog-custom-render-feature.fixture.d.ts +0 -16
  483. package/dist/__tests__/fog-custom-render-feature.fixture.d.ts.map +0 -1
  484. package/dist/__tests__/fog-custom-render-feature.integration.test.d.ts +0 -2
  485. package/dist/__tests__/fog-custom-render-feature.integration.test.d.ts.map +0 -1
  486. package/dist/__tests__/fog-inspection.integration.test.d.ts +0 -2
  487. package/dist/__tests__/fog-inspection.integration.test.d.ts.map +0 -1
  488. package/dist/__tests__/fog-owner-state.integration.test.d.ts +0 -2
  489. package/dist/__tests__/fog-owner-state.integration.test.d.ts.map +0 -1
  490. package/dist/__tests__/fog-pipeline-topology.integration.test.d.ts +0 -2
  491. package/dist/__tests__/fog-pipeline-topology.integration.test.d.ts.map +0 -1
  492. package/dist/__tests__/fog-public-surface.integration.test.d.ts +0 -2
  493. package/dist/__tests__/fog-public-surface.integration.test.d.ts.map +0 -1
  494. package/dist/__tests__/fog-ray-contract.integration.test.d.ts +0 -2
  495. package/dist/__tests__/fog-ray-contract.integration.test.d.ts.map +0 -1
  496. package/dist/__tests__/fog-source-absence.integration.test.d.ts +0 -2
  497. package/dist/__tests__/fog-source-absence.integration.test.d.ts.map +0 -1
  498. package/dist/__tests__/fog-temporal.integration.test.d.ts +0 -2
  499. package/dist/__tests__/fog-temporal.integration.test.d.ts.map +0 -1
  500. package/dist/__tests__/frame-chain.unit.test.d.ts +0 -2
  501. package/dist/__tests__/frame-chain.unit.test.d.ts.map +0 -1
  502. package/dist/__tests__/gpu-scene-field-type-owner.test-d.d.ts +0 -2
  503. package/dist/__tests__/gpu-scene-field-type-owner.test-d.d.ts.map +0 -1
  504. package/dist/__tests__/hdrp-pipeline.unit.test.d.ts +0 -2
  505. package/dist/__tests__/hdrp-pipeline.unit.test.d.ts.map +0 -1
  506. package/dist/__tests__/ibl/ibl-fallback.unit.test.d.ts +0 -2
  507. package/dist/__tests__/ibl/ibl-fallback.unit.test.d.ts.map +0 -1
  508. package/dist/__tests__/material-derived-error-stop-draw.integration.test.d.ts +0 -2
  509. package/dist/__tests__/material-derived-error-stop-draw.integration.test.d.ts.map +0 -1
  510. package/dist/__tests__/material-derived-payload.integration.test.d.ts +0 -2
  511. package/dist/__tests__/material-derived-payload.integration.test.d.ts.map +0 -1
  512. package/dist/__tests__/materials.unit.test.d.ts +0 -2
  513. package/dist/__tests__/materials.unit.test.d.ts.map +0 -1
  514. package/dist/__tests__/param-schema-projection-census.unit.test.d.ts +0 -2
  515. package/dist/__tests__/param-schema-projection-census.unit.test.d.ts.map +0 -1
  516. package/dist/__tests__/persistent-render-scene.unit.test.d.ts +0 -2
  517. package/dist/__tests__/persistent-render-scene.unit.test.d.ts.map +0 -1
  518. package/dist/__tests__/pipeline-error-policy-owner.unit.test.d.ts +0 -2
  519. package/dist/__tests__/pipeline-error-policy-owner.unit.test.d.ts.map +0 -1
  520. package/dist/__tests__/pipeline-pass-trace.test.d.ts +0 -2
  521. package/dist/__tests__/pipeline-pass-trace.test.d.ts.map +0 -1
  522. package/dist/__tests__/pipeline-stage-owner.test-d.d.ts +0 -2
  523. package/dist/__tests__/pipeline-stage-owner.test-d.d.ts.map +0 -1
  524. package/dist/__tests__/plugin.test.d.ts +0 -2
  525. package/dist/__tests__/plugin.test.d.ts.map +0 -1
  526. package/dist/__tests__/prepared-graphics-backend-matrix.unit.test.d.ts +0 -2
  527. package/dist/__tests__/prepared-graphics-backend-matrix.unit.test.d.ts.map +0 -1
  528. package/dist/__tests__/prepared-graphics-resolver-recording.unit.test.d.ts +0 -2
  529. package/dist/__tests__/prepared-graphics-resolver-recording.unit.test.d.ts.map +0 -1
  530. package/dist/__tests__/public-pipeline-id.test-d.d.ts +0 -2
  531. package/dist/__tests__/public-pipeline-id.test-d.d.ts.map +0 -1
  532. package/dist/__tests__/render-dispatch-membership.unit.test.d.ts +0 -2
  533. package/dist/__tests__/render-dispatch-membership.unit.test.d.ts.map +0 -1
  534. package/dist/__tests__/render-feature-construction.unit.test.d.ts +0 -2
  535. package/dist/__tests__/render-feature-construction.unit.test.d.ts.map +0 -1
  536. package/dist/__tests__/render-feature-error-code-owner.test-d.d.ts +0 -2
  537. package/dist/__tests__/render-feature-error-code-owner.test-d.d.ts.map +0 -1
  538. package/dist/__tests__/render-feature-gpu-buffer-usage-owner.test-d.d.ts +0 -2
  539. package/dist/__tests__/render-feature-gpu-buffer-usage-owner.test-d.d.ts.map +0 -1
  540. package/dist/__tests__/render-feature-graph.integration.test.d.ts +0 -2
  541. package/dist/__tests__/render-feature-graph.integration.test.d.ts.map +0 -1
  542. package/dist/__tests__/render-feature-graphics-staging.unit.test.d.ts +0 -2
  543. package/dist/__tests__/render-feature-graphics-staging.unit.test.d.ts.map +0 -1
  544. package/dist/__tests__/render-feature-order.unit.test.d.ts +0 -2
  545. package/dist/__tests__/render-feature-order.unit.test.d.ts.map +0 -1
  546. package/dist/__tests__/render-feature-prepared-graphics-recording.unit.test.d.ts +0 -2
  547. package/dist/__tests__/render-feature-prepared-graphics-recording.unit.test.d.ts.map +0 -1
  548. package/dist/__tests__/render-feature-staging.unit.test.d.ts +0 -2
  549. package/dist/__tests__/render-feature-staging.unit.test.d.ts.map +0 -1
  550. package/dist/__tests__/renderer-render-scene-public.test-d.d.ts +0 -2
  551. package/dist/__tests__/renderer-render-scene-public.test-d.d.ts.map +0 -1
  552. package/dist/__tests__/scene-temporal-coverage.unit.test.d.ts +0 -2
  553. package/dist/__tests__/scene-temporal-coverage.unit.test.d.ts.map +0 -1
  554. package/dist/__tests__/sun-snapshot-consumers.test.d.ts +0 -2
  555. package/dist/__tests__/sun-snapshot-consumers.test.d.ts.map +0 -1
  556. package/dist/__tests__/surface-backend-kind-owner.test-d.d.ts +0 -2
  557. package/dist/__tests__/surface-backend-kind-owner.test-d.d.ts.map +0 -1
  558. package/dist/__tests__/taa-history-store.unit.test.d.ts +0 -2
  559. package/dist/__tests__/taa-history-store.unit.test.d.ts.map +0 -1
  560. package/dist/__tests__/temporal-frame-transaction.integration.test.d.ts +0 -2
  561. package/dist/__tests__/temporal-frame-transaction.integration.test.d.ts.map +0 -1
  562. package/dist/__tests__/temporal-inspection.unit.test.d.ts +0 -2
  563. package/dist/__tests__/temporal-inspection.unit.test.d.ts.map +0 -1
  564. package/dist/assets/__tests__/asset-decoders.unit.test.d.ts +0 -2
  565. package/dist/assets/__tests__/asset-decoders.unit.test.d.ts.map +0 -1
  566. package/dist/assets/__tests__/mipmap-generator.unit.test.d.ts +0 -2
  567. package/dist/assets/__tests__/mipmap-generator.unit.test.d.ts.map +0 -1
  568. package/dist/assets/__tests__/render-asset-port.unit.test.d.ts +0 -2
  569. package/dist/assets/__tests__/render-asset-port.unit.test.d.ts.map +0 -1
  570. package/dist/assets/__tests__/resolve-render-asset.unit.test.d.ts +0 -2
  571. package/dist/assets/__tests__/resolve-render-asset.unit.test.d.ts.map +0 -1
  572. package/dist/chunk-DJIMFYX6.mjs +0 -1439
  573. package/dist/chunk-DJIMFYX6.mjs.map +0 -1
  574. package/dist/chunk-F2SIOCRM.mjs +0 -7423
  575. package/dist/chunk-F2SIOCRM.mjs.map +0 -1
  576. package/dist/chunk-JMSB7AR4.mjs +0 -3
  577. package/dist/chunk-JMSB7AR4.mjs.map +0 -1
  578. package/dist/chunk-KHI6K4C6.mjs +0 -659
  579. package/dist/chunk-KHI6K4C6.mjs.map +0 -1
  580. package/dist/chunk-PORZOL2V.mjs +0 -569
  581. package/dist/chunk-PORZOL2V.mjs.map +0 -1
  582. package/dist/chunk-UOJGMDGP.mjs +0 -29913
  583. package/dist/chunk-UOJGMDGP.mjs.map +0 -1
  584. package/dist/components/__tests__/atmosphere-red.test.d.ts +0 -2
  585. package/dist/components/__tests__/atmosphere-red.test.d.ts.map +0 -1
  586. package/dist/components/__tests__/atmosphere.test.d.ts +0 -2
  587. package/dist/components/__tests__/atmosphere.test.d.ts.map +0 -1
  588. package/dist/components/__tests__/fog.test-d.d.ts +0 -2
  589. package/dist/components/__tests__/fog.test-d.d.ts.map +0 -1
  590. package/dist/components/__tests__/fog.test.d.ts +0 -2
  591. package/dist/components/__tests__/fog.test.d.ts.map +0 -1
  592. package/dist/components/atmosphere.d.ts +0 -18
  593. package/dist/components/atmosphere.d.ts.map +0 -1
  594. package/dist/components/environment.d.ts +0 -115
  595. package/dist/components/environment.d.ts.map +0 -1
  596. package/dist/deferred-lighting.d.ts +0 -13
  597. package/dist/deferred-lighting.d.ts.map +0 -1
  598. package/dist/dynamic-texture-store.d.ts +0 -42
  599. package/dist/dynamic-texture-store.d.ts.map +0 -1
  600. package/dist/environment/__tests__/failure-injection.test.d.ts +0 -2
  601. package/dist/environment/__tests__/failure-injection.test.d.ts.map +0 -1
  602. package/dist/environment/__tests__/generation-red.test.d.ts +0 -2
  603. package/dist/environment/__tests__/generation-red.test.d.ts.map +0 -1
  604. package/dist/environment/__tests__/generation.test.d.ts +0 -2
  605. package/dist/environment/__tests__/generation.test.d.ts.map +0 -1
  606. package/dist/environment/__tests__/graph-transaction.test.d.ts +0 -2
  607. package/dist/environment/__tests__/graph-transaction.test.d.ts.map +0 -1
  608. package/dist/environment/__tests__/inspection-red.test.d.ts +0 -2
  609. package/dist/environment/__tests__/inspection-red.test.d.ts.map +0 -1
  610. package/dist/environment/__tests__/lifecycle-evidence.test.d.ts +0 -2
  611. package/dist/environment/__tests__/lifecycle-evidence.test.d.ts.map +0 -1
  612. package/dist/environment/__tests__/pipeline-topology.test.d.ts +0 -2
  613. package/dist/environment/__tests__/pipeline-topology.test.d.ts.map +0 -1
  614. package/dist/environment/__tests__/readiness.test.d.ts +0 -2
  615. package/dist/environment/__tests__/readiness.test.d.ts.map +0 -1
  616. package/dist/environment/__tests__/recovery.test.d.ts +0 -2
  617. package/dist/environment/__tests__/recovery.test.d.ts.map +0 -1
  618. package/dist/environment/__tests__/resize-dispose.test.d.ts +0 -2
  619. package/dist/environment/__tests__/resize-dispose.test.d.ts.map +0 -1
  620. package/dist/environment/__tests__/signature-red.test.d.ts +0 -2
  621. package/dist/environment/__tests__/signature-red.test.d.ts.map +0 -1
  622. package/dist/environment/__tests__/signature.test.d.ts +0 -2
  623. package/dist/environment/__tests__/signature.test.d.ts.map +0 -1
  624. package/dist/environment/descriptors.d.ts +0 -2
  625. package/dist/environment/descriptors.d.ts.map +0 -1
  626. package/dist/environment/extracted-environment.d.ts +0 -53
  627. package/dist/environment/extracted-environment.d.ts.map +0 -1
  628. package/dist/environment/generation.d.ts +0 -62
  629. package/dist/environment/generation.d.ts.map +0 -1
  630. package/dist/environment/gpu-bundle.d.ts +0 -23
  631. package/dist/environment/gpu-bundle.d.ts.map +0 -1
  632. package/dist/environment/graph.d.ts +0 -108
  633. package/dist/environment/graph.d.ts.map +0 -1
  634. package/dist/environment/inspection.d.ts +0 -48
  635. package/dist/environment/inspection.d.ts.map +0 -1
  636. package/dist/environment/lifecycle.d.ts +0 -22
  637. package/dist/environment/lifecycle.d.ts.map +0 -1
  638. package/dist/environment/readiness.d.ts +0 -29
  639. package/dist/environment/readiness.d.ts.map +0 -1
  640. package/dist/environment/signature.d.ts +0 -70
  641. package/dist/environment/signature.d.ts.map +0 -1
  642. package/dist/extract/__tests__/directional-csm-domain.unit.test.d.ts +0 -2
  643. package/dist/extract/__tests__/directional-csm-domain.unit.test.d.ts.map +0 -1
  644. package/dist/extract/__tests__/environment-source.test.d.ts +0 -2
  645. package/dist/extract/__tests__/environment-source.test.d.ts.map +0 -1
  646. package/dist/extract/__tests__/schema-readers.unit.test.d.ts +0 -2
  647. package/dist/extract/__tests__/schema-readers.unit.test.d.ts.map +0 -1
  648. package/dist/extract/directional-csm.d.ts +0 -129
  649. package/dist/extract/directional-csm.d.ts.map +0 -1
  650. package/dist/extract/index.d.ts +0 -5
  651. package/dist/extract/index.d.ts.map +0 -1
  652. package/dist/extract/material-interface.d.ts +0 -56
  653. package/dist/extract/material-interface.d.ts.map +0 -1
  654. package/dist/extract/schema-readers.d.ts +0 -20
  655. package/dist/extract/schema-readers.d.ts.map +0 -1
  656. package/dist/features/graph-contribution.d.ts +0 -64
  657. package/dist/features/graph-contribution.d.ts.map +0 -1
  658. package/dist/features/index.d.ts +0 -21
  659. package/dist/features/index.d.ts.map +0 -1
  660. package/dist/features/morph/index.d.ts +0 -3
  661. package/dist/features/morph/index.d.ts.map +0 -1
  662. package/dist/features/morph/morph-bounds.d.ts +0 -42
  663. package/dist/features/morph/morph-bounds.d.ts.map +0 -1
  664. package/dist/features/scene-temporal.d.ts +0 -45
  665. package/dist/features/scene-temporal.d.ts.map +0 -1
  666. package/dist/features/taa-resolve.d.ts +0 -21
  667. package/dist/features/taa-resolve.d.ts.map +0 -1
  668. package/dist/frame-chain.d.ts +0 -14
  669. package/dist/frame-chain.d.ts.map +0 -1
  670. package/dist/gpu-driven/view-reference.d.ts.map +0 -1
  671. package/dist/gpu-resource-store.d.ts.map +0 -1
  672. package/dist/hdrp-cluster-membership.d.ts +0 -2
  673. package/dist/hdrp-cluster-membership.d.ts.map +0 -1
  674. package/dist/hdrp-pipeline.d.ts +0 -36
  675. package/dist/hdrp-pipeline.d.ts.map +0 -1
  676. package/dist/ibl/cubemap-projection.d.ts +0 -23
  677. package/dist/ibl/cubemap-projection.d.ts.map +0 -1
  678. package/dist/ibl/face-uniforms.d.ts +0 -65
  679. package/dist/ibl/face-uniforms.d.ts.map +0 -1
  680. package/dist/mesh-update-errors.d.ts +0 -71
  681. package/dist/mesh-update-errors.d.ts.map +0 -1
  682. package/dist/mipmap-generator.d.ts +0 -39
  683. package/dist/mipmap-generator.d.ts.map +0 -1
  684. package/dist/param-schema-projection-census.d.ts +0 -18
  685. package/dist/param-schema-projection-census.d.ts.map +0 -1
  686. package/dist/persistent-render-scene.d.ts +0 -158
  687. package/dist/persistent-render-scene.d.ts.map +0 -1
  688. package/dist/pipeline/index.d.ts +0 -11
  689. package/dist/pipeline/index.d.ts.map +0 -1
  690. package/dist/pipeline-errors.d.ts +0 -110
  691. package/dist/pipeline-errors.d.ts.map +0 -1
  692. package/dist/prepare/__tests__/schema-readers.unit.test.d.ts +0 -2
  693. package/dist/prepare/__tests__/schema-readers.unit.test.d.ts.map +0 -1
  694. package/dist/prepare/index.d.ts +0 -4
  695. package/dist/prepare/index.d.ts.map +0 -1
  696. package/dist/prepare/schema-readers.d.ts +0 -11
  697. package/dist/prepare/schema-readers.d.ts.map +0 -1
  698. package/dist/record/__tests__/environment-record.test.d.ts +0 -2
  699. package/dist/record/__tests__/environment-record.test.d.ts.map +0 -1
  700. package/dist/record/__tests__/frame-targets.unit.test.d.ts +0 -2
  701. package/dist/record/__tests__/frame-targets.unit.test.d.ts.map +0 -1
  702. package/dist/record/__tests__/membership-timing.unit.test.d.ts +0 -2
  703. package/dist/record/__tests__/membership-timing.unit.test.d.ts.map +0 -1
  704. package/dist/record/__tests__/render-submission.integration.test.d.ts +0 -2
  705. package/dist/record/__tests__/render-submission.integration.test.d.ts.map +0 -1
  706. package/dist/record/__tests__/render-submission.perf.test.d.ts +0 -2
  707. package/dist/record/__tests__/render-submission.perf.test.d.ts.map +0 -1
  708. package/dist/record/__tests__/shadow-submit-mode.unit.test.d.ts +0 -2
  709. package/dist/record/__tests__/shadow-submit-mode.unit.test.d.ts.map +0 -1
  710. package/dist/record/__tests__/view-ubo-layout.unit.test.d.ts +0 -2
  711. package/dist/record/__tests__/view-ubo-layout.unit.test.d.ts.map +0 -1
  712. package/dist/record/frame-observation.d.ts +0 -38
  713. package/dist/record/frame-observation.d.ts.map +0 -1
  714. package/dist/record/index.d.ts +0 -15
  715. package/dist/record/index.d.ts.map +0 -1
  716. package/dist/record/main-pass-skin.d.ts +0 -46
  717. package/dist/record/main-pass-skin.d.ts.map +0 -1
  718. package/dist/record/main-pass-sprite.d.ts +0 -69
  719. package/dist/record/main-pass-sprite.d.ts.map +0 -1
  720. package/dist/record/material-payload.d.ts +0 -43
  721. package/dist/record/material-payload.d.ts.map +0 -1
  722. package/dist/record/material-slot-plan.d.ts +0 -26
  723. package/dist/record/material-slot-plan.d.ts.map +0 -1
  724. package/dist/record/membership-timing.d.ts +0 -232
  725. package/dist/record/membership-timing.d.ts.map +0 -1
  726. package/dist/record/shadow-caster-uniform.d.ts +0 -8
  727. package/dist/record/shadow-caster-uniform.d.ts.map +0 -1
  728. package/dist/record/shadow-submit-mode.d.ts +0 -66
  729. package/dist/record/shadow-submit-mode.d.ts.map +0 -1
  730. package/dist/render-dispatch-membership.d.ts +0 -47
  731. package/dist/render-dispatch-membership.d.ts.map +0 -1
  732. package/dist/render-pipeline-context.d.ts +0 -289
  733. package/dist/render-pipeline-context.d.ts.map +0 -1
  734. package/dist/render-pipeline-target.d.ts +0 -16
  735. package/dist/render-pipeline-target.d.ts.map +0 -1
  736. package/dist/render-scene-projection.d.ts +0 -174
  737. package/dist/render-scene-projection.d.ts.map +0 -1
  738. package/dist/render-system-fold.d.ts +0 -266
  739. package/dist/render-system-fold.d.ts.map +0 -1
  740. package/dist/renderer/asset-service.d.ts +0 -10
  741. package/dist/renderer/asset-service.d.ts.map +0 -1
  742. package/dist/renderer/backend-selection.d.ts.map +0 -1
  743. package/dist/renderer/environment-classify.d.ts +0 -6
  744. package/dist/renderer/environment-classify.d.ts.map +0 -1
  745. package/dist/renderer/environment-error.d.ts +0 -13
  746. package/dist/renderer/environment-error.d.ts.map +0 -1
  747. package/dist/renderer/material/pipeline-projection.d.ts +0 -91
  748. package/dist/renderer/material/pipeline-projection.d.ts.map +0 -1
  749. package/dist/renderer/renderer-factory.d.ts +0 -289
  750. package/dist/renderer/renderer-factory.d.ts.map +0 -1
  751. package/dist/renderer.d.ts +0 -771
  752. package/dist/renderer.d.ts.map +0 -1
  753. package/dist/scene-utils/collect-subtree.d.ts +0 -11
  754. package/dist/scene-utils/collect-subtree.d.ts.map +0 -1
  755. package/dist/ssao-data.d.ts +0 -34
  756. package/dist/ssao-data.d.ts.map +0 -1
  757. package/dist/surface-format.d.ts +0 -10
  758. package/dist/surface-format.d.ts.map +0 -1
  759. package/dist/taa-history-store.d.ts +0 -88
  760. package/dist/taa-history-store.d.ts.map +0 -1
  761. package/dist/temporal-coverage.d.ts +0 -35
  762. package/dist/temporal-coverage.d.ts.map +0 -1
  763. package/dist/temporal-frame-transaction.d.ts +0 -92
  764. package/dist/temporal-frame-transaction.d.ts.map +0 -1
  765. package/dist/temporal-inspection.d.ts +0 -57
  766. package/dist/temporal-inspection.d.ts.map +0 -1
  767. package/dist/temporal-view.d.ts +0 -43
  768. package/dist/temporal-view.d.ts.map +0 -1
  769. package/dist/tilemap/resolve-tileset-runtime.d.ts +0 -23
  770. package/dist/tilemap/resolve-tileset-runtime.d.ts.map +0 -1
  771. package/dist/urp-pipeline.d.ts +0 -4
  772. package/dist/urp-pipeline.d.ts.map +0 -1
  773. package/src/__tests__/analytic-sky-contract.test.ts +0 -27
  774. package/src/__tests__/analytic-sky-falsify-carriers.mjs +0 -43
  775. package/src/__tests__/analytic-sky-falsify.test.ts +0 -94
  776. package/src/__tests__/assets-runtime-handoff.integration.test.ts +0 -36
  777. package/src/__tests__/backend-selection.integration.test.ts +0 -11
  778. package/src/__tests__/camera-temporal.test-d.ts +0 -8
  779. package/src/__tests__/camera-temporal.test.ts +0 -188
  780. package/src/__tests__/directional-shadow-probe-atlas-layout.unit.test.ts +0 -18
  781. package/src/__tests__/environment-inspection.test.ts +0 -45
  782. package/src/__tests__/fog-ai-user.fixture.ts +0 -350
  783. package/src/__tests__/fog-custom-render-feature.fixture.ts +0 -33
  784. package/src/__tests__/fog-custom-render-feature.integration.test.ts +0 -76
  785. package/src/__tests__/fog-inspection.integration.test.ts +0 -127
  786. package/src/__tests__/fog-owner-state.integration.test.ts +0 -112
  787. package/src/__tests__/fog-pipeline-topology.integration.test.ts +0 -93
  788. package/src/__tests__/fog-public-surface.integration.test.ts +0 -60
  789. package/src/__tests__/fog-ray-contract.integration.test.ts +0 -73
  790. package/src/__tests__/fog-source-absence.integration.test.ts +0 -51
  791. package/src/__tests__/fog-temporal.integration.test.ts +0 -115
  792. package/src/__tests__/frame-chain.unit.test.ts +0 -26
  793. package/src/__tests__/gpu-scene-field-type-owner.test-d.ts +0 -27
  794. package/src/__tests__/hdrp-pipeline.unit.test.ts +0 -100
  795. package/src/__tests__/ibl/ibl-fallback.unit.test.ts +0 -23
  796. package/src/__tests__/material-derived-error-stop-draw.integration.test.ts +0 -69
  797. package/src/__tests__/material-derived-payload.integration.test.ts +0 -164
  798. package/src/__tests__/materials.unit.test.ts +0 -25
  799. package/src/__tests__/param-schema-projection-census.unit.test.ts +0 -40
  800. package/src/__tests__/persistent-render-scene.unit.test.ts +0 -1311
  801. package/src/__tests__/pipeline-error-policy-owner.unit.test.ts +0 -167
  802. package/src/__tests__/pipeline-pass-trace.test.ts +0 -92
  803. package/src/__tests__/pipeline-stage-owner.test-d.ts +0 -13
  804. package/src/__tests__/plugin.test.ts +0 -25
  805. package/src/__tests__/prepared-graphics-backend-matrix.unit.test.ts +0 -129
  806. package/src/__tests__/prepared-graphics-resolver-recording.unit.test.ts +0 -180
  807. package/src/__tests__/public-pipeline-id.test-d.ts +0 -6
  808. package/src/__tests__/render-dispatch-membership.unit.test.ts +0 -117
  809. package/src/__tests__/render-feature-construction.unit.test.ts +0 -124
  810. package/src/__tests__/render-feature-error-code-owner.test-d.ts +0 -27
  811. package/src/__tests__/render-feature-gpu-buffer-usage-owner.test-d.ts +0 -46
  812. package/src/__tests__/render-feature-graph.integration.test.ts +0 -205
  813. package/src/__tests__/render-feature-graphics-staging.unit.test.ts +0 -200
  814. package/src/__tests__/render-feature-order.unit.test.ts +0 -66
  815. package/src/__tests__/render-feature-prepared-graphics-recording.unit.test.ts +0 -107
  816. package/src/__tests__/render-feature-staging.unit.test.ts +0 -94
  817. package/src/__tests__/renderer-render-scene-public.test-d.ts +0 -27
  818. package/src/__tests__/scene-temporal-coverage.unit.test.ts +0 -259
  819. package/src/__tests__/sun-snapshot-consumers.test.ts +0 -35
  820. package/src/__tests__/surface-backend-kind-owner.test-d.ts +0 -42
  821. package/src/__tests__/taa-history-store.unit.test.ts +0 -196
  822. package/src/__tests__/temporal-frame-transaction.integration.test.ts +0 -537
  823. package/src/__tests__/temporal-inspection.unit.test.ts +0 -138
  824. package/src/assets/__tests__/asset-decoders.unit.test.ts +0 -92
  825. package/src/assets/__tests__/mipmap-generator.unit.test.ts +0 -52
  826. package/src/assets/__tests__/render-asset-port.unit.test.ts +0 -54
  827. package/src/assets/__tests__/resolve-render-asset.unit.test.ts +0 -47
  828. package/src/components/__tests__/atmosphere-red.test.ts +0 -51
  829. package/src/components/__tests__/atmosphere.test.ts +0 -79
  830. package/src/components/__tests__/fog.test-d.ts +0 -49
  831. package/src/components/__tests__/fog.test.ts +0 -60
  832. package/src/components/atmosphere.ts +0 -64
  833. package/src/deferred-lighting.ts +0 -92
  834. package/src/dynamic-texture-store.ts +0 -111
  835. package/src/environment/README.md +0 -76
  836. package/src/environment/__tests__/failure-injection.test.ts +0 -50
  837. package/src/environment/__tests__/generation-red.test.ts +0 -64
  838. package/src/environment/__tests__/generation.test.ts +0 -37
  839. package/src/environment/__tests__/graph-transaction.test.ts +0 -85
  840. package/src/environment/__tests__/inspection-red.test.ts +0 -53
  841. package/src/environment/__tests__/lifecycle-evidence.test.ts +0 -40
  842. package/src/environment/__tests__/pipeline-topology.test.ts +0 -33
  843. package/src/environment/__tests__/readiness.test.ts +0 -42
  844. package/src/environment/__tests__/recovery.test.ts +0 -62
  845. package/src/environment/__tests__/resize-dispose.test.ts +0 -30
  846. package/src/environment/__tests__/signature-red.test.ts +0 -45
  847. package/src/environment/__tests__/signature.test.ts +0 -60
  848. package/src/environment/descriptors.ts +0 -7
  849. package/src/environment/extracted-environment.ts +0 -239
  850. package/src/environment/generation.ts +0 -158
  851. package/src/environment/gpu-bundle.ts +0 -144
  852. package/src/environment/graph.ts +0 -588
  853. package/src/environment/inspection.ts +0 -107
  854. package/src/environment/lifecycle.ts +0 -124
  855. package/src/environment/readiness.ts +0 -76
  856. package/src/environment/signature.ts +0 -185
  857. package/src/extract/__tests__/directional-csm-domain.unit.test.ts +0 -391
  858. package/src/extract/__tests__/environment-source.test.ts +0 -105
  859. package/src/extract/__tests__/schema-readers.unit.test.ts +0 -16
  860. package/src/extract/directional-csm.ts +0 -959
  861. package/src/extract/index.ts +0 -10
  862. package/src/extract/material-interface.ts +0 -604
  863. package/src/extract/schema-readers.ts +0 -27
  864. package/src/features/graph-contribution.ts +0 -577
  865. package/src/features/index.ts +0 -100
  866. package/src/features/morph/index.ts +0 -24
  867. package/src/features/morph/morph-bounds.ts +0 -123
  868. package/src/features/scene-temporal.ts +0 -274
  869. package/src/features/taa-resolve.ts +0 -244
  870. package/src/frame-chain.ts +0 -21
  871. package/src/hdrp-cluster-membership.ts +0 -70
  872. package/src/ibl/cubemap-projection.ts +0 -60
  873. package/src/ibl/face-uniforms.ts +0 -150
  874. package/src/mesh-update-errors.ts +0 -113
  875. package/src/mipmap-generator.ts +0 -244
  876. package/src/param-schema-projection-census.ts +0 -73
  877. package/src/persistent-render-scene.ts +0 -1752
  878. package/src/pipeline/index.ts +0 -40
  879. package/src/pipeline-errors.ts +0 -172
  880. package/src/prepare/__tests__/schema-readers.unit.test.ts +0 -16
  881. package/src/prepare/index.ts +0 -8
  882. package/src/prepare/schema-readers.ts +0 -20
  883. package/src/record/__tests__/environment-record.test.ts +0 -35
  884. package/src/record/__tests__/frame-targets.unit.test.ts +0 -54
  885. package/src/record/__tests__/membership-timing.unit.test.ts +0 -524
  886. package/src/record/__tests__/render-submission.integration.test.ts +0 -76
  887. package/src/record/__tests__/render-submission.perf.test.ts +0 -141
  888. package/src/record/__tests__/shadow-submit-mode.unit.test.ts +0 -88
  889. package/src/record/__tests__/view-ubo-layout.unit.test.ts +0 -101
  890. package/src/record/frame-observation.ts +0 -122
  891. package/src/record/index.ts +0 -15
  892. package/src/record/main-pass-skin.ts +0 -51
  893. package/src/record/main-pass-sprite.ts +0 -166
  894. package/src/record/material-payload.ts +0 -292
  895. package/src/record/material-slot-plan.ts +0 -68
  896. package/src/record/membership-timing.ts +0 -1012
  897. package/src/record/shadow-caster-uniform.ts +0 -37
  898. package/src/record/shadow-submit-mode.ts +0 -277
  899. package/src/render-dispatch-membership.ts +0 -155
  900. package/src/render-pipeline-context.ts +0 -332
  901. package/src/render-pipeline-target.ts +0 -96
  902. package/src/render-scene-projection.ts +0 -1738
  903. package/src/render-system-fold.ts +0 -531
  904. package/src/renderer/asset-service.ts +0 -32
  905. package/src/renderer/backend-selection.ts +0 -121
  906. package/src/renderer/environment-classify.ts +0 -30
  907. package/src/renderer/environment-error.ts +0 -19
  908. package/src/renderer/material/pipeline-projection.ts +0 -140
  909. package/src/renderer.ts +0 -940
  910. package/src/scene-utils/collect-subtree.ts +0 -40
  911. package/src/ssao-data.ts +0 -106
  912. package/src/surface-format.ts +0 -37
  913. package/src/taa-history-store.ts +0 -429
  914. package/src/temporal-coverage.ts +0 -106
  915. package/src/temporal-frame-transaction.ts +0 -301
  916. package/src/temporal-inspection.ts +0 -194
  917. package/src/temporal-view.ts +0 -174
  918. package/src/tilemap/resolve-tileset-runtime.ts +0 -72
@@ -13,59 +13,32 @@ import type {
13
13
  Result,
14
14
  RhiDevice,
15
15
  ShaderModule,
16
+ TextureFormat,
16
17
  } from '@forgeax/engine-rhi';
17
18
  import { err, ok, RhiError } from '@forgeax/engine-rhi';
18
- import { type MaterialRenderState, RenderQueue } from '@forgeax/engine-types';
19
+ import type { MaterialRenderState } from '@forgeax/engine-types';
20
+ import type { MeshGpuHandles } from '../device/gpu-residency';
19
21
  import { GPU_SCENE_WGSL } from '../gpu-scene-schema';
20
22
  import {
21
23
  GPU_BUFFER_USAGE_COPY_DST,
22
24
  GPU_BUFFER_USAGE_INDEX,
23
- GPU_BUFFER_USAGE_UNIFORM,
24
25
  GPU_BUFFER_USAGE_VERTEX,
25
26
  } from '../gpu-usage';
26
- import type { PersistentGpuDrivenState } from '../persistent-render-scene';
27
+ import type { GpuDrivenProductionInspection } from '../inspection-types';
27
28
  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';
29
+ import { worldEntityKey } from '../record/frame-snapshot';
30
+ import { geometryRenderStateForTopology } from '../record/main-pass-material';
31
+ import type { CameraSnapshot } from '../render-contract';
32
+ import type { RenderPipelineFrame, RenderPipelineGpuDrivenProjection } from '../render-pipeline';
33
+ import type { RenderableSnapshot } from '../render-system-extract';
34
+ import type { PersistentGpuDrivenState } from '../scene/render-scene';
35
+ import type { GpuDrivenBatch, SubmissionPlan } from './batch-topology';
36
+ import { GpuDrivenView } from './view-gpu';
55
37
 
56
38
  const VERTEX_STAGE = 0x1;
57
39
  const FRAGMENT_STAGE = 0x2;
58
40
  const EMPTY_RESOURCE_CLASS = JSON.stringify({ textures: [], samplers: [], video: [] });
59
41
 
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
42
  export const GPU_DRIVEN_RIGID_UNLIT_WGSL = /* wgsl */ `
70
43
  ${GPU_SCENE_WGSL}
71
44
 
@@ -110,45 +83,6 @@ fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
110
83
  }
111
84
  `;
112
85
 
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
86
  interface PreparedBatch {
153
87
  readonly batch: GpuDrivenBatch;
154
88
  readonly mesh: MeshGpuHandles;
@@ -199,85 +133,19 @@ function activeFrustum(camera: CameraSnapshot): Float32Array {
199
133
  );
200
134
  }
201
135
 
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 {
136
+ function productionEligible(snapshot: RenderableSnapshot, batch: GpuDrivenBatch): boolean {
228
137
  const material = snapshot.materials[batch.key.materialSlot] ?? snapshot.material;
229
138
  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
139
  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
140
+ shader === 'forgeax::default-unlit' &&
141
+ batch.key.materialResourceClass === EMPTY_RESOURCE_CLASS &&
142
+ material.baseColorTexture === undefined &&
143
+ material.transparent !== true
276
144
  );
277
145
  }
278
146
 
279
147
  function meshSupportsBatch(mesh: MeshGpuHandles, batch: GpuDrivenBatch): boolean {
280
- if (!supportsRigidGpuDrivenProjection(mesh)) return false;
148
+ if (mesh.layoutProjection.arrayStride !== 48) return false;
281
149
  return batch.key.drawKind === 'indexed'
282
150
  ? mesh.indexed && mesh.indexBuffer !== null
283
151
  : !mesh.indexed;
@@ -289,159 +157,72 @@ function filteredPlan(
289
157
  meshes: ReadonlyMap<number, MeshGpuHandles>,
290
158
  ): {
291
159
  readonly plan: SubmissionPlan;
292
- readonly shadowPlan: SubmissionPlan;
293
160
  readonly batches: readonly PreparedBatch[];
294
- readonly itemKeys: ReadonlySet<RasterItemKey>;
295
- readonly forwardItemKeys: ReadonlySet<RasterItemKey>;
161
+ readonly entityKeys: ReadonlySet<number>;
296
162
  } {
297
163
  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;
164
+ const entityKeys = new Set<number>();
165
+ const eligiblePrimitives = new Set<number>();
301
166
  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;
167
+ const mesh = meshes.get(slot.snapshot.assetHandle);
168
+ const participating = source.batches.filter((batch) =>
169
+ batch.candidates.some((candidate) => candidate.primitiveIndex === slot.slot),
170
+ );
171
+ if (
172
+ mesh !== undefined &&
173
+ participating.length === (slot.snapshot.gpuDrivenDraws?.length ?? 0) &&
174
+ participating.every(
175
+ (batch) => productionEligible(slot.snapshot, batch) && meshSupportsBatch(mesh, batch),
176
+ )
177
+ ) {
178
+ eligiblePrimitives.add(slot.slot);
179
+ entityKeys.add(worldEntityKey(slot.snapshot.worldId, slot.snapshot.entityKey));
311
180
  }
312
181
  }
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>();
182
+ const batches: PreparedBatch[] = [];
183
+ let visibleBase = 0;
184
+ const filteredBatches: GpuDrivenBatch[] = [];
317
185
  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
186
  const candidates = batch.candidates.filter((candidate) => {
325
187
  const slot = slotByPrimitive.get(candidate.primitiveIndex);
326
- if (slot === undefined || !productionEligible(slot.snapshot, batch)) return false;
188
+ if (slot === undefined || !eligiblePrimitives.has(slot.slot)) return false;
327
189
  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;
190
+ return mesh !== undefined && meshSupportsBatch(mesh, batch);
340
191
  });
341
192
  if (candidates.length === 0) continue;
193
+ visibleBase = Math.ceil(visibleBase / 64) * 64;
194
+ const filtered: GpuDrivenBatch = Object.freeze({
195
+ ...batch,
196
+ candidates: Object.freeze(candidates),
197
+ visibleBase,
198
+ visibleCapacity: candidates.length,
199
+ });
200
+ visibleBase += candidates.length;
342
201
  const first = slotByPrimitive.get(candidates[0]?.primitiveIndex ?? -1);
343
202
  const mesh = first === undefined ? undefined : meshes.get(first.snapshot.assetHandle);
344
203
  if (mesh === undefined || first === undefined) continue;
345
- candidatesByBatch.set(batch.batchId, Object.freeze(candidates));
346
- meshByBatch.set(batch.batchId, mesh);
204
+ filteredBatches.push(filtered);
347
205
  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
206
  batches.push({
375
- batch,
207
+ batch: filtered,
376
208
  mesh,
377
- renderState: renderStateByBatch.get(batch.batchId),
209
+ renderState: geometryRenderStateForTopology(batch.key.topology, material.renderState),
378
210
  });
379
211
  }
380
212
  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,
213
+ plan: Object.freeze({
214
+ revision: source.revision,
215
+ batches: Object.freeze(filteredBatches),
216
+ candidateCount: filteredBatches.reduce((total, batch) => total + batch.candidates.length, 0),
217
+ visibleCapacity: visibleBase,
218
+ }),
386
219
  batches: Object.freeze(batches),
387
- itemKeys,
388
- forwardItemKeys,
220
+ entityKeys,
389
221
  };
390
222
  }
391
223
 
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
224
  type FilteredProductionPlan = ReturnType<typeof filteredPlan>;
410
225
 
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
226
  class GpuDrivenRigidRaster {
446
227
  private readonly pipelines = new Map<string, RenderPipeline>();
447
228
 
@@ -492,7 +273,7 @@ class GpuDrivenRigidRaster {
492
273
  }
493
274
 
494
275
  pipeline(
495
- format: string,
276
+ format: TextureFormat,
496
277
  sampleCount: 1 | 4,
497
278
  vertexStride: number,
498
279
  topology: GpuDrivenBatch['key']['topology'],
@@ -504,9 +285,9 @@ class GpuDrivenRigidRaster {
504
285
  if (cached !== undefined) return ok(cached);
505
286
  const created = this.device.createRenderPipeline({
506
287
  label: `gpu-driven-rigid-unlit.${key}`,
507
- layout: this.pipelineLayout as unknown as GPUPipelineLayout,
288
+ layout: this.pipelineLayout,
508
289
  vertex: {
509
- module: this.module as unknown as GPUShaderModule,
290
+ module: this.module,
510
291
  entryPoint: 'vs_main',
511
292
  buffers: [
512
293
  {
@@ -517,17 +298,17 @@ class GpuDrivenRigidRaster {
517
298
  ],
518
299
  },
519
300
  fragment: {
520
- module: this.module as unknown as GPUShaderModule,
301
+ module: this.module,
521
302
  entryPoint: 'fs_main',
522
303
  targets: [
523
304
  {
524
- format: format as GPUTextureFormat,
305
+ format,
525
306
  ...(renderState?.blend === undefined ? {} : { blend: renderState.blend }),
526
307
  },
527
308
  ],
528
309
  },
529
310
  primitive: {
530
- topology: topology as GPUPrimitiveTopology,
311
+ topology,
531
312
  cullMode: renderState?.cullMode ?? 'back',
532
313
  frontFace: renderState?.frontFace ?? 'ccw',
533
314
  ...(stripIndexFormat === undefined ? {} : { stripIndexFormat }),
@@ -594,292 +375,22 @@ class GpuDrivenRigidRaster {
594
375
  }
595
376
  }
596
377
 
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
378
  export interface PreparedGpuDrivenFrame {
845
379
  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;
380
+ readonly entityKeys: ReadonlySet<number>;
381
+ readonly ownsAllRenderables: boolean;
382
+ /** @internal Commits a replacement generation only after graph promotion. */
383
+ readonly _commitResourceReplacement: () => void;
850
384
  project(
851
385
  graph: RenderGraphBuilder<RenderPipelineFrame>,
852
- format: string,
386
+ format: TextureFormat,
853
387
  sampleCount: 1 | 4,
854
388
  ): Result<RenderPipelineGpuDrivenProjection, RenderGraphError | RhiError>;
855
389
  }
856
390
 
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
391
  export class GpuDrivenProduction {
878
392
  private view: GpuDrivenView | undefined;
879
393
  private raster: GpuDrivenRigidRaster | undefined;
880
- private shadowRaster: GpuDrivenShadowRaster | undefined;
881
- private readonly shadowViews = new Map<number, GpuDrivenView>();
882
- private preparedShadowViews: readonly PreparedShadowView[] = [];
883
394
  private readonly sceneIdentities = new WeakMap<object, number>();
884
395
  private nextSceneIdentity = 1;
885
396
  private filteredCache:
@@ -891,32 +402,10 @@ export class GpuDrivenProduction {
891
402
  | undefined;
892
403
  private gpuOwnedSnapshotsMaterialized = 0;
893
404
  private filteredPlanBuilds = 0;
894
- private gpuOwnedItemCount = 0;
405
+ private gpuOwnedEntityCount = 0;
895
406
  private batchBindGroupCreates = 0;
896
407
  private validatedGpuOwnedRows = 0;
897
408
  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
409
  private signatureCache:
921
410
  | {
922
411
  readonly filtered: FilteredProductionPlan;
@@ -932,146 +421,11 @@ export class GpuDrivenProduction {
932
421
  private readonly shaderModuleFactory: PipelineBuilderShaderModuleFactory,
933
422
  ) {}
934
423
 
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
424
  prepare(input: {
1070
425
  readonly scene: PersistentGpuDrivenState | undefined;
1071
426
  readonly camera: CameraSnapshot;
1072
427
  readonly meshes: ReadonlyMap<number, MeshGpuHandles>;
1073
428
  readonly viewBindGroupLayout: BindGroupLayout;
1074
- readonly materialBindGroupLayout?: BindGroupLayout;
1075
429
  readonly meshResidencyEpoch: number;
1076
430
  readonly hdrp: boolean;
1077
431
  }): Result<PreparedGpuDrivenFrame | undefined, RhiError> {
@@ -1080,11 +434,14 @@ export class GpuDrivenProduction {
1080
434
  this.batchBindGroupCreates = 0;
1081
435
  this.validatedGpuOwnedRows = 0;
1082
436
  this.cpuFallbackDrawItems = 0;
1083
- this.shadowSubmission = undefined;
1084
- this.shadowCandidateMembership = undefined;
1085
- this.preparedShadowViews = [];
1086
- if (input.scene === undefined) {
1087
- this.gpuOwnedItemCount = 0;
437
+ if (
438
+ input.hdrp ||
439
+ input.scene === undefined ||
440
+ !this.device.caps.compute ||
441
+ !this.device.caps.storageBuffer ||
442
+ !this.device.caps.indirectDrawing
443
+ ) {
444
+ this.gpuOwnedEntityCount = 0;
1088
445
  return ok(undefined);
1089
446
  }
1090
447
  const scene = input.scene;
@@ -1103,41 +460,14 @@ export class GpuDrivenProduction {
1103
460
  this.gpuOwnedSnapshotsMaterialized = scene.slots.length;
1104
461
  this.filteredPlanBuilds = 1;
1105
462
  }
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
- }
463
+ this.gpuOwnedEntityCount = filtered.entityKeys.size;
464
+ if (filtered.batches.length === 0) return ok(undefined);
1132
465
  if (this.view === undefined) {
1133
466
  const created = GpuDrivenView.create({
1134
467
  device: this.device,
1135
468
  shaderModuleFactory: this.shaderModuleFactory,
1136
469
  });
1137
- if (!created.ok) {
1138
- this.addRhiFault(created.error, 'all', filtered.plan.revision);
1139
- return created;
1140
- }
470
+ if (!created.ok) return created;
1141
471
  this.view = created.value;
1142
472
  }
1143
473
  if (this.raster === undefined) {
@@ -1146,35 +476,11 @@ export class GpuDrivenProduction {
1146
476
  shaderModuleFactory: this.shaderModuleFactory,
1147
477
  viewBindGroupLayout: input.viewBindGroupLayout,
1148
478
  });
1149
- if (!created.ok) {
1150
- this.addRhiFault(created.error, 'all', filtered.plan.revision);
1151
- return created;
1152
- }
479
+ if (!created.ok) return created;
1153
480
  this.raster = created.value;
1154
481
  }
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
482
  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
- }
483
+ if (!updated.ok) return updated;
1178
484
  const view = this.view;
1179
485
  const raster = this.raster;
1180
486
  const sceneIdentity = this.sceneIdentity(scene.scene);
@@ -1204,7 +510,7 @@ export class GpuDrivenProduction {
1204
510
  mesh.vboBytes,
1205
511
  mesh.iboBytes,
1206
512
  mesh.indexFormat,
1207
- mesh.layoutProjection.digest,
513
+ mesh.uvSetCount,
1208
514
  ]),
1209
515
  capacities: [
1210
516
  viewInspection.candidateCapacity,
@@ -1222,11 +528,9 @@ export class GpuDrivenProduction {
1222
528
  }
1223
529
  return ok({
1224
530
  topologySignature: signature,
1225
- ownedItemKeys: filtered.itemKeys,
1226
- ownsAllForwardItems:
1227
- filtered.forwardItemKeys.size > 0 &&
1228
- [...filtered.forwardItemKeys].every((key) => filtered.itemKeys.has(key)),
1229
- shadowSubmission,
531
+ entityKeys: filtered.entityKeys,
532
+ ownsAllRenderables: filtered.entityKeys.size === scene.slots.length,
533
+ _commitResourceReplacement: () => view._commitResourceReplacement(),
1230
534
  project: (graph, format, sampleCount) => {
1231
535
  const outputs = view.addPasses(graph);
1232
536
  if (!outputs.ok) return outputs;
@@ -1279,7 +583,7 @@ export class GpuDrivenProduction {
1279
583
  const pipeline = raster.pipeline(
1280
584
  format,
1281
585
  sampleCount,
1282
- prepared.mesh.layoutProjection.arrayStride,
586
+ 48 + (prepared.mesh.uvSetCount - 1) * 8,
1283
587
  prepared.batch.key.topology,
1284
588
  prepared.batch.key.drawKind === 'indexed' &&
1285
589
  (prepared.batch.key.topology === 'line-strip' ||
@@ -1299,68 +603,8 @@ export class GpuDrivenProduction {
1299
603
  bindings: bindings.value,
1300
604
  });
1301
605
  }
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
606
  return ok({
1362
607
  accesses,
1363
- shadow: Object.freeze(shadow),
1364
608
  encode: (viewBindGroup, pass, resources: GraphResourceResolver) => {
1365
609
  pass.setBindGroup(0, viewBindGroup);
1366
610
  let currentPipeline: RenderPipeline | undefined;
@@ -1398,238 +642,12 @@ export class GpuDrivenProduction {
1398
642
  });
1399
643
  }
1400
644
 
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
645
  dispose(): void {
1618
646
  this.view?.dispose();
1619
- for (const view of this.shadowViews.values()) view.dispose();
1620
- this.shadowViews.clear();
1621
- this.shadowRaster?.dispose();
1622
647
  this.view = undefined;
1623
648
  this.raster = undefined;
1624
- this.shadowRaster = undefined;
1625
- this.preparedShadowViews = [];
1626
649
  this.filteredCache = undefined;
1627
650
  this.signatureCache = undefined;
1628
- this.cpuVisibility = undefined;
1629
- this.shadowCasterSlotIndices = undefined;
1630
- this.shadowSubmission = undefined;
1631
- this.shadowPlanCache.clear();
1632
- this.shadowCandidateMembership = undefined;
1633
651
  }
1634
652
 
1635
653
  inspect(): GpuDrivenProductionInspection {
@@ -1637,7 +655,7 @@ export class GpuDrivenProduction {
1637
655
  return {
1638
656
  gpuOwnedSnapshotsMaterialized: this.gpuOwnedSnapshotsMaterialized,
1639
657
  filteredPlanBuilds: this.filteredPlanBuilds,
1640
- gpuOwnedItemCount: this.gpuOwnedItemCount,
658
+ gpuOwnedEntityCount: this.gpuOwnedEntityCount,
1641
659
  candidateUploadBytes: view?.candidateUploadBytes ?? 0,
1642
660
  batchUploadBytes: view?.batchUploadBytes ?? 0,
1643
661
  viewConstantsUploadBytes: view?.viewConstantsUploadBytes ?? 0,
@@ -1646,37 +664,19 @@ export class GpuDrivenProduction {
1646
664
  topologyRevision: view?.topologyRevision,
1647
665
  validatedGpuOwnedRows: this.validatedGpuOwnedRows,
1648
666
  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
667
  };
1658
668
  }
1659
669
 
1660
670
  recordCpuValidation(
1661
671
  validated: readonly { readonly source: RenderableSnapshot }[],
1662
- gpuOwned: ReadonlySet<RasterItemKey>,
672
+ gpuOwned: ReadonlySet<number>,
1663
673
  ): void {
1664
- let cpuFallbackItems = 0;
674
+ this.cpuFallbackDrawItems = validated.length;
675
+ let gpuOwnedRows = 0;
1665
676
  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
- }
677
+ if (gpuOwned.has(worldEntityKey(row.source.worldId, row.source.entityKey))) gpuOwnedRows += 1;
1675
678
  }
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;
679
+ this.validatedGpuOwnedRows = gpuOwnedRows;
1680
680
  }
1681
681
 
1682
682
  private sceneIdentity(scene: object): number {
@@ -1687,19 +687,4 @@ export class GpuDrivenProduction {
1687
687
  this.sceneIdentities.set(scene, identity);
1688
688
  return identity;
1689
689
  }
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
690
  }