@woosh/meep-engine 3.11.3 → 3.13.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 (596) hide show
  1. package/README.md +14 -18
  2. package/editor/SelectionVisualizer.js +127 -127
  3. package/editor/entity_world_bounds.js +27 -27
  4. package/editor/particles/rebuildParticleEmitter.js +31 -31
  5. package/editor/process/SymbolicDisplayProcess.js +1 -1
  6. package/editor/process/symbolic/CameraSymbolicDisplay.js +146 -146
  7. package/editor/process/symbolic/LightSymbolicDisplay.js +172 -172
  8. package/editor/prototypeEditorShell.js +156 -156
  9. package/editor/selection/editor_pick.js +130 -130
  10. package/editor/selection/screen_rect_frustum.js +119 -119
  11. package/editor/tools/v2/TransformControls.js +971 -971
  12. package/package.json +1 -1
  13. package/src/engine/Engine.d.ts +3 -3
  14. package/src/engine/Engine.d.ts.map +1 -1
  15. package/src/engine/Engine.js +726 -726
  16. package/src/engine/EngineHarness.d.ts +1 -1
  17. package/src/engine/EngineHarness.js +590 -590
  18. package/src/engine/ecs/HIERARCHY_REVIEW.md +717 -717
  19. package/src/engine/ecs/terrain/ecs/BuildLightTexture.d.ts +1 -1
  20. package/src/engine/ecs/terrain/ecs/BuildLightTexture.js +27 -27
  21. package/src/engine/ecs/terrain/ecs/Terrain.d.ts +1 -5
  22. package/src/engine/ecs/terrain/ecs/Terrain.d.ts.map +1 -1
  23. package/src/engine/ecs/terrain/ecs/Terrain.js +790 -790
  24. package/src/engine/ecs/terrain/util/loadVisibleTerrainTiles.js +129 -129
  25. package/src/engine/graphics/ecs/camera/camera_find_active.d.ts +1 -1
  26. package/src/engine/graphics/ecs/camera/camera_find_active.js +28 -28
  27. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.d.ts +1 -1
  28. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +428 -428
  29. package/src/engine/graphics/ecs/water/Water.d.ts +1 -1
  30. package/src/engine/graphics/ecs/water/Water.js +104 -104
  31. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts +1 -1
  32. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js +1 -1
  33. package/src/engine/graphics3/AnimationGraphSystem.d.ts +65 -0
  34. package/src/engine/graphics3/AnimationGraphSystem.d.ts.map +1 -0
  35. package/src/engine/graphics3/AnimationGraphSystem.js +329 -0
  36. package/src/engine/graphics3/AnimationGraphSystem3.d.ts +6 -61
  37. package/src/engine/graphics3/AnimationGraphSystem3.d.ts.map +1 -1
  38. package/src/engine/graphics3/AnimationGraphSystem3.js +6 -325
  39. package/src/engine/graphics3/AnimationSystem.d.ts +76 -0
  40. package/src/engine/graphics3/AnimationSystem.d.ts.map +1 -0
  41. package/src/engine/graphics3/AnimationSystem.js +352 -0
  42. package/src/engine/graphics3/AnimationSystem3.d.ts +6 -72
  43. package/src/engine/graphics3/AnimationSystem3.d.ts.map +1 -1
  44. package/src/engine/graphics3/AnimationSystem3.js +6 -348
  45. package/src/engine/graphics3/CameraSystem.d.ts +49 -0
  46. package/src/engine/graphics3/CameraSystem.d.ts.map +1 -0
  47. package/src/engine/graphics3/CameraSystem.js +170 -0
  48. package/src/engine/graphics3/CameraSystem3.d.ts +6 -45
  49. package/src/engine/graphics3/CameraSystem3.d.ts.map +1 -1
  50. package/src/engine/graphics3/CameraSystem3.js +6 -166
  51. package/src/engine/graphics3/DebugDrawSystem.d.ts +72 -0
  52. package/src/engine/graphics3/DebugDrawSystem.d.ts.map +1 -0
  53. package/src/engine/graphics3/DebugDrawSystem.js +205 -0
  54. package/src/engine/graphics3/DebugDrawSystem3.d.ts +6 -68
  55. package/src/engine/graphics3/DebugDrawSystem3.d.ts.map +1 -1
  56. package/src/engine/graphics3/DebugDrawSystem3.js +6 -201
  57. package/src/engine/graphics3/DecalSystem.d.ts +81 -0
  58. package/src/engine/graphics3/DecalSystem.d.ts.map +1 -0
  59. package/src/engine/graphics3/DecalSystem.js +441 -0
  60. package/src/engine/graphics3/DecalSystem3.d.ts +6 -77
  61. package/src/engine/graphics3/DecalSystem3.d.ts.map +1 -1
  62. package/src/engine/graphics3/DecalSystem3.js +6 -437
  63. package/src/engine/graphics3/FogOfWarSystem.d.ts +74 -0
  64. package/src/engine/graphics3/FogOfWarSystem.d.ts.map +1 -0
  65. package/src/engine/graphics3/FogOfWarSystem.js +265 -0
  66. package/src/engine/graphics3/FogOfWarSystem3.d.ts +6 -70
  67. package/src/engine/graphics3/FogOfWarSystem3.d.ts.map +1 -1
  68. package/src/engine/graphics3/FogOfWarSystem3.js +6 -261
  69. package/src/engine/graphics3/GraphicsEngine.d.ts +340 -0
  70. package/src/engine/graphics3/GraphicsEngine.d.ts.map +1 -0
  71. package/src/engine/graphics3/GraphicsEngine.js +790 -0
  72. package/src/engine/graphics3/GraphicsEngine3.d.ts +6 -336
  73. package/src/engine/graphics3/GraphicsEngine3.d.ts.map +1 -1
  74. package/src/engine/graphics3/GraphicsEngine3.js +6 -786
  75. package/src/engine/graphics3/HighlightSystem.d.ts +82 -0
  76. package/src/engine/graphics3/HighlightSystem.d.ts.map +1 -0
  77. package/src/engine/graphics3/HighlightSystem.js +241 -0
  78. package/src/engine/graphics3/HighlightSystem3.d.ts +6 -78
  79. package/src/engine/graphics3/HighlightSystem3.d.ts.map +1 -1
  80. package/src/engine/graphics3/HighlightSystem3.js +6 -237
  81. package/src/engine/graphics3/LightSystem.d.ts +40 -0
  82. package/src/engine/graphics3/LightSystem.d.ts.map +1 -0
  83. package/src/engine/graphics3/LightSystem.js +211 -0
  84. package/src/engine/graphics3/LightSystem3.d.ts +6 -36
  85. package/src/engine/graphics3/LightSystem3.d.ts.map +1 -1
  86. package/src/engine/graphics3/LightSystem3.js +6 -207
  87. package/src/engine/graphics3/MeshSystem.d.ts +106 -0
  88. package/src/engine/graphics3/MeshSystem.d.ts.map +1 -0
  89. package/src/engine/graphics3/MeshSystem.js +647 -0
  90. package/src/engine/graphics3/MeshSystem3.d.ts +6 -102
  91. package/src/engine/graphics3/MeshSystem3.d.ts.map +1 -1
  92. package/src/engine/graphics3/MeshSystem3.js +6 -642
  93. package/src/engine/graphics3/ParticipatingMedia.d.ts +2 -2
  94. package/src/engine/graphics3/ParticipatingMedia.js +203 -203
  95. package/src/engine/graphics3/ParticipatingMediaSystem.d.ts +87 -0
  96. package/src/engine/graphics3/ParticipatingMediaSystem.d.ts.map +1 -0
  97. package/src/engine/graphics3/ParticipatingMediaSystem.js +184 -0
  98. package/src/engine/graphics3/ParticipatingMediaSystem3.d.ts +6 -83
  99. package/src/engine/graphics3/ParticipatingMediaSystem3.d.ts.map +1 -1
  100. package/src/engine/graphics3/ParticipatingMediaSystem3.js +6 -180
  101. package/src/engine/graphics3/ParticleEmitterSystem.d.ts +76 -0
  102. package/src/engine/graphics3/ParticleEmitterSystem.d.ts.map +1 -0
  103. package/src/engine/graphics3/ParticleEmitterSystem.js +289 -0
  104. package/src/engine/graphics3/ParticleEmitterSystem3.d.ts +6 -72
  105. package/src/engine/graphics3/ParticleEmitterSystem3.d.ts.map +1 -1
  106. package/src/engine/graphics3/ParticleEmitterSystem3.js +6 -285
  107. package/src/engine/graphics3/PathDisplaySystem.d.ts +70 -0
  108. package/src/engine/graphics3/PathDisplaySystem.d.ts.map +1 -0
  109. package/src/engine/graphics3/PathDisplaySystem.js +309 -0
  110. package/src/engine/graphics3/PathDisplaySystem3.d.ts +6 -66
  111. package/src/engine/graphics3/PathDisplaySystem3.d.ts.map +1 -1
  112. package/src/engine/graphics3/PathDisplaySystem3.js +6 -305
  113. package/src/engine/graphics3/Pickable.d.ts +1 -1
  114. package/src/engine/graphics3/Pickable.js +65 -65
  115. package/src/engine/graphics3/PickingQuery.d.ts +1 -1
  116. package/src/engine/graphics3/PickingQuery.js +48 -48
  117. package/src/engine/graphics3/PickingSystem.d.ts +67 -0
  118. package/src/engine/graphics3/PickingSystem.d.ts.map +1 -0
  119. package/src/engine/graphics3/PickingSystem.js +273 -0
  120. package/src/engine/graphics3/PickingSystem3.d.ts +6 -63
  121. package/src/engine/graphics3/PickingSystem3.d.ts.map +1 -1
  122. package/src/engine/graphics3/PickingSystem3.js +6 -269
  123. package/src/engine/graphics3/ShadedGeometrySystem.d.ts +47 -0
  124. package/src/engine/graphics3/ShadedGeometrySystem.d.ts.map +1 -0
  125. package/src/engine/graphics3/ShadedGeometrySystem.js +169 -0
  126. package/src/engine/graphics3/ShadedGeometrySystem3.d.ts +6 -43
  127. package/src/engine/graphics3/ShadedGeometrySystem3.d.ts.map +1 -1
  128. package/src/engine/graphics3/ShadedGeometrySystem3.js +6 -165
  129. package/src/engine/graphics3/TerrainSystem.d.ts +80 -0
  130. package/src/engine/graphics3/TerrainSystem.d.ts.map +1 -0
  131. package/src/engine/graphics3/TerrainSystem.js +566 -0
  132. package/src/engine/graphics3/TerrainSystem3.d.ts +6 -76
  133. package/src/engine/graphics3/TerrainSystem3.d.ts.map +1 -1
  134. package/src/engine/graphics3/TerrainSystem3.js +6 -562
  135. package/src/engine/graphics3/TooltipComponentSystem.d.ts +65 -0
  136. package/src/engine/graphics3/TooltipComponentSystem.d.ts.map +1 -0
  137. package/src/engine/graphics3/TooltipComponentSystem.js +328 -0
  138. package/src/engine/graphics3/TooltipComponentSystem3.d.ts +6 -61
  139. package/src/engine/graphics3/TooltipComponentSystem3.d.ts.map +1 -1
  140. package/src/engine/graphics3/TooltipComponentSystem3.js +6 -324
  141. package/src/engine/graphics3/Trail3DSystem.d.ts +73 -0
  142. package/src/engine/graphics3/Trail3DSystem.d.ts.map +1 -0
  143. package/src/engine/graphics3/Trail3DSystem.js +221 -0
  144. package/src/engine/graphics3/Trail3DSystem3.d.ts +6 -69
  145. package/src/engine/graphics3/Trail3DSystem3.d.ts.map +1 -1
  146. package/src/engine/graphics3/Trail3DSystem3.js +6 -217
  147. package/src/engine/graphics3/VolumetricLightMap.d.ts +2 -2
  148. package/src/engine/graphics3/VolumetricLightMap.js +2 -2
  149. package/src/engine/graphics3/VolumetricLightMapSystem.d.ts +98 -0
  150. package/src/engine/graphics3/VolumetricLightMapSystem.d.ts.map +1 -0
  151. package/src/engine/graphics3/VolumetricLightMapSystem.js +261 -0
  152. package/src/engine/graphics3/VolumetricLightMapSystem3.d.ts +6 -94
  153. package/src/engine/graphics3/VolumetricLightMapSystem3.d.ts.map +1 -1
  154. package/src/engine/graphics3/VolumetricLightMapSystem3.js +10 -261
  155. package/src/engine/graphics3/WaterSystem.d.ts +59 -0
  156. package/src/engine/graphics3/WaterSystem.d.ts.map +1 -0
  157. package/src/engine/graphics3/WaterSystem.js +293 -0
  158. package/src/engine/graphics3/WaterSystem3.d.ts +6 -55
  159. package/src/engine/graphics3/WaterSystem3.d.ts.map +1 -1
  160. package/src/engine/graphics3/WaterSystem3.js +6 -289
  161. package/src/engine/graphics3/animation/AnimationGraphController.d.ts +1 -1
  162. package/src/engine/graphics3/animation/AnimationGraphController.js +518 -518
  163. package/src/engine/graphics3/animation/ClipListPlayer.d.ts +1 -1
  164. package/src/engine/graphics3/animation/ClipListPlayer.js +263 -263
  165. package/src/engine/graphics3/animation/ClipPlayback.d.ts +2 -2
  166. package/src/engine/graphics3/animation/ClipPlayback.js +84 -84
  167. package/src/engine/graphics3/decal/GPUDecalRenderer.js +3 -3
  168. package/src/engine/graphics3/decal/graph_build_decal_clusters.d.ts.map +1 -1
  169. package/src/engine/graphics3/decal/graph_build_decal_clusters.js +6 -8
  170. package/src/engine/graphics3/decal/shader_cluster_assign_decals.d.ts +0 -7
  171. package/src/engine/graphics3/decal/shader_cluster_assign_decals.d.ts.map +1 -1
  172. package/src/engine/graphics3/decal/shader_cluster_assign_decals.js +1 -1
  173. package/src/engine/graphics3/decal/shader_cull_decals_frustum.d.ts +0 -4
  174. package/src/engine/graphics3/decal/shader_cull_decals_frustum.d.ts.map +1 -1
  175. package/src/engine/graphics3/decal/shader_cull_decals_frustum.js +1 -1
  176. package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
  177. package/src/engine/graphics3/decal/shader_decal_composite.js +4 -2
  178. package/src/engine/graphics3/highlight/GPUHighlightRenderer.d.ts.map +1 -1
  179. package/src/engine/graphics3/highlight/GPUHighlightRenderer.js +2 -3
  180. package/src/engine/graphics3/highlight/pack_highlight_table.d.ts +2 -2
  181. package/src/engine/graphics3/highlight/pack_highlight_table.d.ts.map +1 -1
  182. package/src/engine/graphics3/highlight/pack_highlight_table.js +74 -74
  183. package/src/engine/graphics3/highlight/shader_highlight_outline.js +150 -150
  184. package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts +1 -1
  185. package/src/engine/graphics3/pose/query_entity_node_world_pose.js +101 -101
  186. package/src/engine/graphics3/preview/make_model_thumbnail.d.ts +3 -3
  187. package/src/engine/graphics3/preview/make_model_thumbnail.d.ts.map +1 -1
  188. package/src/engine/graphics3/preview/make_model_thumbnail.js +48 -48
  189. package/src/engine/graphics3/shade_camera_projection_ray.d.ts +1 -1
  190. package/src/engine/graphics3/shade_camera_projection_ray.js +77 -77
  191. package/src/engine/graphics3/shade_node_to_entity_composition.d.ts +1 -1
  192. package/src/engine/graphics3/shade_node_to_entity_composition.js +84 -84
  193. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  194. package/src/shade/RENDERER_CONTRACT.md +2 -1
  195. package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.d.ts +18 -0
  196. package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.d.ts.map +1 -1
  197. package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.js +73 -0
  198. package/src/shade/device/PASS_ENCODER_PROPOSAL_2026_08_31.md +750 -0
  199. package/src/shade/device/ShadeGPUCommandContext.d.ts +10 -16
  200. package/src/shade/device/ShadeGPUCommandContext.d.ts.map +1 -1
  201. package/src/shade/device/ShadeGPUCommandContext.js +801 -994
  202. package/src/shade/device/pass/ShadeGPUComputePassEncoder.d.ts +107 -0
  203. package/src/shade/device/pass/ShadeGPUComputePassEncoder.d.ts.map +1 -0
  204. package/src/shade/device/pass/ShadeGPUComputePassEncoder.js +222 -0
  205. package/src/shade/device/pass/ShadeGPURenderPassEncoder.d.ts +168 -0
  206. package/src/shade/device/pass/ShadeGPURenderPassEncoder.d.ts.map +1 -0
  207. package/src/shade/device/pass/ShadeGPURenderPassEncoder.js +317 -0
  208. package/src/shade/device/timing/GPUTimerArray.d.ts +4 -9
  209. package/src/shade/device/timing/GPUTimerArray.d.ts.map +1 -1
  210. package/src/shade/device/timing/GPUTimerArray.js +261 -289
  211. package/src/shade/device/timing/GPU_PROFILER_PROPOSAL_2026_08_28.md +20 -2
  212. package/src/shade/device/timing/ShadeGPUContextProfiler.d.ts +59 -0
  213. package/src/shade/device/timing/ShadeGPUContextProfiler.d.ts.map +1 -0
  214. package/src/shade/device/timing/ShadeGPUContextProfiler.js +182 -0
  215. package/src/shade/device/timing/profile/GPUProfileSession.d.ts +4 -4
  216. package/src/shade/device/timing/profile/GPUProfileSession.js +4 -4
  217. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_leaf_triangles.d.ts.map +1 -1
  218. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_leaf_triangles.js +3 -2
  219. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_points.d.ts.map +1 -1
  220. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_points.js +3 -2
  221. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_visibility.d.ts.map +1 -1
  222. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_visibility.js +135 -134
  223. package/src/shade/playground/skinned_blas_refit/verify_leaf_triangles.js +202 -202
  224. package/src/shade/playground/skinned_blas_refit/verify_traversal_reachability.js +249 -249
  225. package/src/shade/renderer/Renderer.d.ts +0 -6
  226. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  227. package/src/shade/renderer/Renderer.js +0 -29
  228. package/src/shade/renderer/STATIC_GRAPHICS_ENGINE_ASSETS.js +1 -1
  229. package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
  230. package/src/shade/renderer/animation/GPUAnimationManager.js +1 -3
  231. package/src/shade/renderer/animation/pose/PosePlayback.d.ts +2 -1
  232. package/src/shade/renderer/animation/pose/PosePlayback.d.ts.map +1 -1
  233. package/src/shade/renderer/animation/pose/PosePlayback.js +2 -1
  234. package/src/shade/renderer/animation/shader_animation_apply.d.ts.map +1 -1
  235. package/src/shade/renderer/animation/shader_animation_apply.js +128 -129
  236. package/src/shade/renderer/animation/shader_animation_pose_resolve.d.ts.map +1 -1
  237. package/src/shade/renderer/animation/shader_animation_pose_resolve.js +176 -177
  238. package/src/shade/renderer/animation/shader_animation_tick.d.ts.map +1 -1
  239. package/src/shade/renderer/animation/shader_animation_tick.js +4 -2
  240. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
  241. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +8 -18
  242. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_geometry_sphere_derive.d.ts.map +1 -1
  243. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_geometry_sphere_derive.js +3 -2
  244. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_reduce.d.ts.map +1 -1
  245. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_reduce.js +4 -2
  246. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_scatter.d.ts +1 -1
  247. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_scatter.d.ts.map +1 -1
  248. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_scatter.js +24 -10
  249. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_skinned_mesh_bounds_refresh.d.ts.map +1 -1
  250. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_skinned_mesh_bounds_refresh.js +3 -2
  251. package/src/shade/renderer/animation/skinning/shader_meshlet_apply_skinning.d.ts.map +1 -1
  252. package/src/shade/renderer/animation/skinning/shader_meshlet_apply_skinning.js +5 -2
  253. package/src/shade/renderer/animation/skinning/shader_skin_matrix_prep.d.ts.map +1 -1
  254. package/src/shade/renderer/animation/skinning/shader_skin_matrix_prep.js +104 -105
  255. package/src/shade/renderer/atmosphere/shader_multiscatter_lut.d.ts.map +1 -1
  256. package/src/shade/renderer/atmosphere/shader_multiscatter_lut.js +0 -1
  257. package/src/shade/renderer/atmosphere/shader_transmittance_lut.js +3 -3
  258. package/src/shade/renderer/buffer/graph_inspect_gpu_buffer.js +136 -136
  259. package/src/shade/renderer/buffer/table/GPUDatabase.d.ts.map +1 -1
  260. package/src/shade/renderer/buffer/table/GPUDatabase.js +16 -22
  261. package/src/shade/renderer/buffer/table/gpu_table_element_upload_shader.d.ts.map +1 -1
  262. package/src/shade/renderer/buffer/table/gpu_table_element_upload_shader.js +7 -2
  263. package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.d.ts.map +1 -1
  264. package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.js +11 -5
  265. package/src/shade/renderer/buffer/util/shader_buffer_copy_storage_to_storage.d.ts.map +1 -1
  266. package/src/shade/renderer/buffer/util/shader_buffer_copy_storage_to_storage.js +43 -42
  267. package/src/shade/renderer/buffer/util/shader_buffer_intra_copy_regions.d.ts.map +1 -1
  268. package/src/shade/renderer/buffer/util/shader_buffer_intra_copy_regions.js +83 -84
  269. package/src/shade/renderer/deferred/shader_tonemap_HDR.d.ts.map +1 -1
  270. package/src/shade/renderer/deferred/shader_tonemap_HDR.js +4 -1
  271. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.d.ts +2 -2
  272. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.d.ts.map +1 -1
  273. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.js +167 -167
  274. package/src/shade/renderer/dynamic/shader_dynamic_mesh.d.ts.map +1 -1
  275. package/src/shade/renderer/dynamic/shader_dynamic_mesh.js +177 -170
  276. package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +918 -918
  277. package/src/shade/renderer/fow/GPUFogOfWarRenderer.js +3 -3
  278. package/src/shade/renderer/fow/shader_fog_of_war.d.ts.map +1 -1
  279. package/src/shade/renderer/fow/shader_fog_of_war.js +3 -1
  280. package/src/shade/renderer/geometry/bvh/record_blas_refit.js +102 -102
  281. package/src/shade/renderer/geometry/bvh/shader_blas_refit_leaf_bounds.d.ts.map +1 -1
  282. package/src/shade/renderer/geometry/bvh/shader_blas_refit_leaf_bounds.js +5 -2
  283. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts.map +1 -1
  284. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.js +3 -11
  285. package/src/shade/renderer/geometry/meshlet/shader_meshlet_metadata_address_patch.d.ts +1 -1
  286. package/src/shade/renderer/geometry/meshlet/shader_meshlet_metadata_address_patch.d.ts.map +1 -1
  287. package/src/shade/renderer/geometry/meshlet/shader_meshlet_metadata_address_patch.js +6 -4
  288. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
  289. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +5 -10
  290. package/src/shade/renderer/geometry/sdf/shader_build_sdf.js +129 -129
  291. package/src/shade/renderer/geometry/sdf/shader_sdf_visualize.d.ts.map +1 -1
  292. package/src/shade/renderer/geometry/sdf/shader_sdf_visualize.js +5 -3
  293. package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_probes.d.ts.map +1 -1
  294. package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_probes.js +4 -1
  295. package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_resolve_probes.d.ts.map +1 -1
  296. package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_resolve_probes.js +3 -1
  297. package/src/shade/renderer/global_illumination/clipmap/shader_update_clipmap_cascade.d.ts.map +1 -1
  298. package/src/shade/renderer/global_illumination/clipmap/shader_update_clipmap_cascade.js +114 -112
  299. package/src/shade/renderer/global_illumination/lpv/placement/graph_generate_probe_locations.js +367 -367
  300. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lpv_store_sh.d.ts.map +1 -1
  301. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lpv_store_sh.js +4 -1
  302. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lvp_atlas_to_sh.d.ts.map +1 -1
  303. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lvp_atlas_to_sh.js +9 -6
  304. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_reduce_atlas_to_sh.d.ts.map +1 -1
  305. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_reduce_atlas_to_sh.js +4 -1
  306. package/src/shade/renderer/global_illumination/sharc/SpatialHashRadianceCache.d.ts.map +1 -1
  307. package/src/shade/renderer/global_illumination/sharc/SpatialHashRadianceCache.js +6 -8
  308. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_evict.d.ts.map +1 -1
  309. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_evict.js +3 -1
  310. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_update.d.ts.map +1 -1
  311. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_update.js +3 -1
  312. package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +1115 -1115
  313. package/src/shade/renderer/gpu_primitive/bvh/PHASE1_HANDOVER.md +3 -3
  314. package/src/shade/renderer/gpu_primitive/bvh/graph_bvh_build_lbvh.js +10 -10
  315. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.d.ts.map +1 -1
  316. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.js +4 -2
  317. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.d.ts.map +1 -1
  318. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.js +87 -83
  319. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_refit.d.ts.map +1 -1
  320. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_refit.js +4 -2
  321. package/src/shade/renderer/gpu_primitive/bvh/verify_gpu_bvh_build.d.ts +2 -2
  322. package/src/shade/renderer/gpu_primitive/bvh/verify_gpu_bvh_build.d.ts.map +1 -1
  323. package/src/shade/renderer/gpu_primitive/bvh/verify_gpu_bvh_build.js +43 -8
  324. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts.map +1 -1
  325. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.js +4 -5
  326. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.d.ts.map +1 -1
  327. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.js +88 -85
  328. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.d.ts.map +1 -1
  329. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.js +194 -192
  330. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
  331. package/src/shade/renderer/hiz/HierarchicalZBuffer.js +33 -69
  332. package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts.map +1 -1
  333. package/src/shade/renderer/hiz/shader_hzb_reduce_any.js +6 -1
  334. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts.map +1 -1
  335. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.js +23 -7
  336. package/src/shade/renderer/light/cluster/cull/graph_cull_lights.d.ts.map +1 -1
  337. package/src/shade/renderer/light/cluster/cull/graph_cull_lights.js +191 -198
  338. package/src/shade/renderer/light/cluster/cull/shader_cull_lights_frustum.d.ts +0 -6
  339. package/src/shade/renderer/light/cluster/cull/shader_cull_lights_frustum.d.ts.map +1 -1
  340. package/src/shade/renderer/light/cluster/cull/shader_cull_lights_frustum.js +120 -120
  341. package/src/shade/renderer/light/cluster/cull/shader_cull_lights_hzb.d.ts +0 -4
  342. package/src/shade/renderer/light/cluster/cull/shader_cull_lights_hzb.d.ts.map +1 -1
  343. package/src/shade/renderer/light/cluster/cull/shader_cull_lights_hzb.js +112 -112
  344. package/src/shade/renderer/light/cluster/graph_assign_clsuters.d.ts.map +1 -1
  345. package/src/shade/renderer/light/cluster/graph_assign_clsuters.js +4 -7
  346. package/src/shade/renderer/light/cluster/shader_cluster_assign_lights.d.ts +0 -6
  347. package/src/shade/renderer/light/cluster/shader_cluster_assign_lights.d.ts.map +1 -1
  348. package/src/shade/renderer/light/cluster/shader_cluster_assign_lights.js +1 -1
  349. package/src/shade/renderer/light/environment/execute_filter_environment_map.d.ts.map +1 -1
  350. package/src/shade/renderer/light/environment/execute_filter_environment_map.js +1 -2
  351. package/src/shade/renderer/light/environment/shader_convolve_reflection_map.d.ts.map +1 -1
  352. package/src/shade/renderer/light/environment/shader_convolve_reflection_map.js +6 -1
  353. package/src/shade/renderer/lightmap/bake/raster/graph_draw_lightmap_viz_buffer.d.ts.map +1 -1
  354. package/src/shade/renderer/lightmap/bake/raster/graph_draw_lightmap_viz_buffer.js +234 -219
  355. package/src/shade/renderer/lightmap/bake/raster/shader_lightmap_to_viz_buffer.js +222 -222
  356. package/src/shade/renderer/lightmap/bake/shader_lightmap_denoise_sh.js +191 -191
  357. package/src/shade/renderer/lightmap/bake/tile/shader_lightmap_accummulate_tile.d.ts.map +1 -1
  358. package/src/shade/renderer/lightmap/bake/tile/shader_lightmap_accummulate_tile.js +85 -82
  359. package/src/shade/renderer/lightmap/bake/tile/shader_lightmap_tile_composit.js +81 -81
  360. package/src/shade/renderer/material/GPUMaterialContext.js +380 -380
  361. package/src/shade/renderer/material/standard/fragment_gbuffer_vt.js +169 -169
  362. package/src/shade/renderer/object_property/shader_object_property_process.d.ts.map +1 -1
  363. package/src/shade/renderer/object_property/shader_object_property_process.js +83 -84
  364. package/src/shade/renderer/object_property/shader_refresh_all_mesh_bounds.d.ts.map +1 -1
  365. package/src/shade/renderer/object_property/shader_refresh_all_mesh_bounds.js +57 -58
  366. package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
  367. package/src/shade/renderer/particles/graph_particles.js +5 -3
  368. package/src/shade/renderer/particles/prototypeParticleSystem.js +5 -7
  369. package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
  370. package/src/shade/renderer/particles/shaders/shader_particle_emit.js +27 -13
  371. package/src/shade/renderer/particles/shaders/shader_particle_finalize.d.ts.map +1 -1
  372. package/src/shade/renderer/particles/shaders/shader_particle_finalize.js +4 -4
  373. package/src/shade/renderer/particles/shaders/shader_particle_render.d.ts.map +1 -1
  374. package/src/shade/renderer/particles/shaders/shader_particle_render.js +190 -183
  375. package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
  376. package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +18 -7
  377. package/src/shade/renderer/particles/sort/shader_particle_sort.d.ts.map +1 -1
  378. package/src/shade/renderer/particles/sort/shader_particle_sort.js +47 -21
  379. package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.d.ts.map +1 -1
  380. package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.js +7 -10
  381. package/src/shade/renderer/path_tracer/accumulating/shader_accumulating_path_tracer.d.ts.map +1 -1
  382. package/src/shade/renderer/path_tracer/accumulating/shader_accumulating_path_tracer.js +4 -1
  383. package/src/shade/renderer/path_tracer/graph_path_trace_scene.js +184 -184
  384. package/src/shade/renderer/postprocess/bloom/shader_bloom_mix.d.ts.map +1 -1
  385. package/src/shade/renderer/postprocess/bloom/shader_bloom_mix.js +3 -1
  386. package/src/shade/renderer/postprocess/cas/shader_ffx_rcas.d.ts.map +1 -1
  387. package/src/shade/renderer/postprocess/cas/shader_ffx_rcas.js +4 -2
  388. package/src/shade/renderer/postprocess/denoise/fragment_shader_denoise_ao.js +147 -147
  389. package/src/shade/renderer/postprocess/denoise/graph_atorus_denoise_luma.d.ts.map +1 -1
  390. package/src/shade/renderer/postprocess/denoise/graph_atorus_denoise_luma.js +19 -17
  391. package/src/shade/renderer/postprocess/dof/gather/graph_postprocess_dof2.d.ts.map +1 -1
  392. package/src/shade/renderer/postprocess/dof/gather/graph_postprocess_dof2.js +1 -2
  393. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_far.d.ts.map +1 -1
  394. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_far.js +4 -1
  395. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_near.d.ts.map +1 -1
  396. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_near.js +4 -1
  397. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_recombine.d.ts.map +1 -1
  398. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_recombine.js +4 -1
  399. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_setup.d.ts.map +1 -1
  400. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_setup.js +4 -1
  401. package/src/shade/renderer/postprocess/dof/raymarch/graph_postprocess_dof.d.ts.map +1 -1
  402. package/src/shade/renderer/postprocess/dof/raymarch/graph_postprocess_dof.js +5 -8
  403. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_composite.d.ts.map +1 -1
  404. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_composite.js +4 -1
  405. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_prefilter.d.ts.map +1 -1
  406. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_prefilter.js +4 -1
  407. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch.d.ts.map +1 -1
  408. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch.js +4 -1
  409. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.d.ts.map +1 -1
  410. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.js +4 -2
  411. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.d.ts.map +1 -1
  412. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.js +4 -2
  413. package/src/shade/renderer/postprocess/dof/shader_dof_autofocus.d.ts.map +1 -1
  414. package/src/shade/renderer/postprocess/dof/shader_dof_autofocus.js +4 -1
  415. package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts.map +1 -1
  416. package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.js +8 -11
  417. package/src/shade/renderer/postprocess/eye/shader_autoexposure_adapt.d.ts.map +1 -1
  418. package/src/shade/renderer/postprocess/eye/shader_autoexposure_adapt.js +5 -1
  419. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.d.ts.map +1 -1
  420. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.js +11 -8
  421. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.d.ts.map +1 -1
  422. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.js +7 -8
  423. package/src/shade/renderer/postprocess/motion_blur/shader_motion_blur_reconstruct.d.ts.map +1 -1
  424. package/src/shade/renderer/postprocess/motion_blur/shader_motion_blur_reconstruct.js +3 -1
  425. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  426. package/src/shade/renderer/postprocess/nss/shader_nss_concat.d.ts.map +1 -1
  427. package/src/shade/renderer/postprocess/nss/shader_nss_concat.js +3 -2
  428. package/src/shade/renderer/postprocess/nss/shader_nss_conv_layer.d.ts.map +1 -1
  429. package/src/shade/renderer/postprocess/nss/shader_nss_conv_layer.js +225 -226
  430. package/src/shade/renderer/postprocess/nss/shader_nss_extract_feedback.d.ts.map +1 -1
  431. package/src/shade/renderer/postprocess/nss/shader_nss_extract_feedback.js +49 -50
  432. package/src/shade/renderer/postprocess/nss/shader_nss_postprocess.d.ts.map +1 -1
  433. package/src/shade/renderer/postprocess/nss/shader_nss_postprocess.js +291 -292
  434. package/src/shade/renderer/postprocess/nss/shader_nss_preprocess.d.ts.map +1 -1
  435. package/src/shade/renderer/postprocess/nss/shader_nss_preprocess.js +230 -231
  436. package/src/shade/renderer/postprocess/ssr/depth_max_shader.d.ts.map +1 -1
  437. package/src/shade/renderer/postprocess/ssr/depth_max_shader.js +70 -68
  438. package/src/shade/renderer/postprocess/ssr/reproject/shader_ffx_denoiser_reflections_reproject.d.ts +16 -2
  439. package/src/shade/renderer/postprocess/ssr/reproject/shader_ffx_denoiser_reflections_reproject.d.ts.map +1 -1
  440. package/src/shade/renderer/postprocess/ssr/reproject/shader_ffx_denoiser_reflections_reproject.js +12 -12
  441. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_IBL.d.ts.map +1 -1
  442. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_IBL.js +3 -1
  443. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_LPV.d.ts.map +1 -1
  444. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_LPV.js +4 -1
  445. package/src/shade/renderer/postprocess/ssr/shader_downsample_encoded_normal.d.ts.map +1 -1
  446. package/src/shade/renderer/postprocess/ssr/shader_downsample_encoded_normal.js +103 -101
  447. package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.d.ts.map +1 -1
  448. package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.js +4 -2
  449. package/src/shade/renderer/postprocess/ssr/ssr_trace_shader.d.ts.map +1 -1
  450. package/src/shade/renderer/postprocess/ssr/ssr_trace_shader.js +3 -1
  451. package/src/shade/renderer/postprocess/taa/shader_taa.d.ts.map +1 -1
  452. package/src/shade/renderer/postprocess/taa/shader_taa.js +4 -1
  453. package/src/shade/renderer/postprocess/upscale-dither/fragment_shader_upscale_dither.js +5 -5
  454. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
  455. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +339 -341
  456. package/src/shade/renderer/rasterize/bucket/shader_count_meshlets_by_material.d.ts.map +1 -1
  457. package/src/shade/renderer/rasterize/bucket/shader_count_meshlets_by_material.js +68 -69
  458. package/src/shade/renderer/rasterize/bucket/shader_make_meshlet_indirect_draw_commands_by_material.d.ts.map +1 -1
  459. package/src/shade/renderer/rasterize/bucket/shader_make_meshlet_indirect_draw_commands_by_material.js +59 -60
  460. package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.d.ts.map +1 -1
  461. package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.js +0 -1
  462. package/src/shade/renderer/rasterize/bucket/shader_sort_meshlets_by_material.d.ts.map +1 -1
  463. package/src/shade/renderer/rasterize/bucket/shader_sort_meshlets_by_material.js +64 -65
  464. package/src/shade/renderer/rasterize/compute/graph_mesh_frustum_cull.d.ts.map +1 -1
  465. package/src/shade/renderer/rasterize/compute/graph_mesh_frustum_cull.js +168 -169
  466. package/src/shade/renderer/rasterize/compute/graph_mesh_sphere_cull.d.ts.map +1 -1
  467. package/src/shade/renderer/rasterize/compute/graph_mesh_sphere_cull.js +160 -161
  468. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.d.ts.map +1 -1
  469. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.js +6 -2
  470. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.d.ts.map +1 -1
  471. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.js +4 -2
  472. package/src/shade/renderer/rasterize/expand/bucket/mesh/shader_instances_classify_bucket.d.ts.map +1 -1
  473. package/src/shade/renderer/rasterize/expand/bucket/mesh/shader_instances_classify_bucket.js +139 -140
  474. package/src/shade/renderer/rasterize/expand/bucket/mesh/shader_instances_count_by_rasterization_bucket.d.ts.map +1 -1
  475. package/src/shade/renderer/rasterize/expand/bucket/mesh/shader_instances_count_by_rasterization_bucket.js +91 -92
  476. package/src/shade/renderer/rasterize/expand/bucket/mesh/shader_instances_rasterization_bucket_sort.d.ts.map +1 -1
  477. package/src/shade/renderer/rasterize/expand/bucket/mesh/shader_instances_rasterization_bucket_sort.js +88 -89
  478. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_count_by_rasterization_bucket.d.ts.map +1 -1
  479. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_count_by_rasterization_bucket.js +90 -91
  480. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.d.ts.map +1 -1
  481. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.js +5 -2
  482. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_rasterization_bucket_sort.d.ts.map +1 -1
  483. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_rasterization_bucket_sort.js +89 -90
  484. package/src/shade/renderer/rasterize/expand/graph_mesh_filter_one_way.d.ts.map +1 -1
  485. package/src/shade/renderer/rasterize/expand/graph_mesh_filter_one_way.js +169 -170
  486. package/src/shade/renderer/rasterize/expand/mesh/shader_mesh_expand_to_meshlets_prefix.d.ts.map +1 -1
  487. package/src/shade/renderer/rasterize/expand/mesh/shader_mesh_expand_to_meshlets_prefix.js +89 -90
  488. package/src/shade/renderer/rasterize/expand/mesh/shader_meshes_to_meshlet_counts.d.ts.map +1 -1
  489. package/src/shade/renderer/rasterize/expand/mesh/shader_meshes_to_meshlet_counts.js +61 -62
  490. package/src/shade/renderer/rasterize/expand/pass1/filter_meshlets.2-way.compute.d.ts.map +1 -1
  491. package/src/shade/renderer/rasterize/expand/pass1/filter_meshlets.2-way.compute.js +153 -154
  492. package/src/shade/renderer/rasterize/native/depth/shadow_rasterization_alpha_tested_pass_descriptor.js +144 -144
  493. package/src/shade/renderer/rasterize/native/depth/shadow_rasterization_pass_descriptor.js +88 -88
  494. package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.js +722 -722
  495. package/src/shade/renderer/rasterize/native/oit/shader_oit_generate_moments.js +217 -217
  496. package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments.js +179 -179
  497. package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments_ibl.js +178 -178
  498. package/src/shade/renderer/rasterize/native/viz/viz_rasterization_alpha_tested_pass_descriptor.js +194 -194
  499. package/src/shade/renderer/rasterize/native/viz/viz_rasterization_opaque_pass_descriptor.js +76 -76
  500. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
  501. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +1 -9
  502. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
  503. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +1 -6
  504. package/src/shade/renderer/restir/di/graph_restir_di.d.ts.map +1 -1
  505. package/src/shade/renderer/restir/di/graph_restir_di.js +2 -3
  506. package/src/shade/renderer/restir/di/graph_restir_di_denoise.d.ts.map +1 -1
  507. package/src/shade/renderer/restir/di/graph_restir_di_denoise.js +1 -2
  508. package/src/shade/renderer/restir/di/shader_restir_di_denoise.d.ts.map +1 -1
  509. package/src/shade/renderer/restir/di/shader_restir_di_denoise.js +5 -3
  510. package/src/shade/renderer/restir/di/shader_restir_di_resample.d.ts.map +1 -1
  511. package/src/shade/renderer/restir/di/shader_restir_di_resample.js +4 -3
  512. package/src/shade/renderer/restir/di/shader_restir_di_resolve.d.ts.map +1 -1
  513. package/src/shade/renderer/restir/di/shader_restir_di_resolve.js +4 -3
  514. package/src/shade/renderer/restir/di/shader_restir_di_spatial.d.ts.map +1 -1
  515. package/src/shade/renderer/restir/di/shader_restir_di_spatial.js +116 -117
  516. package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.d.ts.map +1 -1
  517. package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.js +3 -7
  518. package/src/shade/renderer/scene/hierarchy/graph_scene_update_transform_hierarchy_naive.js +123 -123
  519. package/src/shade/renderer/scene/hierarchy/shader_nodes_record_input_positions.d.ts.map +1 -1
  520. package/src/shade/renderer/scene/hierarchy/shader_nodes_record_input_positions.js +64 -65
  521. package/src/shade/renderer/scene/hierarchy/shader_nodes_update_transform_hierarchy.d.ts.map +1 -1
  522. package/src/shade/renderer/scene/hierarchy/shader_nodes_update_transform_hierarchy.js +372 -373
  523. package/src/shade/renderer/scene/hierarchy/shader_nodes_update_transform_hierarchy_naive.d.ts.map +1 -1
  524. package/src/shade/renderer/scene/hierarchy/shader_nodes_update_transform_hierarchy_naive.js +111 -112
  525. package/src/shade/renderer/scene/shader_bvh_extract_instance_leaves.d.ts.map +1 -1
  526. package/src/shade/renderer/scene/shader_bvh_extract_instance_leaves.js +147 -145
  527. package/src/shade/renderer/shader/ComputeShader.d.ts +26 -5
  528. package/src/shade/renderer/shader/ComputeShader.d.ts.map +1 -1
  529. package/src/shade/renderer/shader/ComputeShader.js +347 -296
  530. package/src/shade/renderer/shader/ImageShader.js +217 -217
  531. package/src/shade/renderer/shader/ShaderDescriptor.d.ts +5 -0
  532. package/src/shade/renderer/shader/ShaderDescriptor.d.ts.map +1 -1
  533. package/src/shade/renderer/shader/ShaderDescriptor.js +20 -0
  534. package/src/shade/renderer/shader/pass/RenderPassDescriptor.d.ts +2 -2
  535. package/src/shade/renderer/shader/pass/RenderPassDescriptor.d.ts.map +1 -1
  536. package/src/shade/renderer/shader/pass/RenderPassDescriptor.js +189 -189
  537. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts.map +1 -1
  538. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.js +3 -1
  539. package/src/shade/renderer/shader/util/compute_infer_workgroup_size_from_source.d.ts +47 -0
  540. package/src/shade/renderer/shader/util/compute_infer_workgroup_size_from_source.d.ts.map +1 -0
  541. package/src/shade/renderer/shader/util/compute_infer_workgroup_size_from_source.js +448 -0
  542. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts.map +1 -1
  543. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +14 -18
  544. package/src/shade/renderer/shadow/map/csm/graph_csm_setup_cascades.js +3 -3
  545. package/src/shade/renderer/shadow/map/shader/shader_shadowmap_remap_cube_to_octahedral.d.ts.map +1 -1
  546. package/src/shade/renderer/shadow/map/shader/shader_shadowmap_remap_cube_to_octahedral.js +5 -1
  547. package/src/shade/renderer/shadow/ray/shader_shadow_upscale.d.ts.map +1 -1
  548. package/src/shade/renderer/shadow/ray/shader_shadow_upscale.js +3 -1
  549. package/src/shade/renderer/shadow/ray/staged/gen/graph_gen_rays.js +73 -73
  550. package/src/shade/renderer/shadow/ray/staged/gen/shader_generate_rays.d.ts.map +1 -1
  551. package/src/shade/renderer/shadow/ray/staged/gen/shader_generate_rays.js +151 -148
  552. package/src/shade/renderer/shadow/ray/staged/trace/graph_trace_rays.d.ts.map +1 -1
  553. package/src/shade/renderer/shadow/ray/staged/trace/graph_trace_rays.js +6 -4
  554. package/src/shade/renderer/shadow/ray/staged/trace/shader_trace_rays.d.ts.map +1 -1
  555. package/src/shade/renderer/shadow/ray/staged/trace/shader_trace_rays.js +18 -4
  556. package/src/shade/renderer/shadow/sdf/cascade/CascadedSceneSDF.d.ts.map +1 -1
  557. package/src/shade/renderer/shadow/sdf/cascade/CascadedSceneSDF.js +11 -12
  558. package/src/shade/renderer/shadow/sdf/cascade/shader_build_scene_sdf_f32.d.ts.map +1 -1
  559. package/src/shade/renderer/shadow/sdf/cascade/shader_build_scene_sdf_f32.js +6 -2
  560. package/src/shade/renderer/shadow/sdf/cascade/shader_scene_sdf_debug_viz.d.ts.map +1 -1
  561. package/src/shade/renderer/shadow/sdf/cascade/shader_scene_sdf_debug_viz.js +129 -127
  562. package/src/shade/renderer/shadow/sdf/graph_draw_sdf_shadows.d.ts.map +1 -1
  563. package/src/shade/renderer/shadow/sdf/graph_draw_sdf_shadows.js +5 -3
  564. package/src/shade/renderer/texture/virtual/VirtualTextureManager.d.ts.map +1 -1
  565. package/src/shade/renderer/texture/virtual/VirtualTextureManager.js +2 -5
  566. package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.d.ts.map +1 -1
  567. package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.js +3 -2
  568. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.js +1 -1
  569. package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts.map +1 -1
  570. package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +14 -19
  571. package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.d.ts +3 -2
  572. package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.d.ts.map +1 -1
  573. package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.js +3 -2
  574. package/src/shade/renderer/volumetrics/taa/shader_volumetrics_taa.d.ts +0 -2
  575. package/src/shade/renderer/volumetrics/taa/shader_volumetrics_taa.d.ts.map +1 -1
  576. package/src/shade/renderer/volumetrics/taa/shader_volumetrics_taa.js +17 -6
  577. package/src/shade/renderer/water/shader_water.js +246 -246
  578. package/src/shade/vitest.setup.mjs +1 -1
  579. package/src/shade/wgsl/emulator/ComputeShaderEmulator.js +291 -291
  580. package/src/shade/wgsl/validate_wgsl_source.d.ts.map +1 -1
  581. package/src/shade/wgsl/validate_wgsl_source.js +8 -3
  582. package/src/view/minimap/Minimap.d.ts +2 -2
  583. package/src/view/minimap/Minimap.d.ts.map +1 -1
  584. package/src/view/minimap/Minimap.js +225 -225
  585. package/src/view/minimap/dom/MinimapCameraView.d.ts +3 -3
  586. package/src/view/minimap/dom/MinimapCameraView.d.ts.map +1 -1
  587. package/src/view/minimap/dom/MinimapCameraView.js +206 -206
  588. package/src/shade/device/timing/profile/make_profiling_pass_encoder.d.ts +0 -21
  589. package/src/shade/device/timing/profile/make_profiling_pass_encoder.d.ts.map +0 -1
  590. package/src/shade/device/timing/profile/make_profiling_pass_encoder.js +0 -114
  591. package/src/shade/device/timing/profile/parse_workgroup_size.d.ts +0 -20
  592. package/src/shade/device/timing/profile/parse_workgroup_size.d.ts.map +0 -1
  593. package/src/shade/device/timing/profile/parse_workgroup_size.js +0 -43
  594. package/src/shade/renderer/shadow/map/csm/shader/shader_setup_cascades.d.ts +0 -3
  595. package/src/shade/renderer/shadow/map/csm/shader/shader_setup_cascades.d.ts.map +0 -1
  596. package/src/shade/renderer/shadow/map/csm/shader/shader_setup_cascades.js +0 -20
@@ -1,995 +1,802 @@
1
- import { assert } from "../../core/assert.js";
2
- import { BinaryBuffer } from "../../core/binary/BinaryBuffer.js";
3
- import { platform_compute_endianness } from "../../core/binary/platform_compute_endianness.js";
4
- import { array_push_if_unique } from "../../core/collection/array/array_push_if_unique.js";
5
- import { array_remove_first } from "../../core/collection/array/array_remove_first.js";
6
- import { array_buffer_copy } from "../../core/collection/array/typed/array_buffer_copy.js";
7
- import Signal from "../../core/events/signal/Signal.js";
8
- import { noop } from "../../core/function/noop.js";
9
- import { GPUTimerArray } from "./timing/GPUTimerArray.js";
10
- import { make_profiling_pass_encoder } from "./timing/profile/make_profiling_pass_encoder.js";
11
- import { parse_workgroup_size } from "./timing/profile/parse_workgroup_size.js";
12
- import { warn_limited } from "../util/warn_limited.js";
13
- import { write_gpu_typed_buffer } from "../renderer/shader/type/serde/write_gpu_typed_buffer.js";
14
- import { BufferResourceDescriptor } from "./graph/BufferResourceDescriptor.js";
15
- import { GraphicsExecutionContext } from "./graph/GraphicsExecutionContext.js";
16
-
17
- /**
18
- * Keep track of how many contexts are currently open (unfinished)
19
- * Important because contexts can have transient resources allocated, and those are not cleaned up until the context is `finished`
20
- * @type {number}
21
- */
22
- let debug_open_context_count = 0;
23
-
24
- /**
25
- *
26
- * @type {ShadeGPUCommandContext[]}
27
- */
28
- const debug_open_contexts = [];
29
-
30
- const scratch_buffer_descriptor = new BufferResourceDescriptor();
31
-
32
- let id_counter = 0;
33
-
34
- /**
35
- * Abstraction on top of {@link GPUCommandEncoder}.
36
- *
37
- * Inspired by Intel's "MiniEngine" CommandContext
38
- * @see https://github.com/GameTechDev/TAA/blob/39786709cf70a1e0906196c600f6079571a33ceb/MiniEngine/Core/CommandContext.h
39
- * @see https://www.w3.org/TR/webgpu/#gpucommandencoder
40
- */
41
- export class ShadeGPUCommandContext {
42
-
43
- #id = id_counter++;
44
-
45
- /**
46
- * Unique identifier for this context, useful for debugging
47
- *
48
- * @return {number}
49
- */
50
- get id() {
51
- return this.#id;
52
- }
53
-
54
- /**
55
- *
56
- * @returns {boolean}
57
- */
58
- get isGPUCommandContext() {
59
- return true;
60
- }
61
-
62
-
63
- /**
64
- * Actual underlying encoder
65
- * @type {GPUCommandEncoder}
66
- */
67
- #gpu_encoder
68
-
69
- /**
70
- * Don't circumvent {@link ShadeGPUCommandContext} unless you know what you're doing.
71
- * {@link ShadeGPUCommandContext} is a wrapper around {@link GPUCommandEncoder} that provides additional spec-compliance asserts to help find errors sooner.
72
- * @returns {GPUCommandEncoder}
73
- */
74
- get gpu_encoder() {
75
- return this.#gpu_encoder;
76
- }
77
-
78
- /**
79
- * @type {GPUTimerArray|undefined}
80
- */
81
- #debug_timers;
82
-
83
- /**
84
- *
85
- * @type {function}
86
- */
87
- #debug_timers_callback = noop;
88
-
89
- /**
90
- *
91
- * @param {function} debug_timers_callback
92
- */
93
- enable_debug_timers(debug_timers_callback) {
94
- if (this.#debug_timers !== undefined) {
95
- // already enabled
96
- return;
97
- }
98
-
99
- this.#debug_timers = new GPUTimerArray(this.device);
100
- this.#debug_timers_callback = debug_timers_callback;
101
- }
102
-
103
- /**
104
- * The frame recorder collecting this context's spans, or null.
105
- *
106
- * @type {GPUFrameRecorder|null}
107
- */
108
- #profile_recorder = null;
109
-
110
- /**
111
- * Which query set this context is, within its frame. Carried into every span it records —
112
- * timestamps from two query sets are not specified to share a clock domain, and a frame has
113
- * one set per context.
114
- *
115
- * @type {number}
116
- */
117
- #profile_query_set_id = 0;
118
-
119
- /**
120
- * The work record for the pass currently being opened.
121
- *
122
- * Set by {@link #with_timestamp_writes} and consumed immediately by the `begin*Pass` that asked
123
- * for it — the two are one operation, split only because the descriptor has to be built before
124
- * the encoder exists.
125
- *
126
- * @type {GPUProfileWork|null}
127
- */
128
- #pending_work = null;
129
-
130
- /**
131
- * Wrap `encoder` so its dispatches and draws are recorded, when a capture asked for them.
132
- *
133
- * @param {GPUComputePassEncoder|GPURenderPassEncoder} encoder
134
- * @returns {GPUComputePassEncoder|GPURenderPassEncoder}
135
- */
136
- #instrument_pass(encoder) {
137
- const work = this.#pending_work;
138
-
139
- if (work === null) {
140
- this.#last_work = null;
141
-
142
- return encoder;
143
- }
144
-
145
- this.#pending_work = null;
146
- this.#last_work = work;
147
-
148
- return make_profiling_pass_encoder(encoder, work);
149
- }
150
-
151
- /**
152
- * Resolves once this context's timings have reached its recorder.
153
- *
154
- * @type {Promise<void>}
155
- */
156
- #profiling_absorbed = Promise.resolve();
157
-
158
- /**
159
- * @type {function}
160
- */
161
- #profiling_absorbed_resolve = noop;
162
-
163
- /**
164
- * Resolves after this context's timings have been read back and handed to its recorder.
165
- *
166
- * **Not the same moment as {@link done}.** `done` resolves from `onFinished`, which fires
167
- * synchronously at submit — before any timestamp has been read. A caller that closes its frame
168
- * on `done` commits an empty one, every time. Already-resolved when nothing is profiling.
169
- *
170
- * @returns {Promise<void>}
171
- */
172
- get profiling_absorbed() {
173
- return this.#profiling_absorbed;
174
- }
175
-
176
- /**
177
- * Record this context's pass timings into `recorder`.
178
- *
179
- * Independent of {@link enable_debug_timers}, which is the console-shaped one-off; both share
180
- * the underlying {@link GPUTimerArray} and either may enable it.
181
- *
182
- * @param {GPUFrameRecorder} recorder
183
- * @param {number} query_set_id this context's index within the frame
184
- * @returns {void}
185
- */
186
- enable_profiling(recorder, query_set_id) {
187
- assert.defined(recorder, 'recorder');
188
- assert.isNonNegativeInteger(query_set_id, 'query_set_id');
189
- assert.notOk(this.#finished, 'already finished');
190
-
191
- if (this.#debug_timers === undefined) {
192
- this.#debug_timers = new GPUTimerArray(this.device);
193
- }
194
-
195
- this.#profile_recorder = recorder;
196
- this.#profile_query_set_id = query_set_id;
197
-
198
- this.#profiling_absorbed = new Promise(resolve => {
199
- this.#profiling_absorbed_resolve = resolve;
200
- });
201
- }
202
-
203
- /**
204
- * @type {GraphicsContext}
205
- */
206
- #graphics
207
-
208
- /**
209
- *
210
- * @return {GPUDevice}
211
- */
212
- get device() {
213
- return this.#graphics.device;
214
- }
215
-
216
- /**
217
- *
218
- * @return {TextureManager}
219
- */
220
- get textures() {
221
- return this.#graphics.textures;
222
- }
223
-
224
- /**
225
- * These are to be destroyed at the end of the context's lifetime.
226
- * Need to be released at the end of the lifetime.
227
- * @type {GPUBuffer[]}
228
- */
229
- #transient_buffers = [];
230
-
231
- /**
232
- *
233
- * @type {GPUBuffer[]}
234
- */
235
- #staging_buffers = [];
236
-
237
- /**
238
- * Once finished, the encoder becomes inactive, we use this flag to track potential misuse and inform the user
239
- * @type {boolean}
240
- */
241
- #finished = false;
242
-
243
- /**
244
- * @readonly
245
- * @type {Signal<this>}
246
- */
247
- onFinished = new Signal();
248
-
249
- /**
250
- * @readonly
251
- * @type {Signal<this>}
252
- */
253
- onBeforeFinish = new Signal();
254
-
255
- /**
256
- *
257
- * @return {Promise<void>}
258
- */
259
- get done() {
260
- if (this.#finished) {
261
- return Promise.resolve();
262
- }
263
-
264
- return new Promise(resolve => {
265
- this.onFinished.addOne(resolve);
266
-
267
- if (this.#finished) {
268
- // special case, double-checking to avoid race conditions
269
- resolve();
270
- }
271
-
272
- });
273
- }
274
-
275
- /**
276
- * Do not call directly, always use {@link create}
277
- * @private
278
- */
279
- constructor() {
280
- // private, do not call from the outside
281
- }
282
-
283
- /**
284
- *
285
- * @param {GraphicsContext} graphics
286
- * @param {string} [label]
287
- * @returns {ShadeGPUCommandContext}
288
- */
289
- static create(
290
- graphics,
291
- label = ""
292
- ) {
293
-
294
- assert.defined(graphics, 'graphics');
295
- assert.equal(graphics.isGraphicsContext, true, "graphics.isGraphicsContext !== true");
296
-
297
- assert.isString(label, 'label');
298
-
299
- const r = new ShadeGPUCommandContext();
300
-
301
- r.#graphics = graphics;
302
- r.#gpu_encoder = graphics.device.createCommandEncoder({
303
- label
304
- });
305
-
306
- // track how many we have open
307
- debug_open_context_count++;
308
- array_push_if_unique(debug_open_contexts, r);
309
-
310
- if (debug_open_context_count > 1024) {
311
- warn_limited(`Too many open GPU contexts`, 20);
312
- }
313
-
314
- return r;
315
-
316
- }
317
-
318
- /**
319
- *
320
- * @returns {GraphicsExecutionContext}
321
- */
322
- createFrameGraphContext() {
323
- return new GraphicsExecutionContext(this.#graphics, this);
324
- }
325
-
326
- /**
327
- *
328
- * @param {FrameGraph} graph
329
- */
330
- encodeGraph(graph) {
331
- assert.defined(graph, 'graph');
332
- assert.isObject(graph, 'graph');
333
- assert.equal(graph.isFrameGraph, true, "graph.isFrameGraph !== true");
334
-
335
- // TODO check if the graph is empty, if so, we can skip the whole thing
336
-
337
- const ctx = this.createFrameGraphContext();
338
-
339
- graph.compile();
340
- graph.execute(ctx);
341
- }
342
-
343
- /**
344
- * @see https://www.w3.org/TR/webgpu/#dom-gpucommandencoder-clearbuffer
345
- * @param {GPUBuffer} buffer
346
- * @param {number} [offset=0]
347
- * @param {number} [size]
348
- */
349
- clearBuffer(buffer, offset = 0, size) {
350
- assert.defined(buffer, 'buffer');
351
- assert.equal(buffer.usage & GPUBufferUsage.COPY_DST, GPUBufferUsage.COPY_DST, 'buffer must include COPY_DST usage flag');
352
- assert.isNonNegativeInteger(offset, 'offset');
353
- assert.equal(offset % 4, 0, 'offset must be a multiple of 4');
354
-
355
- // console.log(`cmd.clearBuffer(${buffer.label}, ${offset}, ${size})`);
356
-
357
- this.#gpu_encoder.clearBuffer(buffer, offset, size);
358
- }
359
-
360
- /**
361
- * Not supported, only here to offer documentation hint
362
- * see {@link texture_fill_rectangle}
363
- * @throws {Error} Always, documentation hint only
364
- */
365
- clearTexture() {
366
- throw new Error(`Documentation hint only, use texture_fill_rectangle instead`);
367
- }
368
-
369
- /**
370
- * NOTE: only the explicit verbose form of the API is supported, shorthand such as `copyBufferToBuffer(source, destination, size)` are not supported.
371
- * see https://www.w3.org/TR/webgpu/#gpucommandencoder-copybuffertobuffer
372
- * @see GPUCommandEncoder.copyBufferToBuffer
373
- * @param {GPUBuffer} source The GPUBuffer to copy from.
374
- * @param {number} sourceOffset Offset in bytes into the source to begin copying from.
375
- * @param {GPUBuffer} destination The GPUBuffer to copy to.
376
- * @param {number} destinationOffset Offset in bytes into destination to place the copied data.
377
- * @param {number} [size] Bytes to copy. In not specified, defaults to `source.size - sourceOffset`
378
- */
379
- copyBufferToBuffer(
380
- source,
381
- sourceOffset,
382
- destination,
383
- destinationOffset,
384
- size
385
- ) {
386
-
387
- assert.notEqual(source.usage & GPUBufferUsage.COPY_SRC, 0, 'source must include COPY_SRC usage flag');
388
- assert.isNonNegativeInteger(sourceOffset, 'sourceOffset');
389
- assert.equal(sourceOffset % 4, 0, 'sourceOffset must be a multiple of 4');
390
-
391
- assert.notEqual(destination.usage & GPUBufferUsage.COPY_DST, 0, 'destination must include COPY_DST usage flag');
392
- assert.isNonNegativeInteger(destinationOffset, 'destinationOffset');
393
- assert.equal(destinationOffset % 4, 0, 'destinationOffset must be a multiple of 4');
394
-
395
- if (size !== undefined) {
396
- assert.isNonNegativeInteger(size, 'size');
397
- assert.equal(size % 4, 0, 'size must be a multiple of 4');
398
-
399
- assert.greaterThanOrEqual(source.size, sourceOffset + size, 'source underflow');
400
- assert.greaterThanOrEqual(destination.size, destinationOffset + size, 'destination underflow');
401
- }
402
-
403
- assert.notEqual(source, destination, 'source and destination must be different');
404
-
405
- // console.log(`cmd.copyBufferToBuffer("${source.label}", ${sourceOffset}, "${destination.label}", ${destinationOffset}, ${size})`);
406
-
407
- this.#gpu_encoder.copyBufferToBuffer(
408
- source,
409
- sourceOffset,
410
- destination,
411
- destinationOffset,
412
- size
413
- );
414
- }
415
-
416
-
417
- /**
418
- *
419
- * @param {GPUImageCopyTexture} source
420
- * @param {GPUImageCopyTexture} destination
421
- * @param {GPUExtent3DStrict} copySize
422
- */
423
- copyTextureToTexture(source,
424
- destination,
425
- copySize
426
- ) {
427
- this.#gpu_encoder.copyTextureToTexture(source, destination, copySize);
428
- }
429
-
430
- /**
431
- *
432
- * @param {GPUComputePassDescriptor} [descriptor]
433
- * @returns {GPUComputePassEncoder}
434
- */
435
- beginComputePass(descriptor) {
436
- const encoder = this.#gpu_encoder;
437
-
438
- const _descriptor = this.#with_timestamp_writes(descriptor, 'compute');
439
-
440
- // console.log(`cmd.beginComputePass(${descriptor.label})`);
441
-
442
- return this.#instrument_pass(encoder.beginComputePass(_descriptor))
443
- }
444
-
445
- /**
446
- * The descriptor a pass should actually be begun with, once timing has had its say.
447
- *
448
- * Copies rather than writing through. Several call sites hand in a descriptor they reuse across
449
- * passes, and stamping `timestampWrites` onto it left the next pass carrying the previous
450
- * pass's query indices. The copy is one shallow spread per pass and only when timers are on.
451
- *
452
- * Returns the descriptor unchanged when timing is off, when the device withheld the feature, or
453
- * when the timer array has no slot left ({@link GPUTimerArray#dropped_count}). An untimed pass
454
- * is the correct outcome in all three; a pass carrying indices the query set does not have is a
455
- * validation error.
456
- *
457
- * @param {GPUComputePassDescriptor|GPURenderPassDescriptor} [descriptor]
458
- * @param {string} kind one of 'compute', 'render'
459
- * @returns {GPUComputePassDescriptor|GPURenderPassDescriptor}
460
- */
461
- #with_timestamp_writes(descriptor, kind) {
462
- const timers = this.#debug_timers;
463
-
464
- if (timers === undefined) {
465
- return descriptor;
466
- }
467
-
468
- if (!this.#graphics.device.features.has('timestamp-query')) {
469
- return descriptor;
470
- }
471
-
472
- // `beginComputePass()` is legal with no descriptor at all; reading `.label` off nothing is
473
- // not, and used to throw here the moment timers were switched on
474
- const source = descriptor !== undefined ? descriptor : {};
475
-
476
- const writes = kind === 'compute'
477
- ? timers.getComputeWrites(source.label)
478
- : timers.getRenderWrites(source.label);
479
-
480
- if (writes === undefined) {
481
- return descriptor;
482
- }
483
-
484
- const recorder = this.#profile_recorder;
485
-
486
- if (recorder !== null) {
487
- /*
488
- The one moment the join can be made. The recorder knows which frame graph pass is
489
- executing right now; the slot is what the timings will come back keyed by. Neither
490
- fact is recoverable later — see GPUFrameRecorder.
491
- */
492
- this.#pending_work = recorder.note_pass_slot(
493
- this.#profile_query_set_id,
494
- writes.beginningOfPassWriteIndex / 2
495
- );
496
- } else {
497
- this.#pending_work = null;
498
- }
499
-
500
- return {
501
- ...source,
502
- timestampWrites: writes
503
- };
504
- }
505
-
506
- /**
507
- *
508
- * @param {ComputePipelineDescriptor} pipeline
509
- * @param {string} [label]
510
- * @param {GPUBindingResource[][]} [bindings]
511
- * @returns {GPUComputePassEncoder}
512
- */
513
- constructComputePass({
514
- pipeline,
515
- label,
516
- bindings = [],
517
- immediate
518
- }) {
519
-
520
- const pass_descriptor = {
521
- label
522
- };
523
-
524
- if (label === undefined) {
525
- pass_descriptor.label = pipeline.label;
526
- }
527
-
528
- const graphics = this.#graphics;
529
-
530
- const pass = this.beginComputePass(pass_descriptor);
531
-
532
- const gpu_pipeline = graphics.compute_pipelines.obtain(pipeline);
533
-
534
- pass.setPipeline(gpu_pipeline);
535
-
536
- this.#note_pipeline(pipeline, true);
537
-
538
- graphics.setPipelineBindings(pass, pipeline, bindings, immediate);
539
-
540
- // console.warn(`cmd.constructComputePass(${pass_descriptor.label})`)
541
-
542
- return pass;
543
- }
544
-
545
- /**
546
- * Record which pipeline a pass ran, and for a compute pipeline its workgroup size.
547
- *
548
- * Only reachable from `constructComputePass` / `constructRenderPass`, which is the only place a
549
- * *descriptor* is in hand. `setPipeline` receives the compiled `GPUComputePipeline`, and the
550
- * WGSL that carries `@workgroup_size` is not on it — so a pass begun the long way records its
551
- * counts but not what ran them, which the model represents as an unknown rather than a zero.
552
- *
553
- * @param {ComputePipelineDescriptor|RenderPipelineDescriptor} pipeline
554
- * @param {boolean} is_compute
555
- * @returns {void}
556
- */
557
- #note_pipeline(pipeline, is_compute) {
558
- const work = this.#last_work;
559
-
560
- if (work === null) {
561
- return;
562
- }
563
-
564
- work.pipeline = pipeline.label ?? "";
565
-
566
- if (is_compute) {
567
- work.workgroup_size = parse_workgroup_size(pipeline.compute?.module?.code);
568
- }
569
- }
570
-
571
- /**
572
- * The work record of the most recently opened pass, so `construct*Pass` can annotate it after
573
- * the encoder has been made.
574
- *
575
- * @type {GPUProfileWork|null}
576
- */
577
- #last_work = null;
578
-
579
- /**
580
- * Begins a labeled debug group containing subsequent commands.
581
- * @see https://gpuweb.github.io/gpuweb/#debug-markers
582
- * @param {string} label
583
- */
584
- pushDebugGroup(label) {
585
- assert.isString(label, 'label');
586
- this.#gpu_encoder.pushDebugGroup(label);
587
-
588
- // console.group("cmd/debug_group=" + label)
589
- }
590
-
591
- /**
592
- * Ends the labeled debug group most recently started by pushDebugGroup().
593
- * @see https://gpuweb.github.io/gpuweb/#debug-markers
594
- */
595
- popDebugGroup() {
596
- this.#gpu_encoder.popDebugGroup();
597
-
598
- // console.groupEnd();
599
- }
600
-
601
- /**
602
- * Marks a point in a stream of commands with a label.
603
- * @see https://gpuweb.github.io/gpuweb/#debug-markers
604
- * @param {string} label
605
- */
606
- insertDebugMarker(label) {
607
- assert.isString(label, 'label');
608
- this.#gpu_encoder.insertDebugMarker(label);
609
- }
610
-
611
- /**
612
- *
613
- * @param {string} [label]
614
- * @param {RenderPipelineDescriptor} pipeline
615
- * @param {GPUBindingResource[][]} [bindings]
616
- * @param {GPURenderPassColorAttachment[]} colorAttachments
617
- * @param {GPURenderPassDepthStencilAttachment} [depthStencilAttachment]
618
- * @returns {GPURenderPassEncoder}
619
- */
620
- constructRenderPass({
621
- label,
622
- pipeline,
623
- bindings,
624
- colorAttachments,
625
- depthStencilAttachment,
626
- immediate,
627
- }) {
628
- assert.defined(pipeline, 'pipeline');
629
- assert.equal(pipeline.isRenderPipelineDescriptor, true, "pipeline.isRenderPipelineDescriptor !== true");
630
-
631
- const pass_descriptor = {
632
- label,
633
- colorAttachments,
634
- depthStencilAttachment
635
- };
636
-
637
- if (label === undefined) {
638
- pass_descriptor.label = pipeline.label;
639
- }
640
-
641
- const graphics = this.#graphics;
642
-
643
- // TODO rewrite the pipeline if necessary to achieve compatibility with colorAttachment formats
644
- const gpu_pipeline = graphics.render_pipelines.obtain(pipeline);
645
-
646
- const pass = this.beginRenderPass(pass_descriptor);
647
-
648
- pass.setPipeline(gpu_pipeline);
649
-
650
- this.#note_pipeline(pipeline, false);
651
-
652
- graphics.setPipelineBindings(pass, pipeline, bindings, immediate);
653
-
654
- // console.warn(`cmd.constructRenderPass(${pass_descriptor.label})`)
655
-
656
- return pass;
657
- }
658
-
659
- /**
660
- *
661
- * @param {GPURenderPassDescriptor} descriptor
662
- * @returns {GPURenderPassEncoder}
663
- */
664
- beginRenderPass(descriptor) {
665
-
666
- const _descriptor = this.#with_timestamp_writes(descriptor, 'render');
667
-
668
- // console.log(`cmd.beginRenderPass(${descriptor.label})`);
669
-
670
- return this.#instrument_pass(this.#gpu_encoder.beginRenderPass(_descriptor))
671
- }
672
-
673
- /**
674
- *
675
- * @param {GPUQuerySet} querySet
676
- * @param {number} firstQuery
677
- * @param {number} queryCount
678
- * @param {GPUBuffer} destination
679
- * @param {number} destinationOffset
680
- */
681
- resolveQuerySet(querySet, firstQuery, queryCount, destination, destinationOffset) {
682
- this.#gpu_encoder.resolveQuerySet(querySet, firstQuery, queryCount, destination, destinationOffset);
683
- }
684
-
685
- /**
686
- * Transient buffers are automatically released at the end of the context's lifetime;
687
- * however, we can explicitly release it earlier to allow for reuse.
688
- *
689
- * @param {GPUBuffer} buffer
690
- * @return {boolean} true if buffer was released, false if it was not found
691
- */
692
- releaseTransientBuffer(buffer) {
693
- assert.defined(buffer, 'buffer');
694
-
695
- if (!array_remove_first(this.#transient_buffers, buffer)) {
696
- return false;
697
- }
698
-
699
- const allocator = this.#transient_allocator;
700
-
701
- return allocator.release(buffer);
702
- }
703
-
704
- /**
705
- *
706
- * @return {GPUBufferAllocator}
707
- */
708
- get #transient_allocator() {
709
- return this.#graphics.buffer_allocator_main;
710
- }
711
-
712
- /**
713
- * Allocated buffer will only be valid until the context is finished.
714
- *
715
- * @param {number|GPUBufferUsage} usage
716
- * @param {number} size
717
- * @returns {GPUBuffer} managed buffer
718
- */
719
- allocateTransientBuffer(
720
- usage = GPUBufferUsage.UNIFORM,
721
- size
722
- ) {
723
- assert.isNonNegativeInteger(size, 'size');
724
- assert.isInteger(usage, 'usage');
725
-
726
- assert.notOk(this.#finished, 'already finished');
727
-
728
- scratch_buffer_descriptor.size = size;
729
- // COPY_DST is needed to write the data
730
- scratch_buffer_descriptor.usage = usage | GPUBufferUsage.COPY_DST;
731
-
732
- const allocator = this.#transient_allocator;
733
- const buffer = allocator.get(scratch_buffer_descriptor, this);
734
-
735
- // remember so we can clean up at the end
736
- this.#transient_buffers.push(buffer);
737
-
738
- return buffer;
739
- }
740
-
741
- /**
742
- *
743
- * @param {ArrayBuffer} data CPU-side data to place into the GPU buffer
744
- * @param {number|GPUBufferUsage} [usage=GPUBufferUsage.UNIFORM]
745
- * @param {number} [offset] offset into source data where to start copying from
746
- * @param {number} [size] in bytes
747
- * @returns {GPUBuffer} managed buffer, will be automatically destroyed when context is finished
748
- */
749
- allocateTransientBufferAndLoad(
750
- data,
751
- usage = GPUBufferUsage.UNIFORM,
752
- offset = 0,
753
- size = data.byteLength
754
- ) {
755
- assert.isInstanceOf(data, ArrayBuffer, 'data');
756
- assert.isInteger(usage, 'usage');
757
- assert.isNonNegativeInteger(offset, 'offset');
758
- assert.isNonNegativeInteger(size, 'size');
759
-
760
- assert.notOk(this.#finished, 'already finished');
761
-
762
- const buffer = this.allocateTransientBuffer(
763
- usage,
764
- size
765
- );
766
-
767
- this.writeBuffer(buffer, 0, data, offset, size);
768
-
769
- return buffer;
770
- }
771
-
772
- /**
773
- * Scratch for immediate data, created on first use and reused for the life of the context.
774
- *
775
- * One buffer is enough, and `position` returns to 0 for every write, because `setImmediates`
776
- * copies the bytes it is given at the point of the call — the region is free again the moment
777
- * the pass encoder has taken it. Nothing here ever grows: the default capacity is far above the
778
- * 64-byte ceiling {@link ShaderResourceSetDescriptor#setImmediate} enforces, so the backing
779
- * `ArrayBuffer` is allocated once and never reallocated.
780
- *
781
- * @type {BinaryBuffer|null}
782
- */
783
- #immediate_buffer = null;
784
-
785
- /**
786
- * Serialise a shader's immediate data ready for `setImmediates`, or return undefined when the
787
- * shader declares none.
788
- *
789
- * Allocates nothing after the first call.
790
- *
791
- * @param {ShaderResourceSetDescriptor} resources
792
- * @param {Object} map the shader's binding map
793
- * @returns {{buffer: BinaryBuffer, offset: number, size: number}|undefined}
794
- */
795
- writeImmediate(resources, map) {
796
- if (resources.immediateSize === 0) {
797
- return undefined;
798
- }
799
-
800
- let buffer = this.#immediate_buffer;
801
-
802
- if (buffer === null) {
803
- buffer = new BinaryBuffer();
804
-
805
- // GPU buffer contents must match the host, and BinaryBuffer's own default is
806
- // little-endian regardless of platform. Getting this wrong produces bytes that are
807
- // correct on every machine anyone is likely to test on and wrong on the rest.
808
- buffer.endianness = platform_compute_endianness();
809
-
810
- this.#immediate_buffer = buffer;
811
- }
812
-
813
- buffer.position = 0;
814
-
815
- if (!resources.writeImmediate(map, buffer)) {
816
- return undefined;
817
- }
818
-
819
- return { buffer, offset: 0, size: buffer.position };
820
- }
821
-
822
- /**
823
- * @template T
824
- * @param {WebGPUType} type
825
- * @param {T} value
826
- * @param {number|GPUBufferUsage} [usage]
827
- * @return {GPUBuffer}
828
- */
829
- allocateTransientValueBuffer(
830
- type,
831
- value,
832
- usage
833
- ) {
834
- assert.defined(type, 'type');
835
- assert.notNull(type, 'type');
836
-
837
- const buffer = this.allocateTransientBuffer(usage, type.aligned_size);
838
-
839
- this.writeValueBuffer(buffer, 0, type, value);
840
-
841
- return buffer;
842
- }
843
-
844
- /**
845
- * @template T
846
- * @param {GPUBuffer} buffer
847
- * @param {number} buffer_offset
848
- * @param {WebGPUType} type
849
- * @param {T} value
850
- */
851
- writeValueBuffer(buffer, buffer_offset, type, value) {
852
-
853
- assert.notOk(this.#finished, 'already finished');
854
-
855
- const gfx = this.#graphics;
856
-
857
- const size = type.aligned_size;
858
-
859
- const stage = gfx.buffer_allocator_staging.get(size);
860
-
861
- const mapped = stage.getMappedRange(0, size);
862
-
863
- write_gpu_typed_buffer(value, type, mapped, 0);
864
-
865
- stage.unmap();
866
-
867
- this.#staging_buffers.push(stage);
868
-
869
- this.copyBufferToBuffer(stage, 0, buffer, buffer_offset, size);
870
- }
871
-
872
- /**
873
- * Very similar to {@link GPUQueue.writeBuffer}, but instead of doing the operation direction on the queue - uses a staging buffer under the hood and performs the actual write operation as part of the commmand buffer
874
- * @param {GPUBuffer} buffer
875
- * @param {number} buffer_offset
876
- * @param {ArrayBuffer} data
877
- * @param {number} data_offset
878
- * @param {number} size
879
- */
880
- writeBuffer(buffer, buffer_offset, data, data_offset, size) {
881
- assert.defined(buffer, 'buffer');
882
- assert.isNonNegativeInteger(buffer_offset, 'buffer_offset');
883
- assert.defined(data, 'data');
884
- assert.isNonNegativeInteger(data_offset, 'data_offset');
885
- assert.isNonNegativeInteger(size, 'size');
886
-
887
- const gfx = this.#graphics;
888
-
889
- const stage = gfx.buffer_allocator_staging.get(size);
890
-
891
- const mapped = stage.getMappedRange(0, size);
892
-
893
- array_buffer_copy(data, data_offset, mapped, 0, size);
894
-
895
- stage.unmap();
896
-
897
- this.#staging_buffers.push(stage);
898
-
899
- this.copyBufferToBuffer(stage, 0, buffer, buffer_offset, size);
900
-
901
- }
902
-
903
- #cleanup() {
904
-
905
- // console.warn('cmd.cleanup()');
906
-
907
- const transient_buffers = this.#transient_buffers;
908
- const transient_buffer_count = transient_buffers.length;
909
-
910
- const buffer_allocator_transient = this.#transient_allocator;
911
-
912
- // release in reverse order to make it more likely that we'd end up in the same acquisition order next time, which is desirable for caching
913
- for (let i = transient_buffer_count - 1; i >= 0; i--) {
914
- const buffer = transient_buffers[i];
915
-
916
- buffer_allocator_transient.release(buffer);
917
-
918
- }
919
-
920
- // staging buffers
921
- const buffer_allocator_staging = this.#graphics.buffer_allocator_staging;
922
- for (const staging of this.#staging_buffers) {
923
- buffer_allocator_staging.release(staging);
924
- }
925
- }
926
-
927
- /**
928
- * Performs both {@link GPUCommandEncoder.finish} and flushed command buffer
929
- */
930
- finish() {
931
- if (this.#finished) {
932
- console.warn('Context already finished');
933
- return;
934
- }
935
-
936
- this.onBeforeFinish.send1(this);
937
-
938
- debug_open_context_count--;
939
- array_remove_first(debug_open_contexts, this);
940
-
941
- const encoder = this.#gpu_encoder;
942
-
943
- const debug_timers = this.#debug_timers;
944
- if (debug_timers !== undefined) {
945
- debug_timers.resolve(encoder);
946
- }
947
-
948
- this.#finished = true;
949
-
950
- // release encoder reference
951
- this.#gpu_encoder = undefined;
952
-
953
- const command_buffer = encoder.finish();
954
-
955
- const graphics = this.#graphics;
956
- const queue = graphics.device.queue;
957
-
958
- queue.submit([command_buffer]);
959
-
960
- // cleanup allocated memory
961
- this.#cleanup();
962
-
963
- if (debug_timers !== undefined) {
964
- const recorder = this.#profile_recorder;
965
- const query_set_id = this.#profile_query_set_id;
966
-
967
- debug_timers
968
- .download_results()
969
- .then(() => {
970
- if (recorder !== null) {
971
- recorder.absorb(debug_timers, query_set_id);
972
- }
973
-
974
- // The console-shaped path stays exactly as it was; a context can be doing both.
975
- const table = debug_timers.results_to_console_table();
976
-
977
- this.#debug_timers_callback(table);
978
- })
979
- .finally(() => {
980
- debug_timers.destroy();
981
-
982
- // In `finally` so a failed readback still releases whoever is waiting on the
983
- // frame. A profile session that hangs because one download rejected is worse
984
- // than one missing a frame.
985
- this.#profiling_absorbed_resolve();
986
- });
987
-
988
- this.#debug_timers = undefined;
989
- this.#profile_recorder = null;
990
- }
991
-
992
- this.onFinished.send1(this);
993
-
994
- }
1
+ import { assert } from "../../core/assert.js";
2
+ import { BinaryBuffer } from "../../core/binary/BinaryBuffer.js";
3
+ import { platform_compute_endianness } from "../../core/binary/platform_compute_endianness.js";
4
+ import { array_push_if_unique } from "../../core/collection/array/array_push_if_unique.js";
5
+ import { array_remove_first } from "../../core/collection/array/array_remove_first.js";
6
+ import { array_buffer_copy } from "../../core/collection/array/typed/array_buffer_copy.js";
7
+ import Signal from "../../core/events/signal/Signal.js";
8
+ import { ShadeGPUComputePassEncoder } from "./pass/ShadeGPUComputePassEncoder.js";
9
+ import { ShadeGPURenderPassEncoder } from "./pass/ShadeGPURenderPassEncoder.js";
10
+ import { ShadeGPUContextProfiler } from "./timing/ShadeGPUContextProfiler.js";
11
+ import { warn_limited } from "../util/warn_limited.js";
12
+ import { write_gpu_typed_buffer } from "../renderer/shader/type/serde/write_gpu_typed_buffer.js";
13
+ import { BufferResourceDescriptor } from "./graph/BufferResourceDescriptor.js";
14
+ import { GraphicsExecutionContext } from "./graph/GraphicsExecutionContext.js";
15
+
16
+ /**
17
+ * Keep track of how many contexts are currently open (unfinished)
18
+ * Important because contexts can have transient resources allocated, and those are not cleaned up until the context is `finished`
19
+ * @type {number}
20
+ */
21
+ let debug_open_context_count = 0;
22
+
23
+ /**
24
+ *
25
+ * @type {ShadeGPUCommandContext[]}
26
+ */
27
+ const debug_open_contexts = [];
28
+
29
+ const scratch_buffer_descriptor = new BufferResourceDescriptor();
30
+
31
+ let id_counter = 0;
32
+
33
+ /**
34
+ * Abstraction on top of {@link GPUCommandEncoder}.
35
+ *
36
+ * Inspired by Intel's "MiniEngine" CommandContext
37
+ * @see https://github.com/GameTechDev/TAA/blob/39786709cf70a1e0906196c600f6079571a33ceb/MiniEngine/Core/CommandContext.h
38
+ * @see https://www.w3.org/TR/webgpu/#gpucommandencoder
39
+ */
40
+ export class ShadeGPUCommandContext {
41
+
42
+ #id = id_counter++;
43
+
44
+ /**
45
+ * Unique identifier for this context, useful for debugging
46
+ *
47
+ * @return {number}
48
+ */
49
+ get id() {
50
+ return this.#id;
51
+ }
52
+
53
+ /**
54
+ *
55
+ * @returns {boolean}
56
+ */
57
+ get isGPUCommandContext() {
58
+ return true;
59
+ }
60
+
61
+
62
+ /**
63
+ * Actual underlying encoder
64
+ * @type {GPUCommandEncoder}
65
+ */
66
+ #gpu_encoder
67
+
68
+ /**
69
+ * Don't circumvent {@link ShadeGPUCommandContext} unless you know what you're doing.
70
+ * {@link ShadeGPUCommandContext} is a wrapper around {@link GPUCommandEncoder} that provides additional spec-compliance asserts to help find errors sooner.
71
+ * @returns {GPUCommandEncoder}
72
+ */
73
+ get gpu_encoder() {
74
+ return this.#gpu_encoder;
75
+ }
76
+
77
+ /**
78
+ * This context's profiling attachment, or null when nothing is profiling — which is the
79
+ * ordinary case and costs one null check per pass.
80
+ *
81
+ * **Never cleared.** `finish()` is followed by a read of {@link profiling_absorbed}, and a null
82
+ * here reports an already-resolved promise, which closes the frame before a single timestamp has
83
+ * come back. It holds no GPU resources after `absorb()` destroys the timer array, so keeping the
84
+ * reference costs nothing.
85
+ *
86
+ * @type {ShadeGPUContextProfiler|null}
87
+ */
88
+ #profiler = null;
89
+
90
+ /**
91
+ * Resolves after this context's timings have been read back and handed to its recorder.
92
+ *
93
+ * **Not the same moment as {@link done}.** `done` resolves from `onFinished`, which fires
94
+ * synchronously at submit — before any timestamp has been read. A caller that closes its frame
95
+ * on `done` commits an empty one, every time. Already-resolved when nothing is profiling.
96
+ *
97
+ * @returns {Promise<void>}
98
+ */
99
+ get profiling_absorbed() {
100
+ const profiler = this.#profiler;
101
+
102
+ return profiler === null ? Promise.resolve() : profiler.absorbed;
103
+ }
104
+
105
+ /**
106
+ * Record this context's pass timings into `recorder`.
107
+ *
108
+ * @param {GPUFrameRecorder} recorder
109
+ * @param {number} query_set_id this context's index within the frame
110
+ * @returns {void}
111
+ */
112
+ enable_profiling(recorder, query_set_id) {
113
+ assert.notOk(this.#finished, 'already finished');
114
+ assert.isNull(this.#profiler, 'already profiling');
115
+
116
+ this.#profiler = new ShadeGPUContextProfiler(this.device, recorder, query_set_id);
117
+ }
118
+
119
+ /**
120
+ * @type {GraphicsContext}
121
+ */
122
+ #graphics
123
+
124
+ /**
125
+ *
126
+ * @return {GPUDevice}
127
+ */
128
+ get device() {
129
+ return this.#graphics.device;
130
+ }
131
+
132
+ /**
133
+ *
134
+ * @return {TextureManager}
135
+ */
136
+ get textures() {
137
+ return this.#graphics.textures;
138
+ }
139
+
140
+ /**
141
+ * These are to be destroyed at the end of the context's lifetime.
142
+ * Need to be released at the end of the lifetime.
143
+ * @type {GPUBuffer[]}
144
+ */
145
+ #transient_buffers = [];
146
+
147
+ /**
148
+ *
149
+ * @type {GPUBuffer[]}
150
+ */
151
+ #staging_buffers = [];
152
+
153
+ /**
154
+ * Once finished, the encoder becomes inactive, we use this flag to track potential misuse and inform the user
155
+ * @type {boolean}
156
+ */
157
+ #finished = false;
158
+
159
+ /**
160
+ * @readonly
161
+ * @type {Signal<this>}
162
+ */
163
+ onFinished = new Signal();
164
+
165
+ /**
166
+ * @readonly
167
+ * @type {Signal<this>}
168
+ */
169
+ onBeforeFinish = new Signal();
170
+
171
+ /**
172
+ *
173
+ * @return {Promise<void>}
174
+ */
175
+ get done() {
176
+ if (this.#finished) {
177
+ return Promise.resolve();
178
+ }
179
+
180
+ return new Promise(resolve => {
181
+ this.onFinished.addOne(resolve);
182
+
183
+ if (this.#finished) {
184
+ // special case, double-checking to avoid race conditions
185
+ resolve();
186
+ }
187
+
188
+ });
189
+ }
190
+
191
+ /**
192
+ * Do not call directly, always use {@link create}
193
+ * @private
194
+ */
195
+ constructor() {
196
+ // private, do not call from the outside
197
+ }
198
+
199
+ /**
200
+ *
201
+ * @param {GraphicsContext} graphics
202
+ * @param {string} [label]
203
+ * @returns {ShadeGPUCommandContext}
204
+ */
205
+ static create(
206
+ graphics,
207
+ label = ""
208
+ ) {
209
+
210
+ assert.defined(graphics, 'graphics');
211
+ assert.equal(graphics.isGraphicsContext, true, "graphics.isGraphicsContext !== true");
212
+
213
+ assert.isString(label, 'label');
214
+
215
+ const r = new ShadeGPUCommandContext();
216
+
217
+ r.#graphics = graphics;
218
+ r.#gpu_encoder = graphics.device.createCommandEncoder({
219
+ label
220
+ });
221
+
222
+ // track how many we have open
223
+ debug_open_context_count++;
224
+ array_push_if_unique(debug_open_contexts, r);
225
+
226
+ if (debug_open_context_count > 1024) {
227
+ warn_limited(`Too many open GPU contexts`, 20);
228
+ }
229
+
230
+ return r;
231
+
232
+ }
233
+
234
+ /**
235
+ *
236
+ * @returns {GraphicsExecutionContext}
237
+ */
238
+ createFrameGraphContext() {
239
+ return new GraphicsExecutionContext(this.#graphics, this);
240
+ }
241
+
242
+ /**
243
+ *
244
+ * @param {FrameGraph} graph
245
+ */
246
+ encodeGraph(graph) {
247
+ assert.defined(graph, 'graph');
248
+ assert.isObject(graph, 'graph');
249
+ assert.equal(graph.isFrameGraph, true, "graph.isFrameGraph !== true");
250
+
251
+ // TODO check if the graph is empty, if so, we can skip the whole thing
252
+
253
+ const ctx = this.createFrameGraphContext();
254
+
255
+ graph.compile();
256
+ graph.execute(ctx);
257
+ }
258
+
259
+ /**
260
+ * @see https://www.w3.org/TR/webgpu/#dom-gpucommandencoder-clearbuffer
261
+ * @param {GPUBuffer} buffer
262
+ * @param {number} [offset=0]
263
+ * @param {number} [size]
264
+ */
265
+ clearBuffer(buffer, offset = 0, size) {
266
+ assert.defined(buffer, 'buffer');
267
+ assert.equal(buffer.usage & GPUBufferUsage.COPY_DST, GPUBufferUsage.COPY_DST, 'buffer must include COPY_DST usage flag');
268
+ assert.isNonNegativeInteger(offset, 'offset');
269
+ assert.equal(offset % 4, 0, 'offset must be a multiple of 4');
270
+
271
+ // console.log(`cmd.clearBuffer(${buffer.label}, ${offset}, ${size})`);
272
+
273
+ this.#gpu_encoder.clearBuffer(buffer, offset, size);
274
+ }
275
+
276
+ /**
277
+ * Not supported, only here to offer documentation hint
278
+ * see {@link texture_fill_rectangle}
279
+ * @throws {Error} Always, documentation hint only
280
+ */
281
+ clearTexture() {
282
+ throw new Error(`Documentation hint only, use texture_fill_rectangle instead`);
283
+ }
284
+
285
+ /**
286
+ * NOTE: only the explicit verbose form of the API is supported, shorthand such as `copyBufferToBuffer(source, destination, size)` are not supported.
287
+ * see https://www.w3.org/TR/webgpu/#gpucommandencoder-copybuffertobuffer
288
+ * @see GPUCommandEncoder.copyBufferToBuffer
289
+ * @param {GPUBuffer} source The GPUBuffer to copy from.
290
+ * @param {number} sourceOffset Offset in bytes into the source to begin copying from.
291
+ * @param {GPUBuffer} destination The GPUBuffer to copy to.
292
+ * @param {number} destinationOffset Offset in bytes into destination to place the copied data.
293
+ * @param {number} [size] Bytes to copy. In not specified, defaults to `source.size - sourceOffset`
294
+ */
295
+ copyBufferToBuffer(
296
+ source,
297
+ sourceOffset,
298
+ destination,
299
+ destinationOffset,
300
+ size
301
+ ) {
302
+
303
+ assert.notEqual(source.usage & GPUBufferUsage.COPY_SRC, 0, 'source must include COPY_SRC usage flag');
304
+ assert.isNonNegativeInteger(sourceOffset, 'sourceOffset');
305
+ assert.equal(sourceOffset % 4, 0, 'sourceOffset must be a multiple of 4');
306
+
307
+ assert.notEqual(destination.usage & GPUBufferUsage.COPY_DST, 0, 'destination must include COPY_DST usage flag');
308
+ assert.isNonNegativeInteger(destinationOffset, 'destinationOffset');
309
+ assert.equal(destinationOffset % 4, 0, 'destinationOffset must be a multiple of 4');
310
+
311
+ if (size !== undefined) {
312
+ assert.isNonNegativeInteger(size, 'size');
313
+ assert.equal(size % 4, 0, 'size must be a multiple of 4');
314
+
315
+ assert.greaterThanOrEqual(source.size, sourceOffset + size, 'source underflow');
316
+ assert.greaterThanOrEqual(destination.size, destinationOffset + size, 'destination underflow');
317
+ }
318
+
319
+ assert.notEqual(source, destination, 'source and destination must be different');
320
+
321
+ // console.log(`cmd.copyBufferToBuffer("${source.label}", ${sourceOffset}, "${destination.label}", ${destinationOffset}, ${size})`);
322
+
323
+ this.#gpu_encoder.copyBufferToBuffer(
324
+ source,
325
+ sourceOffset,
326
+ destination,
327
+ destinationOffset,
328
+ size
329
+ );
330
+ }
331
+
332
+
333
+ /**
334
+ *
335
+ * @param {GPUImageCopyTexture} source
336
+ * @param {GPUImageCopyTexture} destination
337
+ * @param {GPUExtent3DStrict} copySize
338
+ */
339
+ copyTextureToTexture(source,
340
+ destination,
341
+ copySize
342
+ ) {
343
+ this.#gpu_encoder.copyTextureToTexture(source, destination, copySize);
344
+ }
345
+
346
+ /**
347
+ *
348
+ * @param {GPUComputePassDescriptor} [descriptor]
349
+ * @returns {ShadeGPUComputePassEncoder}
350
+ */
351
+ beginComputePass(descriptor) {
352
+ const encoder = this.#gpu_encoder;
353
+ const profiler = this.#profiler;
354
+
355
+ // console.log(`cmd.beginComputePass(${descriptor.label})`);
356
+
357
+ if (profiler === null) {
358
+ return new ShadeGPUComputePassEncoder(encoder.beginComputePass(descriptor), null);
359
+ }
360
+
361
+ return profiler.begin_compute_pass(encoder, descriptor);
362
+ }
363
+
364
+
365
+ /**
366
+ *
367
+ * @param {ComputePipelineDescriptor} pipeline
368
+ * @param {string} [label]
369
+ * @param {GPUBindingResource[][]} [bindings]
370
+ * @returns {ShadeGPUComputePassEncoder}
371
+ */
372
+ constructComputePass({
373
+ pipeline,
374
+ label,
375
+ bindings = [],
376
+ immediate
377
+ }) {
378
+
379
+ const pass_descriptor = {
380
+ label
381
+ };
382
+
383
+ if (label === undefined) {
384
+ pass_descriptor.label = pipeline.label;
385
+ }
386
+
387
+ const graphics = this.#graphics;
388
+
389
+ const pass = this.beginComputePass(pass_descriptor);
390
+
391
+ const gpu_pipeline = graphics.compute_pipelines.obtain(pipeline);
392
+
393
+ pass.setPipeline(gpu_pipeline);
394
+
395
+ pass.record_pipeline(pipeline);
396
+
397
+ graphics.setPipelineBindings(pass, pipeline, bindings, immediate);
398
+
399
+ // console.warn(`cmd.constructComputePass(${pass_descriptor.label})`)
400
+
401
+ return pass;
402
+ }
403
+
404
+ /**
405
+ * Begins a labeled debug group containing subsequent commands.
406
+ * @see https://gpuweb.github.io/gpuweb/#debug-markers
407
+ * @param {string} label
408
+ */
409
+ pushDebugGroup(label) {
410
+ assert.isString(label, 'label');
411
+ this.#gpu_encoder.pushDebugGroup(label);
412
+
413
+ // console.group("cmd/debug_group=" + label)
414
+ }
415
+
416
+ /**
417
+ * Ends the labeled debug group most recently started by pushDebugGroup().
418
+ * @see https://gpuweb.github.io/gpuweb/#debug-markers
419
+ */
420
+ popDebugGroup() {
421
+ this.#gpu_encoder.popDebugGroup();
422
+
423
+ // console.groupEnd();
424
+ }
425
+
426
+ /**
427
+ * Marks a point in a stream of commands with a label.
428
+ * @see https://gpuweb.github.io/gpuweb/#debug-markers
429
+ * @param {string} label
430
+ */
431
+ insertDebugMarker(label) {
432
+ assert.isString(label, 'label');
433
+ this.#gpu_encoder.insertDebugMarker(label);
434
+ }
435
+
436
+ /**
437
+ *
438
+ * @param {string} [label]
439
+ * @param {RenderPipelineDescriptor} pipeline
440
+ * @param {GPUBindingResource[][]} [bindings]
441
+ * @param {GPURenderPassColorAttachment[]} colorAttachments
442
+ * @param {GPURenderPassDepthStencilAttachment} [depthStencilAttachment]
443
+ * @returns {ShadeGPURenderPassEncoder}
444
+ */
445
+ constructRenderPass({
446
+ label,
447
+ pipeline,
448
+ bindings,
449
+ colorAttachments,
450
+ depthStencilAttachment,
451
+ immediate,
452
+ }) {
453
+ assert.defined(pipeline, 'pipeline');
454
+ assert.equal(pipeline.isRenderPipelineDescriptor, true, "pipeline.isRenderPipelineDescriptor !== true");
455
+
456
+ const pass_descriptor = {
457
+ label,
458
+ colorAttachments,
459
+ depthStencilAttachment
460
+ };
461
+
462
+ if (label === undefined) {
463
+ pass_descriptor.label = pipeline.label;
464
+ }
465
+
466
+ const graphics = this.#graphics;
467
+
468
+ // TODO rewrite the pipeline if necessary to achieve compatibility with colorAttachment formats
469
+ const gpu_pipeline = graphics.render_pipelines.obtain(pipeline);
470
+
471
+ const pass = this.beginRenderPass(pass_descriptor);
472
+
473
+ pass.setPipeline(gpu_pipeline);
474
+
475
+ pass.record_pipeline(pipeline);
476
+
477
+ graphics.setPipelineBindings(pass, pipeline, bindings, immediate);
478
+
479
+ // console.warn(`cmd.constructRenderPass(${pass_descriptor.label})`)
480
+
481
+ return pass;
482
+ }
483
+
484
+ /**
485
+ *
486
+ * @param {GPURenderPassDescriptor} descriptor
487
+ * @returns {ShadeGPURenderPassEncoder}
488
+ */
489
+ beginRenderPass(descriptor) {
490
+ const encoder = this.#gpu_encoder;
491
+ const profiler = this.#profiler;
492
+
493
+ // console.log(`cmd.beginRenderPass(${descriptor.label})`);
494
+
495
+ if (profiler === null) {
496
+ return new ShadeGPURenderPassEncoder(encoder.beginRenderPass(descriptor), null);
497
+ }
498
+
499
+ return profiler.begin_render_pass(encoder, descriptor);
500
+ }
501
+
502
+ /**
503
+ *
504
+ * @param {GPUQuerySet} querySet
505
+ * @param {number} firstQuery
506
+ * @param {number} queryCount
507
+ * @param {GPUBuffer} destination
508
+ * @param {number} destinationOffset
509
+ */
510
+ resolveQuerySet(querySet, firstQuery, queryCount, destination, destinationOffset) {
511
+ this.#gpu_encoder.resolveQuerySet(querySet, firstQuery, queryCount, destination, destinationOffset);
512
+ }
513
+
514
+ /**
515
+ * Transient buffers are automatically released at the end of the context's lifetime;
516
+ * however, we can explicitly release it earlier to allow for reuse.
517
+ *
518
+ * @param {GPUBuffer} buffer
519
+ * @return {boolean} true if buffer was released, false if it was not found
520
+ */
521
+ releaseTransientBuffer(buffer) {
522
+ assert.defined(buffer, 'buffer');
523
+
524
+ if (!array_remove_first(this.#transient_buffers, buffer)) {
525
+ return false;
526
+ }
527
+
528
+ const allocator = this.#transient_allocator;
529
+
530
+ return allocator.release(buffer);
531
+ }
532
+
533
+ /**
534
+ *
535
+ * @return {GPUBufferAllocator}
536
+ */
537
+ get #transient_allocator() {
538
+ return this.#graphics.buffer_allocator_main;
539
+ }
540
+
541
+ /**
542
+ * Allocated buffer will only be valid until the context is finished.
543
+ *
544
+ * @param {number|GPUBufferUsage} usage
545
+ * @param {number} size
546
+ * @returns {GPUBuffer} managed buffer
547
+ */
548
+ allocateTransientBuffer(
549
+ usage = GPUBufferUsage.UNIFORM,
550
+ size
551
+ ) {
552
+ assert.isNonNegativeInteger(size, 'size');
553
+ assert.isInteger(usage, 'usage');
554
+
555
+ assert.notOk(this.#finished, 'already finished');
556
+
557
+ scratch_buffer_descriptor.size = size;
558
+ // COPY_DST is needed to write the data
559
+ scratch_buffer_descriptor.usage = usage | GPUBufferUsage.COPY_DST;
560
+
561
+ const allocator = this.#transient_allocator;
562
+ const buffer = allocator.get(scratch_buffer_descriptor, this);
563
+
564
+ // remember so we can clean up at the end
565
+ this.#transient_buffers.push(buffer);
566
+
567
+ return buffer;
568
+ }
569
+
570
+ /**
571
+ *
572
+ * @param {ArrayBuffer} data CPU-side data to place into the GPU buffer
573
+ * @param {number|GPUBufferUsage} [usage=GPUBufferUsage.UNIFORM]
574
+ * @param {number} [offset] offset into source data where to start copying from
575
+ * @param {number} [size] in bytes
576
+ * @returns {GPUBuffer} managed buffer, will be automatically destroyed when context is finished
577
+ */
578
+ allocateTransientBufferAndLoad(
579
+ data,
580
+ usage = GPUBufferUsage.UNIFORM,
581
+ offset = 0,
582
+ size = data.byteLength
583
+ ) {
584
+ assert.isInstanceOf(data, ArrayBuffer, 'data');
585
+ assert.isInteger(usage, 'usage');
586
+ assert.isNonNegativeInteger(offset, 'offset');
587
+ assert.isNonNegativeInteger(size, 'size');
588
+
589
+ assert.notOk(this.#finished, 'already finished');
590
+
591
+ const buffer = this.allocateTransientBuffer(
592
+ usage,
593
+ size
594
+ );
595
+
596
+ this.writeBuffer(buffer, 0, data, offset, size);
597
+
598
+ return buffer;
599
+ }
600
+
601
+ /**
602
+ * Scratch for immediate data, created on first use and reused for the life of the context.
603
+ *
604
+ * One buffer is enough, and `position` returns to 0 for every write, because `setImmediates`
605
+ * copies the bytes it is given at the point of the call — the region is free again the moment
606
+ * the pass encoder has taken it. Nothing here ever grows: the default capacity is far above the
607
+ * 64-byte ceiling {@link ShaderResourceSetDescriptor#setImmediate} enforces, so the backing
608
+ * `ArrayBuffer` is allocated once and never reallocated.
609
+ *
610
+ * @type {BinaryBuffer|null}
611
+ */
612
+ #immediate_buffer = null;
613
+
614
+ /**
615
+ * Serialise a shader's immediate data ready for `setImmediates`, or return undefined when the
616
+ * shader declares none.
617
+ *
618
+ * Allocates nothing after the first call.
619
+ *
620
+ * @param {ShaderResourceSetDescriptor} resources
621
+ * @param {Object} map the shader's binding map
622
+ * @returns {{buffer: BinaryBuffer, offset: number, size: number}|undefined}
623
+ */
624
+ writeImmediate(resources, map) {
625
+ if (resources.immediateSize === 0) {
626
+ return undefined;
627
+ }
628
+
629
+ let buffer = this.#immediate_buffer;
630
+
631
+ if (buffer === null) {
632
+ buffer = new BinaryBuffer();
633
+
634
+ // GPU buffer contents must match the host, and BinaryBuffer's own default is
635
+ // little-endian regardless of platform. Getting this wrong produces bytes that are
636
+ // correct on every machine anyone is likely to test on and wrong on the rest.
637
+ buffer.endianness = platform_compute_endianness();
638
+
639
+ this.#immediate_buffer = buffer;
640
+ }
641
+
642
+ buffer.position = 0;
643
+
644
+ if (!resources.writeImmediate(map, buffer)) {
645
+ return undefined;
646
+ }
647
+
648
+ return { buffer, offset: 0, size: buffer.position };
649
+ }
650
+
651
+ /**
652
+ * @template T
653
+ * @param {WebGPUType} type
654
+ * @param {T} value
655
+ * @param {number|GPUBufferUsage} [usage]
656
+ * @return {GPUBuffer}
657
+ */
658
+ allocateTransientValueBuffer(
659
+ type,
660
+ value,
661
+ usage
662
+ ) {
663
+ assert.defined(type, 'type');
664
+ assert.notNull(type, 'type');
665
+
666
+ const buffer = this.allocateTransientBuffer(usage, type.aligned_size);
667
+
668
+ this.writeValueBuffer(buffer, 0, type, value);
669
+
670
+ return buffer;
671
+ }
672
+
673
+ /**
674
+ * @template T
675
+ * @param {GPUBuffer} buffer
676
+ * @param {number} buffer_offset
677
+ * @param {WebGPUType} type
678
+ * @param {T} value
679
+ */
680
+ writeValueBuffer(buffer, buffer_offset, type, value) {
681
+
682
+ assert.notOk(this.#finished, 'already finished');
683
+
684
+ const gfx = this.#graphics;
685
+
686
+ const size = type.aligned_size;
687
+
688
+ const stage = gfx.buffer_allocator_staging.get(size);
689
+
690
+ const mapped = stage.getMappedRange(0, size);
691
+
692
+ write_gpu_typed_buffer(value, type, mapped, 0);
693
+
694
+ stage.unmap();
695
+
696
+ this.#staging_buffers.push(stage);
697
+
698
+ this.copyBufferToBuffer(stage, 0, buffer, buffer_offset, size);
699
+ }
700
+
701
+ /**
702
+ * Very similar to {@link GPUQueue.writeBuffer}, but instead of doing the operation direction on the queue - uses a staging buffer under the hood and performs the actual write operation as part of the commmand buffer
703
+ * @param {GPUBuffer} buffer
704
+ * @param {number} buffer_offset
705
+ * @param {ArrayBuffer} data
706
+ * @param {number} data_offset
707
+ * @param {number} size
708
+ */
709
+ writeBuffer(buffer, buffer_offset, data, data_offset, size) {
710
+ assert.defined(buffer, 'buffer');
711
+ assert.isNonNegativeInteger(buffer_offset, 'buffer_offset');
712
+ assert.defined(data, 'data');
713
+ assert.isNonNegativeInteger(data_offset, 'data_offset');
714
+ assert.isNonNegativeInteger(size, 'size');
715
+
716
+ const gfx = this.#graphics;
717
+
718
+ const stage = gfx.buffer_allocator_staging.get(size);
719
+
720
+ const mapped = stage.getMappedRange(0, size);
721
+
722
+ array_buffer_copy(data, data_offset, mapped, 0, size);
723
+
724
+ stage.unmap();
725
+
726
+ this.#staging_buffers.push(stage);
727
+
728
+ this.copyBufferToBuffer(stage, 0, buffer, buffer_offset, size);
729
+
730
+ }
731
+
732
+ #cleanup() {
733
+
734
+ // console.warn('cmd.cleanup()');
735
+
736
+ const transient_buffers = this.#transient_buffers;
737
+ const transient_buffer_count = transient_buffers.length;
738
+
739
+ const buffer_allocator_transient = this.#transient_allocator;
740
+
741
+ // release in reverse order to make it more likely that we'd end up in the same acquisition order next time, which is desirable for caching
742
+ for (let i = transient_buffer_count - 1; i >= 0; i--) {
743
+ const buffer = transient_buffers[i];
744
+
745
+ buffer_allocator_transient.release(buffer);
746
+
747
+ }
748
+
749
+ // staging buffers
750
+ const buffer_allocator_staging = this.#graphics.buffer_allocator_staging;
751
+ for (const staging of this.#staging_buffers) {
752
+ buffer_allocator_staging.release(staging);
753
+ }
754
+ }
755
+
756
+ /**
757
+ * Performs both {@link GPUCommandEncoder.finish} and flushed command buffer
758
+ */
759
+ finish() {
760
+ if (this.#finished) {
761
+ console.warn('Context already finished');
762
+ return;
763
+ }
764
+
765
+ this.onBeforeFinish.send1(this);
766
+
767
+ debug_open_context_count--;
768
+ array_remove_first(debug_open_contexts, this);
769
+
770
+ const encoder = this.#gpu_encoder;
771
+
772
+ const profiler = this.#profiler;
773
+
774
+ if (profiler !== null) {
775
+ profiler.resolve(encoder);
776
+ }
777
+
778
+ this.#finished = true;
779
+
780
+ // release encoder reference
781
+ this.#gpu_encoder = undefined;
782
+
783
+ const command_buffer = encoder.finish();
784
+
785
+ const graphics = this.#graphics;
786
+ const queue = graphics.device.queue;
787
+
788
+ queue.submit([command_buffer]);
789
+
790
+ // cleanup allocated memory
791
+ this.#cleanup();
792
+
793
+ if (profiler !== null) {
794
+ // Kept, not cleared — `profiling_absorbed` is read after `finish()` and a null here
795
+ // would report an already-resolved promise. See the field.
796
+ profiler.absorb();
797
+ }
798
+
799
+ this.onFinished.send1(this);
800
+
801
+ }
995
802
  }