@forgeax/engine-render 0.1.33 → 0.1.34

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 (518) hide show
  1. package/README.md +1010 -124
  2. package/dist/assembly/backend-contract.d.ts +2 -0
  3. package/dist/assembly/backend-contract.d.ts.map +1 -1
  4. package/dist/assembly/barrel-distortion-inspection.d.ts +3 -0
  5. package/dist/assembly/barrel-distortion-inspection.d.ts.map +1 -0
  6. package/dist/assembly/canvas-draw-guard.d.ts +3 -0
  7. package/dist/assembly/canvas-draw-guard.d.ts.map +1 -0
  8. package/dist/assembly/cloud-shadow-entry.d.ts +4 -0
  9. package/dist/assembly/cloud-shadow-entry.d.ts.map +1 -0
  10. package/dist/assembly/dynamic-geometry-host.d.ts +4 -1
  11. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
  12. package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
  13. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
  14. package/dist/assembly/factory.d.ts +1 -1
  15. package/dist/assembly/factory.d.ts.map +1 -1
  16. package/dist/assembly/host-contract.d.ts +3 -3
  17. package/dist/assembly/host-contract.d.ts.map +1 -1
  18. package/dist/assembly/material/assembly.d.ts.map +1 -1
  19. package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
  20. package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
  21. package/dist/assembly/material-shader-policy.d.ts +16 -2
  22. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  23. package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
  24. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
  25. package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
  26. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  27. package/dist/assembly/render-feature-post-processes.d.ts +6 -0
  28. package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
  29. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  30. package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
  31. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
  32. package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
  33. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  34. package/dist/assembly/renderer-inspection.d.ts +11 -0
  35. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  36. package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
  37. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
  38. package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
  39. package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
  40. package/dist/assembly/webgpu-ready.d.ts +1 -1
  41. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  42. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
  43. package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
  44. package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
  45. package/dist/assembly/webgpu-renderer.d.ts +1 -1
  46. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  47. package/dist/authoring.mjs +1 -1
  48. package/dist/barrel-distortion.d.ts +47 -0
  49. package/dist/barrel-distortion.d.ts.map +1 -0
  50. package/dist/{chunk-PA5DRJNI.mjs → chunk-ELJFJ2BU.mjs} +2 -2
  51. package/dist/chunk-ELJFJ2BU.mjs.map +1 -0
  52. package/dist/{chunk-ZDQWGQW7.mjs → chunk-HEB564WF.mjs} +4 -4
  53. package/dist/{chunk-ZDQWGQW7.mjs.map → chunk-HEB564WF.mjs.map} +1 -1
  54. package/dist/{chunk-VOZWDM3L.mjs → chunk-MKDIT2EM.mjs} +1307 -188
  55. package/dist/chunk-MKDIT2EM.mjs.map +1 -0
  56. package/dist/{chunk-LEAXOMYJ.mjs → chunk-OCDLEI6I.mjs} +3 -3
  57. package/dist/{chunk-LEAXOMYJ.mjs.map → chunk-OCDLEI6I.mjs.map} +1 -1
  58. package/dist/chunk-ODZWR6JQ.mjs +4927 -0
  59. package/dist/chunk-ODZWR6JQ.mjs.map +1 -0
  60. package/dist/{chunk-3RTCJTH4.mjs → chunk-SHFUFJ5N.mjs} +184 -13
  61. package/dist/chunk-SHFUFJ5N.mjs.map +1 -0
  62. package/dist/{chunk-OO3DRYK7.mjs → chunk-UI5SFODX.mjs} +176 -96
  63. package/dist/chunk-UI5SFODX.mjs.map +1 -0
  64. package/dist/{chunk-PLAXOOX5.mjs → chunk-UINHLCZA.mjs} +561 -79
  65. package/dist/chunk-UINHLCZA.mjs.map +1 -0
  66. package/dist/{chunk-NB2S7ZRX.mjs → chunk-WEX45HKH.mjs} +127 -386
  67. package/dist/chunk-WEX45HKH.mjs.map +1 -0
  68. package/dist/cloud/density.d.ts +55 -0
  69. package/dist/cloud/density.d.ts.map +1 -0
  70. package/dist/cloud/extract.d.ts +25 -0
  71. package/dist/cloud/extract.d.ts.map +1 -0
  72. package/dist/cloud/feature.d.ts +57 -0
  73. package/dist/cloud/feature.d.ts.map +1 -0
  74. package/dist/cloud/frame-context.d.ts +8 -0
  75. package/dist/cloud/frame-context.d.ts.map +1 -0
  76. package/dist/cloud/inspection.d.ts +59 -0
  77. package/dist/cloud/inspection.d.ts.map +1 -0
  78. package/dist/cloud/optics.d.ts +56 -0
  79. package/dist/cloud/optics.d.ts.map +1 -0
  80. package/dist/cloud/parameters.d.ts +73 -0
  81. package/dist/cloud/parameters.d.ts.map +1 -0
  82. package/dist/cloud/resources.d.ts +60 -0
  83. package/dist/cloud/resources.d.ts.map +1 -0
  84. package/dist/cloud/shadow.d.ts +42 -0
  85. package/dist/cloud/shadow.d.ts.map +1 -0
  86. package/dist/cloud/temporal.d.ts +74 -0
  87. package/dist/cloud/temporal.d.ts.map +1 -0
  88. package/dist/components/barrel-distortion.d.ts +13 -0
  89. package/dist/components/barrel-distortion.d.ts.map +1 -0
  90. package/dist/components/cloud-layer.d.ts +29 -0
  91. package/dist/components/cloud-layer.d.ts.map +1 -0
  92. package/dist/components/index.d.ts +2 -0
  93. package/dist/components/index.d.ts.map +1 -1
  94. package/dist/components/instances.d.ts +20 -6
  95. package/dist/components/instances.d.ts.map +1 -1
  96. package/dist/construct-renderer.d.ts +1 -1
  97. package/dist/construct-renderer.d.ts.map +1 -1
  98. package/dist/construct-renderer.mjs +6759 -2875
  99. package/dist/construct-renderer.mjs.map +1 -1
  100. package/dist/dynamic-geometry.d.ts +5 -1
  101. package/dist/dynamic-geometry.d.ts.map +1 -1
  102. package/dist/errors/cloud.d.ts +59 -0
  103. package/dist/errors/cloud.d.ts.map +1 -0
  104. package/dist/errors/render.d.ts +18 -4
  105. package/dist/errors/render.d.ts.map +1 -1
  106. package/dist/examples/single-layer-medium-surface.d.ts +47 -0
  107. package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
  108. package/dist/extract/camera.d.ts.map +1 -1
  109. package/dist/extract/contracts.d.ts +5 -1
  110. package/dist/extract/contracts.d.ts.map +1 -1
  111. package/dist/features/barrel-distortion.d.ts +29 -0
  112. package/dist/features/barrel-distortion.d.ts.map +1 -0
  113. package/dist/features/error-reporting.d.ts +6 -2
  114. package/dist/features/error-reporting.d.ts.map +1 -1
  115. package/dist/features/host.d.ts +10 -0
  116. package/dist/features/host.d.ts.map +1 -1
  117. package/dist/features/plan.d.ts +8 -0
  118. package/dist/features/plan.d.ts.map +1 -1
  119. package/dist/features/render-graph-contribution.d.ts +5 -0
  120. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  121. package/dist/features/render-graph-raster.d.ts +1 -0
  122. package/dist/features/render-graph-raster.d.ts.map +1 -1
  123. package/dist/features/targets.d.ts +2 -0
  124. package/dist/features/targets.d.ts.map +1 -1
  125. package/dist/features/types.d.ts +44 -0
  126. package/dist/features/types.d.ts.map +1 -1
  127. package/dist/fullscreen-post-process-pass.d.ts +15 -7
  128. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  129. package/dist/gpu-dirty-ranges.d.ts +11 -0
  130. package/dist/gpu-dirty-ranges.d.ts.map +1 -0
  131. package/dist/gpu-driven/batch-topology.d.ts +17 -0
  132. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  133. package/dist/gpu-driven/material-artifacts.d.ts +6 -0
  134. package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
  135. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  136. package/dist/gpu-driven/production-raster-material.d.ts +178 -0
  137. package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
  138. package/dist/gpu-driven/production-raster.d.ts +47 -3
  139. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  140. package/dist/gpu-driven/resource-allocation.d.ts +31 -0
  141. package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
  142. package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
  143. package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
  144. package/dist/gpu-driven/view-gpu.d.ts +26 -2
  145. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  146. package/dist/gpu-scene.d.ts +5 -0
  147. package/dist/gpu-scene.d.ts.map +1 -1
  148. package/dist/hdrp-buffers.d.ts +2 -2
  149. package/dist/hdrp-buffers.d.ts.map +1 -1
  150. package/dist/ibl/skylight-bind-group.d.ts +10 -1
  151. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  152. package/dist/index.d.ts +27 -7
  153. package/dist/index.d.ts.map +1 -1
  154. package/dist/index.mjs +258 -8
  155. package/dist/index.mjs.map +1 -1
  156. package/dist/inspection-types.d.ts +135 -1
  157. package/dist/inspection-types.d.ts.map +1 -1
  158. package/dist/instance-buffer-cache.d.ts +4 -4
  159. package/dist/instance-buffer-cache.d.ts.map +1 -1
  160. package/dist/instances.d.ts +48 -100
  161. package/dist/instances.d.ts.map +1 -1
  162. package/dist/internal.mjs +7 -7
  163. package/dist/pbr-pipeline.d.ts +19 -1
  164. package/dist/pbr-pipeline.d.ts.map +1 -1
  165. package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
  166. package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
  167. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  168. package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
  169. package/dist/pipeline/standard-output/types.d.ts +4 -2
  170. package/dist/pipeline/standard-output/types.d.ts.map +1 -1
  171. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  172. package/dist/pipeline/standard-post.d.ts.map +1 -1
  173. package/dist/pipeline-builder.d.ts +1 -1
  174. package/dist/pipeline-builder.d.ts.map +1 -1
  175. package/dist/plugin.d.ts.map +1 -1
  176. package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
  177. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  178. package/dist/record/barrel-distortion-frame.d.ts +15 -0
  179. package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
  180. package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
  181. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
  182. package/dist/record/fold-buckets.d.ts +95 -0
  183. package/dist/record/fold-buckets.d.ts.map +1 -0
  184. package/dist/record/fold-instance-buffer.d.ts +6 -0
  185. package/dist/record/fold-instance-buffer.d.ts.map +1 -0
  186. package/dist/record/frame-lighting.d.ts +1 -0
  187. package/dist/record/frame-lighting.d.ts.map +1 -1
  188. package/dist/record/frame-snapshot.d.ts +37 -3
  189. package/dist/record/frame-snapshot.d.ts.map +1 -1
  190. package/dist/record/frame.d.ts +10 -61
  191. package/dist/record/frame.d.ts.map +1 -1
  192. package/dist/record/gpu-draw-receipts.d.ts +11 -0
  193. package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
  194. package/dist/record/gpu-timing.d.ts +8 -0
  195. package/dist/record/gpu-timing.d.ts.map +1 -1
  196. package/dist/record/main-pass-geometry.d.ts +21 -5
  197. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  198. package/dist/record/main-pass-material.d.ts +7 -1
  199. package/dist/record/main-pass-material.d.ts.map +1 -1
  200. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  201. package/dist/record/main-pass.d.ts +13 -2
  202. package/dist/record/main-pass.d.ts.map +1 -1
  203. package/dist/record/motion-blur-receipt.d.ts +11 -0
  204. package/dist/record/motion-blur-receipt.d.ts.map +1 -0
  205. package/dist/record/probe-blend-buffer.d.ts +16 -0
  206. package/dist/record/probe-blend-buffer.d.ts.map +1 -0
  207. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  208. package/dist/record/render-context.d.ts +22 -3
  209. package/dist/record/render-context.d.ts.map +1 -1
  210. package/dist/record/shadow-pass.d.ts +2 -0
  211. package/dist/record/shadow-pass.d.ts.map +1 -1
  212. package/dist/record/skybox-post-pass.d.ts +1 -1
  213. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  214. package/dist/record/typed-frame-graph.d.ts +22 -2
  215. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  216. package/dist/record/view-ubo.d.ts +11 -3
  217. package/dist/record/view-ubo.d.ts.map +1 -1
  218. package/dist/record/volume-params.d.ts +9 -0
  219. package/dist/record/volume-params.d.ts.map +1 -0
  220. package/dist/recovery/render-system-candidate.d.ts +10 -0
  221. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  222. package/dist/reflection/record-owner.d.ts.map +1 -1
  223. package/dist/render-contract.d.ts +42 -4
  224. package/dist/render-contract.d.ts.map +1 -1
  225. package/dist/render-graph-primitives.d.ts.map +1 -1
  226. package/dist/render-pipeline.d.ts +103 -2
  227. package/dist/render-pipeline.d.ts.map +1 -1
  228. package/dist/render-system-extract-tail.d.ts +3 -2
  229. package/dist/render-system-extract-tail.d.ts.map +1 -1
  230. package/dist/render-system-extract.d.ts +16 -9
  231. package/dist/render-system-extract.d.ts.map +1 -1
  232. package/dist/render-system-presentation.d.ts +23 -0
  233. package/dist/render-system-presentation.d.ts.map +1 -0
  234. package/dist/render-system-producer-roots.d.ts +10 -0
  235. package/dist/render-system-producer-roots.d.ts.map +1 -0
  236. package/dist/render-system-residency.d.ts +12 -0
  237. package/dist/render-system-residency.d.ts.map +1 -0
  238. package/dist/render-system.d.ts +19 -14
  239. package/dist/render-system.d.ts.map +1 -1
  240. package/dist/scene/probe-blend.d.ts +27 -0
  241. package/dist/scene/probe-blend.d.ts.map +1 -1
  242. package/dist/scene/render-scene.d.ts +12 -5
  243. package/dist/scene/render-scene.d.ts.map +1 -1
  244. package/dist/ssao-buffers.d.ts +9 -0
  245. package/dist/ssao-buffers.d.ts.map +1 -1
  246. package/dist/surface/dynamic-input.d.ts +133 -0
  247. package/dist/surface/dynamic-input.d.ts.map +1 -0
  248. package/dist/surface/gpu-driven.d.ts +41 -0
  249. package/dist/surface/gpu-driven.d.ts.map +1 -0
  250. package/dist/surface/submission-observation.d.ts +136 -0
  251. package/dist/surface/submission-observation.d.ts.map +1 -0
  252. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  253. package/dist/temporal/gpu.d.ts +13 -1
  254. package/dist/temporal/gpu.d.ts.map +1 -1
  255. package/dist/temporal/index.mjs +5 -5
  256. package/dist/temporal/inspection.d.ts.map +1 -1
  257. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  258. package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
  259. package/dist/transmission/single-layer-medium.d.ts +89 -0
  260. package/dist/transmission/single-layer-medium.d.ts.map +1 -0
  261. package/dist/typed-render-graph-primitives.d.ts +14 -2
  262. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  263. package/dist/volume/component.d.ts +9 -4
  264. package/dist/volume/component.d.ts.map +1 -1
  265. package/dist/volume/extract.d.ts +1 -1
  266. package/dist/volume/extract.d.ts.map +1 -1
  267. package/dist/volume/inspection.d.ts +2 -0
  268. package/dist/volume/inspection.d.ts.map +1 -1
  269. package/dist/volume/passes.d.ts +4 -1
  270. package/dist/volume/passes.d.ts.map +1 -1
  271. package/dist/volume/resources.d.ts.map +1 -1
  272. package/package.json +22 -21
  273. package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
  274. package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
  275. package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
  276. package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
  277. package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
  278. package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
  279. package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
  280. package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
  281. package/src/__tests__/factory-contract.integration.test.ts +295 -45
  282. package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
  283. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +14 -3
  284. package/src/__tests__/gpu-dirty-ranges.unit.test.ts +22 -0
  285. package/src/__tests__/gpu-driven-baseline.characterization.test.ts +16 -3
  286. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +12 -0
  287. package/src/__tests__/gpu-driven-material-artifacts.unit.test.ts +143 -0
  288. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +2 -2
  289. package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
  290. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +6 -5
  291. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +94 -6
  292. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
  293. package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
  294. package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
  295. package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
  296. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
  297. package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
  298. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
  299. package/src/__tests__/gpu-scene.unit.test.ts +119 -9
  300. package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
  301. package/src/__tests__/instances-culling.integration.test.ts +10 -36
  302. package/src/__tests__/instances-store.unit.test.ts +97 -305
  303. package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
  304. package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +146 -0
  305. package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
  306. package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
  307. package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
  308. package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
  309. package/src/__tests__/motion-blur-compute.dawn.test.ts +13 -7
  310. package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
  311. package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
  312. package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
  313. package/src/__tests__/physical-clearcoat.integration.test.ts +58 -0
  314. package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
  315. package/src/__tests__/probe-bindings.unit.test.ts +582 -1
  316. package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
  317. package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
  318. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
  319. package/src/__tests__/render-error-code-owner.test-d.ts +7 -0
  320. package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
  321. package/src/__tests__/render-feature-error-reporting.unit.test.ts +21 -1
  322. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
  323. package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
  324. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
  325. package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
  326. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +20 -20
  327. package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
  328. package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
  329. package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
  330. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +41 -7
  331. package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
  332. package/src/__tests__/renderer-frame-transaction.integration.test.ts +26 -10
  333. package/src/__tests__/resource-allocation.unit.test.ts +123 -0
  334. package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
  335. package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
  336. package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
  337. package/src/__tests__/skinned-shadow-caster.test.ts +15 -0
  338. package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
  339. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
  340. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
  341. package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
  342. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
  343. package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
  344. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
  345. package/src/__tests__/standard-pipeline.integration.test.ts +182 -1
  346. package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
  347. package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
  348. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
  349. package/src/__tests__/temporal-performance.integration.test.ts +3 -3
  350. package/src/__tests__/visibility-instances.integration.test.ts +7 -19
  351. package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
  352. package/src/__tests__/volume-optics-oracle.unit.test.ts +4 -2
  353. package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +30 -20
  354. package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
  355. package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
  356. package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
  357. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +113 -9
  358. package/src/__tests__/volumetric-fog-topology.unit.test.ts +5 -3
  359. package/src/assembly/backend-contract.ts +30 -0
  360. package/src/assembly/barrel-distortion-inspection.ts +22 -0
  361. package/src/assembly/canvas-draw-guard.ts +11 -0
  362. package/src/assembly/cloud-shadow-entry.ts +22 -0
  363. package/src/assembly/dynamic-geometry-host.ts +65 -37
  364. package/src/assembly/dynamic-geometry-runtime.ts +7 -1
  365. package/src/assembly/factory.ts +2 -30
  366. package/src/assembly/host-contract.ts +3 -3
  367. package/src/assembly/material/assembly.ts +25 -13
  368. package/src/assembly/material/pipeline-helpers.ts +53 -12
  369. package/src/assembly/material-shader-policy.ts +55 -0
  370. package/src/assembly/material-shader-prewarm.ts +21 -10
  371. package/src/assembly/recovery/device-loss-fanout.ts +13 -0
  372. package/src/assembly/recovery/renderer-recover.ts +41 -18
  373. package/src/assembly/render-feature-post-processes.ts +54 -0
  374. package/src/assembly/renderer-facade.ts +4 -1
  375. package/src/assembly/renderer-feature-inspection.ts +8 -2
  376. package/src/assembly/renderer-frame-transaction.ts +23 -0
  377. package/src/assembly/renderer-inspection.ts +28 -0
  378. package/src/assembly/skin-palette-owner.ts +1 -1
  379. package/src/assembly/temporal-post-process-prewarm.ts +3 -3
  380. package/src/assembly/webgpu-pbr-ready.ts +9 -1
  381. package/src/assembly/webgpu-ready-per-pass.ts +104 -0
  382. package/src/assembly/webgpu-ready.ts +115 -61
  383. package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
  384. package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
  385. package/src/assembly/webgpu-renderer.ts +214 -252
  386. package/src/assembly/webgpu-vertex-layouts.ts +1 -1
  387. package/src/barrel-distortion.ts +247 -0
  388. package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
  389. package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
  390. package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
  391. package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
  392. package/src/cloud/density.ts +600 -0
  393. package/src/cloud/extract.ts +110 -0
  394. package/src/cloud/feature.ts +1810 -0
  395. package/src/cloud/frame-context.ts +42 -0
  396. package/src/cloud/inspection.ts +130 -0
  397. package/src/cloud/optics.ts +285 -0
  398. package/src/cloud/parameters.ts +255 -0
  399. package/src/cloud/resources.ts +122 -0
  400. package/src/cloud/shadow.ts +167 -0
  401. package/src/cloud/temporal.ts +226 -0
  402. package/src/components/barrel-distortion.ts +46 -0
  403. package/src/components/cloud-layer.ts +47 -0
  404. package/src/components/index.ts +2 -0
  405. package/src/components/instances.ts +18 -45
  406. package/src/components/sprite-instances.ts +1 -1
  407. package/src/construct-renderer.ts +1 -1
  408. package/src/dynamic-geometry.ts +12 -1
  409. package/src/errors/cloud.ts +103 -0
  410. package/src/errors/render.ts +44 -7
  411. package/src/examples/single-layer-medium-surface.ts +59 -0
  412. package/src/extract/camera.ts +15 -1
  413. package/src/extract/contracts.ts +5 -0
  414. package/src/features/barrel-distortion.ts +172 -0
  415. package/src/features/error-reporting.ts +26 -6
  416. package/src/features/host.ts +115 -14
  417. package/src/features/plan.ts +8 -0
  418. package/src/features/render-graph-contribution.ts +9 -0
  419. package/src/features/render-graph-raster.ts +45 -3
  420. package/src/features/targets.ts +66 -0
  421. package/src/features/types.ts +47 -0
  422. package/src/fullscreen-post-process-pass.ts +41 -9
  423. package/src/gpu-dirty-ranges.ts +48 -0
  424. package/src/gpu-driven/batch-topology.ts +53 -0
  425. package/src/gpu-driven/material-artifacts.ts +33 -25
  426. package/src/gpu-driven/prepared-draw.ts +12 -4
  427. package/src/gpu-driven/production-raster-material.ts +1894 -0
  428. package/src/gpu-driven/production-raster.ts +825 -784
  429. package/src/gpu-driven/resource-allocation.ts +142 -0
  430. package/src/gpu-driven/shadow-ownership.ts +71 -0
  431. package/src/gpu-driven/view-gpu.ts +164 -10
  432. package/src/gpu-scene.ts +75 -84
  433. package/src/hdrp-buffers.ts +4 -3
  434. package/src/ibl/skylight-bind-group.ts +49 -7
  435. package/src/index.ts +196 -9
  436. package/src/inspection-types.ts +162 -0
  437. package/src/instance-buffer-cache.ts +4 -4
  438. package/src/instances.ts +149 -569
  439. package/src/pbr-pipeline.ts +219 -13
  440. package/src/pipeline/single-layer-medium-passes.ts +267 -0
  441. package/src/pipeline/standard-forward-lane.ts +313 -57
  442. package/src/pipeline/standard-output/graph.ts +8 -2
  443. package/src/pipeline/standard-output/types.ts +12 -1
  444. package/src/pipeline/standard-pipeline.ts +291 -18
  445. package/src/pipeline/standard-post.ts +90 -24
  446. package/src/pipeline-builder.ts +1 -1
  447. package/src/plugin.ts +4 -0
  448. package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
  449. package/src/prepare/prepared-graphics-resolver.ts +2 -0
  450. package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
  451. package/src/record/__tests__/sprite-material-abi.unit.test.ts +1 -1
  452. package/src/record/__tests__/temporal-payload.unit.test.ts +1 -1
  453. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
  454. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
  455. package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
  456. package/src/record/barrel-distortion-frame.ts +110 -0
  457. package/src/record/dynamic-geometry-consumption.ts +39 -9
  458. package/src/record/fold-buckets.ts +852 -0
  459. package/src/record/fold-instance-buffer.ts +51 -0
  460. package/src/record/frame-lighting.ts +36 -2
  461. package/src/record/frame-snapshot.ts +39 -3
  462. package/src/record/frame.ts +217 -1084
  463. package/src/record/gpu-draw-receipts.ts +38 -0
  464. package/src/record/gpu-timing.ts +48 -5
  465. package/src/record/main-pass-geometry.ts +251 -82
  466. package/src/record/main-pass-material.ts +66 -4
  467. package/src/record/main-pass-sprite-draws.ts +7 -65
  468. package/src/record/main-pass.ts +156 -20
  469. package/src/record/motion-blur-receipt.ts +91 -0
  470. package/src/record/probe-blend-buffer.ts +180 -0
  471. package/src/record/recovery-pipeline.ts +35 -3
  472. package/src/record/render-context.ts +39 -3
  473. package/src/record/shadow-pass.ts +30 -1
  474. package/src/record/skybox-post-pass.ts +28 -4
  475. package/src/record/typed-frame-graph.ts +770 -134
  476. package/src/record/view-ubo.ts +26 -3
  477. package/src/record/volume-params.ts +225 -0
  478. package/src/recovery/render-system-candidate.ts +235 -42
  479. package/src/reflection/record-owner.ts +7 -3
  480. package/src/render-contract.ts +48 -4
  481. package/src/render-graph-primitives.ts +7 -1
  482. package/src/render-pipeline.ts +130 -0
  483. package/src/render-system-extract-tail.ts +57 -61
  484. package/src/render-system-extract.ts +74 -76
  485. package/src/render-system-presentation.ts +56 -0
  486. package/src/render-system-producer-roots.ts +96 -0
  487. package/src/render-system-residency.ts +159 -0
  488. package/src/render-system.ts +347 -363
  489. package/src/scene/probe-blend.ts +96 -4
  490. package/src/scene/render-scene.ts +349 -280
  491. package/src/ssao-buffers.ts +95 -2
  492. package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
  493. package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
  494. package/src/surface/dynamic-input.ts +658 -0
  495. package/src/surface/gpu-driven.ts +147 -0
  496. package/src/surface/submission-observation.ts +517 -0
  497. package/src/systems/skin-palette-allocator.ts +4 -1
  498. package/src/temporal/gpu.ts +101 -17
  499. package/src/temporal/inspection.ts +7 -1
  500. package/src/temporal/standard-scene-data.ts +5 -0
  501. package/src/temporal/target-coverage-attachment.ts +4 -0
  502. package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
  503. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
  504. package/src/transmission/single-layer-medium.ts +322 -0
  505. package/src/typed-render-graph-primitives.ts +70 -2
  506. package/src/volume/component.ts +10 -9
  507. package/src/volume/extract.ts +11 -5
  508. package/src/volume/inspection.ts +3 -0
  509. package/src/volume/passes.ts +87 -4
  510. package/src/volume/resources.ts +2 -1
  511. package/dist/chunk-3RTCJTH4.mjs.map +0 -1
  512. package/dist/chunk-NB2S7ZRX.mjs.map +0 -1
  513. package/dist/chunk-NNQL7CB3.mjs +0 -1713
  514. package/dist/chunk-NNQL7CB3.mjs.map +0 -1
  515. package/dist/chunk-OO3DRYK7.mjs.map +0 -1
  516. package/dist/chunk-PA5DRJNI.mjs.map +0 -1
  517. package/dist/chunk-PLAXOOX5.mjs.map +0 -1
  518. package/dist/chunk-VOZWDM3L.mjs.map +0 -1
package/src/gpu-scene.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { Buffer, Result, RhiDevice } from '@forgeax/engine-rhi';
2
2
  import { err, ok, RhiError } from '@forgeax/engine-rhi';
3
3
  import { createStandardPbrArtifactReceipt } from '@forgeax/engine-shader';
4
+ import { GpuDirtyRanges } from './gpu-dirty-ranges';
4
5
  import {
5
6
  GPU_SCENE_LAYOUTS,
6
7
  type GpuSceneTableLayout,
@@ -13,6 +14,7 @@ import {
13
14
  } from './gpu-usage';
14
15
  import type { GpuSceneInspection } from './inspection-types';
15
16
  import { packMaterialProgramRow, packStandardPbrMaterialRow } from './material-row';
17
+ import type { MaterialSnapshot } from './render-system-extract';
16
18
  import type { RenderSceneApplyResult, RenderSceneSlot } from './scene/render-scene-types';
17
19
 
18
20
  export type { GpuSceneInspection } from './inspection-types';
@@ -206,22 +208,6 @@ function stableU32(value: string): number {
206
208
  return hash >>> 0;
207
209
  }
208
210
 
209
- function coalesceSlots(
210
- slots: readonly number[],
211
- ): readonly { readonly start: number; readonly end: number }[] {
212
- const ordered = [...new Set(slots)].sort((a, b) => a - b);
213
- const ranges: Array<{ start: number; end: number }> = [];
214
- for (const slot of ordered) {
215
- const previous = ranges.at(-1);
216
- if (previous !== undefined && previous.end === slot) {
217
- previous.end = slot + 1;
218
- } else {
219
- ranges.push({ start: slot, end: slot + 1 });
220
- }
221
- }
222
- return ranges;
223
- }
224
-
225
211
  /**
226
212
  * Build a lookup from the current instance identity to its submitted ordinal.
227
213
  * The GPU table is physically compacted by ordinal, so this small CPU lookup
@@ -274,6 +260,9 @@ function instanceIdentityChanged(
274
260
 
275
261
  /** Persistent GPU tables derived only from renderer projection slots. */
276
262
  export class GpuScene {
263
+ private readonly dirtyRanges = new GpuDirtyRanges();
264
+ private readonly rowScratch = new Uint8Array(Math.max(PRIMITIVE.stride, DRAW_TEMPLATE.stride));
265
+ private readonly rowScratchView = new DataView(this.rowScratch.buffer);
277
266
  private disposed = false;
278
267
  private tableBytes: Record<GpuSceneTableName, ArrayBuffer>;
279
268
  private transformBytes: Uint8Array;
@@ -444,6 +433,9 @@ export class GpuScene {
444
433
  if (!grown.ok) return grown;
445
434
  }
446
435
 
436
+ // A shared material has one packed value per publication, independent of
437
+ // how many primitives reference it. Do not retain mutable caller snapshots.
438
+ const materialRows = new Map<MaterialSnapshot, Uint8Array>();
447
439
  const publications = [...delta.createdSlots, ...delta.updatedSlots, ...delta.recreatedSlots];
448
440
  const newSlots = new Set(
449
441
  [...delta.createdSlots, ...delta.recreatedSlots].map((record) => record.slot),
@@ -451,7 +443,7 @@ export class GpuScene {
451
443
  for (const record of publications) {
452
444
  const reset = newSlots.has(record.slot) || allocationResets.has(record.slot);
453
445
  if (reset || contentUpdatedSlotIds.has(record.slot)) {
454
- this.writeSlot(record, reset, writesByTable, temporalResolver?.(record));
446
+ this.writeSlot(record, reset, writesByTable, materialRows, temporalResolver?.(record));
455
447
  continue;
456
448
  }
457
449
  if (instanceUpdatedSlotIds.has(record.slot))
@@ -483,7 +475,7 @@ export class GpuScene {
483
475
  if (this.pendingTemporalTransforms.size === 0) return ok(undefined);
484
476
  const currentOffset = offset(TRANSFORM, 'currentWorld');
485
477
  const previousOffset = offset(TRANSFORM, 'previousWorld');
486
- const ranges = coalesceSlots([...this.pendingTemporalTransforms]);
478
+ const ranges = this.dirtyRanges.coalesce([...this.pendingTemporalTransforms]);
487
479
  for (const range of ranges) {
488
480
  for (let index = range.start; index < range.end; index += 1) {
489
481
  this.pendingTemporalUploads.add(index);
@@ -549,7 +541,8 @@ export class GpuScene {
549
541
  }
550
542
  for (const bytes of Object.values(this.tableBytes)) new Uint8Array(bytes).fill(0);
551
543
  this.writeIdentityTransform();
552
- for (const slot of slots) this.writeSlot(slot, true, writesByTable);
544
+ const materialRows = new Map<MaterialSnapshot, Uint8Array>();
545
+ for (const slot of slots) this.writeSlot(slot, true, writesByTable, materialRows);
553
546
  let bytes = 0;
554
547
  for (const name of TABLE_NAMES) {
555
548
  const table = this.tableBytes[name];
@@ -610,64 +603,44 @@ export class GpuScene {
610
603
  record: RenderSceneSlot,
611
604
  resetPrevious: boolean,
612
605
  writes: Record<GpuSceneTableName, number[]>,
606
+ materialRows: Map<MaterialSnapshot, Uint8Array>,
613
607
  temporal?: GpuSceneTemporalSnapshot,
614
608
  ): void {
615
609
  const allocation = this.allocations.get(record.slot);
616
610
  if (allocation === undefined) throw new RangeError('GPU Scene allocation unavailable');
617
- const primitiveOffset = record.slot * PRIMITIVE.stride;
618
- const primitive = new DataView(this.tableBytes.primitive);
611
+ this.rowScratch.fill(0);
612
+ const primitive = this.rowScratchView;
619
613
  const bounds = record.snapshot.localAabb;
620
- primitive.setUint32(primitiveOffset + offset(PRIMITIVE, 'generation'), record.generation, true);
614
+ primitive.setUint32(offset(PRIMITIVE, 'generation'), record.generation, true);
621
615
  primitive.setUint32(
622
- primitiveOffset + offset(PRIMITIVE, 'flags'),
616
+ offset(PRIMITIVE, 'flags'),
623
617
  PRIMITIVE_ACTIVE |
624
618
  (bounds === undefined ? 0 : PRIMITIVE_HAS_BOUNDS) |
625
619
  (record.snapshot.gpuDrivenDraws === undefined ? 0 : PRIMITIVE_GPU_DRIVEN),
626
620
  true,
627
621
  );
628
- primitive.setUint32(
629
- primitiveOffset + offset(PRIMITIVE, 'transformIndex'),
630
- allocation.transformStart,
631
- true,
632
- );
633
- primitive.setUint32(
634
- primitiveOffset + offset(PRIMITIVE, 'materialIndex'),
635
- allocation.materialStart,
636
- true,
637
- );
638
- primitive.setUint32(
639
- primitiveOffset + offset(PRIMITIVE, 'drawTemplateIndex'),
640
- allocation.drawStart,
641
- true,
642
- );
643
- primitive.setUint32(
644
- primitiveOffset + offset(PRIMITIVE, 'instanceStart'),
645
- allocation.instanceStart,
646
- true,
647
- );
648
- primitive.setUint32(
649
- primitiveOffset + offset(PRIMITIVE, 'instanceCount'),
650
- allocation.instanceCount,
651
- true,
652
- );
653
- primitive.setUint32(
654
- primitiveOffset + offset(PRIMITIVE, 'assetHandle'),
655
- record.snapshot.assetHandle,
656
- true,
657
- );
658
- writeVec4(primitive, primitiveOffset + offset(PRIMITIVE, 'localBoundsMin'), [
622
+ primitive.setUint32(offset(PRIMITIVE, 'transformIndex'), allocation.transformStart, true);
623
+ primitive.setUint32(offset(PRIMITIVE, 'materialIndex'), allocation.materialStart, true);
624
+ primitive.setUint32(offset(PRIMITIVE, 'drawTemplateIndex'), allocation.drawStart, true);
625
+ primitive.setUint32(offset(PRIMITIVE, 'instanceStart'), allocation.instanceStart, true);
626
+ primitive.setUint32(offset(PRIMITIVE, 'instanceCount'), allocation.instanceCount, true);
627
+ primitive.setUint32(offset(PRIMITIVE, 'assetHandle'), record.snapshot.assetHandle, true);
628
+ writeVec4(primitive, offset(PRIMITIVE, 'localBoundsMin'), [
659
629
  bounds?.[0] ?? 0,
660
630
  bounds?.[1] ?? 0,
661
631
  bounds?.[2] ?? 0,
662
632
  0,
663
633
  ]);
664
- writeVec4(primitive, primitiveOffset + offset(PRIMITIVE, 'localBoundsMax'), [
634
+ writeVec4(primitive, offset(PRIMITIVE, 'localBoundsMax'), [
665
635
  bounds?.[3] ?? 0,
666
636
  bounds?.[4] ?? 0,
667
637
  bounds?.[5] ?? 0,
668
638
  0,
669
639
  ]);
670
640
 
641
+ if (this.writeRow('primitive', record.slot, this.rowScratch) || resetPrevious)
642
+ writes.primitive.push(record.slot);
643
+
671
644
  const instance = new DataView(this.tableBytes.instance);
672
645
  const transform = this.transformView;
673
646
  const instances = record.snapshot.instances;
@@ -773,16 +746,15 @@ export class GpuScene {
773
746
  this.rememberInstanceGenerations(record.slot, currentGenerations, allocation.instanceCount);
774
747
 
775
748
  this.writeRootTransform(record, resetPrevious, writes);
776
- writes.primitive.push(record.slot);
777
749
 
778
- const draw = new DataView(this.tableBytes.drawTemplate);
750
+ const draw = this.rowScratchView;
779
751
  const drawSnapshots = record.snapshot.gpuDrivenDraws ?? [];
780
752
  for (let ordinal = 0; ordinal < allocation.drawCount; ordinal += 1) {
781
753
  const drawIndex = allocation.drawStart + ordinal;
782
- const drawOffset = drawIndex * DRAW_TEMPLATE.stride;
754
+ this.rowScratch.fill(0);
783
755
  const drawSnapshot = drawSnapshots[ordinal];
784
756
  draw.setUint32(
785
- drawOffset + offset(DRAW_TEMPLATE, 'pipelineClass'),
757
+ offset(DRAW_TEMPLATE, 'pipelineClass'),
786
758
  drawSnapshot === undefined
787
759
  ? 0
788
760
  : stableU32(
@@ -793,58 +765,77 @@ export class GpuScene {
793
765
  true,
794
766
  );
795
767
  draw.setUint32(
796
- drawOffset + offset(DRAW_TEMPLATE, 'materialIndex'),
768
+ offset(DRAW_TEMPLATE, 'materialIndex'),
797
769
  allocation.materialStart + (drawSnapshot?.materialSlot ?? 0),
798
770
  true,
799
771
  );
800
772
  draw.setUint32(
801
- drawOffset + offset(DRAW_TEMPLATE, 'firstIndex'),
773
+ offset(DRAW_TEMPLATE, 'firstIndex'),
802
774
  drawSnapshot?.prepared?.first ?? drawSnapshot?.first ?? 0,
803
775
  true,
804
776
  );
805
777
  draw.setUint32(
806
- drawOffset + offset(DRAW_TEMPLATE, 'indexCount'),
778
+ offset(DRAW_TEMPLATE, 'indexCount'),
807
779
  drawSnapshot?.prepared?.count ?? drawSnapshot?.count ?? 0,
808
780
  true,
809
781
  );
810
782
  draw.setInt32(
811
- drawOffset + offset(DRAW_TEMPLATE, 'baseVertex'),
783
+ offset(DRAW_TEMPLATE, 'baseVertex'),
812
784
  drawSnapshot?.prepared?.baseVertex ?? drawSnapshot?.baseVertex ?? 0,
813
785
  true,
814
786
  );
815
- draw.setUint32(drawOffset + offset(DRAW_TEMPLATE, 'firstInstance'), 0, true);
816
- draw.setUint32(drawOffset + offset(DRAW_TEMPLATE, 'passFlags'), 0, true);
817
- draw.setUint32(drawOffset + offset(DRAW_TEMPLATE, 'reserved'), 0, true);
818
- writes.drawTemplate.push(drawIndex);
787
+ draw.setUint32(offset(DRAW_TEMPLATE, 'firstInstance'), 0, true);
788
+ draw.setUint32(offset(DRAW_TEMPLATE, 'passFlags'), 0, true);
789
+ draw.setUint32(offset(DRAW_TEMPLATE, 'reserved'), 0, true);
790
+ if (this.writeRow('drawTemplate', drawIndex, this.rowScratch) || resetPrevious)
791
+ writes.drawTemplate.push(drawIndex);
819
792
  }
820
793
 
821
- this.writeMaterialSlot(record, writes);
794
+ this.writeMaterialSlot(record, writes, materialRows, resetPrevious);
795
+ }
796
+
797
+ /** Compare against the resident CPU bytes; pending upload rows survive failure. */
798
+ private writeRow(table: GpuSceneTableName, index: number, row: Uint8Array): boolean {
799
+ const stride = TABLE_LAYOUTS[table].stride;
800
+ const destination = new Uint8Array(this.tableBytes[table], index * stride, stride);
801
+ let changed = false;
802
+ for (let byte = 0; byte < stride; byte += 1) {
803
+ const value = row[byte] ?? 0;
804
+ if (destination[byte] === value) continue;
805
+ destination[byte] = value;
806
+ changed = true;
807
+ }
808
+ return changed;
822
809
  }
823
810
 
824
811
  private writeMaterialSlot(
825
812
  record: RenderSceneSlot,
826
813
  writes: Record<GpuSceneTableName, number[]>,
814
+ materialRows: Map<MaterialSnapshot, Uint8Array>,
815
+ reset: boolean,
827
816
  ): void {
828
817
  const allocation = this.allocations.get(record.slot);
829
818
  if (allocation === undefined) throw new RangeError('GPU Scene allocation unavailable');
830
819
  for (let ordinal = 0; ordinal < allocation.materialCount; ordinal += 1) {
831
820
  const materialIndex = allocation.materialStart + ordinal;
832
- const materialOffset = materialIndex * MATERIAL.stride;
833
821
  const snapshot = record.snapshot.materials[ordinal] ?? record.snapshot.material;
834
- const shaderId = snapshot.materialShaderId;
835
- const schema = snapshot.materialParamSchema;
836
- const row =
837
- shaderId !== undefined &&
838
- shaderId !== 'forgeax::default-standard-pbr' &&
839
- shaderId !== 'forgeax::pbr-skin' &&
840
- shaderId !== 'forgeax::default-standard-pbr-skin' &&
841
- schema !== undefined
842
- ? packMaterialProgramRow(schema, snapshot, MATERIAL.stride)
843
- : packStandardPbrMaterialRow(STANDARD_PBR_RECEIPT, snapshot);
844
- const destination = new Uint8Array(this.tableBytes.material, materialOffset, MATERIAL.stride);
845
- destination.fill(0);
846
- if (row !== undefined) destination.set(row.subarray(0, MATERIAL.stride));
847
- writes.material.push(materialIndex);
822
+ let row = materialRows.get(snapshot);
823
+ if (row === undefined) {
824
+ const shaderId = snapshot.materialShaderId;
825
+ const schema = snapshot.materialParamSchema;
826
+ row =
827
+ shaderId !== undefined &&
828
+ shaderId !== 'forgeax::default-standard-pbr' &&
829
+ shaderId !== 'forgeax::pbr-skin' &&
830
+ shaderId !== 'forgeax::default-standard-pbr-skin' &&
831
+ schema !== undefined
832
+ ? packMaterialProgramRow(schema, snapshot, MATERIAL.stride)
833
+ : packStandardPbrMaterialRow(STANDARD_PBR_RECEIPT, snapshot);
834
+ row ??= new Uint8Array(MATERIAL.stride);
835
+ materialRows.set(snapshot, row);
836
+ }
837
+ if (this.writeRow('material', materialIndex, row) || reset)
838
+ writes.material.push(materialIndex);
848
839
  }
849
840
  }
850
841
 
@@ -972,7 +963,7 @@ export class GpuScene {
972
963
  let rangeCount = 0;
973
964
  let bytes = 0;
974
965
  for (const name of TABLE_NAMES) {
975
- const ranges = coalesceSlots(rows[name]);
966
+ const ranges = this.dirtyRanges.coalesce(rows[name]);
976
967
  rangeCount += ranges.length;
977
968
  for (const range of ranges) {
978
969
  const layout = TABLE_LAYOUTS[name];
@@ -559,6 +559,7 @@ export function createHdrpUnifiedBindGroup(
559
559
  hdrpBuffers: HdrpBuffers,
560
560
  meshStorageBuffer: Buffer,
561
561
  ssaoOptions: SsaoBindOptions = { enabled: false },
562
+ meshBindingBytes = MESH_PER_ENTITY_STRIDE,
562
563
  ): BindGroup | null {
563
564
  const fallback = getOrCreateSsaoFallbackTexture(runtime);
564
565
  if (fallback === null) return null;
@@ -579,7 +580,7 @@ export function createHdrpUnifiedBindGroup(
579
580
  value: {
580
581
  buffer: meshStorageBuffer,
581
582
  offset: 0,
582
- size: MESH_PER_ENTITY_STRIDE,
583
+ size: meshBindingBytes,
583
584
  },
584
585
  },
585
586
  },
@@ -602,17 +603,17 @@ export function createHdrpSkinUnifiedBindGroup(
602
603
  paletteBuffer: Buffer,
603
604
  paletteBindingWindowBytes: number,
604
605
  ssaoOptions: SsaoBindOptions = { enabled: false },
606
+ meshBindingBytes = MESH_PER_ENTITY_STRIDE,
605
607
  ): BindGroup | null {
606
608
  const fallback = getOrCreateSsaoFallbackTexture(runtime);
607
609
  if (fallback === null) return null;
608
- const meshSize = MESH_PER_ENTITY_STRIDE;
609
610
  const result = runtime.device.createBindGroup({
610
611
  label: 'hdrp-skin-unified-bg-group2',
611
612
  layout,
612
613
  entries: [
613
614
  ...createPbrSkinMeshBindGroupEntries(
614
615
  meshStorageBuffer,
615
- meshSize,
616
+ meshBindingBytes,
616
617
  paletteBuffer,
617
618
  paletteBindingWindowBytes,
618
619
  ),
@@ -242,6 +242,16 @@ export interface TransmissionBindGroupResources {
242
242
  readonly backdropView?: TextureView | null;
243
243
  }
244
244
 
245
+ /** Renderer-owned sampled resources consumed by the single-layer medium. */
246
+ export interface SurfaceMediumBindGroupResources {
247
+ readonly rawDepthSampler: Sampler;
248
+ readonly rawDepthView: TextureView;
249
+ readonly nearestLayerSampler: Sampler;
250
+ readonly nearestLayerView: TextureView;
251
+ readonly nearestDepthSampler: Sampler;
252
+ readonly nearestDepthView: TextureView;
253
+ }
254
+
245
255
  /** Engine-owned texture injection resources derived from material parameters. */
246
256
  export interface TextureInjectionResource {
247
257
  readonly slot: number;
@@ -258,6 +268,7 @@ export function assembleMaterialWithSkylightEntries(
258
268
  skylight: SkylightBindGroupResources,
259
269
  transmission?: TransmissionBindGroupResources | null | undefined,
260
270
  textureInjections: readonly TextureInjectionResource[] = [],
271
+ surfaceMedium?: SurfaceMediumBindGroupResources | undefined,
261
272
  ): BindGroupEntry[] {
262
273
  // IBL injection start = end of the user-region. The user-region IS
263
274
  // `materialEntries` (UBO binding 0 + N sampler/texture pairs), so its length
@@ -314,6 +325,35 @@ export function assembleMaterialWithSkylightEntries(
314
325
  resource: { kind: 'textureView', value: transmissionView },
315
326
  },
316
327
  );
328
+ if (surfaceMedium !== undefined) {
329
+ const surfaceStart = result.length;
330
+ result.push(
331
+ {
332
+ binding: surfaceStart,
333
+ resource: { kind: 'sampler', value: surfaceMedium.rawDepthSampler },
334
+ },
335
+ {
336
+ binding: surfaceStart + 1,
337
+ resource: { kind: 'textureView', value: surfaceMedium.rawDepthView },
338
+ },
339
+ {
340
+ binding: surfaceStart + 2,
341
+ resource: { kind: 'sampler', value: surfaceMedium.nearestLayerSampler },
342
+ },
343
+ {
344
+ binding: surfaceStart + 3,
345
+ resource: { kind: 'textureView', value: surfaceMedium.nearestLayerView },
346
+ },
347
+ {
348
+ binding: surfaceStart + 4,
349
+ resource: { kind: 'sampler', value: surfaceMedium.nearestDepthSampler },
350
+ },
351
+ {
352
+ binding: surfaceStart + 5,
353
+ resource: { kind: 'textureView', value: surfaceMedium.nearestDepthView },
354
+ },
355
+ );
356
+ }
317
357
  // Standard physical maps occupy fixed bindings 26..45. The `slot` value
318
358
  // is the canonical index from STANDARD_PHYSICAL_TEXTURE_FIELDS; preserve
319
359
  // gaps for omitted authored maps instead of compacting this tail.
@@ -333,13 +373,15 @@ export function assembleMaterialWithSkylightEntries(
333
373
  },
334
374
  );
335
375
  }
336
- result.push({
337
- binding: 47,
338
- resource: {
339
- kind: 'textureView',
340
- value: skylight.skylightPrefilterView ?? skylight.prefilterView,
341
- },
342
- });
376
+ if (surfaceMedium === undefined) {
377
+ result.push({
378
+ binding: 47,
379
+ resource: {
380
+ kind: 'textureView',
381
+ value: skylight.skylightPrefilterView ?? skylight.prefilterView,
382
+ },
383
+ });
384
+ }
343
385
  return result;
344
386
  }
345
387