@forgeax/engine-render 0.1.26 → 0.1.28
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.
- package/README.md +215 -0
- package/dist/assembly/dynamic-geometry-host.d.ts +31 -0
- package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -0
- package/dist/assembly/host-contract.d.ts +11 -0
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/renderer-facade.d.ts.map +1 -1
- package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
- package/dist/authoring.mjs +2 -2
- package/dist/{chunk-FJ6P52EE.mjs → chunk-ILQ5MEZF.mjs} +3 -17
- package/dist/chunk-ILQ5MEZF.mjs.map +1 -0
- package/dist/{chunk-HKXTW355.mjs → chunk-IQMKJLNU.mjs} +3 -3
- package/dist/{chunk-HKXTW355.mjs.map → chunk-IQMKJLNU.mjs.map} +1 -1
- package/dist/{chunk-KM2NOX2I.mjs → chunk-J52NMQKR.mjs} +462 -6
- package/dist/chunk-J52NMQKR.mjs.map +1 -0
- package/dist/{chunk-ZZ4YQ474.mjs → chunk-J6KACNOH.mjs} +2 -2
- package/dist/{chunk-ZZ4YQ474.mjs.map → chunk-J6KACNOH.mjs.map} +1 -1
- package/dist/{chunk-ADHHVYLW.mjs → chunk-JAASCMXA.mjs} +3 -3
- package/dist/{chunk-ADHHVYLW.mjs.map → chunk-JAASCMXA.mjs.map} +1 -1
- package/dist/{chunk-TMIASV2N.mjs → chunk-MBU4ZVE7.mjs} +20 -12
- package/dist/chunk-MBU4ZVE7.mjs.map +1 -0
- package/dist/{chunk-E34VL5VI.mjs → chunk-MYJ5RPJO.mjs} +3 -3
- package/dist/{chunk-E34VL5VI.mjs.map → chunk-MYJ5RPJO.mjs.map} +1 -1
- package/dist/{chunk-JDWARUOI.mjs → chunk-RBDBZ5R7.mjs} +17 -3
- package/dist/chunk-RBDBZ5R7.mjs.map +1 -0
- package/dist/{chunk-YUQXSEHG.mjs → chunk-VSL23LZE.mjs} +26 -12
- package/dist/chunk-VSL23LZE.mjs.map +1 -0
- package/dist/construct-renderer.mjs +862 -106
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/gpu-residency.d.ts +10 -5
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/device/mesh-residency-lifetime.d.ts +21 -0
- package/dist/device/mesh-residency-lifetime.d.ts.map +1 -0
- package/dist/dynamic-geometry.d.ts +125 -0
- package/dist/dynamic-geometry.d.ts.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +7 -6
- package/dist/index.mjs.map +1 -1
- package/dist/internal.mjs +7 -7
- package/dist/record/frame.d.ts +1 -1
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +2 -0
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/render-contract.d.ts +12 -0
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-system-extract-tail.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +6 -0
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts +7 -0
- package/dist/render-system.d.ts.map +1 -1
- package/dist/temporal/index.mjs +4 -4
- package/package.json +20 -20
- package/src/__tests__/dynamic-geometry-host.unit.test.ts +1123 -0
- package/src/__tests__/dynamic-geometry.unit.test.ts +233 -0
- package/src/__tests__/factory-contract.integration.test.ts +6 -14
- package/src/__tests__/mesh-submission-lifetime.unit.test.ts +53 -0
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +1 -1
- package/src/assembly/dynamic-geometry-host.ts +839 -0
- package/src/assembly/host-contract.ts +26 -0
- package/src/assembly/renderer-facade.ts +17 -0
- package/src/assembly/webgpu-renderer.ts +49 -2
- package/src/components/sprite-animation.ts +1 -1
- package/src/device/gpu-residency.ts +62 -62
- package/src/device/mesh-residency-lifetime.ts +73 -0
- package/src/dynamic-geometry.ts +736 -0
- package/src/index.ts +16 -0
- package/src/record/__tests__/standard-pbr-ubo-layout.unit.test.ts +68 -1
- package/src/record/frame.ts +2 -0
- package/src/record/main-pass-geometry.ts +13 -4
- package/src/record/main-pass-sprite-draws.ts +2 -0
- package/src/record/render-context.ts +2 -0
- package/src/record/typed-frame-graph.ts +2 -9
- package/src/render-contract.ts +24 -0
- package/src/render-system-extract-tail.ts +3 -2
- package/src/render-system-extract.ts +30 -1
- package/src/render-system.ts +42 -0
- package/dist/chunk-FJ6P52EE.mjs.map +0 -1
- package/dist/chunk-JDWARUOI.mjs.map +0 -1
- package/dist/chunk-KM2NOX2I.mjs.map +0 -1
- package/dist/chunk-TMIASV2N.mjs.map +0 -1
- package/dist/chunk-YUQXSEHG.mjs.map +0 -1
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { inspectVolumetricFog, inspectLodOcclusion, resolveSsrAdmissionGeneration, projectSsrDependencies, inspectReflectionFallback, admitReflectionProbe, DEFAULT_REFLECTION_PROBE_LIMITS, buildReflectionProbeTable, advanceProbeFilter, buildCubeCameraFaceViews, commitProbeFilterStep, resolveReflectionFallbackSource, deriveReflectionFallbackProjection, reflectionFallbackCoverage, reflectionFallbackSourceKey, reflectionFallbackProjectionSignature, createProbeFilterState, ReflectionProbeProjection, admitPointsLines, inspectPointShadow } from './chunk-
|
|
2
|
-
import { createExtendedLightingState, promoteExtendedLightingCandidate, OcclusionRenderRuntime, extractFrames, viewKey, primitiveKey, glyphTextLayoutSystem, projectExtendedLightingInspection, viewKeyId, primitiveKeyId, ProbeBlendSceneProjection, SKYLIGHT_RECOVERY_FALLBACK, InstanceBoundsCache, fingerprintNumericArray, createCookieProjectionMatrixData } from './chunk-
|
|
3
|
-
import './chunk-
|
|
4
|
-
import { MeshFilter, MeshRenderer, Instances, Layer, Visibility, Points, Lines, SortKey, Camera, MotionBlur, DirectionalLight, LightProbe, PointLight, PointLightShadow, SpotLight, Skylight, SkyboxBackground, PostProcessParams, ReflectionProbe, VolumetricFog, projectMeshMaterialBindingObservation, createVisibilityBudget, hasVolumetricFogCapability, CUBE_CAMERA_FACE_ORDER, CAMERA_PROJECTION_ORTHOGRAPHIC } from './chunk-
|
|
5
|
-
import { SpriteInstances, SpriteRegionOverride, TileLayer, decodeSortScope, Tilemap } from './chunk-
|
|
6
|
-
import { assertStorageBufferCap, GpuBuffer, GpuTexture, deriveRenderDataTexture, deriveRenderDataMesh, deriveRenderDataCubemap, createIblPipelines, CUBEMAP_FACE_VERTICES, runIblPrecompute, InstanceProjectionStore, createClusterBinScratch, resetHdrpBuffers, retireTemporalGpuState, PostProcessError, entryHasDepthRead, DEPTH_MIN_PARAMS_BYTE_SIZE, postProcessShaderModuleLabel, resolveSsaoParameters, buildPerFrameBindGroups, postProcessShaderEntrySignature, PipelineSpecError, CAPTURE_VIEW_PROJS, PREFILTER_MIP_LEVELS, selectSwapChainFormat, setIblComposedShaders, POINTS_LINES_MATERIAL_SHADER_ID, createHdrpClusterMembershipBindGroupLayoutDescriptor, createSkylightFallback, buildSpecConstTable, buildLinearLdrMaterialSpecTable, getOrBuildPipeline, cacheKeyOf, REFLECTION_PROBE_VIEW_SLOT_BASE, VIEW_UNIFORM_SLOT_STRIDE, getOrCreateIblCache, postProcessShaderPipelineLabel, createPointsLinesLaneAdapter, computeViewMatrix, computeProjectionMatrix, prepareFrameLighting, warnMultiSkylight, warnMultiSkybox, selectLazyEquirectHandle, driveLazyEquirectProjection, warnZeroLightStandard, writeShadowParamsBuffer, writeSpotModifierTextures, writeHdrpClusterAndSsaoBuffers, resolveSkyboxActive, computeSplitLdrSprite, writeViewUbo, writePointsLinesViewUbo, writeShadowCasterUniforms, uploadMeshSsboBatch, passKindPolicyTable, colorFormatsForPassKind, configureSurface, VIEW_UNIFORM_BUFFER_SIZE, POINTS_LINES_VIEW_BUFFER_SIZE, SHADOW_CASTER_BUFFER_SIZE, FALLBACK_BYTES_PER_ROW, PREFILTER_SIZE, geometryRenderStateForTopology, assembleMaterialWithSkylightEntries, MESH_SSBO_BYTES, createPointsLinesLaneContract, foldDispatchBuckets, CUBE_CAPTURE_VIEW_SLOT_BASE, variantSetFromDefines, cleanPerEntityCache, ensureMeshSsboCapacity, buildFoldDispatchPlan, evaluateFoldBucketUniformCap, incrementFoldedDrawsMetric, writePbrMaterialUboPayload, applyParamSnapshotToUbo, applyMaterialTextureUvScales, residentTextureView, MATERIAL_PER_ENTITY_STRIDE, detectNineSliceScaleTooSmall, resolveGeometryInstanceBuffer, buildFullscreenPostProcessPass, getTemporalGpuState, getTemporalParamsBuffer, getTemporalBindGroupResources, resolveSurfaceFormatPair, resolveSurfaceProfile, encodeMainPass, STANDARD_PBR_UBO_SIZE, abortTemporalGpuSubmit, commitTemporalGpuSubmit, retireTemporalGpuStateAfterFence, hasPendingTemporalGpuSubmit, importRenderPipelineSurface, DEFERRED_COLOR_FORMATS, aggregateTemporalDemand, standardTemporalLaneAdmission, addTypedScenePass, addTypedSsaoPasses, typedFrameClearColor, addTypedSkyboxPass, createStandardSceneDataTarget, addStandardSceneDataPass, addTypedFrameObservationPass, temporalReadIndex, temporalWriteIndex, addReflectionFallbackObservationPass, BYTES_PER_DIRECT_LIGHT_SLOT, createRenderPipelineTarget, resolveOutputDither, addTypedTemporalResolvePass, addTypedBloomPasses, addTypedOutputTransformPass, addTypedFullscreenPass, addTypedCompositePostEffects, standardTopologyVariantSet, geometryRenderStateForPass, standardStorageVariantSet, getOrCreateHdrpBuffers, encodeDirectionalShadowPass, encodePointShadowPass, encodeSpotShadowPass, VIEW_UNIFORM_BYTES, variantSetFromVertexLayoutProjection, isTemporalFullscreenBinding, createFullscreenBindGroup, TYPED_BLOOM_PASS_NAMES } from './chunk-
|
|
1
|
+
import { createDynamicGeometryLifecycle, inspectVolumetricFog, inspectLodOcclusion, resolveSsrAdmissionGeneration, projectSsrDependencies, inspectReflectionFallback, admitReflectionProbe, DEFAULT_REFLECTION_PROBE_LIMITS, buildReflectionProbeTable, advanceProbeFilter, buildCubeCameraFaceViews, commitProbeFilterStep, resolveReflectionFallbackSource, deriveReflectionFallbackProjection, reflectionFallbackCoverage, reflectionFallbackSourceKey, reflectionFallbackProjectionSignature, createProbeFilterState, ReflectionProbeProjection, admitPointsLines, inspectPointShadow, DynamicGeometryError, sameCandidateCredential } from './chunk-J52NMQKR.mjs';
|
|
2
|
+
import { createExtendedLightingState, promoteExtendedLightingCandidate, OcclusionRenderRuntime, extractFrames, viewKey, primitiveKey, glyphTextLayoutSystem, projectExtendedLightingInspection, viewKeyId, primitiveKeyId, ProbeBlendSceneProjection, SKYLIGHT_RECOVERY_FALLBACK, InstanceBoundsCache, fingerprintNumericArray, createCookieProjectionMatrixData } from './chunk-VSL23LZE.mjs';
|
|
3
|
+
import './chunk-ILQ5MEZF.mjs';
|
|
4
|
+
import { MeshFilter, MeshRenderer, Instances, Layer, Visibility, Points, Lines, SortKey, Camera, MotionBlur, DirectionalLight, LightProbe, PointLight, PointLightShadow, SpotLight, Skylight, SkyboxBackground, PostProcessParams, ReflectionProbe, VolumetricFog, projectMeshMaterialBindingObservation, createVisibilityBudget, hasVolumetricFogCapability, CUBE_CAMERA_FACE_ORDER, CAMERA_PROJECTION_ORTHOGRAPHIC } from './chunk-JAASCMXA.mjs';
|
|
5
|
+
import { SpriteInstances, SpriteRegionOverride, TileLayer, decodeSortScope, Tilemap } from './chunk-RBDBZ5R7.mjs';
|
|
6
|
+
import { assertStorageBufferCap, GpuBuffer, GpuTexture, deriveRenderDataTexture, deriveRenderDataMesh, deriveRenderDataCubemap, createIblPipelines, CUBEMAP_FACE_VERTICES, runIblPrecompute, InstanceProjectionStore, createClusterBinScratch, resetHdrpBuffers, retireTemporalGpuState, PostProcessError, entryHasDepthRead, DEPTH_MIN_PARAMS_BYTE_SIZE, postProcessShaderModuleLabel, resolveSsaoParameters, buildPerFrameBindGroups, postProcessShaderEntrySignature, PipelineSpecError, CAPTURE_VIEW_PROJS, PREFILTER_MIP_LEVELS, selectSwapChainFormat, setIblComposedShaders, POINTS_LINES_MATERIAL_SHADER_ID, createHdrpClusterMembershipBindGroupLayoutDescriptor, createSkylightFallback, buildSpecConstTable, buildLinearLdrMaterialSpecTable, getOrBuildPipeline, cacheKeyOf, REFLECTION_PROBE_VIEW_SLOT_BASE, VIEW_UNIFORM_SLOT_STRIDE, getOrCreateIblCache, postProcessShaderPipelineLabel, createPointsLinesLaneAdapter, computeViewMatrix, computeProjectionMatrix, prepareFrameLighting, warnMultiSkylight, warnMultiSkybox, selectLazyEquirectHandle, driveLazyEquirectProjection, warnZeroLightStandard, writeShadowParamsBuffer, writeSpotModifierTextures, writeHdrpClusterAndSsaoBuffers, resolveSkyboxActive, computeSplitLdrSprite, writeViewUbo, writePointsLinesViewUbo, writeShadowCasterUniforms, uploadMeshSsboBatch, passKindPolicyTable, colorFormatsForPassKind, configureSurface, VIEW_UNIFORM_BUFFER_SIZE, POINTS_LINES_VIEW_BUFFER_SIZE, SHADOW_CASTER_BUFFER_SIZE, FALLBACK_BYTES_PER_ROW, PREFILTER_SIZE, geometryRenderStateForTopology, assembleMaterialWithSkylightEntries, MESH_SSBO_BYTES, createPointsLinesLaneContract, foldDispatchBuckets, CUBE_CAPTURE_VIEW_SLOT_BASE, variantSetFromDefines, cleanPerEntityCache, ensureMeshSsboCapacity, buildFoldDispatchPlan, evaluateFoldBucketUniformCap, incrementFoldedDrawsMetric, writePbrMaterialUboPayload, applyParamSnapshotToUbo, applyMaterialTextureUvScales, residentTextureView, MATERIAL_PER_ENTITY_STRIDE, detectNineSliceScaleTooSmall, resolveGeometryInstanceBuffer, buildFullscreenPostProcessPass, getTemporalGpuState, getTemporalParamsBuffer, getTemporalBindGroupResources, resolveSurfaceFormatPair, resolveSurfaceProfile, encodeMainPass, STANDARD_PBR_UBO_SIZE, abortTemporalGpuSubmit, commitTemporalGpuSubmit, retireTemporalGpuStateAfterFence, hasPendingTemporalGpuSubmit, importRenderPipelineSurface, DEFERRED_COLOR_FORMATS, aggregateTemporalDemand, standardTemporalLaneAdmission, addTypedScenePass, addTypedSsaoPasses, typedFrameClearColor, addTypedSkyboxPass, createStandardSceneDataTarget, addStandardSceneDataPass, addTypedFrameObservationPass, temporalReadIndex, temporalWriteIndex, addReflectionFallbackObservationPass, BYTES_PER_DIRECT_LIGHT_SLOT, createRenderPipelineTarget, resolveOutputDither, addTypedTemporalResolvePass, addTypedBloomPasses, addTypedOutputTransformPass, addTypedFullscreenPass, addTypedCompositePostEffects, standardTopologyVariantSet, geometryRenderStateForPass, standardStorageVariantSet, getOrCreateHdrpBuffers, encodeDirectionalShadowPass, encodePointShadowPass, encodeSpotShadowPass, VIEW_UNIFORM_BYTES, variantSetFromVertexLayoutProjection, isTemporalFullscreenBinding, createFullscreenBindGroup, TYPED_BLOOM_PASS_NAMES } from './chunk-MBU4ZVE7.mjs';
|
|
7
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, createSceneDataCatalog, STANDARD_PIPELINE_ID, STANDARD_LIGHT_COUNTS, STANDARD_POST_STAGE_NAMES, resolveVolumetricFogProfile, isSceneDataTarget } from './chunk-
|
|
8
|
+
import { DEFAULT_STANDARD_PROFILE, DEFAULT_CLUSTER_GRID, createSceneDataCatalog, STANDARD_PIPELINE_ID, STANDARD_LIGHT_COUNTS, STANDARD_POST_STAGE_NAMES, resolveVolumetricFogProfile, isSceneDataTarget } from './chunk-MYJ5RPJO.mjs';
|
|
9
9
|
import { SPRITE_PREMULTIPLIED_ALPHA_BLEND } from './chunk-GF523LHF.mjs';
|
|
10
|
-
import { DeviceScope, SKIN_MATERIAL_SHADER_ID, EXTENDED_LIGHTING_REQUIRED_SAMPLED_TEXTURES, GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_MAP_READ, resolveRenderTargetMaterialSource, createRenderTargetMaterialSource, deriveExtendedLightingCapability, GPU_BUFFER_USAGE_VERTEX, GPU_BUFFER_USAGE_INDEX, EXTENDED_LIGHTING_TOPOLOGY, GPU_BUFFER_USAGE_UNIFORM, getTextureIdentity, worldEntityKey, createHdrpBindGroupLayoutDescriptor, createHdrpSkinBindGroupLayoutDescriptor, IES_SLICE_WIDTH, IES_SLICE_HEIGHT, COOKIE_SLICE_SIZE, COOKIE_MATRIX_BYTES, makeZeroCameraFallbackSnapshot, GPU_BUFFER_USAGE_QUERY_RESOLVE, GPU_BUFFER_USAGE_COPY_SRC, buildPbrPipelineLayouts, buildPbrSkinLayouts, GPU_BUFFER_USAGE_STORAGE, resolvePipelineGroup2Contract, GPU_SHADER_STAGE_FRAGMENT, instanceCollectionCacheKey, validateGraphTargetCaptureReadback, isCanonicalStandardPbrMaterialShader, isStandardPbrMaterialShader, buildBindGroupLayoutDescriptor, GPU_BUFFER_USAGE_INDIRECT, buildPbrMaterialUserRegionEntries, extendedLightingSampledTextureCapacityAvailable, GPU_SHADER_STAGE_VERTEX, SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET, shadowCasterVariantSet, SHADOW_CASTER_SHADER_ID, LifecycleTransaction } from './chunk-
|
|
11
|
-
import { RendererContractFailureError, RendererOperationError, STANDARD_OUTPUT_TRANSFORM_FEATURE_ID, RenderTargetStateInvalidError, RenderTargetOperationFailedError, RenderTargetCapabilityMissingError, RenderTargetDescriptorInvalidError, GPU_TEXTURE_USAGE_TEXTURE_BINDING, GPU_TEXTURE_USAGE_COPY_DST, RENDER_PHASE_CATALOG, FrameReceiptStaleError, RenderFeatureStageFailedError, RenderFeatureCapabilityMissingError, RenderFeatureRegistrationConflictError, GPU_TEXTURE_USAGE_RENDER_ATTACHMENT_AND_TEXTURE_BINDING, GPU_TEXTURE_USAGE_COPY_SRC, EnvironmentGenerationFailedError, PointsLinesMaterialUnsupportedError, StandardProfileInvalidError, TransmissionCapabilityMissingError, SHADOW_ATLAS_DEFAULT_LAYERS, GPU_TEXTURE_USAGE_RENDER_ATTACHMENT, TemporalFrameSubmitError, ObservationUnavailableError, RenderFeaturePreparationFailedError, PointsLinesPrepareFailedError, SHADOW_ATLAS_DEFAULT_FACE_SIZE, SceneDataUnavailableError, RenderFeatureDrawRecordingFailedError, PointShadowAtlasUninitializedError, SkinPaletteOverflowError, RenderFeaturePreparedStateMismatchError, FXAA_POST_PROCESS_ID } from './chunk-
|
|
10
|
+
import { DeviceScope, SKIN_MATERIAL_SHADER_ID, EXTENDED_LIGHTING_REQUIRED_SAMPLED_TEXTURES, GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_MAP_READ, resolveRenderTargetMaterialSource, createRenderTargetMaterialSource, deriveExtendedLightingCapability, GPU_BUFFER_USAGE_VERTEX, GPU_BUFFER_USAGE_INDEX, EXTENDED_LIGHTING_TOPOLOGY, GPU_BUFFER_USAGE_UNIFORM, getTextureIdentity, worldEntityKey, createHdrpBindGroupLayoutDescriptor, createHdrpSkinBindGroupLayoutDescriptor, IES_SLICE_WIDTH, IES_SLICE_HEIGHT, COOKIE_SLICE_SIZE, COOKIE_MATRIX_BYTES, makeZeroCameraFallbackSnapshot, GPU_BUFFER_USAGE_QUERY_RESOLVE, GPU_BUFFER_USAGE_COPY_SRC, buildPbrPipelineLayouts, buildPbrSkinLayouts, GPU_BUFFER_USAGE_STORAGE, resolvePipelineGroup2Contract, GPU_SHADER_STAGE_FRAGMENT, instanceCollectionCacheKey, validateGraphTargetCaptureReadback, isCanonicalStandardPbrMaterialShader, isStandardPbrMaterialShader, buildBindGroupLayoutDescriptor, GPU_BUFFER_USAGE_INDIRECT, buildPbrMaterialUserRegionEntries, extendedLightingSampledTextureCapacityAvailable, GPU_SHADER_STAGE_VERTEX, SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET, shadowCasterVariantSet, SHADOW_CASTER_SHADER_ID, LifecycleTransaction } from './chunk-IQMKJLNU.mjs';
|
|
11
|
+
import { RendererContractFailureError, RendererOperationError, STANDARD_OUTPUT_TRANSFORM_FEATURE_ID, RenderTargetStateInvalidError, RenderTargetOperationFailedError, RenderTargetCapabilityMissingError, RenderTargetDescriptorInvalidError, GPU_TEXTURE_USAGE_TEXTURE_BINDING, GPU_TEXTURE_USAGE_COPY_DST, RENDER_PHASE_CATALOG, FrameReceiptStaleError, RenderFeatureStageFailedError, RenderFeatureCapabilityMissingError, RenderFeatureRegistrationConflictError, GPU_TEXTURE_USAGE_RENDER_ATTACHMENT_AND_TEXTURE_BINDING, GPU_TEXTURE_USAGE_COPY_SRC, EnvironmentGenerationFailedError, PointsLinesMaterialUnsupportedError, StandardProfileInvalidError, TransmissionCapabilityMissingError, SHADOW_ATLAS_DEFAULT_LAYERS, GPU_TEXTURE_USAGE_RENDER_ATTACHMENT, TemporalFrameSubmitError, ObservationUnavailableError, RenderFeaturePreparationFailedError, PointsLinesPrepareFailedError, SHADOW_ATLAS_DEFAULT_FACE_SIZE, SceneDataUnavailableError, RenderFeatureDrawRecordingFailedError, PointShadowAtlasUninitializedError, SkinPaletteOverflowError, RenderFeaturePreparedStateMismatchError, FXAA_POST_PROCESS_ID } from './chunk-J6KACNOH.mjs';
|
|
12
12
|
import { ok, err, RhiError, validateDrawArgs } from '@forgeax/engine-rhi';
|
|
13
13
|
import { AssetRegistry, DynamicTextureStore, adaptDynamicTextureDevice, getOrCreateMipmapPipeline, prepareMipmaps, blitMipmapsSync, HANDLE_CUBE, HANDLE_TRIANGLE, HANDLE_QUAD, HANDLE_SPHERE, HANDLE_NINESLICE_QUAD, BuiltinAssetRegistry, resolveAssetHandle, numMipLevels, encodeMipmapLevel, resolveTilesetRuntime, MeshSsboCeilingReachedError, MeshSsboCapacityExceededError } from '@forgeax/engine-assets-runtime';
|
|
14
14
|
import { audioLoader } from '@forgeax/engine-audio-webaudio';
|
|
15
|
-
import { Update } from '@forgeax/engine-ecs';
|
|
15
|
+
import { Update, FixedTime } from '@forgeax/engine-ecs';
|
|
16
16
|
import { createRenderReadLease } from '@forgeax/engine-ecs/projection';
|
|
17
17
|
import { PROCEDURAL_FLOATS_PER_VERTEX, deriveVertexLayoutProjection, deriveVertexBufferLayoutFromProjection, deriveVertexBufferLayout } from '@forgeax/engine-geometry';
|
|
18
18
|
import { GlobalTransform, ChildOf, MorphWeights, collectSubtree, Name, registerPropagateTransforms, Children, Transform } from '@forgeax/engine-scene';
|
|
@@ -284,6 +284,11 @@ function exposeRenderer(renderer) {
|
|
|
284
284
|
})
|
|
285
285
|
);
|
|
286
286
|
},
|
|
287
|
+
prepareDynamicGeometry: (input) => renderer.prepareDynamicGeometry(input),
|
|
288
|
+
acceptDynamicGeometry: (candidate, ordering) => renderer.acceptDynamicGeometry(candidate, ordering),
|
|
289
|
+
dynamicGeometryReceipt: (candidate) => renderer.dynamicGeometryReceipt(candidate),
|
|
290
|
+
cancelDynamicGeometry: (candidate) => renderer.cancelDynamicGeometry(candidate),
|
|
291
|
+
retireDynamicGeometry: (candidate) => renderer.retireDynamicGeometry(candidate),
|
|
287
292
|
createRenderTarget: (descriptor) => renderer.createRenderTarget(descriptor),
|
|
288
293
|
resizeRenderTarget: (target4, descriptor) => renderer.resizeRenderTarget(target4, descriptor),
|
|
289
294
|
createRenderTargetTextureSource: (target4, options) => renderer.createRenderTargetTextureSource(target4, options),
|
|
@@ -498,6 +503,68 @@ function freezeRenderProfile(profile) {
|
|
|
498
503
|
postStages: Object.freeze([...profile.postStages])
|
|
499
504
|
});
|
|
500
505
|
}
|
|
506
|
+
|
|
507
|
+
// src/device/mesh-residency-lifetime.ts
|
|
508
|
+
var MeshResidencyLifetime = class {
|
|
509
|
+
constructor(destroy) {
|
|
510
|
+
this.destroy = destroy;
|
|
511
|
+
}
|
|
512
|
+
destroy;
|
|
513
|
+
leases = 0;
|
|
514
|
+
retired = false;
|
|
515
|
+
eviction;
|
|
516
|
+
submissions = /* @__PURE__ */ new Set();
|
|
517
|
+
waiters = /* @__PURE__ */ new Set();
|
|
518
|
+
get owners() {
|
|
519
|
+
return this.leases;
|
|
520
|
+
}
|
|
521
|
+
retain(evict) {
|
|
522
|
+
this.leases += 1;
|
|
523
|
+
this.eviction = void 0;
|
|
524
|
+
let released = false;
|
|
525
|
+
let completion;
|
|
526
|
+
return {
|
|
527
|
+
track: (submitted) => this.track(submitted),
|
|
528
|
+
release: (shouldEvict) => {
|
|
529
|
+
if (released) return completion;
|
|
530
|
+
released = true;
|
|
531
|
+
this.leases -= 1;
|
|
532
|
+
if (this.leases === 0 && shouldEvict) this.eviction = evict;
|
|
533
|
+
completion = this.submissions.size === 0 ? void 0 : new Promise((resolve) => this.waiters.add(resolve));
|
|
534
|
+
this.flush();
|
|
535
|
+
return completion;
|
|
536
|
+
}
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
track(completed) {
|
|
540
|
+
if (this.submissions.has(completed)) return;
|
|
541
|
+
this.submissions.add(completed);
|
|
542
|
+
const finish = () => {
|
|
543
|
+
this.submissions.delete(completed);
|
|
544
|
+
this.flush();
|
|
545
|
+
};
|
|
546
|
+
void completed.then(finish, finish);
|
|
547
|
+
}
|
|
548
|
+
retire() {
|
|
549
|
+
this.retired = true;
|
|
550
|
+
this.flush();
|
|
551
|
+
}
|
|
552
|
+
flush() {
|
|
553
|
+
if (this.submissions.size !== 0) return;
|
|
554
|
+
if (this.leases === 0 && this.eviction !== void 0) {
|
|
555
|
+
const evict = this.eviction;
|
|
556
|
+
this.eviction = void 0;
|
|
557
|
+
evict();
|
|
558
|
+
}
|
|
559
|
+
if (this.retired && this.leases === 0 && this.destroy !== void 0) {
|
|
560
|
+
const destroy = this.destroy;
|
|
561
|
+
this.destroy = void 0;
|
|
562
|
+
destroy();
|
|
563
|
+
}
|
|
564
|
+
for (const resolve of this.waiters) resolve();
|
|
565
|
+
this.waiters.clear();
|
|
566
|
+
}
|
|
567
|
+
};
|
|
501
568
|
var DYNAMIC_OFFSET_STRIDE = 256;
|
|
502
569
|
var FACE_COUNT = 6;
|
|
503
570
|
var PREFILTER_SUBPASS_COUNT = PREFILTER_MIP_LEVELS * FACE_COUNT;
|
|
@@ -741,6 +808,33 @@ var GpuResidencyCache = class {
|
|
|
741
808
|
// equirect source always resolves to the same cubemap (idempotent, A2).
|
|
742
809
|
cubemapIdempotentMap = /* @__PURE__ */ new Map();
|
|
743
810
|
meshGpuHandles = /* @__PURE__ */ new Map();
|
|
811
|
+
meshLifetimes = /* @__PURE__ */ new WeakMap();
|
|
812
|
+
retiredMeshes = /* @__PURE__ */ new Set();
|
|
813
|
+
meshLifetime(entry) {
|
|
814
|
+
let lifetime = this.meshLifetimes.get(entry);
|
|
815
|
+
if (lifetime === void 0) {
|
|
816
|
+
lifetime = new MeshResidencyLifetime(() => {
|
|
817
|
+
if (!entry.vertexBuffer.isDestroyed) entry.vertexBuffer.destroy();
|
|
818
|
+
if (entry.indexBuffer !== null && !entry.indexBuffer.isDestroyed)
|
|
819
|
+
entry.indexBuffer.destroy();
|
|
820
|
+
this.retiredMeshes.delete(entry);
|
|
821
|
+
});
|
|
822
|
+
this.meshLifetimes.set(entry, lifetime);
|
|
823
|
+
}
|
|
824
|
+
return lifetime;
|
|
825
|
+
}
|
|
826
|
+
/** All resident entries conservatively cover main, shadow and cached GPU-driven draws. */
|
|
827
|
+
trackMeshSubmission(completed) {
|
|
828
|
+
for (const entry of this.meshGpuHandles.values()) this.meshLifetime(entry).track(completed);
|
|
829
|
+
}
|
|
830
|
+
retireMeshEntry(key, entry) {
|
|
831
|
+
if (this.meshGpuHandles.get(key) === entry) {
|
|
832
|
+
this.meshGpuHandles.delete(key);
|
|
833
|
+
this.meshResidencyEpoch += 1;
|
|
834
|
+
}
|
|
835
|
+
this.retiredMeshes.add(entry);
|
|
836
|
+
this.meshLifetime(entry).retire();
|
|
837
|
+
}
|
|
744
838
|
/**
|
|
745
839
|
* Compose a cache key from the raw handle slot and its owning World. The
|
|
746
840
|
* draw-time world index is only a position in one frame's `worlds[]`; it is
|
|
@@ -870,11 +964,12 @@ var GpuResidencyCache = class {
|
|
|
870
964
|
}
|
|
871
965
|
this.cubemapGpuHandles.clear();
|
|
872
966
|
this.cubemapIdempotentMap.clear();
|
|
873
|
-
for (const entry of this.meshGpuHandles.values()) {
|
|
967
|
+
for (const entry of [...this.meshGpuHandles.values(), ...this.retiredMeshes]) {
|
|
874
968
|
destroyBuf(entry.vertexBuffer);
|
|
875
969
|
if (entry.indexBuffer !== null) destroyBuf(entry.indexBuffer);
|
|
876
970
|
}
|
|
877
971
|
this.meshGpuHandles.clear();
|
|
972
|
+
this.retiredMeshes.clear();
|
|
878
973
|
}
|
|
879
974
|
/** Number of candidate-owned GPU resources currently held by this cache. */
|
|
880
975
|
recoveryResourceCount() {
|
|
@@ -886,7 +981,7 @@ var GpuResidencyCache = class {
|
|
|
886
981
|
cubemapResources += 1;
|
|
887
982
|
}
|
|
888
983
|
}
|
|
889
|
-
return this.meshGpuHandles.size + this.textureGpuHandles.size + this.samplerGpuHandles.size + cubemapResources;
|
|
984
|
+
return this.meshGpuHandles.size + this.retiredMeshes.size + this.textureGpuHandles.size + this.samplerGpuHandles.size + cubemapResources;
|
|
890
985
|
}
|
|
891
986
|
/** Candidate root for the cache owner, not a scalar readiness marker. */
|
|
892
987
|
createRecoveryRoot(scope) {
|
|
@@ -941,24 +1036,12 @@ var GpuResidencyCache = class {
|
|
|
941
1036
|
const id = this.worldKey(handleSlot(handle), worldId);
|
|
942
1037
|
const entry = this.meshGpuHandles.get(id);
|
|
943
1038
|
if (entry === void 0) return { freed: 0, errors: [] };
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
if (r.ok) {
|
|
950
|
-
freed += 1;
|
|
951
|
-
} else {
|
|
952
|
-
errors.push(r.error);
|
|
953
|
-
if (this.errorRegistry) this.errorRegistry.fire(r.error);
|
|
954
|
-
}
|
|
955
|
-
}
|
|
1039
|
+
if (this.meshLifetime(entry).owners > 0) return { freed: 0, errors: [] };
|
|
1040
|
+
this.retireMeshEntry(id, entry);
|
|
1041
|
+
return {
|
|
1042
|
+
freed: Number(entry.vertexBuffer.isDestroyed) + Number(entry.indexBuffer?.isDestroyed ?? false),
|
|
1043
|
+
errors: []
|
|
956
1044
|
};
|
|
957
|
-
destroyBuf(entry.vertexBuffer);
|
|
958
|
-
if (entry.indexBuffer !== null) destroyBuf(entry.indexBuffer);
|
|
959
|
-
this.meshGpuHandles.delete(id);
|
|
960
|
-
this.meshResidencyEpoch += 1;
|
|
961
|
-
return { freed: freed > 0 ? 1 : 0, errors };
|
|
962
1045
|
}
|
|
963
1046
|
evictCubemap(id) {
|
|
964
1047
|
const entry = this.cubemapGpuHandles.get(id);
|
|
@@ -989,7 +1072,6 @@ var GpuResidencyCache = class {
|
|
|
989
1072
|
releaseUnreferenced(liveSet) {
|
|
990
1073
|
let freed = 0;
|
|
991
1074
|
const errors = [];
|
|
992
|
-
let meshResidencyChanged = false;
|
|
993
1075
|
let materialResidencyChanged = false;
|
|
994
1076
|
const liveSlots = new Set([...liveSet].map((slot) => String(slot)));
|
|
995
1077
|
const isLiveKey = (key) => {
|
|
@@ -1037,34 +1119,12 @@ var GpuResidencyCache = class {
|
|
|
1037
1119
|
}
|
|
1038
1120
|
}
|
|
1039
1121
|
}
|
|
1040
|
-
for (const key of this.meshGpuHandles
|
|
1041
|
-
if (!isLiveKey(key)) {
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
if (!entry.vertexBuffer.isDestroyed) {
|
|
1045
|
-
const r = entry.vertexBuffer.destroy();
|
|
1046
|
-
if (r.ok) {
|
|
1047
|
-
freed += 1;
|
|
1048
|
-
} else {
|
|
1049
|
-
errors.push(r.error);
|
|
1050
|
-
if (this.errorRegistry) this.errorRegistry.fire(r.error);
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
if (entry.indexBuffer !== null && !entry.indexBuffer.isDestroyed) {
|
|
1054
|
-
const r = entry.indexBuffer.destroy();
|
|
1055
|
-
if (r.ok) {
|
|
1056
|
-
freed += 1;
|
|
1057
|
-
} else {
|
|
1058
|
-
errors.push(r.error);
|
|
1059
|
-
if (this.errorRegistry) this.errorRegistry.fire(r.error);
|
|
1060
|
-
}
|
|
1061
|
-
}
|
|
1062
|
-
this.meshGpuHandles.delete(key);
|
|
1063
|
-
meshResidencyChanged = true;
|
|
1064
|
-
}
|
|
1122
|
+
for (const [key, entry] of this.meshGpuHandles) {
|
|
1123
|
+
if (!isLiveKey(key) && this.meshLifetime(entry).owners === 0) {
|
|
1124
|
+
this.retireMeshEntry(key, entry);
|
|
1125
|
+
freed += Number(entry.vertexBuffer.isDestroyed) + Number(entry.indexBuffer?.isDestroyed ?? false);
|
|
1065
1126
|
}
|
|
1066
1127
|
}
|
|
1067
|
-
if (meshResidencyChanged) this.meshResidencyEpoch += 1;
|
|
1068
1128
|
if (materialResidencyChanged) this.materialResourceEpoch += 1;
|
|
1069
1129
|
return { freed, errors };
|
|
1070
1130
|
}
|
|
@@ -1184,19 +1244,20 @@ var GpuResidencyCache = class {
|
|
|
1184
1244
|
getMeshGpuHandles(handle, worldId = 0) {
|
|
1185
1245
|
return this.meshGpuHandles.get(this.worldKey(handleSlot(handle), worldId));
|
|
1186
1246
|
}
|
|
1187
|
-
/**
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1247
|
+
/** Candidate leases retain the concrete allocation even after cache invalidation. */
|
|
1248
|
+
retainMeshResidency(handle, worldId = 0) {
|
|
1249
|
+
const key = this.worldKey(handleSlot(handle), worldId);
|
|
1250
|
+
const entry = this.meshGpuHandles.get(key);
|
|
1251
|
+
return entry === void 0 ? void 0 : this.meshLifetime(entry).retain(() => {
|
|
1252
|
+
if (this.meshGpuHandles.get(key) === entry) this.invalidateMesh(handle, worldId);
|
|
1253
|
+
else this.meshLifetime(entry).retire();
|
|
1254
|
+
});
|
|
1255
|
+
}
|
|
1256
|
+
/** In-place author changes immediately miss the cache; old submissions keep their allocation. */
|
|
1192
1257
|
invalidateMesh(handle, worldId = 0) {
|
|
1193
1258
|
const key = this.worldKey(handleSlot(toShared(handle)), worldId);
|
|
1194
1259
|
const entry = this.meshGpuHandles.get(key);
|
|
1195
|
-
if (entry
|
|
1196
|
-
entry.vertexBuffer.destroy();
|
|
1197
|
-
if (entry.indexBuffer !== null) entry.indexBuffer.destroy();
|
|
1198
|
-
this.meshGpuHandles.delete(key);
|
|
1199
|
-
this.meshResidencyEpoch += 1;
|
|
1260
|
+
if (entry !== void 0) this.retireMeshEntry(key, entry);
|
|
1200
1261
|
}
|
|
1201
1262
|
ensureResident(handle, pod, worldId = 0, lodMeshes = []) {
|
|
1202
1263
|
const id = handleSlot(handle);
|
|
@@ -13460,12 +13521,6 @@ function ensureCompiledFrameGraph(internals, frameState, pipelineState, camera,
|
|
|
13460
13521
|
}
|
|
13461
13522
|
function executeCompiledFrameGraph(internals, frameState, frame, encoder, runPass, frameHooks, readbackFaces, onSubmitted, timingCapture) {
|
|
13462
13523
|
const graph = frameState.compiledFrameGraph;
|
|
13463
|
-
const invalidatePostProcessModule = (id) => {
|
|
13464
|
-
const entry = internals.lookupPostProcess?.(id);
|
|
13465
|
-
if (entry !== void 0) {
|
|
13466
|
-
internals.invalidateShaderModule?.(postProcessShaderModuleLabel(id, entry.source));
|
|
13467
|
-
}
|
|
13468
|
-
};
|
|
13469
13524
|
const rejectTemporalFrame = () => {
|
|
13470
13525
|
if (frameState.temporalFrameInput === void 0) return;
|
|
13471
13526
|
frameState.temporalFrameTransaction.commit({ accepted: false });
|
|
@@ -13753,7 +13808,6 @@ function executeCompiledFrameGraph(internals, frameState, frame, encoder, runPas
|
|
|
13753
13808
|
frameState.activeTemporalGpuState = stagedGpuState;
|
|
13754
13809
|
if (previousGpuState !== void 0 && previousGpuState !== stagedGpuState) {
|
|
13755
13810
|
internals.clearPostProcessPipelineCache?.("forgeax.taa-resolve");
|
|
13756
|
-
invalidatePostProcessModule("forgeax.taa-resolve");
|
|
13757
13811
|
retireTemporalGpuStateAfterFence(
|
|
13758
13812
|
previousGpuState,
|
|
13759
13813
|
internals.device.queue,
|
|
@@ -13783,7 +13837,6 @@ function executeCompiledFrameGraph(internals, frameState, frame, encoder, runPas
|
|
|
13783
13837
|
}
|
|
13784
13838
|
if (stagedTemporalCommit.kind === "off") {
|
|
13785
13839
|
internals.clearPostProcessPipelineCache?.("forgeax.taa-resolve");
|
|
13786
|
-
invalidatePostProcessModule("forgeax.taa-resolve");
|
|
13787
13840
|
const activeGpuState = frameState.activeTemporalGpuState;
|
|
13788
13841
|
if (activeGpuState !== void 0) {
|
|
13789
13842
|
retireTemporalGpuStateAfterFence(
|
|
@@ -14678,7 +14731,7 @@ function updateVolumetricFogInspection(frameState, fog, lights, prepared, submit
|
|
|
14678
14731
|
memoryBytes: 0
|
|
14679
14732
|
});
|
|
14680
14733
|
}
|
|
14681
|
-
function recordFrame(internals, world, cameras, lights, renderables, transparentDispatch, frameState, dispatchCounts, bindGroupCounts, skylight, skylightCount, skybox, skyboxCount, postProcessParams, worlds = [world], profilePhase, gpuDriven, renderReadLeases, featureGraphCandidate, pointsLinesOwner, cubeCapture, environmentSignature = "", fogSignature = "", environmentReady = true, transmissionDemand, volumetricFog, timingCapture) {
|
|
14734
|
+
function recordFrame(internals, world, cameras, lights, renderables, transparentDispatch, frameState, dispatchCounts, bindGroupCounts, skylight, skylightCount, skybox, skyboxCount, postProcessParams, worlds = [world], profilePhase, gpuDriven, renderReadLeases, featureGraphCandidate, pointsLinesOwner, cubeCapture, environmentSignature = "", fogSignature = "", environmentReady = true, transmissionDemand, volumetricFog, timingCapture, onRenderableDraw) {
|
|
14682
14735
|
frameState.reflectionFallbackObservationSource = void 0;
|
|
14683
14736
|
frameState.reflectionFallbackCompletion = void 0;
|
|
14684
14737
|
let activeCameras = cameras;
|
|
@@ -15223,6 +15276,7 @@ function recordFrame(internals, world, cameras, lights, renderables, transparent
|
|
|
15223
15276
|
...cubeCapture?.reflectionProbes === void 0 ? {} : { reflectionProbes: cubeCapture.reflectionProbes },
|
|
15224
15277
|
pointsLines: pointsLinesOwner,
|
|
15225
15278
|
materialBgAssemblyCache: frameState.materialBgAssemblyCache,
|
|
15279
|
+
...onRenderableDraw === void 0 ? {} : { onRenderableDraw },
|
|
15226
15280
|
directionalShadowCacheReuse: directionalShadowCache.reuse,
|
|
15227
15281
|
...profilePhase !== void 0 ? { profilePhase } : {}
|
|
15228
15282
|
};
|
|
@@ -21967,6 +22021,7 @@ function createRenderSystem(internals) {
|
|
|
21967
22021
|
);
|
|
21968
22022
|
let releaseProfilerCatalog = phaseCatalogRegistration?.ok === true ? phaseCatalogRegistration.value : void 0;
|
|
21969
22023
|
let preparedWorlds = [];
|
|
22024
|
+
let lastSubmittedDynamicGeometryBindings = /* @__PURE__ */ new WeakMap();
|
|
21970
22025
|
let latestCamera;
|
|
21971
22026
|
const pointsLinesOwner = new StandardPointsLinesOwner(internals);
|
|
21972
22027
|
const instanceCollections = new InstanceProjectionStore();
|
|
@@ -22952,6 +23007,14 @@ function createRenderSystem(internals) {
|
|
|
22952
23007
|
releaseProfilerCatalog?.();
|
|
22953
23008
|
releaseProfilerCatalog = void 0;
|
|
22954
23009
|
},
|
|
23010
|
+
invalidateGeometryHistory() {
|
|
23011
|
+
frameState.temporalFrameTransaction.reset("signature-change");
|
|
23012
|
+
frameState.temporalFrame = void 0;
|
|
23013
|
+
frameState.temporalFrameInput = void 0;
|
|
23014
|
+
frameState.lastSuccessfulTemporalView = void 0;
|
|
23015
|
+
frameState.successfulTemporalFrameIndex = 0;
|
|
23016
|
+
frameState.pendingTemporalCommit = { kind: "none" };
|
|
23017
|
+
},
|
|
22955
23018
|
get renderScene() {
|
|
22956
23019
|
return {
|
|
22957
23020
|
...persistentRenderScene.inspect(),
|
|
@@ -23131,6 +23194,8 @@ function createRenderSystem(internals) {
|
|
|
23131
23194
|
const profileSession = internals.profiler?.activeSession();
|
|
23132
23195
|
let ownsProfileFrame = false;
|
|
23133
23196
|
let submitted = false;
|
|
23197
|
+
lastSubmittedDynamicGeometryBindings = /* @__PURE__ */ new WeakMap();
|
|
23198
|
+
const frameConsumedDynamicGeometryBindings = /* @__PURE__ */ new WeakMap();
|
|
23134
23199
|
if (profileSession !== void 0 && opts.profileFrame === void 0) {
|
|
23135
23200
|
try {
|
|
23136
23201
|
ownsProfileFrame = profileSession.beginFrame(++directFrameId).ok;
|
|
@@ -23655,9 +23720,23 @@ function createRenderSystem(internals) {
|
|
|
23655
23720
|
environmentReady && environment !== void 0,
|
|
23656
23721
|
persistentRenderScene.transmissionTopologyDemand(),
|
|
23657
23722
|
volumetricFog,
|
|
23658
|
-
timingCapture
|
|
23723
|
+
timingCapture,
|
|
23724
|
+
(entry) => {
|
|
23725
|
+
const renderable = entry.source;
|
|
23726
|
+
const world = compositionWorlds[renderable.worldId];
|
|
23727
|
+
if (world === void 0) return;
|
|
23728
|
+
let bindings = frameConsumedDynamicGeometryBindings.get(world);
|
|
23729
|
+
if (bindings === void 0) {
|
|
23730
|
+
bindings = /* @__PURE__ */ new Map();
|
|
23731
|
+
frameConsumedDynamicGeometryBindings.set(world, bindings);
|
|
23732
|
+
}
|
|
23733
|
+
bindings.set(renderable.entityKey, renderable.assetHandle);
|
|
23734
|
+
}
|
|
23659
23735
|
)
|
|
23660
23736
|
);
|
|
23737
|
+
if (submitted) {
|
|
23738
|
+
lastSubmittedDynamicGeometryBindings = frameConsumedDynamicGeometryBindings;
|
|
23739
|
+
}
|
|
23661
23740
|
if (submitted) {
|
|
23662
23741
|
try {
|
|
23663
23742
|
internals.recoveryColdWorkGuard?.finish();
|
|
@@ -23750,16 +23829,16 @@ function createRenderSystem(internals) {
|
|
|
23750
23829
|
if (!retired.ok) internals.errorRegistry.fire(retired.error);
|
|
23751
23830
|
}
|
|
23752
23831
|
}
|
|
23753
|
-
} catch (
|
|
23832
|
+
} catch (err42) {
|
|
23754
23833
|
if (!submitted) {
|
|
23755
23834
|
internals.getPipelineState()?.perPassResources.discardBloomResources?.();
|
|
23756
23835
|
}
|
|
23757
|
-
const innerError =
|
|
23758
|
-
name:
|
|
23759
|
-
code:
|
|
23760
|
-
message:
|
|
23761
|
-
detail:
|
|
23762
|
-
} :
|
|
23836
|
+
const innerError = err42 instanceof PipelineSpecError ? {
|
|
23837
|
+
name: err42.name,
|
|
23838
|
+
code: err42.code,
|
|
23839
|
+
message: err42.message,
|
|
23840
|
+
detail: err42.detail
|
|
23841
|
+
} : err42 instanceof RhiError ? err42 : { code: "unknown", message: String(err42), name: err42?.name };
|
|
23763
23842
|
internals.errorRegistry.fire(
|
|
23764
23843
|
new RhiError({
|
|
23765
23844
|
code: "webgpu-runtime-error",
|
|
@@ -23778,6 +23857,10 @@ function createRenderSystem(internals) {
|
|
|
23778
23857
|
}
|
|
23779
23858
|
return submitted;
|
|
23780
23859
|
},
|
|
23860
|
+
isDynamicGeometryConsumed(world, entity, meshHandle) {
|
|
23861
|
+
if (!Number.isInteger(entity) || meshHandle === void 0) return false;
|
|
23862
|
+
return lastSubmittedDynamicGeometryBindings.get(world)?.get(entity) === meshHandle;
|
|
23863
|
+
},
|
|
23781
23864
|
pipelineDispatchCounts: dispatchCounts,
|
|
23782
23865
|
observeCurrentFrame(options) {
|
|
23783
23866
|
const currentFrameId = frameState.frameNumber - 1;
|
|
@@ -25085,6 +25168,641 @@ function deviceOptionsForAdapter(adapter, options) {
|
|
|
25085
25168
|
const admission = deriveDeviceFeatureAdmission(adapter, options);
|
|
25086
25169
|
return admission.requiredFeatures.length === 0 && admission.requiredLimits === void 0 ? void 0 : admission;
|
|
25087
25170
|
}
|
|
25171
|
+
function fixedStepOf(world) {
|
|
25172
|
+
try {
|
|
25173
|
+
return world.getResource(FixedTime).tick;
|
|
25174
|
+
} catch {
|
|
25175
|
+
return void 0;
|
|
25176
|
+
}
|
|
25177
|
+
}
|
|
25178
|
+
function hasRenderableBinding(world, entity) {
|
|
25179
|
+
if (entity === void 0 || !Number.isInteger(entity)) return false;
|
|
25180
|
+
const transform = world.get(entity, Transform);
|
|
25181
|
+
const mesh = world.get(entity, MeshFilter);
|
|
25182
|
+
const material = world.get(entity, MeshRenderer);
|
|
25183
|
+
if (!transform.ok || !mesh.ok || !material.ok) return false;
|
|
25184
|
+
return true;
|
|
25185
|
+
}
|
|
25186
|
+
function meshHandleOf(world, entity) {
|
|
25187
|
+
if (entity === void 0 || !Number.isInteger(entity)) return void 0;
|
|
25188
|
+
const mesh = world.get(entity, MeshFilter);
|
|
25189
|
+
if (!mesh.ok) return void 0;
|
|
25190
|
+
return mesh.value.assetHandle;
|
|
25191
|
+
}
|
|
25192
|
+
function hasMaterialIdentity(world, entity, mesh, identity) {
|
|
25193
|
+
if (identity === void 0) return true;
|
|
25194
|
+
const normalized = identity.trim();
|
|
25195
|
+
if (normalized.length === 0 || entity === void 0) return false;
|
|
25196
|
+
const material = world.get(entity, MeshRenderer);
|
|
25197
|
+
if (!material.ok) return false;
|
|
25198
|
+
const values = material.value.materials ?? [];
|
|
25199
|
+
if (mesh.materialSlots.some((slot) => slot.sourceKey === normalized || slot.slotName === normalized))
|
|
25200
|
+
return true;
|
|
25201
|
+
if (mesh.materialSlots.some(
|
|
25202
|
+
(slot) => slot.defaultMaterial !== void 0 && AssetGuid.format(slot.defaultMaterial).toLowerCase() === normalized.toLowerCase()
|
|
25203
|
+
))
|
|
25204
|
+
return true;
|
|
25205
|
+
return values.some((value) => {
|
|
25206
|
+
if (String(value) === normalized) return true;
|
|
25207
|
+
try {
|
|
25208
|
+
const resolved2 = world.sharedRefs.resolve(value);
|
|
25209
|
+
if (!resolved2.ok || typeof resolved2.value !== "object" || resolved2.value === null)
|
|
25210
|
+
return false;
|
|
25211
|
+
const payload = resolved2.value;
|
|
25212
|
+
return payload.sourceKey === normalized || payload.guid === normalized;
|
|
25213
|
+
} catch {
|
|
25214
|
+
return false;
|
|
25215
|
+
}
|
|
25216
|
+
});
|
|
25217
|
+
}
|
|
25218
|
+
function hasMeshBinding(world, handle) {
|
|
25219
|
+
try {
|
|
25220
|
+
const query = world.query({ read: [MeshFilter] }).unwrap();
|
|
25221
|
+
for (const row of query) {
|
|
25222
|
+
if (Number(row.get(MeshFilter).assetHandle) === handle) return true;
|
|
25223
|
+
}
|
|
25224
|
+
} catch {
|
|
25225
|
+
}
|
|
25226
|
+
return false;
|
|
25227
|
+
}
|
|
25228
|
+
function ownsMeshPayload(world, meshHandle, mesh) {
|
|
25229
|
+
if (meshHandle === void 0) return false;
|
|
25230
|
+
try {
|
|
25231
|
+
const resolved2 = world.sharedRefs.resolve(meshHandle);
|
|
25232
|
+
return resolved2.ok && resolved2.value === mesh;
|
|
25233
|
+
} catch {
|
|
25234
|
+
return false;
|
|
25235
|
+
}
|
|
25236
|
+
}
|
|
25237
|
+
function physicsPublicationOf(world, entity, admitting = false) {
|
|
25238
|
+
try {
|
|
25239
|
+
const physics = world.getResource("PhysicsWorld");
|
|
25240
|
+
return admitting ? physics.getDerivedAdmission?.(entity) : physics.getDerivedPublication?.(entity);
|
|
25241
|
+
} catch {
|
|
25242
|
+
return void 0;
|
|
25243
|
+
}
|
|
25244
|
+
}
|
|
25245
|
+
function createDynamicGeometryHost(options) {
|
|
25246
|
+
const { lifecycle, attachedWorlds, getGpuStore, currentGeneration, isConsumedByRenderFrame } = options;
|
|
25247
|
+
const hostCandidates = /* @__PURE__ */ new Map();
|
|
25248
|
+
let observedGeneration = -1;
|
|
25249
|
+
const releaseMeshLease = (record) => {
|
|
25250
|
+
if (!record.meshLeaseHeld) return void 0;
|
|
25251
|
+
const released = record.world.sharedRefs.release(record.meshHandle);
|
|
25252
|
+
if (!released.ok) {
|
|
25253
|
+
return new DynamicGeometryError(
|
|
25254
|
+
"dynamic-geometry-invalid",
|
|
25255
|
+
"the Renderer candidate lease remains a live World shared reference",
|
|
25256
|
+
"retain the MeshAsset handle until candidate cancellation or ECS acceptance completes",
|
|
25257
|
+
{ candidateId: record.candidate.candidateId, actual: released.error }
|
|
25258
|
+
);
|
|
25259
|
+
}
|
|
25260
|
+
record.meshLeaseHeld = false;
|
|
25261
|
+
return void 0;
|
|
25262
|
+
};
|
|
25263
|
+
const releasePreviousMeshLease = (record) => {
|
|
25264
|
+
if (!record.previousMeshLeaseHeld) return void 0;
|
|
25265
|
+
const released = record.world.sharedRefs.release(record.previousMeshHandle);
|
|
25266
|
+
if (!released.ok) {
|
|
25267
|
+
return new DynamicGeometryError(
|
|
25268
|
+
"dynamic-geometry-invalid",
|
|
25269
|
+
"the previous ECS MeshFilter binding remains a live World shared reference",
|
|
25270
|
+
"retain the previous MeshAsset until candidate cancellation, retirement, or invalidation completes",
|
|
25271
|
+
{ candidateId: record.candidate.candidateId, actual: released.error }
|
|
25272
|
+
);
|
|
25273
|
+
}
|
|
25274
|
+
record.previousMeshLeaseHeld = false;
|
|
25275
|
+
return void 0;
|
|
25276
|
+
};
|
|
25277
|
+
const releaseMeshLeases = (record) => {
|
|
25278
|
+
const candidateError = releaseMeshLease(record);
|
|
25279
|
+
const previousError = releasePreviousMeshLease(record);
|
|
25280
|
+
return candidateError ?? previousError;
|
|
25281
|
+
};
|
|
25282
|
+
const synchronizeGeneration = () => {
|
|
25283
|
+
const generation = currentGeneration();
|
|
25284
|
+
lifecycle.invalidateGeneration(generation);
|
|
25285
|
+
if (observedGeneration !== generation) {
|
|
25286
|
+
for (const [candidateId, record] of hostCandidates) {
|
|
25287
|
+
if (record.generation !== generation) {
|
|
25288
|
+
hostCandidates.delete(candidateId);
|
|
25289
|
+
scheduleCandidateCleanup(record, true);
|
|
25290
|
+
}
|
|
25291
|
+
}
|
|
25292
|
+
observedGeneration = generation;
|
|
25293
|
+
}
|
|
25294
|
+
return generation;
|
|
25295
|
+
};
|
|
25296
|
+
const candidateRecord2 = (candidate) => {
|
|
25297
|
+
const record = hostCandidates.get(candidate.candidateId);
|
|
25298
|
+
if (record === void 0 || !sameCandidateCredential(candidate, record.candidate))
|
|
25299
|
+
return void 0;
|
|
25300
|
+
return record;
|
|
25301
|
+
};
|
|
25302
|
+
const cleanupCandidateResidency = (record, force = false) => record.residency?.release(force || !hasMeshBinding(record.world, record.meshHandle));
|
|
25303
|
+
const scheduleCandidateCleanup = (record, force = false) => {
|
|
25304
|
+
hostCandidates.delete(record.candidate.candidateId);
|
|
25305
|
+
const completion = cleanupCandidateResidency(record, force);
|
|
25306
|
+
const finish = () => {
|
|
25307
|
+
releaseMeshLeases(record);
|
|
25308
|
+
lifecycle.finalizeRetirement(record.candidate);
|
|
25309
|
+
if (hostCandidates.get(record.candidate.candidateId) === record)
|
|
25310
|
+
hostCandidates.delete(record.candidate.candidateId);
|
|
25311
|
+
};
|
|
25312
|
+
if (completion === void 0) finish();
|
|
25313
|
+
else void completion.then(finish, finish);
|
|
25314
|
+
return completion;
|
|
25315
|
+
};
|
|
25316
|
+
return {
|
|
25317
|
+
prepareDynamicGeometry(input) {
|
|
25318
|
+
const generation = synchronizeGeneration();
|
|
25319
|
+
const world = input.world;
|
|
25320
|
+
if (!attachedWorlds.has(world))
|
|
25321
|
+
return err$1(
|
|
25322
|
+
new DynamicGeometryError(
|
|
25323
|
+
"dynamic-geometry-world-not-attached",
|
|
25324
|
+
"the candidate World is attached to this Renderer",
|
|
25325
|
+
"call renderer.attach(world) before preparing dynamic geometry"
|
|
25326
|
+
)
|
|
25327
|
+
);
|
|
25328
|
+
if (input.entity === void 0 || !hasRenderableBinding(world, input.entity)) {
|
|
25329
|
+
return err$1(
|
|
25330
|
+
new DynamicGeometryError(
|
|
25331
|
+
"dynamic-geometry-invalid",
|
|
25332
|
+
"the candidate entity and MeshAsset payload belong to the attached World",
|
|
25333
|
+
"attach MeshFilter/MeshRenderer and pass the payload resolved by its World shared handle",
|
|
25334
|
+
{ actual: { entity: input.entity, meshHandle: input.meshHandle } }
|
|
25335
|
+
)
|
|
25336
|
+
);
|
|
25337
|
+
}
|
|
25338
|
+
if (input.meshHandle === void 0)
|
|
25339
|
+
return err$1(
|
|
25340
|
+
new DynamicGeometryError(
|
|
25341
|
+
"dynamic-geometry-gpu-not-ready",
|
|
25342
|
+
"the standard MeshAsset shared handle is present before Renderer admission",
|
|
25343
|
+
"allocate the MeshAsset through world.allocSharedRef and retry after asset projection",
|
|
25344
|
+
{ actual: { entity: input.entity, meshHandle: input.meshHandle } }
|
|
25345
|
+
)
|
|
25346
|
+
);
|
|
25347
|
+
const meshHandle = input.meshHandle;
|
|
25348
|
+
if (!ownsMeshPayload(world, meshHandle, input.mesh) || !hasMaterialIdentity(world, input.entity, input.mesh, input.materialIdentity)) {
|
|
25349
|
+
return err$1(
|
|
25350
|
+
new DynamicGeometryError(
|
|
25351
|
+
"dynamic-geometry-invalid",
|
|
25352
|
+
"the candidate MeshAsset and material identity belong to the attached World",
|
|
25353
|
+
"pass the payload resolved by its World shared handle and its live material slot identity",
|
|
25354
|
+
{ actual: { entity: input.entity, meshHandle } }
|
|
25355
|
+
)
|
|
25356
|
+
);
|
|
25357
|
+
}
|
|
25358
|
+
const fixedStep = fixedStepOf(world);
|
|
25359
|
+
if (fixedStep === void 0) {
|
|
25360
|
+
return err$1(
|
|
25361
|
+
new DynamicGeometryError(
|
|
25362
|
+
"dynamic-geometry-ordering-required",
|
|
25363
|
+
"the attached World exposes its ECS FixedTime resource",
|
|
25364
|
+
"prepare geometry from an initialized World fixed-step schedule"
|
|
25365
|
+
)
|
|
25366
|
+
);
|
|
25367
|
+
}
|
|
25368
|
+
const previousMeshHandle = meshHandleOf(world, input.entity);
|
|
25369
|
+
if (previousMeshHandle === void 0) {
|
|
25370
|
+
return err$1(
|
|
25371
|
+
new DynamicGeometryError(
|
|
25372
|
+
"dynamic-geometry-invalid",
|
|
25373
|
+
"the prepared entity retains a live MeshFilter binding",
|
|
25374
|
+
"keep the ECS render entity alive while staging geometry",
|
|
25375
|
+
{ actual: { entity: input.entity } }
|
|
25376
|
+
)
|
|
25377
|
+
);
|
|
25378
|
+
}
|
|
25379
|
+
const previousRetained = world.sharedRefs.retain(previousMeshHandle);
|
|
25380
|
+
if (!previousRetained.ok)
|
|
25381
|
+
return err$1(
|
|
25382
|
+
new DynamicGeometryError(
|
|
25383
|
+
"dynamic-geometry-invalid",
|
|
25384
|
+
"the previous ECS MeshFilter binding remains live for Renderer preparation",
|
|
25385
|
+
"retain the current MeshAsset handle before staging replacement geometry",
|
|
25386
|
+
{ actual: previousRetained.error }
|
|
25387
|
+
)
|
|
25388
|
+
);
|
|
25389
|
+
const retained = world.sharedRefs.retain(meshHandle);
|
|
25390
|
+
if (!retained.ok) {
|
|
25391
|
+
const releasedPrevious = world.sharedRefs.release(previousMeshHandle);
|
|
25392
|
+
return releasedPrevious.ok ? err$1(
|
|
25393
|
+
new DynamicGeometryError(
|
|
25394
|
+
"dynamic-geometry-invalid",
|
|
25395
|
+
"the candidate MeshAsset shared reference remains live for Renderer preparation",
|
|
25396
|
+
"retain the World-owned MeshAsset handle before staging a candidate",
|
|
25397
|
+
{ actual: retained.error }
|
|
25398
|
+
)
|
|
25399
|
+
) : err$1(
|
|
25400
|
+
new DynamicGeometryError(
|
|
25401
|
+
"dynamic-geometry-invalid",
|
|
25402
|
+
"candidate preparation leaves both MeshAsset leases recoverable",
|
|
25403
|
+
"repair the World shared references before retrying geometry preparation",
|
|
25404
|
+
{ actual: { candidate: retained.error, previous: releasedPrevious.error } }
|
|
25405
|
+
)
|
|
25406
|
+
);
|
|
25407
|
+
}
|
|
25408
|
+
const releaseRetained = () => {
|
|
25409
|
+
const releasedCandidate = world.sharedRefs.release(meshHandle);
|
|
25410
|
+
const releasedPrevious = world.sharedRefs.release(previousMeshHandle);
|
|
25411
|
+
if (!releasedCandidate.ok || !releasedPrevious.ok)
|
|
25412
|
+
return new DynamicGeometryError(
|
|
25413
|
+
"dynamic-geometry-invalid",
|
|
25414
|
+
"failed candidate preparation releases both World shared-reference leases",
|
|
25415
|
+
"repair the World shared references before retrying geometry preparation",
|
|
25416
|
+
{
|
|
25417
|
+
actual: {
|
|
25418
|
+
candidate: releasedCandidate.ok ? void 0 : releasedCandidate.error,
|
|
25419
|
+
previous: releasedPrevious.ok ? void 0 : releasedPrevious.error
|
|
25420
|
+
}
|
|
25421
|
+
}
|
|
25422
|
+
);
|
|
25423
|
+
return void 0;
|
|
25424
|
+
};
|
|
25425
|
+
const prepared = lifecycle.prepare({ ...input, fixedStep }, generation);
|
|
25426
|
+
if (!prepared.ok) {
|
|
25427
|
+
const released = releaseRetained();
|
|
25428
|
+
return released === void 0 ? prepared : err$1(released);
|
|
25429
|
+
}
|
|
25430
|
+
const residencyStore = getGpuStore();
|
|
25431
|
+
const resident = residencyStore.ensureResident(
|
|
25432
|
+
meshHandle,
|
|
25433
|
+
prepared.value.mesh,
|
|
25434
|
+
input.world
|
|
25435
|
+
);
|
|
25436
|
+
if (!resident.ok) {
|
|
25437
|
+
lifecycle.cancel(prepared.value);
|
|
25438
|
+
cleanupCandidateResidency({
|
|
25439
|
+
candidate: prepared.value,
|
|
25440
|
+
world,
|
|
25441
|
+
entity: input.entity,
|
|
25442
|
+
meshHandle,
|
|
25443
|
+
residency: void 0});
|
|
25444
|
+
const released = releaseMeshLeases({
|
|
25445
|
+
candidate: prepared.value,
|
|
25446
|
+
world,
|
|
25447
|
+
entity: input.entity,
|
|
25448
|
+
previousMeshHandle,
|
|
25449
|
+
meshHandle,
|
|
25450
|
+
meshLeaseHeld: true,
|
|
25451
|
+
previousMeshLeaseHeld: true
|
|
25452
|
+
});
|
|
25453
|
+
if (released !== void 0) return err$1(released);
|
|
25454
|
+
return err$1(
|
|
25455
|
+
new DynamicGeometryError(
|
|
25456
|
+
"dynamic-geometry-gpu-failed",
|
|
25457
|
+
"the standard MeshAsset has GPU residency for the active device generation",
|
|
25458
|
+
"wait for Renderer.initialization or repair the RHI resource failure before retrying",
|
|
25459
|
+
{ candidateId: prepared.value.candidateId, actual: resident.error }
|
|
25460
|
+
)
|
|
25461
|
+
);
|
|
25462
|
+
}
|
|
25463
|
+
const residency = residencyStore.retainMeshResidency(meshHandle, world);
|
|
25464
|
+
if (residency === void 0) {
|
|
25465
|
+
lifecycle.cancel(prepared.value);
|
|
25466
|
+
residencyStore.invalidateMesh(meshHandle, world);
|
|
25467
|
+
const released = releaseRetained();
|
|
25468
|
+
return released === void 0 ? err$1(
|
|
25469
|
+
new DynamicGeometryError(
|
|
25470
|
+
"dynamic-geometry-gpu-failed",
|
|
25471
|
+
"the standard MeshAsset retains a shared GPU residency owner",
|
|
25472
|
+
"repair the active GPU residency before retrying geometry preparation",
|
|
25473
|
+
{ candidateId: prepared.value.candidateId }
|
|
25474
|
+
)
|
|
25475
|
+
) : err$1(released);
|
|
25476
|
+
}
|
|
25477
|
+
hostCandidates.set(prepared.value.candidateId, {
|
|
25478
|
+
candidate: prepared.value,
|
|
25479
|
+
world,
|
|
25480
|
+
entity: input.entity,
|
|
25481
|
+
previousMeshHandle,
|
|
25482
|
+
meshHandle,
|
|
25483
|
+
residency,
|
|
25484
|
+
generation,
|
|
25485
|
+
meshLeaseHeld: true,
|
|
25486
|
+
previousMeshLeaseHeld: true,
|
|
25487
|
+
accepted: false,
|
|
25488
|
+
published: false
|
|
25489
|
+
});
|
|
25490
|
+
return prepared;
|
|
25491
|
+
},
|
|
25492
|
+
acceptDynamicGeometry(candidate, ordering) {
|
|
25493
|
+
synchronizeGeneration();
|
|
25494
|
+
const world = candidate.world;
|
|
25495
|
+
const hostRecordById = hostCandidates.get(candidate.candidateId);
|
|
25496
|
+
const hostRecord = candidateRecord2(candidate);
|
|
25497
|
+
if (hostRecord === void 0 && hostRecordById !== void 0)
|
|
25498
|
+
return err$1(
|
|
25499
|
+
new DynamicGeometryError(
|
|
25500
|
+
"dynamic-geometry-receipt-mismatch",
|
|
25501
|
+
"admission uses the exact host candidate owner and lifecycle credential",
|
|
25502
|
+
"discard the altered credential and use the value returned by preparation",
|
|
25503
|
+
{ candidateId: candidate.candidateId }
|
|
25504
|
+
)
|
|
25505
|
+
);
|
|
25506
|
+
if (hostRecord !== void 0 && candidate.state !== "prepared")
|
|
25507
|
+
return err$1(
|
|
25508
|
+
new DynamicGeometryError(
|
|
25509
|
+
"dynamic-geometry-candidate-state",
|
|
25510
|
+
"admission consumes a prepared candidate exactly once",
|
|
25511
|
+
"retain the accepted or published candidate receipt instead of admitting it again",
|
|
25512
|
+
{ candidateId: candidate.candidateId }
|
|
25513
|
+
)
|
|
25514
|
+
);
|
|
25515
|
+
if (ordering === void 0 || !attachedWorlds.has(world) || ordering.world !== candidate.world)
|
|
25516
|
+
return err$1(
|
|
25517
|
+
new DynamicGeometryError(
|
|
25518
|
+
"dynamic-geometry-world-not-attached",
|
|
25519
|
+
"candidate and fixed-step ordering belong to the same attached World",
|
|
25520
|
+
"attach the World and submit its PhysicsWorld ordering before accepting geometry",
|
|
25521
|
+
{ candidateId: candidate.candidateId }
|
|
25522
|
+
)
|
|
25523
|
+
);
|
|
25524
|
+
if (!candidate.gpuReady)
|
|
25525
|
+
return err$1(
|
|
25526
|
+
new DynamicGeometryError(
|
|
25527
|
+
"dynamic-geometry-gpu-not-ready",
|
|
25528
|
+
"candidate has standard GPU residency before acceptance",
|
|
25529
|
+
"prepare with an existing MeshAsset shared handle and repair residency failures",
|
|
25530
|
+
{ candidateId: candidate.candidateId }
|
|
25531
|
+
)
|
|
25532
|
+
);
|
|
25533
|
+
if (hostRecord === void 0 || !hasRenderableBinding(world, candidate.entity) || !hasMaterialIdentity(world, candidate.entity, candidate.mesh, candidate.materialIdentity))
|
|
25534
|
+
return err$1(
|
|
25535
|
+
new DynamicGeometryError(
|
|
25536
|
+
"dynamic-geometry-invalid",
|
|
25537
|
+
"the candidate is bound to a live ECS MeshFilter and MeshRenderer",
|
|
25538
|
+
"keep the candidate MeshFilter binding intact until the consuming draw",
|
|
25539
|
+
{ candidateId: candidate.candidateId }
|
|
25540
|
+
)
|
|
25541
|
+
);
|
|
25542
|
+
if (meshHandleOf(world, candidate.entity) !== hostRecord.previousMeshHandle)
|
|
25543
|
+
return err$1(
|
|
25544
|
+
new DynamicGeometryError(
|
|
25545
|
+
"dynamic-geometry-invalid",
|
|
25546
|
+
"the old MeshFilter binding remains visible until candidate acceptance",
|
|
25547
|
+
"do not replace the live ECS binding while geometry is prepared",
|
|
25548
|
+
{ candidateId: candidate.candidateId }
|
|
25549
|
+
)
|
|
25550
|
+
);
|
|
25551
|
+
const currentFixedStep = fixedStepOf(world);
|
|
25552
|
+
if (currentFixedStep === void 0 || candidate.fixedStep === void 0 || candidate.fixedStep > currentFixedStep || ordering.fixedStep !== currentFixedStep)
|
|
25553
|
+
return err$1(
|
|
25554
|
+
new DynamicGeometryError(
|
|
25555
|
+
"dynamic-geometry-ordering-required",
|
|
25556
|
+
"ordering matches the current World tick, no earlier than preparation",
|
|
25557
|
+
"accept a prepared candidate during the current fixed-step admission",
|
|
25558
|
+
{
|
|
25559
|
+
candidateId: candidate.candidateId,
|
|
25560
|
+
actual: {
|
|
25561
|
+
candidate: candidate.fixedStep,
|
|
25562
|
+
currentFixedStep,
|
|
25563
|
+
ordering: ordering.fixedStep
|
|
25564
|
+
}
|
|
25565
|
+
}
|
|
25566
|
+
)
|
|
25567
|
+
);
|
|
25568
|
+
if (candidate.physicsEntity !== void 0) {
|
|
25569
|
+
const publication = physicsPublicationOf(world, candidate.physicsEntity, true);
|
|
25570
|
+
if (publication === void 0 || publication.fixedStep !== currentFixedStep || publication.revision !== candidate.revision)
|
|
25571
|
+
return err$1(
|
|
25572
|
+
new DynamicGeometryError(
|
|
25573
|
+
"dynamic-geometry-ordering-required",
|
|
25574
|
+
"candidate physicsEntity has the active paired PhysicsWorld admission",
|
|
25575
|
+
"accept geometry inside admitDerivedShapeCandidate commitGeometry, before physics step",
|
|
25576
|
+
{ candidateId: candidate.candidateId, actual: publication }
|
|
25577
|
+
)
|
|
25578
|
+
);
|
|
25579
|
+
}
|
|
25580
|
+
const superseded = [...hostCandidates.values()].filter(
|
|
25581
|
+
(record) => record.candidate.candidateId !== candidate.candidateId && record.world === world && record.entity === candidate.entity && !record.published
|
|
25582
|
+
);
|
|
25583
|
+
const accepted = lifecycle.accept(candidate, ordering);
|
|
25584
|
+
if (!accepted.ok) return accepted;
|
|
25585
|
+
const swapped = world.set(candidate.entity, MeshFilter, {
|
|
25586
|
+
assetHandle: hostRecord.meshHandle
|
|
25587
|
+
});
|
|
25588
|
+
if (!swapped.ok) {
|
|
25589
|
+
lifecycle.cancel(accepted.value);
|
|
25590
|
+
hostCandidates.delete(candidate.candidateId);
|
|
25591
|
+
cleanupCandidateResidency(hostRecord);
|
|
25592
|
+
const released = releaseMeshLeases(hostRecord);
|
|
25593
|
+
if (released !== void 0) return err$1(released);
|
|
25594
|
+
return err$1(
|
|
25595
|
+
new DynamicGeometryError(
|
|
25596
|
+
"dynamic-geometry-invalid",
|
|
25597
|
+
"the candidate MeshFilter swap commits through the ECS write barrier",
|
|
25598
|
+
"restore the live entity and retry from a fresh candidate",
|
|
25599
|
+
{ candidateId: candidate.candidateId, actual: swapped.error }
|
|
25600
|
+
)
|
|
25601
|
+
);
|
|
25602
|
+
}
|
|
25603
|
+
hostRecord.candidate = accepted.value;
|
|
25604
|
+
hostRecord.accepted = true;
|
|
25605
|
+
options.onTopologyChanged?.();
|
|
25606
|
+
for (const record of superseded) {
|
|
25607
|
+
const completion = cleanupCandidateResidency(record);
|
|
25608
|
+
const cancelled = lifecycle.cancel(record.candidate, completion);
|
|
25609
|
+
if (!cancelled.ok && cancelled.error.code !== "dynamic-geometry-candidate-not-found") {
|
|
25610
|
+
const restored = world.set(candidate.entity, MeshFilter, {
|
|
25611
|
+
assetHandle: hostRecord.previousMeshHandle
|
|
25612
|
+
});
|
|
25613
|
+
lifecycle.cancel(accepted.value);
|
|
25614
|
+
hostCandidates.delete(candidate.candidateId);
|
|
25615
|
+
cleanupCandidateResidency(hostRecord);
|
|
25616
|
+
releasePreviousMeshLease(hostRecord);
|
|
25617
|
+
return err$1(
|
|
25618
|
+
new DynamicGeometryError(
|
|
25619
|
+
"dynamic-geometry-invalid",
|
|
25620
|
+
"candidate supersession cancels the prior credential atomically",
|
|
25621
|
+
"keep the prior ECS binding and candidate lifecycle intact when supersession fails",
|
|
25622
|
+
{
|
|
25623
|
+
candidateId: candidate.candidateId,
|
|
25624
|
+
actual: {
|
|
25625
|
+
cancelled: cancelled.error,
|
|
25626
|
+
restored: restored.ok ? void 0 : restored.error
|
|
25627
|
+
}
|
|
25628
|
+
}
|
|
25629
|
+
)
|
|
25630
|
+
);
|
|
25631
|
+
}
|
|
25632
|
+
hostCandidates.delete(record.candidate.candidateId);
|
|
25633
|
+
scheduleCandidateCleanup(record);
|
|
25634
|
+
}
|
|
25635
|
+
return accepted;
|
|
25636
|
+
},
|
|
25637
|
+
dynamicGeometryReceipt(candidate) {
|
|
25638
|
+
synchronizeGeneration();
|
|
25639
|
+
return lifecycle.receipt(candidate);
|
|
25640
|
+
},
|
|
25641
|
+
cancelDynamicGeometry(candidate) {
|
|
25642
|
+
synchronizeGeneration();
|
|
25643
|
+
const record = candidateRecord2(candidate);
|
|
25644
|
+
if (record === void 0) {
|
|
25645
|
+
if (hostCandidates.has(candidate.candidateId))
|
|
25646
|
+
return err$1(
|
|
25647
|
+
new DynamicGeometryError(
|
|
25648
|
+
"dynamic-geometry-receipt-mismatch",
|
|
25649
|
+
"cancellation uses the exact host candidate owner and lifecycle credential",
|
|
25650
|
+
"discard the altered credential and use the value returned by preparation",
|
|
25651
|
+
{ candidateId: candidate.candidateId }
|
|
25652
|
+
)
|
|
25653
|
+
);
|
|
25654
|
+
return lifecycle.cancel(candidate);
|
|
25655
|
+
}
|
|
25656
|
+
if (!record.accepted && candidate.state !== "prepared" || record.accepted && !record.published && candidate.state !== "accepted" || record.published && candidate.state !== "accepted" && candidate.state !== "published")
|
|
25657
|
+
return err$1(
|
|
25658
|
+
new DynamicGeometryError(
|
|
25659
|
+
"dynamic-geometry-receipt-mismatch",
|
|
25660
|
+
"cancellation uses the candidate state issued by the host lifecycle",
|
|
25661
|
+
"discard the altered credential and use the value returned by preparation or acceptance",
|
|
25662
|
+
{ candidateId: candidate.candidateId }
|
|
25663
|
+
)
|
|
25664
|
+
);
|
|
25665
|
+
if (record.published)
|
|
25666
|
+
return err$1(
|
|
25667
|
+
new DynamicGeometryError(
|
|
25668
|
+
"dynamic-geometry-candidate-state",
|
|
25669
|
+
"published geometry remains until its receipt retires",
|
|
25670
|
+
"retire the receipt-bound candidate instead of cancelling it",
|
|
25671
|
+
{ candidateId: candidate.candidateId }
|
|
25672
|
+
)
|
|
25673
|
+
);
|
|
25674
|
+
if (record.accepted) {
|
|
25675
|
+
const currentHandle = meshHandleOf(record.world, record.entity);
|
|
25676
|
+
if (currentHandle !== record.meshHandle && currentHandle !== record.previousMeshHandle)
|
|
25677
|
+
return err$1(
|
|
25678
|
+
new DynamicGeometryError(
|
|
25679
|
+
"dynamic-geometry-invalid",
|
|
25680
|
+
"cancel does not overwrite a newer ECS MeshFilter binding",
|
|
25681
|
+
"reconcile the live entity before cancelling this candidate",
|
|
25682
|
+
{ candidateId: candidate.candidateId }
|
|
25683
|
+
)
|
|
25684
|
+
);
|
|
25685
|
+
if (currentHandle === record.meshHandle) {
|
|
25686
|
+
const restored = record.world.set(record.entity, MeshFilter, {
|
|
25687
|
+
assetHandle: record.previousMeshHandle
|
|
25688
|
+
});
|
|
25689
|
+
if (!restored.ok)
|
|
25690
|
+
return err$1(
|
|
25691
|
+
new DynamicGeometryError(
|
|
25692
|
+
"dynamic-geometry-invalid",
|
|
25693
|
+
"cancel restores the previous MeshFilter through the ECS write barrier",
|
|
25694
|
+
"restore the entity before retrying cancellation",
|
|
25695
|
+
{ candidateId: candidate.candidateId, actual: restored.error }
|
|
25696
|
+
)
|
|
25697
|
+
);
|
|
25698
|
+
}
|
|
25699
|
+
}
|
|
25700
|
+
const completion = cleanupCandidateResidency(record);
|
|
25701
|
+
const cancelled = lifecycle.cancel(candidate, completion);
|
|
25702
|
+
if (!cancelled.ok) return cancelled;
|
|
25703
|
+
hostCandidates.delete(candidate.candidateId);
|
|
25704
|
+
scheduleCandidateCleanup(record);
|
|
25705
|
+
return cancelled;
|
|
25706
|
+
},
|
|
25707
|
+
invalidateDynamicGeometryWorld(world) {
|
|
25708
|
+
const doomed = [...hostCandidates.values()].filter((record) => record.world === world);
|
|
25709
|
+
const completions = doomed.map((record) => scheduleCandidateCleanup(record, true)).filter((completion) => completion !== void 0);
|
|
25710
|
+
lifecycle.invalidateWorld(
|
|
25711
|
+
world,
|
|
25712
|
+
completions.length === 0 ? void 0 : Promise.allSettled(completions)
|
|
25713
|
+
);
|
|
25714
|
+
},
|
|
25715
|
+
retireDynamicGeometry(candidate) {
|
|
25716
|
+
synchronizeGeneration();
|
|
25717
|
+
const record = candidateRecord2(candidate);
|
|
25718
|
+
if (record === void 0) {
|
|
25719
|
+
if (hostCandidates.has(candidate.candidateId))
|
|
25720
|
+
return err$1(
|
|
25721
|
+
new DynamicGeometryError(
|
|
25722
|
+
"dynamic-geometry-receipt-mismatch",
|
|
25723
|
+
"retirement uses the exact host candidate owner and lifecycle credential",
|
|
25724
|
+
"discard the altered credential and use the value returned by acceptance",
|
|
25725
|
+
{ candidateId: candidate.candidateId }
|
|
25726
|
+
)
|
|
25727
|
+
);
|
|
25728
|
+
return lifecycle.retire(candidate);
|
|
25729
|
+
}
|
|
25730
|
+
if (candidate.state !== "accepted" && candidate.state !== "published")
|
|
25731
|
+
return err$1(
|
|
25732
|
+
new DynamicGeometryError(
|
|
25733
|
+
"dynamic-geometry-receipt-mismatch",
|
|
25734
|
+
"retirement uses a candidate state issued by the host lifecycle",
|
|
25735
|
+
"discard the altered credential and use the value returned by acceptance",
|
|
25736
|
+
{ candidateId: candidate.candidateId }
|
|
25737
|
+
)
|
|
25738
|
+
);
|
|
25739
|
+
if (meshHandleOf(record.world, record.entity) === record.meshHandle)
|
|
25740
|
+
return err$1(
|
|
25741
|
+
new DynamicGeometryError(
|
|
25742
|
+
"dynamic-geometry-invalid",
|
|
25743
|
+
"retirement does not evict the MeshFilter that still consumes the candidate",
|
|
25744
|
+
"swap the ECS MeshFilter through its write barrier before retiring this geometry",
|
|
25745
|
+
{ candidateId: candidate.candidateId }
|
|
25746
|
+
)
|
|
25747
|
+
);
|
|
25748
|
+
const retired = lifecycle.retire(candidate);
|
|
25749
|
+
if (!retired.ok) return retired;
|
|
25750
|
+
record.candidate = Object.freeze({ ...record.candidate, state: "retired" });
|
|
25751
|
+
const previousReleased = releasePreviousMeshLease(record);
|
|
25752
|
+
if (previousReleased !== void 0) return err$1(previousReleased);
|
|
25753
|
+
scheduleCandidateCleanup(record);
|
|
25754
|
+
return retired;
|
|
25755
|
+
},
|
|
25756
|
+
publishDynamicGeometry(frame, worlds, fixedStep) {
|
|
25757
|
+
synchronizeGeneration();
|
|
25758
|
+
const targetWorlds = /* @__PURE__ */ new Set();
|
|
25759
|
+
for (const candidateWorld of worlds ?? attachedWorlds) {
|
|
25760
|
+
const world = candidateWorld;
|
|
25761
|
+
if (attachedWorlds.has(world)) targetWorlds.add(world);
|
|
25762
|
+
}
|
|
25763
|
+
const receipts = [];
|
|
25764
|
+
for (const world of targetWorlds) {
|
|
25765
|
+
const worldFixedStep = fixedStepOf(world);
|
|
25766
|
+
if (worldFixedStep === void 0) continue;
|
|
25767
|
+
const publicationFixedStep = fixedStep ?? worldFixedStep;
|
|
25768
|
+
receipts.push(
|
|
25769
|
+
...lifecycle.publishFrame(frame, [world], publicationFixedStep, (candidate) => {
|
|
25770
|
+
const candidateWorld = candidate.world;
|
|
25771
|
+
if (candidateWorld !== world || !attachedWorlds.has(candidateWorld)) return false;
|
|
25772
|
+
const hostRecord = candidateRecord2(candidate);
|
|
25773
|
+
if (hostRecord === void 0 || !hostRecord.accepted || !hasRenderableBinding(candidateWorld, candidate.entity) || meshHandleOf(candidateWorld, candidate.entity) !== candidate.meshHandle || !hasMaterialIdentity(
|
|
25774
|
+
candidateWorld,
|
|
25775
|
+
candidate.entity,
|
|
25776
|
+
candidate.mesh,
|
|
25777
|
+
candidate.materialIdentity
|
|
25778
|
+
))
|
|
25779
|
+
return false;
|
|
25780
|
+
if (!isConsumedByRenderFrame(candidate)) return false;
|
|
25781
|
+
const actualFixedStep = fixedStep ?? worldFixedStep;
|
|
25782
|
+
if (candidate.fixedStep === void 0 || actualFixedStep === void 0) return false;
|
|
25783
|
+
if (worldFixedStep !== actualFixedStep || actualFixedStep < candidate.fixedStep)
|
|
25784
|
+
return false;
|
|
25785
|
+
if (candidate.physicsEntity !== void 0) {
|
|
25786
|
+
const publication = physicsPublicationOf(candidateWorld, candidate.physicsEntity);
|
|
25787
|
+
if (publication === void 0 || publication.fixedStep < candidate.fixedStep || publication.revision !== candidate.revision)
|
|
25788
|
+
return false;
|
|
25789
|
+
}
|
|
25790
|
+
return true;
|
|
25791
|
+
})
|
|
25792
|
+
);
|
|
25793
|
+
}
|
|
25794
|
+
for (const receipt of receipts) {
|
|
25795
|
+
const record = hostCandidates.get(receipt.candidateId);
|
|
25796
|
+
if (record !== void 0) {
|
|
25797
|
+
record.published = true;
|
|
25798
|
+
if (receipt.frame.completed !== void 0)
|
|
25799
|
+
record.residency?.track(receipt.frame.completed);
|
|
25800
|
+
}
|
|
25801
|
+
}
|
|
25802
|
+
return receipts;
|
|
25803
|
+
}
|
|
25804
|
+
};
|
|
25805
|
+
}
|
|
25088
25806
|
var STANDARD_PBR_REQUIRED_SAMPLED_TEXTURES2 = 17;
|
|
25089
25807
|
function selectHdrpPbrPrewarmVariants(manifestEntry, storageBufferCapable, extendedLightingShaderAvailableOrTransmissionCapable = true, transmissionCapable = true, directionalPcssAvailable = true, projectorAvailable = true) {
|
|
25090
25808
|
const variants = manifestEntry?.variants ?? [];
|
|
@@ -29950,11 +30668,11 @@ async function buildReadyWebGPU(rhiDevice, rendererScope, getShader, gpuStore, a
|
|
|
29950
30668
|
}
|
|
29951
30669
|
try {
|
|
29952
30670
|
getOrBuildPipeline(spec, pipelineDeviceProvider, pipelineCache, modules);
|
|
29953
|
-
} catch (
|
|
29954
|
-
if (
|
|
30671
|
+
} catch (err42) {
|
|
30672
|
+
if (err42 instanceof PipelineSpecError) throw err42;
|
|
29955
30673
|
throw new PipelineSpecError({
|
|
29956
30674
|
code: "pipeline-build-failed",
|
|
29957
|
-
detail: { cause:
|
|
30675
|
+
detail: { cause: err42 },
|
|
29958
30676
|
hint: `Boot-time SPEC_CONST pre-warm failed for shader '${spec.shader.id}'; inspect gpuMessage on the cause`
|
|
29959
30677
|
});
|
|
29960
30678
|
}
|
|
@@ -30123,11 +30841,11 @@ async function buildReadyWebGPU(rhiDevice, rendererScope, getShader, gpuStore, a
|
|
|
30123
30841
|
pipelineCache,
|
|
30124
30842
|
modules
|
|
30125
30843
|
);
|
|
30126
|
-
} catch (
|
|
30127
|
-
if (
|
|
30844
|
+
} catch (err42) {
|
|
30845
|
+
if (err42 instanceof PipelineSpecError) throw err42;
|
|
30128
30846
|
throw new PipelineSpecError({
|
|
30129
30847
|
code: "pipeline-build-failed",
|
|
30130
|
-
detail: { cause:
|
|
30848
|
+
detail: { cause: err42 },
|
|
30131
30849
|
hint: "createRenderPipeline (fxaa fullscreen) failed; inspect gpuMessage"
|
|
30132
30850
|
});
|
|
30133
30851
|
}
|
|
@@ -30381,11 +31099,11 @@ async function buildReadyWebGPU(rhiDevice, rendererScope, getShader, gpuStore, a
|
|
|
30381
31099
|
bloomBrightPipelineHandle,
|
|
30382
31100
|
() => void 0
|
|
30383
31101
|
);
|
|
30384
|
-
} catch (
|
|
30385
|
-
if (
|
|
31102
|
+
} catch (err42) {
|
|
31103
|
+
if (err42 instanceof PipelineSpecError) throw err42;
|
|
30386
31104
|
throw new PipelineSpecError({
|
|
30387
31105
|
code: "pipeline-build-failed",
|
|
30388
|
-
detail: { cause:
|
|
31106
|
+
detail: { cause: err42 },
|
|
30389
31107
|
hint: "createRenderPipeline (bloom-bright fullscreen) failed; inspect gpuMessage"
|
|
30390
31108
|
});
|
|
30391
31109
|
}
|
|
@@ -30482,11 +31200,11 @@ async function buildReadyWebGPU(rhiDevice, rendererScope, getShader, gpuStore, a
|
|
|
30482
31200
|
bloomBlurHPipelineHandle,
|
|
30483
31201
|
() => void 0
|
|
30484
31202
|
);
|
|
30485
|
-
} catch (
|
|
30486
|
-
if (
|
|
31203
|
+
} catch (err42) {
|
|
31204
|
+
if (err42 instanceof PipelineSpecError) throw err42;
|
|
30487
31205
|
throw new PipelineSpecError({
|
|
30488
31206
|
code: "pipeline-build-failed",
|
|
30489
|
-
detail: { cause:
|
|
31207
|
+
detail: { cause: err42 },
|
|
30490
31208
|
hint: "createRenderPipeline (bloom-blur-h fullscreen) failed; inspect gpuMessage"
|
|
30491
31209
|
});
|
|
30492
31210
|
}
|
|
@@ -30603,11 +31321,11 @@ async function buildReadyWebGPU(rhiDevice, rendererScope, getShader, gpuStore, a
|
|
|
30603
31321
|
bloomCompositePipelineHandle,
|
|
30604
31322
|
() => void 0
|
|
30605
31323
|
);
|
|
30606
|
-
} catch (
|
|
30607
|
-
if (
|
|
31324
|
+
} catch (err42) {
|
|
31325
|
+
if (err42 instanceof PipelineSpecError) throw err42;
|
|
30608
31326
|
throw new PipelineSpecError({
|
|
30609
31327
|
code: "pipeline-build-failed",
|
|
30610
|
-
detail: { cause:
|
|
31328
|
+
detail: { cause: err42 },
|
|
30611
31329
|
hint: "createRenderPipeline (bloom-composite fullscreen) failed; inspect gpuMessage"
|
|
30612
31330
|
});
|
|
30613
31331
|
}
|
|
@@ -30897,11 +31615,11 @@ async function buildReadyWebGPU(rhiDevice, rendererScope, getShader, gpuStore, a
|
|
|
30897
31615
|
pipelineCache,
|
|
30898
31616
|
{ ...baseModules, fragmentEntryPoint: "fs_ssao_calc" }
|
|
30899
31617
|
);
|
|
30900
|
-
} catch (
|
|
30901
|
-
if (
|
|
31618
|
+
} catch (err42) {
|
|
31619
|
+
if (err42 instanceof PipelineSpecError) throw err42;
|
|
30902
31620
|
throw new PipelineSpecError({
|
|
30903
31621
|
code: "pipeline-build-failed",
|
|
30904
|
-
detail: { cause:
|
|
31622
|
+
detail: { cause: err42 },
|
|
30905
31623
|
hint: "createRenderPipeline (ssao-calc fullscreen) failed; inspect gpuMessage"
|
|
30906
31624
|
});
|
|
30907
31625
|
}
|
|
@@ -30932,11 +31650,11 @@ async function buildReadyWebGPU(rhiDevice, rendererScope, getShader, gpuStore, a
|
|
|
30932
31650
|
pipelineCache,
|
|
30933
31651
|
{ ...baseModules, fragmentEntryPoint: "fs_ssao_blur" }
|
|
30934
31652
|
);
|
|
30935
|
-
} catch (
|
|
30936
|
-
if (
|
|
31653
|
+
} catch (err42) {
|
|
31654
|
+
if (err42 instanceof PipelineSpecError) throw err42;
|
|
30937
31655
|
throw new PipelineSpecError({
|
|
30938
31656
|
code: "pipeline-build-failed",
|
|
30939
|
-
detail: { cause:
|
|
31657
|
+
detail: { cause: err42 },
|
|
30940
31658
|
hint: "createRenderPipeline (ssao-blur fullscreen) failed; inspect gpuMessage"
|
|
30941
31659
|
});
|
|
30942
31660
|
}
|
|
@@ -31683,6 +32401,7 @@ async function makeWebGPURenderer(internals) {
|
|
|
31683
32401
|
const publishRendererGeneration = (candidate) => {
|
|
31684
32402
|
publishGeneration(generationPublication, candidate, (value) => value.scope.isAlive());
|
|
31685
32403
|
activeDeviceScope = candidate.scope;
|
|
32404
|
+
dynamicGeometry.invalidateGeneration(activeDeviceScope.generation);
|
|
31686
32405
|
internals.generationState.current = activeDeviceScope.generation;
|
|
31687
32406
|
pipelineState = candidate.pipeline;
|
|
31688
32407
|
const bindings = candidate.producerBindings;
|
|
@@ -32222,7 +32941,7 @@ async function makeWebGPURenderer(internals) {
|
|
|
32222
32941
|
const currentState = currentPipelineState();
|
|
32223
32942
|
if (currentState === null) return null;
|
|
32224
32943
|
const ldrColorFormat = colorFormatOverride ?? currentState.colorAttachmentFormat;
|
|
32225
|
-
const fragmentEntry = authoredFragmentEntry ?? (isHdr && (materialShaderId === "forgeax::sprite" || materialShaderId === "forgeax::sprite-lit") ? "fs_main_hdr" : void 0);
|
|
32944
|
+
const fragmentEntry = authoredFragmentEntry ?? (isHdr && passKind === "forward" && (materialShaderId === "forgeax::sprite" || materialShaderId === "forgeax::sprite-lit") ? "fs_main_hdr" : void 0);
|
|
32226
32945
|
const built = buildPipelineForMaterialShader(
|
|
32227
32946
|
cacheKey,
|
|
32228
32947
|
// The catalog entry is projected into the material-shader entry shape.
|
|
@@ -32729,6 +33448,19 @@ async function makeWebGPURenderer(internals) {
|
|
|
32729
33448
|
const attachedWorlds = /* @__PURE__ */ new Set();
|
|
32730
33449
|
const attachedLeases = /* @__PURE__ */ new Map();
|
|
32731
33450
|
const leasesByWorld = /* @__PURE__ */ new Map();
|
|
33451
|
+
const dynamicGeometry = createDynamicGeometryLifecycle();
|
|
33452
|
+
const dynamicGeometryHost = createDynamicGeometryHost({
|
|
33453
|
+
lifecycle: dynamicGeometry,
|
|
33454
|
+
attachedWorlds,
|
|
33455
|
+
getGpuStore: () => gpuStore,
|
|
33456
|
+
currentGeneration: () => activeDeviceScope.generation,
|
|
33457
|
+
onTopologyChanged: () => renderSystem.invalidateGeometryHistory(),
|
|
33458
|
+
isConsumedByRenderFrame: (candidate) => renderSystem.isDynamicGeometryConsumed(
|
|
33459
|
+
candidate.world,
|
|
33460
|
+
candidate.entity ?? -1,
|
|
33461
|
+
candidate.meshHandle
|
|
33462
|
+
)
|
|
33463
|
+
});
|
|
32732
33464
|
const derivedSystemNames = /* @__PURE__ */ new Map();
|
|
32733
33465
|
const transformReleases = /* @__PURE__ */ new Map();
|
|
32734
33466
|
const attachmentOwner = {};
|
|
@@ -32749,6 +33481,7 @@ async function makeWebGPURenderer(internals) {
|
|
|
32749
33481
|
leasesByWorld.set(world, lease);
|
|
32750
33482
|
return ok(lease);
|
|
32751
33483
|
},
|
|
33484
|
+
...dynamicGeometryHost,
|
|
32752
33485
|
createRenderTarget: (descriptor) => renderTargetHost.createRenderTarget(descriptor),
|
|
32753
33486
|
resizeRenderTarget: (target4, descriptor) => renderTargetHost.resizeRenderTarget(target4, descriptor),
|
|
32754
33487
|
createRenderTargetTextureSource: (target4, options) => renderTargetHost.createRenderTargetTextureSource(target4, options),
|
|
@@ -32852,6 +33585,7 @@ async function makeWebGPURenderer(internals) {
|
|
|
32852
33585
|
})
|
|
32853
33586
|
)
|
|
32854
33587
|
),
|
|
33588
|
+
dynamicGeometry: dynamicGeometry.inspect(),
|
|
32855
33589
|
renderScene: renderSystem.renderScene,
|
|
32856
33590
|
reflectionProbes: renderSystem.reflectionProbes,
|
|
32857
33591
|
ssrDependencies: renderSystem.ssrDependencies,
|
|
@@ -32973,6 +33707,7 @@ async function makeWebGPURenderer(internals) {
|
|
|
32973
33707
|
},
|
|
32974
33708
|
detachScene(world) {
|
|
32975
33709
|
if (!attachedWorlds.delete(world)) return;
|
|
33710
|
+
dynamicGeometryHost.invalidateDynamicGeometryWorld(world);
|
|
32976
33711
|
for (const [lease, leaseWorld] of attachedLeases) {
|
|
32977
33712
|
if (leaseWorld === world) {
|
|
32978
33713
|
lease.dispose();
|
|
@@ -33147,6 +33882,21 @@ async function makeWebGPURenderer(internals) {
|
|
|
33147
33882
|
const frameRequest = isFrameRequest ? worldsOrRequest : void 0;
|
|
33148
33883
|
const worlds = frameRequest !== void 0 ? frameRequest.leases.map((lease) => attachedLeases.get(lease)).filter((world) => world !== void 0) : worldsOrRequest;
|
|
33149
33884
|
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;
|
|
33885
|
+
for (const world of worlds) {
|
|
33886
|
+
if (!world.hasResource("PhysicsWorld")) continue;
|
|
33887
|
+
const physics = world.getResource("PhysicsWorld");
|
|
33888
|
+
if (physics?.getDerivedAdmission?.() !== void 0 || physics?.getDerivedRecoveryState?.() === "rebuild-required") {
|
|
33889
|
+
return err(
|
|
33890
|
+
new RendererOperationError("frame-input-invalid", {
|
|
33891
|
+
operation: "draw",
|
|
33892
|
+
cause: new RendererContractFailureError(
|
|
33893
|
+
"draw",
|
|
33894
|
+
"paired geometry admission must finish physics step and writeback in a healthy World before draw"
|
|
33895
|
+
)
|
|
33896
|
+
})
|
|
33897
|
+
);
|
|
33898
|
+
}
|
|
33899
|
+
}
|
|
33150
33900
|
if (frameRequest !== void 0 && worlds.length !== frameRequest.leases.length) {
|
|
33151
33901
|
return err(
|
|
33152
33902
|
new RendererOperationError("world-lease-invalid", {
|
|
@@ -33268,6 +34018,8 @@ async function makeWebGPURenderer(internals) {
|
|
|
33268
34018
|
const timingCompletion = timingHost.gpuPassTimingSubmittedWork;
|
|
33269
34019
|
timingHost.gpuPassTimingSubmittedWork = void 0;
|
|
33270
34020
|
const reflectionFallbackCompletion = renderSystem.reflectionFallbackCompletion;
|
|
34021
|
+
const queueCompletion = timingCompletion ?? internals.device.queue.onSubmittedWorkDone();
|
|
34022
|
+
gpuStore.trackMeshSubmission(queueCompletion);
|
|
33271
34023
|
internals.pack.instrumentation?.onFrameBoundary?.();
|
|
33272
34024
|
if (!isFrameRequest) {
|
|
33273
34025
|
renderTargetHost.onFrameSubmitted();
|
|
@@ -33275,7 +34027,6 @@ async function makeWebGPURenderer(internals) {
|
|
|
33275
34027
|
}
|
|
33276
34028
|
const receiptFrameId = ++frameId;
|
|
33277
34029
|
const receiptGeneration = activeDeviceScope.generation;
|
|
33278
|
-
const queueCompletion = timingCompletion ?? internals.device.queue.onSubmittedWorkDone();
|
|
33279
34030
|
const completion = Promise.all([
|
|
33280
34031
|
queueCompletion,
|
|
33281
34032
|
reflectionFallbackCompletion ?? Promise.resolve()
|
|
@@ -33383,6 +34134,7 @@ async function makeWebGPURenderer(internals) {
|
|
|
33383
34134
|
);
|
|
33384
34135
|
}
|
|
33385
34136
|
issuedReceipts.add(receipt);
|
|
34137
|
+
dynamicGeometryHost.publishDynamicGeometry(receipt, worlds, frameRequest?.fixedStep);
|
|
33386
34138
|
return ok(receipt);
|
|
33387
34139
|
} catch (cause) {
|
|
33388
34140
|
const error = cause instanceof Error ? { code: "unknown", message: cause.message, name: cause.name } : { code: "unknown", message: String(cause) };
|
|
@@ -33510,6 +34262,10 @@ async function makeWebGPURenderer(internals) {
|
|
|
33510
34262
|
dispose() {
|
|
33511
34263
|
if (disposed) return ok(void 0);
|
|
33512
34264
|
disposed = true;
|
|
34265
|
+
for (const world of attachedWorlds) {
|
|
34266
|
+
dynamicGeometryHost.invalidateDynamicGeometryWorld(world);
|
|
34267
|
+
}
|
|
34268
|
+
dynamicGeometry.dispose();
|
|
33513
34269
|
for (const continuation of frameContinuations) {
|
|
33514
34270
|
continuation.terminate({ code: "disposed" });
|
|
33515
34271
|
}
|