@forgeax/engine-render 0.1.27 → 0.1.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (655) hide show
  1. package/README.md +842 -124
  2. package/dist/assembly/atmosphere-shader-prewarm.d.ts +6 -0
  3. package/dist/assembly/atmosphere-shader-prewarm.d.ts.map +1 -0
  4. package/dist/assembly/dynamic-geometry-host.d.ts +52 -0
  5. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -0
  6. package/dist/assembly/dynamic-geometry-runtime.d.ts +20 -0
  7. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -0
  8. package/dist/assembly/factory.d.ts +3 -1
  9. package/dist/assembly/factory.d.ts.map +1 -1
  10. package/dist/assembly/gpu-driven-owner.d.ts +10 -0
  11. package/dist/assembly/gpu-driven-owner.d.ts.map +1 -0
  12. package/dist/assembly/host-contract.d.ts +19 -0
  13. package/dist/assembly/host-contract.d.ts.map +1 -1
  14. package/dist/assembly/material/assembly.d.ts +7 -0
  15. package/dist/assembly/material/assembly.d.ts.map +1 -1
  16. package/dist/assembly/material-shader-policy.d.ts +3 -1
  17. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  18. package/dist/assembly/recovery/failure-location.d.ts +12 -0
  19. package/dist/assembly/recovery/failure-location.d.ts.map +1 -0
  20. package/dist/assembly/recovery/renderer-recover.d.ts +6 -4
  21. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  22. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  23. package/dist/assembly/renderer-feature-inspection.d.ts +5 -0
  24. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -0
  25. package/dist/assembly/renderer-frame-transaction.d.ts +19 -0
  26. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  27. package/dist/assembly/renderer-helpers.d.ts +3 -0
  28. package/dist/assembly/renderer-helpers.d.ts.map +1 -1
  29. package/dist/assembly/renderer-inspection.d.ts +4 -0
  30. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  31. package/dist/assembly/shader-prewarm-policy.d.ts +6 -0
  32. package/dist/assembly/shader-prewarm-policy.d.ts.map +1 -1
  33. package/dist/assembly/skin-palette-owner.d.ts +8 -0
  34. package/dist/assembly/skin-palette-owner.d.ts.map +1 -0
  35. package/dist/assembly/ssr-shader-prewarm.d.ts +6 -0
  36. package/dist/assembly/ssr-shader-prewarm.d.ts.map +1 -0
  37. package/dist/assembly/webgpu-device-loss.d.ts +15 -0
  38. package/dist/assembly/webgpu-device-loss.d.ts.map +1 -0
  39. package/dist/assembly/webgpu-pbr-ready.d.ts +38 -0
  40. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -0
  41. package/dist/assembly/webgpu-ready-mipmap.d.ts +11 -0
  42. package/dist/assembly/webgpu-ready-mipmap.d.ts.map +1 -0
  43. package/dist/assembly/webgpu-ready.d.ts +7 -3
  44. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  45. package/dist/assembly/webgpu-renderer-bootstrap.d.ts +10 -0
  46. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -0
  47. package/dist/assembly/webgpu-renderer-contract.d.ts +62 -0
  48. package/dist/assembly/webgpu-renderer-contract.d.ts.map +1 -0
  49. package/dist/assembly/webgpu-renderer-guards.d.ts +9 -0
  50. package/dist/assembly/webgpu-renderer-guards.d.ts.map +1 -0
  51. package/dist/assembly/webgpu-renderer-observation.d.ts +6 -0
  52. package/dist/assembly/webgpu-renderer-observation.d.ts.map +1 -0
  53. package/dist/assembly/webgpu-renderer-recovery-failure.d.ts +12 -0
  54. package/dist/assembly/webgpu-renderer-recovery-failure.d.ts.map +1 -0
  55. package/dist/assembly/webgpu-renderer.d.ts +7 -141
  56. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  57. package/dist/assembly/webgpu-vertex-layouts.d.ts +28 -84
  58. package/dist/assembly/webgpu-vertex-layouts.d.ts.map +1 -1
  59. package/dist/authoring.mjs +3 -3
  60. package/dist/{chunk-ADHHVYLW.mjs → chunk-33XZFTQU.mjs} +245 -39
  61. package/dist/chunk-33XZFTQU.mjs.map +1 -0
  62. package/dist/{chunk-GF523LHF.mjs → chunk-BLXGONR2.mjs} +30 -12
  63. package/dist/chunk-BLXGONR2.mjs.map +1 -0
  64. package/dist/{chunk-KM2NOX2I.mjs → chunk-BQVQOQJH.mjs} +958 -254
  65. package/dist/chunk-BQVQOQJH.mjs.map +1 -0
  66. package/dist/{chunk-HKXTW355.mjs → chunk-BTWH7BP4.mjs} +386 -17
  67. package/dist/chunk-BTWH7BP4.mjs.map +1 -0
  68. package/dist/{chunk-TMIASV2N.mjs → chunk-FUODTTIA.mjs} +3934 -676
  69. package/dist/chunk-FUODTTIA.mjs.map +1 -0
  70. package/dist/{chunk-FJ6P52EE.mjs → chunk-ILQ5MEZF.mjs} +3 -17
  71. package/dist/chunk-ILQ5MEZF.mjs.map +1 -0
  72. package/dist/{chunk-E34VL5VI.mjs → chunk-JQTSEI3Z.mjs} +3 -3
  73. package/dist/{chunk-E34VL5VI.mjs.map → chunk-JQTSEI3Z.mjs.map} +1 -1
  74. package/dist/{chunk-GE3SDD72.mjs → chunk-NICXSHAT.mjs} +16 -38
  75. package/dist/chunk-NICXSHAT.mjs.map +1 -0
  76. package/dist/{chunk-ZZ4YQ474.mjs → chunk-NRNXBLIJ.mjs} +577 -7
  77. package/dist/chunk-NRNXBLIJ.mjs.map +1 -0
  78. package/dist/{chunk-JDWARUOI.mjs → chunk-PA5DRJNI.mjs} +17 -3
  79. package/dist/chunk-PA5DRJNI.mjs.map +1 -0
  80. package/dist/{chunk-XDP6XE5V.mjs → chunk-S4DNKQYQ.mjs} +1118 -446
  81. package/dist/chunk-S4DNKQYQ.mjs.map +1 -0
  82. package/dist/components/camera.d.ts +62 -2
  83. package/dist/components/camera.d.ts.map +1 -1
  84. package/dist/components/index.d.ts +1 -0
  85. package/dist/components/index.d.ts.map +1 -1
  86. package/dist/components/instances.d.ts +6 -20
  87. package/dist/components/instances.d.ts.map +1 -1
  88. package/dist/components/scene-instance.d.ts +2 -1
  89. package/dist/components/scene-instance.d.ts.map +1 -1
  90. package/dist/components/screen-space-reflection.d.ts +14 -0
  91. package/dist/components/screen-space-reflection.d.ts.map +1 -0
  92. package/dist/construct-renderer.mjs +13805 -7186
  93. package/dist/construct-renderer.mjs.map +1 -1
  94. package/dist/device/gpu-residency.d.ts +11 -17
  95. package/dist/device/gpu-residency.d.ts.map +1 -1
  96. package/dist/device/mesh-residency-lifetime.d.ts +21 -0
  97. package/dist/device/mesh-residency-lifetime.d.ts.map +1 -0
  98. package/dist/dynamic-geometry.d.ts +125 -0
  99. package/dist/dynamic-geometry.d.ts.map +1 -0
  100. package/dist/environment/background.d.ts +6 -0
  101. package/dist/environment/background.d.ts.map +1 -0
  102. package/dist/errors/gpu-driven.d.ts +6 -3
  103. package/dist/errors/gpu-driven.d.ts.map +1 -1
  104. package/dist/errors/render.d.ts +7 -4
  105. package/dist/errors/render.d.ts.map +1 -1
  106. package/dist/extract/camera.d.ts.map +1 -1
  107. package/dist/extract/gpu-driven.d.ts +33 -3
  108. package/dist/extract/gpu-driven.d.ts.map +1 -1
  109. package/dist/features/host.d.ts +23 -1
  110. package/dist/features/host.d.ts.map +1 -1
  111. package/dist/features/noise-texture.d.ts +17 -0
  112. package/dist/features/noise-texture.d.ts.map +1 -0
  113. package/dist/features/plan.d.ts +83 -2
  114. package/dist/features/plan.d.ts.map +1 -1
  115. package/dist/features/prepared-gpu-work.d.ts +37 -4
  116. package/dist/features/prepared-gpu-work.d.ts.map +1 -1
  117. package/dist/features/prepared-graphics-store.d.ts.map +1 -1
  118. package/dist/features/prepared-graphics.d.ts +5 -0
  119. package/dist/features/prepared-graphics.d.ts.map +1 -1
  120. package/dist/features/render-graph-compute.d.ts +5 -3
  121. package/dist/features/render-graph-compute.d.ts.map +1 -1
  122. package/dist/features/render-graph-contribution.d.ts +11 -3
  123. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  124. package/dist/features/render-graph-raster.d.ts +19 -3
  125. package/dist/features/render-graph-raster.d.ts.map +1 -1
  126. package/dist/features/types.d.ts +11 -0
  127. package/dist/features/types.d.ts.map +1 -1
  128. package/dist/fullscreen-post-process-pass.d.ts +2 -0
  129. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  130. package/dist/gpu-driven/batch-topology.d.ts +34 -1
  131. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  132. package/dist/gpu-driven/pbr-program.d.ts +10 -0
  133. package/dist/gpu-driven/pbr-program.d.ts.map +1 -0
  134. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  135. package/dist/gpu-driven/production-raster.d.ts +144 -23
  136. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  137. package/dist/gpu-driven/shadow-views.d.ts +126 -0
  138. package/dist/gpu-driven/shadow-views.d.ts.map +1 -0
  139. package/dist/gpu-driven/view-gpu.d.ts +18 -2
  140. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  141. package/dist/gpu-scene-schema.d.ts +2 -8
  142. package/dist/gpu-scene-schema.d.ts.map +1 -1
  143. package/dist/gpu-scene.d.ts +14 -0
  144. package/dist/gpu-scene.d.ts.map +1 -1
  145. package/dist/gpu-texture-usage.d.ts +1 -0
  146. package/dist/gpu-texture-usage.d.ts.map +1 -1
  147. package/dist/hdrp-buffers.d.ts +6 -0
  148. package/dist/hdrp-buffers.d.ts.map +1 -1
  149. package/dist/ibl/frame-resources.d.ts +8 -0
  150. package/dist/ibl/frame-resources.d.ts.map +1 -0
  151. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  152. package/dist/index.d.ts +21 -8
  153. package/dist/index.d.ts.map +1 -1
  154. package/dist/index.mjs +8 -7
  155. package/dist/index.mjs.map +1 -1
  156. package/dist/inspection-types.d.ts +164 -0
  157. package/dist/inspection-types.d.ts.map +1 -1
  158. package/dist/instances-derived-bounds.d.ts +11 -0
  159. package/dist/instances-derived-bounds.d.ts.map +1 -1
  160. package/dist/instances.d.ts +89 -44
  161. package/dist/instances.d.ts.map +1 -1
  162. package/dist/internal.d.ts +3 -0
  163. package/dist/internal.d.ts.map +1 -1
  164. package/dist/internal.mjs +118 -10
  165. package/dist/internal.mjs.map +1 -1
  166. package/dist/lifecycle.d.ts +2 -1
  167. package/dist/lifecycle.d.ts.map +1 -1
  168. package/dist/material-row.d.ts +5 -0
  169. package/dist/material-row.d.ts.map +1 -0
  170. package/dist/materials.d.ts +15 -0
  171. package/dist/materials.d.ts.map +1 -1
  172. package/dist/pbr-pipeline.d.ts +21 -5
  173. package/dist/pbr-pipeline.d.ts.map +1 -1
  174. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  175. package/dist/pipeline/standard-output/auto-exposure/capability.d.ts +12 -0
  176. package/dist/pipeline/standard-output/auto-exposure/capability.d.ts.map +1 -0
  177. package/dist/pipeline/standard-output/auto-exposure/gpu.d.ts +70 -0
  178. package/dist/pipeline/standard-output/auto-exposure/gpu.d.ts.map +1 -0
  179. package/dist/pipeline/standard-output/auto-exposure/graph.d.ts +75 -0
  180. package/dist/pipeline/standard-output/auto-exposure/graph.d.ts.map +1 -0
  181. package/dist/pipeline/standard-output/auto-exposure/inspection.d.ts +111 -0
  182. package/dist/pipeline/standard-output/auto-exposure/inspection.d.ts.map +1 -0
  183. package/dist/pipeline/standard-output/auto-exposure/oracle.d.ts +16 -0
  184. package/dist/pipeline/standard-output/auto-exposure/oracle.d.ts.map +1 -0
  185. package/dist/pipeline/standard-output/auto-exposure/preset.d.ts +14 -0
  186. package/dist/pipeline/standard-output/auto-exposure/preset.d.ts.map +1 -0
  187. package/dist/pipeline/standard-output/auto-exposure/state.d.ts +46 -0
  188. package/dist/pipeline/standard-output/auto-exposure/state.d.ts.map +1 -0
  189. package/dist/pipeline/standard-output/color-transform.d.ts +27 -0
  190. package/dist/pipeline/standard-output/color-transform.d.ts.map +1 -0
  191. package/dist/pipeline/standard-output/graph.d.ts +15 -0
  192. package/dist/pipeline/standard-output/graph.d.ts.map +1 -0
  193. package/dist/pipeline/standard-output/lut-admission.d.ts +29 -0
  194. package/dist/pipeline/standard-output/lut-admission.d.ts.map +1 -0
  195. package/dist/pipeline/standard-output/lut-gpu.d.ts +48 -0
  196. package/dist/pipeline/standard-output/lut-gpu.d.ts.map +1 -0
  197. package/dist/pipeline/standard-output/lut-state.d.ts +68 -0
  198. package/dist/pipeline/standard-output/lut-state.d.ts.map +1 -0
  199. package/dist/pipeline/standard-output/resources.d.ts +10 -0
  200. package/dist/pipeline/standard-output/resources.d.ts.map +1 -0
  201. package/dist/pipeline/standard-output/types.d.ts +39 -0
  202. package/dist/pipeline/standard-output/types.d.ts.map +1 -0
  203. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  204. package/dist/pipeline/standard-post.d.ts +2 -2
  205. package/dist/pipeline/standard-post.d.ts.map +1 -1
  206. package/dist/pipeline-builder.d.ts +2 -1
  207. package/dist/pipeline-builder.d.ts.map +1 -1
  208. package/dist/pipeline-spec-types.d.ts +4 -0
  209. package/dist/pipeline-spec-types.d.ts.map +1 -1
  210. package/dist/pipeline-spec.d.ts +1 -9
  211. package/dist/pipeline-spec.d.ts.map +1 -1
  212. package/dist/points-lines/standard-owner.d.ts +1 -1
  213. package/dist/points-lines/standard-owner.d.ts.map +1 -1
  214. package/dist/prepare/prepared-graphics-resolver.d.ts +6 -1
  215. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  216. package/dist/record/dynamic-geometry-consumption.d.ts +15 -0
  217. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -0
  218. package/dist/record/frame-lighting.d.ts +3 -3
  219. package/dist/record/frame-lighting.d.ts.map +1 -1
  220. package/dist/record/frame-snapshot.d.ts +106 -5
  221. package/dist/record/frame-snapshot.d.ts.map +1 -1
  222. package/dist/record/frame-targets.d.ts.map +1 -1
  223. package/dist/record/frame.d.ts +39 -4
  224. package/dist/record/frame.d.ts.map +1 -1
  225. package/dist/record/main-pass-geometry.d.ts +7 -8
  226. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  227. package/dist/record/main-pass-material.d.ts +38 -1
  228. package/dist/record/main-pass-material.d.ts.map +1 -1
  229. package/dist/record/main-pass-sprite-draws.d.ts +2 -10
  230. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  231. package/dist/record/main-pass.d.ts +12 -2
  232. package/dist/record/main-pass.d.ts.map +1 -1
  233. package/dist/record/mesh-ssbo.d.ts +15 -6
  234. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  235. package/dist/record/prepared-material-bindings.d.ts +19 -0
  236. package/dist/record/prepared-material-bindings.d.ts.map +1 -0
  237. package/dist/record/recovery-pipeline.d.ts +2 -9
  238. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  239. package/dist/record/render-context.d.ts +76 -26
  240. package/dist/record/render-context.d.ts.map +1 -1
  241. package/dist/record/shadow-pass.d.ts +62 -7
  242. package/dist/record/shadow-pass.d.ts.map +1 -1
  243. package/dist/record/skybox-post-pass.d.ts +1 -1
  244. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  245. package/dist/record/typed-frame-graph.d.ts +35 -7
  246. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  247. package/dist/record/view-ubo.d.ts +1 -0
  248. package/dist/record/view-ubo.d.ts.map +1 -1
  249. package/dist/recovery/render-system-candidate.d.ts +10 -2
  250. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  251. package/dist/recovery/render-system-roots.d.ts +11 -0
  252. package/dist/recovery/render-system-roots.d.ts.map +1 -0
  253. package/dist/recovery/types.d.ts +76 -0
  254. package/dist/recovery/types.d.ts.map +1 -0
  255. package/dist/reflection/record-owner.d.ts +0 -2
  256. package/dist/reflection/record-owner.d.ts.map +1 -1
  257. package/dist/render-contract.d.ts +185 -30
  258. package/dist/render-contract.d.ts.map +1 -1
  259. package/dist/render-graph-primitives.d.ts +1 -0
  260. package/dist/render-graph-primitives.d.ts.map +1 -1
  261. package/dist/render-pipeline.d.ts +64 -5
  262. package/dist/render-pipeline.d.ts.map +1 -1
  263. package/dist/render-system-extract-tail.d.ts +7 -5
  264. package/dist/render-system-extract-tail.d.ts.map +1 -1
  265. package/dist/render-system-extract.d.ts +101 -41
  266. package/dist/render-system-extract.d.ts.map +1 -1
  267. package/dist/render-system-projections.d.ts +22 -0
  268. package/dist/render-system-projections.d.ts.map +1 -0
  269. package/dist/render-system.d.ts +34 -77
  270. package/dist/render-system.d.ts.map +1 -1
  271. package/dist/scene/render-scene-types.d.ts +14 -7
  272. package/dist/scene/render-scene-types.d.ts.map +1 -1
  273. package/dist/scene/render-scene.d.ts +29 -11
  274. package/dist/scene/render-scene.d.ts.map +1 -1
  275. package/dist/scene/shadow-visibility.d.ts +5 -0
  276. package/dist/scene/shadow-visibility.d.ts.map +1 -0
  277. package/dist/ssr/admission.d.ts +70 -1
  278. package/dist/ssr/admission.d.ts.map +1 -1
  279. package/dist/ssr/compose.d.ts +13 -0
  280. package/dist/ssr/compose.d.ts.map +1 -0
  281. package/dist/ssr/errors.d.ts +35 -0
  282. package/dist/ssr/errors.d.ts.map +1 -1
  283. package/dist/ssr/graph.d.ts +60 -0
  284. package/dist/ssr/graph.d.ts.map +1 -0
  285. package/dist/ssr/history.d.ts +97 -0
  286. package/dist/ssr/history.d.ts.map +1 -0
  287. package/dist/ssr/hiz.d.ts +37 -0
  288. package/dist/ssr/hiz.d.ts.map +1 -0
  289. package/dist/ssr/inspection.d.ts +42 -0
  290. package/dist/ssr/inspection.d.ts.map +1 -0
  291. package/dist/ssr/resources.d.ts +58 -0
  292. package/dist/ssr/resources.d.ts.map +1 -0
  293. package/dist/ssr/temporal.d.ts +38 -0
  294. package/dist/ssr/temporal.d.ts.map +1 -0
  295. package/dist/systems/skin-palette-allocator.d.ts +32 -10
  296. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  297. package/dist/systems/skin-palette-types.d.ts +15 -0
  298. package/dist/systems/skin-palette-types.d.ts.map +1 -1
  299. package/dist/systems/transparent-dispatch.d.ts +9 -0
  300. package/dist/systems/transparent-dispatch.d.ts.map +1 -0
  301. package/dist/targets/material-source.d.ts +7 -0
  302. package/dist/targets/material-source.d.ts.map +1 -1
  303. package/dist/temporal/frame-coordinator.d.ts +7 -0
  304. package/dist/temporal/frame-coordinator.d.ts.map +1 -1
  305. package/dist/temporal/gpu.d.ts +8 -0
  306. package/dist/temporal/gpu.d.ts.map +1 -1
  307. package/dist/temporal/history.d.ts.map +1 -1
  308. package/dist/temporal/index.mjs +6 -6
  309. package/dist/temporal/inspection.d.ts.map +1 -1
  310. package/dist/temporal/standard-scene-data.d.ts +2 -1
  311. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  312. package/dist/temporal/temporal-view.d.ts +2 -0
  313. package/dist/temporal/temporal-view.d.ts.map +1 -1
  314. package/dist/typed-render-graph-primitives.d.ts +35 -1
  315. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  316. package/dist/typed-shadow-passes.d.ts +3 -1
  317. package/dist/typed-shadow-passes.d.ts.map +1 -1
  318. package/dist/volume/temporal.d.ts +6 -0
  319. package/dist/volume/temporal.d.ts.map +1 -1
  320. package/package.json +21 -20
  321. package/src/__tests__/auto-exposure-gpu-evidence.ts +291 -0
  322. package/src/__tests__/auto-exposure-inspection.unit.test.ts +80 -0
  323. package/src/__tests__/auto-exposure-transaction.integration.test.ts +99 -0
  324. package/src/__tests__/auto-exposure.browser.test.ts +33 -0
  325. package/src/__tests__/auto-exposure.dawn.test.ts +33 -0
  326. package/src/__tests__/detached-inspection.integration.test.ts +5 -0
  327. package/src/__tests__/device-scope-lifecycle.unit.test.ts +18 -0
  328. package/src/__tests__/device-scope-stale-matrix.unit.test.ts +18 -0
  329. package/src/__tests__/docs-gate-green.unit.test.ts +3 -3
  330. package/src/__tests__/dynamic-geometry-host.unit.test.ts +1123 -0
  331. package/src/__tests__/dynamic-geometry.unit.test.ts +233 -0
  332. package/src/__tests__/factory-contract.integration.test.ts +73 -22
  333. package/src/__tests__/fallback-row-stride-surface.unit.test.ts +19 -0
  334. package/src/__tests__/feature-depth-input.dawn.test.ts +121 -0
  335. package/src/__tests__/feature-noise.unit.test.ts +38 -0
  336. package/src/__tests__/fixtures/taa-resolve-pinned-baseline.wgsl +301 -0
  337. package/src/__tests__/frame-camera-selection.unit.test.ts +131 -0
  338. package/src/__tests__/frame-plan-contract.unit.test.ts +24 -0
  339. package/src/__tests__/frame-targets.unit.test.ts +24 -0
  340. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +3 -0
  341. package/src/__tests__/gpu-driven-baseline.characterization.test.ts +79 -0
  342. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +287 -6
  343. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +122 -142
  344. package/src/__tests__/gpu-driven-indirect-raster.browser.test.ts +10 -1
  345. package/src/__tests__/gpu-driven-lod-cache.unit.test.ts +264 -0
  346. package/src/__tests__/gpu-driven-mesh-world-identity.unit.test.ts +349 -0
  347. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +1417 -0
  348. package/src/__tests__/gpu-driven-pbr.integration.test.ts +21 -0
  349. package/src/__tests__/gpu-driven-production-fixture.ts +96 -0
  350. package/src/__tests__/gpu-driven-production.integration.test.ts +1075 -93
  351. package/src/__tests__/gpu-driven-scaling.unit.test.ts +1 -3
  352. package/src/__tests__/gpu-driven-shadow-views.browser.test.ts +63 -0
  353. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +294 -0
  354. package/src/__tests__/gpu-driven-shadow-views.integration.test.ts +97 -0
  355. package/src/__tests__/gpu-driven-shadow-views.unit.test.ts +168 -0
  356. package/src/__tests__/gpu-driven-skin-contract.test-d.ts +11 -0
  357. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +72 -20
  358. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +30 -9
  359. package/src/__tests__/gpu-driven-view.unit.test.ts +159 -52
  360. package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -1
  361. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +42 -0
  362. package/src/__tests__/gpu-scene-render-graph-gpu.ts +19 -5
  363. package/src/__tests__/gpu-scene.dawn.test.ts +40 -13
  364. package/src/__tests__/gpu-scene.unit.test.ts +559 -33
  365. package/src/__tests__/instances-culling.integration.test.ts +36 -10
  366. package/src/__tests__/instances-derived-bounds.unit.test.ts +54 -0
  367. package/src/__tests__/instances-store.unit.test.ts +242 -39
  368. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +6 -0
  369. package/src/__tests__/lighting-scene-roundtrip.integration.test.ts +13 -16
  370. package/src/__tests__/lut-lkg-transaction.integration.test.ts +122 -0
  371. package/src/__tests__/material-contract-inventory.unit.test.ts +5 -6
  372. package/src/__tests__/material-dispatch-shader-id.unit.test.ts +51 -0
  373. package/src/__tests__/material-lane-selection.unit.test.ts +60 -0
  374. package/src/__tests__/material-numeric-upload.unit.test.ts +53 -0
  375. package/src/__tests__/material-texture-handles.unit.test.ts +18 -0
  376. package/src/__tests__/material-texture-source.unit.test.ts +87 -0
  377. package/src/__tests__/materials-authoring-validation.unit.test.ts +41 -0
  378. package/src/__tests__/materials-standard-contract.unit.test.ts +52 -2
  379. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +4 -0
  380. package/src/__tests__/mesh-submission-lifetime.unit.test.ts +53 -0
  381. package/src/__tests__/normal-fallback.dawn.test.ts +122 -0
  382. package/src/__tests__/particle-material-input-layout.unit.test.ts +104 -0
  383. package/src/__tests__/physical-clearcoat.integration.test.ts +37 -3
  384. package/src/__tests__/pipeline-texture-specialization.unit.test.ts +138 -0
  385. package/src/__tests__/point-shadow-inspection.unit.test.ts +2 -0
  386. package/src/__tests__/prepared-gpu-driven-pbr-contract.test-d.ts +31 -0
  387. package/src/__tests__/prepared-gpu-driven-pbr-contract.unit.test.ts +39 -0
  388. package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +35 -4
  389. package/src/__tests__/prepared-graphics-capability.unit.test.ts +21 -0
  390. package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +6 -2
  391. package/src/__tests__/profiler-phase-catalog.test.ts +5 -0
  392. package/src/__tests__/public-surface.test-d.ts +3 -0
  393. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +30 -12
  394. package/src/__tests__/reflection-fallback-async-publication.unit.test.ts +104 -0
  395. package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +2 -1
  396. package/src/__tests__/render-error-code-owner.test-d.ts +4 -0
  397. package/src/__tests__/render-error-detail-ssot.test-d.ts +22 -0
  398. package/src/__tests__/render-error-exhaustive.test-d.ts +15 -0
  399. package/src/__tests__/render-feature-gpu-work.integration.test.ts +285 -2
  400. package/src/__tests__/render-feature-plan.unit.test.ts +245 -0
  401. package/src/__tests__/render-feature-shadow-order.unit.test.ts +228 -0
  402. package/src/__tests__/render-feature-zero-work.unit.test.ts +35 -1
  403. package/src/__tests__/render-graph-fallback.integration.test.ts +2 -2
  404. package/src/__tests__/render-owner-cohesion.unit.test.ts +55 -0
  405. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +426 -0
  406. package/src/__tests__/render-scene-projection.unit.test.ts +914 -23
  407. package/src/__tests__/render-scene-resource-updates.integration.test.ts +214 -0
  408. package/src/__tests__/render-scene-skin-lifecycle.integration.test.ts +173 -0
  409. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +133 -0
  410. package/src/__tests__/render-target-material-source.test-d.ts +27 -3
  411. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +61 -1
  412. package/src/__tests__/renderer-frame-transaction.integration.test.ts +923 -5
  413. package/src/__tests__/shader-manifest-fixture.ts +39 -0
  414. package/src/__tests__/skin-motion-regression.unit.test.ts +0 -33
  415. package/src/__tests__/skin-palette-persistent.integration.test.ts +28 -0
  416. package/src/__tests__/skin-palette-persistent.unit.test.ts +247 -0
  417. package/src/__tests__/skinned-shadow-caster.test.ts +118 -14
  418. package/src/__tests__/specular-environment-scale.dawn.test.ts +156 -0
  419. package/src/__tests__/ssr-admission-matrix.integration.test.ts +7 -1
  420. package/src/__tests__/ssr-confidence-compose.unit.test.ts +84 -0
  421. package/src/__tests__/ssr-coordinate-oracle.unit.test.ts +28 -0
  422. package/src/__tests__/ssr-format-probe-gating.integration.test.ts +82 -0
  423. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +91 -0
  424. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +112 -0
  425. package/src/__tests__/ssr-gpu-dispatch.ts +946 -0
  426. package/src/__tests__/ssr-graph-topology.unit.test.ts +104 -0
  427. package/src/__tests__/ssr-history-filter.dawn.test.ts +198 -0
  428. package/src/__tests__/ssr-hit-color.dawn.test.ts +273 -0
  429. package/src/__tests__/ssr-hiz-odd-reduction.dawn.test.ts +569 -0
  430. package/src/__tests__/ssr-hiz-rescue.dawn.test.ts +279 -0
  431. package/src/__tests__/ssr-hiz.browser.test.ts +150 -0
  432. package/src/__tests__/ssr-hiz.dawn.test.ts +150 -0
  433. package/src/__tests__/ssr-hiz.unit.test.ts +56 -0
  434. package/src/__tests__/ssr-inspection.unit.test.ts +105 -0
  435. package/src/__tests__/ssr-memory-budget.unit.test.ts +45 -0
  436. package/src/__tests__/ssr-performance-sequence-aggregation.unit.test.ts +15 -0
  437. package/src/__tests__/ssr-public-surface.test-d.ts +37 -0
  438. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +387 -0
  439. package/src/__tests__/ssr-reflection-mip-reducer.dawn.test.ts +309 -0
  440. package/src/__tests__/ssr-reprojection-probe.ts +90 -0
  441. package/src/__tests__/ssr-roughness-mip.dawn.test.ts +163 -0
  442. package/src/__tests__/ssr-shader-prewarm.unit.test.ts +59 -0
  443. package/src/__tests__/ssr-spatial.integration.test.ts +141 -0
  444. package/src/__tests__/ssr-stable-lattice.dawn.test.ts +475 -0
  445. package/src/__tests__/ssr-temporal-history.unit.test.ts +202 -0
  446. package/src/__tests__/ssr-texel-crossing.dawn.test.ts +448 -0
  447. package/src/__tests__/ssr-zero-work.integration.test.ts +87 -0
  448. package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +44 -12
  449. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +29 -0
  450. package/src/__tests__/standard-output-chain-contract.unit.test.ts +99 -0
  451. package/src/__tests__/standard-output-chain.integration.test.ts +73 -0
  452. package/src/__tests__/standard-output-gpu-evidence.ts +205 -0
  453. package/src/__tests__/standard-output.browser.test.ts +15 -0
  454. package/src/__tests__/standard-output.dawn.test.ts +15 -0
  455. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +38 -0
  456. package/src/__tests__/standard-pipeline.integration.test.ts +320 -3
  457. package/src/__tests__/standard-profile-oracle.unit.test.ts +22 -0
  458. package/src/__tests__/standard-surface-lighting.unit.test.ts +41 -0
  459. package/src/__tests__/standard-texture-specialization.dawn.test.ts +141 -0
  460. package/src/__tests__/surface-adjacent-regressions.integration.test.ts +6 -3
  461. package/src/__tests__/taa-coverage-edge.dawn.test.ts +193 -0
  462. package/src/__tests__/taa-history-clipping.dawn.test.ts +328 -0
  463. package/src/__tests__/taa-neighborhood-equivalence.dawn.test.ts +778 -0
  464. package/src/__tests__/taa-stability-feedback.browser.test.ts +23 -0
  465. package/src/__tests__/taa-stability-feedback.dawn.test.ts +68 -0
  466. package/src/__tests__/taa-stability-feedback.ts +341 -0
  467. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +49 -7
  468. package/src/__tests__/temporal-reset-matrix.unit.test.ts +9 -0
  469. package/src/__tests__/temporal-transaction.integration.test.ts +28 -0
  470. package/src/__tests__/texture-usage-surface.unit.test.ts +4 -2
  471. package/src/__tests__/typed-pipeline-topology.unit.test.ts +109 -4
  472. package/src/__tests__/typed-scene-pass-material-cache.integration.test.ts +126 -0
  473. package/src/__tests__/vertex-layouts-ssot.unit.test.ts +47 -0
  474. package/src/__tests__/visibility-extract.perf.test.ts +20 -8
  475. package/src/__tests__/visibility-instances.integration.test.ts +19 -7
  476. package/src/__tests__/visibility-producer-matrix.integration.test.ts +20 -9
  477. package/src/assembly/atmosphere-shader-prewarm.ts +38 -0
  478. package/src/assembly/dynamic-geometry-host.ts +887 -0
  479. package/src/assembly/dynamic-geometry-runtime.ts +71 -0
  480. package/src/assembly/factory.ts +4 -0
  481. package/src/assembly/gpu-driven-owner.ts +29 -0
  482. package/src/assembly/host-contract.ts +36 -0
  483. package/src/assembly/material/assembly.ts +38 -0
  484. package/src/assembly/material-shader-policy.ts +71 -28
  485. package/src/assembly/recovery/failure-location.ts +62 -0
  486. package/src/assembly/recovery/renderer-recover.ts +19 -17
  487. package/src/assembly/renderer-facade.ts +29 -0
  488. package/src/assembly/renderer-feature-inspection.ts +13 -0
  489. package/src/assembly/renderer-frame-transaction.ts +63 -0
  490. package/src/assembly/renderer-helpers.ts +26 -0
  491. package/src/assembly/renderer-inspection.ts +6 -0
  492. package/src/assembly/shader-prewarm-policy.ts +32 -0
  493. package/src/assembly/skin-palette-owner.ts +21 -0
  494. package/src/assembly/ssr-shader-prewarm.ts +41 -0
  495. package/src/assembly/webgpu-device-loss.ts +75 -0
  496. package/src/assembly/webgpu-pbr-ready.ts +232 -0
  497. package/src/assembly/webgpu-ready-mipmap.ts +26 -0
  498. package/src/assembly/webgpu-ready.ts +142 -121
  499. package/src/assembly/webgpu-renderer-bootstrap.ts +85 -0
  500. package/src/assembly/webgpu-renderer-contract.ts +69 -0
  501. package/src/assembly/webgpu-renderer-guards.ts +32 -0
  502. package/src/assembly/webgpu-renderer-observation.ts +43 -0
  503. package/src/assembly/webgpu-renderer-recovery-failure.ts +62 -0
  504. package/src/assembly/webgpu-renderer.ts +675 -614
  505. package/src/assembly/webgpu-vertex-layouts.ts +233 -87
  506. package/src/components/__tests__/camera-exposure.contract.unit.test.ts +153 -0
  507. package/src/components/camera.ts +287 -7
  508. package/src/components/index.ts +1 -0
  509. package/src/components/instances.ts +45 -18
  510. package/src/components/scene-instance.ts +2 -1
  511. package/src/components/screen-space-reflection.ts +21 -0
  512. package/src/components/sprite-animation.ts +3 -3
  513. package/src/components/sprite-instances.ts +1 -1
  514. package/src/device/gpu-residency.ts +96 -93
  515. package/src/device/mesh-residency-lifetime.ts +73 -0
  516. package/src/dynamic-geometry.ts +736 -0
  517. package/src/environment/background.ts +263 -0
  518. package/src/errors/gpu-driven.ts +39 -5
  519. package/src/errors/render.ts +27 -3
  520. package/src/extract/camera.ts +26 -1
  521. package/src/extract/gpu-driven.ts +185 -10
  522. package/src/features/host.ts +237 -19
  523. package/src/features/noise-texture.ts +91 -0
  524. package/src/features/plan.ts +553 -24
  525. package/src/features/prepared-gpu-work.ts +631 -49
  526. package/src/features/prepared-graphics-store.ts +31 -0
  527. package/src/features/prepared-graphics.ts +5 -0
  528. package/src/features/render-graph-compute.ts +41 -8
  529. package/src/features/render-graph-contribution.ts +141 -3
  530. package/src/features/render-graph-raster.ts +143 -30
  531. package/src/features/types.ts +11 -0
  532. package/src/fullscreen-post-process-pass.ts +3 -0
  533. package/src/gpu-driven/batch-topology.ts +424 -102
  534. package/src/gpu-driven/pbr-program.ts +31 -0
  535. package/src/gpu-driven/prepared-draw.ts +29 -4
  536. package/src/gpu-driven/production-raster.ts +2267 -694
  537. package/src/gpu-driven/shadow-views.ts +539 -0
  538. package/src/gpu-driven/view-gpu.ts +188 -41
  539. package/src/gpu-scene-schema.ts +52 -11
  540. package/src/gpu-scene.ts +186 -99
  541. package/src/gpu-texture-usage.ts +1 -0
  542. package/src/hdrp-buffers.ts +72 -36
  543. package/src/ibl/frame-resources.ts +38 -0
  544. package/src/ibl/skylight-bind-group.ts +5 -4
  545. package/src/index.ts +125 -1
  546. package/src/inspection-types.ts +191 -0
  547. package/src/instances-derived-bounds.ts +258 -34
  548. package/src/instances.ts +459 -150
  549. package/src/internal.ts +22 -0
  550. package/src/lifecycle.ts +2 -0
  551. package/src/material-row.ts +145 -0
  552. package/src/materials.ts +44 -8
  553. package/src/pbr-pipeline.ts +159 -17
  554. package/src/pipeline/standard-forward-lane.ts +52 -24
  555. package/src/pipeline/standard-output/__tests__/lut-admission.unit.test.ts +103 -0
  556. package/src/pipeline/standard-output/auto-exposure/__tests__/capability.unit.test.ts +40 -0
  557. package/src/pipeline/standard-output/auto-exposure/__tests__/gpu.contract.unit.test.ts +125 -0
  558. package/src/pipeline/standard-output/auto-exposure/__tests__/graph.contract.unit.test.ts +94 -0
  559. package/src/pipeline/standard-output/auto-exposure/__tests__/oracle.test.ts +108 -0
  560. package/src/pipeline/standard-output/auto-exposure/__tests__/preset.test.ts +26 -0
  561. package/src/pipeline/standard-output/auto-exposure/capability.ts +38 -0
  562. package/src/pipeline/standard-output/auto-exposure/gpu.ts +567 -0
  563. package/src/pipeline/standard-output/auto-exposure/graph.ts +221 -0
  564. package/src/pipeline/standard-output/auto-exposure/inspection.ts +231 -0
  565. package/src/pipeline/standard-output/auto-exposure/oracle.ts +291 -0
  566. package/src/pipeline/standard-output/auto-exposure/preset.ts +28 -0
  567. package/src/pipeline/standard-output/auto-exposure/state.ts +156 -0
  568. package/src/pipeline/standard-output/color-transform.ts +124 -0
  569. package/src/pipeline/standard-output/graph.ts +139 -0
  570. package/src/pipeline/standard-output/lut-admission.ts +121 -0
  571. package/src/pipeline/standard-output/lut-gpu.ts +399 -0
  572. package/src/pipeline/standard-output/lut-state.ts +176 -0
  573. package/src/pipeline/standard-output/resources.ts +121 -0
  574. package/src/pipeline/standard-output/types.ts +58 -0
  575. package/src/pipeline/standard-pipeline.ts +192 -59
  576. package/src/pipeline/standard-post.ts +186 -27
  577. package/src/pipeline-builder.ts +16 -6
  578. package/src/pipeline-spec-types.ts +4 -0
  579. package/src/pipeline-spec.ts +37 -29
  580. package/src/points-lines/standard-owner.ts +6 -14
  581. package/src/prepare/prepared-graphics-resolver.ts +9 -2
  582. package/src/record/__tests__/material-slot-plan.unit.test.ts +48 -0
  583. package/src/record/__tests__/mesh-ssbo.unit.test.ts +40 -1
  584. package/src/record/__tests__/recovery-pipeline.unit.test.ts +2 -29
  585. package/src/record/__tests__/sprite-material-abi.unit.test.ts +36 -5
  586. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +45 -0
  587. package/src/record/__tests__/view-ubo-layout.unit.test.ts +5 -0
  588. package/src/record/dynamic-geometry-consumption.ts +59 -0
  589. package/src/record/frame-lighting.ts +12 -11
  590. package/src/record/frame-snapshot.ts +133 -23
  591. package/src/record/frame-targets.ts +9 -0
  592. package/src/record/frame.ts +727 -133
  593. package/src/record/main-pass-geometry.ts +162 -98
  594. package/src/record/main-pass-material.ts +115 -26
  595. package/src/record/main-pass-sprite-draws.ts +18 -107
  596. package/src/record/main-pass.ts +78 -8
  597. package/src/record/material-uniforms.ts +1 -1
  598. package/src/record/mesh-ssbo.ts +59 -15
  599. package/src/record/prepared-material-bindings.ts +234 -0
  600. package/src/record/recovery-pipeline.ts +59 -136
  601. package/src/record/render-context.ts +92 -22
  602. package/src/record/shadow-pass.ts +1231 -209
  603. package/src/record/skybox-post-pass.ts +14 -3
  604. package/src/record/typed-frame-graph.ts +1006 -53
  605. package/src/record/view-ubo.ts +11 -0
  606. package/src/recovery/render-system-candidate.ts +90 -66
  607. package/src/recovery/render-system-roots.ts +113 -0
  608. package/src/recovery/types.ts +77 -0
  609. package/src/reflection/record-owner.ts +26 -54
  610. package/src/render-contract.ts +219 -25
  611. package/src/render-graph-primitives.ts +6 -2
  612. package/src/render-pipeline.ts +70 -1
  613. package/src/render-system-extract-tail.ts +409 -160
  614. package/src/render-system-extract.ts +376 -102
  615. package/src/render-system-projections.ts +241 -0
  616. package/src/render-system.ts +692 -791
  617. package/src/scene/render-scene-types.ts +13 -4
  618. package/src/scene/render-scene.ts +569 -355
  619. package/src/scene/shadow-visibility.ts +21 -0
  620. package/src/ssr/admission.ts +380 -14
  621. package/src/ssr/compose.ts +144 -0
  622. package/src/ssr/errors.ts +48 -0
  623. package/src/ssr/graph.ts +777 -0
  624. package/src/ssr/history.ts +436 -0
  625. package/src/ssr/hiz.ts +124 -0
  626. package/src/ssr/inspection.ts +124 -0
  627. package/src/ssr/resources.ts +202 -0
  628. package/src/ssr/temporal.ts +164 -0
  629. package/src/systems/skin-palette-allocator.ts +495 -148
  630. package/src/systems/skin-palette-types.ts +17 -0
  631. package/src/systems/transparent-dispatch.ts +90 -0
  632. package/src/targets/material-source.ts +34 -0
  633. package/src/temporal/coverage.ts +1 -1
  634. package/src/temporal/frame-coordinator.ts +23 -2
  635. package/src/temporal/gpu.ts +74 -12
  636. package/src/temporal/history.ts +3 -1
  637. package/src/temporal/inspection.ts +2 -1
  638. package/src/temporal/standard-scene-data.ts +3 -1
  639. package/src/temporal/temporal-view.ts +3 -0
  640. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +204 -139
  641. package/src/typed-render-graph-primitives.ts +266 -74
  642. package/src/typed-shadow-passes.ts +122 -12
  643. package/src/volume/temporal.ts +10 -0
  644. package/dist/chunk-ADHHVYLW.mjs.map +0 -1
  645. package/dist/chunk-FJ6P52EE.mjs.map +0 -1
  646. package/dist/chunk-GE3SDD72.mjs.map +0 -1
  647. package/dist/chunk-GF523LHF.mjs.map +0 -1
  648. package/dist/chunk-HKXTW355.mjs.map +0 -1
  649. package/dist/chunk-JDWARUOI.mjs.map +0 -1
  650. package/dist/chunk-KM2NOX2I.mjs.map +0 -1
  651. package/dist/chunk-TMIASV2N.mjs.map +0 -1
  652. package/dist/chunk-XDP6XE5V.mjs.map +0 -1
  653. package/dist/chunk-ZZ4YQ474.mjs.map +0 -1
  654. package/src/__tests__/instances-world-ownership.integration.test.ts +0 -62
  655. package/src/scene/__tests__/changed-block-summary.candidate.test.ts +0 -36
@@ -0,0 +1,139 @@
1
+ import { err, ok, type Result } from '@forgeax/engine-types';
2
+ import { DISPLAY_ENCODED_DOMAIN, LINEAR_HDR_DOMAIN, LINEAR_LDR_DOMAIN } from './color-transform';
3
+ import type {
4
+ StandardOutputLogicalStage,
5
+ StandardOutputPhysicalStage,
6
+ StandardOutputPlan,
7
+ StandardOutputRequest,
8
+ } from './types';
9
+
10
+ export class StandardOutputPlanError extends Error {
11
+ readonly code = 'standard-output-plan-invalid' as const;
12
+ readonly expected: string;
13
+ readonly hint: string;
14
+ readonly detail: { readonly field: string; readonly actual: string };
15
+
16
+ constructor(field: string, actual: string, expected: string) {
17
+ super(`standard-output-plan-invalid: ${field} ${actual}; expected ${expected}`);
18
+ this.name = 'StandardOutputPlanError';
19
+ this.expected = expected;
20
+ this.hint = `repair the ${field} projection before recording the Standard graph`;
21
+ this.detail = { field, actual };
22
+ }
23
+ }
24
+
25
+ function requestedStages(input: StandardOutputRequest): StandardOutputLogicalStage[] {
26
+ const stages: StandardOutputLogicalStage[] = [];
27
+ if (input.temporal) stages.push('temporal');
28
+ if (input.meter) stages.push('meter');
29
+ if (input.bloom) stages.push('bloom');
30
+ if (input.exposure || input.whiteBalance) stages.push('exposure-white-balance');
31
+ stages.push('tone');
32
+ if (input.lut) stages.push('lut');
33
+ if (input.fxaa) stages.push('fxaa');
34
+ stages.push('output-encoding');
35
+ return stages;
36
+ }
37
+
38
+ function physicalStages(
39
+ logicalStages: readonly StandardOutputLogicalStage[],
40
+ ): StandardOutputPhysicalStage[] {
41
+ return logicalStages.map((name) => {
42
+ switch (name) {
43
+ case 'temporal':
44
+ case 'meter':
45
+ case 'bloom':
46
+ case 'exposure-white-balance':
47
+ return { name, input: LINEAR_HDR_DOMAIN, output: LINEAR_HDR_DOMAIN };
48
+ case 'tone':
49
+ return { name, input: LINEAR_HDR_DOMAIN, output: LINEAR_LDR_DOMAIN };
50
+ case 'lut':
51
+ case 'fxaa':
52
+ return { name, input: LINEAR_LDR_DOMAIN, output: LINEAR_LDR_DOMAIN };
53
+ case 'output-encoding':
54
+ return { name, input: LINEAR_LDR_DOMAIN, output: DISPLAY_ENCODED_DOMAIN };
55
+ default:
56
+ throw new Error(`Unknown Standard output stage: ${name}`);
57
+ }
58
+ });
59
+ }
60
+
61
+ export function createStandardOutputPlan(input: StandardOutputRequest): StandardOutputPlan {
62
+ const logicalStages = requestedStages(input);
63
+ const incrementalResources = input.lut ? ['standard-color-lut'] : [];
64
+ const incrementalBindings = input.lut ? 2 : 0;
65
+ return {
66
+ lane: input.lane,
67
+ features: {
68
+ temporal: input.temporal,
69
+ meter: input.meter,
70
+ bloom: input.bloom,
71
+ exposure: input.exposure,
72
+ whiteBalance: input.whiteBalance,
73
+ lut: input.lut,
74
+ fxaa: input.fxaa,
75
+ },
76
+ outputEncoding: input.outputEncoding,
77
+ logicalStages,
78
+ physicalStages: physicalStages(logicalStages),
79
+ finalWriterCount: 1,
80
+ outputEncodingCount: 1,
81
+ incrementalResources,
82
+ incrementalBindings,
83
+ incrementalTimestamps: 0,
84
+ };
85
+ }
86
+
87
+ function invalid(
88
+ field: string,
89
+ actual: string,
90
+ expected: string,
91
+ ): Result<never, StandardOutputPlanError> {
92
+ return err(new StandardOutputPlanError(field, actual, expected));
93
+ }
94
+
95
+ export function validateStandardOutputPlan(
96
+ plan: StandardOutputPlan,
97
+ ): Result<StandardOutputPlan, StandardOutputPlanError> {
98
+ const expected = requestedStages({
99
+ lane: plan.lane,
100
+ ...plan.features,
101
+ outputEncoding: plan.outputEncoding,
102
+ });
103
+ if (
104
+ plan.logicalStages.length !== expected.length ||
105
+ plan.logicalStages.some((stage, index) => stage !== expected[index])
106
+ ) {
107
+ return invalid('logicalStages', plan.logicalStages.join(','), expected.join(','));
108
+ }
109
+ if (plan.finalWriterCount !== 1)
110
+ return invalid('finalWriterCount', String(plan.finalWriterCount), '1');
111
+ if (plan.outputEncodingCount !== 1)
112
+ return invalid('outputEncodingCount', String(plan.outputEncodingCount), '1');
113
+ if (plan.physicalStages.length !== plan.logicalStages.length) {
114
+ return invalid(
115
+ 'physicalStages',
116
+ String(plan.physicalStages.length),
117
+ String(plan.logicalStages.length),
118
+ );
119
+ }
120
+ const expectedPhysical = physicalStages(expected);
121
+ for (let index = 0; index < expectedPhysical.length; index += 1) {
122
+ const actual = plan.physicalStages[index];
123
+ const wanted = expectedPhysical[index];
124
+ if (
125
+ actual?.name !== wanted?.name ||
126
+ actual?.input !== wanted?.input ||
127
+ actual?.output !== wanted?.output
128
+ ) {
129
+ return invalid(`physicalStages[${index}]`, JSON.stringify(actual), JSON.stringify(wanted));
130
+ }
131
+ }
132
+ if (
133
+ plan.outputEncoding === 'explicit-oetf' &&
134
+ plan.physicalStages.at(-1)?.output !== DISPLAY_ENCODED_DOMAIN
135
+ ) {
136
+ return invalid('outputEncoding', plan.outputEncoding, 'one final display-encoded writer');
137
+ }
138
+ return ok(plan);
139
+ }
@@ -0,0 +1,121 @@
1
+ import type { SamplerDescriptor } from '@forgeax/engine-rhi';
2
+ import type { TextureAsset } from '@forgeax/engine-types';
3
+ import { err, ok, type Result } from '@forgeax/engine-types';
4
+
5
+ export type StandardLutAdmissionErrorCode =
6
+ | 'standard-lut-shape-invalid'
7
+ | 'standard-lut-limit-exceeded'
8
+ | 'standard-lut-filter-unavailable'
9
+ | 'standard-lut-bind-failed';
10
+
11
+ export type StandardLutAdmissionError = {
12
+ readonly code: StandardLutAdmissionErrorCode;
13
+ readonly expected: string;
14
+ readonly hint: string;
15
+ readonly detail: Readonly<Record<string, number | string | boolean>>;
16
+ };
17
+
18
+ export interface StandardColorLutAdmissionInput {
19
+ readonly texture: TextureAsset;
20
+ readonly maxTextureDimension3D: number;
21
+ readonly rgba16floatFilterable: boolean;
22
+ readonly bind: () => boolean;
23
+ }
24
+
25
+ export interface StandardColorLutAdmission {
26
+ readonly viewDimension: '3d';
27
+ readonly extent: Readonly<{ width: number; height: number; depth: number }>;
28
+ readonly sampler: SamplerDescriptor;
29
+ }
30
+
31
+ export function createStandardLutSamplerDescriptor(): SamplerDescriptor {
32
+ return {
33
+ addressModeU: 'clamp-to-edge',
34
+ addressModeV: 'clamp-to-edge',
35
+ addressModeW: 'clamp-to-edge',
36
+ magFilter: 'linear',
37
+ minFilter: 'linear',
38
+ mipmapFilter: 'nearest',
39
+ };
40
+ }
41
+
42
+ export function lutTexelCenter(index: number, size: number): number {
43
+ return (index + 0.5) / size;
44
+ }
45
+
46
+ function failure(
47
+ code: StandardLutAdmissionErrorCode,
48
+ expected: string,
49
+ hint: string,
50
+ detail: Readonly<Record<string, number | string | boolean>>,
51
+ ): Result<never, StandardLutAdmissionError> {
52
+ return err({ code, expected, hint, detail });
53
+ }
54
+
55
+ export function admitStandardColorLut(
56
+ input: StandardColorLutAdmissionInput,
57
+ ): Result<StandardColorLutAdmission, StandardLutAdmissionError> {
58
+ const { texture } = input;
59
+ if (
60
+ texture.shape.viewDimension !== '3d' ||
61
+ texture.format !== 'rgba16float' ||
62
+ texture.colorSpace !== 'linear' ||
63
+ texture.mips.kind === 'generate' ||
64
+ (texture.mips.kind === 'packed' && texture.mips.levelCount !== 1)
65
+ ) {
66
+ return failure(
67
+ 'standard-lut-shape-invalid',
68
+ 'a linear rgba16float 3D texture with one resident mip level',
69
+ 're-import the LUT as an ordinary linear 3D TextureAsset without generated mips',
70
+ {
71
+ viewDimension: texture.shape.viewDimension,
72
+ format: texture.format,
73
+ colorSpace: texture.colorSpace,
74
+ mipPolicy: texture.mips.kind,
75
+ },
76
+ );
77
+ }
78
+
79
+ const extent = texture.shape.extent;
80
+ if (extent.width !== extent.height || extent.width !== extent.depth) {
81
+ return failure(
82
+ 'standard-lut-shape-invalid',
83
+ 'LUT width, height, and depth must be equal',
84
+ 'produce a cubic 3D LUT',
85
+ { width: extent.width, height: extent.height, depth: extent.depth },
86
+ );
87
+ }
88
+ if (
89
+ !Number.isInteger(input.maxTextureDimension3D) ||
90
+ input.maxTextureDimension3D <= 0 ||
91
+ extent.width > input.maxTextureDimension3D
92
+ ) {
93
+ return failure(
94
+ 'standard-lut-limit-exceeded',
95
+ 'the LUT extent must fit the live maxTextureDimension3D limit',
96
+ 'use a smaller LUT or select a device with a larger 3D texture limit',
97
+ { size: extent.width, maxTextureDimension3D: input.maxTextureDimension3D },
98
+ );
99
+ }
100
+ if (!input.rgba16floatFilterable) {
101
+ return failure(
102
+ 'standard-lut-filter-unavailable',
103
+ 'rgba16float 3D sampling must be filterable on the live device',
104
+ 'disable the LUT or use a device that exposes rgba16float filtering',
105
+ { format: texture.format, rgba16floatFilterable: false },
106
+ );
107
+ }
108
+ if (!input.bind()) {
109
+ return failure(
110
+ 'standard-lut-bind-failed',
111
+ 'the LUT view and sampler must bind on the live device',
112
+ 'disable the LUT and retain the last known good output',
113
+ { size: extent.width },
114
+ );
115
+ }
116
+ return ok({
117
+ viewDimension: '3d',
118
+ extent: { width: extent.width, height: extent.height, depth: extent.depth },
119
+ sampler: createStandardLutSamplerDescriptor(),
120
+ });
121
+ }
@@ -0,0 +1,399 @@
1
+ import type { AssetRegistry } from '@forgeax/engine-assets-runtime';
2
+ import { resolveAssetHandle } from '@forgeax/engine-assets-runtime';
3
+ import type { World } from '@forgeax/engine-ecs';
4
+ import type { RenderGraphBuilder, RenderGraphError } from '@forgeax/engine-render-graph';
5
+ import type {
6
+ BindGroup,
7
+ BindGroupLayout,
8
+ RenderPipeline,
9
+ RhiDevice,
10
+ Sampler,
11
+ Texture,
12
+ TextureView,
13
+ } from '@forgeax/engine-rhi';
14
+ import { err, type Handle, ok, type Result, type TextureAsset } from '@forgeax/engine-types';
15
+ import type { GpuResidencyCache, TextureGpuEntry } from '../../device/gpu-residency';
16
+ import type { RenderPipelineFrame, RenderPipelineTarget } from '../../render-pipeline';
17
+ import {
18
+ admitStandardColorLut,
19
+ createStandardLutSamplerDescriptor,
20
+ type StandardLutAdmissionError,
21
+ type StandardLutAdmissionErrorCode,
22
+ } from './lut-admission';
23
+
24
+ export interface StandardLutGpuResources {
25
+ readonly texture: Texture;
26
+ readonly view: TextureView;
27
+ readonly sampler: Sampler;
28
+ readonly sourceKey: string;
29
+ readonly size: number;
30
+ readonly strength: number;
31
+ readonly bindGroupLayout: BindGroupLayout;
32
+ readonly bindGroup: BindGroup;
33
+ }
34
+
35
+ export interface StandardLutGraphProjection {
36
+ readonly view: import('@forgeax/engine-render-graph').GraphTextureView;
37
+ readonly sampler: Sampler;
38
+ readonly strength: number;
39
+ readonly bindGroupLayout: BindGroupLayout;
40
+ readonly bindGroup: BindGroup;
41
+ }
42
+
43
+ export interface StandardLutGpuPreparationInput {
44
+ readonly world: World;
45
+ readonly handle: Handle<'TextureAsset', 'shared'>;
46
+ readonly strength: number;
47
+ readonly assets: AssetRegistry;
48
+ readonly gpuStore: GpuResidencyCache;
49
+ readonly device: RhiDevice;
50
+ }
51
+
52
+ interface CachedLutBinding {
53
+ readonly texture: Texture;
54
+ readonly view: TextureView;
55
+ readonly sampler: Sampler;
56
+ readonly bindGroupLayout: BindGroupLayout;
57
+ readonly bindGroup: BindGroup;
58
+ readonly size: number;
59
+ }
60
+
61
+ const lutBindingCache = new WeakMap<object, Map<string, CachedLutBinding>>();
62
+
63
+ /** Release only the projection-owned LUT objects; texture residency is cache-owned. */
64
+ export function retireStandardLutGpuResources(_resources: StandardLutGpuResources): void {
65
+ // RHI samplers and bind-group layouts are device-lifetime objects. The
66
+ // GpuResidencyCache remains the sole owner of the resident TextureAsset.
67
+ }
68
+
69
+ export type StandardLutGpuErrorCode =
70
+ | StandardLutAdmissionErrorCode
71
+ | 'standard-lut-strength-invalid'
72
+ | 'standard-lut-catalog-source-missing'
73
+ | 'standard-lut-residency-failed'
74
+ | 'standard-lut-not-resident'
75
+ | 'standard-lut-3d-view-unavailable'
76
+ | 'standard-lut-sampler-failed'
77
+ | 'standard-lut-bind-group-layout-failed'
78
+ | 'standard-lut-bind-failed';
79
+
80
+ export interface StandardLutGpuError {
81
+ readonly code: StandardLutGpuErrorCode;
82
+ readonly expected: string;
83
+ readonly hint: string;
84
+ readonly detail: Readonly<Record<string, number | string | boolean>>;
85
+ }
86
+
87
+ export type StandardLutPreparationError = StandardLutAdmissionError | StandardLutGpuError;
88
+
89
+ function failure(
90
+ code: StandardLutGpuErrorCode,
91
+ expected: string,
92
+ hint: string,
93
+ detail: Readonly<Record<string, number | string | boolean>> = {},
94
+ ): Result<never, StandardLutGpuError> {
95
+ return err({ code, expected, hint, detail });
96
+ }
97
+
98
+ function causeDetail(cause: unknown): Readonly<Record<string, number | string | boolean>> {
99
+ if (typeof cause !== 'object' || cause === null) return { cause: String(cause) };
100
+ const value = cause as {
101
+ readonly code?: unknown;
102
+ readonly expected?: unknown;
103
+ readonly hint?: unknown;
104
+ };
105
+ return {
106
+ ...(typeof value.code === 'string' ? { causeCode: value.code } : {}),
107
+ ...(typeof value.expected === 'string' ? { causeExpected: value.expected } : {}),
108
+ ...(typeof value.hint === 'string' ? { causeHint: value.hint } : {}),
109
+ };
110
+ }
111
+
112
+ /** Resolve, admit, make resident, and bind one ordinary TextureAsset LUT. */
113
+ export function prepareStandardLutGpu(
114
+ input: StandardLutGpuPreparationInput,
115
+ ): Result<StandardLutGpuResources, StandardLutPreparationError> {
116
+ if (!Number.isFinite(input.strength) || input.strength <= 0) {
117
+ return failure(
118
+ 'standard-lut-strength-invalid',
119
+ 'the LUT blend strength must be finite and positive',
120
+ 'set Camera.colorLutStrength to a value in (0, 1]',
121
+ { strength: String(input.strength) },
122
+ );
123
+ }
124
+ const asset = resolveAssetHandle<TextureAsset>(input.world, input.handle);
125
+ if (!asset.ok) {
126
+ return failure(
127
+ 'standard-lut-residency-failed',
128
+ 'the authored TextureAsset handle resolves in the active World',
129
+ 'register or rebuild the TextureAsset, then retry the same camera generation',
130
+ causeDetail(asset.error),
131
+ );
132
+ }
133
+ const guid = input.assets.guidOf(asset.value);
134
+ const catalogEntry = input.assets.listCatalog().find((entry) => entry.guid === guid);
135
+ const sourceKey = catalogEntry?.sourceKey;
136
+ if (sourceKey === undefined) {
137
+ return failure(
138
+ 'standard-lut-catalog-source-missing',
139
+ 'the authoritative asset catalog provides a stable sourceKey for the LUT GUID',
140
+ 'repair the producer-owned catalog entry and retry the same GUID/sourceKey',
141
+ { guid: String(guid) },
142
+ );
143
+ }
144
+ const resident = input.gpuStore.getTextureGpuView(input.handle, input.world);
145
+ let entry: TextureGpuEntry | undefined;
146
+ if (resident === undefined) {
147
+ const prepared = input.gpuStore.ensureResident(input.handle, asset.value, input.world);
148
+ if (!prepared.ok) {
149
+ return failure(
150
+ 'standard-lut-residency-failed',
151
+ 'the LUT TextureAsset becomes resident through the producer-owned GPU store',
152
+ 'inspect the structured residency failure and rebuild the source asset before retrying',
153
+ causeDetail(prepared.error),
154
+ );
155
+ }
156
+ if (!('texture' in prepared.value)) {
157
+ return failure(
158
+ 'standard-lut-residency-failed',
159
+ 'the LUT handle resolves to a resident TextureAsset, not a mesh resource',
160
+ 'repair the authored handle kind and retry the same source key',
161
+ { guid: String(guid) },
162
+ );
163
+ }
164
+ entry = prepared.value;
165
+ }
166
+ const view = resident ?? entry?.view;
167
+ const texture =
168
+ entry?.texture.handle ??
169
+ input.gpuStore._getTextureGpuTexture(input.handle, input.world)?.handle;
170
+ if (view === undefined || texture === undefined) {
171
+ return failure(
172
+ 'standard-lut-not-resident',
173
+ 'the LUT has a live GPU texture and view before graph admission',
174
+ 'retain the current LKG and retry producer-owned residency for the same GUID/sourceKey',
175
+ { guid: String(guid), sourceKey },
176
+ );
177
+ }
178
+ const cache =
179
+ lutBindingCache.get(input.device) ??
180
+ (() => {
181
+ const created = new Map<string, CachedLutBinding>();
182
+ lutBindingCache.set(input.device, created);
183
+ return created;
184
+ })();
185
+ const cached = cache.get(sourceKey);
186
+ if (cached !== undefined && cached.texture === texture) {
187
+ return ok({
188
+ texture,
189
+ view: cached.view,
190
+ sampler: cached.sampler,
191
+ sourceKey,
192
+ size: cached.size,
193
+ strength: input.strength,
194
+ bindGroupLayout: cached.bindGroupLayout,
195
+ bindGroup: cached.bindGroup,
196
+ });
197
+ }
198
+ // Recreate the resident view with an explicit 3D descriptor. This is a
199
+ // live capability check rather than a shape assertion: a device that
200
+ // rejects a 3D view cannot admit this LUT route.
201
+ const liveView = input.device.createTextureView(texture, { dimension: '3d' });
202
+ if (!liveView.ok) {
203
+ return failure(
204
+ 'standard-lut-3d-view-unavailable',
205
+ 'the resident texture creates a live 3D texture view',
206
+ 'disable the LUT and retain the last known good output on this device',
207
+ causeDetail(liveView.error),
208
+ );
209
+ }
210
+ const sampler = input.device.createSampler(createStandardLutSamplerDescriptor());
211
+ if (!sampler.ok) {
212
+ return failure(
213
+ 'standard-lut-sampler-failed',
214
+ 'the live device creates the filtering sampler required by the LUT',
215
+ 'disable the LUT and retain the last known good output',
216
+ causeDetail(sampler.error),
217
+ );
218
+ }
219
+ const bindGroupLayout = input.device.createBindGroupLayout({
220
+ entries: [
221
+ { binding: 0, visibility: 2, texture: { sampleType: 'float', viewDimension: '3d' } },
222
+ { binding: 1, visibility: 2, sampler: { type: 'filtering' } },
223
+ ],
224
+ });
225
+ if (!bindGroupLayout.ok) {
226
+ return failure(
227
+ 'standard-lut-bind-group-layout-failed',
228
+ 'the live device accepts a filtering float 3D LUT bind-group layout',
229
+ 'disable the LUT and retain the last known good output',
230
+ causeDetail(bindGroupLayout.error),
231
+ );
232
+ }
233
+ let liveBindGroup: ReturnType<RhiDevice['createBindGroup']>;
234
+ try {
235
+ liveBindGroup = input.device.createBindGroup({
236
+ layout: bindGroupLayout.value,
237
+ entries: [
238
+ { binding: 0, resource: { kind: 'textureView', value: liveView.value } },
239
+ { binding: 1, resource: { kind: 'sampler', value: sampler.value } },
240
+ ],
241
+ });
242
+ } catch (cause) {
243
+ return failure(
244
+ 'standard-lut-filter-unavailable',
245
+ 'the live device binds the rgba16float 3D view with a filtering sampler',
246
+ 'disable the LUT and retain the last known good output on this device',
247
+ { cause: String(cause) },
248
+ );
249
+ }
250
+ // The result of the real BGL/BG probe is the filterability fact passed to
251
+ // the pure shape admission. No device capability is inferred or forced.
252
+ const admission = admitStandardColorLut({
253
+ texture: asset.value,
254
+ maxTextureDimension3D: input.device.limits.maxTextureDimension3D,
255
+ rgba16floatFilterable: liveBindGroup.ok,
256
+ bind: () => liveBindGroup.ok,
257
+ });
258
+ if (!admission.ok) {
259
+ if (admission.error.code === 'standard-lut-filter-unavailable' && !liveBindGroup.ok) {
260
+ return err({
261
+ ...admission.error,
262
+ detail: Object.freeze({
263
+ ...admission.error.detail,
264
+ ...causeDetail(liveBindGroup.error),
265
+ }),
266
+ });
267
+ }
268
+ return admission;
269
+ }
270
+ if (!liveBindGroup.ok) {
271
+ return failure(
272
+ 'standard-lut-bind-failed',
273
+ 'the admitted LUT view and sampler bind successfully',
274
+ 'disable the LUT and retain the last known good output',
275
+ causeDetail(liveBindGroup.error),
276
+ );
277
+ }
278
+ cache.set(sourceKey, {
279
+ texture,
280
+ view: liveView.value,
281
+ sampler: sampler.value,
282
+ bindGroupLayout: bindGroupLayout.value,
283
+ bindGroup: liveBindGroup.value,
284
+ size: admission.value.extent.width,
285
+ });
286
+ return ok({
287
+ texture,
288
+ view: liveView.value,
289
+ sampler: sampler.value,
290
+ sourceKey,
291
+ size: admission.value.extent.width,
292
+ strength: input.strength,
293
+ bindGroupLayout: bindGroupLayout.value,
294
+ bindGroup: liveBindGroup.value,
295
+ });
296
+ }
297
+
298
+ const LUT_FULLSCREEN_WGSL = /* wgsl */ `
299
+ struct VertexOutput { @builtin(position) position: vec4<f32>, @location(0) uv: vec2<f32> };
300
+ @vertex fn lut_vs(@builtin(vertex_index) index: u32) -> VertexOutput {
301
+ var positions = array<vec2<f32>, 3>(vec2<f32>(-1.0, -3.0), vec2<f32>(3.0, 1.0), vec2<f32>(-1.0, 1.0));
302
+ let p = positions[index];
303
+ return VertexOutput(vec4<f32>(p, 0.0, 1.0), vec2<f32>(p.x * 0.5 + 0.5, 0.5 - p.y * 0.5));
304
+ }
305
+ @group(0) @binding(0) var source: texture_2d<f32>;
306
+ @group(0) @binding(1) var sourceSampler: sampler;
307
+ @group(1) @binding(0) var lut: texture_3d<f32>;
308
+ @group(1) @binding(1) var lutSampler: sampler;
309
+ @fragment fn lut_fs(input: VertexOutput) -> @location(0) vec4<f32> {
310
+ let color = textureSampleLevel(source, sourceSampler, input.uv, 0.0);
311
+ let mapped = textureSampleLevel(lut, lutSampler, clamp(color.rgb, vec3<f32>(0.0), vec3<f32>(1.0)), 0.0);
312
+ return vec4<f32>(mix(color.rgb, mapped.rgb, LUT_STRENGTH), color.a);
313
+ }`;
314
+
315
+ /** Record a fullscreen 3D LUT sample into the same Standard graph. */
316
+ export function addStandardColorLutPass(
317
+ graph: RenderGraphBuilder<RenderPipelineFrame>,
318
+ input: RenderPipelineTarget,
319
+ output: RenderPipelineTarget,
320
+ lut: StandardLutGraphProjection,
321
+ ): Result<void, RenderGraphError> {
322
+ let pipeline: RenderPipeline | undefined;
323
+ let layout: BindGroupLayout | undefined;
324
+ let sampler: Sampler | undefined;
325
+ const added = graph.addRasterPass('standard-color-lut', {
326
+ accesses: [
327
+ { resource: input.view, usage: 'sampled-read' },
328
+ { resource: lut.view, usage: 'sampled-read' },
329
+ { resource: output.view, usage: 'color-attachment' },
330
+ ],
331
+ colorAttachments: [
332
+ {
333
+ view: output.view,
334
+ loadOp: 'clear',
335
+ storeOp: 'store',
336
+ clearValue: { r: 0, g: 0, b: 0, a: 1 },
337
+ },
338
+ ],
339
+ encode: ({ pass, frame, resources }) => {
340
+ const factory =
341
+ frame.runtime.immediateShaderModuleFactory ?? frame.runtime.shaderModuleFactory;
342
+ if (factory === undefined) throw new Error('standard LUT shader factory unavailable');
343
+ const source = factory.createShaderModule({
344
+ code: LUT_FULLSCREEN_WGSL.replace('LUT_STRENGTH', String(lut.strength)),
345
+ label: 'standard-color-lut',
346
+ });
347
+ if (!source.ok) throw source.error;
348
+ if (layout === undefined) {
349
+ const created = frame.runtime.device.createBindGroupLayout({
350
+ label: 'standard-color-lut.bgl',
351
+ entries: [
352
+ { binding: 0, visibility: 2, texture: { sampleType: 'float', viewDimension: '2d' } },
353
+ { binding: 1, visibility: 2, sampler: { type: 'filtering' } },
354
+ ],
355
+ });
356
+ if (!created.ok) throw created.error;
357
+ layout = created.value;
358
+ }
359
+ sampler ??= frame.runtime.device
360
+ .createSampler({ minFilter: 'linear', magFilter: 'linear' })
361
+ .unwrap();
362
+ if (pipeline === undefined) {
363
+ const pipelineLayout = frame.runtime.device.createPipelineLayout({
364
+ label: 'standard-color-lut.layout',
365
+ bindGroupLayouts: [layout, lut.bindGroupLayout],
366
+ });
367
+ if (!pipelineLayout.ok) throw pipelineLayout.error;
368
+ const created = frame.runtime.device.createRenderPipeline({
369
+ label: 'standard-color-lut',
370
+ layout: pipelineLayout.value,
371
+ vertex: { module: source.value, entryPoint: 'lut_vs', buffers: [] },
372
+ fragment: {
373
+ module: source.value,
374
+ entryPoint: 'lut_fs',
375
+ targets: [{ format: output.format as GPUTextureFormat }],
376
+ },
377
+ primitive: { topology: 'triangle-list' },
378
+ });
379
+ if (!created.ok) throw created.error;
380
+ pipeline = created.value;
381
+ }
382
+ const inputView = resources.textureView(input.view);
383
+ if (!inputView.ok) throw inputView.error;
384
+ const bindings = frame.runtime.device.createBindGroup({
385
+ layout,
386
+ entries: [
387
+ { binding: 0, resource: { kind: 'textureView', value: inputView.value } },
388
+ { binding: 1, resource: { kind: 'sampler', value: sampler as Sampler } },
389
+ ],
390
+ });
391
+ if (!bindings.ok) throw bindings.error;
392
+ pass.setPipeline(pipeline as RenderPipeline);
393
+ pass.setBindGroup(0, bindings.value);
394
+ pass.setBindGroup(1, lut.bindGroup);
395
+ pass.draw(3, 1, 0, 0);
396
+ },
397
+ });
398
+ return added.ok ? ok(undefined) : added;
399
+ }