@forgeax/engine-render 0.1.21 → 0.1.23

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 (426) hide show
  1. package/README.md +150 -29
  2. package/dist/assembly/backend-contract.d.ts +13 -0
  3. package/dist/assembly/backend-contract.d.ts.map +1 -1
  4. package/dist/assembly/device-feature-admission.d.ts.map +1 -1
  5. package/dist/assembly/factory.d.ts +14 -6
  6. package/dist/assembly/factory.d.ts.map +1 -1
  7. package/dist/assembly/host-contract.d.ts +10 -0
  8. package/dist/assembly/host-contract.d.ts.map +1 -1
  9. package/dist/authoring.mjs +1 -1
  10. package/dist/{chunk-PCHBPYML.mjs → chunk-4L3P6DT5.mjs} +2 -2
  11. package/dist/chunk-4L3P6DT5.mjs.map +1 -0
  12. package/dist/{chunk-VFPLTKCU.mjs → chunk-4NPUASZR.mjs} +15 -4
  13. package/dist/chunk-4NPUASZR.mjs.map +1 -0
  14. package/dist/chunk-DIYW3M5D.mjs +5085 -0
  15. package/dist/chunk-DIYW3M5D.mjs.map +1 -0
  16. package/dist/chunk-FBC4R44J.mjs +1003 -0
  17. package/dist/chunk-FBC4R44J.mjs.map +1 -0
  18. package/dist/{chunk-FS2KNUQH.mjs → chunk-FF7K3FSO.mjs} +253 -489
  19. package/dist/chunk-FF7K3FSO.mjs.map +1 -0
  20. package/dist/chunk-HZUPSYW7.mjs +1104 -0
  21. package/dist/chunk-HZUPSYW7.mjs.map +1 -0
  22. package/dist/{chunk-6OPXDQ2E.mjs → chunk-QODA5UKU.mjs} +33 -294
  23. package/dist/chunk-QODA5UKU.mjs.map +1 -0
  24. package/dist/chunk-YALPS44A.mjs +296 -0
  25. package/dist/chunk-YALPS44A.mjs.map +1 -0
  26. package/dist/{chunk-5YADUCA7.mjs → chunk-ZUWKAZ2I.mjs} +585 -991
  27. package/dist/chunk-ZUWKAZ2I.mjs.map +1 -0
  28. package/dist/cluster-binner.d.ts +5 -0
  29. package/dist/cluster-binner.d.ts.map +1 -1
  30. package/dist/components/index.d.ts +3 -0
  31. package/dist/components/index.d.ts.map +1 -1
  32. package/dist/components/light-helpers.d.ts +4 -0
  33. package/dist/components/light-helpers.d.ts.map +1 -1
  34. package/dist/components/light-probe.d.ts +9 -0
  35. package/dist/components/light-probe.d.ts.map +1 -0
  36. package/dist/components/rect-area-light.d.ts +12 -0
  37. package/dist/components/rect-area-light.d.ts.map +1 -0
  38. package/dist/components/scene-instance.d.ts +4 -0
  39. package/dist/components/scene-instance.d.ts.map +1 -1
  40. package/dist/components/spot-light.d.ts +3 -0
  41. package/dist/components/spot-light.d.ts.map +1 -1
  42. package/dist/construct-renderer.mjs +10437 -10044
  43. package/dist/construct-renderer.mjs.map +1 -1
  44. package/dist/device/gpu-residency.d.ts +8 -1
  45. package/dist/device/gpu-residency.d.ts.map +1 -1
  46. package/dist/device/lifecycle-transaction.d.ts +2 -0
  47. package/dist/device/lifecycle-transaction.d.ts.map +1 -0
  48. package/dist/environment/lifecycle.d.ts.map +1 -1
  49. package/dist/errors/gpu-driven.d.ts +26 -0
  50. package/dist/errors/gpu-driven.d.ts.map +1 -0
  51. package/dist/errors/index.d.ts +1 -0
  52. package/dist/errors/index.d.ts.map +1 -1
  53. package/dist/errors/recover.d.ts +9 -1
  54. package/dist/errors/recover.d.ts.map +1 -1
  55. package/dist/errors/render.d.ts +26 -1
  56. package/dist/errors/render.d.ts.map +1 -1
  57. package/dist/extract/gpu-driven.d.ts +50 -0
  58. package/dist/extract/gpu-driven.d.ts.map +1 -0
  59. package/dist/extract/visibility.d.ts.map +1 -1
  60. package/dist/gpu-driven/batch-topology.d.ts +34 -0
  61. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  62. package/dist/gpu-driven/prepared-draw.d.ts +63 -0
  63. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -0
  64. package/dist/gpu-driven/production-raster.d.ts +98 -2
  65. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  66. package/dist/gpu-driven/view-gpu.d.ts +64 -1
  67. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  68. package/dist/gpu-scene-schema.d.ts +14 -0
  69. package/dist/gpu-scene-schema.d.ts.map +1 -1
  70. package/dist/gpu-scene.d.ts +8 -1
  71. package/dist/gpu-scene.d.ts.map +1 -1
  72. package/dist/gpu-usage.d.ts +0 -1
  73. package/dist/gpu-usage.d.ts.map +1 -1
  74. package/dist/hdrp-buffers.d.ts +3 -3
  75. package/dist/hdrp-buffers.d.ts.map +1 -1
  76. package/dist/index.d.ts +12 -1
  77. package/dist/index.d.ts.map +1 -1
  78. package/dist/index.mjs +90 -5
  79. package/dist/index.mjs.map +1 -1
  80. package/dist/inspection-types.d.ts +163 -1
  81. package/dist/inspection-types.d.ts.map +1 -1
  82. package/dist/internal.d.ts +9 -0
  83. package/dist/internal.d.ts.map +1 -1
  84. package/dist/internal.mjs +23 -2
  85. package/dist/internal.mjs.map +1 -1
  86. package/dist/light-buffer-layout.d.ts +58 -149
  87. package/dist/light-buffer-layout.d.ts.map +1 -1
  88. package/dist/materials.d.ts.map +1 -1
  89. package/dist/pbr-pipeline.d.ts +26 -12
  90. package/dist/pbr-pipeline.d.ts.map +1 -1
  91. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  92. package/dist/pipeline/standard-lighting/graph.d.ts.map +1 -1
  93. package/dist/pipeline/standard-lighting/light-frame.d.ts +3 -3
  94. package/dist/pipeline/standard-lighting/light-frame.d.ts.map +1 -1
  95. package/dist/pipeline/standard-lighting/topology.d.ts +1 -1
  96. package/dist/pipeline/standard-lighting/topology.d.ts.map +1 -1
  97. package/dist/pipeline/standard-lighting/transport.d.ts.map +1 -1
  98. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  99. package/dist/pipeline-builder.d.ts +2 -0
  100. package/dist/pipeline-builder.d.ts.map +1 -1
  101. package/dist/pipeline-spec.d.ts +1 -1
  102. package/dist/pipeline-spec.d.ts.map +1 -1
  103. package/dist/plugin.d.ts.map +1 -1
  104. package/dist/prepare/extended-lighting/ltc-resources.d.ts +31 -0
  105. package/dist/prepare/extended-lighting/ltc-resources.d.ts.map +1 -0
  106. package/dist/prepare/extended-lighting/resources.d.ts +72 -0
  107. package/dist/prepare/extended-lighting/resources.d.ts.map +1 -0
  108. package/dist/prepare/extended-lighting/spot-modifiers.d.ts +42 -0
  109. package/dist/prepare/extended-lighting/spot-modifiers.d.ts.map +1 -0
  110. package/dist/prepare/extended-lighting/state.d.ts +24 -0
  111. package/dist/prepare/extended-lighting/state.d.ts.map +1 -0
  112. package/dist/record/frame-lighting.d.ts +8 -6
  113. package/dist/record/frame-lighting.d.ts.map +1 -1
  114. package/dist/record/frame-snapshot.d.ts +50 -10
  115. package/dist/record/frame-snapshot.d.ts.map +1 -1
  116. package/dist/record/frame.d.ts +7 -3
  117. package/dist/record/frame.d.ts.map +1 -1
  118. package/dist/record/gpu-timing.d.ts +19 -7
  119. package/dist/record/gpu-timing.d.ts.map +1 -1
  120. package/dist/record/helpers.d.ts +0 -20
  121. package/dist/record/helpers.d.ts.map +1 -1
  122. package/dist/record/main-pass-geometry.d.ts +6 -1
  123. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  124. package/dist/record/main-pass-material.d.ts +3 -1
  125. package/dist/record/main-pass-material.d.ts.map +1 -1
  126. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  127. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  128. package/dist/record/render-context.d.ts +57 -6
  129. package/dist/record/render-context.d.ts.map +1 -1
  130. package/dist/record/shadow-pass.d.ts.map +1 -1
  131. package/dist/record/typed-frame-graph.d.ts +49 -2
  132. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  133. package/dist/record/view-ubo.d.ts +1 -2
  134. package/dist/record/view-ubo.d.ts.map +1 -1
  135. package/dist/reflection/inspection.d.ts +10 -0
  136. package/dist/reflection/inspection.d.ts.map +1 -0
  137. package/dist/reflection/projection.d.ts +49 -0
  138. package/dist/reflection/projection.d.ts.map +1 -1
  139. package/dist/reflection/record-owner.d.ts +60 -0
  140. package/dist/reflection/record-owner.d.ts.map +1 -0
  141. package/dist/render-contract.d.ts +14 -8
  142. package/dist/render-contract.d.ts.map +1 -1
  143. package/dist/render-pipeline.d.ts +7 -0
  144. package/dist/render-pipeline.d.ts.map +1 -1
  145. package/dist/render-system-extract.d.ts +104 -16
  146. package/dist/render-system-extract.d.ts.map +1 -1
  147. package/dist/render-system.d.ts +12 -1
  148. package/dist/render-system.d.ts.map +1 -1
  149. package/dist/scene/probe-blend-record.d.ts +22 -0
  150. package/dist/scene/probe-blend-record.d.ts.map +1 -0
  151. package/dist/scene/probe-blend.d.ts +142 -0
  152. package/dist/scene/probe-blend.d.ts.map +1 -0
  153. package/dist/scene/render-scene-types.d.ts +0 -6
  154. package/dist/scene/render-scene-types.d.ts.map +1 -1
  155. package/dist/scene/render-scene.d.ts +103 -9
  156. package/dist/scene/render-scene.d.ts.map +1 -1
  157. package/dist/scene/visibility/bounds.d.ts +20 -0
  158. package/dist/scene/visibility/bounds.d.ts.map +1 -0
  159. package/dist/scene/visibility/budget.d.ts +16 -0
  160. package/dist/scene/visibility/budget.d.ts.map +1 -0
  161. package/dist/scene/visibility/facet.d.ts +73 -0
  162. package/dist/scene/visibility/facet.d.ts.map +1 -0
  163. package/dist/scene/visibility/gpu-frame-timing.d.ts +41 -0
  164. package/dist/scene/visibility/gpu-frame-timing.d.ts.map +1 -0
  165. package/dist/scene/visibility/gpu-lod.d.ts +46 -0
  166. package/dist/scene/visibility/gpu-lod.d.ts.map +1 -0
  167. package/dist/scene/visibility/inspection.d.ts +132 -0
  168. package/dist/scene/visibility/inspection.d.ts.map +1 -0
  169. package/dist/scene/visibility/lod-selector.d.ts +25 -0
  170. package/dist/scene/visibility/lod-selector.d.ts.map +1 -0
  171. package/dist/scene/visibility/occlusion-confidence.d.ts +81 -0
  172. package/dist/scene/visibility/occlusion-confidence.d.ts.map +1 -0
  173. package/dist/scene/visibility/occlusion-pass.d.ts +57 -0
  174. package/dist/scene/visibility/occlusion-pass.d.ts.map +1 -0
  175. package/dist/scene/visibility/occlusion-query-pool.d.ts +57 -0
  176. package/dist/scene/visibility/occlusion-query-pool.d.ts.map +1 -0
  177. package/dist/scene/visibility/occlusion-runtime.d.ts +96 -0
  178. package/dist/scene/visibility/occlusion-runtime.d.ts.map +1 -0
  179. package/dist/scene/visibility/types.d.ts +34 -0
  180. package/dist/scene/visibility/types.d.ts.map +1 -0
  181. package/dist/ssr/admission.d.ts +122 -0
  182. package/dist/ssr/admission.d.ts.map +1 -0
  183. package/dist/ssr/composition.d.ts +32 -0
  184. package/dist/ssr/composition.d.ts.map +1 -0
  185. package/dist/ssr/errors.d.ts +39 -0
  186. package/dist/ssr/errors.d.ts.map +1 -0
  187. package/dist/ssr/identity.d.ts +13 -0
  188. package/dist/ssr/identity.d.ts.map +1 -0
  189. package/dist/systems/skin-palette-allocator.d.ts +1 -1
  190. package/dist/temporal/frame-coordinator.d.ts +13 -0
  191. package/dist/temporal/frame-coordinator.d.ts.map +1 -1
  192. package/dist/temporal/frame.d.ts +2 -0
  193. package/dist/temporal/frame.d.ts.map +1 -1
  194. package/dist/temporal/index.mjs +6 -5
  195. package/dist/temporal/view.d.ts +7 -0
  196. package/dist/temporal/view.d.ts.map +1 -1
  197. package/dist/tilemap-chunk-extract-system.d.ts +1 -1
  198. package/dist/typed-render-graph-primitives.d.ts +4 -0
  199. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  200. package/dist/volume/passes.d.ts +8 -4
  201. package/dist/volume/passes.d.ts.map +1 -1
  202. package/package.json +20 -20
  203. package/src/__tests__/cluster-grid-default-surface.unit.test.ts +5 -0
  204. package/src/__tests__/detached-inspection.integration.test.ts +6 -0
  205. package/src/__tests__/device-feature-admission.unit.test.ts +13 -1
  206. package/src/__tests__/direct-light-snapshot.unit.test.ts +59 -3
  207. package/src/__tests__/environment-generation.integration.test.ts +16 -0
  208. package/src/__tests__/evidence-identity.ts +13 -0
  209. package/src/__tests__/evidence-identity.unit.test.ts +24 -0
  210. package/src/__tests__/extended-lighting-recovery.browser.test.ts +14 -0
  211. package/src/__tests__/extended-lighting-recovery.dawn.test.ts +14 -0
  212. package/src/__tests__/extended-lighting-recovery.integration.test.ts +81 -0
  213. package/src/__tests__/extended-lighting-resources.unit.test.ts +51 -0
  214. package/src/__tests__/extended-lighting-zero-feature.integration.test.ts +52 -0
  215. package/src/__tests__/factory-contract.integration.test.ts +33 -0
  216. package/src/__tests__/frame-observation.contract.test.ts +15 -0
  217. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +146 -0
  218. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +1 -0
  219. package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +1 -0
  220. package/src/__tests__/gpu-driven-production.integration.test.ts +572 -9
  221. package/src/__tests__/gpu-driven-scaling.unit.test.ts +66 -2
  222. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +26 -1
  223. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +89 -2
  224. package/src/__tests__/gpu-driven-view.browser.test.ts +3 -3
  225. package/src/__tests__/gpu-driven-view.dawn.test.ts +3 -3
  226. package/src/__tests__/gpu-driven-view.unit.test.ts +50 -0
  227. package/src/__tests__/gpu-lod-evidence.ts +188 -0
  228. package/src/__tests__/gpu-lod-fallback.integration.test.ts +10 -0
  229. package/src/__tests__/gpu-lod-indirect.integration.test.ts +40 -0
  230. package/src/__tests__/gpu-lod-parity.dawn.test.ts +29 -0
  231. package/src/__tests__/gpu-lod-readiness.integration.test.ts +52 -0
  232. package/src/__tests__/gpu-lod-schema.unit.test.ts +66 -0
  233. package/src/__tests__/gpu-lod-selector.unit.test.ts +28 -0
  234. package/src/__tests__/gpu-lod-silhouette.browser.test.ts +13 -0
  235. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +66 -1
  236. package/src/__tests__/gpu-scene.dawn.test.ts +8 -1
  237. package/src/__tests__/gpu-scene.unit.test.ts +49 -3
  238. package/src/__tests__/light-buffer-layout.unit.test.ts +113 -3
  239. package/src/__tests__/light-inspection.unit.test.ts +55 -0
  240. package/src/__tests__/light-resource-error.unit.test.ts +43 -0
  241. package/src/__tests__/lighting-scene-roundtrip.integration.test.ts +109 -0
  242. package/src/__tests__/lod-bounds.unit.test.ts +42 -0
  243. package/src/__tests__/lod-cpu-lane.integration.test.ts +55 -0
  244. package/src/__tests__/lod-cpu-no-change.perf.test.ts +19 -0
  245. package/src/__tests__/lod-gpu-frame-timing.unit.test.ts +49 -0
  246. package/src/__tests__/lod-multi-view.integration.test.ts +63 -0
  247. package/src/__tests__/lod-occlusion-device-loss.integration.test.ts +27 -0
  248. package/src/__tests__/lod-occlusion-final-decision.integration.test.ts +47 -0
  249. package/src/__tests__/lod-occlusion-inspection.integration.test.ts +217 -0
  250. package/src/__tests__/lod-occlusion-inspection.schema.test-d.ts +14 -0
  251. package/src/__tests__/lod-occlusion-inspection.unit.test.ts +72 -0
  252. package/src/__tests__/lod-occlusion-visual-evidence.ts +91 -0
  253. package/src/__tests__/lod-occlusion.browser.test.ts +15 -0
  254. package/src/__tests__/lod-occlusion.dawn.test.ts +20 -0
  255. package/src/__tests__/lod-selector.profile.test.ts +35 -0
  256. package/src/__tests__/lod-selector.unit.test.ts +68 -0
  257. package/src/__tests__/lod-visibility-identity.unit.test.ts +198 -0
  258. package/src/__tests__/lod-visibility-lifecycle.integration.test.ts +132 -0
  259. package/src/__tests__/ltc-resources.unit.test.ts +32 -0
  260. package/src/__tests__/material-contract-inventory.unit.test.ts +17 -0
  261. package/src/__tests__/occlusion-confidence.unit.test.ts +168 -0
  262. package/src/__tests__/occlusion-invalidation.integration.test.ts +37 -0
  263. package/src/__tests__/occlusion-pass-routing.unit.test.ts +16 -0
  264. package/src/__tests__/occlusion-pass.dawn.test.ts +20 -0
  265. package/src/__tests__/occlusion-pass.integration.test.ts +43 -0
  266. package/src/__tests__/occlusion-pass.rhi-null.test.ts +22 -0
  267. package/src/__tests__/occlusion-query-pool.rhi-null.test.ts +21 -0
  268. package/src/__tests__/occlusion-query-pool.unit.test.ts +95 -0
  269. package/src/__tests__/occlusion-query-ticket.integration.test.ts +47 -0
  270. package/src/__tests__/occlusion-query.dawn.test.ts +16 -0
  271. package/src/__tests__/occlusion-query.evidence.ts +178 -0
  272. package/src/__tests__/occlusion-query.rhi-null.test.ts +31 -0
  273. package/src/__tests__/occlusion-runtime.unit.test.ts +120 -0
  274. package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +196 -0
  275. package/src/__tests__/probe-bindings.unit.test.ts +200 -0
  276. package/src/__tests__/probe-blend-numeric.unit.test.ts +67 -0
  277. package/src/__tests__/probe-blend-oracle.unit.test.ts +136 -0
  278. package/src/__tests__/probe-capacity.integration.test.ts +97 -0
  279. package/src/__tests__/probe-recovery.integration.test.ts +104 -0
  280. package/src/__tests__/probe-scene-dirty.integration.test.ts +211 -0
  281. package/src/__tests__/profiler-phase-catalog.test.ts +4 -1
  282. package/src/__tests__/profiler-phase-token.test.ts +1 -0
  283. package/src/__tests__/rect-area-boundary.unit.test.ts +24 -0
  284. package/src/__tests__/reflection-fallback-graph.unit.test.ts +67 -0
  285. package/src/__tests__/reflection-fallback-inspection.unit.test.ts +77 -0
  286. package/src/__tests__/reflection-fallback-lifecycle.integration.test.ts +21 -0
  287. package/src/__tests__/reflection-fallback-projection.unit.test.ts +90 -0
  288. package/src/__tests__/reflection-fallback-source.unit.test.ts +32 -0
  289. package/src/__tests__/reflection-probe-owner-placement.unit.test.ts +39 -0
  290. package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +120 -0
  291. package/src/__tests__/render-error-code-owner.test-d.ts +1 -0
  292. package/src/__tests__/render-feature-docs.unit.test.ts +12 -7
  293. package/src/__tests__/render-graph-fallback.integration.test.ts +24 -0
  294. package/src/__tests__/render-perf/extended-lighting.bench.test.ts +66 -0
  295. package/src/__tests__/render-scene-projection.unit.test.ts +447 -18
  296. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +76 -0
  297. package/src/__tests__/skin-motion-regression.unit.test.ts +22 -0
  298. package/src/__tests__/skinned-shadow-caster.test.ts +2 -2
  299. package/src/__tests__/spot-modifier-projection.unit.test.ts +70 -0
  300. package/src/__tests__/ssr-admission-matrix.integration.test.ts +206 -0
  301. package/src/__tests__/ssr-composition.unit.test.ts +46 -0
  302. package/src/__tests__/ssr-fallback-zero-work.bench.test.ts +94 -0
  303. package/src/__tests__/ssr-recovery-errors.unit.test.ts +58 -0
  304. package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +67 -0
  305. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +7 -0
  306. package/src/__tests__/standard-lighting-inspection.integration.test.ts +1 -1
  307. package/src/__tests__/standard-lighting-write.unit.test.ts +66 -2
  308. package/src/__tests__/temporal-fallback-generation.integration.test.ts +16 -0
  309. package/src/__tests__/temporal-view.unit.test.ts +3 -3
  310. package/src/__tests__/transmission-prewarm.unit.test.ts +69 -0
  311. package/src/__tests__/visibility-budget.integration.test.ts +140 -0
  312. package/src/__tests__/visibility-budget.unit.test.ts +70 -0
  313. package/src/__tests__/visibility-extract.integration.test.ts +11 -6
  314. package/src/__tests__/volumetric-fog-point-spot-accumulation.integration.test.ts +6 -3
  315. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +31 -28
  316. package/src/assembly/backend-contract.ts +13 -0
  317. package/src/assembly/device-feature-admission.ts +16 -9
  318. package/src/assembly/factory.ts +547 -93
  319. package/src/assembly/host-contract.ts +10 -0
  320. package/src/cluster-binner.ts +31 -0
  321. package/src/components/__tests__/lighting-authoring.unit.test.ts +39 -0
  322. package/src/components/__tests__/rect-area-light.unit.test.ts +33 -0
  323. package/src/components/index.ts +3 -0
  324. package/src/components/light-helpers.ts +52 -1
  325. package/src/components/light-probe.ts +13 -0
  326. package/src/components/rect-area-light.ts +15 -0
  327. package/src/components/scene-instance.ts +6 -0
  328. package/src/components/spot-light.ts +3 -0
  329. package/src/device/__tests__/extended-lighting-recovery.unit.test.ts +24 -0
  330. package/src/device/gpu-residency.ts +140 -9
  331. package/src/device/lifecycle-transaction.ts +12 -0
  332. package/src/environment/lifecycle.ts +8 -1
  333. package/src/errors/gpu-driven.ts +92 -0
  334. package/src/errors/index.ts +1 -0
  335. package/src/errors/recover.ts +32 -0
  336. package/src/errors/render.ts +55 -1
  337. package/src/extract/camera.ts +3 -3
  338. package/src/extract/gpu-driven.ts +108 -0
  339. package/src/extract/visibility.ts +0 -23
  340. package/src/gpu-driven/batch-topology.ts +206 -28
  341. package/src/gpu-driven/prepared-draw.ts +208 -0
  342. package/src/gpu-driven/production-raster.ts +953 -41
  343. package/src/gpu-driven/view-gpu.ts +411 -29
  344. package/src/gpu-scene-schema.ts +13 -0
  345. package/src/gpu-scene.ts +134 -65
  346. package/src/gpu-usage.ts +0 -1
  347. package/src/hdrp-buffers.ts +6 -6
  348. package/src/index.ts +74 -0
  349. package/src/inspection-types.ts +220 -1
  350. package/src/internal.ts +38 -0
  351. package/src/light-buffer-layout.ts +154 -324
  352. package/src/materials.ts +16 -2
  353. package/src/pbr-pipeline.ts +151 -45
  354. package/src/pipeline/standard-forward-lane.ts +47 -0
  355. package/src/pipeline/standard-lighting/graph.ts +2 -1
  356. package/src/pipeline/standard-lighting/light-frame.ts +3 -2
  357. package/src/pipeline/standard-lighting/topology.ts +1 -1
  358. package/src/pipeline/standard-lighting/transport.ts +2 -1
  359. package/src/pipeline/standard-pipeline.ts +2 -0
  360. package/src/pipeline-builder.ts +5 -2
  361. package/src/pipeline-spec.ts +12 -1
  362. package/src/plugin.ts +4 -0
  363. package/src/prepare/__tests__/extended-lighting-capability.unit.test.ts +56 -0
  364. package/src/prepare/extended-lighting/ltc-resources.ts +136 -0
  365. package/src/prepare/extended-lighting/resources.ts +389 -0
  366. package/src/prepare/extended-lighting/spot-modifiers.ts +194 -0
  367. package/src/prepare/extended-lighting/state.ts +92 -0
  368. package/src/record/__tests__/gpu-timing.unit.test.ts +177 -0
  369. package/src/record/__tests__/temporal-payload.unit.test.ts +23 -1
  370. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +20 -1
  371. package/src/record/frame-lighting.ts +252 -53
  372. package/src/record/frame-snapshot.ts +57 -12
  373. package/src/record/frame.ts +410 -93
  374. package/src/record/gpu-timing.ts +108 -44
  375. package/src/record/helpers.ts +0 -58
  376. package/src/record/main-pass-geometry.ts +204 -39
  377. package/src/record/main-pass-material.ts +8 -1
  378. package/src/record/main-pass-sprite-draws.ts +52 -85
  379. package/src/record/mesh-ssbo.ts +47 -36
  380. package/src/record/render-context.ts +65 -4
  381. package/src/record/shadow-pass.ts +66 -40
  382. package/src/record/typed-frame-graph.ts +225 -83
  383. package/src/record/view-ubo.ts +14 -24
  384. package/src/reflection/inspection.ts +67 -0
  385. package/src/reflection/projection.ts +196 -1
  386. package/src/reflection/record-owner.ts +1283 -0
  387. package/src/render-contract.ts +17 -5
  388. package/src/render-pipeline.ts +5 -0
  389. package/src/render-system-extract.ts +493 -134
  390. package/src/render-system.ts +811 -615
  391. package/src/scene/__tests__/changed-block-summary.candidate.test.ts +36 -0
  392. package/src/scene/probe-blend-record.ts +54 -0
  393. package/src/scene/probe-blend.ts +813 -0
  394. package/src/scene/render-scene-types.ts +0 -7
  395. package/src/scene/render-scene.ts +848 -183
  396. package/src/scene/visibility/bounds.ts +57 -0
  397. package/src/scene/visibility/budget.ts +40 -0
  398. package/src/scene/visibility/facet.ts +400 -0
  399. package/src/scene/visibility/gpu-frame-timing.ts +101 -0
  400. package/src/scene/visibility/gpu-lod.ts +119 -0
  401. package/src/scene/visibility/inspection.ts +313 -0
  402. package/src/scene/visibility/lod-selector.ts +84 -0
  403. package/src/scene/visibility/occlusion-confidence.ts +478 -0
  404. package/src/scene/visibility/occlusion-pass.ts +165 -0
  405. package/src/scene/visibility/occlusion-query-pool.ts +178 -0
  406. package/src/scene/visibility/occlusion-runtime.ts +672 -0
  407. package/src/scene/visibility/types.ts +50 -0
  408. package/src/ssr/admission.ts +451 -0
  409. package/src/ssr/composition.ts +73 -0
  410. package/src/ssr/errors.ts +76 -0
  411. package/src/ssr/identity.ts +12 -0
  412. package/src/systems/skin-palette-allocator.ts +1 -1
  413. package/src/temporal/frame-coordinator.ts +26 -0
  414. package/src/temporal/frame.ts +14 -1
  415. package/src/temporal/view.ts +11 -0
  416. package/src/tilemap-chunk-extract-system.ts +4 -4
  417. package/src/typed-render-graph-primitives.ts +48 -0
  418. package/src/volume/passes.ts +46 -49
  419. package/dist/.tsbuildinfo +0 -1
  420. package/dist/chunk-5YADUCA7.mjs.map +0 -1
  421. package/dist/chunk-6OPXDQ2E.mjs.map +0 -1
  422. package/dist/chunk-BXBQQKFQ.mjs +0 -67
  423. package/dist/chunk-BXBQQKFQ.mjs.map +0 -1
  424. package/dist/chunk-FS2KNUQH.mjs.map +0 -1
  425. package/dist/chunk-PCHBPYML.mjs.map +0 -1
  426. package/dist/chunk-VFPLTKCU.mjs.map +0 -1
@@ -0,0 +1,136 @@
1
+ // @forgeax/engine-render - DeviceScope-owned RectArea LTC resources.
2
+
3
+ import type { Result, RhiDevice, RhiError, Texture } from '@forgeax/engine-rhi';
4
+ import { LTC_TABLE_HEIGHT, LTC_TABLE_WIDTH, LTC_TABLES } from '@forgeax/engine-shader';
5
+ import { err, ok } from '@forgeax/engine-types';
6
+ import { type DeviceScope, LifecycleTransaction } from '../../device/device-scope';
7
+ import {
8
+ GPU_TEXTURE_USAGE_COPY_DST,
9
+ GPU_TEXTURE_USAGE_TEXTURE_BINDING,
10
+ } from '../../gpu-texture-usage';
11
+ import { deriveExtendedLightingCapability, EXTENDED_LIGHTING_TOPOLOGY } from './resources';
12
+
13
+ export interface LtcResourcePlanInput {
14
+ readonly scope: DeviceScope;
15
+ readonly ltcAvailable: boolean;
16
+ readonly residentGeneration?: number;
17
+ }
18
+
19
+ export interface LtcResourcePlan {
20
+ readonly topology: typeof EXTENDED_LIGHTING_TOPOLOGY;
21
+ readonly generation: number;
22
+ readonly rectAdmission: 'admitted' | 'omitted';
23
+ readonly tableCount: number;
24
+ readonly uploadCount: number;
25
+ }
26
+
27
+ export interface LtcResourceCandidate {
28
+ readonly topology: typeof EXTENDED_LIGHTING_TOPOLOGY;
29
+ readonly generation: number;
30
+ readonly scope: DeviceScope;
31
+ readonly lambertTexture: Texture;
32
+ readonly ggxTexture: Texture;
33
+ readonly tableCount: 2;
34
+ readonly uploadCount: 2;
35
+ }
36
+
37
+ export function deriveLtcResourcePlan(input: LtcResourcePlanInput): LtcResourcePlan {
38
+ const admitted = input.ltcAvailable;
39
+ return {
40
+ topology: EXTENDED_LIGHTING_TOPOLOGY,
41
+ generation: input.scope.generation,
42
+ rectAdmission: admitted ? 'admitted' : 'omitted',
43
+ tableCount: admitted ? 2 : 0,
44
+ uploadCount: admitted && input.residentGeneration !== input.scope.generation ? 2 : 0,
45
+ };
46
+ }
47
+
48
+ function failure(expected: string, actual: string): Result<never, RhiError> {
49
+ return err({
50
+ code: 'webgpu-runtime-error',
51
+ expected,
52
+ hint: 'inspect device capabilities and retry the extendedLighting candidate',
53
+ detail: { error: { code: 'ltc-resource', message: actual } },
54
+ } as RhiError);
55
+ }
56
+
57
+ function textureBytes(table: Uint16Array): Uint8Array {
58
+ return new Uint8Array(table.buffer, table.byteOffset, table.byteLength);
59
+ }
60
+
61
+ /** Create both tracked tables atomically; unavailable LTC only omits Rect. */
62
+ export async function createLtcResourceCandidate(input: {
63
+ readonly device: RhiDevice | undefined;
64
+ readonly scope: DeviceScope;
65
+ }): Promise<Result<LtcResourceCandidate | undefined, RhiError>> {
66
+ if (input.device === undefined) return ok(undefined);
67
+ if (!deriveExtendedLightingCapability(input.device).admitted) return ok(undefined);
68
+ const device = input.device;
69
+
70
+ const transaction = new LifecycleTransaction(input.scope);
71
+ let lambertTexture: Texture | undefined;
72
+ let ggxTexture: Texture | undefined;
73
+ const createTable = (label: string, table: Uint16Array): Texture => {
74
+ const texture = device.createTexture({
75
+ label,
76
+ size: { width: LTC_TABLE_WIDTH, height: LTC_TABLE_HEIGHT, depthOrArrayLayers: 1 },
77
+ mipLevelCount: 1,
78
+ sampleCount: 1,
79
+ dimension: '2d',
80
+ format: 'rgba16float',
81
+ usage: GPU_TEXTURE_USAGE_COPY_DST | GPU_TEXTURE_USAGE_TEXTURE_BINDING,
82
+ viewFormats: [],
83
+ textureBindingViewDimension: undefined,
84
+ });
85
+ if (texture === undefined || !texture.ok) {
86
+ throw texture?.error ?? new Error('LTC texture creation returned no result');
87
+ }
88
+ const write = device.queue.writeTexture(
89
+ { texture: texture.value, mipLevel: 0, origin: { x: 0, y: 0, z: 0 } },
90
+ textureBytes(table),
91
+ { offset: 0, bytesPerRow: LTC_TABLE_WIDTH * 8, rowsPerImage: LTC_TABLE_HEIGHT },
92
+ { width: LTC_TABLE_WIDTH, height: LTC_TABLE_HEIGHT, depthOrArrayLayers: 1 },
93
+ );
94
+ if (!write.ok) throw write.error;
95
+ return texture.value;
96
+ };
97
+
98
+ transaction.add({
99
+ kind: 'texture',
100
+ create: () => {
101
+ lambertTexture = createTable('extended-lighting-ltc-lambert', LTC_TABLES.lambert);
102
+ return lambertTexture;
103
+ },
104
+ cleanup: (value) => {
105
+ const destroyed = input.device?.destroyTexture(value);
106
+ if (destroyed !== undefined && !destroyed.ok) throw destroyed.error;
107
+ },
108
+ });
109
+ transaction.add({
110
+ kind: 'texture',
111
+ create: () => {
112
+ ggxTexture = createTable('extended-lighting-ltc-ggx', LTC_TABLES.ggx);
113
+ return ggxTexture;
114
+ },
115
+ cleanup: (value) => {
116
+ const destroyed = input.device?.destroyTexture(value);
117
+ if (destroyed !== undefined && !destroyed.ok) throw destroyed.error;
118
+ },
119
+ });
120
+
121
+ const committed = await transaction.commit();
122
+ if (!committed.ok)
123
+ return failure(committed.error.primary.expected, committed.error.primary.message);
124
+ if (lambertTexture === undefined || ggxTexture === undefined) {
125
+ return failure('two LTC textures', 'the transaction committed without both tables');
126
+ }
127
+ return ok({
128
+ topology: EXTENDED_LIGHTING_TOPOLOGY,
129
+ generation: input.scope.generation,
130
+ scope: input.scope,
131
+ lambertTexture,
132
+ ggxTexture,
133
+ tableCount: 2,
134
+ uploadCount: 2,
135
+ });
136
+ }
@@ -0,0 +1,389 @@
1
+ import type { Buffer, Result, RhiDevice, Sampler, Texture } from '@forgeax/engine-rhi';
2
+ import { RhiError } from '@forgeax/engine-rhi';
3
+ import { err, ok } from '@forgeax/engine-types';
4
+ import type { DeviceScope } from '../../device/device-scope';
5
+ import { LifecycleTransaction } from '../../device/lifecycle-transaction';
6
+ import {
7
+ GPU_TEXTURE_USAGE_COPY_DST,
8
+ GPU_TEXTURE_USAGE_TEXTURE_BINDING,
9
+ } from '../../gpu-texture-usage';
10
+ import { GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_UNIFORM } from '../../gpu-usage';
11
+
12
+ export const EXTENDED_LIGHTING_TOPOLOGY = 'extendedLighting' as const;
13
+ export const IES_SLICE_CAPACITY = 32;
14
+ export const COOKIE_SLICE_CAPACITY = 32;
15
+ export const PROBE_RECORD_CAPACITY = 64;
16
+ export const IES_SLICE_WIDTH = 256;
17
+ export const IES_SLICE_HEIGHT = 128;
18
+ export const COOKIE_SLICE_SIZE = 256;
19
+ export const COOKIE_MATRIX_BYTES = 32 * 16 * Float32Array.BYTES_PER_ELEMENT;
20
+ /**
21
+ * Minimum per-stage sampled-texture limit for the shared PBR + extended-
22
+ * lighting pipeline-layout topology. The current BGL closure reserves 18
23
+ * sampled textures for the URP path and 20 for the HDRP/Probe path after the
24
+ * material IBL and transmission injections; WebGPU validates this pipeline-
25
+ * layout count even when a compiled shader variant does not read every
26
+ * optional entry.
27
+ */
28
+ export const EXTENDED_LIGHTING_REQUIRED_SAMPLED_TEXTURES = 20;
29
+
30
+ /**
31
+ * Keep shader-variant selection and resource admission on one capability fact.
32
+ * An omitted limit is treated as unavailable: a caller must not claim the
33
+ * extended topology without a numeric device limit proving it fits.
34
+ */
35
+ export function extendedLightingSampledTextureCapacityAvailable(
36
+ maxSampledTexturesPerShaderStage: number | undefined,
37
+ ): boolean {
38
+ return (
39
+ maxSampledTexturesPerShaderStage !== undefined &&
40
+ maxSampledTexturesPerShaderStage >= EXTENDED_LIGHTING_REQUIRED_SAMPLED_TEXTURES
41
+ );
42
+ }
43
+
44
+ export interface ExtendedLightingCapabilityResult {
45
+ readonly admitted: boolean;
46
+ readonly topology: typeof EXTENDED_LIGHTING_TOPOLOGY;
47
+ readonly reason: string | undefined;
48
+ }
49
+
50
+ export interface ExtendedLightingResourceInput {
51
+ readonly device: RhiDevice | undefined;
52
+ readonly scope: DeviceScope;
53
+ readonly iesSliceCount: number;
54
+ readonly cookieSliceCount: number;
55
+ readonly cookieMatrices: number;
56
+ readonly iesData?: Uint8Array | undefined;
57
+ readonly cookieData?: Uint8Array | undefined;
58
+ readonly cookieMatrixData?: Float32Array | undefined;
59
+ }
60
+
61
+ export interface ExtendedLightingResourceCandidate {
62
+ readonly topology: typeof EXTENDED_LIGHTING_TOPOLOGY;
63
+ readonly generation: number;
64
+ readonly scope: DeviceScope;
65
+ readonly iesSliceCount: number;
66
+ readonly cookieSliceCount: number;
67
+ readonly cookieMatrices: number;
68
+ readonly sampler: Sampler;
69
+ readonly iesTexture: Texture | undefined;
70
+ readonly cookieTexture: Texture | undefined;
71
+ readonly cookieMatrixBuffer: Buffer | undefined;
72
+ readonly descriptorBytes: number;
73
+ readonly uploadCount: number;
74
+ }
75
+
76
+ export interface ExtendedLightingResourceInspection {
77
+ readonly topology: typeof EXTENDED_LIGHTING_TOPOLOGY;
78
+ readonly generation: number;
79
+ readonly status: 'empty' | 'candidate' | 'accepted';
80
+ readonly accepted: boolean;
81
+ readonly resourceCount: number;
82
+ readonly descriptorBytes: number;
83
+ readonly uploadCount: number;
84
+ readonly blendInvalidations: number;
85
+ readonly passCount: number;
86
+ }
87
+
88
+ function failure(expected: string, actual: string): Result<never, RhiError> {
89
+ return err(
90
+ new RhiError({
91
+ code: 'webgpu-runtime-error',
92
+ expected,
93
+ hint: 'repair the extended lighting resource facts and retry the candidate generation',
94
+ detail: { error: { code: 'extended-lighting-resource', message: actual } },
95
+ }),
96
+ );
97
+ }
98
+
99
+ function validCount(value: number, capacity: number): boolean {
100
+ return Number.isSafeInteger(value) && value >= 0 && value <= capacity;
101
+ }
102
+
103
+ /** Derive admission from the RHI facts; no backend-kind policy is involved. */
104
+ export function deriveExtendedLightingCapability(
105
+ device: Pick<RhiDevice, 'caps' | 'limits'>,
106
+ ): ExtendedLightingCapabilityResult {
107
+ const maxSampledTextures = device.limits.maxSampledTexturesPerShaderStage;
108
+ if (!extendedLightingSampledTextureCapacityAvailable(maxSampledTextures)) {
109
+ return {
110
+ admitted: false,
111
+ topology: EXTENDED_LIGHTING_TOPOLOGY,
112
+ reason: `maxSampledTexturesPerShaderStage ${maxSampledTextures ?? 0} < ${EXTENDED_LIGHTING_REQUIRED_SAMPLED_TEXTURES}`,
113
+ };
114
+ }
115
+ const maxLayers = device.limits.maxTextureArrayLayers ?? 0;
116
+ const maxUniformBuffers = device.limits.maxUniformBuffersPerShaderStage ?? 0;
117
+ if (maxLayers < IES_SLICE_CAPACITY) {
118
+ return {
119
+ admitted: false,
120
+ topology: EXTENDED_LIGHTING_TOPOLOGY,
121
+ reason: `maxTextureArrayLayers ${maxLayers} < ${IES_SLICE_CAPACITY}`,
122
+ };
123
+ }
124
+ if (maxUniformBuffers < 1) {
125
+ return {
126
+ admitted: false,
127
+ topology: EXTENDED_LIGHTING_TOPOLOGY,
128
+ reason: `maxUniformBuffersPerShaderStage ${maxUniformBuffers} < 1`,
129
+ };
130
+ }
131
+ if (
132
+ !device.caps.storageBuffer ||
133
+ !device.caps.rgba16floatRenderable ||
134
+ !device.caps.samplerAliasing
135
+ ) {
136
+ return {
137
+ admitted: false,
138
+ topology: EXTENDED_LIGHTING_TOPOLOGY,
139
+ reason: 'required storage-buffer, rgba16float, or sampler capability is unavailable',
140
+ };
141
+ }
142
+ return { admitted: true, topology: EXTENDED_LIGHTING_TOPOLOGY, reason: undefined };
143
+ }
144
+
145
+ function createTexture(
146
+ device: RhiDevice,
147
+ label: string,
148
+ format: 'r16float' | 'rgba8unorm',
149
+ width: number,
150
+ height: number,
151
+ layers: number,
152
+ ): Result<Texture, RhiError> {
153
+ return device.createTexture({
154
+ label,
155
+ size: { width, height, depthOrArrayLayers: layers },
156
+ mipLevelCount: 1,
157
+ sampleCount: 1,
158
+ dimension: '2d',
159
+ format,
160
+ usage: GPU_TEXTURE_USAGE_COPY_DST | GPU_TEXTURE_USAGE_TEXTURE_BINDING,
161
+ viewFormats: [],
162
+ textureBindingViewDimension: undefined,
163
+ });
164
+ }
165
+
166
+ function requireResource<T>(result: Result<T, RhiError>): T {
167
+ if (!result.ok) throw result.error;
168
+ return result.value;
169
+ }
170
+
171
+ function writeTextureSlices(
172
+ device: RhiDevice,
173
+ texture: Texture,
174
+ data: Uint8Array | undefined,
175
+ bytesPerRow: number,
176
+ height: number,
177
+ layerCount: number,
178
+ width: number,
179
+ ): number {
180
+ if (data === undefined || layerCount === 0) return 0;
181
+ const bytesPerSlice = bytesPerRow * height;
182
+ const requiredBytes = bytesPerSlice * layerCount;
183
+ if (data.byteLength < requiredBytes) {
184
+ throw new Error(`extended lighting texture upload requires ${requiredBytes} bytes`);
185
+ }
186
+ for (let layer = 0; layer < layerCount; layer += 1) {
187
+ const start = layer * bytesPerSlice;
188
+ requireResource(
189
+ device.queue.writeTexture(
190
+ { texture, mipLevel: 0, origin: { x: 0, y: 0, z: layer } },
191
+ data.subarray(start, start + bytesPerSlice),
192
+ { offset: 0, bytesPerRow, rowsPerImage: height },
193
+ { width, height, depthOrArrayLayers: 1 },
194
+ ),
195
+ );
196
+ }
197
+ return layerCount;
198
+ }
199
+
200
+ /** Build a complete candidate; nothing is adopted until the transaction commits. */
201
+ export async function createExtendedLightingResourceCandidate(
202
+ input: ExtendedLightingResourceInput,
203
+ ): Promise<Result<ExtendedLightingResourceCandidate, RhiError>> {
204
+ const { device, scope } = input;
205
+ if (device === undefined) return failure('a live RHI device is required', 'device is undefined');
206
+ if (!validCount(input.iesSliceCount, IES_SLICE_CAPACITY)) {
207
+ return failure(`IES slice count <= ${IES_SLICE_CAPACITY}`, String(input.iesSliceCount));
208
+ }
209
+ if (!validCount(input.cookieSliceCount, COOKIE_SLICE_CAPACITY)) {
210
+ return failure(
211
+ `Cookie slice count <= ${COOKIE_SLICE_CAPACITY}`,
212
+ String(input.cookieSliceCount),
213
+ );
214
+ }
215
+ if (!validCount(input.cookieMatrices, COOKIE_SLICE_CAPACITY)) {
216
+ return failure(`Cookie matrix count <= ${COOKIE_SLICE_CAPACITY}`, String(input.cookieMatrices));
217
+ }
218
+ const capability = deriveExtendedLightingCapability(device);
219
+ if (!capability.admitted)
220
+ return failure('extendedLighting capability admission', capability.reason ?? 'unavailable');
221
+ if (
222
+ input.cookieMatrixData !== undefined &&
223
+ input.cookieMatrixData.byteLength < input.cookieMatrices * 16 * Float32Array.BYTES_PER_ELEMENT
224
+ ) {
225
+ return failure(
226
+ 'cookie matrix upload payload',
227
+ `requires ${input.cookieMatrices * 16 * Float32Array.BYTES_PER_ELEMENT} bytes`,
228
+ );
229
+ }
230
+
231
+ const transaction = new LifecycleTransaction(scope);
232
+ let iesTexture: Texture | undefined;
233
+ let cookieTexture: Texture | undefined;
234
+ let cookieMatrixBuffer: Buffer | undefined;
235
+ let sampler: Sampler | undefined;
236
+ let uploadCount = 0;
237
+ transaction.add({
238
+ kind: 'texture',
239
+ create: () => {
240
+ const created = requireResource(
241
+ createTexture(
242
+ device,
243
+ 'extended-lighting-ies',
244
+ 'r16float',
245
+ IES_SLICE_WIDTH,
246
+ IES_SLICE_HEIGHT,
247
+ IES_SLICE_CAPACITY,
248
+ ),
249
+ );
250
+ uploadCount += writeTextureSlices(
251
+ device,
252
+ created,
253
+ input.iesData,
254
+ IES_SLICE_WIDTH * 2,
255
+ IES_SLICE_HEIGHT,
256
+ input.iesSliceCount,
257
+ IES_SLICE_WIDTH,
258
+ );
259
+ iesTexture = created;
260
+ return created;
261
+ },
262
+ cleanup: (value) => {
263
+ const destroyed = device.destroyTexture(value);
264
+ if (!destroyed.ok) throw destroyed.error;
265
+ },
266
+ });
267
+ transaction.add({
268
+ kind: 'texture',
269
+ create: () => {
270
+ const created = requireResource(
271
+ createTexture(
272
+ device,
273
+ 'extended-lighting-cookie',
274
+ 'rgba8unorm',
275
+ COOKIE_SLICE_SIZE,
276
+ COOKIE_SLICE_SIZE,
277
+ COOKIE_SLICE_CAPACITY,
278
+ ),
279
+ );
280
+ uploadCount += writeTextureSlices(
281
+ device,
282
+ created,
283
+ input.cookieData,
284
+ COOKIE_SLICE_SIZE * 4,
285
+ COOKIE_SLICE_SIZE,
286
+ input.cookieSliceCount,
287
+ COOKIE_SLICE_SIZE,
288
+ );
289
+ cookieTexture = created;
290
+ return created;
291
+ },
292
+ cleanup: (value) => {
293
+ const destroyed = device.destroyTexture(value);
294
+ if (!destroyed.ok) throw destroyed.error;
295
+ },
296
+ });
297
+ transaction.add({
298
+ kind: 'buffer',
299
+ create: () => {
300
+ const created = requireResource(
301
+ device.createBuffer({
302
+ label: 'extended-lighting-cookie-matrices',
303
+ size: COOKIE_MATRIX_BYTES,
304
+ usage: GPU_BUFFER_USAGE_COPY_DST | GPU_BUFFER_USAGE_UNIFORM,
305
+ mappedAtCreation: false,
306
+ }),
307
+ );
308
+ if (input.cookieMatrixData !== undefined && input.cookieMatrices > 0) {
309
+ requireResource(device.queue.writeBuffer(created, 0, input.cookieMatrixData));
310
+ uploadCount += 1;
311
+ }
312
+ cookieMatrixBuffer = created;
313
+ return created;
314
+ },
315
+ cleanup: (value) => {
316
+ const destroyed = device.destroyBuffer(value);
317
+ if (!destroyed.ok) throw destroyed.error;
318
+ },
319
+ });
320
+ transaction.add({
321
+ // Samplers are bindable GPU resources, not host listeners. Keeping the
322
+ // lifecycle kind aligned with the resource's actual renderer role makes
323
+ // scope inspection and rollback receipts truthful.
324
+ kind: 'binding',
325
+ create: () => {
326
+ const created = requireResource(
327
+ device.createSampler({
328
+ label: 'extended-lighting-clamp-linear',
329
+ addressModeU: 'clamp-to-edge',
330
+ addressModeV: 'clamp-to-edge',
331
+ addressModeW: 'clamp-to-edge',
332
+ magFilter: 'linear',
333
+ minFilter: 'linear',
334
+ mipmapFilter: 'nearest',
335
+ }),
336
+ );
337
+ sampler = created;
338
+ return created;
339
+ },
340
+ cleanup: () => undefined,
341
+ });
342
+ const committed = await transaction.commit();
343
+ if (!committed.ok)
344
+ return failure(committed.error.primary.expected, committed.error.primary.message);
345
+ if (
346
+ iesTexture === undefined ||
347
+ cookieTexture === undefined ||
348
+ cookieMatrixBuffer === undefined ||
349
+ sampler === undefined
350
+ ) {
351
+ return failure(
352
+ 'complete extendedLighting candidate resources',
353
+ 'resource transaction returned an incomplete set',
354
+ );
355
+ }
356
+ return ok({
357
+ topology: EXTENDED_LIGHTING_TOPOLOGY,
358
+ generation: scope.generation,
359
+ scope,
360
+ iesSliceCount: input.iesSliceCount,
361
+ cookieSliceCount: input.cookieSliceCount,
362
+ cookieMatrices: input.cookieMatrices,
363
+ sampler,
364
+ iesTexture,
365
+ cookieTexture,
366
+ cookieMatrixBuffer,
367
+ descriptorBytes:
368
+ IES_SLICE_WIDTH * IES_SLICE_HEIGHT * 2 * IES_SLICE_CAPACITY +
369
+ COOKIE_SLICE_SIZE * COOKIE_SLICE_SIZE * 4 * COOKIE_SLICE_CAPACITY +
370
+ COOKIE_MATRIX_BYTES,
371
+ uploadCount,
372
+ });
373
+ }
374
+
375
+ export function inspectExtendedLightingResources(
376
+ scope: DeviceScope,
377
+ ): ExtendedLightingResourceInspection {
378
+ return {
379
+ topology: EXTENDED_LIGHTING_TOPOLOGY,
380
+ generation: scope.generation,
381
+ status: 'empty',
382
+ accepted: false,
383
+ resourceCount: 0,
384
+ descriptorBytes: 0,
385
+ uploadCount: 0,
386
+ blendInvalidations: 0,
387
+ passCount: 0,
388
+ };
389
+ }