@forgeax/engine-render 0.1.4 → 0.1.7

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 (979) hide show
  1. package/README.md +268 -640
  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 +214 -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 +11 -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-HCOGPHKS.mjs +93 -0
  54. package/dist/chunk-HCOGPHKS.mjs.map +1 -0
  55. package/dist/chunk-YEJIUW7D.mjs +1152 -0
  56. package/dist/chunk-YEJIUW7D.mjs.map +1 -0
  57. package/dist/components/__tests__/points-lines-admission.unit.test.d.ts +2 -0
  58. package/dist/components/__tests__/points-lines-admission.unit.test.d.ts.map +1 -0
  59. package/dist/components/__tests__/points-lines-schema.unit.test.d.ts +2 -0
  60. package/dist/components/__tests__/points-lines-schema.unit.test.d.ts.map +1 -0
  61. package/dist/components/__tests__/schema-contract.unit.test.d.ts +2 -0
  62. package/dist/components/__tests__/schema-contract.unit.test.d.ts.map +1 -0
  63. package/dist/components/glyph-text.d.ts +1 -1
  64. package/dist/components/glyph-text.d.ts.map +1 -1
  65. package/dist/components/index.d.ts +4 -2
  66. package/dist/components/index.d.ts.map +1 -1
  67. package/dist/components/instances.d.ts +1 -1
  68. package/dist/components/instances.d.ts.map +1 -1
  69. package/dist/components/light-helpers.d.ts +1 -1
  70. package/dist/components/light-helpers.d.ts.map +1 -1
  71. package/dist/components/lines.d.ts +5 -0
  72. package/dist/components/lines.d.ts.map +1 -0
  73. package/dist/components/mesh-filter.d.ts +7 -7
  74. package/dist/components/mesh-filter.d.ts.map +1 -1
  75. package/dist/components/points.d.ts +15 -0
  76. package/dist/components/points.d.ts.map +1 -0
  77. package/dist/components/scene-instance.d.ts +11 -11
  78. package/dist/components/skybox-background.d.ts +56 -0
  79. package/dist/components/skybox-background.d.ts.map +1 -0
  80. package/dist/components/skylight.d.ts +55 -0
  81. package/dist/components/skylight.d.ts.map +1 -0
  82. package/dist/components/sprite-animation.d.ts +2 -3
  83. package/dist/components/sprite-animation.d.ts.map +1 -1
  84. package/dist/components/sprite-instances.d.ts +1 -1
  85. package/dist/components/sprite-playback-mode.d.ts +6 -1
  86. package/dist/components/sprite-playback-mode.d.ts.map +1 -1
  87. package/dist/components/sprite-region-override.d.ts +2 -3
  88. package/dist/components/sprite-region-override.d.ts.map +1 -1
  89. package/dist/components/tile-layer.d.ts +5 -0
  90. package/dist/components/tile-layer.d.ts.map +1 -1
  91. package/dist/construct-renderer.d.ts +18 -1
  92. package/dist/construct-renderer.d.ts.map +1 -1
  93. package/dist/construct-renderer.mjs +27463 -4
  94. package/dist/construct-renderer.mjs.map +1 -1
  95. package/dist/debug-draw-glue.d.ts +2 -53
  96. package/dist/debug-draw-glue.d.ts.map +1 -1
  97. package/dist/device/device-scope.d.ts +83 -0
  98. package/dist/device/device-scope.d.ts.map +1 -0
  99. package/dist/{gpu-resource-store.d.ts → device/gpu-residency.d.ts} +91 -48
  100. package/dist/device/gpu-residency.d.ts.map +1 -0
  101. package/dist/device/resource-types.d.ts +8 -0
  102. package/dist/device/resource-types.d.ts.map +1 -0
  103. package/dist/engine-metrics.d.ts +2 -2
  104. package/dist/engine-metrics.d.ts.map +1 -1
  105. package/dist/errors/recover.d.ts +28 -1
  106. package/dist/errors/recover.d.ts.map +1 -1
  107. package/dist/errors/render.d.ts +320 -248
  108. package/dist/errors/render.d.ts.map +1 -1
  109. package/dist/features/fullscreen.d.ts +19 -0
  110. package/dist/features/fullscreen.d.ts.map +1 -0
  111. package/dist/features/host.d.ts +32 -26
  112. package/dist/features/host.d.ts.map +1 -1
  113. package/dist/features/morph/morph-feature.d.ts +39 -5
  114. package/dist/features/morph/morph-feature.d.ts.map +1 -1
  115. package/dist/features/plan.d.ts +182 -0
  116. package/dist/features/plan.d.ts.map +1 -0
  117. package/dist/features/prepared-gpu-work.d.ts +21 -17
  118. package/dist/features/prepared-gpu-work.d.ts.map +1 -1
  119. package/dist/features/prepared-graphics-store.d.ts +2 -1
  120. package/dist/features/prepared-graphics-store.d.ts.map +1 -1
  121. package/dist/features/prepared-graphics.d.ts +11 -21
  122. package/dist/features/prepared-graphics.d.ts.map +1 -1
  123. package/dist/features/render-graph-compute.d.ts +2 -2
  124. package/dist/features/render-graph-compute.d.ts.map +1 -1
  125. package/dist/features/render-graph-contribution.d.ts +4 -7
  126. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  127. package/dist/features/render-graph-raster.d.ts +7 -3
  128. package/dist/features/render-graph-raster.d.ts.map +1 -1
  129. package/dist/features/render-graph-resources.d.ts +6 -6
  130. package/dist/features/render-graph-resources.d.ts.map +1 -1
  131. package/dist/features/targets.d.ts +5 -5
  132. package/dist/features/targets.d.ts.map +1 -1
  133. package/dist/features/types.d.ts +11 -190
  134. package/dist/features/types.d.ts.map +1 -1
  135. package/dist/features/vocabulary.d.ts +14 -0
  136. package/dist/features/vocabulary.d.ts.map +1 -0
  137. package/dist/fullscreen-post-process-pass.d.ts +4 -25
  138. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  139. package/dist/glyph-text-layout-system.d.ts +3 -2
  140. package/dist/glyph-text-layout-system.d.ts.map +1 -1
  141. package/dist/gpu-driven/batch-topology.d.ts +6 -75
  142. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  143. package/dist/gpu-driven/production-raster.d.ts +13 -112
  144. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  145. package/dist/gpu-driven/view-gpu.d.ts +10 -66
  146. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  147. package/dist/gpu-resource.d.ts +3 -3
  148. package/dist/gpu-scene-schema.d.ts +1 -94
  149. package/dist/gpu-scene-schema.d.ts.map +1 -1
  150. package/dist/gpu-scene.d.ts +7 -33
  151. package/dist/gpu-scene.d.ts.map +1 -1
  152. package/dist/hdrp-buffers.d.ts +3 -53
  153. package/dist/hdrp-buffers.d.ts.map +1 -1
  154. package/dist/ibl/IblPipelineCache.d.ts +74 -180
  155. package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
  156. package/dist/ibl/skylight-bind-group.d.ts +1 -1
  157. package/dist/index.d.ts +17 -43
  158. package/dist/index.d.ts.map +1 -1
  159. package/dist/index.mjs +167 -3
  160. package/dist/index.mjs.map +1 -1
  161. package/dist/inspection-types.d.ts +72 -0
  162. package/dist/inspection-types.d.ts.map +1 -0
  163. package/dist/instance-buffer-cache.d.ts +1 -4
  164. package/dist/instance-buffer-cache.d.ts.map +1 -1
  165. package/dist/internal.d.ts +1 -73
  166. package/dist/internal.d.ts.map +1 -1
  167. package/dist/internal.mjs +1 -43
  168. package/dist/internal.mjs.map +1 -1
  169. package/dist/lifecycle.d.ts +36 -2
  170. package/dist/lifecycle.d.ts.map +1 -1
  171. package/dist/materials.d.ts +0 -3
  172. package/dist/materials.d.ts.map +1 -1
  173. package/dist/mesh-material-bindings.d.ts +0 -1
  174. package/dist/mesh-material-bindings.d.ts.map +1 -1
  175. package/dist/pbr-pipeline.d.ts +77 -29
  176. package/dist/pbr-pipeline.d.ts.map +1 -1
  177. package/dist/pipeline/standard-forward-lane.d.ts +5 -0
  178. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -0
  179. package/dist/pipeline/standard-pipeline.d.ts +31 -0
  180. package/dist/pipeline/standard-pipeline.d.ts.map +1 -0
  181. package/dist/pipeline/standard-profile.d.ts +40 -0
  182. package/dist/pipeline/standard-profile.d.ts.map +1 -0
  183. package/dist/pipeline-builder.d.ts +3 -3
  184. package/dist/pipeline-builder.d.ts.map +1 -1
  185. package/dist/pipeline-spec-types.d.ts +24 -0
  186. package/dist/pipeline-spec-types.d.ts.map +1 -0
  187. package/dist/pipeline-spec.d.ts +16 -155
  188. package/dist/pipeline-spec.d.ts.map +1 -1
  189. package/dist/plugin.d.ts +1 -14
  190. package/dist/plugin.d.ts.map +1 -1
  191. package/dist/points-lines/__tests__/bounds.unit.test.d.ts +2 -0
  192. package/dist/points-lines/__tests__/bounds.unit.test.d.ts.map +1 -0
  193. package/dist/points-lines/__tests__/cache-recovery.unit.test.d.ts +2 -0
  194. package/dist/points-lines/__tests__/cache-recovery.unit.test.d.ts.map +1 -0
  195. package/dist/points-lines/__tests__/inspection-lanes.integration.test.d.ts +2 -0
  196. package/dist/points-lines/__tests__/inspection-lanes.integration.test.d.ts.map +1 -0
  197. package/dist/points-lines/__tests__/inspection.unit.test.d.ts +2 -0
  198. package/dist/points-lines/__tests__/inspection.unit.test.d.ts.map +1 -0
  199. package/dist/points-lines/__tests__/lane-structural.integration.test.d.ts +2 -0
  200. package/dist/points-lines/__tests__/lane-structural.integration.test.d.ts.map +1 -0
  201. package/dist/points-lines/__tests__/points-lines.bench.d.ts +2 -0
  202. package/dist/points-lines/__tests__/points-lines.bench.d.ts.map +1 -0
  203. package/dist/points-lines/__tests__/raster-lane.integration.test.d.ts +2 -0
  204. package/dist/points-lines/__tests__/raster-lane.integration.test.d.ts.map +1 -0
  205. package/dist/points-lines/__tests__/snapshot.unit.test.d.ts +2 -0
  206. package/dist/points-lines/__tests__/snapshot.unit.test.d.ts.map +1 -0
  207. package/dist/points-lines/__tests__/view-ubo.unit.test.d.ts +2 -0
  208. package/dist/points-lines/__tests__/view-ubo.unit.test.d.ts.map +1 -0
  209. package/dist/points-lines/admission.d.ts +36 -0
  210. package/dist/points-lines/admission.d.ts.map +1 -0
  211. package/dist/points-lines/bounds.d.ts +8 -0
  212. package/dist/points-lines/bounds.d.ts.map +1 -0
  213. package/dist/points-lines/expansion-cache.d.ts +28 -0
  214. package/dist/points-lines/expansion-cache.d.ts.map +1 -0
  215. package/dist/points-lines/inspection.d.ts +53 -0
  216. package/dist/points-lines/inspection.d.ts.map +1 -0
  217. package/dist/points-lines/prepare.d.ts +67 -0
  218. package/dist/points-lines/prepare.d.ts.map +1 -0
  219. package/dist/points-lines/record.d.ts +60 -0
  220. package/dist/points-lines/record.d.ts.map +1 -0
  221. package/dist/points-lines/snapshot.d.ts +49 -0
  222. package/dist/points-lines/snapshot.d.ts.map +1 -0
  223. package/dist/post-process-errors.d.ts +18 -18
  224. package/dist/post-process-errors.d.ts.map +1 -1
  225. package/dist/prepare/prepared-graphics-resolver.d.ts +2 -5
  226. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  227. package/dist/record/__tests__/typed-frame-graph-plan.unit.test.d.ts +2 -0
  228. package/dist/record/__tests__/typed-frame-graph-plan.unit.test.d.ts.map +1 -0
  229. package/dist/record/frame-lighting.d.ts +7 -73
  230. package/dist/record/frame-lighting.d.ts.map +1 -1
  231. package/dist/record/frame-snapshot.d.ts +44 -44
  232. package/dist/record/frame-snapshot.d.ts.map +1 -1
  233. package/dist/record/frame-targets.d.ts +5 -38
  234. package/dist/record/frame-targets.d.ts.map +1 -1
  235. package/dist/record/frame.d.ts +64 -52
  236. package/dist/record/frame.d.ts.map +1 -1
  237. package/dist/record/helpers.d.ts +3 -2
  238. package/dist/record/helpers.d.ts.map +1 -1
  239. package/dist/record/main-pass-geometry.d.ts +12 -4
  240. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  241. package/dist/record/main-pass-material.d.ts +90 -59
  242. package/dist/record/main-pass-material.d.ts.map +1 -1
  243. package/dist/record/main-pass-sprite-draws.d.ts +28 -3
  244. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  245. package/dist/record/main-pass.d.ts +1 -1
  246. package/dist/record/main-pass.d.ts.map +1 -1
  247. package/dist/record/mesh-ssbo.d.ts +276 -3
  248. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  249. package/dist/record/render-context.d.ts +252 -0
  250. package/dist/record/render-context.d.ts.map +1 -0
  251. package/dist/record/shadow-pass.d.ts +15 -88
  252. package/dist/record/shadow-pass.d.ts.map +1 -1
  253. package/dist/record/skybox-post-pass.d.ts +1 -1
  254. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  255. package/dist/record/typed-frame-graph.d.ts +29 -7
  256. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  257. package/dist/record/view-ubo.d.ts +9 -3
  258. package/dist/record/view-ubo.d.ts.map +1 -1
  259. package/dist/render-contract.d.ts +424 -0
  260. package/dist/render-contract.d.ts.map +1 -0
  261. package/dist/render-data.d.ts.map +1 -1
  262. package/dist/render-graph-primitives.d.ts +14 -362
  263. package/dist/render-graph-primitives.d.ts.map +1 -1
  264. package/dist/render-pipeline.d.ts +25 -64
  265. package/dist/render-pipeline.d.ts.map +1 -1
  266. package/dist/render-system-extract.d.ts +110 -338
  267. package/dist/render-system-extract.d.ts.map +1 -1
  268. package/dist/render-system.d.ts +24 -713
  269. package/dist/render-system.d.ts.map +1 -1
  270. package/dist/scene/render-scene-types.d.ts +61 -0
  271. package/dist/scene/render-scene-types.d.ts.map +1 -0
  272. package/dist/scene/render-scene.d.ts +112 -0
  273. package/dist/scene/render-scene.d.ts.map +1 -0
  274. package/dist/scene-instances/post-spawn-resolve-joints.d.ts +2 -5
  275. package/dist/scene-instances/post-spawn-resolve-joints.d.ts.map +1 -1
  276. package/dist/ssao-buffers.d.ts +22 -3
  277. package/dist/ssao-buffers.d.ts.map +1 -1
  278. package/dist/systems/skin-palette-allocator.d.ts +2 -4
  279. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  280. package/dist/systems/skin-palette-types.d.ts +14 -0
  281. package/dist/systems/skin-palette-types.d.ts.map +1 -0
  282. package/dist/systems/transparent-sort-config.d.ts +23 -2
  283. package/dist/systems/transparent-sort-config.d.ts.map +1 -1
  284. package/dist/tilemap-chunk-extract-system.d.ts +4 -3
  285. package/dist/tilemap-chunk-extract-system.d.ts.map +1 -1
  286. package/dist/typed-render-graph-primitives.d.ts +2 -4
  287. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  288. package/dist/typed-shadow-passes.d.ts +3 -3
  289. package/dist/typed-shadow-passes.d.ts.map +1 -1
  290. package/package.json +23 -23
  291. package/src/__tests__/authoring-path.unit.test.ts +9 -0
  292. package/src/__tests__/backend-selection-rhi-capture.test-d.ts +1 -1
  293. package/src/__tests__/callback-inference.test-d.ts +6 -3
  294. package/src/__tests__/cluster-grid-default-surface.unit.test.ts +7 -4
  295. package/src/__tests__/construct-renderer-identity.unit.test.ts +15 -2
  296. package/src/__tests__/device-scope-lifecycle.unit.test.ts +151 -0
  297. package/src/__tests__/device-scope-stale-matrix.unit.test.ts +42 -0
  298. package/src/__tests__/direct-extract-consumer-contract.test-d.ts +8 -19
  299. package/src/__tests__/direct-light-snapshot.unit.test.ts +3 -13
  300. package/src/__tests__/factory-contract.integration.test.ts +158 -209
  301. package/src/__tests__/fallback-row-stride-surface.unit.test.ts +1 -4
  302. package/src/__tests__/frame-observation.contract.test.ts +17 -8
  303. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +32 -0
  304. package/src/__tests__/glyph-text-layout-recovery.unit.test.ts +6 -11
  305. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +21 -18
  306. package/src/__tests__/gpu-driven-production.integration.test.ts +32 -205
  307. package/src/__tests__/gpu-driven-scaling.unit.test.ts +4 -7
  308. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +87 -8
  309. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +170 -8
  310. package/src/{gpu-driven/view-reference.ts → __tests__/gpu-driven-view-reference.ts} +4 -3
  311. package/src/__tests__/gpu-driven-view.browser.test.ts +12 -1
  312. package/src/__tests__/gpu-driven-view.dawn.test.ts +12 -1
  313. package/src/__tests__/gpu-driven-view.unit.test.ts +11 -267
  314. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +3 -3
  315. package/src/__tests__/gpu-scene-render-graph-gpu.ts +2 -3
  316. package/src/__tests__/gpu-scene.dawn.test.ts +2 -6
  317. package/src/__tests__/gpu-scene.unit.test.ts +10 -24
  318. package/src/__tests__/ibl/face-uniforms.unit.test.ts +46 -0
  319. package/src/__tests__/infinite-grid-no-vertex-probe.unit.test.ts +34 -66
  320. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +14 -5
  321. package/src/__tests__/light-buffer-layout.unit.test.ts +4 -49
  322. package/src/__tests__/material-cooked-projection.unit.test.ts +31 -58
  323. package/src/__tests__/material-snapshot-mutation.integration.test.ts +10 -15
  324. package/src/__tests__/material-static-dynamic-route.unit.test.ts +31 -50
  325. package/src/__tests__/material-stride-surface.unit.test.ts +2 -2
  326. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +7 -8
  327. package/src/__tests__/morph-culling-reentry.dawn.test.ts +29 -38
  328. package/src/__tests__/morph-feature-gpu-work.integration.test.ts +45 -43
  329. package/src/__tests__/morph-feature-plan.unit.test.ts +53 -0
  330. package/src/__tests__/morph-visual-evidence.integration.test.ts +47 -33
  331. package/src/__tests__/nineslice-handle-surface.unit.test.ts +11 -6
  332. package/src/__tests__/post-process-error-policy-owner.unit.test.ts +6 -13
  333. package/src/__tests__/prepared-graphics-capability.unit.test.ts +6 -81
  334. package/src/__tests__/prepared-graphics-generation.unit.test.ts +3 -17
  335. package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +6 -74
  336. package/src/__tests__/prepared-graphics-resolver.unit.test.ts +1 -3
  337. package/src/__tests__/prepared-graphics-snapshot.unit.test.ts +2 -2
  338. package/src/__tests__/profiler-default-off.test.ts +1 -1
  339. package/src/__tests__/profiler-phase-catalog.test.ts +2 -2
  340. package/src/__tests__/profiler-phase-integration.test.ts +5 -13
  341. package/src/__tests__/profiler-phase-token.test.ts +3 -8
  342. package/src/__tests__/public-surface.test-d.ts +65 -3
  343. package/src/__tests__/recover-error-policy-owner.unit.test.ts +1 -21
  344. package/src/__tests__/render-error-code-owner.test-d.ts +24 -23
  345. package/src/__tests__/render-error-detail-ssot.test-d.ts +0 -95
  346. package/src/__tests__/render-error-exhaustive.test-d.ts +27 -1
  347. package/src/__tests__/render-feature-assembly.test-d.ts +8 -16
  348. package/src/__tests__/render-feature-context.test-d.ts +16 -40
  349. package/src/__tests__/render-feature-contract.test-d.ts +9 -18
  350. package/src/__tests__/render-feature-diagnostics.unit.test.ts +6 -8
  351. package/src/__tests__/render-feature-docs.unit.test.ts +8 -7
  352. package/src/__tests__/render-feature-gpu-work.integration.test.ts +14 -75
  353. package/src/__tests__/render-feature-plan.test-d.ts +161 -0
  354. package/src/__tests__/render-feature-plan.unit.test.ts +170 -0
  355. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +8 -19
  356. package/src/__tests__/render-feature-prepared-errors.test-d.ts +3 -6
  357. package/src/__tests__/render-feature-prepared-graphics-docs.unit.test.ts +10 -71
  358. package/src/__tests__/render-feature-prepared-graphics-isolation.unit.test.ts +11 -61
  359. package/src/__tests__/render-feature-prepared-graphics-negative.test-d.ts +20 -43
  360. package/src/__tests__/render-feature-prepared-graphics.test-d.ts +56 -78
  361. package/src/__tests__/render-feature-public-surface.test-d.ts +6 -24
  362. package/src/__tests__/render-feature-retry.unit.test.ts +7 -48
  363. package/src/__tests__/render-feature-scheduling.unit.test.ts +15 -27
  364. package/src/__tests__/render-feature-stage-failed-policy-owner.unit.test.ts +0 -9
  365. package/src/__tests__/render-feature-stage-fault-recovery.unit.test.ts +19 -109
  366. package/src/__tests__/render-feature-visibility-context.test-d.ts +1 -6
  367. package/src/__tests__/render-feature-visibility-context.unit.test.ts +1 -2
  368. package/src/__tests__/render-feature-zero-work.unit.test.ts +14 -20
  369. package/src/__tests__/render-scene-projection.unit.test.ts +73 -111
  370. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +82 -95
  371. package/src/__tests__/renderer-lifecycle.integration.test.ts +49 -1
  372. package/src/__tests__/shader-stage-surface.unit.test.ts +14 -9
  373. package/src/__tests__/ssao-config.unit.test.ts +36 -0
  374. package/src/__tests__/ssao-kernel-surface.unit.test.ts +4 -5
  375. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +28 -0
  376. package/src/__tests__/standard-descriptors.test-d.ts +22 -0
  377. package/src/__tests__/standard-pipeline.dawn.test.ts +61 -0
  378. package/src/__tests__/standard-pipeline.integration.test.ts +124 -0
  379. package/src/__tests__/standard-profile-oracle.unit.test.ts +62 -0
  380. package/src/__tests__/surface-configuration.unit.test.ts +1 -2
  381. package/src/__tests__/texture-usage-surface.unit.test.ts +3 -6
  382. package/src/__tests__/typed-pipeline-topology.unit.test.ts +40 -206
  383. package/src/__tests__/urp-pipeline-targets.unit.test.ts +1 -11
  384. package/src/__tests__/urp-pipeline.unit.test.ts +2 -2
  385. package/src/__tests__/vertex-color-pipeline.unit.test.ts +10 -2
  386. package/src/__tests__/vertex-layout-consumer.unit.test.ts +1 -1
  387. package/src/__tests__/visibility-diagnostics.integration.test.ts +7 -11
  388. package/src/__tests__/visibility-extract.integration.test.ts +20 -11
  389. package/src/__tests__/visibility-extract.perf.test.ts +66 -32
  390. package/src/__tests__/visibility-feature-dedup.integration.test.ts +2 -4
  391. package/src/__tests__/visibility-hidden-report.unit.test.ts +1 -2
  392. package/src/__tests__/visibility-instances.integration.test.ts +7 -11
  393. package/src/__tests__/visibility-multi-world.integration.test.ts +38 -6
  394. package/src/__tests__/visibility-producer-matrix.integration.test.ts +18 -41
  395. package/src/__tests__/visibility-public-surface.test-d.ts +10 -9
  396. package/src/__tests__/visibility-resolver.unit.test.ts +2 -1
  397. package/src/__tests__/visibility-resource-short-circuit.unit.test.ts +80 -0
  398. package/src/__tests__/visibility-snapshot-contract.unit.test.ts +2 -1
  399. package/src/__tests__/vocabulary.unit.test.ts +1 -1
  400. package/src/assembly/backend-contract.ts +57 -0
  401. package/src/{renderer/renderer-factory.ts → assembly/factory.ts} +1741 -2699
  402. package/src/assembly/host-contract.ts +101 -0
  403. package/src/{renderer → assembly}/material/assembly.ts +2 -7
  404. package/src/assembly/material/pipeline-projection.ts +63 -0
  405. package/src/authoring.ts +15 -22
  406. package/src/components/__tests__/points-lines-admission.unit.test.ts +219 -0
  407. package/src/components/__tests__/points-lines-schema.unit.test.ts +56 -0
  408. package/src/components/__tests__/schema-contract.unit.test.ts +10 -0
  409. package/src/components/glyph-text.ts +3 -2
  410. package/src/components/index.ts +14 -9
  411. package/src/components/instances.ts +4 -5
  412. package/src/components/light-helpers.ts +1 -1
  413. package/src/components/lines.ts +18 -0
  414. package/src/components/mesh-filter.ts +11 -10
  415. package/src/components/points.ts +40 -0
  416. package/src/components/post-process-params.ts +3 -3
  417. package/src/components/scene-instance.ts +12 -12
  418. package/src/components/skybox-background.ts +103 -0
  419. package/src/components/{environment.ts → skylight.ts} +2 -110
  420. package/src/components/sprite-animation.ts +3 -4
  421. package/src/components/sprite-instances.ts +2 -2
  422. package/src/components/sprite-playback-mode.ts +7 -1
  423. package/src/components/sprite-region-override.ts +2 -3
  424. package/src/components/tile-layer.ts +8 -2
  425. package/src/construct-renderer.ts +67 -4
  426. package/src/debug-draw-glue.ts +8 -129
  427. package/src/device/device-scope.ts +306 -0
  428. package/src/{gpu-resource-store.ts → device/gpu-residency.ts} +540 -639
  429. package/src/device/resource-types.ts +20 -0
  430. package/src/engine-metrics.ts +12 -19
  431. package/src/errors/recover.ts +45 -3
  432. package/src/errors/render.ts +469 -429
  433. package/src/features/fullscreen.ts +46 -0
  434. package/src/features/host.ts +575 -309
  435. package/src/features/morph/morph-feature.ts +195 -105
  436. package/src/features/plan.ts +447 -0
  437. package/src/features/prepared-gpu-work.ts +72 -15
  438. package/src/features/prepared-graphics-store.ts +20 -6
  439. package/src/features/prepared-graphics.ts +12 -71
  440. package/src/features/render-graph-compute.ts +14 -5
  441. package/src/features/render-graph-contribution.ts +43 -63
  442. package/src/features/render-graph-raster.ts +32 -8
  443. package/src/features/render-graph-resources.ts +25 -23
  444. package/src/features/targets.ts +8 -21
  445. package/src/features/types.ts +39 -227
  446. package/src/features/vocabulary.ts +24 -0
  447. package/src/fullscreen-post-process-pass.ts +14 -57
  448. package/src/glyph-text-layout-system.ts +70 -96
  449. package/src/gpu-driven/batch-topology.ts +24 -202
  450. package/src/gpu-driven/production-raster.ts +99 -1109
  451. package/src/gpu-driven/view-gpu.ts +46 -192
  452. package/src/gpu-resource.ts +4 -4
  453. package/src/gpu-scene-schema.ts +11 -99
  454. package/src/gpu-scene.ts +231 -364
  455. package/src/hdrp-buffers.ts +12 -221
  456. package/src/ibl/IblPipelineCache.ts +471 -711
  457. package/src/ibl/skylight-bind-group.ts +4 -4
  458. package/src/index.ts +75 -217
  459. package/src/inspection-types.ts +80 -0
  460. package/src/instance-buffer-cache.ts +1 -29
  461. package/src/internal.ts +6 -85
  462. package/src/lifecycle.ts +64 -19
  463. package/src/materials.ts +7 -29
  464. package/src/mesh-material-bindings.ts +0 -1
  465. package/src/pbr-pipeline.ts +441 -53
  466. package/src/{urp-pipeline.ts → pipeline/standard-forward-lane.ts} +38 -149
  467. package/src/{hdrp-pipeline.ts → pipeline/standard-pipeline.ts} +221 -191
  468. package/src/pipeline/standard-profile.ts +65 -0
  469. package/src/pipeline-builder.ts +60 -64
  470. package/src/pipeline-spec-types.ts +28 -0
  471. package/src/pipeline-spec.ts +72 -609
  472. package/src/plugin.ts +7 -75
  473. package/src/points-lines/__tests__/bounds.unit.test.ts +21 -0
  474. package/src/points-lines/__tests__/cache-recovery.unit.test.ts +157 -0
  475. package/src/points-lines/__tests__/inspection-lanes.integration.test.ts +146 -0
  476. package/src/points-lines/__tests__/inspection.unit.test.ts +173 -0
  477. package/src/points-lines/__tests__/lane-structural.integration.test.ts +122 -0
  478. package/src/points-lines/__tests__/points-lines.bench.ts +400 -0
  479. package/src/points-lines/__tests__/raster-lane.integration.test.ts +44 -0
  480. package/src/points-lines/__tests__/snapshot.unit.test.ts +101 -0
  481. package/src/points-lines/__tests__/view-ubo.unit.test.ts +73 -0
  482. package/src/points-lines/admission.ts +238 -0
  483. package/src/points-lines/bounds.ts +23 -0
  484. package/src/points-lines/expansion-cache.ts +215 -0
  485. package/src/points-lines/inspection.ts +97 -0
  486. package/src/points-lines/prepare.ts +177 -0
  487. package/src/points-lines/record.ts +125 -0
  488. package/src/points-lines/snapshot.ts +130 -0
  489. package/src/post-process-errors.ts +31 -33
  490. package/src/prepare/prepared-graphics-resolver.ts +5 -4
  491. package/src/record/__tests__/material-slot-plan.unit.test.ts +1 -33
  492. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +41 -0
  493. package/src/record/__tests__/video-texture-view.unit.test.ts +1 -1
  494. package/src/record/frame-lighting.ts +88 -197
  495. package/src/record/frame-snapshot.ts +45 -60
  496. package/src/record/frame-targets.ts +8 -243
  497. package/src/record/frame.ts +521 -797
  498. package/src/record/helpers.ts +6 -11
  499. package/src/record/main-pass-geometry.ts +198 -147
  500. package/src/record/main-pass-material.ts +517 -190
  501. package/src/record/main-pass-sprite-draws.ts +199 -118
  502. package/src/record/main-pass.ts +166 -144
  503. package/src/record/mesh-ssbo.ts +517 -38
  504. package/src/record/render-context.ts +384 -0
  505. package/src/record/shadow-pass.ts +154 -1843
  506. package/src/record/skybox-post-pass.ts +14 -15
  507. package/src/record/typed-frame-graph.ts +224 -262
  508. package/src/record/view-ubo.ts +53 -37
  509. package/src/render-contract.ts +582 -0
  510. package/src/render-data.ts +3 -3
  511. package/src/render-graph-primitives.ts +76 -851
  512. package/src/render-pipeline.ts +104 -188
  513. package/src/render-system-extract.ts +1114 -1732
  514. package/src/render-system.ts +614 -1939
  515. package/src/scene/render-scene-types.ts +67 -0
  516. package/src/scene/render-scene.ts +1087 -0
  517. package/src/scene-instances/post-spawn-resolve-joints.ts +4 -7
  518. package/src/ssao-buffers.ts +167 -8
  519. package/src/systems/skin-palette-allocator.ts +21 -64
  520. package/src/systems/skin-palette-types.ts +14 -0
  521. package/src/systems/transparent-sort-config.ts +25 -3
  522. package/src/tilemap-chunk-extract-system.ts +53 -70
  523. package/src/typed-render-graph-primitives.ts +35 -24
  524. package/src/typed-shadow-passes.ts +26 -56
  525. package/dist/__tests__/analytic-sky-contract.test.d.ts +0 -2
  526. package/dist/__tests__/analytic-sky-contract.test.d.ts.map +0 -1
  527. package/dist/__tests__/analytic-sky-falsify.test.d.ts +0 -2
  528. package/dist/__tests__/analytic-sky-falsify.test.d.ts.map +0 -1
  529. package/dist/__tests__/assets-runtime-handoff.integration.test.d.ts +0 -2
  530. package/dist/__tests__/assets-runtime-handoff.integration.test.d.ts.map +0 -1
  531. package/dist/__tests__/backend-selection.integration.test.d.ts +0 -2
  532. package/dist/__tests__/backend-selection.integration.test.d.ts.map +0 -1
  533. package/dist/__tests__/camera-temporal.test-d.d.ts +0 -2
  534. package/dist/__tests__/camera-temporal.test-d.d.ts.map +0 -1
  535. package/dist/__tests__/camera-temporal.test.d.ts +0 -2
  536. package/dist/__tests__/camera-temporal.test.d.ts.map +0 -1
  537. package/dist/__tests__/directional-shadow-probe-atlas-layout.unit.test.d.ts +0 -2
  538. package/dist/__tests__/directional-shadow-probe-atlas-layout.unit.test.d.ts.map +0 -1
  539. package/dist/__tests__/environment-inspection.test.d.ts +0 -2
  540. package/dist/__tests__/environment-inspection.test.d.ts.map +0 -1
  541. package/dist/__tests__/fog-ai-user.fixture.d.ts +0 -2
  542. package/dist/__tests__/fog-ai-user.fixture.d.ts.map +0 -1
  543. package/dist/__tests__/fog-custom-render-feature.fixture.d.ts +0 -16
  544. package/dist/__tests__/fog-custom-render-feature.fixture.d.ts.map +0 -1
  545. package/dist/__tests__/fog-custom-render-feature.integration.test.d.ts +0 -2
  546. package/dist/__tests__/fog-custom-render-feature.integration.test.d.ts.map +0 -1
  547. package/dist/__tests__/fog-inspection.integration.test.d.ts +0 -2
  548. package/dist/__tests__/fog-inspection.integration.test.d.ts.map +0 -1
  549. package/dist/__tests__/fog-owner-state.integration.test.d.ts +0 -2
  550. package/dist/__tests__/fog-owner-state.integration.test.d.ts.map +0 -1
  551. package/dist/__tests__/fog-pipeline-topology.integration.test.d.ts +0 -2
  552. package/dist/__tests__/fog-pipeline-topology.integration.test.d.ts.map +0 -1
  553. package/dist/__tests__/fog-public-surface.integration.test.d.ts +0 -2
  554. package/dist/__tests__/fog-public-surface.integration.test.d.ts.map +0 -1
  555. package/dist/__tests__/fog-ray-contract.integration.test.d.ts +0 -2
  556. package/dist/__tests__/fog-ray-contract.integration.test.d.ts.map +0 -1
  557. package/dist/__tests__/fog-source-absence.integration.test.d.ts +0 -2
  558. package/dist/__tests__/fog-source-absence.integration.test.d.ts.map +0 -1
  559. package/dist/__tests__/fog-temporal.integration.test.d.ts +0 -2
  560. package/dist/__tests__/fog-temporal.integration.test.d.ts.map +0 -1
  561. package/dist/__tests__/frame-chain.unit.test.d.ts +0 -2
  562. package/dist/__tests__/frame-chain.unit.test.d.ts.map +0 -1
  563. package/dist/__tests__/gpu-scene-field-type-owner.test-d.d.ts +0 -2
  564. package/dist/__tests__/gpu-scene-field-type-owner.test-d.d.ts.map +0 -1
  565. package/dist/__tests__/hdrp-pipeline.unit.test.d.ts +0 -2
  566. package/dist/__tests__/hdrp-pipeline.unit.test.d.ts.map +0 -1
  567. package/dist/__tests__/ibl/ibl-fallback.unit.test.d.ts +0 -2
  568. package/dist/__tests__/ibl/ibl-fallback.unit.test.d.ts.map +0 -1
  569. package/dist/__tests__/material-derived-error-stop-draw.integration.test.d.ts +0 -2
  570. package/dist/__tests__/material-derived-error-stop-draw.integration.test.d.ts.map +0 -1
  571. package/dist/__tests__/material-derived-payload.integration.test.d.ts +0 -2
  572. package/dist/__tests__/material-derived-payload.integration.test.d.ts.map +0 -1
  573. package/dist/__tests__/materials.unit.test.d.ts +0 -2
  574. package/dist/__tests__/materials.unit.test.d.ts.map +0 -1
  575. package/dist/__tests__/param-schema-projection-census.unit.test.d.ts +0 -2
  576. package/dist/__tests__/param-schema-projection-census.unit.test.d.ts.map +0 -1
  577. package/dist/__tests__/persistent-render-scene.unit.test.d.ts +0 -2
  578. package/dist/__tests__/persistent-render-scene.unit.test.d.ts.map +0 -1
  579. package/dist/__tests__/pipeline-error-policy-owner.unit.test.d.ts +0 -2
  580. package/dist/__tests__/pipeline-error-policy-owner.unit.test.d.ts.map +0 -1
  581. package/dist/__tests__/pipeline-pass-trace.test.d.ts +0 -2
  582. package/dist/__tests__/pipeline-pass-trace.test.d.ts.map +0 -1
  583. package/dist/__tests__/pipeline-stage-owner.test-d.d.ts +0 -2
  584. package/dist/__tests__/pipeline-stage-owner.test-d.d.ts.map +0 -1
  585. package/dist/__tests__/plugin.test.d.ts +0 -2
  586. package/dist/__tests__/plugin.test.d.ts.map +0 -1
  587. package/dist/__tests__/prepared-graphics-backend-matrix.unit.test.d.ts +0 -2
  588. package/dist/__tests__/prepared-graphics-backend-matrix.unit.test.d.ts.map +0 -1
  589. package/dist/__tests__/prepared-graphics-resolver-recording.unit.test.d.ts +0 -2
  590. package/dist/__tests__/prepared-graphics-resolver-recording.unit.test.d.ts.map +0 -1
  591. package/dist/__tests__/public-pipeline-id.test-d.d.ts +0 -2
  592. package/dist/__tests__/public-pipeline-id.test-d.d.ts.map +0 -1
  593. package/dist/__tests__/render-dispatch-membership.unit.test.d.ts +0 -2
  594. package/dist/__tests__/render-dispatch-membership.unit.test.d.ts.map +0 -1
  595. package/dist/__tests__/render-feature-construction.unit.test.d.ts +0 -2
  596. package/dist/__tests__/render-feature-construction.unit.test.d.ts.map +0 -1
  597. package/dist/__tests__/render-feature-error-code-owner.test-d.d.ts +0 -2
  598. package/dist/__tests__/render-feature-error-code-owner.test-d.d.ts.map +0 -1
  599. package/dist/__tests__/render-feature-gpu-buffer-usage-owner.test-d.d.ts +0 -2
  600. package/dist/__tests__/render-feature-gpu-buffer-usage-owner.test-d.d.ts.map +0 -1
  601. package/dist/__tests__/render-feature-graph.integration.test.d.ts +0 -2
  602. package/dist/__tests__/render-feature-graph.integration.test.d.ts.map +0 -1
  603. package/dist/__tests__/render-feature-graphics-staging.unit.test.d.ts +0 -2
  604. package/dist/__tests__/render-feature-graphics-staging.unit.test.d.ts.map +0 -1
  605. package/dist/__tests__/render-feature-order.unit.test.d.ts +0 -2
  606. package/dist/__tests__/render-feature-order.unit.test.d.ts.map +0 -1
  607. package/dist/__tests__/render-feature-prepared-graphics-recording.unit.test.d.ts +0 -2
  608. package/dist/__tests__/render-feature-prepared-graphics-recording.unit.test.d.ts.map +0 -1
  609. package/dist/__tests__/render-feature-staging.unit.test.d.ts +0 -2
  610. package/dist/__tests__/render-feature-staging.unit.test.d.ts.map +0 -1
  611. package/dist/__tests__/renderer-render-scene-public.test-d.d.ts +0 -2
  612. package/dist/__tests__/renderer-render-scene-public.test-d.d.ts.map +0 -1
  613. package/dist/__tests__/scene-temporal-coverage.unit.test.d.ts +0 -2
  614. package/dist/__tests__/scene-temporal-coverage.unit.test.d.ts.map +0 -1
  615. package/dist/__tests__/sun-snapshot-consumers.test.d.ts +0 -2
  616. package/dist/__tests__/sun-snapshot-consumers.test.d.ts.map +0 -1
  617. package/dist/__tests__/surface-backend-kind-owner.test-d.d.ts +0 -2
  618. package/dist/__tests__/surface-backend-kind-owner.test-d.d.ts.map +0 -1
  619. package/dist/__tests__/taa-history-store.unit.test.d.ts +0 -2
  620. package/dist/__tests__/taa-history-store.unit.test.d.ts.map +0 -1
  621. package/dist/__tests__/temporal-frame-transaction.integration.test.d.ts +0 -2
  622. package/dist/__tests__/temporal-frame-transaction.integration.test.d.ts.map +0 -1
  623. package/dist/__tests__/temporal-inspection.unit.test.d.ts +0 -2
  624. package/dist/__tests__/temporal-inspection.unit.test.d.ts.map +0 -1
  625. package/dist/assets/__tests__/asset-decoders.unit.test.d.ts +0 -2
  626. package/dist/assets/__tests__/asset-decoders.unit.test.d.ts.map +0 -1
  627. package/dist/assets/__tests__/mipmap-generator.unit.test.d.ts +0 -2
  628. package/dist/assets/__tests__/mipmap-generator.unit.test.d.ts.map +0 -1
  629. package/dist/assets/__tests__/render-asset-port.unit.test.d.ts +0 -2
  630. package/dist/assets/__tests__/render-asset-port.unit.test.d.ts.map +0 -1
  631. package/dist/assets/__tests__/resolve-render-asset.unit.test.d.ts +0 -2
  632. package/dist/assets/__tests__/resolve-render-asset.unit.test.d.ts.map +0 -1
  633. package/dist/chunk-DJIMFYX6.mjs +0 -1439
  634. package/dist/chunk-DJIMFYX6.mjs.map +0 -1
  635. package/dist/chunk-F2SIOCRM.mjs +0 -7423
  636. package/dist/chunk-F2SIOCRM.mjs.map +0 -1
  637. package/dist/chunk-JMSB7AR4.mjs +0 -3
  638. package/dist/chunk-JMSB7AR4.mjs.map +0 -1
  639. package/dist/chunk-KHI6K4C6.mjs +0 -659
  640. package/dist/chunk-KHI6K4C6.mjs.map +0 -1
  641. package/dist/chunk-PORZOL2V.mjs +0 -569
  642. package/dist/chunk-PORZOL2V.mjs.map +0 -1
  643. package/dist/chunk-UOJGMDGP.mjs +0 -29913
  644. package/dist/chunk-UOJGMDGP.mjs.map +0 -1
  645. package/dist/components/__tests__/atmosphere-red.test.d.ts +0 -2
  646. package/dist/components/__tests__/atmosphere-red.test.d.ts.map +0 -1
  647. package/dist/components/__tests__/atmosphere.test.d.ts +0 -2
  648. package/dist/components/__tests__/atmosphere.test.d.ts.map +0 -1
  649. package/dist/components/__tests__/fog.test-d.d.ts +0 -2
  650. package/dist/components/__tests__/fog.test-d.d.ts.map +0 -1
  651. package/dist/components/__tests__/fog.test.d.ts +0 -2
  652. package/dist/components/__tests__/fog.test.d.ts.map +0 -1
  653. package/dist/components/atmosphere.d.ts +0 -18
  654. package/dist/components/atmosphere.d.ts.map +0 -1
  655. package/dist/components/environment.d.ts +0 -115
  656. package/dist/components/environment.d.ts.map +0 -1
  657. package/dist/deferred-lighting.d.ts +0 -13
  658. package/dist/deferred-lighting.d.ts.map +0 -1
  659. package/dist/dynamic-texture-store.d.ts +0 -42
  660. package/dist/dynamic-texture-store.d.ts.map +0 -1
  661. package/dist/environment/__tests__/failure-injection.test.d.ts +0 -2
  662. package/dist/environment/__tests__/failure-injection.test.d.ts.map +0 -1
  663. package/dist/environment/__tests__/generation-red.test.d.ts +0 -2
  664. package/dist/environment/__tests__/generation-red.test.d.ts.map +0 -1
  665. package/dist/environment/__tests__/generation.test.d.ts +0 -2
  666. package/dist/environment/__tests__/generation.test.d.ts.map +0 -1
  667. package/dist/environment/__tests__/graph-transaction.test.d.ts +0 -2
  668. package/dist/environment/__tests__/graph-transaction.test.d.ts.map +0 -1
  669. package/dist/environment/__tests__/inspection-red.test.d.ts +0 -2
  670. package/dist/environment/__tests__/inspection-red.test.d.ts.map +0 -1
  671. package/dist/environment/__tests__/lifecycle-evidence.test.d.ts +0 -2
  672. package/dist/environment/__tests__/lifecycle-evidence.test.d.ts.map +0 -1
  673. package/dist/environment/__tests__/pipeline-topology.test.d.ts +0 -2
  674. package/dist/environment/__tests__/pipeline-topology.test.d.ts.map +0 -1
  675. package/dist/environment/__tests__/readiness.test.d.ts +0 -2
  676. package/dist/environment/__tests__/readiness.test.d.ts.map +0 -1
  677. package/dist/environment/__tests__/recovery.test.d.ts +0 -2
  678. package/dist/environment/__tests__/recovery.test.d.ts.map +0 -1
  679. package/dist/environment/__tests__/resize-dispose.test.d.ts +0 -2
  680. package/dist/environment/__tests__/resize-dispose.test.d.ts.map +0 -1
  681. package/dist/environment/__tests__/signature-red.test.d.ts +0 -2
  682. package/dist/environment/__tests__/signature-red.test.d.ts.map +0 -1
  683. package/dist/environment/__tests__/signature.test.d.ts +0 -2
  684. package/dist/environment/__tests__/signature.test.d.ts.map +0 -1
  685. package/dist/environment/descriptors.d.ts +0 -2
  686. package/dist/environment/descriptors.d.ts.map +0 -1
  687. package/dist/environment/extracted-environment.d.ts +0 -53
  688. package/dist/environment/extracted-environment.d.ts.map +0 -1
  689. package/dist/environment/generation.d.ts +0 -62
  690. package/dist/environment/generation.d.ts.map +0 -1
  691. package/dist/environment/gpu-bundle.d.ts +0 -23
  692. package/dist/environment/gpu-bundle.d.ts.map +0 -1
  693. package/dist/environment/graph.d.ts +0 -108
  694. package/dist/environment/graph.d.ts.map +0 -1
  695. package/dist/environment/inspection.d.ts +0 -48
  696. package/dist/environment/inspection.d.ts.map +0 -1
  697. package/dist/environment/lifecycle.d.ts +0 -22
  698. package/dist/environment/lifecycle.d.ts.map +0 -1
  699. package/dist/environment/readiness.d.ts +0 -29
  700. package/dist/environment/readiness.d.ts.map +0 -1
  701. package/dist/environment/signature.d.ts +0 -70
  702. package/dist/environment/signature.d.ts.map +0 -1
  703. package/dist/extract/__tests__/directional-csm-domain.unit.test.d.ts +0 -2
  704. package/dist/extract/__tests__/directional-csm-domain.unit.test.d.ts.map +0 -1
  705. package/dist/extract/__tests__/environment-source.test.d.ts +0 -2
  706. package/dist/extract/__tests__/environment-source.test.d.ts.map +0 -1
  707. package/dist/extract/__tests__/schema-readers.unit.test.d.ts +0 -2
  708. package/dist/extract/__tests__/schema-readers.unit.test.d.ts.map +0 -1
  709. package/dist/extract/directional-csm.d.ts +0 -129
  710. package/dist/extract/directional-csm.d.ts.map +0 -1
  711. package/dist/extract/index.d.ts +0 -5
  712. package/dist/extract/index.d.ts.map +0 -1
  713. package/dist/extract/material-interface.d.ts +0 -56
  714. package/dist/extract/material-interface.d.ts.map +0 -1
  715. package/dist/extract/schema-readers.d.ts +0 -20
  716. package/dist/extract/schema-readers.d.ts.map +0 -1
  717. package/dist/features/graph-contribution.d.ts +0 -64
  718. package/dist/features/graph-contribution.d.ts.map +0 -1
  719. package/dist/features/index.d.ts +0 -21
  720. package/dist/features/index.d.ts.map +0 -1
  721. package/dist/features/morph/index.d.ts +0 -3
  722. package/dist/features/morph/index.d.ts.map +0 -1
  723. package/dist/features/morph/morph-bounds.d.ts +0 -42
  724. package/dist/features/morph/morph-bounds.d.ts.map +0 -1
  725. package/dist/features/scene-temporal.d.ts +0 -45
  726. package/dist/features/scene-temporal.d.ts.map +0 -1
  727. package/dist/features/taa-resolve.d.ts +0 -21
  728. package/dist/features/taa-resolve.d.ts.map +0 -1
  729. package/dist/frame-chain.d.ts +0 -14
  730. package/dist/frame-chain.d.ts.map +0 -1
  731. package/dist/gpu-driven/view-reference.d.ts.map +0 -1
  732. package/dist/gpu-resource-store.d.ts.map +0 -1
  733. package/dist/hdrp-cluster-membership.d.ts +0 -2
  734. package/dist/hdrp-cluster-membership.d.ts.map +0 -1
  735. package/dist/hdrp-pipeline.d.ts +0 -36
  736. package/dist/hdrp-pipeline.d.ts.map +0 -1
  737. package/dist/ibl/cubemap-projection.d.ts +0 -23
  738. package/dist/ibl/cubemap-projection.d.ts.map +0 -1
  739. package/dist/ibl/face-uniforms.d.ts +0 -65
  740. package/dist/ibl/face-uniforms.d.ts.map +0 -1
  741. package/dist/mesh-update-errors.d.ts +0 -71
  742. package/dist/mesh-update-errors.d.ts.map +0 -1
  743. package/dist/mipmap-generator.d.ts +0 -39
  744. package/dist/mipmap-generator.d.ts.map +0 -1
  745. package/dist/param-schema-projection-census.d.ts +0 -18
  746. package/dist/param-schema-projection-census.d.ts.map +0 -1
  747. package/dist/persistent-render-scene.d.ts +0 -158
  748. package/dist/persistent-render-scene.d.ts.map +0 -1
  749. package/dist/pipeline/index.d.ts +0 -11
  750. package/dist/pipeline/index.d.ts.map +0 -1
  751. package/dist/pipeline-errors.d.ts +0 -110
  752. package/dist/pipeline-errors.d.ts.map +0 -1
  753. package/dist/prepare/__tests__/schema-readers.unit.test.d.ts +0 -2
  754. package/dist/prepare/__tests__/schema-readers.unit.test.d.ts.map +0 -1
  755. package/dist/prepare/index.d.ts +0 -4
  756. package/dist/prepare/index.d.ts.map +0 -1
  757. package/dist/prepare/schema-readers.d.ts +0 -11
  758. package/dist/prepare/schema-readers.d.ts.map +0 -1
  759. package/dist/record/__tests__/environment-record.test.d.ts +0 -2
  760. package/dist/record/__tests__/environment-record.test.d.ts.map +0 -1
  761. package/dist/record/__tests__/frame-targets.unit.test.d.ts +0 -2
  762. package/dist/record/__tests__/frame-targets.unit.test.d.ts.map +0 -1
  763. package/dist/record/__tests__/membership-timing.unit.test.d.ts +0 -2
  764. package/dist/record/__tests__/membership-timing.unit.test.d.ts.map +0 -1
  765. package/dist/record/__tests__/render-submission.integration.test.d.ts +0 -2
  766. package/dist/record/__tests__/render-submission.integration.test.d.ts.map +0 -1
  767. package/dist/record/__tests__/render-submission.perf.test.d.ts +0 -2
  768. package/dist/record/__tests__/render-submission.perf.test.d.ts.map +0 -1
  769. package/dist/record/__tests__/shadow-submit-mode.unit.test.d.ts +0 -2
  770. package/dist/record/__tests__/shadow-submit-mode.unit.test.d.ts.map +0 -1
  771. package/dist/record/__tests__/view-ubo-layout.unit.test.d.ts +0 -2
  772. package/dist/record/__tests__/view-ubo-layout.unit.test.d.ts.map +0 -1
  773. package/dist/record/frame-observation.d.ts +0 -38
  774. package/dist/record/frame-observation.d.ts.map +0 -1
  775. package/dist/record/index.d.ts +0 -15
  776. package/dist/record/index.d.ts.map +0 -1
  777. package/dist/record/main-pass-skin.d.ts +0 -46
  778. package/dist/record/main-pass-skin.d.ts.map +0 -1
  779. package/dist/record/main-pass-sprite.d.ts +0 -69
  780. package/dist/record/main-pass-sprite.d.ts.map +0 -1
  781. package/dist/record/material-payload.d.ts +0 -43
  782. package/dist/record/material-payload.d.ts.map +0 -1
  783. package/dist/record/material-slot-plan.d.ts +0 -26
  784. package/dist/record/material-slot-plan.d.ts.map +0 -1
  785. package/dist/record/membership-timing.d.ts +0 -232
  786. package/dist/record/membership-timing.d.ts.map +0 -1
  787. package/dist/record/shadow-caster-uniform.d.ts +0 -8
  788. package/dist/record/shadow-caster-uniform.d.ts.map +0 -1
  789. package/dist/record/shadow-submit-mode.d.ts +0 -66
  790. package/dist/record/shadow-submit-mode.d.ts.map +0 -1
  791. package/dist/render-dispatch-membership.d.ts +0 -47
  792. package/dist/render-dispatch-membership.d.ts.map +0 -1
  793. package/dist/render-pipeline-context.d.ts +0 -289
  794. package/dist/render-pipeline-context.d.ts.map +0 -1
  795. package/dist/render-pipeline-target.d.ts +0 -16
  796. package/dist/render-pipeline-target.d.ts.map +0 -1
  797. package/dist/render-scene-projection.d.ts +0 -174
  798. package/dist/render-scene-projection.d.ts.map +0 -1
  799. package/dist/render-system-fold.d.ts +0 -266
  800. package/dist/render-system-fold.d.ts.map +0 -1
  801. package/dist/renderer/asset-service.d.ts +0 -10
  802. package/dist/renderer/asset-service.d.ts.map +0 -1
  803. package/dist/renderer/backend-selection.d.ts.map +0 -1
  804. package/dist/renderer/environment-classify.d.ts +0 -6
  805. package/dist/renderer/environment-classify.d.ts.map +0 -1
  806. package/dist/renderer/environment-error.d.ts +0 -13
  807. package/dist/renderer/environment-error.d.ts.map +0 -1
  808. package/dist/renderer/material/pipeline-projection.d.ts +0 -91
  809. package/dist/renderer/material/pipeline-projection.d.ts.map +0 -1
  810. package/dist/renderer/renderer-factory.d.ts +0 -289
  811. package/dist/renderer/renderer-factory.d.ts.map +0 -1
  812. package/dist/renderer.d.ts +0 -771
  813. package/dist/renderer.d.ts.map +0 -1
  814. package/dist/scene-utils/collect-subtree.d.ts +0 -11
  815. package/dist/scene-utils/collect-subtree.d.ts.map +0 -1
  816. package/dist/ssao-data.d.ts +0 -34
  817. package/dist/ssao-data.d.ts.map +0 -1
  818. package/dist/surface-format.d.ts +0 -10
  819. package/dist/surface-format.d.ts.map +0 -1
  820. package/dist/taa-history-store.d.ts +0 -88
  821. package/dist/taa-history-store.d.ts.map +0 -1
  822. package/dist/temporal-coverage.d.ts +0 -35
  823. package/dist/temporal-coverage.d.ts.map +0 -1
  824. package/dist/temporal-frame-transaction.d.ts +0 -92
  825. package/dist/temporal-frame-transaction.d.ts.map +0 -1
  826. package/dist/temporal-inspection.d.ts +0 -57
  827. package/dist/temporal-inspection.d.ts.map +0 -1
  828. package/dist/temporal-view.d.ts +0 -43
  829. package/dist/temporal-view.d.ts.map +0 -1
  830. package/dist/tilemap/resolve-tileset-runtime.d.ts +0 -23
  831. package/dist/tilemap/resolve-tileset-runtime.d.ts.map +0 -1
  832. package/dist/urp-pipeline.d.ts +0 -4
  833. package/dist/urp-pipeline.d.ts.map +0 -1
  834. package/src/__tests__/analytic-sky-contract.test.ts +0 -27
  835. package/src/__tests__/analytic-sky-falsify-carriers.mjs +0 -43
  836. package/src/__tests__/analytic-sky-falsify.test.ts +0 -94
  837. package/src/__tests__/assets-runtime-handoff.integration.test.ts +0 -36
  838. package/src/__tests__/backend-selection.integration.test.ts +0 -11
  839. package/src/__tests__/camera-temporal.test-d.ts +0 -8
  840. package/src/__tests__/camera-temporal.test.ts +0 -188
  841. package/src/__tests__/directional-shadow-probe-atlas-layout.unit.test.ts +0 -18
  842. package/src/__tests__/environment-inspection.test.ts +0 -45
  843. package/src/__tests__/fog-ai-user.fixture.ts +0 -350
  844. package/src/__tests__/fog-custom-render-feature.fixture.ts +0 -33
  845. package/src/__tests__/fog-custom-render-feature.integration.test.ts +0 -76
  846. package/src/__tests__/fog-inspection.integration.test.ts +0 -127
  847. package/src/__tests__/fog-owner-state.integration.test.ts +0 -112
  848. package/src/__tests__/fog-pipeline-topology.integration.test.ts +0 -93
  849. package/src/__tests__/fog-public-surface.integration.test.ts +0 -60
  850. package/src/__tests__/fog-ray-contract.integration.test.ts +0 -73
  851. package/src/__tests__/fog-source-absence.integration.test.ts +0 -51
  852. package/src/__tests__/fog-temporal.integration.test.ts +0 -115
  853. package/src/__tests__/frame-chain.unit.test.ts +0 -26
  854. package/src/__tests__/gpu-scene-field-type-owner.test-d.ts +0 -27
  855. package/src/__tests__/hdrp-pipeline.unit.test.ts +0 -100
  856. package/src/__tests__/ibl/ibl-fallback.unit.test.ts +0 -23
  857. package/src/__tests__/material-derived-error-stop-draw.integration.test.ts +0 -69
  858. package/src/__tests__/material-derived-payload.integration.test.ts +0 -164
  859. package/src/__tests__/materials.unit.test.ts +0 -25
  860. package/src/__tests__/param-schema-projection-census.unit.test.ts +0 -40
  861. package/src/__tests__/persistent-render-scene.unit.test.ts +0 -1311
  862. package/src/__tests__/pipeline-error-policy-owner.unit.test.ts +0 -167
  863. package/src/__tests__/pipeline-pass-trace.test.ts +0 -92
  864. package/src/__tests__/pipeline-stage-owner.test-d.ts +0 -13
  865. package/src/__tests__/plugin.test.ts +0 -25
  866. package/src/__tests__/prepared-graphics-backend-matrix.unit.test.ts +0 -129
  867. package/src/__tests__/prepared-graphics-resolver-recording.unit.test.ts +0 -180
  868. package/src/__tests__/public-pipeline-id.test-d.ts +0 -6
  869. package/src/__tests__/render-dispatch-membership.unit.test.ts +0 -117
  870. package/src/__tests__/render-feature-construction.unit.test.ts +0 -124
  871. package/src/__tests__/render-feature-error-code-owner.test-d.ts +0 -27
  872. package/src/__tests__/render-feature-gpu-buffer-usage-owner.test-d.ts +0 -46
  873. package/src/__tests__/render-feature-graph.integration.test.ts +0 -205
  874. package/src/__tests__/render-feature-graphics-staging.unit.test.ts +0 -200
  875. package/src/__tests__/render-feature-order.unit.test.ts +0 -66
  876. package/src/__tests__/render-feature-prepared-graphics-recording.unit.test.ts +0 -107
  877. package/src/__tests__/render-feature-staging.unit.test.ts +0 -94
  878. package/src/__tests__/renderer-render-scene-public.test-d.ts +0 -27
  879. package/src/__tests__/scene-temporal-coverage.unit.test.ts +0 -259
  880. package/src/__tests__/sun-snapshot-consumers.test.ts +0 -35
  881. package/src/__tests__/surface-backend-kind-owner.test-d.ts +0 -42
  882. package/src/__tests__/taa-history-store.unit.test.ts +0 -196
  883. package/src/__tests__/temporal-frame-transaction.integration.test.ts +0 -537
  884. package/src/__tests__/temporal-inspection.unit.test.ts +0 -138
  885. package/src/assets/__tests__/asset-decoders.unit.test.ts +0 -92
  886. package/src/assets/__tests__/mipmap-generator.unit.test.ts +0 -52
  887. package/src/assets/__tests__/render-asset-port.unit.test.ts +0 -54
  888. package/src/assets/__tests__/resolve-render-asset.unit.test.ts +0 -47
  889. package/src/components/__tests__/atmosphere-red.test.ts +0 -51
  890. package/src/components/__tests__/atmosphere.test.ts +0 -79
  891. package/src/components/__tests__/fog.test-d.ts +0 -49
  892. package/src/components/__tests__/fog.test.ts +0 -60
  893. package/src/components/atmosphere.ts +0 -64
  894. package/src/deferred-lighting.ts +0 -92
  895. package/src/dynamic-texture-store.ts +0 -111
  896. package/src/environment/README.md +0 -76
  897. package/src/environment/__tests__/failure-injection.test.ts +0 -50
  898. package/src/environment/__tests__/generation-red.test.ts +0 -64
  899. package/src/environment/__tests__/generation.test.ts +0 -37
  900. package/src/environment/__tests__/graph-transaction.test.ts +0 -85
  901. package/src/environment/__tests__/inspection-red.test.ts +0 -53
  902. package/src/environment/__tests__/lifecycle-evidence.test.ts +0 -40
  903. package/src/environment/__tests__/pipeline-topology.test.ts +0 -33
  904. package/src/environment/__tests__/readiness.test.ts +0 -42
  905. package/src/environment/__tests__/recovery.test.ts +0 -62
  906. package/src/environment/__tests__/resize-dispose.test.ts +0 -30
  907. package/src/environment/__tests__/signature-red.test.ts +0 -45
  908. package/src/environment/__tests__/signature.test.ts +0 -60
  909. package/src/environment/descriptors.ts +0 -7
  910. package/src/environment/extracted-environment.ts +0 -239
  911. package/src/environment/generation.ts +0 -158
  912. package/src/environment/gpu-bundle.ts +0 -144
  913. package/src/environment/graph.ts +0 -588
  914. package/src/environment/inspection.ts +0 -107
  915. package/src/environment/lifecycle.ts +0 -124
  916. package/src/environment/readiness.ts +0 -76
  917. package/src/environment/signature.ts +0 -185
  918. package/src/extract/__tests__/directional-csm-domain.unit.test.ts +0 -391
  919. package/src/extract/__tests__/environment-source.test.ts +0 -105
  920. package/src/extract/__tests__/schema-readers.unit.test.ts +0 -16
  921. package/src/extract/directional-csm.ts +0 -959
  922. package/src/extract/index.ts +0 -10
  923. package/src/extract/material-interface.ts +0 -604
  924. package/src/extract/schema-readers.ts +0 -27
  925. package/src/features/graph-contribution.ts +0 -577
  926. package/src/features/index.ts +0 -100
  927. package/src/features/morph/index.ts +0 -24
  928. package/src/features/morph/morph-bounds.ts +0 -123
  929. package/src/features/scene-temporal.ts +0 -274
  930. package/src/features/taa-resolve.ts +0 -244
  931. package/src/frame-chain.ts +0 -21
  932. package/src/hdrp-cluster-membership.ts +0 -70
  933. package/src/ibl/cubemap-projection.ts +0 -60
  934. package/src/ibl/face-uniforms.ts +0 -150
  935. package/src/mesh-update-errors.ts +0 -113
  936. package/src/mipmap-generator.ts +0 -244
  937. package/src/param-schema-projection-census.ts +0 -73
  938. package/src/persistent-render-scene.ts +0 -1752
  939. package/src/pipeline/index.ts +0 -40
  940. package/src/pipeline-errors.ts +0 -172
  941. package/src/prepare/__tests__/schema-readers.unit.test.ts +0 -16
  942. package/src/prepare/index.ts +0 -8
  943. package/src/prepare/schema-readers.ts +0 -20
  944. package/src/record/__tests__/environment-record.test.ts +0 -35
  945. package/src/record/__tests__/frame-targets.unit.test.ts +0 -54
  946. package/src/record/__tests__/membership-timing.unit.test.ts +0 -524
  947. package/src/record/__tests__/render-submission.integration.test.ts +0 -76
  948. package/src/record/__tests__/render-submission.perf.test.ts +0 -141
  949. package/src/record/__tests__/shadow-submit-mode.unit.test.ts +0 -88
  950. package/src/record/__tests__/view-ubo-layout.unit.test.ts +0 -101
  951. package/src/record/frame-observation.ts +0 -122
  952. package/src/record/index.ts +0 -15
  953. package/src/record/main-pass-skin.ts +0 -51
  954. package/src/record/main-pass-sprite.ts +0 -166
  955. package/src/record/material-payload.ts +0 -292
  956. package/src/record/material-slot-plan.ts +0 -68
  957. package/src/record/membership-timing.ts +0 -1012
  958. package/src/record/shadow-caster-uniform.ts +0 -37
  959. package/src/record/shadow-submit-mode.ts +0 -277
  960. package/src/render-dispatch-membership.ts +0 -155
  961. package/src/render-pipeline-context.ts +0 -332
  962. package/src/render-pipeline-target.ts +0 -96
  963. package/src/render-scene-projection.ts +0 -1738
  964. package/src/render-system-fold.ts +0 -531
  965. package/src/renderer/asset-service.ts +0 -32
  966. package/src/renderer/backend-selection.ts +0 -121
  967. package/src/renderer/environment-classify.ts +0 -30
  968. package/src/renderer/environment-error.ts +0 -19
  969. package/src/renderer/material/pipeline-projection.ts +0 -140
  970. package/src/renderer.ts +0 -940
  971. package/src/scene-utils/collect-subtree.ts +0 -40
  972. package/src/ssao-data.ts +0 -106
  973. package/src/surface-format.ts +0 -37
  974. package/src/taa-history-store.ts +0 -429
  975. package/src/temporal-coverage.ts +0 -106
  976. package/src/temporal-frame-transaction.ts +0 -301
  977. package/src/temporal-inspection.ts +0 -194
  978. package/src/temporal-view.ts +0 -174
  979. 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,70 +603,15 @@ 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
- pass.setBindGroup(0, viewBindGroup);
609
+ // pbr-view-bgl carries the vertex-only Points/Lines UBO at binding
610
+ // 10 as a dynamic uniform buffer. The production view group is
611
+ // shared by the GPU-driven raster pipeline, so even rigid draws
612
+ // must provide the binding-10 offset (zero selects the frame
613
+ // default slot).
614
+ pass.setBindGroup(0, viewBindGroup, [0]);
1366
615
  let currentPipeline: RenderPipeline | undefined;
1367
616
  let currentVertex: GraphBuffer | undefined;
1368
617
  let currentIndex: GraphBuffer | undefined;
@@ -1398,238 +647,12 @@ export class GpuDrivenProduction {
1398
647
  });
1399
648
  }
1400
649
 
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
650
  dispose(): void {
1618
651
  this.view?.dispose();
1619
- for (const view of this.shadowViews.values()) view.dispose();
1620
- this.shadowViews.clear();
1621
- this.shadowRaster?.dispose();
1622
652
  this.view = undefined;
1623
653
  this.raster = undefined;
1624
- this.shadowRaster = undefined;
1625
- this.preparedShadowViews = [];
1626
654
  this.filteredCache = undefined;
1627
655
  this.signatureCache = undefined;
1628
- this.cpuVisibility = undefined;
1629
- this.shadowCasterSlotIndices = undefined;
1630
- this.shadowSubmission = undefined;
1631
- this.shadowPlanCache.clear();
1632
- this.shadowCandidateMembership = undefined;
1633
656
  }
1634
657
 
1635
658
  inspect(): GpuDrivenProductionInspection {
@@ -1637,7 +660,7 @@ export class GpuDrivenProduction {
1637
660
  return {
1638
661
  gpuOwnedSnapshotsMaterialized: this.gpuOwnedSnapshotsMaterialized,
1639
662
  filteredPlanBuilds: this.filteredPlanBuilds,
1640
- gpuOwnedItemCount: this.gpuOwnedItemCount,
663
+ gpuOwnedEntityCount: this.gpuOwnedEntityCount,
1641
664
  candidateUploadBytes: view?.candidateUploadBytes ?? 0,
1642
665
  batchUploadBytes: view?.batchUploadBytes ?? 0,
1643
666
  viewConstantsUploadBytes: view?.viewConstantsUploadBytes ?? 0,
@@ -1646,37 +669,19 @@ export class GpuDrivenProduction {
1646
669
  topologyRevision: view?.topologyRevision,
1647
670
  validatedGpuOwnedRows: this.validatedGpuOwnedRows,
1648
671
  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
672
  };
1658
673
  }
1659
674
 
1660
675
  recordCpuValidation(
1661
676
  validated: readonly { readonly source: RenderableSnapshot }[],
1662
- gpuOwned: ReadonlySet<RasterItemKey>,
677
+ gpuOwned: ReadonlySet<number>,
1663
678
  ): void {
1664
- let cpuFallbackItems = 0;
679
+ this.cpuFallbackDrawItems = validated.length;
680
+ let gpuOwnedRows = 0;
1665
681
  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
- }
682
+ if (gpuOwned.has(worldEntityKey(row.source.worldId, row.source.entityKey))) gpuOwnedRows += 1;
1675
683
  }
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;
684
+ this.validatedGpuOwnedRows = gpuOwnedRows;
1680
685
  }
1681
686
 
1682
687
  private sceneIdentity(scene: object): number {
@@ -1687,19 +692,4 @@ export class GpuDrivenProduction {
1687
692
  this.sceneIdentities.set(scene, identity);
1688
693
  return identity;
1689
694
  }
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
695
  }