@woosh/meep-engine 3.39.0 → 3.41.0
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/build/bundle-worker-terrain.js +1 -1
- package/package.json +1 -1
- package/src/core/geom/3d/quaternion/swing_twist_clamp.d.ts +24 -0
- package/src/core/geom/3d/quaternion/swing_twist_clamp.d.ts.map +1 -0
- package/src/core/geom/3d/quaternion/swing_twist_clamp.js +62 -0
- package/src/core/geom/3d/quaternion/swing_twist_compose.d.ts +15 -0
- package/src/core/geom/3d/quaternion/swing_twist_compose.d.ts.map +1 -0
- package/src/core/geom/3d/quaternion/swing_twist_compose.js +36 -0
- package/src/core/geom/3d/quaternion/swing_twist_error.d.ts +39 -0
- package/src/core/geom/3d/quaternion/swing_twist_error.d.ts.map +1 -0
- package/src/core/geom/3d/quaternion/swing_twist_error.js +85 -0
- package/src/core/geom/vec3/v3_rigid_align_paired_unit_vectors.d.ts +11 -6
- package/src/core/geom/vec3/v3_rigid_align_paired_unit_vectors.d.ts.map +1 -1
- package/src/core/geom/vec3/v3_rigid_align_paired_unit_vectors.js +27 -13
- package/src/core/math/linalg/eigen/matrix_symmetric_4x4_eigen.d.ts +25 -0
- package/src/core/math/linalg/eigen/matrix_symmetric_4x4_eigen.d.ts.map +1 -0
- package/src/core/math/linalg/eigen/matrix_symmetric_4x4_eigen.js +166 -0
- package/src/core/math/linalg/eigen/matrix_top_eigenvector_power_iteration.d.ts +5 -3
- package/src/core/math/linalg/eigen/matrix_top_eigenvector_power_iteration.d.ts.map +1 -1
- package/src/core/math/linalg/eigen/matrix_top_eigenvector_power_iteration.js +5 -3
- package/src/engine/EngineHarness.d.ts.map +1 -1
- package/src/engine/EngineHarness.js +17 -4
- package/src/engine/animation/curve/AnimationCurve.d.ts +3 -0
- package/src/engine/animation/curve/AnimationCurve.d.ts.map +1 -1
- package/src/engine/animation/curve/AnimationCurve.js +6 -1
- package/src/engine/asset/loaders/image/avif/threaded_image_encoder.js +1 -1
- package/src/engine/ecs/EntityManager.d.ts +9 -1
- package/src/engine/ecs/EntityManager.d.ts.map +1 -1
- package/src/engine/ecs/EntityManager.js +26 -27
- package/src/engine/ecs/gpu/GPUStateAuthority.d.ts +20 -0
- package/src/engine/ecs/gpu/GPUStateAuthority.d.ts.map +1 -1
- package/src/engine/ecs/gpu/GPUStateAuthority.js +21 -0
- package/src/engine/ecs/gpu/GPU_AUTHORITY_EVENT_HOLD_CHANGE.d.ts +13 -0
- package/src/engine/ecs/gpu/GPU_AUTHORITY_EVENT_HOLD_CHANGE.d.ts.map +1 -0
- package/src/engine/ecs/gpu/GPU_AUTHORITY_EVENT_HOLD_CHANGE.js +12 -0
- package/src/engine/ecs/gpu/gpu_authority_grant.d.ts +6 -0
- package/src/engine/ecs/gpu/gpu_authority_grant.d.ts.map +1 -1
- package/src/engine/ecs/gpu/gpu_authority_grant.js +7 -1
- package/src/engine/ecs/gpu/gpu_authority_held.d.ts +14 -0
- package/src/engine/ecs/gpu/gpu_authority_held.d.ts.map +1 -0
- package/src/engine/ecs/gpu/gpu_authority_held.js +23 -0
- package/src/engine/ecs/gpu/gpu_authority_hold.d.ts +23 -0
- package/src/engine/ecs/gpu/gpu_authority_hold.d.ts.map +1 -0
- package/src/engine/ecs/gpu/gpu_authority_hold.js +41 -0
- package/src/engine/ecs/gpu/gpu_authority_unhold.d.ts +14 -0
- package/src/engine/ecs/gpu/gpu_authority_unhold.d.ts.map +1 -0
- package/src/engine/ecs/gpu/gpu_authority_unhold.js +32 -0
- package/src/engine/ecs/ik/IKGoal.d.ts +59 -0
- package/src/engine/ecs/ik/IKGoal.d.ts.map +1 -0
- package/src/engine/ecs/ik/IKGoal.js +83 -0
- package/src/engine/ecs/ik/IKGoalSystem.d.ts +75 -0
- package/src/engine/ecs/ik/IKGoalSystem.d.ts.map +1 -0
- package/src/engine/ecs/ik/IKGoalSystem.js +1456 -0
- package/src/engine/ecs/ik/PLAN.md +179 -0
- package/src/engine/ecs/speaker/VoiceSystem.d.ts +2 -2
- package/src/engine/ecs/speaker/VoiceSystem.d.ts.map +1 -1
- package/src/engine/ecs/storage/BinaryBufferSerializer.d.ts.map +1 -1
- package/src/engine/ecs/storage/BinaryBufferSerializer.js +4 -5
- package/src/engine/ecs/storage/binary/SERIALIZATION_COVERAGE.md +7 -3
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +5 -2
- package/src/engine/ecs/system/orderSystemsByDeclaredAccess.d.ts +33 -0
- package/src/engine/ecs/system/orderSystemsByDeclaredAccess.d.ts.map +1 -0
- package/src/engine/ecs/system/orderSystemsByDeclaredAccess.js +282 -0
- package/src/engine/ecs/transform/T64WorldCache.js +139 -139
- package/src/engine/ecs/transform/t64_evaluate_local.d.ts +25 -0
- package/src/engine/ecs/transform/t64_evaluate_local.d.ts.map +1 -0
- package/src/engine/ecs/transform/t64_evaluate_local.js +35 -0
- package/src/engine/ecs/transform/t64_evaluate_world.d.ts +5 -3
- package/src/engine/ecs/transform/t64_evaluate_world.d.ts.map +1 -1
- package/src/engine/ecs/transform/t64_evaluate_world.js +128 -126
- package/src/engine/graphics/ecs/water/Water.d.ts +14 -17
- package/src/engine/graphics/ecs/water/Water.d.ts.map +1 -1
- package/src/engine/graphics/ecs/water/Water.js +100 -110
- package/src/engine/graphics/ecs/water/WaterSerializationAdapter.d.ts.map +1 -1
- package/src/engine/graphics/ecs/water/WaterSerializationAdapter.js +36 -38
- package/src/engine/graphics/ecs/water/WaterSerializationUpgrader_3_4.d.ts +6 -0
- package/src/engine/graphics/ecs/water/WaterSerializationUpgrader_3_4.d.ts.map +1 -0
- package/src/engine/graphics/ecs/water/WaterSerializationUpgrader_3_4.js +10 -0
- package/src/engine/graphics/ecs/water/WaterWaves.d.ts +3 -3
- package/src/engine/graphics/ecs/water/WaterWaves.js +46 -46
- package/src/engine/graphics/texture/sampler/sampler2d_to_avif.d.ts.map +1 -1
- package/src/engine/graphics/texture/sampler/sampler2d_to_avif.js +8 -5
- package/src/engine/graphics3/AnimationGraphSystem.d.ts +2 -0
- package/src/engine/graphics3/AnimationGraphSystem.d.ts.map +1 -1
- package/src/engine/graphics3/AnimationGraphSystem.js +337 -329
- package/src/engine/graphics3/AnimationSystem.d.ts +2 -0
- package/src/engine/graphics3/AnimationSystem.d.ts.map +1 -1
- package/src/engine/graphics3/AnimationSystem.js +360 -352
- package/src/engine/graphics3/WaterSystem.d.ts +21 -74
- package/src/engine/graphics3/WaterSystem.d.ts.map +1 -1
- package/src/engine/graphics3/WaterSystem.js +174 -367
- package/src/engine/physics/cloth/MEASUREMENTS.md +130 -0
- package/src/engine/physics/cloth/PLAN.md +16 -1
- package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts +5 -6
- package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothColliderSystem.js +5 -6
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +4 -7
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothInstance.js +4 -7
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +4 -3
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothSystem.js +4 -3
- package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothWorld.js +10 -0
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +24 -24
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +46 -43
- package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts +1 -1
- package/src/engine/physics/cloth/ecs/cloth_write_back.js +1 -1
- package/src/engine/physics/constraint/solve_constraints.d.ts +0 -35
- package/src/engine/physics/constraint/solve_constraints.d.ts.map +1 -1
- package/src/engine/physics/constraint/solve_constraints.js +1 -83
- package/src/engine/physics/ecs/ContactProbe.d.ts +73 -0
- package/src/engine/physics/ecs/ContactProbe.d.ts.map +1 -0
- package/src/engine/physics/ecs/ContactProbe.js +103 -0
- package/src/engine/physics/ecs/ContactProbeSystem.d.ts +44 -0
- package/src/engine/physics/ecs/ContactProbeSystem.d.ts.map +1 -0
- package/src/engine/physics/ecs/ContactProbeSystem.js +397 -0
- package/src/engine/physics/fluid/ecs/FluidComponent.d.ts +1 -1
- package/src/engine/physics/fluid/ecs/FluidComponent.js +1 -1
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/engine/physics/inverse_kinematics/frame_fabrik/FrameFabrikProblem.d.ts +205 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/FrameFabrikProblem.d.ts.map +1 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/FrameFabrikProblem.js +245 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_limit_from_joint.d.ts +21 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_limit_from_joint.d.ts.map +1 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_limit_from_joint.js +63 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_solve.d.ts +33 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_solve.d.ts.map +1 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_solve.js +874 -0
- package/src/engine/physics/inverse_kinematics/joint_hinge_mid_axis.d.ts +27 -0
- package/src/engine/physics/inverse_kinematics/joint_hinge_mid_axis.d.ts.map +1 -0
- package/src/engine/physics/inverse_kinematics/joint_hinge_mid_axis.js +77 -0
- package/src/engine/physics/inverse_kinematics/two_bone_path_solve.d.ts +36 -0
- package/src/engine/physics/inverse_kinematics/two_bone_path_solve.d.ts.map +1 -0
- package/src/engine/physics/inverse_kinematics/two_bone_path_solve.js +97 -0
- package/src/engine/physics/inverse_kinematics/two_joint_ik.d.ts +33 -11
- package/src/engine/physics/inverse_kinematics/two_joint_ik.d.ts.map +1 -1
- package/src/engine/physics/inverse_kinematics/two_joint_ik.js +158 -67
- package/src/format/image/avif/api/convert_to_rgba.d.ts +2 -2
- package/src/format/image/avif/api/convert_to_rgba.d.ts.map +1 -1
- package/src/format/image/avif/api/convert_to_rgba.js +10 -9
- package/src/format/image/avif/api/decode_avif.d.ts +2 -2
- package/src/format/image/avif/api/decode_avif.d.ts.map +1 -1
- package/src/format/image/avif/api/decode_avif.js +1 -1
- package/src/shade/playground/ssr_reprojection/README.md +111 -103
- package/src/shade/playground/ssr_reprojection/SpatialFilterProbe.js +68 -68
- package/src/shade/playground/ssr_reprojection/index.html +80 -79
- package/src/shade/playground/ssr_reprojection/main.js +256 -247
- package/src/shade/playground/ssr_variance/capture.js +96 -96
- package/src/shade/playground/ssr_variance/reference.js +78 -78
- package/src/shade/playground/vsm/README.md +96 -0
- package/src/shade/playground/vsm/VSMDebugOverlay.d.ts +49 -0
- package/src/shade/playground/vsm/VSMDebugOverlay.d.ts.map +1 -0
- package/src/shade/playground/vsm/VSMDebugOverlay.js +351 -0
- package/src/shade/playground/vsm/clipmap_panel.d.ts +8 -0
- package/src/shade/playground/vsm/clipmap_panel.d.ts.map +1 -0
- package/src/shade/playground/vsm/clipmap_panel.js +138 -0
- package/src/shade/playground/vsm/index.html +170 -0
- package/src/shade/playground/vsm/main.d.ts +2 -0
- package/src/shade/playground/vsm/main.d.ts.map +1 -0
- package/src/shade/playground/vsm/main.js +389 -0
- package/src/shade/playground/vsm/scenes.d.ts +52 -0
- package/src/shade/playground/vsm/scenes.d.ts.map +1 -0
- package/src/shade/playground/vsm/scenes.js +320 -0
- package/src/shade/playground/vsm/verify_vsm.d.ts +38 -0
- package/src/shade/playground/vsm/verify_vsm.d.ts.map +1 -0
- package/src/shade/playground/vsm/verify_vsm.js +305 -0
- package/src/shade/playground/water_refraction/README.md +57 -9
- package/src/shade/playground/water_refraction/main.js +12 -3
- package/src/shade/playground/water_refraction/world.d.ts +1 -0
- package/src/shade/playground/water_refraction/world.d.ts.map +1 -1
- package/src/shade/playground/water_refraction/world.js +15 -5
- package/src/shade/renderer/Renderer.d.ts +19 -0
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +72 -1
- package/src/shade/renderer/animation/ANIMATION_TRACK_BINDING_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/animation/ANIMATION_TRACK_BINDING_STRUCT.js +10 -1
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts +18 -4
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
- package/src/shade/renderer/animation/GPUAnimationManager.js +269 -23
- package/src/shade/renderer/animation/POSE_ACCUMULATOR_LAYOUT.d.ts +12 -4
- package/src/shade/renderer/animation/POSE_ACCUMULATOR_LAYOUT.d.ts.map +1 -1
- package/src/shade/renderer/animation/POSE_ACCUMULATOR_LAYOUT.js +12 -4
- package/src/shade/renderer/animation/chunk_pose_accumulator.d.ts.map +1 -1
- package/src/shade/renderer/animation/chunk_pose_accumulator.js +14 -1
- package/src/shade/renderer/animation/pose/PoseChannelIndex.d.ts +78 -0
- package/src/shade/renderer/animation/pose/PoseChannelIndex.d.ts.map +1 -0
- package/src/shade/renderer/animation/pose/PoseChannelIndex.js +274 -0
- package/src/shade/renderer/animation/pose/PosePlayback.d.ts +40 -3
- package/src/shade/renderer/animation/pose/PosePlayback.d.ts.map +1 -1
- package/src/shade/renderer/animation/pose/PosePlayback.js +77 -3
- package/src/shade/renderer/animation/pose/pose_evaluate_local.d.ts +21 -3
- package/src/shade/renderer/animation/pose/pose_evaluate_local.d.ts.map +1 -1
- package/src/shade/renderer/animation/pose/pose_evaluate_local.js +79 -11
- package/src/shade/renderer/animation/shader_animation_apply.js +1 -1
- package/src/shade/renderer/animation/shader_animation_pose_resolve.d.ts +3 -2
- package/src/shade/renderer/animation/shader_animation_pose_resolve.d.ts.map +1 -1
- package/src/shade/renderer/animation/shader_animation_pose_resolve.js +187 -176
- package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts +7 -0
- package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +11 -0
- package/src/shade/renderer/animation/skinning/SKINNING_BINDING_STRUCT.d.ts +3 -1
- package/src/shade/renderer/animation/skinning/SKINNING_BINDING_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/SKINNING_BINDING_STRUCT.js +10 -1
- package/src/shade/renderer/buffer/table/serde/table_wgsl_gen_read_code.d.ts.map +1 -1
- package/src/shade/renderer/buffer/table/serde/table_wgsl_gen_read_code.js +28 -0
- package/src/shade/renderer/buffer/table/serde/table_wgsl_gen_write_code.d.ts.map +1 -1
- package/src/shade/renderer/buffer/table/serde/table_wgsl_gen_write_code.js +31 -1
- package/src/shade/renderer/geometry/MeshletGeometry.d.ts +3 -0
- package/src/shade/renderer/geometry/MeshletGeometry.d.ts.map +1 -1
- package/src/shade/renderer/geometry/MeshletGeometry.js +1 -0
- package/src/shade/renderer/light/LIGHT_DATABASE_SPEC.d.ts.map +1 -1
- package/src/shade/renderer/light/LIGHT_DATABASE_SPEC.js +62 -4
- package/src/shade/renderer/light/environment/rgbe/parse_rgbe.d.ts +1 -1
- package/src/shade/renderer/light/environment/rgbe/parse_rgbe.js +2 -2
- package/src/shade/renderer/light/environment/rgbe/rgbe_byte_to_rgb_half.d.ts +2 -2
- package/src/shade/renderer/light/environment/rgbe/rgbe_byte_to_rgb_half.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/rgbe/rgbe_byte_to_rgb_half.js +6 -14
- package/src/shade/renderer/light/environment/sh_exponential/chunk_sh_exp_workgroup_sum.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/sh_exponential/chunk_sh_exp_workgroup_sum.js +5 -1
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/medium/ParticipatingMedium.d.ts +3 -0
- package/src/shade/renderer/medium/ParticipatingMedium.d.ts.map +1 -1
- package/src/shade/renderer/medium/ParticipatingMedium.js +7 -0
- package/src/shade/renderer/object_property/chunk_write_object_property.d.ts +3 -1
- package/src/shade/renderer/object_property/chunk_write_object_property.d.ts.map +1 -1
- package/src/shade/renderer/object_property/chunk_write_object_property.js +5 -2
- package/src/shade/renderer/object_property/chunk_write_object_property_node3d.d.ts +4 -0
- package/src/shade/renderer/object_property/chunk_write_object_property_node3d.d.ts.map +1 -1
- package/src/shade/renderer/object_property/chunk_write_object_property_node3d.js +6 -1
- package/src/shade/renderer/postprocess/eye/shader_autoexposure_build_histogram.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/eye/shader_autoexposure_build_histogram.js +5 -35
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/postprocess/ssr/SSR.d.ts +12 -4
- package/src/shade/renderer/postprocess/ssr/SSR.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/SSR.js +36 -8
- package/src/shade/renderer/postprocess/ssr/SSR_DENOISE_TILE_SIZE.d.ts +3 -0
- package/src/shade/renderer/postprocess/ssr/SSR_DENOISE_TILE_SIZE.d.ts.map +1 -0
- package/src/shade/renderer/postprocess/ssr/SSR_DENOISE_TILE_SIZE.js +2 -0
- package/src/shade/renderer/postprocess/ssr/chunk_ssr_denoise_tile_active.d.ts +8 -0
- package/src/shade/renderer/postprocess/ssr/chunk_ssr_denoise_tile_active.d.ts.map +1 -0
- package/src/shade/renderer/postprocess/ssr/chunk_ssr_denoise_tile_active.js +40 -0
- package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.js +150 -137
- package/src/shade/renderer/postprocess/ssr/shader_ssr_denoise_tile_classify.d.ts +3 -0
- package/src/shade/renderer/postprocess/ssr/shader_ssr_denoise_tile_classify.d.ts.map +1 -0
- package/src/shade/renderer/postprocess/ssr/shader_ssr_denoise_tile_classify.js +44 -0
- package/src/shade/renderer/postprocess/ssr/shader_ssr_denoise_tile_dilate.d.ts +5 -0
- package/src/shade/renderer/postprocess/ssr/shader_ssr_denoise_tile_dilate.d.ts.map +1 -0
- package/src/shade/renderer/postprocess/ssr/shader_ssr_denoise_tile_dilate.js +35 -0
- package/src/shade/renderer/postprocess/ssr/ssr_graph_denoise_tiles.d.ts +26 -0
- package/src/shade/renderer/postprocess/ssr/ssr_graph_denoise_tiles.d.ts.map +1 -0
- package/src/shade/renderer/postprocess/ssr/ssr_graph_denoise_tiles.js +42 -0
- package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.d.ts +1 -0
- package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.js +113 -105
- package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.d.ts +2 -0
- package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.js +177 -167
- package/src/shade/renderer/rasterize/DEPTH_STENCIL_STATE_SHADOW.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/DEPTH_STENCIL_STATE_SHADOW.js +10 -0
- package/src/shade/renderer/rasterize/RasterizationJob.d.ts +1 -2
- package/src/shade/renderer/rasterize/RasterizationJob.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/RasterizationJob.js +1 -2
- package/src/shade/renderer/rasterize/bucket/construct_primitive_state.d.ts +5 -6
- package/src/shade/renderer/rasterize/bucket/construct_primitive_state.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/construct_primitive_state.js +5 -6
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts +2 -2
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.js +1 -1
- package/src/shade/renderer/scene/SCENE_DATABASE_SPEC.d.ts.map +1 -1
- package/src/shade/renderer/scene/SCENE_DATABASE_SPEC.js +11 -0
- package/src/shade/renderer/scene/optimization/geometry/geometry_deduplicate.d.ts +1 -1
- package/src/shade/renderer/scene/optimization/geometry/geometry_deduplicate.d.ts.map +1 -1
- package/src/shade/renderer/scene/optimization/geometry/geometry_deduplicate.js +135 -73
- package/src/shade/renderer/scene/optimization/geometry/internal/cover_greedy.d.ts +7 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/cover_greedy.d.ts.map +1 -1
- package/src/shade/renderer/scene/optimization/geometry/internal/cover_greedy.js +29 -1
- package/src/shade/renderer/scene/optimization/geometry/internal/face_neighbourhood_hash.d.ts +19 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/face_neighbourhood_hash.d.ts.map +1 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/face_neighbourhood_hash.js +167 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/neighbourhood_anchor_index.d.ts +25 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/neighbourhood_anchor_index.d.ts.map +1 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/neighbourhood_anchor_index.js +124 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/seed_correspondence_from_face_pair.d.ts +19 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/seed_correspondence_from_face_pair.d.ts.map +1 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/seed_correspondence_from_face_pair.js +48 -0
- package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts +17 -1
- package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts.map +1 -1
- package/src/shade/renderer/scene/rows/GPUSceneRows.js +29 -3
- package/src/shade/renderer/shader/chunk/atmosphere/phase/jd/build_lut_fog_parameters_jendersie_deon.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/atmosphere/phase/jd/build_lut_fog_parameters_jendersie_deon.js +4 -5
- package/src/shade/renderer/shader/chunk/brdf/dfg/generate_dfg_texture.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/brdf/dfg/generate_dfg_texture.js +1 -5
- package/src/shade/renderer/shader/chunk/screen_space/chunk_screen_importance.d.ts +30 -0
- package/src/shade/renderer/shader/chunk/screen_space/chunk_screen_importance.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/screen_space/chunk_screen_importance.js +54 -0
- package/src/shade/renderer/shader/type/serde/read_gpu_typed_buffer.d.ts.map +1 -1
- package/src/shade/renderer/shader/type/serde/read_gpu_typed_buffer.js +3 -2
- package/src/shade/renderer/shadow/map/DIRECTIONAL_SHADOWMAP_STRUCT.d.ts +19 -0
- package/src/shade/renderer/shadow/map/DIRECTIONAL_SHADOWMAP_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/shadow/map/DIRECTIONAL_SHADOWMAP_STRUCT.js +27 -0
- package/src/shade/renderer/shadow/map/DirectionalLightShadowmap.d.ts +1 -0
- package/src/shade/renderer/shadow/map/DirectionalLightShadowmap.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/DirectionalLightShadowmap.js +4 -0
- package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts +54 -0
- package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +502 -10
- package/src/shade/renderer/shadow/map/Shadowmap.d.ts +3 -2
- package/src/shade/renderer/shadow/map/Shadowmap.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/Shadowmap.js +3 -2
- package/src/shade/renderer/shadow/map/shader/chunk_sample_shadowmap_atlas_for_light.d.ts +8 -0
- package/src/shade/renderer/shadow/map/shader/chunk_sample_shadowmap_atlas_for_light.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/shader/chunk_sample_shadowmap_atlas_for_light.js +34 -3
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional.d.ts +3 -2
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional.js +17 -2
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_point2.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_point2.js +137 -133
- package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_FIRST_TEXEL_SIZE.d.ts +15 -0
- package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_FIRST_TEXEL_SIZE.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_FIRST_TEXEL_SIZE.js +14 -0
- package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_PAGE_BUDGET.d.ts +16 -0
- package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_PAGE_BUDGET.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_PAGE_BUDGET.js +15 -0
- package/src/shade/renderer/shadow/vsm/PLAN.md +440 -0
- package/src/shade/renderer/shadow/vsm/REVIEW_LEDGER.md +43 -0
- package/src/shade/renderer/shadow/vsm/VSMMoverTracker.d.ts +42 -0
- package/src/shade/renderer/shadow/vsm/VSMMoverTracker.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/VSMMoverTracker.js +153 -0
- package/src/shade/renderer/shadow/vsm/VSMPageManager.d.ts +327 -0
- package/src/shade/renderer/shadow/vsm/VSMPageManager.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/VSMPageManager.js +1408 -0
- package/src/shade/renderer/shadow/vsm/VSM_COVER_LEVEL_STEP.d.ts +14 -0
- package/src/shade/renderer/shadow/vsm/VSM_COVER_LEVEL_STEP.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/VSM_COVER_LEVEL_STEP.js +13 -0
- package/src/shade/renderer/shadow/vsm/VSM_FEEDBACK_LAYOUT.d.ts +63 -0
- package/src/shade/renderer/shadow/vsm/VSM_FEEDBACK_LAYOUT.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/VSM_FEEDBACK_LAYOUT.js +70 -0
- package/src/shade/renderer/shadow/vsm/VSM_LEVEL_LIMIT.d.ts +11 -0
- package/src/shade/renderer/shadow/vsm/VSM_LEVEL_LIMIT.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/VSM_LEVEL_LIMIT.js +10 -0
- package/src/shade/renderer/shadow/vsm/VSM_MOVER_LAYOUT.d.ts +54 -0
- package/src/shade/renderer/shadow/vsm/VSM_MOVER_LAYOUT.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/VSM_MOVER_LAYOUT.js +75 -0
- package/src/shade/renderer/shadow/vsm/VSM_RECORD_STRUCT.d.ts +23 -0
- package/src/shade/renderer/shadow/vsm/VSM_RECORD_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/VSM_RECORD_STRUCT.js +85 -0
- package/src/shade/renderer/shadow/vsm/VSM_SLOT_STRUCT.d.ts +16 -0
- package/src/shade/renderer/shadow/vsm/VSM_SLOT_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/VSM_SLOT_STRUCT.js +29 -0
- package/src/shade/renderer/shadow/vsm/VirtualShadowMap.d.ts +136 -25
- package/src/shade/renderer/shadow/vsm/VirtualShadowMap.d.ts.map +1 -1
- package/src/shade/renderer/shadow/vsm/VirtualShadowMap.js +282 -116
- package/src/shade/renderer/shadow/vsm/graph_vsm_feedback.d.ts +39 -0
- package/src/shade/renderer/shadow/vsm/graph_vsm_feedback.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/graph_vsm_feedback.js +289 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_shadowmap_sample_virtual.d.ts +18 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_shadowmap_sample_virtual.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_shadowmap_sample_virtual.js +65 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_addressing.d.ts +17 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_addressing.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_addressing.js +75 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_append_mover.d.ts +14 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_append_mover.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_append_mover.js +45 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_find_page.d.ts +17 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_find_page.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_find_page.js +100 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_page_view_projection.d.ts +15 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_page_view_projection.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_page_view_projection.js +47 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_demand.d.ts +26 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_demand.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_demand.js +156 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_gather_counts.d.ts +13 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_gather_counts.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_gather_counts.js +65 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_movers.d.ts +30 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_movers.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_movers.js +184 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_skinned_movers.d.ts +23 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_skinned_movers.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_skinned_movers.js +109 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_stale.d.ts +56 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_stale.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_stale.js +211 -0
- package/src/shade/renderer/texture/format/decode_typed_gpu_data.d.ts +1 -1
- package/src/shade/renderer/texture/format/decode_typed_gpu_data.d.ts.map +1 -1
- package/src/shade/renderer/texture/format/decode_typed_gpu_data.js +3 -13
- package/src/shade/renderer/texture/format/infer_format_from_parameters.d.ts.map +1 -1
- package/src/shade/renderer/texture/format/infer_format_from_parameters.js +2 -3
- package/src/shade/renderer/texture/texture_write_to_gpu.d.ts.map +1 -1
- package/src/shade/renderer/texture/texture_write_to_gpu.js +16 -16
- package/src/shade/renderer/texture/virtual/VTPhysicalCache.d.ts +4 -90
- package/src/shade/renderer/texture/virtual/VTPhysicalCache.d.ts.map +1 -1
- package/src/shade/renderer/texture/virtual/VTPhysicalCache.js +6 -210
- package/src/shade/renderer/texture/virtual/VTPhysicalSlots.d.ts +119 -0
- package/src/shade/renderer/texture/virtual/VTPhysicalSlots.d.ts.map +1 -0
- package/src/shade/renderer/texture/virtual/VTPhysicalSlots.js +245 -0
- package/src/shade/renderer/texture/virtual/build_chunk_vt_lookup.d.ts +1 -1
- package/src/shade/renderer/texture/virtual/build_chunk_vt_lookup.d.ts.map +1 -1
- package/src/shade/renderer/texture/virtual/build_chunk_vt_lookup.js +3 -19
- package/src/shade/renderer/texture/virtual/chunk_vt_page_table_entry.d.ts +13 -0
- package/src/shade/renderer/texture/virtual/chunk_vt_page_table_entry.d.ts.map +1 -0
- package/src/shade/renderer/texture/virtual/chunk_vt_page_table_entry.js +34 -0
- package/src/shade/renderer/water/GPUWaterRenderer.d.ts +7 -2
- package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
- package/src/shade/renderer/water/GPUWaterRenderer.js +49 -49
- package/src/shade/renderer/water/chunk_water_transport.js +3 -3
- package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts +11 -25
- package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts.map +1 -1
- package/src/shade/renderer/water/medium/GPUWaterBodies.js +64 -116
- package/src/shade/renderer/water/medium/WATER_BODIES_STRUCT.d.ts +1 -20
- package/src/shade/renderer/water/medium/WATER_BODIES_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/water/medium/WATER_BODIES_STRUCT.js +10 -42
- package/src/shade/renderer/water/medium/chunk_water_bodies.d.ts +3 -0
- package/src/shade/renderer/water/medium/chunk_water_bodies.d.ts.map +1 -0
- package/src/shade/renderer/water/medium/chunk_water_bodies.js +3 -0
- package/src/shade/renderer/water/medium/shader_water_bodies_derive.d.ts +1 -5
- package/src/shade/renderer/water/medium/shader_water_bodies_derive.d.ts.map +1 -1
- package/src/shade/renderer/water/medium/shader_water_bodies_derive.js +32 -30
- package/src/shade/renderer/water/medium/shader_water_meshlets.d.ts +4 -0
- package/src/shade/renderer/water/medium/shader_water_meshlets.d.ts.map +1 -0
- package/src/shade/renderer/water/medium/shader_water_meshlets.js +69 -0
- package/src/shade/renderer/water/optics/chunk_water_inscatter.d.ts.map +1 -1
- package/src/shade/renderer/water/optics/chunk_water_inscatter.js +124 -123
- package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.d.ts.map +1 -1
- package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.js +75 -74
- package/src/shade/renderer/water/shader_water.d.ts +1 -1
- package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
- package/src/shade/renderer/water/shader_water.js +490 -406
- package/src/shade/renderer/water/surface/GPUWaterWaveSimulation.d.ts +12 -85
- package/src/shade/renderer/water/surface/GPUWaterWaveSimulation.d.ts.map +1 -1
- package/src/shade/renderer/water/surface/GPUWaterWaveSimulation.js +128 -408
- package/src/shade/renderer/water/surface/WATER_WAVE_RECORD_STRUCT.d.ts +6 -0
- package/src/shade/renderer/water/surface/WATER_WAVE_RECORD_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/water/surface/WATER_WAVE_RECORD_STRUCT.js +23 -0
- package/src/shade/renderer/water/surface/chunk_water_tessellation.d.ts +9 -0
- package/src/shade/renderer/water/surface/chunk_water_tessellation.d.ts.map +1 -0
- package/src/shade/renderer/water/surface/chunk_water_tessellation.js +144 -0
- package/src/shade/renderer/water/surface/chunk_water_wave.d.ts +3 -5
- package/src/shade/renderer/water/surface/chunk_water_wave.d.ts.map +1 -1
- package/src/shade/renderer/water/surface/chunk_water_wave.js +40 -48
- package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts +14 -0
- package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts.map +1 -0
- package/src/shade/renderer/water/surface/graph_water_tessellation.js +34 -0
- package/src/shade/renderer/water/surface/shader_water_tiles.d.ts +4 -0
- package/src/shade/renderer/water/surface/shader_water_tiles.d.ts.map +1 -0
- package/src/shade/renderer/water/surface/shader_water_tiles.js +123 -0
- package/src/shade/renderer/water/surface/shader_water_wave_batch.d.ts +6 -0
- package/src/shade/renderer/water/surface/shader_water_wave_batch.d.ts.map +1 -0
- package/src/shade/renderer/water/surface/shader_water_wave_batch.js +85 -0
- package/src/shade/renderer/water/surface/shader_water_wave_domain.d.ts +6 -0
- package/src/shade/renderer/water/surface/shader_water_wave_domain.d.ts.map +1 -0
- package/src/shade/renderer/water/surface/shader_water_wave_domain.js +83 -0
- package/src/shade/renderer/water/water_height_texture_from_sampler.d.ts.map +1 -1
- package/src/shade/renderer/water/water_height_texture_from_sampler.js +4 -3
- package/src/engine/ecs/ik/IKConstraint.d.ts +0 -52
- package/src/engine/ecs/ik/IKConstraint.d.ts.map +0 -1
- package/src/engine/ecs/ik/IKConstraint.js +0 -95
- package/src/engine/ecs/ik/IKProblem.d.ts +0 -45
- package/src/engine/ecs/ik/IKProblem.d.ts.map +0 -1
- package/src/engine/ecs/ik/IKProblem.js +0 -58
- package/src/engine/ecs/ik/IKSolver.d.ts +0 -8
- package/src/engine/ecs/ik/IKSolver.d.ts.map +0 -1
- package/src/engine/ecs/ik/IKSolver.js +0 -9
- package/src/engine/ecs/ik/InverseKinematics.d.ts +0 -48
- package/src/engine/ecs/ik/InverseKinematics.d.ts.map +0 -1
- package/src/engine/ecs/ik/InverseKinematics.js +0 -119
- package/src/engine/ecs/ik/InverseKinematicsSerializationAdapter.d.ts +0 -19
- package/src/engine/ecs/ik/InverseKinematicsSerializationAdapter.d.ts.map +0 -1
- package/src/engine/ecs/ik/InverseKinematicsSerializationAdapter.js +0 -72
- package/src/engine/ecs/ik/InverseKinematicsSystem.d.ts +0 -54
- package/src/engine/ecs/ik/InverseKinematicsSystem.d.ts.map +0 -1
- package/src/engine/ecs/ik/InverseKinematicsSystem.js +0 -212
- package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.d.ts +0 -8
- package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.d.ts.map +0 -1
- package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.js +0 -153
- package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.d.ts +0 -5
- package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.d.ts.map +0 -1
- package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.js +0 -120
- package/src/engine/ecs/ik/ik_bone_chain.d.ts +0 -64
- package/src/engine/ecs/ik/ik_bone_chain.d.ts.map +0 -1
- package/src/engine/ecs/ik/ik_bone_chain.js +0 -142
- package/src/engine/ecs/ik/ik_probe_terrain_contact.d.ts +0 -42
- package/src/engine/ecs/ik/ik_probe_terrain_contact.d.ts.map +0 -1
- package/src/engine/ecs/ik/ik_probe_terrain_contact.js +0 -123
- package/src/engine/ecs/ik/ik_write_local_rotation.d.ts +0 -18
- package/src/engine/ecs/ik/ik_write_local_rotation.d.ts.map +0 -1
- package/src/engine/ecs/ik/ik_write_local_rotation.js +0 -32
- package/src/engine/graphics/ecs/water/WATER_SIZE.d.ts +0 -2
- package/src/engine/graphics/ecs/water/WATER_SIZE.d.ts.map +0 -1
- package/src/engine/graphics/ecs/water/WATER_SIZE.js +0 -1
- package/src/shade/renderer/light/GPUViewLightContext.d.ts +0 -22
- package/src/shade/renderer/light/GPUViewLightContext.d.ts.map +0 -1
- package/src/shade/renderer/light/GPUViewLightContext.js +0 -62
- package/src/shade/renderer/shadow/map/csm/CSM_SHADOWMAP_STRUCT.d.ts +0 -14
- package/src/shade/renderer/shadow/map/csm/CSM_SHADOWMAP_STRUCT.d.ts.map +0 -1
- package/src/shade/renderer/shadow/map/csm/CSM_SHADOWMAP_STRUCT.js +0 -20
- package/src/shade/renderer/shadow/vsm/GPUViewShadowMaps.d.ts +0 -27
- package/src/shade/renderer/shadow/vsm/GPUViewShadowMaps.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/GPUViewShadowMaps.js +0 -147
- package/src/shade/renderer/shadow/vsm/GPUVirtualShadowTextureResidence.d.ts +0 -7
- package/src/shade/renderer/shadow/vsm/GPUVirtualShadowTextureResidence.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/GPUVirtualShadowTextureResidence.js +0 -10
- package/src/shade/renderer/shadow/vsm/VSM_RESIDENCE_WORKGROUP_TILE_RESOLUTION.d.ts +0 -2
- package/src/shade/renderer/shadow/vsm/VSM_RESIDENCE_WORKGROUP_TILE_RESOLUTION.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/VSM_RESIDENCE_WORKGROUP_TILE_RESOLUTION.js +0 -1
- package/src/shade/renderer/shadow/vsm/VSM_UNIFORMS_STRUCT.d.ts +0 -3
- package/src/shade/renderer/shadow/vsm/VSM_UNIFORMS_STRUCT.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/VSM_UNIFORMS_STRUCT.js +0 -8
- package/src/shade/renderer/shadow/vsm/VirtualShadowmapRenderer.d.ts +0 -27
- package/src/shade/renderer/shadow/vsm/VirtualShadowmapRenderer.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/VirtualShadowmapRenderer.js +0 -102
- package/src/shade/renderer/shadow/vsm/debug_inspect_coarse_bounds_buffer.d.ts +0 -8
- package/src/shade/renderer/shadow/vsm/debug_inspect_coarse_bounds_buffer.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/debug_inspect_coarse_bounds_buffer.js +0 -34
- package/src/shade/renderer/shadow/vsm/debug_inspect_residence_buffer.d.ts +0 -10
- package/src/shade/renderer/shadow/vsm/debug_inspect_residence_buffer.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/debug_inspect_residence_buffer.js +0 -64
- package/src/shade/renderer/shadow/vsm/decode_tile_address.d.ts +0 -11
- package/src/shade/renderer/shadow/vsm/decode_tile_address.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/decode_tile_address.js +0 -26
- package/src/shade/renderer/shadow/vsm/render/vms_render_tiles.d.ts +0 -2
- package/src/shade/renderer/shadow/vsm/render/vms_render_tiles.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/render/vms_render_tiles.js +0 -11
- package/src/shade/renderer/shadow/vsm/vms_pipeline_compute_coarse_bounds.d.ts +0 -20
- package/src/shade/renderer/shadow/vsm/vms_pipeline_compute_coarse_bounds.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/vms_pipeline_compute_coarse_bounds.js +0 -184
- package/src/shade/renderer/shadow/vsm/vsm_residence_pipeline.d.ts +0 -25
- package/src/shade/renderer/shadow/vsm/vsm_residence_pipeline.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/vsm_residence_pipeline.js +0 -230
- package/src/shade/renderer/shadow/vsm/vsm_tile_allocation_pipeline.d.ts +0 -19
- package/src/shade/renderer/shadow/vsm/vsm_tile_allocation_pipeline.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/vsm_tile_allocation_pipeline.js +0 -127
- package/src/shade/renderer/texture/encode/ENCODE_NOTES_2026_09_02.md +0 -462
- package/src/shade/renderer/water/optics/chunk_water_light_transmittance.d.ts +0 -23
- package/src/shade/renderer/water/optics/chunk_water_light_transmittance.d.ts.map +0 -1
- package/src/shade/renderer/water/optics/chunk_water_light_transmittance_dry.d.ts +0 -18
- package/src/shade/renderer/water/optics/chunk_water_light_transmittance_dry.d.ts.map +0 -1
- package/src/shade/renderer/water/surface/WATER_SURFACE_VERTEX_STRUCT.d.ts +0 -12
- package/src/shade/renderer/water/surface/WATER_SURFACE_VERTEX_STRUCT.d.ts.map +0 -1
- package/src/shade/renderer/water/surface/WATER_SURFACE_VERTEX_STRUCT.js +0 -27
- package/src/shade/renderer/water/surface/WATER_WAVE_PARAMETERS_STRUCT.d.ts +0 -14
- package/src/shade/renderer/water/surface/WATER_WAVE_PARAMETERS_STRUCT.d.ts.map +0 -1
- package/src/shade/renderer/water/surface/WATER_WAVE_PARAMETERS_STRUCT.js +0 -49
- package/src/shade/renderer/water/surface/chunk_water_wave_grid.d.ts +0 -9
- package/src/shade/renderer/water/surface/chunk_water_wave_grid.d.ts.map +0 -1
- package/src/shade/renderer/water/surface/chunk_water_wave_grid.js +0 -47
- package/src/shade/renderer/water/surface/shader_water_surface_write.d.ts +0 -10
- package/src/shade/renderer/water/surface/shader_water_surface_write.d.ts.map +0 -1
- package/src/shade/renderer/water/surface/shader_water_surface_write.js +0 -51
- package/src/shade/renderer/water/surface/shader_water_wave_step.d.ts +0 -12
- package/src/shade/renderer/water/surface/shader_water_wave_step.d.ts.map +0 -1
- package/src/shade/renderer/water/surface/shader_water_wave_step.js +0 -54
- package/src/shade/renderer/water/surface/water_surface_grid_indices.d.ts +0 -13
- package/src/shade/renderer/water/surface/water_surface_grid_indices.d.ts.map +0 -1
- package/src/shade/renderer/water/surface/water_surface_grid_indices.js +0 -39
|
@@ -0,0 +1,1408 @@
|
|
|
1
|
+
import { assert } from "../../../../core/assert.js";
|
|
2
|
+
import { IndexedFloatMaxHeap } from "../../../../core/collection/heap/IndexedFloatMaxHeap.js";
|
|
3
|
+
import { isPowerOfTwo } from "../../../../core/math/isPowerOfTwo.js";
|
|
4
|
+
import { VT_ENTRY_INVALID, VT_ENTRY_PHYS_MASK, vt_entry_pack } from "../../texture/virtual/VT_CONSTANTS.js";
|
|
5
|
+
import { VTPhysicalSlots } from "../../texture/virtual/VTPhysicalSlots.js";
|
|
6
|
+
import { VSM_COVER_LEVEL_STEP } from "./VSM_COVER_LEVEL_STEP.js";
|
|
7
|
+
import { VSM_FEEDBACK_LAYOUT, vsm_feedback_stale_offset } from "./VSM_FEEDBACK_LAYOUT.js";
|
|
8
|
+
import { VSM_LEVEL_LIMIT } from "./VSM_LEVEL_LIMIT.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Candidate kinds. A **cover** — a page several levels up that gives pixels with nothing resident
|
|
12
|
+
* above them a shadow at all — is served before anything else. Everything else is an **update**: a
|
|
13
|
+
* resident page that went stale under a mover while something looks at it, or a missing page that
|
|
14
|
+
* something coarser stands in for meanwhile.
|
|
15
|
+
*/
|
|
16
|
+
const KIND_UPDATE = 1;
|
|
17
|
+
const KIND_COVER = 2;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* What a cover scores above: an update scores `log2((1 + importance)(1 + frames waited))`, which
|
|
21
|
+
* stays under 64 for any screen's importance and any frame count a session reaches.
|
|
22
|
+
*/
|
|
23
|
+
const COVER_SCORE = 128;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Light spaces remembered: the view each recent light space began with, so that a reading recorded
|
|
27
|
+
* under one that has since been replaced can be carried into the current one rather than refused.
|
|
28
|
+
* A reading is at most a few frames old — three readbacks in flight — and a light turning every frame
|
|
29
|
+
* replaces its light space every frame, so sixteen is room to spare.
|
|
30
|
+
*/
|
|
31
|
+
const LIGHT_SPACE_HISTORY = 16;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Where a page of a level lands when carried from one light view to another, through a receiver
|
|
35
|
+
* point at the page's centre and a depth along the old light: back to the world through the old
|
|
36
|
+
* view's transpose — light views are rotations — and into the new view. Exact for the point,
|
|
37
|
+
* approximate for the page.
|
|
38
|
+
*
|
|
39
|
+
* @param {ArrayLike<number>} from view the page was asked for under
|
|
40
|
+
* @param {number} from_offset where that view starts in `from`
|
|
41
|
+
* @param {ArrayLike<number>} to view to carry it into
|
|
42
|
+
* @param {number} size world size of a page of the level
|
|
43
|
+
* @param {number} x page
|
|
44
|
+
* @param {number} y page
|
|
45
|
+
* @param {number} depth along the old light
|
|
46
|
+
* @param {Float64Array} out [x, y, depth] in the new view
|
|
47
|
+
*/
|
|
48
|
+
function carry_page(from, from_offset, to, size, x, y, depth, out) {
|
|
49
|
+
const f = from_offset;
|
|
50
|
+
|
|
51
|
+
// light space as the old view saw it; its view z is the depth negated
|
|
52
|
+
const lx = (x + 0.5) * size - from[f + 12];
|
|
53
|
+
const ly = (y + 0.5) * size - from[f + 13];
|
|
54
|
+
const lz = -depth - from[f + 14];
|
|
55
|
+
|
|
56
|
+
const wx = from[f] * lx + from[f + 1] * ly + from[f + 2] * lz;
|
|
57
|
+
const wy = from[f + 4] * lx + from[f + 5] * ly + from[f + 6] * lz;
|
|
58
|
+
const wz = from[f + 8] * lx + from[f + 9] * ly + from[f + 10] * lz;
|
|
59
|
+
|
|
60
|
+
const nx = to[0] * wx + to[4] * wy + to[8] * wz + to[12];
|
|
61
|
+
const ny = to[1] * wx + to[5] * wy + to[9] * wz + to[13];
|
|
62
|
+
const nz = to[2] * wx + to[6] * wy + to[10] * wz + to[14];
|
|
63
|
+
|
|
64
|
+
out[0] = Math.floor(nx / size);
|
|
65
|
+
out[1] = Math.floor(ny / size);
|
|
66
|
+
out[2] = -nz;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* A candidate's score.
|
|
71
|
+
*
|
|
72
|
+
* Updates compete by the importance of the pixels asking — their count, weighted by where they are
|
|
73
|
+
* on screen — times the frames they have waited: the weighting `compute_shadowmap_update_score`
|
|
74
|
+
* gives a local light's shadow map, area times staleness. A page
|
|
75
|
+
* kept stale by a mover is re-marked from zero each time it is redrawn, while a missing page's wait
|
|
76
|
+
* only grows until it arrives, so under constant motion the missing page still gets its turn: a
|
|
77
|
+
* strict "stale before missing" order starved it for as long as anything moved.
|
|
78
|
+
*
|
|
79
|
+
* In log2, so a float32 heap orders it exactly enough.
|
|
80
|
+
*
|
|
81
|
+
* @param {number} kind
|
|
82
|
+
* @param {number} importance of the pixels asking, as the demand pass sums it
|
|
83
|
+
* @param {number} waited frames
|
|
84
|
+
* @returns {number}
|
|
85
|
+
*/
|
|
86
|
+
function candidate_score(kind, importance, waited) {
|
|
87
|
+
if (kind === KIND_COVER) {
|
|
88
|
+
return COVER_SCORE + Math.log2(1 + importance);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return Math.log2((1 + importance) * (1 + waited));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* The CPU half of a virtual shadow map: what is resident where, what the GPU said it wanted and
|
|
96
|
+
* what it said went stale, and which pages to render this frame.
|
|
97
|
+
*
|
|
98
|
+
* It holds no GPU resource and draws nothing. The GPU's feedback comes in through
|
|
99
|
+
* {@link apply_reading}; the frame's pages go out through the job list {@link select} fills; and
|
|
100
|
+
* the rows the GPU reads — page-table entries, slot pages, window corners — change only as pages
|
|
101
|
+
* are installed, evicted and scrolled away, which the dirty lists say ({@link dirty_cell_count} and
|
|
102
|
+
* friends), so that writing them is O(what changed).
|
|
103
|
+
*
|
|
104
|
+
* **The clipmap.** `level_count` levels; a page of level `k` is `page_size · first_texel_size · 2^k`
|
|
105
|
+
* world units on a side, anchored to the world in light space. Each level keeps a window of
|
|
106
|
+
* `pages_per_level²` pages around the camera ({@link update_windows}), and a page of the window sits
|
|
107
|
+
* in cell `(x mod N, y mod N)` of the level — so a window that scrolls keeps every page still inside
|
|
108
|
+
* it where it was, and gives back only the pages it left behind.
|
|
109
|
+
*
|
|
110
|
+
* **The pool** is a {@link VTPhysicalSlots}: VT's slot grid, least-recently-touched eviction outside
|
|
111
|
+
* a protection window, and the finest page shed first on a tie.
|
|
112
|
+
*
|
|
113
|
+
* **What is rendered.** Each reading replaces the want set — it is a whole frame's snapshot — and
|
|
114
|
+
* {@link select} turns it into candidates for a max-heap, drained to the frame's budget:
|
|
115
|
+
* 1. first, a **cover** for every page that is missing with nothing coarser resident: one page
|
|
116
|
+
* {@link VSM_COVER_LEVEL_STEP} levels up, which gives every pixel under it a shadow at once,
|
|
117
|
+
* ordered by the importance of the pixels under it;
|
|
118
|
+
* 2. then the **updates** — a stale page something still looks at (wanted itself, or standing in
|
|
119
|
+
* for a wanted one), and a missing page something coarser stands in for meanwhile — ordered by
|
|
120
|
+
* the importance of the pixels asking times the frames waited, so that neither kind can starve
|
|
121
|
+
* the other.
|
|
122
|
+
*
|
|
123
|
+
* A pixel's importance is its weight under the screen importance mask, the automatic exposure's
|
|
124
|
+
* metering mask: full over most of the screen, less toward its edges.
|
|
125
|
+
*/
|
|
126
|
+
export class VSMPageManager {
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @type {number}
|
|
130
|
+
* @readonly
|
|
131
|
+
*/
|
|
132
|
+
level_count;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* A window's side, in pages. A power of two.
|
|
136
|
+
* @type {number}
|
|
137
|
+
* @readonly
|
|
138
|
+
*/
|
|
139
|
+
pages_per_level;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* World size of a level-0 texel.
|
|
143
|
+
* @type {number}
|
|
144
|
+
* @readonly
|
|
145
|
+
*/
|
|
146
|
+
first_texel_size;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Texels on a page's side, without the border.
|
|
150
|
+
* @type {number}
|
|
151
|
+
* @readonly
|
|
152
|
+
*/
|
|
153
|
+
page_size;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* @type {number}
|
|
157
|
+
* @readonly
|
|
158
|
+
*/
|
|
159
|
+
border;
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* The pool's slot bookkeeping.
|
|
163
|
+
* @type {VTPhysicalSlots}
|
|
164
|
+
* @readonly
|
|
165
|
+
*/
|
|
166
|
+
slots;
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Requests a reading holds at most — the feedback buffer's capacity.
|
|
170
|
+
* @type {number}
|
|
171
|
+
* @readonly
|
|
172
|
+
*/
|
|
173
|
+
request_capacity;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Frames a touched page is safe from eviction for. Has to outlast the readback, or a page in
|
|
177
|
+
* view is evicted between the frame that asked for it and the reading that says so.
|
|
178
|
+
* @type {number}
|
|
179
|
+
* @readonly
|
|
180
|
+
*/
|
|
181
|
+
protect_frames;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Per window cell of every level, the slot holding it, or -1.
|
|
185
|
+
* @type {Int32Array}
|
|
186
|
+
*/
|
|
187
|
+
#cell_slot;
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Per slot, the level of its page, or -1 for an empty slot.
|
|
191
|
+
* @type {Int32Array}
|
|
192
|
+
*/
|
|
193
|
+
#slot_level;
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Per slot, its page's world coordinates.
|
|
197
|
+
* @type {Int32Array}
|
|
198
|
+
*/
|
|
199
|
+
#slot_x;
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* @type {Int32Array}
|
|
203
|
+
*/
|
|
204
|
+
#slot_y;
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Per slot, 1 when a mover crossed it after it was last rendered.
|
|
208
|
+
* @type {Uint8Array}
|
|
209
|
+
*/
|
|
210
|
+
#slot_stale;
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Per slot, the frame it was last rendered in, or -1.
|
|
214
|
+
* @type {Float64Array}
|
|
215
|
+
*/
|
|
216
|
+
#slot_rendered;
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Per slot, the frame of the reading that marked it stale — how long a stale page has waited.
|
|
220
|
+
* @type {Float64Array}
|
|
221
|
+
*/
|
|
222
|
+
#slot_stale_since;
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Per cell, the frame a missing page started waiting, and the {@link select} it was last offered
|
|
226
|
+
* in — a page is waiting only while every select offers it.
|
|
227
|
+
* @type {Float64Array}
|
|
228
|
+
*/
|
|
229
|
+
#cell_wait_since;
|
|
230
|
+
#cell_wait_select;
|
|
231
|
+
#select_index = 0;
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Per level, the window's corner in world pages.
|
|
235
|
+
* @type {Int32Array}
|
|
236
|
+
*/
|
|
237
|
+
#origin_x;
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* @type {Int32Array}
|
|
241
|
+
*/
|
|
242
|
+
#origin_y;
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Whether {@link update_windows} has placed the windows yet.
|
|
246
|
+
* @type {boolean}
|
|
247
|
+
*/
|
|
248
|
+
#windows_placed = false;
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* The want set: the latest reading's requests, in its order.
|
|
252
|
+
*/
|
|
253
|
+
#want_level;
|
|
254
|
+
#want_x;
|
|
255
|
+
#want_y;
|
|
256
|
+
#want_importance;
|
|
257
|
+
#want_depth;
|
|
258
|
+
#want_count = 0;
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Recent light spaces, oldest overwritten first: each one's view, and the frame it began in.
|
|
262
|
+
*/
|
|
263
|
+
#history_views = new Float64Array(LIGHT_SPACE_HISTORY * 16);
|
|
264
|
+
#history_frames = new Float64Array(LIGHT_SPACE_HISTORY).fill(Infinity);
|
|
265
|
+
#history_next = 0;
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Where {@link carry_page} leaves a carried page.
|
|
269
|
+
*/
|
|
270
|
+
#carried = new Float64Array(3);
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* The frame of the latest reading applied; an older one arriving late is not applied.
|
|
274
|
+
* @type {number}
|
|
275
|
+
*/
|
|
276
|
+
#last_reading_frame = -Infinity;
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* The light space the pages were drawn in: the light view, and its depth range.
|
|
280
|
+
* @type {Float64Array}
|
|
281
|
+
*/
|
|
282
|
+
#view = new Float64Array(16);
|
|
283
|
+
#near = 0;
|
|
284
|
+
#far = 0;
|
|
285
|
+
#light_space_set = false;
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Candidate bookkeeping, per cell of every level: the heap, the stamp of the {@link select} that
|
|
289
|
+
* offered the cell, its kind, and the importance behind it.
|
|
290
|
+
*/
|
|
291
|
+
#heap;
|
|
292
|
+
#candidate_stamp;
|
|
293
|
+
#candidate_kind;
|
|
294
|
+
#candidate_importance;
|
|
295
|
+
#candidate_waited;
|
|
296
|
+
#stamp = 0;
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* The frame's jobs: a slot to render and the page it holds.
|
|
300
|
+
*/
|
|
301
|
+
#job_slot;
|
|
302
|
+
#job_level;
|
|
303
|
+
#job_x;
|
|
304
|
+
#job_y;
|
|
305
|
+
#job_count = 0;
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Rows that changed since {@link clear_dirty}.
|
|
309
|
+
*/
|
|
310
|
+
#dirty_cells;
|
|
311
|
+
#dirty_cell_mark;
|
|
312
|
+
#dirty_cell_count = 0;
|
|
313
|
+
#dirty_slots;
|
|
314
|
+
#dirty_slot_mark;
|
|
315
|
+
#dirty_slot_count = 0;
|
|
316
|
+
#levels_dirty = false;
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* What the manager did, cumulative since construction except where noted.
|
|
320
|
+
*/
|
|
321
|
+
stats = {
|
|
322
|
+
/** wants in the latest reading */
|
|
323
|
+
wants: 0,
|
|
324
|
+
/** wants the latest {@link select} found with nothing resident to stand in for them */
|
|
325
|
+
uncovered: 0,
|
|
326
|
+
/** candidates the latest {@link select} left for later frames, those it found no slot for included */
|
|
327
|
+
backlog: 0,
|
|
328
|
+
/** pages rendered by the latest {@link select} */
|
|
329
|
+
renders: 0,
|
|
330
|
+
/** movers in the latest reading, and whether there were more than the GPU could list */
|
|
331
|
+
movers: 0,
|
|
332
|
+
/** requests the GPU dropped past its capacity, in the latest reading */
|
|
333
|
+
requests_dropped: 0,
|
|
334
|
+
readings_applied: 0,
|
|
335
|
+
readings_dropped: 0,
|
|
336
|
+
installs: 0,
|
|
337
|
+
evictions: 0,
|
|
338
|
+
scroll_evictions: 0,
|
|
339
|
+
refused: 0,
|
|
340
|
+
stale_marked: 0,
|
|
341
|
+
invalidations: 0,
|
|
342
|
+
re_rendered: 0,
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* @param {Object} options
|
|
347
|
+
* @param {number} options.level_count
|
|
348
|
+
* @param {number} options.pages_per_level a power of two
|
|
349
|
+
* @param {number} options.first_texel_size world size of a level-0 texel
|
|
350
|
+
* @param {number} options.page_size texels on a page's side, without the border
|
|
351
|
+
* @param {number} options.border texels of border each side
|
|
352
|
+
* @param {number} options.pool_size texels on the pool's side
|
|
353
|
+
* @param {number} options.request_capacity requests a reading holds at most
|
|
354
|
+
* @param {number} options.protect_frames frames a touched page is safe from eviction for
|
|
355
|
+
*/
|
|
356
|
+
constructor({
|
|
357
|
+
level_count,
|
|
358
|
+
pages_per_level,
|
|
359
|
+
first_texel_size,
|
|
360
|
+
page_size,
|
|
361
|
+
border,
|
|
362
|
+
pool_size,
|
|
363
|
+
request_capacity,
|
|
364
|
+
protect_frames,
|
|
365
|
+
}) {
|
|
366
|
+
assert.isPositiveInteger(level_count, 'level_count');
|
|
367
|
+
assert.lessThanOrEqual(level_count, VSM_LEVEL_LIMIT, 'level_count');
|
|
368
|
+
assert.isPositiveInteger(pages_per_level, 'pages_per_level');
|
|
369
|
+
assert.ok(isPowerOfTwo(pages_per_level), 'pages_per_level must be a power of two');
|
|
370
|
+
assert.greaterThanOrEqual(pages_per_level, 2, 'pages_per_level');
|
|
371
|
+
assert.isNumber(first_texel_size, 'first_texel_size');
|
|
372
|
+
assert.greaterThan(first_texel_size, 0, 'first_texel_size');
|
|
373
|
+
assert.isPositiveInteger(page_size, 'page_size');
|
|
374
|
+
assert.isNonNegativeInteger(border, 'border');
|
|
375
|
+
assert.isPositiveInteger(pool_size, 'pool_size');
|
|
376
|
+
assert.isPositiveInteger(request_capacity, 'request_capacity');
|
|
377
|
+
assert.isPositiveInteger(protect_frames, 'protect_frames');
|
|
378
|
+
|
|
379
|
+
this.level_count = level_count;
|
|
380
|
+
this.pages_per_level = pages_per_level;
|
|
381
|
+
this.first_texel_size = first_texel_size;
|
|
382
|
+
this.page_size = page_size;
|
|
383
|
+
this.border = border;
|
|
384
|
+
this.request_capacity = request_capacity;
|
|
385
|
+
this.protect_frames = protect_frames;
|
|
386
|
+
|
|
387
|
+
const slots = this.slots = new VTPhysicalSlots({ atlas_size: pool_size, page_size, border });
|
|
388
|
+
|
|
389
|
+
// a page-table entry names its slot in eight bits a side
|
|
390
|
+
assert.lessThanOrEqual(slots.slots_per_axis, VT_ENTRY_PHYS_MASK + 1, 'slots per pool side');
|
|
391
|
+
|
|
392
|
+
const cell_count = level_count * pages_per_level * pages_per_level;
|
|
393
|
+
const capacity = slots.capacity;
|
|
394
|
+
|
|
395
|
+
this.#cell_slot = new Int32Array(cell_count).fill(-1);
|
|
396
|
+
|
|
397
|
+
this.#slot_level = new Int32Array(capacity).fill(-1);
|
|
398
|
+
this.#slot_x = new Int32Array(capacity);
|
|
399
|
+
this.#slot_y = new Int32Array(capacity);
|
|
400
|
+
this.#slot_stale = new Uint8Array(capacity);
|
|
401
|
+
this.#slot_rendered = new Float64Array(capacity).fill(-1);
|
|
402
|
+
this.#slot_stale_since = new Float64Array(capacity);
|
|
403
|
+
|
|
404
|
+
this.#origin_x = new Int32Array(level_count);
|
|
405
|
+
this.#origin_y = new Int32Array(level_count);
|
|
406
|
+
|
|
407
|
+
this.#want_level = new Uint8Array(request_capacity);
|
|
408
|
+
this.#want_x = new Int32Array(request_capacity);
|
|
409
|
+
this.#want_y = new Int32Array(request_capacity);
|
|
410
|
+
this.#want_importance = new Uint32Array(request_capacity);
|
|
411
|
+
this.#want_depth = new Float32Array(request_capacity);
|
|
412
|
+
|
|
413
|
+
this.#heap = new IndexedFloatMaxHeap(cell_count);
|
|
414
|
+
this.#candidate_stamp = new Uint32Array(cell_count);
|
|
415
|
+
this.#candidate_kind = new Uint8Array(cell_count);
|
|
416
|
+
this.#candidate_importance = new Float64Array(cell_count);
|
|
417
|
+
this.#candidate_waited = new Float64Array(cell_count);
|
|
418
|
+
|
|
419
|
+
this.#cell_wait_since = new Float64Array(cell_count);
|
|
420
|
+
this.#cell_wait_select = new Float64Array(cell_count).fill(-1);
|
|
421
|
+
|
|
422
|
+
this.#job_slot = new Uint32Array(capacity);
|
|
423
|
+
this.#job_level = new Int32Array(capacity);
|
|
424
|
+
this.#job_x = new Int32Array(capacity);
|
|
425
|
+
this.#job_y = new Int32Array(capacity);
|
|
426
|
+
|
|
427
|
+
this.#dirty_cells = new Uint32Array(cell_count);
|
|
428
|
+
this.#dirty_cell_mark = new Uint8Array(cell_count);
|
|
429
|
+
this.#dirty_slots = new Uint32Array(capacity);
|
|
430
|
+
this.#dirty_slot_mark = new Uint8Array(capacity);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* Cells of every level: the length of the page table.
|
|
435
|
+
* @returns {number}
|
|
436
|
+
*/
|
|
437
|
+
get cell_count() {
|
|
438
|
+
return this.#cell_slot.length;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* World units on the side of a page of a level.
|
|
443
|
+
*
|
|
444
|
+
* @param {number} level
|
|
445
|
+
* @returns {number}
|
|
446
|
+
*/
|
|
447
|
+
page_world_size(level) {
|
|
448
|
+
return this.page_size * this.first_texel_size * 2 ** level;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* The page-table row, from the map's first, of a world page's cell.
|
|
453
|
+
*
|
|
454
|
+
* @param {number} level
|
|
455
|
+
* @param {number} x world page
|
|
456
|
+
* @param {number} y world page
|
|
457
|
+
* @returns {number}
|
|
458
|
+
*/
|
|
459
|
+
cell_of(level, x, y) {
|
|
460
|
+
const n = this.pages_per_level;
|
|
461
|
+
const mask = n - 1;
|
|
462
|
+
|
|
463
|
+
return (level * n + (y & mask)) * n + (x & mask);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* @param {number} level
|
|
468
|
+
* @returns {number} the level's window corner, world pages
|
|
469
|
+
*/
|
|
470
|
+
origin_x(level) {
|
|
471
|
+
return this.#origin_x[level];
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* @param {number} level
|
|
476
|
+
* @returns {number}
|
|
477
|
+
*/
|
|
478
|
+
origin_y(level) {
|
|
479
|
+
return this.#origin_y[level];
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* @param {number} level
|
|
484
|
+
* @param {number} x
|
|
485
|
+
* @param {number} y
|
|
486
|
+
* @returns {boolean}
|
|
487
|
+
*/
|
|
488
|
+
window_contains(level, x, y) {
|
|
489
|
+
const n = this.pages_per_level;
|
|
490
|
+
const rx = x - this.#origin_x[level];
|
|
491
|
+
const ry = y - this.#origin_y[level];
|
|
492
|
+
|
|
493
|
+
return this.#windows_placed && rx >= 0 && ry >= 0 && rx < n && ry < n;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* The slot holding a world page, or -1 when it is not resident or not in its level's window.
|
|
498
|
+
*
|
|
499
|
+
* @param {number} level
|
|
500
|
+
* @param {number} x
|
|
501
|
+
* @param {number} y
|
|
502
|
+
* @returns {number}
|
|
503
|
+
*/
|
|
504
|
+
slot_of_page(level, x, y) {
|
|
505
|
+
if (!this.window_contains(level, x, y)) {
|
|
506
|
+
return -1;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
return this.#cell_slot[this.cell_of(level, x, y)];
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Place every level's window around the camera, giving back the pages a window leaves behind.
|
|
514
|
+
*
|
|
515
|
+
* @param {number} light_x the camera, across the light
|
|
516
|
+
* @param {number} light_y
|
|
517
|
+
*/
|
|
518
|
+
update_windows(light_x, light_y) {
|
|
519
|
+
assert.isFinite(light_x, 'light_x');
|
|
520
|
+
assert.isFinite(light_y, 'light_y');
|
|
521
|
+
|
|
522
|
+
const half = this.pages_per_level >> 1;
|
|
523
|
+
|
|
524
|
+
for (let level = 0; level < this.level_count; level++) {
|
|
525
|
+
const size = this.page_world_size(level);
|
|
526
|
+
|
|
527
|
+
const x = Math.floor(light_x / size) - half;
|
|
528
|
+
const y = Math.floor(light_y / size) - half;
|
|
529
|
+
|
|
530
|
+
const old_x = this.#origin_x[level];
|
|
531
|
+
const old_y = this.#origin_y[level];
|
|
532
|
+
|
|
533
|
+
if (this.#windows_placed) {
|
|
534
|
+
if (x === old_x && y === old_y) {
|
|
535
|
+
continue;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
this.#evict_vacated(level, old_x, old_y, x, y);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
this.#origin_x[level] = x;
|
|
542
|
+
this.#origin_y[level] = y;
|
|
543
|
+
this.#levels_dirty = true;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
this.#windows_placed = true;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* Give back every resident page of a level that its window, moving from one corner to the other,
|
|
551
|
+
* leaves behind. Walks the strips it vacates, or the whole level when it jumps a window or more.
|
|
552
|
+
*
|
|
553
|
+
* @param {number} level
|
|
554
|
+
* @param {number} old_x
|
|
555
|
+
* @param {number} old_y
|
|
556
|
+
* @param {number} new_x
|
|
557
|
+
* @param {number} new_y
|
|
558
|
+
*/
|
|
559
|
+
#evict_vacated(level, old_x, old_y, new_x, new_y) {
|
|
560
|
+
const n = this.pages_per_level;
|
|
561
|
+
|
|
562
|
+
if (Math.abs(new_x - old_x) >= n || Math.abs(new_y - old_y) >= n) {
|
|
563
|
+
const first = level * n * n;
|
|
564
|
+
|
|
565
|
+
for (let cell = first; cell < first + n * n; cell++) {
|
|
566
|
+
const slot = this.#cell_slot[cell];
|
|
567
|
+
|
|
568
|
+
if (slot !== -1) {
|
|
569
|
+
this.#evict(slot);
|
|
570
|
+
this.stats.scroll_evictions++;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
// the columns of the old window outside the new one, all rows
|
|
578
|
+
const keep_x0 = Math.max(old_x, new_x);
|
|
579
|
+
const keep_x1 = Math.min(old_x, new_x) + n;
|
|
580
|
+
|
|
581
|
+
for (let x = old_x; x < old_x + n; x++) {
|
|
582
|
+
if (x >= keep_x0 && x < keep_x1) {
|
|
583
|
+
continue;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
for (let y = old_y; y < old_y + n; y++) {
|
|
587
|
+
this.#evict_page_for_scroll(level, x, y);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// then the rows outside it, over the columns both windows share
|
|
592
|
+
const keep_y0 = Math.max(old_y, new_y);
|
|
593
|
+
const keep_y1 = Math.min(old_y, new_y) + n;
|
|
594
|
+
|
|
595
|
+
for (let y = old_y; y < old_y + n; y++) {
|
|
596
|
+
if (y >= keep_y0 && y < keep_y1) {
|
|
597
|
+
continue;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
for (let x = keep_x0; x < keep_x1; x++) {
|
|
601
|
+
this.#evict_page_for_scroll(level, x, y);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* @param {number} level
|
|
608
|
+
* @param {number} x
|
|
609
|
+
* @param {number} y
|
|
610
|
+
*/
|
|
611
|
+
#evict_page_for_scroll(level, x, y) {
|
|
612
|
+
const slot = this.#cell_slot[this.cell_of(level, x, y)];
|
|
613
|
+
|
|
614
|
+
if (slot === -1) {
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
this.#evict(slot);
|
|
619
|
+
this.stats.scroll_evictions++;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
/**
|
|
623
|
+
* Take the light space the pages are drawn in. A light space that differs from the last one —
|
|
624
|
+
* the light turned, or the depth range moved — invalidates every page: the want set is carried
|
|
625
|
+
* into the new light space through the receiver point each want recorded, every page is given
|
|
626
|
+
* back, and readings recorded before `frame` are refused.
|
|
627
|
+
*
|
|
628
|
+
* @param {ArrayLike<number>} view world to light space, column-major, rotation only
|
|
629
|
+
* @param {number} near
|
|
630
|
+
* @param {number} far
|
|
631
|
+
* @param {number} frame
|
|
632
|
+
* @returns {boolean} whether the pages were invalidated
|
|
633
|
+
*/
|
|
634
|
+
set_light_space(view, near, far, frame) {
|
|
635
|
+
assert.equal(view.length, 16, 'view.length');
|
|
636
|
+
assert.isFinite(near, 'near');
|
|
637
|
+
assert.isFinite(far, 'far');
|
|
638
|
+
|
|
639
|
+
const current = this.#view;
|
|
640
|
+
|
|
641
|
+
if (!this.#light_space_set) {
|
|
642
|
+
for (let i = 0; i < 16; i++) {
|
|
643
|
+
current[i] = view[i];
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
this.#near = near;
|
|
647
|
+
this.#far = far;
|
|
648
|
+
this.#light_space_set = true;
|
|
649
|
+
|
|
650
|
+
this.#remember_light_space(frame);
|
|
651
|
+
|
|
652
|
+
return false;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
let changed = near !== this.#near || far !== this.#far;
|
|
656
|
+
|
|
657
|
+
for (let i = 0; i < 16 && !changed; i++) {
|
|
658
|
+
changed = view[i] !== current[i];
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
if (!changed) {
|
|
662
|
+
return false;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
this.#reproject_wants(current, view);
|
|
666
|
+
|
|
667
|
+
for (let i = 0; i < 16; i++) {
|
|
668
|
+
current[i] = view[i];
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
this.#near = near;
|
|
672
|
+
this.#far = far;
|
|
673
|
+
|
|
674
|
+
this.#evict_all();
|
|
675
|
+
|
|
676
|
+
this.#remember_light_space(frame);
|
|
677
|
+
this.stats.invalidations++;
|
|
678
|
+
|
|
679
|
+
return true;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
/**
|
|
683
|
+
* Remember the current light space as beginning in `frame`.
|
|
684
|
+
*
|
|
685
|
+
* @param {number} frame
|
|
686
|
+
*/
|
|
687
|
+
#remember_light_space(frame) {
|
|
688
|
+
const i = this.#history_next;
|
|
689
|
+
|
|
690
|
+
this.#history_views.set(this.#view, i * 16);
|
|
691
|
+
this.#history_frames[i] = frame;
|
|
692
|
+
|
|
693
|
+
this.#history_next = (i + 1) % LIGHT_SPACE_HISTORY;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
/**
|
|
697
|
+
* The remembered light space a reading recorded in `frame` was asked under: the latest one that
|
|
698
|
+
* began no later than it. -1 when it is older than every one remembered.
|
|
699
|
+
*
|
|
700
|
+
* @param {number} frame
|
|
701
|
+
* @returns {number} history index
|
|
702
|
+
*/
|
|
703
|
+
#light_space_at(frame) {
|
|
704
|
+
let best = -1;
|
|
705
|
+
let best_frame = -Infinity;
|
|
706
|
+
|
|
707
|
+
for (let i = 0; i < LIGHT_SPACE_HISTORY; i++) {
|
|
708
|
+
const began = this.#history_frames[i];
|
|
709
|
+
|
|
710
|
+
if (began <= frame && began > best_frame) {
|
|
711
|
+
best = i;
|
|
712
|
+
best_frame = began;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
return best;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
/**
|
|
720
|
+
* Carry the want set from one light space to another, each want through its page centre and
|
|
721
|
+
* the receiver depth it recorded ({@link carry_page}). The next reading replaces it.
|
|
722
|
+
*
|
|
723
|
+
* @param {ArrayLike<number>} from
|
|
724
|
+
* @param {ArrayLike<number>} to
|
|
725
|
+
*/
|
|
726
|
+
#reproject_wants(from, to) {
|
|
727
|
+
const count = this.#want_count;
|
|
728
|
+
const carried = this.#carried;
|
|
729
|
+
|
|
730
|
+
for (let i = 0; i < count; i++) {
|
|
731
|
+
carry_page(from, 0, to, this.page_world_size(this.#want_level[i]), this.#want_x[i], this.#want_y[i], this.#want_depth[i], carried);
|
|
732
|
+
|
|
733
|
+
this.#want_x[i] = carried[0];
|
|
734
|
+
this.#want_y[i] = carried[1];
|
|
735
|
+
this.#want_depth[i] = carried[2];
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* Give back every resident page.
|
|
741
|
+
*/
|
|
742
|
+
#evict_all() {
|
|
743
|
+
const capacity = this.slots.capacity;
|
|
744
|
+
|
|
745
|
+
for (let slot = 0; slot < capacity; slot++) {
|
|
746
|
+
if (this.#slot_level[slot] !== -1) {
|
|
747
|
+
this.#evict(slot);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
/**
|
|
753
|
+
* Take a frame's feedback: the pages wanted, which become the want set, and the slots a mover
|
|
754
|
+
* crossed. A reading recorded under a light space that has since been replaced has its wants
|
|
755
|
+
* carried into the current one through the view it was recorded under; one older than every
|
|
756
|
+
* light space remembered, or older than a reading already applied, is refused.
|
|
757
|
+
*
|
|
758
|
+
* @param {Uint32Array} words the feedback buffer, {@link VSM_FEEDBACK_LAYOUT}
|
|
759
|
+
* @param {Float32Array} floats the same words as f32
|
|
760
|
+
* @param {number} reading_frame the frame the GPU recorded it in
|
|
761
|
+
* @returns {boolean} whether it was applied
|
|
762
|
+
*/
|
|
763
|
+
apply_reading(words, floats, reading_frame) {
|
|
764
|
+
assert.equal(words.buffer, floats.buffer, 'words and floats must view the same memory');
|
|
765
|
+
assert.equal(words.byteOffset, floats.byteOffset, 'words and floats must start together');
|
|
766
|
+
|
|
767
|
+
const recorded_under = reading_frame > this.#last_reading_frame ? this.#light_space_at(reading_frame) : -1;
|
|
768
|
+
|
|
769
|
+
if (recorded_under === -1) {
|
|
770
|
+
this.stats.readings_dropped++;
|
|
771
|
+
return false;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
// the light space has changed since: each want goes through the view it was asked under
|
|
775
|
+
const carry = this.#history_frames[recorded_under] !== this.#history_frames[(this.#history_next + LIGHT_SPACE_HISTORY - 1) % LIGHT_SPACE_HISTORY];
|
|
776
|
+
const carried = this.#carried;
|
|
777
|
+
|
|
778
|
+
this.#last_reading_frame = reading_frame;
|
|
779
|
+
this.stats.readings_applied++;
|
|
780
|
+
|
|
781
|
+
const L = VSM_FEEDBACK_LAYOUT;
|
|
782
|
+
const capacity = this.request_capacity;
|
|
783
|
+
const asked = words[L.REQUEST_COUNT];
|
|
784
|
+
const count = Math.min(asked, capacity);
|
|
785
|
+
|
|
786
|
+
this.stats.requests_dropped = asked - count;
|
|
787
|
+
this.stats.movers = words[L.MOVER_COUNT];
|
|
788
|
+
|
|
789
|
+
let wants = 0;
|
|
790
|
+
|
|
791
|
+
for (let i = 0; i < count; i++) {
|
|
792
|
+
const base = L.HEADER_WORDS + i * L.REQUEST_WORDS;
|
|
793
|
+
const level = words[base + L.REQUEST_LEVEL];
|
|
794
|
+
|
|
795
|
+
if (level >= this.level_count) {
|
|
796
|
+
continue;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
let x = words[base + L.REQUEST_X] | 0;
|
|
800
|
+
let y = words[base + L.REQUEST_Y] | 0;
|
|
801
|
+
let depth = floats[base + L.REQUEST_DEPTH];
|
|
802
|
+
|
|
803
|
+
if (carry) {
|
|
804
|
+
carry_page(this.#history_views, recorded_under * 16, this.#view, this.page_world_size(level), x, y, depth, carried);
|
|
805
|
+
|
|
806
|
+
x = carried[0];
|
|
807
|
+
y = carried[1];
|
|
808
|
+
depth = carried[2];
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
this.#want_level[wants] = level;
|
|
812
|
+
this.#want_x[wants] = x;
|
|
813
|
+
this.#want_y[wants] = y;
|
|
814
|
+
this.#want_importance[wants] = words[base + L.REQUEST_IMPORTANCE];
|
|
815
|
+
this.#want_depth[wants] = depth;
|
|
816
|
+
|
|
817
|
+
wants++;
|
|
818
|
+
|
|
819
|
+
// what the pixels sample — the page, or whatever stands in for it — is in use
|
|
820
|
+
const slot = this.slot_of_page(level, x, y);
|
|
821
|
+
|
|
822
|
+
if (slot !== -1) {
|
|
823
|
+
this.#touch(slot, reading_frame);
|
|
824
|
+
} else {
|
|
825
|
+
const fallback = this.#find_fallback(level, x, y);
|
|
826
|
+
|
|
827
|
+
if (fallback !== -1) {
|
|
828
|
+
this.#touch(fallback, reading_frame);
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
this.#want_count = wants;
|
|
834
|
+
this.stats.wants = wants;
|
|
835
|
+
|
|
836
|
+
const slot_capacity = this.slots.capacity;
|
|
837
|
+
const stale_offset = vsm_feedback_stale_offset(capacity);
|
|
838
|
+
const stale_count = Math.min(words[L.STALE_COUNT], slot_capacity);
|
|
839
|
+
|
|
840
|
+
for (let i = 0; i < stale_count; i++) {
|
|
841
|
+
const slot = words[stale_offset + i];
|
|
842
|
+
|
|
843
|
+
if (slot >= slot_capacity || this.#slot_level[slot] === -1) {
|
|
844
|
+
continue;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
// a page drawn in the frame the mover was seen, or later, already shows it
|
|
848
|
+
if (this.#slot_rendered[slot] >= reading_frame) {
|
|
849
|
+
continue;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
if (this.#slot_stale[slot] === 0) {
|
|
853
|
+
this.#slot_stale[slot] = 1;
|
|
854
|
+
this.#slot_stale_since[slot] = reading_frame;
|
|
855
|
+
this.stats.stale_marked++;
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
return true;
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
/**
|
|
863
|
+
* Touch a slot, never moving its last touch back: a late reading must not age a page a later
|
|
864
|
+
* frame used.
|
|
865
|
+
*
|
|
866
|
+
* @param {number} slot
|
|
867
|
+
* @param {number} frame
|
|
868
|
+
*/
|
|
869
|
+
#touch(slot, frame) {
|
|
870
|
+
const slots = this.slots;
|
|
871
|
+
|
|
872
|
+
if (slots.last_touch(slot) < frame) {
|
|
873
|
+
slots.touch(slot, frame);
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
/**
|
|
878
|
+
* The resident page standing in for a world page: its nearest resident ancestor whose level's
|
|
879
|
+
* window holds it, or -1.
|
|
880
|
+
*
|
|
881
|
+
* @param {number} level
|
|
882
|
+
* @param {number} x
|
|
883
|
+
* @param {number} y
|
|
884
|
+
* @returns {number} slot
|
|
885
|
+
*/
|
|
886
|
+
#find_fallback(level, x, y) {
|
|
887
|
+
for (let up = level + 1; up < this.level_count; up++) {
|
|
888
|
+
const shift = up - level;
|
|
889
|
+
const slot = this.slot_of_page(up, x >> shift, y >> shift);
|
|
890
|
+
|
|
891
|
+
if (slot !== -1) {
|
|
892
|
+
return slot;
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
return -1;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
/**
|
|
900
|
+
* Offer a cell to this frame's heap. A cell offered twice keeps the higher kind, the sum of the
|
|
901
|
+
* importance behind it, and the longer wait.
|
|
902
|
+
*
|
|
903
|
+
* @param {number} cell
|
|
904
|
+
* @param {number} kind
|
|
905
|
+
* @param {number} importance
|
|
906
|
+
* @param {number} waited frames
|
|
907
|
+
*/
|
|
908
|
+
#offer(cell, kind, importance, waited) {
|
|
909
|
+
const heap = this.#heap;
|
|
910
|
+
|
|
911
|
+
if (this.#candidate_stamp[cell] === this.#stamp) {
|
|
912
|
+
if (kind > this.#candidate_kind[cell]) {
|
|
913
|
+
this.#candidate_kind[cell] = kind;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
if (waited > this.#candidate_waited[cell]) {
|
|
917
|
+
this.#candidate_waited[cell] = waited;
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
const total = this.#candidate_importance[cell] + importance;
|
|
921
|
+
|
|
922
|
+
this.#candidate_importance[cell] = total;
|
|
923
|
+
|
|
924
|
+
heap.update(cell, candidate_score(this.#candidate_kind[cell], total, this.#candidate_waited[cell]));
|
|
925
|
+
|
|
926
|
+
return;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
this.#candidate_stamp[cell] = this.#stamp;
|
|
930
|
+
this.#candidate_kind[cell] = kind;
|
|
931
|
+
this.#candidate_importance[cell] = importance;
|
|
932
|
+
this.#candidate_waited[cell] = waited;
|
|
933
|
+
|
|
934
|
+
heap.insert(cell, candidate_score(kind, importance, waited));
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
/**
|
|
938
|
+
* How long a missing cell has waited: since the first of an unbroken run of selects that each
|
|
939
|
+
* offered it. A page that stopped being wanted, or arrived, starts again from nothing.
|
|
940
|
+
*
|
|
941
|
+
* @param {number} cell
|
|
942
|
+
* @param {number} frame
|
|
943
|
+
* @returns {number} frames
|
|
944
|
+
*/
|
|
945
|
+
#missing_wait(cell, frame) {
|
|
946
|
+
const last = this.#cell_wait_select[cell];
|
|
947
|
+
const now = this.#select_index;
|
|
948
|
+
|
|
949
|
+
if (last !== now && last !== now - 1) {
|
|
950
|
+
this.#cell_wait_since[cell] = frame;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
this.#cell_wait_select[cell] = now;
|
|
954
|
+
|
|
955
|
+
return frame - this.#cell_wait_since[cell];
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
/**
|
|
959
|
+
* @param {number} slot
|
|
960
|
+
* @param {number} frame
|
|
961
|
+
* @returns {number} frames the slot has been stale
|
|
962
|
+
*/
|
|
963
|
+
#stale_wait(slot, frame) {
|
|
964
|
+
return Math.max(0, frame - this.#slot_stale_since[slot]);
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
/**
|
|
968
|
+
* Choose and claim this frame's pages: candidates from the want set into the heap, then drained
|
|
969
|
+
* best first until `budget` pages are to be rendered. A missing page takes a free slot, or the
|
|
970
|
+
* least recently touched one outside the protection window; when there is none it is refused
|
|
971
|
+
* and the next candidate is tried. Fills the job list.
|
|
972
|
+
*
|
|
973
|
+
* @param {number} frame
|
|
974
|
+
* @param {number} budget pages to render at most
|
|
975
|
+
*/
|
|
976
|
+
select(frame, budget) {
|
|
977
|
+
assert.isNonNegativeInteger(budget, 'budget');
|
|
978
|
+
|
|
979
|
+
const heap = this.#heap;
|
|
980
|
+
|
|
981
|
+
heap.clear();
|
|
982
|
+
this.#job_count = 0;
|
|
983
|
+
|
|
984
|
+
this.#select_index++;
|
|
985
|
+
this.#stamp = (this.#stamp + 1) >>> 0;
|
|
986
|
+
|
|
987
|
+
if (this.#stamp === 0) {
|
|
988
|
+
// the stamps wrapped: no cell may still look offered
|
|
989
|
+
this.#candidate_stamp.fill(0);
|
|
990
|
+
this.#stamp = 1;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
let uncovered = 0;
|
|
994
|
+
|
|
995
|
+
const level_count = this.level_count;
|
|
996
|
+
|
|
997
|
+
for (let i = 0; i < this.#want_count; i++) {
|
|
998
|
+
const level = this.#want_level[i];
|
|
999
|
+
const x = this.#want_x[i];
|
|
1000
|
+
const y = this.#want_y[i];
|
|
1001
|
+
const importance = this.#want_importance[i];
|
|
1002
|
+
|
|
1003
|
+
if (!this.window_contains(level, x, y)) {
|
|
1004
|
+
// scrolled out of its window since it was asked for
|
|
1005
|
+
continue;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
const cell = this.cell_of(level, x, y);
|
|
1009
|
+
const slot = this.#cell_slot[cell];
|
|
1010
|
+
|
|
1011
|
+
if (slot !== -1) {
|
|
1012
|
+
if (this.#slot_stale[slot] !== 0) {
|
|
1013
|
+
this.#offer(cell, KIND_UPDATE, importance, this.#stale_wait(slot, frame));
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
continue;
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
const waited = this.#missing_wait(cell, frame);
|
|
1020
|
+
const fallback = this.#find_fallback(level, x, y);
|
|
1021
|
+
|
|
1022
|
+
if (fallback !== -1) {
|
|
1023
|
+
this.#offer(cell, KIND_UPDATE, importance, waited);
|
|
1024
|
+
|
|
1025
|
+
if (this.#slot_stale[fallback] !== 0) {
|
|
1026
|
+
// what these pixels see meanwhile is stale too
|
|
1027
|
+
this.#offer(this.#cell_of_slot(fallback), KIND_UPDATE, importance, this.#stale_wait(fallback, frame));
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
continue;
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
uncovered++;
|
|
1034
|
+
|
|
1035
|
+
// the page itself, behind the cover: a budget with room for both fills it this frame
|
|
1036
|
+
this.#offer(cell, KIND_UPDATE, importance, waited);
|
|
1037
|
+
|
|
1038
|
+
let cover = Math.min(level + VSM_COVER_LEVEL_STEP, level_count - 1);
|
|
1039
|
+
|
|
1040
|
+
while (cover < level_count && !this.window_contains(cover, x >> (cover - level), y >> (cover - level))) {
|
|
1041
|
+
cover++;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
if (cover < level_count) {
|
|
1045
|
+
const shift = cover - level;
|
|
1046
|
+
|
|
1047
|
+
this.#offer(this.cell_of(cover, x >> shift, y >> shift), KIND_COVER, importance, 0);
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
this.stats.uncovered = uncovered;
|
|
1052
|
+
|
|
1053
|
+
const n = this.pages_per_level;
|
|
1054
|
+
const cells_per_level = n * n;
|
|
1055
|
+
const mask = n - 1;
|
|
1056
|
+
|
|
1057
|
+
let renders = 0;
|
|
1058
|
+
|
|
1059
|
+
// once no slot can be had, none can for the rest of the frame — nothing below frees one —
|
|
1060
|
+
// so the pages after it wait without a search of the pool each
|
|
1061
|
+
let pool_exhausted = false;
|
|
1062
|
+
let refused = 0;
|
|
1063
|
+
|
|
1064
|
+
while (renders < budget && heap.size > 0) {
|
|
1065
|
+
const cell = heap.pop_max();
|
|
1066
|
+
const slot = this.#cell_slot[cell];
|
|
1067
|
+
|
|
1068
|
+
if (slot !== -1) {
|
|
1069
|
+
if (this.#slot_stale[slot] !== 0) {
|
|
1070
|
+
this.#render(slot, frame);
|
|
1071
|
+
this.stats.re_rendered++;
|
|
1072
|
+
renders++;
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
continue;
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
const level = (cell / cells_per_level) | 0;
|
|
1079
|
+
const local = cell - level * cells_per_level;
|
|
1080
|
+
const cell_x = local & mask;
|
|
1081
|
+
const cell_y = (local / n) | 0;
|
|
1082
|
+
|
|
1083
|
+
// the window's page in that cell
|
|
1084
|
+
const origin_x = this.#origin_x[level];
|
|
1085
|
+
const origin_y = this.#origin_y[level];
|
|
1086
|
+
const x = origin_x + ((cell_x - origin_x) & mask);
|
|
1087
|
+
const y = origin_y + ((cell_y - origin_y) & mask);
|
|
1088
|
+
|
|
1089
|
+
const claimed = pool_exhausted ? -1 : this.#claim_slot(frame, level);
|
|
1090
|
+
|
|
1091
|
+
if (claimed === -1) {
|
|
1092
|
+
pool_exhausted = true;
|
|
1093
|
+
refused++;
|
|
1094
|
+
continue;
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
this.#install(claimed, level, x, y, cell);
|
|
1098
|
+
this.#render(claimed, frame);
|
|
1099
|
+
renders++;
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
this.stats.renders = renders;
|
|
1103
|
+
this.stats.refused += refused;
|
|
1104
|
+
this.stats.backlog = heap.size + refused;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
/**
|
|
1108
|
+
* @param {number} slot
|
|
1109
|
+
* @returns {number} the cell its page sits in
|
|
1110
|
+
*/
|
|
1111
|
+
#cell_of_slot(slot) {
|
|
1112
|
+
return this.cell_of(this.#slot_level[slot], this.#slot_x[slot], this.#slot_y[slot]);
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
/**
|
|
1116
|
+
* A free slot, or the least recently touched page's outside the protection window; -1 when
|
|
1117
|
+
* there is neither.
|
|
1118
|
+
*
|
|
1119
|
+
* @param {number} frame
|
|
1120
|
+
* @param {number} level the page coming in
|
|
1121
|
+
* @returns {number}
|
|
1122
|
+
*/
|
|
1123
|
+
#claim_slot(frame, level) {
|
|
1124
|
+
const slots = this.slots;
|
|
1125
|
+
|
|
1126
|
+
const free = slots.allocate(frame, false, level);
|
|
1127
|
+
|
|
1128
|
+
if (free !== -1) {
|
|
1129
|
+
return free;
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
const victim = slots.find_eviction_candidate(frame, this.protect_frames);
|
|
1133
|
+
|
|
1134
|
+
if (victim === -1) {
|
|
1135
|
+
return -1;
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
this.#evict(victim);
|
|
1139
|
+
this.stats.evictions++;
|
|
1140
|
+
|
|
1141
|
+
return slots.allocate(frame, false, level);
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
/**
|
|
1145
|
+
* @param {number} slot
|
|
1146
|
+
* @param {number} level
|
|
1147
|
+
* @param {number} x
|
|
1148
|
+
* @param {number} y
|
|
1149
|
+
* @param {number} cell
|
|
1150
|
+
*/
|
|
1151
|
+
#install(slot, level, x, y, cell) {
|
|
1152
|
+
this.#cell_slot[cell] = slot;
|
|
1153
|
+
|
|
1154
|
+
this.#slot_level[slot] = level;
|
|
1155
|
+
this.#slot_x[slot] = x;
|
|
1156
|
+
this.#slot_y[slot] = y;
|
|
1157
|
+
this.#slot_stale[slot] = 0;
|
|
1158
|
+
|
|
1159
|
+
this.#mark_cell(cell);
|
|
1160
|
+
this.#mark_slot(slot);
|
|
1161
|
+
|
|
1162
|
+
this.stats.installs++;
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
/**
|
|
1166
|
+
* @param {number} slot
|
|
1167
|
+
* @param {number} frame
|
|
1168
|
+
*/
|
|
1169
|
+
#render(slot, frame) {
|
|
1170
|
+
const i = this.#job_count++;
|
|
1171
|
+
|
|
1172
|
+
this.#job_slot[i] = slot;
|
|
1173
|
+
this.#job_level[i] = this.#slot_level[slot];
|
|
1174
|
+
this.#job_x[i] = this.#slot_x[slot];
|
|
1175
|
+
this.#job_y[i] = this.#slot_y[slot];
|
|
1176
|
+
|
|
1177
|
+
this.#slot_stale[slot] = 0;
|
|
1178
|
+
this.#slot_rendered[slot] = frame;
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
/**
|
|
1182
|
+
* @param {number} slot
|
|
1183
|
+
*/
|
|
1184
|
+
#evict(slot) {
|
|
1185
|
+
const cell = this.#cell_of_slot(slot);
|
|
1186
|
+
|
|
1187
|
+
this.#cell_slot[cell] = -1;
|
|
1188
|
+
this.#mark_cell(cell);
|
|
1189
|
+
|
|
1190
|
+
this.#slot_level[slot] = -1;
|
|
1191
|
+
this.#slot_stale[slot] = 0;
|
|
1192
|
+
this.#slot_rendered[slot] = -1;
|
|
1193
|
+
this.#mark_slot(slot);
|
|
1194
|
+
|
|
1195
|
+
this.slots.free(slot);
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
/**
|
|
1199
|
+
* @param {number} cell
|
|
1200
|
+
*/
|
|
1201
|
+
#mark_cell(cell) {
|
|
1202
|
+
if (this.#dirty_cell_mark[cell] === 0) {
|
|
1203
|
+
this.#dirty_cell_mark[cell] = 1;
|
|
1204
|
+
this.#dirty_cells[this.#dirty_cell_count++] = cell;
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
/**
|
|
1209
|
+
* @param {number} slot
|
|
1210
|
+
*/
|
|
1211
|
+
#mark_slot(slot) {
|
|
1212
|
+
if (this.#dirty_slot_mark[slot] === 0) {
|
|
1213
|
+
this.#dirty_slot_mark[slot] = 1;
|
|
1214
|
+
this.#dirty_slots[this.#dirty_slot_count++] = slot;
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
/**
|
|
1219
|
+
* The page-table entry of a cell: the slot holding it, as {@link vt_entry_pack} packs it, or
|
|
1220
|
+
* {@link VT_ENTRY_INVALID}.
|
|
1221
|
+
*
|
|
1222
|
+
* @param {number} cell
|
|
1223
|
+
* @returns {number}
|
|
1224
|
+
*/
|
|
1225
|
+
cell_entry(cell) {
|
|
1226
|
+
const slot = this.#cell_slot[cell];
|
|
1227
|
+
|
|
1228
|
+
if (slot === -1) {
|
|
1229
|
+
return VT_ENTRY_INVALID;
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
const per_axis = this.slots.slots_per_axis;
|
|
1233
|
+
|
|
1234
|
+
return vt_entry_pack(slot % per_axis, (slot / per_axis) | 0, this.#slot_level[slot]);
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
/**
|
|
1238
|
+
* @param {number} cell
|
|
1239
|
+
* @returns {number} the slot holding the cell's page, or -1
|
|
1240
|
+
*/
|
|
1241
|
+
cell_slot(cell) {
|
|
1242
|
+
return this.#cell_slot[cell];
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
/**
|
|
1246
|
+
* @returns {number} cells whose entry changed since {@link clear_dirty}
|
|
1247
|
+
*/
|
|
1248
|
+
get dirty_cell_count() {
|
|
1249
|
+
return this.#dirty_cell_count;
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
/**
|
|
1253
|
+
* @param {number} i
|
|
1254
|
+
* @returns {number}
|
|
1255
|
+
*/
|
|
1256
|
+
dirty_cell(i) {
|
|
1257
|
+
return this.#dirty_cells[i];
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
/**
|
|
1261
|
+
* @returns {number} slots whose page changed since {@link clear_dirty}
|
|
1262
|
+
*/
|
|
1263
|
+
get dirty_slot_count() {
|
|
1264
|
+
return this.#dirty_slot_count;
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
/**
|
|
1268
|
+
* @param {number} i
|
|
1269
|
+
* @returns {number}
|
|
1270
|
+
*/
|
|
1271
|
+
dirty_slot(i) {
|
|
1272
|
+
return this.#dirty_slots[i];
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
/**
|
|
1276
|
+
* @returns {boolean} whether a window moved since {@link clear_dirty}
|
|
1277
|
+
*/
|
|
1278
|
+
get levels_dirty() {
|
|
1279
|
+
return this.#levels_dirty;
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
/**
|
|
1283
|
+
* Forget what changed: the rows have been written.
|
|
1284
|
+
*/
|
|
1285
|
+
clear_dirty() {
|
|
1286
|
+
for (let i = 0; i < this.#dirty_cell_count; i++) {
|
|
1287
|
+
this.#dirty_cell_mark[this.#dirty_cells[i]] = 0;
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
for (let i = 0; i < this.#dirty_slot_count; i++) {
|
|
1291
|
+
this.#dirty_slot_mark[this.#dirty_slots[i]] = 0;
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
this.#dirty_cell_count = 0;
|
|
1295
|
+
this.#dirty_slot_count = 0;
|
|
1296
|
+
this.#levels_dirty = false;
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
/**
|
|
1300
|
+
* @param {number} slot
|
|
1301
|
+
* @returns {number} the level of the slot's page, or -1 when it is empty
|
|
1302
|
+
*/
|
|
1303
|
+
slot_level(slot) {
|
|
1304
|
+
return this.#slot_level[slot];
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
/**
|
|
1308
|
+
* @param {number} slot
|
|
1309
|
+
* @returns {number}
|
|
1310
|
+
*/
|
|
1311
|
+
slot_x(slot) {
|
|
1312
|
+
return this.#slot_x[slot];
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
/**
|
|
1316
|
+
* @param {number} slot
|
|
1317
|
+
* @returns {number}
|
|
1318
|
+
*/
|
|
1319
|
+
slot_y(slot) {
|
|
1320
|
+
return this.#slot_y[slot];
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
/**
|
|
1324
|
+
* @param {number} slot
|
|
1325
|
+
* @returns {boolean} whether a mover crossed the slot's page after it was last rendered
|
|
1326
|
+
*/
|
|
1327
|
+
slot_stale(slot) {
|
|
1328
|
+
return this.#slot_stale[slot] !== 0;
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
/**
|
|
1332
|
+
* @param {number} slot
|
|
1333
|
+
* @returns {number} the frame it was last rendered in, or -1
|
|
1334
|
+
*/
|
|
1335
|
+
slot_rendered_frame(slot) {
|
|
1336
|
+
return this.#slot_rendered[slot];
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
/**
|
|
1340
|
+
* @returns {number} wants in the want set
|
|
1341
|
+
*/
|
|
1342
|
+
get want_count() {
|
|
1343
|
+
return this.#want_count;
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
/**
|
|
1347
|
+
* @param {number} i
|
|
1348
|
+
* @returns {number}
|
|
1349
|
+
*/
|
|
1350
|
+
want_level(i) {
|
|
1351
|
+
return this.#want_level[i];
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
/**
|
|
1355
|
+
* @param {number} i
|
|
1356
|
+
* @returns {number}
|
|
1357
|
+
*/
|
|
1358
|
+
want_x(i) {
|
|
1359
|
+
return this.#want_x[i];
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
/**
|
|
1363
|
+
* @param {number} i
|
|
1364
|
+
* @returns {number}
|
|
1365
|
+
*/
|
|
1366
|
+
want_y(i) {
|
|
1367
|
+
return this.#want_y[i];
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
/**
|
|
1371
|
+
* @returns {number} pages {@link select} chose to render
|
|
1372
|
+
*/
|
|
1373
|
+
get job_count() {
|
|
1374
|
+
return this.#job_count;
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
/**
|
|
1378
|
+
* @param {number} i
|
|
1379
|
+
* @returns {number}
|
|
1380
|
+
*/
|
|
1381
|
+
job_slot(i) {
|
|
1382
|
+
return this.#job_slot[i];
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
/**
|
|
1386
|
+
* @param {number} i
|
|
1387
|
+
* @returns {number}
|
|
1388
|
+
*/
|
|
1389
|
+
job_level(i) {
|
|
1390
|
+
return this.#job_level[i];
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
/**
|
|
1394
|
+
* @param {number} i
|
|
1395
|
+
* @returns {number}
|
|
1396
|
+
*/
|
|
1397
|
+
job_x(i) {
|
|
1398
|
+
return this.#job_x[i];
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
/**
|
|
1402
|
+
* @param {number} i
|
|
1403
|
+
* @returns {number}
|
|
1404
|
+
*/
|
|
1405
|
+
job_y(i) {
|
|
1406
|
+
return this.#job_y[i];
|
|
1407
|
+
}
|
|
1408
|
+
}
|