@forgeax/engine-render 0.1.34 → 0.1.35

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 (243) hide show
  1. package/README.md +52 -3
  2. package/dist/assembly/device-feature-admission.d.ts +2 -2
  3. package/dist/assembly/host-contract.d.ts +3 -2
  4. package/dist/assembly/host-contract.d.ts.map +1 -1
  5. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  6. package/dist/assembly/render-target-host.d.ts +5 -0
  7. package/dist/assembly/render-target-host.d.ts.map +1 -1
  8. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  9. package/dist/assembly/webgpu-renderer.d.ts +1 -0
  10. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  11. package/dist/authoring.mjs +2 -4
  12. package/dist/authoring.mjs.map +1 -1
  13. package/dist/chunk-3XUBWRY2.mjs +1842 -0
  14. package/dist/chunk-3XUBWRY2.mjs.map +1 -0
  15. package/dist/{chunk-UI5SFODX.mjs → chunk-G6HDNGY7.mjs} +2329 -1776
  16. package/dist/chunk-G6HDNGY7.mjs.map +1 -0
  17. package/dist/{chunk-HEB564WF.mjs → chunk-LM5IE7GF.mjs} +4 -4
  18. package/dist/{chunk-HEB564WF.mjs.map → chunk-LM5IE7GF.mjs.map} +1 -1
  19. package/dist/{chunk-MKDIT2EM.mjs → chunk-LNIUIKQ7.mjs} +143 -246
  20. package/dist/chunk-LNIUIKQ7.mjs.map +1 -0
  21. package/dist/chunk-MXTWKZO4.mjs +3268 -0
  22. package/dist/chunk-MXTWKZO4.mjs.map +1 -0
  23. package/dist/{chunk-ODZWR6JQ.mjs → chunk-MZ4C7EHF.mjs} +2042 -27
  24. package/dist/chunk-MZ4C7EHF.mjs.map +1 -0
  25. package/dist/chunk-RIPAEGI6.mjs +48 -0
  26. package/dist/chunk-RIPAEGI6.mjs.map +1 -0
  27. package/dist/{chunk-OCDLEI6I.mjs → chunk-SGPUJW3F.mjs} +117 -5
  28. package/dist/chunk-SGPUJW3F.mjs.map +1 -0
  29. package/dist/{chunk-ELJFJ2BU.mjs → chunk-X2KA6WHM.mjs} +29 -4
  30. package/dist/chunk-X2KA6WHM.mjs.map +1 -0
  31. package/dist/{chunk-BLXGONR2.mjs → chunk-XSFB7XXQ.mjs} +51 -4
  32. package/dist/chunk-XSFB7XXQ.mjs.map +1 -0
  33. package/dist/cloud/frame-context.d.ts +2 -2
  34. package/dist/cloud/frame-context.d.ts.map +1 -1
  35. package/dist/construct-renderer.mjs +810 -2073
  36. package/dist/construct-renderer.mjs.map +1 -1
  37. package/dist/device/gpu-residency.d.ts +19 -19
  38. package/dist/device/gpu-residency.d.ts.map +1 -1
  39. package/dist/errors/render.d.ts +3 -2
  40. package/dist/errors/render.d.ts.map +1 -1
  41. package/dist/extract/material-context.d.ts +7 -0
  42. package/dist/extract/material-context.d.ts.map +1 -0
  43. package/dist/features/host.d.ts +5 -0
  44. package/dist/features/host.d.ts.map +1 -1
  45. package/dist/features/plan.d.ts +2 -0
  46. package/dist/features/plan.d.ts.map +1 -1
  47. package/dist/features/types.d.ts +4 -0
  48. package/dist/features/types.d.ts.map +1 -1
  49. package/dist/glyph-text-layout-system.d.ts +1 -1
  50. package/dist/glyph-text-layout-system.d.ts.map +1 -1
  51. package/dist/gpu-driven/shadow-ownership.d.ts +3 -3
  52. package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -1
  53. package/dist/ibl/frame-resources.d.ts.map +1 -1
  54. package/dist/ibl/skylight-bind-group.d.ts +4 -4
  55. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  56. package/dist/index.d.ts +3 -0
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.mjs +530 -9
  59. package/dist/index.mjs.map +1 -1
  60. package/dist/instances.d.ts +3 -4
  61. package/dist/instances.d.ts.map +1 -1
  62. package/dist/internal.mjs +7 -8
  63. package/dist/internal.mjs.map +1 -1
  64. package/dist/pbr-pipeline.d.ts +3 -3
  65. package/dist/pbr-pipeline.d.ts.map +1 -1
  66. package/dist/pipeline/standard-output/lut-gpu.d.ts +2 -2
  67. package/dist/pipeline/standard-output/lut-gpu.d.ts.map +1 -1
  68. package/dist/pipeline/standard-output/resources.d.ts +2 -2
  69. package/dist/pipeline/standard-output/resources.d.ts.map +1 -1
  70. package/dist/publication/contract.d.ts +77 -0
  71. package/dist/publication/contract.d.ts.map +1 -0
  72. package/dist/publication/dependencies.d.ts +7 -0
  73. package/dist/publication/dependencies.d.ts.map +1 -0
  74. package/dist/publication/prepare-geometry.d.ts +9 -0
  75. package/dist/publication/prepare-geometry.d.ts.map +1 -0
  76. package/dist/publication/programs.d.ts +5 -0
  77. package/dist/publication/programs.d.ts.map +1 -0
  78. package/dist/publication/publisher.d.ts +33 -0
  79. package/dist/publication/publisher.d.ts.map +1 -0
  80. package/dist/publication/receiver.d.ts +29 -0
  81. package/dist/publication/receiver.d.ts.map +1 -0
  82. package/dist/publication/resource-scope.d.ts +18 -0
  83. package/dist/publication/resource-scope.d.ts.map +1 -0
  84. package/dist/publication/targets.d.ts +33 -0
  85. package/dist/publication/targets.d.ts.map +1 -0
  86. package/dist/publication/video.d.ts +5 -0
  87. package/dist/publication/video.d.ts.map +1 -0
  88. package/dist/record/fold-buckets.d.ts +3 -3
  89. package/dist/record/fold-buckets.d.ts.map +1 -1
  90. package/dist/record/frame-snapshot.d.ts +6 -6
  91. package/dist/record/frame-snapshot.d.ts.map +1 -1
  92. package/dist/record/frame.d.ts +5 -4
  93. package/dist/record/frame.d.ts.map +1 -1
  94. package/dist/record/helpers.d.ts +2 -2
  95. package/dist/record/helpers.d.ts.map +1 -1
  96. package/dist/record/main-pass-geometry.d.ts +2 -2
  97. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  98. package/dist/record/main-pass-material.d.ts +7 -9
  99. package/dist/record/main-pass-material.d.ts.map +1 -1
  100. package/dist/record/main-pass-sprite-draws.d.ts +3 -16
  101. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  102. package/dist/record/main-pass.d.ts.map +1 -1
  103. package/dist/record/prepared-material-bindings.d.ts +3 -3
  104. package/dist/record/prepared-material-bindings.d.ts.map +1 -1
  105. package/dist/record/render-context.d.ts +2 -2
  106. package/dist/record/render-context.d.ts.map +1 -1
  107. package/dist/record/sprite-instance-buffer.d.ts +31 -0
  108. package/dist/record/sprite-instance-buffer.d.ts.map +1 -0
  109. package/dist/record/target-capture-graph.d.ts +19 -0
  110. package/dist/record/target-capture-graph.d.ts.map +1 -0
  111. package/dist/record/typed-frame-graph.d.ts +2 -13
  112. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  113. package/dist/record/view-ubo.d.ts.map +1 -1
  114. package/dist/record/volume-params.d.ts +2 -2
  115. package/dist/record/volume-params.d.ts.map +1 -1
  116. package/dist/recovery/render-system-candidate.d.ts +5 -5
  117. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  118. package/dist/render-contract.d.ts +4 -1
  119. package/dist/render-contract.d.ts.map +1 -1
  120. package/dist/render-system-extract-tail.d.ts.map +1 -1
  121. package/dist/render-system-extract.d.ts +2 -0
  122. package/dist/render-system-extract.d.ts.map +1 -1
  123. package/dist/render-system-presentation.d.ts +2 -2
  124. package/dist/render-system-presentation.d.ts.map +1 -1
  125. package/dist/render-system-projections.d.ts +3 -2
  126. package/dist/render-system-projections.d.ts.map +1 -1
  127. package/dist/render-system-residency.d.ts +2 -2
  128. package/dist/render-system-residency.d.ts.map +1 -1
  129. package/dist/render-system.d.ts +3 -7
  130. package/dist/render-system.d.ts.map +1 -1
  131. package/dist/scene/render-scene.d.ts +8 -4
  132. package/dist/scene/render-scene.d.ts.map +1 -1
  133. package/dist/scene/render-source.d.ts +42 -0
  134. package/dist/scene/render-source.d.ts.map +1 -0
  135. package/dist/scene/source-systems.d.ts +6 -0
  136. package/dist/scene/source-systems.d.ts.map +1 -0
  137. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  138. package/dist/systems/skin-palette-types.d.ts +10 -0
  139. package/dist/systems/skin-palette-types.d.ts.map +1 -1
  140. package/dist/systems/transparent-dispatch.d.ts +2 -2
  141. package/dist/systems/transparent-dispatch.d.ts.map +1 -1
  142. package/dist/systems/transparent-sort-config.d.ts +2 -1
  143. package/dist/systems/transparent-sort-config.d.ts.map +1 -1
  144. package/dist/temporal/index.mjs +6 -7
  145. package/package.json +21 -21
  146. package/src/__tests__/auto-exposure-transaction.integration.test.ts +4 -9
  147. package/src/__tests__/device-feature-admission.unit.test.ts +3 -2
  148. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +3 -4
  149. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +4 -1
  150. package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +0 -1
  151. package/src/__tests__/materials-standard-contract.unit.test.ts +0 -1
  152. package/src/__tests__/physical-clearcoat.integration.test.ts +23 -23
  153. package/src/__tests__/physical-material-budget.unit.test.ts +40 -0
  154. package/src/__tests__/render-error-code-owner.test-d.ts +1 -0
  155. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +1 -1
  156. package/src/assembly/device-feature-admission.ts +2 -2
  157. package/src/assembly/host-contract.ts +5 -2
  158. package/src/assembly/recovery/renderer-recover.ts +9 -0
  159. package/src/assembly/render-target-host.ts +57 -47
  160. package/src/assembly/renderer-facade.ts +3 -1
  161. package/src/assembly/webgpu-ready.ts +1 -1
  162. package/src/assembly/webgpu-renderer.ts +89 -61
  163. package/src/cloud/frame-context.ts +2 -2
  164. package/src/device/gpu-residency.ts +26 -25
  165. package/src/errors/render.ts +3 -1
  166. package/src/extract/material-context.ts +21 -0
  167. package/src/features/host.ts +13 -5
  168. package/src/features/plan.ts +2 -0
  169. package/src/features/types.ts +4 -0
  170. package/src/glyph-text-layout-system.ts +2 -2
  171. package/src/gpu-driven/shadow-ownership.ts +3 -3
  172. package/src/ibl/frame-resources.ts +0 -1
  173. package/src/ibl/skylight-bind-group.ts +13 -25
  174. package/src/index.ts +9 -0
  175. package/src/instances.ts +9 -6
  176. package/src/pbr-pipeline.ts +11 -17
  177. package/src/pipeline/standard-output/lut-gpu.ts +3 -3
  178. package/src/pipeline/standard-output/resources.ts +2 -2
  179. package/src/publication/__tests__/derived-geometry.integration.test.ts +177 -0
  180. package/src/publication/__tests__/features.integration.test.ts +122 -0
  181. package/src/publication/__tests__/programs.unit.test.ts +25 -0
  182. package/src/publication/__tests__/publication.integration.test.ts +370 -0
  183. package/src/publication/__tests__/targets.integration.test.ts +120 -0
  184. package/src/publication/__tests__/video.browser.test.ts +50 -0
  185. package/src/publication/contract.ts +104 -0
  186. package/src/publication/dependencies.ts +54 -0
  187. package/src/publication/prepare-geometry.ts +94 -0
  188. package/src/publication/programs.ts +45 -0
  189. package/src/publication/publisher.ts +618 -0
  190. package/src/publication/receiver.ts +297 -0
  191. package/src/publication/resource-scope.ts +31 -0
  192. package/src/publication/targets.ts +182 -0
  193. package/src/publication/video.ts +33 -0
  194. package/src/record/__tests__/material-bg-cache.unit.test.ts +15 -1
  195. package/src/record/__tests__/sprite-material-abi.unit.test.ts +8 -10
  196. package/src/record/__tests__/video-texture-view.unit.test.ts +9 -9
  197. package/src/record/fold-buckets.ts +8 -5
  198. package/src/record/frame-snapshot.ts +6 -6
  199. package/src/record/frame.ts +42 -22
  200. package/src/record/helpers.ts +2 -2
  201. package/src/record/main-pass-geometry.ts +21 -2
  202. package/src/record/main-pass-material.ts +37 -33
  203. package/src/record/main-pass-sprite-draws.ts +6 -152
  204. package/src/record/main-pass.ts +8 -7
  205. package/src/record/prepared-material-bindings.ts +11 -6
  206. package/src/record/render-context.ts +2 -2
  207. package/src/record/shadow-pass.ts +0 -3
  208. package/src/record/sprite-instance-buffer.ts +155 -0
  209. package/src/record/target-capture-graph.ts +258 -0
  210. package/src/record/typed-frame-graph.ts +6 -206
  211. package/src/record/view-ubo.ts +1 -1
  212. package/src/record/volume-params.ts +6 -6
  213. package/src/recovery/render-system-candidate.ts +10 -10
  214. package/src/render-contract.ts +6 -1
  215. package/src/render-system-extract-tail.ts +33 -17
  216. package/src/render-system-extract.ts +2 -0
  217. package/src/render-system-presentation.ts +2 -2
  218. package/src/render-system-projections.ts +3 -2
  219. package/src/render-system-residency.ts +2 -2
  220. package/src/render-system.ts +82 -53
  221. package/src/scene/render-scene.ts +110 -100
  222. package/src/scene/render-source.ts +90 -0
  223. package/src/scene/source-systems.ts +33 -0
  224. package/src/systems/skin-palette-allocator.ts +1 -0
  225. package/src/systems/skin-palette-types.ts +11 -0
  226. package/src/systems/transparent-dispatch.ts +2 -2
  227. package/src/systems/transparent-sort-config.ts +3 -1
  228. package/dist/chunk-BLXGONR2.mjs.map +0 -1
  229. package/dist/chunk-ELJFJ2BU.mjs.map +0 -1
  230. package/dist/chunk-ILQ5MEZF.mjs +0 -32
  231. package/dist/chunk-ILQ5MEZF.mjs.map +0 -1
  232. package/dist/chunk-MKDIT2EM.mjs.map +0 -1
  233. package/dist/chunk-OCDLEI6I.mjs.map +0 -1
  234. package/dist/chunk-ODZWR6JQ.mjs.map +0 -1
  235. package/dist/chunk-RXZ3RGOU.mjs +0 -53
  236. package/dist/chunk-RXZ3RGOU.mjs.map +0 -1
  237. package/dist/chunk-SHFUFJ5N.mjs +0 -1781
  238. package/dist/chunk-SHFUFJ5N.mjs.map +0 -1
  239. package/dist/chunk-UI5SFODX.mjs.map +0 -1
  240. package/dist/chunk-UINHLCZA.mjs +0 -2389
  241. package/dist/chunk-UINHLCZA.mjs.map +0 -1
  242. package/dist/chunk-WEX45HKH.mjs +0 -1524
  243. package/dist/chunk-WEX45HKH.mjs.map +0 -1
@@ -1,8 +1,1316 @@
1
- import { CLOUD_EXTINCTION_COEFFICIENT, CLOUD_QUALITY_PROFILES, cloudLayerFormationKey, CloudLayerCacheInvalidError, cloudShadowResolutionForQuality, PointShapeValue, pointShapeFromU32, cloudViewDistanceForQuality } from './chunk-UINHLCZA.mjs';
2
- import { PointsLinesBudgetExceededError, createVisibilityBudget, PointsLinesStyleUnsupportedError, PointsLinesMaterialUnsupportedError, PointsLinesInvalidStyleError, PointsLinesTopologyMismatchError } from './chunk-WEX45HKH.mjs';
3
- import { ok, err, deriveMaterialDynamicInputLayout } from '@forgeax/engine-types';
1
+ import { CLOUD_EXTINCTION_COEFFICIENT, MeshFilter, MeshRenderer, Instances, Layer, Visibility, Points, Lines, SortKey, CLOUD_QUALITY_PROFILES, cloudLayerFormationKey, CloudLayerCacheInvalidError, cloudShadowResolutionForQuality, glyphTextLayoutSystem, PointShapeValue, pointShapeFromU32, Camera, CAMERA_PROJECTION_ORTHOGRAPHIC, cloudViewDistanceForQuality } from './chunk-G6HDNGY7.mjs';
2
+ import { SpriteInstances, SpriteRegionOverride, TileLayer, decodeSortScope, Tilemap } from './chunk-X2KA6WHM.mjs';
3
+ import { configureSurface } from './chunk-SGPUJW3F.mjs';
4
+ import { SPRITE_PREMULTIPLIED_ALPHA_BLEND } from './chunk-XSFB7XXQ.mjs';
5
+ import { RenderTargetStateInvalidError, RenderTargetOperationFailedError, RenderTargetCapabilityMissingError, RenderTargetDescriptorInvalidError, GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_MAP_READ, resolveRenderTargetMaterialSource, createRenderTargetMaterialSource, PointsLinesBudgetExceededError, createVisibilityBudget, PointsLinesStyleUnsupportedError, PointsLinesMaterialUnsupportedError, GPU_TEXTURE_USAGE_RENDER_ATTACHMENT, GPU_TEXTURE_USAGE_TEXTURE_BINDING, GPU_TEXTURE_USAGE_COPY_SRC, PointsLinesInvalidStyleError, PointsLinesTopologyMismatchError } from './chunk-MXTWKZO4.mjs';
6
+ import { ok, err, deriveMaterialDynamicInputLayout, toShared, unwrapHandle } from '@forgeax/engine-types';
4
7
  import { validateR32FloatReceipt } from '@forgeax/engine-rhi';
8
+ import { Update } from '@forgeax/engine-ecs';
9
+ import { ChildOf, MorphWeights, registerPropagateTransforms, GlobalTransform, Transform, Children } from '@forgeax/engine-scene';
10
+ import { RuntimeMaterialValue, RuntimeMeshVertices, HANDLE_QUAD, resolveTilesetRuntime } from '@forgeax/engine-assets-runtime';
11
+ import { decodeTileBits } from '@forgeax/engine-graphics-extras';
12
+ import { frustum, mat4 } from '@forgeax/engine-math';
13
+ import { createStateProjection } from '@forgeax/engine-ecs/projection';
14
+ import { Skin } from '@forgeax/engine-skinning';
5
15
 
16
+ // src/publication/contract.ts
17
+ function renderPublicationTransfers(packet) {
18
+ return [
19
+ packet.upserts.buffer,
20
+ packet.removed.buffer,
21
+ packet.transformEntities.buffer,
22
+ packet.transforms.buffer
23
+ ];
24
+ }
25
+ var RenderPublicationError = class extends Error {
26
+ constructor(detail) {
27
+ super(`render-publication-invalid: ${detail.reason}: ${detail.subject}`);
28
+ this.detail = detail;
29
+ this.name = "RenderPublicationError";
30
+ }
31
+ detail;
32
+ code = "render-publication-invalid";
33
+ expected = "one valid publication for the bound source session and accepted base";
34
+ hint = "inspect detail.reason; repair the source or start a new session with a complete current baseline";
35
+ };
36
+
37
+ // src/typed-shadow-atlas.ts
38
+ function resolveDirectionalShadowAtlasGrid(cascadeCount) {
39
+ const count = Math.max(1, Math.min(4, Math.round(cascadeCount)));
40
+ if (count === 1) return { columns: 1, rows: 1 };
41
+ if (count === 2) return { columns: 2, rows: 1 };
42
+ return { columns: 2, rows: 2 };
43
+ }
44
+
45
+ // src/record/frame-targets.ts
46
+ function graphExecutionPhase(passName) {
47
+ if (passName.startsWith("shadowCascade")) return "record/graph-execute/shadow";
48
+ if (passName.startsWith("point-shadow")) return "record/graph-execute/point-shadow";
49
+ if (passName.startsWith("spot-shadow")) return "record/graph-execute/spot-shadow";
50
+ if (passName === "ssr-hiz-seed" || passName.startsWith("ssr-hiz-reduce-")) {
51
+ return "record/graph-execute/ssr-hiz";
52
+ }
53
+ if (passName === "ssr-trace") return "record/graph-execute/ssr-trace";
54
+ if (passName === "ssr-temporal") return "record/graph-execute/ssr-temporal";
55
+ if (passName.startsWith("ssr-reflection-mip-")) {
56
+ return "record/graph-execute/ssr-reflection-mip";
57
+ }
58
+ if (passName === "ssr-compose") return "record/graph-execute/ssr-compose";
59
+ if (passName.startsWith("bloom-downsample-")) {
60
+ return "record/graph-execute/bloom-downsample";
61
+ }
62
+ if (passName.startsWith("bloom-upsample-")) {
63
+ return "record/graph-execute/bloom-upsample";
64
+ }
65
+ switch (passName) {
66
+ case "cluster-binner-upload":
67
+ case "cluster-membership-producer":
68
+ return "record/graph-execute/cluster-binner-upload";
69
+ case "g-buffer":
70
+ return "record/graph-execute/g-buffer";
71
+ case "ssao-calc":
72
+ return "record/graph-execute/ssao-calc";
73
+ case "ssao-blur":
74
+ return "record/graph-execute/ssao-blur";
75
+ case "lighting":
76
+ return "record/graph-execute/lighting";
77
+ case "forward":
78
+ case "transmission-forward":
79
+ return "record/graph-execute/forward";
80
+ case "output-transform":
81
+ return "record/graph-execute/output-transform";
82
+ case "present":
83
+ return "record/graph-execute/present";
84
+ case "debug-overlay":
85
+ return "record/graph-execute/debug-overlay";
86
+ case "shadow":
87
+ return "record/graph-execute/shadow";
88
+ case "skybox":
89
+ return "record/graph-execute/skybox";
90
+ case "main":
91
+ return "record/graph-execute/main";
92
+ case "fxaa":
93
+ return "record/graph-execute/fxaa";
94
+ case "bloom-downsample":
95
+ return "record/graph-execute/bloom-downsample";
96
+ case "bloom-upsample":
97
+ return "record/graph-execute/bloom-upsample";
98
+ case "bloom-composite":
99
+ return "record/graph-execute/bloom-composite";
100
+ default:
101
+ return "record/graph-execute/other";
102
+ }
103
+ }
104
+ function resolveRenderTargetMipExtent(descriptor, mipLevel) {
105
+ const mipCount2 = descriptor.mipLevels === 1 ? 1 : Math.floor(Math.log2(Math.max(descriptor.width, descriptor.height))) + 1;
106
+ const level = Math.max(0, Math.min(mipLevel, mipCount2 - 1));
107
+ return {
108
+ width: Math.max(1, descriptor.width >> level),
109
+ height: Math.max(1, descriptor.height >> level)
110
+ };
111
+ }
112
+ function acquireSwapChainTarget(internals, pipelineState) {
113
+ const canvasContext = internals.context;
114
+ if (canvasContext === null) return null;
115
+ let currentTextureResult = canvasContext.getCurrentTexture();
116
+ if (!currentTextureResult.ok) {
117
+ const configuredDevice = internals.resolveSurfaceDevice?.(internals.device);
118
+ if (configuredDevice !== void 0 && !configuredDevice.ok) {
119
+ internals.errorRegistry.fire(configuredDevice.error);
120
+ internals.healthRegistry.fire({
121
+ reason: "internal-fault",
122
+ detail: { message: "surface device resolution failed; current frame skipped" },
123
+ recoverable: true
124
+ });
125
+ return null;
126
+ }
127
+ const configured = configureSurface(
128
+ canvasContext,
129
+ configuredDevice?.value ?? internals.device,
130
+ pipelineState.format,
131
+ pipelineState.colorAttachmentFormat
132
+ );
133
+ if (!configured.ok) {
134
+ internals.errorRegistry.fire(configured.error);
135
+ internals.healthRegistry.fire({
136
+ reason: "internal-fault",
137
+ detail: { message: "surface configure candidate failed; current frame skipped" },
138
+ recoverable: true
139
+ });
140
+ return null;
141
+ }
142
+ pipelineState.perPassResources.configured = true;
143
+ globalThis.__forgeaxSwapChainFormat = pipelineState.format;
144
+ const retry = canvasContext.getCurrentTexture();
145
+ if (!retry.ok) {
146
+ internals.errorRegistry.fire(retry.error);
147
+ internals.healthRegistry.fire({
148
+ reason: "internal-fault",
149
+ detail: {
150
+ message: "surface-configure-failed after retry: getCurrentTexture failed twice consecutively"
151
+ },
152
+ recoverable: false
153
+ });
154
+ return null;
155
+ }
156
+ currentTextureResult = retry;
157
+ }
158
+ const viewDescriptor = pipelineState.colorAttachmentFormat === pipelineState.format ? {} : { format: pipelineState.colorAttachmentFormat };
159
+ const viewResult = internals.device.createTextureView(currentTextureResult.value, viewDescriptor);
160
+ if (!viewResult.ok) {
161
+ internals.errorRegistry.fire(viewResult.error);
162
+ return null;
163
+ }
164
+ return {
165
+ currentTexture: currentTextureResult.value,
166
+ view: viewResult.value,
167
+ targetW: internals.canvas.width | 0,
168
+ targetH: internals.canvas.height | 0
169
+ };
170
+ }
171
+ function resolveShadowMapSize(internals, lights) {
172
+ if (lights.cascadeCount === void 0) return void 0;
173
+ const requested = lights.shadowMapSize;
174
+ if (!(requested !== void 0 && requested > 0)) return requested;
175
+ const cascades = Math.max(1, Math.min(4, Math.round(lights.cascadeCount ?? 1)));
176
+ const atlasGrid = resolveDirectionalShadowAtlasGrid(cascades);
177
+ const maxDimension = internals.device.limits.maxTextureDimension2D;
178
+ if (!(maxDimension > 0)) return Math.floor(requested);
179
+ const depthTextureDimension = internals.device.caps?.backendKind === "wgpu-webgl2" ? Math.max(1, Math.floor(maxDimension / 2)) : maxDimension;
180
+ const maxPerTile = Math.max(
181
+ 1,
182
+ Math.floor(depthTextureDimension / Math.max(atlasGrid.columns, atlasGrid.rows))
183
+ );
184
+ return Math.max(1, Math.min(Math.floor(requested), maxPerTile));
185
+ }
186
+ function resolveSpotShadowMapSize(internals, lights) {
187
+ const requested = lights.spot.find(
188
+ (spot) => spot.shadowAtlasTile >= 0 && spot.lightViewProj !== void 0
189
+ )?.mapSize;
190
+ if (!(requested !== void 0 && requested > 0)) return requested;
191
+ const maxDimension = internals.device.limits.maxTextureDimension2D;
192
+ if (!(maxDimension > 0)) return Math.floor(requested);
193
+ const maxPerTile = Math.max(1, Math.floor(maxDimension / 2));
194
+ return Math.max(1, Math.min(Math.floor(requested), maxPerTile));
195
+ }
196
+
197
+ // src/targets/contracts.ts
198
+ var FORMAT_BYTES = {
199
+ rgba16float: 8,
200
+ rgba8unorm: 4,
201
+ "rgba8unorm-srgb": 4
202
+ };
203
+ function mipFactor(mipLevels) {
204
+ return mipLevels === "full" ? 4 / 3 : 1;
205
+ }
206
+ function estimatedBytes(descriptor) {
207
+ const layers = descriptor.shape === "cube" ? 6 : 1;
208
+ const samples = descriptor.sampleCount;
209
+ const depthBytes = descriptor.depth === void 0 ? 0 : 4;
210
+ return Math.ceil(
211
+ descriptor.width * descriptor.height * FORMAT_BYTES[descriptor.format] * layers * samples * mipFactor(descriptor.mipLevels) + descriptor.width * descriptor.height * depthBytes * layers * samples * mipFactor(descriptor.mipLevels)
212
+ );
213
+ }
214
+ function invalid(field, value, expected) {
215
+ return {
216
+ ok: false,
217
+ error: new RenderTargetDescriptorInvalidError({ field, value, expected })
218
+ };
219
+ }
220
+ function admitRenderTargetDescriptor(descriptor, limits) {
221
+ if (!Number.isInteger(descriptor.width) || descriptor.width < 1) {
222
+ return invalid("width", descriptor.width, "an integer >= 1");
223
+ }
224
+ if (!Number.isInteger(descriptor.height) || descriptor.height < 1) {
225
+ return invalid("height", descriptor.height, "an integer >= 1");
226
+ }
227
+ if (descriptor.width > limits.maxTextureDimension2D || descriptor.height > limits.maxTextureDimension2D) {
228
+ return invalid(
229
+ "extent",
230
+ { width: descriptor.width, height: descriptor.height },
231
+ `width and height <= ${limits.maxTextureDimension2D}`
232
+ );
233
+ }
234
+ if (descriptor.shape === "cube" && descriptor.width !== descriptor.height) {
235
+ return invalid("shape", descriptor.shape, "cube width === height");
236
+ }
237
+ if (!limits.renderableFormats.includes(descriptor.format)) {
238
+ return {
239
+ ok: false,
240
+ error: new RenderTargetCapabilityMissingError({
241
+ operation: "create",
242
+ requested: descriptor.format,
243
+ capability: "renderableFormats",
244
+ actual: limits.renderableFormats.join(", ")
245
+ })
246
+ };
247
+ }
248
+ if (!limits.sampleCounts.includes(descriptor.sampleCount)) {
249
+ return {
250
+ ok: false,
251
+ error: new RenderTargetCapabilityMissingError({
252
+ operation: "create",
253
+ requested: String(descriptor.sampleCount),
254
+ capability: "sampleCounts",
255
+ actual: limits.sampleCounts.join(", ")
256
+ })
257
+ };
258
+ }
259
+ if (descriptor.depth !== void 0 && !limits.depthFormats.includes(descriptor.depth)) {
260
+ return {
261
+ ok: false,
262
+ error: new RenderTargetCapabilityMissingError({
263
+ operation: "create",
264
+ requested: descriptor.depth,
265
+ capability: "depthFormats",
266
+ actual: limits.depthFormats.join(", ")
267
+ })
268
+ };
269
+ }
270
+ const bytes = estimatedBytes(descriptor);
271
+ if (bytes > limits.maxBytesPerTarget) {
272
+ return invalid("bytes", bytes, `estimated allocation <= ${limits.maxBytesPerTarget}`);
273
+ }
274
+ return { ok: true, value: descriptor };
275
+ }
276
+
277
+ // src/targets/owner.ts
278
+ function frozenDescriptor(descriptor) {
279
+ return Object.freeze({ ...descriptor });
280
+ }
281
+ function invalid2(operation, reason, state, generation) {
282
+ return {
283
+ ok: false,
284
+ error: new RenderTargetStateInvalidError({ operation, reason, state, generation })
285
+ };
286
+ }
287
+ function token() {
288
+ return Object.freeze({});
289
+ }
290
+ function createRenderTargetOwner(options) {
291
+ const targets = /* @__PURE__ */ new WeakMap();
292
+ const requireTarget = (target, operation) => {
293
+ const state = targets.get(target);
294
+ if (state === void 0) return invalid2(operation, "foreign-renderer", "destroyed", 0);
295
+ if (state.rendererId !== options.rendererId) {
296
+ return invalid2(operation, "foreign-renderer", state.state, state.generation);
297
+ }
298
+ if (state.state === "destroyed") {
299
+ return invalid2(operation, "destroyed", state.state, state.generation);
300
+ }
301
+ return { ok: true, value: state };
302
+ };
303
+ return {
304
+ create(descriptor) {
305
+ const target = token();
306
+ targets.set(target, {
307
+ target,
308
+ rendererId: options.rendererId,
309
+ state: "uninitialized",
310
+ generation: 0,
311
+ descriptor: frozenDescriptor(descriptor),
312
+ candidate: void 0,
313
+ retiredGenerations: /* @__PURE__ */ new Set()
314
+ });
315
+ return { ok: true, value: target };
316
+ },
317
+ stage(target, descriptor) {
318
+ const found = requireTarget(target, "resize");
319
+ if (!found.ok) return found;
320
+ const state = found.value;
321
+ if (state.state === "rebuilding") {
322
+ return invalid2("resize", "generation-mismatch", state.state, state.generation);
323
+ }
324
+ const candidate = Object.freeze({
325
+ generation: state.state === "uninitialized" ? options.initialGeneration : state.generation,
326
+ descriptor: frozenDescriptor(descriptor ?? state.descriptor)
327
+ });
328
+ state.candidate = candidate;
329
+ state.state = "candidate";
330
+ return { ok: true, value: candidate };
331
+ },
332
+ promote(target, generation) {
333
+ const found = requireTarget(target, "resize");
334
+ if (!found.ok) return found;
335
+ const state = found.value;
336
+ if (state.candidate?.generation !== generation) {
337
+ return invalid2("resize", "generation-mismatch", state.state, state.generation);
338
+ }
339
+ state.descriptor = state.candidate.descriptor;
340
+ state.generation = generation;
341
+ state.candidate = void 0;
342
+ state.state = "active";
343
+ return { ok: true, value: void 0 };
344
+ },
345
+ rejectCandidate(target, generation, stage) {
346
+ const found = requireTarget(target, "resize");
347
+ if (!found.ok) return found;
348
+ const state = found.value;
349
+ if (state.candidate?.generation !== generation) {
350
+ return invalid2("resize", "generation-mismatch", state.state, state.generation);
351
+ }
352
+ state.candidate = void 0;
353
+ state.state = state.generation === 0 ? "uninitialized" : "active";
354
+ return {
355
+ ok: false,
356
+ error: new RenderTargetOperationFailedError({
357
+ operation: "resize",
358
+ stage,
359
+ generation,
360
+ cause: new Error(`candidate ${generation} failed during ${stage}`),
361
+ recovery: state.generation === 0 ? "retry" : "retain-last-known-good"
362
+ })
363
+ };
364
+ },
365
+ beginRecovery(target, generation) {
366
+ const found = requireTarget(target, "resize");
367
+ if (!found.ok) return found;
368
+ const state = found.value;
369
+ if (state.state !== "active" || generation <= state.generation) {
370
+ return invalid2("resize", "generation-mismatch", state.state, state.generation);
371
+ }
372
+ state.generation = generation;
373
+ state.candidate = void 0;
374
+ state.state = "rebuilding";
375
+ return { ok: true, value: void 0 };
376
+ },
377
+ finishRecovery(target) {
378
+ const found = requireTarget(target, "resize");
379
+ if (!found.ok) return found;
380
+ const state = found.value;
381
+ if (state.state !== "rebuilding") {
382
+ return invalid2("resize", "generation-mismatch", state.state, state.generation);
383
+ }
384
+ state.state = "uninitialized";
385
+ return { ok: true, value: void 0 };
386
+ },
387
+ retire(target, generation) {
388
+ const found = requireTarget(target, "destroy");
389
+ if (!found.ok) return found;
390
+ found.value.retiredGenerations.add(generation);
391
+ return { ok: true, value: void 0 };
392
+ },
393
+ destroy(target) {
394
+ const state = targets.get(target);
395
+ if (state === void 0) return invalid2("destroy", "foreign-renderer", "destroyed", 0);
396
+ if (state.rendererId !== options.rendererId) {
397
+ return invalid2("destroy", "foreign-renderer", state.state, state.generation);
398
+ }
399
+ if (state.state === "destroyed") return { ok: true, value: void 0 };
400
+ state.candidate = void 0;
401
+ state.state = "destroyed";
402
+ return { ok: true, value: void 0 };
403
+ },
404
+ inspect(target) {
405
+ const found = requireTarget(target, "inspect");
406
+ if (!found.ok) return found;
407
+ const state = found.value;
408
+ return {
409
+ ok: true,
410
+ value: Object.freeze({
411
+ token: state.target,
412
+ state: state.state,
413
+ generation: state.generation,
414
+ descriptor: state.descriptor,
415
+ ...state.candidate === void 0 ? {} : { candidate: state.candidate }
416
+ })
417
+ };
418
+ }
419
+ };
420
+ }
421
+
422
+ // src/targets/readback.ts
423
+ function invalidTicket(ticket, reason) {
424
+ return {
425
+ ok: false,
426
+ error: new RenderTargetStateInvalidError({
427
+ operation: "readback",
428
+ reason,
429
+ state: reason === "destroyed" ? "destroyed" : "active",
430
+ generation: ticket.deviceGeneration
431
+ })
432
+ };
433
+ }
434
+ function bindRenderTargetReadbackTicket(ticket, receipt) {
435
+ if (ticket.consumed) return invalidTicket(ticket, "destroyed");
436
+ if (ticket.frameId !== void 0) {
437
+ return invalidTicket(ticket, "generation-mismatch");
438
+ }
439
+ ticket.frameId = receipt.frameId;
440
+ ticket.deviceGeneration = receipt.deviceGeneration;
441
+ return { ok: true, value: void 0 };
442
+ }
443
+ function createRenderTargetReadbackTicket(target, input) {
444
+ if (input.frameId !== void 0 && (!Number.isInteger(input.frameId) || input.frameId < 0) || !Number.isInteger(input.deviceGeneration) || input.deviceGeneration < 0 || !Number.isInteger(input.mipLevel) || input.mipLevel < 0 || !Number.isInteger(input.width) || input.width < 1 || !Number.isInteger(input.height) || input.height < 1 || !Number.isInteger(input.bytesPerPixel) || input.bytesPerPixel < 1) {
445
+ return {
446
+ ok: false,
447
+ error: new RenderTargetOperationFailedError({
448
+ operation: "readback",
449
+ stage: "copy",
450
+ generation: input.deviceGeneration,
451
+ cause: new Error("readback dimensions and identity must be non-negative integers"),
452
+ recovery: "retry"
453
+ })
454
+ };
455
+ }
456
+ const unalignedRowBytes = input.width * input.bytesPerPixel;
457
+ const bytesPerRow = Math.ceil(unalignedRowBytes / 256) * 256;
458
+ return {
459
+ ok: true,
460
+ value: {
461
+ target,
462
+ frameId: input.frameId,
463
+ deviceGeneration: input.deviceGeneration,
464
+ mipLevel: input.mipLevel,
465
+ ...input.face === void 0 ? {} : { face: input.face },
466
+ width: input.width,
467
+ height: input.height,
468
+ bytesPerRow,
469
+ byteLength: bytesPerRow * input.height,
470
+ consumed: false
471
+ }
472
+ };
473
+ }
474
+ function completeRenderTargetReadback(ticket, receipt, bytes) {
475
+ if (ticket.consumed) return invalidTicket(ticket, "destroyed");
476
+ if (ticket.frameId === void 0 || receipt.frameId !== ticket.frameId || receipt.deviceGeneration !== ticket.deviceGeneration) {
477
+ return invalidTicket(ticket, "generation-mismatch");
478
+ }
479
+ if (bytes.byteLength !== ticket.byteLength) {
480
+ return {
481
+ ok: false,
482
+ error: new RenderTargetOperationFailedError({
483
+ operation: "readback",
484
+ stage: "copy",
485
+ generation: ticket.deviceGeneration,
486
+ cause: new Error(`expected ${ticket.byteLength} bytes, received ${bytes.byteLength}`),
487
+ recovery: "retry"
488
+ })
489
+ };
490
+ }
491
+ ticket.consumed = true;
492
+ return {
493
+ ok: true,
494
+ value: {
495
+ bytes,
496
+ frameId: ticket.frameId,
497
+ deviceGeneration: ticket.deviceGeneration,
498
+ mipLevel: ticket.mipLevel,
499
+ ...ticket.face === void 0 ? {} : { face: ticket.face }
500
+ }
501
+ };
502
+ }
503
+
504
+ // src/assembly/render-target-host.ts
505
+ var DEFAULT_LIMITS = {
506
+ maxTextureDimension2D: 8192,
507
+ maxBytesPerTarget: 256 * 1024 * 1024,
508
+ renderableFormats: ["rgba16float", "rgba8unorm", "rgba8unorm-srgb"],
509
+ sampleCounts: [1, 4],
510
+ depthFormats: ["depth24plus-stencil8", "depth32float"]
511
+ };
512
+ function opaqueTicket() {
513
+ return Object.freeze({});
514
+ }
515
+ function bytesPerPixel(format) {
516
+ return format === "rgba16float" ? 8 : 4;
517
+ }
518
+ function mipCount(descriptor) {
519
+ return descriptor.mipLevels === 1 ? 1 : Math.floor(Math.log2(Math.max(descriptor.width, descriptor.height))) + 1;
520
+ }
521
+ function makePhysical(device, descriptor, generation) {
522
+ const layers = descriptor.shape === "cube" ? 6 : 1;
523
+ const usage = GPU_TEXTURE_USAGE_RENDER_ATTACHMENT | (descriptor.sampled ? GPU_TEXTURE_USAGE_TEXTURE_BINDING : 0) | (descriptor.readback ? GPU_TEXTURE_USAGE_COPY_SRC : 0);
524
+ const created = device.createTexture({
525
+ label: `render-target.${generation}`,
526
+ size: { width: descriptor.width, height: descriptor.height, depthOrArrayLayers: layers },
527
+ format: descriptor.format,
528
+ mipLevelCount: mipCount(descriptor),
529
+ // WebGPU forbids multisampled array textures. The cube is always the
530
+ // single-sample resolve destination; MSAA capture uses one depth=1 color
531
+ // texture per face below.
532
+ sampleCount: 1,
533
+ dimension: "2d",
534
+ usage,
535
+ viewFormats: void 0,
536
+ textureBindingViewDimension: descriptor.shape === "cube" ? "cube" : void 0
537
+ });
538
+ if (!created.ok)
539
+ return {
540
+ ok: false,
541
+ error: new RenderTargetOperationFailedError({
542
+ operation: "create",
543
+ stage: "allocation",
544
+ generation,
545
+ cause: created.error,
546
+ recovery: "retry"
547
+ })
548
+ };
549
+ const texture = created.value;
550
+ const view = device.createTextureView(texture, {
551
+ dimension: descriptor.shape,
552
+ baseMipLevel: 0,
553
+ mipLevelCount: mipCount(descriptor),
554
+ baseArrayLayer: 0,
555
+ arrayLayerCount: layers
556
+ });
557
+ if (!view.ok)
558
+ return {
559
+ ok: false,
560
+ error: new RenderTargetOperationFailedError({
561
+ operation: "create",
562
+ stage: "allocation",
563
+ generation,
564
+ cause: view.error,
565
+ recovery: "retry"
566
+ })
567
+ };
568
+ const mipViews = [];
569
+ for (let mip = 0; mip < mipCount(descriptor); mip += 1) {
570
+ const mipView = device.createTextureView(texture, {
571
+ dimension: descriptor.shape,
572
+ baseMipLevel: mip,
573
+ mipLevelCount: 1,
574
+ baseArrayLayer: 0,
575
+ arrayLayerCount: layers
576
+ });
577
+ if (!mipView.ok)
578
+ return {
579
+ ok: false,
580
+ error: new RenderTargetOperationFailedError({
581
+ operation: "create",
582
+ stage: "allocation",
583
+ generation,
584
+ cause: mipView.error,
585
+ recovery: "retry"
586
+ })
587
+ };
588
+ mipViews.push(mipView.value);
589
+ }
590
+ const resolveFaceViews = [];
591
+ for (let face = 0; face < layers; face += 1) {
592
+ const faceView = device.createTextureView(texture, {
593
+ dimension: "2d",
594
+ baseMipLevel: 0,
595
+ mipLevelCount: 1,
596
+ baseArrayLayer: face,
597
+ arrayLayerCount: 1
598
+ });
599
+ if (!faceView.ok)
600
+ return {
601
+ ok: false,
602
+ error: new RenderTargetOperationFailedError({
603
+ operation: "create",
604
+ stage: "allocation",
605
+ generation,
606
+ cause: faceView.error,
607
+ recovery: "retry"
608
+ })
609
+ };
610
+ resolveFaceViews.push(faceView.value);
611
+ }
612
+ const colorTextures = [];
613
+ const faceViews = [];
614
+ const depthTextures = [];
615
+ const depthViews = [];
616
+ for (let face = 0; face < layers; face += 1) {
617
+ const depth = device.createTexture({
618
+ label: `render-target.${generation}.depth.${face}`,
619
+ size: {
620
+ width: descriptor.width,
621
+ height: descriptor.height,
622
+ depthOrArrayLayers: descriptor.sampleCount === 4 ? 1 : layers
623
+ },
624
+ mipLevelCount: 1,
625
+ sampleCount: descriptor.sampleCount,
626
+ dimension: "2d",
627
+ format: "depth24plus-stencil8",
628
+ usage: GPU_TEXTURE_USAGE_RENDER_ATTACHMENT,
629
+ viewFormats: void 0,
630
+ textureBindingViewDimension: void 0
631
+ });
632
+ if (!depth.ok)
633
+ return {
634
+ ok: false,
635
+ error: new RenderTargetOperationFailedError({
636
+ operation: "create",
637
+ stage: "allocation",
638
+ generation,
639
+ cause: depth.error,
640
+ recovery: "retry"
641
+ })
642
+ };
643
+ const depthView = device.createTextureView(depth.value, {
644
+ dimension: "2d",
645
+ baseArrayLayer: descriptor.sampleCount === 4 ? 0 : face,
646
+ arrayLayerCount: 1
647
+ });
648
+ if (!depthView.ok)
649
+ return {
650
+ ok: false,
651
+ error: new RenderTargetOperationFailedError({
652
+ operation: "create",
653
+ stage: "allocation",
654
+ generation,
655
+ cause: depthView.error,
656
+ recovery: "retry"
657
+ })
658
+ };
659
+ depthTextures.push(depth.value);
660
+ depthViews.push(depthView.value);
661
+ }
662
+ if (descriptor.sampleCount === 4) {
663
+ for (let face = 0; face < layers; face += 1) {
664
+ const msaa = device.createTexture({
665
+ label: `render-target.${generation}.msaa.${face}`,
666
+ size: { width: descriptor.width, height: descriptor.height, depthOrArrayLayers: 1 },
667
+ format: descriptor.format,
668
+ mipLevelCount: 1,
669
+ sampleCount: 4,
670
+ dimension: "2d",
671
+ usage: GPU_TEXTURE_USAGE_RENDER_ATTACHMENT,
672
+ viewFormats: void 0,
673
+ textureBindingViewDimension: void 0
674
+ });
675
+ if (!msaa.ok)
676
+ return {
677
+ ok: false,
678
+ error: new RenderTargetOperationFailedError({
679
+ operation: "create",
680
+ stage: "allocation",
681
+ generation,
682
+ cause: msaa.error,
683
+ recovery: "retry"
684
+ })
685
+ };
686
+ const msaaView = device.createTextureView(msaa.value, {
687
+ dimension: "2d",
688
+ baseMipLevel: 0,
689
+ mipLevelCount: 1,
690
+ baseArrayLayer: 0,
691
+ arrayLayerCount: 1
692
+ });
693
+ if (!msaaView.ok)
694
+ return {
695
+ ok: false,
696
+ error: new RenderTargetOperationFailedError({
697
+ operation: "create",
698
+ stage: "allocation",
699
+ generation,
700
+ cause: msaaView.error,
701
+ recovery: "retry"
702
+ })
703
+ };
704
+ colorTextures.push(msaa.value);
705
+ faceViews.push(msaaView.value);
706
+ }
707
+ } else {
708
+ for (let face = 0; face < layers; face += 1) {
709
+ colorTextures.push(texture);
710
+ faceViews.push(resolveFaceViews[face] ?? view.value);
711
+ }
712
+ }
713
+ return {
714
+ ok: true,
715
+ value: {
716
+ generation,
717
+ descriptor,
718
+ texture,
719
+ view: view.value,
720
+ mipViews,
721
+ colorTextures,
722
+ faceViews,
723
+ depthTextures,
724
+ depthViews,
725
+ ...descriptor.sampleCount === 4 ? { resolveTexture: texture } : {},
726
+ resolveView: view.value,
727
+ resolveFaceViews
728
+ }
729
+ };
730
+ }
731
+ function destroyPhysical(device, physical) {
732
+ if (device === void 0 || physical === void 0) return;
733
+ const textures = /* @__PURE__ */ new Set();
734
+ textures.add(physical.texture);
735
+ if (physical.resolveTexture !== void 0) textures.add(physical.resolveTexture);
736
+ for (const texture of physical.colorTextures) textures.add(texture);
737
+ for (const texture of physical.depthTextures) textures.add(texture);
738
+ for (const texture of textures) device.destroyTexture(texture);
739
+ }
740
+ function createRenderTargetHost(options = {}) {
741
+ let disposed = false;
742
+ const limits = options.limits ?? DEFAULT_LIMITS;
743
+ const owner = createRenderTargetOwner({
744
+ rendererId: options.rendererId ?? /* @__PURE__ */ Symbol("renderer"),
745
+ initialGeneration: options.initialGeneration ?? 0
746
+ });
747
+ const targets = /* @__PURE__ */ new Set();
748
+ const staged = /* @__PURE__ */ new Set();
749
+ const activePhysical = /* @__PURE__ */ new WeakMap();
750
+ const candidatePhysical = /* @__PURE__ */ new WeakMap();
751
+ const sources = /* @__PURE__ */ new WeakMap();
752
+ const readbacks = /* @__PURE__ */ new WeakMap();
753
+ const readbackRecords = /* @__PURE__ */ new Set();
754
+ const currentGeneration = () => options.getGeneration?.() ?? options.initialGeneration ?? 0;
755
+ const stagePhysical = (target, descriptor) => {
756
+ const stagedTarget = owner.stage(target, descriptor);
757
+ if (!stagedTarget.ok) return stagedTarget;
758
+ const device = options.getDevice?.();
759
+ if (device === void 0) {
760
+ staged.add(target);
761
+ return { ok: true, value: void 0 };
762
+ }
763
+ const physical = makePhysical(
764
+ device,
765
+ stagedTarget.value.descriptor,
766
+ stagedTarget.value.generation
767
+ );
768
+ if (!physical.ok) {
769
+ owner.rejectCandidate(target, stagedTarget.value.generation, "allocation");
770
+ return physical;
771
+ }
772
+ candidatePhysical.set(target, physical.value);
773
+ staged.add(target);
774
+ return { ok: true, value: void 0 };
775
+ };
776
+ return Object.freeze({
777
+ owner: "renderer",
778
+ descriptions() {
779
+ return [...targets].map((target) => {
780
+ const state = owner.inspect(target);
781
+ if (!state.ok) throw state.error;
782
+ return { target, descriptor: state.value.candidate?.descriptor ?? state.value.descriptor };
783
+ });
784
+ },
785
+ createRenderTarget(descriptor) {
786
+ if (disposed) {
787
+ return {
788
+ ok: false,
789
+ error: new RenderTargetStateInvalidError({
790
+ operation: "inspect",
791
+ reason: "destroyed",
792
+ state: "destroyed",
793
+ generation: currentGeneration()
794
+ })
795
+ };
796
+ }
797
+ const admitted = admitRenderTargetDescriptor(descriptor, limits);
798
+ if (!admitted.ok) return admitted;
799
+ const created = owner.create(admitted.value);
800
+ if (created.ok) targets.add(created.value);
801
+ return created;
802
+ },
803
+ resizeRenderTarget(target, descriptor) {
804
+ const admitted = admitRenderTargetDescriptor(descriptor, limits);
805
+ if (!admitted.ok) return admitted;
806
+ return stagePhysical(target, admitted.value);
807
+ },
808
+ createRenderTargetTextureSource(target, sourceOptions) {
809
+ const inspected = owner.inspect(target);
810
+ if (!inspected.ok) return inspected;
811
+ if (!inspected.value.descriptor.sampled) {
812
+ return {
813
+ ok: false,
814
+ error: new RenderTargetCapabilityMissingError({
815
+ operation: "source",
816
+ requested: "sampled=true",
817
+ capability: "sampled",
818
+ actual: "false"
819
+ })
820
+ };
821
+ }
822
+ if (sourceOptions.dimension !== inspected.value.descriptor.shape) {
823
+ return {
824
+ ok: false,
825
+ error: new RenderTargetDescriptorInvalidError({
826
+ field: "dimension",
827
+ value: sourceOptions.dimension,
828
+ expected: `dimension matches ${inspected.value.descriptor.shape}`
829
+ })
830
+ };
831
+ }
832
+ if (!Number.isInteger(sourceOptions.mipLevel) || sourceOptions.mipLevel < 0 || inspected.value.descriptor.mipLevels === 1 && sourceOptions.mipLevel !== 0) {
833
+ return {
834
+ ok: false,
835
+ error: new RenderTargetDescriptorInvalidError({
836
+ field: "mipLevel",
837
+ value: sourceOptions.mipLevel,
838
+ expected: "an admitted mip level for the target"
839
+ })
840
+ };
841
+ }
842
+ const binding = createRenderTargetMaterialSource(target, inspected.value.descriptor, {
843
+ ...sourceOptions,
844
+ generation: inspected.value.generation
845
+ });
846
+ if (!binding.ok) return binding;
847
+ sources.set(binding.value.source, binding.value);
848
+ return { ok: true, value: binding.value.source };
849
+ },
850
+ resolveRenderTargetTextureSource(source) {
851
+ const binding = sources.get(source) ?? resolveRenderTargetMaterialSource(source);
852
+ if (binding === void 0) return void 0;
853
+ const physical = activePhysical.get(binding.target);
854
+ if (physical === void 0) return binding;
855
+ const view = physical.mipViews[binding.view.mipLevel] ?? (binding.shape === "cube" ? physical.view : physical.resolveView);
856
+ if (binding.generation !== physical.generation) return binding;
857
+ return { ...binding, textureView: view };
858
+ },
859
+ requestTargetReadback(target, request) {
860
+ const inspected = owner.inspect(target);
861
+ if (!inspected.ok) return inspected;
862
+ if (!inspected.value.descriptor.readback) {
863
+ return {
864
+ ok: false,
865
+ error: new RenderTargetCapabilityMissingError({
866
+ operation: "readback",
867
+ requested: "readback=true",
868
+ capability: "readback",
869
+ actual: "false"
870
+ })
871
+ };
872
+ }
873
+ if (!Number.isInteger(request.mipLevel) || request.mipLevel < 0) {
874
+ return {
875
+ ok: false,
876
+ error: new RenderTargetDescriptorInvalidError({
877
+ field: "mipLevel",
878
+ value: request.mipLevel,
879
+ expected: "a non-negative integer"
880
+ })
881
+ };
882
+ }
883
+ const mipCount2 = inspected.value.descriptor.mipLevels === 1 ? 1 : Math.floor(
884
+ Math.log2(
885
+ Math.max(inspected.value.descriptor.width, inspected.value.descriptor.height)
886
+ )
887
+ ) + 1;
888
+ if (request.mipLevel >= mipCount2) {
889
+ return {
890
+ ok: false,
891
+ error: new RenderTargetDescriptorInvalidError({
892
+ field: "mipLevel",
893
+ value: request.mipLevel,
894
+ expected: `mipLevel < ${mipCount2}`
895
+ })
896
+ };
897
+ }
898
+ if (request.face !== void 0 && (!Number.isInteger(request.face) || request.face < 0 || request.face > 5 || inspected.value.descriptor.shape !== "cube")) {
899
+ return {
900
+ ok: false,
901
+ error: new RenderTargetDescriptorInvalidError({
902
+ field: "face",
903
+ value: request.face,
904
+ expected: inspected.value.descriptor.shape === "cube" ? "an integer in [0, 5]" : "omitted for a 2d target"
905
+ })
906
+ };
907
+ }
908
+ const ticket = opaqueTicket();
909
+ const extent = resolveRenderTargetMipExtent(inspected.value.descriptor, request.mipLevel);
910
+ const buffer = options.getDevice?.()?.createBuffer({
911
+ label: `render-target-readback.${request.mipLevel}.${request.face ?? 0}`,
912
+ size: Math.ceil(extent.width * bytesPerPixel(inspected.value.descriptor.format) / 256) * 256 * extent.height,
913
+ usage: GPU_BUFFER_USAGE_COPY_DST | GPU_BUFFER_USAGE_MAP_READ,
914
+ mappedAtCreation: false
915
+ });
916
+ if (buffer !== void 0 && !buffer.ok) {
917
+ return {
918
+ ok: false,
919
+ error: new RenderTargetOperationFailedError({
920
+ operation: "readback",
921
+ stage: "allocation",
922
+ generation: inspected.value.generation,
923
+ cause: buffer.error,
924
+ recovery: "retry"
925
+ })
926
+ };
927
+ }
928
+ const internalTicket = createRenderTargetReadbackTicket(target, {
929
+ deviceGeneration: inspected.value.generation,
930
+ mipLevel: request.mipLevel,
931
+ ...request.face === void 0 ? {} : { face: request.face },
932
+ width: extent.width,
933
+ height: extent.height,
934
+ bytesPerPixel: bytesPerPixel(inspected.value.descriptor.format)
935
+ });
936
+ if (!internalTicket.ok) return internalTicket;
937
+ const record = {
938
+ target,
939
+ request,
940
+ ticket: internalTicket.value,
941
+ ...buffer === void 0 ? {} : { buffer: buffer.value },
942
+ encoded: false
943
+ };
944
+ readbacks.set(ticket, record);
945
+ readbackRecords.add(record);
946
+ return { ok: true, value: ticket };
947
+ },
948
+ async observeTargetReadbacks(receipt, tickets) {
949
+ const results = [];
950
+ for (const publicTicket of tickets) {
951
+ const record = readbacks.get(publicTicket);
952
+ if (record === void 0) {
953
+ return {
954
+ ok: false,
955
+ error: new RenderTargetStateInvalidError({
956
+ operation: "readback",
957
+ reason: "foreign-renderer",
958
+ state: "destroyed",
959
+ generation: receipt.deviceGeneration
960
+ })
961
+ };
962
+ }
963
+ const inspected = owner.inspect(record.target);
964
+ if (!inspected.ok) return inspected;
965
+ if (inspected.value.state !== "active") {
966
+ return {
967
+ ok: false,
968
+ error: new RenderTargetStateInvalidError({
969
+ operation: "readback",
970
+ reason: "uninitialized",
971
+ state: inspected.value.state,
972
+ generation: inspected.value.generation
973
+ })
974
+ };
975
+ }
976
+ if (inspected.value.generation !== receipt.deviceGeneration) {
977
+ return {
978
+ ok: false,
979
+ error: new RenderTargetStateInvalidError({
980
+ operation: "readback",
981
+ reason: "generation-mismatch",
982
+ state: inspected.value.state,
983
+ generation: inspected.value.generation
984
+ })
985
+ };
986
+ }
987
+ const bound = bindRenderTargetReadbackTicket(record.ticket, receipt);
988
+ if (!bound.ok) return bound;
989
+ let bytes = new Uint8Array(record.ticket.byteLength);
990
+ if (record.buffer !== void 0 && typeof record.buffer.mapAsync === "function") {
991
+ const mapped = await record.buffer.mapAsync(1);
992
+ if (!mapped.ok) {
993
+ return {
994
+ ok: false,
995
+ error: new RenderTargetOperationFailedError({
996
+ operation: "readback",
997
+ stage: "copy",
998
+ generation: receipt.deviceGeneration,
999
+ cause: mapped.error,
1000
+ recovery: "retry"
1001
+ })
1002
+ };
1003
+ }
1004
+ const range = mapped.value.getMappedRange();
1005
+ if (!range.ok) {
1006
+ return {
1007
+ ok: false,
1008
+ error: new RenderTargetOperationFailedError({
1009
+ operation: "readback",
1010
+ stage: "copy",
1011
+ generation: receipt.deviceGeneration,
1012
+ cause: range.error,
1013
+ recovery: "retry"
1014
+ })
1015
+ };
1016
+ }
1017
+ bytes = new Uint8Array(range.value.slice(0));
1018
+ mapped.value.unmap();
1019
+ }
1020
+ const completed = completeRenderTargetReadback(record.ticket, receipt, bytes);
1021
+ if (!completed.ok) return completed;
1022
+ results.push({
1023
+ ticket: publicTicket,
1024
+ bytes: completed.value.bytes,
1025
+ frameId: completed.value.frameId,
1026
+ deviceGeneration: completed.value.deviceGeneration,
1027
+ mipLevel: completed.value.mipLevel,
1028
+ ...completed.value.face === void 0 ? {} : { face: completed.value.face },
1029
+ bytesPerRow: record.ticket.bytesPerRow,
1030
+ byteLength: record.ticket.byteLength
1031
+ });
1032
+ }
1033
+ return { ok: true, value: Object.freeze(results) };
1034
+ },
1035
+ destroyRenderTarget(target) {
1036
+ const destroyed = owner.destroy(target);
1037
+ if (destroyed.ok) {
1038
+ destroyPhysical(options.getDevice?.(), activePhysical.get(target));
1039
+ destroyPhysical(options.getDevice?.(), candidatePhysical.get(target));
1040
+ activePhysical.delete(target);
1041
+ candidatePhysical.delete(target);
1042
+ for (const record of readbackRecords) {
1043
+ if (record.target !== target) continue;
1044
+ if (record.buffer !== void 0) options.getDevice?.()?.destroyBuffer(record.buffer);
1045
+ readbacks.delete(record.ticket);
1046
+ readbackRecords.delete(record);
1047
+ }
1048
+ targets.delete(target);
1049
+ }
1050
+ return destroyed;
1051
+ },
1052
+ beginFrame() {
1053
+ if (disposed) return;
1054
+ for (const target of targets) {
1055
+ const inspected = owner.inspect(target);
1056
+ if (!inspected.ok || inspected.value.state === "active" || inspected.value.state === "candidate") {
1057
+ continue;
1058
+ }
1059
+ stagePhysical(target);
1060
+ }
1061
+ },
1062
+ onFrameSubmitted(completed = Promise.resolve({ ok: true, value: void 0 })) {
1063
+ if (disposed) return;
1064
+ const submittedTargets = [...staged];
1065
+ staged.clear();
1066
+ void completed.then((result) => {
1067
+ for (const target of submittedTargets) {
1068
+ const candidate = owner.inspect(target);
1069
+ if (!candidate.ok || candidate.value.candidate === void 0) continue;
1070
+ if (!result.ok) {
1071
+ owner.rejectCandidate(target, candidate.value.candidate.generation, "submit");
1072
+ destroyPhysical(options.getDevice?.(), candidatePhysical.get(target));
1073
+ candidatePhysical.delete(target);
1074
+ continue;
1075
+ }
1076
+ if (options.canPromoteTarget?.(target) === false) {
1077
+ staged.add(target);
1078
+ continue;
1079
+ }
1080
+ const generation = candidate.value.candidate.generation;
1081
+ const physical = candidatePhysical.get(target);
1082
+ if (physical === void 0) {
1083
+ owner.rejectCandidate(target, generation, "submit");
1084
+ continue;
1085
+ }
1086
+ const promoted = owner.promote(target, generation);
1087
+ if (!promoted.ok) {
1088
+ destroyPhysical(options.getDevice?.(), physical);
1089
+ candidatePhysical.delete(target);
1090
+ continue;
1091
+ }
1092
+ const previous = activePhysical.get(target);
1093
+ activePhysical.set(target, physical);
1094
+ candidatePhysical.delete(target);
1095
+ destroyPhysical(options.getDevice?.(), previous);
1096
+ }
1097
+ });
1098
+ },
1099
+ getPhysicalTarget(target) {
1100
+ return candidatePhysical.get(target) ?? activePhysical.get(target);
1101
+ },
1102
+ encodePendingReadbacks(encoder, faces) {
1103
+ for (const record of readbackRecords) {
1104
+ if (record.encoded || record.buffer === void 0) continue;
1105
+ if (faces !== void 0 && record.ticket.face !== void 0 && !faces.includes(record.ticket.face)) {
1106
+ continue;
1107
+ }
1108
+ const candidate = candidatePhysical.get(record.target);
1109
+ const physical = faces !== void 0 && candidate !== void 0 && record.ticket.face !== void 0 && faces.includes(record.ticket.face) ? candidate : activePhysical.get(record.target);
1110
+ if (physical === void 0) continue;
1111
+ const source = physical.resolveTexture ?? physical.texture;
1112
+ encoder.copyTextureToBuffer(
1113
+ {
1114
+ texture: source,
1115
+ mipLevel: record.ticket.mipLevel,
1116
+ origin: { x: 0, y: 0, z: record.ticket.face ?? 0 }
1117
+ },
1118
+ {
1119
+ buffer: record.buffer,
1120
+ bytesPerRow: record.ticket.bytesPerRow,
1121
+ rowsPerImage: record.ticket.height
1122
+ },
1123
+ [record.ticket.width, record.ticket.height, 1]
1124
+ );
1125
+ record.encoded = true;
1126
+ }
1127
+ },
1128
+ recover() {
1129
+ if (disposed) return;
1130
+ const generation = currentGeneration();
1131
+ for (const target of targets) {
1132
+ const inspected = owner.inspect(target);
1133
+ if (!inspected.ok || inspected.value.state !== "active") continue;
1134
+ destroyPhysical(options.getDevice?.(), activePhysical.get(target));
1135
+ destroyPhysical(options.getDevice?.(), candidatePhysical.get(target));
1136
+ activePhysical.delete(target);
1137
+ candidatePhysical.delete(target);
1138
+ for (const record of readbackRecords) {
1139
+ if (record.target !== target) continue;
1140
+ if (record.buffer !== void 0) options.getDevice?.()?.destroyBuffer(record.buffer);
1141
+ readbacks.delete(record.ticket);
1142
+ readbackRecords.delete(record);
1143
+ }
1144
+ const begun = owner.beginRecovery(target, generation);
1145
+ if (begun.ok) owner.finishRecovery(target);
1146
+ }
1147
+ },
1148
+ dispose() {
1149
+ disposed = true;
1150
+ for (const target of [...targets]) {
1151
+ destroyPhysical(options.getDevice?.(), activePhysical.get(target));
1152
+ destroyPhysical(options.getDevice?.(), candidatePhysical.get(target));
1153
+ for (const record of readbackRecords) {
1154
+ if (record.target !== target) continue;
1155
+ if (record.buffer !== void 0) options.getDevice?.()?.destroyBuffer(record.buffer);
1156
+ readbacks.delete(record.ticket);
1157
+ readbackRecords.delete(record);
1158
+ }
1159
+ activePhysical.delete(target);
1160
+ candidatePhysical.delete(target);
1161
+ owner.destroy(target);
1162
+ }
1163
+ targets.clear();
1164
+ staged.clear();
1165
+ readbackRecords.clear();
1166
+ }
1167
+ });
1168
+ }
1169
+
1170
+ // src/publication/targets.ts
1171
+ var RenderPublicationTargetOwner = class {
1172
+ host = createRenderTargetHost();
1173
+ ids = /* @__PURE__ */ new WeakMap();
1174
+ nextId = 0;
1175
+ authoring = this.host;
1176
+ snapshot() {
1177
+ return this.host.descriptions().map(({ target, descriptor }) => {
1178
+ let id = this.ids.get(target);
1179
+ if (id === void 0) {
1180
+ id = ++this.nextId;
1181
+ this.ids.set(target, id);
1182
+ }
1183
+ return { id, token: target, descriptor };
1184
+ });
1185
+ }
1186
+ dispose() {
1187
+ this.host.dispose();
1188
+ }
1189
+ };
1190
+ function publicationTargetSources(templates) {
1191
+ const sources = /* @__PURE__ */ new Map();
1192
+ for (const template of templates)
1193
+ for (const material of template.snapshot.materials) {
1194
+ for (const source of material.textureSources?.values() ?? []) {
1195
+ if (sources.has(source)) continue;
1196
+ const binding = resolveRenderTargetMaterialSource(source);
1197
+ if (binding === void 0)
1198
+ throw new RenderPublicationError({
1199
+ reason: "shape",
1200
+ subject: "unknown material target source"
1201
+ });
1202
+ sources.set(source, {
1203
+ token: source,
1204
+ target: binding.target,
1205
+ options: {
1206
+ aspect: "color",
1207
+ dimension: binding.view.dimension,
1208
+ mipLevel: binding.view.mipLevel
1209
+ }
1210
+ });
1211
+ }
1212
+ }
1213
+ return [...sources.values()];
1214
+ }
1215
+ var RenderPublicationTargetReceiver = class {
1216
+ constructor(host) {
1217
+ this.host = host;
1218
+ }
1219
+ host;
1220
+ targets = /* @__PURE__ */ new Map();
1221
+ apply(input) {
1222
+ const packet = input.packet;
1223
+ if (packet.targets.length === 0 && packet.targetSources.length === 0 && this.targets.size === 0)
1224
+ return input;
1225
+ const tokens = /* @__PURE__ */ new Map();
1226
+ const records = /* @__PURE__ */ new Map();
1227
+ const active = new Set(packet.targets.map((row) => row.id));
1228
+ for (const [id, record] of this.targets)
1229
+ if (!active.has(id)) {
1230
+ const destroyed = this.host.destroyRenderTarget(record.target);
1231
+ if (!destroyed.ok) throw destroyed.error;
1232
+ this.targets.delete(id);
1233
+ }
1234
+ for (const row of packet.targets) {
1235
+ let record = this.targets.get(row.id);
1236
+ if (record === void 0) {
1237
+ const created = this.host.createRenderTarget(row.descriptor);
1238
+ if (!created.ok) throw created.error;
1239
+ record = { target: created.value, descriptor: row.descriptor, sources: /* @__PURE__ */ new Map() };
1240
+ this.targets.set(row.id, record);
1241
+ } else if (JSON.stringify(record.descriptor) !== JSON.stringify(row.descriptor)) {
1242
+ const resized = this.host.resizeRenderTarget(record.target, row.descriptor);
1243
+ if (!resized.ok) throw resized.error;
1244
+ record.descriptor = row.descriptor;
1245
+ record.sources.clear();
1246
+ }
1247
+ tokens.set(row.token, record.target);
1248
+ records.set(row.token, record);
1249
+ }
1250
+ const resolve = (token2) => {
1251
+ const target = tokens.get(token2);
1252
+ if (target === void 0)
1253
+ throw new RenderPublicationError({ reason: "shape", subject: "missing target descriptor" });
1254
+ return target;
1255
+ };
1256
+ const sources = /* @__PURE__ */ new Map();
1257
+ for (const row of packet.targetSources) {
1258
+ const record = records.get(row.target);
1259
+ if (record === void 0)
1260
+ throw new RenderPublicationError({ reason: "shape", subject: "missing material target" });
1261
+ const key = JSON.stringify(row.options);
1262
+ let source = record.sources.get(key);
1263
+ if (source === void 0) {
1264
+ const created = this.host.createRenderTargetTextureSource(record.target, row.options);
1265
+ if (!created.ok) throw created.error;
1266
+ source = created.value;
1267
+ record.sources.set(key, source);
1268
+ }
1269
+ sources.set(row.token, source);
1270
+ }
1271
+ const camera = (row) => row.target === void 0 ? row : { ...row, target: resolve(row.target) };
1272
+ const renderables = input.frame.renderables.map((row) => {
1273
+ const materials = row.materials.map((material) => {
1274
+ if (material.textureSources === void 0) return material;
1275
+ const textureSources = new Map(
1276
+ [...material.textureSources].map(([name, token2]) => {
1277
+ const source = sources.get(token2);
1278
+ if (source === void 0)
1279
+ throw new RenderPublicationError({
1280
+ reason: "shape",
1281
+ subject: "missing material target source"
1282
+ });
1283
+ return [name, source];
1284
+ })
1285
+ );
1286
+ return { ...material, textureSources };
1287
+ });
1288
+ const first = row.materials.indexOf(row.material);
1289
+ return { ...row, materials, material: materials[Math.max(0, first)] ?? row.material };
1290
+ });
1291
+ const snapshots = new Map(renderables.map((row) => [row.entityKey, row]));
1292
+ return {
1293
+ ...input,
1294
+ frame: {
1295
+ ...input.frame,
1296
+ renderables,
1297
+ cameras: input.frame.cameras.map(camera),
1298
+ auxiliaryCameras: input.frame.auxiliaryCameras.map(camera),
1299
+ cubeCameras: input.frame.cubeCameras.map(camera)
1300
+ },
1301
+ operations: input.operations.map((operation) => {
1302
+ if (operation.kind === "remove" || operation.snapshot === void 0) return operation;
1303
+ const snapshot = snapshots.get(operation.entityKey);
1304
+ if (snapshot === void 0)
1305
+ throw new RenderPublicationError({
1306
+ reason: "shape",
1307
+ subject: "missing remapped snapshot"
1308
+ });
1309
+ return { ...operation, snapshot };
1310
+ })
1311
+ };
1312
+ }
1313
+ };
6
1314
  var BARREL_DISTORTION_POST_PROCESS_ID = "fullscreen.forgeax.barrel-distortion";
7
1315
  var BARREL_DISTORTION_FEATURE_IDENTITY = BARREL_DISTORTION_POST_PROCESS_ID;
8
1316
  var BARREL_DISTORTION_WGSL_COORDINATE = (
@@ -3482,7 +4790,7 @@ function fieldWidth(type) {
3482
4790
  function finiteNumber(value) {
3483
4791
  return typeof value === "number" && Number.isFinite(value);
3484
4792
  }
3485
- function invalid(code, operation, expected, actual, field, page) {
4793
+ function invalid3(code, operation, expected, actual, field, page) {
3486
4794
  return new DynamicInputError(code, {
3487
4795
  operation,
3488
4796
  expected,
@@ -3523,7 +4831,7 @@ var ReadonlyDynamicInputPage = class _ReadonlyDynamicInputPage {
3523
4831
  static create(input) {
3524
4832
  if (input.sourceId.length === 0 || !Number.isSafeInteger(input.pageId) || input.pageId < 0) {
3525
4833
  return err(
3526
- invalid(
4834
+ invalid3(
3527
4835
  "invalid-schema",
3528
4836
  "create",
3529
4837
  "sourceId is non-empty and pageId is non-negative",
@@ -3534,7 +4842,7 @@ var ReadonlyDynamicInputPage = class _ReadonlyDynamicInputPage {
3534
4842
  const layout = deriveMaterialDynamicInputLayout(input.schema);
3535
4843
  if (!layout.ok) {
3536
4844
  return err(
3537
- invalid(
4845
+ invalid3(
3538
4846
  "invalid-schema",
3539
4847
  "create",
3540
4848
  layout.error.expected,
@@ -3568,7 +4876,7 @@ var ReadonlyDynamicInputPage = class _ReadonlyDynamicInputPage {
3568
4876
  if (!live.ok) return live;
3569
4877
  if (!Number.isSafeInteger(index) || index < 0 || index >= this.schema.maxRecords) {
3570
4878
  return err(
3571
- invalid(
4879
+ invalid3(
3572
4880
  "range-overflow",
3573
4881
  "write",
3574
4882
  `record index is within [0, ${this.schema.maxRecords})`,
@@ -3585,7 +4893,7 @@ var ReadonlyDynamicInputPage = class _ReadonlyDynamicInputPage {
3585
4893
  const value = values[field.name];
3586
4894
  if (value === void 0) {
3587
4895
  return err(
3588
- invalid(
4896
+ invalid3(
3589
4897
  "invalid-record",
3590
4898
  "write",
3591
4899
  `record contains field ${field.name}`,
@@ -3599,7 +4907,7 @@ var ReadonlyDynamicInputPage = class _ReadonlyDynamicInputPage {
3599
4907
  const numbers = typeof value === "number" ? [value] : value;
3600
4908
  if (numbers.length !== width || numbers.some((candidate) => !finiteNumber(candidate))) {
3601
4909
  return err(
3602
- invalid(
4910
+ invalid3(
3603
4911
  "invalid-record",
3604
4912
  "write",
3605
4913
  `${field.name} is a finite ${field.type}`,
@@ -3611,7 +4919,7 @@ var ReadonlyDynamicInputPage = class _ReadonlyDynamicInputPage {
3611
4919
  }
3612
4920
  if (field.type === "u32" && (!Number.isInteger(numbers[0]) || numbers[0] < 0 || numbers[0] > 4294967295)) {
3613
4921
  return err(
3614
- invalid(
4922
+ invalid3(
3615
4923
  "invalid-record",
3616
4924
  "write",
3617
4925
  `${field.name} is an unsigned 32-bit integer`,
@@ -3638,7 +4946,7 @@ var ReadonlyDynamicInputPage = class _ReadonlyDynamicInputPage {
3638
4946
  if (!live.ok) return live;
3639
4947
  if (input.domain.length === 0) {
3640
4948
  return err(
3641
- invalid(
4949
+ invalid3(
3642
4950
  "domain-overflow",
3643
4951
  "reserve",
3644
4952
  "domain is a non-empty identity",
@@ -3650,7 +4958,7 @@ var ReadonlyDynamicInputPage = class _ReadonlyDynamicInputPage {
3650
4958
  }
3651
4959
  if (!this.domains.has(input.domain) && this.domains.size >= this.schema.maxDomains) {
3652
4960
  return err(
3653
- invalid(
4961
+ invalid3(
3654
4962
  "domain-overflow",
3655
4963
  "reserve",
3656
4964
  `at most ${this.schema.maxDomains} domains are active`,
@@ -3662,7 +4970,7 @@ var ReadonlyDynamicInputPage = class _ReadonlyDynamicInputPage {
3662
4970
  }
3663
4971
  if (!Number.isSafeInteger(input.instanceIndex) || input.instanceIndex < 0 || input.instanceIndex > 4294967295) {
3664
4972
  return err(
3665
- invalid(
4973
+ invalid3(
3666
4974
  "range-overflow",
3667
4975
  "reserve",
3668
4976
  "instance index is an exact unsigned 32-bit integer",
@@ -3674,7 +4982,7 @@ var ReadonlyDynamicInputPage = class _ReadonlyDynamicInputPage {
3674
4982
  }
3675
4983
  if (input.member.worldIdentity.length === 0 || !Number.isSafeInteger(input.member.entityKey) || input.member.entityKey < 0 || input.member.entityKey > 4294967295 || !Number.isSafeInteger(input.member.drawItemIndex) || input.member.drawItemIndex < 0 || input.member.drawItemIndex > 4294967295 || !Number.isSafeInteger(input.member.instanceOrdinal) || input.member.instanceOrdinal < 0 || input.member.instanceOrdinal > 4294967295) {
3676
4984
  return err(
3677
- invalid(
4985
+ invalid3(
3678
4986
  "range-overflow",
3679
4987
  "reserve",
3680
4988
  "member is a stable World identity plus exact unsigned 32-bit entity, draw-item, and instance identities",
@@ -3686,7 +4994,7 @@ var ReadonlyDynamicInputPage = class _ReadonlyDynamicInputPage {
3686
4994
  }
3687
4995
  if (!Number.isSafeInteger(input.recordStart) || !Number.isSafeInteger(input.recordCount) || input.recordStart < 0 || input.recordCount <= 0 || input.recordStart + input.recordCount > this.schema.maxRecords) {
3688
4996
  return err(
3689
- invalid(
4997
+ invalid3(
3690
4998
  "range-overflow",
3691
4999
  "reserve",
3692
5000
  "record range and instance index fit the declared page",
@@ -3745,7 +5053,7 @@ var ReadonlyDynamicInputPage = class _ReadonlyDynamicInputPage {
3745
5053
  if (!live.ok) return live;
3746
5054
  if (!this.ownedUploads.has(receipt) || receipt.sourceId !== this.sourceId || receipt.pageId !== this.pageId || receipt.bufferGeneration !== this.bufferGenerationValue || receipt.deviceGeneration !== this.deviceGenerationValue || receipt.contentRevision !== this.contentRevisionValue) {
3747
5055
  return err(
3748
- invalid(
5056
+ invalid3(
3749
5057
  "stale-generation",
3750
5058
  "upload",
3751
5059
  "the upload receipt still describes the current page revision and generation",
@@ -3779,7 +5087,7 @@ var ReadonlyDynamicInputPage = class _ReadonlyDynamicInputPage {
3779
5087
  if (!live.ok) return live;
3780
5088
  if (!this.ownedRanges.has(range) || range.sourceId !== this.sourceId || range.pageId !== this.pageId || range.bufferGeneration !== this.bufferGenerationValue || range.deviceGeneration !== this.deviceGenerationValue || range.recordStart < 0 || range.recordCount <= 0 || range.recordStart + range.recordCount > this.schema.maxRecords) {
3781
5089
  return err(
3782
- invalid(
5090
+ invalid3(
3783
5091
  "stale-generation",
3784
5092
  "consume",
3785
5093
  "range belongs to this current page generation",
@@ -3791,7 +5099,7 @@ var ReadonlyDynamicInputPage = class _ReadonlyDynamicInputPage {
3791
5099
  }
3792
5100
  if (this.uploadedRevisionValue < range.contentRevision) {
3793
5101
  return err(
3794
- invalid(
5102
+ invalid3(
3795
5103
  "not-uploaded",
3796
5104
  "consume",
3797
5105
  "range content revision was uploaded before consumption",
@@ -3809,7 +5117,7 @@ var ReadonlyDynamicInputPage = class _ReadonlyDynamicInputPage {
3809
5117
  if (!live.ok) return live;
3810
5118
  if (!Number.isSafeInteger(deviceGeneration) || deviceGeneration < 0) {
3811
5119
  return err(
3812
- invalid(
5120
+ invalid3(
3813
5121
  "stale-generation",
3814
5122
  "reconfigure",
3815
5123
  "deviceGeneration is a non-negative safe integer",
@@ -3822,7 +5130,7 @@ var ReadonlyDynamicInputPage = class _ReadonlyDynamicInputPage {
3822
5130
  const rendererInitialGeneration = this.bufferGenerationValue === 1 && this.deviceGenerationValue === 1 && deviceGeneration === 0;
3823
5131
  if (deviceGeneration < this.deviceGenerationValue && !rendererInitialGeneration) {
3824
5132
  return err(
3825
- invalid(
5133
+ invalid3(
3826
5134
  "stale-generation",
3827
5135
  "reconfigure",
3828
5136
  "deviceGeneration does not precede the current device generation",
@@ -3847,7 +5155,7 @@ var ReadonlyDynamicInputPage = class _ReadonlyDynamicInputPage {
3847
5155
  }
3848
5156
  assertLive(operation) {
3849
5157
  return this.released ? err(
3850
- invalid(
5158
+ invalid3(
3851
5159
  "released",
3852
5160
  operation,
3853
5161
  ERROR_POLICY2.released.expected,
@@ -4586,12 +5894,12 @@ function createDynamicGeometryLifecycle(maxCandidates = 32, maxMeshBytes = 64 *
4586
5894
  { actual: records.size }
4587
5895
  );
4588
5896
  }
4589
- const invalid2 = validateMesh(input.mesh);
4590
- if (invalid2 !== void 0)
5897
+ const invalid4 = validateMesh(input.mesh);
5898
+ if (invalid4 !== void 0)
4591
5899
  return failure3(
4592
5900
  "dynamic-geometry-invalid",
4593
5901
  "MeshAsset satisfies the standard geometry contract",
4594
- invalid2
5902
+ invalid4
4595
5903
  );
4596
5904
  const candidateBytes = meshByteSize(input.mesh);
4597
5905
  if (!Number.isSafeInteger(candidateBytes) || candidateBytes < 0 || meshBytes > maxMeshBytes - candidateBytes) {
@@ -4922,6 +6230,713 @@ function createDynamicGeometryLifecycle(maxCandidates = 32, maxMeshBytes = 64 *
4922
6230
  };
4923
6231
  }
4924
6232
 
4925
- export { BARREL_DISTORTION_FEATURE_IDENTITY, BARREL_DISTORTION_POST_PROCESS_ID, BARREL_DISTORTION_WGSL, BARREL_DISTORTION_WGSL_COORDINATE, CLOUD_DENSITY_COMPUTE_WGSL, CLOUD_HISTORY_FULLSCREEN_WGSL, CLOUD_HISTORY_SURFACE_COUNT, CLOUD_LAYER_DENSITY_BINDINGS, CLOUD_LAYER_DENSITY_CACHE, CLOUD_LAYER_DENSITY_OUTPUT, CLOUD_LAYER_DENSITY_PROGRAM, CLOUD_LAYER_FEATURE_IDENTITY, CLOUD_RGBA16FLOAT_BYTES_PER_TEXEL, CLOUD_VIEW_FULLSCREEN_WGSL, CLOUD_VIEW_PARAMS_BYTES, CloudHistoryStore, DEFAULT_REFLECTION_PROBE_LIMITS, DynamicGeometryError, DynamicInputError, LOD_OCCLUSION_INSPECTION_MAX_BYTES, LOD_OCCLUSION_INSPECTION_SCHEMA, ReadonlyDynamicInputPage, ReflectionProbeProjection, SSR_FORMAT_PROFILE, SSR_FORMAT_STAGES, acceptCloudLayerGeneration, admitPointsLines, admitReflectionProbe, admitSingleLayerMediumSubmission, admitSsrM0, admitSsrSpatial, advanceProbeFilter, applyCloudSolarTransmittance, boxProjectReflectionDirection, buildCloudDensityCache, buildReflectionProbeTable, cloudCapabilitiesFromRhi, cloudTemporalResetReasons, cloudTemporalSignature, commitProbeFilterStep, compositeCloudRadiance, consumeLodOcclusionInspection, createBarrelDistortionRenderFeature, createCloudHistory, createCloudLayerFeature, createCloudShadowProjection, createDynamicGeometryLifecycle, createProbeFilterState, deriveReflectionFallbackProjection, estimateReflectionProbeBytes, evaluateCloudDensity, inspectCloudLayer, inspectCloudLayerResources, inspectLodOcclusion, inspectPointShadow, inspectReflectionFallback, inspectVolumetricFog, integrateCloudCameraPath, integrateCloudInterior, integrateCloudPath, integrateCloudSolarColumn, intersectCloudLayer, probeFilterIsSteady, projectCloudShadowUv, projectSsrDependencies, projectSsrSpatialInspection, reconstructCloudDensityCache, reflectionFallbackCoverage, reflectionFallbackProjectionSignature, reflectionFallbackSourceKey, reflectionProbeTableBytes, reprojectCloudHistory, resolveReflectionFallbackSource, resolveSsrAdmissionGeneration, retainCloudLayerAfterFailure, sameCandidateCredential, sampleCloudDensity, sampleCloudShadow, selectReflectionProbe, serializeLodOcclusionInspection, serializeSsrSpatialInspection, snapshotCloudDensityCache, validateReflectionProbeInput, validateScreenSpaceReflection, zeroSsrAdmissionWork };
4926
- //# sourceMappingURL=chunk-ODZWR6JQ.mjs.map
4927
- //# sourceMappingURL=chunk-ODZWR6JQ.mjs.map
6233
+ // src/publication/dependencies.ts
6234
+ function publicationDependencies(row) {
6235
+ const handles = /* @__PURE__ */ new Set([row.assetHandle]);
6236
+ for (const material of row.materials) {
6237
+ for (const handle of [
6238
+ material.materialHandle,
6239
+ material.baseColorTexture,
6240
+ material.metallicRoughnessTexture,
6241
+ material.normalTexture,
6242
+ material.emissiveTexture,
6243
+ material.occlusionTexture
6244
+ ]) {
6245
+ if (handle) handles.add(handle);
6246
+ }
6247
+ for (const handle of material.textureHandles?.values() ?? []) handles.add(handle);
6248
+ for (const handle of material.samplerHandles?.values() ?? []) handles.add(handle);
6249
+ }
6250
+ return [...handles];
6251
+ }
6252
+ function publicationFrameDependencies(frame) {
6253
+ const handles = /* @__PURE__ */ new Set();
6254
+ const add = (handle) => {
6255
+ if (handle) handles.add(handle);
6256
+ };
6257
+ add(frame.skylight?.equirectHandle);
6258
+ add(frame.skybox?.equirectHandle);
6259
+ for (const camera of [...frame.cameras, ...frame.auxiliaryCameras]) add(camera.output?.colorLut);
6260
+ for (const light of frame.lights.spot) {
6261
+ add(light.iesProfileHandle);
6262
+ add(light.cookieHandle);
6263
+ add(light.projectorHandle);
6264
+ }
6265
+ const fogs = frame.volumetricFog === void 0 ? [] : [frame.volumetricFog, ...frame.volumetricFog.additional ?? []];
6266
+ for (const fog of fogs) {
6267
+ add(fog.densityHandle);
6268
+ add(fog.projectorHandle);
6269
+ }
6270
+ return [...handles];
6271
+ }
6272
+ var atlasMaterialCache = /* @__PURE__ */ new WeakMap();
6273
+ var atlasOnlyMaterialCache = /* @__PURE__ */ new WeakMap();
6274
+ var streamingCacheByWorld = /* @__PURE__ */ new WeakMap();
6275
+ function streamingCache(world) {
6276
+ let cache = streamingCacheByWorld.get(world);
6277
+ if (cache === void 0) {
6278
+ cache = {
6279
+ layers: /* @__PURE__ */ new Map(),
6280
+ chunkEntities: /* @__PURE__ */ new Map(),
6281
+ activeChunks: /* @__PURE__ */ new Map()
6282
+ };
6283
+ streamingCacheByWorld.set(world, cache);
6284
+ }
6285
+ return cache;
6286
+ }
6287
+ function encodeTilemapLayerValue(layerOrder, chunkIndex, sortScope = "layer") {
6288
+ if (sortScope === "per-cell") return layerOrder << 20 | 0;
6289
+ return layerOrder << 20 | chunkIndex & 1048575 | 0;
6290
+ }
6291
+ function resolveTilesetMaterial(world, tileset, regionIndex, lookup) {
6292
+ const region = tileset.regions[regionIndex];
6293
+ if (region === void 0) return toShared(0);
6294
+ const atlasIndex = region.atlasIndex ?? 0;
6295
+ const atlasGuid = tileset.atlases[atlasIndex];
6296
+ if (atlasGuid === void 0) return toShared(0);
6297
+ const atlas = resolveTilesetRuntime(world, atlasGuid, lookup);
6298
+ if (!atlas.ok) return toShared(0);
6299
+ const atlasHandle = atlas.value.handle;
6300
+ const atlasId = unwrapHandle(atlasHandle);
6301
+ const cacheKey = `${atlasId}|${regionIndex}`;
6302
+ const cache = atlasMaterialCache.get(world) ?? /* @__PURE__ */ new Map();
6303
+ atlasMaterialCache.set(world, cache);
6304
+ const cached = cache.get(cacheKey);
6305
+ if (cached !== void 0) return cached;
6306
+ const atlasSize = tileset.atlasSizes?.[atlasIndex];
6307
+ const atlasWidth = Math.max(
6308
+ 1,
6309
+ atlasSize !== void 0 ? atlasSize.pixelWidth : tileset.columns * tileset.tileWidth
6310
+ );
6311
+ const atlasHeight = Math.max(
6312
+ 1,
6313
+ atlasSize !== void 0 ? atlasSize.pixelHeight : tileset.rows * tileset.tileHeight
6314
+ );
6315
+ const halfTexelU = 0.5 / atlasWidth;
6316
+ const halfTexelV = 0.5 / atlasHeight;
6317
+ const u = region.x / atlasWidth + halfTexelU;
6318
+ const v = region.y / atlasHeight + halfTexelV;
6319
+ const w = region.width / atlasWidth - 2 * halfTexelU;
6320
+ const h = region.height / atlasHeight - 2 * halfTexelV;
6321
+ const matPayload = {
6322
+ kind: "material",
6323
+ passes: [
6324
+ {
6325
+ name: "Forward",
6326
+ program: { module: "forgeax::sprite" },
6327
+ renderState: {
6328
+ ...{ blend: SPRITE_PREMULTIPLIED_ALPHA_BLEND },
6329
+ tags: { LightMode: "Forward" },
6330
+ queue: 3e3
6331
+ }
6332
+ }
6333
+ ],
6334
+ values: {
6335
+ colorTint: [1, 1, 1, 1],
6336
+ baseColorTexture: atlasHandle,
6337
+ region: [u, v, w, h],
6338
+ pivotAndSize: [0.5, 0.5, 1, 1],
6339
+ flipY: 1
6340
+ }
6341
+ };
6342
+ const matHandle = world.allocSharedRef(
6343
+ "MaterialAsset",
6344
+ matPayload
6345
+ );
6346
+ cache.set(cacheKey, matHandle);
6347
+ return matHandle;
6348
+ }
6349
+ function resolveAtlasOnlyMaterial(world, tileset, atlasIndex, lookup) {
6350
+ const atlasGuid = tileset.atlases[atlasIndex];
6351
+ if (atlasGuid === void 0) return toShared(0);
6352
+ const atlas = resolveTilesetRuntime(world, atlasGuid, lookup);
6353
+ if (!atlas.ok) return toShared(0);
6354
+ const atlasHandle = atlas.value.handle;
6355
+ const atlasId = unwrapHandle(atlasHandle);
6356
+ const cacheKey = String(atlasId);
6357
+ const cache = atlasOnlyMaterialCache.get(world) ?? /* @__PURE__ */ new Map();
6358
+ atlasOnlyMaterialCache.set(world, cache);
6359
+ const cached = cache.get(cacheKey);
6360
+ if (cached !== void 0) return cached;
6361
+ const matPayload = {
6362
+ kind: "material",
6363
+ passes: [
6364
+ {
6365
+ name: "Forward",
6366
+ program: { module: "forgeax::sprite" },
6367
+ renderState: {
6368
+ ...{ blend: SPRITE_PREMULTIPLIED_ALPHA_BLEND },
6369
+ tags: { LightMode: "Forward" },
6370
+ queue: 3e3
6371
+ }
6372
+ }
6373
+ ],
6374
+ values: {
6375
+ colorTint: [1, 1, 1, 1],
6376
+ baseColorTexture: atlasHandle,
6377
+ region: [0, 0, 1, 1],
6378
+ pivotAndSize: [0.5, 0.5, 1, 1],
6379
+ flipY: 1
6380
+ }
6381
+ };
6382
+ const matHandle = world.allocSharedRef(
6383
+ "MaterialAsset",
6384
+ matPayload
6385
+ );
6386
+ cache.set(cacheKey, matHandle);
6387
+ return matHandle;
6388
+ }
6389
+ function computeRegionUv(tileset, region, atlasIndex) {
6390
+ const atlasSize = tileset.atlasSizes?.[atlasIndex];
6391
+ const atlasWidth = Math.max(
6392
+ 1,
6393
+ atlasSize !== void 0 ? atlasSize.pixelWidth : tileset.columns * tileset.tileWidth
6394
+ );
6395
+ const atlasHeight = Math.max(
6396
+ 1,
6397
+ atlasSize !== void 0 ? atlasSize.pixelHeight : tileset.rows * tileset.tileHeight
6398
+ );
6399
+ const halfTexelU = 0.5 / atlasWidth;
6400
+ const halfTexelV = 0.5 / atlasHeight;
6401
+ return [
6402
+ region.x / atlasWidth + halfTexelU,
6403
+ region.y / atlasHeight + halfTexelV,
6404
+ region.width / atlasWidth - 2 * halfTexelU,
6405
+ region.height / atlasHeight - 2 * halfTexelV
6406
+ ];
6407
+ }
6408
+ var SQRT1_2 = Math.SQRT1_2;
6409
+ function effectivePivotYForTilemapFlip(pivotY, pivotX, flipV, flipDiagonal) {
6410
+ const base = flipDiagonal ? pivotX : pivotY;
6411
+ return flipV ? 1 - base : base;
6412
+ }
6413
+ function specFor(layerCols, chunkSize, cellIndex, packedTile, materialHandle, entry, atlasIndex) {
6414
+ const cellX = cellIndex % layerCols;
6415
+ const cellY = Math.floor(cellIndex / layerCols);
6416
+ const chunkX = Math.floor(cellX / chunkSize);
6417
+ const chunkY = Math.floor(cellY / chunkSize);
6418
+ const chunksPerRow = Math.max(1, Math.ceil(layerCols / chunkSize));
6419
+ const chunkIndex = chunkY * chunksPerRow + chunkX;
6420
+ const { tileId } = decodeTileBits(packedTile);
6421
+ return {
6422
+ cellX,
6423
+ cellY,
6424
+ tileId,
6425
+ packedTile,
6426
+ materialHandle,
6427
+ chunkIndex,
6428
+ widthCells: entry.widthCells ?? 1,
6429
+ heightCells: entry.heightCells ?? 1,
6430
+ pivotX: entry.pivotX ?? 0.5,
6431
+ pivotY: entry.pivotY ?? 0.5,
6432
+ atlasIndex,
6433
+ regionIndex: entry.regionIndex
6434
+ };
6435
+ }
6436
+ function computeTileTrs(tilemap, spec, packedTile) {
6437
+ const { flipH, flipV, flipDiagonal } = decodeTileBits(packedTile);
6438
+ const basePivotForX = flipDiagonal ? spec.pivotY : spec.pivotX;
6439
+ const effectivePivotX = flipH ? 1 - basePivotForX : basePivotForX;
6440
+ const effectivePivotY = effectivePivotYForTilemapFlip(
6441
+ spec.pivotY,
6442
+ spec.pivotX,
6443
+ flipV,
6444
+ flipDiagonal
6445
+ );
6446
+ const tileSizeX = tilemap.tileSize[0] ?? 1;
6447
+ const tileSizeY = tilemap.tileSize[1] ?? 1;
6448
+ return {
6449
+ posX: (spec.cellX + effectivePivotX + (0.5 - effectivePivotX) * spec.widthCells) * tileSizeX,
6450
+ posY: (spec.cellY + effectivePivotY + (0.5 - effectivePivotY) * spec.heightCells) * tileSizeY,
6451
+ scaleX: (flipH ? -1 : 1) * spec.widthCells * tileSizeX,
6452
+ scaleY: (flipV ? -1 : 1) * spec.heightCells * tileSizeY,
6453
+ quatZ: flipDiagonal ? SQRT1_2 : 0,
6454
+ quatW: flipDiagonal ? SQRT1_2 : 1
6455
+ };
6456
+ }
6457
+ function spawnDerivedRenderEntities(world, tilemap, layerEntity, layerOrder, spec, packedTile, sortScope = "layer") {
6458
+ const { posX, posY, scaleX, scaleY, quatZ, quatW } = computeTileTrs(tilemap, spec, packedTile);
6459
+ const layerValue = encodeTilemapLayerValue(layerOrder, spec.chunkIndex, sortScope);
6460
+ return world.spawn(
6461
+ {
6462
+ component: Transform,
6463
+ data: {
6464
+ pos: [posX, posY, 0],
6465
+ quat: [0, 0, quatZ, quatW],
6466
+ scale: [scaleX, scaleY, 1]
6467
+ }
6468
+ },
6469
+ { component: MeshFilter, data: { assetHandle: HANDLE_QUAD } },
6470
+ {
6471
+ component: MeshRenderer,
6472
+ data: {
6473
+ materials: [spec.materialHandle]
6474
+ }
6475
+ },
6476
+ { component: Layer, data: { value: layerValue } },
6477
+ { component: ChildOf, data: { parent: layerEntity } }
6478
+ ).unwrap();
6479
+ }
6480
+ function spawnSpriteInstancesGroup(world, tilemap, tileset, layerEntity, layerOrder, chunkIndex, atlasIndex, materialHandle, cellSpecs) {
6481
+ if (cellSpecs.length === 0) return void 0;
6482
+ const N = cellSpecs.length;
6483
+ const transforms = new Float32Array(N * 16);
6484
+ const regions = new Float32Array(N * 4);
6485
+ const tmpMat = mat4.create();
6486
+ const tmpT = [0, 0, 0];
6487
+ const tmpR = [0, 0, 0, 1];
6488
+ const tmpS = [1, 1, 1];
6489
+ const chunksPerRow = Math.max(1, Math.ceil(tilemap.cols / tilemap.chunkSize));
6490
+ const chunkX = chunkIndex % chunksPerRow;
6491
+ const chunkY = Math.floor(chunkIndex / chunksPerRow);
6492
+ const chunkScaleX = tilemap.chunkSize * (tilemap.tileSize[0] ?? 1);
6493
+ const chunkScaleY = tilemap.chunkSize * (tilemap.tileSize[1] ?? 1);
6494
+ const chunkCenterX = (chunkX + 0.5) * chunkScaleX;
6495
+ const chunkCenterY = (chunkY + 0.5) * chunkScaleY;
6496
+ const invSX = chunkScaleX > 0 ? 1 / chunkScaleX : 1;
6497
+ const invSY = chunkScaleY > 0 ? 1 / chunkScaleY : 1;
6498
+ for (let i = 0; i < N; i++) {
6499
+ const spec = cellSpecs[i];
6500
+ const { posX, posY, scaleX, scaleY, quatZ, quatW } = computeTileTrs(
6501
+ tilemap,
6502
+ spec,
6503
+ spec.packedTile
6504
+ );
6505
+ tmpT[0] = posX;
6506
+ tmpT[1] = posY;
6507
+ tmpT[2] = 0;
6508
+ tmpR[0] = 0;
6509
+ tmpR[1] = 0;
6510
+ tmpR[2] = quatZ;
6511
+ tmpR[3] = quatW;
6512
+ tmpS[0] = scaleX;
6513
+ tmpS[1] = scaleY;
6514
+ tmpS[2] = 1;
6515
+ mat4.compose(tmpMat, tmpT, tmpR, tmpS);
6516
+ const dst = i * 16;
6517
+ for (let c = 0; c < 4; c++) {
6518
+ const base = c * 4;
6519
+ const w3 = tmpMat[base + 3] ?? 0;
6520
+ transforms[dst + base + 0] = ((tmpMat[base + 0] ?? 0) - chunkCenterX * w3) * invSX;
6521
+ transforms[dst + base + 1] = ((tmpMat[base + 1] ?? 0) - chunkCenterY * w3) * invSY;
6522
+ transforms[dst + base + 2] = tmpMat[base + 2] ?? 0;
6523
+ transforms[dst + base + 3] = w3;
6524
+ }
6525
+ const region = tileset.regions[spec.regionIndex];
6526
+ if (region !== void 0) {
6527
+ const [u, v, w, h] = computeRegionUv(tileset, region, atlasIndex);
6528
+ regions[i * 4 + 0] = u;
6529
+ regions[i * 4 + 1] = v;
6530
+ regions[i * 4 + 2] = w;
6531
+ regions[i * 4 + 3] = h;
6532
+ }
6533
+ }
6534
+ const layerValue = encodeTilemapLayerValue(layerOrder, chunkIndex, "layer");
6535
+ return world.spawn(
6536
+ {
6537
+ component: Transform,
6538
+ data: {
6539
+ pos: [chunkCenterX, chunkCenterY, 0],
6540
+ quat: [0, 0, 0, 1],
6541
+ scale: [chunkScaleX, chunkScaleY, 1]
6542
+ }
6543
+ },
6544
+ { component: MeshFilter, data: { assetHandle: HANDLE_QUAD } },
6545
+ {
6546
+ component: MeshRenderer,
6547
+ data: {
6548
+ materials: [materialHandle]
6549
+ }
6550
+ },
6551
+ { component: SpriteInstances, data: { transforms, regions } },
6552
+ { component: Layer, data: { value: layerValue } },
6553
+ { component: ChildOf, data: { parent: layerEntity } }
6554
+ ).unwrap();
6555
+ }
6556
+ function bucketTileLayer(world, layerEntity, parentEntity, lookup) {
6557
+ const tilemapRes = world.get(parentEntity, Tilemap);
6558
+ if (!tilemapRes.ok) return void 0;
6559
+ const tilemap = tilemapRes.value;
6560
+ const tilesetPayload = lookup(tilemap.tileset);
6561
+ if (tilesetPayload === void 0 || "code" in tilesetPayload) return void 0;
6562
+ if (tilesetPayload.kind !== "tileset") return void 0;
6563
+ const tileset = tilesetPayload;
6564
+ const layerRes = world.get(layerEntity, TileLayer);
6565
+ if (!layerRes.ok) return void 0;
6566
+ const layer = layerRes.value;
6567
+ const tiles = layer.tiles;
6568
+ const sortScope = decodeSortScope(layer.sortScope);
6569
+ const useSpriteInstances = sortScope === "layer";
6570
+ const specs = [];
6571
+ for (let i = 0; i < tiles.length; i++) {
6572
+ const packed = tiles[i] ?? 0;
6573
+ if (packed === 0) continue;
6574
+ const { tileId } = decodeTileBits(packed);
6575
+ if (tileId === 0) continue;
6576
+ const entry = tileset.tiles[tileId - 1];
6577
+ if (entry === void 0) continue;
6578
+ const region = tileset.regions[entry.regionIndex];
6579
+ if (region === void 0) continue;
6580
+ const atlasIndex = region.atlasIndex ?? 0;
6581
+ const materialHandle = useSpriteInstances ? resolveAtlasOnlyMaterial(world, tileset, atlasIndex, lookup) : resolveTilesetMaterial(world, tileset, entry.regionIndex, lookup);
6582
+ const spec = specFor(
6583
+ tilemap.cols,
6584
+ tilemap.chunkSize,
6585
+ i,
6586
+ packed,
6587
+ materialHandle,
6588
+ entry,
6589
+ atlasIndex
6590
+ );
6591
+ specs.push(spec);
6592
+ }
6593
+ return {
6594
+ tilemap,
6595
+ layerOrder: layer.layerOrder,
6596
+ sortScope,
6597
+ tileset,
6598
+ specs
6599
+ };
6600
+ }
6601
+ function buildCameraFrustumPlanes(world) {
6602
+ const query = world.query({ with: [Camera, Transform, GlobalTransform] }).unwrap();
6603
+ let result = null;
6604
+ for (const row of query) {
6605
+ const camEntity = row.entity;
6606
+ const camRes = world.get(camEntity, Camera);
6607
+ const trRes = world.get(camEntity, GlobalTransform);
6608
+ if (!camRes.ok || !trRes.ok) continue;
6609
+ const cam = camRes.value;
6610
+ const tr = trRes.value;
6611
+ const { near, far } = cam;
6612
+ if (near >= far) continue;
6613
+ const proj = mat4.create();
6614
+ if (cam.projection === CAMERA_PROJECTION_ORTHOGRAPHIC) {
6615
+ mat4.orthographic(
6616
+ proj,
6617
+ cam.left,
6618
+ cam.right,
6619
+ cam.top,
6620
+ cam.bottom,
6621
+ near,
6622
+ far
6623
+ );
6624
+ } else {
6625
+ mat4.perspective(
6626
+ proj,
6627
+ cam.fov,
6628
+ cam.aspect,
6629
+ near,
6630
+ far
6631
+ );
6632
+ }
6633
+ const view = mat4.create();
6634
+ mat4.invert(
6635
+ view,
6636
+ tr.world
6637
+ );
6638
+ const vp = mat4.create();
6639
+ mat4.multiply(
6640
+ vp,
6641
+ proj,
6642
+ view
6643
+ );
6644
+ const f = frustum.create();
6645
+ frustum.fromViewProjection(f, vp);
6646
+ result = f;
6647
+ break;
6648
+ }
6649
+ return result;
6650
+ }
6651
+ function computeChunkStreamBounds(tilemap, specs) {
6652
+ let minX = Number.MAX_VALUE;
6653
+ let minY = Number.MAX_VALUE;
6654
+ let maxX = -Number.MAX_VALUE;
6655
+ let maxY = -Number.MAX_VALUE;
6656
+ for (const spec of specs) {
6657
+ const { posX, posY, scaleX, scaleY } = computeTileTrs(tilemap, spec, spec.packedTile);
6658
+ const halfW = Math.abs(scaleX) * 0.5;
6659
+ const halfH = Math.abs(scaleY) * 0.5;
6660
+ const x0 = posX - halfW;
6661
+ const x1 = posX + halfW;
6662
+ const y0 = posY - halfH;
6663
+ const y1 = posY + halfH;
6664
+ if (x0 < minX) minX = x0;
6665
+ if (y0 < minY) minY = y0;
6666
+ if (x1 > maxX) maxX = x1;
6667
+ if (y1 > maxY) maxY = y1;
6668
+ }
6669
+ return [minX, minY, -1, maxX, maxY, 1];
6670
+ }
6671
+ function purgeDerivedEntities(world, layerEntity) {
6672
+ const r = world.get(layerEntity, Children);
6673
+ if (!r.ok) return;
6674
+ const snap = r.value.entities;
6675
+ for (let i = 0; i < snap.length; i++) {
6676
+ const e = snap[i];
6677
+ if (e !== void 0) world.despawn(e);
6678
+ }
6679
+ }
6680
+ function evictDeadPerCellStreamingCaches(work, world) {
6681
+ const cache = streamingCache(world);
6682
+ const aliveLayerKeys = /* @__PURE__ */ new Set();
6683
+ for (const w of work) {
6684
+ aliveLayerKeys.add(String(w.layerEntity));
6685
+ }
6686
+ const deadLayerKeys = /* @__PURE__ */ new Set();
6687
+ for (const layerKey of cache.activeChunks.keys()) {
6688
+ if (!aliveLayerKeys.has(layerKey)) deadLayerKeys.add(layerKey);
6689
+ }
6690
+ for (const layerKey of cache.layers.keys()) {
6691
+ if (!aliveLayerKeys.has(layerKey)) deadLayerKeys.add(layerKey);
6692
+ }
6693
+ for (const deadKey of deadLayerKeys) {
6694
+ const activeSet = cache.activeChunks.get(deadKey);
6695
+ if (activeSet !== void 0) {
6696
+ for (const chunkIdx of activeSet) {
6697
+ cache.chunkEntities.delete(`${deadKey}:${chunkIdx}`);
6698
+ }
6699
+ cache.activeChunks.delete(deadKey);
6700
+ }
6701
+ cache.layers.delete(deadKey);
6702
+ }
6703
+ }
6704
+ function tilemapChunkExtractSystem(world, lookup = () => void 0) {
6705
+ const streaming = streamingCache(world);
6706
+ const work = [];
6707
+ const tileLayerQuery = world.query({ read: [TileLayer, ChildOf] }).unwrap();
6708
+ for (const row of tileLayerQuery) {
6709
+ const layer = row.get(TileLayer);
6710
+ const parent = row.get(ChildOf).parent;
6711
+ if (parent === null) continue;
6712
+ work.push({
6713
+ layerEntity: row.entity,
6714
+ parentEntity: parent,
6715
+ dirty: layer.dirty,
6716
+ sortScopeRaw: layer.sortScope
6717
+ });
6718
+ }
6719
+ evictDeadPerCellStreamingCaches(work, world);
6720
+ let frustumPlanes;
6721
+ for (const w of work) {
6722
+ const layerKey = String(w.layerEntity);
6723
+ const isStreaming = decodeSortScope(w.sortScopeRaw) === "per-cell";
6724
+ if (!isStreaming) {
6725
+ const childrenRes = world.get(w.layerEntity, Children);
6726
+ const childCount = childrenRes.ok ? childrenRes.value.entities.length : 0;
6727
+ if (childCount > 0 && w.dirty === 0) continue;
6728
+ purgeDerivedEntities(world, w.layerEntity);
6729
+ const bucket = bucketTileLayer(world, w.layerEntity, w.parentEntity, lookup);
6730
+ if (bucket === void 0) continue;
6731
+ const byChunkAtlas = /* @__PURE__ */ new Map();
6732
+ for (const spec of bucket.specs) {
6733
+ const key = (spec.chunkIndex & 1048575) << 16 | spec.atlasIndex & 65535;
6734
+ const list = byChunkAtlas.get(key);
6735
+ if (list === void 0) {
6736
+ byChunkAtlas.set(key, [spec]);
6737
+ } else {
6738
+ list.push(spec);
6739
+ }
6740
+ }
6741
+ for (const groupSpecs of byChunkAtlas.values()) {
6742
+ const first = groupSpecs[0];
6743
+ if (first === void 0) continue;
6744
+ spawnSpriteInstancesGroup(
6745
+ world,
6746
+ bucket.tilemap,
6747
+ bucket.tileset,
6748
+ w.layerEntity,
6749
+ bucket.layerOrder,
6750
+ first.chunkIndex,
6751
+ first.atlasIndex,
6752
+ first.materialHandle,
6753
+ groupSpecs
6754
+ );
6755
+ }
6756
+ if (w.dirty !== 0) {
6757
+ world.set(w.layerEntity, TileLayer, { dirty: 0 }).unwrap();
6758
+ }
6759
+ continue;
6760
+ }
6761
+ if (w.dirty !== 0 || !streaming.layers.has(layerKey)) {
6762
+ const activeSet2 = streaming.activeChunks.get(layerKey);
6763
+ if (activeSet2 !== void 0) {
6764
+ for (const chunkIdx of activeSet2) {
6765
+ const key = `${layerKey}:${chunkIdx}`;
6766
+ const entities = streaming.chunkEntities.get(key);
6767
+ if (entities !== void 0) {
6768
+ for (const e of entities) world.despawn(e);
6769
+ streaming.chunkEntities.delete(key);
6770
+ }
6771
+ }
6772
+ activeSet2.clear();
6773
+ }
6774
+ streaming.layers.delete(layerKey);
6775
+ const bucket = bucketTileLayer(world, w.layerEntity, w.parentEntity, lookup);
6776
+ if (bucket !== void 0) {
6777
+ const byChunkSpecs = /* @__PURE__ */ new Map();
6778
+ for (const spec of bucket.specs) {
6779
+ const list = byChunkSpecs.get(spec.chunkIndex);
6780
+ if (list === void 0) {
6781
+ byChunkSpecs.set(spec.chunkIndex, [spec]);
6782
+ } else {
6783
+ list.push(spec);
6784
+ }
6785
+ }
6786
+ const byChunk = /* @__PURE__ */ new Map();
6787
+ for (const [chunkIdx, specs] of byChunkSpecs) {
6788
+ byChunk.set(chunkIdx, {
6789
+ specs,
6790
+ bounds: computeChunkStreamBounds(bucket.tilemap, specs)
6791
+ });
6792
+ }
6793
+ streaming.layers.set(layerKey, {
6794
+ byChunk,
6795
+ tilemap: bucket.tilemap,
6796
+ layerOrder: bucket.layerOrder,
6797
+ sortScope: bucket.sortScope
6798
+ });
6799
+ }
6800
+ if (w.dirty !== 0) {
6801
+ world.set(w.layerEntity, TileLayer, { dirty: 0 }).unwrap();
6802
+ }
6803
+ }
6804
+ const cache = streaming.layers.get(layerKey);
6805
+ if (cache === void 0) continue;
6806
+ if (frustumPlanes === void 0) {
6807
+ frustumPlanes = buildCameraFrustumPlanes(world);
6808
+ }
6809
+ const activeSet = streaming.activeChunks.get(layerKey) ?? /* @__PURE__ */ new Set();
6810
+ streaming.activeChunks.set(layerKey, activeSet);
6811
+ const { tilemap } = cache;
6812
+ for (const [chunkIdx, entry] of cache.byChunk) {
6813
+ const { specs, bounds } = entry;
6814
+ const visible = frustumPlanes === null || frustum.intersectsBox(frustumPlanes, bounds);
6815
+ const wasActive = activeSet.has(chunkIdx);
6816
+ if (visible && !wasActive) {
6817
+ const spawned = [];
6818
+ for (const spec of specs) {
6819
+ const e = spawnDerivedRenderEntities(
6820
+ world,
6821
+ tilemap,
6822
+ w.layerEntity,
6823
+ cache.layerOrder,
6824
+ spec,
6825
+ spec.packedTile,
6826
+ cache.sortScope
6827
+ );
6828
+ spawned.push(e);
6829
+ }
6830
+ streaming.chunkEntities.set(`${layerKey}:${chunkIdx}`, spawned);
6831
+ activeSet.add(chunkIdx);
6832
+ } else if (!visible && wasActive) {
6833
+ const key = `${layerKey}:${chunkIdx}`;
6834
+ const entities = streaming.chunkEntities.get(key);
6835
+ if (entities !== void 0) {
6836
+ for (const e of entities) world.despawn(e);
6837
+ streaming.chunkEntities.delete(key);
6838
+ }
6839
+ activeSet.delete(chunkIdx);
6840
+ }
6841
+ }
6842
+ }
6843
+ }
6844
+
6845
+ // src/scene/source-systems.ts
6846
+ var nextId = 0;
6847
+ function registerRenderSourceSystems(world, assets, meshes) {
6848
+ const releaseTransforms = registerPropagateTransforms(world);
6849
+ const name = `renderDerived:${++nextId}`;
6850
+ const result = world.addSystem(Update, {
6851
+ name,
6852
+ queries: [],
6853
+ fn: (world2) => {
6854
+ tilemapChunkExtractSystem(world2, (guid) => assets.lookup(guid));
6855
+ glyphTextLayoutSystem(world2, meshes).unwrap();
6856
+ }
6857
+ });
6858
+ if (!result.ok) {
6859
+ releaseTransforms();
6860
+ throw result.error;
6861
+ }
6862
+ return () => {
6863
+ world.removeSystem(Update, name).unwrap();
6864
+ releaseTransforms();
6865
+ };
6866
+ }
6867
+
6868
+ // src/extract/material-context.ts
6869
+ function renderMaterialContext(caps) {
6870
+ if (caps.backendKind === "null") return {};
6871
+ return {
6872
+ materialContext: {
6873
+ backend: caps.backendKind === "wgpu-webgl2" ? "webgl2" : caps.backendKind,
6874
+ capability: caps.storageBuffer ? "storage-buffer" : "uniform-fallback",
6875
+ pipeline: "forward",
6876
+ geometry: "mesh",
6877
+ pass: "forward",
6878
+ profile: "forgeax-material-wgsl-v1",
6879
+ toolchain: "naga-oil",
6880
+ instrumentation: "none"
6881
+ }
6882
+ };
6883
+ }
6884
+ var RENDERABLE_SOURCE_COMPONENTS = [
6885
+ ChildOf,
6886
+ MeshFilter,
6887
+ MeshRenderer,
6888
+ Instances,
6889
+ SpriteInstances,
6890
+ SpriteRegionOverride,
6891
+ Skin,
6892
+ Layer,
6893
+ Visibility,
6894
+ MorphWeights,
6895
+ Points,
6896
+ Lines,
6897
+ SortKey
6898
+ ];
6899
+ function createGlobalTransformChangeQuery(world) {
6900
+ const result = world.query({ read: [GlobalTransform], changed: [GlobalTransform] });
6901
+ if (!result.ok) throw result.error;
6902
+ const query = result.value;
6903
+ for (const _span of query.spans().unwrap()) {
6904
+ }
6905
+ return query;
6906
+ }
6907
+ function createRenderSourceState(world, additional = []) {
6908
+ const components = [
6909
+ ...RENDERABLE_SOURCE_COMPONENTS,
6910
+ RuntimeMaterialValue,
6911
+ RuntimeMeshVertices,
6912
+ ...additional
6913
+ ];
6914
+ const projection = createStateProjection(world, components, [
6915
+ ...components,
6916
+ Transform,
6917
+ GlobalTransform
6918
+ ]);
6919
+ const entities = /* @__PURE__ */ new Map();
6920
+ const contentHandles = /* @__PURE__ */ new Map();
6921
+ const batch = projection.read();
6922
+ for (const index of batch.indices) {
6923
+ const entity = projection.entity(index);
6924
+ if (entity !== void 0) {
6925
+ entities.set(index, entity);
6926
+ const handles = [];
6927
+ const material = world.hasComponent(entity, RuntimeMaterialValue) ? world.get(entity, RuntimeMaterialValue) : void 0;
6928
+ const mesh = world.hasComponent(entity, RuntimeMeshVertices) ? world.get(entity, RuntimeMeshVertices) : void 0;
6929
+ if (material?.ok) handles.push(Number(material.value.asset));
6930
+ if (mesh?.ok) handles.push(Number(mesh.value.asset));
6931
+ if (handles.length > 0) contentHandles.set(index, handles);
6932
+ }
6933
+ }
6934
+ return { projection, entities, contentHandles, batch };
6935
+ }
6936
+ function isRenderableMember(world, entity) {
6937
+ return world.hasComponent(entity, MeshRenderer) && world.hasComponent(entity, Transform) && world.hasComponent(entity, MeshFilter);
6938
+ }
6939
+
6940
+ export { BARREL_DISTORTION_FEATURE_IDENTITY, BARREL_DISTORTION_POST_PROCESS_ID, BARREL_DISTORTION_WGSL, BARREL_DISTORTION_WGSL_COORDINATE, CLOUD_DENSITY_COMPUTE_WGSL, CLOUD_HISTORY_FULLSCREEN_WGSL, CLOUD_HISTORY_SURFACE_COUNT, CLOUD_LAYER_DENSITY_BINDINGS, CLOUD_LAYER_DENSITY_CACHE, CLOUD_LAYER_DENSITY_OUTPUT, CLOUD_LAYER_DENSITY_PROGRAM, CLOUD_LAYER_FEATURE_IDENTITY, CLOUD_RGBA16FLOAT_BYTES_PER_TEXEL, CLOUD_VIEW_FULLSCREEN_WGSL, CLOUD_VIEW_PARAMS_BYTES, CloudHistoryStore, DEFAULT_REFLECTION_PROBE_LIMITS, DynamicGeometryError, DynamicInputError, LOD_OCCLUSION_INSPECTION_MAX_BYTES, LOD_OCCLUSION_INSPECTION_SCHEMA, RENDERABLE_SOURCE_COMPONENTS, ReadonlyDynamicInputPage, ReflectionProbeProjection, RenderPublicationError, RenderPublicationTargetOwner, RenderPublicationTargetReceiver, SSR_FORMAT_PROFILE, SSR_FORMAT_STAGES, acceptCloudLayerGeneration, acquireSwapChainTarget, admitPointsLines, admitReflectionProbe, admitSingleLayerMediumSubmission, admitSsrM0, admitSsrSpatial, advanceProbeFilter, applyCloudSolarTransmittance, boxProjectReflectionDirection, buildCloudDensityCache, buildReflectionProbeTable, cloudCapabilitiesFromRhi, cloudTemporalResetReasons, cloudTemporalSignature, commitProbeFilterStep, compositeCloudRadiance, consumeLodOcclusionInspection, createBarrelDistortionRenderFeature, createCloudHistory, createCloudLayerFeature, createCloudShadowProjection, createDynamicGeometryLifecycle, createGlobalTransformChangeQuery, createProbeFilterState, createRenderSourceState, createRenderTargetHost, deriveReflectionFallbackProjection, estimateReflectionProbeBytes, evaluateCloudDensity, graphExecutionPhase, inspectCloudLayer, inspectCloudLayerResources, inspectLodOcclusion, inspectPointShadow, inspectReflectionFallback, inspectVolumetricFog, integrateCloudCameraPath, integrateCloudInterior, integrateCloudPath, integrateCloudSolarColumn, intersectCloudLayer, isRenderableMember, probeFilterIsSteady, projectCloudShadowUv, projectSsrDependencies, projectSsrSpatialInspection, publicationDependencies, publicationFrameDependencies, publicationTargetSources, reconstructCloudDensityCache, reflectionFallbackCoverage, reflectionFallbackProjectionSignature, reflectionFallbackSourceKey, reflectionProbeTableBytes, registerRenderSourceSystems, renderMaterialContext, renderPublicationTransfers, reprojectCloudHistory, resolveDirectionalShadowAtlasGrid, resolveReflectionFallbackSource, resolveShadowMapSize, resolveSpotShadowMapSize, resolveSsrAdmissionGeneration, retainCloudLayerAfterFailure, sameCandidateCredential, sampleCloudDensity, sampleCloudShadow, selectReflectionProbe, serializeLodOcclusionInspection, serializeSsrSpatialInspection, snapshotCloudDensityCache, validateReflectionProbeInput, validateScreenSpaceReflection, zeroSsrAdmissionWork };
6941
+ //# sourceMappingURL=chunk-MZ4C7EHF.mjs.map
6942
+ //# sourceMappingURL=chunk-MZ4C7EHF.mjs.map