@woosh/meep-engine 3.56.0 → 3.57.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.
Files changed (625) hide show
  1. package/build/bundle-worker-terrain.js +1 -1
  2. package/package.json +1 -1
  3. package/src/DUPLICATION_REVIEW_2026_10_24.md +1072 -0
  4. package/src/core/binary/BitSet.js +1 -1
  5. package/src/core/binary/FLOAT16_MAX.d.ts +2 -0
  6. package/src/core/binary/FLOAT16_MAX.d.ts.map +1 -0
  7. package/src/core/binary/FLOAT16_MAX.js +1 -0
  8. package/src/core/binary/base58/base58_encode.js +2 -2
  9. package/src/core/binary/type/TypeBuilder.js +1 -1
  10. package/src/core/bvh2/bvh3/BVH.js +1 -1
  11. package/src/core/bvh2/bvh3/ebvh_optimize_treelet.d.ts.map +1 -1
  12. package/src/core/bvh2/bvh3/ebvh_optimize_treelet.js +7 -3
  13. package/src/core/bvh2/bvh3/ebvh_update_hierarchy_bounds.d.ts.map +1 -1
  14. package/src/core/bvh2/bvh3/ebvh_update_hierarchy_bounds.js +5 -1
  15. package/src/core/bvh2/bvh3/query/compute_tight_near_far_clipping_planes.d.ts.map +1 -1
  16. package/src/core/bvh2/bvh3/query/compute_tight_near_far_clipping_planes.js +195 -246
  17. package/src/core/collection/CuckooFilter.js +1 -1
  18. package/src/core/collection/array/isArrayEqual.d.ts.map +1 -1
  19. package/src/core/collection/array/isArrayEqual.js +33 -58
  20. package/src/core/collection/array/typed/array_buffer_hash.d.ts.map +1 -1
  21. package/src/core/collection/array/typed/array_buffer_hash.js +41 -39
  22. package/src/core/collection/array/typed/float32_array_hash.js +38 -38
  23. package/src/core/collection/array/typed/uint16_array_hash.d.ts +2 -1
  24. package/src/core/collection/array/typed/uint16_array_hash.d.ts.map +1 -1
  25. package/src/core/collection/array/typed/uint16_array_hash.js +30 -29
  26. package/src/core/collection/array/typed/uint32_array_hash.d.ts +2 -1
  27. package/src/core/collection/array/typed/uint32_array_hash.d.ts.map +1 -1
  28. package/src/core/collection/array/typed/uint32_array_hash.js +21 -20
  29. package/src/core/collection/array/typed/uint8_array_hash.d.ts +2 -1
  30. package/src/core/collection/array/typed/uint8_array_hash.d.ts.map +1 -1
  31. package/src/core/collection/array/typed/uint8_array_hash.js +37 -36
  32. package/src/core/collection/array/typed/uint_array_for_count.js +2 -2
  33. package/src/core/collection/list/List.d.ts.map +1 -1
  34. package/src/core/collection/list/List.js +3 -19
  35. package/src/core/collection/table/RowFirstTable.d.ts.map +1 -1
  36. package/src/core/collection/table/RowFirstTable.js +4 -28
  37. package/src/core/debug/matchers/DescribeAs.d.ts.map +1 -1
  38. package/src/core/debug/matchers/DescribeAs.js +62 -64
  39. package/src/core/function/FunctionCompiler.js +4 -4
  40. package/src/core/function/objectsEqual.d.ts.map +1 -1
  41. package/src/core/function/objectsEqual.js +3 -2
  42. package/src/core/geom/2d/bvh/BVH2D.d.ts.map +1 -1
  43. package/src/core/geom/2d/bvh/BVH2D.js +4 -3
  44. package/src/core/geom/2d/convex-hull/convex_hull_fixed_count_2d_relaxation.d.ts +5 -2
  45. package/src/core/geom/2d/convex-hull/convex_hull_fixed_count_2d_relaxation.d.ts.map +1 -1
  46. package/src/core/geom/2d/convex-hull/convex_hull_fixed_count_2d_relaxation.js +49 -11
  47. package/src/core/geom/2d/hash-grid/shg_query_elements_circle.d.ts.map +1 -1
  48. package/src/core/geom/2d/hash-grid/shg_query_elements_circle.js +122 -159
  49. package/src/core/geom/2d/hash-grid/shg_query_elements_line.d.ts.map +1 -1
  50. package/src/core/geom/2d/hash-grid/shg_query_elements_line.js +8 -5
  51. package/src/core/geom/2d/polygon/polygon2_rasterize_coverage.d.ts +18 -0
  52. package/src/core/geom/2d/polygon/polygon2_rasterize_coverage.d.ts.map +1 -0
  53. package/src/core/geom/2d/polygon/polygon2_rasterize_coverage.js +97 -0
  54. package/src/core/geom/2d/r-tree/StaticR2Tree.js +2 -2
  55. package/src/core/geom/2d/triangle/tri2_rasterize_coverage.d.ts +21 -0
  56. package/src/core/geom/2d/triangle/tri2_rasterize_coverage.d.ts.map +1 -0
  57. package/src/core/geom/2d/triangle/tri2_rasterize_coverage.js +54 -0
  58. package/src/core/geom/3d/aabb/aabb3_build_frustum.d.ts.map +1 -1
  59. package/src/core/geom/3d/aabb/aabb3_build_frustum.js +20 -53
  60. package/src/core/geom/3d/aabb/aabb3_score_boxes_SAH.d.ts +1 -1
  61. package/src/core/geom/3d/aabb/aabb3_score_boxes_SAH.d.ts.map +1 -1
  62. package/src/core/geom/3d/aabb/aabb3_score_boxes_SAH.js +11 -42
  63. package/src/core/geom/3d/atlas/pack/atlas_pack_charts.d.ts.map +1 -1
  64. package/src/core/geom/3d/atlas/pack/atlas_pack_charts.js +30 -32
  65. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_bff.d.ts.map +1 -1
  66. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_bff.js +1 -5
  67. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_lscm.d.ts.map +1 -1
  68. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_lscm.js +1 -15
  69. package/src/core/geom/3d/atlas/segment/atlas_merge_charts.d.ts.map +1 -1
  70. package/src/core/geom/3d/atlas/segment/atlas_merge_charts.js +105 -116
  71. package/src/core/geom/3d/line/line3_compute_segment_point_distance_sqr.d.ts.map +1 -1
  72. package/src/core/geom/3d/line/line3_compute_segment_point_distance_sqr.js +36 -54
  73. package/src/core/geom/3d/plane/plane3_compute_intersection_objects.d.ts +5 -10
  74. package/src/core/geom/3d/plane/plane3_compute_intersection_objects.d.ts.map +1 -1
  75. package/src/core/geom/3d/plane/plane3_compute_intersection_objects.js +20 -82
  76. package/src/core/geom/3d/plane/plane3_slerp.d.ts.map +1 -1
  77. package/src/core/geom/3d/plane/plane3_slerp.js +87 -102
  78. package/src/core/geom/3d/polygon/polygon3_compute_normal.d.ts +12 -0
  79. package/src/core/geom/3d/polygon/polygon3_compute_normal.d.ts.map +1 -1
  80. package/src/core/geom/3d/polygon/polygon3_compute_normal.js +107 -60
  81. package/src/core/geom/3d/ray/ray3_compute_closest_point.d.ts.map +1 -1
  82. package/src/core/geom/3d/ray/ray3_compute_closest_point.js +37 -43
  83. package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts.map +1 -1
  84. package/src/core/geom/3d/shape/ConvexHullShape3D.js +5 -16
  85. package/src/core/geom/3d/shape/MeshShape3D.js +2 -56
  86. package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
  87. package/src/core/geom/3d/shape/TransformedShape3D.js +10 -7
  88. package/src/core/geom/3d/shape/UnionShape3D.d.ts.map +1 -1
  89. package/src/core/geom/3d/shape/UnionShape3D.js +9 -3
  90. package/src/core/geom/3d/shape/json/shape_to_type.js +2 -2
  91. package/src/core/geom/3d/sphere/harmonics/SH3_COEFFICIENTS.js +17 -17
  92. package/src/core/geom/3d/tetrahedra/TetrahedralMesh.d.ts.map +1 -1
  93. package/src/core/geom/3d/tetrahedra/TetrahedralMesh.js +6 -2
  94. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.d.ts.map +1 -1
  95. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.js +3 -2
  96. package/src/core/geom/3d/tetrahedra/tetrahedron_contains_point.d.ts +20 -2
  97. package/src/core/geom/3d/tetrahedra/tetrahedron_contains_point.d.ts.map +1 -1
  98. package/src/core/geom/3d/tetrahedra/tetrahedron_contains_point.js +52 -37
  99. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_face_normals.d.ts.map +1 -1
  100. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_face_normals.js +40 -56
  101. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_vertex_quadrics.d.ts.map +1 -1
  102. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_vertex_quadrics.js +251 -260
  103. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_wedge_attribute_quadrics.d.ts.map +1 -1
  104. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_wedge_attribute_quadrics.js +104 -113
  105. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_resolve_t_junctions.d.ts.map +1 -1
  106. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_resolve_t_junctions.js +227 -238
  107. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_simplify.d.ts.map +1 -1
  108. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_simplify.js +15 -24
  109. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_create.d.ts.map +1 -1
  110. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_create.js +31 -115
  111. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_fuse_duplicate_edges.d.ts.map +1 -1
  112. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_fuse_duplicate_edges.js +142 -150
  113. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_replace.d.ts.map +1 -1
  114. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_replace.js +151 -194
  115. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_incenter.d.ts.map +1 -1
  116. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_incenter.js +60 -85
  117. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_build_boundary_distance_field.d.ts.map +1 -1
  118. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_build_boundary_distance_field.js +156 -171
  119. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path.d.ts.map +1 -1
  120. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path.js +8 -44
  121. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path_polyanya.d.ts.map +1 -1
  122. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path_polyanya.js +2 -7
  123. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.d.ts.map +1 -1
  124. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.js +3 -2
  125. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_segment_penetrates_surface.d.ts.map +1 -1
  126. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_segment_penetrates_surface.js +128 -133
  127. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_surface_ray_parity.d.ts +8 -14
  128. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_surface_ray_parity.d.ts.map +1 -1
  129. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_surface_ray_parity.js +36 -82
  130. package/src/core/geom/3d/triangle/tri3_ray_intersection.d.ts.map +1 -1
  131. package/src/core/geom/3d/triangle/tri3_ray_intersection.js +7 -144
  132. package/src/core/geom/ConicRay.d.ts.map +1 -1
  133. package/src/core/geom/ConicRay.js +230 -237
  134. package/src/core/localization/LocaleDataset.d.ts +6 -0
  135. package/src/core/localization/LocaleDataset.d.ts.map +1 -1
  136. package/src/core/localization/LocaleDataset.js +48 -37
  137. package/src/core/localization/LocalizationEngine.d.ts.map +1 -1
  138. package/src/core/localization/LocalizationEngine.js +3 -2
  139. package/src/core/math/lookup/ParameterLookupTable.d.ts.map +1 -1
  140. package/src/core/math/lookup/ParameterLookupTable.js +3 -1
  141. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_nd.d.ts.map +1 -1
  142. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_nd.js +330 -400
  143. package/src/core/math/spline/spline3_hermite_nearest_point.d.ts +16 -0
  144. package/src/core/math/spline/spline3_hermite_nearest_point.d.ts.map +1 -1
  145. package/src/core/math/spline/spline3_hermite_nearest_point.js +134 -167
  146. package/src/core/model/DebouncedObservedBoolean.d.ts +1 -2
  147. package/src/core/model/DebouncedObservedBoolean.d.ts.map +1 -1
  148. package/src/core/model/DebouncedObservedBoolean.js +1 -1
  149. package/src/core/model/node-graph/node/NodeInstance.d.ts.map +1 -1
  150. package/src/core/model/node-graph/node/NodeInstance.js +2 -7
  151. package/src/core/model/node-graph/node/parameter/NodeParameterDescription.js +1 -1
  152. package/src/core/model/object/optional_equality.d.ts +3 -3
  153. package/src/core/model/object/optional_equality.d.ts.map +1 -1
  154. package/src/core/model/object/optional_equality.js +10 -27
  155. package/src/core/model/object/write_property.js +1 -1
  156. package/src/core/model/reactive/evaluation/MultiPredicateEvaluator.js +2 -2
  157. package/src/core/primitives/strings/string_compute_byte_size.d.ts +3 -3
  158. package/src/core/primitives/strings/string_compute_byte_size.d.ts.map +1 -1
  159. package/src/core/primitives/strings/string_compute_byte_size.js +8 -21
  160. package/src/core/process/executor/ConcurrentExecutor.d.ts.map +1 -1
  161. package/src/core/process/executor/ConcurrentExecutor.js +14 -2
  162. package/src/engine/achievements/gateway/StorageAchievementGateway.d.ts +6 -3
  163. package/src/engine/achievements/gateway/StorageAchievementGateway.d.ts.map +1 -1
  164. package/src/engine/achievements/gateway/StorageAchievementGateway.js +31 -75
  165. package/src/engine/asset/loaders/SVGAssetLoader.d.ts.map +1 -1
  166. package/src/engine/asset/loaders/SVGAssetLoader.js +33 -31
  167. package/src/engine/control/first-person/math/criticallyDampedSpring.d.ts.map +1 -1
  168. package/src/engine/control/first-person/math/criticallyDampedSpring.js +3 -14
  169. package/src/engine/ecs/EntityComponentDataset.d.ts.map +1 -1
  170. package/src/engine/ecs/EntityComponentDataset.js +4 -1
  171. package/src/engine/ecs/storage/binary/object/BinaryObjectSerializationAdapter.d.ts +0 -2
  172. package/src/engine/ecs/storage/binary/object/BinaryObjectSerializationAdapter.d.ts.map +1 -1
  173. package/src/engine/ecs/storage/binary/object/BinaryObjectSerializationAdapter.js +3 -3
  174. package/src/engine/ecs/terrain/ecs/layers/TerrainLayer.js +2 -2
  175. package/src/engine/graphics/sh3/path_tracer/geometry/sort_triangles_by_distance_to_point.js +1 -1
  176. package/src/engine/graphics/texture/sampler/sampler2d_channel_compute_min_indices.js +1 -1
  177. package/src/engine/graphics3/WaterSystem.d.ts.map +1 -1
  178. package/src/engine/graphics3/WaterSystem.js +2 -1
  179. package/src/engine/graphics3/prefab/prefab_skin_frame.d.ts.map +1 -1
  180. package/src/engine/graphics3/prefab/prefab_skin_frame.js +1 -12
  181. package/src/engine/grid/grid2transform/GridPosition2TransformSystem.d.ts +1 -1
  182. package/src/engine/grid/grid2transform/GridPosition2TransformSystem.d.ts.map +1 -1
  183. package/src/engine/grid/grid2transform/GridPosition2TransformSystem.js +141 -137
  184. package/src/engine/input/ecs/systems/InputControllerSystem.d.ts.map +1 -1
  185. package/src/engine/input/ecs/systems/InputControllerSystem.js +13 -3
  186. package/src/engine/input/ecs/systems/InputSystem.d.ts.map +1 -1
  187. package/src/engine/input/ecs/systems/InputSystem.js +2 -1
  188. package/src/engine/intelligence/behavior/composite/ParallelBehavior.d.ts +1 -1
  189. package/src/engine/intelligence/behavior/composite/ParallelBehavior.d.ts.map +1 -1
  190. package/src/engine/intelligence/behavior/composite/ParallelBehavior.js +4 -1
  191. package/src/engine/intelligence/behavior/decorator/InvertStatusBehavior.d.ts.map +1 -1
  192. package/src/engine/intelligence/behavior/decorator/InvertStatusBehavior.js +3 -1
  193. package/src/engine/intelligence/behavior/decorator/RepeatBehavior.d.ts.map +1 -1
  194. package/src/engine/intelligence/behavior/decorator/RepeatBehavior.js +3 -1
  195. package/src/engine/intelligence/behavior/decorator/RepeatBehaviorSerializationAdapter.d.ts.map +1 -1
  196. package/src/engine/intelligence/behavior/decorator/RepeatBehaviorSerializationAdapter.js +39 -33
  197. package/src/engine/intelligence/behavior/util/ConditionalBehavior.d.ts +5 -0
  198. package/src/engine/intelligence/behavior/util/ConditionalBehavior.d.ts.map +1 -1
  199. package/src/engine/intelligence/behavior/util/ConditionalBehavior.js +93 -75
  200. package/src/engine/intelligence/behavior/util/RotationBehavior.d.ts.map +1 -1
  201. package/src/engine/intelligence/behavior/util/RotationBehavior.js +79 -76
  202. package/src/engine/intelligence/blackboard/BlackboardStack.d.ts +1 -0
  203. package/src/engine/intelligence/blackboard/BlackboardStack.d.ts.map +1 -1
  204. package/src/engine/intelligence/blackboard/BlackboardStack.js +159 -123
  205. package/src/engine/intelligence/mcts/StateNode.d.ts.map +1 -1
  206. package/src/engine/intelligence/mcts/StateNode.js +366 -364
  207. package/src/engine/intelligence/resource/ResourceAllocationSolver.js +1 -1
  208. package/src/engine/navigation/ecs/components/Path.d.ts.map +1 -1
  209. package/src/engine/navigation/ecs/components/Path.js +2 -1
  210. package/src/engine/navigation/ecs/path_following/PathFollowingSystem.d.ts.map +1 -1
  211. package/src/engine/navigation/ecs/path_following/PathFollowingSystem.js +5 -2
  212. package/src/engine/physics/body/SolverBodyState.d.ts.map +1 -1
  213. package/src/engine/physics/body/SolverBodyState.js +2 -6
  214. package/src/engine/physics/ccd/linear_sweep.d.ts.map +1 -1
  215. package/src/engine/physics/ccd/linear_sweep.js +3 -16
  216. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts.map +1 -1
  217. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.js +2 -16
  218. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts +13 -1
  219. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -1
  220. package/src/engine/physics/cloth/ecs/cloth_build_rows.js +15 -4
  221. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  222. package/src/engine/physics/ecs/PhysicsSystem.js +2 -5
  223. package/src/engine/physics/inertia/locked_inverse_inertia.d.ts +12 -0
  224. package/src/engine/physics/inertia/locked_inverse_inertia.d.ts.map +1 -0
  225. package/src/engine/physics/inertia/locked_inverse_inertia.js +22 -0
  226. package/src/engine/physics/integration/integrate_velocity.d.ts.map +1 -1
  227. package/src/engine/physics/integration/integrate_velocity.js +3 -18
  228. package/src/engine/physics/mls-mpm/MLS_MPM.d.ts +1 -0
  229. package/src/engine/physics/mls-mpm/MLS_MPM.d.ts.map +1 -1
  230. package/src/engine/physics/mls-mpm/MLS_MPM.js +5 -4
  231. package/src/engine/physics/narrowphase/convex_decomposition.d.ts.map +1 -1
  232. package/src/engine/physics/narrowphase/convex_decomposition.js +7 -16
  233. package/src/engine/physics/vehicle/RaycastVehicle.d.ts.map +1 -1
  234. package/src/engine/physics/vehicle/RaycastVehicle.js +15 -5
  235. package/src/engine/save/StorageBackedList.d.ts +5 -0
  236. package/src/engine/save/StorageBackedList.d.ts.map +1 -1
  237. package/src/engine/save/StorageBackedList.js +161 -144
  238. package/src/engine/simulation/Ticker.d.ts.map +1 -1
  239. package/src/engine/simulation/Ticker.js +394 -391
  240. package/src/engine/sound/simulation/probe/AcousticProbeField.d.ts.map +1 -1
  241. package/src/engine/sound/simulation/probe/AcousticProbeField.js +6 -19
  242. package/src/engine/sound/simulation/probe/probe_edge_visible.d.ts +15 -0
  243. package/src/engine/sound/simulation/probe/probe_edge_visible.d.ts.map +1 -1
  244. package/src/engine/sound/simulation/probe/probe_edge_visible.js +59 -41
  245. package/src/engine/sound/simulation/probe/probe_refine_connectivity.d.ts.map +1 -1
  246. package/src/engine/sound/simulation/probe/probe_refine_connectivity.js +164 -181
  247. package/src/engine/sound/simulation/render/FoaProbeReverbRenderer.d.ts.map +1 -1
  248. package/src/engine/sound/simulation/render/FoaProbeReverbRenderer.js +20 -5
  249. package/src/format/image/avif/av1/decode/Av1FrameContext.d.ts.map +1 -1
  250. package/src/format/image/avif/av1/decode/Av1FrameContext.js +3 -10
  251. package/src/format/image/avif/av1/decode/reconstruct.d.ts +20 -0
  252. package/src/format/image/avif/av1/decode/reconstruct.d.ts.map +1 -1
  253. package/src/format/image/avif/av1/decode/reconstruct.js +22 -9
  254. package/src/format/image/avif/av1/encode/choose_restoration.js +2 -18
  255. package/src/format/image/avif/av1/encode/quantise.d.ts.map +1 -1
  256. package/src/format/image/avif/av1/encode/quantise.js +1 -55
  257. package/src/format/image/avif/av1/filter/loop_restoration.d.ts +9 -0
  258. package/src/format/image/avif/av1/filter/loop_restoration.d.ts.map +1 -1
  259. package/src/format/image/avif/av1/filter/loop_restoration.js +1 -1
  260. package/src/format/texture/basis/transcode/etc1s_to_bc7.js +2 -33
  261. package/src/format/texture/basis/transcode/fit_endpoints.d.ts +11 -0
  262. package/src/format/texture/basis/transcode/fit_endpoints.d.ts.map +1 -1
  263. package/src/format/texture/basis/transcode/fit_endpoints.js +1 -1
  264. package/src/format/texture/basis/uastc/uastc_decode_block.d.ts.map +1 -1
  265. package/src/format/texture/basis/uastc/uastc_decode_block.js +2 -19
  266. package/src/generation/foliage/ANNUAL_SHOOTS_BRIEF_2026_10_25.md +220 -0
  267. package/src/generation/foliage/CROWN_FILLING_BRIEF_2026_10_26.md +172 -0
  268. package/src/generation/foliage/FOLIAGE_DESIGN.md +165 -15
  269. package/src/generation/foliage/LEAF_ARCHITECTURE_BRIEF_2026_10_26.md +158 -0
  270. package/src/generation/foliage/SHOOT_SYSTEMS_ALL_SPECIES_BRIEF_2026_10_26.md +248 -0
  271. package/src/generation/foliage/SPEEDTREE_COMPARISON_2026_10_24.md +694 -0
  272. package/src/generation/foliage/analysis/CrownOpacity.d.ts +118 -0
  273. package/src/generation/foliage/analysis/CrownOpacity.d.ts.map +1 -0
  274. package/src/generation/foliage/analysis/CrownOpacity.js +182 -0
  275. package/src/generation/foliage/analysis/crown_opacity_frames.d.ts +10 -0
  276. package/src/generation/foliage/analysis/crown_opacity_frames.d.ts.map +1 -0
  277. package/src/generation/foliage/analysis/crown_opacity_frames.js +132 -0
  278. package/src/generation/foliage/analysis/crown_opacity_measure.d.ts +51 -0
  279. package/src/generation/foliage/analysis/crown_opacity_measure.d.ts.map +1 -0
  280. package/src/generation/foliage/analysis/crown_opacity_measure.js +649 -0
  281. package/src/generation/foliage/analysis/foliage_measure_leaf_area.d.ts +66 -0
  282. package/src/generation/foliage/analysis/foliage_measure_leaf_area.d.ts.map +1 -0
  283. package/src/generation/foliage/analysis/foliage_measure_leaf_area.js +192 -0
  284. package/src/generation/foliage/analysis/tree_crown_opacity.d.ts +27 -0
  285. package/src/generation/foliage/analysis/tree_crown_opacity.d.ts.map +1 -0
  286. package/src/generation/foliage/analysis/tree_crown_opacity.js +58 -0
  287. package/src/generation/foliage/animation/build_tree_wind_rig.d.ts +3 -2
  288. package/src/generation/foliage/animation/build_tree_wind_rig.d.ts.map +1 -1
  289. package/src/generation/foliage/animation/build_tree_wind_rig.js +12 -30
  290. package/src/generation/foliage/animation/tree_wind_bend_limit.d.ts +12 -0
  291. package/src/generation/foliage/animation/tree_wind_bend_limit.d.ts.map +1 -0
  292. package/src/generation/foliage/animation/tree_wind_bend_limit.js +13 -0
  293. package/src/generation/foliage/asset/TreeAsset.d.ts +5 -0
  294. package/src/generation/foliage/asset/TreeAsset.d.ts.map +1 -1
  295. package/src/generation/foliage/asset/TreeAsset.js +6 -0
  296. package/src/generation/foliage/asset/generate_tree.d.ts.map +1 -1
  297. package/src/generation/foliage/asset/generate_tree.js +23 -6
  298. package/src/generation/foliage/config/{BranchLevelConfig.d.ts → BranchGeneratorConfig.d.ts} +61 -75
  299. package/src/generation/foliage/config/BranchGeneratorConfig.d.ts.map +1 -0
  300. package/src/generation/foliage/config/{BranchLevelConfig.js → BranchGeneratorConfig.js} +83 -126
  301. package/src/generation/foliage/config/BranchSpawnRule.d.ts +118 -0
  302. package/src/generation/foliage/config/BranchSpawnRule.d.ts.map +1 -0
  303. package/src/generation/foliage/config/BranchSpawnRule.js +217 -0
  304. package/src/generation/foliage/config/FoliageCardType.d.ts +1 -1
  305. package/src/generation/foliage/config/FoliageCardType.js +2 -2
  306. package/src/generation/foliage/config/FoliageConfig.d.ts +23 -45
  307. package/src/generation/foliage/config/FoliageConfig.d.ts.map +1 -1
  308. package/src/generation/foliage/config/FoliageConfig.js +47 -93
  309. package/src/generation/foliage/config/FoliageMaterialConfig.d.ts +12 -20
  310. package/src/generation/foliage/config/FoliageMaterialConfig.d.ts.map +1 -1
  311. package/src/generation/foliage/config/FoliageMaterialConfig.js +261 -279
  312. package/src/generation/foliage/config/FoliageSpawnRule.d.ts +77 -0
  313. package/src/generation/foliage/config/FoliageSpawnRule.d.ts.map +1 -0
  314. package/src/generation/foliage/config/FoliageSpawnRule.js +135 -0
  315. package/src/generation/foliage/config/FoliageTileContent.d.ts +9 -0
  316. package/src/generation/foliage/config/FoliageTileContent.d.ts.map +1 -0
  317. package/src/generation/foliage/config/FoliageTileContent.js +12 -0
  318. package/src/generation/foliage/config/LeafApexShape.d.ts +12 -0
  319. package/src/generation/foliage/config/LeafApexShape.d.ts.map +1 -0
  320. package/src/generation/foliage/config/LeafApexShape.js +17 -0
  321. package/src/generation/foliage/config/LeafArchitecture.d.ts +155 -0
  322. package/src/generation/foliage/config/LeafArchitecture.d.ts.map +1 -0
  323. package/src/generation/foliage/config/LeafArchitecture.js +288 -0
  324. package/src/generation/foliage/config/LeafBaseShape.d.ts +14 -0
  325. package/src/generation/foliage/config/LeafBaseShape.d.ts.map +1 -0
  326. package/src/generation/foliage/config/LeafBaseShape.js +21 -0
  327. package/src/generation/foliage/config/LeafLobation.d.ts +10 -0
  328. package/src/generation/foliage/config/LeafLobation.d.ts.map +1 -0
  329. package/src/generation/foliage/config/LeafLobation.js +14 -0
  330. package/src/generation/foliage/config/PhyllotaxisMode.d.ts +11 -0
  331. package/src/generation/foliage/config/PhyllotaxisMode.d.ts.map +1 -1
  332. package/src/generation/foliage/config/PhyllotaxisMode.js +36 -0
  333. package/src/generation/foliage/config/ShootBudZone.d.ts +105 -0
  334. package/src/generation/foliage/config/ShootBudZone.d.ts.map +1 -0
  335. package/src/generation/foliage/config/ShootBudZone.js +219 -0
  336. package/src/generation/foliage/config/ShootGrowthConfig.d.ts +84 -0
  337. package/src/generation/foliage/config/ShootGrowthConfig.d.ts.map +1 -0
  338. package/src/generation/foliage/config/ShootGrowthConfig.js +146 -0
  339. package/src/generation/foliage/config/ShootSystemRule.d.ts +144 -0
  340. package/src/generation/foliage/config/ShootSystemRule.d.ts.map +1 -0
  341. package/src/generation/foliage/config/ShootSystemRule.js +316 -0
  342. package/src/generation/foliage/config/TreeLODConfig.d.ts +1 -1
  343. package/src/generation/foliage/config/TreeLODConfig.js +1 -1
  344. package/src/generation/foliage/config/TreeSpeciesConfig.d.ts +40 -8
  345. package/src/generation/foliage/config/TreeSpeciesConfig.d.ts.map +1 -1
  346. package/src/generation/foliage/config/TreeSpeciesConfig.js +124 -68
  347. package/src/generation/foliage/config/TreeWindConfig.d.ts +23 -10
  348. package/src/generation/foliage/config/TreeWindConfig.d.ts.map +1 -1
  349. package/src/generation/foliage/config/TreeWindConfig.js +34 -25
  350. package/src/generation/foliage/index.d.ts +19 -2
  351. package/src/generation/foliage/index.js +63 -44
  352. package/src/generation/foliage/material/FoliageAtlasCutout.d.ts +59 -0
  353. package/src/generation/foliage/material/FoliageAtlasCutout.d.ts.map +1 -0
  354. package/src/generation/foliage/material/FoliageAtlasCutout.js +93 -0
  355. package/src/generation/foliage/material/compute_foliage_variant_atlas_layout.d.ts +26 -0
  356. package/src/generation/foliage/material/compute_foliage_variant_atlas_layout.d.ts.map +1 -0
  357. package/src/generation/foliage/material/compute_foliage_variant_atlas_layout.js +63 -0
  358. package/src/generation/foliage/material/foliage_atlas_cutout.d.ts +34 -0
  359. package/src/generation/foliage/material/foliage_atlas_cutout.d.ts.map +1 -0
  360. package/src/generation/foliage/material/foliage_atlas_cutout.js +174 -0
  361. package/src/generation/foliage/material/foliage_tile.d.ts +110 -0
  362. package/src/generation/foliage/material/foliage_tile.d.ts.map +1 -0
  363. package/src/generation/foliage/material/foliage_tile.js +286 -0
  364. package/src/generation/foliage/material/leaf_geometry.d.ts +103 -0
  365. package/src/generation/foliage/material/leaf_geometry.d.ts.map +1 -0
  366. package/src/generation/foliage/material/leaf_geometry.js +528 -0
  367. package/src/generation/foliage/material/make_foliage_material.d.ts +13 -33
  368. package/src/generation/foliage/material/make_foliage_material.d.ts.map +1 -1
  369. package/src/generation/foliage/material/make_foliage_material.js +356 -605
  370. package/src/generation/foliage/mesh/foliage_collect_attachments.d.ts +39 -4
  371. package/src/generation/foliage/mesh/foliage_collect_attachments.d.ts.map +1 -1
  372. package/src/generation/foliage/mesh/foliage_collect_attachments.js +637 -569
  373. package/src/generation/foliage/mesh/interpolate_ring_skin_weights4.d.ts +48 -0
  374. package/src/generation/foliage/mesh/interpolate_ring_skin_weights4.d.ts.map +1 -0
  375. package/src/generation/foliage/mesh/interpolate_ring_skin_weights4.js +232 -0
  376. package/src/generation/foliage/mesh/tree_mesh_build_bark.d.ts.map +1 -1
  377. package/src/generation/foliage/mesh/tree_mesh_build_bark.js +1023 -1049
  378. package/src/generation/foliage/mesh/tree_mesh_build_foliage.d.ts +9 -2
  379. package/src/generation/foliage/mesh/tree_mesh_build_foliage.d.ts.map +1 -1
  380. package/src/generation/foliage/mesh/tree_mesh_build_foliage.js +467 -454
  381. package/src/generation/foliage/presets/make_tree_species_preset.d.ts.map +1 -1
  382. package/src/generation/foliage/presets/make_tree_species_preset.js +1648 -870
  383. package/src/generation/foliage/skeleton/ShootFrameworkHash.d.ts +35 -0
  384. package/src/generation/foliage/skeleton/ShootFrameworkHash.d.ts.map +1 -0
  385. package/src/generation/foliage/skeleton/ShootFrameworkHash.js +129 -0
  386. package/src/generation/foliage/skeleton/ShootGirth.d.ts +51 -0
  387. package/src/generation/foliage/skeleton/ShootGirth.d.ts.map +1 -0
  388. package/src/generation/foliage/skeleton/ShootGirth.js +212 -0
  389. package/src/generation/foliage/skeleton/ShootLightField.d.ts +73 -0
  390. package/src/generation/foliage/skeleton/ShootLightField.d.ts.map +1 -0
  391. package/src/generation/foliage/skeleton/ShootLightField.js +197 -0
  392. package/src/generation/foliage/skeleton/TreeSkeleton.d.ts +106 -3
  393. package/src/generation/foliage/skeleton/TreeSkeleton.d.ts.map +1 -1
  394. package/src/generation/foliage/skeleton/TreeSkeleton.js +217 -39
  395. package/src/generation/foliage/skeleton/flare_lobe_phase_offset.d.ts +13 -0
  396. package/src/generation/foliage/skeleton/flare_lobe_phase_offset.d.ts.map +1 -0
  397. package/src/generation/foliage/skeleton/flare_lobe_phase_offset.js +16 -0
  398. package/src/generation/foliage/skeleton/foliage_card_density.d.ts +71 -0
  399. package/src/generation/foliage/skeleton/foliage_card_density.d.ts.map +1 -0
  400. package/src/generation/foliage/skeleton/foliage_card_density.js +101 -0
  401. package/src/generation/foliage/skeleton/foliage_senescence.d.ts +101 -0
  402. package/src/generation/foliage/skeleton/foliage_senescence.d.ts.map +1 -0
  403. package/src/generation/foliage/skeleton/foliage_senescence.js +149 -0
  404. package/src/generation/foliage/skeleton/foliage_unit_cards.d.ts +76 -0
  405. package/src/generation/foliage/skeleton/foliage_unit_cards.d.ts.map +1 -0
  406. package/src/generation/foliage/skeleton/foliage_unit_cards.js +95 -0
  407. package/src/generation/foliage/skeleton/shoot_demography.d.ts +22 -0
  408. package/src/generation/foliage/skeleton/shoot_demography.d.ts.map +1 -0
  409. package/src/generation/foliage/skeleton/shoot_demography.js +96 -0
  410. package/src/generation/foliage/skeleton/shoot_geometry.d.ts +66 -0
  411. package/src/generation/foliage/skeleton/shoot_geometry.d.ts.map +1 -0
  412. package/src/generation/foliage/skeleton/shoot_geometry.js +109 -0
  413. package/src/generation/foliage/skeleton/shoot_systems_simulate.d.ts +166 -0
  414. package/src/generation/foliage/skeleton/shoot_systems_simulate.d.ts.map +1 -0
  415. package/src/generation/foliage/skeleton/shoot_systems_simulate.js +588 -0
  416. package/src/generation/foliage/skeleton/tree_skeleton_assign_skin_joints.d.ts +28 -12
  417. package/src/generation/foliage/skeleton/tree_skeleton_assign_skin_joints.d.ts.map +1 -1
  418. package/src/generation/foliage/skeleton/tree_skeleton_assign_skin_joints.js +137 -102
  419. package/src/generation/foliage/skeleton/tree_skeleton_compute_joint_mechanics.d.ts +112 -0
  420. package/src/generation/foliage/skeleton/tree_skeleton_compute_joint_mechanics.d.ts.map +1 -0
  421. package/src/generation/foliage/skeleton/tree_skeleton_compute_joint_mechanics.js +408 -0
  422. package/src/generation/foliage/skeleton/tree_skeleton_compute_pipe_radii.d.ts.map +1 -1
  423. package/src/generation/foliage/skeleton/tree_skeleton_compute_pipe_radii.js +208 -206
  424. package/src/generation/foliage/skeleton/tree_skeleton_grow.d.ts +5 -2
  425. package/src/generation/foliage/skeleton/tree_skeleton_grow.d.ts.map +1 -1
  426. package/src/generation/foliage/skeleton/tree_skeleton_grow.js +2048 -1871
  427. package/src/generation/foliage/skeleton/tree_skeleton_grow_shoots.d.ts +17 -0
  428. package/src/generation/foliage/skeleton/tree_skeleton_grow_shoots.d.ts.map +1 -0
  429. package/src/generation/foliage/skeleton/tree_skeleton_grow_shoots.js +231 -0
  430. package/src/generation/foliage/skeleton/tree_skeleton_read_joint_motion.d.ts +14 -0
  431. package/src/generation/foliage/skeleton/tree_skeleton_read_joint_motion.d.ts.map +1 -0
  432. package/src/generation/foliage/skeleton/tree_skeleton_read_joint_motion.js +26 -0
  433. package/src/generation/foliage/skeleton/tree_skeleton_read_joint_parents.d.ts +10 -0
  434. package/src/generation/foliage/skeleton/tree_skeleton_read_joint_parents.d.ts.map +1 -0
  435. package/src/generation/foliage/skeleton/tree_skeleton_read_joint_parents.js +20 -0
  436. package/src/generation/grid/generation/road/GridTaskGenerateRoads.d.ts.map +1 -1
  437. package/src/generation/grid/generation/road/GridTaskGenerateRoads.js +4 -1
  438. package/src/generation/markers/GridCellActionPlaceMarkerGroup.d.ts +1 -0
  439. package/src/generation/markers/GridCellActionPlaceMarkerGroup.d.ts.map +1 -1
  440. package/src/generation/markers/GridCellActionPlaceMarkerGroup.js +98 -86
  441. package/src/shade/SHADER_F16_PROPOSAL_2026_10_24.md +263 -0
  442. package/src/shade/descriptor/WebGPUExtensionType.d.ts +17 -0
  443. package/src/shade/descriptor/WebGPUExtensionType.d.ts.map +1 -1
  444. package/src/shade/descriptor/WebGPUExtensionType.js +31 -1
  445. package/src/shade/playground/foliage_wind/FoliageRigOverlay.d.ts +37 -0
  446. package/src/shade/playground/foliage_wind/FoliageRigOverlay.d.ts.map +1 -0
  447. package/src/shade/playground/foliage_wind/FoliageRigOverlay.js +491 -0
  448. package/src/shade/playground/foliage_wind/foliage_world.d.ts.map +1 -1
  449. package/src/shade/playground/foliage_wind/foliage_world.js +600 -602
  450. package/src/shade/playground/foliage_wind/index.html +6 -0
  451. package/src/shade/playground/foliage_wind/main.js +14 -0
  452. package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
  453. package/src/shade/renderer/animation/GPUAnimationManager.js +2 -1
  454. package/src/shade/renderer/animation/foliage/FoliageWindJoint.d.ts +2 -1
  455. package/src/shade/renderer/animation/foliage/FoliageWindJoint.d.ts.map +1 -1
  456. package/src/shade/renderer/animation/foliage/FoliageWindJoint.js +2 -1
  457. package/src/shade/renderer/animation/foliage/chunk_foliage_wind_step.d.ts.map +1 -1
  458. package/src/shade/renderer/animation/foliage/chunk_foliage_wind_step.js +4 -2
  459. package/src/shade/renderer/buffer/table/GPUTypedTable.js +1 -1
  460. package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.d.ts.map +1 -1
  461. package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.js +403 -401
  462. package/src/shade/renderer/camera/OrbitalCameraController.d.ts +1 -62
  463. package/src/shade/renderer/camera/OrbitalCameraController.d.ts.map +1 -1
  464. package/src/shade/renderer/camera/OrbitalCameraController.js +1 -374
  465. package/src/shade/renderer/deferred/indirect/chunk_lpv_2d_cache_sample_irradiance.d.ts.map +1 -1
  466. package/src/shade/renderer/deferred/indirect/chunk_lpv_2d_cache_sample_irradiance.js +3 -0
  467. package/src/shade/renderer/deferred/indirect/chunk_lpv_sample_light.d.ts.map +1 -1
  468. package/src/shade/renderer/deferred/indirect/chunk_lpv_sample_light.js +6 -1
  469. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_splat.js +1 -1
  470. package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +2 -2
  471. package/src/shade/renderer/fluid/GPUFluidCascade.d.ts.map +1 -1
  472. package/src/shade/renderer/fluid/GPUFluidCascade.js +6 -3
  473. package/src/shade/renderer/fluid/GPU_FLUID_OCCUPANCY_AND_SOTA_REVIEW_2026_10_26.md +361 -0
  474. package/src/shade/renderer/fluid/coupling/chunk_fluid_cascade_parent.d.ts.map +1 -1
  475. package/src/shade/renderer/fluid/coupling/chunk_fluid_cascade_parent.js +335 -241
  476. package/src/shade/renderer/fluid/coupling/shader_fluid_cascade_ghosts.d.ts.map +1 -1
  477. package/src/shade/renderer/fluid/coupling/shader_fluid_cascade_ghosts.js +108 -101
  478. package/src/shade/renderer/fluid/forcing/chunk_fluid_forcing_query_select.d.ts.map +1 -1
  479. package/src/shade/renderer/fluid/forcing/chunk_fluid_forcing_query_select.js +69 -67
  480. package/src/shade/renderer/fluid/forcing/shader_fluid_forcing_apply.d.ts +7 -6
  481. package/src/shade/renderer/fluid/forcing/shader_fluid_forcing_apply.d.ts.map +1 -1
  482. package/src/shade/renderer/fluid/forcing/shader_fluid_forcing_apply.js +341 -287
  483. package/src/shade/renderer/fluid/mac/FluidMacPasses.d.ts +6 -4
  484. package/src/shade/renderer/fluid/mac/FluidMacPasses.d.ts.map +1 -1
  485. package/src/shade/renderer/fluid/mac/FluidMacPasses.js +427 -400
  486. package/src/shade/renderer/fluid/mac/chunk_fluid_mac_seams.d.ts +10 -5
  487. package/src/shade/renderer/fluid/mac/chunk_fluid_mac_seams.d.ts.map +1 -1
  488. package/src/shade/renderer/fluid/mac/chunk_fluid_mac_seams.js +532 -190
  489. package/src/shade/renderer/fluid/mac/chunk_v3_mac_lattice_corners.d.ts.map +1 -1
  490. package/src/shade/renderer/fluid/mac/chunk_v3_mac_lattice_corners.js +231 -237
  491. package/src/shade/renderer/fluid/mac/shader_fluid_mac_advect_correct.d.ts +2 -2
  492. package/src/shade/renderer/fluid/mac/shader_fluid_mac_advect_correct.d.ts.map +1 -1
  493. package/src/shade/renderer/fluid/mac/shader_fluid_mac_advect_correct.js +282 -245
  494. package/src/shade/renderer/fluid/mac/shader_fluid_mac_advect_predict.d.ts +1 -3
  495. package/src/shade/renderer/fluid/mac/shader_fluid_mac_advect_predict.d.ts.map +1 -1
  496. package/src/shade/renderer/fluid/mac/shader_fluid_mac_advect_predict.js +139 -109
  497. package/src/shade/renderer/fluid/mac/shader_fluid_mac_curl.d.ts +6 -6
  498. package/src/shade/renderer/fluid/mac/shader_fluid_mac_curl.d.ts.map +1 -1
  499. package/src/shade/renderer/fluid/mac/shader_fluid_mac_curl.js +257 -222
  500. package/src/shade/renderer/fluid/mac/shader_fluid_mac_divergence.d.ts +8 -7
  501. package/src/shade/renderer/fluid/mac/shader_fluid_mac_divergence.d.ts.map +1 -1
  502. package/src/shade/renderer/fluid/mac/shader_fluid_mac_divergence.js +119 -92
  503. package/src/shade/renderer/fluid/mac/shader_fluid_mac_gradient.d.ts +6 -9
  504. package/src/shade/renderer/fluid/mac/shader_fluid_mac_gradient.d.ts.map +1 -1
  505. package/src/shade/renderer/fluid/mac/shader_fluid_mac_gradient.js +229 -181
  506. package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +17 -7
  507. package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts.map +1 -1
  508. package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.js +634 -621
  509. package/src/shade/renderer/fluid/pressure/shader_fluid_mg_residual_restrict.d.ts +8 -6
  510. package/src/shade/renderer/fluid/pressure/shader_fluid_mg_residual_restrict.d.ts.map +1 -1
  511. package/src/shade/renderer/fluid/pressure/shader_fluid_mg_residual_restrict.js +166 -149
  512. package/src/shade/renderer/fluid/pressure/shader_fluid_mg_smooth.d.ts +8 -6
  513. package/src/shade/renderer/fluid/pressure/shader_fluid_mg_smooth.d.ts.map +1 -1
  514. package/src/shade/renderer/fluid/pressure/shader_fluid_mg_smooth.js +219 -183
  515. package/src/shade/renderer/fluid/publish/shader_fluid_wind_publish.d.ts.map +1 -1
  516. package/src/shade/renderer/fluid/publish/shader_fluid_wind_publish.js +142 -122
  517. package/src/shade/renderer/geometry/meshlet/COMPACTION_PLAN_2026_09_16.md +674 -663
  518. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts +1 -1
  519. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts.map +1 -1
  520. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.js +63 -29
  521. package/src/shade/renderer/geometry/meshlet/build/meshoptimizer/geometry_to_meshlets_meshoptimizer.d.ts.map +1 -1
  522. package/src/shade/renderer/geometry/meshlet/build/meshoptimizer/geometry_to_meshlets_meshoptimizer.js +77 -87
  523. package/src/shade/renderer/geometry/meshlet/build/meshoptimizer/meshopt_clusterizer.d.ts.map +1 -1
  524. package/src/shade/renderer/geometry/meshlet/build/meshoptimizer/meshopt_clusterizer.js +4 -3
  525. package/src/shade/renderer/geometry/meshlet/shader_meshlet_metadata_address_patch.d.ts +11 -11
  526. package/src/shade/renderer/geometry/meshlet/shader_meshlet_metadata_address_patch.d.ts.map +1 -1
  527. package/src/shade/renderer/geometry/meshlet/shader_meshlet_metadata_address_patch.js +17 -19
  528. package/src/shade/renderer/global_illumination/lpv/graph_bake_irradiance_lookup_2d.js +4 -4
  529. package/src/shade/renderer/global_illumination/probe/octahedral/sample/chunk_lpv_mesh_interpolate_radiance_via_atlas.d.ts.map +1 -1
  530. package/src/shade/renderer/global_illumination/probe/octahedral/sample/chunk_lpv_mesh_interpolate_radiance_via_atlas.js +5 -1
  531. package/src/shade/renderer/loader/gltf/load_gltf.d.ts.map +1 -1
  532. package/src/shade/renderer/loader/gltf/load_gltf.js +11 -35
  533. package/src/shade/renderer/loader/usd/load_usd.d.ts.map +1 -1
  534. package/src/shade/renderer/loader/usd/load_usd.js +6 -19
  535. package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.d.ts.map +1 -1
  536. package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.js +199 -193
  537. package/src/shade/renderer/particles/shaders/shader_particle_avboit_splat.d.ts.map +1 -1
  538. package/src/shade/renderer/particles/shaders/shader_particle_avboit_splat.js +151 -143
  539. package/src/shade/renderer/postprocess/bloom/chunk_karis_blur4x4_sample.d.ts.map +1 -1
  540. package/src/shade/renderer/postprocess/bloom/chunk_karis_blur4x4_sample.js +11 -5
  541. package/src/shade/renderer/postprocess/denoise/graph_atorus_denoise_luma.d.ts.map +1 -1
  542. package/src/shade/renderer/postprocess/denoise/graph_atorus_denoise_luma.js +6 -18
  543. package/src/shade/renderer/postprocess/gtao/GTAO.js +1 -1
  544. package/src/shade/renderer/postprocess/gtao/ao_reproject_shader.d.ts.map +1 -1
  545. package/src/shade/renderer/postprocess/gtao/ao_reproject_shader.js +3 -5
  546. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.js +1 -1
  547. package/src/shade/renderer/postprocess/nss/chunk_nss_luma_derivative.d.ts.map +1 -1
  548. package/src/shade/renderer/postprocess/nss/chunk_nss_luma_derivative.js +7 -3
  549. package/src/shade/renderer/postprocess/nss/shader_nss_postprocess.d.ts.map +1 -1
  550. package/src/shade/renderer/postprocess/nss/shader_nss_postprocess.js +4 -2
  551. package/src/shade/renderer/postprocess/nss/shader_nss_preprocess.d.ts.map +1 -1
  552. package/src/shade/renderer/postprocess/nss/shader_nss_preprocess.js +4 -1
  553. package/src/shade/renderer/postprocess/ssr/downsample_karis.d.ts.map +1 -1
  554. package/src/shade/renderer/postprocess/ssr/downsample_karis.js +6 -3
  555. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.d.ts.map +1 -1
  556. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.js +4 -3
  557. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader.d.ts.map +1 -1
  558. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader.js +4 -1
  559. package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.d.ts.map +1 -1
  560. package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.js +4 -2
  561. package/src/shade/renderer/postprocess/taa/chunk_taa_tonemap.d.ts.map +1 -1
  562. package/src/shade/renderer/postprocess/taa/chunk_taa_tonemap.js +35 -39
  563. package/src/shade/renderer/postprocess/taa/chunk_taa_tonemap_inv.d.ts.map +1 -1
  564. package/src/shade/renderer/postprocess/taa/chunk_taa_tonemap_inv.js +20 -17
  565. package/src/shade/renderer/postprocess/taa/shader_taa.d.ts.map +1 -1
  566. package/src/shade/renderer/postprocess/taa/shader_taa.js +6 -3
  567. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.d.ts.map +1 -1
  568. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.js +3 -1
  569. package/src/shade/renderer/rasterize/native/avboit/avboit_draw_fragment_body.js +1 -1
  570. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_splat_slice.js +2 -2
  571. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +1 -1
  572. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_integrate.d.ts.map +1 -1
  573. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_integrate.js +92 -83
  574. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_splat.js +1 -1
  575. package/src/shade/renderer/shader/ShaderDescriptor.d.ts.map +1 -1
  576. package/src/shade/renderer/shader/ShaderDescriptor.js +12 -4
  577. package/src/shade/renderer/shader/chunk/bvh/chunk_bvh_query_aabb_cooperative.d.ts.map +1 -1
  578. package/src/shade/renderer/shader/chunk/bvh/chunk_bvh_query_aabb_cooperative.js +294 -286
  579. package/src/shade/renderer/shader/chunk/light/lpv/chunk_lpv_interpolate_probe_irradiance8.js +5 -5
  580. package/src/shade/renderer/shader/chunk/light/lpv/chunk_lpv_mesh_interpolate_probe.d.ts.map +1 -1
  581. package/src/shade/renderer/shader/chunk/light/lpv/chunk_lpv_mesh_interpolate_probe.js +5 -3
  582. package/src/shade/renderer/shader/chunk/light/lpv/chunk_lpv_mesh_interpolate_probe_irradiance.d.ts.map +1 -1
  583. package/src/shade/renderer/shader/chunk/light/lpv/chunk_lpv_mesh_interpolate_probe_irradiance.js +9 -6
  584. package/src/shade/renderer/shader/chunk/light/lpv/chunk_lpv_sample_sh3_at.d.ts.map +1 -1
  585. package/src/shade/renderer/shader/chunk/light/lpv/chunk_lpv_sample_sh3_at.js +33 -38
  586. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts.map +1 -1
  587. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.js +690 -675
  588. package/src/shade/renderer/shader/type/WebGPUArray.d.ts +3 -0
  589. package/src/shade/renderer/shader/type/WebGPUArray.d.ts.map +1 -1
  590. package/src/shade/renderer/shader/type/WebGPUArray.js +185 -167
  591. package/src/shade/renderer/shader/type/WebGPUStruct.d.ts.map +1 -1
  592. package/src/shade/renderer/shader/type/WebGPUStruct.js +461 -455
  593. package/src/shade/renderer/shader/type/serde/read_gpu_typed_buffer.d.ts.map +1 -1
  594. package/src/shade/renderer/shader/type/serde/read_gpu_typed_buffer.js +335 -211
  595. package/src/shade/renderer/shader/type/serde/write_gpu_typed_buffer.d.ts.map +1 -1
  596. package/src/shade/renderer/shader/type/serde/write_gpu_typed_buffer.js +329 -221
  597. package/src/shade/renderer/shader/type/type_has_f16.d.ts +12 -0
  598. package/src/shade/renderer/shader/type/type_has_f16.d.ts.map +1 -0
  599. package/src/shade/renderer/shader/type/type_has_f16.js +66 -0
  600. package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.d.ts.map +1 -1
  601. package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.js +16 -2
  602. package/src/shade/renderer/volumetrics/taa/shader_volumetrics_taa.d.ts.map +1 -1
  603. package/src/shade/renderer/volumetrics/taa/shader_volumetrics_taa.js +5 -2
  604. package/src/shade/renderer/water/shader_water_avboit.js +1 -1
  605. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts.map +1 -1
  606. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +260 -23
  607. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts +6 -7
  608. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  609. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +269 -69
  610. package/src/shade/wgsl/validate_wgsl_source.d.ts.map +1 -1
  611. package/src/shade/wgsl/validate_wgsl_source.js +27 -1
  612. package/src/view/controller/controls/ListController.d.ts.map +1 -1
  613. package/src/view/controller/controls/ListController.js +118 -113
  614. package/src/view/controller/controls/Vector1Control.js +97 -97
  615. package/src/view/elements/image/SvgImageView.d.ts +1 -0
  616. package/src/view/elements/image/SvgImageView.d.ts.map +1 -1
  617. package/src/view/elements/image/SvgImageView.js +92 -90
  618. package/src/view/minimap/dom/MinimapTerrainView.d.ts +1 -0
  619. package/src/view/minimap/dom/MinimapTerrainView.d.ts.map +1 -1
  620. package/src/view/minimap/dom/MinimapTerrainView.js +151 -147
  621. package/src/view/tooltip/gml/TooltipParser.js +2 -2
  622. package/src/engine/network/PriorityFetch.d.ts +0 -59
  623. package/src/engine/network/PriorityFetch.d.ts.map +0 -1
  624. package/src/engine/network/PriorityFetch.js +0 -193
  625. package/src/generation/foliage/config/BranchLevelConfig.d.ts.map +0 -1
@@ -1,675 +1,690 @@
1
- import { assert } from "../../../../core/assert.js";
2
- import { round_up } from "../../../../core/math/round_up.js";
3
- import LineBuilder from "../../../../core/codegen/LineBuilder.js";
4
- import { array_push_if_unique } from "../../../../core/collection/array/array_push_if_unique.js";
5
- import { objectKeyByValue } from "../../../../core/model/object/objectKeyByValue.js";
6
- import { PipelineLayoutDescriptor } from "../../../descriptor/pipeline/PipelineLayoutDescriptor.js";
7
- import {
8
- wgsl_texture_declaration_by_sample_type
9
- } from "../../texture/format/wgsl_texture_declaration_by_sample_type.js";
10
- import { CodeChunk } from "../compiler/CodeChunk.js";
11
- import { parse_wgsl_type } from "../type/parse_wgsl_type.js";
12
- import { type_has_arrays } from "../type/type_has_arrays.js";
13
- import { type_has_atomics } from "../type/type_has_atomics.js";
14
- import { WebGPUStruct } from "../type/WebGPUStruct.js";
15
- import { write_wgsl_type_value } from "../type/serde/write_gpu_typed_buffer.js";
16
- import { IMMEDIATE_ADDRESS_SPACE_EXTENSION, IMMEDIATE_SIZE_FLOOR } from "./IMMEDIATE_DATA.js";
17
- import { ResourceType } from "./ResourceType.js";
18
- import { ShaderResourceGroupDescriptor } from "./ShaderResourceGroupDescriptor.js";
19
-
20
- /**
21
- * @typedef {import("../../../../core/binary/BinaryBuffer.js").BinaryBuffer} BinaryBuffer
22
- * @typedef {import("../../../device/ShadeGPUCommandContext.js").ShadeGPUCommandContext} ShadeGPUCommandContext
23
- * @typedef {import("../type/WebGPUType.js").WebGPUType} WebGPUType
24
- */
25
-
26
- /**
27
- *
28
- * @param {TextureBindingLayout} member
29
- * @returns {string}
30
- */
31
- function gen_type_texture(member) {
32
- if (member.sampleType === "depth") {
33
-
34
- if (member.viewDimension !== "2d") {
35
- throw new Error('Must be 2d');
36
- }
37
-
38
- // special case
39
- return "texture_depth_2d";
40
- }
41
-
42
- /**
43
- * @type {string}
44
- */
45
- let proper_type;
46
-
47
- switch (member.viewDimension) {
48
- case "1d":
49
- proper_type = "texture_1d";
50
- break;
51
- case "2d":
52
- proper_type = "texture_2d";
53
- break;
54
- case "3d":
55
- proper_type = "texture_3d";
56
- break;
57
- case "2d-array":
58
- proper_type = "texture_2d_array";
59
- break;
60
- default:
61
- throw new Error(`Unsupported viewDimension '${member.viewDimension}'`);
62
- }
63
-
64
- proper_type += "<";
65
-
66
- proper_type += wgsl_texture_declaration_by_sample_type(member.sampleType);
67
-
68
- proper_type += ">";
69
-
70
- return proper_type;
71
- }
72
-
73
- /**
74
- *
75
- * @param {StorageTextureBindingLayout} member
76
- * @returns {string}
77
- */
78
- function gen_type_storage_texture(member) {
79
- /**
80
- * @type {string}
81
- */
82
- let proper_type;
83
-
84
- if (member.viewDimension === "2d") {
85
- proper_type = "texture_storage_2d"
86
- } else if (member.viewDimension === "2d-array") {
87
- proper_type = "texture_storage_2d_array";
88
- } else if (member.viewDimension === "3d") {
89
- proper_type = "texture_storage_3d";
90
- } else {
91
- throw new Error(`Unsupported viewDimension '${member.viewDimension}'`);
92
- }
93
-
94
- /**
95
- *
96
- * @param {GPUStorageTextureAccess} access
97
- */
98
- function gen_access(access) {
99
- switch (access) {
100
- case "write-only":
101
- return "write";
102
- case "read-write":
103
- // TODO validate
104
- return "read_write";
105
- case "read-only":
106
- // TODO valida
107
- return "read";
108
- default:
109
- throw new Error(`Unsupported access ${access}`);
110
- }
111
- }
112
-
113
- proper_type += `< ${member.format}, ${gen_access(member.access)} >`
114
-
115
- return proper_type;
116
- }
117
-
118
- /**
119
- *
120
- * @param {SamplerBindingLayout} member
121
- * @returns {string}
122
- */
123
- function gen_type_sampler(member) {
124
- // see https://www.w3.org/TR/WGSL/#sampler-type
125
-
126
- // WGSL has no "non-filtering" sampler type; filtering is a bind-group-layout property, so
127
- // both "filtering" and "non-filtering" declare a plain `sampler`
128
- if (member.type === "filtering" || member.type === "non-filtering") {
129
- return "sampler";
130
- } else if (member.type === "comparison") {
131
- return "sampler_comparison";
132
- } else {
133
- throw new Error(`Unsupported sampler type '${member.type}'`);
134
- }
135
-
136
- }
137
-
138
- export class ShaderResourceSetDescriptor {
139
-
140
- /**
141
- *
142
- * @type {ShaderResourceGroupDescriptor[]}
143
- */
144
- #groups = [];
145
-
146
- /**
147
- * The shader's immediate data declaration, or undefined when it has none.
148
- *
149
- * Deliberately not a member of any {@link ShaderResourceGroupDescriptor}: immediate data has no
150
- * `@group` and no `@binding`, and WGSL is explicit that it is part of a shader's *interface*
151
- * without being part of its *resource interface*. Modelling it as a group member would give it
152
- * a binding index that does not exist.
153
- *
154
- * @type {{name: string, type: WebGPUType}|undefined}
155
- */
156
- #immediate = undefined;
157
-
158
- /**
159
- * @returns {{name: string, type: WebGPUType}|undefined}
160
- */
161
- get immediate() {
162
- return this.#immediate;
163
- }
164
-
165
- /**
166
- * Bytes of immediate data this shader reads, rounded up to the 4-byte granularity WebGPU
167
- * requires of `immediateSize`. Zero when there is no immediate declaration.
168
- *
169
- * @returns {number}
170
- */
171
- get immediateSize() {
172
- if (this.#immediate === undefined) {
173
- return 0;
174
- }
175
-
176
- return round_up(this.#immediate.type.size, 4);
177
- }
178
-
179
- /**
180
- * Declare this shader's immediate data — the WGSL `immediate` address space, which reaches the
181
- * GPU through `setImmediates` on the pass encoder rather than through a bind group.
182
- *
183
- * Every restriction below is checked here rather than left to `createShaderModule`, because the
184
- * device-side failure is a shader-creation error whose message names neither this descriptor nor
185
- * the shader it belongs to.
186
- *
187
- * @param {string} name
188
- * @param {WebGPUType|string} _type must be host-shareable, constructible, array-free, and fit
189
- * the device's `maxImmediateSize`
190
- * @returns {this}
191
- */
192
- setImmediate(name, _type) {
193
- assert.isString(name, 'name');
194
- assert.defined(_type, 'type');
195
-
196
- if (this.#immediate !== undefined) {
197
- throw new Error(
198
- `Immediate data is already declared as '${this.#immediate.name}'. WGSL allows at most one immediate variable per entry point, so '${name}' would have to replace it.`
199
- );
200
- }
201
-
202
- let type = _type;
203
-
204
- if (typeof type === "string") {
205
- type = parse_wgsl_type(type);
206
- } else {
207
- assert.equal(type.isWebGPUType, true, 'type.isWebGPUType !== true');
208
- }
209
-
210
- if (type.runtime_sized) {
211
- throw new Error(`Immediate data '${name}' must have a size known ahead of time, and '${type}' is runtime-sized`);
212
- }
213
-
214
- if (type_has_arrays(type)) {
215
- throw new Error(
216
- `Immediate data '${name}' may not contain an array: the immediate address space excludes arrays and structures with array members. Keep the array in a storage buffer and pass an index.`
217
- );
218
- }
219
-
220
- // https://www.w3.org/TR/WGSL/#atomic-type — an immediate is immutable, so an atomic in one
221
- // could never be operated on anyway
222
- assert.equal(type_has_atomics(type), false, 'atomics are not allowed in immediate data');
223
-
224
- const size = round_up(type.size, 4);
225
-
226
- if (size > IMMEDIATE_SIZE_FLOOR) {
227
- throw new Error(
228
- `Immediate data '${name}' is ${size} bytes, over the ${IMMEDIATE_SIZE_FLOOR}-byte maxImmediateSize that every WebGPU device is guaranteed to offer. Move the bulk of it to a uniform buffer.`
229
- );
230
- }
231
-
232
- // The top-level member names, kept so that `writeImmediate` can tell a value of this type
233
- // from something that merely happens to be an object. `undefined` for a scalar, vector or
234
- // matrix immediate, which has no members to name.
235
- const field_names = type instanceof WebGPUStruct
236
- ? type.fields.map(field => field.name)
237
- : undefined;
238
-
239
- this.#immediate = { name, type, field_names };
240
-
241
- return this;
242
- }
243
-
244
- /**
245
- * Do not modify directly
246
- * @returns {ShaderResourceGroupDescriptor[]}
247
- */
248
- get groups() {
249
- return this.#groups;
250
- }
251
-
252
-
253
- /**
254
- *
255
- * @return {boolean}
256
- */
257
- get isShaderResourceSetDescriptor() {
258
- return true;
259
- }
260
-
261
- #getEmptySlot() {
262
- for (let i = 0; i < 1024; i++) {
263
- if (this.#groups[i] === undefined) {
264
- return i;
265
- }
266
- }
267
-
268
- throw new Error(`All slots are used up`);
269
- }
270
-
271
-
272
- /**
273
- *
274
- * @param {string} name
275
- * @returns {ShaderResourceDescriptor}
276
- */
277
- /**
278
- * Whether `name` is this shader's immediate data.
279
- *
280
- * Immediate data is deliberately absent from {@link getResourceByName}: it is not a bound
281
- * resource and has no binding layout, so anything walking the resource interface should not see
282
- * it. The graph helpers still need to recognise the name, because an immediate value travels to
283
- * the encoder as a plain value rather than as a graph resource — and a `u32` immediate is a
284
- * number, which those helpers would otherwise read as a graph resource id.
285
- *
286
- * @param {string} name
287
- * @returns {boolean}
288
- */
289
- isImmediateName(name) {
290
- return this.#immediate !== undefined && this.#immediate.name === name;
291
- }
292
-
293
- getResourceByName(name) {
294
-
295
- for (const group of this.#groups) {
296
-
297
- const resource = group.get(name);
298
-
299
- if (resource !== undefined) {
300
- return resource;
301
- }
302
-
303
- }
304
-
305
- }
306
-
307
- /**
308
- *
309
- * @param {Object} [options]
310
- * @param {number} [options.index]
311
- * @param {string} [options.label]
312
- * @returns {ShaderResourceGroupDescriptor}
313
- */
314
- createGroup({
315
- index = this.#getEmptySlot(),
316
- label = "",
317
- } = {}) {
318
-
319
- assert.isNonNegativeInteger(index, 'index');
320
- assert.lessThan(index, 1024, 'Too high');
321
- assert.isString(label, 'label');
322
-
323
- if (this.#groups[index] !== undefined) {
324
- throw new Error(`Group ${index} already exists`);
325
- }
326
-
327
- const r = new ShaderResourceGroupDescriptor();
328
-
329
- r.label = label;
330
-
331
- this.#groups[index] = r;
332
-
333
- return r;
334
- }
335
-
336
- /**
337
- *
338
- * @param {ShaderResourceGroupDescriptor} group
339
- * @returns {boolean}
340
- */
341
- addGroup(group) {
342
- // TODO check for name collisions
343
-
344
- const added = array_push_if_unique(this.#groups, group);
345
-
346
- return added;
347
- }
348
-
349
- /**
350
- *
351
- * @param {GPUShaderStage|number} stage
352
- */
353
- addVisibility(stage) {
354
- const groups = this.#groups;
355
- const group_count = groups.length;
356
-
357
- for (let i = 0; i < group_count; i++) {
358
- const group = groups[i];
359
-
360
- group.addVisibility(stage);
361
- }
362
- }
363
-
364
- /**
365
- * @returns {PipelineLayoutDescriptor}
366
- */
367
- generatePipelineLayoutDescriptor() {
368
- const r = new PipelineLayoutDescriptor();
369
-
370
- const groups = this.#groups;
371
- const group_count = groups.length;
372
- for (let i = 0; i < group_count; i++) {
373
-
374
- const group = groups[i];
375
-
376
- r.bindGroupLayouts[i] = group.generateBindGroupLayoutDescriptor();
377
- }
378
-
379
- r.immediateSize = this.immediateSize;
380
-
381
- return r;
382
- }
383
-
384
- /**
385
- *
386
- * @return {[][]}
387
- */
388
- generateBindingsArray() {
389
- const binding_groups = [];
390
-
391
- const groups = this.#groups;
392
-
393
- for (let group_index = 0; group_index < groups.length; group_index++) {
394
- const group = groups[group_index];
395
-
396
- binding_groups[group_index] = group.resources.map(r => r.member_descriptor);
397
- }
398
-
399
- return binding_groups;
400
- }
401
-
402
- /**
403
- *
404
- * @param {GPUShaderStage|number} stage
405
- * @returns {PipelineLayoutDescriptor}
406
- */
407
- generatePipelineLayout(stage) {
408
- assert.defined(stage, 'stage');
409
-
410
- return PipelineLayoutDescriptor.forStage(stage, this.generateBindingsArray(), this.immediateSize);
411
- }
412
-
413
- /**
414
- *
415
- * @param {Object} map
416
- * @param {ShadeGPUCommandContext} [encoder] optional, allows resolving more defaults
417
- * @returns {GPUBindingResource[][]}
418
- */
419
- generateBindings(map, encoder) {
420
-
421
- const groups = this.#groups;
422
- const group_count = groups.length;
423
-
424
- const output = [];
425
-
426
- for (let i = 0; i < group_count; i++) {
427
- const group = groups[i];
428
-
429
- output[i] = group.generateBindings(map, encoder);
430
- }
431
-
432
- return output;
433
- }
434
-
435
- /**
436
- * Generates WGSL code declaring bindings
437
- * @return {CodeChunk}
438
- */
439
- generateCodeChunk() {
440
- const builder = new LineBuilder();
441
-
442
- /**
443
- *
444
- * @type {Set<CodeChunk>}
445
- */
446
- const dependencies = new Set();
447
-
448
- const groups = this.#groups;
449
-
450
- const immediate = this.#immediate;
451
-
452
- if (immediate !== undefined) {
453
- const immediate_type = immediate.type;
454
-
455
- if (immediate_type.requires_declaration) {
456
- dependencies.add(immediate_type.declaration_chunk);
457
- }
458
-
459
- // no @group, no @binding — this is the one module-scope variable that has neither
460
- builder.add(`var<immediate> ${immediate.name} : ${immediate_type.wgsl_ref};`);
461
- }
462
-
463
- for (let group_index = 0; group_index < groups.length; group_index++) {
464
- const group = groups[group_index];
465
-
466
-
467
- const resources = group.resources;
468
- const resource_count = resources.length;
469
-
470
-
471
- for (let i = 0; i < resource_count; i++) {
472
- const resource = resources[i];
473
-
474
- const member = resource.member_descriptor;
475
- const resource_type = resource.type;
476
-
477
- let declaration = `@group(${group_index}) @binding(${resource.binding_index}) var`
478
-
479
- let proper_type;
480
-
481
- if (resource_type === ResourceType.Buffer) {
482
-
483
- const gpu_type = resource.buffer_type;
484
-
485
- if (gpu_type.requires_declaration) {
486
- dependencies.add(gpu_type.declaration_chunk);
487
- }
488
-
489
- const layout_type = member.type;
490
-
491
- if (layout_type === "uniform") {
492
- declaration += "<uniform>"
493
- } else if (layout_type === "storage") {
494
- declaration += "<storage, read_write>"
495
- } else if (layout_type === "read-only-storage") {
496
- declaration += "<storage, read>"
497
- } else {
498
- throw new Error(`Unsupported layout type '${layout_type}'`);
499
- }
500
-
501
- proper_type = gpu_type.wgsl_ref;
502
-
503
- } else if (resource_type === ResourceType.Texture) {
504
- proper_type = gen_type_texture(member);
505
-
506
- } else if (resource_type === ResourceType.StorageTexture) {
507
-
508
- proper_type = gen_type_storage_texture(member);
509
-
510
- } else if (resource_type === ResourceType.Sampler) {
511
-
512
- proper_type = gen_type_sampler(member);
513
-
514
- } else {
515
- throw new Error(`Unsupported type ${objectKeyByValue(ResourceType, resource_type)}(=${resource_type})`)
516
- }
517
-
518
- declaration += " ";
519
- declaration += resource.name;
520
- declaration += " : ";
521
-
522
-
523
- declaration += proper_type;
524
-
525
- declaration += ";" // terminate the line
526
-
527
- builder.add(declaration);
528
- }
529
-
530
- }
531
-
532
- const chunk = CodeChunk.from(builder.build(), Array.from(dependencies));
533
-
534
- if (immediate !== undefined) {
535
- // `requires`, not `enable` — see CodeChunk#addLanguageExtension
536
- chunk.addLanguageExtension(IMMEDIATE_ADDRESS_SPACE_EXTENSION);
537
- }
538
-
539
- return chunk;
540
-
541
- }
542
-
543
- /**
544
- * Serialise this shader's immediate data into `buffer` at its current `position`, advancing
545
- * `position` past what was written.
546
- *
547
- * **Allocates nothing.** That is the point of taking a caller-owned {@link BinaryBuffer} rather
548
- * than returning bytes: `write_gpu_typed_buffer` would rebind a scratch buffer with a fresh
549
- * `DataView` and `Uint8Array` on every call, which is two allocations per dispatch for a value
550
- * that is often four bytes. {@link write_wgsl_type_value} takes the buffer directly and does not.
551
- *
552
- * The caller owns `position` because the caller owns the buffer — this only ever appends at the
553
- * cursor it is handed.
554
- *
555
- * @param {Object} map the same binding map {@link generateBindings} reads
556
- * @param {BinaryBuffer} buffer must already be set to the platform's endianness
557
- * @returns {boolean} false when this shader declares no immediate data, and nothing was written
558
- */
559
- writeImmediate(map, buffer) {
560
- const immediate = this.#immediate;
561
-
562
- if (immediate === undefined) {
563
- return false;
564
- }
565
-
566
- const value = map[immediate.name];
567
-
568
- if (value === undefined || value === null) {
569
- throw new Error(
570
- `Value for immediate data '${immediate.name}' is missing from the input. Unlike a buffer binding it has no default: WebGPU refuses a draw whose immediate slots were never written.`
571
- );
572
- }
573
-
574
- // Refuse a value of the wrong shape rather than serialise what it does not contain.
575
- //
576
- // The whole declared range travels every dispatch, and the zeroes this method clears it to are
577
- // indistinguishable from deliberate ones: every slot ends up *set*, so WebGPU's immediate
578
- // validation — and the software device's copy of it — has nothing to report. A wrong-shaped
579
- // value therefore reaches the shader as zeroes, silently, and the only symptom is wrong
580
- // output. That is what a call site left behind by the uniform -> immediate migration does: it
581
- // keeps handing over the transient GPUBuffer the uniform needed, `generateBindings` ignores
582
- // the extra key so the buffer is never bound, and nothing on a GPUBuffer matches the type.
583
- //
584
- // A value that names *some* of the members is left alone. Structs carry explicit padding
585
- // members the CPU side has no value for, and skipping absent fields is load-bearing anyway
586
- // (GPUTypedTable#set_range writes one member of a record through the same serialiser). Only a
587
- // value that could not have populated the type at all is an unambiguous mistake.
588
- const field_names = immediate.field_names;
589
-
590
- if (field_names === undefined) {
591
- // Scalar, vector or matrix: the serialiser reads the value as a number or indexes it.
592
- const usable = typeof value === "number"
593
- || typeof value === "boolean"
594
- || typeof value[0] === "number";
595
-
596
- if (!usable) {
597
- throw new Error(
598
- `Immediate data '${immediate.name}' of type '${immediate.type}' was given a value the`
599
- + ` serialiser cannot read as a number: '${value}'. An immediate takes the plain value,`
600
- + ` not something bindable — a GPUBuffer is what a *uniform* binding wants, and one`
601
- + ` passed here is ignored by generateBindings and would serialise as zeroes.`
602
- );
603
- }
604
- } else if (!value_names_a_member(value, field_names)) {
605
- // Note: no `${immediate.type}` in the message. Interpolating a struct type runs its whole
606
- // WGSL declaration through the code generator, and the member list is the actionable half
607
- // of that anyway.
608
- throw new Error(
609
- `Immediate data '${immediate.name}' was given a value naming none of its members`
610
- + ` (${field_names.join(', ')}), so the dispatch would have read zeroes. An immediate`
611
- + ` takes the plain value — '{ ${field_names[0]}: ... }' — not`
612
- + ` something bindable: a GPUBuffer is what a *uniform* binding wants, and one passed`
613
- + ` here is ignored by generateBindings and serialises to nothing.`
614
- );
615
- }
616
-
617
- const start = buffer.position;
618
- const size = this.immediateSize;
619
-
620
- buffer.ensureCapacity(start + size);
621
-
622
- // Clear the whole declared range up front, rather than filling in from wherever the
623
- // serialiser's cursor stopped.
624
- //
625
- // Two reasons, and the second is the one that bites. The first: the serialiser stops after the
626
- // final member, so a struct with trailing padding — say `{vec4f, u32}`, 20 bytes written of a
627
- // 32-byte type — leaves a tail. That tail is padding, WebGPU's AccessibleSlots excludes
628
- // padding, and a short write would in fact validate; it would also make the bytes handed to
629
- // `setImmediates` shorter than the `immediateSize` the pipeline layout declares, true-but-subtle
630
- // in a way that only holds as long as nobody changes how either number is derived.
631
- //
632
- // The second: this buffer is one scratch region reused by every dispatch of a context, and it
633
- // is only ever written over, never cleared. A member the value did not name is skipped, and a
634
- // skipped member before the final one is not in the tail — filling from the cursor left it
635
- // holding the bytes the *previous* dispatch put at that offset. A partial value is legal (see
636
- // above), so that made one dispatch's immediate data a function of the one before it. Clearing
637
- // first closes the holes and the tail together, and costs at most 64 bytes of memset.
638
- buffer.raw_bytes.fill(0, start, start + size);
639
-
640
- write_wgsl_type_value(value, buffer, immediate.type);
641
-
642
- buffer.position = start + size;
643
-
644
- return true;
645
- }
646
- }
647
-
648
- /**
649
- * Whether `value` carries at least one of `field_names`.
650
- *
651
- * A plain loop, and a free function rather than a closure over `value`, because
652
- * {@link ShaderResourceSetDescriptor#writeImmediate} runs once per dispatch and allocates nothing.
653
- *
654
- * @param {Object} value
655
- * @param {string[]} field_names
656
- * @returns {boolean}
657
- */
658
- function value_names_a_member(value, field_names) {
659
- const count = field_names.length;
660
-
661
- for (let i = 0; i < count; i++) {
662
- if (value[field_names[i]] !== undefined) {
663
- return true;
664
- }
665
- }
666
-
667
- return false;
668
- }
669
-
670
- /**
671
- * Special immutable empty set
672
- * @readonly
673
- * @type {Readonly<ShaderResourceSetDescriptor>}
674
- */
675
- ShaderResourceSetDescriptor.EMPTY = Object.freeze(new ShaderResourceSetDescriptor());
1
+ import { assert } from "../../../../core/assert.js";
2
+ import { round_up } from "../../../../core/math/round_up.js";
3
+ import LineBuilder from "../../../../core/codegen/LineBuilder.js";
4
+ import { array_push_if_unique } from "../../../../core/collection/array/array_push_if_unique.js";
5
+ import { objectKeyByValue } from "../../../../core/model/object/objectKeyByValue.js";
6
+ import { PipelineLayoutDescriptor } from "../../../descriptor/pipeline/PipelineLayoutDescriptor.js";
7
+ import { WebGPUExtensionType } from "../../../descriptor/WebGPUExtensionType.js";
8
+ import {
9
+ wgsl_texture_declaration_by_sample_type
10
+ } from "../../texture/format/wgsl_texture_declaration_by_sample_type.js";
11
+ import { CodeChunk } from "../compiler/CodeChunk.js";
12
+ import { parse_wgsl_type } from "../type/parse_wgsl_type.js";
13
+ import { type_has_arrays } from "../type/type_has_arrays.js";
14
+ import { type_has_atomics } from "../type/type_has_atomics.js";
15
+ import { type_has_f16 } from "../type/type_has_f16.js";
16
+ import { WebGPUStruct } from "../type/WebGPUStruct.js";
17
+ import { write_wgsl_type_value } from "../type/serde/write_gpu_typed_buffer.js";
18
+ import { IMMEDIATE_ADDRESS_SPACE_EXTENSION, IMMEDIATE_SIZE_FLOOR } from "./IMMEDIATE_DATA.js";
19
+ import { ResourceType } from "./ResourceType.js";
20
+ import { ShaderResourceGroupDescriptor } from "./ShaderResourceGroupDescriptor.js";
21
+
22
+ /**
23
+ * @typedef {import("../../../../core/binary/BinaryBuffer.js").BinaryBuffer} BinaryBuffer
24
+ * @typedef {import("../../../device/ShadeGPUCommandContext.js").ShadeGPUCommandContext} ShadeGPUCommandContext
25
+ * @typedef {import("../type/WebGPUType.js").WebGPUType} WebGPUType
26
+ */
27
+
28
+ /**
29
+ *
30
+ * @param {TextureBindingLayout} member
31
+ * @returns {string}
32
+ */
33
+ function gen_type_texture(member) {
34
+ if (member.sampleType === "depth") {
35
+
36
+ if (member.viewDimension !== "2d") {
37
+ throw new Error('Must be 2d');
38
+ }
39
+
40
+ // special case
41
+ return "texture_depth_2d";
42
+ }
43
+
44
+ /**
45
+ * @type {string}
46
+ */
47
+ let proper_type;
48
+
49
+ switch (member.viewDimension) {
50
+ case "1d":
51
+ proper_type = "texture_1d";
52
+ break;
53
+ case "2d":
54
+ proper_type = "texture_2d";
55
+ break;
56
+ case "3d":
57
+ proper_type = "texture_3d";
58
+ break;
59
+ case "2d-array":
60
+ proper_type = "texture_2d_array";
61
+ break;
62
+ default:
63
+ throw new Error(`Unsupported viewDimension '${member.viewDimension}'`);
64
+ }
65
+
66
+ proper_type += "<";
67
+
68
+ proper_type += wgsl_texture_declaration_by_sample_type(member.sampleType);
69
+
70
+ proper_type += ">";
71
+
72
+ return proper_type;
73
+ }
74
+
75
+ /**
76
+ *
77
+ * @param {StorageTextureBindingLayout} member
78
+ * @returns {string}
79
+ */
80
+ function gen_type_storage_texture(member) {
81
+ /**
82
+ * @type {string}
83
+ */
84
+ let proper_type;
85
+
86
+ if (member.viewDimension === "2d") {
87
+ proper_type = "texture_storage_2d"
88
+ } else if (member.viewDimension === "2d-array") {
89
+ proper_type = "texture_storage_2d_array";
90
+ } else if (member.viewDimension === "3d") {
91
+ proper_type = "texture_storage_3d";
92
+ } else {
93
+ throw new Error(`Unsupported viewDimension '${member.viewDimension}'`);
94
+ }
95
+
96
+ /**
97
+ *
98
+ * @param {GPUStorageTextureAccess} access
99
+ */
100
+ function gen_access(access) {
101
+ switch (access) {
102
+ case "write-only":
103
+ return "write";
104
+ case "read-write":
105
+ // TODO validate
106
+ return "read_write";
107
+ case "read-only":
108
+ // TODO valida
109
+ return "read";
110
+ default:
111
+ throw new Error(`Unsupported access ${access}`);
112
+ }
113
+ }
114
+
115
+ proper_type += `< ${member.format}, ${gen_access(member.access)} >`
116
+
117
+ return proper_type;
118
+ }
119
+
120
+ /**
121
+ *
122
+ * @param {SamplerBindingLayout} member
123
+ * @returns {string}
124
+ */
125
+ function gen_type_sampler(member) {
126
+ // see https://www.w3.org/TR/WGSL/#sampler-type
127
+
128
+ // WGSL has no "non-filtering" sampler type; filtering is a bind-group-layout property, so
129
+ // both "filtering" and "non-filtering" declare a plain `sampler`
130
+ if (member.type === "filtering" || member.type === "non-filtering") {
131
+ return "sampler";
132
+ } else if (member.type === "comparison") {
133
+ return "sampler_comparison";
134
+ } else {
135
+ throw new Error(`Unsupported sampler type '${member.type}'`);
136
+ }
137
+
138
+ }
139
+
140
+ export class ShaderResourceSetDescriptor {
141
+
142
+ /**
143
+ *
144
+ * @type {ShaderResourceGroupDescriptor[]}
145
+ */
146
+ #groups = [];
147
+
148
+ /**
149
+ * The shader's immediate data declaration, or undefined when it has none.
150
+ *
151
+ * Deliberately not a member of any {@link ShaderResourceGroupDescriptor}: immediate data has no
152
+ * `@group` and no `@binding`, and WGSL is explicit that it is part of a shader's *interface*
153
+ * without being part of its *resource interface*. Modelling it as a group member would give it
154
+ * a binding index that does not exist.
155
+ *
156
+ * @type {{name: string, type: WebGPUType}|undefined}
157
+ */
158
+ #immediate = undefined;
159
+
160
+ /**
161
+ * @returns {{name: string, type: WebGPUType}|undefined}
162
+ */
163
+ get immediate() {
164
+ return this.#immediate;
165
+ }
166
+
167
+ /**
168
+ * Bytes of immediate data this shader reads, rounded up to the 4-byte granularity WebGPU
169
+ * requires of `immediateSize`. Zero when there is no immediate declaration.
170
+ *
171
+ * @returns {number}
172
+ */
173
+ get immediateSize() {
174
+ if (this.#immediate === undefined) {
175
+ return 0;
176
+ }
177
+
178
+ return round_up(this.#immediate.type.size, 4);
179
+ }
180
+
181
+ /**
182
+ * Declare this shader's immediate data — the WGSL `immediate` address space, which reaches the
183
+ * GPU through `setImmediates` on the pass encoder rather than through a bind group.
184
+ *
185
+ * Every restriction below is checked here rather than left to `createShaderModule`, because the
186
+ * device-side failure is a shader-creation error whose message names neither this descriptor nor
187
+ * the shader it belongs to.
188
+ *
189
+ * @param {string} name
190
+ * @param {WebGPUType|string} _type must be host-shareable, constructible, array-free, and fit
191
+ * the device's `maxImmediateSize`
192
+ * @returns {this}
193
+ */
194
+ setImmediate(name, _type) {
195
+ assert.isString(name, 'name');
196
+ assert.defined(_type, 'type');
197
+
198
+ if (this.#immediate !== undefined) {
199
+ throw new Error(
200
+ `Immediate data is already declared as '${this.#immediate.name}'. WGSL allows at most one immediate variable per entry point, so '${name}' would have to replace it.`
201
+ );
202
+ }
203
+
204
+ let type = _type;
205
+
206
+ if (typeof type === "string") {
207
+ type = parse_wgsl_type(type);
208
+ } else {
209
+ assert.equal(type.isWebGPUType, true, 'type.isWebGPUType !== true');
210
+ }
211
+
212
+ if (type.runtime_sized) {
213
+ throw new Error(`Immediate data '${name}' must have a size known ahead of time, and '${type}' is runtime-sized`);
214
+ }
215
+
216
+ if (type_has_arrays(type)) {
217
+ throw new Error(
218
+ `Immediate data '${name}' may not contain an array: the immediate address space excludes arrays and structures with array members. Keep the array in a storage buffer and pass an index.`
219
+ );
220
+ }
221
+
222
+ // https://www.w3.org/TR/WGSL/#atomic-type — an immediate is immutable, so an atomic in one
223
+ // could never be operated on anyway
224
+ assert.equal(type_has_atomics(type), false, 'atomics are not allowed in immediate data');
225
+
226
+ const size = round_up(type.size, 4);
227
+
228
+ if (size > IMMEDIATE_SIZE_FLOOR) {
229
+ throw new Error(
230
+ `Immediate data '${name}' is ${size} bytes, over the ${IMMEDIATE_SIZE_FLOOR}-byte maxImmediateSize that every WebGPU device is guaranteed to offer. Move the bulk of it to a uniform buffer.`
231
+ );
232
+ }
233
+
234
+ // The top-level member names, kept so that `writeImmediate` can tell a value of this type
235
+ // from something that merely happens to be an object. `undefined` for a scalar, vector or
236
+ // matrix immediate, which has no members to name.
237
+ const field_names = type instanceof WebGPUStruct
238
+ ? type.fields.map(field => field.name)
239
+ : undefined;
240
+
241
+ this.#immediate = { name, type, field_names };
242
+
243
+ return this;
244
+ }
245
+
246
+ /**
247
+ * Do not modify directly
248
+ * @returns {ShaderResourceGroupDescriptor[]}
249
+ */
250
+ get groups() {
251
+ return this.#groups;
252
+ }
253
+
254
+
255
+ /**
256
+ *
257
+ * @return {boolean}
258
+ */
259
+ get isShaderResourceSetDescriptor() {
260
+ return true;
261
+ }
262
+
263
+ #getEmptySlot() {
264
+ for (let i = 0; i < 1024; i++) {
265
+ if (this.#groups[i] === undefined) {
266
+ return i;
267
+ }
268
+ }
269
+
270
+ throw new Error(`All slots are used up`);
271
+ }
272
+
273
+
274
+ /**
275
+ *
276
+ * @param {string} name
277
+ * @returns {ShaderResourceDescriptor}
278
+ */
279
+ /**
280
+ * Whether `name` is this shader's immediate data.
281
+ *
282
+ * Immediate data is deliberately absent from {@link getResourceByName}: it is not a bound
283
+ * resource and has no binding layout, so anything walking the resource interface should not see
284
+ * it. The graph helpers still need to recognise the name, because an immediate value travels to
285
+ * the encoder as a plain value rather than as a graph resource — and a `u32` immediate is a
286
+ * number, which those helpers would otherwise read as a graph resource id.
287
+ *
288
+ * @param {string} name
289
+ * @returns {boolean}
290
+ */
291
+ isImmediateName(name) {
292
+ return this.#immediate !== undefined && this.#immediate.name === name;
293
+ }
294
+
295
+ getResourceByName(name) {
296
+
297
+ for (const group of this.#groups) {
298
+
299
+ const resource = group.get(name);
300
+
301
+ if (resource !== undefined) {
302
+ return resource;
303
+ }
304
+
305
+ }
306
+
307
+ }
308
+
309
+ /**
310
+ *
311
+ * @param {Object} [options]
312
+ * @param {number} [options.index]
313
+ * @param {string} [options.label]
314
+ * @returns {ShaderResourceGroupDescriptor}
315
+ */
316
+ createGroup({
317
+ index = this.#getEmptySlot(),
318
+ label = "",
319
+ } = {}) {
320
+
321
+ assert.isNonNegativeInteger(index, 'index');
322
+ assert.lessThan(index, 1024, 'Too high');
323
+ assert.isString(label, 'label');
324
+
325
+ if (this.#groups[index] !== undefined) {
326
+ throw new Error(`Group ${index} already exists`);
327
+ }
328
+
329
+ const r = new ShaderResourceGroupDescriptor();
330
+
331
+ r.label = label;
332
+
333
+ this.#groups[index] = r;
334
+
335
+ return r;
336
+ }
337
+
338
+ /**
339
+ *
340
+ * @param {ShaderResourceGroupDescriptor} group
341
+ * @returns {boolean}
342
+ */
343
+ addGroup(group) {
344
+ // TODO check for name collisions
345
+
346
+ const added = array_push_if_unique(this.#groups, group);
347
+
348
+ return added;
349
+ }
350
+
351
+ /**
352
+ *
353
+ * @param {GPUShaderStage|number} stage
354
+ */
355
+ addVisibility(stage) {
356
+ const groups = this.#groups;
357
+ const group_count = groups.length;
358
+
359
+ for (let i = 0; i < group_count; i++) {
360
+ const group = groups[i];
361
+
362
+ group.addVisibility(stage);
363
+ }
364
+ }
365
+
366
+ /**
367
+ * @returns {PipelineLayoutDescriptor}
368
+ */
369
+ generatePipelineLayoutDescriptor() {
370
+ const r = new PipelineLayoutDescriptor();
371
+
372
+ const groups = this.#groups;
373
+ const group_count = groups.length;
374
+ for (let i = 0; i < group_count; i++) {
375
+
376
+ const group = groups[i];
377
+
378
+ r.bindGroupLayouts[i] = group.generateBindGroupLayoutDescriptor();
379
+ }
380
+
381
+ r.immediateSize = this.immediateSize;
382
+
383
+ return r;
384
+ }
385
+
386
+ /**
387
+ *
388
+ * @return {[][]}
389
+ */
390
+ generateBindingsArray() {
391
+ const binding_groups = [];
392
+
393
+ const groups = this.#groups;
394
+
395
+ for (let group_index = 0; group_index < groups.length; group_index++) {
396
+ const group = groups[group_index];
397
+
398
+ binding_groups[group_index] = group.resources.map(r => r.member_descriptor);
399
+ }
400
+
401
+ return binding_groups;
402
+ }
403
+
404
+ /**
405
+ *
406
+ * @param {GPUShaderStage|number} stage
407
+ * @returns {PipelineLayoutDescriptor}
408
+ */
409
+ generatePipelineLayout(stage) {
410
+ assert.defined(stage, 'stage');
411
+
412
+ return PipelineLayoutDescriptor.forStage(stage, this.generateBindingsArray(), this.immediateSize);
413
+ }
414
+
415
+ /**
416
+ *
417
+ * @param {Object} map
418
+ * @param {ShadeGPUCommandContext} [encoder] optional, allows resolving more defaults
419
+ * @returns {GPUBindingResource[][]}
420
+ */
421
+ generateBindings(map, encoder) {
422
+
423
+ const groups = this.#groups;
424
+ const group_count = groups.length;
425
+
426
+ const output = [];
427
+
428
+ for (let i = 0; i < group_count; i++) {
429
+ const group = groups[i];
430
+
431
+ output[i] = group.generateBindings(map, encoder);
432
+ }
433
+
434
+ return output;
435
+ }
436
+
437
+ /**
438
+ * Generates WGSL code declaring bindings
439
+ * @return {CodeChunk}
440
+ */
441
+ generateCodeChunk() {
442
+ const builder = new LineBuilder();
443
+
444
+ /**
445
+ *
446
+ * @type {Set<CodeChunk>}
447
+ */
448
+ const dependencies = new Set();
449
+
450
+ const groups = this.#groups;
451
+
452
+ const immediate = this.#immediate;
453
+ let uses_f16 = false;
454
+
455
+ if (immediate !== undefined) {
456
+ const immediate_type = immediate.type;
457
+
458
+ if (immediate_type.requires_declaration) {
459
+ dependencies.add(immediate_type.declaration_chunk);
460
+ }
461
+
462
+ if (type_has_f16(immediate_type)) {
463
+ uses_f16 = true;
464
+ }
465
+
466
+ // no @group, no @binding — this is the one module-scope variable that has neither
467
+ builder.add(`var<immediate> ${immediate.name} : ${immediate_type.wgsl_ref};`);
468
+ }
469
+
470
+ for (let group_index = 0; group_index < groups.length; group_index++) {
471
+ const group = groups[group_index];
472
+
473
+
474
+ const resources = group.resources;
475
+ const resource_count = resources.length;
476
+
477
+
478
+ for (let i = 0; i < resource_count; i++) {
479
+ const resource = resources[i];
480
+
481
+ const member = resource.member_descriptor;
482
+ const resource_type = resource.type;
483
+
484
+ let declaration = `@group(${group_index}) @binding(${resource.binding_index}) var`
485
+
486
+ let proper_type;
487
+
488
+ if (resource_type === ResourceType.Buffer) {
489
+
490
+ const gpu_type = resource.buffer_type;
491
+
492
+ if (gpu_type.requires_declaration) {
493
+ dependencies.add(gpu_type.declaration_chunk);
494
+ }
495
+
496
+ if (type_has_f16(gpu_type)) {
497
+ uses_f16 = true;
498
+ }
499
+
500
+ const layout_type = member.type;
501
+
502
+ if (layout_type === "uniform") {
503
+ declaration += "<uniform>"
504
+ } else if (layout_type === "storage") {
505
+ declaration += "<storage, read_write>"
506
+ } else if (layout_type === "read-only-storage") {
507
+ declaration += "<storage, read>"
508
+ } else {
509
+ throw new Error(`Unsupported layout type '${layout_type}'`);
510
+ }
511
+
512
+ proper_type = gpu_type.wgsl_ref;
513
+
514
+ } else if (resource_type === ResourceType.Texture) {
515
+ proper_type = gen_type_texture(member);
516
+
517
+ } else if (resource_type === ResourceType.StorageTexture) {
518
+
519
+ proper_type = gen_type_storage_texture(member);
520
+
521
+ } else if (resource_type === ResourceType.Sampler) {
522
+
523
+ proper_type = gen_type_sampler(member);
524
+
525
+ } else {
526
+ throw new Error(`Unsupported type ${objectKeyByValue(ResourceType, resource_type)}(=${resource_type})`)
527
+ }
528
+
529
+ declaration += " ";
530
+ declaration += resource.name;
531
+ declaration += " : ";
532
+
533
+
534
+ declaration += proper_type;
535
+
536
+ declaration += ";" // terminate the line
537
+
538
+ builder.add(declaration);
539
+ }
540
+
541
+ }
542
+
543
+ const chunk = CodeChunk.from(builder.build(), Array.from(dependencies));
544
+
545
+ if (immediate !== undefined) {
546
+ // `requires`, not `enable` — see CodeChunk#addLanguageExtension
547
+ chunk.addLanguageExtension(IMMEDIATE_ADDRESS_SPACE_EXTENSION);
548
+ }
549
+
550
+ if (uses_f16) {
551
+ chunk.addExtension(WebGPUExtensionType.ShaderF16);
552
+ }
553
+
554
+ return chunk;
555
+
556
+ }
557
+
558
+ /**
559
+ * Serialise this shader's immediate data into `buffer` at its current `position`, advancing
560
+ * `position` past what was written.
561
+ *
562
+ * **Allocates nothing.** That is the point of taking a caller-owned {@link BinaryBuffer} rather
563
+ * than returning bytes: `write_gpu_typed_buffer` would rebind a scratch buffer with a fresh
564
+ * `DataView` and `Uint8Array` on every call, which is two allocations per dispatch for a value
565
+ * that is often four bytes. {@link write_wgsl_type_value} takes the buffer directly and does not.
566
+ *
567
+ * The caller owns `position` because the caller owns the buffer — this only ever appends at the
568
+ * cursor it is handed.
569
+ *
570
+ * @param {Object} map the same binding map {@link generateBindings} reads
571
+ * @param {BinaryBuffer} buffer must already be set to the platform's endianness
572
+ * @returns {boolean} false when this shader declares no immediate data, and nothing was written
573
+ */
574
+ writeImmediate(map, buffer) {
575
+ const immediate = this.#immediate;
576
+
577
+ if (immediate === undefined) {
578
+ return false;
579
+ }
580
+
581
+ const value = map[immediate.name];
582
+
583
+ if (value === undefined || value === null) {
584
+ throw new Error(
585
+ `Value for immediate data '${immediate.name}' is missing from the input. Unlike a buffer binding it has no default: WebGPU refuses a draw whose immediate slots were never written.`
586
+ );
587
+ }
588
+
589
+ // Refuse a value of the wrong shape rather than serialise what it does not contain.
590
+ //
591
+ // The whole declared range travels every dispatch, and the zeroes this method clears it to are
592
+ // indistinguishable from deliberate ones: every slot ends up *set*, so WebGPU's immediate
593
+ // validation — and the software device's copy of it — has nothing to report. A wrong-shaped
594
+ // value therefore reaches the shader as zeroes, silently, and the only symptom is wrong
595
+ // output. That is what a call site left behind by the uniform -> immediate migration does: it
596
+ // keeps handing over the transient GPUBuffer the uniform needed, `generateBindings` ignores
597
+ // the extra key so the buffer is never bound, and nothing on a GPUBuffer matches the type.
598
+ //
599
+ // A value that names *some* of the members is left alone. Structs carry explicit padding
600
+ // members the CPU side has no value for, and skipping absent fields is load-bearing anyway
601
+ // (GPUTypedTable#set_range writes one member of a record through the same serialiser). Only a
602
+ // value that could not have populated the type at all is an unambiguous mistake.
603
+ const field_names = immediate.field_names;
604
+
605
+ if (field_names === undefined) {
606
+ // Scalar, vector or matrix: the serialiser reads the value as a number or indexes it.
607
+ const usable = typeof value === "number"
608
+ || typeof value === "boolean"
609
+ || typeof value[0] === "number";
610
+
611
+ if (!usable) {
612
+ throw new Error(
613
+ `Immediate data '${immediate.name}' of type '${immediate.type}' was given a value the`
614
+ + ` serialiser cannot read as a number: '${value}'. An immediate takes the plain value,`
615
+ + ` not something bindable — a GPUBuffer is what a *uniform* binding wants, and one`
616
+ + ` passed here is ignored by generateBindings and would serialise as zeroes.`
617
+ );
618
+ }
619
+ } else if (!value_names_a_member(value, field_names)) {
620
+ // Note: no `${immediate.type}` in the message. Interpolating a struct type runs its whole
621
+ // WGSL declaration through the code generator, and the member list is the actionable half
622
+ // of that anyway.
623
+ throw new Error(
624
+ `Immediate data '${immediate.name}' was given a value naming none of its members`
625
+ + ` (${field_names.join(', ')}), so the dispatch would have read zeroes. An immediate`
626
+ + ` takes the plain value — '{ ${field_names[0]}: ... }' — not`
627
+ + ` something bindable: a GPUBuffer is what a *uniform* binding wants, and one passed`
628
+ + ` here is ignored by generateBindings and serialises to nothing.`
629
+ );
630
+ }
631
+
632
+ const start = buffer.position;
633
+ const size = this.immediateSize;
634
+
635
+ buffer.ensureCapacity(start + size);
636
+
637
+ // Clear the whole declared range up front, rather than filling in from wherever the
638
+ // serialiser's cursor stopped.
639
+ //
640
+ // Two reasons, and the second is the one that bites. The first: the serialiser stops after the
641
+ // final member, so a struct with trailing padding — say `{vec4f, u32}`, 20 bytes written of a
642
+ // 32-byte type — leaves a tail. That tail is padding, WebGPU's AccessibleSlots excludes
643
+ // padding, and a short write would in fact validate; it would also make the bytes handed to
644
+ // `setImmediates` shorter than the `immediateSize` the pipeline layout declares, true-but-subtle
645
+ // in a way that only holds as long as nobody changes how either number is derived.
646
+ //
647
+ // The second: this buffer is one scratch region reused by every dispatch of a context, and it
648
+ // is only ever written over, never cleared. A member the value did not name is skipped, and a
649
+ // skipped member before the final one is not in the tail — filling from the cursor left it
650
+ // holding the bytes the *previous* dispatch put at that offset. A partial value is legal (see
651
+ // above), so that made one dispatch's immediate data a function of the one before it. Clearing
652
+ // first closes the holes and the tail together, and costs at most 64 bytes of memset.
653
+ buffer.raw_bytes.fill(0, start, start + size);
654
+
655
+ write_wgsl_type_value(value, buffer, immediate.type);
656
+
657
+ buffer.position = start + size;
658
+
659
+ return true;
660
+ }
661
+ }
662
+
663
+ /**
664
+ * Whether `value` carries at least one of `field_names`.
665
+ *
666
+ * A plain loop, and a free function rather than a closure over `value`, because
667
+ * {@link ShaderResourceSetDescriptor#writeImmediate} runs once per dispatch and allocates nothing.
668
+ *
669
+ * @param {Object} value
670
+ * @param {string[]} field_names
671
+ * @returns {boolean}
672
+ */
673
+ function value_names_a_member(value, field_names) {
674
+ const count = field_names.length;
675
+
676
+ for (let i = 0; i < count; i++) {
677
+ if (value[field_names[i]] !== undefined) {
678
+ return true;
679
+ }
680
+ }
681
+
682
+ return false;
683
+ }
684
+
685
+ /**
686
+ * Special immutable empty set
687
+ * @readonly
688
+ * @type {Readonly<ShaderResourceSetDescriptor>}
689
+ */
690
+ ShaderResourceSetDescriptor.EMPTY = Object.freeze(new ShaderResourceSetDescriptor());