@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,5 @@
1
1
  import type { EntityHandle } from '@forgeax/engine-ecs';
2
- import type { RhiCaps, TextureFormat } from '@forgeax/engine-rhi';
2
+ import type { Buffer, RhiCaps, Sampler, TextureFormat, TextureView } from '@forgeax/engine-rhi';
3
3
  import { err, ok, type Result } from '@forgeax/engine-types';
4
4
  import type { DeviceScope, LifecycleResourceSpec } from '../device/device-scope';
5
5
  import {
@@ -10,6 +10,7 @@ import {
10
10
  RenderFeatureStageFailedError,
11
11
  } from '../errors/render';
12
12
  import type { PostProcessShaderEntry } from '../fullscreen-post-process-pass';
13
+ import type { RenderFeatureHostInspection } from '../inspection-types';
13
14
  import type {
14
15
  PreparedGraphicsReference,
15
16
  PreparedGraphicsResolvedSnapshot,
@@ -19,19 +20,26 @@ import type {
19
20
  import type { SceneDataTarget } from '../temporal/scene-data';
20
21
  import { createSceneDataCatalog, type SceneDataCatalog } from '../temporal/scene-data-catalog';
21
22
  import {
23
+ cloneRenderFeaturePlanSignatureSnapshot,
22
24
  freezeRenderFeaturePlan,
23
25
  type RenderFeatureLogicalTarget,
24
26
  type RenderFeatureMaterialShaderBindingContract,
25
27
  type RenderFeaturePassDeclaration,
26
28
  type RenderFeaturePlan,
29
+ type RenderFeaturePlanContext,
27
30
  type RenderFeaturePlannedFrame,
31
+ type RenderFeaturePlanSignatureMetrics,
32
+ type RenderFeaturePlanSignatureSnapshot,
28
33
  type RenderFeatureResourceDeclaration,
34
+ rememberRenderFeaturePlanSignature,
29
35
  renderFeaturePlanSignature,
36
+ renderFeaturePlanSignatureSnapshotEquals,
30
37
  } from './plan';
31
38
  import type {
32
39
  RenderFeatureGpuBindingsRef,
33
40
  RenderFeatureGpuBufferRef,
34
41
  RenderFeatureGpuComputePassDescriptor,
42
+ RenderFeatureGpuPreparedResourceRef,
35
43
  RenderFeatureGpuPrepareSession,
36
44
  RenderFeatureGpuProgramRef,
37
45
  RenderFeatureGpuWorkOwner,
@@ -48,6 +56,7 @@ import {
48
56
  type PreparedGraphicsStore,
49
57
  type PreparedGraphicsTransaction,
50
58
  } from './prepared-graphics-store';
59
+ import { isRenderFeatureTargetHandle } from './targets';
51
60
  import type {
52
61
  RenderFeature,
53
62
  RenderFeatureCapabilityKey,
@@ -68,7 +77,29 @@ const planExecutionProjections = new WeakMap<
68
77
  RenderFeaturePlanExecution
69
78
  >();
70
79
 
80
+ const submissionAcknowledgments = new WeakMap<RenderFeaturePlannedFrame, () => void>();
81
+ const submissionSensitivePlans = new WeakSet<RenderFeaturePlannedFrame>();
82
+
83
+ /** A cached command graph must not replay a producer's already-consumed intents. */
84
+ export function hasSubmissionSensitiveFeatures(
85
+ plans: readonly RenderFeaturePlannedFrame[],
86
+ ): boolean {
87
+ return plans.some((plan) => submissionSensitivePlans.has(plan));
88
+ }
89
+
90
+ /** Acknowledge only plans in the submitted graph, once, including a retained graph. */
91
+ export function acknowledgeRenderFeatureSubmission(
92
+ plans: readonly RenderFeaturePlannedFrame[],
93
+ ): void {
94
+ for (const plan of plans) {
95
+ const acknowledge = submissionAcknowledgments.get(plan);
96
+ submissionAcknowledgments.delete(plan);
97
+ acknowledge?.();
98
+ }
99
+ }
100
+
71
101
  export interface RenderFeaturePlanExecutionPass {
102
+ readonly shadowCaster?: true;
72
103
  readonly featureIdentity: string;
73
104
  readonly order: number;
74
105
  readonly name: string;
@@ -115,6 +146,8 @@ export interface RenderFeatureFrameInput {
115
146
  readonly materialShaderBindingContract?: (
116
147
  materialShaderId: string,
117
148
  ) => RenderFeatureMaterialShaderBindingContract;
149
+ /** Renderer-owned prepared camera/depth/noise resources for feature plans. */
150
+ readonly preparedDataInterfaces?: RenderFeaturePlanContext['preparedDataInterfaces'];
118
151
  readonly createPreparedGraphicsResolver?: (
119
152
  input: RenderFeaturePreparedGraphicsResolverInput,
120
153
  ) => PreparedGraphicsResolver;
@@ -141,7 +174,17 @@ export interface RenderFeatureFrameResult {
141
174
  readonly plans: readonly RenderFeaturePlannedFrame[];
142
175
  readonly fullscreenEffects: ReadonlyMap<string, PostProcessShaderEntry>;
143
176
  readonly preparedResourceBatches: readonly RenderFeaturePreparedResourceBatch[];
177
+ /**
178
+ * True only when the current graph resolves a transient graphics lease.
179
+ * Retired GPU-work leases are kept alive until queue completion but are not
180
+ * referenced by this candidate and therefore do not require a new graph.
181
+ */
182
+ readonly requiresPreparedResourceKey: boolean;
144
183
  readonly hiddenEntityReports: readonly RenderFeatureHiddenEntityReport[];
184
+ /** Invoke producer consumption after the frame reaches queue submission. */
185
+ readonly onSubmitted: () => void;
186
+ /** Discard producer frame state after graph admission/submission failure. */
187
+ readonly onAborted: () => void;
145
188
  }
146
189
 
147
190
  export interface RenderFeatureHost {
@@ -180,6 +223,10 @@ export interface RenderFeatureHost {
180
223
  diagnostics(): readonly RenderFeatureDiagnostics[];
181
224
  /** Subscribe to lifecycle projection changes; unchanged active frames are silent. */
182
225
  subscribeDiagnostics(listener: () => void): () => void;
226
+ /** Detached signature and prepared-resource accounting for diagnostics. */
227
+ readonly inspection?: () => RenderFeatureHostInspection;
228
+ /** Host-owned signature entry point so accounting remains per feature. */
229
+ readonly recordPlanSignature?: (identity: string, plan: RenderFeaturePlan) => string;
183
230
  dispose(): Result<void, RenderError>;
184
231
  }
185
232
 
@@ -454,6 +501,7 @@ interface PreparedPlanResources {
454
501
  readonly computePrograms: ReadonlyMap<string, RenderFeatureGpuProgramRef>;
455
502
  readonly graphicsPrograms: ReadonlyMap<string, RenderFeaturePreparedRef<'pipeline'>>;
456
503
  readonly buffers: ReadonlyMap<string, RenderFeatureGpuBufferRef>;
504
+ readonly preparedGpuResources: ReadonlyMap<string, RenderFeatureGpuPreparedResourceRef>;
457
505
  readonly computeBindings: ReadonlyMap<string, RenderFeatureGpuBindingsRef>;
458
506
  readonly graphicsBindings: ReadonlyMap<string, RenderFeaturePreparedRef<'bindings'>>;
459
507
  readonly vertexData: ReadonlyMap<string, RenderFeaturePreparedRef<'vertex-data'>>;
@@ -498,6 +546,7 @@ function preparePlanResources(
498
546
  const computePrograms = new Map<string, RenderFeatureGpuProgramRef>();
499
547
  const graphicsPrograms = new Map<string, RenderFeaturePreparedRef<'pipeline'>>();
500
548
  const buffers = new Map<string, RenderFeatureGpuBufferRef>();
549
+ const preparedGpuResources = new Map<string, RenderFeatureGpuPreparedResourceRef>();
501
550
  const computeBindings = new Map<string, RenderFeatureGpuBindingsRef>();
502
551
  const graphicsBindings = new Map<string, RenderFeaturePreparedRef<'bindings'>>();
503
552
  const vertexData = new Map<string, RenderFeaturePreparedRef<'vertex-data'>>();
@@ -511,7 +560,9 @@ function preparePlanResources(
511
560
  if (
512
561
  gpu === undefined &&
513
562
  plan.resources.some((resource) =>
514
- ['compute-program', 'buffer', 'compute-bindings'].includes(resource.kind),
563
+ ['compute-program', 'buffer', 'prepared-gpu-resource', 'compute-bindings'].includes(
564
+ resource.kind,
565
+ ),
515
566
  )
516
567
  ) {
517
568
  return err(planFailure(slot));
@@ -537,21 +588,60 @@ function preparePlanResources(
537
588
  if (!prepared.ok) return prepared;
538
589
  buffers.set(resource.name, prepared.value);
539
590
  }
591
+ for (const resource of byKind('prepared-gpu-resource')) {
592
+ if (gpu === undefined) return err(planFailure(slot));
593
+ if (resource.resource.kind === 'buffer') {
594
+ const prepared = gpu.prepareBufferResource(resource.name, resource.resource.value as Buffer, {
595
+ size: resource.resource.size,
596
+ usage: resource.resource.usage ?? ['uniform'],
597
+ });
598
+ if (!prepared.ok) return prepared;
599
+ preparedGpuResources.set(resource.name, { kind: 'buffer', reference: prepared.value });
600
+ continue;
601
+ }
602
+ if (resource.resource.kind === 'texture-view') {
603
+ const logical =
604
+ resource.logicalTarget === undefined
605
+ ? undefined
606
+ : targetHandle(resource.logicalTarget, targets);
607
+ if (
608
+ resource.logicalTarget !== undefined &&
609
+ (logical === undefined || !isRenderFeatureTargetHandle(logical))
610
+ ) {
611
+ return err(planFailure(slot));
612
+ }
613
+ const prepared = gpu.prepareTextureView(
614
+ resource.name,
615
+ resource.resource.value as TextureView,
616
+ logical === undefined || !isRenderFeatureTargetHandle(logical) ? undefined : logical,
617
+ );
618
+ if (!prepared.ok) return prepared;
619
+ preparedGpuResources.set(resource.name, {
620
+ kind: 'texture-view',
621
+ reference: prepared.value,
622
+ });
623
+ continue;
624
+ }
625
+ const prepared = gpu.prepareSampler(resource.name, resource.resource.value as Sampler);
626
+ if (!prepared.ok) return prepared;
627
+ preparedGpuResources.set(resource.name, { kind: 'sampler', reference: prepared.value });
628
+ }
540
629
  for (const resource of byKind('compute-bindings')) {
541
630
  const program = computePrograms.get(resource.program);
542
- const entries = resource.entries.map((entry) => ({
543
- binding: entry.binding,
544
- buffer: buffers.get(entry.resource),
545
- }));
546
- if (program === undefined || entries.some((entry) => entry.buffer === undefined)) {
631
+ const entries = resource.entries.map((entry) => {
632
+ const buffer = buffers.get(entry.resource);
633
+ if (buffer !== undefined) return { binding: entry.binding, buffer } as const;
634
+ const prepared = preparedGpuResources.get(entry.resource);
635
+ return prepared === undefined
636
+ ? undefined
637
+ : ({ binding: entry.binding, resource: prepared } as const);
638
+ });
639
+ if (program === undefined || entries.some((entry) => entry === undefined)) {
547
640
  return err(planFailure(slot));
548
641
  }
549
642
  const prepared = gpu?.prepareBindings(resource.name, {
550
643
  program,
551
- entries: entries.map((entry) => ({
552
- binding: entry.binding,
553
- buffer: entry.buffer as RenderFeatureGpuBufferRef,
554
- })),
644
+ entries: entries as NonNullable<(typeof entries)[number]>[],
555
645
  });
556
646
  if (prepared === undefined) return err(planFailure(slot));
557
647
  if (!prepared.ok) return prepared;
@@ -600,6 +690,7 @@ function preparePlanResources(
600
690
  computePrograms,
601
691
  graphicsPrograms,
602
692
  buffers,
693
+ preparedGpuResources,
603
694
  computeBindings,
604
695
  graphicsBindings,
605
696
  vertexData,
@@ -802,14 +893,14 @@ function projectPlanPasses(
802
893
  ? declaration.program.colorFormats[0]
803
894
  : undefined;
804
895
  })();
805
- const colors = pass.colorAttachments.map((attachment) => ({
896
+ const colors = (pass.kind === 'raster' ? pass.colorAttachments : []).map((attachment) => ({
806
897
  resource: targetHandle(attachment.target, targets),
807
898
  format: targetFormat(attachment.target, logical, fallbackFormat),
808
899
  loadOp: attachment.loadOp,
809
900
  storeOp: attachment.storeOp,
810
901
  }));
811
902
  const depth =
812
- pass.depthStencilAttachment === undefined
903
+ pass.kind !== 'raster' || pass.depthStencilAttachment === undefined
813
904
  ? undefined
814
905
  : {
815
906
  resource: targetHandle(pass.depthStencilAttachment.target, targets),
@@ -817,7 +908,9 @@ function projectPlanPasses(
817
908
  depthLoadOp: pass.depthStencilAttachment.depthLoadOp,
818
909
  depthStoreOp: pass.depthStencilAttachment.depthStoreOp,
819
910
  };
820
- const sampledTargets = (pass.sampledTargets ?? []).map((name) => targetHandle(name, targets));
911
+ const sampledTargets = (pass.kind === 'raster' ? (pass.sampledTargets ?? []) : []).map((name) =>
912
+ targetHandle(name, targets),
913
+ );
821
914
  if (
822
915
  colors.some(
823
916
  (attachment) => attachment.resource === undefined || attachment.format === undefined,
@@ -862,6 +955,7 @@ function projectPlanPasses(
862
955
  order: slot.order,
863
956
  name: pass.name,
864
957
  graphics: descriptor,
958
+ ...(pass.kind === 'shadow-caster' ? { shadowCaster: true as const } : {}),
865
959
  graphicsState: graphicsState.value,
866
960
  ...(resolved?.ok === true ? { resolvedGraphics: resolved.value } : {}),
867
961
  });
@@ -898,6 +992,22 @@ class FeatureHostImpl implements RenderFeatureHost {
898
992
  private generation = 0;
899
993
  private lastRecoveryFrame: number | undefined;
900
994
  private readonly diagnosticsListeners = new Set<() => void>();
995
+ private readonly signatureByFeature = new Map<
996
+ string,
997
+ RenderFeatureHostInspection['signatures'][number]
998
+ >();
999
+ private readonly signatureCacheByFeature = new Map<
1000
+ string,
1001
+ { readonly signature: string; readonly snapshot: RenderFeaturePlanSignatureSnapshot }
1002
+ >();
1003
+ /** Monotonic compact identity for a changed feature-plan snapshot. */
1004
+ private signatureRevision = 0;
1005
+ private readonly preparedInspection = {
1006
+ retained: 0,
1007
+ submitted: 0,
1008
+ released: 0,
1009
+ releaseFailures: 0,
1010
+ };
901
1011
  private readonly preparedBatchStates = new WeakMap<
902
1012
  RenderFeaturePreparedResourceBatch,
903
1013
  'unsubmitted' | 'submitted'
@@ -917,6 +1027,77 @@ class FeatureHostImpl implements RenderFeatureHost {
917
1027
  return this.slots.map((slot) => slot.feature);
918
1028
  }
919
1029
 
1030
+ recordPlanSignature(identity: string, plan: RenderFeaturePlan): string {
1031
+ const now = (): number => (typeof performance === 'undefined' ? Date.now() : performance.now());
1032
+ const started = now();
1033
+ const previous = this.signatureCacheByFeature.get(identity);
1034
+ if (
1035
+ previous !== undefined &&
1036
+ renderFeaturePlanSignatureSnapshotEquals(plan, previous.snapshot)
1037
+ ) {
1038
+ const elapsed = now() - started;
1039
+ const priorInspection = this.signatureByFeature.get(identity);
1040
+ this.signatureByFeature.set(identity, {
1041
+ featureIdentity: identity,
1042
+ calls: priorInspection?.calls ?? 0,
1043
+ typedArrayBytes: priorInspection?.typedArrayBytes ?? 0,
1044
+ outputChars: priorInspection?.outputChars ?? 0,
1045
+ cpuMs: (priorInspection?.cpuMs ?? 0) + elapsed,
1046
+ cacheHits: (priorInspection?.cacheHits ?? 0) + 1,
1047
+ cacheMisses: priorInspection?.cacheMisses ?? 0,
1048
+ });
1049
+ // The graph validator receives a fresh plan object every frame. Reuse
1050
+ // is safe only because it will perform the same exact structural check
1051
+ // against this detached snapshot.
1052
+ rememberRenderFeaturePlanSignature(plan, previous.signature, previous.snapshot);
1053
+ return previous.signature;
1054
+ }
1055
+ // A changed plan usually mutates a small VFX membership/pass leaf. Keep
1056
+ // the previous detached evidence as a sharing source so unchanged
1057
+ // resource/program subtrees remain immutable and allocation-free; the
1058
+ // candidate snapshot is still a fresh root and is revalidated by graph
1059
+ // admission exactly as before.
1060
+ const snapshot = cloneRenderFeaturePlanSignatureSnapshot(plan, previous?.snapshot);
1061
+ // Keep one canonical spelling for the initial diagnostic/API observation.
1062
+ // Subsequent changes only need a compact monotonic identity: the detached
1063
+ // snapshot remains the exact structural proof and avoids rebuilding
1064
+ // megabytes of text for every VFX plan revision.
1065
+ const metrics: RenderFeaturePlanSignatureMetrics = {
1066
+ calls: 0,
1067
+ typedArrayBytes: 0,
1068
+ outputChars: 0,
1069
+ };
1070
+ const signature =
1071
+ previous === undefined
1072
+ ? renderFeaturePlanSignature(plan, metrics)
1073
+ : `revision-${++this.signatureRevision}`;
1074
+ this.signatureCacheByFeature.set(identity, { signature, snapshot });
1075
+ rememberRenderFeaturePlanSignature(plan, signature, snapshot);
1076
+ const elapsed = now() - started;
1077
+ const priorInspection = this.signatureByFeature.get(identity);
1078
+ this.signatureByFeature.set(identity, {
1079
+ featureIdentity: identity,
1080
+ calls: (priorInspection?.calls ?? 0) + metrics.calls,
1081
+ typedArrayBytes: (priorInspection?.typedArrayBytes ?? 0) + metrics.typedArrayBytes,
1082
+ outputChars: (priorInspection?.outputChars ?? 0) + metrics.outputChars,
1083
+ cpuMs: (priorInspection?.cpuMs ?? 0) + elapsed,
1084
+ cacheHits: priorInspection?.cacheHits ?? 0,
1085
+ cacheMisses: (priorInspection?.cacheMisses ?? 0) + 1,
1086
+ });
1087
+ return signature;
1088
+ }
1089
+
1090
+ inspection(): RenderFeatureHostInspection {
1091
+ return Object.freeze({
1092
+ signatures: Object.freeze(
1093
+ [...this.signatureByFeature.values()]
1094
+ .sort((left, right) => left.featureIdentity.localeCompare(right.featureIdentity))
1095
+ .map((entry) => Object.freeze({ ...entry })),
1096
+ ),
1097
+ prepared: Object.freeze({ ...this.preparedInspection }),
1098
+ });
1099
+ }
1100
+
920
1101
  createRecoveryRoot(scope: DeviceScope): LifecycleResourceSpec<unknown> {
921
1102
  return {
922
1103
  kind: 'feature',
@@ -978,6 +1159,8 @@ class FeatureHostImpl implements RenderFeatureHost {
978
1159
  }
979
1160
  slot.status = 'disposed';
980
1161
  this.slots.splice(index, 1);
1162
+ this.signatureByFeature.delete(feature.identity);
1163
+ this.signatureCacheByFeature.delete(feature.identity);
981
1164
  for (const [order, remaining] of this.slots.entries()) remaining.order = order;
982
1165
  this.publishDiagnosticsChanged();
983
1166
  return firstError === undefined ? ok(undefined) : err(firstError);
@@ -1055,11 +1238,14 @@ class FeatureHostImpl implements RenderFeatureHost {
1055
1238
  const result = lease.release();
1056
1239
  if (!result.ok && firstError === undefined) firstError = result.error;
1057
1240
  }
1241
+ this.preparedInspection.released += 1;
1242
+ if (firstError !== undefined) this.preparedInspection.releaseFailures += 1;
1058
1243
  return firstError === undefined ? ok(undefined) : err(firstError);
1059
1244
  },
1060
1245
  };
1061
1246
  this.preparedBatchStates.set(batch, 'unsubmitted');
1062
1247
  slot.preparedResourceBatches.add(batch);
1248
+ this.preparedInspection.retained += 1;
1063
1249
  return ok(batch);
1064
1250
  }
1065
1251
 
@@ -1067,6 +1253,7 @@ class FeatureHostImpl implements RenderFeatureHost {
1067
1253
  for (const batch of batches) {
1068
1254
  if (this.preparedBatchStates.get(batch) === 'unsubmitted') {
1069
1255
  this.preparedBatchStates.set(batch, 'submitted');
1256
+ this.preparedInspection.submitted += 1;
1070
1257
  }
1071
1258
  }
1072
1259
  }
@@ -1166,9 +1353,11 @@ export function runRenderFeatureFrame(
1166
1353
  const plans: RenderFeaturePlannedFrame[] = [];
1167
1354
  const fullscreenEffects = new Map<string, PostProcessShaderEntry>();
1168
1355
  const preparedResourceBatches: RenderFeaturePreparedResourceBatch[] = [];
1356
+ let requiresPreparedResourceKey = false;
1169
1357
  const hiddenEntityReports: RenderFeatureHiddenEntityReport[] = [
1170
1358
  ...(input.hiddenEntityReports ?? []),
1171
1359
  ];
1360
+ const abortedCallbacks: (() => void)[] = [];
1172
1361
 
1173
1362
  const diagnostics = host.diagnostics();
1174
1363
  for (const [order, feature] of host.features.entries()) {
@@ -1247,6 +1436,9 @@ export function runRenderFeatureFrame(
1247
1436
  ...(input.materialShaderBindingContract === undefined
1248
1437
  ? {}
1249
1438
  : { materialShaderBindingContract: input.materialShaderBindingContract }),
1439
+ ...(input.preparedDataInterfaces === undefined
1440
+ ? {}
1441
+ : { preparedDataInterfaces: input.preparedDataInterfaces }),
1250
1442
  }),
1251
1443
  stageEvents,
1252
1444
  errors,
@@ -1266,7 +1458,9 @@ export function runRenderFeatureFrame(
1266
1458
  const plannedFrame: RenderFeaturePlannedFrame = Object.freeze({
1267
1459
  featureIdentity: identity,
1268
1460
  generation: transaction.generation,
1269
- signature: renderFeaturePlanSignature(frozen.value),
1461
+ signature:
1462
+ host.recordPlanSignature?.(identity, frozen.value) ??
1463
+ renderFeaturePlanSignature(frozen.value),
1270
1464
  plan: frozen.value,
1271
1465
  });
1272
1466
  for (const resource of frozen.value.resources) {
@@ -1335,10 +1529,11 @@ export function runRenderFeatureFrame(
1335
1529
  host.setStatus(identity, 'failed', slot.latestError);
1336
1530
  continue;
1337
1531
  }
1338
- const leases = [
1339
- ...new Set(projected.value.passes.flatMap((pass) => pass.resolvedGraphics?.leases ?? [])),
1340
- ...(gpu?.retireUntouched() ?? []),
1341
- ];
1532
+ const graphicsLeases = projected.value.passes.flatMap(
1533
+ (pass) => pass.resolvedGraphics?.leases ?? [],
1534
+ );
1535
+ if (graphicsLeases.length > 0) requiresPreparedResourceKey = true;
1536
+ const leases = [...new Set(graphicsLeases), ...(gpu?.retireUntouched() ?? [])];
1342
1537
  const retained = host.retainPreparedGraphics(identity, leases);
1343
1538
  if (!retained.ok) {
1344
1539
  recordFailure(slot, 'plan', retained.error, errors);
@@ -1347,19 +1542,42 @@ export function runRenderFeatureFrame(
1347
1542
  continue;
1348
1543
  }
1349
1544
  planExecutionProjections.set(plannedFrame, projected.value);
1545
+ if (feature.onFrameSubmitted !== undefined) {
1546
+ submissionSensitivePlans.add(plannedFrame);
1547
+ submissionAcknowledgments.set(plannedFrame, () =>
1548
+ feature.onFrameSubmitted?.(extracted.value),
1549
+ );
1550
+ }
1350
1551
  plans.push(plannedFrame);
1552
+ if (feature.onFrameAborted !== undefined) {
1553
+ abortedCallbacks.push(() => feature.onFrameAborted?.(extracted.value));
1554
+ }
1351
1555
  if (leases.length > 0) preparedResourceBatches.push(retained.value);
1352
1556
  hiddenEntityReports.push(...featureHiddenEntityReports);
1353
1557
  host.setStatus(identity, 'active');
1354
1558
  }
1355
1559
 
1560
+ let submitted = false;
1561
+ let aborted = false;
1356
1562
  return {
1357
1563
  stageEvents,
1358
1564
  errors,
1359
1565
  plans,
1360
1566
  fullscreenEffects,
1361
1567
  preparedResourceBatches,
1568
+ requiresPreparedResourceKey,
1362
1569
  hiddenEntityReports: mergeHiddenEntityReports(hiddenEntityReports),
1570
+ onSubmitted: () => {
1571
+ if (submitted || aborted) return;
1572
+ submitted = true;
1573
+ acknowledgeRenderFeatureSubmission(plans);
1574
+ },
1575
+ onAborted: () => {
1576
+ if (submitted || aborted) return;
1577
+ aborted = true;
1578
+ for (const plan of plans) submissionAcknowledgments.delete(plan);
1579
+ for (const callback of abortedCallbacks) callback();
1580
+ },
1363
1581
  };
1364
1582
  }
1365
1583
 
@@ -0,0 +1,91 @@
1
+ import type { RhiDevice, RhiError, Texture, TextureView } from '@forgeax/engine-rhi';
2
+ import { ok, type Result } from '@forgeax/engine-types';
3
+ import type { DeviceScope } from '../device/device-scope';
4
+ import {
5
+ GPU_TEXTURE_USAGE_COPY_DST,
6
+ GPU_TEXTURE_USAGE_TEXTURE_BINDING,
7
+ } from '../gpu-texture-usage';
8
+
9
+ /** A reproducible, filterable RGBA noise field; each channel has an independent sample. */
10
+ export function createFeatureNoisePixels(): Uint8Array {
11
+ const pixels = new Uint8Array(64 * 64 * 4);
12
+ let state = 0x6d2b79f5;
13
+ for (let index = 0; index < pixels.length; index++) {
14
+ state ^= state << 13;
15
+ state ^= state >>> 17;
16
+ state ^= state << 5;
17
+ pixels[index] = state >>> 24;
18
+ }
19
+ return pixels;
20
+ }
21
+
22
+ /** The caller's device scope owns the texture, like the other built-in material inputs. */
23
+ export function createFeatureNoiseTexture(
24
+ device: RhiDevice,
25
+ ): Result<{ readonly texture: Texture; readonly view: TextureView }, RhiError> {
26
+ const texture = device.createTexture({
27
+ label: 'feature-noise-64x64',
28
+ size: { width: 64, height: 64 },
29
+ format: 'rgba8unorm',
30
+ usage: GPU_TEXTURE_USAGE_COPY_DST | GPU_TEXTURE_USAGE_TEXTURE_BINDING,
31
+ textureBindingViewDimension: undefined,
32
+ });
33
+ if (!texture.ok) return texture;
34
+ const uploaded = device.queue.writeTexture(
35
+ { texture: texture.value },
36
+ createFeatureNoisePixels(),
37
+ { bytesPerRow: 256, rowsPerImage: 64 },
38
+ { width: 64, height: 64 },
39
+ );
40
+ if (!uploaded.ok) {
41
+ device.destroyTexture(texture.value);
42
+ return uploaded;
43
+ }
44
+ const view = device.createTextureView(texture.value, {
45
+ label: 'feature-noise-view',
46
+ dimension: '2d',
47
+ });
48
+ if (!view.ok) {
49
+ device.destroyTexture(texture.value);
50
+ return view;
51
+ }
52
+ return ok({ texture: texture.value, view: view.value });
53
+ }
54
+
55
+ /** Lazily provisions one generation-owned noise view for feature preparation. */
56
+ export function createFeatureNoiseResolver(input: {
57
+ readonly scope: DeviceScope;
58
+ readonly getDevice: () => RhiDevice;
59
+ readonly onError: (error: RhiError) => void;
60
+ }): (frameNumber: number) => TextureView | undefined {
61
+ let current:
62
+ | { readonly device: RhiDevice; readonly generation: number; readonly view: TextureView }
63
+ | undefined;
64
+ let attempt:
65
+ | { readonly device: RhiDevice; readonly generation: number; readonly frameNumber: number }
66
+ | undefined;
67
+ return (frameNumber) => {
68
+ const device = input.getDevice();
69
+ const generation = input.scope.generation;
70
+ if (current?.device === device && current.generation === generation) return current.view;
71
+ if (
72
+ attempt?.device === device &&
73
+ attempt.generation === generation &&
74
+ attempt.frameNumber === frameNumber
75
+ ) {
76
+ return undefined;
77
+ }
78
+ current = undefined;
79
+ attempt = { device, generation, frameNumber };
80
+ const created = createFeatureNoiseTexture(device);
81
+ if (!created.ok) {
82
+ input.onError(created.error);
83
+ return undefined;
84
+ }
85
+ input.scope._adopt('texture', created.value.texture, (value) => {
86
+ device.destroyTexture(value);
87
+ });
88
+ current = { device, generation, view: created.value.view };
89
+ return current.view;
90
+ };
91
+ }