@forgeax/engine-render 0.0.0-dev.8d955ade1c79

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 (891) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +647 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/__tests__/authoring-path.unit.test.d.ts +2 -0
  5. package/dist/__tests__/authoring-path.unit.test.d.ts.map +1 -0
  6. package/dist/__tests__/backend-selection-rhi-capture.test-d.d.ts +2 -0
  7. package/dist/__tests__/backend-selection-rhi-capture.test-d.d.ts.map +1 -0
  8. package/dist/__tests__/callback-inference.test-d.d.ts +2 -0
  9. package/dist/__tests__/callback-inference.test-d.d.ts.map +1 -0
  10. package/dist/__tests__/cluster-binner.test.d.ts +2 -0
  11. package/dist/__tests__/cluster-binner.test.d.ts.map +1 -0
  12. package/dist/__tests__/cluster-grid-default-surface.unit.test.d.ts +2 -0
  13. package/dist/__tests__/cluster-grid-default-surface.unit.test.d.ts.map +1 -0
  14. package/dist/__tests__/construct-renderer-identity.unit.test.d.ts +2 -0
  15. package/dist/__tests__/construct-renderer-identity.unit.test.d.ts.map +1 -0
  16. package/dist/__tests__/device-scope-lifecycle.unit.test.d.ts +2 -0
  17. package/dist/__tests__/device-scope-lifecycle.unit.test.d.ts.map +1 -0
  18. package/dist/__tests__/device-scope-stale-matrix.unit.test.d.ts +2 -0
  19. package/dist/__tests__/device-scope-stale-matrix.unit.test.d.ts.map +1 -0
  20. package/dist/__tests__/direct-extract-consumer-contract.test-d.d.ts +2 -0
  21. package/dist/__tests__/direct-extract-consumer-contract.test-d.d.ts.map +1 -0
  22. package/dist/__tests__/direct-light-snapshot.unit.test.d.ts +2 -0
  23. package/dist/__tests__/direct-light-snapshot.unit.test.d.ts.map +1 -0
  24. package/dist/__tests__/factory-contract.integration.test.d.ts +2 -0
  25. package/dist/__tests__/factory-contract.integration.test.d.ts.map +1 -0
  26. package/dist/__tests__/fallback-row-stride-surface.unit.test.d.ts +2 -0
  27. package/dist/__tests__/fallback-row-stride-surface.unit.test.d.ts.map +1 -0
  28. package/dist/__tests__/frame-observation.contract.test.d.ts +2 -0
  29. package/dist/__tests__/frame-observation.contract.test.d.ts.map +1 -0
  30. package/dist/__tests__/fullscreen-feature-plan.unit.test.d.ts +2 -0
  31. package/dist/__tests__/fullscreen-feature-plan.unit.test.d.ts.map +1 -0
  32. package/dist/__tests__/glyph-text-layout-recovery.unit.test.d.ts +2 -0
  33. package/dist/__tests__/glyph-text-layout-recovery.unit.test.d.ts.map +1 -0
  34. package/dist/__tests__/gpu-driven-indirect-raster-evidence.d.ts +6 -0
  35. package/dist/__tests__/gpu-driven-indirect-raster-evidence.d.ts.map +1 -0
  36. package/dist/__tests__/gpu-driven-indirect-raster.browser.test.d.ts +2 -0
  37. package/dist/__tests__/gpu-driven-indirect-raster.browser.test.d.ts.map +1 -0
  38. package/dist/__tests__/gpu-driven-indirect-raster.dawn.test.d.ts +2 -0
  39. package/dist/__tests__/gpu-driven-indirect-raster.dawn.test.d.ts.map +1 -0
  40. package/dist/__tests__/gpu-driven-production.integration.test.d.ts +2 -0
  41. package/dist/__tests__/gpu-driven-production.integration.test.d.ts.map +1 -0
  42. package/dist/__tests__/gpu-driven-scaling.unit.test.d.ts +2 -0
  43. package/dist/__tests__/gpu-driven-scaling.unit.test.d.ts.map +1 -0
  44. package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts +18 -0
  45. package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts.map +1 -0
  46. package/dist/__tests__/gpu-driven-view-graph.integration.test.d.ts +2 -0
  47. package/dist/__tests__/gpu-driven-view-graph.integration.test.d.ts.map +1 -0
  48. package/dist/__tests__/gpu-driven-view-reference.d.ts +15 -0
  49. package/dist/__tests__/gpu-driven-view-reference.d.ts.map +1 -0
  50. package/dist/__tests__/gpu-driven-view.browser.test.d.ts +2 -0
  51. package/dist/__tests__/gpu-driven-view.browser.test.d.ts.map +1 -0
  52. package/dist/__tests__/gpu-driven-view.dawn.test.d.ts +2 -0
  53. package/dist/__tests__/gpu-driven-view.dawn.test.d.ts.map +1 -0
  54. package/dist/__tests__/gpu-driven-view.unit.test.d.ts +2 -0
  55. package/dist/__tests__/gpu-driven-view.unit.test.d.ts.map +1 -0
  56. package/dist/__tests__/gpu-resource-store-stride.unit.test.d.ts +2 -0
  57. package/dist/__tests__/gpu-resource-store-stride.unit.test.d.ts.map +1 -0
  58. package/dist/__tests__/gpu-scene-render-graph-gpu.d.ts +7 -0
  59. package/dist/__tests__/gpu-scene-render-graph-gpu.d.ts.map +1 -0
  60. package/dist/__tests__/gpu-scene-render-graph.browser.test.d.ts +2 -0
  61. package/dist/__tests__/gpu-scene-render-graph.browser.test.d.ts.map +1 -0
  62. package/dist/__tests__/gpu-scene-render-graph.dawn.test.d.ts +2 -0
  63. package/dist/__tests__/gpu-scene-render-graph.dawn.test.d.ts.map +1 -0
  64. package/dist/__tests__/gpu-scene-schema.unit.test.d.ts +2 -0
  65. package/dist/__tests__/gpu-scene-schema.unit.test.d.ts.map +1 -0
  66. package/dist/__tests__/gpu-scene.dawn.test.d.ts +2 -0
  67. package/dist/__tests__/gpu-scene.dawn.test.d.ts.map +1 -0
  68. package/dist/__tests__/gpu-scene.unit.test.d.ts +2 -0
  69. package/dist/__tests__/gpu-scene.unit.test.d.ts.map +1 -0
  70. package/dist/__tests__/ibl/face-uniforms.unit.test.d.ts +2 -0
  71. package/dist/__tests__/ibl/face-uniforms.unit.test.d.ts.map +1 -0
  72. package/dist/__tests__/infinite-grid-no-vertex-probe.unit.test.d.ts +2 -0
  73. package/dist/__tests__/infinite-grid-no-vertex-probe.unit.test.d.ts.map +1 -0
  74. package/dist/__tests__/injection-kind-owner.test-d.d.ts +2 -0
  75. package/dist/__tests__/injection-kind-owner.test-d.d.ts.map +1 -0
  76. package/dist/__tests__/ktx2-basis-gpu-consumer.dawn.test.d.ts +2 -0
  77. package/dist/__tests__/ktx2-basis-gpu-consumer.dawn.test.d.ts.map +1 -0
  78. package/dist/__tests__/light-buffer-layout.unit.test.d.ts +2 -0
  79. package/dist/__tests__/light-buffer-layout.unit.test.d.ts.map +1 -0
  80. package/dist/__tests__/material-contract-inventory.unit.test.d.ts +2 -0
  81. package/dist/__tests__/material-contract-inventory.unit.test.d.ts.map +1 -0
  82. package/dist/__tests__/material-cooked-projection.unit.test.d.ts +2 -0
  83. package/dist/__tests__/material-cooked-projection.unit.test.d.ts.map +1 -0
  84. package/dist/__tests__/material-snapshot-mutation.integration.test.d.ts +2 -0
  85. package/dist/__tests__/material-snapshot-mutation.integration.test.d.ts.map +1 -0
  86. package/dist/__tests__/material-static-dynamic-route.unit.test.d.ts +2 -0
  87. package/dist/__tests__/material-static-dynamic-route.unit.test.d.ts.map +1 -0
  88. package/dist/__tests__/material-stride-surface.unit.test.d.ts +2 -0
  89. package/dist/__tests__/material-stride-surface.unit.test.d.ts.map +1 -0
  90. package/dist/__tests__/mesh-buffer-usage-surface.unit.test.d.ts +2 -0
  91. package/dist/__tests__/mesh-buffer-usage-surface.unit.test.d.ts.map +1 -0
  92. package/dist/__tests__/mesh-material-bindings.unit.test.d.ts +2 -0
  93. package/dist/__tests__/mesh-material-bindings.unit.test.d.ts.map +1 -0
  94. package/dist/__tests__/mesh-stride-surface.unit.test.d.ts +2 -0
  95. package/dist/__tests__/mesh-stride-surface.unit.test.d.ts.map +1 -0
  96. package/dist/__tests__/morph-culling-reentry.dawn.test.d.ts +2 -0
  97. package/dist/__tests__/morph-culling-reentry.dawn.test.d.ts.map +1 -0
  98. package/dist/__tests__/morph-feature-gpu-work.integration.test.d.ts +2 -0
  99. package/dist/__tests__/morph-feature-gpu-work.integration.test.d.ts.map +1 -0
  100. package/dist/__tests__/morph-feature-plan.unit.test.d.ts +2 -0
  101. package/dist/__tests__/morph-feature-plan.unit.test.d.ts.map +1 -0
  102. package/dist/__tests__/morph-visual-evidence.integration.test.d.ts +2 -0
  103. package/dist/__tests__/morph-visual-evidence.integration.test.d.ts.map +1 -0
  104. package/dist/__tests__/nineslice-handle-surface.unit.test.d.ts +2 -0
  105. package/dist/__tests__/nineslice-handle-surface.unit.test.d.ts.map +1 -0
  106. package/dist/__tests__/post-process-error-policy-owner.unit.test.d.ts +2 -0
  107. package/dist/__tests__/post-process-error-policy-owner.unit.test.d.ts.map +1 -0
  108. package/dist/__tests__/prepared-buffer-kind-owner.test-d.d.ts +2 -0
  109. package/dist/__tests__/prepared-buffer-kind-owner.test-d.d.ts.map +1 -0
  110. package/dist/__tests__/prepared-graphics-capability.unit.test.d.ts +2 -0
  111. package/dist/__tests__/prepared-graphics-capability.unit.test.d.ts.map +1 -0
  112. package/dist/__tests__/prepared-graphics-generation.unit.test.d.ts +2 -0
  113. package/dist/__tests__/prepared-graphics-generation.unit.test.d.ts.map +1 -0
  114. package/dist/__tests__/prepared-graphics-lifecycle.unit.test.d.ts +2 -0
  115. package/dist/__tests__/prepared-graphics-lifecycle.unit.test.d.ts.map +1 -0
  116. package/dist/__tests__/prepared-graphics-pipeline-warmup.unit.test.d.ts +2 -0
  117. package/dist/__tests__/prepared-graphics-pipeline-warmup.unit.test.d.ts.map +1 -0
  118. package/dist/__tests__/prepared-graphics-resolver.unit.test.d.ts +2 -0
  119. package/dist/__tests__/prepared-graphics-resolver.unit.test.d.ts.map +1 -0
  120. package/dist/__tests__/prepared-graphics-snapshot.unit.test.d.ts +2 -0
  121. package/dist/__tests__/prepared-graphics-snapshot.unit.test.d.ts.map +1 -0
  122. package/dist/__tests__/prepared-graphics-store.unit.test.d.ts +2 -0
  123. package/dist/__tests__/prepared-graphics-store.unit.test.d.ts.map +1 -0
  124. package/dist/__tests__/prepared-graphics-validation.unit.test.d.ts +2 -0
  125. package/dist/__tests__/prepared-graphics-validation.unit.test.d.ts.map +1 -0
  126. package/dist/__tests__/profiler-default-off.test.d.ts +2 -0
  127. package/dist/__tests__/profiler-default-off.test.d.ts.map +1 -0
  128. package/dist/__tests__/profiler-phase-catalog.test.d.ts +2 -0
  129. package/dist/__tests__/profiler-phase-catalog.test.d.ts.map +1 -0
  130. package/dist/__tests__/profiler-phase-integration.test.d.ts +2 -0
  131. package/dist/__tests__/profiler-phase-integration.test.d.ts.map +1 -0
  132. package/dist/__tests__/profiler-phase-token.test.d.ts +2 -0
  133. package/dist/__tests__/profiler-phase-token.test.d.ts.map +1 -0
  134. package/dist/__tests__/public-surface.test-d.d.ts +2 -0
  135. package/dist/__tests__/public-surface.test-d.d.ts.map +1 -0
  136. package/dist/__tests__/recover-error-policy-owner.unit.test.d.ts +2 -0
  137. package/dist/__tests__/recover-error-policy-owner.unit.test.d.ts.map +1 -0
  138. package/dist/__tests__/render-error-code-owner.test-d.d.ts +2 -0
  139. package/dist/__tests__/render-error-code-owner.test-d.d.ts.map +1 -0
  140. package/dist/__tests__/render-error-detail-ssot.test-d.d.ts +2 -0
  141. package/dist/__tests__/render-error-detail-ssot.test-d.d.ts.map +1 -0
  142. package/dist/__tests__/render-error-exhaustive.test-d.d.ts +2 -0
  143. package/dist/__tests__/render-error-exhaustive.test-d.d.ts.map +1 -0
  144. package/dist/__tests__/render-feature-assembly.test-d.d.ts +2 -0
  145. package/dist/__tests__/render-feature-assembly.test-d.d.ts.map +1 -0
  146. package/dist/__tests__/render-feature-context.test-d.d.ts +2 -0
  147. package/dist/__tests__/render-feature-context.test-d.d.ts.map +1 -0
  148. package/dist/__tests__/render-feature-contract.test-d.d.ts +2 -0
  149. package/dist/__tests__/render-feature-contract.test-d.d.ts.map +1 -0
  150. package/dist/__tests__/render-feature-diagnostics.unit.test.d.ts +2 -0
  151. package/dist/__tests__/render-feature-diagnostics.unit.test.d.ts.map +1 -0
  152. package/dist/__tests__/render-feature-docs.unit.test.d.ts +2 -0
  153. package/dist/__tests__/render-feature-docs.unit.test.d.ts.map +1 -0
  154. package/dist/__tests__/render-feature-errors.unit.test.d.ts +2 -0
  155. package/dist/__tests__/render-feature-errors.unit.test.d.ts.map +1 -0
  156. package/dist/__tests__/render-feature-gpu-work.integration.test.d.ts +2 -0
  157. package/dist/__tests__/render-feature-gpu-work.integration.test.d.ts.map +1 -0
  158. package/dist/__tests__/render-feature-plan.test-d.d.ts +2 -0
  159. package/dist/__tests__/render-feature-plan.test-d.d.ts.map +1 -0
  160. package/dist/__tests__/render-feature-plan.unit.test.d.ts +2 -0
  161. package/dist/__tests__/render-feature-plan.unit.test.d.ts.map +1 -0
  162. package/dist/__tests__/render-feature-prepared-diagnostics.unit.test.d.ts +2 -0
  163. package/dist/__tests__/render-feature-prepared-diagnostics.unit.test.d.ts.map +1 -0
  164. package/dist/__tests__/render-feature-prepared-errors.test-d.d.ts +2 -0
  165. package/dist/__tests__/render-feature-prepared-errors.test-d.d.ts.map +1 -0
  166. package/dist/__tests__/render-feature-prepared-graphics-docs.unit.test.d.ts +2 -0
  167. package/dist/__tests__/render-feature-prepared-graphics-docs.unit.test.d.ts.map +1 -0
  168. package/dist/__tests__/render-feature-prepared-graphics-isolation.unit.test.d.ts +2 -0
  169. package/dist/__tests__/render-feature-prepared-graphics-isolation.unit.test.d.ts.map +1 -0
  170. package/dist/__tests__/render-feature-prepared-graphics-negative.test-d.d.ts +2 -0
  171. package/dist/__tests__/render-feature-prepared-graphics-negative.test-d.d.ts.map +1 -0
  172. package/dist/__tests__/render-feature-prepared-graphics.test-d.d.ts +2 -0
  173. package/dist/__tests__/render-feature-prepared-graphics.test-d.d.ts.map +1 -0
  174. package/dist/__tests__/render-feature-prepared-graphics.unit.test.d.ts +2 -0
  175. package/dist/__tests__/render-feature-prepared-graphics.unit.test.d.ts.map +1 -0
  176. package/dist/__tests__/render-feature-public-surface.test-d.d.ts +2 -0
  177. package/dist/__tests__/render-feature-public-surface.test-d.d.ts.map +1 -0
  178. package/dist/__tests__/render-feature-retry.unit.test.d.ts +2 -0
  179. package/dist/__tests__/render-feature-retry.unit.test.d.ts.map +1 -0
  180. package/dist/__tests__/render-feature-scheduling.unit.test.d.ts +2 -0
  181. package/dist/__tests__/render-feature-scheduling.unit.test.d.ts.map +1 -0
  182. package/dist/__tests__/render-feature-stage-failed-policy-owner.unit.test.d.ts +2 -0
  183. package/dist/__tests__/render-feature-stage-failed-policy-owner.unit.test.d.ts.map +1 -0
  184. package/dist/__tests__/render-feature-stage-fault-recovery.unit.test.d.ts +2 -0
  185. package/dist/__tests__/render-feature-stage-fault-recovery.unit.test.d.ts.map +1 -0
  186. package/dist/__tests__/render-feature-visibility-context.test-d.d.ts +2 -0
  187. package/dist/__tests__/render-feature-visibility-context.test-d.d.ts.map +1 -0
  188. package/dist/__tests__/render-feature-visibility-context.unit.test.d.ts +2 -0
  189. package/dist/__tests__/render-feature-visibility-context.unit.test.d.ts.map +1 -0
  190. package/dist/__tests__/render-feature-zero-work.unit.test.d.ts +2 -0
  191. package/dist/__tests__/render-feature-zero-work.unit.test.d.ts.map +1 -0
  192. package/dist/__tests__/render-graph-compute-raster-gpu.d.ts +7 -0
  193. package/dist/__tests__/render-graph-compute-raster-gpu.d.ts.map +1 -0
  194. package/dist/__tests__/render-graph-compute-raster.browser.test.d.ts +2 -0
  195. package/dist/__tests__/render-graph-compute-raster.browser.test.d.ts.map +1 -0
  196. package/dist/__tests__/render-graph-compute-raster.dawn.test.d.ts +2 -0
  197. package/dist/__tests__/render-graph-compute-raster.dawn.test.d.ts.map +1 -0
  198. package/dist/__tests__/render-graph-hzb-gpu.d.ts +7 -0
  199. package/dist/__tests__/render-graph-hzb-gpu.d.ts.map +1 -0
  200. package/dist/__tests__/render-graph-hzb.browser.test.d.ts +2 -0
  201. package/dist/__tests__/render-graph-hzb.browser.test.d.ts.map +1 -0
  202. package/dist/__tests__/render-graph-hzb.dawn.test.d.ts +2 -0
  203. package/dist/__tests__/render-graph-hzb.dawn.test.d.ts.map +1 -0
  204. package/dist/__tests__/render-graph-primitives.unit.test.d.ts +2 -0
  205. package/dist/__tests__/render-graph-primitives.unit.test.d.ts.map +1 -0
  206. package/dist/__tests__/render-graph-storage-indirect-gpu.d.ts +12 -0
  207. package/dist/__tests__/render-graph-storage-indirect-gpu.d.ts.map +1 -0
  208. package/dist/__tests__/render-graph-storage-indirect.browser.test.d.ts +2 -0
  209. package/dist/__tests__/render-graph-storage-indirect.browser.test.d.ts.map +1 -0
  210. package/dist/__tests__/render-graph-storage-indirect.dawn.test.d.ts +2 -0
  211. package/dist/__tests__/render-graph-storage-indirect.dawn.test.d.ts.map +1 -0
  212. package/dist/__tests__/render-scene-projection.unit.test.d.ts +2 -0
  213. package/dist/__tests__/render-scene-projection.unit.test.d.ts.map +1 -0
  214. package/dist/__tests__/renderer-factory-material-contract.unit.test.d.ts +2 -0
  215. package/dist/__tests__/renderer-factory-material-contract.unit.test.d.ts.map +1 -0
  216. package/dist/__tests__/renderer-lifecycle.integration.test.d.ts +2 -0
  217. package/dist/__tests__/renderer-lifecycle.integration.test.d.ts.map +1 -0
  218. package/dist/__tests__/rhi-backend-package-boundary.unit.test.d.ts +2 -0
  219. package/dist/__tests__/rhi-backend-package-boundary.unit.test.d.ts.map +1 -0
  220. package/dist/__tests__/scriptable-pack-consumer.test-d.d.ts +2 -0
  221. package/dist/__tests__/scriptable-pack-consumer.test-d.d.ts.map +1 -0
  222. package/dist/__tests__/shader-stage-surface.unit.test.d.ts +2 -0
  223. package/dist/__tests__/shader-stage-surface.unit.test.d.ts.map +1 -0
  224. package/dist/__tests__/ssao-config.unit.test.d.ts +2 -0
  225. package/dist/__tests__/ssao-config.unit.test.d.ts.map +1 -0
  226. package/dist/__tests__/ssao-kernel-surface.unit.test.d.ts +2 -0
  227. package/dist/__tests__/ssao-kernel-surface.unit.test.d.ts.map +1 -0
  228. package/dist/__tests__/standard-clustered-pipeline.unit.test.d.ts +2 -0
  229. package/dist/__tests__/standard-clustered-pipeline.unit.test.d.ts.map +1 -0
  230. package/dist/__tests__/standard-descriptors.test-d.d.ts +2 -0
  231. package/dist/__tests__/standard-descriptors.test-d.d.ts.map +1 -0
  232. package/dist/__tests__/standard-pipeline.dawn.test.d.ts +2 -0
  233. package/dist/__tests__/standard-pipeline.dawn.test.d.ts.map +1 -0
  234. package/dist/__tests__/standard-pipeline.integration.test.d.ts +2 -0
  235. package/dist/__tests__/standard-pipeline.integration.test.d.ts.map +1 -0
  236. package/dist/__tests__/standard-profile-oracle.unit.test.d.ts +2 -0
  237. package/dist/__tests__/standard-profile-oracle.unit.test.d.ts.map +1 -0
  238. package/dist/__tests__/surface-configuration.unit.test.d.ts +2 -0
  239. package/dist/__tests__/surface-configuration.unit.test.d.ts.map +1 -0
  240. package/dist/__tests__/texture-usage-surface.unit.test.d.ts +2 -0
  241. package/dist/__tests__/texture-usage-surface.unit.test.d.ts.map +1 -0
  242. package/dist/__tests__/typed-pipeline-topology.unit.test.d.ts +2 -0
  243. package/dist/__tests__/typed-pipeline-topology.unit.test.d.ts.map +1 -0
  244. package/dist/__tests__/urp-pipeline-targets.unit.test.d.ts +2 -0
  245. package/dist/__tests__/urp-pipeline-targets.unit.test.d.ts.map +1 -0
  246. package/dist/__tests__/urp-pipeline.unit.test.d.ts +2 -0
  247. package/dist/__tests__/urp-pipeline.unit.test.d.ts.map +1 -0
  248. package/dist/__tests__/vertex-color-pipeline.unit.test.d.ts +2 -0
  249. package/dist/__tests__/vertex-color-pipeline.unit.test.d.ts.map +1 -0
  250. package/dist/__tests__/vertex-layout-consumer.unit.test.d.ts +2 -0
  251. package/dist/__tests__/vertex-layout-consumer.unit.test.d.ts.map +1 -0
  252. package/dist/__tests__/visibility-diagnostics.integration.test.d.ts +2 -0
  253. package/dist/__tests__/visibility-diagnostics.integration.test.d.ts.map +1 -0
  254. package/dist/__tests__/visibility-extract.integration.test.d.ts +2 -0
  255. package/dist/__tests__/visibility-extract.integration.test.d.ts.map +1 -0
  256. package/dist/__tests__/visibility-extract.perf.test.d.ts +2 -0
  257. package/dist/__tests__/visibility-extract.perf.test.d.ts.map +1 -0
  258. package/dist/__tests__/visibility-feature-dedup.integration.test.d.ts +2 -0
  259. package/dist/__tests__/visibility-feature-dedup.integration.test.d.ts.map +1 -0
  260. package/dist/__tests__/visibility-hidden-report.unit.test.d.ts +2 -0
  261. package/dist/__tests__/visibility-hidden-report.unit.test.d.ts.map +1 -0
  262. package/dist/__tests__/visibility-instances.integration.test.d.ts +2 -0
  263. package/dist/__tests__/visibility-instances.integration.test.d.ts.map +1 -0
  264. package/dist/__tests__/visibility-multi-world.integration.test.d.ts +2 -0
  265. package/dist/__tests__/visibility-multi-world.integration.test.d.ts.map +1 -0
  266. package/dist/__tests__/visibility-producer-matrix.integration.test.d.ts +2 -0
  267. package/dist/__tests__/visibility-producer-matrix.integration.test.d.ts.map +1 -0
  268. package/dist/__tests__/visibility-producer-matrix.unit.test.d.ts +2 -0
  269. package/dist/__tests__/visibility-producer-matrix.unit.test.d.ts.map +1 -0
  270. package/dist/__tests__/visibility-public-surface.test-d.d.ts +2 -0
  271. package/dist/__tests__/visibility-public-surface.test-d.d.ts.map +1 -0
  272. package/dist/__tests__/visibility-resolver.unit.test.d.ts +2 -0
  273. package/dist/__tests__/visibility-resolver.unit.test.d.ts.map +1 -0
  274. package/dist/__tests__/visibility-resource-short-circuit.unit.test.d.ts +2 -0
  275. package/dist/__tests__/visibility-resource-short-circuit.unit.test.d.ts.map +1 -0
  276. package/dist/__tests__/visibility-snapshot-contract.unit.test.d.ts +2 -0
  277. package/dist/__tests__/visibility-snapshot-contract.unit.test.d.ts.map +1 -0
  278. package/dist/__tests__/vocabulary.unit.test.d.ts +2 -0
  279. package/dist/__tests__/vocabulary.unit.test.d.ts.map +1 -0
  280. package/dist/assembly/backend-contract.d.ts +37 -0
  281. package/dist/assembly/backend-contract.d.ts.map +1 -0
  282. package/dist/assembly/factory.d.ts +207 -0
  283. package/dist/assembly/factory.d.ts.map +1 -0
  284. package/dist/assembly/host-contract.d.ts +84 -0
  285. package/dist/assembly/host-contract.d.ts.map +1 -0
  286. package/dist/assembly/material/assembly.d.ts +21 -0
  287. package/dist/assembly/material/assembly.d.ts.map +1 -0
  288. package/dist/assembly/material/pipeline-projection.d.ts +30 -0
  289. package/dist/assembly/material/pipeline-projection.d.ts.map +1 -0
  290. package/dist/assets/asset-decoders.d.ts +5 -0
  291. package/dist/assets/asset-decoders.d.ts.map +1 -0
  292. package/dist/assets/render-asset-port.d.ts +17 -0
  293. package/dist/assets/render-asset-port.d.ts.map +1 -0
  294. package/dist/assets/resolve-render-asset.d.ts +6 -0
  295. package/dist/assets/resolve-render-asset.d.ts.map +1 -0
  296. package/dist/authoring.d.ts +12 -0
  297. package/dist/authoring.d.ts.map +1 -0
  298. package/dist/authoring.mjs +27 -0
  299. package/dist/authoring.mjs.map +1 -0
  300. package/dist/chunk-CQXZC5XI.mjs +182 -0
  301. package/dist/chunk-CQXZC5XI.mjs.map +1 -0
  302. package/dist/chunk-HCOGPHKS.mjs +93 -0
  303. package/dist/chunk-HCOGPHKS.mjs.map +1 -0
  304. package/dist/chunk-YEJIUW7D.mjs +1152 -0
  305. package/dist/chunk-YEJIUW7D.mjs.map +1 -0
  306. package/dist/cluster-binner.d.ts +152 -0
  307. package/dist/cluster-binner.d.ts.map +1 -0
  308. package/dist/components/__tests__/points-lines-admission.unit.test.d.ts +2 -0
  309. package/dist/components/__tests__/points-lines-admission.unit.test.d.ts.map +1 -0
  310. package/dist/components/__tests__/points-lines-schema.unit.test.d.ts +2 -0
  311. package/dist/components/__tests__/points-lines-schema.unit.test.d.ts.map +1 -0
  312. package/dist/components/__tests__/schema-contract.unit.test.d.ts +2 -0
  313. package/dist/components/__tests__/schema-contract.unit.test.d.ts.map +1 -0
  314. package/dist/components/__tests__/schema-parity.unit.test.d.ts +2 -0
  315. package/dist/components/__tests__/schema-parity.unit.test.d.ts.map +1 -0
  316. package/dist/components/__tests__/visibility-schema.unit.test.d.ts +2 -0
  317. package/dist/components/__tests__/visibility-schema.unit.test.d.ts.map +1 -0
  318. package/dist/components/camera.d.ts +311 -0
  319. package/dist/components/camera.d.ts.map +1 -0
  320. package/dist/components/directional-light.d.ts +76 -0
  321. package/dist/components/directional-light.d.ts.map +1 -0
  322. package/dist/components/glyph-text.d.ts +26 -0
  323. package/dist/components/glyph-text.d.ts.map +1 -0
  324. package/dist/components/index.d.ts +24 -0
  325. package/dist/components/index.d.ts.map +1 -0
  326. package/dist/components/instances.d.ts +41 -0
  327. package/dist/components/instances.d.ts.map +1 -0
  328. package/dist/components/layer.d.ts +34 -0
  329. package/dist/components/layer.d.ts.map +1 -0
  330. package/dist/components/light-helpers.d.ts +53 -0
  331. package/dist/components/light-helpers.d.ts.map +1 -0
  332. package/dist/components/lines.d.ts +5 -0
  333. package/dist/components/lines.d.ts.map +1 -0
  334. package/dist/components/mesh-filter.d.ts +24 -0
  335. package/dist/components/mesh-filter.d.ts.map +1 -0
  336. package/dist/components/mesh-renderer.d.ts +33 -0
  337. package/dist/components/mesh-renderer.d.ts.map +1 -0
  338. package/dist/components/point-light-shadow.d.ts +27 -0
  339. package/dist/components/point-light-shadow.d.ts.map +1 -0
  340. package/dist/components/point-light.d.ts +35 -0
  341. package/dist/components/point-light.d.ts.map +1 -0
  342. package/dist/components/points.d.ts +15 -0
  343. package/dist/components/points.d.ts.map +1 -0
  344. package/dist/components/post-process-params.d.ts +5 -0
  345. package/dist/components/post-process-params.d.ts.map +1 -0
  346. package/dist/components/scene-instance.d.ts +140 -0
  347. package/dist/components/scene-instance.d.ts.map +1 -0
  348. package/dist/components/skybox-background.d.ts +56 -0
  349. package/dist/components/skybox-background.d.ts.map +1 -0
  350. package/dist/components/skylight.d.ts +55 -0
  351. package/dist/components/skylight.d.ts.map +1 -0
  352. package/dist/components/sort-key.d.ts +44 -0
  353. package/dist/components/sort-key.d.ts.map +1 -0
  354. package/dist/components/spot-light.d.ts +81 -0
  355. package/dist/components/spot-light.d.ts.map +1 -0
  356. package/dist/components/sprite-animation.d.ts +74 -0
  357. package/dist/components/sprite-animation.d.ts.map +1 -0
  358. package/dist/components/sprite-instances.d.ts +51 -0
  359. package/dist/components/sprite-instances.d.ts.map +1 -0
  360. package/dist/components/sprite-playback-mode.d.ts +42 -0
  361. package/dist/components/sprite-playback-mode.d.ts.map +1 -0
  362. package/dist/components/sprite-region-override.d.ts +46 -0
  363. package/dist/components/sprite-region-override.d.ts.map +1 -0
  364. package/dist/components/tile-layer.d.ts +106 -0
  365. package/dist/components/tile-layer.d.ts.map +1 -0
  366. package/dist/components/tilemap.d.ts +25 -0
  367. package/dist/components/tilemap.d.ts.map +1 -0
  368. package/dist/components/visibility.d.ts +22 -0
  369. package/dist/components/visibility.d.ts.map +1 -0
  370. package/dist/construct-renderer.d.ts +19 -0
  371. package/dist/construct-renderer.d.ts.map +1 -0
  372. package/dist/construct-renderer.mjs +27462 -0
  373. package/dist/construct-renderer.mjs.map +1 -0
  374. package/dist/debug-draw-glue.d.ts +5 -0
  375. package/dist/debug-draw-glue.d.ts.map +1 -0
  376. package/dist/device/device-scope.d.ts +83 -0
  377. package/dist/device/device-scope.d.ts.map +1 -0
  378. package/dist/device/gpu-residency.d.ts +337 -0
  379. package/dist/device/gpu-residency.d.ts.map +1 -0
  380. package/dist/device/resource-types.d.ts +8 -0
  381. package/dist/device/resource-types.d.ts.map +1 -0
  382. package/dist/engine-metrics.d.ts +23 -0
  383. package/dist/engine-metrics.d.ts.map +1 -0
  384. package/dist/errors/ecs-validation.d.ts +3 -0
  385. package/dist/errors/ecs-validation.d.ts.map +1 -0
  386. package/dist/errors/index.d.ts +4 -0
  387. package/dist/errors/index.d.ts.map +1 -0
  388. package/dist/errors/recover.d.ts +105 -0
  389. package/dist/errors/recover.d.ts.map +1 -0
  390. package/dist/errors/render.d.ts +705 -0
  391. package/dist/errors/render.d.ts.map +1 -0
  392. package/dist/extract/visibility.d.ts +26 -0
  393. package/dist/extract/visibility.d.ts.map +1 -0
  394. package/dist/features/fullscreen.d.ts +19 -0
  395. package/dist/features/fullscreen.d.ts.map +1 -0
  396. package/dist/features/host.d.ts +106 -0
  397. package/dist/features/host.d.ts.map +1 -0
  398. package/dist/features/morph/morph-feature.d.ts +79 -0
  399. package/dist/features/morph/morph-feature.d.ts.map +1 -0
  400. package/dist/features/plan.d.ts +182 -0
  401. package/dist/features/plan.d.ts.map +1 -0
  402. package/dist/features/prepared-gpu-work.d.ts +117 -0
  403. package/dist/features/prepared-gpu-work.d.ts.map +1 -0
  404. package/dist/features/prepared-graphics-store.d.ts +66 -0
  405. package/dist/features/prepared-graphics-store.d.ts.map +1 -0
  406. package/dist/features/prepared-graphics.d.ts +215 -0
  407. package/dist/features/prepared-graphics.d.ts.map +1 -0
  408. package/dist/features/render-graph-compute.d.ts +13 -0
  409. package/dist/features/render-graph-compute.d.ts.map +1 -0
  410. package/dist/features/render-graph-contribution.d.ts +12 -0
  411. package/dist/features/render-graph-contribution.d.ts.map +1 -0
  412. package/dist/features/render-graph-raster.d.ts +38 -0
  413. package/dist/features/render-graph-raster.d.ts.map +1 -0
  414. package/dist/features/render-graph-resources.d.ts +11 -0
  415. package/dist/features/render-graph-resources.d.ts.map +1 -0
  416. package/dist/features/targets.d.ts +32 -0
  417. package/dist/features/targets.d.ts.map +1 -0
  418. package/dist/features/types.d.ts +68 -0
  419. package/dist/features/types.d.ts.map +1 -0
  420. package/dist/features/vocabulary.d.ts +14 -0
  421. package/dist/features/vocabulary.d.ts.map +1 -0
  422. package/dist/fullscreen-post-process-pass.d.ts +157 -0
  423. package/dist/fullscreen-post-process-pass.d.ts.map +1 -0
  424. package/dist/glyph-text-layout-system.d.ts +19 -0
  425. package/dist/glyph-text-layout-system.d.ts.map +1 -0
  426. package/dist/gpu-driven/batch-topology.d.ts +55 -0
  427. package/dist/gpu-driven/batch-topology.d.ts.map +1 -0
  428. package/dist/gpu-driven/production-raster.d.ts +51 -0
  429. package/dist/gpu-driven/production-raster.d.ts.map +1 -0
  430. package/dist/gpu-driven/view-gpu.d.ts +85 -0
  431. package/dist/gpu-driven/view-gpu.d.ts.map +1 -0
  432. package/dist/gpu-resource.d.ts +73 -0
  433. package/dist/gpu-resource.d.ts.map +1 -0
  434. package/dist/gpu-scene-schema.d.ts +78 -0
  435. package/dist/gpu-scene-schema.d.ts.map +1 -0
  436. package/dist/gpu-scene.d.ts +55 -0
  437. package/dist/gpu-scene.d.ts.map +1 -0
  438. package/dist/gpu-stage.d.ts +4 -0
  439. package/dist/gpu-stage.d.ts.map +1 -0
  440. package/dist/gpu-texture-usage.d.ts +6 -0
  441. package/dist/gpu-texture-usage.d.ts.map +1 -0
  442. package/dist/gpu-usage.d.ts +9 -0
  443. package/dist/gpu-usage.d.ts.map +1 -0
  444. package/dist/hdrp-buffers.d.ts +163 -0
  445. package/dist/hdrp-buffers.d.ts.map +1 -0
  446. package/dist/ibl/IblPipelineCache.d.ts +168 -0
  447. package/dist/ibl/IblPipelineCache.d.ts.map +1 -0
  448. package/dist/ibl/skylight-bind-group.d.ts +130 -0
  449. package/dist/ibl/skylight-bind-group.d.ts.map +1 -0
  450. package/dist/index.d.ts +31 -0
  451. package/dist/index.d.ts.map +1 -0
  452. package/dist/index.mjs +169 -0
  453. package/dist/index.mjs.map +1 -0
  454. package/dist/inspection-types.d.ts +72 -0
  455. package/dist/inspection-types.d.ts.map +1 -0
  456. package/dist/instance-buffer-cache.d.ts +56 -0
  457. package/dist/instance-buffer-cache.d.ts.map +1 -0
  458. package/dist/internal.d.ts +2 -0
  459. package/dist/internal.d.ts.map +1 -0
  460. package/dist/internal.mjs +3 -0
  461. package/dist/internal.mjs.map +1 -0
  462. package/dist/lifecycle.d.ts +62 -0
  463. package/dist/lifecycle.d.ts.map +1 -0
  464. package/dist/light-buffer-layout.d.ts +164 -0
  465. package/dist/light-buffer-layout.d.ts.map +1 -0
  466. package/dist/materials.d.ts +47 -0
  467. package/dist/materials.d.ts.map +1 -0
  468. package/dist/mesh-material-bindings.d.ts +43 -0
  469. package/dist/mesh-material-bindings.d.ts.map +1 -0
  470. package/dist/pbr-pipeline.d.ts +301 -0
  471. package/dist/pbr-pipeline.d.ts.map +1 -0
  472. package/dist/pipeline/standard-forward-lane.d.ts +5 -0
  473. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -0
  474. package/dist/pipeline/standard-pipeline.d.ts +31 -0
  475. package/dist/pipeline/standard-pipeline.d.ts.map +1 -0
  476. package/dist/pipeline/standard-profile.d.ts +40 -0
  477. package/dist/pipeline/standard-profile.d.ts.map +1 -0
  478. package/dist/pipeline-builder.d.ts +122 -0
  479. package/dist/pipeline-builder.d.ts.map +1 -0
  480. package/dist/pipeline-spec-types.d.ts +24 -0
  481. package/dist/pipeline-spec-types.d.ts.map +1 -0
  482. package/dist/pipeline-spec.d.ts +367 -0
  483. package/dist/pipeline-spec.d.ts.map +1 -0
  484. package/dist/plugin.d.ts +4 -0
  485. package/dist/plugin.d.ts.map +1 -0
  486. package/dist/points-lines/__tests__/bounds.unit.test.d.ts +2 -0
  487. package/dist/points-lines/__tests__/bounds.unit.test.d.ts.map +1 -0
  488. package/dist/points-lines/__tests__/cache-recovery.unit.test.d.ts +2 -0
  489. package/dist/points-lines/__tests__/cache-recovery.unit.test.d.ts.map +1 -0
  490. package/dist/points-lines/__tests__/inspection-lanes.integration.test.d.ts +2 -0
  491. package/dist/points-lines/__tests__/inspection-lanes.integration.test.d.ts.map +1 -0
  492. package/dist/points-lines/__tests__/inspection.unit.test.d.ts +2 -0
  493. package/dist/points-lines/__tests__/inspection.unit.test.d.ts.map +1 -0
  494. package/dist/points-lines/__tests__/lane-structural.integration.test.d.ts +2 -0
  495. package/dist/points-lines/__tests__/lane-structural.integration.test.d.ts.map +1 -0
  496. package/dist/points-lines/__tests__/points-lines.bench.d.ts +2 -0
  497. package/dist/points-lines/__tests__/points-lines.bench.d.ts.map +1 -0
  498. package/dist/points-lines/__tests__/raster-lane.integration.test.d.ts +2 -0
  499. package/dist/points-lines/__tests__/raster-lane.integration.test.d.ts.map +1 -0
  500. package/dist/points-lines/__tests__/snapshot.unit.test.d.ts +2 -0
  501. package/dist/points-lines/__tests__/snapshot.unit.test.d.ts.map +1 -0
  502. package/dist/points-lines/__tests__/view-ubo.unit.test.d.ts +2 -0
  503. package/dist/points-lines/__tests__/view-ubo.unit.test.d.ts.map +1 -0
  504. package/dist/points-lines/admission.d.ts +36 -0
  505. package/dist/points-lines/admission.d.ts.map +1 -0
  506. package/dist/points-lines/bounds.d.ts +8 -0
  507. package/dist/points-lines/bounds.d.ts.map +1 -0
  508. package/dist/points-lines/expansion-cache.d.ts +28 -0
  509. package/dist/points-lines/expansion-cache.d.ts.map +1 -0
  510. package/dist/points-lines/inspection.d.ts +53 -0
  511. package/dist/points-lines/inspection.d.ts.map +1 -0
  512. package/dist/points-lines/prepare.d.ts +67 -0
  513. package/dist/points-lines/prepare.d.ts.map +1 -0
  514. package/dist/points-lines/record.d.ts +60 -0
  515. package/dist/points-lines/record.d.ts.map +1 -0
  516. package/dist/points-lines/snapshot.d.ts +49 -0
  517. package/dist/points-lines/snapshot.d.ts.map +1 -0
  518. package/dist/post-process-errors.d.ts +182 -0
  519. package/dist/post-process-errors.d.ts.map +1 -0
  520. package/dist/prepare/prepared-graphics-resolver.d.ts +59 -0
  521. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -0
  522. package/dist/record/__tests__/material-bg-cache.unit.test.d.ts +2 -0
  523. package/dist/record/__tests__/material-bg-cache.unit.test.d.ts.map +1 -0
  524. package/dist/record/__tests__/material-slot-plan.unit.test.d.ts +2 -0
  525. package/dist/record/__tests__/material-slot-plan.unit.test.d.ts.map +1 -0
  526. package/dist/record/__tests__/typed-frame-graph-plan.unit.test.d.ts +2 -0
  527. package/dist/record/__tests__/typed-frame-graph-plan.unit.test.d.ts.map +1 -0
  528. package/dist/record/__tests__/video-texture-view.unit.test.d.ts +2 -0
  529. package/dist/record/__tests__/video-texture-view.unit.test.d.ts.map +1 -0
  530. package/dist/record/frame-lighting.d.ts +121 -0
  531. package/dist/record/frame-lighting.d.ts.map +1 -0
  532. package/dist/record/frame-snapshot.d.ts +429 -0
  533. package/dist/record/frame-snapshot.d.ts.map +1 -0
  534. package/dist/record/frame-targets.d.ts +20 -0
  535. package/dist/record/frame-targets.d.ts.map +1 -0
  536. package/dist/record/frame.d.ts +71 -0
  537. package/dist/record/frame.d.ts.map +1 -0
  538. package/dist/record/helpers.d.ts +102 -0
  539. package/dist/record/helpers.d.ts.map +1 -0
  540. package/dist/record/main-pass-geometry.d.ts +28 -0
  541. package/dist/record/main-pass-geometry.d.ts.map +1 -0
  542. package/dist/record/main-pass-material.d.ts +204 -0
  543. package/dist/record/main-pass-material.d.ts.map +1 -0
  544. package/dist/record/main-pass-sprite-draws.d.ts +43 -0
  545. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -0
  546. package/dist/record/main-pass.d.ts +20 -0
  547. package/dist/record/main-pass.d.ts.map +1 -0
  548. package/dist/record/mesh-ssbo.d.ts +446 -0
  549. package/dist/record/mesh-ssbo.d.ts.map +1 -0
  550. package/dist/record/render-context.d.ts +252 -0
  551. package/dist/record/render-context.d.ts.map +1 -0
  552. package/dist/record/shadow-pass.d.ts +52 -0
  553. package/dist/record/shadow-pass.d.ts.map +1 -0
  554. package/dist/record/skybox-post-pass.d.ts +33 -0
  555. package/dist/record/skybox-post-pass.d.ts.map +1 -0
  556. package/dist/record/typed-frame-graph.d.ts +35 -0
  557. package/dist/record/typed-frame-graph.d.ts.map +1 -0
  558. package/dist/record/view-ubo.d.ts +45 -0
  559. package/dist/record/view-ubo.d.ts.map +1 -0
  560. package/dist/render-contract.d.ts +424 -0
  561. package/dist/render-contract.d.ts.map +1 -0
  562. package/dist/render-data.d.ts +143 -0
  563. package/dist/render-data.d.ts.map +1 -0
  564. package/dist/render-graph-primitives.d.ts +76 -0
  565. package/dist/render-graph-primitives.d.ts.map +1 -0
  566. package/dist/render-pipeline.d.ts +110 -0
  567. package/dist/render-pipeline.d.ts.map +1 -0
  568. package/dist/render-system-extract.d.ts +868 -0
  569. package/dist/render-system-extract.d.ts.map +1 -0
  570. package/dist/render-system.d.ts +125 -0
  571. package/dist/render-system.d.ts.map +1 -0
  572. package/dist/scene/render-scene-types.d.ts +61 -0
  573. package/dist/scene/render-scene-types.d.ts.map +1 -0
  574. package/dist/scene/render-scene.d.ts +112 -0
  575. package/dist/scene/render-scene.d.ts.map +1 -0
  576. package/dist/scene-instances/post-spawn-resolve-joints.d.ts +30 -0
  577. package/dist/scene-instances/post-spawn-resolve-joints.d.ts.map +1 -0
  578. package/dist/shadow-atlas.d.ts +117 -0
  579. package/dist/shadow-atlas.d.ts.map +1 -0
  580. package/dist/ssao-buffers.d.ts +50 -0
  581. package/dist/ssao-buffers.d.ts.map +1 -0
  582. package/dist/ssao-config.d.ts +28 -0
  583. package/dist/ssao-config.d.ts.map +1 -0
  584. package/dist/systems/active-camera.d.ts +53 -0
  585. package/dist/systems/active-camera.d.ts.map +1 -0
  586. package/dist/systems/pass-selector.d.ts +24 -0
  587. package/dist/systems/pass-selector.d.ts.map +1 -0
  588. package/dist/systems/skin-palette-allocator.d.ts +49 -0
  589. package/dist/systems/skin-palette-allocator.d.ts.map +1 -0
  590. package/dist/systems/skin-palette-types.d.ts +14 -0
  591. package/dist/systems/skin-palette-types.d.ts.map +1 -0
  592. package/dist/systems/transparent-sort-config.d.ts +112 -0
  593. package/dist/systems/transparent-sort-config.d.ts.map +1 -0
  594. package/dist/tilemap-chunk-extract-system.d.ts +143 -0
  595. package/dist/tilemap-chunk-extract-system.d.ts.map +1 -0
  596. package/dist/typed-render-graph-primitives.d.ts +57 -0
  597. package/dist/typed-render-graph-primitives.d.ts.map +1 -0
  598. package/dist/typed-shadow-passes.d.ts +11 -0
  599. package/dist/typed-shadow-passes.d.ts.map +1 -0
  600. package/package.json +94 -0
  601. package/src/__tests__/authoring-path.unit.test.ts +23 -0
  602. package/src/__tests__/backend-selection-rhi-capture.test-d.ts +21 -0
  603. package/src/__tests__/callback-inference.test-d.ts +8 -0
  604. package/src/__tests__/cluster-binner.test.ts +272 -0
  605. package/src/__tests__/cluster-grid-default-surface.unit.test.ts +20 -0
  606. package/src/__tests__/construct-renderer-identity.unit.test.ts +23 -0
  607. package/src/__tests__/device-scope-lifecycle.unit.test.ts +151 -0
  608. package/src/__tests__/device-scope-stale-matrix.unit.test.ts +42 -0
  609. package/src/__tests__/direct-extract-consumer-contract.test-d.ts +23 -0
  610. package/src/__tests__/direct-light-snapshot.unit.test.ts +61 -0
  611. package/src/__tests__/factory-contract.integration.test.ts +280 -0
  612. package/src/__tests__/fallback-row-stride-surface.unit.test.ts +15 -0
  613. package/src/__tests__/frame-observation.contract.test.ts +112 -0
  614. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +32 -0
  615. package/src/__tests__/glyph-text-layout-recovery.unit.test.ts +167 -0
  616. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +350 -0
  617. package/src/__tests__/gpu-driven-indirect-raster.browser.test.ts +12 -0
  618. package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +16 -0
  619. package/src/__tests__/gpu-driven-production.integration.test.ts +436 -0
  620. package/src/__tests__/gpu-driven-scaling.unit.test.ts +87 -0
  621. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +271 -0
  622. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +290 -0
  623. package/src/__tests__/gpu-driven-view-reference.ts +111 -0
  624. package/src/__tests__/gpu-driven-view.browser.test.ts +30 -0
  625. package/src/__tests__/gpu-driven-view.dawn.test.ts +28 -0
  626. package/src/__tests__/gpu-driven-view.unit.test.ts +199 -0
  627. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +59 -0
  628. package/src/__tests__/gpu-scene-render-graph-gpu.ts +308 -0
  629. package/src/__tests__/gpu-scene-render-graph.browser.test.ts +19 -0
  630. package/src/__tests__/gpu-scene-render-graph.dawn.test.ts +19 -0
  631. package/src/__tests__/gpu-scene-schema.unit.test.ts +16 -0
  632. package/src/__tests__/gpu-scene.dawn.test.ts +205 -0
  633. package/src/__tests__/gpu-scene.unit.test.ts +147 -0
  634. package/src/__tests__/ibl/face-uniforms.unit.test.ts +46 -0
  635. package/src/__tests__/infinite-grid-no-vertex-probe.unit.test.ts +92 -0
  636. package/src/__tests__/injection-kind-owner.test-d.ts +14 -0
  637. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +728 -0
  638. package/src/__tests__/light-buffer-layout.unit.test.ts +40 -0
  639. package/src/__tests__/material-contract-inventory.unit.test.ts +24 -0
  640. package/src/__tests__/material-cooked-projection.unit.test.ts +150 -0
  641. package/src/__tests__/material-snapshot-mutation.integration.test.ts +53 -0
  642. package/src/__tests__/material-static-dynamic-route.unit.test.ts +94 -0
  643. package/src/__tests__/material-stride-surface.unit.test.ts +32 -0
  644. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +106 -0
  645. package/src/__tests__/mesh-material-bindings.unit.test.ts +89 -0
  646. package/src/__tests__/mesh-stride-surface.unit.test.ts +16 -0
  647. package/src/__tests__/morph-culling-reentry.dawn.test.ts +157 -0
  648. package/src/__tests__/morph-feature-gpu-work.integration.test.ts +80 -0
  649. package/src/__tests__/morph-feature-plan.unit.test.ts +53 -0
  650. package/src/__tests__/morph-visual-evidence.integration.test.ts +80 -0
  651. package/src/__tests__/nineslice-handle-surface.unit.test.ts +19 -0
  652. package/src/__tests__/post-process-error-policy-owner.unit.test.ts +201 -0
  653. package/src/__tests__/prepared-buffer-kind-owner.test-d.ts +29 -0
  654. package/src/__tests__/prepared-graphics-capability.unit.test.ts +65 -0
  655. package/src/__tests__/prepared-graphics-generation.unit.test.ts +161 -0
  656. package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +138 -0
  657. package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +29 -0
  658. package/src/__tests__/prepared-graphics-resolver.unit.test.ts +285 -0
  659. package/src/__tests__/prepared-graphics-snapshot.unit.test.ts +105 -0
  660. package/src/__tests__/prepared-graphics-store.unit.test.ts +154 -0
  661. package/src/__tests__/prepared-graphics-validation.unit.test.ts +176 -0
  662. package/src/__tests__/profiler-default-off.test.ts +22 -0
  663. package/src/__tests__/profiler-phase-catalog.test.ts +66 -0
  664. package/src/__tests__/profiler-phase-integration.test.ts +62 -0
  665. package/src/__tests__/profiler-phase-token.test.ts +79 -0
  666. package/src/__tests__/public-surface.test-d.ts +94 -0
  667. package/src/__tests__/recover-error-policy-owner.unit.test.ts +107 -0
  668. package/src/__tests__/render-error-code-owner.test-d.ts +116 -0
  669. package/src/__tests__/render-error-detail-ssot.test-d.ts +139 -0
  670. package/src/__tests__/render-error-exhaustive.test-d.ts +110 -0
  671. package/src/__tests__/render-feature-assembly.test-d.ts +43 -0
  672. package/src/__tests__/render-feature-context.test-d.ts +57 -0
  673. package/src/__tests__/render-feature-contract.test-d.ts +49 -0
  674. package/src/__tests__/render-feature-diagnostics.unit.test.ts +149 -0
  675. package/src/__tests__/render-feature-docs.unit.test.ts +89 -0
  676. package/src/__tests__/render-feature-errors.unit.test.ts +47 -0
  677. package/src/__tests__/render-feature-gpu-work.integration.test.ts +316 -0
  678. package/src/__tests__/render-feature-plan.test-d.ts +161 -0
  679. package/src/__tests__/render-feature-plan.unit.test.ts +170 -0
  680. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +90 -0
  681. package/src/__tests__/render-feature-prepared-errors.test-d.ts +79 -0
  682. package/src/__tests__/render-feature-prepared-graphics-docs.unit.test.ts +80 -0
  683. package/src/__tests__/render-feature-prepared-graphics-isolation.unit.test.ts +72 -0
  684. package/src/__tests__/render-feature-prepared-graphics-negative.test-d.ts +36 -0
  685. package/src/__tests__/render-feature-prepared-graphics.test-d.ts +74 -0
  686. package/src/__tests__/render-feature-prepared-graphics.unit.test.ts +121 -0
  687. package/src/__tests__/render-feature-public-surface.test-d.ts +57 -0
  688. package/src/__tests__/render-feature-retry.unit.test.ts +87 -0
  689. package/src/__tests__/render-feature-scheduling.unit.test.ts +110 -0
  690. package/src/__tests__/render-feature-stage-failed-policy-owner.unit.test.ts +137 -0
  691. package/src/__tests__/render-feature-stage-fault-recovery.unit.test.ts +146 -0
  692. package/src/__tests__/render-feature-visibility-context.test-d.ts +33 -0
  693. package/src/__tests__/render-feature-visibility-context.unit.test.ts +37 -0
  694. package/src/__tests__/render-feature-zero-work.unit.test.ts +76 -0
  695. package/src/__tests__/render-graph-compute-raster-gpu.ts +342 -0
  696. package/src/__tests__/render-graph-compute-raster.browser.test.ts +16 -0
  697. package/src/__tests__/render-graph-compute-raster.dawn.test.ts +22 -0
  698. package/src/__tests__/render-graph-hzb-gpu.ts +239 -0
  699. package/src/__tests__/render-graph-hzb.browser.test.ts +16 -0
  700. package/src/__tests__/render-graph-hzb.dawn.test.ts +23 -0
  701. package/src/__tests__/render-graph-primitives.unit.test.ts +22 -0
  702. package/src/__tests__/render-graph-storage-indirect-gpu.ts +162 -0
  703. package/src/__tests__/render-graph-storage-indirect.browser.test.ts +21 -0
  704. package/src/__tests__/render-graph-storage-indirect.dawn.test.ts +28 -0
  705. package/src/__tests__/render-scene-projection.unit.test.ts +168 -0
  706. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +121 -0
  707. package/src/__tests__/renderer-lifecycle.integration.test.ts +58 -0
  708. package/src/__tests__/rhi-backend-package-boundary.unit.test.ts +11 -0
  709. package/src/__tests__/scriptable-pack-consumer.test-d.ts +14 -0
  710. package/src/__tests__/shader-stage-surface.unit.test.ts +43 -0
  711. package/src/__tests__/ssao-config.unit.test.ts +36 -0
  712. package/src/__tests__/ssao-kernel-surface.unit.test.ts +14 -0
  713. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +28 -0
  714. package/src/__tests__/standard-descriptors.test-d.ts +22 -0
  715. package/src/__tests__/standard-pipeline.dawn.test.ts +61 -0
  716. package/src/__tests__/standard-pipeline.integration.test.ts +124 -0
  717. package/src/__tests__/standard-profile-oracle.unit.test.ts +62 -0
  718. package/src/__tests__/surface-configuration.unit.test.ts +91 -0
  719. package/src/__tests__/texture-usage-surface.unit.test.ts +58 -0
  720. package/src/__tests__/typed-pipeline-topology.unit.test.ts +223 -0
  721. package/src/__tests__/urp-pipeline-targets.unit.test.ts +42 -0
  722. package/src/__tests__/urp-pipeline.unit.test.ts +14 -0
  723. package/src/__tests__/vertex-color-pipeline.unit.test.ts +132 -0
  724. package/src/__tests__/vertex-layout-consumer.unit.test.ts +25 -0
  725. package/src/__tests__/visibility-diagnostics.integration.test.ts +62 -0
  726. package/src/__tests__/visibility-extract.integration.test.ts +98 -0
  727. package/src/__tests__/visibility-extract.perf.test.ts +130 -0
  728. package/src/__tests__/visibility-feature-dedup.integration.test.ts +55 -0
  729. package/src/__tests__/visibility-hidden-report.unit.test.ts +36 -0
  730. package/src/__tests__/visibility-instances.integration.test.ts +46 -0
  731. package/src/__tests__/visibility-multi-world.integration.test.ts +86 -0
  732. package/src/__tests__/visibility-producer-matrix.integration.test.ts +168 -0
  733. package/src/__tests__/visibility-producer-matrix.unit.test.ts +96 -0
  734. package/src/__tests__/visibility-public-surface.test-d.ts +27 -0
  735. package/src/__tests__/visibility-resolver.unit.test.ts +85 -0
  736. package/src/__tests__/visibility-resource-short-circuit.unit.test.ts +80 -0
  737. package/src/__tests__/visibility-snapshot-contract.unit.test.ts +60 -0
  738. package/src/__tests__/vocabulary.unit.test.ts +21 -0
  739. package/src/assembly/backend-contract.ts +57 -0
  740. package/src/assembly/factory.ts +8130 -0
  741. package/src/assembly/host-contract.ts +101 -0
  742. package/src/assembly/material/assembly.ts +48 -0
  743. package/src/assembly/material/pipeline-projection.ts +63 -0
  744. package/src/assets/asset-decoders.ts +158 -0
  745. package/src/assets/render-asset-port.ts +44 -0
  746. package/src/assets/resolve-render-asset.ts +13 -0
  747. package/src/authoring.ts +17 -0
  748. package/src/cluster-binner.ts +700 -0
  749. package/src/components/__tests__/points-lines-admission.unit.test.ts +219 -0
  750. package/src/components/__tests__/points-lines-schema.unit.test.ts +56 -0
  751. package/src/components/__tests__/schema-contract.unit.test.ts +10 -0
  752. package/src/components/__tests__/schema-parity.unit.test.ts +25 -0
  753. package/src/components/__tests__/visibility-schema.unit.test.ts +35 -0
  754. package/src/components/camera.ts +512 -0
  755. package/src/components/directional-light.ts +120 -0
  756. package/src/components/glyph-text.ts +64 -0
  757. package/src/components/index.ts +54 -0
  758. package/src/components/instances.ts +206 -0
  759. package/src/components/layer.ts +69 -0
  760. package/src/components/light-helpers.ts +188 -0
  761. package/src/components/lines.ts +18 -0
  762. package/src/components/mesh-filter.ts +60 -0
  763. package/src/components/mesh-renderer.ts +61 -0
  764. package/src/components/point-light-shadow.ts +43 -0
  765. package/src/components/point-light.ts +65 -0
  766. package/src/components/points.ts +40 -0
  767. package/src/components/post-process-params.ts +35 -0
  768. package/src/components/scene-instance.ts +193 -0
  769. package/src/components/skybox-background.ts +103 -0
  770. package/src/components/skylight.ts +97 -0
  771. package/src/components/sort-key.ts +75 -0
  772. package/src/components/spot-light.ts +124 -0
  773. package/src/components/sprite-animation.ts +168 -0
  774. package/src/components/sprite-instances.ts +179 -0
  775. package/src/components/sprite-playback-mode.ts +79 -0
  776. package/src/components/sprite-region-override.ts +105 -0
  777. package/src/components/tile-layer.ts +167 -0
  778. package/src/components/tilemap.ts +48 -0
  779. package/src/components/visibility.ts +53 -0
  780. package/src/construct-renderer.ts +67 -0
  781. package/src/debug-draw-glue.ts +48 -0
  782. package/src/device/device-scope.ts +306 -0
  783. package/src/device/gpu-residency.ts +1822 -0
  784. package/src/device/resource-types.ts +20 -0
  785. package/src/engine-metrics.ts +82 -0
  786. package/src/errors/ecs-validation.ts +16 -0
  787. package/src/errors/index.ts +3 -0
  788. package/src/errors/recover.ts +161 -0
  789. package/src/errors/render.ts +1284 -0
  790. package/src/extract/visibility.ts +120 -0
  791. package/src/features/fullscreen.ts +46 -0
  792. package/src/features/host.ts +1363 -0
  793. package/src/features/morph/morph-feature.ts +377 -0
  794. package/src/features/plan.ts +447 -0
  795. package/src/features/prepared-gpu-work.ts +959 -0
  796. package/src/features/prepared-graphics-store.ts +449 -0
  797. package/src/features/prepared-graphics.ts +420 -0
  798. package/src/features/render-graph-compute.ts +69 -0
  799. package/src/features/render-graph-contribution.ts +75 -0
  800. package/src/features/render-graph-raster.ts +332 -0
  801. package/src/features/render-graph-resources.ts +38 -0
  802. package/src/features/targets.ts +70 -0
  803. package/src/features/types.ts +103 -0
  804. package/src/features/vocabulary.ts +24 -0
  805. package/src/fullscreen-post-process-pass.ts +363 -0
  806. package/src/glyph-text-layout-system.ts +421 -0
  807. package/src/gpu-driven/batch-topology.ts +245 -0
  808. package/src/gpu-driven/production-raster.ts +695 -0
  809. package/src/gpu-driven/view-gpu.ts +703 -0
  810. package/src/gpu-resource.ts +159 -0
  811. package/src/gpu-scene-schema.ts +136 -0
  812. package/src/gpu-scene.ts +722 -0
  813. package/src/gpu-stage.ts +9 -0
  814. package/src/gpu-texture-usage.ts +12 -0
  815. package/src/gpu-usage.ts +14 -0
  816. package/src/hdrp-buffers.ts +480 -0
  817. package/src/ibl/IblPipelineCache.ts +1006 -0
  818. package/src/ibl/skylight-bind-group.ts +513 -0
  819. package/src/index.ts +129 -0
  820. package/src/inspection-types.ts +80 -0
  821. package/src/instance-buffer-cache.ts +95 -0
  822. package/src/internal.ts +9 -0
  823. package/src/lifecycle.ts +168 -0
  824. package/src/light-buffer-layout.ts +346 -0
  825. package/src/materials.ts +214 -0
  826. package/src/mesh-material-bindings.ts +103 -0
  827. package/src/pbr-pipeline.ts +1137 -0
  828. package/src/pipeline/standard-forward-lane.ts +229 -0
  829. package/src/pipeline/standard-pipeline.ts +555 -0
  830. package/src/pipeline/standard-profile.ts +65 -0
  831. package/src/pipeline-builder.ts +382 -0
  832. package/src/pipeline-spec-types.ts +28 -0
  833. package/src/pipeline-spec.ts +1231 -0
  834. package/src/plugin.ts +69 -0
  835. package/src/points-lines/__tests__/bounds.unit.test.ts +21 -0
  836. package/src/points-lines/__tests__/cache-recovery.unit.test.ts +157 -0
  837. package/src/points-lines/__tests__/inspection-lanes.integration.test.ts +146 -0
  838. package/src/points-lines/__tests__/inspection.unit.test.ts +173 -0
  839. package/src/points-lines/__tests__/lane-structural.integration.test.ts +122 -0
  840. package/src/points-lines/__tests__/points-lines.bench.ts +400 -0
  841. package/src/points-lines/__tests__/raster-lane.integration.test.ts +44 -0
  842. package/src/points-lines/__tests__/snapshot.unit.test.ts +101 -0
  843. package/src/points-lines/__tests__/view-ubo.unit.test.ts +73 -0
  844. package/src/points-lines/admission.ts +238 -0
  845. package/src/points-lines/bounds.ts +23 -0
  846. package/src/points-lines/expansion-cache.ts +215 -0
  847. package/src/points-lines/inspection.ts +97 -0
  848. package/src/points-lines/prepare.ts +177 -0
  849. package/src/points-lines/record.ts +125 -0
  850. package/src/points-lines/snapshot.ts +130 -0
  851. package/src/post-process-errors.ts +302 -0
  852. package/src/prepare/prepared-graphics-resolver.ts +456 -0
  853. package/src/record/__tests__/material-bg-cache.unit.test.ts +41 -0
  854. package/src/record/__tests__/material-slot-plan.unit.test.ts +44 -0
  855. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +41 -0
  856. package/src/record/__tests__/video-texture-view.unit.test.ts +90 -0
  857. package/src/record/frame-lighting.ts +1074 -0
  858. package/src/record/frame-snapshot.ts +500 -0
  859. package/src/record/frame-targets.ts +137 -0
  860. package/src/record/frame.ts +1598 -0
  861. package/src/record/helpers.ts +284 -0
  862. package/src/record/main-pass-geometry.ts +1065 -0
  863. package/src/record/main-pass-material.ts +1043 -0
  864. package/src/record/main-pass-sprite-draws.ts +1137 -0
  865. package/src/record/main-pass.ts +610 -0
  866. package/src/record/mesh-ssbo.ts +885 -0
  867. package/src/record/render-context.ts +384 -0
  868. package/src/record/shadow-pass.ts +698 -0
  869. package/src/record/skybox-post-pass.ts +593 -0
  870. package/src/record/typed-frame-graph.ts +461 -0
  871. package/src/record/view-ubo.ts +222 -0
  872. package/src/render-contract.ts +582 -0
  873. package/src/render-data.ts +385 -0
  874. package/src/render-graph-primitives.ts +811 -0
  875. package/src/render-pipeline.ts +259 -0
  876. package/src/render-system-extract.ts +4585 -0
  877. package/src/render-system.ts +1933 -0
  878. package/src/scene/render-scene-types.ts +67 -0
  879. package/src/scene/render-scene.ts +1087 -0
  880. package/src/scene-instances/post-spawn-resolve-joints.ts +165 -0
  881. package/src/shadow-atlas.ts +244 -0
  882. package/src/ssao-buffers.ts +334 -0
  883. package/src/ssao-config.ts +61 -0
  884. package/src/systems/active-camera.ts +116 -0
  885. package/src/systems/pass-selector.ts +49 -0
  886. package/src/systems/skin-palette-allocator.ts +251 -0
  887. package/src/systems/skin-palette-types.ts +14 -0
  888. package/src/systems/transparent-sort-config.ts +233 -0
  889. package/src/tilemap-chunk-extract-system.ts +1290 -0
  890. package/src/typed-render-graph-primitives.ts +541 -0
  891. package/src/typed-shadow-passes.ts +165 -0
@@ -0,0 +1,1137 @@
1
+ // @forgeax/engine-runtime - RenderSystem record stage: main-pass sprite draws.
2
+ // feat-20260704 M5/w31: further-split from main-pass.ts (AC-05 <=1500 lines/file).
3
+ // recordSpritePass + sprite entity/transparent/instance-buffer helpers, moved verbatim.
4
+
5
+ import type { World } from '@forgeax/engine-ecs';
6
+ import {
7
+ type BindGroup,
8
+ type Buffer,
9
+ type RenderPipeline,
10
+ RhiError,
11
+ type RhiRenderPassEncoder,
12
+ } from '@forgeax/engine-rhi';
13
+ import type { Handle, MaterialRenderState } from '@forgeax/engine-types';
14
+ import { GpuBuffer } from '../gpu-resource';
15
+ import {
16
+ GPU_BUFFER_USAGE_COPY_DST,
17
+ GPU_BUFFER_USAGE_STORAGE,
18
+ GPU_BUFFER_USAGE_UNIFORM,
19
+ } from '../gpu-usage';
20
+ import {
21
+ assembleMaterialWithSkylightEntries,
22
+ type EmissiveAoBindGroupResources,
23
+ type SkylightBindGroupResources,
24
+ } from '../ibl/skylight-bind-group';
25
+ import type { InstanceBufferCacheEntry } from '../instance-buffer-cache';
26
+ import { SPRITE_PREMULTIPLIED_ALPHA_BLEND } from '../materials';
27
+ import { SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET } from '../pbr-pipeline';
28
+ import {
29
+ buildBeginRenderPassDescriptor,
30
+ variantSetFromVertexLayoutProjection,
31
+ } from '../pipeline-spec';
32
+ import type { MaterialSnapshot, SpriteInstancesSnapshot } from '../render-system-extract';
33
+ import { worldEntityKey } from './frame-snapshot';
34
+ import { entityHasTransparentSubmesh, residentTextureView } from './main-pass-material';
35
+ import {
36
+ extractEntryResourceHandle,
37
+ getOrCreatePerEntity,
38
+ MAX_UNIFORM_INSTANCES,
39
+ MESH_PER_ENTITY_STRIDE,
40
+ packInstanceStorageBuffer,
41
+ } from './mesh-ssbo';
42
+ import type { _InternalRenderPipelineContext } from './render-context';
43
+ import { MATERIAL_PER_ENTITY_STRIDE, STANDARD_PBR_UBO_SIZE } from './render-context';
44
+
45
+ export type { SpriteInstancesSnapshot };
46
+
47
+ /**
48
+ * Build the interleaved sprite instance payload consumed by this record owner.
49
+ * The extract stage validates the two packed arrays before they reach this
50
+ * function, so the record path has one source of count-mismatch errors.
51
+ */
52
+ export function interleaveSpriteInstanceBuffer(
53
+ transforms: Float32Array,
54
+ regions: Float32Array,
55
+ includePrevious = false,
56
+ ): Float32Array {
57
+ const count = transforms.length / 16;
58
+ const stride = includePrevious ? 36 : 20;
59
+ const regionOffset = includePrevious ? 32 : 16;
60
+ const out = new Float32Array(count * stride);
61
+ for (let i = 0; i < count; i++) {
62
+ const dstBase = i * stride;
63
+ const transformBase = i * 16;
64
+ const regionBase = i * 4;
65
+ for (let k = 0; k < 16; k++) out[dstBase + k] = transforms[transformBase + k] ?? 0;
66
+ if (includePrevious) {
67
+ for (let k = 0; k < 16; k++) {
68
+ out[dstBase + 16 + k] = transforms[transformBase + k] ?? 0;
69
+ }
70
+ }
71
+ for (let k = 0; k < 4; k++) {
72
+ out[dstBase + regionOffset + k] = regions[regionBase + k] ?? 0;
73
+ }
74
+ }
75
+ return out;
76
+ }
77
+
78
+ /**
79
+ * Check whether the existing per-entity sprite buffer still matches the
80
+ * extract snapshot and interleaved byte count.
81
+ */
82
+ export function spriteInstancesCacheHit(
83
+ entry: InstanceBufferCacheEntry | undefined,
84
+ snapshot: SpriteInstancesSnapshot,
85
+ requestedBytes: number,
86
+ ): boolean {
87
+ return (
88
+ entry !== undefined &&
89
+ entry.uploadedArchVersion === snapshot.archVersion &&
90
+ entry.uploadedByteLength === requestedBytes
91
+ );
92
+ }
93
+
94
+ /**
95
+ * Decide whether the LDR record needs the transparent sprite sub-pass. This
96
+ * remains beside the sprite record owner so the frame stage and draw stage
97
+ * share the same transparent-material rule.
98
+ */
99
+ export function computeSplitLdrSprite(
100
+ validatedOrdered: readonly (
101
+ | {
102
+ readonly source: {
103
+ readonly material: MaterialSnapshot;
104
+ readonly materials?: readonly MaterialSnapshot[];
105
+ };
106
+ }
107
+ | undefined
108
+ )[],
109
+ tonemapActive: boolean,
110
+ ): boolean {
111
+ if (tonemapActive) return false;
112
+ for (const entry of validatedOrdered) {
113
+ if (entry === undefined) continue;
114
+ const materials = entry.source.materials;
115
+ if (materials !== undefined) {
116
+ if (materials.some((material) => material.transparent === true)) return true;
117
+ } else if (entry.source.material.transparent === true) {
118
+ return true;
119
+ }
120
+ }
121
+ return false;
122
+ }
123
+
124
+ /**
125
+ * feat-20260704 M3/w19: LDR sprite split sub-pass, extracted verbatim from
126
+ * recordMainPass. Runs after the geometry pass when there are sprite / LDR
127
+ * transparent entities and the split path is active (splitLdrSprite && a raw
128
+ * unorm swap-chain view exists). Ends the geometry `pass`, opens a `spritePass`
129
+ * on the resolved transparent-pass view (loadOp=load), draws the sprite / sprite-lit
130
+ * entities (fold-instanced where possible) then the generic per-submesh
131
+ * transparent PBR submeshes, and ends the sprite pass. Returns the updated
132
+ * `geometryPassEnded` flag so the caller skips the unconditional pass.end().
133
+ *
134
+ * @internal
135
+ */
136
+ export function recordSpritePass(
137
+ c: _InternalRenderPipelineContext,
138
+ pass: RhiRenderPassEncoder,
139
+ matchedIndices: Set<number> | null,
140
+ materialSlotIndices: readonly (readonly number[])[],
141
+ sampleCount: number,
142
+ resolveMaterialBindGroup: (
143
+ materialSlot: number,
144
+ submeshMaterial: MaterialSnapshot,
145
+ entityKey: number,
146
+ materialWorld: World,
147
+ ) => BindGroup,
148
+ skylightResources: SkylightBindGroupResources,
149
+ graphPass?: RhiRenderPassEncoder,
150
+ ): boolean {
151
+ const {
152
+ runtime,
153
+ pipelineState,
154
+ encoder,
155
+ msaaActive,
156
+ ldrSpritePassView,
157
+ ldrSpriteColorView,
158
+ geometryDepthView,
159
+ viewBindGroup,
160
+ splitLdrSprite,
161
+ } = c;
162
+ let geometryPassEnded = false;
163
+ if (splitLdrSprite && (graphPass !== undefined || ldrSpritePassView !== null)) {
164
+ if (graphPass === undefined) {
165
+ pass.end();
166
+ geometryPassEnded = true;
167
+ }
168
+
169
+ // feat-20260604 M2 / w9 (F-1): under MSAA the sprite sub-pass writes the
170
+ // count=4 transparent-pass view of the SAME multisample texture the
171
+ // geometry pass wrote (loadOp=load preserves geometry under sprites) and
172
+ // resolves the combined result to the single-sample transparent-pass
173
+ // view at this (last) pass end. Depth reuses the shared count=4
174
+ // multisample depth (depthLoadOp=load preserves sprite-vs-mesh occlusion).
175
+ // The single-
176
+ // sample path is byte-for-byte unchanged (writes the swap-chain view).
177
+ const spriteColorView = msaaActive ? ldrSpriteColorView : ldrSpritePassView;
178
+ // sprite-split sub-pass: forward shape with both color and depth loaded
179
+ // (preserves prior content from the main forward pass under the sprites).
180
+ // Stencil ops auto-emitted by the helper because depthFormat carries
181
+ // stencil8.
182
+ const spritePass: RhiRenderPassEncoder =
183
+ graphPass ??
184
+ encoder.beginRenderPass(
185
+ buildBeginRenderPassDescriptor(
186
+ {
187
+ // SSOT for the sprite-pass color format is the resolved transparent
188
+ // attachment. Native linear-LDR frames use graph-owned `ldrColor`
189
+ // (possibly rgba16float); swap-chain fallback frames use their raw
190
+ // storage format. WebGPU requires the attachment format and PSO
191
+ // target to match, so both are resolved by the same helper.
192
+ colorFormats: [transparentPassColorFormat(c) as GPUTextureFormat],
193
+ depthFormat: 'depth24plus-stencil8',
194
+ sampleCount: msaaActive ? 4 : 1,
195
+ },
196
+ {
197
+ colorViews: [spriteColorView],
198
+ depthView: geometryDepthView,
199
+ ...(msaaActive ? { resolveTargets: [ldrSpritePassView] } : {}),
200
+ },
201
+ 'forward',
202
+ { colorLoadOp: 'load', depthLoadOp: 'load' },
203
+ ) as never,
204
+ );
205
+
206
+ spritePass.setBindGroup(0, viewBindGroup as BindGroup, [0]);
207
+
208
+ // feat-20260625-refactor-sprite-as-transparent-mesh M3 / w14 (D-7):
209
+ // sprite PSO resolution migrated from the dedicated boot-time PSO
210
+ // fields (deleted) to the generic per-MaterialShader pipeline cache.
211
+ // feat-20260626-collapse M2 / M2-T2: blend factor pair literal moved
212
+ // to the public `SPRITE_PREMULTIPLIED_ALPHA_BLEND` named constant
213
+ // (re-exported from `@forgeax/engine-runtime`) so each AI user
214
+ // building a transparent material declares the same blend by
215
+ // reference; the previous implicit blend-state factory helper is
216
+ // gone. Cache miss still surfaces as a structured
217
+ // `shader-compile-failed` RhiError mirroring the pre-w14 behaviour.
218
+ //
219
+ // feat-20260608-tilemap-object-layer-rendering M2 / m2-t6 (D-8): sprite
220
+ // pipeline cullMode='none'. H/V flip via negative scale x/y (tilemap
221
+ // per-cell entity TRS form) inverts the triangle winding; cullMode='back'
222
+ // would throw the flipped quad away. The sprite pass runs in the
223
+ // alpha-blend transparent bucket back-to-front already, so cullMode='none'
224
+ // adds no overdraw cost. Pre-feat-20260625 the dedicated spritePipeline
225
+ // hard-coded 'none' (deleted in w14); the generic path must replicate
226
+ // it here or the cullmode-flip dawn smoke goes black on negative-scale.
227
+ const spritePremulBlend: MaterialRenderState = {
228
+ depthWriteEnabled: false,
229
+ depthCompare: 'less-equal',
230
+ cullMode: 'none',
231
+ blend: SPRITE_PREMULTIPLIED_ALPHA_BLEND,
232
+ };
233
+ // bug-20260629: PR #526 added PER_INSTANCE_REGION as a second variant
234
+ // axis on sprite.wgsl. Build BOTH variants here; the per-entity loop
235
+ // picks the right one based on whether the entity carries a
236
+ // SpriteInstances snapshot:
237
+ // - spritePH (PER_INSTANCE_REGION=false): regular per-entity sprites
238
+ // + fold-bucket instanced draws (64-byte mat4 only instance buf);
239
+ // UV region comes from the material UBO `region` slot.
240
+ // - spritePH_withRegion (PER_INSTANCE_REGION=true): SpriteInstances
241
+ // entities with 80-byte interleaved (mat4 64B + region 16B) per
242
+ // instance; UV region comes from `instances[idx].region`.
243
+ //
244
+ // Without spritePH_withRegion the SpriteInstances data was uploaded
245
+ // but the shader read bytes 64-79 as region=0 → black quads.
246
+ //
247
+ // feat-20260624-sprite-lit-shading-model-pure-2d-lighting M1' / t7:
248
+ // sprite-lit walks the same LDR transparent split pass with mirror
249
+ // PSO request shape (only materialShaderId string differs). The
250
+ // sprite-lit PSO is fetched lazily per-entity below since the pass
251
+ // mixes sprite + sprite-lit transparent entities. PSO cache strings
252
+ // are isolated by `materialShaderId` (D-11), no slot collision.
253
+ const spritePH =
254
+ runtime.getMaterialShaderPipeline?.(
255
+ 'forgeax::sprite',
256
+ /* isHdr */ false,
257
+ spritePremulBlend,
258
+ 'triangle-list',
259
+ undefined,
260
+ undefined,
261
+ 'forward',
262
+ undefined,
263
+ msaaActive ? 4 : 1,
264
+ // feat-20260625-refactor-sprite-as-transparent-mesh R2 fix-up:
265
+ // the split sub-pass PSO must use the same attachment format as the
266
+ // encoder. Native linear-LDR frames resolve graph-owned `ldrColor`
267
+ // (possibly rgba16float); swap-chain fallback frames resolve their raw
268
+ // storage format. `transparentPassColorFormat` is the single owner for
269
+ // this format so lazy PSO construction cannot fall back to the geometry
270
+ // sRGB view.
271
+ transparentPassColorFormat(c, pipelineState) as GPUTextureFormat,
272
+ ) ?? null;
273
+ const spritePH_withRegion =
274
+ runtime.getMaterialShaderPipeline?.(
275
+ 'forgeax::sprite',
276
+ /* isHdr */ false,
277
+ spritePremulBlend,
278
+ 'triangle-list',
279
+ undefined,
280
+ SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET,
281
+ 'forward',
282
+ undefined,
283
+ msaaActive ? 4 : 1,
284
+ transparentPassColorFormat(c) as GPUTextureFormat,
285
+ ) ?? null;
286
+
287
+ // bug-20260629: spritePH===null check moved OUTSIDE the entity loop so the
288
+ // sprite pass is properly ended before returning. Inside the loop the early
289
+ // `return` left spritePass open → render-pass-not-ended error every frame
290
+ // where the pipeline is still being compiled (frame 0 on first load).
291
+ //
292
+ // feat-city-glb Bug 5: a missing sprite PSO must NOT abort the whole
293
+ // sub-pass — the generic per-submesh PBR transparent loop below does not
294
+ // depend on the sprite shader. Only skip the sprite ENTITIES when spritePH
295
+ // is null (fire the diagnostic once, iff a sprite entity is actually
296
+ // present), then fall through to the PBR loop. A PBR-only transparent
297
+ // scene (e.g. a glTF BLEND decal, no sprites) renders regardless of
298
+ // whether sprite.wgsl is in the manifest.
299
+ const spriteUnavailable = spritePH === null;
300
+ let spriteUnavailableReported = false;
301
+ const reportSpriteUnavailable = (): void => {
302
+ if (spriteUnavailableReported) return;
303
+ spriteUnavailableReported = true;
304
+ runtime.errorRegistry.fire(
305
+ new RhiError({
306
+ code: 'shader-compile-failed',
307
+ expected:
308
+ 'manifest entries include sprite.wgsl + the engine triple (pbr + unlit + tonemap)',
309
+ hint: 'verify @forgeax/engine-vite-plugin-shader emits manifest.json with the 4 engine entries (sprite.wgsl is required when spawning sprite materials); check vite plugin engineEntries option',
310
+ }),
311
+ );
312
+ };
313
+
314
+ // feat-20260624 M1' / t7: parallel sprite-lit PSO request — same
315
+ // arg shape, only materialShaderId differs.
316
+ const spriteLitPH =
317
+ runtime.getMaterialShaderPipeline?.(
318
+ 'forgeax::sprite-lit',
319
+ /* isHdr */ false,
320
+ spritePremulBlend,
321
+ 'triangle-list',
322
+ undefined,
323
+ undefined,
324
+ 'forward',
325
+ undefined,
326
+ msaaActive ? 4 : 1,
327
+ transparentPassColorFormat(c) as GPUTextureFormat,
328
+ ) ?? null;
329
+
330
+ recordSpriteEntityDraws(
331
+ c,
332
+ spritePass,
333
+ matchedIndices,
334
+ skylightResources,
335
+ spritePH,
336
+ spritePH_withRegion,
337
+ spriteLitPH,
338
+ spriteUnavailable,
339
+ reportSpriteUnavailable,
340
+ );
341
+
342
+ // feat-city-glb Bug 5 (per-submesh transparency): generic per-submesh PBR
343
+ // draws in the LDR blend sub-pass. The sprite loop above handles only true
344
+ // sprite / sprite-lit entities (whole-mesh sprite PSO). EVERY non-sprite
345
+ // transparent material — built-in PBR, single- or multi-submesh, incl.
346
+ // glTF alphaMode=BLEND (the crosswalk decal submesh AND the 4.3-blending
347
+ // window quad) — is drawn here with its real shader + per-submesh
348
+ // geometry, reusing the geometry pass's PBR machinery but rendering into
349
+ // the resolved transparent attachment (colorFormatOverride =
350
+ // transparentPassColorFormat(c)).
351
+ // Opaque submeshes of a mixed mesh were already drawn in the geometry pass
352
+ // (per-submesh skip there).
353
+ //
354
+ // Non-skinned, non-instanced (glTF static meshes): group 2 = the shared
355
+ // frame meshBindGroup with the per-entity dynamic offset; group 3 = the
356
+ // identity instance BG (drawIndexed instanceCount=1). Skinned / instanced
357
+ // transparent submeshes are OOS here (no such content) and fall through.
358
+ recordSpriteTransparentPbrDraws(
359
+ c,
360
+ spritePass,
361
+ matchedIndices,
362
+ materialSlotIndices,
363
+ sampleCount,
364
+ resolveMaterialBindGroup,
365
+ );
366
+
367
+ if (graphPass === undefined) spritePass.end();
368
+ }
369
+ return geometryPassEnded;
370
+ }
371
+
372
+ /**
373
+ * feat-20260704 M3/w19: generic per-submesh transparent PBR draws in the LDR
374
+ * blend sub-pass, extracted verbatim from the sprite split pass. Every
375
+ * non-sprite transparent material (built-in PBR, single- or multi-submesh, incl.
376
+ * glTF alphaMode=BLEND) draws here with its real shader + per-submesh geometry,
377
+ * reusing the geometry pass's PBR machinery but rendering into the resolved
378
+ * transparent attachment (colorFormatOverride = transparentPassColorFormat(c)). Opaque submeshes of a
379
+ * mixed mesh were already drawn in the geometry pass (per-submesh skip there).
380
+ * Sprites are handled by the sprite loop; skinned / instanced transparent
381
+ * submeshes are OOS here and fall through.
382
+ *
383
+ * @internal
384
+ */
385
+ function recordSpriteTransparentPbrDraws(
386
+ c: _InternalRenderPipelineContext,
387
+ spritePass: RhiRenderPassEncoder,
388
+ matchedIndices: Set<number> | null,
389
+ materialSlotIndices: readonly (readonly number[])[],
390
+ sampleCount: number,
391
+ resolveMaterialBindGroup: (
392
+ materialSlot: number,
393
+ submeshMaterial: MaterialSnapshot,
394
+ entityKey: number,
395
+ materialWorld: World,
396
+ ) => BindGroup,
397
+ ): void {
398
+ const { runtime, pipelineState, frameState, bindGroupCounts, validatedOrdered, meshBindGroup } =
399
+ c;
400
+ let lastPbrSubPipelineHandle: typeof pipelineState.unlitPipeline = null;
401
+ let lastPbrSubVertexBuffer: GpuBuffer | null = null;
402
+ let lastPbrSubIndexBuffer: GpuBuffer | null = null;
403
+ for (let i = 0; i < validatedOrdered.length; i++) {
404
+ const entry = validatedOrdered[i];
405
+ if (entry === undefined) continue;
406
+ if (matchedIndices !== null && !matchedIndices.has(entry.renderableIndex)) continue;
407
+ // Sprites are handled by the sprite loop above; skip them here.
408
+ const entShaderId = entry.source.material.materialShaderId;
409
+ const entIsSprite = entShaderId === 'forgeax::sprite' || entShaderId === 'forgeax::sprite-lit';
410
+ if (entIsSprite) continue;
411
+ // Only entities that carry at least one transparent submesh reach a draw
412
+ // (single-submesh transparent PBR and mixed opaque+transparent meshes).
413
+ if (!entityHasTransparentSubmesh(entry.source)) continue;
414
+ // Skinned / instanced transparent submeshes are not supported in this
415
+ // sub-pass path (no such content today); skip to avoid mis-binding.
416
+ if (entry.source.skin !== undefined || entry.source.instances !== undefined) continue;
417
+
418
+ const matsForRebind = entry.source.materials;
419
+ if (entry.mesh.vertexBuffer !== lastPbrSubVertexBuffer) {
420
+ spritePass.setVertexBuffer(0, entry.mesh.vertexBuffer.handle);
421
+ lastPbrSubVertexBuffer = entry.mesh.vertexBuffer;
422
+ }
423
+ if (
424
+ entry.mesh.indexed &&
425
+ entry.mesh.indexBuffer !== null &&
426
+ entry.mesh.indexBuffer !== lastPbrSubIndexBuffer
427
+ ) {
428
+ spritePass.setIndexBuffer(entry.mesh.indexBuffer.handle, entry.mesh.indexFormat);
429
+ lastPbrSubIndexBuffer = entry.mesh.indexBuffer;
430
+ }
431
+ spritePass.setBindGroup(2, meshBindGroup as BindGroup, [i * MESH_PER_ENTITY_STRIDE]);
432
+ // Identity instance BG (instanceCount=1); reuse the per-entity cache.
433
+ const identityInstBg: BindGroup = getOrCreatePerEntity(
434
+ frameState.instancesBgPerEntity,
435
+ worldEntityKey(entry.source.worldId, entry.source.entityKey),
436
+ [pipelineState.identityInstanceBuffer],
437
+ 'instances',
438
+ () => {
439
+ const result = runtime.device.createBindGroup({
440
+ label: 'pbr-transparent-sub-instances-bg',
441
+ layout: pipelineState.instancesBindGroupLayout,
442
+ entries: [
443
+ {
444
+ binding: 0,
445
+ resource: {
446
+ kind: 'buffer',
447
+ value: { buffer: pipelineState.identityInstanceBuffer },
448
+ },
449
+ },
450
+ ],
451
+ });
452
+ if (!result.ok) throw result.error;
453
+ return result.value;
454
+ },
455
+ bindGroupCounts,
456
+ );
457
+ spritePass.setBindGroup(3, identityInstBg);
458
+
459
+ const subVariantSet = frameState.isHdrpActive
460
+ ? ''
461
+ : 'CLUSTER_FORWARD_AVAILABLE=false+STORAGE_BUFFER_AVAILABLE=true';
462
+ const projectionVariantSetResult = variantSetFromVertexLayoutProjection(
463
+ entry.mesh.layoutProjection,
464
+ subVariantSet,
465
+ );
466
+ if (!projectionVariantSetResult.ok) {
467
+ runtime.errorRegistry.fire(projectionVariantSetResult.error);
468
+ continue;
469
+ }
470
+ const projectionVariantSet = projectionVariantSetResult.value;
471
+
472
+ for (let smIdx = 0; smIdx < entry.mesh.submeshes.length; smIdx++) {
473
+ const sm = entry.mesh.submeshes[smIdx];
474
+ if (sm === undefined) continue;
475
+ const matSlotIdx = sm.materialSlot;
476
+ const submeshMaterial = matsForRebind[matSlotIdx] ?? entry.source.material;
477
+ // Only transparent submeshes belong in this blend sub-pass; opaque
478
+ // submeshes were drawn in the geometry pass.
479
+ if (submeshMaterial.transparent !== true) continue;
480
+ const smShaderId = submeshMaterial.materialShaderId;
481
+ if (smShaderId === undefined) continue;
482
+
483
+ // Bind the per-submesh material BG first (mirrors the geometry pass
484
+ // order), then resolve the PSO; a first-frame async-compile miss skips
485
+ // only the draw, not the BG (one transient frame, PSO flows in next).
486
+ const materialSlot = materialSlotIndices[i]?.[matSlotIdx] ?? materialSlotIndices[i]?.[0] ?? 0;
487
+ const subBg = resolveMaterialBindGroup(
488
+ materialSlot,
489
+ submeshMaterial,
490
+ entry.source.entityKey,
491
+ entry.world ?? c.world,
492
+ );
493
+ spritePass.setBindGroup(1, subBg, [materialSlot * MATERIAL_PER_ENTITY_STRIDE]);
494
+
495
+ const subPipeline =
496
+ runtime.getMaterialShaderPipeline?.(
497
+ smShaderId,
498
+ /* isHdr */ false,
499
+ submeshMaterial.renderState,
500
+ sm.topology,
501
+ entry.mesh.indexFormat,
502
+ projectionVariantSet,
503
+ 'forward',
504
+ undefined,
505
+ sampleCount,
506
+ // Non-sRGB blend view (same override the sprite path uses).
507
+ transparentPassColorFormat(c) as GPUTextureFormat,
508
+ undefined,
509
+ undefined,
510
+ undefined,
511
+ entry.mesh.layoutProjection,
512
+ ) ?? null;
513
+ if (subPipeline === null) continue;
514
+
515
+ if (lastPbrSubPipelineHandle !== subPipeline) {
516
+ spritePass.setPipeline(subPipeline);
517
+ lastPbrSubPipelineHandle = subPipeline;
518
+ }
519
+ if (entry.mesh.indexed) {
520
+ spritePass.drawIndexed(sm.indexCount, 1, sm.indexOffset, 0, 0);
521
+ } else {
522
+ spritePass.draw(sm.vertexCount, 1, 0, 0);
523
+ }
524
+ }
525
+ }
526
+ }
527
+
528
+ /**
529
+ * feat-20260704 M3/w19: per-entity sprite / sprite-lit draw loop for the LDR
530
+ * blend sub-pass, extracted verbatim from the sprite split pass. Selects the
531
+ * sprite vs sprite-lit PSO per entity, resolves the per-entity / fold-bucket
532
+ * instance buffer (fold-instanced drawIndexed where a fold bucket applies and
533
+ * the entity has no explicit Instances), uploads the per-entity sprite material
534
+ * UBO slice, binds view / material / mesh / instances groups, and issues the
535
+ * draw. Non-sprite transparent submeshes are drawn separately
536
+ * (recordSpriteTransparentPbrDraws). The loop-invariant sprite PSO handles + the
537
+ * once-per-frame sprite-unavailable diagnostic are threaded in.
538
+ *
539
+ * @internal
540
+ */
541
+ function recordSpriteEntityDraws(
542
+ c: _InternalRenderPipelineContext,
543
+ spritePass: RhiRenderPassEncoder,
544
+ matchedIndices: Set<number> | null,
545
+ skylightResources: SkylightBindGroupResources,
546
+ spritePH: RenderPipeline | null,
547
+ spritePH_withRegion: RenderPipeline | null,
548
+ spriteLitPH: RenderPipeline | null,
549
+ spriteUnavailable: boolean,
550
+ reportSpriteUnavailable: () => void,
551
+ ): void {
552
+ const {
553
+ runtime,
554
+ world,
555
+ store,
556
+ pipelineState,
557
+ frameState,
558
+ bindGroupCounts,
559
+ validatedOrdered,
560
+ meshBindGroup,
561
+ foldDispatchPlan,
562
+ materialSlotIndices,
563
+ } = c;
564
+ let lastSpritePipelineHandle: RenderPipeline | null = null;
565
+ let lastSpriteVertexBuffer: GpuBuffer | null = null;
566
+ let lastSpriteIndexBuffer: GpuBuffer | null = null;
567
+ for (let i = 0; i < validatedOrdered.length; i++) {
568
+ const spriteEntry = validatedOrdered[i];
569
+ // feat-20260625 M3 / w13: sub-pass entity filter migrated from
570
+ // `shadingModel === 'sprite'` to `transparent === true` — the
571
+ // shadingModel arm is gone post-feat (plan-strategy D-3).
572
+ if (spriteEntry === undefined || spriteEntry.source.material.transparent !== true) continue;
573
+ // feat-city-glb Bug 5 (per-submesh transparency): this loop is the
574
+ // SPRITE path (whole-mesh sprite / sprite-lit PSO). Non-sprite
575
+ // transparent materials (built-in PBR, incl. glTF alphaMode=BLEND) are
576
+ // drawn per-submesh with their real shader in the dedicated PBR loop
577
+ // below — so skip them here. Previously the 4.3-blending window (a PBR
578
+ // material) was drawn through here with the sprite shader; it now flows
579
+ // through the PBR loop, which is both correct and multi-submesh-capable.
580
+ {
581
+ const sid = spriteEntry.source.material.materialShaderId;
582
+ const isSpriteShader = sid === 'forgeax::sprite' || sid === 'forgeax::sprite-lit';
583
+ if (!isSpriteShader) continue;
584
+ }
585
+ // Sprite PSO unavailable (sprite.wgsl absent / still compiling): skip
586
+ // sprite entities and report once, but do NOT abort the sub-pass — the
587
+ // PBR transparent loop below is independent of the sprite shader.
588
+ if (spriteUnavailable) {
589
+ reportSpriteUnavailable();
590
+ continue;
591
+ }
592
+
593
+ // feat-20260622-chunk-gpu-instancing-sprite-tilemap M1 / w4-record-swap
594
+ // (D-1): fold-bucket non-head member — skip; the bucket head emits one
595
+ // instanced drawIndexed covering all members.
596
+ if (foldDispatchPlan?.skipIndices.has(i) === true) continue;
597
+ const foldHeadBucket = foldDispatchPlan?.headBuckets.get(i);
598
+
599
+ // feat-20260609 M2: skip entities that don't match the pass selector.
600
+ if (matchedIndices !== null && !matchedIndices.has(spriteEntry.renderableIndex)) continue;
601
+
602
+ // feat-20260624 M1' / t7: select sprite vs sprite-lit PSO per
603
+ // entity. Both paths share the LDR sub-pass + the same UBO
604
+ // layout; only the shader module + fragment math differ. PSO
605
+ // cache strings are isolated by materialShaderId (D-11) so
606
+ // routing here keeps the cache slots disjoint.
607
+ //
608
+ // bug-20260629: SpriteInstances entities additionally need the
609
+ // PER_INSTANCE_REGION=true variant so the shader reads UV region
610
+ // from the 80B-per-instance interleaved buffer rather than from
611
+ // the material UBO. Only the base sprite path has the per-instance
612
+ // region variant compiled; sprite-lit + non-instances entities
613
+ // keep the PER_INSTANCE_REGION=false variant.
614
+ const entityShaderId = spriteEntry.source.material.materialShaderId;
615
+ const useRegionVariant =
616
+ entityShaderId !== 'forgeax::sprite-lit' && spriteEntry.source.spriteInstances !== undefined;
617
+ const activeSpritePH =
618
+ entityShaderId === 'forgeax::sprite-lit'
619
+ ? spriteLitPH
620
+ : useRegionVariant
621
+ ? spritePH_withRegion
622
+ : spritePH;
623
+ if (activeSpritePH === null) {
624
+ // Variant not yet compiled — for PER_INSTANCE_REGION=true the
625
+ // variant cache fill is async on first use (mirrors the
626
+ // spritePH===null guard above); falling back to the non-region
627
+ // variant would render black quads (region read returns 0).
628
+ // For sprite-lit the manifest may lack sprite-lit.wgsl; either
629
+ // way fail-safe-skip is the closest the renderer can get to
630
+ // "show nothing visibly wrong" without ending the sprite pass
631
+ // (which would drop remaining sprite entities for the frame).
632
+ if (entityShaderId === 'forgeax::sprite-lit') {
633
+ runtime.errorRegistry.fire(
634
+ new RhiError({
635
+ code: 'shader-compile-failed',
636
+ expected:
637
+ 'manifest entries include sprite.wgsl + sprite-lit.wgsl (when sprite-lit materials are used) + the engine triple (pbr + unlit + tonemap)',
638
+ hint: 'verify @forgeax/engine-vite-plugin-shader emits manifest.json with sprite.wgsl AND sprite-lit.wgsl entries; check vite plugin engineEntries option',
639
+ }),
640
+ );
641
+ }
642
+ continue;
643
+ }
644
+ if (lastSpritePipelineHandle !== activeSpritePH) {
645
+ spritePass.setPipeline(activeSpritePH);
646
+ lastSpritePipelineHandle = activeSpritePH;
647
+ }
648
+
649
+ if (spriteEntry.mesh.vertexBuffer !== lastSpriteVertexBuffer) {
650
+ spritePass.setVertexBuffer(0, spriteEntry.mesh.vertexBuffer.handle);
651
+ lastSpriteVertexBuffer = spriteEntry.mesh.vertexBuffer;
652
+ }
653
+ if (
654
+ spriteEntry.mesh.indexBuffer !== null &&
655
+ spriteEntry.mesh.indexBuffer !== lastSpriteIndexBuffer
656
+ ) {
657
+ spritePass.setIndexBuffer(spriteEntry.mesh.indexBuffer.handle, spriteEntry.mesh.indexFormat);
658
+ lastSpriteIndexBuffer = spriteEntry.mesh.indexBuffer;
659
+ }
660
+
661
+ // Instance buffer resolution: same cap-gate logic as the geometry
662
+ // pass entity loop; sprites with Instances (e.g. hello-sprite-atlas
663
+ // 100-instance walk-cycle) require per-entity storage buffer upload.
664
+ // SSOT mirror of geometry pass instances block above (~line 1610):
665
+ // identical cap-gate sequence (storageBuffer cap → limit-exceeded →
666
+ // cache-lookup → createBuffer → writeBuffer); variable names carry
667
+ // "sprite" prefix; logic divergence would be a bug.
668
+ //
669
+ // feat-20260622-chunk-gpu-instancing-sprite-tilemap M1 / w4-record-swap
670
+ // (D-1): when `foldHeadBucket !== undefined` AND the sprite entity has
671
+ // no explicit Instances component, assemble the bucket transforms into
672
+ // a transient instance buffer + override `spriteInstanceCount =
673
+ // bucket.bucketSize`. The mesh slot at `i*MESH_PER_ENTITY_STRIDE` was
674
+ // already overwritten to identity in the mesh SSBO upload loop above,
675
+ // so the shader computes `world = identity * bucket.transforms[idx] *
676
+ // pos`, per-instance correct. Entities with explicit Instances bypass
677
+ // fold (their per-entity Instances semantic wins); bucket key forces
678
+ // such an entity to be a singleton bucket in practice because its
679
+ // material is distinct or unfolded, but defensively check here as a
680
+ // belt-and-suspenders guard.
681
+ let spriteInstanceBuffer: Buffer = pipelineState.identityInstanceBuffer;
682
+ let spriteInstanceCount = 1;
683
+ const spriteInst = spriteEntry.source.instances;
684
+ const useFold = foldHeadBucket !== undefined && spriteInst === undefined;
685
+ if (useFold && foldHeadBucket !== undefined) {
686
+ // w6 (D-8): bucket transient buffer reuse — composite cacheKey from
687
+ // (materialHandle, layer, validatedOrdered head index) so the
688
+ // existing `frameState.instanceBuffers` byteLength/archVersion path
689
+ // covers static steady-state upload-skip. Numeric Map<number,…> key
690
+ // requires a 32-bit-safe fold; we use a negative number-space prefix
691
+ // (-1, -2, ...) by `((materialHandle << 16) | i)` shifted into the
692
+ // negative half so it never collides with positive entity-Instances
693
+ // cacheKeys (which are extracted from Instances component cacheKey
694
+ // numeric ids, always non-negative). The `archVersion` proxy is
695
+ // bucketSize (a structural-shape signal) so static frames hit the
696
+ // cache.
697
+ const bucketCacheKey = -1 - (((foldHeadBucket.materialHandle & 0xffff) << 16) | (i & 0xffff));
698
+ const uniformFallback = runtime.device.caps.storageBuffer === false;
699
+ const bucketPayload = uniformFallback
700
+ ? foldHeadBucket.transforms
701
+ : packInstanceStorageBuffer(foldHeadBucket.transforms);
702
+ const bucketBytes = bucketPayload.byteLength;
703
+ const bucketBufUsage = uniformFallback
704
+ ? GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST
705
+ : GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST;
706
+ const cachedBucket = frameState.instanceBuffers.get(bucketCacheKey);
707
+ let activeBucket: InstanceBufferCacheEntry | null = null;
708
+ if (
709
+ cachedBucket !== undefined &&
710
+ cachedBucket.uploadedArchVersion === foldHeadBucket.bucketSize &&
711
+ cachedBucket.uploadedByteLength === bucketBytes
712
+ ) {
713
+ activeBucket = cachedBucket;
714
+ } else if (bucketBytes > 0) {
715
+ const bufRes = runtime.device.createBuffer({
716
+ size: bucketBytes,
717
+ usage: bucketBufUsage,
718
+ mappedAtCreation: false,
719
+ });
720
+ if (!bufRes.ok) {
721
+ runtime.errorRegistry.fire(bufRes.error);
722
+ } else {
723
+ if (cachedBucket !== undefined && !cachedBucket.buffer.isDestroyed) {
724
+ const r = cachedBucket.buffer.destroy();
725
+ if (!r.ok) runtime.errorRegistry.fire(r.error);
726
+ }
727
+ const newBuf = new GpuBuffer(runtime.device, bufRes.value);
728
+ activeBucket = {
729
+ buffer: newBuf,
730
+ uploadedArchVersion: foldHeadBucket.bucketSize,
731
+ uploadedByteLength: bucketBytes,
732
+ };
733
+ frameState.instanceBuffers.set(bucketCacheKey, activeBucket);
734
+ }
735
+ }
736
+ if (activeBucket !== null) {
737
+ const writeRes = runtime.device.queue.writeBuffer(
738
+ activeBucket.buffer.handle,
739
+ 0,
740
+ bucketPayload,
741
+ );
742
+ if (!writeRes.ok) {
743
+ runtime.errorRegistry.fire(writeRes.error);
744
+ } else {
745
+ spriteInstanceBuffer = activeBucket.buffer.handle;
746
+ spriteInstanceCount = foldHeadBucket.bucketSize;
747
+ }
748
+ }
749
+ } else if (spriteInst !== undefined) {
750
+ const uniformFallback = runtime.device.caps.storageBuffer === false;
751
+ let spriteBufUsage = GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST;
752
+
753
+ if (uniformFallback) {
754
+ if (spriteInst.instanceCount > MAX_UNIFORM_INSTANCES) {
755
+ runtime.errorRegistry.fire(
756
+ new RhiError({
757
+ code: 'limit-exceeded',
758
+ expected: `instance count <= ${MAX_UNIFORM_INSTANCES} (uniform fallback cap)`,
759
+ hint: `reduce instance count to ${MAX_UNIFORM_INSTANCES} or use a WebGPU-capable backend`,
760
+ detail: {
761
+ maxStorageBufferBindingSize: MAX_UNIFORM_INSTANCES * 64,
762
+ requestedBytes: spriteInst.instanceCount * 64,
763
+ },
764
+ }),
765
+ );
766
+ spriteInstanceCount = spriteInst.instanceCount;
767
+ spriteInstanceBuffer = pipelineState.identityInstanceBuffer;
768
+ const spriteInstBgResult = runtime.device.createBindGroup({
769
+ label: 'sprite-pass-instances-bg',
770
+ layout: pipelineState.instancesBindGroupLayout,
771
+ entries: [
772
+ {
773
+ binding: 0,
774
+ resource: {
775
+ kind: 'buffer',
776
+ value: { buffer: spriteInstanceBuffer },
777
+ },
778
+ },
779
+ ],
780
+ });
781
+ if (!spriteInstBgResult.ok) throw spriteInstBgResult.error;
782
+ spritePass.setBindGroup(3, spriteInstBgResult.value as BindGroup);
783
+ spritePass.drawIndexed(spriteEntry.mesh.indexCount, spriteInstanceCount, 0, 0, 0);
784
+ continue;
785
+ }
786
+ spriteBufUsage = GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST;
787
+ }
788
+
789
+ {
790
+ const instancePayload = uniformFallback
791
+ ? spriteInst.transforms
792
+ : packInstanceStorageBuffer(spriteInst.transforms);
793
+ const requestedBytes = instancePayload.byteLength;
794
+ const cap = runtime.device.limits.maxStorageBufferBindingSize;
795
+ if (typeof cap === 'number' && requestedBytes > cap) {
796
+ runtime.errorRegistry.fire(
797
+ new RhiError({
798
+ code: 'limit-exceeded',
799
+ expected: `requestedBytes (${requestedBytes}) <= maxStorageBufferBindingSize (${cap})`,
800
+ hint: 'reduce instance count to fit within device.limits.maxStorageBufferBindingSize, or split transforms across multiple Instances entries',
801
+ detail: {
802
+ maxStorageBufferBindingSize: cap,
803
+ requestedBytes,
804
+ },
805
+ }),
806
+ );
807
+ } else {
808
+ const cachedSprite = frameState.instanceBuffers.get(
809
+ worldEntityKey(spriteEntry.source.worldId, spriteInst.cacheKey),
810
+ );
811
+ let activeSprite: InstanceBufferCacheEntry | null = null;
812
+ if (
813
+ cachedSprite !== undefined &&
814
+ cachedSprite.uploadedArchVersion === spriteInst.archVersion &&
815
+ cachedSprite.uploadedByteLength === requestedBytes
816
+ ) {
817
+ activeSprite = cachedSprite;
818
+ } else if (requestedBytes > 0) {
819
+ const bufRes = runtime.device.createBuffer({
820
+ size: requestedBytes,
821
+ usage: spriteBufUsage,
822
+ mappedAtCreation: false,
823
+ });
824
+ if (!bufRes.ok) {
825
+ runtime.errorRegistry.fire(bufRes.error);
826
+ } else {
827
+ // feat-20260619 M4 / F12: destroy the old cached buffer
828
+ // before replacing it with the new one (D-6).
829
+ if (cachedSprite !== undefined && !cachedSprite.buffer.isDestroyed) {
830
+ const r = cachedSprite.buffer.destroy();
831
+ if (!r.ok) runtime.errorRegistry.fire(r.error);
832
+ }
833
+ const newBuf = new GpuBuffer(runtime.device, bufRes.value);
834
+ activeSprite = {
835
+ buffer: newBuf,
836
+ uploadedArchVersion: spriteInst.archVersion,
837
+ uploadedByteLength: requestedBytes,
838
+ };
839
+ frameState.instanceBuffers.set(
840
+ worldEntityKey(spriteEntry.source.worldId, spriteInst.cacheKey),
841
+ activeSprite,
842
+ );
843
+ }
844
+ }
845
+ if (activeSprite !== null) {
846
+ const writeRes = runtime.device.queue.writeBuffer(
847
+ activeSprite.buffer.handle,
848
+ 0,
849
+ instancePayload,
850
+ );
851
+ if (!writeRes.ok) {
852
+ runtime.errorRegistry.fire(writeRes.error);
853
+ } else {
854
+ spriteInstanceBuffer = activeSprite.buffer.handle;
855
+ spriteInstanceCount = Math.max(1, spriteInst.instanceCount);
856
+ }
857
+ }
858
+ }
859
+ }
860
+ }
861
+
862
+ // feat-20260625-sprite-instances-and-tilemap-terrain-static-batch
863
+ // M3 / w11: SpriteInstances 80B-per-instance interleaved upload path.
864
+ // SSOT for the per-entity 2D mat4 + per-instance UV region buffer
865
+ // (plan-strategy D-1 interleaved single buffer + single binding slot;
866
+ // D-9 cacheKey = entity packed u32). The extract-stage validator
867
+ // (M3 / w10) enforces the XOR contract `Instances XOR SpriteInstances`
868
+ // (sprite-instances-mutually-exclusive-with-instances), so the
869
+ // legacy `spriteInst` block above and this block are never both
870
+ // active for the same entity.
871
+ const _si = resolveSpriteInstancesBuffer(
872
+ c,
873
+ spriteEntry,
874
+ spriteInstanceBuffer,
875
+ spriteInstanceCount,
876
+ );
877
+ spriteInstanceBuffer = _si.buffer;
878
+ spriteInstanceCount = _si.count;
879
+
880
+ // M3 / w12: LDR sprite split pass per-entity instances BG cache.
881
+ // Same pattern as #7.
882
+ const spriteInstancesBg: BindGroup = getOrCreatePerEntity(
883
+ frameState.instancesBgPerEntity,
884
+ worldEntityKey(spriteEntry.source.worldId, spriteEntry.source.entityKey),
885
+ [spriteInstanceBuffer],
886
+ 'instances',
887
+ () => {
888
+ const result = runtime.device.createBindGroup({
889
+ label: 'sprite-pass-instances-bg',
890
+ layout: pipelineState.instancesBindGroupLayout,
891
+ entries: [
892
+ {
893
+ binding: 0,
894
+ resource: {
895
+ kind: 'buffer',
896
+ value: { buffer: spriteInstanceBuffer },
897
+ },
898
+ },
899
+ ],
900
+ });
901
+ if (!result.ok) throw result.error;
902
+ return result.value;
903
+ },
904
+ bindGroupCounts,
905
+ );
906
+
907
+ spritePass.setBindGroup(2, meshBindGroup as BindGroup, [i * MESH_PER_ENTITY_STRIDE]);
908
+
909
+ // Per-entity sprite material bind group: same standard PBR user-region
910
+ // layout as in the geometry pass sprite branch + Skylight merged entries
911
+ // the geometry pass sprite branch + Skylight merged entries (same
912
+ // skylightResources in scope from above). Texture view is resolved
913
+ // from the sprite material's baseColorTexture handle.
914
+ const spriteTexHandle = spriteEntry.source.material.baseColorTexture as
915
+ | Handle<'TextureAsset', 'shared'>
916
+ | undefined;
917
+ let spriteTexView = pipelineState.defaultWhiteTextureView;
918
+ if (spriteTexHandle !== undefined) {
919
+ const tv = residentTextureView(spriteEntry.world ?? world, store, runtime, spriteTexHandle);
920
+ if (tv !== undefined) spriteTexView = tv as never;
921
+ }
922
+ const spritePassBaseMaterialEntries = [
923
+ {
924
+ binding: 0,
925
+ resource: {
926
+ kind: 'buffer' as const,
927
+ value: {
928
+ buffer: pipelineState.materialUniformBuffer.buffer,
929
+ offset: 0,
930
+ size: STANDARD_PBR_UBO_SIZE,
931
+ },
932
+ },
933
+ },
934
+ {
935
+ binding: 1,
936
+ resource: { kind: 'sampler' as const, value: pipelineState.nearestSampler },
937
+ },
938
+ { binding: 2, resource: { kind: 'textureView' as const, value: spriteTexView } },
939
+ {
940
+ binding: 3,
941
+ resource: { kind: 'sampler' as const, value: pipelineState.defaultSampler },
942
+ },
943
+ {
944
+ binding: 4,
945
+ resource: {
946
+ kind: 'textureView' as const,
947
+ value: pipelineState.defaultWhiteTextureView,
948
+ },
949
+ },
950
+ {
951
+ binding: 5,
952
+ resource: { kind: 'sampler' as const, value: pipelineState.defaultSampler },
953
+ },
954
+ {
955
+ binding: 6,
956
+ resource: {
957
+ kind: 'textureView' as const,
958
+ value: pipelineState.defaultNormalTextureView,
959
+ },
960
+ },
961
+ {
962
+ binding: 7,
963
+ resource: { kind: 'sampler' as const, value: pipelineState.defaultSampler },
964
+ },
965
+ {
966
+ binding: 8,
967
+ resource: {
968
+ kind: 'textureView' as const,
969
+ value: pipelineState.defaultWhiteTextureView,
970
+ },
971
+ },
972
+ {
973
+ binding: 9,
974
+ resource: { kind: 'sampler' as const, value: pipelineState.defaultSampler },
975
+ },
976
+ {
977
+ binding: 10,
978
+ resource: {
979
+ kind: 'textureView' as const,
980
+ value: pipelineState.defaultWhiteTextureView,
981
+ },
982
+ },
983
+ {
984
+ binding: 11,
985
+ resource: { kind: 'sampler' as const, value: pipelineState.defaultSampler },
986
+ },
987
+ {
988
+ binding: 12,
989
+ resource: {
990
+ kind: 'textureView' as const,
991
+ value: pipelineState.defaultWhiteTextureView,
992
+ },
993
+ },
994
+ ];
995
+ const spritePassEmissiveAo: EmissiveAoBindGroupResources = {
996
+ emissiveSampler: pipelineState.defaultSampler,
997
+ emissiveView: pipelineState.defaultWhiteTextureView,
998
+ occlusionSampler: pipelineState.defaultSampler,
999
+ occlusionView: pipelineState.defaultWhiteTextureView,
1000
+ };
1001
+ const spritePassMergedEntries = assembleMaterialWithSkylightEntries(
1002
+ spritePassBaseMaterialEntries,
1003
+ skylightResources,
1004
+ spritePassEmissiveAo,
1005
+ );
1006
+
1007
+ // Sprite-pass material BG cache: keyed on shader id (shared across all
1008
+ // sprite entities) so entities using the same atlas texture share one
1009
+ // BindGroup instead of creating one per entity (O5 fix — inner WeakMap
1010
+ // chain naturally deduplicates by GPU resource object identity, so two
1011
+ // entities with different atlases still get distinct BGs).
1012
+ const spritePassBg: BindGroup = getOrCreatePerEntity(
1013
+ frameState.materialBgShared,
1014
+ 'forgeax::sprite',
1015
+ spritePassMergedEntries.map((e) => extractEntryResourceHandle(e)),
1016
+ 'sprite-pass-material',
1017
+ () => {
1018
+ const result = runtime.device.createBindGroup({
1019
+ label: 'sprite-pass-material-bg',
1020
+ layout: pipelineState.materialBindGroupLayout,
1021
+ entries: spritePassMergedEntries,
1022
+ });
1023
+ if (!result.ok) throw result.error;
1024
+ return result.value;
1025
+ },
1026
+ bindGroupCounts,
1027
+ );
1028
+
1029
+ const materialSlot = materialSlotIndices[i]?.[0] ?? 0;
1030
+ spritePass.setBindGroup(1, spritePassBg, [materialSlot * MATERIAL_PER_ENTITY_STRIDE]);
1031
+ spritePass.setBindGroup(3, spriteInstancesBg);
1032
+ spritePass.drawIndexed(spriteEntry.mesh.indexCount, spriteInstanceCount, 0, 0, 0);
1033
+ }
1034
+ }
1035
+
1036
+ /**
1037
+ * feat-20260704 M3/w19: resolve the interleaved SpriteInstances (@group(3))
1038
+ * buffer + instanceCount for a sprite entity in the LDR blend sub-pass,
1039
+ * extracted verbatim from recordSpriteEntityDraws. Uploads the interleaved
1040
+ * mat4 + per-instance UV region transforms (cache-keyed on the snapshot); on
1041
+ * over-cap fires the structured limit-exceeded error and leaves the passed-in
1042
+ * fallback buffer/count. Returns the resolved (or unchanged) buffer + count.
1043
+ *
1044
+ * @internal
1045
+ */
1046
+ function resolveSpriteInstancesBuffer(
1047
+ c: _InternalRenderPipelineContext,
1048
+ spriteEntry: _InternalRenderPipelineContext['validatedOrdered'][number],
1049
+ fallbackBuffer: Buffer,
1050
+ fallbackCount: number,
1051
+ ): { buffer: Buffer; count: number } {
1052
+ const { runtime, frameState } = c;
1053
+ let buffer = fallbackBuffer;
1054
+ let count = fallbackCount;
1055
+ const spriteInstancesSnap: SpriteInstancesSnapshot | undefined =
1056
+ spriteEntry.source.spriteInstances;
1057
+ if (spriteInstancesSnap !== undefined) {
1058
+ const uniformFallback = runtime.device.caps.storageBuffer === false;
1059
+ const interleaved = interleaveSpriteInstanceBuffer(
1060
+ spriteInstancesSnap.transforms,
1061
+ spriteInstancesSnap.regions,
1062
+ !uniformFallback,
1063
+ );
1064
+ const requestedBytes = interleaved.byteLength;
1065
+ const cap = runtime.device.limits.maxStorageBufferBindingSize;
1066
+ if (typeof cap === 'number' && requestedBytes > cap) {
1067
+ runtime.errorRegistry.fire(
1068
+ new RhiError({
1069
+ code: 'limit-exceeded',
1070
+ expected: `requestedBytes (${requestedBytes}) <= maxStorageBufferBindingSize (${cap})`,
1071
+ hint: 'reduce SpriteInstances instance count to fit within device.limits.maxStorageBufferBindingSize (144 bytes per instance: current mat4 64B + previous mat4 64B + region 16B)',
1072
+ detail: {
1073
+ maxStorageBufferBindingSize: cap,
1074
+ requestedBytes,
1075
+ },
1076
+ }),
1077
+ );
1078
+ } else {
1079
+ const cachedSpriteInst = frameState.instanceBuffers.get(
1080
+ worldEntityKey(spriteEntry.source.worldId, spriteInstancesSnap.cacheKey),
1081
+ );
1082
+ let activeSpriteInst: InstanceBufferCacheEntry | null = null;
1083
+ if (spriteInstancesCacheHit(cachedSpriteInst, spriteInstancesSnap, requestedBytes)) {
1084
+ activeSpriteInst = cachedSpriteInst ?? null;
1085
+ } else if (requestedBytes > 0) {
1086
+ const bufRes = runtime.device.createBuffer({
1087
+ size: requestedBytes,
1088
+ usage:
1089
+ (uniformFallback ? GPU_BUFFER_USAGE_UNIFORM : GPU_BUFFER_USAGE_STORAGE) |
1090
+ GPU_BUFFER_USAGE_COPY_DST,
1091
+ mappedAtCreation: false,
1092
+ });
1093
+ if (!bufRes.ok) {
1094
+ runtime.errorRegistry.fire(bufRes.error);
1095
+ } else {
1096
+ if (cachedSpriteInst !== undefined && !cachedSpriteInst.buffer.isDestroyed) {
1097
+ const r = cachedSpriteInst.buffer.destroy();
1098
+ if (!r.ok) runtime.errorRegistry.fire(r.error);
1099
+ }
1100
+ const newBuf = new GpuBuffer(runtime.device, bufRes.value);
1101
+ activeSpriteInst = {
1102
+ buffer: newBuf,
1103
+ uploadedArchVersion: spriteInstancesSnap.archVersion,
1104
+ uploadedByteLength: requestedBytes,
1105
+ };
1106
+ frameState.instanceBuffers.set(
1107
+ worldEntityKey(spriteEntry.source.worldId, spriteInstancesSnap.cacheKey),
1108
+ activeSpriteInst,
1109
+ );
1110
+ }
1111
+ }
1112
+ if (activeSpriteInst !== null && requestedBytes > 0) {
1113
+ const writeRes = runtime.device.queue.writeBuffer(
1114
+ activeSpriteInst.buffer.handle,
1115
+ 0,
1116
+ interleaved,
1117
+ );
1118
+ if (!writeRes.ok) {
1119
+ runtime.errorRegistry.fire(writeRes.error);
1120
+ } else {
1121
+ buffer = activeSpriteInst.buffer.handle;
1122
+ count = spriteInstancesSnap.instanceCount;
1123
+ }
1124
+ }
1125
+ }
1126
+ }
1127
+ return { buffer, count };
1128
+ }
1129
+
1130
+ function transparentPassColorFormat(
1131
+ c: _InternalRenderPipelineContext,
1132
+ pipelineState: _InternalRenderPipelineContext['pipelineState'] = c.pipelineState,
1133
+ ): string {
1134
+ if (c.transparentColorFormat !== undefined) return c.transparentColorFormat;
1135
+ if (!c.runtime.device.caps.storageBuffer) return pipelineState.colorAttachmentFormat;
1136
+ return pipelineState.format;
1137
+ }