@forgeax/engine-render 0.1.19 → 0.1.21

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 (452) hide show
  1. package/README.md +215 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/assembly/device-feature-admission.d.ts +18 -0
  4. package/dist/assembly/device-feature-admission.d.ts.map +1 -0
  5. package/dist/assembly/directional-shadow-inspection.d.ts +38 -0
  6. package/dist/assembly/directional-shadow-inspection.d.ts.map +1 -0
  7. package/dist/assembly/factory.d.ts +34 -20
  8. package/dist/assembly/factory.d.ts.map +1 -1
  9. package/dist/assembly/host-contract.d.ts +9 -0
  10. package/dist/assembly/host-contract.d.ts.map +1 -1
  11. package/dist/assembly/render-target-host.d.ts +46 -0
  12. package/dist/assembly/render-target-host.d.ts.map +1 -0
  13. package/dist/assets/render-asset-port.d.ts.map +1 -1
  14. package/dist/authoring.mjs +3 -0
  15. package/dist/authoring.mjs.map +1 -1
  16. package/dist/capture/cube-views.d.ts +21 -0
  17. package/dist/capture/cube-views.d.ts.map +1 -0
  18. package/dist/capture/scheduler.d.ts +54 -0
  19. package/dist/capture/scheduler.d.ts.map +1 -0
  20. package/dist/{chunk-RJRUS55L.mjs → chunk-5YADUCA7.mjs} +1896 -1624
  21. package/dist/chunk-5YADUCA7.mjs.map +1 -0
  22. package/dist/{chunk-LOSO4CTV.mjs → chunk-6OPXDQ2E.mjs} +423 -46
  23. package/dist/chunk-6OPXDQ2E.mjs.map +1 -0
  24. package/dist/{chunk-IPXCABEP.mjs → chunk-BXBQQKFQ.mjs} +3 -9
  25. package/dist/chunk-BXBQQKFQ.mjs.map +1 -0
  26. package/dist/chunk-FS2KNUQH.mjs +1294 -0
  27. package/dist/chunk-FS2KNUQH.mjs.map +1 -0
  28. package/dist/components/camera.d.ts +1 -0
  29. package/dist/components/camera.d.ts.map +1 -1
  30. package/dist/components/cube-camera.d.ts +20 -0
  31. package/dist/components/cube-camera.d.ts.map +1 -0
  32. package/dist/components/directional-light.d.ts +11 -2
  33. package/dist/components/directional-light.d.ts.map +1 -1
  34. package/dist/components/directional-shadow-filter.d.ts +25 -0
  35. package/dist/components/directional-shadow-filter.d.ts.map +1 -0
  36. package/dist/components/index.d.ts +2 -0
  37. package/dist/components/index.d.ts.map +1 -1
  38. package/dist/components/light-helpers.d.ts.map +1 -1
  39. package/dist/components/reflection-probe.d.ts +17 -0
  40. package/dist/components/reflection-probe.d.ts.map +1 -0
  41. package/dist/components/spot-light.d.ts +12 -0
  42. package/dist/components/spot-light.d.ts.map +1 -1
  43. package/dist/construct-renderer.mjs +8552 -1612
  44. package/dist/construct-renderer.mjs.map +1 -1
  45. package/dist/device/gpu-residency.d.ts +19 -2
  46. package/dist/device/gpu-residency.d.ts.map +1 -1
  47. package/dist/environment/frame.d.ts.map +1 -1
  48. package/dist/environment/lifecycle.d.ts +5 -0
  49. package/dist/environment/lifecycle.d.ts.map +1 -1
  50. package/dist/errors/render.d.ts +209 -93
  51. package/dist/errors/render.d.ts.map +1 -1
  52. package/dist/extract/directional-shadow-projection.d.ts +23 -0
  53. package/dist/extract/directional-shadow-projection.d.ts.map +1 -0
  54. package/dist/extract/environment.d.ts +14 -0
  55. package/dist/extract/environment.d.ts.map +1 -1
  56. package/dist/extract/visibility.d.ts.map +1 -1
  57. package/dist/features/fullscreen.d.ts.map +1 -1
  58. package/dist/features/targets.d.ts.map +1 -1
  59. package/dist/features/types.d.ts +10 -0
  60. package/dist/features/types.d.ts.map +1 -1
  61. package/dist/fullscreen-post-process-pass.d.ts +13 -2
  62. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  63. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  64. package/dist/gpu-driven/production-raster.d.ts +0 -1
  65. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  66. package/dist/gpu-scene.d.ts.map +1 -1
  67. package/dist/gpu-usage.d.ts +2 -0
  68. package/dist/gpu-usage.d.ts.map +1 -1
  69. package/dist/hdrp-buffers.d.ts +19 -17
  70. package/dist/hdrp-buffers.d.ts.map +1 -1
  71. package/dist/ibl/IblPipelineCache.d.ts +4 -0
  72. package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
  73. package/dist/ibl/kernel-cache.d.ts +36 -0
  74. package/dist/ibl/kernel-cache.d.ts.map +1 -0
  75. package/dist/index.d.ts +35 -4
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.mjs +4 -4
  78. package/dist/index.mjs.map +1 -1
  79. package/dist/inspection-types.d.ts +51 -0
  80. package/dist/inspection-types.d.ts.map +1 -1
  81. package/dist/instances-derived-bounds.d.ts +50 -0
  82. package/dist/instances-derived-bounds.d.ts.map +1 -0
  83. package/dist/internal.mjs +1 -1
  84. package/dist/light-buffer-layout.d.ts +30 -13
  85. package/dist/light-buffer-layout.d.ts.map +1 -1
  86. package/dist/mesh-material-bindings.d.ts +54 -0
  87. package/dist/mesh-material-bindings.d.ts.map +1 -1
  88. package/dist/pbr-pipeline.d.ts +20 -7
  89. package/dist/pbr-pipeline.d.ts.map +1 -1
  90. package/dist/pipeline/standard-forward-lane.d.ts +2 -1
  91. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  92. package/dist/pipeline/standard-lighting/errors.d.ts +4 -0
  93. package/dist/pipeline/standard-lighting/errors.d.ts.map +1 -0
  94. package/dist/pipeline/standard-lighting/graph.d.ts +24 -0
  95. package/dist/pipeline/standard-lighting/graph.d.ts.map +1 -0
  96. package/dist/pipeline/standard-lighting/inspection.d.ts +38 -0
  97. package/dist/pipeline/standard-lighting/inspection.d.ts.map +1 -0
  98. package/dist/pipeline/standard-lighting/layout.d.ts +28 -0
  99. package/dist/pipeline/standard-lighting/layout.d.ts.map +1 -0
  100. package/dist/pipeline/standard-lighting/light-frame.d.ts +33 -0
  101. package/dist/pipeline/standard-lighting/light-frame.d.ts.map +1 -0
  102. package/dist/pipeline/standard-lighting/membership.d.ts +14 -0
  103. package/dist/pipeline/standard-lighting/membership.d.ts.map +1 -0
  104. package/dist/pipeline/standard-lighting/prepare.d.ts +16 -0
  105. package/dist/pipeline/standard-lighting/prepare.d.ts.map +1 -0
  106. package/dist/pipeline/standard-lighting/topology.d.ts +45 -0
  107. package/dist/pipeline/standard-lighting/topology.d.ts.map +1 -0
  108. package/dist/pipeline/standard-lighting/transport.d.ts +36 -0
  109. package/dist/pipeline/standard-lighting/transport.d.ts.map +1 -0
  110. package/dist/pipeline/standard-pipeline.d.ts +4 -13
  111. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  112. package/dist/pipeline/standard-post.d.ts.map +1 -1
  113. package/dist/pipeline/standard-profile.d.ts +12 -20
  114. package/dist/pipeline/standard-profile.d.ts.map +1 -1
  115. package/dist/pipeline-spec.d.ts +40 -7
  116. package/dist/pipeline-spec.d.ts.map +1 -1
  117. package/dist/point-shadow-inspection.d.ts +21 -0
  118. package/dist/point-shadow-inspection.d.ts.map +1 -0
  119. package/dist/record/frame-lighting.d.ts +29 -32
  120. package/dist/record/frame-lighting.d.ts.map +1 -1
  121. package/dist/record/frame-snapshot.d.ts +65 -15
  122. package/dist/record/frame-snapshot.d.ts.map +1 -1
  123. package/dist/record/frame-targets.d.ts +5 -0
  124. package/dist/record/frame-targets.d.ts.map +1 -1
  125. package/dist/record/frame.d.ts +12 -5
  126. package/dist/record/frame.d.ts.map +1 -1
  127. package/dist/record/gpu-pass-timing/contract.d.ts +96 -0
  128. package/dist/record/gpu-pass-timing/contract.d.ts.map +1 -0
  129. package/dist/record/gpu-pass-timing/errors.d.ts +18 -0
  130. package/dist/record/gpu-pass-timing/errors.d.ts.map +1 -0
  131. package/dist/record/gpu-pass-timing/index.d.ts +8 -0
  132. package/dist/record/gpu-pass-timing/index.d.ts.map +1 -0
  133. package/dist/record/gpu-pass-timing/parser.d.ts +11 -0
  134. package/dist/record/gpu-pass-timing/parser.d.ts.map +1 -0
  135. package/dist/record/gpu-pass-timing/session.d.ts +43 -0
  136. package/dist/record/gpu-pass-timing/session.d.ts.map +1 -0
  137. package/dist/record/gpu-timing.d.ts +37 -0
  138. package/dist/record/gpu-timing.d.ts.map +1 -0
  139. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  140. package/dist/record/main-pass-material.d.ts +23 -2
  141. package/dist/record/main-pass-material.d.ts.map +1 -1
  142. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  143. package/dist/record/main-pass.d.ts +2 -0
  144. package/dist/record/main-pass.d.ts.map +1 -1
  145. package/dist/record/render-context.d.ts +48 -3
  146. package/dist/record/render-context.d.ts.map +1 -1
  147. package/dist/record/shadow-pass.d.ts.map +1 -1
  148. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  149. package/dist/record/typed-frame-graph.d.ts +81 -5
  150. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  151. package/dist/record/view-ubo.d.ts +7 -4
  152. package/dist/record/view-ubo.d.ts.map +1 -1
  153. package/dist/reflection/filter.d.ts +22 -0
  154. package/dist/reflection/filter.d.ts.map +1 -0
  155. package/dist/reflection/gpu-table.d.ts +25 -0
  156. package/dist/reflection/gpu-table.d.ts.map +1 -0
  157. package/dist/reflection/projection.d.ts +91 -0
  158. package/dist/reflection/projection.d.ts.map +1 -0
  159. package/dist/render-contract.d.ts +114 -7
  160. package/dist/render-contract.d.ts.map +1 -1
  161. package/dist/render-data.d.ts +10 -6
  162. package/dist/render-data.d.ts.map +1 -1
  163. package/dist/render-graph-primitives.d.ts +1 -0
  164. package/dist/render-graph-primitives.d.ts.map +1 -1
  165. package/dist/render-pipeline.d.ts +78 -2
  166. package/dist/render-pipeline.d.ts.map +1 -1
  167. package/dist/render-system-extract.d.ts +113 -20
  168. package/dist/render-system-extract.d.ts.map +1 -1
  169. package/dist/render-system.d.ts +24 -3
  170. package/dist/render-system.d.ts.map +1 -1
  171. package/dist/renderer-inspect.d.ts +29 -0
  172. package/dist/renderer-inspect.d.ts.map +1 -0
  173. package/dist/renderer.d.ts +43 -0
  174. package/dist/renderer.d.ts.map +1 -0
  175. package/dist/scene/render-scene.d.ts +14 -0
  176. package/dist/scene/render-scene.d.ts.map +1 -1
  177. package/dist/shadow-atlas.d.ts +3 -3
  178. package/dist/shadow-atlas.d.ts.map +1 -1
  179. package/dist/ssao-buffers.d.ts +3 -0
  180. package/dist/ssao-buffers.d.ts.map +1 -1
  181. package/dist/targets/contracts.d.ts +66 -0
  182. package/dist/targets/contracts.d.ts.map +1 -0
  183. package/dist/targets/graph-projection.d.ts +29 -0
  184. package/dist/targets/graph-projection.d.ts.map +1 -0
  185. package/dist/targets/material-source.d.ts +34 -0
  186. package/dist/targets/material-source.d.ts.map +1 -0
  187. package/dist/targets/owner.d.ts +32 -0
  188. package/dist/targets/owner.d.ts.map +1 -0
  189. package/dist/targets/physical.d.ts +18 -0
  190. package/dist/targets/physical.d.ts.map +1 -0
  191. package/dist/targets/readback.d.ts +39 -0
  192. package/dist/targets/readback.d.ts.map +1 -0
  193. package/dist/temporal/frame.d.ts +44 -0
  194. package/dist/temporal/frame.d.ts.map +1 -0
  195. package/dist/temporal/index.mjs +3 -3
  196. package/dist/typed-render-graph-primitives.d.ts +6 -1
  197. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  198. package/dist/typed-shadow-atlas.d.ts +10 -0
  199. package/dist/typed-shadow-atlas.d.ts.map +1 -0
  200. package/dist/typed-shadow-passes.d.ts +1 -1
  201. package/dist/typed-shadow-passes.d.ts.map +1 -1
  202. package/dist/volume/capability.d.ts +57 -0
  203. package/dist/volume/capability.d.ts.map +1 -0
  204. package/dist/volume/component.d.ts +61 -0
  205. package/dist/volume/component.d.ts.map +1 -0
  206. package/dist/volume/extract.d.ts +11 -0
  207. package/dist/volume/extract.d.ts.map +1 -0
  208. package/dist/volume/inspection.d.ts +38 -0
  209. package/dist/volume/inspection.d.ts.map +1 -0
  210. package/dist/volume/passes.d.ts +38 -0
  211. package/dist/volume/passes.d.ts.map +1 -0
  212. package/dist/volume/recovery.d.ts +38 -0
  213. package/dist/volume/recovery.d.ts.map +1 -0
  214. package/dist/volume/resources.d.ts +57 -0
  215. package/dist/volume/resources.d.ts.map +1 -0
  216. package/dist/volume/temporal.d.ts +35 -0
  217. package/dist/volume/temporal.d.ts.map +1 -0
  218. package/package.json +20 -20
  219. package/src/__tests__/bloom-exact-zero.unit.test.ts +48 -19
  220. package/src/__tests__/bloom-lifecycle.integration.test.ts +41 -13
  221. package/src/__tests__/camera-target-consumption.unit.test.ts +53 -0
  222. package/src/__tests__/cluster-binner.unit.test.ts +35 -0
  223. package/src/__tests__/cluster-grid-default-surface.unit.test.ts +7 -2
  224. package/src/__tests__/cube-camera-scheduler.unit.test.ts +70 -0
  225. package/src/__tests__/cube-camera-single-submit.perf.test.ts +75 -0
  226. package/src/__tests__/cube-camera-view-matrices.unit.test.ts +41 -0
  227. package/src/__tests__/cube-camera-vocabulary.unit.test.ts +47 -0
  228. package/src/__tests__/cube-camera.integration.test.ts +42 -0
  229. package/src/__tests__/device-feature-admission.unit.test.ts +73 -0
  230. package/src/__tests__/direct-light-snapshot.unit.test.ts +3 -3
  231. package/src/__tests__/docs-gate-green.unit.test.ts +38 -0
  232. package/src/__tests__/factory-contract.integration.test.ts +255 -29
  233. package/src/__tests__/fog-component.unit.test.ts +67 -0
  234. package/src/__tests__/fog.integration.test.ts +86 -0
  235. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +37 -0
  236. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +10 -9
  237. package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +17 -1
  238. package/src/__tests__/gpu-driven-production.integration.test.ts +16 -17
  239. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +12 -4
  240. package/src/__tests__/gpu-pass-timing-browser-runner.ts +281 -0
  241. package/src/__tests__/gpu-pass-timing-coexistence.integration.test.ts +80 -0
  242. package/src/__tests__/gpu-pass-timing-contract.unit.test.ts +243 -0
  243. package/src/__tests__/gpu-pass-timing-exact-zero.unit.test.ts +131 -0
  244. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +230 -0
  245. package/src/__tests__/gpu-pass-timing-observation.unit.test.ts +233 -0
  246. package/src/__tests__/gpu-pass-timing-session.unit.test.ts +438 -0
  247. package/src/__tests__/gpu-pass-timing.browser.test.ts +26 -0
  248. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +125 -0
  249. package/src/__tests__/hdrp-group2-visibility.unit.test.ts +24 -0
  250. package/src/__tests__/instances-culling.integration.test.ts +94 -0
  251. package/src/__tests__/instances-derived-bounds.unit.test.ts +118 -0
  252. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +14 -14
  253. package/src/__tests__/material-observation.integration.test.ts +101 -0
  254. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +1 -1
  255. package/src/__tests__/pbr-view-layout.unit.test.ts +16 -0
  256. package/src/__tests__/point-shadow-inspection.unit.test.ts +60 -0
  257. package/src/__tests__/public-surface.test-d.ts +10 -0
  258. package/src/__tests__/reflection-probe-authoring.unit.test.ts +71 -0
  259. package/src/__tests__/reflection-probe-filter.unit.test.ts +54 -0
  260. package/src/__tests__/reflection-probe-ibl-topology.unit.test.ts +45 -0
  261. package/src/__tests__/reflection-probe-pass-encode.integration.test.ts +101 -0
  262. package/src/__tests__/reflection-probe-performance.perf.test.ts +60 -0
  263. package/src/__tests__/reflection-probe-recovery.integration.test.ts +55 -0
  264. package/src/__tests__/reflection-probe-selection.unit.test.ts +46 -0
  265. package/src/__tests__/render-error-code-owner.test-d.ts +23 -3
  266. package/src/__tests__/render-feature-docs.unit.test.ts +1 -1
  267. package/src/__tests__/render-target-admission.unit.test.ts +80 -0
  268. package/src/__tests__/render-target-graph-projection.unit.test.ts +102 -0
  269. package/src/__tests__/render-target-inspection.unit.test.ts +52 -0
  270. package/src/__tests__/render-target-material-source.test-d.ts +30 -0
  271. package/src/__tests__/render-target-material-source.unit.test.ts +97 -0
  272. package/src/__tests__/render-target-owner-placement.unit.test.ts +203 -0
  273. package/src/__tests__/render-target-owner.unit.test.ts +122 -0
  274. package/src/__tests__/render-target-probe-soak.perf.test.ts +94 -0
  275. package/src/__tests__/render-target-public-schema.json +107 -0
  276. package/src/__tests__/render-target-public-schema.unit.test.ts +91 -0
  277. package/src/__tests__/render-target-public-surface.test-d.ts +83 -0
  278. package/src/__tests__/render-target-readback.integration.test.ts +90 -0
  279. package/src/__tests__/render-target-recovery.integration.test.ts +85 -0
  280. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +76 -0
  281. package/src/__tests__/renderer-frame-transaction.integration.test.ts +1 -1
  282. package/src/__tests__/renderer-lifecycle.integration.test.ts +14 -0
  283. package/src/__tests__/shader-stage-surface.unit.test.ts +19 -4
  284. package/src/__tests__/skin-motion-regression.unit.test.ts +132 -0
  285. package/src/__tests__/skinned-shadow-caster.test.ts +32 -2
  286. package/src/__tests__/standard-cluster-capability.integration.test.ts +63 -0
  287. package/src/__tests__/standard-cluster-transport.unit.test.ts +121 -0
  288. package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +232 -0
  289. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +8 -5
  290. package/src/__tests__/standard-lighting-inspection.integration.test.ts +138 -0
  291. package/src/__tests__/standard-lighting-ssot.unit.test.ts +18 -0
  292. package/src/__tests__/standard-lighting-write.unit.test.ts +377 -0
  293. package/src/__tests__/standard-lighting.integration.test.ts +67 -0
  294. package/src/__tests__/standard-pipeline.dawn.test.ts +206 -5
  295. package/src/__tests__/standard-pipeline.integration.test.ts +181 -150
  296. package/src/__tests__/standard-probe-binding.unit.test.ts +25 -0
  297. package/src/__tests__/standard-profile-oracle.unit.test.ts +23 -36
  298. package/src/__tests__/typed-pipeline-topology.unit.test.ts +395 -14
  299. package/src/__tests__/urp-pipeline-targets.unit.test.ts +2 -2
  300. package/src/__tests__/visibility-resolver.unit.test.ts +15 -0
  301. package/src/__tests__/volume-optics-oracle.unit.test.ts +85 -0
  302. package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +655 -0
  303. package/src/__tests__/volumetric-fog-component.unit.test.ts +71 -0
  304. package/src/__tests__/volumetric-fog-composite-stage-readback.dawn.test.ts +376 -0
  305. package/src/__tests__/volumetric-fog-errors.unit.test.ts +51 -0
  306. package/src/__tests__/volumetric-fog-inspection.unit.test.ts +77 -0
  307. package/src/__tests__/volumetric-fog-light-capability.unit.test.ts +19 -0
  308. package/src/__tests__/volumetric-fog-light-consumers.integration.test.ts +18 -0
  309. package/src/__tests__/volumetric-fog-light-errors.unit.test.ts +17 -0
  310. package/src/__tests__/volumetric-fog-light-topology.unit.test.ts +21 -0
  311. package/src/__tests__/volumetric-fog-light-transaction.integration.test.ts +53 -0
  312. package/src/__tests__/volumetric-fog-m9-watcher.integration.test.ts +27 -0
  313. package/src/__tests__/volumetric-fog-point-light-owner.integration.test.ts +44 -0
  314. package/src/__tests__/volumetric-fog-point-spot-accumulation.integration.test.ts +49 -0
  315. package/src/__tests__/volumetric-fog-point-spot-contract.unit.test.ts +28 -0
  316. package/src/__tests__/volumetric-fog-point-spot-lkg.integration.test.ts +65 -0
  317. package/src/__tests__/volumetric-fog-point-spot-selection.integration.test.ts +49 -0
  318. package/src/__tests__/volumetric-fog-point-spot-temporal.unit.test.ts +55 -0
  319. package/src/__tests__/volumetric-fog-projector-contract.unit.test.ts +22 -0
  320. package/src/__tests__/volumetric-fog-projector-inspection.unit.test.ts +12 -0
  321. package/src/__tests__/volumetric-fog-projector-surface-volume.integration.test.ts +11 -0
  322. package/src/__tests__/volumetric-fog-projector-transaction.integration.test.ts +26 -0
  323. package/src/__tests__/volumetric-fog-recovery.integration.test.ts +47 -0
  324. package/src/__tests__/volumetric-fog-selected-light-resolution.integration.test.ts +63 -0
  325. package/src/__tests__/volumetric-fog-spot-closure.integration.test.ts +26 -0
  326. package/src/__tests__/volumetric-fog-spot-contract.test-d.ts +21 -0
  327. package/src/__tests__/volumetric-fog-spot-contract.unit.test.ts +27 -0
  328. package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +14 -0
  329. package/src/__tests__/volumetric-fog-spot-optics.integration.test.ts +29 -0
  330. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +550 -0
  331. package/src/__tests__/volumetric-fog-temporal-selected-light.unit.test.ts +33 -0
  332. package/src/__tests__/volumetric-fog-temporal.unit.test.ts +45 -0
  333. package/src/__tests__/volumetric-fog-topology.unit.test.ts +237 -0
  334. package/src/__tests__/volumetric-fog-transparent.integration.test.ts +27 -0
  335. package/src/assembly/device-feature-admission.ts +73 -0
  336. package/src/assembly/directional-shadow-inspection.ts +122 -0
  337. package/src/assembly/factory.ts +1093 -246
  338. package/src/assembly/host-contract.ts +25 -0
  339. package/src/assembly/render-target-host.ts +847 -0
  340. package/src/assets/asset-decoders.ts +1 -1
  341. package/src/assets/render-asset-port.ts +7 -1
  342. package/src/capture/cube-views.ts +69 -0
  343. package/src/capture/scheduler.ts +265 -0
  344. package/src/components/__tests__/schema-contract.unit.test.ts +12 -0
  345. package/src/components/__tests__/schema-parity.unit.test.ts +9 -0
  346. package/src/components/camera.ts +4 -0
  347. package/src/components/cube-camera.ts +52 -0
  348. package/src/components/directional-light.ts +22 -2
  349. package/src/components/directional-shadow-filter.ts +57 -0
  350. package/src/components/index.ts +2 -0
  351. package/src/components/light-helpers.ts +85 -7
  352. package/src/components/reflection-probe.ts +49 -0
  353. package/src/components/spot-light.ts +22 -3
  354. package/src/device/gpu-residency.ts +168 -58
  355. package/src/environment/frame.ts +6 -24
  356. package/src/environment/lifecycle.ts +12 -0
  357. package/src/errors/render.ts +405 -143
  358. package/src/extract/directional-shadow-projection.ts +61 -0
  359. package/src/extract/environment.ts +57 -0
  360. package/src/extract/visibility.ts +25 -1
  361. package/src/features/fullscreen.ts +3 -0
  362. package/src/features/targets.ts +4 -1
  363. package/src/features/types.ts +10 -0
  364. package/src/fullscreen-post-process-pass.ts +43 -2
  365. package/src/gpu-driven/batch-topology.ts +1 -0
  366. package/src/gpu-driven/production-raster.ts +1 -3
  367. package/src/gpu-scene.ts +8 -1
  368. package/src/gpu-usage.ts +2 -0
  369. package/src/hdrp-buffers.ts +165 -59
  370. package/src/ibl/IblPipelineCache.ts +11 -0
  371. package/src/ibl/kernel-cache.ts +88 -0
  372. package/src/index.ts +186 -1
  373. package/src/inspection-types.ts +56 -0
  374. package/src/instances-derived-bounds.ts +171 -0
  375. package/src/light-buffer-layout.ts +74 -26
  376. package/src/mesh-material-bindings.ts +132 -0
  377. package/src/pbr-pipeline.ts +139 -27
  378. package/src/pipeline/standard-forward-lane.ts +65 -15
  379. package/src/pipeline/standard-lighting/errors.ts +6 -0
  380. package/src/pipeline/standard-lighting/graph.ts +157 -0
  381. package/src/pipeline/standard-lighting/inspection.ts +88 -0
  382. package/src/pipeline/standard-lighting/layout.ts +31 -0
  383. package/src/pipeline/standard-lighting/light-frame.ts +34 -0
  384. package/src/pipeline/standard-lighting/membership.ts +43 -0
  385. package/src/pipeline/standard-lighting/prepare.ts +37 -0
  386. package/src/pipeline/standard-lighting/topology.ts +120 -0
  387. package/src/pipeline/standard-lighting/transport.ts +77 -0
  388. package/src/pipeline/standard-pipeline.ts +141 -192
  389. package/src/pipeline/standard-post.ts +26 -7
  390. package/src/pipeline/standard-profile.ts +23 -30
  391. package/src/pipeline-spec.ts +84 -21
  392. package/src/point-shadow-inspection.ts +55 -0
  393. package/src/record/__tests__/temporal-payload.unit.test.ts +42 -1
  394. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +73 -0
  395. package/src/record/__tests__/view-ubo-layout.unit.test.ts +40 -0
  396. package/src/record/frame-lighting.ts +470 -516
  397. package/src/record/frame-snapshot.ts +76 -28
  398. package/src/record/frame-targets.ts +23 -2
  399. package/src/record/frame.ts +1169 -79
  400. package/src/record/gpu-pass-timing/contract.ts +180 -0
  401. package/src/record/gpu-pass-timing/errors.ts +34 -0
  402. package/src/record/gpu-pass-timing/index.ts +37 -0
  403. package/src/record/gpu-pass-timing/parser.ts +97 -0
  404. package/src/record/gpu-pass-timing/session.ts +938 -0
  405. package/src/record/gpu-timing.ts +233 -0
  406. package/src/record/main-pass-geometry.ts +120 -80
  407. package/src/record/main-pass-material.ts +101 -11
  408. package/src/record/main-pass-sprite-draws.ts +54 -25
  409. package/src/record/main-pass.ts +71 -15
  410. package/src/record/render-context.ts +77 -0
  411. package/src/record/shadow-pass.ts +104 -66
  412. package/src/record/skybox-post-pass.ts +20 -4
  413. package/src/record/typed-frame-graph.ts +1016 -32
  414. package/src/record/view-ubo.ts +63 -28
  415. package/src/reflection/filter.ts +81 -0
  416. package/src/reflection/gpu-table.ts +44 -0
  417. package/src/reflection/projection.ts +281 -0
  418. package/src/render-contract.ts +147 -4
  419. package/src/render-data.ts +50 -22
  420. package/src/render-graph-primitives.ts +9 -4
  421. package/src/render-pipeline.ts +161 -2
  422. package/src/render-system-extract.ts +886 -103
  423. package/src/render-system.ts +1174 -66
  424. package/src/renderer-inspect.ts +66 -0
  425. package/src/renderer.ts +222 -0
  426. package/src/scene/render-scene.ts +117 -9
  427. package/src/shadow-atlas.ts +5 -5
  428. package/src/ssao-buffers.ts +9 -2
  429. package/src/targets/contracts.ts +182 -0
  430. package/src/targets/graph-projection.ts +169 -0
  431. package/src/targets/material-source.ts +143 -0
  432. package/src/targets/owner.ts +214 -0
  433. package/src/targets/physical.ts +18 -0
  434. package/src/targets/readback.ts +153 -0
  435. package/src/temporal/frame.ts +128 -0
  436. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +61 -23
  437. package/src/typed-render-graph-primitives.ts +34 -2
  438. package/src/typed-shadow-atlas.ts +17 -0
  439. package/src/typed-shadow-passes.ts +47 -40
  440. package/src/volume/capability.ts +173 -0
  441. package/src/volume/component.ts +110 -0
  442. package/src/volume/extract.ts +21 -0
  443. package/src/volume/inspection.ts +78 -0
  444. package/src/volume/passes.ts +686 -0
  445. package/src/volume/recovery.ts +86 -0
  446. package/src/volume/resources.ts +236 -0
  447. package/src/volume/temporal.ts +89 -0
  448. package/dist/chunk-IPXCABEP.mjs.map +0 -1
  449. package/dist/chunk-LOSO4CTV.mjs.map +0 -1
  450. package/dist/chunk-RJRUS55L.mjs.map +0 -1
  451. package/dist/chunk-YTQ5C7YQ.mjs +0 -584
  452. package/dist/chunk-YTQ5C7YQ.mjs.map +0 -1
@@ -16,6 +16,7 @@ import type {
16
16
  RhiInstance,
17
17
  RhiRenderPassEncoder,
18
18
  RenderPipeline as RhiRenderPipeline,
19
+ Sampler,
19
20
  Texture,
20
21
  TextureFormat,
21
22
  TextureView,
@@ -30,20 +31,55 @@ import type { RenderFeature, RenderFeatureDiagnostics } from './features/types';
30
31
  import type { PostProcessShaderEntry } from './fullscreen-post-process-pass';
31
32
  import type {
32
33
  BloomInspection,
34
+ DirectionalShadowInspection,
33
35
  MotionBlurInspection,
36
+ ReflectionProbeInspection,
34
37
  RenderSceneInspection,
35
38
  TemporalTargetInspection,
36
39
  TransmissionInspection,
37
40
  } from './inspection-types';
41
+ import type {
42
+ RenderTarget,
43
+ RenderTargetDescriptor,
44
+ RenderTargetReadbackData,
45
+ RenderTargetReadbackRequest,
46
+ RenderTargetReadbackTicket,
47
+ RenderTargetTextureSource,
48
+ RenderTargetTextureSourceOptions,
49
+ } from './targets/contracts';
38
50
  import type { TemporalInspection } from './temporal/inspection';
39
51
 
40
52
  export type { TransmissionInspection } from './inspection-types';
41
53
  export type { PointsLinesInspection } from './points-lines/inspection';
42
54
 
43
55
  import type { MeshMaterialBindingObservation } from './mesh-material-bindings';
56
+ import type { StandardLightingInspection } from './pipeline/standard-lighting/inspection';
44
57
  import type { StandardProfile } from './pipeline/standard-profile';
58
+ import type { PointShadowInspection } from './point-shadow-inspection';
45
59
  import type { PostProcessError } from './post-process-errors';
60
+ import type {
61
+ GpuPassTimingObservation,
62
+ GpuPassTimingOptions,
63
+ } from './record/gpu-pass-timing/index.js';
64
+ import type { VolumeTimingObservation } from './record/gpu-timing';
46
65
  import type { TemporalView } from './temporal/view';
66
+ import type { VolumetricFogInspection } from './volume/inspection';
67
+
68
+ export type {
69
+ CubeCameraFace,
70
+ CubeCameraUpdateIntent,
71
+ } from './components/cube-camera';
72
+
73
+ export interface CubeCameraSnapshot {
74
+ readonly entityKey?: number;
75
+ readonly target: RenderTarget;
76
+ readonly position: readonly [number, number, number];
77
+ readonly near: number;
78
+ readonly far: number;
79
+ readonly updateIntent: import('./components/cube-camera').CubeCameraUpdateIntent;
80
+ readonly requestVersion: number;
81
+ readonly faceBudget: number;
82
+ }
47
83
 
48
84
  export type RenderResult<T, E> =
49
85
  | { readonly ok: true; readonly value: T }
@@ -62,6 +98,8 @@ export type RenderWorldLease = RenderReadLease;
62
98
  export interface CameraSnapshot {
63
99
  /** Stable ECS identity used by the frame plan's camera authority fact. */
64
100
  readonly entityKey?: number;
101
+ /** Auxiliary logical target; physical views remain renderer-owned. */
102
+ readonly target?: RenderTarget;
65
103
  /** World index supplied by the multi-world extract merge. */
66
104
  readonly worldId?: number;
67
105
  /** Camera-owned history generation forwarded into the frame plan. */
@@ -102,6 +140,9 @@ export interface CameraSnapshot {
102
140
  /** Stable identity owned by the Standard feature host for output transform. */
103
141
  export const STANDARD_OUTPUT_TRANSFORM_FEATURE_ID = 'forgeax::standard::output-transform';
104
142
 
143
+ /** Stable identity for the special FXAA pass' per-frame output policy UBO. */
144
+ export const FXAA_POST_PROCESS_ID = 'forgeax::post::fxaa';
145
+
105
146
  export type {
106
147
  EnvironmentFrame,
107
148
  EnvironmentSource,
@@ -118,6 +159,14 @@ export type { TemporalView } from './temporal/view';
118
159
  interface RenderPipelineStateView {
119
160
  readonly format: TextureFormat;
120
161
  readonly colorAttachmentFormat: TextureFormat;
162
+ /** Renderer-owned View UBO shared by Standard lighting, shadows, and fog. */
163
+ readonly viewUniformBuffer: Buffer;
164
+ /** Renderer-owned SpotLight std430 buffer shared by Standard and volume. */
165
+ readonly pointLightsBuffer: Buffer;
166
+ readonly spotLightsBuffer: Buffer;
167
+ /** Fallback resources keep the shared view layout valid when no projector is authored. */
168
+ readonly defaultWhiteTextureView: TextureView;
169
+ readonly defaultSampler: Sampler;
121
170
  }
122
171
 
123
172
  /**
@@ -127,6 +176,16 @@ interface RenderPipelineStateView {
127
176
  */
128
177
  interface RenderPipelineRuntime {
129
178
  readonly device: RhiDevice;
179
+ /** Runtime-owned shader module factory used by built-in graph producers. */
180
+ readonly shaderModuleFactory?: {
181
+ createShaderModule(input: {
182
+ readonly code: string;
183
+ readonly label?: string | undefined;
184
+ }): import('@forgeax/engine-types').Result<
185
+ import('@forgeax/engine-rhi').ShaderModule,
186
+ RhiError
187
+ >;
188
+ };
130
189
  readonly errorRegistry: { fire(error: RendererError): void };
131
190
  readonly debugOverlay?: RenderDebugOverlay | undefined;
132
191
  readonly lookupPostProcess?: (id: string) => PostProcessShaderEntry | undefined;
@@ -135,6 +194,7 @@ interface RenderPipelineRuntime {
135
194
  id: string,
136
195
  bgl: BindGroupLayout,
137
196
  colorFormat: GPUTextureFormat,
197
+ entry?: PostProcessShaderEntry,
138
198
  ) => RhiRenderPipeline | null;
139
199
  }
140
200
 
@@ -170,6 +230,56 @@ export interface RenderPipelineContext {
170
230
  readonly msaaActive: boolean;
171
231
  readonly geometryColorResolveView: TextureView | null;
172
232
  readonly ldrSpriteColorView: TextureView | null;
233
+ /** Renderer-owned volume resources prepared from the authored ECS snapshot. */
234
+ readonly volumetricFog?: VolumetricFogFrameContext;
235
+ /** Renderer-owned SpotLight projector resources, independent of fog. */
236
+ readonly spotLightProjector?: SpotLightProjectorFrameContext;
237
+ /** Build-time composed utility sources for the renderer-owned volume passes. */
238
+ readonly volumetricFogShaders?: VolumetricFogShaderSources;
239
+ }
240
+
241
+ /** Stable utility entry-point sources emitted by the shader manifest. */
242
+ export interface VolumetricFogShaderSources {
243
+ readonly inject: string;
244
+ readonly temporal: string;
245
+ readonly integrate: string;
246
+ readonly composite: string;
247
+ }
248
+
249
+ /**
250
+ * GPU resources for one validated volumetric-fog candidate. The record stage
251
+ * owns residency and parameter uploads; graph passes consume this narrow view
252
+ * and never reach into AssetRegistry or World.
253
+ */
254
+ export interface VolumetricFogFrameContext {
255
+ readonly densityTexture: Texture;
256
+ readonly densityView: TextureView;
257
+ readonly paramsBuffer: Buffer;
258
+ readonly densityGeneration: number;
259
+ /** Accepted graph-owned history slot; null means first frame/reset. */
260
+ readonly historyReadSlot: 0 | 1 | null;
261
+ /** Pending graph-owned history slot; promoted only after queue.submit succeeds. */
262
+ readonly historyWriteSlot: 0 | 1;
263
+ readonly historyValid: boolean;
264
+ /** Accepted SpotLight projector resources resolved by the GPU residency owner. */
265
+ readonly projectorTexture?: Texture;
266
+ readonly projectorView?: TextureView;
267
+ readonly projectorSampler?: Sampler;
268
+ }
269
+
270
+ /**
271
+ * GPU resources for the single surface SpotLight projector binding. The
272
+ * projector is a SpotLight-owned cookie and therefore remains available when
273
+ * volumetric fog is disabled; volume integration may reuse the same tuple.
274
+ */
275
+ export interface SpotLightProjectorFrameContext {
276
+ readonly texture: Texture;
277
+ readonly view: TextureView;
278
+ readonly sampler: Sampler;
279
+ /** Spot-light index in ExtractedLights.spot for the accepted texture. */
280
+ readonly spotIndex?: number;
281
+ /** Unified Standard Cluster slot index (points precede spots). */
282
+ readonly lightSlotIndex?: number;
173
283
  }
174
284
 
175
285
  /**
@@ -179,6 +289,20 @@ export interface RenderPipelineContext {
179
289
  export interface Renderer {
180
290
  attach(world: World): RenderResult<RenderWorldLease, RenderError>;
181
291
  draw(input: RenderFrameInput): RenderResult<FrameReceipt, RenderError>;
292
+ createRenderTarget(descriptor: RenderTargetDescriptor): RenderResult<RenderTarget, RenderError>;
293
+ resizeRenderTarget(
294
+ target: RenderTarget,
295
+ descriptor: RenderTargetDescriptor,
296
+ ): RenderResult<void, RenderError>;
297
+ createRenderTargetTextureSource(
298
+ target: RenderTarget,
299
+ options: RenderTargetTextureSourceOptions,
300
+ ): RenderResult<RenderTargetTextureSource, RenderError>;
301
+ requestTargetReadback(
302
+ target: RenderTarget,
303
+ request: RenderTargetReadbackRequest,
304
+ ): RenderResult<RenderTargetReadbackTicket, RenderError>;
305
+ destroyRenderTarget(target: RenderTarget): RenderResult<void, RenderError>;
182
306
  setProfile(profile: RenderProfile): RenderResult<void, RenderError>;
183
307
  state(): RendererState;
184
308
  inspect(): RenderInspection;
@@ -189,6 +313,7 @@ export interface Renderer {
189
313
  subscribe(listener: (event: RendererEvent) => void): () => void;
190
314
  releaseSurface(): RenderResult<void, RenderError>;
191
315
  restoreSurface(): RenderResult<void, RenderError>;
316
+ /** Recover only from device-lost; a healthy renderer returns a guard error. */
192
317
  recover(): Promise<RenderResult<void, RenderError>>;
193
318
  dispose(): Promise<RenderResult<void, RenderError>>;
194
319
  }
@@ -238,11 +363,12 @@ export interface FrameEnvironment {
238
363
 
239
364
  /**
240
365
  * Receipt-bound observation selection. The request is consumed by `observe`
241
- * only with the matching FrameReceipt and returns a structured Result error
242
- * when the generation or frame identity is stale.
366
+ * only with the matching FrameReceipt after `receipt.completed` and returns a
367
+ * structured Result error when the generation or frame identity is stale.
243
368
  */
244
369
  export interface FrameObservationRequest {
245
- readonly include: readonly ('timings' | 'draws' | 'bindings')[];
370
+ readonly include: readonly ('timings' | 'draws' | 'bindings' | 'target-readbacks')[];
371
+ readonly targetReadbacks?: readonly RenderTargetReadbackTicket[];
246
372
  }
247
373
 
248
374
  /**
@@ -273,7 +399,12 @@ export interface RenderFrameInput {
273
399
  export interface FrameReceiptObservation {
274
400
  readonly frameId: number;
275
401
  readonly deviceGeneration: number;
276
- readonly include: readonly ('timings' | 'draws' | 'bindings')[];
402
+ readonly include: readonly ('timings' | 'draws' | 'bindings' | 'target-readbacks')[];
403
+ /** Receipt-bound Render-owned GPU pass facts; absent when not requested. */
404
+ readonly timings?: GpuPassTimingObservation | undefined;
405
+ /** Receipt-bound volume GPU timing facts; absent when not requested. */
406
+ readonly volumeTimings?: VolumeTimingObservation | undefined;
407
+ readonly targetReadbacks?: readonly RenderTargetReadbackData[];
277
408
  }
278
409
 
279
410
  /** Stable backend facts for the Standard output transform projection. */
@@ -342,14 +473,21 @@ export interface RenderInspection {
342
473
  readonly frameId: number;
343
474
  readonly deviceGeneration: number;
344
475
  };
476
+ /** Renderer-owned authored volume projection and submit/LKG state. */
477
+ readonly volumetricFog?: VolumetricFogInspection;
345
478
  readonly features: readonly string[];
346
479
  /** Truthful lifecycle facts for every registered declarative feature. */
347
480
  readonly featureDiagnostics: readonly RenderFeatureDiagnostics[];
348
481
  readonly frustumStats: { readonly culled: number; readonly total: number };
349
482
  readonly visibilityStats: { readonly explicitlyHidden: number };
350
483
  readonly renderScene: RenderSceneInspection;
484
+ readonly reflectionProbes: ReflectionProbeInspection;
351
485
  /** Last completed transmission candidate facts, detached from GPU handles. */
352
486
  readonly transmission?: TransmissionInspection;
487
+ /** Last prepared Standard transport facts, detached from GPU handles. */
488
+ readonly standardLighting?: StandardLightingInspection;
489
+ /** Renderer-owned point-shadow atlas budget facts from the last frame. */
490
+ readonly pointShadow?: PointShadowInspection;
353
491
  readonly meshMaterialBindings: readonly MeshMaterialBindingObservation[];
354
492
  readonly perFramePassNames: readonly string[];
355
493
  readonly bindGroupCounts: {
@@ -370,6 +508,7 @@ export interface RenderInspection {
370
508
  readonly environment: EnvironmentInspection;
371
509
  readonly temporal: TemporalInspection;
372
510
  readonly bloom: BloomInspection;
511
+ readonly directionalShadow: DirectionalShadowInspection;
373
512
  /** Semantic Standard temporal target metadata; no graph or RHI handles. */
374
513
  readonly temporalTarget?: TemporalTargetInspection;
375
514
  /** Renderer-owned Motion Blur facts; absent when no component is active. */
@@ -577,8 +716,12 @@ export interface RendererOptions {
577
716
  readonly standardProfile?: RenderProfile | undefined;
578
717
  /** Explicit profiler capability shared by App and Render. */
579
718
  readonly profiler?: Profiler | undefined;
719
+ /** Explicitly request timestamp-query for receipt-bound GPU profiling. */
720
+ readonly captureGpuTimings?: boolean | undefined;
580
721
  /** Optional host-owned RHI lifecycle instrumentation, such as recording. */
581
722
  readonly rhiInstrumentation?: RhiBackendInstrumentation | undefined;
723
+ /** Optional bounded GPU pass timing facts; this is not frame latency. */
724
+ readonly gpuPassTiming?: GpuPassTimingOptions | undefined;
582
725
  // feat-20260608-create-app-param-surface-trim / M1 / AC-02: `clearColor`
583
726
  // was deleted as a one-cut breaking change (AGENTS.md Change stance +
584
727
  // requirements constraint #1: no deprecation window, no shim). Scene
@@ -15,7 +15,6 @@
15
15
  // GPU-resource kind would surface as a `tsc -b` exhaustiveness error at the
16
16
  // switch rather than a silent fallthrough (AC-06).
17
17
 
18
- import { numMipLevels } from '@forgeax/engine-assets-runtime';
19
18
  import {
20
19
  bytesPerRow as blockBytesPerRow,
21
20
  blockParamsForFormat,
@@ -29,9 +28,11 @@ import { err, ok, type Result } from '@forgeax/engine-rhi';
29
28
  import {
30
29
  ASSET_ERROR_HINTS,
31
30
  type AssetError,
31
+ deriveTextureLayout,
32
32
  type MeshAsset,
33
33
  type Submesh,
34
34
  type TextureAsset,
35
+ type TextureShape,
35
36
  } from '@forgeax/engine-types';
36
37
  import {
37
38
  GPU_TEXTURE_USAGE_COPY_DST,
@@ -88,12 +89,16 @@ export interface MeshRenderData {
88
89
  readonly submeshes: readonly Submesh[];
89
90
  }
90
91
 
91
- /** Descriptor for a 2D texture's GPU resource (projected from POD). */
92
+ /** Descriptor for a sampled texture's GPU resource (projected from POD). */
92
93
  export interface TextureRenderData {
93
94
  /** Logical width retained for existing projection consumers. */
94
95
  readonly width: number;
95
96
  /** Logical height retained for existing projection consumers. */
96
97
  readonly height: number;
98
+ /** Authored shape; the residency layer must preserve this view dimension. */
99
+ readonly shape: TextureShape;
100
+ /** Array layers for `2d-array`, depth slices for `3d`, otherwise one. */
101
+ readonly depthOrArrayLayers: number;
97
102
  /** Authored content extent; TextureAsset remains the logical asset SSOT. */
98
103
  readonly logicalExtent: TextureExtent;
99
104
  /** GPU allocation extent, derived from format + logicalExtent. */
@@ -105,10 +110,10 @@ export interface TextureRenderData {
105
110
  readonly usage: number;
106
111
  /**
107
112
  * Row pitch for the BASE mip (level 0) the store passes to `writeTexture`.
108
- * Uncompressed: `width * 4` (RGBA8). Block-compressed: the block-padded
109
- * `ceil(width / blockW) * bytesPerBlock` (feat-20260707 M5 / w35, AC-08).
110
- * The per-mip layout for a multi-level compressed upload comes from
111
- * {@link deriveMipUploadLayout}.
113
+ * Derived from the canonical texture layout, so format-specific uncompressed
114
+ * widths (for example R8 density) and block-compressed widths stay aligned
115
+ * with the upload contract. The per-mip layout for a multi-level compressed
116
+ * upload comes from {@link deriveMipUploadLayout}.
112
117
  */
113
118
  readonly bytesPerRow: number;
114
119
  /** True iff `format` is a block-compressed format (drives the store's upload arm). */
@@ -262,6 +267,8 @@ export function deriveRenderDataMesh(mesh: MeshAsset): Result<MeshRenderData, As
262
267
  * inconsistent (a `-srgb` format requires an `srgb` colorSpace and vice versa).
263
268
  */
264
269
  export function deriveRenderDataTexture(tex: TextureAsset): Result<TextureRenderData, AssetError> {
270
+ const width = tex.shape.extent.width;
271
+ const height = tex.shape.extent.height;
265
272
  const isSrgbFormat = tex.format.endsWith('-srgb');
266
273
  const expectedColorSpace: 'srgb' | 'linear' = isSrgbFormat ? 'srgb' : 'linear';
267
274
  if (tex.colorSpace !== expectedColorSpace) {
@@ -275,14 +282,23 @@ export function deriveRenderDataTexture(tex: TextureAsset): Result<TextureRender
275
282
  }
276
283
 
277
284
  const compressed = isCompressedFormat(tex.format);
285
+ const layout = deriveTextureLayout({ shape: tex.shape, format: tex.format, mips: tex.mips });
286
+ if (!layout.ok) {
287
+ return err(
288
+ projectionError({
289
+ code: 'invalid-source-format',
290
+ expected: layout.error.expected,
291
+ hint: layout.error.hint,
292
+ }),
293
+ );
294
+ }
278
295
  // feat-20260707 M5 / w35 (AC-09, D-9): a block-compressed texture cannot have
279
296
  // its mips GPU-generated (F-7). An OFFLINE chain baked into `data`
280
297
  // (mipLevelCount > 1, e.g. a KTX2 level chain) is the normal compressed path
281
298
  // and passes; requesting RUNTIME mip generation (`mipmap:true` with no offline
282
299
  // chain) fails fast with a self-recovery hint (fail-fast at the projection
283
300
  // layer -- producer self-validate).
284
- const hasOfflineMipChain = (tex.mipLevelCount ?? 1) > 1;
285
- if (compressed && tex.mipmap === true && !hasOfflineMipChain) {
301
+ if (compressed && tex.mips.kind === 'generate') {
286
302
  return err(
287
303
  projectionError({
288
304
  code: 'mipgen-unsupported-compressed-format',
@@ -296,15 +312,19 @@ export function deriveRenderDataTexture(tex: TextureAsset): Result<TextureRender
296
312
  // Uncompressed: runtime mip-gen count from the pixel size. Compressed: the
297
313
  // level count is authored (offline chain) -- honour the POD's mipLevelCount,
298
314
  // never re-derive it from the size (a compressed chain may stop early).
299
- const mipLevelCount = compressed
300
- ? Math.max(1, tex.mipLevelCount ?? 1)
301
- : tex.mipmap
302
- ? numMipLevels(tex)
303
- : 1;
315
+ const mipLevelCount = layout.value.levels.length;
304
316
 
305
- const uncompressedBytesPerTexel =
306
- tex.format === 'rgba32float' ? 16 : tex.format === 'rgba16float' ? 8 : 4;
307
- if (!compressed && tex.data.byteLength < tex.width * tex.height * uncompressedBytesPerTexel) {
317
+ const baseLevel = layout.value.levels[0];
318
+ if (baseLevel === undefined) {
319
+ return err(
320
+ projectionError({
321
+ code: 'invalid-source-format',
322
+ expected: 'texture layout contains a base mip level',
323
+ hint: ASSET_ERROR_HINTS['invalid-source-format'],
324
+ }),
325
+ );
326
+ }
327
+ if (!compressed && tex.data.byteLength < baseLevel.byteLength) {
308
328
  return err(
309
329
  projectionError({
310
330
  code: 'invalid-source-format',
@@ -318,8 +338,8 @@ export function deriveRenderDataTexture(tex: TextureAsset): Result<TextureRender
318
338
  // from the format, not aggregate payload length: imported images may retain
319
339
  // trailing decoder bytes and offline mip chains contain more than the base mip.
320
340
  const bytesPerRow = compressed
321
- ? (blockBytesPerRow(tex.format, tex.width) ?? tex.width * 4)
322
- : tex.width * uncompressedBytesPerTexel;
341
+ ? (blockBytesPerRow(tex.format, width) ?? baseLevel.bytesPerRow)
342
+ : baseLevel.bytesPerRow;
323
343
 
324
344
  // Compressed formats are not renderable -- RENDER_ATTACHMENT would fail
325
345
  // createTexture validation, and the runtime mipmap blit (which needs it) never
@@ -333,9 +353,16 @@ export function deriveRenderDataTexture(tex: TextureAsset): Result<TextureRender
333
353
  GPU_TEXTURE_USAGE_COPY_SRC;
334
354
 
335
355
  return ok({
336
- width: tex.width,
337
- height: tex.height,
338
- ...deriveTextureExtent(tex.format, tex.width, tex.height),
356
+ width,
357
+ height,
358
+ shape: tex.shape,
359
+ depthOrArrayLayers:
360
+ tex.shape.viewDimension === '2d'
361
+ ? 1
362
+ : tex.shape.viewDimension === '2d-array'
363
+ ? tex.shape.extent.layers
364
+ : tex.shape.extent.depth,
365
+ ...deriveTextureExtent(tex.format, width, height),
339
366
  format: tex.format,
340
367
  mipLevelCount,
341
368
  usage,
@@ -373,8 +400,9 @@ export function deriveRenderDataCubemap(source: TextureAsset): Result<CubeRender
373
400
  }),
374
401
  );
375
402
  }
403
+ const sourceHeight = source.shape.viewDimension === '2d' ? source.shape.extent.height : 0;
376
404
  return ok({
377
- cubeFaceSize: source.height,
405
+ cubeFaceSize: sourceHeight,
378
406
  outputFormat: 'rgba16float',
379
407
  needsHalfConversion: source.format === 'rgba32float',
380
408
  cubeUsage:
@@ -550,6 +550,7 @@ function dispatchFullscreenPass(
550
550
  graphPass?: RhiRenderPassEncoder,
551
551
  graphOutputFormat?: GPUTextureFormat,
552
552
  graphDepthView?: TextureView,
553
+ paramsOverride?: Uint8Array,
553
554
  ): void {
554
555
  if (shader === 'fxaa') {
555
556
  if (resolveCtx === undefined) {
@@ -705,7 +706,11 @@ function dispatchFullscreenPass(
705
706
  if (entry.params !== undefined) {
706
707
  const ubo = ctx.runtime.getPostProcessParamsBuffer?.(shader);
707
708
  if (ubo !== undefined) {
708
- const data = ctx.postProcessParams.get(shader);
709
+ // Typed graph passes may make a narrow, per-pass copy of the payload
710
+ // (for example enabling final-surface dither without changing the
711
+ // camera-owned SSOT). Use it when present, while preserving the normal
712
+ // frame snapshot for legacy callers.
713
+ const data = paramsOverride ?? ctx.postProcessParams.get(shader);
709
714
  if (data !== undefined) {
710
715
  if (data.byteLength !== entry.params.byteSize) {
711
716
  throw new PostProcessError({
@@ -769,9 +774,7 @@ function dispatchFullscreenPass(
769
774
  if (lookupPipeline === undefined) return;
770
775
  const postColorFormat = writeFormat;
771
776
  const pipeline = lookupPipeline(shader, built.bindGroupLayout, postColorFormat);
772
- if (pipeline === null) {
773
- return;
774
- }
777
+ if (pipeline === null) return;
775
778
  const handle = built.createHandle(name, pipeline, paramsBuffer);
776
779
 
777
780
  // Open a render pass writing into the resolved color target. Fullscreen
@@ -810,6 +813,7 @@ export function encodeFullscreenPass(
810
813
  readonly outputFormat: GPUTextureFormat;
811
814
  readonly rawSwapchainOutput?: boolean | undefined;
812
815
  readonly depthView?: TextureView | undefined;
816
+ readonly paramsOverride?: Uint8Array | undefined;
813
817
  },
814
818
  ): void {
815
819
  dispatchFullscreenPass(
@@ -824,5 +828,6 @@ export function encodeFullscreenPass(
824
828
  pass,
825
829
  input.outputFormat,
826
830
  input.depthView,
831
+ input.paramsOverride,
827
832
  );
828
833
  }