@forgeax/engine-render 0.1.27 → 0.1.29

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 (655) hide show
  1. package/README.md +842 -124
  2. package/dist/assembly/atmosphere-shader-prewarm.d.ts +6 -0
  3. package/dist/assembly/atmosphere-shader-prewarm.d.ts.map +1 -0
  4. package/dist/assembly/dynamic-geometry-host.d.ts +52 -0
  5. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -0
  6. package/dist/assembly/dynamic-geometry-runtime.d.ts +20 -0
  7. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -0
  8. package/dist/assembly/factory.d.ts +3 -1
  9. package/dist/assembly/factory.d.ts.map +1 -1
  10. package/dist/assembly/gpu-driven-owner.d.ts +10 -0
  11. package/dist/assembly/gpu-driven-owner.d.ts.map +1 -0
  12. package/dist/assembly/host-contract.d.ts +19 -0
  13. package/dist/assembly/host-contract.d.ts.map +1 -1
  14. package/dist/assembly/material/assembly.d.ts +7 -0
  15. package/dist/assembly/material/assembly.d.ts.map +1 -1
  16. package/dist/assembly/material-shader-policy.d.ts +3 -1
  17. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  18. package/dist/assembly/recovery/failure-location.d.ts +12 -0
  19. package/dist/assembly/recovery/failure-location.d.ts.map +1 -0
  20. package/dist/assembly/recovery/renderer-recover.d.ts +6 -4
  21. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  22. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  23. package/dist/assembly/renderer-feature-inspection.d.ts +5 -0
  24. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -0
  25. package/dist/assembly/renderer-frame-transaction.d.ts +19 -0
  26. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  27. package/dist/assembly/renderer-helpers.d.ts +3 -0
  28. package/dist/assembly/renderer-helpers.d.ts.map +1 -1
  29. package/dist/assembly/renderer-inspection.d.ts +4 -0
  30. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  31. package/dist/assembly/shader-prewarm-policy.d.ts +6 -0
  32. package/dist/assembly/shader-prewarm-policy.d.ts.map +1 -1
  33. package/dist/assembly/skin-palette-owner.d.ts +8 -0
  34. package/dist/assembly/skin-palette-owner.d.ts.map +1 -0
  35. package/dist/assembly/ssr-shader-prewarm.d.ts +6 -0
  36. package/dist/assembly/ssr-shader-prewarm.d.ts.map +1 -0
  37. package/dist/assembly/webgpu-device-loss.d.ts +15 -0
  38. package/dist/assembly/webgpu-device-loss.d.ts.map +1 -0
  39. package/dist/assembly/webgpu-pbr-ready.d.ts +38 -0
  40. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -0
  41. package/dist/assembly/webgpu-ready-mipmap.d.ts +11 -0
  42. package/dist/assembly/webgpu-ready-mipmap.d.ts.map +1 -0
  43. package/dist/assembly/webgpu-ready.d.ts +7 -3
  44. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  45. package/dist/assembly/webgpu-renderer-bootstrap.d.ts +10 -0
  46. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -0
  47. package/dist/assembly/webgpu-renderer-contract.d.ts +62 -0
  48. package/dist/assembly/webgpu-renderer-contract.d.ts.map +1 -0
  49. package/dist/assembly/webgpu-renderer-guards.d.ts +9 -0
  50. package/dist/assembly/webgpu-renderer-guards.d.ts.map +1 -0
  51. package/dist/assembly/webgpu-renderer-observation.d.ts +6 -0
  52. package/dist/assembly/webgpu-renderer-observation.d.ts.map +1 -0
  53. package/dist/assembly/webgpu-renderer-recovery-failure.d.ts +12 -0
  54. package/dist/assembly/webgpu-renderer-recovery-failure.d.ts.map +1 -0
  55. package/dist/assembly/webgpu-renderer.d.ts +7 -141
  56. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  57. package/dist/assembly/webgpu-vertex-layouts.d.ts +28 -84
  58. package/dist/assembly/webgpu-vertex-layouts.d.ts.map +1 -1
  59. package/dist/authoring.mjs +3 -3
  60. package/dist/{chunk-ADHHVYLW.mjs → chunk-33XZFTQU.mjs} +245 -39
  61. package/dist/chunk-33XZFTQU.mjs.map +1 -0
  62. package/dist/{chunk-GF523LHF.mjs → chunk-BLXGONR2.mjs} +30 -12
  63. package/dist/chunk-BLXGONR2.mjs.map +1 -0
  64. package/dist/{chunk-KM2NOX2I.mjs → chunk-BQVQOQJH.mjs} +958 -254
  65. package/dist/chunk-BQVQOQJH.mjs.map +1 -0
  66. package/dist/{chunk-HKXTW355.mjs → chunk-BTWH7BP4.mjs} +386 -17
  67. package/dist/chunk-BTWH7BP4.mjs.map +1 -0
  68. package/dist/{chunk-TMIASV2N.mjs → chunk-FUODTTIA.mjs} +3934 -676
  69. package/dist/chunk-FUODTTIA.mjs.map +1 -0
  70. package/dist/{chunk-FJ6P52EE.mjs → chunk-ILQ5MEZF.mjs} +3 -17
  71. package/dist/chunk-ILQ5MEZF.mjs.map +1 -0
  72. package/dist/{chunk-E34VL5VI.mjs → chunk-JQTSEI3Z.mjs} +3 -3
  73. package/dist/{chunk-E34VL5VI.mjs.map → chunk-JQTSEI3Z.mjs.map} +1 -1
  74. package/dist/{chunk-GE3SDD72.mjs → chunk-NICXSHAT.mjs} +16 -38
  75. package/dist/chunk-NICXSHAT.mjs.map +1 -0
  76. package/dist/{chunk-ZZ4YQ474.mjs → chunk-NRNXBLIJ.mjs} +577 -7
  77. package/dist/chunk-NRNXBLIJ.mjs.map +1 -0
  78. package/dist/{chunk-JDWARUOI.mjs → chunk-PA5DRJNI.mjs} +17 -3
  79. package/dist/chunk-PA5DRJNI.mjs.map +1 -0
  80. package/dist/{chunk-XDP6XE5V.mjs → chunk-S4DNKQYQ.mjs} +1118 -446
  81. package/dist/chunk-S4DNKQYQ.mjs.map +1 -0
  82. package/dist/components/camera.d.ts +62 -2
  83. package/dist/components/camera.d.ts.map +1 -1
  84. package/dist/components/index.d.ts +1 -0
  85. package/dist/components/index.d.ts.map +1 -1
  86. package/dist/components/instances.d.ts +6 -20
  87. package/dist/components/instances.d.ts.map +1 -1
  88. package/dist/components/scene-instance.d.ts +2 -1
  89. package/dist/components/scene-instance.d.ts.map +1 -1
  90. package/dist/components/screen-space-reflection.d.ts +14 -0
  91. package/dist/components/screen-space-reflection.d.ts.map +1 -0
  92. package/dist/construct-renderer.mjs +13805 -7186
  93. package/dist/construct-renderer.mjs.map +1 -1
  94. package/dist/device/gpu-residency.d.ts +11 -17
  95. package/dist/device/gpu-residency.d.ts.map +1 -1
  96. package/dist/device/mesh-residency-lifetime.d.ts +21 -0
  97. package/dist/device/mesh-residency-lifetime.d.ts.map +1 -0
  98. package/dist/dynamic-geometry.d.ts +125 -0
  99. package/dist/dynamic-geometry.d.ts.map +1 -0
  100. package/dist/environment/background.d.ts +6 -0
  101. package/dist/environment/background.d.ts.map +1 -0
  102. package/dist/errors/gpu-driven.d.ts +6 -3
  103. package/dist/errors/gpu-driven.d.ts.map +1 -1
  104. package/dist/errors/render.d.ts +7 -4
  105. package/dist/errors/render.d.ts.map +1 -1
  106. package/dist/extract/camera.d.ts.map +1 -1
  107. package/dist/extract/gpu-driven.d.ts +33 -3
  108. package/dist/extract/gpu-driven.d.ts.map +1 -1
  109. package/dist/features/host.d.ts +23 -1
  110. package/dist/features/host.d.ts.map +1 -1
  111. package/dist/features/noise-texture.d.ts +17 -0
  112. package/dist/features/noise-texture.d.ts.map +1 -0
  113. package/dist/features/plan.d.ts +83 -2
  114. package/dist/features/plan.d.ts.map +1 -1
  115. package/dist/features/prepared-gpu-work.d.ts +37 -4
  116. package/dist/features/prepared-gpu-work.d.ts.map +1 -1
  117. package/dist/features/prepared-graphics-store.d.ts.map +1 -1
  118. package/dist/features/prepared-graphics.d.ts +5 -0
  119. package/dist/features/prepared-graphics.d.ts.map +1 -1
  120. package/dist/features/render-graph-compute.d.ts +5 -3
  121. package/dist/features/render-graph-compute.d.ts.map +1 -1
  122. package/dist/features/render-graph-contribution.d.ts +11 -3
  123. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  124. package/dist/features/render-graph-raster.d.ts +19 -3
  125. package/dist/features/render-graph-raster.d.ts.map +1 -1
  126. package/dist/features/types.d.ts +11 -0
  127. package/dist/features/types.d.ts.map +1 -1
  128. package/dist/fullscreen-post-process-pass.d.ts +2 -0
  129. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  130. package/dist/gpu-driven/batch-topology.d.ts +34 -1
  131. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  132. package/dist/gpu-driven/pbr-program.d.ts +10 -0
  133. package/dist/gpu-driven/pbr-program.d.ts.map +1 -0
  134. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  135. package/dist/gpu-driven/production-raster.d.ts +144 -23
  136. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  137. package/dist/gpu-driven/shadow-views.d.ts +126 -0
  138. package/dist/gpu-driven/shadow-views.d.ts.map +1 -0
  139. package/dist/gpu-driven/view-gpu.d.ts +18 -2
  140. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  141. package/dist/gpu-scene-schema.d.ts +2 -8
  142. package/dist/gpu-scene-schema.d.ts.map +1 -1
  143. package/dist/gpu-scene.d.ts +14 -0
  144. package/dist/gpu-scene.d.ts.map +1 -1
  145. package/dist/gpu-texture-usage.d.ts +1 -0
  146. package/dist/gpu-texture-usage.d.ts.map +1 -1
  147. package/dist/hdrp-buffers.d.ts +6 -0
  148. package/dist/hdrp-buffers.d.ts.map +1 -1
  149. package/dist/ibl/frame-resources.d.ts +8 -0
  150. package/dist/ibl/frame-resources.d.ts.map +1 -0
  151. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  152. package/dist/index.d.ts +21 -8
  153. package/dist/index.d.ts.map +1 -1
  154. package/dist/index.mjs +8 -7
  155. package/dist/index.mjs.map +1 -1
  156. package/dist/inspection-types.d.ts +164 -0
  157. package/dist/inspection-types.d.ts.map +1 -1
  158. package/dist/instances-derived-bounds.d.ts +11 -0
  159. package/dist/instances-derived-bounds.d.ts.map +1 -1
  160. package/dist/instances.d.ts +89 -44
  161. package/dist/instances.d.ts.map +1 -1
  162. package/dist/internal.d.ts +3 -0
  163. package/dist/internal.d.ts.map +1 -1
  164. package/dist/internal.mjs +118 -10
  165. package/dist/internal.mjs.map +1 -1
  166. package/dist/lifecycle.d.ts +2 -1
  167. package/dist/lifecycle.d.ts.map +1 -1
  168. package/dist/material-row.d.ts +5 -0
  169. package/dist/material-row.d.ts.map +1 -0
  170. package/dist/materials.d.ts +15 -0
  171. package/dist/materials.d.ts.map +1 -1
  172. package/dist/pbr-pipeline.d.ts +21 -5
  173. package/dist/pbr-pipeline.d.ts.map +1 -1
  174. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  175. package/dist/pipeline/standard-output/auto-exposure/capability.d.ts +12 -0
  176. package/dist/pipeline/standard-output/auto-exposure/capability.d.ts.map +1 -0
  177. package/dist/pipeline/standard-output/auto-exposure/gpu.d.ts +70 -0
  178. package/dist/pipeline/standard-output/auto-exposure/gpu.d.ts.map +1 -0
  179. package/dist/pipeline/standard-output/auto-exposure/graph.d.ts +75 -0
  180. package/dist/pipeline/standard-output/auto-exposure/graph.d.ts.map +1 -0
  181. package/dist/pipeline/standard-output/auto-exposure/inspection.d.ts +111 -0
  182. package/dist/pipeline/standard-output/auto-exposure/inspection.d.ts.map +1 -0
  183. package/dist/pipeline/standard-output/auto-exposure/oracle.d.ts +16 -0
  184. package/dist/pipeline/standard-output/auto-exposure/oracle.d.ts.map +1 -0
  185. package/dist/pipeline/standard-output/auto-exposure/preset.d.ts +14 -0
  186. package/dist/pipeline/standard-output/auto-exposure/preset.d.ts.map +1 -0
  187. package/dist/pipeline/standard-output/auto-exposure/state.d.ts +46 -0
  188. package/dist/pipeline/standard-output/auto-exposure/state.d.ts.map +1 -0
  189. package/dist/pipeline/standard-output/color-transform.d.ts +27 -0
  190. package/dist/pipeline/standard-output/color-transform.d.ts.map +1 -0
  191. package/dist/pipeline/standard-output/graph.d.ts +15 -0
  192. package/dist/pipeline/standard-output/graph.d.ts.map +1 -0
  193. package/dist/pipeline/standard-output/lut-admission.d.ts +29 -0
  194. package/dist/pipeline/standard-output/lut-admission.d.ts.map +1 -0
  195. package/dist/pipeline/standard-output/lut-gpu.d.ts +48 -0
  196. package/dist/pipeline/standard-output/lut-gpu.d.ts.map +1 -0
  197. package/dist/pipeline/standard-output/lut-state.d.ts +68 -0
  198. package/dist/pipeline/standard-output/lut-state.d.ts.map +1 -0
  199. package/dist/pipeline/standard-output/resources.d.ts +10 -0
  200. package/dist/pipeline/standard-output/resources.d.ts.map +1 -0
  201. package/dist/pipeline/standard-output/types.d.ts +39 -0
  202. package/dist/pipeline/standard-output/types.d.ts.map +1 -0
  203. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  204. package/dist/pipeline/standard-post.d.ts +2 -2
  205. package/dist/pipeline/standard-post.d.ts.map +1 -1
  206. package/dist/pipeline-builder.d.ts +2 -1
  207. package/dist/pipeline-builder.d.ts.map +1 -1
  208. package/dist/pipeline-spec-types.d.ts +4 -0
  209. package/dist/pipeline-spec-types.d.ts.map +1 -1
  210. package/dist/pipeline-spec.d.ts +1 -9
  211. package/dist/pipeline-spec.d.ts.map +1 -1
  212. package/dist/points-lines/standard-owner.d.ts +1 -1
  213. package/dist/points-lines/standard-owner.d.ts.map +1 -1
  214. package/dist/prepare/prepared-graphics-resolver.d.ts +6 -1
  215. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  216. package/dist/record/dynamic-geometry-consumption.d.ts +15 -0
  217. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -0
  218. package/dist/record/frame-lighting.d.ts +3 -3
  219. package/dist/record/frame-lighting.d.ts.map +1 -1
  220. package/dist/record/frame-snapshot.d.ts +106 -5
  221. package/dist/record/frame-snapshot.d.ts.map +1 -1
  222. package/dist/record/frame-targets.d.ts.map +1 -1
  223. package/dist/record/frame.d.ts +39 -4
  224. package/dist/record/frame.d.ts.map +1 -1
  225. package/dist/record/main-pass-geometry.d.ts +7 -8
  226. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  227. package/dist/record/main-pass-material.d.ts +38 -1
  228. package/dist/record/main-pass-material.d.ts.map +1 -1
  229. package/dist/record/main-pass-sprite-draws.d.ts +2 -10
  230. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  231. package/dist/record/main-pass.d.ts +12 -2
  232. package/dist/record/main-pass.d.ts.map +1 -1
  233. package/dist/record/mesh-ssbo.d.ts +15 -6
  234. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  235. package/dist/record/prepared-material-bindings.d.ts +19 -0
  236. package/dist/record/prepared-material-bindings.d.ts.map +1 -0
  237. package/dist/record/recovery-pipeline.d.ts +2 -9
  238. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  239. package/dist/record/render-context.d.ts +76 -26
  240. package/dist/record/render-context.d.ts.map +1 -1
  241. package/dist/record/shadow-pass.d.ts +62 -7
  242. package/dist/record/shadow-pass.d.ts.map +1 -1
  243. package/dist/record/skybox-post-pass.d.ts +1 -1
  244. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  245. package/dist/record/typed-frame-graph.d.ts +35 -7
  246. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  247. package/dist/record/view-ubo.d.ts +1 -0
  248. package/dist/record/view-ubo.d.ts.map +1 -1
  249. package/dist/recovery/render-system-candidate.d.ts +10 -2
  250. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  251. package/dist/recovery/render-system-roots.d.ts +11 -0
  252. package/dist/recovery/render-system-roots.d.ts.map +1 -0
  253. package/dist/recovery/types.d.ts +76 -0
  254. package/dist/recovery/types.d.ts.map +1 -0
  255. package/dist/reflection/record-owner.d.ts +0 -2
  256. package/dist/reflection/record-owner.d.ts.map +1 -1
  257. package/dist/render-contract.d.ts +185 -30
  258. package/dist/render-contract.d.ts.map +1 -1
  259. package/dist/render-graph-primitives.d.ts +1 -0
  260. package/dist/render-graph-primitives.d.ts.map +1 -1
  261. package/dist/render-pipeline.d.ts +64 -5
  262. package/dist/render-pipeline.d.ts.map +1 -1
  263. package/dist/render-system-extract-tail.d.ts +7 -5
  264. package/dist/render-system-extract-tail.d.ts.map +1 -1
  265. package/dist/render-system-extract.d.ts +101 -41
  266. package/dist/render-system-extract.d.ts.map +1 -1
  267. package/dist/render-system-projections.d.ts +22 -0
  268. package/dist/render-system-projections.d.ts.map +1 -0
  269. package/dist/render-system.d.ts +34 -77
  270. package/dist/render-system.d.ts.map +1 -1
  271. package/dist/scene/render-scene-types.d.ts +14 -7
  272. package/dist/scene/render-scene-types.d.ts.map +1 -1
  273. package/dist/scene/render-scene.d.ts +29 -11
  274. package/dist/scene/render-scene.d.ts.map +1 -1
  275. package/dist/scene/shadow-visibility.d.ts +5 -0
  276. package/dist/scene/shadow-visibility.d.ts.map +1 -0
  277. package/dist/ssr/admission.d.ts +70 -1
  278. package/dist/ssr/admission.d.ts.map +1 -1
  279. package/dist/ssr/compose.d.ts +13 -0
  280. package/dist/ssr/compose.d.ts.map +1 -0
  281. package/dist/ssr/errors.d.ts +35 -0
  282. package/dist/ssr/errors.d.ts.map +1 -1
  283. package/dist/ssr/graph.d.ts +60 -0
  284. package/dist/ssr/graph.d.ts.map +1 -0
  285. package/dist/ssr/history.d.ts +97 -0
  286. package/dist/ssr/history.d.ts.map +1 -0
  287. package/dist/ssr/hiz.d.ts +37 -0
  288. package/dist/ssr/hiz.d.ts.map +1 -0
  289. package/dist/ssr/inspection.d.ts +42 -0
  290. package/dist/ssr/inspection.d.ts.map +1 -0
  291. package/dist/ssr/resources.d.ts +58 -0
  292. package/dist/ssr/resources.d.ts.map +1 -0
  293. package/dist/ssr/temporal.d.ts +38 -0
  294. package/dist/ssr/temporal.d.ts.map +1 -0
  295. package/dist/systems/skin-palette-allocator.d.ts +32 -10
  296. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  297. package/dist/systems/skin-palette-types.d.ts +15 -0
  298. package/dist/systems/skin-palette-types.d.ts.map +1 -1
  299. package/dist/systems/transparent-dispatch.d.ts +9 -0
  300. package/dist/systems/transparent-dispatch.d.ts.map +1 -0
  301. package/dist/targets/material-source.d.ts +7 -0
  302. package/dist/targets/material-source.d.ts.map +1 -1
  303. package/dist/temporal/frame-coordinator.d.ts +7 -0
  304. package/dist/temporal/frame-coordinator.d.ts.map +1 -1
  305. package/dist/temporal/gpu.d.ts +8 -0
  306. package/dist/temporal/gpu.d.ts.map +1 -1
  307. package/dist/temporal/history.d.ts.map +1 -1
  308. package/dist/temporal/index.mjs +6 -6
  309. package/dist/temporal/inspection.d.ts.map +1 -1
  310. package/dist/temporal/standard-scene-data.d.ts +2 -1
  311. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  312. package/dist/temporal/temporal-view.d.ts +2 -0
  313. package/dist/temporal/temporal-view.d.ts.map +1 -1
  314. package/dist/typed-render-graph-primitives.d.ts +35 -1
  315. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  316. package/dist/typed-shadow-passes.d.ts +3 -1
  317. package/dist/typed-shadow-passes.d.ts.map +1 -1
  318. package/dist/volume/temporal.d.ts +6 -0
  319. package/dist/volume/temporal.d.ts.map +1 -1
  320. package/package.json +21 -20
  321. package/src/__tests__/auto-exposure-gpu-evidence.ts +291 -0
  322. package/src/__tests__/auto-exposure-inspection.unit.test.ts +80 -0
  323. package/src/__tests__/auto-exposure-transaction.integration.test.ts +99 -0
  324. package/src/__tests__/auto-exposure.browser.test.ts +33 -0
  325. package/src/__tests__/auto-exposure.dawn.test.ts +33 -0
  326. package/src/__tests__/detached-inspection.integration.test.ts +5 -0
  327. package/src/__tests__/device-scope-lifecycle.unit.test.ts +18 -0
  328. package/src/__tests__/device-scope-stale-matrix.unit.test.ts +18 -0
  329. package/src/__tests__/docs-gate-green.unit.test.ts +3 -3
  330. package/src/__tests__/dynamic-geometry-host.unit.test.ts +1123 -0
  331. package/src/__tests__/dynamic-geometry.unit.test.ts +233 -0
  332. package/src/__tests__/factory-contract.integration.test.ts +73 -22
  333. package/src/__tests__/fallback-row-stride-surface.unit.test.ts +19 -0
  334. package/src/__tests__/feature-depth-input.dawn.test.ts +121 -0
  335. package/src/__tests__/feature-noise.unit.test.ts +38 -0
  336. package/src/__tests__/fixtures/taa-resolve-pinned-baseline.wgsl +301 -0
  337. package/src/__tests__/frame-camera-selection.unit.test.ts +131 -0
  338. package/src/__tests__/frame-plan-contract.unit.test.ts +24 -0
  339. package/src/__tests__/frame-targets.unit.test.ts +24 -0
  340. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +3 -0
  341. package/src/__tests__/gpu-driven-baseline.characterization.test.ts +79 -0
  342. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +287 -6
  343. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +122 -142
  344. package/src/__tests__/gpu-driven-indirect-raster.browser.test.ts +10 -1
  345. package/src/__tests__/gpu-driven-lod-cache.unit.test.ts +264 -0
  346. package/src/__tests__/gpu-driven-mesh-world-identity.unit.test.ts +349 -0
  347. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +1417 -0
  348. package/src/__tests__/gpu-driven-pbr.integration.test.ts +21 -0
  349. package/src/__tests__/gpu-driven-production-fixture.ts +96 -0
  350. package/src/__tests__/gpu-driven-production.integration.test.ts +1075 -93
  351. package/src/__tests__/gpu-driven-scaling.unit.test.ts +1 -3
  352. package/src/__tests__/gpu-driven-shadow-views.browser.test.ts +63 -0
  353. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +294 -0
  354. package/src/__tests__/gpu-driven-shadow-views.integration.test.ts +97 -0
  355. package/src/__tests__/gpu-driven-shadow-views.unit.test.ts +168 -0
  356. package/src/__tests__/gpu-driven-skin-contract.test-d.ts +11 -0
  357. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +72 -20
  358. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +30 -9
  359. package/src/__tests__/gpu-driven-view.unit.test.ts +159 -52
  360. package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -1
  361. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +42 -0
  362. package/src/__tests__/gpu-scene-render-graph-gpu.ts +19 -5
  363. package/src/__tests__/gpu-scene.dawn.test.ts +40 -13
  364. package/src/__tests__/gpu-scene.unit.test.ts +559 -33
  365. package/src/__tests__/instances-culling.integration.test.ts +36 -10
  366. package/src/__tests__/instances-derived-bounds.unit.test.ts +54 -0
  367. package/src/__tests__/instances-store.unit.test.ts +242 -39
  368. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +6 -0
  369. package/src/__tests__/lighting-scene-roundtrip.integration.test.ts +13 -16
  370. package/src/__tests__/lut-lkg-transaction.integration.test.ts +122 -0
  371. package/src/__tests__/material-contract-inventory.unit.test.ts +5 -6
  372. package/src/__tests__/material-dispatch-shader-id.unit.test.ts +51 -0
  373. package/src/__tests__/material-lane-selection.unit.test.ts +60 -0
  374. package/src/__tests__/material-numeric-upload.unit.test.ts +53 -0
  375. package/src/__tests__/material-texture-handles.unit.test.ts +18 -0
  376. package/src/__tests__/material-texture-source.unit.test.ts +87 -0
  377. package/src/__tests__/materials-authoring-validation.unit.test.ts +41 -0
  378. package/src/__tests__/materials-standard-contract.unit.test.ts +52 -2
  379. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +4 -0
  380. package/src/__tests__/mesh-submission-lifetime.unit.test.ts +53 -0
  381. package/src/__tests__/normal-fallback.dawn.test.ts +122 -0
  382. package/src/__tests__/particle-material-input-layout.unit.test.ts +104 -0
  383. package/src/__tests__/physical-clearcoat.integration.test.ts +37 -3
  384. package/src/__tests__/pipeline-texture-specialization.unit.test.ts +138 -0
  385. package/src/__tests__/point-shadow-inspection.unit.test.ts +2 -0
  386. package/src/__tests__/prepared-gpu-driven-pbr-contract.test-d.ts +31 -0
  387. package/src/__tests__/prepared-gpu-driven-pbr-contract.unit.test.ts +39 -0
  388. package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +35 -4
  389. package/src/__tests__/prepared-graphics-capability.unit.test.ts +21 -0
  390. package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +6 -2
  391. package/src/__tests__/profiler-phase-catalog.test.ts +5 -0
  392. package/src/__tests__/public-surface.test-d.ts +3 -0
  393. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +30 -12
  394. package/src/__tests__/reflection-fallback-async-publication.unit.test.ts +104 -0
  395. package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +2 -1
  396. package/src/__tests__/render-error-code-owner.test-d.ts +4 -0
  397. package/src/__tests__/render-error-detail-ssot.test-d.ts +22 -0
  398. package/src/__tests__/render-error-exhaustive.test-d.ts +15 -0
  399. package/src/__tests__/render-feature-gpu-work.integration.test.ts +285 -2
  400. package/src/__tests__/render-feature-plan.unit.test.ts +245 -0
  401. package/src/__tests__/render-feature-shadow-order.unit.test.ts +228 -0
  402. package/src/__tests__/render-feature-zero-work.unit.test.ts +35 -1
  403. package/src/__tests__/render-graph-fallback.integration.test.ts +2 -2
  404. package/src/__tests__/render-owner-cohesion.unit.test.ts +55 -0
  405. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +426 -0
  406. package/src/__tests__/render-scene-projection.unit.test.ts +914 -23
  407. package/src/__tests__/render-scene-resource-updates.integration.test.ts +214 -0
  408. package/src/__tests__/render-scene-skin-lifecycle.integration.test.ts +173 -0
  409. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +133 -0
  410. package/src/__tests__/render-target-material-source.test-d.ts +27 -3
  411. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +61 -1
  412. package/src/__tests__/renderer-frame-transaction.integration.test.ts +923 -5
  413. package/src/__tests__/shader-manifest-fixture.ts +39 -0
  414. package/src/__tests__/skin-motion-regression.unit.test.ts +0 -33
  415. package/src/__tests__/skin-palette-persistent.integration.test.ts +28 -0
  416. package/src/__tests__/skin-palette-persistent.unit.test.ts +247 -0
  417. package/src/__tests__/skinned-shadow-caster.test.ts +118 -14
  418. package/src/__tests__/specular-environment-scale.dawn.test.ts +156 -0
  419. package/src/__tests__/ssr-admission-matrix.integration.test.ts +7 -1
  420. package/src/__tests__/ssr-confidence-compose.unit.test.ts +84 -0
  421. package/src/__tests__/ssr-coordinate-oracle.unit.test.ts +28 -0
  422. package/src/__tests__/ssr-format-probe-gating.integration.test.ts +82 -0
  423. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +91 -0
  424. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +112 -0
  425. package/src/__tests__/ssr-gpu-dispatch.ts +946 -0
  426. package/src/__tests__/ssr-graph-topology.unit.test.ts +104 -0
  427. package/src/__tests__/ssr-history-filter.dawn.test.ts +198 -0
  428. package/src/__tests__/ssr-hit-color.dawn.test.ts +273 -0
  429. package/src/__tests__/ssr-hiz-odd-reduction.dawn.test.ts +569 -0
  430. package/src/__tests__/ssr-hiz-rescue.dawn.test.ts +279 -0
  431. package/src/__tests__/ssr-hiz.browser.test.ts +150 -0
  432. package/src/__tests__/ssr-hiz.dawn.test.ts +150 -0
  433. package/src/__tests__/ssr-hiz.unit.test.ts +56 -0
  434. package/src/__tests__/ssr-inspection.unit.test.ts +105 -0
  435. package/src/__tests__/ssr-memory-budget.unit.test.ts +45 -0
  436. package/src/__tests__/ssr-performance-sequence-aggregation.unit.test.ts +15 -0
  437. package/src/__tests__/ssr-public-surface.test-d.ts +37 -0
  438. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +387 -0
  439. package/src/__tests__/ssr-reflection-mip-reducer.dawn.test.ts +309 -0
  440. package/src/__tests__/ssr-reprojection-probe.ts +90 -0
  441. package/src/__tests__/ssr-roughness-mip.dawn.test.ts +163 -0
  442. package/src/__tests__/ssr-shader-prewarm.unit.test.ts +59 -0
  443. package/src/__tests__/ssr-spatial.integration.test.ts +141 -0
  444. package/src/__tests__/ssr-stable-lattice.dawn.test.ts +475 -0
  445. package/src/__tests__/ssr-temporal-history.unit.test.ts +202 -0
  446. package/src/__tests__/ssr-texel-crossing.dawn.test.ts +448 -0
  447. package/src/__tests__/ssr-zero-work.integration.test.ts +87 -0
  448. package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +44 -12
  449. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +29 -0
  450. package/src/__tests__/standard-output-chain-contract.unit.test.ts +99 -0
  451. package/src/__tests__/standard-output-chain.integration.test.ts +73 -0
  452. package/src/__tests__/standard-output-gpu-evidence.ts +205 -0
  453. package/src/__tests__/standard-output.browser.test.ts +15 -0
  454. package/src/__tests__/standard-output.dawn.test.ts +15 -0
  455. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +38 -0
  456. package/src/__tests__/standard-pipeline.integration.test.ts +320 -3
  457. package/src/__tests__/standard-profile-oracle.unit.test.ts +22 -0
  458. package/src/__tests__/standard-surface-lighting.unit.test.ts +41 -0
  459. package/src/__tests__/standard-texture-specialization.dawn.test.ts +141 -0
  460. package/src/__tests__/surface-adjacent-regressions.integration.test.ts +6 -3
  461. package/src/__tests__/taa-coverage-edge.dawn.test.ts +193 -0
  462. package/src/__tests__/taa-history-clipping.dawn.test.ts +328 -0
  463. package/src/__tests__/taa-neighborhood-equivalence.dawn.test.ts +778 -0
  464. package/src/__tests__/taa-stability-feedback.browser.test.ts +23 -0
  465. package/src/__tests__/taa-stability-feedback.dawn.test.ts +68 -0
  466. package/src/__tests__/taa-stability-feedback.ts +341 -0
  467. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +49 -7
  468. package/src/__tests__/temporal-reset-matrix.unit.test.ts +9 -0
  469. package/src/__tests__/temporal-transaction.integration.test.ts +28 -0
  470. package/src/__tests__/texture-usage-surface.unit.test.ts +4 -2
  471. package/src/__tests__/typed-pipeline-topology.unit.test.ts +109 -4
  472. package/src/__tests__/typed-scene-pass-material-cache.integration.test.ts +126 -0
  473. package/src/__tests__/vertex-layouts-ssot.unit.test.ts +47 -0
  474. package/src/__tests__/visibility-extract.perf.test.ts +20 -8
  475. package/src/__tests__/visibility-instances.integration.test.ts +19 -7
  476. package/src/__tests__/visibility-producer-matrix.integration.test.ts +20 -9
  477. package/src/assembly/atmosphere-shader-prewarm.ts +38 -0
  478. package/src/assembly/dynamic-geometry-host.ts +887 -0
  479. package/src/assembly/dynamic-geometry-runtime.ts +71 -0
  480. package/src/assembly/factory.ts +4 -0
  481. package/src/assembly/gpu-driven-owner.ts +29 -0
  482. package/src/assembly/host-contract.ts +36 -0
  483. package/src/assembly/material/assembly.ts +38 -0
  484. package/src/assembly/material-shader-policy.ts +71 -28
  485. package/src/assembly/recovery/failure-location.ts +62 -0
  486. package/src/assembly/recovery/renderer-recover.ts +19 -17
  487. package/src/assembly/renderer-facade.ts +29 -0
  488. package/src/assembly/renderer-feature-inspection.ts +13 -0
  489. package/src/assembly/renderer-frame-transaction.ts +63 -0
  490. package/src/assembly/renderer-helpers.ts +26 -0
  491. package/src/assembly/renderer-inspection.ts +6 -0
  492. package/src/assembly/shader-prewarm-policy.ts +32 -0
  493. package/src/assembly/skin-palette-owner.ts +21 -0
  494. package/src/assembly/ssr-shader-prewarm.ts +41 -0
  495. package/src/assembly/webgpu-device-loss.ts +75 -0
  496. package/src/assembly/webgpu-pbr-ready.ts +232 -0
  497. package/src/assembly/webgpu-ready-mipmap.ts +26 -0
  498. package/src/assembly/webgpu-ready.ts +142 -121
  499. package/src/assembly/webgpu-renderer-bootstrap.ts +85 -0
  500. package/src/assembly/webgpu-renderer-contract.ts +69 -0
  501. package/src/assembly/webgpu-renderer-guards.ts +32 -0
  502. package/src/assembly/webgpu-renderer-observation.ts +43 -0
  503. package/src/assembly/webgpu-renderer-recovery-failure.ts +62 -0
  504. package/src/assembly/webgpu-renderer.ts +675 -614
  505. package/src/assembly/webgpu-vertex-layouts.ts +233 -87
  506. package/src/components/__tests__/camera-exposure.contract.unit.test.ts +153 -0
  507. package/src/components/camera.ts +287 -7
  508. package/src/components/index.ts +1 -0
  509. package/src/components/instances.ts +45 -18
  510. package/src/components/scene-instance.ts +2 -1
  511. package/src/components/screen-space-reflection.ts +21 -0
  512. package/src/components/sprite-animation.ts +3 -3
  513. package/src/components/sprite-instances.ts +1 -1
  514. package/src/device/gpu-residency.ts +96 -93
  515. package/src/device/mesh-residency-lifetime.ts +73 -0
  516. package/src/dynamic-geometry.ts +736 -0
  517. package/src/environment/background.ts +263 -0
  518. package/src/errors/gpu-driven.ts +39 -5
  519. package/src/errors/render.ts +27 -3
  520. package/src/extract/camera.ts +26 -1
  521. package/src/extract/gpu-driven.ts +185 -10
  522. package/src/features/host.ts +237 -19
  523. package/src/features/noise-texture.ts +91 -0
  524. package/src/features/plan.ts +553 -24
  525. package/src/features/prepared-gpu-work.ts +631 -49
  526. package/src/features/prepared-graphics-store.ts +31 -0
  527. package/src/features/prepared-graphics.ts +5 -0
  528. package/src/features/render-graph-compute.ts +41 -8
  529. package/src/features/render-graph-contribution.ts +141 -3
  530. package/src/features/render-graph-raster.ts +143 -30
  531. package/src/features/types.ts +11 -0
  532. package/src/fullscreen-post-process-pass.ts +3 -0
  533. package/src/gpu-driven/batch-topology.ts +424 -102
  534. package/src/gpu-driven/pbr-program.ts +31 -0
  535. package/src/gpu-driven/prepared-draw.ts +29 -4
  536. package/src/gpu-driven/production-raster.ts +2267 -694
  537. package/src/gpu-driven/shadow-views.ts +539 -0
  538. package/src/gpu-driven/view-gpu.ts +188 -41
  539. package/src/gpu-scene-schema.ts +52 -11
  540. package/src/gpu-scene.ts +186 -99
  541. package/src/gpu-texture-usage.ts +1 -0
  542. package/src/hdrp-buffers.ts +72 -36
  543. package/src/ibl/frame-resources.ts +38 -0
  544. package/src/ibl/skylight-bind-group.ts +5 -4
  545. package/src/index.ts +125 -1
  546. package/src/inspection-types.ts +191 -0
  547. package/src/instances-derived-bounds.ts +258 -34
  548. package/src/instances.ts +459 -150
  549. package/src/internal.ts +22 -0
  550. package/src/lifecycle.ts +2 -0
  551. package/src/material-row.ts +145 -0
  552. package/src/materials.ts +44 -8
  553. package/src/pbr-pipeline.ts +159 -17
  554. package/src/pipeline/standard-forward-lane.ts +52 -24
  555. package/src/pipeline/standard-output/__tests__/lut-admission.unit.test.ts +103 -0
  556. package/src/pipeline/standard-output/auto-exposure/__tests__/capability.unit.test.ts +40 -0
  557. package/src/pipeline/standard-output/auto-exposure/__tests__/gpu.contract.unit.test.ts +125 -0
  558. package/src/pipeline/standard-output/auto-exposure/__tests__/graph.contract.unit.test.ts +94 -0
  559. package/src/pipeline/standard-output/auto-exposure/__tests__/oracle.test.ts +108 -0
  560. package/src/pipeline/standard-output/auto-exposure/__tests__/preset.test.ts +26 -0
  561. package/src/pipeline/standard-output/auto-exposure/capability.ts +38 -0
  562. package/src/pipeline/standard-output/auto-exposure/gpu.ts +567 -0
  563. package/src/pipeline/standard-output/auto-exposure/graph.ts +221 -0
  564. package/src/pipeline/standard-output/auto-exposure/inspection.ts +231 -0
  565. package/src/pipeline/standard-output/auto-exposure/oracle.ts +291 -0
  566. package/src/pipeline/standard-output/auto-exposure/preset.ts +28 -0
  567. package/src/pipeline/standard-output/auto-exposure/state.ts +156 -0
  568. package/src/pipeline/standard-output/color-transform.ts +124 -0
  569. package/src/pipeline/standard-output/graph.ts +139 -0
  570. package/src/pipeline/standard-output/lut-admission.ts +121 -0
  571. package/src/pipeline/standard-output/lut-gpu.ts +399 -0
  572. package/src/pipeline/standard-output/lut-state.ts +176 -0
  573. package/src/pipeline/standard-output/resources.ts +121 -0
  574. package/src/pipeline/standard-output/types.ts +58 -0
  575. package/src/pipeline/standard-pipeline.ts +192 -59
  576. package/src/pipeline/standard-post.ts +186 -27
  577. package/src/pipeline-builder.ts +16 -6
  578. package/src/pipeline-spec-types.ts +4 -0
  579. package/src/pipeline-spec.ts +37 -29
  580. package/src/points-lines/standard-owner.ts +6 -14
  581. package/src/prepare/prepared-graphics-resolver.ts +9 -2
  582. package/src/record/__tests__/material-slot-plan.unit.test.ts +48 -0
  583. package/src/record/__tests__/mesh-ssbo.unit.test.ts +40 -1
  584. package/src/record/__tests__/recovery-pipeline.unit.test.ts +2 -29
  585. package/src/record/__tests__/sprite-material-abi.unit.test.ts +36 -5
  586. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +45 -0
  587. package/src/record/__tests__/view-ubo-layout.unit.test.ts +5 -0
  588. package/src/record/dynamic-geometry-consumption.ts +59 -0
  589. package/src/record/frame-lighting.ts +12 -11
  590. package/src/record/frame-snapshot.ts +133 -23
  591. package/src/record/frame-targets.ts +9 -0
  592. package/src/record/frame.ts +727 -133
  593. package/src/record/main-pass-geometry.ts +162 -98
  594. package/src/record/main-pass-material.ts +115 -26
  595. package/src/record/main-pass-sprite-draws.ts +18 -107
  596. package/src/record/main-pass.ts +78 -8
  597. package/src/record/material-uniforms.ts +1 -1
  598. package/src/record/mesh-ssbo.ts +59 -15
  599. package/src/record/prepared-material-bindings.ts +234 -0
  600. package/src/record/recovery-pipeline.ts +59 -136
  601. package/src/record/render-context.ts +92 -22
  602. package/src/record/shadow-pass.ts +1231 -209
  603. package/src/record/skybox-post-pass.ts +14 -3
  604. package/src/record/typed-frame-graph.ts +1006 -53
  605. package/src/record/view-ubo.ts +11 -0
  606. package/src/recovery/render-system-candidate.ts +90 -66
  607. package/src/recovery/render-system-roots.ts +113 -0
  608. package/src/recovery/types.ts +77 -0
  609. package/src/reflection/record-owner.ts +26 -54
  610. package/src/render-contract.ts +219 -25
  611. package/src/render-graph-primitives.ts +6 -2
  612. package/src/render-pipeline.ts +70 -1
  613. package/src/render-system-extract-tail.ts +409 -160
  614. package/src/render-system-extract.ts +376 -102
  615. package/src/render-system-projections.ts +241 -0
  616. package/src/render-system.ts +692 -791
  617. package/src/scene/render-scene-types.ts +13 -4
  618. package/src/scene/render-scene.ts +569 -355
  619. package/src/scene/shadow-visibility.ts +21 -0
  620. package/src/ssr/admission.ts +380 -14
  621. package/src/ssr/compose.ts +144 -0
  622. package/src/ssr/errors.ts +48 -0
  623. package/src/ssr/graph.ts +777 -0
  624. package/src/ssr/history.ts +436 -0
  625. package/src/ssr/hiz.ts +124 -0
  626. package/src/ssr/inspection.ts +124 -0
  627. package/src/ssr/resources.ts +202 -0
  628. package/src/ssr/temporal.ts +164 -0
  629. package/src/systems/skin-palette-allocator.ts +495 -148
  630. package/src/systems/skin-palette-types.ts +17 -0
  631. package/src/systems/transparent-dispatch.ts +90 -0
  632. package/src/targets/material-source.ts +34 -0
  633. package/src/temporal/coverage.ts +1 -1
  634. package/src/temporal/frame-coordinator.ts +23 -2
  635. package/src/temporal/gpu.ts +74 -12
  636. package/src/temporal/history.ts +3 -1
  637. package/src/temporal/inspection.ts +2 -1
  638. package/src/temporal/standard-scene-data.ts +3 -1
  639. package/src/temporal/temporal-view.ts +3 -0
  640. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +204 -139
  641. package/src/typed-render-graph-primitives.ts +266 -74
  642. package/src/typed-shadow-passes.ts +122 -12
  643. package/src/volume/temporal.ts +10 -0
  644. package/dist/chunk-ADHHVYLW.mjs.map +0 -1
  645. package/dist/chunk-FJ6P52EE.mjs.map +0 -1
  646. package/dist/chunk-GE3SDD72.mjs.map +0 -1
  647. package/dist/chunk-GF523LHF.mjs.map +0 -1
  648. package/dist/chunk-HKXTW355.mjs.map +0 -1
  649. package/dist/chunk-JDWARUOI.mjs.map +0 -1
  650. package/dist/chunk-KM2NOX2I.mjs.map +0 -1
  651. package/dist/chunk-TMIASV2N.mjs.map +0 -1
  652. package/dist/chunk-XDP6XE5V.mjs.map +0 -1
  653. package/dist/chunk-ZZ4YQ474.mjs.map +0 -1
  654. package/src/__tests__/instances-world-ownership.integration.test.ts +0 -62
  655. package/src/scene/__tests__/changed-block-summary.candidate.test.ts +0 -36
@@ -1,5 +1,6 @@
1
1
  import { mat3 } from '@forgeax/engine-math';
2
2
  import { type BindGroup, type Buffer, RhiError, type RhiQueue } from '@forgeax/engine-rhi';
3
+ import { ok, type Result } from '@forgeax/engine-types';
3
4
  import type { DispatchEntry } from '../render-system-extract';
4
5
  import {
5
6
  TRANSPARENT_SORT_MODE_LAYER_Y,
@@ -127,6 +128,42 @@ export function getOrCreateFromChain(
127
128
  return bg;
128
129
  }
129
130
 
131
+ /**
132
+ * Result-preserving sibling of `getOrCreateFromChain`. RHI creation can fail
133
+ * transiently during recovery or capability probing; a failed attempt must
134
+ * not enter the cache and must remain a structured Result for the caller.
135
+ */
136
+ export function getOrCreateFromChainResult<E>(
137
+ root: WeakMap<object, unknown>,
138
+ handles: readonly object[],
139
+ variant: string,
140
+ factory: () => Result<BindGroup, E>,
141
+ counts: { createBindGroup: number; keys: string[] },
142
+ ): Result<BindGroup, E> {
143
+ let node = root;
144
+ for (const h of handles) {
145
+ let next = node.get(h) as WeakMap<object, unknown> | undefined;
146
+ if (next === undefined) {
147
+ next = new WeakMap();
148
+ node.set(h, next);
149
+ }
150
+ node = next;
151
+ }
152
+ let leaf = node.get(BIND_GROUP_CHAIN_LEAF_KEY) as Map<string, BindGroup> | undefined;
153
+ if (leaf === undefined) {
154
+ leaf = new Map();
155
+ node.set(BIND_GROUP_CHAIN_LEAF_KEY, leaf);
156
+ }
157
+ const hit = leaf.get(variant);
158
+ if (hit !== undefined) return ok(hit);
159
+ const created = factory();
160
+ if (!created.ok) return created;
161
+ counts.createBindGroup += 1;
162
+ counts.keys.push(variant);
163
+ leaf.set(variant, created.value);
164
+ return created;
165
+ }
166
+
130
167
  /**
131
168
  * Read a cached bind group using the same variable-depth chain contract as
132
169
  * `getOrCreateFromChain`. Readers must traverse the terminal marker instead
@@ -376,6 +413,7 @@ export function uploadMeshSsboBatch(
376
413
  meshStorageBuffer: { readonly buffer: Buffer },
377
414
  validatedOrdered: readonly ValidatedRenderable[],
378
415
  foldDispatchPlan: FoldDispatchPlan | null,
416
+ startSlot = 0,
379
417
  ): void {
380
418
  const slotCount = validatedOrdered.length;
381
419
  const neededBytes = slotCount * MESH_PER_ENTITY_STRIDE;
@@ -450,7 +488,7 @@ export function uploadMeshSsboBatch(
450
488
  if (neededBytes > 0) {
451
489
  const meshUpload = queue.writeBuffer(
452
490
  meshStorageBuffer.buffer,
453
- 0,
491
+ startSlot * MESH_PER_ENTITY_STRIDE,
454
492
  _meshSsboScratch,
455
493
  0,
456
494
  neededBytes,
@@ -511,17 +549,26 @@ export interface FoldBucket {
511
549
  * minimal shape. The gate read inside the helper uses `=== true` /
512
550
  * `!== true` so both `false` and `undefined` enter the singleton branch.
513
551
  *
514
- * feat-20260625-refactor-sprite-as-transparent-mesh R2 fix-up: gate
515
- * migrated from `shadingModel === 'sprite'` (the union member was
516
- * removed in M3 / w15) to `transparent === true` (the new SSOT for
517
- * "routes through the LDR split sub-pass" same predicate the
518
- * `splitLdrSprite` filter at render-system-record.ts:4826/5612 uses).
552
+ * feat-20260625-refactor-sprite-as-transparent-mesh R2 fix-up: the
553
+ * transparent flag identifies the LDR split sub-pass, while the shader id
554
+ * identifies the sprite owner that is safe to fold. Standard PBR Alpha Blend
555
+ * remains singleton so its geometry pass keeps one projection row per draw.
519
556
  */
520
557
  export interface FoldRenderableLike {
521
558
  readonly transform: { readonly world: Float32Array };
522
559
  readonly material: { readonly transparent?: boolean | undefined };
523
560
  }
524
561
 
562
+ const FOLDABLE_TRANSPARENT_SHADER_IDS = new Set(['forgeax::sprite', 'forgeax::sprite-lit']);
563
+
564
+ function isFoldEligible(entry: DispatchEntry, renderables: readonly FoldRenderableLike[]): boolean {
565
+ return (
566
+ renderables[entry.renderableIndex]?.material.transparent === true &&
567
+ entry.materialShaderId !== undefined &&
568
+ FOLDABLE_TRANSPARENT_SHADER_IDS.has(entry.materialShaderId)
569
+ );
570
+ }
571
+
525
572
  /**
526
573
  * Linear-scan fold operator (plan-strategy D-1).
527
574
  *
@@ -588,7 +635,7 @@ export function foldDispatchBuckets(
588
635
  // identity and renders the 3D geometry at the origin — collapsing the
589
636
  // frame to black (hello-room CI regression).
590
637
  //
591
- // Concept-count fix: encode "fold is transparent-sub-pass-only" at the
638
+ // Concept-count fix: encode "fold is transparent-sprite-sub-pass-only" at the
592
639
  // head selection point — the gate is the single bucket-key invariant
593
640
  // that makes both dispatch sites correct without coupling identity-
594
641
  // overwrite logic to a separate check (avoiding the D-9 shared-exit
@@ -603,10 +650,9 @@ export function foldDispatchBuckets(
603
650
  //
604
651
  // feat-20260625 R2 fix-up: pre-feat the gate was `shadingModel ===
605
652
  // 'sprite'`; M3 / w15 narrowed the shadingModel union to
606
- // `'unlit' | undefined` (the `'sprite'` discriminator was the design
607
- // ablation target), so the gate now reads `material.transparent`
608
- // the new SSOT for "routes through the LDR split sub-pass" mirrored
609
- // on `computeSplitLdrSprite` + the `splitLdrSprite` skip filter.
653
+ // `'unlit' | undefined`. The current gate retains the transparent SSOT
654
+ // and adds the explicit sprite shader identity so Standard PBR Alpha Blend
655
+ // cannot enter this fold path.
610
656
  const buckets: FoldBucket[] = [];
611
657
  let runStart = 0;
612
658
  while (runStart < orderedEntries.length) {
@@ -621,8 +667,7 @@ export function foldDispatchBuckets(
621
667
  // carrier (extract stage derives it from the first pass's
622
668
  // `renderState.blend !== undefined`, post-feat-20260626-collapse;
623
669
  // see `MaterialSnapshot.transparent`).
624
- const headTransparent = renderables[head.renderableIndex]?.material.transparent;
625
- if (headTransparent !== true) {
670
+ if (!isFoldEligible(head, renderables)) {
626
671
  buckets.push(makeSingletonBucket(head, renderables, mode));
627
672
  runStart += 1;
628
673
  continue;
@@ -638,8 +683,7 @@ export function foldDispatchBuckets(
638
683
  // Same materialHandle implies same transparent flag in production
639
684
  // (material asset identity), but the check costs O(1) per cand and
640
685
  // makes the bucket invariant locally readable.
641
- const candTransparent = renderables[cand.renderableIndex]?.material.transparent;
642
- if (candTransparent !== true) break;
686
+ if (!isFoldEligible(cand, renderables)) break;
643
687
  const candSortKey = readSortKey(mode, cand.renderableIndex, renderables);
644
688
  if (candSortKey !== headSortKey) break;
645
689
  runEnd += 1;
@@ -0,0 +1,234 @@
1
+ import { resolveAssetHandle } from '@forgeax/engine-assets-runtime';
2
+ import type { World } from '@forgeax/engine-ecs';
3
+ import type { BindGroupEntry, BindGroupLayout, Buffer } from '@forgeax/engine-rhi';
4
+ import { err, ok } from '@forgeax/engine-rhi';
5
+ import {
6
+ derive,
7
+ type Handle,
8
+ type MaterialAsset,
9
+ type MaterialTextureValue,
10
+ materialValuesToLinearRuntime,
11
+ type SamplerAsset,
12
+ } from '@forgeax/engine-types';
13
+ import { GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_UNIFORM } from '../gpu-usage';
14
+ import type { SkylightBindGroupResources } from '../ibl/skylight-bind-group';
15
+ import { assembleMaterialWithSkylightEntries } from '../ibl/skylight-bind-group';
16
+ import {
17
+ applyParamSchemaDefaultsToUbo,
18
+ applyParamSnapshotToUbo,
19
+ defaultViewForUserRegionField,
20
+ residentTextureView,
21
+ } from './main-pass-material';
22
+ import type { RenderSystemInternals } from './render-context';
23
+
24
+ export type PreparedResolverCaches = {
25
+ readonly preparedPipelineIds: WeakMap<object, string>;
26
+ readonly preparedMaterialPipelineShaders: WeakMap<object, string>;
27
+ readonly preparedGroup0Pipelines: WeakSet<object>;
28
+ readonly preparedViewOnlyPipelines: WeakSet<object>;
29
+ readonly preparedRenderMaterialPipelines: WeakSet<object>;
30
+ readonly preparedAssetHandles: WeakMap<World, Map<string, number>>;
31
+ };
32
+
33
+ export function createPreparedResolverCaches(): PreparedResolverCaches {
34
+ return {
35
+ preparedPipelineIds: new WeakMap(),
36
+ preparedMaterialPipelineShaders: new WeakMap(),
37
+ preparedGroup0Pipelines: new WeakSet(),
38
+ preparedViewOnlyPipelines: new WeakSet(),
39
+ preparedRenderMaterialPipelines: new WeakSet(),
40
+ preparedAssetHandles: new WeakMap(),
41
+ };
42
+ }
43
+
44
+ function preparedHandle<Brand extends string>(
45
+ runtime: RenderSystemInternals,
46
+ caches: PreparedResolverCaches,
47
+ world: World,
48
+ guid: string,
49
+ brand: Brand,
50
+ ): Handle<Brand, 'shared'> | undefined {
51
+ let handles = caches.preparedAssetHandles.get(world);
52
+ if (handles === undefined) {
53
+ handles = new Map();
54
+ caches.preparedAssetHandles.set(world, handles);
55
+ }
56
+ const key = `${brand}:${guid.toLowerCase()}`;
57
+ const cached = handles.get(key);
58
+ if (cached !== undefined) return cached as Handle<Brand, 'shared'>;
59
+ const asset = runtime.assets.lookup(guid);
60
+ if (asset === undefined) return undefined;
61
+ const handle = world.allocSharedRef(brand, asset);
62
+ handles.set(key, handle as number);
63
+ return handle;
64
+ }
65
+
66
+ export function preparedMaterialBindings(
67
+ runtime: RenderSystemInternals,
68
+ caches: PreparedResolverCaches,
69
+ worlds: readonly World[],
70
+ materialShaderId: string,
71
+ worldIndex: number,
72
+ materialGuid: string,
73
+ layout: BindGroupLayout,
74
+ skylightResources?: SkylightBindGroupResources,
75
+ ) {
76
+ const world = worlds[worldIndex];
77
+ const material = runtime.assets.lookup(materialGuid) as MaterialAsset | undefined;
78
+ const pipelineState = runtime.getPipelineState();
79
+ if (world === undefined || material?.kind !== 'material' || pipelineState === null) {
80
+ return err(new Error('prepared material asset is unavailable'));
81
+ }
82
+ const schema = runtime.getParamSchema?.(materialShaderId) ?? [];
83
+ // Feature materials share the ordinary linear parameter domain and semantic texture defaults.
84
+ const values = materialValuesToLinearRuntime(
85
+ material.values,
86
+ [...schema, ...(material.parameters ?? [])],
87
+ material.colorSpace,
88
+ );
89
+ const derived = derive(schema);
90
+ const fields = [...derived.textureFieldNames];
91
+ let buffer: Buffer | undefined;
92
+ let payloadByteLength = 0;
93
+ if (derived.uboLayout.totalBytes > 0) {
94
+ const payload = new Uint8Array(Math.max(16, derived.uboLayout.totalBytes));
95
+ applyParamSchemaDefaultsToUbo(payload, schema);
96
+ applyParamSnapshotToUbo(
97
+ payload,
98
+ schema,
99
+ values as Readonly<Record<string, number | readonly number[]>>,
100
+ );
101
+ const created = runtime.device.createBuffer({
102
+ label: `prepared-material:${materialGuid}`,
103
+ size: payload.byteLength,
104
+ usage: GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST,
105
+ });
106
+ if (!created.ok) return created;
107
+ buffer = created.value;
108
+ payloadByteLength = payload.byteLength;
109
+ const written = runtime.device.queue.writeBuffer(buffer, 0, payload);
110
+ if (!written.ok) {
111
+ runtime.device.destroyBuffer(buffer);
112
+ return written;
113
+ }
114
+ }
115
+ const textureResources: Array<{
116
+ sampler: import('@forgeax/engine-rhi').Sampler;
117
+ view: import('@forgeax/engine-rhi').TextureView;
118
+ }> = [];
119
+ for (const field of fields) {
120
+ if (field === undefined) continue;
121
+ const value = values[field];
122
+ const textureValue =
123
+ typeof value === 'object' && value !== null && 'texture' in value
124
+ ? (value as MaterialTextureValue)
125
+ : undefined;
126
+ let sampler = pipelineState.defaultSampler;
127
+ if (textureValue?.sampler !== undefined) {
128
+ const handle = preparedHandle(
129
+ runtime,
130
+ caches,
131
+ world,
132
+ String(textureValue.sampler),
133
+ 'SamplerAsset',
134
+ );
135
+ if (handle !== undefined) {
136
+ const asset = resolveAssetHandle<SamplerAsset>(world, handle);
137
+ if (asset.ok) {
138
+ const resident = runtime.gpuStore.ensureSamplerResident(handle, asset.value, world);
139
+ if (resident.ok) sampler = resident.value;
140
+ }
141
+ }
142
+ }
143
+ let view = defaultViewForUserRegionField(field, pipelineState, schema);
144
+ if (textureValue !== undefined) {
145
+ const handle = preparedHandle(
146
+ runtime,
147
+ caches,
148
+ world,
149
+ String(textureValue.texture),
150
+ 'TextureAsset',
151
+ );
152
+ if (handle !== undefined) {
153
+ view = residentTextureView(world, runtime.gpuStore, runtime, handle) ?? view;
154
+ }
155
+ }
156
+ textureResources.push({ sampler, view });
157
+ }
158
+ const entries: BindGroupEntry[] = [];
159
+ let textureIndex = 0;
160
+ for (let index = 0; index < derived.bglEntries.length; index += 1) {
161
+ const expected = derived.bglEntries[index];
162
+ if (expected?.buffer?.type === 'uniform' && buffer !== undefined) {
163
+ entries.push({
164
+ binding: expected.binding,
165
+ resource: { kind: 'buffer', value: { buffer, size: payloadByteLength } },
166
+ });
167
+ continue;
168
+ }
169
+ const textureResource = textureResources[textureIndex];
170
+ if (
171
+ expected?.sampler?.type === 'filtering' &&
172
+ derived.bglEntries[index + 1]?.texture !== undefined &&
173
+ textureResource !== undefined
174
+ ) {
175
+ entries.push({
176
+ binding: expected.binding,
177
+ resource: { kind: 'sampler', value: textureResource.sampler },
178
+ });
179
+ continue;
180
+ }
181
+ if (expected?.texture !== undefined && textureResource !== undefined) {
182
+ entries.push({
183
+ binding: expected.binding,
184
+ resource: { kind: 'textureView', value: textureResource.view },
185
+ });
186
+ textureIndex += 1;
187
+ continue;
188
+ }
189
+ if (buffer !== undefined) runtime.device.destroyBuffer(buffer);
190
+ return err(new Error('prepared material schema contains unsupported binding kinds'));
191
+ }
192
+ const fallback = pipelineState.skylightFallback;
193
+ if (fallback === null) {
194
+ if (buffer !== undefined) runtime.device.destroyBuffer(buffer);
195
+ return err(new Error('prepared material skylight fallback is unavailable'));
196
+ }
197
+ const completeEntries = assembleMaterialWithSkylightEntries(
198
+ entries,
199
+ skylightResources ?? {
200
+ irradianceView: fallback.irradianceView,
201
+ irradianceSampler: fallback.sampler,
202
+ prefilterView: fallback.prefilterView,
203
+ prefilterSampler: fallback.sampler,
204
+ brdfLutView: fallback.brdfLutView,
205
+ brdfLutSampler: fallback.sampler,
206
+ intensityBuffer: fallback.intensityBuffer,
207
+ },
208
+ );
209
+ // Per-shader PBR layouts reserve the scene-material SSBO at binding 46 on
210
+ // storage-capable devices. Prepared feature materials use this same layout,
211
+ // so they must provide the neutral producer-owned table even when their
212
+ // authored shader does not read it. Omitting the entry makes Dawn reject the
213
+ // bind group before submission.
214
+ if (runtime.device.caps.storageBuffer) {
215
+ completeEntries.push({
216
+ binding: 46,
217
+ resource: {
218
+ kind: 'buffer',
219
+ value: { buffer: pipelineState.meshStorageBuffer.buffer },
220
+ },
221
+ });
222
+ }
223
+ const group = runtime.device.createBindGroup({ layout, entries: completeEntries });
224
+ if (!group.ok) {
225
+ if (buffer !== undefined) runtime.device.destroyBuffer(buffer);
226
+ return group;
227
+ }
228
+ if (buffer === undefined) return group;
229
+ return ok({
230
+ handle: group.value,
231
+ dynamicOffsets: [0],
232
+ release: () => runtime.device.destroyBuffer(buffer),
233
+ });
234
+ }
@@ -1,13 +1,9 @@
1
1
  import {
2
+ DEFAULT_VERTEX_ATTRIBUTE_MAP,
2
3
  deriveVertexLayoutProjection,
3
4
  type VertexLayoutProjection,
4
5
  } from '@forgeax/engine-geometry';
5
- import type {
6
- MaterialRenderState,
7
- PassKind,
8
- PrimitiveTopology,
9
- VertexAttributeMap,
10
- } from '@forgeax/engine-types';
6
+ import type { MaterialRenderState, PassKind, PrimitiveTopology } from '@forgeax/engine-types';
11
7
  import { SPRITE_PREMULTIPLIED_ALPHA_BLEND } from '../materials';
12
8
  import {
13
9
  isStandardPbrMaterialShader,
@@ -35,60 +31,13 @@ import { geometryRenderStateForTopology } from './main-pass-material';
35
31
  import type {
36
32
  MaterialShaderPipelineEntry,
37
33
  PipelineState,
38
- RecoveryColdWorkGuard,
39
34
  RenderSystemInternals,
40
35
  } from './render-context';
41
36
 
42
37
  export interface RecoveryPipelineReadiness {
43
38
  readonly pipelineSpecs: readonly PipelineSpec[];
44
39
  /** Re-resolve every candidate request and assert a stable cache hit. */
45
- readonly assertFirstRecoveryFrame: () => void;
46
- }
47
-
48
- /**
49
- * Create the one-shot assertion used by the first frame after publication.
50
- * Recording a miss is a failure at the owner seam; the draw path never gets a
51
- * chance to submit a frame that hides a shader/pipeline or static-residency
52
- * cold build behind an apparently successful receipt.
53
- */
54
- export function createRecoveryColdWorkGuard(): RecoveryColdWorkGuard {
55
- let armed = false;
56
- let finished = false;
57
- let pipelineColdWork = 0;
58
- let uploadColdWork = 0;
59
- const fail = (kind: 'pipeline' | 'upload'): never => {
60
- if (kind === 'pipeline') pipelineColdWork += 1;
61
- else uploadColdWork += 1;
62
- throw new Error(
63
- `recovery first frame performed cold ${kind} work ` +
64
- `(pipeline=${pipelineColdWork}, upload=${uploadColdWork})`,
65
- );
66
- };
67
- return {
68
- arm(): void {
69
- armed = true;
70
- finished = false;
71
- pipelineColdWork = 0;
72
- uploadColdWork = 0;
73
- },
74
- notePipelineColdWork(): void {
75
- if (armed && !finished) fail('pipeline');
76
- },
77
- noteUploadColdWork(): void {
78
- if (armed && !finished) fail('upload');
79
- },
80
- finish(): void {
81
- if (!armed || finished) return;
82
- finished = true;
83
- armed = false;
84
- if (pipelineColdWork !== 0 || uploadColdWork !== 0) {
85
- throw new Error(
86
- `recovery first frame cold-work assertion failed ` +
87
- `(pipeline=${pipelineColdWork}, upload=${uploadColdWork})`,
88
- );
89
- }
90
- },
91
- };
40
+ readonly assertPreparedCache: () => void;
92
41
  }
93
42
 
94
43
  interface RecoveryPipelineRequest {
@@ -96,13 +45,6 @@ interface RecoveryPipelineRequest {
96
45
  readonly resolve: () => MaterialShaderPipelineEntry | null;
97
46
  }
98
47
 
99
- const DEFAULT_VERTEX_ATTRIBUTES: VertexAttributeMap = {
100
- position: new Float32Array(0),
101
- normal: new Float32Array(0),
102
- uv: new Float32Array(0),
103
- tangent: new Float32Array(0),
104
- };
105
-
106
48
  function optionalRenderState(
107
49
  state: MaterialRenderState | undefined,
108
50
  ): { readonly renderState: MaterialRenderState } | Record<string, never> {
@@ -174,6 +116,9 @@ function addRequest(input: {
174
116
  readonly additionalColorFormats?: readonly GPUTextureFormat[];
175
117
  readonly depthFormatOverride?: GPUTextureFormat | null;
176
118
  readonly vertexLayoutProjection?: VertexLayoutProjection;
119
+ readonly vertexEntry?: string;
120
+ readonly fragmentEntry?: string;
121
+ readonly layoutKindOverride?: 'pbr' | 'pbr-skin';
177
122
  readonly preserveUndefinedVariant?: boolean;
178
123
  readonly variantAlreadyResolved?: boolean;
179
124
  }): void {
@@ -204,6 +149,8 @@ function addRequest(input: {
204
149
  id: input.materialShaderId,
205
150
  passKind,
206
151
  variantSet: resolvedVariantSet,
152
+ ...(input.vertexEntry === undefined ? {} : { vertexEntry: input.vertexEntry }),
153
+ ...(input.fragmentEntry === undefined ? {} : { fragmentEntry: input.fragmentEntry }),
207
154
  }),
208
155
  attachments: Object.freeze({
209
156
  colorFormats: Object.freeze([...colorFormats]),
@@ -213,7 +160,7 @@ function addRequest(input: {
213
160
  geometry: Object.freeze({
214
161
  topology: input.topology ?? 'triangle-list',
215
162
  stripIndexFormat: input.indexFormat,
216
- vertexLayout: DEFAULT_VERTEX_ATTRIBUTES,
163
+ vertexLayout: DEFAULT_VERTEX_ATTRIBUTE_MAP,
217
164
  ...(projection === undefined ? {} : { vertexLayoutProjection: projection }),
218
165
  ...(shaderUvSetCount !== undefined && shaderUvSetCount > 1
219
166
  ? {
@@ -243,8 +190,11 @@ function addRequest(input: {
243
190
  undefined,
244
191
  projection,
245
192
  undefined,
193
+ input.layoutKindOverride,
246
194
  undefined,
247
195
  input.additionalColorFormats,
196
+ input.vertexEntry,
197
+ input.fragmentEntry,
248
198
  ) ?? null;
249
199
  input.requests.push({ spec, resolve });
250
200
  }
@@ -261,12 +211,7 @@ function addStandardMaterialRequests(input: {
261
211
  readonly colorFormatOverride?: GPUTextureFormat;
262
212
  readonly reflectionFallbackAvailable: boolean;
263
213
  }): void {
264
- const pointsLinesProjection = deriveVertexLayoutProjection({
265
- position: new Float32Array(0),
266
- normal: new Float32Array(0),
267
- uv: new Float32Array(0),
268
- tangent: new Float32Array(0),
269
- });
214
+ const pointsLinesProjection = deriveVertexLayoutProjection(DEFAULT_VERTEX_ATTRIBUTE_MAP);
270
215
  for (const entry of input.validated) {
271
216
  if (entry.source.pointsLines !== undefined) {
272
217
  const pointsLinesMaterial = entry.source.material;
@@ -299,7 +244,7 @@ function addStandardMaterialRequests(input: {
299
244
  // The probe record is an object-level ABI extension of the built-in
300
245
  // Standard PBR family. Recovery must request the same variant that the
301
246
  // live record path will select, otherwise the first post-recovery draw
302
- // discovers a cold PSO and the cold-work guard correctly rejects it.
247
+ // discovers avoidable cold PSO work.
303
248
  const probeBlendRecordAvailable =
304
249
  input.internals.device.caps.storageBuffer && entry.source.probeBlendRecord !== undefined;
305
250
  const standardPbrCapabilityVariantSet = standardTopologyVariantSet(
@@ -376,9 +321,7 @@ function addStandardMaterialRequests(input: {
376
321
  : undefined
377
322
  : entry.variantSet === undefined
378
323
  ? materialCapabilityVariantSet
379
- : materialCapabilityVariantSet === ''
380
- ? entry.variantSet
381
- : `${materialCapabilityVariantSet}+${entry.variantSet}`;
324
+ : `${materialCapabilityVariantSet}+${entry.variantSet}`;
382
325
  const reflectionFallbackVariant =
383
326
  input.reflectionFallbackAvailable && materialShaderId === 'forgeax::default-standard-pbr'
384
327
  ? (() => {
@@ -527,80 +470,60 @@ function addShadowRequests(input: {
527
470
  readonly validated: readonly ValidatedRenderable[];
528
471
  readonly dispatch: readonly DispatchEntry[];
529
472
  }): void {
530
- addRequest({
531
- requests: input.requests,
532
- requestKeys: input.requestKeys,
533
- internals: input.internals,
534
- pipelineState: input.pipelineState,
535
- materialShaderId: SHADOW_CASTER_SHADER_ID,
536
- isHdrTarget: false,
537
- topology: 'triangle-list',
538
- variantSet: shadowCasterVariantSet(input.internals.device.caps.storageBuffer, false),
539
- passKind: 'shadow-caster',
540
- sampleCount: 1,
541
- variantAlreadyResolved: true,
542
- });
543
- const customByRenderable = new Map<
544
- number,
545
- Map<number, { id: string; state: MaterialRenderState | undefined }>
546
- >();
547
- for (const dispatch of input.dispatch) {
548
- if (dispatch.tags.LightMode !== 'ShadowCaster' || dispatch.materialShaderId === undefined)
473
+ // Recovery has no record context, so it cannot use the context-backed
474
+ // shadowShaderMap. Group the producer dispatch facts directly and warm every
475
+ // authored ShadowCaster pass for the matching renderable/material pair.
476
+ const dispatches = new Map<number, Map<number, DispatchEntry[]>>();
477
+ for (const candidate of input.dispatch) {
478
+ if (candidate.tags.LightMode !== 'ShadowCaster' || candidate.materialShaderId === undefined)
549
479
  continue;
550
- let materials = customByRenderable.get(dispatch.renderableIndex);
551
- if (materials === undefined) {
552
- materials = new Map();
553
- customByRenderable.set(dispatch.renderableIndex, materials);
480
+ const byMaterial = dispatches.get(candidate.renderableIndex);
481
+ if (byMaterial === undefined) {
482
+ dispatches.set(candidate.renderableIndex, new Map([[candidate.materialHandle, [candidate]]]));
483
+ } else {
484
+ const entries = byMaterial.get(candidate.materialHandle);
485
+ if (entries === undefined) byMaterial.set(candidate.materialHandle, [candidate]);
486
+ else entries.push(candidate);
554
487
  }
555
- materials.set(dispatch.materialHandle, {
556
- id: dispatch.materialShaderId,
557
- state: dispatch.renderState,
558
- });
559
488
  }
560
489
  for (const entry of input.validated) {
561
- const triangles = entry.mesh.submeshes.filter(
562
- (submesh) => submesh.topology === 'triangle-list' || submesh.topology === 'triangle-strip',
563
- );
564
- if (triangles.length === 0) continue;
565
- if (entry.source.skin !== undefined) {
566
- addRequest({
567
- requests: input.requests,
568
- requestKeys: input.requestKeys,
569
- internals: input.internals,
570
- pipelineState: input.pipelineState,
571
- materialShaderId: SHADOW_CASTER_SHADER_ID,
572
- isHdrTarget: false,
573
- topology: entry.mesh.submeshes[0]?.topology ?? 'triangle-list',
574
- indexFormat: entry.mesh.indexFormat,
575
- variantSet: shadowCasterVariantSet(input.internals.device.caps.storageBuffer, true),
576
- passKind: 'shadow-caster',
577
- sampleCount: 1,
578
- vertexLayoutProjection: entry.mesh.layoutProjection,
579
- variantAlreadyResolved: true,
580
- });
581
- }
582
- for (const submesh of triangles) {
490
+ for (const submesh of entry.mesh.submeshes) {
491
+ if (submesh.topology !== 'triangle-list' && submesh.topology !== 'triangle-strip') continue;
583
492
  const material = entry.source.materials[submesh.materialSlot] ?? entry.source.material;
584
- const custom = customByRenderable
585
- .get(entry.renderableIndex)
586
- ?.get(material.materialHandle ?? 0);
587
- if (
588
- entry.source.skin === undefined &&
589
- custom !== undefined &&
590
- (custom.id !== 'forgeax::default-shadow-caster' || custom.state !== undefined)
591
- ) {
493
+ const shadowDispatches =
494
+ dispatches.get(entry.renderableIndex)?.get(material.materialHandle ?? 0) ?? [];
495
+ for (const dispatch of shadowDispatches.length === 0 ? [undefined] : shadowDispatches) {
496
+ const materialShaderId =
497
+ dispatch?.materialShaderId === 'forgeax::default-standard-pbr' ||
498
+ dispatch?.materialShaderId === undefined
499
+ ? SHADOW_CASTER_SHADER_ID
500
+ : dispatch.materialShaderId;
592
501
  addRequest({
593
502
  requests: input.requests,
594
503
  requestKeys: input.requestKeys,
595
504
  internals: input.internals,
596
505
  pipelineState: input.pipelineState,
597
- materialShaderId: custom.id,
506
+ materialShaderId,
598
507
  isHdrTarget: false,
599
- ...optionalRenderState(custom.state),
600
- topology: 'triangle-list',
508
+ ...optionalRenderState(dispatch?.renderState),
509
+ topology: submesh.topology,
510
+ indexFormat: entry.mesh.indexFormat,
511
+ ...optionalVariant(
512
+ materialShaderId === SHADOW_CASTER_SHADER_ID
513
+ ? shadowCasterVariantSet(
514
+ input.internals.device.caps.storageBuffer,
515
+ entry.source.skin !== undefined,
516
+ )
517
+ : undefined,
518
+ ),
601
519
  passKind: 'shadow-caster',
602
520
  sampleCount: 1,
603
- preserveUndefinedVariant: true,
521
+ vertexLayoutProjection: entry.mesh.layoutProjection,
522
+ layoutKindOverride: entry.source.skin === undefined ? 'pbr' : 'pbr-skin',
523
+ ...(dispatch?.vertexEntry === undefined ? {} : { vertexEntry: dispatch.vertexEntry }),
524
+ ...(dispatch?.fragmentEntry === undefined
525
+ ? {}
526
+ : { fragmentEntry: dispatch.fragmentEntry }),
604
527
  variantAlreadyResolved: true,
605
528
  });
606
529
  }
@@ -671,7 +594,7 @@ export function prepareRecoveryPipelineReadiness(input: {
671
594
  dispatch: input.dispatch,
672
595
  });
673
596
  }
674
- const assertFirstRecoveryFrame = (): void => {
597
+ const assertPreparedCache = (): void => {
675
598
  for (const request of requests) {
676
599
  const first = request.resolve();
677
600
  const second = request.resolve();
@@ -687,9 +610,9 @@ export function prepareRecoveryPipelineReadiness(input: {
687
610
  }
688
611
  }
689
612
  };
690
- assertFirstRecoveryFrame();
613
+ assertPreparedCache();
691
614
  return {
692
615
  pipelineSpecs: Object.freeze(requests.map((request) => request.spec)),
693
- assertFirstRecoveryFrame,
616
+ assertPreparedCache,
694
617
  };
695
618
  }