@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,28 +1,25 @@
1
- import { BARREL_DISTORTION_FEATURE_IDENTITY, createBarrelDistortionRenderFeature, inspectVolumetricFog, resolveSsrAdmissionGeneration, inspectLodOcclusion, zeroSsrAdmissionWork, projectSsrSpatialInspection, createDynamicGeometryLifecycle, inspectReflectionFallback, admitReflectionProbe, DEFAULT_REFLECTION_PROBE_LIMITS, buildReflectionProbeTable, advanceProbeFilter, commitProbeFilterStep, resolveReflectionFallbackSource, deriveReflectionFallbackProjection, reflectionFallbackCoverage, reflectionFallbackSourceKey, reflectionFallbackProjectionSignature, createProbeFilterState, ReflectionProbeProjection, admitPointsLines, projectSsrDependencies, admitSsrSpatial, BARREL_DISTORTION_POST_PROCESS_ID, inspectPointShadow, admitSingleLayerMediumSubmission, createCloudShadowProjection, CLOUD_LAYER_FEATURE_IDENTITY, ReadonlyDynamicInputPage, DynamicGeometryError, sameCandidateCredential } from './chunk-ODZWR6JQ.mjs';
2
- import { createExtendedLightingState, promoteExtendedLightingCandidate, glyphTextLayoutSystem, emptyBloomInspection, projectExtendedLightingInspection, OcclusionRenderRuntime, extractFrames, viewKey, primitiveKey, projectBarrelDistortionInspection, viewKeyId, primitiveKeyId, ProbeBlendSceneProjection, InstanceBoundsCache, fingerprintNumericArray, buildShadowFrusta, createSsrHistoryOwner, createSsrSpatialResources, createCookieProjectionMatrixData } from './chunk-UI5SFODX.mjs';
3
- import './chunk-ILQ5MEZF.mjs';
4
- import { DEFAULT_DEPTH_OF_FIELD_PARAMS, projectMeshMaterialBindingObservation, resolveDepthOfFieldFrameParams, buildCubeCameraFaceViews, MeshFilter, MeshRenderer, Instances, Layer, Visibility, Points, Lines, SortKey, SKYLIGHT_RECOVERY_FALLBACK, hasVolumetricFogCapability, packDepthOfFieldParams, Camera, CAMERA_PROJECTION_ORTHOGRAPHIC, cloudShadowResolutionForQuality, CUBE_CAMERA_FACE_ORDER, createBarrelDistortionMapping, attachBarrelDistortionCameraFrame, MAX_VOLUMETRIC_FOG_OWNERS } from './chunk-UINHLCZA.mjs';
5
- import { TileLayer, decodeSortScope, SpriteInstances, SpriteRegionOverride, Tilemap } from './chunk-ELJFJ2BU.mjs';
6
- import { GPU_SCENE_LAYOUTS, deviceOptionsForAdapter, PipelineSpecError, assertStorageBufferCap, STANDARD_PBR_REQUIRED_SAMPLED_TEXTURES, GpuBuffer, GpuTexture, deriveRenderDataTexture, deriveRenderDataMesh, deriveRenderDataCubemap, createIblPipelines, CUBEMAP_FACE_VERTICES, runIblPrecompute, SurfaceSubmissionObservationOwner, createClusterBinScratch, resetSsaoResources, resetHdrpBuffers, retireTemporalGpuState, PostProcessError, entryHasDepthRead, DEPTH_MIN_PARAMS_BYTE_SIZE, postProcessShaderModuleLabel, resolveSsaoParameters, buildPerFrameBindGroups, resolveMaterialSkylight, postProcessShaderEntrySignature, standardBloomAdmitted, selectSwapChainFormat, setIblComposedShaders, POINTS_LINES_MATERIAL_SHADER_ID, selectStandardPbrTransmissionPrewarmVariants, selectHdrpPbrPrewarmVariants, prewarmMaterialShaderVariants, selectProbePrewarmVariants, createHdrpClusterMembershipBindGroupLayoutDescriptor, createSkylightFallback, buildSpecConstTable, buildLinearLdrMaterialSpecTable, getOrBuildPipeline, cacheKeyOf, HDR_COLOR_ATTACHMENT_FORMAT, configureSurface, CAPTURE_VIEW_PROJS, PREFILTER_MIP_LEVELS, REFLECTION_PROBE_VIEW_SLOT_BASE, VIEW_UNIFORM_SLOT_STRIDE, getOrCreateIblCache, decideVisibility, BatchTopology, postProcessShaderPipelineLabel, createPointsLinesLaneAdapter, computeViewMatrix, computeProjectionMatrix, prepareFrameLighting, warnMultiSkylight, warnMultiSkybox, selectLazyEquirectHandle, driveLazyEquirectProjection, warnZeroLightStandard, writeShadowParamsBuffer, ensureProbeBlendRecordBuffer, deriveRenderExtent, writeSpotModifierTextures, writeHdrpClusterAndSsaoBuffers, resolveSkyboxActive, computeSplitLdrSprite, writeViewUbo, writePointsLinesViewUbo, writeShadowCasterUniforms, uploadMeshSsboBatch, passKindPolicyTable, colorFormatsForPassKind, GPU_DRIVEN_VIEW_WGSL, selectGpuDrivenSceneIndexVariant, selectSkinPrewarmVariants, transmissionBackdropAvailable, VIEW_UBO_BYTES, POINTS_LINES_VIEW_BUFFER_SIZE, SHADOW_CASTER_BUFFER_SIZE, FALLBACK_BYTES_PER_ROW, MIPMAP_PREWARM_FORMATS, getIblProbeBackgroundSource, OcclusionConfidenceScheduler, shouldIssueRetest, selectGpuLodLane, ShadowViewStatePool, GpuDrivenView, MATERIAL_PER_ENTITY_STRIDE, shadowViewIdentityKey, combineGpuResourceAllocationInspections, inspectResourceClassSplits, createPointsLinesLaneContract, foldDispatchBuckets, CUBE_CAPTURE_VIEW_SLOT_BASE, variantSetFromDefines, resolveReflectionProbeBinding, cleanPerEntityCache, ensureMeshSsboCapacity, buildFoldDispatchPlan, evaluateFoldBucketUniformCap, incrementFoldedDrawsMetric, writePbrMaterialUboPayload, applyParamSnapshotToUbo, applyMaterialTextureUvScales, residentTextureView, detectNineSliceScaleTooSmall, DEPTH_TEXTURE_FORMAT, PREFILTER_SIZE, gpuSceneFieldOffset, projectedHeightForCandidate, geometryRenderStateForTopology, packInstanceStorageBuffer, GpuResourceAllocationLedger, MESH_PER_ENTITY_STRIDE, MESH_SSBO_BYTES, standardTopologyVariantSet, resolveGeometryInstanceBuffer, buildFullscreenPostProcessPass, getTemporalGpuState, getTemporalParamsBuffer, getTemporalBindGroupResources, TEMPORAL_HISTORY_FORMATS, resolveSurfaceFormatPair, resolveSurfaceProfile, createRenderPipelineTarget, encodeMainPass, STANDARD_PBR_UBO_SIZE, abortTemporalGpuSubmit, commitTemporalGpuSubmit, retireTemporalGpuStateAfterFence, hasPendingTemporalGpuSubmit, importRenderPipelineSurface, renderExtentSize, DEFERRED_COLOR_FORMATS, aggregateTemporalDemand, standardTemporalLaneAdmission, addTypedScenePass, addTypedSsaoPasses, addTypedSkyboxPass, renderPipelineCloudHistoryTargets, createStandardSceneDataTarget, addStandardSceneDataPass, VIEW_UNIFORM_BYTES, addTypedFrameObservationPass, addReflectionFallbackObservationPass, selectLod, temporalReadIndex, temporalWriteIndex, CLOUD_HISTORY_FORMATS, prepareMaterialSkylight, BYTES_PER_DIRECT_LIGHT_SLOT, shadowViewRasterAccesses, encodeDirectionalShadowPass, encodePointShadowPass, encodeSpotShadowPass, getOrCreateFromChain, addTypedFullscreenPass, resolveOutputDither, addTypedTemporalResolvePass, addTypedBloomPasses, addTypedOutputTransformPass, addTypedCompositePostEffects, geometryRenderStateForPass, standardStorageVariantSet, getOrCreateHdrpBuffers, variantSetFromVertexLayoutProjection, createStandardSurfaceLightingBindGroup, BLOOM_DOWNSAMPLE_PARAMS_BYTES, BLOOM_UPSAMPLE_PARAMS_BYTES, BLOOM_COMPOSITE_PARAMS_BYTES, isTemporalFullscreenBinding, createFullscreenBindGroup, stageTemporalGpuSubmit, applyParamSchemaDefaultsToUbo, defaultViewForUserRegionField, assembleMaterialWithSkylightEntries, TYPED_BLOOM_PASS_NAMES } from './chunk-MKDIT2EM.mjs';
7
- import { getTransparentSortConfig, TRANSPARENT_SORT_MODE_DISTANCE, TRANSPARENT_SORT_MODE_LAYER_Z, TRANSPARENT_SORT_MODE_LAYER_Y, TRANSPARENT_SORT_MODE_LAYER_YZ } from './chunk-RXZ3RGOU.mjs';
8
- import { DEFAULT_STANDARD_PROFILE, DEFAULT_CLUSTER_GRID, STANDARD_PIPELINE_ID, STANDARD_LIGHT_COUNTS, STANDARD_POST_STAGE_NAMES, createSceneDataCatalog, isSceneDataTarget, resolveVolumetricFogProfile, SCENE_DATA_TEMPORAL_V1_SCHEMA } from './chunk-OCDLEI6I.mjs';
9
- import { SPRITE_PREMULTIPLIED_ALPHA_BLEND } from './chunk-BLXGONR2.mjs';
10
- import { DeviceScope, SKIN_MATERIAL_SHADER_ID, EXTENDED_LIGHTING_TOPOLOGY, getTextureIdentity, GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_MAP_READ, resolveRenderTargetMaterialSource, createRenderTargetMaterialSource, deriveExtendedLightingCapability, GPU_BUFFER_USAGE_VERTEX, GPU_BUFFER_USAGE_INDEX, IES_SLICE_WIDTH, IES_SLICE_HEIGHT, COOKIE_SLICE_SIZE, COOKIE_MATRIX_BYTES, GPU_BUFFER_USAGE_UNIFORM, worldEntityKey, createHdrpBindGroupLayoutDescriptor, createHdrpSkinBindGroupLayoutDescriptor, GPU_BUFFER_USAGE_QUERY_RESOLVE, GPU_BUFFER_USAGE_COPY_SRC, gpuDrivenShadowDrawKey, makeZeroCameraFallbackSnapshot, buildPbrPipelineLayouts, buildPbrSkinLayouts, buildGpuDrivenPbrInstancesBindGroupLayout, buildSurfaceDirectInstancesBindGroupLayout, buildGpuDrivenPbrPipelineLayout, buildGpuDrivenPbrSkinPipelineLayout, GPU_BUFFER_USAGE_STORAGE, resolvePipelineGroup2Contract, GPU_SHADER_STAGE_FRAGMENT, isCanonicalStandardPbrMaterialShader, getOpaqueResourceIdentity, gpuDrivenDrawKey, gpuDrivenSourceDrawItemIndex, instanceCollectionCacheKey, validateGraphTargetCaptureReadback, createTemporalCoverage, isStandardPbrMaterialShader, buildBindGroupLayoutDescriptor, gpuDrivenMaterialArtifactKey, hasRequiredVertexInputs, buildPbrMaterialUserRegionEntries, extendedLightingSampledTextureCapacityAvailable, PROBE_BLEND_RECORD_BYTE_SIZE, GPU_SHADER_STAGE_VERTEX, SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET, SHADOW_CASTER_SHADER_ID, shadowCasterVariantSet, GPU_SHADER_STAGE_COMPUTE, LifecycleTransaction } from './chunk-SHFUFJ5N.mjs';
11
- import { RendererContractFailureError, RendererOperationError, MotionBlurValidationError, STANDARD_OUTPUT_TRANSFORM_FEATURE_ID, FrameReceiptStaleError, RenderFeatureStageFailedError, RenderFeatureCapabilityMissingError, RenderTargetStateInvalidError, RenderTargetOperationFailedError, RenderTargetCapabilityMissingError, RenderTargetDescriptorInvalidError, GPU_TEXTURE_USAGE_TEXTURE_BINDING, GPU_TEXTURE_USAGE_COPY_DST, RENDER_PHASE_CATALOG, InstanceProjectionStore, motionBlurTemporalDemand, createAutoExposureInspection, RenderFeatureRegistrationConflictError, GPU_TEXTURE_USAGE_RENDER_ATTACHMENT_AND_TEXTURE_BINDING, GPU_TEXTURE_USAGE_COPY_SRC, createVisibilityBudget, EnvironmentGenerationFailedError, PointsLinesMaterialUnsupportedError, StandardProfileInvalidError, TransmissionCapabilityMissingError, motionBlurSampleDelta, isMotionBlurIntervalValid, MOTION_BLUR_PARAMS_BYTE_SIZE, effectiveMotionBlurSampleCount, motionBlurExposureScale, SHADOW_ATLAS_DEFAULT_LAYERS, DEFAULT_MOTION_BLUR_PARAMS, FXAA_POST_PROCESS_ID, GPU_TEXTURE_USAGE_RENDER_ATTACHMENT, GpuDrivenPreparationError, TemporalFrameSubmitError, ObservationUnavailableError, RenderFeaturePreparationFailedError, AutoExposureInvalidParameterError, PointsLinesPrepareFailedError, validateMotionBlurParams, SHADOW_ATLAS_DEFAULT_FACE_SIZE, SceneDataUnavailableError, SkinPaletteOverflowError, GPU_TEXTURE_USAGE_STORAGE_BINDING, RenderFeatureDrawRecordingFailedError, PointShadowAtlasUninitializedError, RenderFeaturePreparedStateMismatchError } from './chunk-WEX45HKH.mjs';
1
+ import { RenderPublicationError, BARREL_DISTORTION_FEATURE_IDENTITY, createBarrelDistortionRenderFeature, createRenderTargetHost, RenderPublicationTargetReceiver, registerRenderSourceSystems, publicationFrameDependencies, publicationDependencies, inspectVolumetricFog, renderMaterialContext, resolveSsrAdmissionGeneration, inspectLodOcclusion, zeroSsrAdmissionWork, projectSsrSpatialInspection, createDynamicGeometryLifecycle, inspectReflectionFallback, admitReflectionProbe, DEFAULT_REFLECTION_PROBE_LIMITS, buildReflectionProbeTable, advanceProbeFilter, commitProbeFilterStep, resolveReflectionFallbackSource, deriveReflectionFallbackProjection, reflectionFallbackCoverage, reflectionFallbackSourceKey, reflectionFallbackProjectionSignature, createProbeFilterState, ReflectionProbeProjection, RENDERABLE_SOURCE_COMPONENTS, isRenderableMember, createRenderSourceState, createGlobalTransformChangeQuery, admitPointsLines, projectSsrDependencies, resolveShadowMapSize, resolveSpotShadowMapSize, admitSsrSpatial, acquireSwapChainTarget, BARREL_DISTORTION_POST_PROCESS_ID, graphExecutionPhase, inspectPointShadow, admitSingleLayerMediumSubmission, createCloudShadowProjection, CLOUD_LAYER_FEATURE_IDENTITY, ReadonlyDynamicInputPage, DynamicGeometryError, resolveDirectionalShadowAtlasGrid, sameCandidateCredential } from './chunk-MZ4C7EHF.mjs';
2
+ import { createExtendedLightingState, promoteExtendedLightingCandidate, emptyBloomInspection, projectExtendedLightingInspection, OcclusionRenderRuntime, viewKey, primitiveKey, projectBarrelDistortionInspection, viewKeyId, primitiveKeyId, ProbeBlendSceneProjection, createSsrHistoryOwner, createSsrSpatialResources } from './chunk-3XUBWRY2.mjs';
3
+ import { DEFAULT_DEPTH_OF_FIELD_PARAMS, extractFrames, projectMeshMaterialBindingObservation, resolveDepthOfFieldFrameParams, buildCubeCameraFaceViews, Instances, Visibility, SKYLIGHT_RECOVERY_FALLBACK, hasVolumetricFogCapability, packDepthOfFieldParams, InstanceBoundsCache, fingerprintNumericArray, Points, Lines, buildShadowFrusta, cloudShadowResolutionForQuality, CUBE_CAMERA_FACE_ORDER, createBarrelDistortionMapping, attachBarrelDistortionCameraFrame, MeshFilter, MAX_VOLUMETRIC_FOG_OWNERS, MeshRenderer, createCookieProjectionMatrixData } from './chunk-G6HDNGY7.mjs';
4
+ import { SpriteInstances } from './chunk-X2KA6WHM.mjs';
5
+ import { GPU_SCENE_LAYOUTS, deviceOptionsForAdapter, PipelineSpecError, assertStorageBufferCap, STANDARD_PBR_REQUIRED_SAMPLED_TEXTURES, GpuBuffer, GpuTexture, deriveRenderDataTexture, deriveRenderDataMesh, deriveRenderDataCubemap, createIblPipelines, CUBEMAP_FACE_VERTICES, runIblPrecompute, SurfaceSubmissionObservationOwner, createClusterBinScratch, resetSsaoResources, resetHdrpBuffers, retireTemporalGpuState, PostProcessError, entryHasDepthRead, DEPTH_MIN_PARAMS_BYTE_SIZE, postProcessShaderModuleLabel, resolveSsaoParameters, buildPerFrameBindGroups, resolveMaterialSkylight, postProcessShaderEntrySignature, standardBloomAdmitted, setIblComposedShaders, POINTS_LINES_MATERIAL_SHADER_ID, selectStandardPbrTransmissionPrewarmVariants, selectHdrpPbrPrewarmVariants, prewarmMaterialShaderVariants, selectProbePrewarmVariants, createHdrpClusterMembershipBindGroupLayoutDescriptor, createSkylightFallback, buildSpecConstTable, buildLinearLdrMaterialSpecTable, getOrBuildPipeline, cacheKeyOf, HDR_COLOR_ATTACHMENT_FORMAT, CAPTURE_VIEW_PROJS, PREFILTER_MIP_LEVELS, REFLECTION_PROBE_VIEW_SLOT_BASE, VIEW_UNIFORM_SLOT_STRIDE, getOrCreateIblCache, decideVisibility, BatchTopology, postProcessShaderPipelineLabel, createPointsLinesLaneAdapter, computeViewMatrix, computeProjectionMatrix, prepareFrameLighting, warnMultiSkylight, warnMultiSkybox, selectLazyEquirectHandle, driveLazyEquirectProjection, warnZeroLightStandard, writeShadowParamsBuffer, ensureProbeBlendRecordBuffer, deriveRenderExtent, writeSpotModifierTextures, writeHdrpClusterAndSsaoBuffers, resolveSkyboxActive, computeSplitLdrSprite, writeViewUbo, writePointsLinesViewUbo, writeShadowCasterUniforms, uploadMeshSsboBatch, passKindPolicyTable, colorFormatsForPassKind, GPU_DRIVEN_VIEW_WGSL, selectGpuDrivenSceneIndexVariant, selectSkinPrewarmVariants, transmissionBackdropAvailable, VIEW_UBO_BYTES, POINTS_LINES_VIEW_BUFFER_SIZE, SHADOW_CASTER_BUFFER_SIZE, FALLBACK_BYTES_PER_ROW, MIPMAP_PREWARM_FORMATS, getIblProbeBackgroundSource, OcclusionConfidenceScheduler, shouldIssueRetest, selectGpuLodLane, ShadowViewStatePool, GpuDrivenView, shadowViewIdentityKey, combineGpuResourceAllocationInspections, inspectResourceClassSplits, createPointsLinesLaneContract, foldDispatchBuckets, CUBE_CAPTURE_VIEW_SLOT_BASE, variantSetFromDefines, resolveReflectionProbeBinding, cleanPerEntityCache, ensureMeshSsboCapacity, buildFoldDispatchPlan, evaluateFoldBucketUniformCap, incrementFoldedDrawsMetric, writePbrMaterialUboPayload, applyParamSnapshotToUbo, applyMaterialTextureUvScales, residentTextureView, detectNineSliceScaleTooSmall, DEPTH_TEXTURE_FORMAT, PREFILTER_SIZE, gpuSceneFieldOffset, projectedHeightForCandidate, geometryRenderStateForTopology, packInstanceStorageBuffer, GpuResourceAllocationLedger, MESH_PER_ENTITY_STRIDE, MESH_SSBO_BYTES, standardTopologyVariantSet, resolveGeometryInstanceBuffer, buildFullscreenPostProcessPass, getTemporalGpuState, getTemporalParamsBuffer, getTemporalBindGroupResources, TEMPORAL_HISTORY_FORMATS, createRenderPipelineTarget, encodeMainPass, abortTemporalGpuSubmit, commitTemporalGpuSubmit, retireTemporalGpuStateAfterFence, hasPendingTemporalGpuSubmit, importRenderPipelineSurface, renderExtentSize, DEFERRED_COLOR_FORMATS, aggregateTemporalDemand, standardTemporalLaneAdmission, addTypedScenePass, addTypedSsaoPasses, addTypedSkyboxPass, renderPipelineCloudHistoryTargets, createStandardSceneDataTarget, addStandardSceneDataPass, VIEW_UNIFORM_BYTES, addTypedFrameObservationPass, addReflectionFallbackObservationPass, selectLod, temporalReadIndex, temporalWriteIndex, CLOUD_HISTORY_FORMATS, prepareMaterialSkylight, BYTES_PER_DIRECT_LIGHT_SLOT, shadowViewRasterAccesses, encodeDirectionalShadowPass, encodePointShadowPass, encodeSpotShadowPass, getOrCreateFromChain, addTypedFullscreenPass, resolveOutputDither, addTypedTemporalResolvePass, addTypedBloomPasses, addTypedOutputTransformPass, addTypedCompositePostEffects, geometryRenderStateForPass, standardStorageVariantSet, getOrCreateHdrpBuffers, variantSetFromVertexLayoutProjection, createStandardSurfaceLightingBindGroup, BLOOM_DOWNSAMPLE_PARAMS_BYTES, BLOOM_UPSAMPLE_PARAMS_BYTES, BLOOM_COMPOSITE_PARAMS_BYTES, isTemporalFullscreenBinding, createFullscreenBindGroup, stageTemporalGpuSubmit, applyParamSchemaDefaultsToUbo, defaultViewForUserRegionField, assembleMaterialWithSkylightEntries, TYPED_BLOOM_PASS_NAMES } from './chunk-LNIUIKQ7.mjs';
6
+ import { DEFAULT_STANDARD_PROFILE, DEFAULT_CLUSTER_GRID, selectSwapChainFormat, configureSurface, STANDARD_PIPELINE_ID, STANDARD_LIGHT_COUNTS, STANDARD_POST_STAGE_NAMES, createSceneDataCatalog, MATERIAL_PER_ENTITY_STRIDE, isSceneDataTarget, resolveSurfaceFormatPair, resolveSurfaceProfile, resolveVolumetricFogProfile, STANDARD_PBR_UBO_SIZE, SCENE_DATA_TEMPORAL_V1_SCHEMA } from './chunk-SGPUJW3F.mjs';
7
+ import { getTransparentSortConfig, TRANSPARENT_SORT_MODE_DISTANCE, TRANSPARENT_SORT_MODE_LAYER_Z, TRANSPARENT_SORT_MODE_LAYER_Y, TRANSPARENT_SORT_MODE_LAYER_YZ, SPRITE_PREMULTIPLIED_ALPHA_BLEND } from './chunk-XSFB7XXQ.mjs';
8
+ import { createTemporalCoverage, PROBE_BLEND_RECORD_BYTE_SIZE } from './chunk-RIPAEGI6.mjs';
9
+ import { RendererContractFailureError, RendererOperationError, MotionBlurValidationError, DeviceScope, SKIN_MATERIAL_SHADER_ID, STANDARD_OUTPUT_TRANSFORM_FEATURE_ID, EXTENDED_LIGHTING_TOPOLOGY, FrameReceiptStaleError, getTextureIdentity, RenderFeatureStageFailedError, RenderFeatureCapabilityMissingError, deriveExtendedLightingCapability, GPU_TEXTURE_USAGE_TEXTURE_BINDING, GPU_TEXTURE_USAGE_COPY_DST, GPU_BUFFER_USAGE_VERTEX, GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_INDEX, IES_SLICE_WIDTH, IES_SLICE_HEIGHT, COOKIE_SLICE_SIZE, COOKIE_MATRIX_BYTES, RENDER_PHASE_CATALOG, InstanceProjectionStore, GPU_BUFFER_USAGE_UNIFORM, worldEntityKey, motionBlurTemporalDemand, createAutoExposureInspection, createHdrpBindGroupLayoutDescriptor, createHdrpSkinBindGroupLayoutDescriptor, GPU_BUFFER_USAGE_QUERY_RESOLVE, GPU_BUFFER_USAGE_COPY_SRC, GPU_BUFFER_USAGE_MAP_READ, RenderFeatureRegistrationConflictError, GPU_TEXTURE_USAGE_RENDER_ATTACHMENT_AND_TEXTURE_BINDING, GPU_TEXTURE_USAGE_COPY_SRC, createVisibilityBudget, gpuDrivenShadowDrawKey, EnvironmentGenerationFailedError, PointsLinesMaterialUnsupportedError, StandardProfileInvalidError, buildGpuDrivenDraws, TransmissionCapabilityMissingError, motionBlurSampleDelta, isMotionBlurIntervalValid, makeZeroCameraFallbackSnapshot, MOTION_BLUR_PARAMS_BYTE_SIZE, effectiveMotionBlurSampleCount, motionBlurExposureScale, SHADOW_ATLAS_DEFAULT_LAYERS, DEFAULT_MOTION_BLUR_PARAMS, FXAA_POST_PROCESS_ID, buildPbrPipelineLayouts, buildPbrSkinLayouts, buildGpuDrivenPbrInstancesBindGroupLayout, buildSurfaceDirectInstancesBindGroupLayout, buildGpuDrivenPbrPipelineLayout, buildGpuDrivenPbrSkinPipelineLayout, GPU_BUFFER_USAGE_STORAGE, resolvePipelineGroup2Contract, GPU_SHADER_STAGE_FRAGMENT, RenderTargetStateInvalidError, GpuDrivenPreparationError, isCanonicalStandardPbrMaterialShader, getOpaqueResourceIdentity, gpuDrivenDrawKey, gpuDrivenSourceDrawItemIndex, TemporalFrameSubmitError, GPU_TEXTURE_USAGE_RENDER_ATTACHMENT, ObservationUnavailableError, RenderFeaturePreparationFailedError, AutoExposureInvalidParameterError, instanceCollectionCacheKey, validateGraphTargetCaptureReadback, isStandardPbrMaterialShader, buildBindGroupLayoutDescriptor, gpuDrivenMaterialArtifactKey, PointsLinesPrepareFailedError, validateMotionBlurParams, hasRequiredVertexInputs, SHADOW_ATLAS_DEFAULT_FACE_SIZE, resolveRenderTargetMaterialSource, buildPbrMaterialUserRegionEntries, extendedLightingSampledTextureCapacityAvailable, SceneDataUnavailableError, SkinPaletteOverflowError, GPU_TEXTURE_USAGE_STORAGE_BINDING, RenderFeatureDrawRecordingFailedError, GPU_SHADER_STAGE_VERTEX, PointShadowAtlasUninitializedError, SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET, SHADOW_CASTER_SHADER_ID, shadowCasterVariantSet, RenderFeaturePreparedStateMismatchError, GPU_SHADER_STAGE_COMPUTE, RenderTargetOperationFailedError, LifecycleTransaction } from './chunk-MXTWKZO4.mjs';
12
10
  import { ok, err, RhiError, validateDrawArgs } from '@forgeax/engine-rhi';
13
- import { AssetRegistry, DynamicTextureStore, adaptDynamicTextureDevice, getOrCreateMipmapPipeline, prepareMipmaps, blitMipmapsSync, HANDLE_CUBE, HANDLE_TRIANGLE, HANDLE_QUAD, HANDLE_SPHERE, HANDLE_NINESLICE_QUAD, BuiltinAssetRegistry, RuntimeMaterialValue, RuntimeMeshVertices, resolveAssetHandle, numMipLevels, encodeMipmapLevel, resolveTilesetRuntime, MeshSsboCeilingReachedError, MeshSsboCapacityExceededError } from '@forgeax/engine-assets-runtime';
11
+ import { AssetRegistry, DynamicTextureStore, adaptDynamicTextureDevice, getOrCreateMipmapPipeline, prepareMipmaps, blitMipmapsSync, HANDLE_CUBE, HANDLE_TRIANGLE, HANDLE_QUAD, HANDLE_SPHERE, HANDLE_NINESLICE_QUAD, BuiltinAssetRegistry, RuntimeMaterialValue, RuntimeMeshVertices, resolveAssetHandle, numMipLevels, encodeMipmapLevel, MeshSsboCeilingReachedError, MeshSsboCapacityExceededError } from '@forgeax/engine-assets-runtime';
14
12
  import { audioLoader } from '@forgeax/engine-audio-webaudio';
15
- import { Update, Time, FixedTime } from '@forgeax/engine-ecs';
16
- import { createRenderReadLease, createStateProjection } from '@forgeax/engine-ecs/projection';
13
+ import { createRenderReadLease } from '@forgeax/engine-ecs/projection';
17
14
  import { buildMeshAttributeMapForUvSets, deriveVertexBufferLayout, DEFAULT_VERTEX_ATTRIBUTE_MAP, deriveVertexCount, deriveVertexLayoutProjection, SKIN_VERTEX_ATTRIBUTE_MAP, deriveVertexBufferLayoutFromProjection } from '@forgeax/engine-geometry';
18
- import { registerPropagateTransforms, collectSubtree, Name, ChildOf, Children, MorphWeights, GlobalTransform, Transform } from '@forgeax/engine-scene';
19
- import { STANDARD_PIPELINE_PARAM_SCHEMA, createStandardPbrArtifactReceipt, SINGLE_LAYER_MEDIUM_RAW_DEPTH_WGSL, SINGLE_LAYER_MEDIUM_MSAA_PAIRED_COLOR_WGSL, SINGLE_LAYER_MEDIUM_MSAA_RAW_DEPTH_WGSL, ShaderCatalog, findVariantByKey, LTC_TABLES, standardPhysicalTextureFields, LTC_TABLE_HEIGHT, LTC_TABLE_WIDTH, DEFAULT_STANDARD_PBR_PARAM_SCHEMA, AUTO_EXPOSURE_METER_WGSL } from '@forgeax/engine-shader';
20
- import { halfFloat, frustum, mat4, vec3, box3, mat3 } from '@forgeax/engine-math';
21
- import { derive, err as err$1, ok as ok$1, handleSlot, deriveTextureLayout, ASSET_ERROR_HINTS, countExtraUvSets, toShared, RenderQueue, IMAGE_ERROR_HINTS, BUILTIN_BASE, unwrapHandle, materialValuesToLinearRuntime } from '@forgeax/engine-types';
15
+ import { STANDARD_PIPELINE_PARAM_SCHEMA, createStandardPbrArtifactReceipt, SINGLE_LAYER_MEDIUM_RAW_DEPTH_WGSL, SINGLE_LAYER_MEDIUM_MSAA_PAIRED_COLOR_WGSL, SINGLE_LAYER_MEDIUM_MSAA_RAW_DEPTH_WGSL, ShaderCatalog, findVariantByKey, MaterialArtifactRegistry, ShaderRegistry, LTC_TABLES, standardPhysicalTextureFields, LTC_TABLE_HEIGHT, LTC_TABLE_WIDTH, DEFAULT_STANDARD_PBR_PARAM_SCHEMA, AUTO_EXPOSURE_METER_WGSL } from '@forgeax/engine-shader';
16
+ import { AssetGuid } from '@forgeax/engine-pack/guid';
17
+ import { derive, ok as ok$1, err as err$1, handleSlot, deriveTextureLayout, ASSET_ERROR_HINTS, countExtraUvSets, toShared, AssetError, RenderQueue, IMAGE_ERROR_HINTS, BUILTIN_BASE, materialValuesToLinearRuntime } from '@forgeax/engine-types';
18
+ import { halfFloat, mat4, vec3, box3, frustum, mat3 } from '@forgeax/engine-math';
22
19
  import { createCurrentFrameObservationLease, RenderGraphBuilder, RenderGraphError } from '@forgeax/engine-render-graph';
20
+ import { Time, FixedTime } from '@forgeax/engine-ecs';
21
+ import { collectSubtree, Name, ChildOf, Children, GlobalTransform, MorphWeights, Transform } from '@forgeax/engine-scene';
23
22
  import { Skin } from '@forgeax/engine-skinning';
24
- import { decodeTileBits } from '@forgeax/engine-graphics-extras';
25
- import { AssetGuid } from '@forgeax/engine-pack/guid';
26
23
  import '@forgeax/engine-pack/material-cook';
27
24
 
28
25
  // src/assembly/backend-contract.ts
@@ -268,7 +265,8 @@ function exposeRenderer(renderer) {
268
265
  cause: structuredRendererCause(cause, "renderer-event")
269
266
  });
270
267
  const drawError = (cause) => {
271
- if (cause instanceof MotionBlurValidationError) return cause;
268
+ if (cause instanceof MotionBlurValidationError || cause instanceof RenderPublicationError)
269
+ return cause;
272
270
  if (cause instanceof RendererOperationError) return cause;
273
271
  if (cause instanceof RendererContractFailureError) {
274
272
  return new RendererOperationError("device-operation-failed", {
@@ -543,6 +541,237 @@ function freezeRenderProfile(profile) {
543
541
  postStages: Object.freeze([...profile.postStages])
544
542
  });
545
543
  }
544
+ function installPublicationPrograms(assets, programs) {
545
+ if (programs.length === 0) return;
546
+ const validation = new MaterialArtifactRegistry();
547
+ const shaders = new ShaderRegistry({ manifestUrl: void 0 });
548
+ const keys = /* @__PURE__ */ new Set();
549
+ for (const row of programs) {
550
+ if (keys.has(row.key) || row.artifact !== void 0 && row.artifact.key !== row.key)
551
+ throw new RenderPublicationError({
552
+ reason: "shape",
553
+ subject: "duplicate or mismatched program key"
554
+ });
555
+ keys.add(row.key);
556
+ shaders.installMaterialArtifact(row.key, row.shader);
557
+ const previous = assets.shaderRegistry.findMaterialArtifact(row.key);
558
+ if (previous.ok && (previous.value.source !== row.shader.source || JSON.stringify(previous.value.paramSchema) !== JSON.stringify(row.shader.paramSchema) || JSON.stringify(previous.value.receipt) !== JSON.stringify(row.shader.receipt))) {
559
+ throw new RenderPublicationError({
560
+ reason: "shape",
561
+ subject: `conflicting immutable shader ${row.key}`
562
+ });
563
+ }
564
+ if (row.artifact !== void 0) {
565
+ const existing = assets.getMaterialArtifact(row.key);
566
+ if (existing !== void 0) validation.register(existing).unwrap();
567
+ validation.register(row.artifact).unwrap();
568
+ }
569
+ }
570
+ for (const row of programs) {
571
+ if (row.artifact !== void 0) assets.materialArtifactRegistry.register(row.artifact).unwrap();
572
+ if (!assets.shaderRegistry.findMaterialArtifact(row.key).ok)
573
+ assets.shaderRegistry.installMaterialArtifact(row.key, row.shader);
574
+ }
575
+ }
576
+ var RenderPublicationReceiver = class {
577
+ constructor(identity) {
578
+ this.identity = identity;
579
+ const resolveAsset = (handle) => {
580
+ const value = this.assets.get(handle);
581
+ return value === void 0 ? err$1(
582
+ new AssetError({
583
+ code: "asset-not-found",
584
+ expected: "the accepted publication contains the referenced asset generation",
585
+ hint: "publish the asset closure before drawing its consumer"
586
+ })
587
+ ) : ok$1(value);
588
+ };
589
+ this.resources = {
590
+ identity: `${identity.source}:${identity.epoch}`,
591
+ time: { delta: 0, elapsed: 0, maxDeltaSeconds: 0 },
592
+ transparentSort: { mode: 0, yzAlpha: 1 },
593
+ resolveAsset,
594
+ videoFrame: (entity, clip) => this.videoFrames.get(`${entity}:${clip}`),
595
+ handleForGuid: (guid) => this.guidHandles.get(guid.toLowerCase()),
596
+ lookupAsset: (guid) => {
597
+ const handle = this.guidHandles.get(guid.toLowerCase());
598
+ return handle === void 0 ? void 0 : this.assets.get(handle);
599
+ }
600
+ };
601
+ }
602
+ identity;
603
+ revision = 0;
604
+ videoFrames = /* @__PURE__ */ new Map();
605
+ entities = /* @__PURE__ */ new Set();
606
+ assets = /* @__PURE__ */ new Map();
607
+ resources;
608
+ guidHandles = /* @__PURE__ */ new Map();
609
+ accept(packet) {
610
+ const reject = (reason2, subject) => err$1(new RenderPublicationError({ reason: reason2, subject }));
611
+ if (packet.source !== this.identity.source || packet.epoch !== this.identity.epoch)
612
+ return reject("identity", "source/epoch");
613
+ if (packet.base !== this.revision || packet.baseline !== (this.revision === 0))
614
+ return reject("base", "accepted revision");
615
+ if (!Number.isSafeInteger(packet.revision) || packet.revision !== this.revision + 1)
616
+ return reject("revision", "next revision");
617
+ if (!(packet.upserts instanceof Uint32Array) || packet.upserts.length % 2 !== 0 || !(packet.removed instanceof Uint32Array) || !(packet.transformEntities instanceof Uint32Array) || !(packet.transforms instanceof Float32Array) || packet.transforms.length !== packet.transformEntities.length * 16 || !packet.transforms.every(Number.isFinite) || !Number.isFinite(packet.sampleTimeSeconds))
618
+ return reject("shape", "numeric columns");
619
+ if (!Array.isArray(packet.videoFrames) || !Array.isArray(packet.targets) || !Array.isArray(packet.targetSources) || !Array.isArray(packet.features) || !Array.isArray(packet.templates) || !Array.isArray(packet.programs) || !Array.isArray(packet.assets) || !Array.isArray(packet.retiredAssets) || !Array.isArray(packet.invalidatedAssets) || packet.metadata === null || typeof packet.metadata !== "object" || !Array.isArray(packet.metadata.cameras) || !Number.isFinite(packet.time?.elapsed) || !Number.isFinite(packet.time?.delta))
620
+ return reject("shape", "frame metadata");
621
+ const videoKeys = /* @__PURE__ */ new Set();
622
+ for (const row of packet.videoFrames) {
623
+ const key = `${row.entity}:${row.clip}`;
624
+ if (!Number.isSafeInteger(row.entity) || !Number.isSafeInteger(row.clip) || typeof VideoFrame === "undefined" || !(row.frame instanceof VideoFrame) || row.frame.displayWidth <= 0 || row.frame.displayHeight <= 0 || videoKeys.has(key))
625
+ return reject("shape", "video frame");
626
+ videoKeys.add(key);
627
+ }
628
+ const targetIds = /* @__PURE__ */ new Set();
629
+ const targetTokens = /* @__PURE__ */ new Set();
630
+ for (const row of packet.targets) {
631
+ if (!Number.isSafeInteger(row.id) || row.id <= 0 || targetIds.has(row.id) || typeof row.token !== "object" || row.token === null || targetTokens.has(row.token) || typeof row.descriptor !== "object" || row.descriptor === null)
632
+ return reject("shape", "target identity/descriptor");
633
+ targetIds.add(row.id);
634
+ targetTokens.add(row.token);
635
+ }
636
+ for (const camera of [
637
+ ...packet.metadata.cameras,
638
+ ...packet.metadata.auxiliaryCameras,
639
+ ...packet.metadata.cubeCameras
640
+ ])
641
+ if (camera.target !== void 0 && !targetTokens.has(camera.target))
642
+ return reject("shape", "missing target descriptor");
643
+ const sourceTokens = /* @__PURE__ */ new Set();
644
+ for (const row of packet.targetSources) {
645
+ if (!targetTokens.has(row.target) || typeof row.token !== "object" || row.token === null || sourceTokens.has(row.token))
646
+ return reject("shape", "target source");
647
+ sourceTokens.add(row.token);
648
+ }
649
+ const featureIdentities = /* @__PURE__ */ new Set();
650
+ for (const row of packet.features) {
651
+ if (typeof row.identity !== "string" || featureIdentities.has(row.identity))
652
+ return reject("shape", "feature identity");
653
+ featureIdentities.add(row.identity);
654
+ }
655
+ const matrices = /* @__PURE__ */ new Map();
656
+ for (let i = 0; i < packet.transformEntities.length; i++) {
657
+ const entity = packet.transformEntities[i];
658
+ if (matrices.has(entity)) return reject("shape", "duplicate transform identity");
659
+ matrices.set(entity, packet.transforms.slice(i * 16, i * 16 + 16));
660
+ }
661
+ const operations = [];
662
+ const renderables = [];
663
+ const dispatch = [];
664
+ const updated = /* @__PURE__ */ new Set();
665
+ for (let i = 0; i < packet.upserts.length; i += 2) {
666
+ const entityKey = packet.upserts[i];
667
+ const template = packet.templates[packet.upserts[i + 1]];
668
+ const world = matrices.get(entityKey);
669
+ if (template === void 0 || world === void 0 || updated.has(entityKey))
670
+ return reject("shape", "upsert template/transform");
671
+ if (!Array.isArray(template.snapshot?.materials) || !Array.isArray(template.dispatch))
672
+ return reject("shape", "template");
673
+ for (const material of template.snapshot.materials)
674
+ for (const source of material.textureSources?.values() ?? [])
675
+ if (!sourceTokens.has(source)) return reject("shape", "missing target source");
676
+ if (template.snapshot.skin !== void 0) return reject("shape", "source GPU skin receipt");
677
+ const pose = template.snapshot.skinPose;
678
+ if (pose !== void 0 && (!Number.isInteger(pose.jointCount) || pose.jointCount <= 0 || pose.inverseBindMatrices.length !== pose.jointCount || pose.jointWorlds.length !== pose.jointCount || [...pose.inverseBindMatrices, ...pose.jointWorlds].some(
679
+ (matrix) => !(matrix instanceof Float32Array) || matrix.length !== 16 || !matrix.every(Number.isFinite)
680
+ )))
681
+ return reject("shape", "skin pose");
682
+ updated.add(entityKey);
683
+ const snapshot = {
684
+ ...template.snapshot,
685
+ worldId: 0,
686
+ entityKey,
687
+ transform: { world }
688
+ };
689
+ for (const item of template.dispatch)
690
+ dispatch.push({ ...item, entityIndex: entityKey, renderableIndex: renderables.length });
691
+ renderables.push(snapshot);
692
+ operations.push({ kind: "update", worldId: 0, entityKey, snapshot });
693
+ }
694
+ const removed = /* @__PURE__ */ new Set();
695
+ for (const entityKey of packet.removed) {
696
+ if (!this.entities.has(entityKey) || updated.has(entityKey) || removed.has(entityKey))
697
+ return reject("shape", "duplicate removal");
698
+ removed.add(entityKey);
699
+ operations.push({ kind: "remove", worldId: 0, entityKey });
700
+ }
701
+ for (const [entityKey, world] of matrices) {
702
+ if (removed.has(entityKey)) return reject("shape", "removed transform");
703
+ if (!updated.has(entityKey) && !this.entities.has(entityKey))
704
+ return reject("shape", "unknown transform identity");
705
+ if (!updated.has(entityKey))
706
+ operations.push({ kind: "update", worldId: 0, entityKey, world });
707
+ }
708
+ const assetHandles = /* @__PURE__ */ new Set();
709
+ for (const row of packet.assets) {
710
+ if (row.value === null || typeof row.value !== "object" || !Number.isSafeInteger(row.handle) || assetHandles.has(row.handle) || packet.retiredAssets.includes(row.handle))
711
+ return reject("shape", "asset payload");
712
+ assetHandles.add(row.handle);
713
+ }
714
+ for (const handles of [
715
+ publicationFrameDependencies(packet.metadata),
716
+ ...renderables.map(publicationDependencies)
717
+ ]) {
718
+ if (handles.some(
719
+ (handle) => !assetHandles.has(handle) && (!this.assets.has(handle) || packet.retiredAssets.includes(handle))
720
+ ))
721
+ return reject("shape", "missing asset dependency");
722
+ }
723
+ const guidHandles = new Map(this.guidHandles);
724
+ for (const [guid, handle] of guidHandles)
725
+ if (packet.retiredAssets.includes(handle)) guidHandles.delete(guid);
726
+ for (const row of packet.assets)
727
+ if (row.guid !== void 0) guidHandles.set(row.guid.toLowerCase(), row.handle);
728
+ for (const row of renderables)
729
+ if (row.lods?.some((lod) => !guidHandles.has(AssetGuid.format(lod.mesh).toLowerCase())))
730
+ return reject("shape", "missing LOD dependency");
731
+ for (const entity of removed) this.entities.delete(entity);
732
+ for (const entity of updated) this.entities.add(entity);
733
+ if (packet.baseline) this.assets.clear();
734
+ this.guidHandles.clear();
735
+ for (const [guid, handle] of guidHandles) this.guidHandles.set(guid, handle);
736
+ for (const handle of packet.retiredAssets) this.assets.delete(handle);
737
+ for (const row of packet.assets) this.assets.set(row.handle, row.value);
738
+ Object.assign(this.resources, { time: packet.time, transparentSort: packet.transparentSort });
739
+ this.releaseVideoFrames();
740
+ this.videoFrames = new Map(
741
+ packet.videoFrames.map((row) => [`${row.entity}:${row.clip}`, row.frame])
742
+ );
743
+ this.revision = packet.revision;
744
+ return ok$1({
745
+ resources: this.resources,
746
+ packet,
747
+ operations,
748
+ frame: {
749
+ ...packet.metadata,
750
+ renderables,
751
+ dispatch,
752
+ visibilitySnapshots: [],
753
+ featureVisibilitySnapshots: [],
754
+ hiddenEntityReports: [],
755
+ shadowCasterEntityKeys: /* @__PURE__ */ new Set(),
756
+ shadowCasterDrawKeys: /* @__PURE__ */ new Set()
757
+ }
758
+ });
759
+ }
760
+ /** copyExternalImageToTexture consumes native sources synchronously during draw. */
761
+ releaseVideoFrames() {
762
+ for (const frame of this.videoFrames.values()) frame.close();
763
+ this.videoFrames.clear();
764
+ }
765
+ dispose() {
766
+ this.releaseVideoFrames();
767
+ this.assets.clear();
768
+ this.guidHandles.clear();
769
+ this.entities.clear();
770
+ }
771
+ get acceptedRevision() {
772
+ return this.revision;
773
+ }
774
+ };
546
775
 
547
776
  // src/device/mesh-residency-lifetime.ts
548
777
  var MeshResidencyLifetime = class {
@@ -899,9 +1128,9 @@ var GpuResidencyCache = class {
899
1128
  this.meshLifetime(entry).retire();
900
1129
  }
901
1130
  /**
902
- * Compose a cache key from the raw handle slot and its owning World. The
1131
+ * Compose a cache key from the raw handle slot and its owning RenderResourceScope. The
903
1132
  * draw-time world index is only a position in one frame's `worlds[]`; it is
904
- * not an asset identity and can be reused by a later World. World objects
1133
+ * not an asset identity and can be reused by a later RenderResourceScope. RenderResourceScope objects
905
1134
  * therefore receive a renderer-local namespace, while numeric callers keep
906
1135
  * the legacy namespace for low-level tests and built-in upload paths.
907
1136
  */
@@ -1874,12 +2103,12 @@ var GpuResidencyCache = class {
1874
2103
  });
1875
2104
  if (!equirectViewResult.ok) return recordFailed(equirectViewResult.error);
1876
2105
  const equirectView = equirectViewResult.value;
1877
- const bytesPerPixel2 = tex.format === "rgba32float" ? 16 : tex.format === "rgba16float" ? 8 : 4;
2106
+ const bytesPerPixel = tex.format === "rgba32float" ? 16 : tex.format === "rgba16float" ? 8 : 4;
1878
2107
  const equirectWriteResult = device.queue.writeTexture(
1879
2108
  { texture: equirectGpuTex },
1880
2109
  tex.data,
1881
2110
  {
1882
- bytesPerRow: tex.shape.extent.width * bytesPerPixel2,
2111
+ bytesPerRow: tex.shape.extent.width * bytesPerPixel,
1883
2112
  rowsPerImage: tex.shape.extent.height
1884
2113
  },
1885
2114
  {
@@ -1945,7 +2174,7 @@ var GpuResidencyCache = class {
1945
2174
  view: cubeView,
1946
2175
  faceViews
1947
2176
  });
1948
- const regResult = registerCube(world, cubeAsset);
2177
+ const regResult = registerCube(world, cubeAsset, sourceHandle);
1949
2178
  if (!regResult.ok) return recordFailed(regResult.error);
1950
2179
  const cubeHandle = regResult.value;
1951
2180
  const cubeId = handleSlot(cubeHandle);
@@ -2566,8 +2795,8 @@ function cloneSignatureNode(value, previous) {
2566
2795
  values
2567
2796
  });
2568
2797
  }
2569
- const token2 = stablePrimitiveToken(value);
2570
- return previous?.kind === "primitive" && previous.token === token2 ? previous : { kind: "primitive", token: token2 };
2798
+ const token = stablePrimitiveToken(value);
2799
+ return previous?.kind === "primitive" && previous.token === token ? previous : { kind: "primitive", token };
2571
2800
  }
2572
2801
  function signatureResourceValue(resource) {
2573
2802
  if (resource.kind !== "buffer") return resource;
@@ -4292,7 +4521,10 @@ function runRenderFeatureFrame(host, input) {
4292
4521
  const extracted = invokeStage(
4293
4522
  slot,
4294
4523
  "extract",
4295
- () => slot.feature.extract(extractContext),
4524
+ () => {
4525
+ const published = input.publishedFeatures?.find((row) => row.identity === identity);
4526
+ return published === void 0 ? slot.feature.extract(extractContext) : ok$1(published.data);
4527
+ },
4296
4528
  stageEvents,
4297
4529
  errors
4298
4530
  );
@@ -4447,12 +4679,14 @@ function runRenderFeatureFrame(host, input) {
4447
4679
  continue;
4448
4680
  }
4449
4681
  planExecutionProjections.set(plannedFrame, projected.value);
4450
- if (feature.onFrameSubmitted !== void 0) {
4682
+ if (feature.onFrameSubmitted !== void 0 || feature.onSourceFrameSubmitted !== void 0) {
4451
4683
  submissionSensitivePlans.add(plannedFrame);
4452
- submissionAcknowledgments.set(
4453
- plannedFrame,
4454
- () => feature.onFrameSubmitted?.(extracted.value, projected.value)
4455
- );
4684
+ submissionAcknowledgments.set(plannedFrame, () => {
4685
+ feature.onFrameSubmitted?.(extracted.value, projected.value);
4686
+ if (input.publishedFeatures?.some((row) => row.identity === identity))
4687
+ input.onFeatureSourceSubmitted?.(identity, declared.value.sourceFeedback);
4688
+ else feature.onSourceFrameSubmitted?.(extracted.value, declared.value.sourceFeedback);
4689
+ });
4456
4690
  }
4457
4691
  plans.push(plannedFrame);
4458
4692
  if (feature.onFrameAborted !== void 0) {
@@ -6370,16 +6604,6 @@ function addTransmissionBackdropTemporalPass(graph, source) {
6370
6604
  encode: () => void 0
6371
6605
  });
6372
6606
  }
6373
-
6374
- // src/typed-shadow-atlas.ts
6375
- function resolveDirectionalShadowAtlasGrid(cascadeCount) {
6376
- const count = Math.max(1, Math.min(4, Math.round(cascadeCount)));
6377
- if (count === 1) return { columns: 1, rows: 1 };
6378
- if (count === 2) return { columns: 2, rows: 1 };
6379
- return { columns: 2, rows: 2 };
6380
- }
6381
-
6382
- // src/typed-shadow-passes.ts
6383
6607
  function shadowViewCacheReuse(frame, identity) {
6384
6608
  const context = frame;
6385
6609
  const gpuShadowViews = context.gpuDrivenShadowViews;
@@ -9592,7 +9816,7 @@ function prepareStandardLutGpu(input) {
9592
9816
  if (!asset.ok) {
9593
9817
  return failure2(
9594
9818
  "standard-lut-residency-failed",
9595
- "the authored TextureAsset handle resolves in the active World",
9819
+ "the authored TextureAsset handle resolves in the active RenderResourceScope",
9596
9820
  "register or rebuild the TextureAsset, then retry the same camera generation",
9597
9821
  causeDetail(asset.error)
9598
9822
  );
@@ -13033,6 +13257,75 @@ function projectCaptureScene(retained, visible, displayDispatch) {
13033
13257
  })
13034
13258
  };
13035
13259
  }
13260
+ function renderTime(source) {
13261
+ return "resolveAsset" in source ? source.time : source.getResource(Time);
13262
+ }
13263
+ function renderAssetByGuid(source, assets, guid) {
13264
+ return "resolveAsset" in source ? source.lookupAsset(typeof guid === "string" ? guid : AssetGuid.format(guid)) : assets.lookup(guid);
13265
+ }
13266
+
13267
+ // src/publication/prepare-geometry.ts
13268
+ function preparePublicationGeometry(input, scene, palette, assets, instances, getMaterialShaderArtifact) {
13269
+ const replacements = /* @__PURE__ */ new Map();
13270
+ for (const operation of input.operations) {
13271
+ if (operation.kind !== "remove" && operation.snapshot === void 0) continue;
13272
+ if (operation.kind === "remove" || operation.snapshot?.instances === void 0)
13273
+ instances.release(input.resources, operation.entityKey);
13274
+ const prior = scene.compositionSlot(0, operation.entityKey)?.snapshot.skin;
13275
+ const pose = operation.kind === "remove" ? void 0 : operation.snapshot?.skinPose;
13276
+ if (prior !== void 0 && prior.identity !== pose?.identity)
13277
+ palette?.releasePersistentSlice(prior.identity);
13278
+ }
13279
+ for (const row of input.frame.renderables) {
13280
+ const { skinPose, ...source } = row;
13281
+ let skin = row.skin;
13282
+ if (skinPose !== void 0) {
13283
+ if (palette == null)
13284
+ throw new RenderPublicationError({
13285
+ reason: "unsupported",
13286
+ subject: "skin palette allocator"
13287
+ });
13288
+ palette.observePersistentJoints(
13289
+ skinPose.identity,
13290
+ skinPose.inverseBindMatrices,
13291
+ skinPose.jointWorlds
13292
+ );
13293
+ skin = palette.allocatePersistentSlice(skinPose);
13294
+ palette.writePersistentJointPalette(skin, skinPose.inverseBindMatrices, skinPose.jointWorlds);
13295
+ }
13296
+ const projected = row.instances === void 0 ? void 0 : instances.project(input.resources, row.entityKey, row.instances.transforms);
13297
+ const snapshot = {
13298
+ ...source,
13299
+ ...skin === void 0 ? {} : { skin },
13300
+ ...projected === void 0 || row.instances === void 0 ? {} : { instances: { ...row.instances, ...projected, archVersion: 0 } }
13301
+ };
13302
+ if (projected !== void 0) instances.accept(input.resources, row.entityKey, projected);
13303
+ const mesh = input.resources.resolveAsset(
13304
+ row.assetHandle
13305
+ );
13306
+ if (!mesh.ok) throw mesh.error;
13307
+ const gpuDrivenDraws = row.morph === void 0 ? buildGpuDrivenDraws({
13308
+ mesh: mesh.value,
13309
+ materials: row.materials,
13310
+ fallbackMaterial: row.material,
13311
+ baseSnapshot: snapshot,
13312
+ ...getMaterialShaderArtifact === void 0 ? {} : { getMaterialShaderArtifact },
13313
+ ...row.lods === void 0 ? {} : {
13314
+ lodMeshes: row.lods.map(
13315
+ (lod) => renderAssetByGuid(input.resources, assets, lod.mesh)
13316
+ )
13317
+ }
13318
+ }) : [];
13319
+ replacements.set(row.entityKey, { ...snapshot, gpuDrivenDraws });
13320
+ }
13321
+ return {
13322
+ ...input,
13323
+ frame: { ...input.frame, renderables: [...replacements.values()] },
13324
+ operations: input.operations.map(
13325
+ (operation) => operation.kind !== "remove" && operation.snapshot !== void 0 ? { ...operation, snapshot: replacements.get(operation.entityKey) } : operation
13326
+ )
13327
+ };
13328
+ }
13036
13329
 
13037
13330
  // src/assembly/directional-shadow-inspection.ts
13038
13331
  function deepFreeze2(value, seen = /* @__PURE__ */ new WeakSet()) {
@@ -14641,8 +14934,8 @@ var MaterialAbiRasterAdapter = class _MaterialAbiRasterAdapter {
14641
14934
  return;
14642
14935
  }
14643
14936
  if (!this.pendingProjectionRetirements.add(buffer)) return;
14644
- const token2 = this.allocationTokens.get(buffer);
14645
- if (token2 !== void 0) this.allocationLedger.retire(token2);
14937
+ const token = this.allocationTokens.get(buffer);
14938
+ if (token !== void 0) this.allocationLedger.retire(token);
14646
14939
  void this.device.queue.onSubmittedWorkDone().then(
14647
14940
  () => {
14648
14941
  this.pendingProjectionRetirements.delete(buffer);
@@ -14659,8 +14952,8 @@ var MaterialAbiRasterAdapter = class _MaterialAbiRasterAdapter {
14659
14952
  this.destroyedProjectionBuffers.add(buffer);
14660
14953
  this.projectionBuffers.delete(buffer);
14661
14954
  this.surfaceInputBuffers.delete(buffer);
14662
- const token2 = this.allocationTokens.get(buffer);
14663
- if (token2 !== void 0) this.allocationLedger.release(token2);
14955
+ const token = this.allocationTokens.get(buffer);
14956
+ if (token !== void 0) this.allocationLedger.release(token);
14664
14957
  this.device.destroyBuffer(buffer);
14665
14958
  }
14666
14959
  trackOwnedBuffer(buffer, bytes2) {
@@ -14673,8 +14966,8 @@ var MaterialAbiRasterAdapter = class _MaterialAbiRasterAdapter {
14673
14966
  this.projectionBuffers.delete(buffer);
14674
14967
  this.surfaceInputBuffers.delete(buffer);
14675
14968
  this.pendingProjectionRetirements.delete(buffer);
14676
- const token2 = this.allocationTokens.get(buffer);
14677
- if (token2 !== void 0) this.allocationLedger.rollback(token2);
14969
+ const token = this.allocationTokens.get(buffer);
14970
+ if (token !== void 0) this.allocationLedger.rollback(token);
14678
14971
  this.device.destroyBuffer(buffer);
14679
14972
  }
14680
14973
  get instancesFrameGroup() {
@@ -20189,7 +20482,9 @@ function validateRenderables(internals, world, worlds, pipelineState, frameState
20189
20482
  }
20190
20483
  const meshAssetHandle = toShared(r.assetHandle);
20191
20484
  let meshHandles = internals.gpuStore.getMeshGpuHandles(meshAssetHandle, renderableWorld);
20192
- const lodMeshes = r.lods?.map((lod) => internals.assets.lookup(lod.mesh));
20485
+ const lodMeshes = r.lods?.map(
20486
+ (lod) => renderAssetByGuid(renderableWorld, internals.assets, lod.mesh)
20487
+ );
20193
20488
  const resolvedLodMeshes = lodMeshes?.every((lod) => lod?.kind === "mesh") === true ? lodMeshes : void 0;
20194
20489
  if (meshHandles === void 0 && r.assetHandle > handleSlot(HANDLE_NINESLICE_QUAD)) {
20195
20490
  const residentRes = internals.gpuStore.ensureResident(
@@ -21008,157 +21303,197 @@ function inspectBarrelDistortionState(state, deviceGeneration) {
21008
21303
  lastKnownGood: mapping !== void 0 && state.compiledFrameGraph !== null && state.barrelDistortionGraphResolution === "retained"
21009
21304
  });
21010
21305
  }
21011
-
21012
- // src/record/frame-targets.ts
21013
- function graphExecutionPhase(passName) {
21014
- if (passName.startsWith("shadowCascade")) return "record/graph-execute/shadow";
21015
- if (passName.startsWith("point-shadow")) return "record/graph-execute/point-shadow";
21016
- if (passName.startsWith("spot-shadow")) return "record/graph-execute/spot-shadow";
21017
- if (passName === "ssr-hiz-seed" || passName.startsWith("ssr-hiz-reduce-")) {
21018
- return "record/graph-execute/ssr-hiz";
21019
- }
21020
- if (passName === "ssr-trace") return "record/graph-execute/ssr-trace";
21021
- if (passName === "ssr-temporal") return "record/graph-execute/ssr-temporal";
21022
- if (passName.startsWith("ssr-reflection-mip-")) {
21023
- return "record/graph-execute/ssr-reflection-mip";
21024
- }
21025
- if (passName === "ssr-compose") return "record/graph-execute/ssr-compose";
21026
- if (passName.startsWith("bloom-downsample-")) {
21027
- return "record/graph-execute/bloom-downsample";
21028
- }
21029
- if (passName.startsWith("bloom-upsample-")) {
21030
- return "record/graph-execute/bloom-upsample";
21031
- }
21032
- switch (passName) {
21033
- case "cluster-binner-upload":
21034
- case "cluster-membership-producer":
21035
- return "record/graph-execute/cluster-binner-upload";
21036
- case "g-buffer":
21037
- return "record/graph-execute/g-buffer";
21038
- case "ssao-calc":
21039
- return "record/graph-execute/ssao-calc";
21040
- case "ssao-blur":
21041
- return "record/graph-execute/ssao-blur";
21042
- case "lighting":
21043
- return "record/graph-execute/lighting";
21044
- case "forward":
21045
- case "transmission-forward":
21046
- return "record/graph-execute/forward";
21047
- case "output-transform":
21048
- return "record/graph-execute/output-transform";
21049
- case "present":
21050
- return "record/graph-execute/present";
21051
- case "debug-overlay":
21052
- return "record/graph-execute/debug-overlay";
21053
- case "shadow":
21054
- return "record/graph-execute/shadow";
21055
- case "skybox":
21056
- return "record/graph-execute/skybox";
21057
- case "main":
21058
- return "record/graph-execute/main";
21059
- case "fxaa":
21060
- return "record/graph-execute/fxaa";
21061
- case "bloom-downsample":
21062
- return "record/graph-execute/bloom-downsample";
21063
- case "bloom-upsample":
21064
- return "record/graph-execute/bloom-upsample";
21065
- case "bloom-composite":
21066
- return "record/graph-execute/bloom-composite";
21067
- default:
21068
- return "record/graph-execute/other";
21069
- }
21306
+ function renderTargetMipCount(work) {
21307
+ const { descriptor } = work.physical;
21308
+ return descriptor.mipLevels === 1 ? 1 : Math.floor(Math.log2(Math.max(descriptor.width, descriptor.height))) + 1;
21070
21309
  }
21071
- function resolveRenderTargetMipExtent(descriptor, mipLevel) {
21072
- const mipCount2 = descriptor.mipLevels === 1 ? 1 : Math.floor(Math.log2(Math.max(descriptor.width, descriptor.height))) + 1;
21073
- const level = Math.max(0, Math.min(mipLevel, mipCount2 - 1));
21074
- return {
21075
- width: Math.max(1, descriptor.width >> level),
21076
- height: Math.max(1, descriptor.height >> level)
21077
- };
21078
- }
21079
- function acquireSwapChainTarget(internals, pipelineState) {
21080
- const canvasContext = internals.context;
21081
- if (canvasContext === null) return null;
21082
- let currentTextureResult = canvasContext.getCurrentTexture();
21083
- if (!currentTextureResult.ok) {
21084
- const configuredDevice = internals.resolveSurfaceDevice?.(internals.device);
21085
- if (configuredDevice !== void 0 && !configuredDevice.ok) {
21086
- internals.errorRegistry.fire(configuredDevice.error);
21087
- internals.healthRegistry.fire({
21088
- reason: "internal-fault",
21089
- detail: { message: "surface device resolution failed; current frame skipped" },
21090
- recoverable: true
21091
- });
21092
- return null;
21093
- }
21094
- const configured = configureSurface(
21095
- canvasContext,
21096
- configuredDevice?.value ?? internals.device,
21097
- pipelineState.format,
21098
- pipelineState.colorAttachmentFormat
21310
+ function addTargetCaptureGraphPasses(builder, state) {
21311
+ for (let index = 0; index < state.work.length; index += 1) {
21312
+ const slot = index;
21313
+ const initial = state.work[slot];
21314
+ if (initial === void 0) continue;
21315
+ const current = () => state.work[slot] ?? initial;
21316
+ const texture = builder.importTexture(
21317
+ `cube-capture.${slot}.texture`,
21318
+ {
21319
+ format: initial.physical.descriptor.format,
21320
+ size: {
21321
+ width: initial.physical.descriptor.width,
21322
+ height: initial.physical.descriptor.height,
21323
+ depthOrArrayLayers: initial.physical.descriptor.sampleCount === 4 || initial.physical.descriptor.shape === "2d" ? 1 : 6
21324
+ },
21325
+ mipLevelCount: initial.physical.descriptor.sampleCount === 4 ? 1 : renderTargetMipCount(initial),
21326
+ sampleCount: initial.physical.descriptor.sampleCount,
21327
+ dimension: "2d",
21328
+ usage: 16 | 4 | 1
21329
+ },
21330
+ () => current().physical.colorTextures[current().faceIndex] ?? initial.physical.texture
21099
21331
  );
21100
- if (!configured.ok) {
21101
- internals.errorRegistry.fire(configured.error);
21102
- internals.healthRegistry.fire({
21103
- reason: "internal-fault",
21104
- detail: { message: "surface configure candidate failed; current frame skipped" },
21105
- recoverable: true
21106
- });
21107
- return null;
21108
- }
21109
- pipelineState.perPassResources.configured = true;
21110
- globalThis.__forgeaxSwapChainFormat = pipelineState.format;
21111
- const retry = canvasContext.getCurrentTexture();
21112
- if (!retry.ok) {
21113
- internals.errorRegistry.fire(retry.error);
21114
- internals.healthRegistry.fire({
21115
- reason: "internal-fault",
21116
- detail: {
21117
- message: "surface-configure-failed after retry: getCurrentTexture failed twice consecutively"
21332
+ if (!texture.ok) return texture;
21333
+ const color = builder.importView(
21334
+ texture.value,
21335
+ {
21336
+ label: `cube-capture.${slot}.color`,
21337
+ dimension: "2d",
21338
+ baseMipLevel: 0,
21339
+ mipLevelCount: 1,
21340
+ baseArrayLayer: initial.physical.descriptor.sampleCount === 4 ? 0 : initial.faceIndex,
21341
+ arrayLayerCount: 1
21342
+ },
21343
+ () => current().physical.faceViews[current().faceIndex] ?? initial.physical.faceViews[initial.faceIndex] ?? initial.physical.view
21344
+ );
21345
+ if (!color.ok) return color;
21346
+ const depthTexture = builder.importTexture(
21347
+ `cube-capture.${slot}.depth-texture`,
21348
+ {
21349
+ format: "depth24plus-stencil8",
21350
+ size: {
21351
+ width: initial.physical.descriptor.width,
21352
+ height: initial.physical.descriptor.height,
21353
+ depthOrArrayLayers: initial.physical.descriptor.sampleCount === 4 || initial.physical.descriptor.shape === "2d" ? 1 : 6
21118
21354
  },
21119
- recoverable: false
21120
- });
21121
- return null;
21122
- }
21123
- currentTextureResult = retry;
21124
- }
21125
- const viewDescriptor = pipelineState.colorAttachmentFormat === pipelineState.format ? {} : { format: pipelineState.colorAttachmentFormat };
21126
- const viewResult = internals.device.createTextureView(currentTextureResult.value, viewDescriptor);
21127
- if (!viewResult.ok) {
21128
- internals.errorRegistry.fire(viewResult.error);
21129
- return null;
21355
+ mipLevelCount: 1,
21356
+ sampleCount: initial.physical.descriptor.sampleCount,
21357
+ dimension: "2d",
21358
+ usage: 16
21359
+ },
21360
+ () => current().physical.depthTextures[current().faceIndex]
21361
+ );
21362
+ if (!depthTexture.ok) return depthTexture;
21363
+ const depth = builder.importView(
21364
+ depthTexture.value,
21365
+ {
21366
+ label: `cube-capture.${slot}.depth`,
21367
+ dimension: "2d",
21368
+ baseArrayLayer: initial.physical.descriptor.sampleCount === 4 ? 0 : initial.faceIndex,
21369
+ arrayLayerCount: 1
21370
+ },
21371
+ () => current().physical.depthViews[current().faceIndex]
21372
+ );
21373
+ if (!depth.ok) return depth;
21374
+ const resolveTexture = initial.physical.descriptor.sampleCount === 4 ? builder.importTexture(
21375
+ `cube-capture.${slot}.resolve-texture`,
21376
+ {
21377
+ format: initial.physical.descriptor.format,
21378
+ size: {
21379
+ width: initial.physical.descriptor.width,
21380
+ height: initial.physical.descriptor.height,
21381
+ depthOrArrayLayers: initial.physical.descriptor.shape === "cube" ? 6 : 1
21382
+ },
21383
+ mipLevelCount: renderTargetMipCount(initial),
21384
+ sampleCount: 1,
21385
+ dimension: "2d",
21386
+ usage: 16 | 4 | 1
21387
+ },
21388
+ () => current().physical.resolveTexture ?? initial.physical.resolveTexture ?? initial.physical.texture
21389
+ ) : void 0;
21390
+ if (resolveTexture !== void 0 && !resolveTexture.ok) return resolveTexture;
21391
+ const resolve = resolveTexture === void 0 ? void 0 : builder.importView(
21392
+ resolveTexture.value,
21393
+ {
21394
+ label: `cube-capture.${slot}.resolve`,
21395
+ dimension: "2d",
21396
+ baseMipLevel: 0,
21397
+ mipLevelCount: 1,
21398
+ baseArrayLayer: initial.faceIndex,
21399
+ arrayLayerCount: 1
21400
+ },
21401
+ () => current().physical.resolveFaceViews[current().faceIndex] ?? initial.physical.resolveFaceViews[initial.faceIndex] ?? initial.physical.resolveView
21402
+ );
21403
+ if (resolve !== void 0 && !resolve.ok) return resolve;
21404
+ const added = builder.addRasterPass(`cube-capture-face.${slot}`, {
21405
+ accesses: [
21406
+ { resource: color.value, usage: "color-attachment" },
21407
+ { resource: depth.value, usage: "depth-stencil-write" },
21408
+ ...resolve === void 0 ? [] : [{ resource: resolve.value, usage: "color-attachment" }]
21409
+ ],
21410
+ colorAttachments: [
21411
+ {
21412
+ view: color.value,
21413
+ ...resolve === void 0 ? {} : { resolveTarget: resolve.value },
21414
+ loadOp: "clear",
21415
+ storeOp: "store",
21416
+ clearValue: () => {
21417
+ const clear = current().physical.descriptor.shape === "2d" ? current().faceCamera.clearColor : [0, 0, 0, 1];
21418
+ return { r: clear[0] ?? 0, g: clear[1] ?? 0, b: clear[2] ?? 0, a: clear[3] ?? 1 };
21419
+ }
21420
+ }
21421
+ ],
21422
+ depthStencilAttachment: {
21423
+ view: depth.value,
21424
+ depthClearValue: 1,
21425
+ depthLoadOp: "clear",
21426
+ depthStoreOp: "store",
21427
+ stencilClearValue: 0,
21428
+ stencilLoadOp: "clear",
21429
+ stencilStoreOp: "store"
21430
+ },
21431
+ encode: ({ pass, frame, resources }) => {
21432
+ const internal = frame;
21433
+ const captureColor = resources.textureView(color.value);
21434
+ if (!captureColor.ok) return;
21435
+ const captureDepth = resources.textureView(depth.value);
21436
+ if (!captureDepth.ok) return;
21437
+ const captureResolve = resolve === void 0 ? void 0 : resources.textureView(resolve.value);
21438
+ if (resolve !== void 0 && (captureResolve === void 0 || !captureResolve.ok)) return;
21439
+ const captureResolveView = captureResolve?.ok ? captureResolve.value : null;
21440
+ const selfSampling = /* @__PURE__ */ new Map();
21441
+ for (const row of internal.validatedOrdered) {
21442
+ for (const material of row.source.materials) {
21443
+ if (![...material.textureSources?.values() ?? []].some(
21444
+ (source) => resolveRenderTargetMaterialSource(source)?.target === current().target
21445
+ ))
21446
+ continue;
21447
+ let handles = selfSampling.get(row.renderableIndex);
21448
+ if (handles === void 0) {
21449
+ handles = /* @__PURE__ */ new Set();
21450
+ selfSampling.set(row.renderableIndex, handles);
21451
+ }
21452
+ handles.add(material.materialHandle ?? 0);
21453
+ }
21454
+ }
21455
+ const captureContext = {
21456
+ ...internal,
21457
+ camera: current().faceCamera,
21458
+ targetW: current().physical.descriptor.width,
21459
+ targetH: current().physical.descriptor.height,
21460
+ dispatch: (internal.captureDispatch ?? internal.dispatch).filter(
21461
+ (entry) => !selfSampling.get(entry.renderableIndex)?.has(entry.materialHandle)
21462
+ ),
21463
+ foldDispatchPlan: null,
21464
+ // Cube faces are raw scene captures, not display-camera HDR output.
21465
+ // Select the PSO against the actual target attachment so an LDR
21466
+ // cube target is rendered by a compatible forward pipeline.
21467
+ tonemapActive: false,
21468
+ skyboxActive: false,
21469
+ transparentColorFormat: initial.physical.descriptor.format,
21470
+ msaaActive: initial.physical.descriptor.sampleCount === 4,
21471
+ viewBindGroupDynamicOffset: current().viewBindGroupDynamicOffset,
21472
+ geometryColorView: captureColor.value,
21473
+ geometryDepthView: captureDepth.value,
21474
+ geometryColorResolveView: captureResolveView,
21475
+ splitLdrSprite: false,
21476
+ ldrSpritePassView: null
21477
+ };
21478
+ delete captureContext.gpuDrivenDrawKeys;
21479
+ delete captureContext.gpuDrivenStandardPbrFrameResources;
21480
+ encodeMainPass(
21481
+ captureContext,
21482
+ pass,
21483
+ { LightMode: ["Forward"] },
21484
+ {
21485
+ colorViews: [captureColor.value],
21486
+ colorFormats: [initial.physical.descriptor.format],
21487
+ depthView: captureDepth.value,
21488
+ passKind: "forward",
21489
+ clearColor: current().physical.descriptor.shape === "2d" ? current().faceCamera.clearColor : [0, 0, 0, 1]
21490
+ }
21491
+ );
21492
+ }
21493
+ });
21494
+ if (!added.ok) return added;
21130
21495
  }
21131
- return {
21132
- currentTexture: currentTextureResult.value,
21133
- view: viewResult.value,
21134
- targetW: internals.canvas.width | 0,
21135
- targetH: internals.canvas.height | 0
21136
- };
21137
- }
21138
- function resolveShadowMapSize(internals, lights) {
21139
- if (lights.cascadeCount === void 0) return void 0;
21140
- const requested = lights.shadowMapSize;
21141
- if (!(requested !== void 0 && requested > 0)) return requested;
21142
- const cascades = Math.max(1, Math.min(4, Math.round(lights.cascadeCount ?? 1)));
21143
- const atlasGrid = resolveDirectionalShadowAtlasGrid(cascades);
21144
- const maxDimension = internals.device.limits.maxTextureDimension2D;
21145
- if (!(maxDimension > 0)) return Math.floor(requested);
21146
- const depthTextureDimension = internals.device.caps?.backendKind === "wgpu-webgl2" ? Math.max(1, Math.floor(maxDimension / 2)) : maxDimension;
21147
- const maxPerTile = Math.max(
21148
- 1,
21149
- Math.floor(depthTextureDimension / Math.max(atlasGrid.columns, atlasGrid.rows))
21150
- );
21151
- return Math.max(1, Math.min(Math.floor(requested), maxPerTile));
21152
- }
21153
- function resolveSpotShadowMapSize(internals, lights) {
21154
- const requested = lights.spot.find(
21155
- (spot) => spot.shadowAtlasTile >= 0 && spot.lightViewProj !== void 0
21156
- )?.mapSize;
21157
- if (!(requested !== void 0 && requested > 0)) return requested;
21158
- const maxDimension = internals.device.limits.maxTextureDimension2D;
21159
- if (!(maxDimension > 0)) return Math.floor(requested);
21160
- const maxPerTile = Math.max(1, Math.floor(maxDimension / 2));
21161
- return Math.max(1, Math.min(Math.floor(requested), maxPerTile));
21496
+ return ok$1(void 0);
21162
21497
  }
21163
21498
 
21164
21499
  // src/assembly/renderer-frame-transaction.ts
@@ -22195,169 +22530,6 @@ function isMotionBlurTemporalDemand(motionBlur) {
22195
22530
  targetFps: motionBlur.targetFps ?? 60
22196
22531
  });
22197
22532
  }
22198
- function renderTargetMipCount(work) {
22199
- const { descriptor } = work.physical;
22200
- return descriptor.mipLevels === 1 ? 1 : Math.floor(Math.log2(Math.max(descriptor.width, descriptor.height))) + 1;
22201
- }
22202
- function addCubeCaptureGraphPasses(builder, state) {
22203
- for (let index = 0; index < state.work.length; index += 1) {
22204
- const slot = index;
22205
- const initial = state.work[slot];
22206
- if (initial === void 0) continue;
22207
- const current = () => state.work[slot] ?? initial;
22208
- const texture = builder.importTexture(
22209
- `cube-capture.${slot}.texture`,
22210
- {
22211
- format: initial.physical.descriptor.format,
22212
- size: {
22213
- width: initial.physical.descriptor.width,
22214
- height: initial.physical.descriptor.height,
22215
- depthOrArrayLayers: initial.physical.descriptor.sampleCount === 4 ? 1 : 6
22216
- },
22217
- mipLevelCount: initial.physical.descriptor.sampleCount === 4 ? 1 : renderTargetMipCount(initial),
22218
- sampleCount: initial.physical.descriptor.sampleCount,
22219
- dimension: "2d",
22220
- usage: 16 | 4 | 1
22221
- },
22222
- () => current().physical.colorTextures[current().faceIndex] ?? initial.physical.texture
22223
- );
22224
- if (!texture.ok) return texture;
22225
- const color = builder.importView(
22226
- texture.value,
22227
- {
22228
- label: `cube-capture.${slot}.color`,
22229
- dimension: "2d",
22230
- baseMipLevel: 0,
22231
- mipLevelCount: 1,
22232
- baseArrayLayer: initial.physical.descriptor.sampleCount === 4 ? 0 : initial.faceIndex,
22233
- arrayLayerCount: 1
22234
- },
22235
- () => current().physical.faceViews[current().faceIndex] ?? initial.physical.faceViews[initial.faceIndex] ?? initial.physical.view
22236
- );
22237
- if (!color.ok) return color;
22238
- const depthTexture = builder.importTexture(
22239
- `cube-capture.${slot}.depth-texture`,
22240
- {
22241
- format: "depth24plus-stencil8",
22242
- size: {
22243
- width: initial.physical.descriptor.width,
22244
- height: initial.physical.descriptor.height,
22245
- depthOrArrayLayers: initial.physical.descriptor.sampleCount === 4 ? 1 : 6
22246
- },
22247
- mipLevelCount: 1,
22248
- sampleCount: initial.physical.descriptor.sampleCount,
22249
- dimension: "2d",
22250
- usage: 16
22251
- },
22252
- () => current().physical.depthTextures[current().faceIndex]
22253
- );
22254
- if (!depthTexture.ok) return depthTexture;
22255
- const depth = builder.importView(
22256
- depthTexture.value,
22257
- {
22258
- label: `cube-capture.${slot}.depth`,
22259
- dimension: "2d",
22260
- baseArrayLayer: initial.physical.descriptor.sampleCount === 4 ? 0 : initial.faceIndex,
22261
- arrayLayerCount: 1
22262
- },
22263
- () => current().physical.depthViews[current().faceIndex]
22264
- );
22265
- if (!depth.ok) return depth;
22266
- const resolveTexture = initial.physical.descriptor.sampleCount === 4 ? builder.importTexture(
22267
- `cube-capture.${slot}.resolve-texture`,
22268
- {
22269
- format: initial.physical.descriptor.format,
22270
- size: {
22271
- width: initial.physical.descriptor.width,
22272
- height: initial.physical.descriptor.height,
22273
- depthOrArrayLayers: 6
22274
- },
22275
- mipLevelCount: renderTargetMipCount(initial),
22276
- sampleCount: 1,
22277
- dimension: "2d",
22278
- usage: 16 | 4 | 1
22279
- },
22280
- () => current().physical.resolveTexture ?? initial.physical.resolveTexture ?? initial.physical.texture
22281
- ) : void 0;
22282
- if (resolveTexture !== void 0 && !resolveTexture.ok) return resolveTexture;
22283
- const resolve = resolveTexture === void 0 ? void 0 : builder.importView(
22284
- resolveTexture.value,
22285
- {
22286
- label: `cube-capture.${slot}.resolve`,
22287
- dimension: "2d",
22288
- baseMipLevel: 0,
22289
- mipLevelCount: 1,
22290
- baseArrayLayer: initial.faceIndex,
22291
- arrayLayerCount: 1
22292
- },
22293
- () => current().physical.resolveFaceViews[current().faceIndex] ?? initial.physical.resolveFaceViews[initial.faceIndex] ?? initial.physical.resolveView
22294
- );
22295
- if (resolve !== void 0 && !resolve.ok) return resolve;
22296
- const added = builder.addRasterPass(`cube-capture-face.${slot}`, {
22297
- accesses: [
22298
- { resource: color.value, usage: "color-attachment" },
22299
- { resource: depth.value, usage: "depth-stencil-write" },
22300
- ...resolve === void 0 ? [] : [{ resource: resolve.value, usage: "color-attachment" }]
22301
- ],
22302
- colorAttachments: [
22303
- {
22304
- view: color.value,
22305
- ...resolve === void 0 ? {} : { resolveTarget: resolve.value },
22306
- loadOp: "clear",
22307
- storeOp: "store",
22308
- clearValue: () => {
22309
- return { r: 0, g: 0, b: 0, a: 1 };
22310
- }
22311
- }
22312
- ],
22313
- depthStencilAttachment: {
22314
- view: depth.value,
22315
- depthClearValue: 1,
22316
- depthLoadOp: "clear",
22317
- depthStoreOp: "store",
22318
- stencilClearValue: 0,
22319
- stencilLoadOp: "clear",
22320
- stencilStoreOp: "store"
22321
- },
22322
- encode: ({ pass, frame, resources }) => {
22323
- const internal = frame;
22324
- const captureColor = resources.textureView(color.value);
22325
- if (!captureColor.ok) return;
22326
- const captureDepth = resources.textureView(depth.value);
22327
- if (!captureDepth.ok) return;
22328
- const captureResolve = resolve === void 0 ? void 0 : resources.textureView(resolve.value);
22329
- if (resolve !== void 0 && (captureResolve === void 0 || !captureResolve.ok)) return;
22330
- const captureResolveView = captureResolve?.ok ? captureResolve.value : null;
22331
- const captureContext = {
22332
- ...internal,
22333
- camera: current().faceCamera,
22334
- // Cube faces are raw scene captures, not display-camera HDR output.
22335
- // Select the PSO against the actual target attachment so an LDR
22336
- // cube target is rendered by a compatible forward pipeline.
22337
- tonemapActive: false,
22338
- skyboxActive: false,
22339
- transparentColorFormat: initial.physical.descriptor.format,
22340
- msaaActive: initial.physical.descriptor.sampleCount === 4,
22341
- viewBindGroupDynamicOffset: current().viewBindGroupDynamicOffset,
22342
- geometryColorView: captureColor.value,
22343
- geometryDepthView: captureDepth.value,
22344
- geometryColorResolveView: captureResolveView,
22345
- splitLdrSprite: false,
22346
- ldrSpritePassView: null
22347
- };
22348
- encodeMainPass(captureContext, pass, void 0, {
22349
- colorViews: [captureColor.value],
22350
- colorFormats: [initial.physical.descriptor.format],
22351
- depthView: captureDepth.value,
22352
- passKind: "forward",
22353
- clearColor: [0, 0, 0, 1]
22354
- });
22355
- }
22356
- });
22357
- if (!added.ok) return added;
22358
- }
22359
- return ok$1(void 0);
22360
- }
22361
22533
  function addReflectionProbeGraphPasses(builder, state, environmentCube) {
22362
22534
  const accesses = [];
22363
22535
  for (const work of state.work) {
@@ -23581,7 +23753,7 @@ function ensureCompiledFrameGraph(internals, frameState, pipelineState, camera,
23581
23753
  // renderer-owned and read dynamically by the compiled pass, so a page
23582
23754
  // rotation must not invalidate the graph or its cached bind groups.
23583
23755
  occlusionQuery: occlusion === void 0 ? void 0 : { active: true, sampleCount: occlusion.sampleCount },
23584
- cubeCaptureSlots: cubeCaptureState?.work.length ?? 0,
23756
+ cubeCaptureSlots: cubeCaptureState?.work.map((work) => work.physical.descriptor),
23585
23757
  reflectionProbeSlots: cubeCaptureState?.reflectionProbes?.work.map((work) => [
23586
23758
  work.probeIndex,
23587
23759
  work.rawCaptureFace ?? -1,
@@ -23765,7 +23937,7 @@ function ensureCompiledFrameGraph(internals, frameState, pipelineState, camera,
23765
23937
  environmentCube
23766
23938
  );
23767
23939
  if (!reflectionProbes.ok) return reflectionProbes;
23768
- return cubeCaptureState === void 0 ? ok$1(void 0) : addCubeCaptureGraphPasses(builder, cubeCaptureState);
23940
+ return cubeCaptureState === void 0 ? ok$1(void 0) : addTargetCaptureGraphPasses(builder, cubeCaptureState);
23769
23941
  },
23770
23942
  hasFeature: (identity) => projectedFeaturePlans.value.some((execution) => execution.featureIdentity === identity),
23771
23943
  hasFeatureWork: (identity, placement) => projectedFeaturePlans.value.some(
@@ -24822,7 +24994,7 @@ function gpuDrivenMeshesForFrame(internals, pipelineState, worlds, scene) {
24822
24994
  const asset = resolveAssetHandle(world, sharedHandle);
24823
24995
  if (asset.ok) {
24824
24996
  const lodMeshes = slot.snapshot.lods?.map(
24825
- (lod) => internals.assets.lookup(lod.mesh)
24997
+ (lod) => renderAssetByGuid(world, internals.assets, lod.mesh)
24826
24998
  );
24827
24999
  const resolvedLodMeshes = lodMeshes?.every((lod) => lod?.kind === "mesh") === true ? lodMeshes : void 0;
24828
25000
  const resident = internals.gpuStore.ensureResident(
@@ -24883,6 +25055,18 @@ function prepareCubeCapture(internals, input, displayCamera) {
24883
25055
  viewBindGroupDynamicOffset: (CUBE_CAPTURE_VIEW_SLOT_BASE + physicalWork.length) * VIEW_UNIFORM_SLOT_STRIDE
24884
25056
  });
24885
25057
  }
25058
+ for (const camera of input.auxiliaryCameras) {
25059
+ if (camera.target === void 0) continue;
25060
+ const physical = internals.getRenderTargetPhysical?.(camera.target);
25061
+ if (physical?.descriptor.shape !== "2d") continue;
25062
+ physicalWork.push({
25063
+ target: camera.target,
25064
+ faceIndex: 0,
25065
+ physical,
25066
+ faceCamera: camera,
25067
+ viewBindGroupDynamicOffset: (CUBE_CAPTURE_VIEW_SLOT_BASE + 6) * VIEW_UNIFORM_SLOT_STRIDE
25068
+ });
25069
+ }
24886
25070
  input.state.work = physicalWork;
24887
25071
  return physicalWork;
24888
25072
  }
@@ -25270,7 +25454,7 @@ function frameClockSample(world, worlds, camera, sampleTimeSeconds) {
25270
25454
  const owner = worlds[camera.worldId ?? 0] ?? world;
25271
25455
  const invalidSampleTime = sampleTimeSeconds !== void 0 && !Number.isFinite(sampleTimeSeconds);
25272
25456
  try {
25273
- const clock = owner.getResource(Time);
25457
+ const clock = renderTime(owner);
25274
25458
  return {
25275
25459
  deltaSeconds: Number.isFinite(clock.delta) ? Math.max(0, clock.delta) : 0,
25276
25460
  // Keep the raw host sample even when ECS accepted only a clamped
@@ -26487,7 +26671,7 @@ function recordFrame(internals, world, cameras, lights, renderables, transparent
26487
26671
  }
26488
26672
  acknowledgeRenderFeatureSubmission(getRenderFeatureGraphState(internals).plans);
26489
26673
  }
26490
- if (cubeCapture !== void 0 && cubeCaptureWork.length > 0) {
26674
+ if (cubeCapture !== void 0 && cubeCaptureWork.some((work) => work.physical.descriptor.shape === "cube")) {
26491
26675
  const completed = cubeCapture.scheduler.completeSubmission(submitted, completion);
26492
26676
  if (!completed.ok) internals.errorRegistry.fire(completed.error);
26493
26677
  }
@@ -27393,7 +27577,6 @@ function createRenderSystemRecovery(deps) {
27393
27577
  if (pendingOutput !== void 0) retireAutoExposureGpuResources(pendingOutput);
27394
27578
  candidateFrameState.pendingAutoExposureGpuResources = void 0;
27395
27579
  for (const work of setupWorks) work.discard();
27396
- setupWorks.length = 0;
27397
27580
  const graph = candidateFrameState.compiledFrameGraph;
27398
27581
  candidateFrameState.compiledFrameGraph = null;
27399
27582
  candidateFrameState.perFrameGraph = null;
@@ -27639,7 +27822,7 @@ function createRenderSystemRecovery(deps) {
27639
27822
  cloudHistory: seed.frame.cloudLayer !== void 0
27640
27823
  });
27641
27824
  const featureFrame = runRenderFeatureFrame(candidateFeatureHost, {
27642
- worlds: seed.worlds,
27825
+ worlds: seed.worlds.filter((world) => !("resolveAsset" in world)),
27643
27826
  owner: seed.resourceOwner,
27644
27827
  frameNumber: candidateFrameState.frameNumber,
27645
27828
  selectedCamera: camera,
@@ -29113,11 +29296,11 @@ var ReflectionProbeRecordOwner = class {
29113
29296
  prefilterGroup0Bgl: cache.prefilterGroup0Bgl
29114
29297
  };
29115
29298
  }
29116
- createCubeSet(label, size, mipCount2 = PREFILTER_MIP_LEVELS) {
29299
+ createCubeSet(label, size, mipCount = PREFILTER_MIP_LEVELS) {
29117
29300
  const texture = this.internals.device.createTexture({
29118
29301
  label,
29119
29302
  size: { width: size, height: size, depthOrArrayLayers: 6 },
29120
- mipLevelCount: mipCount2,
29303
+ mipLevelCount: mipCount,
29121
29304
  sampleCount: 1,
29122
29305
  dimension: "2d",
29123
29306
  format: this.outputFormat,
@@ -29130,7 +29313,7 @@ var ReflectionProbeRecordOwner = class {
29130
29313
  label: `${label}-cube`,
29131
29314
  dimension: "cube",
29132
29315
  baseMipLevel: 0,
29133
- mipLevelCount: mipCount2,
29316
+ mipLevelCount: mipCount,
29134
29317
  arrayLayerCount: 6
29135
29318
  });
29136
29319
  if (!cubeView.ok) {
@@ -29139,7 +29322,7 @@ var ReflectionProbeRecordOwner = class {
29139
29322
  }
29140
29323
  const faceViews = [];
29141
29324
  const mipViews = [];
29142
- for (let mip = 0; mip < mipCount2; mip += 1) {
29325
+ for (let mip = 0; mip < mipCount; mip += 1) {
29143
29326
  const faces = [];
29144
29327
  for (let face = 0; face < 6; face += 1) {
29145
29328
  const view = this.internals.device.createTextureView(texture.value, {
@@ -29674,6 +29857,8 @@ function preparedHandle(runtime, caches, world, guid, brand) {
29674
29857
  const key = `${brand}:${guid.toLowerCase()}`;
29675
29858
  const cached = handles.get(key);
29676
29859
  if (cached !== void 0) return cached;
29860
+ if ("resolveAsset" in world)
29861
+ return world.handleForGuid(guid);
29677
29862
  const asset = runtime.assets.lookup(guid);
29678
29863
  if (asset === void 0) return void 0;
29679
29864
  const handle = world.allocSharedRef(brand, asset);
@@ -29682,7 +29867,7 @@ function preparedHandle(runtime, caches, world, guid, brand) {
29682
29867
  }
29683
29868
  function preparedMaterialBindings(runtime, caches, worlds, materialShaderId, worldIndex, materialGuid, layout, skylightResources) {
29684
29869
  const world = worlds[worldIndex];
29685
- const material = runtime.assets.lookup(materialGuid);
29870
+ const material = world === void 0 ? void 0 : renderAssetByGuid(world, runtime.assets, materialGuid);
29686
29871
  const pipelineState = runtime.getPipelineState();
29687
29872
  if (world === void 0 || material?.kind !== "material" || pipelineState === null) {
29688
29873
  return err(new Error("prepared material asset is unavailable"));
@@ -29799,7 +29984,6 @@ function preparedMaterialBindings(runtime, caches, worlds, materialShaderId, wor
29799
29984
  prefilterView: fallback.prefilterView,
29800
29985
  prefilterSampler: fallback.sampler,
29801
29986
  brdfLutView: fallback.brdfLutView,
29802
- brdfLutSampler: fallback.sampler,
29803
29987
  intensityBuffer: fallback.intensityBuffer
29804
29988
  },
29805
29989
  transmissionBackdropAvailable(runtime.device.limits.maxSampledTexturesPerShaderStage) ? void 0 : null
@@ -32263,56 +32447,6 @@ var RenderScene = class {
32263
32447
  return slot === void 0 ? worldBounds(snapshot) : this.cullingWorldBoundsAt(slot);
32264
32448
  }
32265
32449
  };
32266
- var RENDERABLE_SOURCE_COMPONENTS = [
32267
- ChildOf,
32268
- MeshFilter,
32269
- MeshRenderer,
32270
- Instances,
32271
- SpriteInstances,
32272
- SpriteRegionOverride,
32273
- Skin,
32274
- Layer,
32275
- Visibility,
32276
- MorphWeights,
32277
- Points,
32278
- Lines,
32279
- SortKey
32280
- ];
32281
- function createGlobalTransformChangeQuery(world) {
32282
- const result = world.query({ read: [GlobalTransform], changed: [GlobalTransform] });
32283
- if (!result.ok) throw result.error;
32284
- const query = result.value;
32285
- for (const _span of query.spans().unwrap()) {
32286
- }
32287
- return query;
32288
- }
32289
- function createRenderSourceState(world) {
32290
- const components = [...RENDERABLE_SOURCE_COMPONENTS, RuntimeMaterialValue, RuntimeMeshVertices];
32291
- const projection = createStateProjection(world, components, [
32292
- ...components,
32293
- Transform,
32294
- GlobalTransform
32295
- ]);
32296
- const entities = /* @__PURE__ */ new Map();
32297
- const contentHandles = /* @__PURE__ */ new Map();
32298
- const batch = projection.read();
32299
- for (const index of batch.indices) {
32300
- const entity = projection.entity(index);
32301
- if (entity !== void 0) {
32302
- entities.set(index, entity);
32303
- const handles = [];
32304
- const material = world.hasComponent(entity, RuntimeMaterialValue) ? world.get(entity, RuntimeMaterialValue) : void 0;
32305
- const mesh = world.hasComponent(entity, RuntimeMeshVertices) ? world.get(entity, RuntimeMeshVertices) : void 0;
32306
- if (material?.ok) handles.push(Number(material.value.asset));
32307
- if (mesh?.ok) handles.push(Number(mesh.value.asset));
32308
- if (handles.length > 0) contentHandles.set(index, handles);
32309
- }
32310
- }
32311
- return { projection, entities, contentHandles, batch };
32312
- }
32313
- function isRenderableMember(world, entity) {
32314
- return world.hasComponent(entity, MeshRenderer) && world.hasComponent(entity, Transform) && world.hasComponent(entity, MeshFilter);
32315
- }
32316
32450
  function sourceMembershipChanged(world, slot) {
32317
32451
  const entity = slot.entityKey;
32318
32452
  const snapshot = slot.snapshot;
@@ -32593,6 +32727,9 @@ var PersistentRenderScene = class {
32593
32727
  compositionSlots() {
32594
32728
  return this.composition?.projection.slotsSnapshot() ?? [];
32595
32729
  }
32730
+ compositionSlot(worldId, entityKey) {
32731
+ return this.composition?.projection.slot(worldId, entityKey);
32732
+ }
32596
32733
  shadowCasterProjection() {
32597
32734
  return this.shadowProjection;
32598
32735
  }
@@ -32799,11 +32936,81 @@ var PersistentRenderScene = class {
32799
32936
  reflectionProbeProjection() {
32800
32937
  return this.reflectionProbes.snapshot();
32801
32938
  }
32939
+ consumePublication(input) {
32940
+ const { resources, packet, frame } = input;
32941
+ let entry = this.composition;
32942
+ if (entry === void 0 || packet.baseline) {
32943
+ this.invalidate();
32944
+ const projection = new RenderScene();
32945
+ entry = {
32946
+ token: {},
32947
+ worlds: [resources],
32948
+ projection,
32949
+ topology: new BatchTopology(),
32950
+ transmissionDemand: new PersistentTransmissionDemandProjection(),
32951
+ hiddenEntityReports: [],
32952
+ worldKeys: this.visibilityWorldKeysFor([resources]),
32953
+ readVersions: [],
32954
+ leaseIdentities: [],
32955
+ transformQueries: [],
32956
+ sourceStates: [],
32957
+ dispatchBySlot: /* @__PURE__ */ new Map(),
32958
+ dispatchRevision: 0,
32959
+ dispatchCache: void 0,
32960
+ skinConsumersByJoint: /* @__PURE__ */ new Map(),
32961
+ pendingRenderableEntitiesByWorld: [],
32962
+ unavailableSlots: /* @__PURE__ */ new Set(),
32963
+ catalogEpoch: 0,
32964
+ probeProjection: new ProbeBlendSceneProjection(),
32965
+ probeObjects: void 0,
32966
+ temporalDemanded: false,
32967
+ gpuDrivenSceneRequired: true
32968
+ };
32969
+ this.composition = entry;
32970
+ this.fullRebuilds++;
32971
+ this.lastResyncReason = "attach";
32972
+ }
32973
+ this.worldEntitiesScanned = 0;
32974
+ this.sceneTableUploadBytes = 0;
32975
+ const removedDemand = [];
32976
+ for (const operation of input.operations) {
32977
+ if (operation.kind !== "remove" && operation.snapshot === void 0) continue;
32978
+ const previous = entry.projection.slot(0, operation.entityKey);
32979
+ for (let index = 0; index < (previous?.snapshot.materials.length ?? 0); index++)
32980
+ removedDemand.push({ kind: "remove", key: `0:${operation.entityKey}:${index}` });
32981
+ }
32982
+ const delta = entry.projection.apply(input.operations);
32983
+ for (const removed of delta.removedSlots) {
32984
+ entry.dispatchBySlot.delete(removed.slot);
32985
+ this.stableSlotByEntity.delete(worldEntityKey(entry.worldKeys[0] ?? 0, removed.entityKey));
32986
+ }
32987
+ for (const recreated of delta.recreatedSlots) entry.dispatchBySlot.delete(recreated.slot);
32988
+ for (const [slot, dispatch] of dispatchEntriesBySlot(frame, entry.projection))
32989
+ entry.dispatchBySlot.set(slot, dispatch);
32990
+ if (frame.renderables.length || packet.removed.length) {
32991
+ entry.dispatchRevision++;
32992
+ entry.dispatchCache = void 0;
32993
+ this.visibilityFacets.clear();
32994
+ this.invalidateActiveEntityRevision();
32995
+ }
32996
+ for (const slot of [...delta.createdSlots, ...delta.updatedSlots, ...delta.recreatedSlots])
32997
+ this.stableSlotByEntity.set(worldEntityKey(entry.worldKeys[0] ?? 0, slot.entityKey), slot);
32998
+ entry.transmissionDemand.apply([
32999
+ ...removedDemand,
33000
+ ...transmissionDemandOperations(frame.renderables)
33001
+ ]);
33002
+ entry.topology.apply(delta);
33003
+ this.syncGpuOwner(entry.token, entry.projection, delta);
33004
+ if (input.operations.length) this.deltaFrames++;
33005
+ else this.noChangeFrames++;
33006
+ this.transformUpdates += delta.updated;
33007
+ return this.deriveFramePlan(entry, frame);
33008
+ }
32802
33009
  extractComposition(worlds, owner, catalogEpoch, buildCandidateFrame, leases) {
32803
33010
  this.worldEntitiesScanned = 0;
32804
33011
  this.sceneTableUploadBytes = 0;
32805
33012
  const entry = this.composition;
32806
- const sameWorldSet = entry !== void 0 && entry.worlds.length === worlds.length && entry.worlds.every((world) => worlds.includes(world));
33013
+ const sameWorldSet = entry !== void 0 && entry.worlds.length === worlds.length && entry.worlds.every((world) => worlds.some((local) => local === world));
32807
33014
  const worldOrderChanged = entry !== void 0 && sameWorldSet && entry.worlds.some((world, index) => world !== worlds[index]);
32808
33015
  const leaseSetPreserved = entry !== void 0 && leases !== void 0 && leases.length === worlds.length && entry.leaseIdentities.length === leases.length && entry.leaseIdentities.every(
32809
33016
  (identity) => leases.some((lease) => lease.worldIdentity === identity)
@@ -33452,7 +33659,7 @@ var PersistentRenderScene = class {
33452
33659
  }
33453
33660
  reconcileComposition(worlds, _owner, catalogEpoch, buildCandidateFrame, leases, preserveVisibilityOnReorder = false) {
33454
33661
  const previousEntry = this.composition;
33455
- const sourceStates = worlds.map(createRenderSourceState);
33662
+ const sourceStates = worlds.map((world) => createRenderSourceState(world));
33456
33663
  const candidateFrame = buildCandidateFrame({
33457
33664
  kind: "partial",
33458
33665
  entitiesByWorld: sourceStates.map((source) => new Set(source.entities.values()))
@@ -33484,7 +33691,11 @@ var PersistentRenderScene = class {
33484
33691
  const renderables = candidateFrame.renderables;
33485
33692
  const projection = previousEntry?.projection ?? new RenderScene();
33486
33693
  if (previousEntry !== void 0) {
33487
- projection.remapWorlds(previousEntry.worlds.map((world) => worlds.indexOf(world)));
33694
+ projection.remapWorlds(
33695
+ previousEntry.worlds.map(
33696
+ (world) => worlds.indexOf(world)
33697
+ )
33698
+ );
33488
33699
  }
33489
33700
  const desired = new Set(
33490
33701
  renderables.map((snapshot) => identityKey(snapshot.worldId, snapshot.entityKey))
@@ -33529,9 +33740,9 @@ var PersistentRenderScene = class {
33529
33740
  for (const snapshot of stableCandidateFrame.renderables) {
33530
33741
  if (snapshot.skinJointEntities !== void 0) addSkinConsumer(skinConsumersByJoint, snapshot);
33531
33742
  }
33532
- const token2 = previousEntry?.token ?? {};
33743
+ const token = previousEntry?.token ?? {};
33533
33744
  const entry = {
33534
- token: token2,
33745
+ token,
33535
33746
  worlds: [...worlds],
33536
33747
  projection,
33537
33748
  topology,
@@ -33558,7 +33769,7 @@ var PersistentRenderScene = class {
33558
33769
  projection.setTemporalTracking(entry.temporalDemanded);
33559
33770
  this.projectReflectionProbes(candidateFrame.reflectionProbes ?? []);
33560
33771
  this.projectProbes(entry, candidateFrame);
33561
- this.syncGpuOwner(token2, projection, delta);
33772
+ this.syncGpuOwner(token, projection, delta);
33562
33773
  if (previousEntry === void 0) this.fullRebuilds += 1;
33563
33774
  this.lastResyncReason = "attach";
33564
33775
  const materialized = projection.materialize();
@@ -33602,7 +33813,7 @@ var PersistentRenderScene = class {
33602
33813
  const candidateFrame = {
33603
33814
  ...resourceFrame,
33604
33815
  hiddenEntityReports: entry.hiddenEntityReports,
33605
- visibilityStats: { explicitlyHidden: entry.hiddenEntityReports.length },
33816
+ visibilityStats: entry.sourceStates.length === 0 ? resourceFrame.visibilityStats : { explicitlyHidden: entry.hiddenEntityReports.length },
33606
33817
  dispatch
33607
33818
  };
33608
33819
  entry.temporalDemanded = frameDemandsTemporal(candidateFrame);
@@ -33940,12 +34151,12 @@ function assertExtent(extent) {
33940
34151
  function mipExtent(value, level) {
33941
34152
  return Math.max(1, Math.floor(value / 2 ** level));
33942
34153
  }
33943
- function estimateTransmissionBackdropBytes(extent, mipCount2, format = "rgba16float") {
34154
+ function estimateTransmissionBackdropBytes(extent, mipCount, format = "rgba16float") {
33944
34155
  assertExtent(extent);
33945
- assertNonNegativeInteger("transmission inspection mipCount", mipCount2);
33946
- if (format !== "rgba16float" || mipCount2 === 0) return 0;
34156
+ assertNonNegativeInteger("transmission inspection mipCount", mipCount);
34157
+ if (format !== "rgba16float" || mipCount === 0) return 0;
33947
34158
  let bytes2 = 0;
33948
- for (let level = 0; level < mipCount2; level += 1) {
34159
+ for (let level = 0; level < mipCount; level += 1) {
33949
34160
  bytes2 += mipExtent(extent.width, level) * mipExtent(extent.height, level);
33950
34161
  }
33951
34162
  return bytes2 * RGBA16FLOAT_BYTES_PER_PIXEL;
@@ -33971,9 +34182,9 @@ function inspectTransmission(input) {
33971
34182
  assertExtent(input.extent);
33972
34183
  const format = input.format ?? "rgba16float";
33973
34184
  const resourcePresent = input.resourcePresent ?? input.lastKnownGood;
33974
- const mipCount2 = resourcePresent ? input.mipCount ?? input.topology.mipCount + 1 : 0;
33975
- assertNonNegativeInteger("transmission inspection mipCount", mipCount2);
33976
- const bytes2 = resourcePresent ? input.bytes ?? estimateTransmissionBackdropBytes(input.extent, mipCount2, format) : 0;
34185
+ const mipCount = resourcePresent ? input.mipCount ?? input.topology.mipCount + 1 : 0;
34186
+ assertNonNegativeInteger("transmission inspection mipCount", mipCount);
34187
+ const bytes2 = resourcePresent ? input.bytes ?? estimateTransmissionBackdropBytes(input.extent, mipCount, format) : 0;
33977
34188
  assertNonNegativeInteger("transmission inspection bytes", bytes2);
33978
34189
  const copyCount = resourcePresent ? input.topology.copyCount : 0;
33979
34190
  if (copyCount !== (resourcePresent ? 1 : 0)) {
@@ -33984,7 +34195,7 @@ function inspectTransmission(input) {
33984
34195
  needsRoughMips: active && input.demand.needsRoughMips,
33985
34196
  extent: Object.freeze({ ...input.extent }),
33986
34197
  format,
33987
- mipCount: mipCount2,
34198
+ mipCount,
33988
34199
  bytes: bytes2,
33989
34200
  copyCount,
33990
34201
  transmissionDrawCount: input.transmissionDrawCount ?? 0,
@@ -35315,9 +35526,10 @@ function createRenderSystem(internals) {
35315
35526
  }
35316
35527
  persistentRenderScene.detach(world);
35317
35528
  },
35318
- draw(worlds, opts, renderReadLeases, timingCapture) {
35529
+ draw(worlds, opts, renderReadLeases, timingCapture, publication) {
35319
35530
  const composition = canonicalizeWorldComposition(worlds, opts, renderReadLeases);
35320
- const compositionWorlds = composition.worlds;
35531
+ const sourceWorlds = composition.worlds;
35532
+ const compositionWorlds = publication === void 0 ? sourceWorlds : [publication.resources];
35321
35533
  const compositionLeases = composition.leases;
35322
35534
  preparedWorlds = compositionWorlds;
35323
35535
  const profileSession = internals.profiler?.activeSession();
@@ -35340,19 +35552,41 @@ function createRenderSystem(internals) {
35340
35552
  if (frameState.installedPipelineHandle !== lastBuiltPipelineHandle) {
35341
35553
  resetRenderFeatureGraphState(internals);
35342
35554
  lastBuiltPipelineHandle = frameState.installedPipelineHandle;
35343
- persistentRenderScene.invalidate();
35555
+ if (publication === void 0) persistentRenderScene.invalidate();
35344
35556
  }
35345
35557
  dispatchCounts.unlit = 0;
35346
35558
  const resourceWorld = compositionWorlds[resourceOwner];
35347
35559
  let frame;
35348
35560
  try {
35349
35561
  frame = runProfiledRenderPhase(profileSession, "extract", () => {
35562
+ if (publication !== void 0) {
35563
+ for (const handle of [
35564
+ ...publication.packet.invalidatedAssets,
35565
+ ...publication.packet.retiredAssets
35566
+ ]) {
35567
+ internals.gpuStore.invalidateMesh(handle, publication.resources);
35568
+ internals.gpuStore.evictTexture(
35569
+ handle,
35570
+ publication.resources
35571
+ );
35572
+ }
35573
+ return persistentRenderScene.consumePublication(
35574
+ preparePublicationGeometry(
35575
+ publication,
35576
+ persistentRenderScene,
35577
+ internals.getPipelineState()?.skinPaletteAllocator,
35578
+ internals.assets,
35579
+ instanceCollections,
35580
+ internals.device.caps.storageBuffer ? internals.getMaterialShaderArtifact : void 0
35581
+ )
35582
+ );
35583
+ }
35350
35584
  return persistentRenderScene.extractComposition(
35351
- compositionWorlds,
35585
+ sourceWorlds,
35352
35586
  { cameraOwner, resourceOwner },
35353
35587
  internals.assets.catalogEpoch,
35354
35588
  (renderables2) => extractFrames(
35355
- compositionWorlds,
35589
+ sourceWorlds,
35356
35590
  {
35357
35591
  cameraOwner,
35358
35592
  resourceOwner,
@@ -35362,18 +35596,7 @@ function createRenderSystem(internals) {
35362
35596
  internals.getPipelineState(),
35363
35597
  persistentRenderScene.materialSnapshotCacheStore(),
35364
35598
  {
35365
- ...internals.device.caps.backendKind === "null" ? {} : {
35366
- materialContext: {
35367
- backend: internals.device.caps.backendKind === "wgpu-webgl2" ? "webgl2" : internals.device.caps.backendKind,
35368
- capability: internals.device.caps.storageBuffer ? "storage-buffer" : "uniform-fallback",
35369
- pipeline: "forward",
35370
- geometry: "mesh",
35371
- pass: "forward",
35372
- profile: "forgeax-material-wgsl-v1",
35373
- toolchain: "naga-oil",
35374
- instrumentation: "none"
35375
- }
35376
- },
35599
+ ...renderMaterialContext(internals.device.caps),
35377
35600
  cull: "none",
35378
35601
  retainHidden: true,
35379
35602
  renderables: renderables2,
@@ -35396,6 +35619,7 @@ function createRenderSystem(internals) {
35396
35619
  lastMotionBlurInvalidParams = void 0;
35397
35620
  const {
35398
35621
  cameras: extractedCameras,
35622
+ auxiliaryCameras,
35399
35623
  cubeCameras,
35400
35624
  lights,
35401
35625
  environment,
@@ -35818,7 +36042,7 @@ function createRenderSystem(internals) {
35818
36042
  const motionBlurParams = cameras[0]?.motionBlur;
35819
36043
  let motionBlurDelta = 0;
35820
36044
  try {
35821
- const delta = compositionWorlds[cameraOwner].getResource(Time).delta;
36045
+ const delta = renderTime(compositionWorlds[cameraOwner]).delta;
35822
36046
  motionBlurDelta = Number.isFinite(delta) ? Math.max(0, delta) : 0;
35823
36047
  } catch {
35824
36048
  motionBlurDelta = 0;
@@ -35850,9 +36074,22 @@ function createRenderSystem(internals) {
35850
36074
  preparedFeatureSkylightResources = preparedPipelineState === null ? void 0 : resolveMaterialSkylight(internals, preparedPipelineState, skylight, skylightCount).skylightResources;
35851
36075
  let featureGraphCandidate;
35852
36076
  const preparedResourceBatches = runProfiledRenderPhase(profileSession, "features", () => {
36077
+ if (publication?.packet.features.some(
36078
+ (row) => !internals.featureHost?.features.some(
36079
+ (feature) => feature.identity === row.identity
36080
+ )
36081
+ ))
36082
+ throw new RenderPublicationError({
36083
+ reason: "shape",
36084
+ subject: "published feature has no receiver implementation"
36085
+ });
35853
36086
  if (internals.featureHost === void 0) return [];
35854
36087
  const featureFrame = runRenderFeatureFrame(internals.featureHost, {
35855
- worlds: compositionWorlds,
36088
+ worlds: sourceWorlds,
36089
+ ...publication === void 0 ? {} : {
36090
+ publishedFeatures: publication.packet.features,
36091
+ ...publication.onFeatureSourceSubmitted === void 0 ? {} : { onFeatureSourceSubmitted: publication.onFeatureSourceSubmitted }
36092
+ },
35856
36093
  owner: resourceOwner,
35857
36094
  frameNumber: frameState.frameNumber,
35858
36095
  ...cameras[0] === void 0 ? {} : { selectedCamera: cameras[0] },
@@ -35984,7 +36221,7 @@ function createRenderSystem(internals) {
35984
36221
  const hasLiveFeatureState = liveOutput !== void 0 || frameState.autoExposureGpuResources !== void 0 || frameState.pendingAutoExposureGpuResources !== void 0 || frameState.autoExposureState !== void 0 || frameState.pendingAutoExposureState !== void 0 || frameState.standardLutGpuResources !== void 0 || frameState.pendingStandardLutGpuResources !== void 0 || frameState.standardLutState.resident !== null || frameState.pendingStandardLutState !== void 0;
35985
36222
  if (hasLiveFeatureState) {
35986
36223
  const cameraWorld = compositionWorlds[cameraOwner];
35987
- const deltaTime = cameraWorld.getResource(Time).delta;
36224
+ const deltaTime = renderTime(cameraWorld).delta;
35988
36225
  stageLiveFeatureState(
35989
36226
  cameras[0],
35990
36227
  Number.isFinite(deltaTime) ? Math.max(0, deltaTime) : 0
@@ -35997,10 +36234,10 @@ function createRenderSystem(internals) {
35997
36234
  resourceGeneration: gpuDrivenProduction.inspect().resourceGeneration
35998
36235
  });
35999
36236
  frameState.surfaceSubmissionObservation = surfaceSubmissionCandidate;
36000
- const probeCaptureScene = shadowCasterProjection !== void 0 && reflectionProbeRecord.graph.work.some((work) => work.rawCaptureFace !== void 0) ? projectCaptureScene(shadowCasterProjection, submissionRenderables, orderedDispatch) : void 0;
36237
+ const probeCaptureScene = shadowCasterProjection !== void 0 && (auxiliaryCameras.length > 0 || cubeCameras.length > 0 || reflectionProbeRecord.graph.work.some((work) => work.rawCaptureFace !== void 0)) ? projectCaptureScene(shadowCasterProjection, submissionRenderables, orderedDispatch) : void 0;
36001
36238
  const presentedRenderableKeys = /* @__PURE__ */ new Set();
36002
36239
  const presentedSubmeshKeys = /* @__PURE__ */ new Set();
36003
- const consumeDynamicGeometry = dynamicGeometryFrames.onRenderableDraw(compositionWorlds);
36240
+ const consumeDynamicGeometry = dynamicGeometryFrames.onRenderableDraw(sourceWorlds);
36004
36241
  const markPresentedRenderable = (entry, submeshIndex, receipt) => {
36005
36242
  const entityKey = worldEntityKey(
36006
36243
  worldKeys[entry.source.worldId] ?? entry.source.worldId,
@@ -36049,7 +36286,9 @@ function createRenderSystem(internals) {
36049
36286
  },
36050
36287
  ...occlusionProjection === void 0 ? {} : { occlusion: occlusionProjection },
36051
36288
  frameTime: (() => {
36052
- const elapsed = compositionWorlds[cameraOwner].getResource(Time).elapsed;
36289
+ const elapsed = renderTime(
36290
+ compositionWorlds[cameraOwner]
36291
+ ).elapsed;
36053
36292
  return Number.isFinite(elapsed) ? elapsed : 0;
36054
36293
  })(),
36055
36294
  deviceGeneration: internals.deviceScope.generation,
@@ -36061,6 +36300,7 @@ function createRenderSystem(internals) {
36061
36300
  pointsLinesOwner,
36062
36301
  {
36063
36302
  snapshots: cubeCameras,
36303
+ auxiliaryCameras,
36064
36304
  scheduler: cubeCaptureScheduler,
36065
36305
  state: cubeCaptureState,
36066
36306
  reflectionProbes: reflectionProbeRecord,
@@ -36204,7 +36444,9 @@ function createRenderSystem(internals) {
36204
36444
  width: Math.max(1, internals.canvas.width),
36205
36445
  height: Math.max(1, internals.canvas.height),
36206
36446
  frameTime: (() => {
36207
- const elapsed = compositionWorlds[cameraOwner].getResource(Time).elapsed;
36447
+ const elapsed = renderTime(
36448
+ compositionWorlds[cameraOwner]
36449
+ ).elapsed;
36208
36450
  return Number.isFinite(elapsed) ? elapsed : 0;
36209
36451
  })(),
36210
36452
  ...surfaceDynamicInputFrame === void 0 ? {} : { surfaceDynamicInput: surfaceDynamicInputFrame },
@@ -36279,20 +36521,20 @@ function createRenderSystem(internals) {
36279
36521
  if (!retired.ok) internals.errorRegistry.fire(retired.error);
36280
36522
  }
36281
36523
  }
36282
- } catch (err57) {
36524
+ } catch (err58) {
36283
36525
  discardLiveFeatureState();
36284
36526
  if (!submitted) {
36285
36527
  internals.getPipelineState()?.perPassResources.discardBloomResources?.();
36286
36528
  }
36287
- const innerError = err57 instanceof PipelineSpecError ? {
36288
- name: err57.name,
36289
- code: err57.code,
36290
- message: err57.message,
36291
- detail: err57.detail
36292
- } : err57 instanceof RhiError ? err57 : {
36529
+ const innerError = err58 instanceof PipelineSpecError ? {
36530
+ name: err58.name,
36531
+ code: err58.code,
36532
+ message: err58.message,
36533
+ detail: err58.detail
36534
+ } : err58 instanceof RhiError ? err58 : {
36293
36535
  code: "unknown",
36294
- message: String(err57),
36295
- name: err57?.name
36536
+ message: String(err58),
36537
+ name: err58?.name
36296
36538
  };
36297
36539
  internals.errorRegistry.fire(
36298
36540
  new RhiError({
@@ -37022,578 +37264,6 @@ function postSpawnResolveJoints(world, resolver, spawnRoot) {
37022
37264
  }
37023
37265
  return { ok: true };
37024
37266
  }
37025
- var atlasMaterialCache = /* @__PURE__ */ new WeakMap();
37026
- var atlasOnlyMaterialCache = /* @__PURE__ */ new WeakMap();
37027
- var streamingCacheByWorld = /* @__PURE__ */ new WeakMap();
37028
- function streamingCache(world) {
37029
- let cache = streamingCacheByWorld.get(world);
37030
- if (cache === void 0) {
37031
- cache = {
37032
- layers: /* @__PURE__ */ new Map(),
37033
- chunkEntities: /* @__PURE__ */ new Map(),
37034
- activeChunks: /* @__PURE__ */ new Map()
37035
- };
37036
- streamingCacheByWorld.set(world, cache);
37037
- }
37038
- return cache;
37039
- }
37040
- function encodeTilemapLayerValue(layerOrder, chunkIndex, sortScope = "layer") {
37041
- if (sortScope === "per-cell") return layerOrder << 20 | 0;
37042
- return layerOrder << 20 | chunkIndex & 1048575 | 0;
37043
- }
37044
- function resolveTilesetMaterial(world, tileset, regionIndex, lookup) {
37045
- const region = tileset.regions[regionIndex];
37046
- if (region === void 0) return toShared(0);
37047
- const atlasIndex = region.atlasIndex ?? 0;
37048
- const atlasGuid = tileset.atlases[atlasIndex];
37049
- if (atlasGuid === void 0) return toShared(0);
37050
- const atlas = resolveTilesetRuntime(world, atlasGuid, lookup);
37051
- if (!atlas.ok) return toShared(0);
37052
- const atlasHandle = atlas.value.handle;
37053
- const atlasId = unwrapHandle(atlasHandle);
37054
- const cacheKey = `${atlasId}|${regionIndex}`;
37055
- const cache = atlasMaterialCache.get(world) ?? /* @__PURE__ */ new Map();
37056
- atlasMaterialCache.set(world, cache);
37057
- const cached = cache.get(cacheKey);
37058
- if (cached !== void 0) return cached;
37059
- const atlasSize = tileset.atlasSizes?.[atlasIndex];
37060
- const atlasWidth = Math.max(
37061
- 1,
37062
- atlasSize !== void 0 ? atlasSize.pixelWidth : tileset.columns * tileset.tileWidth
37063
- );
37064
- const atlasHeight = Math.max(
37065
- 1,
37066
- atlasSize !== void 0 ? atlasSize.pixelHeight : tileset.rows * tileset.tileHeight
37067
- );
37068
- const halfTexelU = 0.5 / atlasWidth;
37069
- const halfTexelV = 0.5 / atlasHeight;
37070
- const u = region.x / atlasWidth + halfTexelU;
37071
- const v = region.y / atlasHeight + halfTexelV;
37072
- const w = region.width / atlasWidth - 2 * halfTexelU;
37073
- const h = region.height / atlasHeight - 2 * halfTexelV;
37074
- const matPayload = {
37075
- kind: "material",
37076
- passes: [
37077
- {
37078
- name: "Forward",
37079
- program: { module: "forgeax::sprite" },
37080
- renderState: {
37081
- ...{ blend: SPRITE_PREMULTIPLIED_ALPHA_BLEND },
37082
- tags: { LightMode: "Forward" },
37083
- queue: 3e3
37084
- }
37085
- }
37086
- ],
37087
- values: {
37088
- colorTint: [1, 1, 1, 1],
37089
- baseColorTexture: atlasHandle,
37090
- region: [u, v, w, h],
37091
- pivotAndSize: [0.5, 0.5, 1, 1],
37092
- flipY: 1
37093
- }
37094
- };
37095
- const matHandle = world.allocSharedRef(
37096
- "MaterialAsset",
37097
- matPayload
37098
- );
37099
- cache.set(cacheKey, matHandle);
37100
- return matHandle;
37101
- }
37102
- function resolveAtlasOnlyMaterial(world, tileset, atlasIndex, lookup) {
37103
- const atlasGuid = tileset.atlases[atlasIndex];
37104
- if (atlasGuid === void 0) return toShared(0);
37105
- const atlas = resolveTilesetRuntime(world, atlasGuid, lookup);
37106
- if (!atlas.ok) return toShared(0);
37107
- const atlasHandle = atlas.value.handle;
37108
- const atlasId = unwrapHandle(atlasHandle);
37109
- const cacheKey = String(atlasId);
37110
- const cache = atlasOnlyMaterialCache.get(world) ?? /* @__PURE__ */ new Map();
37111
- atlasOnlyMaterialCache.set(world, cache);
37112
- const cached = cache.get(cacheKey);
37113
- if (cached !== void 0) return cached;
37114
- const matPayload = {
37115
- kind: "material",
37116
- passes: [
37117
- {
37118
- name: "Forward",
37119
- program: { module: "forgeax::sprite" },
37120
- renderState: {
37121
- ...{ blend: SPRITE_PREMULTIPLIED_ALPHA_BLEND },
37122
- tags: { LightMode: "Forward" },
37123
- queue: 3e3
37124
- }
37125
- }
37126
- ],
37127
- values: {
37128
- colorTint: [1, 1, 1, 1],
37129
- baseColorTexture: atlasHandle,
37130
- region: [0, 0, 1, 1],
37131
- pivotAndSize: [0.5, 0.5, 1, 1],
37132
- flipY: 1
37133
- }
37134
- };
37135
- const matHandle = world.allocSharedRef(
37136
- "MaterialAsset",
37137
- matPayload
37138
- );
37139
- cache.set(cacheKey, matHandle);
37140
- return matHandle;
37141
- }
37142
- function computeRegionUv(tileset, region, atlasIndex) {
37143
- const atlasSize = tileset.atlasSizes?.[atlasIndex];
37144
- const atlasWidth = Math.max(
37145
- 1,
37146
- atlasSize !== void 0 ? atlasSize.pixelWidth : tileset.columns * tileset.tileWidth
37147
- );
37148
- const atlasHeight = Math.max(
37149
- 1,
37150
- atlasSize !== void 0 ? atlasSize.pixelHeight : tileset.rows * tileset.tileHeight
37151
- );
37152
- const halfTexelU = 0.5 / atlasWidth;
37153
- const halfTexelV = 0.5 / atlasHeight;
37154
- return [
37155
- region.x / atlasWidth + halfTexelU,
37156
- region.y / atlasHeight + halfTexelV,
37157
- region.width / atlasWidth - 2 * halfTexelU,
37158
- region.height / atlasHeight - 2 * halfTexelV
37159
- ];
37160
- }
37161
- var SQRT1_2 = Math.SQRT1_2;
37162
- function effectivePivotYForTilemapFlip(pivotY, pivotX, flipV, flipDiagonal) {
37163
- const base = flipDiagonal ? pivotX : pivotY;
37164
- return flipV ? 1 - base : base;
37165
- }
37166
- function specFor(layerCols, chunkSize, cellIndex, packedTile, materialHandle, entry, atlasIndex) {
37167
- const cellX = cellIndex % layerCols;
37168
- const cellY = Math.floor(cellIndex / layerCols);
37169
- const chunkX = Math.floor(cellX / chunkSize);
37170
- const chunkY = Math.floor(cellY / chunkSize);
37171
- const chunksPerRow = Math.max(1, Math.ceil(layerCols / chunkSize));
37172
- const chunkIndex = chunkY * chunksPerRow + chunkX;
37173
- const { tileId } = decodeTileBits(packedTile);
37174
- return {
37175
- cellX,
37176
- cellY,
37177
- tileId,
37178
- packedTile,
37179
- materialHandle,
37180
- chunkIndex,
37181
- widthCells: entry.widthCells ?? 1,
37182
- heightCells: entry.heightCells ?? 1,
37183
- pivotX: entry.pivotX ?? 0.5,
37184
- pivotY: entry.pivotY ?? 0.5,
37185
- atlasIndex,
37186
- regionIndex: entry.regionIndex
37187
- };
37188
- }
37189
- function computeTileTrs(tilemap, spec, packedTile) {
37190
- const { flipH, flipV, flipDiagonal } = decodeTileBits(packedTile);
37191
- const basePivotForX = flipDiagonal ? spec.pivotY : spec.pivotX;
37192
- const effectivePivotX = flipH ? 1 - basePivotForX : basePivotForX;
37193
- const effectivePivotY = effectivePivotYForTilemapFlip(
37194
- spec.pivotY,
37195
- spec.pivotX,
37196
- flipV,
37197
- flipDiagonal
37198
- );
37199
- const tileSizeX = tilemap.tileSize[0] ?? 1;
37200
- const tileSizeY = tilemap.tileSize[1] ?? 1;
37201
- return {
37202
- posX: (spec.cellX + effectivePivotX + (0.5 - effectivePivotX) * spec.widthCells) * tileSizeX,
37203
- posY: (spec.cellY + effectivePivotY + (0.5 - effectivePivotY) * spec.heightCells) * tileSizeY,
37204
- scaleX: (flipH ? -1 : 1) * spec.widthCells * tileSizeX,
37205
- scaleY: (flipV ? -1 : 1) * spec.heightCells * tileSizeY,
37206
- quatZ: flipDiagonal ? SQRT1_2 : 0,
37207
- quatW: flipDiagonal ? SQRT1_2 : 1
37208
- };
37209
- }
37210
- function spawnDerivedRenderEntities(world, tilemap, layerEntity, layerOrder, spec, packedTile, sortScope = "layer") {
37211
- const { posX, posY, scaleX, scaleY, quatZ, quatW } = computeTileTrs(tilemap, spec, packedTile);
37212
- const layerValue = encodeTilemapLayerValue(layerOrder, spec.chunkIndex, sortScope);
37213
- return world.spawn(
37214
- {
37215
- component: Transform,
37216
- data: {
37217
- pos: [posX, posY, 0],
37218
- quat: [0, 0, quatZ, quatW],
37219
- scale: [scaleX, scaleY, 1]
37220
- }
37221
- },
37222
- { component: MeshFilter, data: { assetHandle: HANDLE_QUAD } },
37223
- {
37224
- component: MeshRenderer,
37225
- data: {
37226
- materials: [spec.materialHandle]
37227
- }
37228
- },
37229
- { component: Layer, data: { value: layerValue } },
37230
- { component: ChildOf, data: { parent: layerEntity } }
37231
- ).unwrap();
37232
- }
37233
- function spawnSpriteInstancesGroup(world, tilemap, tileset, layerEntity, layerOrder, chunkIndex, atlasIndex, materialHandle, cellSpecs) {
37234
- if (cellSpecs.length === 0) return void 0;
37235
- const N = cellSpecs.length;
37236
- const transforms = new Float32Array(N * 16);
37237
- const regions = new Float32Array(N * 4);
37238
- const tmpMat = mat4.create();
37239
- const tmpT = [0, 0, 0];
37240
- const tmpR = [0, 0, 0, 1];
37241
- const tmpS = [1, 1, 1];
37242
- const chunksPerRow = Math.max(1, Math.ceil(tilemap.cols / tilemap.chunkSize));
37243
- const chunkX = chunkIndex % chunksPerRow;
37244
- const chunkY = Math.floor(chunkIndex / chunksPerRow);
37245
- const chunkScaleX = tilemap.chunkSize * (tilemap.tileSize[0] ?? 1);
37246
- const chunkScaleY = tilemap.chunkSize * (tilemap.tileSize[1] ?? 1);
37247
- const chunkCenterX = (chunkX + 0.5) * chunkScaleX;
37248
- const chunkCenterY = (chunkY + 0.5) * chunkScaleY;
37249
- const invSX = chunkScaleX > 0 ? 1 / chunkScaleX : 1;
37250
- const invSY = chunkScaleY > 0 ? 1 / chunkScaleY : 1;
37251
- for (let i = 0; i < N; i++) {
37252
- const spec = cellSpecs[i];
37253
- const { posX, posY, scaleX, scaleY, quatZ, quatW } = computeTileTrs(
37254
- tilemap,
37255
- spec,
37256
- spec.packedTile
37257
- );
37258
- tmpT[0] = posX;
37259
- tmpT[1] = posY;
37260
- tmpT[2] = 0;
37261
- tmpR[0] = 0;
37262
- tmpR[1] = 0;
37263
- tmpR[2] = quatZ;
37264
- tmpR[3] = quatW;
37265
- tmpS[0] = scaleX;
37266
- tmpS[1] = scaleY;
37267
- tmpS[2] = 1;
37268
- mat4.compose(tmpMat, tmpT, tmpR, tmpS);
37269
- const dst = i * 16;
37270
- for (let c = 0; c < 4; c++) {
37271
- const base = c * 4;
37272
- const w3 = tmpMat[base + 3] ?? 0;
37273
- transforms[dst + base + 0] = ((tmpMat[base + 0] ?? 0) - chunkCenterX * w3) * invSX;
37274
- transforms[dst + base + 1] = ((tmpMat[base + 1] ?? 0) - chunkCenterY * w3) * invSY;
37275
- transforms[dst + base + 2] = tmpMat[base + 2] ?? 0;
37276
- transforms[dst + base + 3] = w3;
37277
- }
37278
- const region = tileset.regions[spec.regionIndex];
37279
- if (region !== void 0) {
37280
- const [u, v, w, h] = computeRegionUv(tileset, region, atlasIndex);
37281
- regions[i * 4 + 0] = u;
37282
- regions[i * 4 + 1] = v;
37283
- regions[i * 4 + 2] = w;
37284
- regions[i * 4 + 3] = h;
37285
- }
37286
- }
37287
- const layerValue = encodeTilemapLayerValue(layerOrder, chunkIndex, "layer");
37288
- return world.spawn(
37289
- {
37290
- component: Transform,
37291
- data: {
37292
- pos: [chunkCenterX, chunkCenterY, 0],
37293
- quat: [0, 0, 0, 1],
37294
- scale: [chunkScaleX, chunkScaleY, 1]
37295
- }
37296
- },
37297
- { component: MeshFilter, data: { assetHandle: HANDLE_QUAD } },
37298
- {
37299
- component: MeshRenderer,
37300
- data: {
37301
- materials: [materialHandle]
37302
- }
37303
- },
37304
- { component: SpriteInstances, data: { transforms, regions } },
37305
- { component: Layer, data: { value: layerValue } },
37306
- { component: ChildOf, data: { parent: layerEntity } }
37307
- ).unwrap();
37308
- }
37309
- function bucketTileLayer(world, layerEntity, parentEntity, lookup) {
37310
- const tilemapRes = world.get(parentEntity, Tilemap);
37311
- if (!tilemapRes.ok) return void 0;
37312
- const tilemap = tilemapRes.value;
37313
- const tilesetPayload = lookup(tilemap.tileset);
37314
- if (tilesetPayload === void 0 || "code" in tilesetPayload) return void 0;
37315
- if (tilesetPayload.kind !== "tileset") return void 0;
37316
- const tileset = tilesetPayload;
37317
- const layerRes = world.get(layerEntity, TileLayer);
37318
- if (!layerRes.ok) return void 0;
37319
- const layer = layerRes.value;
37320
- const tiles = layer.tiles;
37321
- const sortScope = decodeSortScope(layer.sortScope);
37322
- const useSpriteInstances = sortScope === "layer";
37323
- const specs = [];
37324
- for (let i = 0; i < tiles.length; i++) {
37325
- const packed = tiles[i] ?? 0;
37326
- if (packed === 0) continue;
37327
- const { tileId } = decodeTileBits(packed);
37328
- if (tileId === 0) continue;
37329
- const entry = tileset.tiles[tileId - 1];
37330
- if (entry === void 0) continue;
37331
- const region = tileset.regions[entry.regionIndex];
37332
- if (region === void 0) continue;
37333
- const atlasIndex = region.atlasIndex ?? 0;
37334
- const materialHandle = useSpriteInstances ? resolveAtlasOnlyMaterial(world, tileset, atlasIndex, lookup) : resolveTilesetMaterial(world, tileset, entry.regionIndex, lookup);
37335
- const spec = specFor(
37336
- tilemap.cols,
37337
- tilemap.chunkSize,
37338
- i,
37339
- packed,
37340
- materialHandle,
37341
- entry,
37342
- atlasIndex
37343
- );
37344
- specs.push(spec);
37345
- }
37346
- return {
37347
- tilemap,
37348
- layerOrder: layer.layerOrder,
37349
- sortScope,
37350
- tileset,
37351
- specs
37352
- };
37353
- }
37354
- function buildCameraFrustumPlanes(world) {
37355
- const query = world.query({ with: [Camera, Transform, GlobalTransform] }).unwrap();
37356
- let result = null;
37357
- for (const row of query) {
37358
- const camEntity = row.entity;
37359
- const camRes = world.get(camEntity, Camera);
37360
- const trRes = world.get(camEntity, GlobalTransform);
37361
- if (!camRes.ok || !trRes.ok) continue;
37362
- const cam = camRes.value;
37363
- const tr = trRes.value;
37364
- const { near, far } = cam;
37365
- if (near >= far) continue;
37366
- const proj = mat4.create();
37367
- if (cam.projection === CAMERA_PROJECTION_ORTHOGRAPHIC) {
37368
- mat4.orthographic(
37369
- proj,
37370
- cam.left,
37371
- cam.right,
37372
- cam.top,
37373
- cam.bottom,
37374
- near,
37375
- far
37376
- );
37377
- } else {
37378
- mat4.perspective(
37379
- proj,
37380
- cam.fov,
37381
- cam.aspect,
37382
- near,
37383
- far
37384
- );
37385
- }
37386
- const view = mat4.create();
37387
- mat4.invert(
37388
- view,
37389
- tr.world
37390
- );
37391
- const vp = mat4.create();
37392
- mat4.multiply(
37393
- vp,
37394
- proj,
37395
- view
37396
- );
37397
- const f = frustum.create();
37398
- frustum.fromViewProjection(f, vp);
37399
- result = f;
37400
- break;
37401
- }
37402
- return result;
37403
- }
37404
- function computeChunkStreamBounds(tilemap, specs) {
37405
- let minX = Number.MAX_VALUE;
37406
- let minY = Number.MAX_VALUE;
37407
- let maxX = -Number.MAX_VALUE;
37408
- let maxY = -Number.MAX_VALUE;
37409
- for (const spec of specs) {
37410
- const { posX, posY, scaleX, scaleY } = computeTileTrs(tilemap, spec, spec.packedTile);
37411
- const halfW = Math.abs(scaleX) * 0.5;
37412
- const halfH = Math.abs(scaleY) * 0.5;
37413
- const x0 = posX - halfW;
37414
- const x1 = posX + halfW;
37415
- const y0 = posY - halfH;
37416
- const y1 = posY + halfH;
37417
- if (x0 < minX) minX = x0;
37418
- if (y0 < minY) minY = y0;
37419
- if (x1 > maxX) maxX = x1;
37420
- if (y1 > maxY) maxY = y1;
37421
- }
37422
- return [minX, minY, -1, maxX, maxY, 1];
37423
- }
37424
- function purgeDerivedEntities(world, layerEntity) {
37425
- const r = world.get(layerEntity, Children);
37426
- if (!r.ok) return;
37427
- const snap = r.value.entities;
37428
- for (let i = 0; i < snap.length; i++) {
37429
- const e = snap[i];
37430
- if (e !== void 0) world.despawn(e);
37431
- }
37432
- }
37433
- function evictDeadPerCellStreamingCaches(work, world) {
37434
- const cache = streamingCache(world);
37435
- const aliveLayerKeys = /* @__PURE__ */ new Set();
37436
- for (const w of work) {
37437
- aliveLayerKeys.add(String(w.layerEntity));
37438
- }
37439
- const deadLayerKeys = /* @__PURE__ */ new Set();
37440
- for (const layerKey of cache.activeChunks.keys()) {
37441
- if (!aliveLayerKeys.has(layerKey)) deadLayerKeys.add(layerKey);
37442
- }
37443
- for (const layerKey of cache.layers.keys()) {
37444
- if (!aliveLayerKeys.has(layerKey)) deadLayerKeys.add(layerKey);
37445
- }
37446
- for (const deadKey of deadLayerKeys) {
37447
- const activeSet = cache.activeChunks.get(deadKey);
37448
- if (activeSet !== void 0) {
37449
- for (const chunkIdx of activeSet) {
37450
- cache.chunkEntities.delete(`${deadKey}:${chunkIdx}`);
37451
- }
37452
- cache.activeChunks.delete(deadKey);
37453
- }
37454
- cache.layers.delete(deadKey);
37455
- }
37456
- }
37457
- function tilemapChunkExtractSystem(world, lookup = () => void 0) {
37458
- const streaming = streamingCache(world);
37459
- const work = [];
37460
- const tileLayerQuery = world.query({ read: [TileLayer, ChildOf] }).unwrap();
37461
- for (const row of tileLayerQuery) {
37462
- const layer = row.get(TileLayer);
37463
- const parent = row.get(ChildOf).parent;
37464
- if (parent === null) continue;
37465
- work.push({
37466
- layerEntity: row.entity,
37467
- parentEntity: parent,
37468
- dirty: layer.dirty,
37469
- sortScopeRaw: layer.sortScope
37470
- });
37471
- }
37472
- evictDeadPerCellStreamingCaches(work, world);
37473
- let frustumPlanes;
37474
- for (const w of work) {
37475
- const layerKey = String(w.layerEntity);
37476
- const isStreaming = decodeSortScope(w.sortScopeRaw) === "per-cell";
37477
- if (!isStreaming) {
37478
- const childrenRes = world.get(w.layerEntity, Children);
37479
- const childCount = childrenRes.ok ? childrenRes.value.entities.length : 0;
37480
- if (childCount > 0 && w.dirty === 0) continue;
37481
- purgeDerivedEntities(world, w.layerEntity);
37482
- const bucket = bucketTileLayer(world, w.layerEntity, w.parentEntity, lookup);
37483
- if (bucket === void 0) continue;
37484
- const byChunkAtlas = /* @__PURE__ */ new Map();
37485
- for (const spec of bucket.specs) {
37486
- const key = (spec.chunkIndex & 1048575) << 16 | spec.atlasIndex & 65535;
37487
- const list = byChunkAtlas.get(key);
37488
- if (list === void 0) {
37489
- byChunkAtlas.set(key, [spec]);
37490
- } else {
37491
- list.push(spec);
37492
- }
37493
- }
37494
- for (const groupSpecs of byChunkAtlas.values()) {
37495
- const first = groupSpecs[0];
37496
- if (first === void 0) continue;
37497
- spawnSpriteInstancesGroup(
37498
- world,
37499
- bucket.tilemap,
37500
- bucket.tileset,
37501
- w.layerEntity,
37502
- bucket.layerOrder,
37503
- first.chunkIndex,
37504
- first.atlasIndex,
37505
- first.materialHandle,
37506
- groupSpecs
37507
- );
37508
- }
37509
- if (w.dirty !== 0) {
37510
- world.set(w.layerEntity, TileLayer, { dirty: 0 }).unwrap();
37511
- }
37512
- continue;
37513
- }
37514
- if (w.dirty !== 0 || !streaming.layers.has(layerKey)) {
37515
- const activeSet2 = streaming.activeChunks.get(layerKey);
37516
- if (activeSet2 !== void 0) {
37517
- for (const chunkIdx of activeSet2) {
37518
- const key = `${layerKey}:${chunkIdx}`;
37519
- const entities = streaming.chunkEntities.get(key);
37520
- if (entities !== void 0) {
37521
- for (const e of entities) world.despawn(e);
37522
- streaming.chunkEntities.delete(key);
37523
- }
37524
- }
37525
- activeSet2.clear();
37526
- }
37527
- streaming.layers.delete(layerKey);
37528
- const bucket = bucketTileLayer(world, w.layerEntity, w.parentEntity, lookup);
37529
- if (bucket !== void 0) {
37530
- const byChunkSpecs = /* @__PURE__ */ new Map();
37531
- for (const spec of bucket.specs) {
37532
- const list = byChunkSpecs.get(spec.chunkIndex);
37533
- if (list === void 0) {
37534
- byChunkSpecs.set(spec.chunkIndex, [spec]);
37535
- } else {
37536
- list.push(spec);
37537
- }
37538
- }
37539
- const byChunk = /* @__PURE__ */ new Map();
37540
- for (const [chunkIdx, specs] of byChunkSpecs) {
37541
- byChunk.set(chunkIdx, {
37542
- specs,
37543
- bounds: computeChunkStreamBounds(bucket.tilemap, specs)
37544
- });
37545
- }
37546
- streaming.layers.set(layerKey, {
37547
- byChunk,
37548
- tilemap: bucket.tilemap,
37549
- layerOrder: bucket.layerOrder,
37550
- sortScope: bucket.sortScope
37551
- });
37552
- }
37553
- if (w.dirty !== 0) {
37554
- world.set(w.layerEntity, TileLayer, { dirty: 0 }).unwrap();
37555
- }
37556
- }
37557
- const cache = streaming.layers.get(layerKey);
37558
- if (cache === void 0) continue;
37559
- if (frustumPlanes === void 0) {
37560
- frustumPlanes = buildCameraFrustumPlanes(world);
37561
- }
37562
- const activeSet = streaming.activeChunks.get(layerKey) ?? /* @__PURE__ */ new Set();
37563
- streaming.activeChunks.set(layerKey, activeSet);
37564
- const { tilemap } = cache;
37565
- for (const [chunkIdx, entry] of cache.byChunk) {
37566
- const { specs, bounds } = entry;
37567
- const visible = frustumPlanes === null || frustum.intersectsBox(frustumPlanes, bounds);
37568
- const wasActive = activeSet.has(chunkIdx);
37569
- if (visible && !wasActive) {
37570
- const spawned = [];
37571
- for (const spec of specs) {
37572
- const e = spawnDerivedRenderEntities(
37573
- world,
37574
- tilemap,
37575
- w.layerEntity,
37576
- cache.layerOrder,
37577
- spec,
37578
- spec.packedTile,
37579
- cache.sortScope
37580
- );
37581
- spawned.push(e);
37582
- }
37583
- streaming.chunkEntities.set(`${layerKey}:${chunkIdx}`, spawned);
37584
- activeSet.add(chunkIdx);
37585
- } else if (!visible && wasActive) {
37586
- const key = `${layerKey}:${chunkIdx}`;
37587
- const entities = streaming.chunkEntities.get(key);
37588
- if (entities !== void 0) {
37589
- for (const e of entities) world.despawn(e);
37590
- streaming.chunkEntities.delete(key);
37591
- }
37592
- activeSet.delete(chunkIdx);
37593
- }
37594
- }
37595
- }
37596
- }
37597
37267
 
37598
37268
  // src/assembly/analytic-fog-registration.ts
37599
37269
  function registerAnalyticFogPostProcess(renderSystem, source, candidate) {
@@ -40087,6 +39757,14 @@ function createRendererRecovery(deps) {
40087
39757
  device,
40088
39758
  adaptMipmapShaderModuleFactory2(internals.pack.createShaderModule),
40089
39759
  (world, pod) => {
39760
+ if ("resolveAsset" in world)
39761
+ return err(
39762
+ new AssetError({
39763
+ code: "asset-not-found",
39764
+ expected: "source-owned environment asset allocation",
39765
+ hint: "publish the environment asset from its source owner before GPU preparation"
39766
+ })
39767
+ );
40090
39768
  const handle = world.allocSharedRef(
40091
39769
  "EquirectAsset",
40092
39770
  pod
@@ -40583,974 +40261,6 @@ function collectRequiredFullscreenPostProcesses(features) {
40583
40261
  return Object.freeze([...entries.values()]);
40584
40262
  }
40585
40263
 
40586
- // src/targets/contracts.ts
40587
- var FORMAT_BYTES = {
40588
- rgba16float: 8,
40589
- rgba8unorm: 4,
40590
- "rgba8unorm-srgb": 4
40591
- };
40592
- function mipFactor(mipLevels) {
40593
- return mipLevels === "full" ? 4 / 3 : 1;
40594
- }
40595
- function estimatedBytes(descriptor) {
40596
- const layers = descriptor.shape === "cube" ? 6 : 1;
40597
- const samples = descriptor.sampleCount;
40598
- const depthBytes = descriptor.depth === void 0 ? 0 : 4;
40599
- return Math.ceil(
40600
- descriptor.width * descriptor.height * FORMAT_BYTES[descriptor.format] * layers * samples * mipFactor(descriptor.mipLevels) + descriptor.width * descriptor.height * depthBytes * layers * samples * mipFactor(descriptor.mipLevels)
40601
- );
40602
- }
40603
- function invalid4(field, value, expected) {
40604
- return {
40605
- ok: false,
40606
- error: new RenderTargetDescriptorInvalidError({ field, value, expected })
40607
- };
40608
- }
40609
- function admitRenderTargetDescriptor(descriptor, limits) {
40610
- if (!Number.isInteger(descriptor.width) || descriptor.width < 1) {
40611
- return invalid4("width", descriptor.width, "an integer >= 1");
40612
- }
40613
- if (!Number.isInteger(descriptor.height) || descriptor.height < 1) {
40614
- return invalid4("height", descriptor.height, "an integer >= 1");
40615
- }
40616
- if (descriptor.width > limits.maxTextureDimension2D || descriptor.height > limits.maxTextureDimension2D) {
40617
- return invalid4(
40618
- "extent",
40619
- { width: descriptor.width, height: descriptor.height },
40620
- `width and height <= ${limits.maxTextureDimension2D}`
40621
- );
40622
- }
40623
- if (descriptor.shape === "cube" && descriptor.width !== descriptor.height) {
40624
- return invalid4("shape", descriptor.shape, "cube width === height");
40625
- }
40626
- if (!limits.renderableFormats.includes(descriptor.format)) {
40627
- return {
40628
- ok: false,
40629
- error: new RenderTargetCapabilityMissingError({
40630
- operation: "create",
40631
- requested: descriptor.format,
40632
- capability: "renderableFormats",
40633
- actual: limits.renderableFormats.join(", ")
40634
- })
40635
- };
40636
- }
40637
- if (!limits.sampleCounts.includes(descriptor.sampleCount)) {
40638
- return {
40639
- ok: false,
40640
- error: new RenderTargetCapabilityMissingError({
40641
- operation: "create",
40642
- requested: String(descriptor.sampleCount),
40643
- capability: "sampleCounts",
40644
- actual: limits.sampleCounts.join(", ")
40645
- })
40646
- };
40647
- }
40648
- if (descriptor.depth !== void 0 && !limits.depthFormats.includes(descriptor.depth)) {
40649
- return {
40650
- ok: false,
40651
- error: new RenderTargetCapabilityMissingError({
40652
- operation: "create",
40653
- requested: descriptor.depth,
40654
- capability: "depthFormats",
40655
- actual: limits.depthFormats.join(", ")
40656
- })
40657
- };
40658
- }
40659
- const bytes2 = estimatedBytes(descriptor);
40660
- if (bytes2 > limits.maxBytesPerTarget) {
40661
- return invalid4("bytes", bytes2, `estimated allocation <= ${limits.maxBytesPerTarget}`);
40662
- }
40663
- return { ok: true, value: descriptor };
40664
- }
40665
-
40666
- // src/targets/owner.ts
40667
- function frozenDescriptor(descriptor) {
40668
- return Object.freeze({ ...descriptor });
40669
- }
40670
- function invalid5(operation, reason2, state, generation) {
40671
- return {
40672
- ok: false,
40673
- error: new RenderTargetStateInvalidError({ operation, reason: reason2, state, generation })
40674
- };
40675
- }
40676
- function token() {
40677
- return Object.freeze({});
40678
- }
40679
- function createRenderTargetOwner(options) {
40680
- const targets = /* @__PURE__ */ new WeakMap();
40681
- const requireTarget = (target5, operation) => {
40682
- const state = targets.get(target5);
40683
- if (state === void 0) return invalid5(operation, "foreign-renderer", "destroyed", 0);
40684
- if (state.rendererId !== options.rendererId) {
40685
- return invalid5(operation, "foreign-renderer", state.state, state.generation);
40686
- }
40687
- if (state.state === "destroyed") {
40688
- return invalid5(operation, "destroyed", state.state, state.generation);
40689
- }
40690
- return { ok: true, value: state };
40691
- };
40692
- return {
40693
- create(descriptor) {
40694
- const target5 = token();
40695
- targets.set(target5, {
40696
- target: target5,
40697
- rendererId: options.rendererId,
40698
- state: "uninitialized",
40699
- generation: 0,
40700
- descriptor: frozenDescriptor(descriptor),
40701
- candidate: void 0,
40702
- retiredGenerations: /* @__PURE__ */ new Set()
40703
- });
40704
- return { ok: true, value: target5 };
40705
- },
40706
- stage(target5, descriptor) {
40707
- const found = requireTarget(target5, "resize");
40708
- if (!found.ok) return found;
40709
- const state = found.value;
40710
- if (state.state === "rebuilding") {
40711
- return invalid5("resize", "generation-mismatch", state.state, state.generation);
40712
- }
40713
- const candidate = Object.freeze({
40714
- generation: state.state === "uninitialized" ? options.initialGeneration : state.generation,
40715
- descriptor: frozenDescriptor(descriptor ?? state.descriptor)
40716
- });
40717
- state.candidate = candidate;
40718
- state.state = "candidate";
40719
- return { ok: true, value: candidate };
40720
- },
40721
- promote(target5, generation) {
40722
- const found = requireTarget(target5, "resize");
40723
- if (!found.ok) return found;
40724
- const state = found.value;
40725
- if (state.candidate?.generation !== generation) {
40726
- return invalid5("resize", "generation-mismatch", state.state, state.generation);
40727
- }
40728
- state.descriptor = state.candidate.descriptor;
40729
- state.generation = generation;
40730
- state.candidate = void 0;
40731
- state.state = "active";
40732
- return { ok: true, value: void 0 };
40733
- },
40734
- rejectCandidate(target5, generation, stage) {
40735
- const found = requireTarget(target5, "resize");
40736
- if (!found.ok) return found;
40737
- const state = found.value;
40738
- if (state.candidate?.generation !== generation) {
40739
- return invalid5("resize", "generation-mismatch", state.state, state.generation);
40740
- }
40741
- state.candidate = void 0;
40742
- state.state = state.generation === 0 ? "uninitialized" : "active";
40743
- return {
40744
- ok: false,
40745
- error: new RenderTargetOperationFailedError({
40746
- operation: "resize",
40747
- stage,
40748
- generation,
40749
- cause: new Error(`candidate ${generation} failed during ${stage}`),
40750
- recovery: state.generation === 0 ? "retry" : "retain-last-known-good"
40751
- })
40752
- };
40753
- },
40754
- beginRecovery(target5, generation) {
40755
- const found = requireTarget(target5, "resize");
40756
- if (!found.ok) return found;
40757
- const state = found.value;
40758
- if (state.state !== "active" || generation <= state.generation) {
40759
- return invalid5("resize", "generation-mismatch", state.state, state.generation);
40760
- }
40761
- state.generation = generation;
40762
- state.candidate = void 0;
40763
- state.state = "rebuilding";
40764
- return { ok: true, value: void 0 };
40765
- },
40766
- finishRecovery(target5) {
40767
- const found = requireTarget(target5, "resize");
40768
- if (!found.ok) return found;
40769
- const state = found.value;
40770
- if (state.state !== "rebuilding") {
40771
- return invalid5("resize", "generation-mismatch", state.state, state.generation);
40772
- }
40773
- state.state = "uninitialized";
40774
- return { ok: true, value: void 0 };
40775
- },
40776
- retire(target5, generation) {
40777
- const found = requireTarget(target5, "destroy");
40778
- if (!found.ok) return found;
40779
- found.value.retiredGenerations.add(generation);
40780
- return { ok: true, value: void 0 };
40781
- },
40782
- destroy(target5) {
40783
- const state = targets.get(target5);
40784
- if (state === void 0) return invalid5("destroy", "foreign-renderer", "destroyed", 0);
40785
- if (state.rendererId !== options.rendererId) {
40786
- return invalid5("destroy", "foreign-renderer", state.state, state.generation);
40787
- }
40788
- if (state.state === "destroyed") return { ok: true, value: void 0 };
40789
- state.candidate = void 0;
40790
- state.state = "destroyed";
40791
- return { ok: true, value: void 0 };
40792
- },
40793
- inspect(target5) {
40794
- const found = requireTarget(target5, "inspect");
40795
- if (!found.ok) return found;
40796
- const state = found.value;
40797
- return {
40798
- ok: true,
40799
- value: Object.freeze({
40800
- token: state.target,
40801
- state: state.state,
40802
- generation: state.generation,
40803
- descriptor: state.descriptor,
40804
- ...state.candidate === void 0 ? {} : { candidate: state.candidate }
40805
- })
40806
- };
40807
- }
40808
- };
40809
- }
40810
-
40811
- // src/targets/readback.ts
40812
- function invalidTicket(ticket, reason2) {
40813
- return {
40814
- ok: false,
40815
- error: new RenderTargetStateInvalidError({
40816
- operation: "readback",
40817
- reason: reason2,
40818
- state: reason2 === "destroyed" ? "destroyed" : "active",
40819
- generation: ticket.deviceGeneration
40820
- })
40821
- };
40822
- }
40823
- function bindRenderTargetReadbackTicket(ticket, receipt) {
40824
- if (ticket.consumed) return invalidTicket(ticket, "destroyed");
40825
- if (ticket.frameId !== void 0) {
40826
- return invalidTicket(ticket, "generation-mismatch");
40827
- }
40828
- ticket.frameId = receipt.frameId;
40829
- ticket.deviceGeneration = receipt.deviceGeneration;
40830
- return { ok: true, value: void 0 };
40831
- }
40832
- function createRenderTargetReadbackTicket(target5, input) {
40833
- 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) {
40834
- return {
40835
- ok: false,
40836
- error: new RenderTargetOperationFailedError({
40837
- operation: "readback",
40838
- stage: "copy",
40839
- generation: input.deviceGeneration,
40840
- cause: new Error("readback dimensions and identity must be non-negative integers"),
40841
- recovery: "retry"
40842
- })
40843
- };
40844
- }
40845
- const unalignedRowBytes = input.width * input.bytesPerPixel;
40846
- const bytesPerRow = Math.ceil(unalignedRowBytes / 256) * 256;
40847
- return {
40848
- ok: true,
40849
- value: {
40850
- target: target5,
40851
- frameId: input.frameId,
40852
- deviceGeneration: input.deviceGeneration,
40853
- mipLevel: input.mipLevel,
40854
- ...input.face === void 0 ? {} : { face: input.face },
40855
- width: input.width,
40856
- height: input.height,
40857
- bytesPerRow,
40858
- byteLength: bytesPerRow * input.height,
40859
- consumed: false
40860
- }
40861
- };
40862
- }
40863
- function completeRenderTargetReadback(ticket, receipt, bytes2) {
40864
- if (ticket.consumed) return invalidTicket(ticket, "destroyed");
40865
- if (ticket.frameId === void 0 || receipt.frameId !== ticket.frameId || receipt.deviceGeneration !== ticket.deviceGeneration) {
40866
- return invalidTicket(ticket, "generation-mismatch");
40867
- }
40868
- if (bytes2.byteLength !== ticket.byteLength) {
40869
- return {
40870
- ok: false,
40871
- error: new RenderTargetOperationFailedError({
40872
- operation: "readback",
40873
- stage: "copy",
40874
- generation: ticket.deviceGeneration,
40875
- cause: new Error(`expected ${ticket.byteLength} bytes, received ${bytes2.byteLength}`),
40876
- recovery: "retry"
40877
- })
40878
- };
40879
- }
40880
- ticket.consumed = true;
40881
- return {
40882
- ok: true,
40883
- value: {
40884
- bytes: bytes2,
40885
- frameId: ticket.frameId,
40886
- deviceGeneration: ticket.deviceGeneration,
40887
- mipLevel: ticket.mipLevel,
40888
- ...ticket.face === void 0 ? {} : { face: ticket.face }
40889
- }
40890
- };
40891
- }
40892
-
40893
- // src/assembly/render-target-host.ts
40894
- var DEFAULT_LIMITS = {
40895
- maxTextureDimension2D: 8192,
40896
- maxBytesPerTarget: 256 * 1024 * 1024,
40897
- renderableFormats: ["rgba16float", "rgba8unorm", "rgba8unorm-srgb"],
40898
- sampleCounts: [1, 4],
40899
- depthFormats: ["depth24plus-stencil8", "depth32float"]
40900
- };
40901
- function opaqueTicket() {
40902
- return Object.freeze({});
40903
- }
40904
- function bytesPerPixel(format) {
40905
- return format === "rgba16float" ? 8 : 4;
40906
- }
40907
- function mipCount(descriptor) {
40908
- return descriptor.mipLevels === 1 ? 1 : Math.floor(Math.log2(Math.max(descriptor.width, descriptor.height))) + 1;
40909
- }
40910
- function makePhysical(device, descriptor, generation) {
40911
- const layers = descriptor.shape === "cube" ? 6 : 1;
40912
- const usage = GPU_TEXTURE_USAGE_RENDER_ATTACHMENT | (descriptor.sampled ? GPU_TEXTURE_USAGE_TEXTURE_BINDING : 0) | (descriptor.readback ? GPU_TEXTURE_USAGE_COPY_SRC : 0);
40913
- const created = device.createTexture({
40914
- label: `render-target.${generation}`,
40915
- size: { width: descriptor.width, height: descriptor.height, depthOrArrayLayers: layers },
40916
- format: descriptor.format,
40917
- mipLevelCount: mipCount(descriptor),
40918
- // WebGPU forbids multisampled array textures. The cube is always the
40919
- // single-sample resolve destination; MSAA capture uses one depth=1 color
40920
- // texture per face below.
40921
- sampleCount: 1,
40922
- dimension: "2d",
40923
- usage,
40924
- viewFormats: void 0,
40925
- textureBindingViewDimension: descriptor.shape === "cube" ? "cube" : void 0
40926
- });
40927
- if (!created.ok)
40928
- return {
40929
- ok: false,
40930
- error: new RenderTargetOperationFailedError({
40931
- operation: "create",
40932
- stage: "allocation",
40933
- generation,
40934
- cause: created.error,
40935
- recovery: "retry"
40936
- })
40937
- };
40938
- const texture = created.value;
40939
- const view = device.createTextureView(texture, {
40940
- dimension: descriptor.shape,
40941
- baseMipLevel: 0,
40942
- mipLevelCount: mipCount(descriptor),
40943
- baseArrayLayer: 0,
40944
- arrayLayerCount: layers
40945
- });
40946
- if (!view.ok)
40947
- return {
40948
- ok: false,
40949
- error: new RenderTargetOperationFailedError({
40950
- operation: "create",
40951
- stage: "allocation",
40952
- generation,
40953
- cause: view.error,
40954
- recovery: "retry"
40955
- })
40956
- };
40957
- const mipViews = [];
40958
- for (let mip = 0; mip < mipCount(descriptor); mip += 1) {
40959
- const mipView = device.createTextureView(texture, {
40960
- dimension: descriptor.shape,
40961
- baseMipLevel: mip,
40962
- mipLevelCount: 1,
40963
- baseArrayLayer: 0,
40964
- arrayLayerCount: layers
40965
- });
40966
- if (!mipView.ok)
40967
- return {
40968
- ok: false,
40969
- error: new RenderTargetOperationFailedError({
40970
- operation: "create",
40971
- stage: "allocation",
40972
- generation,
40973
- cause: mipView.error,
40974
- recovery: "retry"
40975
- })
40976
- };
40977
- mipViews.push(mipView.value);
40978
- }
40979
- const resolveFaceViews = [];
40980
- for (let face = 0; face < layers; face += 1) {
40981
- const faceView = device.createTextureView(texture, {
40982
- dimension: "2d",
40983
- baseMipLevel: 0,
40984
- mipLevelCount: 1,
40985
- baseArrayLayer: face,
40986
- arrayLayerCount: 1
40987
- });
40988
- if (!faceView.ok)
40989
- return {
40990
- ok: false,
40991
- error: new RenderTargetOperationFailedError({
40992
- operation: "create",
40993
- stage: "allocation",
40994
- generation,
40995
- cause: faceView.error,
40996
- recovery: "retry"
40997
- })
40998
- };
40999
- resolveFaceViews.push(faceView.value);
41000
- }
41001
- const colorTextures = [];
41002
- const faceViews = [];
41003
- const depthTextures = [];
41004
- const depthViews = [];
41005
- if (descriptor.shape === "cube") {
41006
- for (let face = 0; face < layers; face += 1) {
41007
- const depth = device.createTexture({
41008
- label: `render-target.${generation}.depth.${face}`,
41009
- size: {
41010
- width: descriptor.width,
41011
- height: descriptor.height,
41012
- depthOrArrayLayers: descriptor.sampleCount === 4 ? 1 : layers
41013
- },
41014
- mipLevelCount: 1,
41015
- sampleCount: descriptor.sampleCount,
41016
- dimension: "2d",
41017
- format: "depth24plus-stencil8",
41018
- usage: GPU_TEXTURE_USAGE_RENDER_ATTACHMENT,
41019
- viewFormats: void 0,
41020
- textureBindingViewDimension: void 0
41021
- });
41022
- if (!depth.ok)
41023
- return {
41024
- ok: false,
41025
- error: new RenderTargetOperationFailedError({
41026
- operation: "create",
41027
- stage: "allocation",
41028
- generation,
41029
- cause: depth.error,
41030
- recovery: "retry"
41031
- })
41032
- };
41033
- const depthView = device.createTextureView(depth.value, {
41034
- dimension: "2d",
41035
- baseArrayLayer: descriptor.sampleCount === 4 ? 0 : face,
41036
- arrayLayerCount: 1
41037
- });
41038
- if (!depthView.ok)
41039
- return {
41040
- ok: false,
41041
- error: new RenderTargetOperationFailedError({
41042
- operation: "create",
41043
- stage: "allocation",
41044
- generation,
41045
- cause: depthView.error,
41046
- recovery: "retry"
41047
- })
41048
- };
41049
- depthTextures.push(depth.value);
41050
- depthViews.push(depthView.value);
41051
- }
41052
- }
41053
- if (descriptor.sampleCount === 4) {
41054
- for (let face = 0; face < layers; face += 1) {
41055
- const msaa = device.createTexture({
41056
- label: `render-target.${generation}.msaa.${face}`,
41057
- size: { width: descriptor.width, height: descriptor.height, depthOrArrayLayers: 1 },
41058
- format: descriptor.format,
41059
- mipLevelCount: 1,
41060
- sampleCount: 4,
41061
- dimension: "2d",
41062
- usage: GPU_TEXTURE_USAGE_RENDER_ATTACHMENT,
41063
- viewFormats: void 0,
41064
- textureBindingViewDimension: void 0
41065
- });
41066
- if (!msaa.ok)
41067
- return {
41068
- ok: false,
41069
- error: new RenderTargetOperationFailedError({
41070
- operation: "create",
41071
- stage: "allocation",
41072
- generation,
41073
- cause: msaa.error,
41074
- recovery: "retry"
41075
- })
41076
- };
41077
- const msaaView = device.createTextureView(msaa.value, {
41078
- dimension: "2d",
41079
- baseMipLevel: 0,
41080
- mipLevelCount: 1,
41081
- baseArrayLayer: 0,
41082
- arrayLayerCount: 1
41083
- });
41084
- if (!msaaView.ok)
41085
- return {
41086
- ok: false,
41087
- error: new RenderTargetOperationFailedError({
41088
- operation: "create",
41089
- stage: "allocation",
41090
- generation,
41091
- cause: msaaView.error,
41092
- recovery: "retry"
41093
- })
41094
- };
41095
- colorTextures.push(msaa.value);
41096
- faceViews.push(msaaView.value);
41097
- }
41098
- } else {
41099
- for (let face = 0; face < layers; face += 1) {
41100
- colorTextures.push(texture);
41101
- faceViews.push(resolveFaceViews[face] ?? view.value);
41102
- }
41103
- }
41104
- return {
41105
- ok: true,
41106
- value: {
41107
- generation,
41108
- descriptor,
41109
- texture,
41110
- view: view.value,
41111
- mipViews,
41112
- colorTextures,
41113
- faceViews,
41114
- depthTextures,
41115
- depthViews,
41116
- ...descriptor.sampleCount === 4 ? { resolveTexture: texture } : {},
41117
- resolveView: view.value,
41118
- resolveFaceViews
41119
- }
41120
- };
41121
- }
41122
- function destroyPhysical(device, physical) {
41123
- if (device === void 0 || physical === void 0) return;
41124
- const textures = /* @__PURE__ */ new Set();
41125
- textures.add(physical.texture);
41126
- if (physical.resolveTexture !== void 0) textures.add(physical.resolveTexture);
41127
- for (const texture of physical.colorTextures) textures.add(texture);
41128
- for (const texture of physical.depthTextures) textures.add(texture);
41129
- for (const texture of textures) device.destroyTexture(texture);
41130
- }
41131
- function createRenderTargetHost(options = {}) {
41132
- let disposed = false;
41133
- const limits = options.limits ?? DEFAULT_LIMITS;
41134
- const owner = createRenderTargetOwner({
41135
- rendererId: options.rendererId ?? /* @__PURE__ */ Symbol("renderer"),
41136
- initialGeneration: options.initialGeneration ?? 0
41137
- });
41138
- const targets = /* @__PURE__ */ new Set();
41139
- const staged = /* @__PURE__ */ new Set();
41140
- const activePhysical = /* @__PURE__ */ new WeakMap();
41141
- const candidatePhysical = /* @__PURE__ */ new WeakMap();
41142
- const sources = /* @__PURE__ */ new WeakMap();
41143
- const readbacks = /* @__PURE__ */ new WeakMap();
41144
- const readbackRecords = /* @__PURE__ */ new Set();
41145
- const currentGeneration = () => options.getGeneration?.() ?? options.initialGeneration ?? 0;
41146
- const stagePhysical = (target5, descriptor) => {
41147
- const stagedTarget = owner.stage(target5, descriptor);
41148
- if (!stagedTarget.ok) return stagedTarget;
41149
- const device = options.getDevice?.();
41150
- if (device === void 0) {
41151
- staged.add(target5);
41152
- return { ok: true, value: void 0 };
41153
- }
41154
- const physical = makePhysical(
41155
- device,
41156
- stagedTarget.value.descriptor,
41157
- stagedTarget.value.generation
41158
- );
41159
- if (!physical.ok) {
41160
- owner.rejectCandidate(target5, stagedTarget.value.generation, "allocation");
41161
- return physical;
41162
- }
41163
- candidatePhysical.set(target5, physical.value);
41164
- staged.add(target5);
41165
- return { ok: true, value: void 0 };
41166
- };
41167
- return Object.freeze({
41168
- owner: "renderer",
41169
- createRenderTarget(descriptor) {
41170
- if (disposed) {
41171
- return {
41172
- ok: false,
41173
- error: new RenderTargetStateInvalidError({
41174
- operation: "inspect",
41175
- reason: "destroyed",
41176
- state: "destroyed",
41177
- generation: currentGeneration()
41178
- })
41179
- };
41180
- }
41181
- const admitted = admitRenderTargetDescriptor(descriptor, limits);
41182
- if (!admitted.ok) return admitted;
41183
- const created = owner.create(admitted.value);
41184
- if (created.ok) targets.add(created.value);
41185
- return created;
41186
- },
41187
- resizeRenderTarget(target5, descriptor) {
41188
- const admitted = admitRenderTargetDescriptor(descriptor, limits);
41189
- if (!admitted.ok) return admitted;
41190
- return stagePhysical(target5, admitted.value);
41191
- },
41192
- createRenderTargetTextureSource(target5, sourceOptions) {
41193
- const inspected = owner.inspect(target5);
41194
- if (!inspected.ok) return inspected;
41195
- if (!inspected.value.descriptor.sampled) {
41196
- return {
41197
- ok: false,
41198
- error: new RenderTargetCapabilityMissingError({
41199
- operation: "source",
41200
- requested: "sampled=true",
41201
- capability: "sampled",
41202
- actual: "false"
41203
- })
41204
- };
41205
- }
41206
- if (sourceOptions.dimension !== inspected.value.descriptor.shape) {
41207
- return {
41208
- ok: false,
41209
- error: new RenderTargetDescriptorInvalidError({
41210
- field: "dimension",
41211
- value: sourceOptions.dimension,
41212
- expected: `dimension matches ${inspected.value.descriptor.shape}`
41213
- })
41214
- };
41215
- }
41216
- if (!Number.isInteger(sourceOptions.mipLevel) || sourceOptions.mipLevel < 0 || inspected.value.descriptor.mipLevels === 1 && sourceOptions.mipLevel !== 0) {
41217
- return {
41218
- ok: false,
41219
- error: new RenderTargetDescriptorInvalidError({
41220
- field: "mipLevel",
41221
- value: sourceOptions.mipLevel,
41222
- expected: "an admitted mip level for the target"
41223
- })
41224
- };
41225
- }
41226
- const binding = createRenderTargetMaterialSource(target5, inspected.value.descriptor, {
41227
- ...sourceOptions,
41228
- generation: inspected.value.generation
41229
- });
41230
- if (!binding.ok) return binding;
41231
- sources.set(binding.value.source, binding.value);
41232
- return { ok: true, value: binding.value.source };
41233
- },
41234
- resolveRenderTargetTextureSource(source) {
41235
- const binding = sources.get(source) ?? resolveRenderTargetMaterialSource(source);
41236
- if (binding === void 0) return void 0;
41237
- const physical = activePhysical.get(binding.target);
41238
- if (physical === void 0) return binding;
41239
- const view = physical.mipViews[binding.view.mipLevel] ?? (binding.shape === "cube" ? physical.view : physical.resolveView);
41240
- if (binding.generation !== physical.generation) return binding;
41241
- return { ...binding, textureView: view };
41242
- },
41243
- requestTargetReadback(target5, request) {
41244
- const inspected = owner.inspect(target5);
41245
- if (!inspected.ok) return inspected;
41246
- if (!inspected.value.descriptor.readback) {
41247
- return {
41248
- ok: false,
41249
- error: new RenderTargetCapabilityMissingError({
41250
- operation: "readback",
41251
- requested: "readback=true",
41252
- capability: "readback",
41253
- actual: "false"
41254
- })
41255
- };
41256
- }
41257
- if (!Number.isInteger(request.mipLevel) || request.mipLevel < 0) {
41258
- return {
41259
- ok: false,
41260
- error: new RenderTargetDescriptorInvalidError({
41261
- field: "mipLevel",
41262
- value: request.mipLevel,
41263
- expected: "a non-negative integer"
41264
- })
41265
- };
41266
- }
41267
- const mipCount2 = inspected.value.descriptor.mipLevels === 1 ? 1 : Math.floor(
41268
- Math.log2(
41269
- Math.max(inspected.value.descriptor.width, inspected.value.descriptor.height)
41270
- )
41271
- ) + 1;
41272
- if (request.mipLevel >= mipCount2) {
41273
- return {
41274
- ok: false,
41275
- error: new RenderTargetDescriptorInvalidError({
41276
- field: "mipLevel",
41277
- value: request.mipLevel,
41278
- expected: `mipLevel < ${mipCount2}`
41279
- })
41280
- };
41281
- }
41282
- if (request.face !== void 0 && (!Number.isInteger(request.face) || request.face < 0 || request.face > 5 || inspected.value.descriptor.shape !== "cube")) {
41283
- return {
41284
- ok: false,
41285
- error: new RenderTargetDescriptorInvalidError({
41286
- field: "face",
41287
- value: request.face,
41288
- expected: inspected.value.descriptor.shape === "cube" ? "an integer in [0, 5]" : "omitted for a 2d target"
41289
- })
41290
- };
41291
- }
41292
- const ticket = opaqueTicket();
41293
- const extent = resolveRenderTargetMipExtent(inspected.value.descriptor, request.mipLevel);
41294
- const buffer = options.getDevice?.()?.createBuffer({
41295
- label: `render-target-readback.${request.mipLevel}.${request.face ?? 0}`,
41296
- size: Math.ceil(extent.width * bytesPerPixel(inspected.value.descriptor.format) / 256) * 256 * extent.height,
41297
- usage: GPU_BUFFER_USAGE_COPY_DST | GPU_BUFFER_USAGE_MAP_READ,
41298
- mappedAtCreation: false
41299
- });
41300
- if (buffer !== void 0 && !buffer.ok) {
41301
- return {
41302
- ok: false,
41303
- error: new RenderTargetOperationFailedError({
41304
- operation: "readback",
41305
- stage: "allocation",
41306
- generation: inspected.value.generation,
41307
- cause: buffer.error,
41308
- recovery: "retry"
41309
- })
41310
- };
41311
- }
41312
- const internalTicket = createRenderTargetReadbackTicket(target5, {
41313
- deviceGeneration: inspected.value.generation,
41314
- mipLevel: request.mipLevel,
41315
- ...request.face === void 0 ? {} : { face: request.face },
41316
- width: extent.width,
41317
- height: extent.height,
41318
- bytesPerPixel: bytesPerPixel(inspected.value.descriptor.format)
41319
- });
41320
- if (!internalTicket.ok) return internalTicket;
41321
- const record = {
41322
- target: target5,
41323
- request,
41324
- ticket: internalTicket.value,
41325
- ...buffer === void 0 ? {} : { buffer: buffer.value },
41326
- encoded: false
41327
- };
41328
- readbacks.set(ticket, record);
41329
- readbackRecords.add(record);
41330
- return { ok: true, value: ticket };
41331
- },
41332
- async observeTargetReadbacks(receipt, tickets) {
41333
- const results = [];
41334
- for (const publicTicket of tickets) {
41335
- const record = readbacks.get(publicTicket);
41336
- if (record === void 0) {
41337
- return {
41338
- ok: false,
41339
- error: new RenderTargetStateInvalidError({
41340
- operation: "readback",
41341
- reason: "foreign-renderer",
41342
- state: "destroyed",
41343
- generation: receipt.deviceGeneration
41344
- })
41345
- };
41346
- }
41347
- const inspected = owner.inspect(record.target);
41348
- if (!inspected.ok) return inspected;
41349
- if (inspected.value.state !== "active") {
41350
- return {
41351
- ok: false,
41352
- error: new RenderTargetStateInvalidError({
41353
- operation: "readback",
41354
- reason: "uninitialized",
41355
- state: inspected.value.state,
41356
- generation: inspected.value.generation
41357
- })
41358
- };
41359
- }
41360
- if (inspected.value.generation !== receipt.deviceGeneration) {
41361
- return {
41362
- ok: false,
41363
- error: new RenderTargetStateInvalidError({
41364
- operation: "readback",
41365
- reason: "generation-mismatch",
41366
- state: inspected.value.state,
41367
- generation: inspected.value.generation
41368
- })
41369
- };
41370
- }
41371
- const bound = bindRenderTargetReadbackTicket(record.ticket, receipt);
41372
- if (!bound.ok) return bound;
41373
- let bytes2 = new Uint8Array(record.ticket.byteLength);
41374
- if (record.buffer !== void 0 && typeof record.buffer.mapAsync === "function") {
41375
- const mapped = await record.buffer.mapAsync(1);
41376
- if (!mapped.ok) {
41377
- return {
41378
- ok: false,
41379
- error: new RenderTargetOperationFailedError({
41380
- operation: "readback",
41381
- stage: "copy",
41382
- generation: receipt.deviceGeneration,
41383
- cause: mapped.error,
41384
- recovery: "retry"
41385
- })
41386
- };
41387
- }
41388
- const range = mapped.value.getMappedRange();
41389
- if (!range.ok) {
41390
- return {
41391
- ok: false,
41392
- error: new RenderTargetOperationFailedError({
41393
- operation: "readback",
41394
- stage: "copy",
41395
- generation: receipt.deviceGeneration,
41396
- cause: range.error,
41397
- recovery: "retry"
41398
- })
41399
- };
41400
- }
41401
- bytes2 = new Uint8Array(range.value.slice(0));
41402
- mapped.value.unmap();
41403
- }
41404
- const completed = completeRenderTargetReadback(record.ticket, receipt, bytes2);
41405
- if (!completed.ok) return completed;
41406
- results.push({
41407
- ticket: publicTicket,
41408
- bytes: completed.value.bytes,
41409
- frameId: completed.value.frameId,
41410
- deviceGeneration: completed.value.deviceGeneration,
41411
- mipLevel: completed.value.mipLevel,
41412
- ...completed.value.face === void 0 ? {} : { face: completed.value.face },
41413
- bytesPerRow: record.ticket.bytesPerRow,
41414
- byteLength: record.ticket.byteLength
41415
- });
41416
- }
41417
- return { ok: true, value: Object.freeze(results) };
41418
- },
41419
- destroyRenderTarget(target5) {
41420
- const destroyed = owner.destroy(target5);
41421
- if (destroyed.ok) {
41422
- destroyPhysical(options.getDevice?.(), activePhysical.get(target5));
41423
- destroyPhysical(options.getDevice?.(), candidatePhysical.get(target5));
41424
- activePhysical.delete(target5);
41425
- candidatePhysical.delete(target5);
41426
- for (const record of readbackRecords) {
41427
- if (record.target !== target5) continue;
41428
- if (record.buffer !== void 0) options.getDevice?.()?.destroyBuffer(record.buffer);
41429
- readbacks.delete(record.ticket);
41430
- readbackRecords.delete(record);
41431
- }
41432
- targets.delete(target5);
41433
- }
41434
- return destroyed;
41435
- },
41436
- beginFrame() {
41437
- if (disposed) return;
41438
- for (const target5 of targets) {
41439
- const inspected = owner.inspect(target5);
41440
- if (!inspected.ok || inspected.value.state === "active" || inspected.value.state === "candidate") {
41441
- continue;
41442
- }
41443
- stagePhysical(target5);
41444
- }
41445
- },
41446
- onFrameSubmitted(completed = Promise.resolve({ ok: true, value: void 0 })) {
41447
- if (disposed) return;
41448
- const submittedTargets = [...staged];
41449
- staged.clear();
41450
- void completed.then((result) => {
41451
- for (const target5 of submittedTargets) {
41452
- const candidate = owner.inspect(target5);
41453
- if (!candidate.ok || candidate.value.candidate === void 0) continue;
41454
- if (!result.ok) {
41455
- owner.rejectCandidate(target5, candidate.value.candidate.generation, "submit");
41456
- destroyPhysical(options.getDevice?.(), candidatePhysical.get(target5));
41457
- candidatePhysical.delete(target5);
41458
- continue;
41459
- }
41460
- if (options.canPromoteTarget?.(target5) === false) {
41461
- staged.add(target5);
41462
- continue;
41463
- }
41464
- const generation = candidate.value.candidate.generation;
41465
- const physical = candidatePhysical.get(target5);
41466
- if (physical === void 0) {
41467
- owner.rejectCandidate(target5, generation, "submit");
41468
- continue;
41469
- }
41470
- const promoted = owner.promote(target5, generation);
41471
- if (!promoted.ok) {
41472
- destroyPhysical(options.getDevice?.(), physical);
41473
- candidatePhysical.delete(target5);
41474
- continue;
41475
- }
41476
- const previous = activePhysical.get(target5);
41477
- activePhysical.set(target5, physical);
41478
- candidatePhysical.delete(target5);
41479
- destroyPhysical(options.getDevice?.(), previous);
41480
- }
41481
- });
41482
- },
41483
- getPhysicalTarget(target5) {
41484
- return candidatePhysical.get(target5) ?? activePhysical.get(target5);
41485
- },
41486
- encodePendingReadbacks(encoder, faces) {
41487
- for (const record of readbackRecords) {
41488
- if (record.encoded || record.buffer === void 0) continue;
41489
- if (faces !== void 0 && record.ticket.face !== void 0 && !faces.includes(record.ticket.face)) {
41490
- continue;
41491
- }
41492
- const candidate = candidatePhysical.get(record.target);
41493
- const physical = faces !== void 0 && candidate !== void 0 && record.ticket.face !== void 0 && faces.includes(record.ticket.face) ? candidate : activePhysical.get(record.target);
41494
- if (physical === void 0) continue;
41495
- const source = physical.resolveTexture ?? physical.texture;
41496
- encoder.copyTextureToBuffer(
41497
- {
41498
- texture: source,
41499
- mipLevel: record.ticket.mipLevel,
41500
- origin: { x: 0, y: 0, z: record.ticket.face ?? 0 }
41501
- },
41502
- {
41503
- buffer: record.buffer,
41504
- bytesPerRow: record.ticket.bytesPerRow,
41505
- rowsPerImage: record.ticket.height
41506
- },
41507
- [record.ticket.width, record.ticket.height, 1]
41508
- );
41509
- record.encoded = true;
41510
- }
41511
- },
41512
- recover() {
41513
- if (disposed) return;
41514
- const generation = currentGeneration();
41515
- for (const target5 of targets) {
41516
- const inspected = owner.inspect(target5);
41517
- if (!inspected.ok || inspected.value.state !== "active") continue;
41518
- destroyPhysical(options.getDevice?.(), activePhysical.get(target5));
41519
- destroyPhysical(options.getDevice?.(), candidatePhysical.get(target5));
41520
- activePhysical.delete(target5);
41521
- candidatePhysical.delete(target5);
41522
- for (const record of readbackRecords) {
41523
- if (record.target !== target5) continue;
41524
- if (record.buffer !== void 0) options.getDevice?.()?.destroyBuffer(record.buffer);
41525
- readbacks.delete(record.ticket);
41526
- readbackRecords.delete(record);
41527
- }
41528
- const begun = owner.beginRecovery(target5, generation);
41529
- if (begun.ok) owner.finishRecovery(target5);
41530
- }
41531
- },
41532
- dispose() {
41533
- disposed = true;
41534
- for (const target5 of [...targets]) {
41535
- destroyPhysical(options.getDevice?.(), activePhysical.get(target5));
41536
- destroyPhysical(options.getDevice?.(), candidatePhysical.get(target5));
41537
- for (const record of readbackRecords) {
41538
- if (record.target !== target5) continue;
41539
- if (record.buffer !== void 0) options.getDevice?.()?.destroyBuffer(record.buffer);
41540
- readbacks.delete(record.ticket);
41541
- readbackRecords.delete(record);
41542
- }
41543
- activePhysical.delete(target5);
41544
- candidatePhysical.delete(target5);
41545
- owner.destroy(target5);
41546
- }
41547
- targets.clear();
41548
- staged.clear();
41549
- readbackRecords.clear();
41550
- }
41551
- });
41552
- }
41553
-
41554
40264
  // src/assembly/renderer-feature-inspection.ts
41555
40265
  function projectRendererFeatureInspection(featureHost) {
41556
40266
  const featureDiagnostics = featureHost?.diagnostics() ?? Object.freeze([]);
@@ -41967,6 +40677,7 @@ function createSkinPaletteAllocator(device, maxBindingSize, useStorageBuffer = t
41967
40677
  if (allocation === void 0) pendingDirty.set(identity, dirty);
41968
40678
  }
41969
40679
  function releasePersistentSlice(identity) {
40680
+ frameSeenPersistent.delete(identity);
41970
40681
  const allocation = persistent.get(identity);
41971
40682
  persistent.delete(identity);
41972
40683
  pendingDirty.delete(identity);
@@ -44249,11 +42960,11 @@ async function buildReadyWebGPU(rhiDevice, rendererScope, getShader, gpuStore, a
44249
42960
  }
44250
42961
  try {
44251
42962
  getOrBuildPipeline(spec, pipelineDeviceProvider, pipelineCache, modules);
44252
- } catch (err57) {
44253
- if (err57 instanceof PipelineSpecError) throw err57;
42963
+ } catch (err58) {
42964
+ if (err58 instanceof PipelineSpecError) throw err58;
44254
42965
  throw new PipelineSpecError({
44255
42966
  code: "pipeline-build-failed",
44256
- detail: { cause: err57 },
42967
+ detail: { cause: err58 },
44257
42968
  hint: `Boot-time SPEC_CONST pre-warm failed for shader '${spec.shader.id}'; inspect gpuMessage on the cause`
44258
42969
  });
44259
42970
  }
@@ -44407,11 +43118,11 @@ async function buildReadyWebGPU(rhiDevice, rendererScope, getShader, gpuStore, a
44407
43118
  pipelineCache,
44408
43119
  modules
44409
43120
  );
44410
- } catch (err57) {
44411
- if (err57 instanceof PipelineSpecError) throw err57;
43121
+ } catch (err58) {
43122
+ if (err58 instanceof PipelineSpecError) throw err58;
44412
43123
  throw new PipelineSpecError({
44413
43124
  code: "pipeline-build-failed",
44414
- detail: { cause: err57 },
43125
+ detail: { cause: err58 },
44415
43126
  hint: "createRenderPipeline (fxaa fullscreen) failed; inspect gpuMessage"
44416
43127
  });
44417
43128
  }
@@ -44666,11 +43377,11 @@ async function buildReadyWebGPU(rhiDevice, rendererScope, getShader, gpuStore, a
44666
43377
  bloomDownsamplePipelineHandle,
44667
43378
  () => void 0
44668
43379
  );
44669
- } catch (err57) {
44670
- if (err57 instanceof PipelineSpecError) throw err57;
43380
+ } catch (err58) {
43381
+ if (err58 instanceof PipelineSpecError) throw err58;
44671
43382
  throw new PipelineSpecError({
44672
43383
  code: "pipeline-build-failed",
44673
- detail: { cause: err57 },
43384
+ detail: { cause: err58 },
44674
43385
  hint: "createRenderPipeline (bloom-downsample fullscreen) failed; inspect gpuMessage"
44675
43386
  });
44676
43387
  }
@@ -44776,11 +43487,11 @@ async function buildReadyWebGPU(rhiDevice, rendererScope, getShader, gpuStore, a
44776
43487
  bloomUpsamplePipelineHandle,
44777
43488
  () => void 0
44778
43489
  );
44779
- } catch (err57) {
44780
- if (err57 instanceof PipelineSpecError) throw err57;
43490
+ } catch (err58) {
43491
+ if (err58 instanceof PipelineSpecError) throw err58;
44781
43492
  throw new PipelineSpecError({
44782
43493
  code: "pipeline-build-failed",
44783
- detail: { cause: err57 },
43494
+ detail: { cause: err58 },
44784
43495
  hint: "createRenderPipeline (bloom-upsample fullscreen) failed; inspect gpuMessage"
44785
43496
  });
44786
43497
  }
@@ -44881,11 +43592,11 @@ async function buildReadyWebGPU(rhiDevice, rendererScope, getShader, gpuStore, a
44881
43592
  bloomCompositePipelineHandle,
44882
43593
  () => void 0
44883
43594
  );
44884
- } catch (err57) {
44885
- if (err57 instanceof PipelineSpecError) throw err57;
43595
+ } catch (err58) {
43596
+ if (err58 instanceof PipelineSpecError) throw err58;
44886
43597
  throw new PipelineSpecError({
44887
43598
  code: "pipeline-build-failed",
44888
- detail: { cause: err57 },
43599
+ detail: { cause: err58 },
44889
43600
  hint: "createRenderPipeline (bloom-composite fullscreen) failed; inspect gpuMessage"
44890
43601
  });
44891
43602
  }
@@ -45183,11 +43894,11 @@ async function buildReadyWebGPU(rhiDevice, rendererScope, getShader, gpuStore, a
45183
43894
  pipelineCache,
45184
43895
  { ...baseModules, fragmentEntryPoint: "fs_ssao_calc" }
45185
43896
  );
45186
- } catch (err57) {
45187
- if (err57 instanceof PipelineSpecError) throw err57;
43897
+ } catch (err58) {
43898
+ if (err58 instanceof PipelineSpecError) throw err58;
45188
43899
  throw new PipelineSpecError({
45189
43900
  code: "pipeline-build-failed",
45190
- detail: { cause: err57 },
43901
+ detail: { cause: err58 },
45191
43902
  hint: "createRenderPipeline (ssao-calc fullscreen) failed; inspect gpuMessage"
45192
43903
  });
45193
43904
  }
@@ -45218,11 +43929,11 @@ async function buildReadyWebGPU(rhiDevice, rendererScope, getShader, gpuStore, a
45218
43929
  pipelineCache,
45219
43930
  { ...baseModules, fragmentEntryPoint: "fs_ssao_blur" }
45220
43931
  );
45221
- } catch (err57) {
45222
- if (err57 instanceof PipelineSpecError) throw err57;
43932
+ } catch (err58) {
43933
+ if (err58 instanceof PipelineSpecError) throw err58;
45223
43934
  throw new PipelineSpecError({
45224
43935
  code: "pipeline-build-failed",
45225
- detail: { cause: err57 },
43936
+ detail: { cause: err58 },
45226
43937
  hint: "createRenderPipeline (ssao-blur fullscreen) failed; inspect gpuMessage"
45227
43938
  });
45228
43939
  }
@@ -45796,12 +44507,13 @@ function resolveWebGPUVertexBufferLayouts(options) {
45796
44507
  }
45797
44508
 
45798
44509
  // src/assembly/webgpu-renderer.ts
45799
- var nextDerivedSystemId = 0;
45800
44510
  async function tryCreateWebGPURenderer2(canvas, options, pack, bundler) {
45801
44511
  return tryCreateWebGPURenderer(canvas, options, pack, bundler, makeWebGPURenderer);
45802
44512
  }
45803
44513
  async function makeWebGPURenderer(internals) {
44514
+ let publicationTargets;
45804
44515
  let disposed = false;
44516
+ const publicationReceiver = internals.options?.publicationSource === void 0 ? void 0 : new RenderPublicationReceiver(internals.options.publicationSource);
45805
44517
  const observeTiming = observeGpuPassTimingDisabled;
45806
44518
  const frameContinuations = /* @__PURE__ */ new Set();
45807
44519
  let recoveryAttempt = 0;
@@ -46096,7 +44808,8 @@ async function makeWebGPURenderer(internals) {
46096
44808
  gpuStore.configureGpuDevice(
46097
44809
  internals.device,
46098
44810
  packShaderFactory,
46099
- (world, pod) => {
44811
+ (world, pod, source) => {
44812
+ if ("resolveAsset" in world) return ok(source);
46100
44813
  const handle = world.allocSharedRef("EquirectAsset", pod);
46101
44814
  return ok(handle);
46102
44815
  },
@@ -47316,7 +46029,6 @@ async function makeWebGPURenderer(internals) {
47316
46029
  currentGeneration: () => activeDeviceScope.generation,
47317
46030
  renderSystem
47318
46031
  });
47319
- const derivedSystemNames = /* @__PURE__ */ new Map();
47320
46032
  const transformReleases = /* @__PURE__ */ new Map();
47321
46033
  const attachmentOwner = {};
47322
46034
  let frameId = 0;
@@ -47352,6 +46064,13 @@ async function makeWebGPURenderer(internals) {
47352
46064
  renderSystem.setSurfaceDynamicInput(frame);
47353
46065
  },
47354
46066
  attach(world) {
46067
+ if (publicationReceiver !== void 0)
46068
+ return err(
46069
+ new RenderPublicationError({
46070
+ reason: "identity",
46071
+ subject: "publication Renderer has no World attachment"
46072
+ })
46073
+ );
47355
46074
  const attached = this.attachScene(world);
47356
46075
  if (!attached.ok) {
47357
46076
  return err(new RendererContractFailureError("attach", attached.error.hint));
@@ -47368,12 +46087,12 @@ async function makeWebGPURenderer(internals) {
47368
46087
  requestTargetReadback: (target5, request) => renderTargetHost.requestTargetReadback(target5, request),
47369
46088
  destroyRenderTarget: (target5) => renderTargetHost.destroyRenderTarget(target5),
47370
46089
  setProfile(profile) {
47371
- const invalid6 = validateRenderProfile(profile);
47372
- if (invalid6 !== void 0) {
46090
+ const invalid4 = validateRenderProfile(profile);
46091
+ if (invalid4 !== void 0) {
47373
46092
  return err(
47374
46093
  new RendererOperationError("frame-input-invalid", {
47375
46094
  operation: "set-profile",
47376
- cause: new RendererContractFailureError("draw", invalid6)
46095
+ cause: new RendererContractFailureError("draw", invalid4)
47377
46096
  })
47378
46097
  );
47379
46098
  }
@@ -47562,23 +46281,7 @@ async function makeWebGPURenderer(internals) {
47562
46281
  }
47563
46282
  if (attachedWorlds.has(world)) return ok(void 0);
47564
46283
  try {
47565
- const releaseTransforms = registerPropagateTransforms(world);
47566
- const derivedSystemName = `renderDerived:${++nextDerivedSystemId}`;
47567
- const derived = world.addSystem(Update, {
47568
- name: derivedSystemName,
47569
- queries: [],
47570
- fn: (world2) => {
47571
- tilemapChunkExtractSystem(world2, (guid) => assets.lookup(guid));
47572
- const glyphResult = glyphTextLayoutSystem(world2, gpuStore);
47573
- if (!glyphResult.ok) throw glyphResult.error;
47574
- }
47575
- });
47576
- if (!derived.ok) {
47577
- releaseTransforms();
47578
- throw new Error(`failed to register ${derivedSystemName}: ${derived.error.code}`);
47579
- }
47580
- transformReleases.set(world, releaseTransforms);
47581
- derivedSystemNames.set(world, derivedSystemName);
46284
+ transformReleases.set(world, registerRenderSourceSystems(world, assets, gpuStore));
47582
46285
  attachedWorlds.add(world);
47583
46286
  return ok(void 0);
47584
46287
  } catch (cause) {
@@ -47609,11 +46312,6 @@ async function makeWebGPURenderer(internals) {
47609
46312
  }
47610
46313
  }
47611
46314
  renderSystem.detachScene(world);
47612
- const derivedSystemName = derivedSystemNames.get(world);
47613
- if (derivedSystemName !== void 0) {
47614
- world.removeSystem(Update, derivedSystemName);
47615
- derivedSystemNames.delete(world);
47616
- }
47617
46315
  transformReleases.get(world)?.();
47618
46316
  transformReleases.delete(world);
47619
46317
  },
@@ -47797,8 +46495,26 @@ async function makeWebGPURenderer(internals) {
47797
46495
  },
47798
46496
  draw(worldsOrRequest, options) {
47799
46497
  const isFrameRequest = !Array.isArray(worldsOrRequest);
47800
- const frameRequest = isFrameRequest ? worldsOrRequest : void 0;
47801
- const worlds = frameRequest !== void 0 ? frameRequest.leases.map((lease) => attachedLeases.get(lease)).filter((world) => world !== void 0) : worldsOrRequest;
46498
+ const publicationRequest = isFrameRequest && "publication" in worldsOrRequest ? worldsOrRequest : void 0;
46499
+ const frameRequest = isFrameRequest && publicationRequest === void 0 ? worldsOrRequest : void 0;
46500
+ let publication;
46501
+ if (publicationRequest !== void 0) {
46502
+ if (publicationReceiver === void 0)
46503
+ return err(
46504
+ new RenderPublicationError({
46505
+ reason: "identity",
46506
+ subject: "RendererOptions.publicationSource"
46507
+ })
46508
+ );
46509
+ } else if (publicationReceiver !== void 0) {
46510
+ return err(
46511
+ new RenderPublicationError({
46512
+ reason: "identity",
46513
+ subject: "a publication-bound renderer cannot consume local World leases"
46514
+ })
46515
+ );
46516
+ }
46517
+ const worlds = frameRequest !== void 0 ? frameRequest.leases.map((lease) => attachedLeases.get(lease)).filter((world) => world !== void 0) : publicationRequest === void 0 ? worldsOrRequest : [];
47802
46518
  const readLeases = frameRequest !== void 0 ? frameRequest.leases : worlds.map((world) => leasesByWorld.get(world)).every((lease) => lease !== void 0) ? worlds.map((world) => leasesByWorld.get(world)) : void 0;
47803
46519
  const physicsFrameError = derivedPhysicsFrameError(worlds);
47804
46520
  if (physicsFrameError !== void 0) return err(physicsFrameError);
@@ -47833,7 +46549,12 @@ async function makeWebGPURenderer(internals) {
47833
46549
  ...motionBlurDrawOptions(frameRequest),
47834
46550
  ...frameRequest.profileFrame === void 0 ? {} : { profileFrame: frameRequest.profileFrame },
47835
46551
  ...frameRequest.geometryLane === void 0 ? {} : { geometryLane: frameRequest.geometryLane }
47836
- } : options ?? { cameraOwner: 0, resourceOwner: 0 };
46552
+ } : publicationRequest === void 0 ? options ?? { cameraOwner: 0, resourceOwner: 0 } : {
46553
+ cameraOwner: 0,
46554
+ resourceOwner: 0,
46555
+ sampleTimeSeconds: publicationRequest.publication.sampleTimeSeconds,
46556
+ temporalReset: publicationRequest.publication.temporalReset
46557
+ };
47837
46558
  if (disposed) {
47838
46559
  const e = new RhiError({
47839
46560
  code: "rhi-not-available",
@@ -47881,7 +46602,7 @@ async function makeWebGPURenderer(internals) {
47881
46602
  internals.errorRegistry.fire(e);
47882
46603
  return err(e);
47883
46604
  }
47884
- const worldCount = Array.isArray(worlds) ? worlds.length : 0;
46605
+ const worldCount = publicationRequest === void 0 ? Array.isArray(worlds) ? worlds.length : 0 : 1;
47885
46606
  if (worldCount === 0 && internals.device.caps.backendKind === "null") {
47886
46607
  return ok(void 0);
47887
46608
  }
@@ -47897,8 +46618,20 @@ async function makeWebGPURenderer(internals) {
47897
46618
  internals.errorRegistry
47898
46619
  );
47899
46620
  if (!contextConfigured.ok) return contextConfigured;
47900
- renderTargetHost.beginFrame();
47901
46621
  try {
46622
+ if (publicationRequest !== void 0 && publicationReceiver !== void 0) {
46623
+ const accepted = publicationReceiver.accept(publicationRequest.publication);
46624
+ if (!accepted.ok) return accepted;
46625
+ publicationTargets ??= new RenderPublicationTargetReceiver(renderTargetHost);
46626
+ publication = {
46627
+ ...publicationTargets.apply(accepted.value),
46628
+ ...publicationRequest.onFeatureSourceSubmitted === void 0 ? {} : {
46629
+ onFeatureSourceSubmitted: publicationRequest.onFeatureSourceSubmitted
46630
+ }
46631
+ };
46632
+ installPublicationPrograms(assets, publicationRequest.publication.programs);
46633
+ }
46634
+ renderTargetHost.beginFrame();
47902
46635
  const timingHost = internals;
47903
46636
  const timingRequested = isFrameRequest && (frameRequest?.profileFrame !== void 0 || internals.options?.captureGpuTimings === true);
47904
46637
  let volumeTimingCapture;
@@ -47917,7 +46650,13 @@ async function makeWebGPURenderer(internals) {
47917
46650
  graphGeneration: 0
47918
46651
  };
47919
46652
  }
47920
- const submitted = renderSystem.draw(worlds, drawOptions, readLeases, volumeTimingCapture);
46653
+ const submitted = renderSystem.draw(
46654
+ worlds,
46655
+ drawOptions,
46656
+ readLeases,
46657
+ volumeTimingCapture,
46658
+ publication
46659
+ );
47921
46660
  timingHost.observationFrameId = void 0;
47922
46661
  timingHost.observationCaptureDomains = void 0;
47923
46662
  timingHost.gpuPassTimingFrameIdentity = void 0;
@@ -48097,6 +46836,8 @@ async function makeWebGPURenderer(internals) {
48097
46836
  });
48098
46837
  internals.errorRegistry.fire(e);
48099
46838
  return err(e);
46839
+ } finally {
46840
+ publicationReceiver?.releaseVideoFrames();
48100
46841
  }
48101
46842
  },
48102
46843
  async observe(receipt, request) {
@@ -48301,6 +47042,7 @@ async function makeWebGPURenderer(internals) {
48301
47042
  disposed = true;
48302
47043
  for (const world of attachedWorlds) dynamicGeometryHost.invalidateDynamicGeometryWorld(world);
48303
47044
  dynamicGeometry.dispose();
47045
+ publicationReceiver?.dispose();
48304
47046
  for (const continuation of frameContinuations) {
48305
47047
  continuation.terminate({ code: "disposed" });
48306
47048
  }
@@ -48311,11 +47053,6 @@ async function makeWebGPURenderer(internals) {
48311
47053
  }
48312
47054
  for (const world of attachedWorlds) {
48313
47055
  try {
48314
- const derivedSystemName = derivedSystemNames.get(world);
48315
- if (derivedSystemName !== void 0) {
48316
- world.removeSystem(Update, derivedSystemName);
48317
- derivedSystemNames.delete(world);
48318
- }
48319
47056
  transformReleases.get(world)?.();
48320
47057
  transformReleases.delete(world);
48321
47058
  } catch (cause) {