@forgeax/engine-render 0.1.33 → 0.1.35

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 (624) hide show
  1. package/README.md +1062 -127
  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/device-feature-admission.d.ts +2 -2
  11. package/dist/assembly/dynamic-geometry-host.d.ts +4 -1
  12. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
  13. package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
  14. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
  15. package/dist/assembly/factory.d.ts +1 -1
  16. package/dist/assembly/factory.d.ts.map +1 -1
  17. package/dist/assembly/host-contract.d.ts +6 -5
  18. package/dist/assembly/host-contract.d.ts.map +1 -1
  19. package/dist/assembly/material/assembly.d.ts.map +1 -1
  20. package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
  21. package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
  22. package/dist/assembly/material-shader-policy.d.ts +16 -2
  23. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  24. package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
  25. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
  26. package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
  27. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  28. package/dist/assembly/render-feature-post-processes.d.ts +6 -0
  29. package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
  30. package/dist/assembly/render-target-host.d.ts +5 -0
  31. package/dist/assembly/render-target-host.d.ts.map +1 -1
  32. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  33. package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
  34. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
  35. package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
  36. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  37. package/dist/assembly/renderer-inspection.d.ts +11 -0
  38. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  39. package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
  40. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
  41. package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
  42. package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
  43. package/dist/assembly/webgpu-ready.d.ts +1 -1
  44. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  45. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
  46. package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
  47. package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
  48. package/dist/assembly/webgpu-renderer.d.ts +2 -1
  49. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  50. package/dist/authoring.mjs +2 -4
  51. package/dist/authoring.mjs.map +1 -1
  52. package/dist/barrel-distortion.d.ts +47 -0
  53. package/dist/barrel-distortion.d.ts.map +1 -0
  54. package/dist/chunk-3XUBWRY2.mjs +1842 -0
  55. package/dist/chunk-3XUBWRY2.mjs.map +1 -0
  56. package/dist/{chunk-OO3DRYK7.mjs → chunk-G6HDNGY7.mjs} +2400 -1767
  57. package/dist/chunk-G6HDNGY7.mjs.map +1 -0
  58. package/dist/{chunk-ZDQWGQW7.mjs → chunk-LM5IE7GF.mjs} +4 -4
  59. package/dist/{chunk-ZDQWGQW7.mjs.map → chunk-LM5IE7GF.mjs.map} +1 -1
  60. package/dist/{chunk-VOZWDM3L.mjs → chunk-LNIUIKQ7.mjs} +1514 -498
  61. package/dist/chunk-LNIUIKQ7.mjs.map +1 -0
  62. package/dist/chunk-MXTWKZO4.mjs +3268 -0
  63. package/dist/chunk-MXTWKZO4.mjs.map +1 -0
  64. package/dist/chunk-MZ4C7EHF.mjs +6942 -0
  65. package/dist/chunk-MZ4C7EHF.mjs.map +1 -0
  66. package/dist/chunk-RIPAEGI6.mjs +48 -0
  67. package/dist/chunk-RIPAEGI6.mjs.map +1 -0
  68. package/dist/{chunk-LEAXOMYJ.mjs → chunk-SGPUJW3F.mjs} +117 -5
  69. package/dist/chunk-SGPUJW3F.mjs.map +1 -0
  70. package/dist/{chunk-PA5DRJNI.mjs → chunk-X2KA6WHM.mjs} +29 -4
  71. package/dist/chunk-X2KA6WHM.mjs.map +1 -0
  72. package/dist/{chunk-BLXGONR2.mjs → chunk-XSFB7XXQ.mjs} +51 -4
  73. package/dist/chunk-XSFB7XXQ.mjs.map +1 -0
  74. package/dist/cloud/density.d.ts +55 -0
  75. package/dist/cloud/density.d.ts.map +1 -0
  76. package/dist/cloud/extract.d.ts +25 -0
  77. package/dist/cloud/extract.d.ts.map +1 -0
  78. package/dist/cloud/feature.d.ts +57 -0
  79. package/dist/cloud/feature.d.ts.map +1 -0
  80. package/dist/cloud/frame-context.d.ts +8 -0
  81. package/dist/cloud/frame-context.d.ts.map +1 -0
  82. package/dist/cloud/inspection.d.ts +59 -0
  83. package/dist/cloud/inspection.d.ts.map +1 -0
  84. package/dist/cloud/optics.d.ts +56 -0
  85. package/dist/cloud/optics.d.ts.map +1 -0
  86. package/dist/cloud/parameters.d.ts +73 -0
  87. package/dist/cloud/parameters.d.ts.map +1 -0
  88. package/dist/cloud/resources.d.ts +60 -0
  89. package/dist/cloud/resources.d.ts.map +1 -0
  90. package/dist/cloud/shadow.d.ts +42 -0
  91. package/dist/cloud/shadow.d.ts.map +1 -0
  92. package/dist/cloud/temporal.d.ts +74 -0
  93. package/dist/cloud/temporal.d.ts.map +1 -0
  94. package/dist/components/barrel-distortion.d.ts +13 -0
  95. package/dist/components/barrel-distortion.d.ts.map +1 -0
  96. package/dist/components/cloud-layer.d.ts +29 -0
  97. package/dist/components/cloud-layer.d.ts.map +1 -0
  98. package/dist/components/index.d.ts +2 -0
  99. package/dist/components/index.d.ts.map +1 -1
  100. package/dist/components/instances.d.ts +20 -6
  101. package/dist/components/instances.d.ts.map +1 -1
  102. package/dist/construct-renderer.d.ts +1 -1
  103. package/dist/construct-renderer.d.ts.map +1 -1
  104. package/dist/construct-renderer.mjs +8406 -5785
  105. package/dist/construct-renderer.mjs.map +1 -1
  106. package/dist/device/gpu-residency.d.ts +19 -19
  107. package/dist/device/gpu-residency.d.ts.map +1 -1
  108. package/dist/dynamic-geometry.d.ts +5 -1
  109. package/dist/dynamic-geometry.d.ts.map +1 -1
  110. package/dist/errors/cloud.d.ts +59 -0
  111. package/dist/errors/cloud.d.ts.map +1 -0
  112. package/dist/errors/render.d.ts +20 -5
  113. package/dist/errors/render.d.ts.map +1 -1
  114. package/dist/examples/single-layer-medium-surface.d.ts +47 -0
  115. package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
  116. package/dist/extract/camera.d.ts.map +1 -1
  117. package/dist/extract/contracts.d.ts +5 -1
  118. package/dist/extract/contracts.d.ts.map +1 -1
  119. package/dist/extract/material-context.d.ts +7 -0
  120. package/dist/extract/material-context.d.ts.map +1 -0
  121. package/dist/features/barrel-distortion.d.ts +29 -0
  122. package/dist/features/barrel-distortion.d.ts.map +1 -0
  123. package/dist/features/error-reporting.d.ts +6 -2
  124. package/dist/features/error-reporting.d.ts.map +1 -1
  125. package/dist/features/host.d.ts +15 -0
  126. package/dist/features/host.d.ts.map +1 -1
  127. package/dist/features/plan.d.ts +10 -0
  128. package/dist/features/plan.d.ts.map +1 -1
  129. package/dist/features/render-graph-contribution.d.ts +5 -0
  130. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  131. package/dist/features/render-graph-raster.d.ts +1 -0
  132. package/dist/features/render-graph-raster.d.ts.map +1 -1
  133. package/dist/features/targets.d.ts +2 -0
  134. package/dist/features/targets.d.ts.map +1 -1
  135. package/dist/features/types.d.ts +48 -0
  136. package/dist/features/types.d.ts.map +1 -1
  137. package/dist/fullscreen-post-process-pass.d.ts +15 -7
  138. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  139. package/dist/glyph-text-layout-system.d.ts +1 -1
  140. package/dist/glyph-text-layout-system.d.ts.map +1 -1
  141. package/dist/gpu-dirty-ranges.d.ts +11 -0
  142. package/dist/gpu-dirty-ranges.d.ts.map +1 -0
  143. package/dist/gpu-driven/batch-topology.d.ts +17 -0
  144. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  145. package/dist/gpu-driven/material-artifacts.d.ts +6 -0
  146. package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
  147. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  148. package/dist/gpu-driven/production-raster-material.d.ts +178 -0
  149. package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
  150. package/dist/gpu-driven/production-raster.d.ts +47 -3
  151. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  152. package/dist/gpu-driven/resource-allocation.d.ts +31 -0
  153. package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
  154. package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
  155. package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
  156. package/dist/gpu-driven/view-gpu.d.ts +26 -2
  157. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  158. package/dist/gpu-scene.d.ts +5 -0
  159. package/dist/gpu-scene.d.ts.map +1 -1
  160. package/dist/hdrp-buffers.d.ts +2 -2
  161. package/dist/hdrp-buffers.d.ts.map +1 -1
  162. package/dist/ibl/frame-resources.d.ts.map +1 -1
  163. package/dist/ibl/skylight-bind-group.d.ts +14 -5
  164. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  165. package/dist/index.d.ts +30 -7
  166. package/dist/index.d.ts.map +1 -1
  167. package/dist/index.mjs +780 -9
  168. package/dist/index.mjs.map +1 -1
  169. package/dist/inspection-types.d.ts +135 -1
  170. package/dist/inspection-types.d.ts.map +1 -1
  171. package/dist/instance-buffer-cache.d.ts +4 -4
  172. package/dist/instance-buffer-cache.d.ts.map +1 -1
  173. package/dist/instances.d.ts +47 -100
  174. package/dist/instances.d.ts.map +1 -1
  175. package/dist/internal.mjs +7 -8
  176. package/dist/internal.mjs.map +1 -1
  177. package/dist/pbr-pipeline.d.ts +22 -4
  178. package/dist/pbr-pipeline.d.ts.map +1 -1
  179. package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
  180. package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
  181. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  182. package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
  183. package/dist/pipeline/standard-output/lut-gpu.d.ts +2 -2
  184. package/dist/pipeline/standard-output/lut-gpu.d.ts.map +1 -1
  185. package/dist/pipeline/standard-output/resources.d.ts +2 -2
  186. package/dist/pipeline/standard-output/resources.d.ts.map +1 -1
  187. package/dist/pipeline/standard-output/types.d.ts +4 -2
  188. package/dist/pipeline/standard-output/types.d.ts.map +1 -1
  189. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  190. package/dist/pipeline/standard-post.d.ts.map +1 -1
  191. package/dist/pipeline-builder.d.ts +1 -1
  192. package/dist/pipeline-builder.d.ts.map +1 -1
  193. package/dist/plugin.d.ts.map +1 -1
  194. package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
  195. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  196. package/dist/publication/contract.d.ts +77 -0
  197. package/dist/publication/contract.d.ts.map +1 -0
  198. package/dist/publication/dependencies.d.ts +7 -0
  199. package/dist/publication/dependencies.d.ts.map +1 -0
  200. package/dist/publication/prepare-geometry.d.ts +9 -0
  201. package/dist/publication/prepare-geometry.d.ts.map +1 -0
  202. package/dist/publication/programs.d.ts +5 -0
  203. package/dist/publication/programs.d.ts.map +1 -0
  204. package/dist/publication/publisher.d.ts +33 -0
  205. package/dist/publication/publisher.d.ts.map +1 -0
  206. package/dist/publication/receiver.d.ts +29 -0
  207. package/dist/publication/receiver.d.ts.map +1 -0
  208. package/dist/publication/resource-scope.d.ts +18 -0
  209. package/dist/publication/resource-scope.d.ts.map +1 -0
  210. package/dist/publication/targets.d.ts +33 -0
  211. package/dist/publication/targets.d.ts.map +1 -0
  212. package/dist/publication/video.d.ts +5 -0
  213. package/dist/publication/video.d.ts.map +1 -0
  214. package/dist/record/barrel-distortion-frame.d.ts +15 -0
  215. package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
  216. package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
  217. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
  218. package/dist/record/fold-buckets.d.ts +95 -0
  219. package/dist/record/fold-buckets.d.ts.map +1 -0
  220. package/dist/record/fold-instance-buffer.d.ts +6 -0
  221. package/dist/record/fold-instance-buffer.d.ts.map +1 -0
  222. package/dist/record/frame-lighting.d.ts +1 -0
  223. package/dist/record/frame-lighting.d.ts.map +1 -1
  224. package/dist/record/frame-snapshot.d.ts +43 -9
  225. package/dist/record/frame-snapshot.d.ts.map +1 -1
  226. package/dist/record/frame.d.ts +15 -65
  227. package/dist/record/frame.d.ts.map +1 -1
  228. package/dist/record/gpu-draw-receipts.d.ts +11 -0
  229. package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
  230. package/dist/record/gpu-timing.d.ts +8 -0
  231. package/dist/record/gpu-timing.d.ts.map +1 -1
  232. package/dist/record/helpers.d.ts +2 -2
  233. package/dist/record/helpers.d.ts.map +1 -1
  234. package/dist/record/main-pass-geometry.d.ts +22 -6
  235. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  236. package/dist/record/main-pass-material.d.ts +14 -10
  237. package/dist/record/main-pass-material.d.ts.map +1 -1
  238. package/dist/record/main-pass-sprite-draws.d.ts +3 -16
  239. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  240. package/dist/record/main-pass.d.ts +13 -2
  241. package/dist/record/main-pass.d.ts.map +1 -1
  242. package/dist/record/motion-blur-receipt.d.ts +11 -0
  243. package/dist/record/motion-blur-receipt.d.ts.map +1 -0
  244. package/dist/record/prepared-material-bindings.d.ts +3 -3
  245. package/dist/record/prepared-material-bindings.d.ts.map +1 -1
  246. package/dist/record/probe-blend-buffer.d.ts +16 -0
  247. package/dist/record/probe-blend-buffer.d.ts.map +1 -0
  248. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  249. package/dist/record/render-context.d.ts +24 -5
  250. package/dist/record/render-context.d.ts.map +1 -1
  251. package/dist/record/shadow-pass.d.ts +2 -0
  252. package/dist/record/shadow-pass.d.ts.map +1 -1
  253. package/dist/record/skybox-post-pass.d.ts +1 -1
  254. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  255. package/dist/record/sprite-instance-buffer.d.ts +31 -0
  256. package/dist/record/sprite-instance-buffer.d.ts.map +1 -0
  257. package/dist/record/target-capture-graph.d.ts +19 -0
  258. package/dist/record/target-capture-graph.d.ts.map +1 -0
  259. package/dist/record/typed-frame-graph.d.ts +24 -15
  260. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  261. package/dist/record/view-ubo.d.ts +11 -3
  262. package/dist/record/view-ubo.d.ts.map +1 -1
  263. package/dist/record/volume-params.d.ts +9 -0
  264. package/dist/record/volume-params.d.ts.map +1 -0
  265. package/dist/recovery/render-system-candidate.d.ts +14 -4
  266. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  267. package/dist/reflection/record-owner.d.ts.map +1 -1
  268. package/dist/render-contract.d.ts +46 -5
  269. package/dist/render-contract.d.ts.map +1 -1
  270. package/dist/render-graph-primitives.d.ts.map +1 -1
  271. package/dist/render-pipeline.d.ts +103 -2
  272. package/dist/render-pipeline.d.ts.map +1 -1
  273. package/dist/render-system-extract-tail.d.ts +3 -2
  274. package/dist/render-system-extract-tail.d.ts.map +1 -1
  275. package/dist/render-system-extract.d.ts +18 -9
  276. package/dist/render-system-extract.d.ts.map +1 -1
  277. package/dist/render-system-presentation.d.ts +23 -0
  278. package/dist/render-system-presentation.d.ts.map +1 -0
  279. package/dist/render-system-producer-roots.d.ts +10 -0
  280. package/dist/render-system-producer-roots.d.ts.map +1 -0
  281. package/dist/render-system-projections.d.ts +3 -2
  282. package/dist/render-system-projections.d.ts.map +1 -1
  283. package/dist/render-system-residency.d.ts +12 -0
  284. package/dist/render-system-residency.d.ts.map +1 -0
  285. package/dist/render-system.d.ts +22 -21
  286. package/dist/render-system.d.ts.map +1 -1
  287. package/dist/scene/probe-blend.d.ts +27 -0
  288. package/dist/scene/probe-blend.d.ts.map +1 -1
  289. package/dist/scene/render-scene.d.ts +18 -7
  290. package/dist/scene/render-scene.d.ts.map +1 -1
  291. package/dist/scene/render-source.d.ts +42 -0
  292. package/dist/scene/render-source.d.ts.map +1 -0
  293. package/dist/scene/source-systems.d.ts +6 -0
  294. package/dist/scene/source-systems.d.ts.map +1 -0
  295. package/dist/ssao-buffers.d.ts +9 -0
  296. package/dist/ssao-buffers.d.ts.map +1 -1
  297. package/dist/surface/dynamic-input.d.ts +133 -0
  298. package/dist/surface/dynamic-input.d.ts.map +1 -0
  299. package/dist/surface/gpu-driven.d.ts +41 -0
  300. package/dist/surface/gpu-driven.d.ts.map +1 -0
  301. package/dist/surface/submission-observation.d.ts +136 -0
  302. package/dist/surface/submission-observation.d.ts.map +1 -0
  303. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  304. package/dist/systems/skin-palette-types.d.ts +10 -0
  305. package/dist/systems/skin-palette-types.d.ts.map +1 -1
  306. package/dist/systems/transparent-dispatch.d.ts +2 -2
  307. package/dist/systems/transparent-dispatch.d.ts.map +1 -1
  308. package/dist/systems/transparent-sort-config.d.ts +2 -1
  309. package/dist/systems/transparent-sort-config.d.ts.map +1 -1
  310. package/dist/temporal/gpu.d.ts +13 -1
  311. package/dist/temporal/gpu.d.ts.map +1 -1
  312. package/dist/temporal/index.mjs +6 -7
  313. package/dist/temporal/inspection.d.ts.map +1 -1
  314. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  315. package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
  316. package/dist/transmission/single-layer-medium.d.ts +89 -0
  317. package/dist/transmission/single-layer-medium.d.ts.map +1 -0
  318. package/dist/typed-render-graph-primitives.d.ts +14 -2
  319. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  320. package/dist/volume/component.d.ts +9 -4
  321. package/dist/volume/component.d.ts.map +1 -1
  322. package/dist/volume/extract.d.ts +1 -1
  323. package/dist/volume/extract.d.ts.map +1 -1
  324. package/dist/volume/inspection.d.ts +2 -0
  325. package/dist/volume/inspection.d.ts.map +1 -1
  326. package/dist/volume/passes.d.ts +4 -1
  327. package/dist/volume/passes.d.ts.map +1 -1
  328. package/dist/volume/resources.d.ts.map +1 -1
  329. package/package.json +22 -21
  330. package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
  331. package/src/__tests__/auto-exposure-transaction.integration.test.ts +4 -9
  332. package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
  333. package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
  334. package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
  335. package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
  336. package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
  337. package/src/__tests__/device-feature-admission.unit.test.ts +3 -2
  338. package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
  339. package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
  340. package/src/__tests__/factory-contract.integration.test.ts +295 -45
  341. package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
  342. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +14 -3
  343. package/src/__tests__/gpu-dirty-ranges.unit.test.ts +22 -0
  344. package/src/__tests__/gpu-driven-baseline.characterization.test.ts +16 -3
  345. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +12 -0
  346. package/src/__tests__/gpu-driven-material-artifacts.unit.test.ts +143 -0
  347. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +5 -6
  348. package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
  349. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +6 -5
  350. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +94 -6
  351. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
  352. package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
  353. package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
  354. package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
  355. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
  356. package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
  357. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
  358. package/src/__tests__/gpu-scene.unit.test.ts +119 -9
  359. package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
  360. package/src/__tests__/instances-culling.integration.test.ts +10 -36
  361. package/src/__tests__/instances-store.unit.test.ts +97 -305
  362. package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
  363. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +4 -1
  364. package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +145 -0
  365. package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
  366. package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
  367. package/src/__tests__/materials-standard-contract.unit.test.ts +0 -1
  368. package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
  369. package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
  370. package/src/__tests__/motion-blur-compute.dawn.test.ts +13 -7
  371. package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
  372. package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
  373. package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
  374. package/src/__tests__/physical-clearcoat.integration.test.ts +66 -8
  375. package/src/__tests__/physical-material-budget.unit.test.ts +40 -0
  376. package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
  377. package/src/__tests__/probe-bindings.unit.test.ts +582 -1
  378. package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
  379. package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
  380. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
  381. package/src/__tests__/render-error-code-owner.test-d.ts +8 -0
  382. package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
  383. package/src/__tests__/render-feature-error-reporting.unit.test.ts +21 -1
  384. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
  385. package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
  386. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
  387. package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
  388. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +20 -20
  389. package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
  390. package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
  391. package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
  392. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +42 -8
  393. package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
  394. package/src/__tests__/renderer-frame-transaction.integration.test.ts +26 -10
  395. package/src/__tests__/resource-allocation.unit.test.ts +123 -0
  396. package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
  397. package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
  398. package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
  399. package/src/__tests__/skinned-shadow-caster.test.ts +15 -0
  400. package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
  401. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
  402. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
  403. package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
  404. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
  405. package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
  406. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
  407. package/src/__tests__/standard-pipeline.integration.test.ts +182 -1
  408. package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
  409. package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
  410. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
  411. package/src/__tests__/temporal-performance.integration.test.ts +3 -3
  412. package/src/__tests__/visibility-instances.integration.test.ts +7 -19
  413. package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
  414. package/src/__tests__/volume-optics-oracle.unit.test.ts +4 -2
  415. package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +30 -20
  416. package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
  417. package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
  418. package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
  419. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +113 -9
  420. package/src/__tests__/volumetric-fog-topology.unit.test.ts +5 -3
  421. package/src/assembly/backend-contract.ts +30 -0
  422. package/src/assembly/barrel-distortion-inspection.ts +22 -0
  423. package/src/assembly/canvas-draw-guard.ts +11 -0
  424. package/src/assembly/cloud-shadow-entry.ts +22 -0
  425. package/src/assembly/device-feature-admission.ts +2 -2
  426. package/src/assembly/dynamic-geometry-host.ts +65 -37
  427. package/src/assembly/dynamic-geometry-runtime.ts +7 -1
  428. package/src/assembly/factory.ts +2 -30
  429. package/src/assembly/host-contract.ts +8 -5
  430. package/src/assembly/material/assembly.ts +25 -13
  431. package/src/assembly/material/pipeline-helpers.ts +53 -12
  432. package/src/assembly/material-shader-policy.ts +55 -0
  433. package/src/assembly/material-shader-prewarm.ts +21 -10
  434. package/src/assembly/recovery/device-loss-fanout.ts +13 -0
  435. package/src/assembly/recovery/renderer-recover.ts +50 -18
  436. package/src/assembly/render-feature-post-processes.ts +54 -0
  437. package/src/assembly/render-target-host.ts +57 -47
  438. package/src/assembly/renderer-facade.ts +7 -2
  439. package/src/assembly/renderer-feature-inspection.ts +8 -2
  440. package/src/assembly/renderer-frame-transaction.ts +23 -0
  441. package/src/assembly/renderer-inspection.ts +28 -0
  442. package/src/assembly/skin-palette-owner.ts +1 -1
  443. package/src/assembly/temporal-post-process-prewarm.ts +3 -3
  444. package/src/assembly/webgpu-pbr-ready.ts +9 -1
  445. package/src/assembly/webgpu-ready-per-pass.ts +104 -0
  446. package/src/assembly/webgpu-ready.ts +116 -62
  447. package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
  448. package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
  449. package/src/assembly/webgpu-renderer.ts +303 -313
  450. package/src/assembly/webgpu-vertex-layouts.ts +1 -1
  451. package/src/barrel-distortion.ts +247 -0
  452. package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
  453. package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
  454. package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
  455. package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
  456. package/src/cloud/density.ts +600 -0
  457. package/src/cloud/extract.ts +110 -0
  458. package/src/cloud/feature.ts +1810 -0
  459. package/src/cloud/frame-context.ts +42 -0
  460. package/src/cloud/inspection.ts +130 -0
  461. package/src/cloud/optics.ts +285 -0
  462. package/src/cloud/parameters.ts +255 -0
  463. package/src/cloud/resources.ts +122 -0
  464. package/src/cloud/shadow.ts +167 -0
  465. package/src/cloud/temporal.ts +226 -0
  466. package/src/components/barrel-distortion.ts +46 -0
  467. package/src/components/cloud-layer.ts +47 -0
  468. package/src/components/index.ts +2 -0
  469. package/src/components/instances.ts +18 -45
  470. package/src/components/sprite-instances.ts +1 -1
  471. package/src/construct-renderer.ts +1 -1
  472. package/src/device/gpu-residency.ts +26 -25
  473. package/src/dynamic-geometry.ts +12 -1
  474. package/src/errors/cloud.ts +103 -0
  475. package/src/errors/render.ts +47 -8
  476. package/src/examples/single-layer-medium-surface.ts +59 -0
  477. package/src/extract/camera.ts +15 -1
  478. package/src/extract/contracts.ts +5 -0
  479. package/src/extract/material-context.ts +21 -0
  480. package/src/features/barrel-distortion.ts +172 -0
  481. package/src/features/error-reporting.ts +26 -6
  482. package/src/features/host.ts +128 -19
  483. package/src/features/plan.ts +10 -0
  484. package/src/features/render-graph-contribution.ts +9 -0
  485. package/src/features/render-graph-raster.ts +45 -3
  486. package/src/features/targets.ts +66 -0
  487. package/src/features/types.ts +51 -0
  488. package/src/fullscreen-post-process-pass.ts +41 -9
  489. package/src/glyph-text-layout-system.ts +2 -2
  490. package/src/gpu-dirty-ranges.ts +48 -0
  491. package/src/gpu-driven/batch-topology.ts +53 -0
  492. package/src/gpu-driven/material-artifacts.ts +33 -25
  493. package/src/gpu-driven/prepared-draw.ts +12 -4
  494. package/src/gpu-driven/production-raster-material.ts +1894 -0
  495. package/src/gpu-driven/production-raster.ts +825 -784
  496. package/src/gpu-driven/resource-allocation.ts +142 -0
  497. package/src/gpu-driven/shadow-ownership.ts +71 -0
  498. package/src/gpu-driven/view-gpu.ts +164 -10
  499. package/src/gpu-scene.ts +75 -84
  500. package/src/hdrp-buffers.ts +4 -3
  501. package/src/ibl/frame-resources.ts +0 -1
  502. package/src/ibl/skylight-bind-group.ts +62 -32
  503. package/src/index.ts +205 -9
  504. package/src/inspection-types.ts +162 -0
  505. package/src/instance-buffer-cache.ts +4 -4
  506. package/src/instances.ts +152 -569
  507. package/src/pbr-pipeline.ts +230 -30
  508. package/src/pipeline/single-layer-medium-passes.ts +267 -0
  509. package/src/pipeline/standard-forward-lane.ts +313 -57
  510. package/src/pipeline/standard-output/graph.ts +8 -2
  511. package/src/pipeline/standard-output/lut-gpu.ts +3 -3
  512. package/src/pipeline/standard-output/resources.ts +2 -2
  513. package/src/pipeline/standard-output/types.ts +12 -1
  514. package/src/pipeline/standard-pipeline.ts +291 -18
  515. package/src/pipeline/standard-post.ts +90 -24
  516. package/src/pipeline-builder.ts +1 -1
  517. package/src/plugin.ts +4 -0
  518. package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
  519. package/src/prepare/prepared-graphics-resolver.ts +2 -0
  520. package/src/publication/__tests__/derived-geometry.integration.test.ts +177 -0
  521. package/src/publication/__tests__/features.integration.test.ts +122 -0
  522. package/src/publication/__tests__/programs.unit.test.ts +25 -0
  523. package/src/publication/__tests__/publication.integration.test.ts +370 -0
  524. package/src/publication/__tests__/targets.integration.test.ts +120 -0
  525. package/src/publication/__tests__/video.browser.test.ts +50 -0
  526. package/src/publication/contract.ts +104 -0
  527. package/src/publication/dependencies.ts +54 -0
  528. package/src/publication/prepare-geometry.ts +94 -0
  529. package/src/publication/programs.ts +45 -0
  530. package/src/publication/publisher.ts +618 -0
  531. package/src/publication/receiver.ts +297 -0
  532. package/src/publication/resource-scope.ts +31 -0
  533. package/src/publication/targets.ts +182 -0
  534. package/src/publication/video.ts +33 -0
  535. package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
  536. package/src/record/__tests__/material-bg-cache.unit.test.ts +15 -1
  537. package/src/record/__tests__/sprite-material-abi.unit.test.ts +9 -11
  538. package/src/record/__tests__/temporal-payload.unit.test.ts +1 -1
  539. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
  540. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
  541. package/src/record/__tests__/video-texture-view.unit.test.ts +9 -9
  542. package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
  543. package/src/record/barrel-distortion-frame.ts +110 -0
  544. package/src/record/dynamic-geometry-consumption.ts +39 -9
  545. package/src/record/fold-buckets.ts +855 -0
  546. package/src/record/fold-instance-buffer.ts +51 -0
  547. package/src/record/frame-lighting.ts +36 -2
  548. package/src/record/frame-snapshot.ts +45 -9
  549. package/src/record/frame.ts +258 -1105
  550. package/src/record/gpu-draw-receipts.ts +38 -0
  551. package/src/record/gpu-timing.ts +48 -5
  552. package/src/record/helpers.ts +2 -2
  553. package/src/record/main-pass-geometry.ts +272 -84
  554. package/src/record/main-pass-material.ts +102 -36
  555. package/src/record/main-pass-sprite-draws.ts +13 -217
  556. package/src/record/main-pass.ts +164 -27
  557. package/src/record/motion-blur-receipt.ts +91 -0
  558. package/src/record/prepared-material-bindings.ts +11 -6
  559. package/src/record/probe-blend-buffer.ts +180 -0
  560. package/src/record/recovery-pipeline.ts +35 -3
  561. package/src/record/render-context.ts +41 -5
  562. package/src/record/shadow-pass.ts +30 -4
  563. package/src/record/skybox-post-pass.ts +28 -4
  564. package/src/record/sprite-instance-buffer.ts +155 -0
  565. package/src/record/target-capture-graph.ts +258 -0
  566. package/src/record/typed-frame-graph.ts +776 -340
  567. package/src/record/view-ubo.ts +27 -4
  568. package/src/record/volume-params.ts +225 -0
  569. package/src/recovery/render-system-candidate.ts +243 -50
  570. package/src/reflection/record-owner.ts +7 -3
  571. package/src/render-contract.ts +54 -5
  572. package/src/render-graph-primitives.ts +7 -1
  573. package/src/render-pipeline.ts +130 -0
  574. package/src/render-system-extract-tail.ts +90 -78
  575. package/src/render-system-extract.ts +76 -76
  576. package/src/render-system-presentation.ts +56 -0
  577. package/src/render-system-producer-roots.ts +96 -0
  578. package/src/render-system-projections.ts +3 -2
  579. package/src/render-system-residency.ts +159 -0
  580. package/src/render-system.ts +421 -408
  581. package/src/scene/probe-blend.ts +96 -4
  582. package/src/scene/render-scene.ts +416 -337
  583. package/src/scene/render-source.ts +90 -0
  584. package/src/scene/source-systems.ts +33 -0
  585. package/src/ssao-buffers.ts +95 -2
  586. package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
  587. package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
  588. package/src/surface/dynamic-input.ts +658 -0
  589. package/src/surface/gpu-driven.ts +147 -0
  590. package/src/surface/submission-observation.ts +517 -0
  591. package/src/systems/skin-palette-allocator.ts +5 -1
  592. package/src/systems/skin-palette-types.ts +11 -0
  593. package/src/systems/transparent-dispatch.ts +2 -2
  594. package/src/systems/transparent-sort-config.ts +3 -1
  595. package/src/temporal/gpu.ts +101 -17
  596. package/src/temporal/inspection.ts +7 -1
  597. package/src/temporal/standard-scene-data.ts +5 -0
  598. package/src/temporal/target-coverage-attachment.ts +4 -0
  599. package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
  600. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
  601. package/src/transmission/single-layer-medium.ts +322 -0
  602. package/src/typed-render-graph-primitives.ts +70 -2
  603. package/src/volume/component.ts +10 -9
  604. package/src/volume/extract.ts +11 -5
  605. package/src/volume/inspection.ts +3 -0
  606. package/src/volume/passes.ts +87 -4
  607. package/src/volume/resources.ts +2 -1
  608. package/dist/chunk-3RTCJTH4.mjs +0 -1610
  609. package/dist/chunk-3RTCJTH4.mjs.map +0 -1
  610. package/dist/chunk-BLXGONR2.mjs.map +0 -1
  611. package/dist/chunk-ILQ5MEZF.mjs +0 -32
  612. package/dist/chunk-ILQ5MEZF.mjs.map +0 -1
  613. package/dist/chunk-LEAXOMYJ.mjs.map +0 -1
  614. package/dist/chunk-NB2S7ZRX.mjs +0 -1783
  615. package/dist/chunk-NB2S7ZRX.mjs.map +0 -1
  616. package/dist/chunk-NNQL7CB3.mjs +0 -1713
  617. package/dist/chunk-NNQL7CB3.mjs.map +0 -1
  618. package/dist/chunk-OO3DRYK7.mjs.map +0 -1
  619. package/dist/chunk-PA5DRJNI.mjs.map +0 -1
  620. package/dist/chunk-PLAXOOX5.mjs +0 -1907
  621. package/dist/chunk-PLAXOOX5.mjs.map +0 -1
  622. package/dist/chunk-RXZ3RGOU.mjs +0 -53
  623. package/dist/chunk-RXZ3RGOU.mjs.map +0 -1
  624. package/dist/chunk-VOZWDM3L.mjs.map +0 -1
@@ -7,8 +7,13 @@ import { BatchTopology } from '../gpu-driven/batch-topology';
7
7
  import { GPU_DRIVEN_VIEW_WGSL, GpuDrivenView } from '../gpu-driven/view-gpu';
8
8
  import { GpuScene } from '../gpu-scene';
9
9
  import { GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_MAP_READ } from '../gpu-usage';
10
+ import { getOpaqueResourceIdentity } from '../record/frame-snapshot';
10
11
  import type { MaterialSnapshot, RenderableSnapshot } from '../render-system-extract';
11
12
  import { RenderScene } from '../scene/render-scene';
13
+ import {
14
+ type SurfaceSubmissionCandidate,
15
+ SurfaceSubmissionObservationOwner,
16
+ } from '../surface/submission-observation';
12
17
 
13
18
  const GPU_MAP_MODE_READ = 0x0001;
14
19
 
@@ -62,6 +67,10 @@ export interface GpuDrivenViewGpuEvidence {
62
67
  readonly firstInstance: number;
63
68
  readonly overflow: number;
64
69
  readonly persistentTranslationX: number;
70
+ readonly firstReadbackFrame: number;
71
+ readonly recoveredReadbackFrame: number;
72
+ readonly firstVisible: number;
73
+ readonly recoveredVisible: number;
65
74
  }
66
75
 
67
76
  export interface GpuDrivenViewLifecycleEvidence {
@@ -71,7 +80,7 @@ export interface GpuDrivenViewLifecycleEvidence {
71
80
  }
72
81
 
73
82
  export async function runGpuDrivenViewLifecycleEvidence(
74
- frames = 300,
83
+ frames = 60,
75
84
  ): Promise<GpuDrivenViewLifecycleEvidence> {
76
85
  const adapter = (await rhi.requestAdapter()).unwrap();
77
86
  const device = (await adapter.requestDevice()).unwrap();
@@ -247,8 +256,27 @@ export async function runGpuDrivenViewGpuEvidence(): Promise<GpuDrivenViewGpuEvi
247
256
  })
248
257
  .unwrap();
249
258
  const graph = new RenderGraphBuilder<{ readonly encoder: RhiCommandEncoder }>();
259
+ const submissionOwner = new SurfaceSubmissionObservationOwner(() => 1);
260
+ const beginSubmission = (frameId: number, indirectOffset: number): SurfaceSubmissionCandidate => {
261
+ const candidate = submissionOwner.begin({
262
+ frameId,
263
+ requestedLane: 'gpu-driven',
264
+ deviceGeneration: 1,
265
+ resourceGeneration: view.inspect().resourceGeneration,
266
+ });
267
+ for (const pass of ['nearest-layer', 'color'] as const) {
268
+ candidate.record(pass, {
269
+ kind: 'draw-indexed-indirect',
270
+ indirectBufferIdentity: getOpaqueResourceIdentity(indirect as object),
271
+ indirectOffset,
272
+ pipelineIdentity: 33,
273
+ });
274
+ }
275
+ return candidate;
276
+ };
277
+ let currentSubmission = beginSubmission(10, 0);
250
278
  view.setTelemetrySubmit({ frameId: 1, deviceGeneration: 0 });
251
- view.addPasses(graph).unwrap();
279
+ view.addPasses(graph, 'gpu-driven', true, () => currentSubmission).unwrap();
252
280
  const compiled = graph.compile({ device, surfaceSize: { width: 1, height: 1 } }).unwrap();
253
281
  const encoder = device.createCommandEncoder({ label: 'gpu-driven-evidence' }).unwrap();
254
282
  compiled.execute({ encoder }).unwrap();
@@ -263,6 +291,7 @@ export async function runGpuDrivenViewGpuEvidence(): Promise<GpuDrivenViewGpuEvi
263
291
  64,
264
292
  );
265
293
  device.queue.submit([encoder.finish().unwrap()]).unwrap();
294
+ currentSubmission.submit(device.queue.onSubmittedWorkDone(), 1);
266
295
 
267
296
  // Start observing immediately, then submit the cached graph again before
268
297
  // the first mapAsync settles. The second copy must be skipped while the
@@ -277,10 +306,43 @@ export async function runGpuDrivenViewGpuEvidence(): Promise<GpuDrivenViewGpuEvi
277
306
  compiled.execute({ encoder: overlappingEncoder }).unwrap();
278
307
  device.queue.submit([overlappingEncoder.finish().unwrap()]).unwrap();
279
308
  const lodSelection = await pendingLodSelection;
280
- if (lodSelection === undefined || lodSelection.batches.length !== lodSelection.batchCount) {
309
+ if (lodSelection === undefined) {
281
310
  throw new Error('GPU-driven LOD selection readback unavailable or incomplete');
282
311
  }
283
- if (lodSelection.submit?.frameId !== 1 || lodSelection.submit.deviceGeneration !== 0) {
312
+ if (lodSelection.batches.length !== lodSelection.batchCount) {
313
+ throw new Error('GPU-driven LOD selection readback unavailable or incomplete');
314
+ }
315
+ const surfaceIndirectParameters = lodSelection.surfaceIndirectParameters;
316
+ if (surfaceIndirectParameters === undefined || surfaceIndirectParameters.length !== 2) {
317
+ throw new Error('GPU-driven Surface indirect parameter readback unavailable');
318
+ }
319
+ const firstSurfaceCommand = surfaceIndirectParameters[0];
320
+ if (
321
+ firstSurfaceCommand === undefined ||
322
+ firstSurfaceCommand.sequence !== lodSelection.surfaceReadback?.sequence ||
323
+ firstSurfaceCommand.frameId !== lodSelection.surfaceReadback?.frameId ||
324
+ firstSurfaceCommand.deviceGeneration !== lodSelection.surfaceReadback?.deviceGeneration ||
325
+ firstSurfaceCommand.resourceGeneration !== lodSelection.surfaceReadback?.resourceGeneration ||
326
+ firstSurfaceCommand.pass !== 'nearest-layer' ||
327
+ firstSurfaceCommand.indirectOffset !== 0 ||
328
+ firstSurfaceCommand.count !== 12 ||
329
+ firstSurfaceCommand.instanceCount !== 1 ||
330
+ firstSurfaceCommand.first !== 9 ||
331
+ firstSurfaceCommand.baseVertex !== 4 ||
332
+ firstSurfaceCommand.firstInstance !== 0
333
+ ) {
334
+ throw new Error(
335
+ `GPU-driven Surface indirect parameters do not match the submitted batch: ${JSON.stringify({
336
+ firstSurfaceCommand,
337
+ surfaceReadback: lodSelection.surfaceReadback,
338
+ })}`,
339
+ );
340
+ }
341
+ if (
342
+ lodSelection.submit === undefined ||
343
+ lodSelection.submit.frameId !== 1 ||
344
+ lodSelection.submit.deviceGeneration !== 0
345
+ ) {
284
346
  throw new Error('GPU-driven LOD telemetry lost the copy submit identity');
285
347
  }
286
348
  await device.queue.onSubmittedWorkDone();
@@ -300,23 +362,45 @@ export async function runGpuDrivenViewGpuEvidence(): Promise<GpuDrivenViewGpuEvi
300
362
  const recoveryEncoder = device
301
363
  .createCommandEncoder({ label: 'gpu-driven-evidence-recovery' })
302
364
  .unwrap();
365
+ currentSubmission = beginSubmission(11, 32);
303
366
  compiled.execute({ encoder: recoveryEncoder }).unwrap();
304
367
  device.queue.submit([recoveryEncoder.finish().unwrap()]).unwrap();
368
+ currentSubmission.submit(device.queue.onSubmittedWorkDone(), 1);
305
369
  await device.queue.onSubmittedWorkDone();
306
370
  const recoveredLodSelection = await view.readLodSelection();
307
371
  if (
308
372
  recoveredLodSelection === undefined ||
309
373
  recoveredLodSelection === lodSelection ||
310
- recoveredLodSelection.visible === lodSelection.visible
374
+ recoveredLodSelection.visible === lodSelection.visible ||
375
+ lodSelection.surfaceReadback?.frameId !== 10 ||
376
+ recoveredLodSelection.surfaceReadback?.frameId !== 11
311
377
  ) {
312
378
  throw new Error('GPU-driven LOD telemetry did not recover after a skipped copy');
313
379
  }
314
380
  if (
315
- recoveredLodSelection.submit?.frameId !== 2 ||
381
+ recoveredLodSelection.surfaceIndirectParameters?.some(
382
+ (command) =>
383
+ command.sequence !== recoveredLodSelection.surfaceReadback?.sequence ||
384
+ command.frameId !== recoveredLodSelection.surfaceReadback?.frameId ||
385
+ command.deviceGeneration !== recoveredLodSelection.surfaceReadback?.deviceGeneration ||
386
+ command.resourceGeneration !== recoveredLodSelection.surfaceReadback?.resourceGeneration,
387
+ )
388
+ ) {
389
+ throw new Error('GPU-driven recovered Surface indirect parameters lost readback identity');
390
+ }
391
+ if (
392
+ recoveredLodSelection.submit === undefined ||
393
+ recoveredLodSelection.submit.frameId !== 2 ||
316
394
  recoveredLodSelection.submit.deviceGeneration !== 0
317
395
  ) {
318
396
  throw new Error('GPU-driven LOD telemetry reused a stale submit identity');
319
397
  }
398
+ if (
399
+ lodSelection.surfaceReadback === undefined ||
400
+ recoveredLodSelection.surfaceReadback === undefined
401
+ ) {
402
+ throw new Error('GPU-driven LOD telemetry lost Surface readback identity');
403
+ }
320
404
  const validationError = await rawDevice.popErrorScope();
321
405
  if (validationError !== null) {
322
406
  throw new Error(`GPU-driven telemetry overlap validation failed: ${validationError.message}`);
@@ -348,6 +432,10 @@ export async function runGpuDrivenViewGpuEvidence(): Promise<GpuDrivenViewGpuEvi
348
432
  firstInstance: indirectValue.getUint32(16, true),
349
433
  overflow: overflowValue,
350
434
  persistentTranslationX,
435
+ firstReadbackFrame: lodSelection.surfaceReadback.frameId,
436
+ recoveredReadbackFrame: recoveredLodSelection.surfaceReadback.frameId,
437
+ firstVisible: lodSelection.visible,
438
+ recoveredVisible: recoveredLodSelection.visible,
351
439
  };
352
440
  view.dispose();
353
441
  sceneAvailability.scene.dispose();
@@ -12,7 +12,7 @@ import { RhiErrorListenerRegistry } from '../lifecycle';
12
12
  import type { RenderFrameState } from '../record/frame-snapshot';
13
13
  import { makeZeroCameraFallbackSnapshot } from '../record/frame-snapshot';
14
14
  import type { PipelineState, RenderSystemInternals } from '../record/render-context';
15
- import { ensureCompiledFrameGraph } from '../record/typed-frame-graph';
15
+ import { ensureCompiledFrameGraph, executeCompiledFrameGraph } from '../record/typed-frame-graph';
16
16
  import type { RenderPipeline, RenderPipelineFrame } from '../render-pipeline';
17
17
  import type {
18
18
  ExtractedLights,
@@ -65,6 +65,7 @@ function updateSnapshot(value: RenderableSnapshot) {
65
65
  function preparedFrame(view: GpuDrivenView): PreparedGpuDrivenFrame {
66
66
  return {
67
67
  topologySignature: `view-generation:${view.inspect().resourceGeneration}`,
68
+ worldKeys: [],
68
69
  ownsAllDrawItems: true,
69
70
  standardPbrFrameResources: {
70
71
  materialBindGroups: [],
@@ -141,6 +142,7 @@ describe('GpuDrivenView graph projection', () => {
141
142
  if (first === null) return;
142
143
  const prepared: PreparedGpuDrivenFrame = {
143
144
  topologySignature: 'stable-gpu-driven-test',
145
+ worldKeys: [],
144
146
  ownsAllDrawItems: true,
145
147
  standardPbrFrameResources: {
146
148
  materialBindGroups: [],
@@ -239,7 +241,7 @@ describe('GpuDrivenView graph projection', () => {
239
241
  {
240
242
  name: 'gpu-driven.lod-selection-readback',
241
243
  kind: 'copy',
242
- dependencies: ['gpu-driven.frustum-compact'],
244
+ dependencies: ['gpu-driven.frustum-compact', 'gpu-driven.finalize-indirect'],
243
245
  },
244
246
  ]);
245
247
  const encoder = device.createCommandEncoder({ label: 'gpu-driven-view' }).unwrap();
@@ -390,7 +392,21 @@ describe('GpuDrivenView graph projection', () => {
390
392
  const retirePrevious = vi.spyOn(compiledPrevious, 'retire');
391
393
  const acceptedGraph = compile(preparedFrame(view), 2);
392
394
  expect(acceptedGraph).not.toBe(compiledPrevious);
395
+ expect(retirePrevious).not.toHaveBeenCalled();
396
+ expect(destroyBuffer.mock.calls.some(([buffer]) => buffer === previousVisible)).toBe(false);
393
397
  expect(frameState.compiledFrameGraphGeneration).toBe(2);
398
+ expect(retirePrevious).not.toHaveBeenCalled();
399
+ const acceptedEncoder = device
400
+ .createCommandEncoder({ label: 'gpu-driven-view-accepted' })
401
+ .unwrap();
402
+ expect(
403
+ executeCompiledFrameGraph(
404
+ internals,
405
+ frameState,
406
+ { encoder: acceptedEncoder } as RenderPipelineFrame,
407
+ acceptedEncoder,
408
+ ),
409
+ ).toBe(true);
394
410
  expect(retirePrevious).toHaveBeenCalledOnce();
395
411
  await device.queue.onSubmittedWorkDone();
396
412
  await Promise.resolve();
@@ -5,14 +5,7 @@ import {
5
5
  } from './gpu-driven-view-gpu-evidence';
6
6
 
7
7
  const browserReady = typeof navigator !== 'undefined' && navigator.gpu !== undefined;
8
- const lifecycleFrames =
9
- (
10
- import.meta as ImportMeta & {
11
- readonly env?: { readonly FORGEAX_BROWSER_CI_LIGHTWEIGHT?: string };
12
- }
13
- ).env?.FORGEAX_BROWSER_CI_LIGHTWEIGHT === '1'
14
- ? 60
15
- : 300;
8
+ const lifecycleFrames = 60;
16
9
 
17
10
  describe.skipIf(!browserReady)('GPU-driven View Browser WebGPU', () => {
18
11
  it('produces compact visible IDs and portable indirect args on the real browser device', async () => {
@@ -25,6 +18,10 @@ describe.skipIf(!browserReady)('GPU-driven View Browser WebGPU', () => {
25
18
  firstInstance: 0,
26
19
  overflow: 0,
27
20
  persistentTranslationX: 0,
21
+ firstReadbackFrame: 10,
22
+ recoveredReadbackFrame: 11,
23
+ firstVisible: 1,
24
+ recoveredVisible: 0,
28
25
  });
29
26
  });
30
27
 
@@ -15,12 +15,16 @@ describe('GPU-driven View Dawn', () => {
15
15
  firstInstance: 0,
16
16
  overflow: 0,
17
17
  persistentTranslationX: 0,
18
+ firstReadbackFrame: 10,
19
+ recoveredReadbackFrame: 11,
20
+ firstVisible: 1,
21
+ recoveredVisible: 0,
18
22
  });
19
23
  });
20
24
 
21
- it('survives 300 frames of spawn/despawn capacity crossings without stale buffers', async () => {
25
+ it('survives 60 frames of spawn/despawn capacity crossings without stale buffers', async () => {
22
26
  await expect(runGpuDrivenViewLifecycleEvidence()).resolves.toEqual({
23
- frames: 300,
27
+ frames: 60,
24
28
  bufferRebuilds: 4,
25
29
  candidateCapacity: 8,
26
30
  });
@@ -99,7 +99,7 @@ describe('GPU-driven batch topology and CPU oracle', () => {
99
99
 
100
100
  it('projects compact visible items into batch-local mesh and material indices', () => {
101
101
  expect(GPU_DRIVEN_VIEW_WGSL).toMatch(
102
- /vec2<u32>\(\s*candidate\.submitAdmission >> 1u,\s*materialOrPalette,/,
102
+ /vec4<u32>\(\s*candidate\.submitAdmission >> 1u,\s*materialOrPalette,\s*candidate\.primitiveIndex \+ 1u,\s*candidate\.generation,/,
103
103
  );
104
104
  expect(GPU_DRIVEN_VIEW_WGSL).toContain('(candidate.submitAdmission & 1u)');
105
105
  expect(GPU_DRIVEN_VIEW_WGSL).toContain('instance.customDataStart');
@@ -145,6 +145,7 @@ describe('GPU pass timing generation-safe lifecycle', () => {
145
145
  const oldReceipt = {
146
146
  frameId: oldIdentity.frameId,
147
147
  deviceGeneration: oldIdentity.deviceGeneration,
148
+ presentation: 'ready',
148
149
  completed: Promise.resolve(ok(undefined)),
149
150
  } as FrameReceipt;
150
151
  store.register(oldReceipt, async () => {
@@ -17,9 +17,9 @@ describe.skipIf(!browserReady)('GPU pass timing Browser dev-server runner', () =
17
17
  expect(omitted.timings).toBeUndefined();
18
18
  });
19
19
 
20
- // The first live lavapipe renderer pair can exceed Vitest's 15s default while
21
- // the shader manifest and timestamp-query path are cold; keep this bound
22
- // local to the real WebGPU owner instead of weakening the global timeout.
20
+ // Each timing case creates a fresh renderer. Its lavapipe initialization can
21
+ // exceed Vitest's 15s default, including the raster-suppressed case below.
22
+ // Both retain the same bounded startup allowance and three-frame assertions.
23
23
  it('keeps receipt facts and unsupported timing structured without stopping draw', {
24
24
  timeout: 30_000,
25
25
  }, async () => {
@@ -35,7 +35,9 @@ describe.skipIf(!browserReady)('GPU pass timing Browser dev-server runner', () =
35
35
  expect(result.visible).toBe(true);
36
36
  });
37
37
 
38
- it('keeps raster suppression as a test-only falsifier, never timing evidence', async () => {
38
+ it('keeps raster suppression as a test-only falsifier, never timing evidence', {
39
+ timeout: 30_000,
40
+ }, async () => {
39
41
  const result = await runBrowserGpuPassTiming({ suppressRaster: true });
40
42
  expect(result.rasterSuppressed).toBe(true);
41
43
  expect(result.frames).toBe(3);
@@ -16,6 +16,7 @@ function receipt(frameId: number): FrameReceipt {
16
16
  return {
17
17
  frameId,
18
18
  deviceGeneration: 1,
19
+ presentation: 'ready',
19
20
  completed: Promise.resolve(ok(undefined)),
20
21
  } as FrameReceipt;
21
22
  }
@@ -191,6 +191,123 @@ function createDevice(queue: RecordingQueue): RhiNullDevice {
191
191
  }
192
192
 
193
193
  describe('GpuScene', () => {
194
+ it('keeps renderer-owned tables resident across World detach and reattach', () => {
195
+ const queue = new RecordingQueue();
196
+ const device = createDevice(queue);
197
+ const persistent = new PersistentRenderScene({ getDevice: () => device });
198
+ const firstWorld = new World();
199
+ const firstLease = createRenderReadLease(firstWorld);
200
+
201
+ persistent.extractComposition(
202
+ [firstWorld],
203
+ { cameraOwner: 0, resourceOwner: 0 },
204
+ 0,
205
+ () => persistentFrame([snapshot(1)]),
206
+ [firstLease],
207
+ );
208
+ const first = persistent.compositionGpuDrivenState();
209
+ expect(first).toBeDefined();
210
+ if (first === undefined) return;
211
+
212
+ persistent.detach(firstWorld);
213
+ firstLease.dispose();
214
+ const secondWorld = new World();
215
+ const secondLease = createRenderReadLease(secondWorld);
216
+ persistent.extractComposition(
217
+ [secondWorld],
218
+ { cameraOwner: 0, resourceOwner: 0 },
219
+ 1,
220
+ () => persistentFrame([snapshot(2)]),
221
+ [secondLease],
222
+ );
223
+ const second = persistent.compositionGpuDrivenState();
224
+ expect(second).toBeDefined();
225
+ expect(second?.scene).toBe(first.scene);
226
+
227
+ secondLease.dispose();
228
+ persistent.dispose();
229
+ });
230
+
231
+ it('uploads only changed material bytes for shared value updates and retries failed writes', () => {
232
+ const queue = new FailingQueue();
233
+ const created = GpuScene.create(createDevice(queue), 8).unwrap();
234
+ expect(created.status).toBe('available');
235
+ if (created.status !== 'available') return;
236
+ const scene = created.scene;
237
+ const projection = new RenderScene();
238
+ const sources = Array.from({ length: 4 }, (_, index) => ({
239
+ ...snapshot(index),
240
+ gpuDrivenDraws: [
241
+ {
242
+ kind: 'indexed' as const,
243
+ first: 0,
244
+ count: 36,
245
+ baseVertex: 0,
246
+ materialSlot: 0,
247
+ topology: 'triangle-list' as const,
248
+ pipelineClass: 'pbr',
249
+ materialResourceClass: '{}',
250
+ },
251
+ ],
252
+ }));
253
+ scene.sync(projection.apply(sources.map(updateSnapshot))).unwrap();
254
+ const changed = { ...material, roughness: 0.3 };
255
+ const updated = sources.map((source) => ({
256
+ ...source,
257
+ material: changed,
258
+ materials: [changed],
259
+ }));
260
+ const delta = projection.apply(updated.map(updateSnapshot));
261
+ queue.failWrites = true;
262
+ expect(scene.sync(delta).ok).toBe(false);
263
+ queue.failWrites = false;
264
+ queue.writes.length = 0;
265
+ const retried = scene.sync(projection.apply([])).unwrap();
266
+ expect(retried.bytes).toBe(4 * GPU_SCENE_LAYOUTS.material.stride);
267
+ expect(queue.writes).toHaveLength(1);
268
+ const roughness = gpuSceneFieldOffset(GPU_SCENE_LAYOUTS.material, 'roughness');
269
+ const upload = queue.writes[0];
270
+ if (upload === undefined) throw new Error('expected material upload');
271
+ for (let index = 0; index < 4; index++) {
272
+ expect(
273
+ new DataView(upload.bytes.buffer).getFloat32(
274
+ index * GPU_SCENE_LAYOUTS.material.stride + roughness,
275
+ true,
276
+ ),
277
+ ).toBeCloseTo(0.3);
278
+ }
279
+ // Fresh snapshots with identical bytes must not upload. Later in-place
280
+ // caller edits remain visible: packed rows are shared only within sync.
281
+ expect(scene.sync(projection.apply(updated.map(updateSnapshot))).unwrap().bytes).toBe(0);
282
+ changed.roughness = 0.6;
283
+ expect(scene.sync(projection.apply(updated.map(updateSnapshot))).unwrap().bytes).toBe(
284
+ 4 * GPU_SCENE_LAYOUTS.material.stride,
285
+ );
286
+ const first = updated[0];
287
+ const draw = first?.gpuDrivenDraws[0];
288
+ if (first === undefined || draw === undefined) throw new Error('expected draw fixture');
289
+ queue.writes.length = 0;
290
+ const geometryChanged = {
291
+ ...first,
292
+ localAabb: new Float32Array([-2, -1, -1, 2, 1, 1]),
293
+ gpuDrivenDraws: [{ ...draw, first: 6, count: 12, baseVertex: -3 }],
294
+ };
295
+ expect(scene.sync(projection.apply([updateSnapshot(geometryChanged)])).unwrap().bytes).toBe(
296
+ GPU_SCENE_LAYOUTS.primitive.stride + GPU_SCENE_LAYOUTS.drawTemplate.stride,
297
+ );
298
+ const drawUpload = queue.writes.find(
299
+ ({ bytes }) => bytes.length === GPU_SCENE_LAYOUTS.drawTemplate.stride,
300
+ );
301
+ if (drawUpload === undefined) throw new Error('expected changed draw upload');
302
+ expect(
303
+ new DataView(drawUpload.bytes.buffer).getInt32(
304
+ gpuSceneFieldOffset(GPU_SCENE_LAYOUTS.drawTemplate, 'baseVertex'),
305
+ true,
306
+ ),
307
+ ).toBe(-3);
308
+ scene.dispose();
309
+ });
310
+
194
311
  it('preserves authored base-color alpha in the scene material row', () => {
195
312
  const row = packStandardPbrMaterialRow(createStandardPbrArtifactReceipt(), {
196
313
  ...material,
@@ -888,20 +1005,13 @@ describe('GpuScene', () => {
888
1005
  expect(delta.updated).toBe(1);
889
1006
  const result = created.scene.sync(delta).unwrap();
890
1007
  expect(result.bytes).toBe(
891
- GPU_SCENE_LAYOUTS.primitive.stride +
892
- GPU_SCENE_LAYOUTS.drawTemplate.stride +
893
- GPU_SCENE_LAYOUTS.material.stride +
894
- 2 * GPU_SCENE_LAYOUTS.transform.stride,
1008
+ GPU_SCENE_LAYOUTS.material.stride + 2 * GPU_SCENE_LAYOUTS.transform.stride,
895
1009
  );
896
1010
  expect(result.grew).toBe(false);
897
1011
  const next = { ...mixed, material: { ...nextMaterial, roughness: 0.7 } };
898
1012
  next.materials = [next.material];
899
1013
  const materialOnly = created.scene.sync(projection.apply([updateSnapshot(next)])).unwrap();
900
- expect(materialOnly.bytes).toBe(
901
- GPU_SCENE_LAYOUTS.primitive.stride +
902
- GPU_SCENE_LAYOUTS.drawTemplate.stride +
903
- GPU_SCENE_LAYOUTS.material.stride,
904
- );
1014
+ expect(materialOnly.bytes).toBe(GPU_SCENE_LAYOUTS.material.stride);
905
1015
  });
906
1016
  });
907
1017
 
@@ -0,0 +1,57 @@
1
+ import { err, RhiError } from '@forgeax/engine-rhi';
2
+ import { rhi } from '@forgeax/engine-rhi-null';
3
+ import { expect, it, vi } from 'vitest';
4
+ import { GPU_SHADER_STAGE_VERTEX } from '../gpu-stage';
5
+ import { GPU_BUFFER_USAGE_STORAGE } from '../gpu-usage';
6
+ import { resolveGeometryInstanceBuffer } from '../record/main-pass-geometry';
7
+
8
+ it('refuses an instance draw when allocation fails instead of drawing the identity fallback', async () => {
9
+ const device = (await (await rhi.requestAdapter()).unwrap().requestDevice()).unwrap();
10
+ const identity = device.createBuffer({ size: 128, usage: GPU_BUFFER_USAGE_STORAGE }).unwrap();
11
+ const layout = device
12
+ .createBindGroupLayout({
13
+ entries: [
14
+ { binding: 0, visibility: GPU_SHADER_STAGE_VERTEX, buffer: { type: 'read-only-storage' } },
15
+ ],
16
+ })
17
+ .unwrap();
18
+ const failure = new RhiError({
19
+ code: 'rhi-not-available',
20
+ expected: 'an instance buffer allocation',
21
+ hint: 'recover the renderer',
22
+ });
23
+ const allocation = vi.spyOn(device, 'createBuffer').mockReturnValue(err(failure));
24
+ const bindGroup = vi.spyOn(device, 'createBindGroup');
25
+ const fire = vi.fn();
26
+ try {
27
+ const result = resolveGeometryInstanceBuffer(
28
+ {
29
+ runtime: { device, errorRegistry: { fire } },
30
+ pipelineState: { identityInstanceBuffer: identity, instancesBindGroupLayout: layout },
31
+ frameState: { instanceBuffers: new Map() },
32
+ bindGroupCounts: { createBindGroup: 0, keys: [] },
33
+ } as unknown as Parameters<typeof resolveGeometryInstanceBuffer>[0],
34
+ {
35
+ source: {
36
+ worldId: 0,
37
+ entityKey: 1,
38
+ instances: {
39
+ transforms: new Float32Array(32),
40
+ instanceCount: 2,
41
+ cacheKey: 1,
42
+ archVersion: 0,
43
+ },
44
+ },
45
+ } as Parameters<typeof resolveGeometryInstanceBuffer>[1],
46
+ [],
47
+ false,
48
+ );
49
+ expect(result).toBeNull();
50
+ expect(fire).toHaveBeenCalledWith(failure);
51
+ expect(bindGroup).not.toHaveBeenCalled();
52
+ } finally {
53
+ allocation.mockRestore();
54
+ bindGroup.mockRestore();
55
+ device.destroyBuffer(identity).unwrap();
56
+ }
57
+ });
@@ -7,8 +7,6 @@ import { Instances } from '../components/instances';
7
7
  import { MeshFilter } from '../components/mesh-filter';
8
8
  import { MeshRenderer } from '../components/mesh-renderer';
9
9
  import { GPU_DRIVEN_VIEW_WGSL } from '../gpu-driven/view-gpu';
10
- import type { InstanceCollectionId } from '../instances';
11
- import { InstanceCollectionStore } from '../instances';
12
10
  import { extractFrames } from '../render-system-extract';
13
11
 
14
12
  const IDENTITY = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
@@ -28,21 +26,13 @@ function spawnCamera(world: World): void {
28
26
  .unwrap();
29
27
  }
30
28
 
31
- function spawnInstancedCube(
32
- world: World,
33
- instanceCollections: InstanceCollectionStore,
34
- entityX: number,
35
- instanceX: number,
36
- ) {
37
- const collectionId = instanceCollections
38
- .create({ transforms: translated(instanceX) })
39
- .unwrap().collectionId;
29
+ function spawnInstancedCube(world: World, entityX: number, instanceX: number) {
40
30
  return world
41
31
  .spawn(
42
32
  { component: Transform, data: { pos: [entityX, 0, 0] } },
43
33
  { component: MeshFilter, data: { assetHandle: HANDLE_CUBE } },
44
34
  { component: MeshRenderer, data: {} },
45
- { component: Instances, data: { collectionId } },
35
+ { component: Instances, data: { transforms: translated(instanceX) } },
46
36
  )
47
37
  .unwrap();
48
38
  }
@@ -52,13 +42,10 @@ describe('Instances CPU/GPU culling ownership', () => {
52
42
  const world = new World();
53
43
  registerPropagateTransforms(world);
54
44
  spawnCamera(world);
55
- const instanceCollections = new InstanceCollectionStore();
56
- const entity = spawnInstancedCube(world, instanceCollections, 20, -20);
45
+ const entity = spawnInstancedCube(world, 20, -20);
57
46
  world.update(0).unwrap();
58
47
 
59
- const frame = extractFrames([world], 0, undefined, undefined, undefined, {
60
- instanceCollections,
61
- });
48
+ const frame = extractFrames([world], 0);
62
49
 
63
50
  expect(frame.renderables.map((renderable) => renderable.entityKey)).toContain(entity);
64
51
  expect(frame.frustumStats).toEqual({ culled: 0, total: 1 });
@@ -68,22 +55,15 @@ describe('Instances CPU/GPU culling ownership', () => {
68
55
  const world = new World();
69
56
  registerPropagateTransforms(world);
70
57
  spawnCamera(world);
71
- const instanceCollections = new InstanceCollectionStore();
72
- const entity = spawnInstancedCube(world, instanceCollections, 20, -20);
58
+ const entity = spawnInstancedCube(world, 20, -20);
73
59
  world.update(0).unwrap();
74
- expect(
75
- extractFrames([world], 0, undefined, undefined, undefined, { instanceCollections })
76
- .renderables,
77
- ).toHaveLength(1);
60
+ expect(extractFrames([world], 0).renderables).toHaveLength(1);
78
61
 
79
62
  world.set(entity, Transform, { pos: [40, 0, 0] }).unwrap();
80
- const collectionId = world.get(entity, Instances).unwrap().collectionId;
81
- instanceCollections.replace(collectionId as InstanceCollectionId, translated(-40)).unwrap();
63
+ world.set(entity, Instances, { transforms: translated(-40) }).unwrap();
82
64
  world.update(0).unwrap();
83
65
 
84
- const frame = extractFrames([world], 0, undefined, undefined, undefined, {
85
- instanceCollections,
86
- });
66
+ const frame = extractFrames([world], 0);
87
67
  expect(frame.renderables).toHaveLength(1);
88
68
  expect(frame.renderables[0]?.instances?.instanceCount).toBe(1);
89
69
  });
@@ -92,23 +72,17 @@ describe('Instances CPU/GPU culling ownership', () => {
92
72
  const world = new World();
93
73
  registerPropagateTransforms(world);
94
74
  spawnCamera(world);
95
- const instanceCollections = new InstanceCollectionStore();
96
- const collectionId = instanceCollections
97
- .create({ transforms: new Float32Array() })
98
- .unwrap().collectionId;
99
75
  const entity = world
100
76
  .spawn(
101
77
  { component: Transform, data: { pos: [20, 0, 0] } },
102
78
  { component: MeshFilter, data: { assetHandle: HANDLE_CUBE } },
103
79
  { component: MeshRenderer, data: {} },
104
- { component: Instances, data: { collectionId } },
80
+ { component: Instances, data: { transforms: new Float32Array() } },
105
81
  )
106
82
  .unwrap();
107
83
  world.update(0).unwrap();
108
84
 
109
- const frame = extractFrames([world], 0, undefined, undefined, undefined, {
110
- instanceCollections,
111
- });
85
+ const frame = extractFrames([world], 0);
112
86
  expect(
113
87
  frame.renderables.find((renderable) => renderable.entityKey === entity)?.instances,
114
88
  ).toMatchObject({ instanceCount: 0 });