@forgeax/engine-render 0.1.3 → 0.1.6

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 (918) hide show
  1. package/README.md +130 -641
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/__tests__/device-scope-lifecycle.unit.test.d.ts +2 -0
  4. package/dist/__tests__/device-scope-lifecycle.unit.test.d.ts.map +1 -0
  5. package/dist/__tests__/device-scope-stale-matrix.unit.test.d.ts +2 -0
  6. package/dist/__tests__/device-scope-stale-matrix.unit.test.d.ts.map +1 -0
  7. package/dist/__tests__/fullscreen-feature-plan.unit.test.d.ts +2 -0
  8. package/dist/__tests__/fullscreen-feature-plan.unit.test.d.ts.map +1 -0
  9. package/dist/__tests__/gpu-driven-indirect-raster-evidence.d.ts.map +1 -1
  10. package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts +6 -0
  11. package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts.map +1 -1
  12. package/dist/{gpu-driven/view-reference.d.ts → __tests__/gpu-driven-view-reference.d.ts} +4 -4
  13. package/dist/__tests__/gpu-driven-view-reference.d.ts.map +1 -0
  14. package/dist/__tests__/gpu-scene-render-graph-gpu.d.ts.map +1 -1
  15. package/dist/__tests__/ibl/face-uniforms.unit.test.d.ts +2 -0
  16. package/dist/__tests__/ibl/face-uniforms.unit.test.d.ts.map +1 -0
  17. package/dist/__tests__/morph-feature-plan.unit.test.d.ts +2 -0
  18. package/dist/__tests__/morph-feature-plan.unit.test.d.ts.map +1 -0
  19. package/dist/__tests__/render-feature-plan.test-d.d.ts +2 -0
  20. package/dist/__tests__/render-feature-plan.test-d.d.ts.map +1 -0
  21. package/dist/__tests__/render-feature-plan.unit.test.d.ts +2 -0
  22. package/dist/__tests__/render-feature-plan.unit.test.d.ts.map +1 -0
  23. package/dist/__tests__/ssao-config.unit.test.d.ts +2 -0
  24. package/dist/__tests__/ssao-config.unit.test.d.ts.map +1 -0
  25. package/dist/__tests__/standard-clustered-pipeline.unit.test.d.ts +2 -0
  26. package/dist/__tests__/standard-clustered-pipeline.unit.test.d.ts.map +1 -0
  27. package/dist/__tests__/standard-descriptors.test-d.d.ts +2 -0
  28. package/dist/__tests__/standard-descriptors.test-d.d.ts.map +1 -0
  29. package/dist/__tests__/standard-pipeline.dawn.test.d.ts +2 -0
  30. package/dist/__tests__/standard-pipeline.dawn.test.d.ts.map +1 -0
  31. package/dist/__tests__/standard-pipeline.integration.test.d.ts +2 -0
  32. package/dist/__tests__/standard-pipeline.integration.test.d.ts.map +1 -0
  33. package/dist/__tests__/standard-profile-oracle.unit.test.d.ts +2 -0
  34. package/dist/__tests__/standard-profile-oracle.unit.test.d.ts.map +1 -0
  35. package/dist/__tests__/visibility-resource-short-circuit.unit.test.d.ts +2 -0
  36. package/dist/__tests__/visibility-resource-short-circuit.unit.test.d.ts.map +1 -0
  37. package/dist/{renderer/backend-selection.d.ts → assembly/backend-contract.d.ts} +15 -4
  38. package/dist/assembly/backend-contract.d.ts.map +1 -0
  39. package/dist/assembly/factory.d.ts +207 -0
  40. package/dist/assembly/factory.d.ts.map +1 -0
  41. package/dist/assembly/host-contract.d.ts +84 -0
  42. package/dist/assembly/host-contract.d.ts.map +1 -0
  43. package/dist/{renderer → assembly}/material/assembly.d.ts +1 -2
  44. package/dist/{renderer → assembly}/material/assembly.d.ts.map +1 -1
  45. package/dist/assembly/material/pipeline-projection.d.ts +30 -0
  46. package/dist/assembly/material/pipeline-projection.d.ts.map +1 -0
  47. package/dist/authoring.d.ts +10 -11
  48. package/dist/authoring.d.ts.map +1 -1
  49. package/dist/authoring.mjs +25 -3
  50. package/dist/authoring.mjs.map +1 -1
  51. package/dist/chunk-CQXZC5XI.mjs +182 -0
  52. package/dist/chunk-CQXZC5XI.mjs.map +1 -0
  53. package/dist/chunk-QC4VW3XJ.mjs +79 -0
  54. package/dist/chunk-QC4VW3XJ.mjs.map +1 -0
  55. package/dist/chunk-SCRSAK5B.mjs +480 -0
  56. package/dist/chunk-SCRSAK5B.mjs.map +1 -0
  57. package/dist/components/__tests__/schema-contract.unit.test.d.ts +2 -0
  58. package/dist/components/__tests__/schema-contract.unit.test.d.ts.map +1 -0
  59. package/dist/components/glyph-text.d.ts +1 -1
  60. package/dist/components/glyph-text.d.ts.map +1 -1
  61. package/dist/components/index.d.ts +2 -2
  62. package/dist/components/index.d.ts.map +1 -1
  63. package/dist/components/instances.d.ts +1 -1
  64. package/dist/components/instances.d.ts.map +1 -1
  65. package/dist/components/light-helpers.d.ts +1 -1
  66. package/dist/components/light-helpers.d.ts.map +1 -1
  67. package/dist/components/mesh-filter.d.ts +7 -7
  68. package/dist/components/mesh-filter.d.ts.map +1 -1
  69. package/dist/components/scene-instance.d.ts +11 -11
  70. package/dist/components/skybox-background.d.ts +56 -0
  71. package/dist/components/skybox-background.d.ts.map +1 -0
  72. package/dist/components/skylight.d.ts +55 -0
  73. package/dist/components/skylight.d.ts.map +1 -0
  74. package/dist/components/sprite-animation.d.ts +2 -3
  75. package/dist/components/sprite-animation.d.ts.map +1 -1
  76. package/dist/components/sprite-instances.d.ts +1 -1
  77. package/dist/components/sprite-playback-mode.d.ts +6 -1
  78. package/dist/components/sprite-playback-mode.d.ts.map +1 -1
  79. package/dist/components/sprite-region-override.d.ts +2 -3
  80. package/dist/components/sprite-region-override.d.ts.map +1 -1
  81. package/dist/components/tile-layer.d.ts +5 -0
  82. package/dist/components/tile-layer.d.ts.map +1 -1
  83. package/dist/construct-renderer.d.ts +18 -1
  84. package/dist/construct-renderer.d.ts.map +1 -1
  85. package/dist/construct-renderer.mjs +27008 -4
  86. package/dist/construct-renderer.mjs.map +1 -1
  87. package/dist/debug-draw-glue.d.ts +2 -53
  88. package/dist/debug-draw-glue.d.ts.map +1 -1
  89. package/dist/device/device-scope.d.ts +83 -0
  90. package/dist/device/device-scope.d.ts.map +1 -0
  91. package/dist/{gpu-resource-store.d.ts → device/gpu-residency.d.ts} +91 -48
  92. package/dist/device/gpu-residency.d.ts.map +1 -0
  93. package/dist/device/resource-types.d.ts +8 -0
  94. package/dist/device/resource-types.d.ts.map +1 -0
  95. package/dist/engine-metrics.d.ts +2 -2
  96. package/dist/engine-metrics.d.ts.map +1 -1
  97. package/dist/errors/recover.d.ts +28 -1
  98. package/dist/errors/recover.d.ts.map +1 -1
  99. package/dist/errors/render.d.ts +249 -258
  100. package/dist/errors/render.d.ts.map +1 -1
  101. package/dist/features/fullscreen.d.ts +19 -0
  102. package/dist/features/fullscreen.d.ts.map +1 -0
  103. package/dist/features/host.d.ts +32 -26
  104. package/dist/features/host.d.ts.map +1 -1
  105. package/dist/features/morph/morph-feature.d.ts +39 -5
  106. package/dist/features/morph/morph-feature.d.ts.map +1 -1
  107. package/dist/features/plan.d.ts +182 -0
  108. package/dist/features/plan.d.ts.map +1 -0
  109. package/dist/features/prepared-gpu-work.d.ts +21 -17
  110. package/dist/features/prepared-gpu-work.d.ts.map +1 -1
  111. package/dist/features/prepared-graphics-store.d.ts +2 -1
  112. package/dist/features/prepared-graphics-store.d.ts.map +1 -1
  113. package/dist/features/prepared-graphics.d.ts +11 -21
  114. package/dist/features/prepared-graphics.d.ts.map +1 -1
  115. package/dist/features/render-graph-compute.d.ts +2 -2
  116. package/dist/features/render-graph-compute.d.ts.map +1 -1
  117. package/dist/features/render-graph-contribution.d.ts +4 -7
  118. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  119. package/dist/features/render-graph-raster.d.ts +2 -2
  120. package/dist/features/render-graph-raster.d.ts.map +1 -1
  121. package/dist/features/render-graph-resources.d.ts +6 -6
  122. package/dist/features/render-graph-resources.d.ts.map +1 -1
  123. package/dist/features/targets.d.ts +5 -5
  124. package/dist/features/targets.d.ts.map +1 -1
  125. package/dist/features/types.d.ts +11 -190
  126. package/dist/features/types.d.ts.map +1 -1
  127. package/dist/features/vocabulary.d.ts +14 -0
  128. package/dist/features/vocabulary.d.ts.map +1 -0
  129. package/dist/fullscreen-post-process-pass.d.ts +4 -25
  130. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  131. package/dist/glyph-text-layout-system.d.ts +3 -2
  132. package/dist/glyph-text-layout-system.d.ts.map +1 -1
  133. package/dist/gpu-driven/batch-topology.d.ts +6 -75
  134. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  135. package/dist/gpu-driven/production-raster.d.ts +13 -112
  136. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  137. package/dist/gpu-driven/view-gpu.d.ts +10 -66
  138. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  139. package/dist/gpu-resource.d.ts +3 -3
  140. package/dist/gpu-scene-schema.d.ts +1 -94
  141. package/dist/gpu-scene-schema.d.ts.map +1 -1
  142. package/dist/gpu-scene.d.ts +7 -33
  143. package/dist/gpu-scene.d.ts.map +1 -1
  144. package/dist/hdrp-buffers.d.ts +3 -53
  145. package/dist/hdrp-buffers.d.ts.map +1 -1
  146. package/dist/ibl/IblPipelineCache.d.ts +74 -180
  147. package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
  148. package/dist/ibl/skylight-bind-group.d.ts +1 -1
  149. package/dist/index.d.ts +13 -43
  150. package/dist/index.d.ts.map +1 -1
  151. package/dist/index.mjs +165 -3
  152. package/dist/index.mjs.map +1 -1
  153. package/dist/inspection-types.d.ts +69 -0
  154. package/dist/inspection-types.d.ts.map +1 -0
  155. package/dist/instance-buffer-cache.d.ts +1 -4
  156. package/dist/instance-buffer-cache.d.ts.map +1 -1
  157. package/dist/internal.d.ts +1 -73
  158. package/dist/internal.d.ts.map +1 -1
  159. package/dist/internal.mjs +1 -43
  160. package/dist/internal.mjs.map +1 -1
  161. package/dist/lifecycle.d.ts +36 -2
  162. package/dist/lifecycle.d.ts.map +1 -1
  163. package/dist/materials.d.ts +0 -3
  164. package/dist/materials.d.ts.map +1 -1
  165. package/dist/mesh-material-bindings.d.ts +0 -1
  166. package/dist/mesh-material-bindings.d.ts.map +1 -1
  167. package/dist/pbr-pipeline.d.ts +75 -29
  168. package/dist/pbr-pipeline.d.ts.map +1 -1
  169. package/dist/pipeline/standard-forward-lane.d.ts +5 -0
  170. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -0
  171. package/dist/pipeline/standard-pipeline.d.ts +31 -0
  172. package/dist/pipeline/standard-pipeline.d.ts.map +1 -0
  173. package/dist/pipeline/standard-profile.d.ts +40 -0
  174. package/dist/pipeline/standard-profile.d.ts.map +1 -0
  175. package/dist/pipeline-builder.d.ts +3 -3
  176. package/dist/pipeline-builder.d.ts.map +1 -1
  177. package/dist/pipeline-spec-types.d.ts +24 -0
  178. package/dist/pipeline-spec-types.d.ts.map +1 -0
  179. package/dist/pipeline-spec.d.ts +16 -155
  180. package/dist/pipeline-spec.d.ts.map +1 -1
  181. package/dist/plugin.d.ts +1 -14
  182. package/dist/plugin.d.ts.map +1 -1
  183. package/dist/post-process-errors.d.ts +18 -18
  184. package/dist/post-process-errors.d.ts.map +1 -1
  185. package/dist/prepare/prepared-graphics-resolver.d.ts +2 -5
  186. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  187. package/dist/record/__tests__/typed-frame-graph-plan.unit.test.d.ts +2 -0
  188. package/dist/record/__tests__/typed-frame-graph-plan.unit.test.d.ts.map +1 -0
  189. package/dist/record/frame-lighting.d.ts +7 -73
  190. package/dist/record/frame-lighting.d.ts.map +1 -1
  191. package/dist/record/frame-snapshot.d.ts +44 -44
  192. package/dist/record/frame-snapshot.d.ts.map +1 -1
  193. package/dist/record/frame-targets.d.ts +5 -38
  194. package/dist/record/frame-targets.d.ts.map +1 -1
  195. package/dist/record/frame.d.ts +64 -52
  196. package/dist/record/frame.d.ts.map +1 -1
  197. package/dist/record/helpers.d.ts +3 -2
  198. package/dist/record/helpers.d.ts.map +1 -1
  199. package/dist/record/main-pass-geometry.d.ts +5 -4
  200. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  201. package/dist/record/main-pass-material.d.ts +90 -59
  202. package/dist/record/main-pass-material.d.ts.map +1 -1
  203. package/dist/record/main-pass-sprite-draws.d.ts +28 -3
  204. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  205. package/dist/record/main-pass.d.ts +1 -1
  206. package/dist/record/main-pass.d.ts.map +1 -1
  207. package/dist/record/mesh-ssbo.d.ts +276 -3
  208. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  209. package/dist/record/render-context.d.ts +235 -0
  210. package/dist/record/render-context.d.ts.map +1 -0
  211. package/dist/record/shadow-pass.d.ts +15 -88
  212. package/dist/record/shadow-pass.d.ts.map +1 -1
  213. package/dist/record/skybox-post-pass.d.ts +1 -1
  214. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  215. package/dist/record/typed-frame-graph.d.ts +29 -7
  216. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  217. package/dist/record/view-ubo.d.ts +3 -3
  218. package/dist/record/view-ubo.d.ts.map +1 -1
  219. package/dist/render-contract.d.ts +416 -0
  220. package/dist/render-contract.d.ts.map +1 -0
  221. package/dist/render-data.d.ts.map +1 -1
  222. package/dist/render-graph-primitives.d.ts +14 -362
  223. package/dist/render-graph-primitives.d.ts.map +1 -1
  224. package/dist/render-pipeline.d.ts +25 -64
  225. package/dist/render-pipeline.d.ts.map +1 -1
  226. package/dist/render-system-extract.d.ts +107 -338
  227. package/dist/render-system-extract.d.ts.map +1 -1
  228. package/dist/render-system.d.ts +21 -713
  229. package/dist/render-system.d.ts.map +1 -1
  230. package/dist/scene/render-scene-types.d.ts +58 -0
  231. package/dist/scene/render-scene-types.d.ts.map +1 -0
  232. package/dist/scene/render-scene.d.ts +105 -0
  233. package/dist/scene/render-scene.d.ts.map +1 -0
  234. package/dist/scene-instances/post-spawn-resolve-joints.d.ts +2 -5
  235. package/dist/scene-instances/post-spawn-resolve-joints.d.ts.map +1 -1
  236. package/dist/ssao-buffers.d.ts +22 -3
  237. package/dist/ssao-buffers.d.ts.map +1 -1
  238. package/dist/systems/skin-palette-allocator.d.ts +2 -4
  239. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  240. package/dist/systems/skin-palette-types.d.ts +14 -0
  241. package/dist/systems/skin-palette-types.d.ts.map +1 -0
  242. package/dist/systems/transparent-sort-config.d.ts +23 -2
  243. package/dist/systems/transparent-sort-config.d.ts.map +1 -1
  244. package/dist/tilemap-chunk-extract-system.d.ts +4 -3
  245. package/dist/tilemap-chunk-extract-system.d.ts.map +1 -1
  246. package/dist/typed-render-graph-primitives.d.ts +2 -4
  247. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  248. package/dist/typed-shadow-passes.d.ts +3 -3
  249. package/dist/typed-shadow-passes.d.ts.map +1 -1
  250. package/package.json +23 -23
  251. package/src/__tests__/backend-selection-rhi-capture.test-d.ts +1 -1
  252. package/src/__tests__/callback-inference.test-d.ts +6 -3
  253. package/src/__tests__/cluster-grid-default-surface.unit.test.ts +7 -4
  254. package/src/__tests__/construct-renderer-identity.unit.test.ts +15 -2
  255. package/src/__tests__/device-scope-lifecycle.unit.test.ts +151 -0
  256. package/src/__tests__/device-scope-stale-matrix.unit.test.ts +42 -0
  257. package/src/__tests__/direct-extract-consumer-contract.test-d.ts +8 -19
  258. package/src/__tests__/direct-light-snapshot.unit.test.ts +3 -13
  259. package/src/__tests__/factory-contract.integration.test.ts +158 -209
  260. package/src/__tests__/fallback-row-stride-surface.unit.test.ts +1 -4
  261. package/src/__tests__/frame-observation.contract.test.ts +17 -8
  262. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +32 -0
  263. package/src/__tests__/glyph-text-layout-recovery.unit.test.ts +6 -11
  264. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +9 -16
  265. package/src/__tests__/gpu-driven-production.integration.test.ts +32 -205
  266. package/src/__tests__/gpu-driven-scaling.unit.test.ts +4 -7
  267. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +87 -8
  268. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +170 -8
  269. package/src/{gpu-driven/view-reference.ts → __tests__/gpu-driven-view-reference.ts} +4 -3
  270. package/src/__tests__/gpu-driven-view.browser.test.ts +12 -1
  271. package/src/__tests__/gpu-driven-view.dawn.test.ts +12 -1
  272. package/src/__tests__/gpu-driven-view.unit.test.ts +11 -267
  273. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +3 -3
  274. package/src/__tests__/gpu-scene-render-graph-gpu.ts +2 -3
  275. package/src/__tests__/gpu-scene.dawn.test.ts +2 -6
  276. package/src/__tests__/gpu-scene.unit.test.ts +10 -24
  277. package/src/__tests__/ibl/face-uniforms.unit.test.ts +46 -0
  278. package/src/__tests__/infinite-grid-no-vertex-probe.unit.test.ts +34 -66
  279. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +14 -5
  280. package/src/__tests__/light-buffer-layout.unit.test.ts +4 -49
  281. package/src/__tests__/material-cooked-projection.unit.test.ts +2 -51
  282. package/src/__tests__/material-snapshot-mutation.integration.test.ts +10 -15
  283. package/src/__tests__/material-static-dynamic-route.unit.test.ts +4 -23
  284. package/src/__tests__/material-stride-surface.unit.test.ts +2 -2
  285. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +7 -8
  286. package/src/__tests__/morph-culling-reentry.dawn.test.ts +29 -38
  287. package/src/__tests__/morph-feature-gpu-work.integration.test.ts +45 -43
  288. package/src/__tests__/morph-feature-plan.unit.test.ts +53 -0
  289. package/src/__tests__/morph-visual-evidence.integration.test.ts +47 -33
  290. package/src/__tests__/nineslice-handle-surface.unit.test.ts +11 -6
  291. package/src/__tests__/post-process-error-policy-owner.unit.test.ts +6 -13
  292. package/src/__tests__/prepared-graphics-capability.unit.test.ts +6 -81
  293. package/src/__tests__/prepared-graphics-generation.unit.test.ts +3 -17
  294. package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +6 -74
  295. package/src/__tests__/prepared-graphics-resolver.unit.test.ts +1 -3
  296. package/src/__tests__/prepared-graphics-snapshot.unit.test.ts +2 -2
  297. package/src/__tests__/profiler-default-off.test.ts +1 -1
  298. package/src/__tests__/profiler-phase-catalog.test.ts +2 -2
  299. package/src/__tests__/profiler-phase-integration.test.ts +5 -13
  300. package/src/__tests__/profiler-phase-token.test.ts +3 -8
  301. package/src/__tests__/public-surface.test-d.ts +65 -3
  302. package/src/__tests__/recover-error-policy-owner.unit.test.ts +1 -21
  303. package/src/__tests__/render-error-code-owner.test-d.ts +18 -23
  304. package/src/__tests__/render-error-detail-ssot.test-d.ts +0 -95
  305. package/src/__tests__/render-error-exhaustive.test-d.ts +8 -1
  306. package/src/__tests__/render-feature-assembly.test-d.ts +8 -16
  307. package/src/__tests__/render-feature-context.test-d.ts +16 -40
  308. package/src/__tests__/render-feature-contract.test-d.ts +9 -18
  309. package/src/__tests__/render-feature-diagnostics.unit.test.ts +6 -8
  310. package/src/__tests__/render-feature-docs.unit.test.ts +8 -7
  311. package/src/__tests__/render-feature-gpu-work.integration.test.ts +14 -75
  312. package/src/__tests__/render-feature-plan.test-d.ts +161 -0
  313. package/src/__tests__/render-feature-plan.unit.test.ts +170 -0
  314. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +8 -19
  315. package/src/__tests__/render-feature-prepared-errors.test-d.ts +3 -6
  316. package/src/__tests__/render-feature-prepared-graphics-docs.unit.test.ts +10 -71
  317. package/src/__tests__/render-feature-prepared-graphics-isolation.unit.test.ts +11 -61
  318. package/src/__tests__/render-feature-prepared-graphics-negative.test-d.ts +20 -43
  319. package/src/__tests__/render-feature-prepared-graphics.test-d.ts +56 -78
  320. package/src/__tests__/render-feature-public-surface.test-d.ts +6 -24
  321. package/src/__tests__/render-feature-retry.unit.test.ts +7 -48
  322. package/src/__tests__/render-feature-scheduling.unit.test.ts +15 -27
  323. package/src/__tests__/render-feature-stage-failed-policy-owner.unit.test.ts +0 -9
  324. package/src/__tests__/render-feature-stage-fault-recovery.unit.test.ts +19 -109
  325. package/src/__tests__/render-feature-visibility-context.test-d.ts +1 -6
  326. package/src/__tests__/render-feature-visibility-context.unit.test.ts +1 -2
  327. package/src/__tests__/render-feature-zero-work.unit.test.ts +14 -20
  328. package/src/__tests__/render-scene-projection.unit.test.ts +73 -111
  329. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +46 -50
  330. package/src/__tests__/renderer-lifecycle.integration.test.ts +49 -1
  331. package/src/__tests__/shader-stage-surface.unit.test.ts +14 -9
  332. package/src/__tests__/ssao-config.unit.test.ts +36 -0
  333. package/src/__tests__/ssao-kernel-surface.unit.test.ts +4 -5
  334. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +28 -0
  335. package/src/__tests__/standard-descriptors.test-d.ts +22 -0
  336. package/src/__tests__/standard-pipeline.dawn.test.ts +61 -0
  337. package/src/__tests__/standard-pipeline.integration.test.ts +124 -0
  338. package/src/__tests__/standard-profile-oracle.unit.test.ts +62 -0
  339. package/src/__tests__/surface-configuration.unit.test.ts +1 -2
  340. package/src/__tests__/texture-usage-surface.unit.test.ts +3 -6
  341. package/src/__tests__/typed-pipeline-topology.unit.test.ts +40 -206
  342. package/src/__tests__/urp-pipeline-targets.unit.test.ts +1 -11
  343. package/src/__tests__/urp-pipeline.unit.test.ts +2 -2
  344. package/src/__tests__/vertex-color-pipeline.unit.test.ts +10 -2
  345. package/src/__tests__/vertex-layout-consumer.unit.test.ts +1 -1
  346. package/src/__tests__/visibility-diagnostics.integration.test.ts +7 -11
  347. package/src/__tests__/visibility-extract.integration.test.ts +20 -11
  348. package/src/__tests__/visibility-extract.perf.test.ts +66 -32
  349. package/src/__tests__/visibility-feature-dedup.integration.test.ts +2 -4
  350. package/src/__tests__/visibility-hidden-report.unit.test.ts +1 -2
  351. package/src/__tests__/visibility-instances.integration.test.ts +7 -11
  352. package/src/__tests__/visibility-multi-world.integration.test.ts +38 -6
  353. package/src/__tests__/visibility-producer-matrix.integration.test.ts +18 -41
  354. package/src/__tests__/visibility-public-surface.test-d.ts +10 -9
  355. package/src/__tests__/visibility-resolver.unit.test.ts +2 -1
  356. package/src/__tests__/visibility-resource-short-circuit.unit.test.ts +80 -0
  357. package/src/__tests__/visibility-snapshot-contract.unit.test.ts +2 -1
  358. package/src/__tests__/vocabulary.unit.test.ts +1 -1
  359. package/src/assembly/backend-contract.ts +57 -0
  360. package/src/{renderer/renderer-factory.ts → assembly/factory.ts} +1709 -2693
  361. package/src/assembly/host-contract.ts +101 -0
  362. package/src/{renderer → assembly}/material/assembly.ts +1 -3
  363. package/src/assembly/material/pipeline-projection.ts +63 -0
  364. package/src/authoring.ts +14 -22
  365. package/src/components/__tests__/schema-contract.unit.test.ts +10 -0
  366. package/src/components/glyph-text.ts +3 -2
  367. package/src/components/index.ts +7 -9
  368. package/src/components/instances.ts +4 -5
  369. package/src/components/light-helpers.ts +1 -1
  370. package/src/components/mesh-filter.ts +11 -10
  371. package/src/components/post-process-params.ts +3 -3
  372. package/src/components/scene-instance.ts +12 -12
  373. package/src/components/skybox-background.ts +103 -0
  374. package/src/components/{environment.ts → skylight.ts} +2 -111
  375. package/src/components/sprite-animation.ts +3 -4
  376. package/src/components/sprite-instances.ts +2 -2
  377. package/src/components/sprite-playback-mode.ts +7 -1
  378. package/src/components/sprite-region-override.ts +2 -3
  379. package/src/components/tile-layer.ts +8 -2
  380. package/src/construct-renderer.ts +67 -4
  381. package/src/debug-draw-glue.ts +8 -129
  382. package/src/device/device-scope.ts +306 -0
  383. package/src/{gpu-resource-store.ts → device/gpu-residency.ts} +540 -639
  384. package/src/device/resource-types.ts +20 -0
  385. package/src/engine-metrics.ts +12 -19
  386. package/src/errors/recover.ts +45 -3
  387. package/src/errors/render.ts +357 -460
  388. package/src/features/fullscreen.ts +46 -0
  389. package/src/features/host.ts +575 -309
  390. package/src/features/morph/morph-feature.ts +195 -105
  391. package/src/features/plan.ts +447 -0
  392. package/src/features/prepared-gpu-work.ts +72 -15
  393. package/src/features/prepared-graphics-store.ts +20 -6
  394. package/src/features/prepared-graphics.ts +12 -71
  395. package/src/features/render-graph-compute.ts +14 -5
  396. package/src/features/render-graph-contribution.ts +43 -63
  397. package/src/features/render-graph-raster.ts +11 -6
  398. package/src/features/render-graph-resources.ts +25 -23
  399. package/src/features/targets.ts +8 -21
  400. package/src/features/types.ts +39 -227
  401. package/src/features/vocabulary.ts +24 -0
  402. package/src/fullscreen-post-process-pass.ts +14 -57
  403. package/src/glyph-text-layout-system.ts +70 -96
  404. package/src/gpu-driven/batch-topology.ts +24 -202
  405. package/src/gpu-driven/production-raster.ts +93 -1108
  406. package/src/gpu-driven/view-gpu.ts +46 -192
  407. package/src/gpu-resource.ts +4 -4
  408. package/src/gpu-scene-schema.ts +11 -99
  409. package/src/gpu-scene.ts +231 -364
  410. package/src/hdrp-buffers.ts +12 -221
  411. package/src/ibl/IblPipelineCache.ts +471 -711
  412. package/src/ibl/skylight-bind-group.ts +4 -4
  413. package/src/index.ts +58 -217
  414. package/src/inspection-types.ts +76 -0
  415. package/src/instance-buffer-cache.ts +1 -29
  416. package/src/internal.ts +6 -85
  417. package/src/lifecycle.ts +64 -19
  418. package/src/materials.ts +7 -29
  419. package/src/mesh-material-bindings.ts +0 -1
  420. package/src/pbr-pipeline.ts +434 -53
  421. package/src/{urp-pipeline.ts → pipeline/standard-forward-lane.ts} +38 -149
  422. package/src/{hdrp-pipeline.ts → pipeline/standard-pipeline.ts} +221 -191
  423. package/src/pipeline/standard-profile.ts +65 -0
  424. package/src/pipeline-builder.ts +60 -64
  425. package/src/pipeline-spec-types.ts +28 -0
  426. package/src/pipeline-spec.ts +72 -609
  427. package/src/plugin.ts +3 -75
  428. package/src/post-process-errors.ts +31 -33
  429. package/src/prepare/prepared-graphics-resolver.ts +5 -4
  430. package/src/record/__tests__/material-slot-plan.unit.test.ts +1 -33
  431. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +41 -0
  432. package/src/record/__tests__/video-texture-view.unit.test.ts +1 -1
  433. package/src/record/frame-lighting.ts +74 -195
  434. package/src/record/frame-snapshot.ts +45 -60
  435. package/src/record/frame-targets.ts +8 -243
  436. package/src/record/frame.ts +509 -796
  437. package/src/record/helpers.ts +6 -11
  438. package/src/record/main-pass-geometry.ts +106 -147
  439. package/src/record/main-pass-material.ts +517 -190
  440. package/src/record/main-pass-sprite-draws.ts +198 -117
  441. package/src/record/main-pass.ts +162 -143
  442. package/src/record/mesh-ssbo.ts +517 -38
  443. package/src/record/render-context.ts +364 -0
  444. package/src/record/shadow-pass.ts +138 -1838
  445. package/src/record/skybox-post-pass.ts +12 -14
  446. package/src/record/typed-frame-graph.ts +215 -254
  447. package/src/record/view-ubo.ts +6 -37
  448. package/src/render-contract.ts +571 -0
  449. package/src/render-data.ts +3 -3
  450. package/src/render-graph-primitives.ts +76 -851
  451. package/src/render-pipeline.ts +104 -188
  452. package/src/render-system-extract.ts +1048 -1729
  453. package/src/render-system.ts +330 -1957
  454. package/src/scene/render-scene-types.ts +64 -0
  455. package/src/scene/render-scene.ts +1032 -0
  456. package/src/scene-instances/post-spawn-resolve-joints.ts +4 -7
  457. package/src/ssao-buffers.ts +167 -8
  458. package/src/systems/skin-palette-allocator.ts +21 -64
  459. package/src/systems/skin-palette-types.ts +14 -0
  460. package/src/systems/transparent-sort-config.ts +25 -3
  461. package/src/tilemap-chunk-extract-system.ts +53 -70
  462. package/src/typed-render-graph-primitives.ts +35 -24
  463. package/src/typed-shadow-passes.ts +26 -56
  464. package/dist/__tests__/analytic-sky-contract.test.d.ts +0 -2
  465. package/dist/__tests__/analytic-sky-contract.test.d.ts.map +0 -1
  466. package/dist/__tests__/analytic-sky-falsify.test.d.ts +0 -2
  467. package/dist/__tests__/analytic-sky-falsify.test.d.ts.map +0 -1
  468. package/dist/__tests__/assets-runtime-handoff.integration.test.d.ts +0 -2
  469. package/dist/__tests__/assets-runtime-handoff.integration.test.d.ts.map +0 -1
  470. package/dist/__tests__/backend-selection.integration.test.d.ts +0 -2
  471. package/dist/__tests__/backend-selection.integration.test.d.ts.map +0 -1
  472. package/dist/__tests__/camera-temporal.test-d.d.ts +0 -2
  473. package/dist/__tests__/camera-temporal.test-d.d.ts.map +0 -1
  474. package/dist/__tests__/camera-temporal.test.d.ts +0 -2
  475. package/dist/__tests__/camera-temporal.test.d.ts.map +0 -1
  476. package/dist/__tests__/directional-shadow-probe-atlas-layout.unit.test.d.ts +0 -2
  477. package/dist/__tests__/directional-shadow-probe-atlas-layout.unit.test.d.ts.map +0 -1
  478. package/dist/__tests__/environment-inspection.test.d.ts +0 -2
  479. package/dist/__tests__/environment-inspection.test.d.ts.map +0 -1
  480. package/dist/__tests__/fog-ai-user.fixture.d.ts +0 -2
  481. package/dist/__tests__/fog-ai-user.fixture.d.ts.map +0 -1
  482. package/dist/__tests__/fog-custom-render-feature.fixture.d.ts +0 -16
  483. package/dist/__tests__/fog-custom-render-feature.fixture.d.ts.map +0 -1
  484. package/dist/__tests__/fog-custom-render-feature.integration.test.d.ts +0 -2
  485. package/dist/__tests__/fog-custom-render-feature.integration.test.d.ts.map +0 -1
  486. package/dist/__tests__/fog-inspection.integration.test.d.ts +0 -2
  487. package/dist/__tests__/fog-inspection.integration.test.d.ts.map +0 -1
  488. package/dist/__tests__/fog-owner-state.integration.test.d.ts +0 -2
  489. package/dist/__tests__/fog-owner-state.integration.test.d.ts.map +0 -1
  490. package/dist/__tests__/fog-pipeline-topology.integration.test.d.ts +0 -2
  491. package/dist/__tests__/fog-pipeline-topology.integration.test.d.ts.map +0 -1
  492. package/dist/__tests__/fog-public-surface.integration.test.d.ts +0 -2
  493. package/dist/__tests__/fog-public-surface.integration.test.d.ts.map +0 -1
  494. package/dist/__tests__/fog-ray-contract.integration.test.d.ts +0 -2
  495. package/dist/__tests__/fog-ray-contract.integration.test.d.ts.map +0 -1
  496. package/dist/__tests__/fog-source-absence.integration.test.d.ts +0 -2
  497. package/dist/__tests__/fog-source-absence.integration.test.d.ts.map +0 -1
  498. package/dist/__tests__/fog-temporal.integration.test.d.ts +0 -2
  499. package/dist/__tests__/fog-temporal.integration.test.d.ts.map +0 -1
  500. package/dist/__tests__/frame-chain.unit.test.d.ts +0 -2
  501. package/dist/__tests__/frame-chain.unit.test.d.ts.map +0 -1
  502. package/dist/__tests__/gpu-scene-field-type-owner.test-d.d.ts +0 -2
  503. package/dist/__tests__/gpu-scene-field-type-owner.test-d.d.ts.map +0 -1
  504. package/dist/__tests__/hdrp-pipeline.unit.test.d.ts +0 -2
  505. package/dist/__tests__/hdrp-pipeline.unit.test.d.ts.map +0 -1
  506. package/dist/__tests__/ibl/ibl-fallback.unit.test.d.ts +0 -2
  507. package/dist/__tests__/ibl/ibl-fallback.unit.test.d.ts.map +0 -1
  508. package/dist/__tests__/material-derived-error-stop-draw.integration.test.d.ts +0 -2
  509. package/dist/__tests__/material-derived-error-stop-draw.integration.test.d.ts.map +0 -1
  510. package/dist/__tests__/material-derived-payload.integration.test.d.ts +0 -2
  511. package/dist/__tests__/material-derived-payload.integration.test.d.ts.map +0 -1
  512. package/dist/__tests__/materials.unit.test.d.ts +0 -2
  513. package/dist/__tests__/materials.unit.test.d.ts.map +0 -1
  514. package/dist/__tests__/param-schema-projection-census.unit.test.d.ts +0 -2
  515. package/dist/__tests__/param-schema-projection-census.unit.test.d.ts.map +0 -1
  516. package/dist/__tests__/persistent-render-scene.unit.test.d.ts +0 -2
  517. package/dist/__tests__/persistent-render-scene.unit.test.d.ts.map +0 -1
  518. package/dist/__tests__/pipeline-error-policy-owner.unit.test.d.ts +0 -2
  519. package/dist/__tests__/pipeline-error-policy-owner.unit.test.d.ts.map +0 -1
  520. package/dist/__tests__/pipeline-pass-trace.test.d.ts +0 -2
  521. package/dist/__tests__/pipeline-pass-trace.test.d.ts.map +0 -1
  522. package/dist/__tests__/pipeline-stage-owner.test-d.d.ts +0 -2
  523. package/dist/__tests__/pipeline-stage-owner.test-d.d.ts.map +0 -1
  524. package/dist/__tests__/plugin.test.d.ts +0 -2
  525. package/dist/__tests__/plugin.test.d.ts.map +0 -1
  526. package/dist/__tests__/prepared-graphics-backend-matrix.unit.test.d.ts +0 -2
  527. package/dist/__tests__/prepared-graphics-backend-matrix.unit.test.d.ts.map +0 -1
  528. package/dist/__tests__/prepared-graphics-resolver-recording.unit.test.d.ts +0 -2
  529. package/dist/__tests__/prepared-graphics-resolver-recording.unit.test.d.ts.map +0 -1
  530. package/dist/__tests__/public-pipeline-id.test-d.d.ts +0 -2
  531. package/dist/__tests__/public-pipeline-id.test-d.d.ts.map +0 -1
  532. package/dist/__tests__/render-dispatch-membership.unit.test.d.ts +0 -2
  533. package/dist/__tests__/render-dispatch-membership.unit.test.d.ts.map +0 -1
  534. package/dist/__tests__/render-feature-construction.unit.test.d.ts +0 -2
  535. package/dist/__tests__/render-feature-construction.unit.test.d.ts.map +0 -1
  536. package/dist/__tests__/render-feature-error-code-owner.test-d.d.ts +0 -2
  537. package/dist/__tests__/render-feature-error-code-owner.test-d.d.ts.map +0 -1
  538. package/dist/__tests__/render-feature-gpu-buffer-usage-owner.test-d.d.ts +0 -2
  539. package/dist/__tests__/render-feature-gpu-buffer-usage-owner.test-d.d.ts.map +0 -1
  540. package/dist/__tests__/render-feature-graph.integration.test.d.ts +0 -2
  541. package/dist/__tests__/render-feature-graph.integration.test.d.ts.map +0 -1
  542. package/dist/__tests__/render-feature-graphics-staging.unit.test.d.ts +0 -2
  543. package/dist/__tests__/render-feature-graphics-staging.unit.test.d.ts.map +0 -1
  544. package/dist/__tests__/render-feature-order.unit.test.d.ts +0 -2
  545. package/dist/__tests__/render-feature-order.unit.test.d.ts.map +0 -1
  546. package/dist/__tests__/render-feature-prepared-graphics-recording.unit.test.d.ts +0 -2
  547. package/dist/__tests__/render-feature-prepared-graphics-recording.unit.test.d.ts.map +0 -1
  548. package/dist/__tests__/render-feature-staging.unit.test.d.ts +0 -2
  549. package/dist/__tests__/render-feature-staging.unit.test.d.ts.map +0 -1
  550. package/dist/__tests__/renderer-render-scene-public.test-d.d.ts +0 -2
  551. package/dist/__tests__/renderer-render-scene-public.test-d.d.ts.map +0 -1
  552. package/dist/__tests__/scene-temporal-coverage.unit.test.d.ts +0 -2
  553. package/dist/__tests__/scene-temporal-coverage.unit.test.d.ts.map +0 -1
  554. package/dist/__tests__/sun-snapshot-consumers.test.d.ts +0 -2
  555. package/dist/__tests__/sun-snapshot-consumers.test.d.ts.map +0 -1
  556. package/dist/__tests__/surface-backend-kind-owner.test-d.d.ts +0 -2
  557. package/dist/__tests__/surface-backend-kind-owner.test-d.d.ts.map +0 -1
  558. package/dist/__tests__/taa-history-store.unit.test.d.ts +0 -2
  559. package/dist/__tests__/taa-history-store.unit.test.d.ts.map +0 -1
  560. package/dist/__tests__/temporal-frame-transaction.integration.test.d.ts +0 -2
  561. package/dist/__tests__/temporal-frame-transaction.integration.test.d.ts.map +0 -1
  562. package/dist/__tests__/temporal-inspection.unit.test.d.ts +0 -2
  563. package/dist/__tests__/temporal-inspection.unit.test.d.ts.map +0 -1
  564. package/dist/assets/__tests__/asset-decoders.unit.test.d.ts +0 -2
  565. package/dist/assets/__tests__/asset-decoders.unit.test.d.ts.map +0 -1
  566. package/dist/assets/__tests__/mipmap-generator.unit.test.d.ts +0 -2
  567. package/dist/assets/__tests__/mipmap-generator.unit.test.d.ts.map +0 -1
  568. package/dist/assets/__tests__/render-asset-port.unit.test.d.ts +0 -2
  569. package/dist/assets/__tests__/render-asset-port.unit.test.d.ts.map +0 -1
  570. package/dist/assets/__tests__/resolve-render-asset.unit.test.d.ts +0 -2
  571. package/dist/assets/__tests__/resolve-render-asset.unit.test.d.ts.map +0 -1
  572. package/dist/chunk-33UF5SAO.mjs +0 -7397
  573. package/dist/chunk-33UF5SAO.mjs.map +0 -1
  574. package/dist/chunk-A5QCJSNL.mjs +0 -29913
  575. package/dist/chunk-A5QCJSNL.mjs.map +0 -1
  576. package/dist/chunk-JMSB7AR4.mjs +0 -3
  577. package/dist/chunk-JMSB7AR4.mjs.map +0 -1
  578. package/dist/chunk-LXNGO6AO.mjs +0 -569
  579. package/dist/chunk-LXNGO6AO.mjs.map +0 -1
  580. package/dist/chunk-QRXPSX4X.mjs +0 -659
  581. package/dist/chunk-QRXPSX4X.mjs.map +0 -1
  582. package/dist/chunk-YAKEQPWO.mjs +0 -1439
  583. package/dist/chunk-YAKEQPWO.mjs.map +0 -1
  584. package/dist/components/__tests__/atmosphere-red.test.d.ts +0 -2
  585. package/dist/components/__tests__/atmosphere-red.test.d.ts.map +0 -1
  586. package/dist/components/__tests__/atmosphere.test.d.ts +0 -2
  587. package/dist/components/__tests__/atmosphere.test.d.ts.map +0 -1
  588. package/dist/components/__tests__/fog.test-d.d.ts +0 -2
  589. package/dist/components/__tests__/fog.test-d.d.ts.map +0 -1
  590. package/dist/components/__tests__/fog.test.d.ts +0 -2
  591. package/dist/components/__tests__/fog.test.d.ts.map +0 -1
  592. package/dist/components/atmosphere.d.ts +0 -18
  593. package/dist/components/atmosphere.d.ts.map +0 -1
  594. package/dist/components/environment.d.ts +0 -116
  595. package/dist/components/environment.d.ts.map +0 -1
  596. package/dist/deferred-lighting.d.ts +0 -13
  597. package/dist/deferred-lighting.d.ts.map +0 -1
  598. package/dist/dynamic-texture-store.d.ts +0 -42
  599. package/dist/dynamic-texture-store.d.ts.map +0 -1
  600. package/dist/environment/__tests__/failure-injection.test.d.ts +0 -2
  601. package/dist/environment/__tests__/failure-injection.test.d.ts.map +0 -1
  602. package/dist/environment/__tests__/generation-red.test.d.ts +0 -2
  603. package/dist/environment/__tests__/generation-red.test.d.ts.map +0 -1
  604. package/dist/environment/__tests__/generation.test.d.ts +0 -2
  605. package/dist/environment/__tests__/generation.test.d.ts.map +0 -1
  606. package/dist/environment/__tests__/graph-transaction.test.d.ts +0 -2
  607. package/dist/environment/__tests__/graph-transaction.test.d.ts.map +0 -1
  608. package/dist/environment/__tests__/inspection-red.test.d.ts +0 -2
  609. package/dist/environment/__tests__/inspection-red.test.d.ts.map +0 -1
  610. package/dist/environment/__tests__/lifecycle-evidence.test.d.ts +0 -2
  611. package/dist/environment/__tests__/lifecycle-evidence.test.d.ts.map +0 -1
  612. package/dist/environment/__tests__/pipeline-topology.test.d.ts +0 -2
  613. package/dist/environment/__tests__/pipeline-topology.test.d.ts.map +0 -1
  614. package/dist/environment/__tests__/readiness.test.d.ts +0 -2
  615. package/dist/environment/__tests__/readiness.test.d.ts.map +0 -1
  616. package/dist/environment/__tests__/recovery.test.d.ts +0 -2
  617. package/dist/environment/__tests__/recovery.test.d.ts.map +0 -1
  618. package/dist/environment/__tests__/resize-dispose.test.d.ts +0 -2
  619. package/dist/environment/__tests__/resize-dispose.test.d.ts.map +0 -1
  620. package/dist/environment/__tests__/signature-red.test.d.ts +0 -2
  621. package/dist/environment/__tests__/signature-red.test.d.ts.map +0 -1
  622. package/dist/environment/__tests__/signature.test.d.ts +0 -2
  623. package/dist/environment/__tests__/signature.test.d.ts.map +0 -1
  624. package/dist/environment/descriptors.d.ts +0 -2
  625. package/dist/environment/descriptors.d.ts.map +0 -1
  626. package/dist/environment/extracted-environment.d.ts +0 -53
  627. package/dist/environment/extracted-environment.d.ts.map +0 -1
  628. package/dist/environment/generation.d.ts +0 -62
  629. package/dist/environment/generation.d.ts.map +0 -1
  630. package/dist/environment/gpu-bundle.d.ts +0 -23
  631. package/dist/environment/gpu-bundle.d.ts.map +0 -1
  632. package/dist/environment/graph.d.ts +0 -108
  633. package/dist/environment/graph.d.ts.map +0 -1
  634. package/dist/environment/inspection.d.ts +0 -48
  635. package/dist/environment/inspection.d.ts.map +0 -1
  636. package/dist/environment/lifecycle.d.ts +0 -22
  637. package/dist/environment/lifecycle.d.ts.map +0 -1
  638. package/dist/environment/readiness.d.ts +0 -29
  639. package/dist/environment/readiness.d.ts.map +0 -1
  640. package/dist/environment/signature.d.ts +0 -70
  641. package/dist/environment/signature.d.ts.map +0 -1
  642. package/dist/extract/__tests__/directional-csm-domain.unit.test.d.ts +0 -2
  643. package/dist/extract/__tests__/directional-csm-domain.unit.test.d.ts.map +0 -1
  644. package/dist/extract/__tests__/environment-source.test.d.ts +0 -2
  645. package/dist/extract/__tests__/environment-source.test.d.ts.map +0 -1
  646. package/dist/extract/__tests__/schema-readers.unit.test.d.ts +0 -2
  647. package/dist/extract/__tests__/schema-readers.unit.test.d.ts.map +0 -1
  648. package/dist/extract/directional-csm.d.ts +0 -129
  649. package/dist/extract/directional-csm.d.ts.map +0 -1
  650. package/dist/extract/index.d.ts +0 -5
  651. package/dist/extract/index.d.ts.map +0 -1
  652. package/dist/extract/material-interface.d.ts +0 -56
  653. package/dist/extract/material-interface.d.ts.map +0 -1
  654. package/dist/extract/schema-readers.d.ts +0 -20
  655. package/dist/extract/schema-readers.d.ts.map +0 -1
  656. package/dist/features/graph-contribution.d.ts +0 -64
  657. package/dist/features/graph-contribution.d.ts.map +0 -1
  658. package/dist/features/index.d.ts +0 -21
  659. package/dist/features/index.d.ts.map +0 -1
  660. package/dist/features/morph/index.d.ts +0 -3
  661. package/dist/features/morph/index.d.ts.map +0 -1
  662. package/dist/features/morph/morph-bounds.d.ts +0 -42
  663. package/dist/features/morph/morph-bounds.d.ts.map +0 -1
  664. package/dist/features/scene-temporal.d.ts +0 -45
  665. package/dist/features/scene-temporal.d.ts.map +0 -1
  666. package/dist/features/taa-resolve.d.ts +0 -21
  667. package/dist/features/taa-resolve.d.ts.map +0 -1
  668. package/dist/frame-chain.d.ts +0 -14
  669. package/dist/frame-chain.d.ts.map +0 -1
  670. package/dist/gpu-driven/view-reference.d.ts.map +0 -1
  671. package/dist/gpu-resource-store.d.ts.map +0 -1
  672. package/dist/hdrp-cluster-membership.d.ts +0 -2
  673. package/dist/hdrp-cluster-membership.d.ts.map +0 -1
  674. package/dist/hdrp-pipeline.d.ts +0 -36
  675. package/dist/hdrp-pipeline.d.ts.map +0 -1
  676. package/dist/ibl/cubemap-projection.d.ts +0 -23
  677. package/dist/ibl/cubemap-projection.d.ts.map +0 -1
  678. package/dist/ibl/face-uniforms.d.ts +0 -65
  679. package/dist/ibl/face-uniforms.d.ts.map +0 -1
  680. package/dist/mesh-update-errors.d.ts +0 -71
  681. package/dist/mesh-update-errors.d.ts.map +0 -1
  682. package/dist/mipmap-generator.d.ts +0 -39
  683. package/dist/mipmap-generator.d.ts.map +0 -1
  684. package/dist/param-schema-projection-census.d.ts +0 -18
  685. package/dist/param-schema-projection-census.d.ts.map +0 -1
  686. package/dist/persistent-render-scene.d.ts +0 -158
  687. package/dist/persistent-render-scene.d.ts.map +0 -1
  688. package/dist/pipeline/index.d.ts +0 -11
  689. package/dist/pipeline/index.d.ts.map +0 -1
  690. package/dist/pipeline-errors.d.ts +0 -110
  691. package/dist/pipeline-errors.d.ts.map +0 -1
  692. package/dist/prepare/__tests__/schema-readers.unit.test.d.ts +0 -2
  693. package/dist/prepare/__tests__/schema-readers.unit.test.d.ts.map +0 -1
  694. package/dist/prepare/index.d.ts +0 -4
  695. package/dist/prepare/index.d.ts.map +0 -1
  696. package/dist/prepare/schema-readers.d.ts +0 -11
  697. package/dist/prepare/schema-readers.d.ts.map +0 -1
  698. package/dist/record/__tests__/environment-record.test.d.ts +0 -2
  699. package/dist/record/__tests__/environment-record.test.d.ts.map +0 -1
  700. package/dist/record/__tests__/frame-targets.unit.test.d.ts +0 -2
  701. package/dist/record/__tests__/frame-targets.unit.test.d.ts.map +0 -1
  702. package/dist/record/__tests__/membership-timing.unit.test.d.ts +0 -2
  703. package/dist/record/__tests__/membership-timing.unit.test.d.ts.map +0 -1
  704. package/dist/record/__tests__/render-submission.integration.test.d.ts +0 -2
  705. package/dist/record/__tests__/render-submission.integration.test.d.ts.map +0 -1
  706. package/dist/record/__tests__/render-submission.perf.test.d.ts +0 -2
  707. package/dist/record/__tests__/render-submission.perf.test.d.ts.map +0 -1
  708. package/dist/record/__tests__/shadow-submit-mode.unit.test.d.ts +0 -2
  709. package/dist/record/__tests__/shadow-submit-mode.unit.test.d.ts.map +0 -1
  710. package/dist/record/__tests__/view-ubo-layout.unit.test.d.ts +0 -2
  711. package/dist/record/__tests__/view-ubo-layout.unit.test.d.ts.map +0 -1
  712. package/dist/record/frame-observation.d.ts +0 -38
  713. package/dist/record/frame-observation.d.ts.map +0 -1
  714. package/dist/record/index.d.ts +0 -15
  715. package/dist/record/index.d.ts.map +0 -1
  716. package/dist/record/main-pass-skin.d.ts +0 -46
  717. package/dist/record/main-pass-skin.d.ts.map +0 -1
  718. package/dist/record/main-pass-sprite.d.ts +0 -69
  719. package/dist/record/main-pass-sprite.d.ts.map +0 -1
  720. package/dist/record/material-payload.d.ts +0 -43
  721. package/dist/record/material-payload.d.ts.map +0 -1
  722. package/dist/record/material-slot-plan.d.ts +0 -26
  723. package/dist/record/material-slot-plan.d.ts.map +0 -1
  724. package/dist/record/membership-timing.d.ts +0 -232
  725. package/dist/record/membership-timing.d.ts.map +0 -1
  726. package/dist/record/shadow-caster-uniform.d.ts +0 -8
  727. package/dist/record/shadow-caster-uniform.d.ts.map +0 -1
  728. package/dist/record/shadow-submit-mode.d.ts +0 -66
  729. package/dist/record/shadow-submit-mode.d.ts.map +0 -1
  730. package/dist/render-dispatch-membership.d.ts +0 -47
  731. package/dist/render-dispatch-membership.d.ts.map +0 -1
  732. package/dist/render-pipeline-context.d.ts +0 -289
  733. package/dist/render-pipeline-context.d.ts.map +0 -1
  734. package/dist/render-pipeline-target.d.ts +0 -16
  735. package/dist/render-pipeline-target.d.ts.map +0 -1
  736. package/dist/render-scene-projection.d.ts +0 -174
  737. package/dist/render-scene-projection.d.ts.map +0 -1
  738. package/dist/render-system-fold.d.ts +0 -266
  739. package/dist/render-system-fold.d.ts.map +0 -1
  740. package/dist/renderer/asset-service.d.ts +0 -10
  741. package/dist/renderer/asset-service.d.ts.map +0 -1
  742. package/dist/renderer/backend-selection.d.ts.map +0 -1
  743. package/dist/renderer/environment-classify.d.ts +0 -6
  744. package/dist/renderer/environment-classify.d.ts.map +0 -1
  745. package/dist/renderer/environment-error.d.ts +0 -13
  746. package/dist/renderer/environment-error.d.ts.map +0 -1
  747. package/dist/renderer/material/pipeline-projection.d.ts +0 -91
  748. package/dist/renderer/material/pipeline-projection.d.ts.map +0 -1
  749. package/dist/renderer/renderer-factory.d.ts +0 -283
  750. package/dist/renderer/renderer-factory.d.ts.map +0 -1
  751. package/dist/renderer.d.ts +0 -771
  752. package/dist/renderer.d.ts.map +0 -1
  753. package/dist/scene-utils/collect-subtree.d.ts +0 -11
  754. package/dist/scene-utils/collect-subtree.d.ts.map +0 -1
  755. package/dist/ssao-data.d.ts +0 -34
  756. package/dist/ssao-data.d.ts.map +0 -1
  757. package/dist/surface-format.d.ts +0 -10
  758. package/dist/surface-format.d.ts.map +0 -1
  759. package/dist/taa-history-store.d.ts +0 -88
  760. package/dist/taa-history-store.d.ts.map +0 -1
  761. package/dist/temporal-coverage.d.ts +0 -35
  762. package/dist/temporal-coverage.d.ts.map +0 -1
  763. package/dist/temporal-frame-transaction.d.ts +0 -92
  764. package/dist/temporal-frame-transaction.d.ts.map +0 -1
  765. package/dist/temporal-inspection.d.ts +0 -57
  766. package/dist/temporal-inspection.d.ts.map +0 -1
  767. package/dist/temporal-view.d.ts +0 -43
  768. package/dist/temporal-view.d.ts.map +0 -1
  769. package/dist/tilemap/resolve-tileset-runtime.d.ts +0 -23
  770. package/dist/tilemap/resolve-tileset-runtime.d.ts.map +0 -1
  771. package/dist/urp-pipeline.d.ts +0 -4
  772. package/dist/urp-pipeline.d.ts.map +0 -1
  773. package/src/__tests__/analytic-sky-contract.test.ts +0 -27
  774. package/src/__tests__/analytic-sky-falsify-carriers.mjs +0 -43
  775. package/src/__tests__/analytic-sky-falsify.test.ts +0 -94
  776. package/src/__tests__/assets-runtime-handoff.integration.test.ts +0 -36
  777. package/src/__tests__/backend-selection.integration.test.ts +0 -11
  778. package/src/__tests__/camera-temporal.test-d.ts +0 -8
  779. package/src/__tests__/camera-temporal.test.ts +0 -188
  780. package/src/__tests__/directional-shadow-probe-atlas-layout.unit.test.ts +0 -18
  781. package/src/__tests__/environment-inspection.test.ts +0 -45
  782. package/src/__tests__/fog-ai-user.fixture.ts +0 -350
  783. package/src/__tests__/fog-custom-render-feature.fixture.ts +0 -33
  784. package/src/__tests__/fog-custom-render-feature.integration.test.ts +0 -76
  785. package/src/__tests__/fog-inspection.integration.test.ts +0 -127
  786. package/src/__tests__/fog-owner-state.integration.test.ts +0 -112
  787. package/src/__tests__/fog-pipeline-topology.integration.test.ts +0 -93
  788. package/src/__tests__/fog-public-surface.integration.test.ts +0 -60
  789. package/src/__tests__/fog-ray-contract.integration.test.ts +0 -73
  790. package/src/__tests__/fog-source-absence.integration.test.ts +0 -51
  791. package/src/__tests__/fog-temporal.integration.test.ts +0 -115
  792. package/src/__tests__/frame-chain.unit.test.ts +0 -26
  793. package/src/__tests__/gpu-scene-field-type-owner.test-d.ts +0 -27
  794. package/src/__tests__/hdrp-pipeline.unit.test.ts +0 -100
  795. package/src/__tests__/ibl/ibl-fallback.unit.test.ts +0 -23
  796. package/src/__tests__/material-derived-error-stop-draw.integration.test.ts +0 -69
  797. package/src/__tests__/material-derived-payload.integration.test.ts +0 -164
  798. package/src/__tests__/materials.unit.test.ts +0 -25
  799. package/src/__tests__/param-schema-projection-census.unit.test.ts +0 -40
  800. package/src/__tests__/persistent-render-scene.unit.test.ts +0 -1311
  801. package/src/__tests__/pipeline-error-policy-owner.unit.test.ts +0 -167
  802. package/src/__tests__/pipeline-pass-trace.test.ts +0 -92
  803. package/src/__tests__/pipeline-stage-owner.test-d.ts +0 -13
  804. package/src/__tests__/plugin.test.ts +0 -25
  805. package/src/__tests__/prepared-graphics-backend-matrix.unit.test.ts +0 -129
  806. package/src/__tests__/prepared-graphics-resolver-recording.unit.test.ts +0 -180
  807. package/src/__tests__/public-pipeline-id.test-d.ts +0 -6
  808. package/src/__tests__/render-dispatch-membership.unit.test.ts +0 -117
  809. package/src/__tests__/render-feature-construction.unit.test.ts +0 -124
  810. package/src/__tests__/render-feature-error-code-owner.test-d.ts +0 -27
  811. package/src/__tests__/render-feature-gpu-buffer-usage-owner.test-d.ts +0 -46
  812. package/src/__tests__/render-feature-graph.integration.test.ts +0 -205
  813. package/src/__tests__/render-feature-graphics-staging.unit.test.ts +0 -200
  814. package/src/__tests__/render-feature-order.unit.test.ts +0 -66
  815. package/src/__tests__/render-feature-prepared-graphics-recording.unit.test.ts +0 -107
  816. package/src/__tests__/render-feature-staging.unit.test.ts +0 -94
  817. package/src/__tests__/renderer-render-scene-public.test-d.ts +0 -27
  818. package/src/__tests__/scene-temporal-coverage.unit.test.ts +0 -259
  819. package/src/__tests__/sun-snapshot-consumers.test.ts +0 -35
  820. package/src/__tests__/surface-backend-kind-owner.test-d.ts +0 -42
  821. package/src/__tests__/taa-history-store.unit.test.ts +0 -196
  822. package/src/__tests__/temporal-frame-transaction.integration.test.ts +0 -537
  823. package/src/__tests__/temporal-inspection.unit.test.ts +0 -138
  824. package/src/assets/__tests__/asset-decoders.unit.test.ts +0 -92
  825. package/src/assets/__tests__/mipmap-generator.unit.test.ts +0 -52
  826. package/src/assets/__tests__/render-asset-port.unit.test.ts +0 -54
  827. package/src/assets/__tests__/resolve-render-asset.unit.test.ts +0 -47
  828. package/src/components/__tests__/atmosphere-red.test.ts +0 -51
  829. package/src/components/__tests__/atmosphere.test.ts +0 -79
  830. package/src/components/__tests__/fog.test-d.ts +0 -49
  831. package/src/components/__tests__/fog.test.ts +0 -60
  832. package/src/components/atmosphere.ts +0 -64
  833. package/src/deferred-lighting.ts +0 -92
  834. package/src/dynamic-texture-store.ts +0 -111
  835. package/src/environment/README.md +0 -76
  836. package/src/environment/__tests__/failure-injection.test.ts +0 -50
  837. package/src/environment/__tests__/generation-red.test.ts +0 -64
  838. package/src/environment/__tests__/generation.test.ts +0 -37
  839. package/src/environment/__tests__/graph-transaction.test.ts +0 -85
  840. package/src/environment/__tests__/inspection-red.test.ts +0 -53
  841. package/src/environment/__tests__/lifecycle-evidence.test.ts +0 -40
  842. package/src/environment/__tests__/pipeline-topology.test.ts +0 -33
  843. package/src/environment/__tests__/readiness.test.ts +0 -42
  844. package/src/environment/__tests__/recovery.test.ts +0 -62
  845. package/src/environment/__tests__/resize-dispose.test.ts +0 -30
  846. package/src/environment/__tests__/signature-red.test.ts +0 -45
  847. package/src/environment/__tests__/signature.test.ts +0 -60
  848. package/src/environment/descriptors.ts +0 -7
  849. package/src/environment/extracted-environment.ts +0 -239
  850. package/src/environment/generation.ts +0 -158
  851. package/src/environment/gpu-bundle.ts +0 -144
  852. package/src/environment/graph.ts +0 -588
  853. package/src/environment/inspection.ts +0 -107
  854. package/src/environment/lifecycle.ts +0 -124
  855. package/src/environment/readiness.ts +0 -76
  856. package/src/environment/signature.ts +0 -185
  857. package/src/extract/__tests__/directional-csm-domain.unit.test.ts +0 -391
  858. package/src/extract/__tests__/environment-source.test.ts +0 -105
  859. package/src/extract/__tests__/schema-readers.unit.test.ts +0 -16
  860. package/src/extract/directional-csm.ts +0 -959
  861. package/src/extract/index.ts +0 -10
  862. package/src/extract/material-interface.ts +0 -604
  863. package/src/extract/schema-readers.ts +0 -27
  864. package/src/features/graph-contribution.ts +0 -577
  865. package/src/features/index.ts +0 -100
  866. package/src/features/morph/index.ts +0 -24
  867. package/src/features/morph/morph-bounds.ts +0 -123
  868. package/src/features/scene-temporal.ts +0 -274
  869. package/src/features/taa-resolve.ts +0 -244
  870. package/src/frame-chain.ts +0 -21
  871. package/src/hdrp-cluster-membership.ts +0 -70
  872. package/src/ibl/cubemap-projection.ts +0 -60
  873. package/src/ibl/face-uniforms.ts +0 -150
  874. package/src/mesh-update-errors.ts +0 -113
  875. package/src/mipmap-generator.ts +0 -244
  876. package/src/param-schema-projection-census.ts +0 -73
  877. package/src/persistent-render-scene.ts +0 -1752
  878. package/src/pipeline/index.ts +0 -40
  879. package/src/pipeline-errors.ts +0 -172
  880. package/src/prepare/__tests__/schema-readers.unit.test.ts +0 -16
  881. package/src/prepare/index.ts +0 -8
  882. package/src/prepare/schema-readers.ts +0 -20
  883. package/src/record/__tests__/environment-record.test.ts +0 -35
  884. package/src/record/__tests__/frame-targets.unit.test.ts +0 -54
  885. package/src/record/__tests__/membership-timing.unit.test.ts +0 -524
  886. package/src/record/__tests__/render-submission.integration.test.ts +0 -76
  887. package/src/record/__tests__/render-submission.perf.test.ts +0 -141
  888. package/src/record/__tests__/shadow-submit-mode.unit.test.ts +0 -88
  889. package/src/record/__tests__/view-ubo-layout.unit.test.ts +0 -101
  890. package/src/record/frame-observation.ts +0 -122
  891. package/src/record/index.ts +0 -15
  892. package/src/record/main-pass-skin.ts +0 -51
  893. package/src/record/main-pass-sprite.ts +0 -166
  894. package/src/record/material-payload.ts +0 -292
  895. package/src/record/material-slot-plan.ts +0 -68
  896. package/src/record/membership-timing.ts +0 -1012
  897. package/src/record/shadow-caster-uniform.ts +0 -37
  898. package/src/record/shadow-submit-mode.ts +0 -277
  899. package/src/render-dispatch-membership.ts +0 -155
  900. package/src/render-pipeline-context.ts +0 -332
  901. package/src/render-pipeline-target.ts +0 -96
  902. package/src/render-scene-projection.ts +0 -1738
  903. package/src/render-system-fold.ts +0 -531
  904. package/src/renderer/asset-service.ts +0 -32
  905. package/src/renderer/backend-selection.ts +0 -121
  906. package/src/renderer/environment-classify.ts +0 -30
  907. package/src/renderer/environment-error.ts +0 -19
  908. package/src/renderer/material/pipeline-projection.ts +0 -140
  909. package/src/renderer.ts +0 -940
  910. package/src/scene-utils/collect-subtree.ts +0 -40
  911. package/src/ssao-data.ts +0 -106
  912. package/src/surface-format.ts +0 -37
  913. package/src/taa-history-store.ts +0 -429
  914. package/src/temporal-coverage.ts +0 -106
  915. package/src/temporal-frame-transaction.ts +0 -301
  916. package/src/temporal-inspection.ts +0 -194
  917. package/src/temporal-view.ts +0 -174
  918. package/src/tilemap/resolve-tileset-runtime.ts +0 -72
@@ -1,19 +1,19 @@
1
- // IblPipelineCache.ts -- Per-device WeakMap pipeline cache for IBL precompute.
1
+ // IblPipelineCache.ts -- DeviceScope-generation cache for IBL precompute.
2
2
  //
3
3
  // Plan-strategy D-1/D-7: cache for 4 GPU passes (equirect->cube /
4
4
  // irradiance / prefilter / BRDF LUT). M2 provides the cache skeleton;
5
5
  // M3 (t18/t20) wires real shader math from ibl.wgsl.
6
6
  //
7
- // Structure mirrors mipmap-generator.ts per-device WeakMap pattern:
8
- // WeakMap<device, IblPipelineCachePerDevice>
7
+ // The cache is keyed by the renderer-owned DeviceScope generation. Raw device
8
+ // handles are inputs to pipeline creation, never cache or lifecycle owners.
9
9
  //
10
10
  // Public surface (M3):
11
- // - getOrCreateIblCache(device): get or initialize per-device cache
11
+ // - getOrCreateIblCache(scope): get or initialize the generation cache
12
12
  // - iblCacheSize(): introspection hook
13
- // - hasIblCache(device): introspection hook
13
+ // - hasIblCache(scope): introspection hook
14
14
  // - setIblWgslSource(source): set the ibl.wgsl WGSL source string
15
15
  // - createIblShaderModules(device, factory): create shader modules from ibl.wgsl
16
- // - createIblPipelines(device, factory, modules): create 4 render pipelines
16
+ // - createIblPipelines(scope, device, factory, modules): create 4 render pipelines
17
17
  // - runIblPrecompute(opts): execute 4 GPU precompute passes (M3 t20)
18
18
  //
19
19
  // M3 t20: pipeline slots are filled with real render pipelines loaded from
@@ -21,86 +21,111 @@
21
21
  // executed in the standard order (equirect->cube -> irradiance -> prefilter
22
22
  // -> BRDF LUT), with counters set post-execution per AC-04/05/06.
23
23
 
24
- // ─── Device shim shapes ──────────────────────────────────────────────────────
24
+ // ─── RHI-owned handles ───────────────────────────────────────────────────────
25
25
 
26
+ import {
27
+ type BindGroup,
28
+ type BindGroupLayout,
29
+ type Buffer,
30
+ type CommandBuffer,
31
+ err,
32
+ ok,
33
+ type RenderPipeline,
34
+ type Result,
35
+ type RhiCommandEncoder,
36
+ type RhiDevice,
37
+ type RhiError,
38
+ type RhiRenderPassEncoder,
39
+ type Sampler,
40
+ type ShaderModule,
41
+ type Texture,
42
+ type TextureFormat,
43
+ type TextureView,
44
+ } from '@forgeax/engine-rhi';
45
+ import type { DeviceScope } from '../device/device-scope';
26
46
  import { GPU_SHADER_STAGE_FRAGMENT, GPU_SHADER_STAGE_VERTEX } from '../gpu-stage';
27
47
  import {
28
48
  GPU_TEXTURE_USAGE_COPY_DST,
29
49
  GPU_TEXTURE_USAGE_COPY_SRC,
30
50
  GPU_TEXTURE_USAGE_RENDER_ATTACHMENT_AND_TEXTURE_BINDING,
31
51
  } from '../gpu-texture-usage';
32
- import { cubemapCaptureProjection } from './cubemap-projection';
33
52
 
34
53
  /**
35
54
  * Shader module factory (async, injected via configureGpuDevice).
36
55
  * Mirrors `MipmapShaderModuleFactory` from mipmap-generator.
37
56
  */
57
+ /**
58
+ * IBL is assembled by the renderer's device owner, so it consumes the full
59
+ * opaque RHI device rather than a structurally-compatible raw/shim split.
60
+ * Keeping the owner as RhiDevice makes the backend boundary explicit: raw
61
+ * GPU handles can only exist inside an RHI implementation or a test readback.
62
+ */
63
+ export type IblRhiOwner = RhiDevice;
64
+
38
65
  export type IblShaderModuleFactory = (
39
- device: object,
66
+ device: IblRhiOwner,
40
67
  desc: { code: string; label?: string },
41
- ) => Promise<{ ok: boolean; value?: unknown; error?: { code: string; message: string } }>;
68
+ ) => Promise<Result<ShaderModule, RhiError>>;
69
+
70
+ export interface IblPipelineSet {
71
+ readonly equirectToCubePipeline: RenderPipeline;
72
+ readonly irradiancePipeline: RenderPipeline;
73
+ readonly prefilterPipeline: RenderPipeline;
74
+ readonly brdfLutPipeline: RenderPipeline;
75
+ }
76
+
77
+ export interface IblPipelineError {
78
+ readonly code: 'ibl-pipeline-create-failed' | 'ibl-shader-module-missing';
79
+ readonly expected: string;
80
+ readonly hint: string;
81
+ readonly detail: { readonly stage: string; readonly rhiCode?: RhiError['code'] };
82
+ }
42
83
 
43
84
  /**
44
- * Per-device IBL pipeline cache instance.
85
+ * Per-DeviceScope-generation IBL pipeline cache instance.
45
86
  *
46
87
  * M3.5 (round-2 t52): the 4 pipeline slots are mutable so createIblPipelines
47
88
  * can fill them after construction. The 4 textures + their views are also
48
89
  * cached here so runIblPrecompute targets are stable across calls
49
90
  * (idempotent).
50
91
  */
51
- export interface IblPipelineCachePerDevice {
92
+ export interface IblPipelineCache {
52
93
  /** Color format shared by all precompute outputs for this device. */
53
- outputFormat?: string;
94
+ outputFormat?: TextureFormat;
54
95
  /** Equirectangular-to-cubemap pipeline. */
55
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU pipeline handle
56
- equirectToCubePipeline?: any;
96
+ equirectToCubePipeline?: RenderPipeline;
57
97
  /** Diffuse irradiance convolution pipeline. */
58
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU pipeline handle
59
- irradiancePipeline?: any;
98
+ irradiancePipeline?: RenderPipeline;
60
99
  /** Specular prefilter pipeline. */
61
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU pipeline handle
62
- prefilterPipeline?: any;
100
+ prefilterPipeline?: RenderPipeline;
63
101
  /** BRDF integration LUT pipeline. */
64
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU pipeline handle
65
- brdfLutPipeline?: any;
102
+ brdfLutPipeline?: RenderPipeline;
66
103
 
67
104
  /** Face uniforms BGL (shared across equirect/irradiance/prefilter, D-9). */
68
- // biome-ignore lint/suspicious/noExplicitAny: opaque BGL
69
- faceUniformsBgl?: any;
105
+ faceUniformsBgl?: BindGroupLayout;
70
106
  /** group(1) BGL for the equirect-to-cube pass (texture_2d + sampler). */
71
- // biome-ignore lint/suspicious/noExplicitAny: opaque BGL
72
- equirectGroup1Bgl?: any;
107
+ equirectGroup1Bgl?: BindGroupLayout;
73
108
  /** group(1) BGL for irradiance + prefilter (texture_cube + sampler). */
74
- // biome-ignore lint/suspicious/noExplicitAny: opaque BGL
75
- cubeGroup1Bgl?: any;
109
+ cubeGroup1Bgl?: BindGroupLayout;
76
110
  /** group(0) BGL for prefilter (face + prefilter uniforms). */
77
- // biome-ignore lint/suspicious/noExplicitAny: opaque BGL
78
- prefilterGroup0Bgl?: any;
111
+ prefilterGroup0Bgl?: BindGroupLayout;
79
112
 
80
113
  /** Irradiance cubemap texture (32x32; outputFormat, cube). */
81
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU texture
82
- irradianceTexture?: any;
114
+ irradianceTexture?: Texture;
83
115
  /** Irradiance cubemap view (dimension:cube). */
84
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU texture view
85
- irradianceView?: any;
116
+ irradianceView?: TextureView;
86
117
  /** Per-face 2D views for irradiance (render-attachment use). */
87
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU texture views
88
- irradianceFaceViews?: ReadonlyArray<any>;
118
+ irradianceFaceViews?: ReadonlyArray<TextureView>;
89
119
  /** Specular prefilter cubemap (128x128, 5 mip levels). */
90
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU texture
91
- prefilterTexture?: any;
120
+ prefilterTexture?: Texture;
92
121
  /** Prefilter cubemap view (dimension:cube, all mips). */
93
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU texture view
94
- prefilterView?: any;
122
+ prefilterView?: TextureView;
95
123
  /** Per-face 2D views per mip for prefilter (5 mips x 6 faces). */
96
- // biome-ignore lint/suspicious/noExplicitAny: nested mip x face views
97
- prefilterFaceViewsByMip?: ReadonlyArray<ReadonlyArray<any>>;
124
+ prefilterFaceViewsByMip?: ReadonlyArray<ReadonlyArray<TextureView>>;
98
125
  /** BRDF LUT (256x256; outputFormat). */
99
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU texture
100
- brdfLutTexture?: any;
126
+ brdfLutTexture?: Texture;
101
127
  /** BRDF LUT view. */
102
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU texture view
103
- brdfLutView?: any;
128
+ brdfLutView?: TextureView;
104
129
 
105
130
  /** Counter: times irradiance pass has executed. AC-04: == 1 after first cook. */
106
131
  irradianceBakeCount: number;
@@ -111,101 +136,41 @@ export interface IblPipelineCachePerDevice {
111
136
  }
112
137
 
113
138
  /**
114
- * Per-device cache map. The WeakMap key is the opaque device object;
115
- * destroying the device naturally clears its cache entry.
139
+ * Cache ownership follows the renderer's DeviceScope generation. A cache is
140
+ * never recovered by looking up an opaque device handle, so every pipeline and
141
+ * side texture is born under the same lifecycle owner as the rest of the
142
+ * renderer resources.
116
143
  */
117
- const deviceCache: WeakMap<object, IblPipelineCachePerDevice> = new WeakMap();
144
+ const scopeCaches: WeakMap<DeviceScope, IblPipelineCache> = new WeakMap();
118
145
 
119
146
  /**
120
- * Get or create the per-device IBL pipeline cache.
147
+ * Get or create the current-generation IBL pipeline cache.
121
148
  */
122
- export function getOrCreateIblCache(device: object): IblPipelineCachePerDevice {
123
- const existing = deviceCache.get(device);
149
+ export function getOrCreateIblCache(scope: DeviceScope): IblPipelineCache {
150
+ const existing = scopeCaches.get(scope);
124
151
  if (existing !== undefined) return existing;
125
152
 
126
- const cache: IblPipelineCachePerDevice = {
153
+ const cache: IblPipelineCache = {
127
154
  irradianceBakeCount: 0,
128
155
  prefilterBakeCount: 0,
129
156
  brdfLutBakeCount: 0,
130
157
  };
131
- deviceCache.set(device, cache);
158
+ scopeCaches.set(scope, cache);
132
159
  return cache;
133
160
  }
134
161
 
135
162
  /**
136
- * Number of cached per-device instances (introspection hook for tests).
137
- */
138
- export function iblCacheSize(): number {
139
- // WeakMap doesn't expose size; approximate by iteration.
140
- let count = 0;
141
- try {
142
- // biome-ignore lint/suspicious/noExplicitAny: WeakMap iteration hack
143
- for (const _ of deviceCache as any) {
144
- count++;
145
- }
146
- } catch {
147
- // WeakMap is not iterable; this is expected.
148
- }
149
- return count;
150
- }
151
-
152
- /**
153
- * Check whether a device has an active cache entry (introspection for tests).
154
- */
155
- export function hasIblCache(device: object): boolean {
156
- return deviceCache.has(device);
157
- }
158
-
159
- /**
160
- * Clear the per-device cache entry for the given device, if any.
161
- *
162
- * feat-20260612-rhi-destroy-renderer-dispose-gpu-lifecycle / M5: called from
163
- * `Renderer.dispose()` step 4 (plan-strategy D-2 6-step walk) so the IBL
164
- * pipelines / textures attached to a torn-down device do not survive in the
165
- * runtime cache. The underlying GPU pipeline / texture handles are not
166
- * separately destroyed here -- they were created on the same RhiDevice the
167
- * dispose chain is about to release at step 5 (`context.unconfigure`); the
168
- * spec contract is that releasing the device tears down its child pipelines
169
- * implicitly. Clearing the WeakMap entry simply lets GC reclaim the JS-side
170
- * cache record.
171
- *
172
- * Idempotent (architecture-principles §6): a second call after the entry
173
- * was deleted is a no-op.
174
- */
175
- export function clearIblCacheForDevice(device: object): void {
176
- deviceCache.delete(device);
177
- }
178
-
179
- // ─── IBL WGSL source management ──────────────────────────────────────────────
180
-
181
- let iblWgslSourceCache: string | undefined;
182
-
183
- /**
184
- * Set the ibl.wgsl source string. Called once by the consumer
185
- * (e.g., AssetRegistry) when the shader module source is loaded.
163
+ * Check whether a DeviceScope generation has an active cache entry.
186
164
  */
187
- export function setIblWgslSource(source: string): void {
188
- iblWgslSourceCache = source;
189
- }
190
-
191
- /**
192
- * Get the cached ibl.wgsl source string.
193
- * Throws if not yet loaded.
194
- */
195
- export function getIblWgslSource(): string {
196
- if (iblWgslSourceCache === undefined) {
197
- throw new Error(
198
- 'ibl.wgsl source not loaded -- call setIblWgslSource before using IBL pipelines',
199
- );
200
- }
201
- return iblWgslSourceCache;
165
+ export function hasIblCache(scope: DeviceScope): boolean {
166
+ return scopeCaches.has(scope);
202
167
  }
203
168
 
204
169
  // ─── M3.5 composed ibl-* shader source registry ─────────────────────────────
205
170
  //
206
171
  // 4 composed WGSL strings -- one per render pipeline. Each string is the
207
172
  // output of @forgeax/engine-naga composeShader after merging ibl_shared +
208
- // the per-pass module. Built by ShaderRegistry / vite-plugin-shader at
173
+ // the per-pass module. Built by ShaderCatalog / vite-plugin-shader at
209
174
  // build-time so the runtime cache never reaches into engine-naga
210
175
  // (AGENTS.md grep gate forbids).
211
176
 
@@ -225,22 +190,12 @@ let iblComposedShadersCache: IblComposedShaders | undefined;
225
190
  /**
226
191
  * Inject the composed ibl-* shader sources used by createIblPipelines.
227
192
  * Called once by the engine bootstrap (createRenderer step "shader-load")
228
- * with the 4 composed entries from ShaderRegistry.
193
+ * with the 4 composed entries from ShaderCatalog.
229
194
  */
230
195
  export function setIblComposedShaders(sources: IblComposedShaders): void {
231
196
  iblComposedShadersCache = sources;
232
197
  }
233
198
 
234
- /**
235
- * Retrieve the cached composed shader bundle.
236
- * Returns undefined when the runtime is operating without a real shader
237
- * source (mock device unit tests that exercise pipeline dispatch surface
238
- * only).
239
- */
240
- export function getIblComposedShaders(): IblComposedShaders | undefined {
241
- return iblComposedShadersCache;
242
- }
243
-
244
199
  // ─── Standard cube vertices for cubemap face rendering ───────────────────────
245
200
  // 36 vertices (6 faces * 2 triangles * 3 vertices), vec3<f32> format.
246
201
  // Unit cube [-1, 1]^3 centered at origin.
@@ -296,6 +251,18 @@ function buildCaptureViewProjs(): Float32Array[] {
296
251
  });
297
252
  }
298
253
 
254
+ function cubemapCaptureProjection(fovy: number, near: number, far: number): Float32Array {
255
+ const f = 1.0 / Math.tan(fovy / 2);
256
+ const nf = 1.0 / (near - far);
257
+ // biome-ignore format: manual column-major mat4
258
+ return new Float32Array([
259
+ f, 0, 0, 0,
260
+ 0, -f, 0, 0,
261
+ 0, 0, (far + near) * nf, -1,
262
+ 0, 0, 2 * far * near * nf, 0,
263
+ ]);
264
+ }
265
+
299
266
  function lookAtMatrix(
300
267
  eye: readonly number[],
301
268
  target: readonly number[],
@@ -379,43 +346,6 @@ export const PREFILTER_SIZE = 128;
379
346
  export const PREFILTER_MIP_LEVELS = 5;
380
347
  export const BRDF_LUT_SIZE = 256;
381
348
 
382
- /**
383
- * Minimal device shape used by createIblPipelines + runIblPrecompute. The
384
- * surface is intentionally narrow so unit-level mock devices can exercise
385
- * the dispatch path without standing up the full RHI shim.
386
- */
387
- export interface IblPipelineDevice {
388
- // biome-ignore lint/suspicious/noExplicitAny: shim shapes
389
- createBindGroupLayout(desc: any): { ok: true; value: any } | { ok: false; error: unknown };
390
- // biome-ignore lint/suspicious/noExplicitAny: shim shapes
391
- createPipelineLayout(desc: any): { ok: true; value: any } | { ok: false; error: unknown };
392
- // biome-ignore lint/suspicious/noExplicitAny: shim shapes
393
- createRenderPipeline(desc: any): { ok: true; value: any } | { ok: false; error: unknown };
394
- // biome-ignore lint/suspicious/noExplicitAny: shim shapes
395
- createBuffer(desc: any): { ok: true; value: any } | { ok: false; error: unknown };
396
- // biome-ignore lint/suspicious/noExplicitAny: shim shapes
397
- createTexture(desc: any): { ok: true; value: any } | { ok: false; error: unknown };
398
- createTextureView(
399
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU texture
400
- texture: any,
401
- // biome-ignore lint/suspicious/noExplicitAny: shim shapes
402
- desc: any,
403
- // biome-ignore lint/suspicious/noExplicitAny: shim shapes
404
- ): { ok: true; value: any } | { ok: false; error: unknown };
405
- // biome-ignore lint/suspicious/noExplicitAny: shim shapes
406
- createSampler(desc?: any): { ok: true; value: any } | { ok: false; error: unknown };
407
- // biome-ignore lint/suspicious/noExplicitAny: shim shapes
408
- createBindGroup(desc: any): { ok: true; value: any } | { ok: false; error: unknown };
409
- // biome-ignore lint/suspicious/noExplicitAny: shim shapes
410
- createCommandEncoder(desc?: any): { ok: true; value: any } | { ok: false; error: unknown };
411
- readonly queue: {
412
- // biome-ignore lint/suspicious/noExplicitAny: shim shapes
413
- submit(buffers: ReadonlyArray<any>): unknown;
414
- // biome-ignore lint/suspicious/noExplicitAny: shim shapes
415
- writeBuffer?: (...args: any[]) => unknown;
416
- };
417
- }
418
-
419
349
  /**
420
350
  * Create 4 independent GPURenderPipelines + their shared / per-pass bind
421
351
  * group layouts. Pipeline slots are stored on the per-device cache and
@@ -427,37 +357,24 @@ export interface IblPipelineDevice {
427
357
  * irradiance + prefilter, none for brdf-lut.
428
358
  */
429
359
  export async function createIblPipelines(
430
- device: IblPipelineDevice,
360
+ scope: DeviceScope,
361
+ device: IblRhiOwner,
431
362
  factory: IblShaderModuleFactory,
432
- // biome-ignore lint/suspicious/noExplicitAny: cubemap output format opaque
433
- cubeOutputFormat: any = 'rgba16float',
434
- ): Promise<
435
- | {
436
- ok: true;
437
- value: {
438
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU pipelines
439
- equirectToCubePipeline: any;
440
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU pipelines
441
- irradiancePipeline: any;
442
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU pipelines
443
- prefilterPipeline: any;
444
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU pipelines
445
- brdfLutPipeline: any;
446
- };
447
- }
448
- | { ok: false; error: unknown }
449
- > {
450
- const cache = getOrCreateIblCache(device);
451
- if (cache.equirectToCubePipeline !== undefined) {
452
- return {
453
- ok: true,
454
- value: {
455
- equirectToCubePipeline: cache.equirectToCubePipeline,
456
- irradiancePipeline: cache.irradiancePipeline,
457
- prefilterPipeline: cache.prefilterPipeline,
458
- brdfLutPipeline: cache.brdfLutPipeline,
459
- },
460
- };
363
+ cubeOutputFormat: TextureFormat = 'rgba16float',
364
+ ): Promise<Result<IblPipelineSet, RhiError | IblPipelineError>> {
365
+ const cache = getOrCreateIblCache(scope);
366
+ if (
367
+ cache.equirectToCubePipeline !== undefined &&
368
+ cache.irradiancePipeline !== undefined &&
369
+ cache.prefilterPipeline !== undefined &&
370
+ cache.brdfLutPipeline !== undefined
371
+ ) {
372
+ return ok({
373
+ equirectToCubePipeline: cache.equirectToCubePipeline,
374
+ irradiancePipeline: cache.irradiancePipeline,
375
+ prefilterPipeline: cache.prefilterPipeline,
376
+ brdfLutPipeline: cache.brdfLutPipeline,
377
+ });
461
378
  }
462
379
  // Keep the output format on the per-device cache so the four pipelines and
463
380
  // their lazily-created side textures cannot drift. WebGL2 may need the
@@ -476,16 +393,6 @@ export async function createIblPipelines(
476
393
  brdfLut: fallbackCode,
477
394
  };
478
395
 
479
- // M5-amend Bug 1: normalise shim/raw return shapes. See runIblPrecompute
480
- // for full rationale -- same helper applied across both functions so
481
- // dawn-node (raw GPUDevice) + browser (rhi-shim) both succeed.
482
- // biome-ignore lint/suspicious/noExplicitAny: union of shim/raw return shapes
483
- const unwrap = (r: any): any => {
484
- if (r === null || r === undefined) return undefined;
485
- if (typeof r === 'object' && 'ok' in r) return r.ok ? r.value : undefined;
486
- return r;
487
- };
488
-
489
396
  const modules = await Promise.all([
490
397
  factory(device, { code: src.equirectToCube, label: 'ibl-equirect-to-cube' }),
491
398
  factory(device, { code: src.irradiance, label: 'ibl-irradiance' }),
@@ -493,183 +400,175 @@ export async function createIblPipelines(
493
400
  factory(device, { code: src.brdfLut, label: 'ibl-brdf-lut' }),
494
401
  ]);
495
402
  for (const m of modules) {
496
- if (!m.ok) return { ok: false, error: m.error };
403
+ if (!m.ok) return err(m.error);
404
+ }
405
+ const shaderModules = modules.flatMap((module) => (module.ok ? [module.value] : []));
406
+ if (shaderModules.length !== 4) {
407
+ return err(iblPipelineError('shader-modules', 'ibl-shader-module-missing'));
408
+ }
409
+ const [mEq, mIr, mPr, mBr] = shaderModules;
410
+ if (mEq === undefined || mIr === undefined || mPr === undefined || mBr === undefined) {
411
+ return err(iblPipelineError('shader-modules', 'ibl-shader-module-missing'));
497
412
  }
498
- // biome-ignore lint/style/noNonNullAssertion: checked above
499
- const [mEq, mIr, mPr, mBr] = modules.map((m) => m.value!) as [unknown, unknown, unknown, unknown];
500
413
 
501
414
  // D-9: faceUniforms BGL shared across 3 pipelines (equirect / irradiance /
502
415
  // prefilter). The prefilter additionally needs binding(1) for prefUniforms;
503
416
  // we keep a separate BGL for the prefilter group(0) to honour the WGSL
504
417
  // declaration in ibl-prefilter.wgsl.
505
- const faceBgl = unwrap(
506
- device.createBindGroupLayout({
507
- label: 'ibl-face-uniforms-bgl',
508
- entries: [{ binding: 0, visibility: GPU_SHADER_STAGE_VERTEX, buffer: { type: 'uniform' } }],
509
- }),
510
- );
511
- if (faceBgl === undefined) return { ok: false, error: 'ibl-face-uniforms-bgl' };
512
- cache.faceUniformsBgl = faceBgl;
513
-
514
- const prefilterGroup0 = unwrap(
515
- device.createBindGroupLayout({
516
- label: 'ibl-prefilter-group0-bgl',
517
- entries: [
518
- { binding: 0, visibility: GPU_SHADER_STAGE_VERTEX, buffer: { type: 'uniform' } },
519
- { binding: 1, visibility: GPU_SHADER_STAGE_FRAGMENT, buffer: { type: 'uniform' } },
520
- ],
521
- }),
522
- );
523
- if (prefilterGroup0 === undefined) return { ok: false, error: 'ibl-prefilter-group0-bgl' };
524
- cache.prefilterGroup0Bgl = prefilterGroup0;
525
-
526
- const equirectGroup1 = unwrap(
527
- device.createBindGroupLayout({
528
- label: 'ibl-equirect-group1-bgl',
529
- entries: [
530
- {
531
- binding: 0,
532
- visibility: GPU_SHADER_STAGE_FRAGMENT,
533
- texture: { sampleType: 'float', viewDimension: '2d' },
534
- },
535
- {
536
- binding: 1,
537
- visibility: GPU_SHADER_STAGE_FRAGMENT,
538
- sampler: { type: 'filtering' },
539
- },
540
- ],
541
- }),
542
- );
543
- if (equirectGroup1 === undefined) return { ok: false, error: 'ibl-equirect-group1-bgl' };
544
- cache.equirectGroup1Bgl = equirectGroup1;
545
-
546
- const cubeGroup1 = unwrap(
547
- device.createBindGroupLayout({
548
- label: 'ibl-cube-group1-bgl',
549
- entries: [
550
- {
551
- binding: 0,
552
- visibility: GPU_SHADER_STAGE_FRAGMENT,
553
- texture: { sampleType: 'float', viewDimension: 'cube' },
554
- },
555
- {
556
- binding: 1,
557
- visibility: GPU_SHADER_STAGE_FRAGMENT,
558
- sampler: { type: 'filtering' },
559
- },
560
- ],
561
- }),
562
- );
563
- if (cubeGroup1 === undefined) return { ok: false, error: 'ibl-cube-group1-bgl' };
564
- cache.cubeGroup1Bgl = cubeGroup1;
418
+ const faceBgl = device.createBindGroupLayout({
419
+ label: 'ibl-face-uniforms-bgl',
420
+ entries: [{ binding: 0, visibility: GPU_SHADER_STAGE_VERTEX, buffer: { type: 'uniform' } }],
421
+ });
422
+ if (!faceBgl.ok) return err(faceBgl.error);
423
+ cache.faceUniformsBgl = faceBgl.value;
424
+
425
+ const prefilterGroup0 = device.createBindGroupLayout({
426
+ label: 'ibl-prefilter-group0-bgl',
427
+ entries: [
428
+ { binding: 0, visibility: GPU_SHADER_STAGE_VERTEX, buffer: { type: 'uniform' } },
429
+ { binding: 1, visibility: GPU_SHADER_STAGE_FRAGMENT, buffer: { type: 'uniform' } },
430
+ ],
431
+ });
432
+ if (!prefilterGroup0.ok) return err(prefilterGroup0.error);
433
+ cache.prefilterGroup0Bgl = prefilterGroup0.value;
434
+
435
+ const equirectGroup1 = device.createBindGroupLayout({
436
+ label: 'ibl-equirect-group1-bgl',
437
+ entries: [
438
+ {
439
+ binding: 0,
440
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
441
+ texture: { sampleType: 'float', viewDimension: '2d' },
442
+ },
443
+ {
444
+ binding: 1,
445
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
446
+ sampler: { type: 'filtering' },
447
+ },
448
+ ],
449
+ });
450
+ if (!equirectGroup1.ok) return err(equirectGroup1.error);
451
+ cache.equirectGroup1Bgl = equirectGroup1.value;
452
+
453
+ const cubeGroup1 = device.createBindGroupLayout({
454
+ label: 'ibl-cube-group1-bgl',
455
+ entries: [
456
+ {
457
+ binding: 0,
458
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
459
+ texture: { sampleType: 'float', viewDimension: 'cube' },
460
+ },
461
+ {
462
+ binding: 1,
463
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
464
+ sampler: { type: 'filtering' },
465
+ },
466
+ ],
467
+ });
468
+ if (!cubeGroup1.ok) return err(cubeGroup1.error);
469
+ cache.cubeGroup1Bgl = cubeGroup1.value;
565
470
 
566
471
  // Pipeline layouts.
567
- const equirectLayout = unwrap(
568
- device.createPipelineLayout({
569
- label: 'ibl-equirect-pipeline-layout',
570
- bindGroupLayouts: [cache.faceUniformsBgl, cache.equirectGroup1Bgl],
571
- }),
572
- );
573
- if (equirectLayout === undefined) return { ok: false, error: 'ibl-equirect-pipeline-layout' };
574
- const irradianceLayout = unwrap(
575
- device.createPipelineLayout({
576
- label: 'ibl-irradiance-pipeline-layout',
577
- bindGroupLayouts: [cache.faceUniformsBgl, cache.cubeGroup1Bgl],
578
- }),
579
- );
580
- if (irradianceLayout === undefined) return { ok: false, error: 'ibl-irradiance-pipeline-layout' };
581
- const prefilterLayout = unwrap(
582
- device.createPipelineLayout({
583
- label: 'ibl-prefilter-pipeline-layout',
584
- bindGroupLayouts: [prefilterGroup0, cache.cubeGroup1Bgl],
585
- }),
586
- );
587
- if (prefilterLayout === undefined) return { ok: false, error: 'ibl-prefilter-pipeline-layout' };
588
- const brdfLutLayout = unwrap(
589
- device.createPipelineLayout({
590
- label: 'ibl-brdf-lut-pipeline-layout',
591
- bindGroupLayouts: [],
592
- }),
593
- );
594
- if (brdfLutLayout === undefined) return { ok: false, error: 'ibl-brdf-lut-pipeline-layout' };
472
+ const equirectLayout = device.createPipelineLayout({
473
+ label: 'ibl-equirect-pipeline-layout',
474
+ bindGroupLayouts: [faceBgl.value, equirectGroup1.value],
475
+ });
476
+ if (!equirectLayout.ok) return err(equirectLayout.error);
477
+ const irradianceLayout = device.createPipelineLayout({
478
+ label: 'ibl-irradiance-pipeline-layout',
479
+ bindGroupLayouts: [faceBgl.value, cubeGroup1.value],
480
+ });
481
+ if (!irradianceLayout.ok) return err(irradianceLayout.error);
482
+ const prefilterLayout = device.createPipelineLayout({
483
+ label: 'ibl-prefilter-pipeline-layout',
484
+ bindGroupLayouts: [prefilterGroup0.value, cubeGroup1.value],
485
+ });
486
+ if (!prefilterLayout.ok) return err(prefilterLayout.error);
487
+ const brdfLutLayout = device.createPipelineLayout({
488
+ label: 'ibl-brdf-lut-pipeline-layout',
489
+ bindGroupLayouts: [],
490
+ });
491
+ if (!brdfLutLayout.ok) return err(brdfLutLayout.error);
595
492
 
596
493
  const vertexLayout3F = {
597
494
  arrayStride: 12,
598
495
  attributes: [{ shaderLocation: 0, offset: 0, format: 'float32x3' as const }],
599
496
  };
600
497
 
601
- const pipeEquirect = unwrap(
602
- device.createRenderPipeline({
603
- label: 'ibl-equirect-to-cube-pipeline',
604
- layout: equirectLayout,
605
- vertex: { module: mEq, entryPoint: 'cubemap_vs', buffers: [vertexLayout3F] },
606
- fragment: {
607
- module: mEq,
608
- entryPoint: 'equirectToCube_fs',
609
- targets: [{ format: cubeOutputFormat }],
610
- },
611
- primitive: { topology: 'triangle-list', cullMode: 'none' },
612
- }),
613
- );
614
- if (pipeEquirect === undefined) return { ok: false, error: 'ibl-equirect-to-cube-pipeline' };
615
- cache.equirectToCubePipeline = pipeEquirect;
616
-
617
- const pipeIrradiance = unwrap(
618
- device.createRenderPipeline({
619
- label: 'ibl-irradiance-pipeline',
620
- layout: irradianceLayout,
621
- vertex: { module: mIr, entryPoint: 'cubemap_vs', buffers: [vertexLayout3F] },
622
- fragment: {
623
- module: mIr,
624
- entryPoint: 'irradianceConvolve_fs',
625
- targets: [{ format: cubeOutputFormat }],
626
- },
627
- primitive: { topology: 'triangle-list', cullMode: 'none' },
628
- }),
629
- );
630
- if (pipeIrradiance === undefined) return { ok: false, error: 'ibl-irradiance-pipeline' };
631
- cache.irradiancePipeline = pipeIrradiance;
632
-
633
- const pipePrefilter = unwrap(
634
- device.createRenderPipeline({
635
- label: 'ibl-prefilter-pipeline',
636
- layout: prefilterLayout,
637
- vertex: { module: mPr, entryPoint: 'cubemap_vs', buffers: [vertexLayout3F] },
638
- fragment: {
639
- module: mPr,
640
- entryPoint: 'prefilterEnv_fs',
641
- targets: [{ format: cubeOutputFormat }],
642
- },
643
- primitive: { topology: 'triangle-list', cullMode: 'none' },
644
- }),
645
- );
646
- if (pipePrefilter === undefined) return { ok: false, error: 'ibl-prefilter-pipeline' };
647
- cache.prefilterPipeline = pipePrefilter;
648
-
649
- const pipeBrdfLut = unwrap(
650
- device.createRenderPipeline({
651
- label: 'ibl-brdf-lut-pipeline',
652
- layout: brdfLutLayout,
653
- vertex: { module: mBr, entryPoint: 'fullscreen_vs', buffers: [] },
654
- fragment: {
655
- module: mBr,
656
- entryPoint: 'brdfLutBake_fs',
657
- targets: [{ format: cubeOutputFormat }],
658
- },
659
- primitive: { topology: 'triangle-list', cullMode: 'none' },
660
- }),
661
- );
662
- if (pipeBrdfLut === undefined) return { ok: false, error: 'ibl-brdf-lut-pipeline' };
663
- cache.brdfLutPipeline = pipeBrdfLut;
498
+ const pipeEquirect = device.createRenderPipeline({
499
+ label: 'ibl-equirect-to-cube-pipeline',
500
+ layout: equirectLayout.value,
501
+ vertex: { module: mEq, entryPoint: 'cubemap_vs', buffers: [vertexLayout3F] },
502
+ fragment: {
503
+ module: mEq,
504
+ entryPoint: 'equirectToCube_fs',
505
+ targets: [{ format: cubeOutputFormat }],
506
+ },
507
+ primitive: { topology: 'triangle-list', cullMode: 'none' },
508
+ });
509
+ if (!pipeEquirect.ok) return err(pipeEquirect.error);
510
+ cache.equirectToCubePipeline = pipeEquirect.value;
511
+
512
+ const pipeIrradiance = device.createRenderPipeline({
513
+ label: 'ibl-irradiance-pipeline',
514
+ layout: irradianceLayout.value,
515
+ vertex: { module: mIr, entryPoint: 'cubemap_vs', buffers: [vertexLayout3F] },
516
+ fragment: {
517
+ module: mIr,
518
+ entryPoint: 'irradianceConvolve_fs',
519
+ targets: [{ format: cubeOutputFormat }],
520
+ },
521
+ primitive: { topology: 'triangle-list', cullMode: 'none' },
522
+ });
523
+ if (!pipeIrradiance.ok) return err(pipeIrradiance.error);
524
+ cache.irradiancePipeline = pipeIrradiance.value;
525
+
526
+ const pipePrefilter = device.createRenderPipeline({
527
+ label: 'ibl-prefilter-pipeline',
528
+ layout: prefilterLayout.value,
529
+ vertex: { module: mPr, entryPoint: 'cubemap_vs', buffers: [vertexLayout3F] },
530
+ fragment: {
531
+ module: mPr,
532
+ entryPoint: 'prefilterEnv_fs',
533
+ targets: [{ format: cubeOutputFormat }],
534
+ },
535
+ primitive: { topology: 'triangle-list', cullMode: 'none' },
536
+ });
537
+ if (!pipePrefilter.ok) return err(pipePrefilter.error);
538
+ cache.prefilterPipeline = pipePrefilter.value;
539
+
540
+ const pipeBrdfLut = device.createRenderPipeline({
541
+ label: 'ibl-brdf-lut-pipeline',
542
+ layout: brdfLutLayout.value,
543
+ vertex: { module: mBr, entryPoint: 'fullscreen_vs', buffers: [] },
544
+ fragment: {
545
+ module: mBr,
546
+ entryPoint: 'brdfLutBake_fs',
547
+ targets: [{ format: cubeOutputFormat }],
548
+ },
549
+ primitive: { topology: 'triangle-list', cullMode: 'none' },
550
+ });
551
+ if (!pipeBrdfLut.ok) return err(pipeBrdfLut.error);
552
+ cache.brdfLutPipeline = pipeBrdfLut.value;
553
+
554
+ return ok({
555
+ equirectToCubePipeline: pipeEquirect.value,
556
+ irradiancePipeline: pipeIrradiance.value,
557
+ prefilterPipeline: pipePrefilter.value,
558
+ brdfLutPipeline: pipeBrdfLut.value,
559
+ });
560
+ }
664
561
 
562
+ function iblPipelineError(
563
+ stage: string,
564
+ code: IblPipelineError['code'],
565
+ cause?: RhiError,
566
+ ): IblPipelineError {
665
567
  return {
666
- ok: true,
667
- value: {
668
- equirectToCubePipeline: cache.equirectToCubePipeline,
669
- irradiancePipeline: cache.irradiancePipeline,
670
- prefilterPipeline: cache.prefilterPipeline,
671
- brdfLutPipeline: cache.brdfLutPipeline,
672
- },
568
+ code,
569
+ expected: `${stage} completed through the RHI Result contract`,
570
+ hint: `inspect the ${stage} RHI error before retrying IBL pipeline creation`,
571
+ detail: { stage, ...(cause === undefined ? {} : { rhiCode: cause.code }) },
673
572
  };
674
573
  }
675
574
 
@@ -677,28 +576,28 @@ export async function createIblPipelines(
677
576
 
678
577
  /**
679
578
  * Options consumed by runIblPrecompute. The caller (the internal
680
- * GpuResourceStore equirect-to-cubemap projection) provides the equirect input
579
+ * GpuResidencyCache equirect-to-cubemap projection) provides the equirect input
681
580
  * + cubemap target GPU resources; the face-uniform / prefilter-uniform buffers
682
581
  * come from the t55 helpers.
683
582
  */
684
583
  export interface RunIblPrecomputeOptions {
685
- readonly device: IblPipelineDevice;
686
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU texture (input equirect)
687
- readonly equirectGpuTex: any;
688
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU texture view (input equirect 2D view)
689
- readonly equirectView: any;
690
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU texture (output cube)
691
- readonly cubeGpuTex: any;
692
- // biome-ignore lint/suspicious/noExplicitAny: opaque cube view (for sampling)
693
- readonly cubeView: any;
694
- // biome-ignore lint/suspicious/noExplicitAny: per-face 2D views (6) for render attachments
695
- readonly cubeFaceViews: ReadonlyArray<any>;
696
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU buffer (6 x 256-byte face uniforms)
697
- readonly faceUniformsBuffer: any;
698
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU buffer (30 x 256-byte prefilter uniforms)
699
- readonly prefilterUniformsBuffer: any;
700
- // biome-ignore lint/suspicious/noExplicitAny: opaque vertex buffer (36 cube verts)
701
- readonly cubeVertexBuffer: any;
584
+ readonly scope: DeviceScope;
585
+ readonly device: IblRhiOwner;
586
+ readonly equirectGpuTex: Texture;
587
+ readonly equirectView: TextureView;
588
+ readonly cubeGpuTex: Texture;
589
+ readonly cubeView: TextureView;
590
+ readonly cubeFaceViews: ReadonlyArray<TextureView>;
591
+ readonly faceUniformsBuffer: Buffer;
592
+ readonly prefilterUniformsBuffer: Buffer;
593
+ readonly cubeVertexBuffer: Buffer;
594
+ }
595
+
596
+ export interface IblPrecomputeError {
597
+ readonly code: 'ibl-precompute-not-dispatched';
598
+ readonly expected: string;
599
+ readonly hint: string;
600
+ readonly detail?: { readonly stage: string; readonly rhiCode?: RhiError['code'] };
702
601
  }
703
602
 
704
603
  /**
@@ -712,107 +611,28 @@ export interface RunIblPrecomputeOptions {
712
611
  * round-1 "counter += 1 as dispatch proxy" anti-pattern.
713
612
  *
714
613
  * Returns Result.err with code='ibl-precompute-not-dispatched' when the
715
- * underlying device lacks queue.submit or any of the 4 pipelines was not
614
+ * underlying device lacks queue.submit or one of the 4 pipelines was not
716
615
  * created (createIblPipelines must run first).
717
616
  */
718
617
  export function runIblPrecompute(
719
618
  opts: RunIblPrecomputeOptions,
720
- ):
721
- | { ok: true; value: { submitted: boolean } }
722
- | { ok: false; error: { code: string; expected: string; hint: string } } {
723
- const { device } = opts;
724
- const cache = getOrCreateIblCache(device);
619
+ ): Result<{ submitted: boolean }, IblPrecomputeError> {
620
+ const { device, scope } = opts;
621
+ const cache = getOrCreateIblCache(scope);
725
622
  const outputFormat = cache.outputFormat ?? 'rgba16float';
726
623
 
727
- // M5-amend Bug 1: support both rhi-shim path (Result<T, RhiError>) and raw
728
- // GPUDevice path (returns value directly). The shim returns
729
- // `{ok, value}`; raw devices return the GPU resource handle directly.
730
- // Same root cause + remedy as the mesh-upload raw-device fix at
731
- // uploadMeshById. Without this normalisation, every `device.createXxx(...)`
732
- // call inside this function bails on `!res.ok` (== !undefined == true)
733
- // when invoked from dawn-node / native bindings, silently skipping the
734
- // entire dispatch chain.
735
- // biome-ignore lint/suspicious/noExplicitAny: union of shim/raw return shapes
736
- const unwrap = (r: any): any => {
737
- if (r === null || r === undefined) return undefined;
738
- if (typeof r === 'object' && 'ok' in r) return r.ok ? r.value : undefined;
739
- return r;
740
- };
741
-
742
- // M5-amend Bug 1: detect raw GPUDevice vs rhi-shim. The shim's
743
- // `createBindGroup` accepts the forgeax tagged-union resource shape
744
- // (`{kind: 'buffer', value: {buffer, offset, size}}` etc.); raw
745
- // GPUDevice strictly requires WebGPU spec shape (`{buffer, offset,
746
- // size}` directly as `resource` for buffer bindings, raw view/sampler
747
- // handles directly for the other kinds). Probe by creating a no-op
748
- // empty BGL: shim wraps in `{ok, value}`; raw returns the BGL handle
749
- // directly. We discard the probe result; the cache already has BGLs.
750
- // biome-ignore lint/suspicious/noExplicitAny: probe call
751
- const probe: any = device.createBindGroupLayout({
752
- label: 'ibl-shape-probe',
753
- entries: [],
754
- });
755
- const isRawDevice =
756
- probe === null || probe === undefined || typeof probe !== 'object' || !('ok' in probe);
757
-
758
- // biome-ignore lint/suspicious/noExplicitAny: spec buffer-binding shape
759
- type SpecBgEntry = { binding: number; resource: any };
760
- // biome-ignore lint/suspicious/noExplicitAny: forgeax tagged-union resource
761
- const toSpecResource = (r: any): any => {
762
- if (r === null || r === undefined) return r;
763
- if (typeof r !== 'object' || !('kind' in r)) return r;
764
- if (r.kind === 'sampler') return r.value;
765
- if (r.kind === 'textureView') return r.value;
766
- if (r.kind === 'externalTexture') return r.value;
767
- if (r.kind === 'buffer') {
768
- const v = r.value;
769
- if (v !== null && typeof v === 'object' && 'buffer' in v) return v;
770
- // legacy shape -- shouldn't occur after Bug 1 fix but tolerate
771
- return { buffer: v };
772
- }
773
- return r;
774
- };
775
- // biome-ignore lint/suspicious/noExplicitAny: descriptor builder
776
- const buildBgDesc = (desc: any): any => {
777
- if (!isRawDevice) return desc;
778
- const entries: SpecBgEntry[] = (
779
- desc.entries as ReadonlyArray<{ binding: number; resource: unknown }>
780
- ).map((e) => ({
781
- binding: e.binding,
782
- resource: toSpecResource(e.resource),
783
- }));
784
- const out: { label?: string; layout: unknown; entries: SpecBgEntry[] } = {
785
- layout: desc.layout,
786
- entries,
787
- };
788
- if ('label' in desc && desc.label !== undefined) out.label = desc.label;
789
- return out;
790
- };
791
-
792
624
  if (
793
625
  cache.equirectToCubePipeline === undefined ||
794
626
  cache.irradiancePipeline === undefined ||
795
627
  cache.prefilterPipeline === undefined ||
796
628
  cache.brdfLutPipeline === undefined
797
629
  ) {
798
- return {
799
- ok: false,
800
- error: {
801
- code: 'ibl-precompute-not-dispatched',
802
- expected: '4 IBL pipelines created via createIblPipelines',
803
- hint: 'check IblPipelineCache.createIblPipelines was called before runIblPrecompute; counters must not increment before queue.submit',
804
- },
805
- };
806
- }
807
- if (typeof device.queue?.submit !== 'function') {
808
- return {
809
- ok: false,
810
- error: {
811
- code: 'ibl-precompute-not-dispatched',
812
- expected: 'device.queue.submit callable',
813
- hint: 'check IblPipelineCache.runIblPrecompute is called inside the GpuResourceStore equirect-to-cubemap projection; counters must not increment before queue.submit',
814
- },
815
- };
630
+ return err({
631
+ code: 'ibl-precompute-not-dispatched',
632
+ expected: '4 IBL pipelines created via createIblPipelines',
633
+ hint: 'check IblPipelineCache.createIblPipelines was called before runIblPrecompute; counters must not increment before queue.submit',
634
+ detail: { stage: 'pipeline-cache' },
635
+ });
816
636
  }
817
637
 
818
638
  // Allocate side textures (irradiance / prefilter / brdf-lut) lazily.
@@ -821,31 +641,8 @@ export function runIblPrecompute(
821
641
  // requires the TextureUsage::CopySrc bit on the source. Without it
822
642
  // Dawn fails-fast "usage doesn't include CopySrc".
823
643
 
824
- // M5-amend Bug 1: helper that normalises shim/raw texture-view creation.
825
- // Raw GPUDevice exposes `gpuTexture.createView(desc)` on the texture
826
- // object itself; the rhi-shim exposes `device.createTextureView(tex, desc)`
827
- // and returns Result<T>.
828
- // biome-ignore lint/suspicious/noExplicitAny: shim/raw device split
829
- const makeView = (texture: any, desc: any): any => {
830
- // biome-ignore lint/suspicious/noExplicitAny: device shim shape
831
- const dev = device as any;
832
- if (typeof dev.createTextureView === 'function') {
833
- const r = dev.createTextureView(texture, desc);
834
- const u = unwrap(r);
835
- if (u !== undefined) return u;
836
- }
837
- if (texture !== null && texture !== undefined && typeof texture.createView === 'function') {
838
- try {
839
- return texture.createView(desc);
840
- } catch {
841
- return undefined;
842
- }
843
- }
844
- return undefined;
845
- };
846
-
847
644
  if (cache.irradianceTexture === undefined) {
848
- const tRaw = device.createTexture({
645
+ const textureResult = device.createTexture({
849
646
  label: 'ibl-irradiance-cube',
850
647
  size: { width: IRRADIANCE_SIZE, height: IRRADIANCE_SIZE, depthOrArrayLayers: 6 },
851
648
  mipLevelCount: 1,
@@ -857,34 +654,33 @@ export function runIblPrecompute(
857
654
  GPU_TEXTURE_USAGE_COPY_DST |
858
655
  GPU_TEXTURE_USAGE_COPY_SRC,
859
656
  viewFormats: [],
657
+ textureBindingViewDimension: undefined,
860
658
  });
861
- const tVal = unwrap(tRaw);
862
- if (tVal === undefined) return { ok: false, error: badAlloc('irradiance-texture') };
863
- cache.irradianceTexture = tVal;
864
- const cubeView = makeView(tVal, {
659
+ if (!textureResult.ok) return err(badAlloc('irradiance-texture', textureResult.error));
660
+ cache.irradianceTexture = textureResult.value;
661
+ const cubeViewResult = device.createTextureView(textureResult.value, {
865
662
  label: 'ibl-irradiance-cube-view',
866
663
  dimension: 'cube',
867
664
  arrayLayerCount: 6,
868
665
  });
869
- if (cubeView === undefined) return { ok: false, error: badAlloc('irradiance-view') };
870
- cache.irradianceView = cubeView;
871
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU views
872
- const faceViews: any[] = [];
666
+ if (!cubeViewResult.ok) return err(badAlloc('irradiance-view', cubeViewResult.error));
667
+ cache.irradianceView = cubeViewResult.value;
668
+ const faceViews: TextureView[] = [];
873
669
  for (let f = 0; f < 6; f++) {
874
- const v = makeView(tVal, {
670
+ const viewResult = device.createTextureView(textureResult.value, {
875
671
  label: `ibl-irradiance-face-${f}`,
876
672
  dimension: '2d',
877
673
  baseArrayLayer: f,
878
674
  arrayLayerCount: 1,
879
675
  });
880
- if (v === undefined) return { ok: false, error: badAlloc('irradiance-face-view') };
881
- faceViews.push(v);
676
+ if (!viewResult.ok) return err(badAlloc('irradiance-face-view', viewResult.error));
677
+ faceViews.push(viewResult.value);
882
678
  }
883
679
  cache.irradianceFaceViews = faceViews;
884
680
  }
885
681
 
886
682
  if (cache.prefilterTexture === undefined) {
887
- const tRaw = device.createTexture({
683
+ const textureResult = device.createTexture({
888
684
  label: 'ibl-prefilter-cube',
889
685
  size: { width: PREFILTER_SIZE, height: PREFILTER_SIZE, depthOrArrayLayers: 6 },
890
686
  mipLevelCount: PREFILTER_MIP_LEVELS,
@@ -896,26 +692,24 @@ export function runIblPrecompute(
896
692
  GPU_TEXTURE_USAGE_COPY_DST |
897
693
  GPU_TEXTURE_USAGE_COPY_SRC,
898
694
  viewFormats: [],
695
+ textureBindingViewDimension: undefined,
899
696
  });
900
- const tVal = unwrap(tRaw);
901
- if (tVal === undefined) return { ok: false, error: badAlloc('prefilter-texture') };
902
- cache.prefilterTexture = tVal;
903
- const cubeView = makeView(tVal, {
697
+ if (!textureResult.ok) return err(badAlloc('prefilter-texture', textureResult.error));
698
+ cache.prefilterTexture = textureResult.value;
699
+ const cubeViewResult = device.createTextureView(textureResult.value, {
904
700
  label: 'ibl-prefilter-cube-view',
905
701
  dimension: 'cube',
906
702
  arrayLayerCount: 6,
907
703
  baseMipLevel: 0,
908
704
  mipLevelCount: PREFILTER_MIP_LEVELS,
909
705
  });
910
- if (cubeView === undefined) return { ok: false, error: badAlloc('prefilter-view') };
911
- cache.prefilterView = cubeView;
912
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU views
913
- const mipViews: any[][] = [];
706
+ if (!cubeViewResult.ok) return err(badAlloc('prefilter-view', cubeViewResult.error));
707
+ cache.prefilterView = cubeViewResult.value;
708
+ const mipViews: TextureView[][] = [];
914
709
  for (let m = 0; m < PREFILTER_MIP_LEVELS; m++) {
915
- // biome-ignore lint/suspicious/noExplicitAny: opaque GPU views
916
- const faces: any[] = [];
710
+ const faces: TextureView[] = [];
917
711
  for (let f = 0; f < 6; f++) {
918
- const v = makeView(tVal, {
712
+ const viewResult = device.createTextureView(textureResult.value, {
919
713
  label: `ibl-prefilter-mip${m}-face${f}`,
920
714
  dimension: '2d',
921
715
  baseMipLevel: m,
@@ -923,8 +717,8 @@ export function runIblPrecompute(
923
717
  baseArrayLayer: f,
924
718
  arrayLayerCount: 1,
925
719
  });
926
- if (v === undefined) return { ok: false, error: badAlloc('prefilter-face-view') };
927
- faces.push(v);
720
+ if (!viewResult.ok) return err(badAlloc('prefilter-face-view', viewResult.error));
721
+ faces.push(viewResult.value);
928
722
  }
929
723
  mipViews.push(faces);
930
724
  }
@@ -932,7 +726,7 @@ export function runIblPrecompute(
932
726
  }
933
727
 
934
728
  if (cache.brdfLutTexture === undefined) {
935
- const tRaw = device.createTexture({
729
+ const textureResult = device.createTexture({
936
730
  label: 'ibl-brdf-lut',
937
731
  size: { width: BRDF_LUT_SIZE, height: BRDF_LUT_SIZE, depthOrArrayLayers: 1 },
938
732
  mipLevelCount: 1,
@@ -944,22 +738,22 @@ export function runIblPrecompute(
944
738
  GPU_TEXTURE_USAGE_COPY_DST |
945
739
  GPU_TEXTURE_USAGE_COPY_SRC,
946
740
  viewFormats: [],
741
+ textureBindingViewDimension: undefined,
947
742
  });
948
- const tVal = unwrap(tRaw);
949
- if (tVal === undefined) return { ok: false, error: badAlloc('brdf-lut-texture') };
950
- cache.brdfLutTexture = tVal;
951
- const v = makeView(tVal, {
743
+ if (!textureResult.ok) return err(badAlloc('brdf-lut-texture', textureResult.error));
744
+ cache.brdfLutTexture = textureResult.value;
745
+ const viewResult = device.createTextureView(textureResult.value, {
952
746
  label: 'ibl-brdf-lut-view',
953
747
  dimension: '2d',
954
748
  });
955
- if (v === undefined) return { ok: false, error: badAlloc('brdf-lut-view') };
956
- cache.brdfLutView = v;
749
+ if (!viewResult.ok) return err(badAlloc('brdf-lut-view', viewResult.error));
750
+ cache.brdfLutView = viewResult.value;
957
751
  }
958
752
 
959
753
  // Shared sampler (filtering, linear-linear).
960
754
  // U=repeat because equirect wraps horizontally (atan2 seam at ±π);
961
755
  // V=clamp because equirect poles are clamped vertically.
962
- const samplerRaw = device.createSampler({
756
+ const samplerResult = device.createSampler({
963
757
  label: 'ibl-precompute-sampler',
964
758
  magFilter: 'linear',
965
759
  minFilter: 'linear',
@@ -968,51 +762,74 @@ export function runIblPrecompute(
968
762
  addressModeV: 'clamp-to-edge',
969
763
  addressModeW: 'clamp-to-edge',
970
764
  });
971
- const sampler = unwrap(samplerRaw);
972
- if (sampler === undefined) return { ok: false, error: badAlloc('sampler') };
973
-
974
- const encoderRaw = device.createCommandEncoder({ label: 'ibl-precompute-encoder' });
975
- const encoder = unwrap(encoderRaw);
976
- if (encoder === undefined) return { ok: false, error: badAlloc('encoder') };
765
+ if (!samplerResult.ok) return err(badAlloc('sampler', samplerResult.error));
766
+ const sampler: Sampler = samplerResult.value;
767
+
768
+ const encoderResult = device.createCommandEncoder({ label: 'ibl-precompute-encoder' });
769
+ if (!encoderResult.ok) return err(badAlloc('encoder', encoderResult.error));
770
+ const encoder: RhiCommandEncoder = encoderResult.value;
771
+
772
+ const faceUniformsBgl = cache.faceUniformsBgl;
773
+ const equirectGroup1Bgl = cache.equirectGroup1Bgl;
774
+ const cubeGroup1Bgl = cache.cubeGroup1Bgl;
775
+ const prefilterGroup0Bgl = cache.prefilterGroup0Bgl;
776
+ const equirectPipeline = cache.equirectToCubePipeline;
777
+ const irradiancePipeline = cache.irradiancePipeline;
778
+ const prefilterPipeline = cache.prefilterPipeline;
779
+ const brdfLutPipeline = cache.brdfLutPipeline;
780
+ const irrFaceViews = cache.irradianceFaceViews;
781
+ const prefMipViews = cache.prefilterFaceViewsByMip;
782
+ const brdfLutView = cache.brdfLutView;
783
+ if (
784
+ faceUniformsBgl === undefined ||
785
+ equirectGroup1Bgl === undefined ||
786
+ cubeGroup1Bgl === undefined ||
787
+ prefilterGroup0Bgl === undefined ||
788
+ equirectPipeline === undefined ||
789
+ irradiancePipeline === undefined ||
790
+ prefilterPipeline === undefined ||
791
+ brdfLutPipeline === undefined ||
792
+ irrFaceViews === undefined ||
793
+ prefMipViews === undefined ||
794
+ brdfLutView === undefined
795
+ ) {
796
+ return err(badAlloc('ibl-cache-resources'));
797
+ }
977
798
 
978
799
  // Bind group: equirect group(1).
979
- const equirectBg = unwrap(
980
- device.createBindGroup(
981
- buildBgDesc({
982
- label: 'ibl-equirect-bg',
983
- layout: cache.equirectGroup1Bgl,
984
- entries: [
985
- { binding: 0, resource: { kind: 'textureView', value: opts.equirectView } },
986
- { binding: 1, resource: { kind: 'sampler', value: sampler } },
987
- ],
988
- }),
989
- ),
990
- );
991
- if (equirectBg === undefined) return { ok: false, error: badAlloc('equirect-bg') };
800
+ const equirectBgResult = device.createBindGroup({
801
+ label: 'ibl-equirect-bg',
802
+ layout: equirectGroup1Bgl,
803
+ entries: [
804
+ { binding: 0, resource: { kind: 'textureView', value: opts.equirectView } },
805
+ { binding: 1, resource: { kind: 'sampler', value: sampler } },
806
+ ],
807
+ });
808
+ if (!equirectBgResult.ok) return err(badAlloc('equirect-bg', equirectBgResult.error));
809
+ const equirectBg: BindGroup = equirectBgResult.value;
992
810
 
993
811
  // Bind group: cube group(1) for irradiance + prefilter.
994
- const cubeBg = unwrap(
995
- device.createBindGroup(
996
- buildBgDesc({
997
- label: 'ibl-cube-bg',
998
- layout: cache.cubeGroup1Bgl,
999
- entries: [
1000
- { binding: 0, resource: { kind: 'textureView', value: opts.cubeView } },
1001
- { binding: 1, resource: { kind: 'sampler', value: sampler } },
1002
- ],
1003
- }),
1004
- ),
1005
- );
1006
- if (cubeBg === undefined) return { ok: false, error: badAlloc('cube-bg') };
812
+ const cubeBgResult = device.createBindGroup({
813
+ label: 'ibl-cube-bg',
814
+ layout: cubeGroup1Bgl,
815
+ entries: [
816
+ { binding: 0, resource: { kind: 'textureView', value: opts.cubeView } },
817
+ { binding: 1, resource: { kind: 'sampler', value: sampler } },
818
+ ],
819
+ });
820
+ if (!cubeBgResult.ok) return err(badAlloc('cube-bg', cubeBgResult.error));
821
+ const cubeBg: BindGroup = cubeBgResult.value;
1007
822
 
1008
823
  // (a) equirect-to-cube: 6 face draws.
1009
824
  const cubeFaceViews = opts.cubeFaceViews;
1010
825
  for (let face = 0; face < 6; face++) {
1011
- const pass = encoder.beginRenderPass({
826
+ const cubeFaceView = cubeFaceViews[face];
827
+ if (cubeFaceView === undefined) return err(badAlloc('cube-face-view'));
828
+ const pass: RhiRenderPassEncoder = encoder.beginRenderPass({
1012
829
  label: 'ibl-equirect-to-cube',
1013
830
  colorAttachments: [
1014
831
  {
1015
- view: cubeFaceViews[face],
832
+ view: cubeFaceView,
1016
833
  clearValue: { r: 0, g: 0, b: 0, a: 1 },
1017
834
  loadOp: 'clear',
1018
835
  storeOp: 'store',
@@ -1020,30 +837,26 @@ export function runIblPrecompute(
1020
837
  ],
1021
838
  });
1022
839
  // Face uniform: dynamic offset = face * 256.
1023
- const faceBg = unwrap(
1024
- device.createBindGroup(
1025
- buildBgDesc({
1026
- label: `ibl-face-bg-${face}`,
1027
- layout: cache.faceUniformsBgl,
1028
- entries: [
1029
- {
1030
- binding: 0,
1031
- resource: {
1032
- kind: 'buffer',
1033
- value: {
1034
- buffer: opts.faceUniformsBuffer,
1035
- offset: face * 256,
1036
- size: 64,
1037
- },
1038
- },
840
+ const faceBgResult = device.createBindGroup({
841
+ label: `ibl-face-bg-${face}`,
842
+ layout: faceUniformsBgl,
843
+ entries: [
844
+ {
845
+ binding: 0,
846
+ resource: {
847
+ kind: 'buffer',
848
+ value: {
849
+ buffer: opts.faceUniformsBuffer,
850
+ offset: face * 256,
851
+ size: 64,
1039
852
  },
1040
- ],
1041
- }),
1042
- ),
1043
- );
1044
- if (faceBg === undefined) return { ok: false, error: badAlloc('face-bg') };
1045
- pass.setPipeline(cache.equirectToCubePipeline);
1046
- pass.setBindGroup(0, faceBg);
853
+ },
854
+ },
855
+ ],
856
+ });
857
+ if (!faceBgResult.ok) return err(badAlloc('face-bg', faceBgResult.error));
858
+ pass.setPipeline(equirectPipeline);
859
+ pass.setBindGroup(0, faceBgResult.value);
1047
860
  pass.setBindGroup(1, equirectBg);
1048
861
  pass.setVertexBuffer(0, opts.cubeVertexBuffer);
1049
862
  pass.draw(6, 1, face * 6, 0);
@@ -1051,43 +864,40 @@ export function runIblPrecompute(
1051
864
  }
1052
865
 
1053
866
  // (b) irradiance convolve: 6 face draws.
1054
- const irrFaceViews = cache.irradianceFaceViews ?? [];
1055
867
  for (let face = 0; face < 6; face++) {
1056
- const pass = encoder.beginRenderPass({
868
+ const irrFaceView = irrFaceViews[face];
869
+ if (irrFaceView === undefined) return err(badAlloc('irradiance-face-view'));
870
+ const pass: RhiRenderPassEncoder = encoder.beginRenderPass({
1057
871
  label: 'ibl-irradiance',
1058
872
  colorAttachments: [
1059
873
  {
1060
- view: irrFaceViews[face],
874
+ view: irrFaceView,
1061
875
  clearValue: { r: 0, g: 0, b: 0, a: 1 },
1062
876
  loadOp: 'clear',
1063
877
  storeOp: 'store',
1064
878
  },
1065
879
  ],
1066
880
  });
1067
- const faceBg = unwrap(
1068
- device.createBindGroup(
1069
- buildBgDesc({
1070
- label: `ibl-irr-face-bg-${face}`,
1071
- layout: cache.faceUniformsBgl,
1072
- entries: [
1073
- {
1074
- binding: 0,
1075
- resource: {
1076
- kind: 'buffer',
1077
- value: {
1078
- buffer: opts.faceUniformsBuffer,
1079
- offset: face * 256,
1080
- size: 64,
1081
- },
1082
- },
881
+ const faceBgResult = device.createBindGroup({
882
+ label: `ibl-irr-face-bg-${face}`,
883
+ layout: faceUniformsBgl,
884
+ entries: [
885
+ {
886
+ binding: 0,
887
+ resource: {
888
+ kind: 'buffer',
889
+ value: {
890
+ buffer: opts.faceUniformsBuffer,
891
+ offset: face * 256,
892
+ size: 64,
1083
893
  },
1084
- ],
1085
- }),
1086
- ),
1087
- );
1088
- if (faceBg === undefined) return { ok: false, error: badAlloc('irr-face-bg') };
1089
- pass.setPipeline(cache.irradiancePipeline);
1090
- pass.setBindGroup(0, faceBg);
894
+ },
895
+ },
896
+ ],
897
+ });
898
+ if (!faceBgResult.ok) return err(badAlloc('irr-face-bg', faceBgResult.error));
899
+ pass.setPipeline(irradiancePipeline);
900
+ pass.setBindGroup(0, faceBgResult.value);
1091
901
  pass.setBindGroup(1, cubeBg);
1092
902
  pass.setVertexBuffer(0, opts.cubeVertexBuffer);
1093
903
  pass.draw(6, 1, face * 6, 0);
@@ -1095,57 +905,55 @@ export function runIblPrecompute(
1095
905
  }
1096
906
 
1097
907
  // (c) prefilter env: 5 mips x 6 faces = 30 sub-passes.
1098
- const prefMipViews = cache.prefilterFaceViewsByMip ?? [];
1099
908
  for (let mip = 0; mip < PREFILTER_MIP_LEVELS; mip++) {
1100
- const mipFaceViews = prefMipViews[mip] ?? [];
909
+ const mipFaceViews = prefMipViews[mip];
910
+ if (mipFaceViews === undefined) return err(badAlloc('prefilter-mip-views'));
1101
911
  for (let face = 0; face < 6; face++) {
1102
912
  const subIdx = mip * 6 + face;
1103
- const pass = encoder.beginRenderPass({
913
+ const mipFaceView = mipFaceViews[face];
914
+ if (mipFaceView === undefined) return err(badAlloc('prefilter-face-view'));
915
+ const pass: RhiRenderPassEncoder = encoder.beginRenderPass({
1104
916
  label: 'ibl-prefilter',
1105
917
  colorAttachments: [
1106
918
  {
1107
- view: mipFaceViews[face],
919
+ view: mipFaceView,
1108
920
  clearValue: { r: 0, g: 0, b: 0, a: 1 },
1109
921
  loadOp: 'clear',
1110
922
  storeOp: 'store',
1111
923
  },
1112
924
  ],
1113
925
  });
1114
- const bg = unwrap(
1115
- device.createBindGroup(
1116
- buildBgDesc({
1117
- label: `ibl-pref-bg-${subIdx}`,
1118
- layout: prefilterGroup0LayoutOf(cache),
1119
- entries: [
1120
- {
1121
- binding: 0,
1122
- resource: {
1123
- kind: 'buffer',
1124
- value: {
1125
- buffer: opts.faceUniformsBuffer,
1126
- offset: face * 256,
1127
- size: 64,
1128
- },
1129
- },
926
+ const bgResult = device.createBindGroup({
927
+ label: `ibl-pref-bg-${subIdx}`,
928
+ layout: prefilterGroup0Bgl,
929
+ entries: [
930
+ {
931
+ binding: 0,
932
+ resource: {
933
+ kind: 'buffer',
934
+ value: {
935
+ buffer: opts.faceUniformsBuffer,
936
+ offset: face * 256,
937
+ size: 64,
1130
938
  },
1131
- {
1132
- binding: 1,
1133
- resource: {
1134
- kind: 'buffer',
1135
- value: {
1136
- buffer: opts.prefilterUniformsBuffer,
1137
- offset: subIdx * 256,
1138
- size: 16,
1139
- },
1140
- },
939
+ },
940
+ },
941
+ {
942
+ binding: 1,
943
+ resource: {
944
+ kind: 'buffer',
945
+ value: {
946
+ buffer: opts.prefilterUniformsBuffer,
947
+ offset: subIdx * 256,
948
+ size: 16,
1141
949
  },
1142
- ],
1143
- }),
1144
- ),
1145
- );
1146
- if (bg === undefined) return { ok: false, error: badAlloc('pref-bg') };
1147
- pass.setPipeline(cache.prefilterPipeline);
1148
- pass.setBindGroup(0, bg);
950
+ },
951
+ },
952
+ ],
953
+ });
954
+ if (!bgResult.ok) return err(badAlloc('pref-bg', bgResult.error));
955
+ pass.setPipeline(prefilterPipeline);
956
+ pass.setBindGroup(0, bgResult.value);
1149
957
  pass.setBindGroup(1, cubeBg);
1150
958
  pass.setVertexBuffer(0, opts.cubeVertexBuffer);
1151
959
  pass.draw(6, 1, face * 6, 0);
@@ -1155,18 +963,18 @@ export function runIblPrecompute(
1155
963
 
1156
964
  // (d) brdf-lut: fullscreen triangle.
1157
965
  {
1158
- const pass = encoder.beginRenderPass({
966
+ const pass: RhiRenderPassEncoder = encoder.beginRenderPass({
1159
967
  label: 'ibl-brdf-lut',
1160
968
  colorAttachments: [
1161
969
  {
1162
- view: cache.brdfLutView,
970
+ view: brdfLutView,
1163
971
  clearValue: { r: 0, g: 0, b: 0, a: 1 },
1164
972
  loadOp: 'clear',
1165
973
  storeOp: 'store',
1166
974
  },
1167
975
  ],
1168
976
  });
1169
- pass.setPipeline(cache.brdfLutPipeline);
977
+ pass.setPipeline(brdfLutPipeline);
1170
978
  pass.draw(3, 1, 0, 0);
1171
979
  pass.end();
1172
980
  }
@@ -1174,73 +982,25 @@ export function runIblPrecompute(
1174
982
  // Finish + submit. Counter increments are STRICTLY after submit; if
1175
983
  // submit throws or fails, counters stay at 0 (AC-20 critical invariant).
1176
984
  const finishRes = encoder.finish();
1177
- // biome-ignore lint/suspicious/noExplicitAny: command buffer opaque
1178
- let cmdBuffer: any;
1179
- if (
1180
- finishRes !== null &&
1181
- finishRes !== undefined &&
1182
- typeof finishRes === 'object' &&
1183
- 'ok' in finishRes
1184
- ) {
1185
- if (!finishRes.ok) return { ok: false, error: badAlloc('finish') };
1186
- cmdBuffer = finishRes.value;
1187
- } else {
1188
- cmdBuffer = finishRes;
1189
- }
1190
-
1191
- // Submit -- may throw on mock devices in failure-injection tests, or
1192
- // return a structured Result.err on the rhi shim path. AC-20 critical:
1193
- // counters are incremented ONLY if submit returns cleanly (no throw +
1194
- // no .ok === false).
1195
- let submitOk = true;
1196
- let submitError: unknown;
1197
- try {
1198
- // biome-ignore lint/suspicious/noExplicitAny: submit returns Result|undefined
1199
- const submitRes = device.queue.submit([cmdBuffer]) as any;
1200
- if (
1201
- submitRes !== null &&
1202
- submitRes !== undefined &&
1203
- typeof submitRes === 'object' &&
1204
- 'ok' in submitRes &&
1205
- submitRes.ok === false
1206
- ) {
1207
- submitOk = false;
1208
- submitError = submitRes.error;
1209
- }
1210
- } catch (e) {
1211
- submitOk = false;
1212
- submitError = e;
1213
- }
1214
-
1215
- if (!submitOk) {
1216
- return {
1217
- ok: false,
1218
- error: {
1219
- code: 'ibl-precompute-not-dispatched',
1220
- expected: 'device.queue.submit returned successfully',
1221
- hint: `queue.submit failed: ${String(submitError)}; counters must not increment before queue.submit`,
1222
- },
1223
- };
1224
- }
985
+ if (!finishRes.ok) return err(badAlloc('finish', finishRes.error));
986
+ const cmdBuffer: CommandBuffer = finishRes.value;
987
+ const submitRes = device.queue.submit([cmdBuffer]);
988
+ if (!submitRes.ok) return err(badAlloc('queue.submit', submitRes.error));
1225
989
 
1226
990
  // POST-SUBMIT counter increments (AC-20).
1227
991
  cache.irradianceBakeCount += 1;
1228
992
  cache.prefilterBakeCount += 1;
1229
993
  cache.brdfLutBakeCount += 1;
1230
994
 
1231
- return { ok: true, value: { submitted: true } };
995
+ return ok({ submitted: true });
1232
996
  }
1233
997
 
1234
998
  // Local helper -- structured error payload shared across allocation paths.
1235
- function badAlloc(stage: string): { code: string; expected: string; hint: string } {
999
+ function badAlloc(stage: string, cause?: RhiError): IblPrecomputeError {
1236
1000
  return {
1237
1001
  code: 'ibl-precompute-not-dispatched',
1238
1002
  expected: `${stage} allocated successfully`,
1239
- hint: `check queue.submit path is reachable and ${stage} GPU resource creation did not fail; counters must not increment before queue.submit`,
1003
+ hint: `check the RHI Result for ${stage}; counters must not increment before queue.submit`,
1004
+ ...(cause === undefined ? {} : { detail: { stage, rhiCode: cause.code } }),
1240
1005
  };
1241
1006
  }
1242
-
1243
- // biome-ignore lint/suspicious/noExplicitAny: opaque BGL return
1244
- function prefilterGroup0LayoutOf(cache: IblPipelineCachePerDevice): any {
1245
- return cache.prefilterGroup0Bgl;
1246
- }