@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
package/src/gpu-scene.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { Buffer, Result, RhiDevice } from '@forgeax/engine-rhi';
2
2
  import { err, ok, RhiError } from '@forgeax/engine-rhi';
3
+ import { createStandardPbrArtifactReceipt } from '@forgeax/engine-shader';
3
4
  import {
4
5
  GPU_SCENE_LAYOUTS,
5
6
  type GpuSceneTableLayout,
@@ -11,6 +12,7 @@ import {
11
12
  GPU_BUFFER_USAGE_STORAGE,
12
13
  } from './gpu-usage';
13
14
  import type { GpuSceneInspection } from './inspection-types';
15
+ import { packStandardPbrMaterialRow } from './material-row';
14
16
  import type { RenderSceneApplyResult, RenderSceneSlot } from './scene/render-scene-types';
15
17
 
16
18
  export type { GpuSceneInspection } from './inspection-types';
@@ -20,6 +22,7 @@ const INSTANCE = GPU_SCENE_LAYOUTS.instance;
20
22
  const TRANSFORM = GPU_SCENE_LAYOUTS.transform;
21
23
  const DRAW_TEMPLATE = GPU_SCENE_LAYOUTS.drawTemplate;
22
24
  const MATERIAL = GPU_SCENE_LAYOUTS.material;
25
+ const STANDARD_PBR_RECEIPT = createStandardPbrArtifactReceipt();
23
26
  const PRIMITIVE_ACTIVE = 1;
24
27
  const PRIMITIVE_HAS_BOUNDS = 2;
25
28
  const PRIMITIVE_GPU_DRIVEN = 4;
@@ -50,6 +53,7 @@ class StableRangeAllocator {
50
53
  private readonly free: Array<{ start: number; count: number }> = [];
51
54
 
52
55
  allocate(count: number): number {
56
+ if (count <= 0) return 0;
53
57
  const freeIndex = this.free.findIndex((range) => range.count >= count);
54
58
  if (freeIndex >= 0) {
55
59
  const range = this.free[freeIndex];
@@ -157,6 +161,29 @@ function writeMat4(view: DataView, byteOffset: number, value: Float32Array): voi
157
161
  }
158
162
  }
159
163
 
164
+ function writeChangedMat4(
165
+ view: DataView,
166
+ byteOffset: number,
167
+ matrix: Float32Array,
168
+ sourceOffset = 0,
169
+ ): boolean {
170
+ let changed = false;
171
+ for (let lane = 0; lane < 16; lane += 1) {
172
+ const at = byteOffset + lane * 4;
173
+ const value = matrix[sourceOffset + lane] ?? 0;
174
+ if (Object.is(view.getFloat32(at, true), value)) continue;
175
+ view.setFloat32(at, value, true);
176
+ changed = true;
177
+ }
178
+ return changed;
179
+ }
180
+
181
+ function writeChangedU32(view: DataView, byteOffset: number, value: number): boolean {
182
+ if (view.getUint32(byteOffset, true) === value) return false;
183
+ view.setUint32(byteOffset, value, true);
184
+ return true;
185
+ }
186
+
160
187
  function writeVec4(view: DataView, byteOffset: number, values: readonly number[]): void {
161
188
  for (let lane = 0; lane < 4; lane += 1) {
162
189
  view.setFloat32(byteOffset + lane * 4, values[lane] ?? 0, true);
@@ -179,14 +206,7 @@ function stableU32(value: string): number {
179
206
  function coalesceSlots(
180
207
  slots: readonly number[],
181
208
  ): readonly { readonly start: number; readonly end: number }[] {
182
- let alreadyOrdered = true;
183
- for (let index = 1; index < slots.length; index += 1) {
184
- if ((slots[index] ?? 0) <= (slots[index - 1] ?? 0)) {
185
- alreadyOrdered = false;
186
- break;
187
- }
188
- }
189
- const ordered = alreadyOrdered ? slots : [...new Set(slots)].sort((a, b) => a - b);
209
+ const ordered = [...new Set(slots)].sort((a, b) => a - b);
190
210
  const ranges: Array<{ start: number; end: number }> = [];
191
211
  for (const slot of ordered) {
192
212
  const previous = ranges.at(-1);
@@ -206,14 +226,18 @@ export class GpuScene {
206
226
  private transformBytes: Uint8Array;
207
227
  private transformView: DataView;
208
228
  private buffers: GpuSceneBuffers;
229
+ /** Table buffers replaced by capacity growth stay alive until the scene is retired. */
230
+ private readonly retiredBuffers: Buffer[] = [];
209
231
  private uploadRanges = 0;
210
232
  private uploadBytes = 0;
211
233
  private capacityGrows = 0;
212
234
  private fullRebuilds = 0;
213
235
  private clearedSlots = 0;
214
236
  private noChangeFrames = 0;
237
+ /** Monotonic content identity consumed by shadow-cache invalidation. */
238
+ private sceneContentRevision = 0;
215
239
  private identityUploaded = false;
216
- private readonly allocations: Array<PrimitiveAllocation | undefined> = [];
240
+ private readonly allocations = new Map<number, PrimitiveAllocation>();
217
241
  private readonly instances = new StableRangeAllocator();
218
242
  private readonly transforms = new StableRangeAllocator();
219
243
  private readonly draws = new StableRangeAllocator();
@@ -276,16 +300,42 @@ export class GpuScene {
276
300
  return this.buffers.material;
277
301
  }
278
302
 
303
+ get contentRevision(): number {
304
+ return this.sceneContentRevision;
305
+ }
306
+
307
+ /**
308
+ * Resolve the stable scene-material row for one retained render slot. The
309
+ * GPU-driven shadow projection uses this producer-owned index instead of
310
+ * reconstructing material identity from a batch position.
311
+ */
312
+ materialIndexForSlot(slot: number, materialSlot: number): number | undefined {
313
+ const allocation = this.allocations.get(slot);
314
+ if (
315
+ allocation === undefined ||
316
+ !Number.isInteger(materialSlot) ||
317
+ materialSlot < 0 ||
318
+ materialSlot >= allocation.materialCount
319
+ ) {
320
+ return undefined;
321
+ }
322
+ return allocation.materialStart + materialSlot;
323
+ }
324
+
279
325
  sync(delta: RenderSceneApplyResult): Result<GpuSceneSyncResult, RhiError> {
280
326
  for (const transformIndex of this.pendingTemporalUploads) {
281
327
  this.writesByTable.transform.push(transformIndex);
282
328
  }
283
329
  const pendingWrites = TABLE_NAMES.some((name) => this.writesByTable[name].length > 0);
330
+ const contentUpdatedSlots = delta.contentUpdatedSlots;
331
+ const instanceUpdatedSlots = delta.instanceUpdatedSlots;
284
332
  if (
285
333
  delta.createdSlots.length === 0 &&
286
334
  delta.updatedSlots.length === 0 &&
287
335
  delta.recreatedSlots.length === 0 &&
288
336
  delta.removedSlots.length === 0 &&
337
+ contentUpdatedSlots.length === 0 &&
338
+ instanceUpdatedSlots.length === 0 &&
289
339
  !pendingWrites
290
340
  ) {
291
341
  this.noChangeFrames += 1;
@@ -296,8 +346,8 @@ export class GpuScene {
296
346
  writesByTable.transform.push(0);
297
347
  }
298
348
  let highestChangedSlot = -1;
299
- const contentUpdatedSlots = delta.contentUpdatedSlots ?? [];
300
349
  const contentUpdatedSlotIds = new Set(contentUpdatedSlots.map((record) => record.slot));
350
+ const instanceUpdatedSlotIds = new Set(instanceUpdatedSlots.map((record) => record.slot));
301
351
  const allocationResets = new Set<number>();
302
352
  // RenderScene may recycle a released CPU slot for a different identity in
303
353
  // the same delta. Clear the old GPU allocation before ensuring the new
@@ -307,11 +357,16 @@ export class GpuScene {
307
357
  if (record.slot > highestChangedSlot) highestChangedSlot = record.slot;
308
358
  this.clearSlot(record.slot, writesByTable);
309
359
  }
310
- for (const records of [delta.createdSlots, contentUpdatedSlots, delta.recreatedSlots]) {
360
+ for (const records of [
361
+ delta.createdSlots,
362
+ contentUpdatedSlots,
363
+ instanceUpdatedSlots,
364
+ delta.recreatedSlots,
365
+ ]) {
311
366
  for (const record of records) {
312
- const previous = this.allocations[record.slot];
367
+ const previous = this.allocations.get(record.slot);
313
368
  this.ensureAllocation(record, writesByTable);
314
- if (previous !== this.allocations[record.slot]) allocationResets.add(record.slot);
369
+ if (previous !== this.allocations.get(record.slot)) allocationResets.add(record.slot);
315
370
  if (record.slot > highestChangedSlot) highestChangedSlot = record.slot;
316
371
  }
317
372
  }
@@ -331,21 +386,27 @@ export class GpuScene {
331
386
  if (!grown.ok) return grown;
332
387
  }
333
388
 
334
- for (const record of delta.createdSlots) this.writeSlot(record, true, writesByTable);
335
- for (const record of contentUpdatedSlots) {
336
- this.writeSlot(record, allocationResets.has(record.slot), writesByTable);
337
- }
338
- for (const record of delta.updatedSlots) {
339
- if (contentUpdatedSlotIds.has(record.slot)) continue;
389
+ const publications = [...delta.createdSlots, ...delta.updatedSlots, ...delta.recreatedSlots];
390
+ const newSlots = new Set(
391
+ [...delta.createdSlots, ...delta.recreatedSlots].map((record) => record.slot),
392
+ );
393
+ for (const record of publications) {
394
+ const reset = newSlots.has(record.slot) || allocationResets.has(record.slot);
395
+ if (reset || contentUpdatedSlotIds.has(record.slot)) {
396
+ this.writeSlot(record, reset, writesByTable);
397
+ continue;
398
+ }
399
+ if (instanceUpdatedSlotIds.has(record.slot))
400
+ this.writeInstanceTransforms(record, writesByTable);
340
401
  this.writeRootTransform(record, false, writesByTable);
341
402
  }
342
- for (const record of delta.recreatedSlots) this.writeSlot(record, true, writesByTable);
343
403
  const uploaded = this.uploadRows(writesByTable);
344
404
  if (!uploaded.ok) return uploaded;
345
405
  this.pendingTemporalUploads.clear();
346
406
  for (const name of TABLE_NAMES) writesByTable[name].length = 0;
347
407
  this.identityUploaded = true;
348
408
  this.clearedSlots += delta.removedSlots.length;
409
+ this.sceneContentRevision += 1;
349
410
  return ok({
350
411
  ranges: uploaded.value.ranges,
351
412
  bytes: uploaded.value.bytes,
@@ -368,10 +429,6 @@ export class GpuScene {
368
429
  for (const range of ranges) {
369
430
  for (let index = range.start; index < range.end; index += 1) {
370
431
  this.pendingTemporalUploads.add(index);
371
- }
372
- }
373
- for (const range of ranges) {
374
- for (let index = range.start; index < range.end; index += 1) {
375
432
  this.transformBytes.copyWithin(
376
433
  index * TRANSFORM.stride + previousOffset,
377
434
  index * TRANSFORM.stride + currentOffset,
@@ -401,7 +458,7 @@ export class GpuScene {
401
458
  }
402
459
 
403
460
  rebuild(slots: readonly RenderSceneSlot[]): Result<GpuSceneSyncResult, RhiError> {
404
- this.allocations.length = 0;
461
+ this.allocations.clear();
405
462
  this.instances.reset();
406
463
  this.transforms.reset(1);
407
464
  this.draws.reset();
@@ -444,6 +501,7 @@ export class GpuScene {
444
501
  this.uploadRanges += TABLE_NAMES.length;
445
502
  this.uploadBytes += bytes;
446
503
  this.fullRebuilds += 1;
504
+ this.sceneContentRevision += 1;
447
505
  this.identityUploaded = true;
448
506
  return ok({ ranges: TABLE_NAMES.length, bytes, grew, cleared: 0 });
449
507
  }
@@ -485,6 +543,7 @@ export class GpuScene {
485
543
  dispose(): void {
486
544
  if (this.disposed) return;
487
545
  this.disposed = true;
546
+ for (const buffer of this.retiredBuffers) this.device.destroyBuffer(buffer);
488
547
  for (const buffer of Object.values(this.buffers)) this.device.destroyBuffer(buffer);
489
548
  }
490
549
 
@@ -493,7 +552,7 @@ export class GpuScene {
493
552
  resetPrevious: boolean,
494
553
  writes: Record<GpuSceneTableName, number[]>,
495
554
  ): void {
496
- const allocation = this.allocations[record.slot];
555
+ const allocation = this.allocations.get(record.slot);
497
556
  if (allocation === undefined) throw new RangeError('GPU Scene allocation unavailable');
498
557
  const primitiveOffset = record.slot * PRIMITIVE.stride;
499
558
  const primitive = new DataView(this.tableBytes.primitive);
@@ -556,25 +615,49 @@ export class GpuScene {
556
615
  const instanceOffset = instanceIndex * INSTANCE.stride;
557
616
  const transformIndex =
558
617
  allocation.instanceTransformCount === 0 ? 0 : allocation.instanceTransformStart + ordinal;
559
- instance.setUint32(instanceOffset + offset(INSTANCE, 'primitiveIndex'), record.slot, true);
560
- instance.setUint32(instanceOffset + offset(INSTANCE, 'transformIndex'), transformIndex, true);
561
- instance.setUint32(instanceOffset + offset(INSTANCE, 'customDataStart'), 0, true);
562
- instance.setUint32(instanceOffset + offset(INSTANCE, 'flags'), PRIMITIVE_ACTIVE, true);
618
+ let metadataChanged = writeChangedU32(
619
+ instance,
620
+ instanceOffset + offset(INSTANCE, 'primitiveIndex'),
621
+ record.slot,
622
+ );
623
+ metadataChanged =
624
+ writeChangedU32(
625
+ instance,
626
+ instanceOffset + offset(INSTANCE, 'transformIndex'),
627
+ transformIndex,
628
+ ) || metadataChanged;
629
+ metadataChanged =
630
+ writeChangedU32(
631
+ instance,
632
+ instanceOffset + offset(INSTANCE, 'customDataStart'),
633
+ record.snapshot.skin?.customDataStart ?? 0,
634
+ ) || metadataChanged;
635
+ metadataChanged =
636
+ writeChangedU32(instance, instanceOffset + offset(INSTANCE, 'flags'), PRIMITIVE_ACTIVE) ||
637
+ metadataChanged;
563
638
  if (allocation.instanceTransformCount > 0) {
564
- const local = record.snapshot.instances?.transforms.subarray(
565
- ordinal * 16,
566
- ordinal * 16 + 16,
567
- );
568
- const localWorld = local?.length === 16 ? local : IDENTITY_MATRIX;
639
+ const transforms = record.snapshot.instances?.transforms;
640
+ const hasLocal = transforms !== undefined && transforms.length >= (ordinal + 1) * 16;
641
+ const local = hasLocal ? transforms : IDENTITY_MATRIX;
642
+ const sourceOffset = hasLocal ? ordinal * 16 : 0;
569
643
  const localOffset = transformIndex * TRANSFORM.stride;
570
- const localCurrentOffset = localOffset + offset(TRANSFORM, 'currentWorld');
571
- const localPreviousOffset = localOffset + offset(TRANSFORM, 'previousWorld');
572
- writeMat4(transform, localCurrentOffset, localWorld);
573
- if (resetPrevious) writeMat4(transform, localPreviousOffset, localWorld);
574
- else this.pendingTemporalTransforms.add(transformIndex);
575
- writes.transform.push(transformIndex);
644
+ const changed = writeChangedMat4(
645
+ transform,
646
+ localOffset + offset(TRANSFORM, 'currentWorld'),
647
+ local,
648
+ sourceOffset,
649
+ );
650
+ if (resetPrevious)
651
+ writeChangedMat4(
652
+ transform,
653
+ localOffset + offset(TRANSFORM, 'previousWorld'),
654
+ local,
655
+ sourceOffset,
656
+ );
657
+ else if (changed) this.pendingTemporalTransforms.add(transformIndex);
658
+ if (changed || resetPrevious) writes.transform.push(transformIndex);
576
659
  }
577
- writes.instance.push(instanceIndex);
660
+ if (metadataChanged || resetPrevious) writes.instance.push(instanceIndex);
578
661
  }
579
662
 
580
663
  this.writeRootTransform(record, resetPrevious, writes);
@@ -623,76 +706,74 @@ export class GpuScene {
623
706
  writes.drawTemplate.push(drawIndex);
624
707
  }
625
708
 
626
- const material = new DataView(this.tableBytes.material);
709
+ this.writeMaterialSlot(record, writes);
710
+ }
711
+
712
+ private writeMaterialSlot(
713
+ record: RenderSceneSlot,
714
+ writes: Record<GpuSceneTableName, number[]>,
715
+ ): void {
716
+ const allocation = this.allocations.get(record.slot);
717
+ if (allocation === undefined) throw new RangeError('GPU Scene allocation unavailable');
627
718
  for (let ordinal = 0; ordinal < allocation.materialCount; ordinal += 1) {
628
719
  const materialIndex = allocation.materialStart + ordinal;
629
720
  const materialOffset = materialIndex * MATERIAL.stride;
630
721
  const snapshot = record.snapshot.materials[ordinal] ?? record.snapshot.material;
631
- writeVec4(material, materialOffset + offset(MATERIAL, 'params0'), [
632
- snapshot.baseColor?.[0] ?? 0,
633
- snapshot.baseColor?.[1] ?? 0,
634
- snapshot.baseColor?.[2] ?? 0,
635
- 1,
636
- ]);
637
- writeVec4(material, materialOffset + offset(MATERIAL, 'params1'), [
638
- snapshot.metallic ?? 0,
639
- snapshot.roughness ?? 1,
640
- ]);
641
- writeVec4(material, materialOffset + offset(MATERIAL, 'params2'), [
642
- snapshot.emissive?.[0] ?? 0,
643
- snapshot.emissive?.[1] ?? 0,
644
- snapshot.emissive?.[2] ?? 0,
645
- snapshot.emissiveIntensity ?? 0,
646
- ]);
647
- writeVec4(material, materialOffset + offset(MATERIAL, 'params3'), [
648
- snapshot.normalScale ?? 1,
649
- snapshot.occlusionStrength ?? 1,
650
- 0,
651
- 0,
652
- ]);
653
- material.setUint32(
654
- materialOffset + offset(MATERIAL, 'resource0'),
655
- snapshot.baseColorTexture ?? 0,
656
- true,
657
- );
658
- material.setUint32(
659
- materialOffset + offset(MATERIAL, 'resource1'),
660
- snapshot.metallicRoughnessTexture ?? 0,
661
- true,
662
- );
663
- material.setUint32(
664
- materialOffset + offset(MATERIAL, 'resource2'),
665
- snapshot.normalTexture ?? 0,
666
- true,
667
- );
668
- material.setUint32(
669
- materialOffset + offset(MATERIAL, 'resource3'),
670
- snapshot.emissiveTexture ?? 0,
671
- true,
672
- );
722
+ const row = packStandardPbrMaterialRow(STANDARD_PBR_RECEIPT, snapshot);
723
+ new Uint8Array(this.tableBytes.material, materialOffset, MATERIAL.stride).set(row);
673
724
  writes.material.push(materialIndex);
674
725
  }
675
726
  }
676
727
 
728
+ /** Consume changed instance fields independently of root or material changes. */
729
+ private writeInstanceTransforms(
730
+ record: RenderSceneSlot,
731
+ writes: Record<GpuSceneTableName, number[]>,
732
+ ): void {
733
+ const allocation = this.allocations.get(record.slot);
734
+ const instances = record.snapshot.instances;
735
+ if (allocation === undefined || instances === undefined) {
736
+ throw new RangeError('GPU Scene instance update has no explicit allocation');
737
+ }
738
+ if (allocation.instanceTransformCount !== instances.instanceCount) {
739
+ throw new RangeError('GPU Scene instance update changed instance count');
740
+ }
741
+ for (let ordinal = 0; ordinal < allocation.instanceTransformCount; ordinal += 1) {
742
+ const transformIndex = allocation.instanceTransformStart + ordinal;
743
+ const transformOffset = transformIndex * TRANSFORM.stride;
744
+ if (
745
+ writeChangedMat4(
746
+ this.transformView,
747
+ transformOffset + offset(TRANSFORM, 'currentWorld'),
748
+ instances.transforms,
749
+ ordinal * 16,
750
+ )
751
+ ) {
752
+ this.pendingTemporalTransforms.add(transformIndex);
753
+ writes.transform.push(transformIndex);
754
+ }
755
+ }
756
+ }
757
+
677
758
  private writeRootTransform(
678
759
  record: RenderSceneSlot,
679
760
  resetPrevious: boolean,
680
761
  writes: Record<GpuSceneTableName, number[]>,
681
762
  ): void {
682
- const allocation = this.allocations[record.slot];
763
+ const allocation = this.allocations.get(record.slot);
683
764
  if (allocation === undefined) throw new RangeError('GPU Scene allocation unavailable');
684
765
  const transformOffset = allocation.transformStart * TRANSFORM.stride;
685
766
  const previousOffset = transformOffset + offset(TRANSFORM, 'previousWorld');
686
767
  if (resetPrevious) {
687
768
  writeMat4(this.transformView, previousOffset, record.snapshot.transform.world);
688
769
  }
689
- writeMat4(
770
+ const changed = writeChangedMat4(
690
771
  this.transformView,
691
772
  transformOffset + offset(TRANSFORM, 'currentWorld'),
692
773
  record.snapshot.transform.world,
693
774
  );
694
- if (!resetPrevious) this.pendingTemporalTransforms.add(allocation.transformStart);
695
- writes.transform.push(allocation.transformStart);
775
+ if (changed && !resetPrevious) this.pendingTemporalTransforms.add(allocation.transformStart);
776
+ if (changed || resetPrevious) writes.transform.push(allocation.transformStart);
696
777
  }
697
778
 
698
779
  private clearSlot(slot: number, writes: Record<GpuSceneTableName, number[]>): void {
@@ -701,10 +782,10 @@ export class GpuScene {
701
782
  new Uint8Array(this.tableBytes[name], slot * layout.stride, layout.stride).fill(0);
702
783
  writes[name].push(slot);
703
784
  }
704
- const allocation = this.allocations[slot];
785
+ const allocation = this.allocations.get(slot);
705
786
  if (allocation === undefined) return;
706
787
  this.clearAllocation(allocation, writes);
707
- this.allocations[slot] = undefined;
788
+ this.allocations.delete(slot);
708
789
  }
709
790
 
710
791
  private uploadRows(
@@ -749,7 +830,7 @@ export class GpuScene {
749
830
  const instanceTransformCount = explicitInstances === undefined ? 0 : instanceCount;
750
831
  const drawCount = Math.max(1, record.snapshot.gpuDrivenDraws?.length ?? 0);
751
832
  const materialCount = Math.max(1, record.snapshot.materials.length);
752
- const existing = this.allocations[record.slot];
833
+ const existing = this.allocations.get(record.slot);
753
834
  if (
754
835
  existing?.instanceCount === instanceCount &&
755
836
  existing.instanceTransformCount === instanceTransformCount &&
@@ -771,7 +852,7 @@ export class GpuScene {
771
852
  materialStart: this.materials.allocate(materialCount),
772
853
  materialCount,
773
854
  };
774
- this.allocations[record.slot] = allocation;
855
+ this.allocations.set(record.slot, allocation);
775
856
  }
776
857
 
777
858
  private clearAllocation(
@@ -787,17 +868,20 @@ export class GpuScene {
787
868
  ).fill(0);
788
869
  writes.instance.push(instanceIndex);
789
870
  }
790
- for (let ordinal = -1; ordinal < allocation.instanceTransformCount; ordinal += 1) {
791
- const transformIndex =
792
- ordinal < 0 ? allocation.transformStart : allocation.instanceTransformStart + ordinal;
871
+ new Uint8Array(
872
+ this.tableBytes.transform,
873
+ allocation.transformStart * TRANSFORM.stride,
874
+ TRANSFORM.stride,
875
+ ).fill(0);
876
+ writes.transform.push(allocation.transformStart);
877
+ for (let ordinal = 0; ordinal < allocation.instanceTransformCount; ordinal += 1) {
878
+ const transformIndex = allocation.instanceTransformStart + ordinal;
793
879
  new Uint8Array(
794
880
  this.tableBytes.transform,
795
881
  transformIndex * TRANSFORM.stride,
796
882
  TRANSFORM.stride,
797
883
  ).fill(0);
798
884
  writes.transform.push(transformIndex);
799
- this.pendingTemporalTransforms.delete(transformIndex);
800
- this.pendingTemporalUploads.delete(transformIndex);
801
885
  }
802
886
  for (let ordinal = 0; ordinal < allocation.drawCount; ordinal += 1) {
803
887
  const drawIndex = allocation.drawStart + ordinal;
@@ -842,7 +926,10 @@ export class GpuScene {
842
926
  return write;
843
927
  }
844
928
  }
845
- for (const buffer of Object.values(this.buffers)) this.device.destroyBuffer(buffer);
929
+ // A submitted frame may still reference the previous table set. Keep it
930
+ // owned by this scene until the scene itself is retired after the queue
931
+ // fence; destroying it here causes validation errors during growth.
932
+ this.retiredBuffers.push(...Object.values(this.buffers));
846
933
  this.buffers = nextBuffers.value;
847
934
  this.tableBytes = nextTables;
848
935
  this.refreshTransformViews();
@@ -7,6 +7,7 @@
7
7
  export const GPU_TEXTURE_USAGE_COPY_SRC = 0x01;
8
8
  export const GPU_TEXTURE_USAGE_COPY_DST = 0x02;
9
9
  export const GPU_TEXTURE_USAGE_TEXTURE_BINDING = 0x04;
10
+ export const GPU_TEXTURE_USAGE_STORAGE_BINDING = 0x08;
10
11
  export const GPU_TEXTURE_USAGE_RENDER_ATTACHMENT = 0x10;
11
12
  export const GPU_TEXTURE_USAGE_RENDER_ATTACHMENT_AND_TEXTURE_BINDING =
12
13
  GPU_TEXTURE_USAGE_RENDER_ATTACHMENT | GPU_TEXTURE_USAGE_TEXTURE_BINDING;
@@ -414,6 +414,77 @@ export type SsaoBindOptions =
414
414
  }
415
415
  | { readonly enabled: false };
416
416
 
417
+ function standardLightingEntries(
418
+ hdrpBuffers: HdrpBuffers,
419
+ ssaoTexView: TextureView,
420
+ ssaoSampler: Sampler,
421
+ ): import('@forgeax/engine-rhi').BindGroupEntry[] {
422
+ return [
423
+ {
424
+ binding: 3,
425
+ resource: {
426
+ kind: 'buffer',
427
+ value: { buffer: hdrpBuffers.lightDataBuffer },
428
+ },
429
+ },
430
+ {
431
+ binding: 4,
432
+ resource: {
433
+ kind: 'buffer',
434
+ value: { buffer: hdrpBuffers.clusterGridBuffer },
435
+ },
436
+ },
437
+ {
438
+ binding: 5,
439
+ resource: {
440
+ kind: 'buffer',
441
+ value: { buffer: hdrpBuffers.lightIndexListBuffer },
442
+ },
443
+ },
444
+ {
445
+ binding: 6,
446
+ resource: {
447
+ kind: 'buffer',
448
+ value: { buffer: hdrpBuffers.clusterUniformBuffer },
449
+ },
450
+ },
451
+ {
452
+ binding: 7,
453
+ resource: { kind: 'textureView', value: ssaoTexView },
454
+ },
455
+ {
456
+ binding: 8,
457
+ resource: { kind: 'sampler', value: ssaoSampler },
458
+ },
459
+ ];
460
+ }
461
+
462
+ /** Standard surface resources without scene geometry tables. */
463
+ export function createStandardSurfaceLightingBindGroup(
464
+ runtime: RenderSystemRuntime,
465
+ layout: BindGroupLayout,
466
+ grid: { readonly x: number; readonly y: number; readonly z: number },
467
+ ssaoOptions: SsaoBindOptions = { enabled: false },
468
+ ): BindGroup | null {
469
+ const buffers = getOrCreateHdrpBuffers(runtime, grid);
470
+ const fallback = getOrCreateSsaoFallbackTexture(runtime);
471
+ if (buffers === null || fallback === null) return null;
472
+ const result = runtime.device.createBindGroup({
473
+ label: 'standard-surface-lighting',
474
+ layout,
475
+ entries: standardLightingEntries(
476
+ buffers,
477
+ ssaoOptions.enabled ? ssaoOptions.ssaoBlurredView : fallback.view,
478
+ fallback.sampler,
479
+ ),
480
+ });
481
+ if (!result.ok) {
482
+ runtime.errorRegistry.fire(result.error);
483
+ return null;
484
+ }
485
+ return result.value;
486
+ }
487
+
417
488
  export function createHdrpUnifiedBindGroup(
418
489
  runtime: RenderSystemRuntime,
419
490
  hdrpBuffers: HdrpBuffers,
@@ -443,42 +514,7 @@ export function createHdrpUnifiedBindGroup(
443
514
  },
444
515
  },
445
516
  },
446
- {
447
- binding: 3,
448
- resource: {
449
- kind: 'buffer',
450
- value: { buffer: hdrpBuffers.lightDataBuffer },
451
- },
452
- },
453
- {
454
- binding: 4,
455
- resource: {
456
- kind: 'buffer',
457
- value: { buffer: hdrpBuffers.clusterGridBuffer },
458
- },
459
- },
460
- {
461
- binding: 5,
462
- resource: {
463
- kind: 'buffer',
464
- value: { buffer: hdrpBuffers.lightIndexListBuffer },
465
- },
466
- },
467
- {
468
- binding: 6,
469
- resource: {
470
- kind: 'buffer',
471
- value: { buffer: hdrpBuffers.clusterUniformBuffer },
472
- },
473
- },
474
- {
475
- binding: 7,
476
- resource: { kind: 'textureView', value: ssaoTexView },
477
- },
478
- {
479
- binding: 8,
480
- resource: { kind: 'sampler', value: ssaoSampler },
481
- },
517
+ ...standardLightingEntries(hdrpBuffers, ssaoTexView, ssaoSampler),
482
518
  ],
483
519
  });
484
520
  if (!result.ok) {
@@ -0,0 +1,38 @@
1
+ import type { RhiError } from '@forgeax/engine-rhi';
2
+ import { ok, type Result } from '@forgeax/engine-types';
3
+ import type { RenderSystemRuntime } from '../record/render-context';
4
+ import type { SkylightSnapshot } from '../render-system-extract';
5
+ import { getOrCreateIblCache } from './IblPipelineCache';
6
+ import type { SkylightBindGroupResources, SkylightFallback } from './skylight-bind-group';
7
+
8
+ const EMPTY_SKYLIGHT = new Float32Array([0, 0, 0, 0, 0, 0, 0, 1]);
9
+
10
+ /** Standard and feature materials consume the same generation-owned environment. */
11
+ export function resolveFrameSkylightResources(
12
+ runtime: Pick<RenderSystemRuntime, 'device' | 'deviceScope'>,
13
+ fallback: SkylightFallback,
14
+ skylight: SkylightSnapshot | undefined,
15
+ ): Result<SkylightBindGroupResources, RhiError> {
16
+ const payload =
17
+ skylight === undefined
18
+ ? EMPTY_SKYLIGHT
19
+ : new Float32Array([skylight.intensity, ...skylight.color, ...skylight.rotation]);
20
+ const uploaded = runtime.device.queue.writeBuffer(fallback.intensityBuffer, 0, payload);
21
+ if (!uploaded.ok) return uploaded;
22
+ const cache = skylight === undefined ? undefined : getOrCreateIblCache(runtime.deviceScope);
23
+ const resident =
24
+ cache?.irradianceView !== undefined &&
25
+ cache.prefilterView !== undefined &&
26
+ cache.brdfLutView !== undefined
27
+ ? cache
28
+ : undefined;
29
+ return ok({
30
+ irradianceView: resident?.irradianceView ?? fallback.irradianceView,
31
+ irradianceSampler: fallback.sampler,
32
+ prefilterView: resident?.prefilterView ?? fallback.prefilterView,
33
+ prefilterSampler: fallback.sampler,
34
+ brdfLutView: resident?.brdfLutView ?? fallback.brdfLutView,
35
+ brdfLutSampler: fallback.sampler,
36
+ intensityBuffer: fallback.intensityBuffer,
37
+ });
38
+ }
@@ -311,13 +311,14 @@ export function assembleMaterialWithSkylightEntries(
311
311
  resource: { kind: 'textureView', value: transmissionView },
312
312
  },
313
313
  );
314
- const clearcoatStart = result.length;
314
+ // Standard physical maps occupy fixed bindings 26..45. The `slot` value
315
+ // is the canonical index from STANDARD_PHYSICAL_TEXTURE_FIELDS; preserve
316
+ // gaps for omitted authored maps instead of compacting this tail.
317
+ const physicalStart = 26;
315
318
  for (let index = 0; index < textureInjections.length; index += 1) {
316
319
  const resource = textureInjections[index];
317
320
  if (resource === undefined) continue;
318
- // Slots are offsets from one stable injection base. Using the growing
319
- // result length here made slot 1/2 drift past their BGL bindings.
320
- const binding = clearcoatStart + resource.slot * 2;
321
+ const binding = physicalStart + resource.slot * 2;
321
322
  result.push(
322
323
  {
323
324
  binding,