@onerjs/core 9.0.2 → 9.0.4

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 (476) hide show
  1. package/Buffers/buffer.pure.js +4 -0
  2. package/Buffers/buffer.pure.js.map +1 -1
  3. package/Cameras/camera.pure.d.ts +14 -0
  4. package/Cameras/camera.pure.js +15 -0
  5. package/Cameras/camera.pure.js.map +1 -1
  6. package/Compute/computeShader.pure.d.ts +2 -1
  7. package/Compute/computeShader.pure.js +29 -10
  8. package/Compute/computeShader.pure.js.map +1 -1
  9. package/Culling/ray.core.js +22 -9
  10. package/Culling/ray.core.js.map +1 -1
  11. package/Engines/IDrawContext.d.ts +2 -0
  12. package/Engines/IDrawContext.js.map +1 -1
  13. package/Engines/Native/nativeInterfaces.d.ts +55 -4
  14. package/Engines/Native/nativeInterfaces.js.map +1 -1
  15. package/Engines/Native/nativeRenderTargetWrapper.d.ts +1 -0
  16. package/Engines/Native/nativeRenderTargetWrapper.js +5 -1
  17. package/Engines/Native/nativeRenderTargetWrapper.js.map +1 -1
  18. package/Engines/Processors/shaderCodeInliner.d.ts +2 -0
  19. package/Engines/Processors/shaderCodeInliner.js +251 -6
  20. package/Engines/Processors/shaderCodeInliner.js.map +1 -1
  21. package/Engines/Processors/shaderProcessor.js +10 -1
  22. package/Engines/Processors/shaderProcessor.js.map +1 -1
  23. package/Engines/WebGPU/Extensions/engine.debugging.pure.js +12 -0
  24. package/Engines/WebGPU/Extensions/engine.debugging.pure.js.map +1 -1
  25. package/Engines/WebGPU/Extensions/engine.multiRender.pure.js +0 -1
  26. package/Engines/WebGPU/Extensions/engine.multiRender.pure.js.map +1 -1
  27. package/Engines/WebGPU/Extensions/engine.query.pure.js +5 -0
  28. package/Engines/WebGPU/Extensions/engine.query.pure.js.map +1 -1
  29. package/Engines/WebGPU/webgpuBufferManager.js +7 -0
  30. package/Engines/WebGPU/webgpuBufferManager.js.map +1 -1
  31. package/Engines/WebGPU/webgpuCacheTextureView.d.ts +1 -1
  32. package/Engines/WebGPU/webgpuCacheTextureView.js +20 -8
  33. package/Engines/WebGPU/webgpuCacheTextureView.js.map +1 -1
  34. package/Engines/WebGPU/webgpuDrawContext.d.ts +2 -0
  35. package/Engines/WebGPU/webgpuDrawContext.js +6 -0
  36. package/Engines/WebGPU/webgpuDrawContext.js.map +1 -1
  37. package/Engines/WebGPU/webgpuQuerySet.d.ts +3 -3
  38. package/Engines/WebGPU/webgpuQuerySet.js +23 -9
  39. package/Engines/WebGPU/webgpuQuerySet.js.map +1 -1
  40. package/Engines/WebGPU/webgpuRenderPassCommandStream.d.ts +156 -0
  41. package/Engines/WebGPU/webgpuRenderPassCommandStream.js +323 -0
  42. package/Engines/WebGPU/webgpuRenderPassCommandStream.js.map +1 -0
  43. package/Engines/WebGPU/webgpuTextureManager.d.ts +1 -1
  44. package/Engines/WebGPU/webgpuTextureManager.js +4 -3
  45. package/Engines/WebGPU/webgpuTextureManager.js.map +1 -1
  46. package/Engines/WebGPU/webgpuTimestampQuery.d.ts +3 -1
  47. package/Engines/WebGPU/webgpuTimestampQuery.js +9 -6
  48. package/Engines/WebGPU/webgpuTimestampQuery.js.map +1 -1
  49. package/Engines/abstractEngine.pure.d.ts +2 -0
  50. package/Engines/abstractEngine.pure.js +14 -5
  51. package/Engines/abstractEngine.pure.js.map +1 -1
  52. package/Engines/constants.d.ts +6 -0
  53. package/Engines/constants.js +6 -0
  54. package/Engines/constants.js.map +1 -1
  55. package/Engines/engine.d.ts +198 -24
  56. package/Engines/pure.d.ts +1 -0
  57. package/Engines/pure.js +1 -0
  58. package/Engines/pure.js.map +1 -1
  59. package/Engines/renderCommandBatcher.pure.d.ts +16 -0
  60. package/Engines/renderCommandBatcher.pure.js +24 -0
  61. package/Engines/renderCommandBatcher.pure.js.map +1 -0
  62. package/Engines/thinEngine.functions.js +3 -2
  63. package/Engines/thinEngine.functions.js.map +1 -1
  64. package/Engines/thinEngine.pure.js +18 -2
  65. package/Engines/thinEngine.pure.js.map +1 -1
  66. package/Engines/thinNativeEngine.pure.d.ts +10 -7
  67. package/Engines/thinNativeEngine.pure.js +117 -46
  68. package/Engines/thinNativeEngine.pure.js.map +1 -1
  69. package/Engines/thinWebGPUEngine.d.ts +8 -0
  70. package/Engines/thinWebGPUEngine.js +11 -0
  71. package/Engines/thinWebGPUEngine.js.map +1 -1
  72. package/Engines/webgpuEngine.pure.d.ts +60 -1
  73. package/Engines/webgpuEngine.pure.js +238 -42
  74. package/Engines/webgpuEngine.pure.js.map +1 -1
  75. package/FlowGraph/Blocks/Data/Audio/flowGraphGetSoundVolumeBlock.pure.d.ts +3 -3
  76. package/FlowGraph/Blocks/Data/Audio/flowGraphGetSoundVolumeBlock.pure.js +2 -1
  77. package/FlowGraph/Blocks/Data/Audio/flowGraphGetSoundVolumeBlock.pure.js.map +1 -1
  78. package/FlowGraph/Blocks/Data/Audio/flowGraphIsSoundPlayingBlock.pure.d.ts +3 -3
  79. package/FlowGraph/Blocks/Data/Audio/flowGraphIsSoundPlayingBlock.pure.js +2 -1
  80. package/FlowGraph/Blocks/Data/Audio/flowGraphIsSoundPlayingBlock.pure.js.map +1 -1
  81. package/FlowGraph/Blocks/Event/flowGraphMeshIntersectionEventBlock.d.ts +5 -0
  82. package/FlowGraph/Blocks/Event/flowGraphMeshIntersectionEventBlock.js +8 -0
  83. package/FlowGraph/Blocks/Event/flowGraphMeshIntersectionEventBlock.js.map +1 -0
  84. package/FlowGraph/Blocks/Event/flowGraphMeshIntersectionEventBlock.pure.d.ts +77 -0
  85. package/FlowGraph/Blocks/Event/flowGraphMeshIntersectionEventBlock.pure.js +141 -0
  86. package/FlowGraph/Blocks/Event/flowGraphMeshIntersectionEventBlock.pure.js.map +1 -0
  87. package/FlowGraph/Blocks/Event/flowGraphSoundEndedEventBlock.pure.d.ts +5 -3
  88. package/FlowGraph/Blocks/Event/flowGraphSoundEndedEventBlock.pure.js +38 -7
  89. package/FlowGraph/Blocks/Event/flowGraphSoundEndedEventBlock.pure.js.map +1 -1
  90. package/FlowGraph/Blocks/Event/index.d.ts +1 -0
  91. package/FlowGraph/Blocks/Event/index.js +1 -0
  92. package/FlowGraph/Blocks/Event/index.js.map +1 -1
  93. package/FlowGraph/Blocks/Event/pure.d.ts +1 -0
  94. package/FlowGraph/Blocks/Event/pure.js +1 -0
  95. package/FlowGraph/Blocks/Event/pure.js.map +1 -1
  96. package/FlowGraph/Blocks/Execution/Audio/flowGraphPauseSoundBlock.pure.d.ts +3 -3
  97. package/FlowGraph/Blocks/Execution/Audio/flowGraphPauseSoundBlock.pure.js +2 -1
  98. package/FlowGraph/Blocks/Execution/Audio/flowGraphPauseSoundBlock.pure.js.map +1 -1
  99. package/FlowGraph/Blocks/Execution/Audio/flowGraphPlaySoundBlock.pure.d.ts +3 -3
  100. package/FlowGraph/Blocks/Execution/Audio/flowGraphPlaySoundBlock.pure.js +2 -1
  101. package/FlowGraph/Blocks/Execution/Audio/flowGraphPlaySoundBlock.pure.js.map +1 -1
  102. package/FlowGraph/Blocks/Execution/Audio/flowGraphSetSoundVolumeBlock.pure.d.ts +3 -3
  103. package/FlowGraph/Blocks/Execution/Audio/flowGraphSetSoundVolumeBlock.pure.js +2 -1
  104. package/FlowGraph/Blocks/Execution/Audio/flowGraphSetSoundVolumeBlock.pure.js.map +1 -1
  105. package/FlowGraph/Blocks/Execution/Audio/flowGraphStopSoundBlock.pure.d.ts +3 -3
  106. package/FlowGraph/Blocks/Execution/Audio/flowGraphStopSoundBlock.pure.js +2 -1
  107. package/FlowGraph/Blocks/Execution/Audio/flowGraphStopSoundBlock.pure.js.map +1 -1
  108. package/FlowGraph/Blocks/allBlocks.pure.js +2 -0
  109. package/FlowGraph/Blocks/allBlocks.pure.js.map +1 -1
  110. package/FlowGraph/Blocks/flowGraphBlockFactory.js +2 -0
  111. package/FlowGraph/Blocks/flowGraphBlockFactory.js.map +1 -1
  112. package/FlowGraph/Blocks/flowGraphBlockNames.d.ts +1 -0
  113. package/FlowGraph/Blocks/flowGraphBlockNames.js +1 -0
  114. package/FlowGraph/Blocks/flowGraphBlockNames.js.map +1 -1
  115. package/FlowGraph/flowGraph.d.ts +12 -1
  116. package/FlowGraph/flowGraph.js +38 -0
  117. package/FlowGraph/flowGraph.js.map +1 -1
  118. package/FlowGraph/flowGraphCoordinator.d.ts +44 -0
  119. package/FlowGraph/flowGraphCoordinator.js +141 -0
  120. package/FlowGraph/flowGraphCoordinator.js.map +1 -1
  121. package/FlowGraph/flowGraphDataConnection.pure.js +41 -14
  122. package/FlowGraph/flowGraphDataConnection.pure.js.map +1 -1
  123. package/FlowGraph/flowGraphParser.js +105 -5
  124. package/FlowGraph/flowGraphParser.js.map +1 -1
  125. package/FlowGraph/flowGraphSoundAssets.d.ts +40 -0
  126. package/FlowGraph/flowGraphSoundAssets.js +33 -0
  127. package/FlowGraph/flowGraphSoundAssets.js.map +1 -0
  128. package/FlowGraph/index.d.ts +1 -0
  129. package/FlowGraph/index.js +1 -0
  130. package/FlowGraph/index.js.map +1 -1
  131. package/FlowGraph/pure.d.ts +1 -0
  132. package/FlowGraph/pure.js +1 -0
  133. package/FlowGraph/pure.js.map +1 -1
  134. package/FlowGraph/serialization.d.ts +8 -0
  135. package/FlowGraph/serialization.js +31 -12
  136. package/FlowGraph/serialization.js.map +1 -1
  137. package/FlowGraph/typeDefinitions.d.ts +25 -0
  138. package/FlowGraph/typeDefinitions.js.map +1 -1
  139. package/FrameGraph/Tasks/PostProcesses/taaTask.js +2 -0
  140. package/FrameGraph/Tasks/PostProcesses/taaTask.js.map +1 -1
  141. package/Instrumentation/engineInstrumentation.d.ts +1 -0
  142. package/Instrumentation/engineInstrumentation.js +25 -6
  143. package/Instrumentation/engineInstrumentation.js.map +1 -1
  144. package/Lights/Clustered/clusteredLightContainer.pure.js +2 -0
  145. package/Lights/Clustered/clusteredLightContainer.pure.js.map +1 -1
  146. package/Lights/Shadows/cascadedShadowGenerator.pure.d.ts +36 -1
  147. package/Lights/Shadows/cascadedShadowGenerator.pure.js +202 -27
  148. package/Lights/Shadows/cascadedShadowGenerator.pure.js.map +1 -1
  149. package/Lights/directionalLight.pure.d.ts +24 -10
  150. package/Lights/directionalLight.pure.js +29 -11
  151. package/Lights/directionalLight.pure.js.map +1 -1
  152. package/Loading/sceneLoader.d.ts +1 -1
  153. package/Loading/sceneLoader.js +1 -1
  154. package/Loading/sceneLoader.js.map +1 -1
  155. package/Materials/GaussianSplatting/gaussianSplattingMaterial.pure.js +4 -4
  156. package/Materials/GaussianSplatting/gaussianSplattingMaterial.pure.js.map +1 -1
  157. package/Materials/Node/Blocks/Dual/lightBlock.pure.js +1 -1
  158. package/Materials/Node/Blocks/Dual/lightBlock.pure.js.map +1 -1
  159. package/Materials/Node/Blocks/Input/inputBlock.pure.js +4 -0
  160. package/Materials/Node/Blocks/Input/inputBlock.pure.js.map +1 -1
  161. package/Materials/Node/Blocks/PBR/pbrMetallicRoughnessBlock.pure.d.ts +9 -0
  162. package/Materials/Node/Blocks/PBR/pbrMetallicRoughnessBlock.pure.js +23 -3
  163. package/Materials/Node/Blocks/PBR/pbrMetallicRoughnessBlock.pure.js.map +1 -1
  164. package/Materials/PBR/openpbrMaterial.pure.js +1 -1
  165. package/Materials/PBR/openpbrMaterial.pure.js.map +1 -1
  166. package/Materials/PBR/pbrBaseMaterial.pure.d.ts +9 -0
  167. package/Materials/PBR/pbrBaseMaterial.pure.js +60 -1
  168. package/Materials/PBR/pbrBaseMaterial.pure.js.map +1 -1
  169. package/Materials/PBR/pbrBaseSimpleMaterial.d.ts +11 -0
  170. package/Materials/PBR/pbrBaseSimpleMaterial.js +21 -2
  171. package/Materials/PBR/pbrBaseSimpleMaterial.js.map +1 -1
  172. package/Materials/PBR/pbrMaterial.pure.d.ts +12 -0
  173. package/Materials/PBR/pbrMaterial.pure.js +23 -3
  174. package/Materials/PBR/pbrMaterial.pure.js.map +1 -1
  175. package/Materials/Textures/Filtering/hdrIrradianceFiltering.d.ts +1 -0
  176. package/Materials/Textures/Filtering/hdrIrradianceFiltering.js +10 -0
  177. package/Materials/Textures/Filtering/hdrIrradianceFiltering.js.map +1 -1
  178. package/Materials/Textures/HTML/htmlInCanvasPolyfill.d.ts +5 -0
  179. package/Materials/Textures/HTML/htmlInCanvasPolyfill.js +7 -0
  180. package/Materials/Textures/HTML/htmlInCanvasPolyfill.js.map +1 -1
  181. package/Materials/Textures/HTML/htmlInteractionManager.d.ts +9 -3
  182. package/Materials/Textures/HTML/htmlInteractionManager.js +64 -5
  183. package/Materials/Textures/HTML/htmlInteractionManager.js.map +1 -1
  184. package/Materials/Textures/HTML/htmlTexture.d.ts +11 -11
  185. package/Materials/Textures/HTML/htmlTexture.js +106 -65
  186. package/Materials/Textures/HTML/htmlTexture.js.map +1 -1
  187. package/Materials/Textures/Loaders/internalTextureLoader.d.ts +2 -1
  188. package/Materials/Textures/Loaders/internalTextureLoader.js.map +1 -1
  189. package/Materials/Textures/Loaders/ktxTextureLoader.d.ts +2 -1
  190. package/Materials/Textures/Loaders/ktxTextureLoader.js +4 -50
  191. package/Materials/Textures/Loaders/ktxTextureLoader.js.map +1 -1
  192. package/Materials/Textures/Procedurals/proceduralTexture.pure.js +10 -0
  193. package/Materials/Textures/Procedurals/proceduralTexture.pure.js.map +1 -1
  194. package/Materials/Textures/dynamicTexture.pure.js +6 -0
  195. package/Materials/Textures/dynamicTexture.pure.js.map +1 -1
  196. package/Materials/Textures/ktx2encoderTypes.d.ts +51 -0
  197. package/Materials/Textures/ktx2encoderTypes.js +2 -0
  198. package/Materials/Textures/ktx2encoderTypes.js.map +1 -0
  199. package/Materials/Textures/renderTargetTexture.pure.js +10 -2
  200. package/Materials/Textures/renderTargetTexture.pure.js.map +1 -1
  201. package/Materials/Textures/textureMerger.d.ts +11 -0
  202. package/Materials/Textures/textureMerger.js +34 -19
  203. package/Materials/Textures/textureMerger.js.map +1 -1
  204. package/Materials/Textures/textureProcessor.d.ts +145 -0
  205. package/Materials/Textures/textureProcessor.js +445 -45
  206. package/Materials/Textures/textureProcessor.js.map +1 -1
  207. package/Materials/Textures/textureSampling.functions.d.ts +41 -0
  208. package/Materials/Textures/textureSampling.functions.js +82 -0
  209. package/Materials/Textures/textureSampling.functions.js.map +1 -0
  210. package/Materials/drawWrapper.d.ts +8 -0
  211. package/Materials/drawWrapper.js +19 -0
  212. package/Materials/drawWrapper.js.map +1 -1
  213. package/Materials/effect.pure.d.ts +6 -0
  214. package/Materials/effect.pure.js +28 -6
  215. package/Materials/effect.pure.js.map +1 -1
  216. package/Materials/effect.webgl.functions.pure.js +1 -1
  217. package/Materials/effect.webgl.functions.pure.js.map +1 -1
  218. package/Materials/material.pure.d.ts +5 -0
  219. package/Materials/material.pure.js +9 -2
  220. package/Materials/material.pure.js.map +1 -1
  221. package/Materials/materialFlags.d.ts +6 -0
  222. package/Materials/materialFlags.js +14 -0
  223. package/Materials/materialFlags.js.map +1 -1
  224. package/Materials/materialHelper.functions.d.ts +2 -1
  225. package/Materials/materialHelper.functions.js +36 -2
  226. package/Materials/materialHelper.functions.js.map +1 -1
  227. package/Materials/materialHelper.geometryrendering.js +19 -16
  228. package/Materials/materialHelper.geometryrendering.js.map +1 -1
  229. package/Materials/materialPluginManager.pure.js +12 -8
  230. package/Materials/materialPluginManager.pure.js.map +1 -1
  231. package/Materials/prePassConfiguration.js +19 -16
  232. package/Materials/prePassConfiguration.js.map +1 -1
  233. package/Materials/shaderMaterial.pure.js +19 -6
  234. package/Materials/shaderMaterial.pure.js.map +1 -1
  235. package/Materials/shadowDepthWrapper.d.ts +6 -0
  236. package/Materials/shadowDepthWrapper.js +17 -0
  237. package/Materials/shadowDepthWrapper.js.map +1 -1
  238. package/Meshes/Compression/dracoCodec.d.ts +14 -0
  239. package/Meshes/Compression/dracoCodec.js +22 -0
  240. package/Meshes/Compression/dracoCodec.js.map +1 -1
  241. package/Meshes/Compression/dracoDecoder.d.ts +1 -0
  242. package/Meshes/Compression/dracoDecoder.js +27 -0
  243. package/Meshes/Compression/dracoDecoder.js.map +1 -1
  244. package/Meshes/Compression/dracoEncoder.d.ts +1 -0
  245. package/Meshes/Compression/dracoEncoder.js +8 -0
  246. package/Meshes/Compression/dracoEncoder.js.map +1 -1
  247. package/Meshes/Compression/meshoptCompression.d.ts +1 -0
  248. package/Meshes/Compression/meshoptCompression.js +9 -0
  249. package/Meshes/Compression/meshoptCompression.js.map +1 -1
  250. package/Meshes/GaussianSplatting/gaussianSplattingGpuSorter.d.ts +415 -0
  251. package/Meshes/GaussianSplatting/gaussianSplattingGpuSorter.js +912 -0
  252. package/Meshes/GaussianSplatting/gaussianSplattingGpuSorter.js.map +1 -0
  253. package/Meshes/GaussianSplatting/gaussianSplattingMesh.pure.d.ts +3 -0
  254. package/Meshes/GaussianSplatting/gaussianSplattingMesh.pure.js +40 -9
  255. package/Meshes/GaussianSplatting/gaussianSplattingMesh.pure.js.map +1 -1
  256. package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.d.ts +112 -8
  257. package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.js +696 -74
  258. package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.js.map +1 -1
  259. package/Meshes/abstractMesh.pure.js +12 -4
  260. package/Meshes/abstractMesh.pure.js.map +1 -1
  261. package/Meshes/geometry.d.ts +5 -0
  262. package/Meshes/geometry.js +25 -0
  263. package/Meshes/geometry.js.map +1 -1
  264. package/Meshes/index.d.ts +1 -0
  265. package/Meshes/index.js +1 -0
  266. package/Meshes/index.js.map +1 -1
  267. package/Meshes/mesh.pure.d.ts +7 -0
  268. package/Meshes/mesh.pure.js +18 -13
  269. package/Meshes/mesh.pure.js.map +1 -1
  270. package/Meshes/pure.d.ts +1 -0
  271. package/Meshes/pure.js +1 -0
  272. package/Meshes/pure.js.map +1 -1
  273. package/Meshes/subMesh.pure.d.ts +3 -0
  274. package/Meshes/subMesh.pure.js +26 -0
  275. package/Meshes/subMesh.pure.js.map +1 -1
  276. package/Meshes/thinInstanceMesh.pure.js +5 -3
  277. package/Meshes/thinInstanceMesh.pure.js.map +1 -1
  278. package/Misc/index.d.ts +1 -0
  279. package/Misc/index.js +1 -0
  280. package/Misc/index.js.map +1 -1
  281. package/Misc/khronosTextureContainer2.d.ts +3 -2
  282. package/Misc/khronosTextureContainer2.js +24 -6
  283. package/Misc/khronosTextureContainer2.js.map +1 -1
  284. package/Misc/khronosTextureContainer2Encoder.d.ts +166 -0
  285. package/Misc/khronosTextureContainer2Encoder.js +556 -0
  286. package/Misc/khronosTextureContainer2Encoder.js.map +1 -0
  287. package/Misc/khronosTextureContainer2EncoderWorker.d.ts +61 -0
  288. package/Misc/khronosTextureContainer2EncoderWorker.js +55 -0
  289. package/Misc/khronosTextureContainer2EncoderWorker.js.map +1 -0
  290. package/Misc/pure.d.ts +1 -0
  291. package/Misc/pure.js +1 -0
  292. package/Misc/pure.js.map +1 -1
  293. package/Misc/textureFormat.functions.d.ts +6 -0
  294. package/Misc/textureFormat.functions.js +54 -0
  295. package/Misc/textureFormat.functions.js.map +1 -0
  296. package/Misc/textureTools.d.ts +6 -2
  297. package/Misc/textureTools.js +100 -42
  298. package/Misc/textureTools.js.map +1 -1
  299. package/Misc/tools.pure.js +1 -1
  300. package/Misc/tools.pure.js.map +1 -1
  301. package/Particles/Node/Blocks/systemBlock.pure.d.ts +1 -1
  302. package/Particles/Node/Blocks/systemBlock.pure.js +6 -3
  303. package/Particles/Node/Blocks/systemBlock.pure.js.map +1 -1
  304. package/Particles/computeShaderParticleSystem.pure.js +5 -0
  305. package/Particles/computeShaderParticleSystem.pure.js.map +1 -1
  306. package/Particles/gpuParticleSystem.pure.d.ts +2 -0
  307. package/Particles/gpuParticleSystem.pure.js +25 -1
  308. package/Particles/gpuParticleSystem.pure.js.map +1 -1
  309. package/Particles/solidParticle.d.ts +5 -0
  310. package/Particles/solidParticle.js +5 -0
  311. package/Particles/solidParticle.js.map +1 -1
  312. package/Particles/solidParticleSystem.d.ts +10 -0
  313. package/Particles/solidParticleSystem.js +72 -13
  314. package/Particles/solidParticleSystem.js.map +1 -1
  315. package/Particles/thinParticleSystem.pure.js +4 -0
  316. package/Particles/thinParticleSystem.pure.js.map +1 -1
  317. package/PostProcesses/RenderPipeline/Pipelines/taaMaterialManager.pure.d.ts +27 -6
  318. package/PostProcesses/RenderPipeline/Pipelines/taaMaterialManager.pure.js +60 -5
  319. package/PostProcesses/RenderPipeline/Pipelines/taaMaterialManager.pure.js.map +1 -1
  320. package/PostProcesses/thinTAAPostProcess.d.ts +1 -0
  321. package/PostProcesses/thinTAAPostProcess.js +17 -1
  322. package/PostProcesses/thinTAAPostProcess.js.map +1 -1
  323. package/PostProcesses/volumetricLightScatteringPostProcess.pure.d.ts +2 -1
  324. package/PostProcesses/volumetricLightScatteringPostProcess.pure.js +6 -5
  325. package/PostProcesses/volumetricLightScatteringPostProcess.pure.js.map +1 -1
  326. package/Rendering/boundingBoxRenderer.pure.js +2 -3
  327. package/Rendering/boundingBoxRenderer.pure.js.map +1 -1
  328. package/Rendering/geometryBufferRenderer.pure.js +8 -2
  329. package/Rendering/geometryBufferRenderer.pure.js.map +1 -1
  330. package/Rendering/objectRenderer.d.ts +1 -0
  331. package/Rendering/objectRenderer.js +14 -0
  332. package/Rendering/objectRenderer.js.map +1 -1
  333. package/Shaders/ShadersInclude/bumpFragmentMainFunctions.js +2 -2
  334. package/Shaders/ShadersInclude/bumpFragmentMainFunctions.js.map +1 -1
  335. package/Shaders/ShadersInclude/bumpVertex.js +1 -1
  336. package/Shaders/ShadersInclude/bumpVertex.js.map +1 -1
  337. package/Shaders/ShadersInclude/bumpVertexDeclaration.js +1 -1
  338. package/Shaders/ShadersInclude/bumpVertexDeclaration.js.map +1 -1
  339. package/Shaders/ShadersInclude/hdrFilteringFunctions.js +5 -1
  340. package/Shaders/ShadersInclude/hdrFilteringFunctions.js.map +1 -1
  341. package/Shaders/ShadersInclude/helperFunctions.js +2 -2
  342. package/Shaders/ShadersInclude/helperFunctions.js.map +1 -1
  343. package/Shaders/ShadersInclude/openpbrBackgroundTransmission.js +1 -1
  344. package/Shaders/ShadersInclude/openpbrBackgroundTransmission.js.map +1 -1
  345. package/Shaders/ShadersInclude/openpbrVertexDeclaration.js +6 -0
  346. package/Shaders/ShadersInclude/openpbrVertexDeclaration.js.map +1 -1
  347. package/Shaders/ShadersInclude/pbrBlockFinalLitComponents.js +11 -1
  348. package/Shaders/ShadersInclude/pbrBlockFinalLitComponents.js.map +1 -1
  349. package/Shaders/ShadersInclude/pbrBlockNormalFinal.js +9 -0
  350. package/Shaders/ShadersInclude/pbrBlockNormalFinal.js.map +1 -1
  351. package/Shaders/ShadersInclude/pbrBlockReflectance.js +1 -1
  352. package/Shaders/ShadersInclude/pbrBlockReflectance.js.map +1 -1
  353. package/Shaders/ShadersInclude/pbrClusteredLightingFunctions.js +1 -1
  354. package/Shaders/ShadersInclude/pbrClusteredLightingFunctions.js.map +1 -1
  355. package/Shaders/ShadersInclude/pbrFragmentDeclaration.js +7 -1
  356. package/Shaders/ShadersInclude/pbrFragmentDeclaration.js.map +1 -1
  357. package/Shaders/ShadersInclude/pbrFragmentSamplersDeclaration.js +1 -0
  358. package/Shaders/ShadersInclude/pbrFragmentSamplersDeclaration.js.map +1 -1
  359. package/Shaders/ShadersInclude/pbrIBLFunctions.js +12 -0
  360. package/Shaders/ShadersInclude/pbrIBLFunctions.js.map +1 -1
  361. package/Shaders/ShadersInclude/pbrUboDeclaration.js +1 -1
  362. package/Shaders/ShadersInclude/pbrUboDeclaration.js.map +1 -1
  363. package/Shaders/ShadersInclude/pbrVertexDeclaration.js +3 -0
  364. package/Shaders/ShadersInclude/pbrVertexDeclaration.js.map +1 -1
  365. package/Shaders/geometry.vertex.js +6 -6
  366. package/Shaders/geometry.vertex.js.map +1 -1
  367. package/Shaders/gpuUpdateParticles.vertex.js +1 -1
  368. package/Shaders/gpuUpdateParticles.vertex.js.map +1 -1
  369. package/Shaders/lod.fragment.js +15 -2
  370. package/Shaders/lod.fragment.js.map +1 -1
  371. package/Shaders/lod3D.fragment.js +15 -2
  372. package/Shaders/lod3D.fragment.js.map +1 -1
  373. package/Shaders/lodCube.fragment.js +15 -2
  374. package/Shaders/lodCube.fragment.js.map +1 -1
  375. package/Shaders/openpbr.vertex.js +2 -0
  376. package/Shaders/openpbr.vertex.js.map +1 -1
  377. package/Shaders/pbr.fragment.js +12 -1
  378. package/Shaders/pbr.fragment.js.map +1 -1
  379. package/Shaders/pbr.vertex.js +2 -0
  380. package/Shaders/pbr.vertex.js.map +1 -1
  381. package/Shaders/textureMerger.fragment.js +28 -0
  382. package/Shaders/textureMerger.fragment.js.map +1 -1
  383. package/Shaders/textureProcessor.fragment.js +26 -4
  384. package/Shaders/textureProcessor.fragment.js.map +1 -1
  385. package/Shaders/volumetricLightScattering.fragment.js +1 -1
  386. package/Shaders/volumetricLightScattering.fragment.js.map +1 -1
  387. package/ShadersWGSL/ShadersInclude/bumpFragmentMainFunctions.js +2 -2
  388. package/ShadersWGSL/ShadersInclude/bumpFragmentMainFunctions.js.map +1 -1
  389. package/ShadersWGSL/ShadersInclude/bumpVertex.js +1 -1
  390. package/ShadersWGSL/ShadersInclude/bumpVertex.js.map +1 -1
  391. package/ShadersWGSL/ShadersInclude/bumpVertexDeclaration.js +1 -1
  392. package/ShadersWGSL/ShadersInclude/bumpVertexDeclaration.js.map +1 -1
  393. package/ShadersWGSL/ShadersInclude/hdrFilteringFunctions.js +1 -1
  394. package/ShadersWGSL/ShadersInclude/hdrFilteringFunctions.js.map +1 -1
  395. package/ShadersWGSL/ShadersInclude/helperFunctions.js +2 -2
  396. package/ShadersWGSL/ShadersInclude/helperFunctions.js.map +1 -1
  397. package/ShadersWGSL/ShadersInclude/lightFragment.js +44 -2
  398. package/ShadersWGSL/ShadersInclude/lightFragment.js.map +1 -1
  399. package/ShadersWGSL/ShadersInclude/lightUboDeclaration.js +17 -3
  400. package/ShadersWGSL/ShadersInclude/lightUboDeclaration.js.map +1 -1
  401. package/ShadersWGSL/ShadersInclude/lightVxUboDeclaration.js +12 -1
  402. package/ShadersWGSL/ShadersInclude/lightVxUboDeclaration.js.map +1 -1
  403. package/ShadersWGSL/ShadersInclude/openpbrBackgroundTransmission.js +1 -1
  404. package/ShadersWGSL/ShadersInclude/openpbrBackgroundTransmission.js.map +1 -1
  405. package/ShadersWGSL/ShadersInclude/pbrBlockFinalLitComponents.js +11 -1
  406. package/ShadersWGSL/ShadersInclude/pbrBlockFinalLitComponents.js.map +1 -1
  407. package/ShadersWGSL/ShadersInclude/pbrBlockNormalFinal.js +9 -0
  408. package/ShadersWGSL/ShadersInclude/pbrBlockNormalFinal.js.map +1 -1
  409. package/ShadersWGSL/ShadersInclude/pbrBlockReflectance.js +1 -1
  410. package/ShadersWGSL/ShadersInclude/pbrBlockReflectance.js.map +1 -1
  411. package/ShadersWGSL/ShadersInclude/pbrClusteredLightingFunctions.js +1 -1
  412. package/ShadersWGSL/ShadersInclude/pbrClusteredLightingFunctions.js.map +1 -1
  413. package/ShadersWGSL/ShadersInclude/pbrDirectLightingSetupFunctions.js +1 -1
  414. package/ShadersWGSL/ShadersInclude/pbrDirectLightingSetupFunctions.js.map +1 -1
  415. package/ShadersWGSL/ShadersInclude/pbrFragmentSamplersDeclaration.js +1 -0
  416. package/ShadersWGSL/ShadersInclude/pbrFragmentSamplersDeclaration.js.map +1 -1
  417. package/ShadersWGSL/ShadersInclude/pbrIBLFunctions.js +8 -0
  418. package/ShadersWGSL/ShadersInclude/pbrIBLFunctions.js.map +1 -1
  419. package/ShadersWGSL/ShadersInclude/pbrUboDeclaration.js +1 -1
  420. package/ShadersWGSL/ShadersInclude/pbrUboDeclaration.js.map +1 -1
  421. package/ShadersWGSL/ShadersInclude/prePassVertex.js +2 -2
  422. package/ShadersWGSL/ShadersInclude/prePassVertex.js.map +1 -1
  423. package/ShadersWGSL/ShadersInclude/prePassVertexDeclaration.js +1 -1
  424. package/ShadersWGSL/ShadersInclude/prePassVertexDeclaration.js.map +1 -1
  425. package/ShadersWGSL/ShadersInclude/sceneUboDeclaration.js +3 -1
  426. package/ShadersWGSL/ShadersInclude/sceneUboDeclaration.js.map +1 -1
  427. package/ShadersWGSL/ShadersInclude/shadowsVertex.js +16 -0
  428. package/ShadersWGSL/ShadersInclude/shadowsVertex.js.map +1 -1
  429. package/ShadersWGSL/default.fragment.js +4 -4
  430. package/ShadersWGSL/default.fragment.js.map +1 -1
  431. package/ShadersWGSL/default.vertex.js +1 -1
  432. package/ShadersWGSL/default.vertex.js.map +1 -1
  433. package/ShadersWGSL/gaussianSplatting.vertex.js +3 -3
  434. package/ShadersWGSL/gaussianSplatting.vertex.js.map +1 -1
  435. package/ShadersWGSL/gpuUpdateParticles.compute.js +1 -1
  436. package/ShadersWGSL/gpuUpdateParticles.compute.js.map +1 -1
  437. package/ShadersWGSL/gsSortCount.compute.d.ts +5 -0
  438. package/ShadersWGSL/gsSortCount.compute.js +19 -0
  439. package/ShadersWGSL/gsSortCount.compute.js.map +1 -0
  440. package/ShadersWGSL/gsSortKeys.compute.d.ts +5 -0
  441. package/ShadersWGSL/gsSortKeys.compute.js +49 -0
  442. package/ShadersWGSL/gsSortKeys.compute.js.map +1 -0
  443. package/ShadersWGSL/gsSortOutput.compute.d.ts +5 -0
  444. package/ShadersWGSL/gsSortOutput.compute.js +28 -0
  445. package/ShadersWGSL/gsSortOutput.compute.js.map +1 -0
  446. package/ShadersWGSL/gsSortScanLocal.compute.d.ts +5 -0
  447. package/ShadersWGSL/gsSortScanLocal.compute.js +23 -0
  448. package/ShadersWGSL/gsSortScanLocal.compute.js.map +1 -0
  449. package/ShadersWGSL/gsSortScanSums.compute.d.ts +5 -0
  450. package/ShadersWGSL/gsSortScanSums.compute.js +19 -0
  451. package/ShadersWGSL/gsSortScanSums.compute.js.map +1 -0
  452. package/ShadersWGSL/gsSortScatter.compute.d.ts +5 -0
  453. package/ShadersWGSL/gsSortScatter.compute.js +33 -0
  454. package/ShadersWGSL/gsSortScatter.compute.js.map +1 -0
  455. package/ShadersWGSL/lod.fragment.js +14 -2
  456. package/ShadersWGSL/lod.fragment.js.map +1 -1
  457. package/ShadersWGSL/lod3D.fragment.js +14 -2
  458. package/ShadersWGSL/lod3D.fragment.js.map +1 -1
  459. package/ShadersWGSL/lodCube.fragment.js +14 -2
  460. package/ShadersWGSL/lodCube.fragment.js.map +1 -1
  461. package/ShadersWGSL/openpbr.vertex.js +3 -1
  462. package/ShadersWGSL/openpbr.vertex.js.map +1 -1
  463. package/ShadersWGSL/pbr.fragment.js +11 -0
  464. package/ShadersWGSL/pbr.fragment.js.map +1 -1
  465. package/ShadersWGSL/pbr.vertex.js +3 -1
  466. package/ShadersWGSL/pbr.vertex.js.map +1 -1
  467. package/ShadersWGSL/textureMerger.fragment.js +40 -4
  468. package/ShadersWGSL/textureMerger.fragment.js.map +1 -1
  469. package/ShadersWGSL/textureProcessor.fragment.js +26 -4
  470. package/ShadersWGSL/textureProcessor.fragment.js.map +1 -1
  471. package/Sprites/spriteRenderer.js +15 -5
  472. package/Sprites/spriteRenderer.js.map +1 -1
  473. package/package.json +1 -1
  474. package/scene.pure.d.ts +23 -1
  475. package/scene.pure.js +83 -1
  476. package/scene.pure.js.map +1 -1
@@ -0,0 +1,912 @@
1
+
2
+ import { ComputeShader } from "../../Compute/computeShader.pure.js";
3
+ import { StorageBuffer } from "../../Buffers/storageBuffer.js";
4
+ import { Buffer } from "../../Buffers/buffer.pure.js";
5
+ import { RegisterEnginesWebGPUExtensionsEngineComputeShader } from "../../Engines/WebGPU/Extensions/engine.computeShader.pure.js";
6
+ import { Logger } from "../../Misc/logger.js";
7
+ const WorkgroupSize = 256;
8
+ // One workgroup sorts a block of WorkgroupSize threads x 4 contiguous keys. Must match the gsSort*.compute.fx shaders.
9
+ const SortBlockSize = 1024;
10
+ const RadixBits = 4;
11
+ const RadixBins = 16;
12
+ // One scan chunk covers 1024 histogram entries (16 bins x 64 blocks). The top-level scan handles at most 256 chunks.
13
+ const BlocksPerScanChunk = 64;
14
+ const MaxScanChunks = 256;
15
+ const MaxSortKeyCount = SortBlockSize * BlocksPerScanChunk * MaxScanChunks;
16
+ const MaxDispatchGroupsPerDimension = 65535;
17
+ // Source indices travel as float32 in the vertex buffer, so they must stay exactly representable.
18
+ const MaxFloatExactSplatCount = 1 << 24;
19
+ const DefaultMaxStorageBufferSize = 134217728;
20
+ const MinKeyBits = 8;
21
+ const MaxKeyBits = 24;
22
+ const DefaultKeyBits = 16;
23
+ const ParamsByteSize = 80;
24
+ const PassParamsByteSize = 16;
25
+ const MinCapacity = 16;
26
+ const MinDepthRange = 1e-12;
27
+ /**
28
+ * Number of keys bits clamped to the supported range.
29
+ * @param keyBits requested number of sort key bits
30
+ * @returns the clamped, integral number of key bits
31
+ * @internal
32
+ */
33
+ export function _ClampGpuSortKeyBits(keyBits) {
34
+ return Math.min(MaxKeyBits, Math.max(MinKeyBits, Math.round(keyBits)));
35
+ }
36
+ /**
37
+ * Number of radix passes needed to sort keys of a given size.
38
+ * @param keyBits number of bits of the sort keys
39
+ * @returns the number of 4-bit radix passes
40
+ * @internal
41
+ */
42
+ export function _GetGpuSortPassCount(keyBits) {
43
+ return Math.ceil(_ClampGpuSortKeyBits(keyBits) / RadixBits);
44
+ }
45
+ /**
46
+ * Count of output slots: the active count rounded up to a multiple of 16 (16 splats per instance), at least 16.
47
+ * @param activeCount number of splats to render
48
+ * @returns the padded count
49
+ * @internal
50
+ */
51
+ export function _GetGpuSortPaddedCount(activeCount) {
52
+ return Math.max((activeCount + 15) & ~15, 16);
53
+ }
54
+ /**
55
+ * Packs flat `[start0, count0, start1, count1, ...]` splat intervals for the key shader. Each GPU entry is `(exclusive prefix of the counts, start)`.
56
+ * Empty intervals are dropped and intervals are clamped to `[0, vertexCount)`.
57
+ * @param intervals flat source-splat intervals (start, count pairs)
58
+ * @param vertexCount number of splats in the mesh
59
+ * @returns the packed entries, the number of entries and the total number of active splats
60
+ * @internal
61
+ */
62
+ export function _PackGpuSortIntervals(intervals, vertexCount) {
63
+ const data = new Uint32Array(Math.max(intervals.length & ~1, 2));
64
+ let count = 0;
65
+ let total = 0;
66
+ for (let i = 0; i + 1 < intervals.length; i += 2) {
67
+ const start = Math.min(Math.max(intervals[i], 0), vertexCount);
68
+ const length = Math.min(Math.max(intervals[i + 1], 0), vertexCount - start);
69
+ if (length > 0) {
70
+ data[count * 2] = total;
71
+ data[count * 2 + 1] = start;
72
+ count++;
73
+ total += length;
74
+ }
75
+ }
76
+ return { data, count, total };
77
+ }
78
+ /**
79
+ * Computes the coefficients of the depth of a splat center: `depth = dot(coef.xyz, center) + coef.w`, in the same space and sign convention as the CPU sort worker
80
+ * (the signed distance along the camera forward axis, negated in right-handed scenes, so a larger value is farther).
81
+ * @param world world matrix (array of 16 numbers) transforming the splat center
82
+ * @param view view matrix (array of 16 numbers)
83
+ * @param depthSign 1 for left-handed scenes, -1 for right-handed scenes
84
+ * @param cameraPosition world camera position, or null to use the view matrix translation
85
+ * @param out receives the 4 coefficients
86
+ * @param offset index of the first coefficient in out
87
+ * @param worldOffset index of the first element of the world matrix in world (defaults to 0), so a matrix can be read from a flat array without creating a view
88
+ * @internal
89
+ */
90
+ export function _ComputeGpuSortDepthCoefficients(world, view, depthSign, cameraPosition, out, offset, worldOffset = 0) {
91
+ const fx = view[2];
92
+ const fy = view[6];
93
+ const fz = view[10];
94
+ const w = worldOffset;
95
+ out[offset] = (fx * world[w] + fy * world[w + 1] + fz * world[w + 2]) * depthSign;
96
+ out[offset + 1] = (fx * world[w + 4] + fy * world[w + 5] + fz * world[w + 6]) * depthSign;
97
+ out[offset + 2] = (fx * world[w + 8] + fy * world[w + 9] + fz * world[w + 10]) * depthSign;
98
+ const translation = fx * world[w + 12] + fy * world[w + 13] + fz * world[w + 14];
99
+ const d = cameraPosition ? translation - (fx * cameraPosition[0] + fy * cameraPosition[1] + fz * cameraPosition[2]) : translation + view[14];
100
+ out[offset + 3] = d * depthSign;
101
+ }
102
+ /**
103
+ * Computes the interval of depths reached by the points of a box, for one or several sets of depth coefficients.
104
+ * @param coefficients depth coefficients (4 per set)
105
+ * @param setCount number of coefficient sets
106
+ * @param boundsMin box minimum (xyz)
107
+ * @param boundsMax box maximum (xyz)
108
+ * @param result optional object receiving the interval, to avoid an allocation when called every frame
109
+ * @returns the min and max depths (the result object when provided)
110
+ * @internal
111
+ */
112
+ export function _ComputeGpuSortDepthRange(coefficients, setCount, boundsMin, boundsMax, result = { min: 0, max: 0 }) {
113
+ let min = Infinity;
114
+ let max = -Infinity;
115
+ for (let set = 0; set < setCount; set++) {
116
+ let setMin = coefficients[set * 4 + 3];
117
+ let setMax = setMin;
118
+ for (let axis = 0; axis < 3; axis++) {
119
+ const a = coefficients[set * 4 + axis] * boundsMin[axis];
120
+ const b = coefficients[set * 4 + axis] * boundsMax[axis];
121
+ setMin += Math.min(a, b);
122
+ setMax += Math.max(a, b);
123
+ }
124
+ min = Math.min(min, setMin);
125
+ max = Math.max(max, setMax);
126
+ }
127
+ result.min = min;
128
+ result.max = max;
129
+ return result;
130
+ }
131
+ /**
132
+ * Scale converting a depth distance to a sort key: `key = (depthMax - depth) * scale`, so the farthest splat gets key 0 (sorted first).
133
+ * @param depthMin smallest depth
134
+ * @param depthMax largest depth
135
+ * @param keyBits number of bits of the sort keys
136
+ * @returns the scale, 0 when the depth range is degenerate (all keys are 0, like the CPU worker)
137
+ * @internal
138
+ */
139
+ export function _ComputeGpuSortKeyScale(depthMin, depthMax, keyBits) {
140
+ const range = depthMax - depthMin;
141
+ return range > MinDepthRange ? (Math.pow(2, _ClampGpuSortKeyBits(keyBits)) - 1) / range : 0;
142
+ }
143
+ /**
144
+ * Inverse of the SOG means log-transform, applied to a quantization range bound.
145
+ * @param value log-encoded value
146
+ * @returns the decoded value
147
+ * @internal
148
+ */
149
+ export function _DecodeGpuSortSogMean(value) {
150
+ return Math.sign(value) * (Math.exp(Math.abs(value)) - 1);
151
+ }
152
+ /**
153
+ * Gets the number of splats a GPU sorter can handle on an engine: limited by the maximum storage buffer binding size (4 bytes per splat),
154
+ * and by 2^24 so that source indices are exactly representable as float32 in the instanced vertex buffer.
155
+ * @param engine the engine
156
+ * @returns the maximum number of splats (a multiple of 16)
157
+ */
158
+ export function GetGaussianSplattingGpuSorterMaxSplatCount(engine) {
159
+ const limits = engine.currentLimits;
160
+ const maxBytes = limits
161
+ ? Math.min(limits.maxStorageBufferBindingSize ?? DefaultMaxStorageBufferSize, limits.maxBufferSize ?? DefaultMaxStorageBufferSize)
162
+ : DefaultMaxStorageBufferSize;
163
+ return Math.min(MaxFloatExactSplatCount, MaxSortKeyCount, Math.floor(maxBytes / Float32Array.BYTES_PER_ELEMENT) & ~15);
164
+ }
165
+ function _RoundUp16(value) {
166
+ return (Math.ceil(value) + 15) & ~15;
167
+ }
168
+ /**
169
+ * Per-view GPU buffer receiving a sorted splat index list. It can be bound as the four instanced `splatIndex0` ... `splatIndex3` vertex attributes
170
+ * of the Gaussian Splatting vertex shader (16 splats per instance), in place of the CPU-uploaded index buffer.
171
+ *
172
+ * Create it with {@link GaussianSplattingGpuSorter.createOutput}. After each successful sort, if {@link buffersVersion} changed,
173
+ * the vertex buffers were recreated (the output grew) and must be bound again.
174
+ */
175
+ export class GaussianSplattingGpuSortOutput {
176
+ /**
177
+ * @param engine the WebGPU engine
178
+ * @param label debug label
179
+ * @internal
180
+ */
181
+ constructor(engine, label) {
182
+ this._storageBuffer = null;
183
+ this._vertexBuffers = [];
184
+ this._wrapper = null;
185
+ this._capacity = 0;
186
+ this._buffersVersion = 0;
187
+ /** @internal */
188
+ this._sortedPaddedCount = 0;
189
+ /** @internal */
190
+ this._coefsBuffer = null;
191
+ /** @internal */
192
+ this._coefsCapacity = 0;
193
+ /** @internal */
194
+ this._keysCs = null;
195
+ /** @internal */
196
+ this._keysCsSog = false;
197
+ /** @internal */
198
+ this._keysCsCompound = false;
199
+ /** @internal Texture views used by the keys context, which may change without replacing their BaseTexture objects. */
200
+ this._keysCsCentersView = null;
201
+ /** @internal */
202
+ this._keysCsMeansHighView = null;
203
+ /** @internal */
204
+ this._keysCsPartIndicesView = null;
205
+ /** @internal Sorter binding version the compute shaders of this output were last bound with. */
206
+ this._boundSorterVersion = -1;
207
+ /** @internal Buffers version of the output storage buffer the output shader was last bound with. */
208
+ this._boundBuffersVersion = -1;
209
+ /** @internal */
210
+ this._boundCoefsBuffer = null;
211
+ /** @internal */
212
+ this._boundKeysCs = null;
213
+ /** @internal */
214
+ this._lastSortError = false;
215
+ /** @internal */
216
+ this._onDisposed = null;
217
+ this._disposed = false;
218
+ this._engine = engine;
219
+ this._label = label;
220
+ this._paramsBuffer = new StorageBuffer(engine, ParamsByteSize, 3, label + "_params");
221
+ this._outputCs = new ComputeShader(label + "_output", engine, "gsSortOutput", {
222
+ bindingsMapping: { params: { group: 0, binding: 0 }, vals: { group: 0, binding: 1 }, indexOut: { group: 0, binding: 2 } },
223
+ });
224
+ }
225
+ /**
226
+ * The buffer holding the sorted splat indices as float32 (back-to-front), padded to a multiple of 16 with the empty splat index.
227
+ */
228
+ get buffer() {
229
+ return this._storageBuffer;
230
+ }
231
+ /**
232
+ * The 4 instanced vertex buffers `splatIndex0` ... `splatIndex3` (vec4 each, stride 16 floats) viewing {@link buffer}.
233
+ */
234
+ get vertexBuffers() {
235
+ return this._vertexBuffers;
236
+ }
237
+ /**
238
+ * Number of output slots written by the last successful sort: a multiple of 16 (0 before the first successful sort).
239
+ */
240
+ get paddedCount() {
241
+ return this._sortedPaddedCount;
242
+ }
243
+ /**
244
+ * Number of instances to draw (16 splats per instance) after the last successful sort.
245
+ */
246
+ get instanceCount() {
247
+ return this._sortedPaddedCount >> 4;
248
+ }
249
+ /**
250
+ * Incremented each time the underlying buffer and vertex buffers are recreated.
251
+ */
252
+ get buffersVersion() {
253
+ return this._buffersVersion;
254
+ }
255
+ /**
256
+ * Creates (or grows) the GPU buffer so it can hold the given number of slots.
257
+ * @param paddedCount number of slots
258
+ * @param maxCapacity maximum capacity allowed by the device limits
259
+ * @internal
260
+ */
261
+ _ensureCapacity(paddedCount, maxCapacity) {
262
+ if (this._storageBuffer && this._capacity >= paddedCount) {
263
+ return;
264
+ }
265
+ const capacity = Math.max(paddedCount, Math.min(_RoundUp16(this._capacity * 1.5), maxCapacity));
266
+ this._releaseBuffers();
267
+ this._capacity = capacity;
268
+ this._storageBuffer = new StorageBuffer(this._engine, capacity * Float32Array.BYTES_PER_ELEMENT, 8 | 3, this._label + "_indices");
269
+ // The wrapper does not own the GPU buffer: it is released through the StorageBuffer only.
270
+ this._wrapper = new Buffer(this._engine, this._storageBuffer.getBuffer(), false, 16, true, true);
271
+ for (let i = 0; i < 4; i++) {
272
+ this._vertexBuffers.push(this._wrapper.createVertexBuffer("splatIndex" + i, i * 4, 4));
273
+ }
274
+ this._buffersVersion++;
275
+ }
276
+ /**
277
+ * Releases the GPU resources.
278
+ */
279
+ dispose() {
280
+ if (this._disposed) {
281
+ return;
282
+ }
283
+ this._disposed = true;
284
+ this._onDisposed?.();
285
+ this._onDisposed = null;
286
+ this._releaseBuffers();
287
+ this._paramsBuffer.dispose();
288
+ this._coefsBuffer?.dispose();
289
+ this._coefsBuffer = null;
290
+ this._keysCs = null;
291
+ }
292
+ _releaseBuffers() {
293
+ for (const vertexBuffer of this._vertexBuffers) {
294
+ vertexBuffer.dispose();
295
+ }
296
+ this._vertexBuffers = [];
297
+ // A device restoration rebuilds the wrapper with its own buffer, which is no longer the storage buffer and must be released.
298
+ if (this._wrapper && this._wrapper.getBuffer() !== this._storageBuffer?.getBuffer()) {
299
+ this._wrapper.dispose();
300
+ }
301
+ this._wrapper = null;
302
+ this._storageBuffer?.dispose();
303
+ this._storageBuffer = null;
304
+ }
305
+ }
306
+ function _Dispatch(cs, groups) {
307
+ const dispatched = groups <= MaxDispatchGroupsPerDimension
308
+ ? cs.dispatch(Math.max(groups, 1), 1, 1)
309
+ : cs.dispatch(MaxDispatchGroupsPerDimension, Math.ceil(groups / MaxDispatchGroupsPerDimension), 1);
310
+ if (dispatched) {
311
+ // The context check leaves this set when rebinding reuses the same resources.
312
+ cs.triggerContextRebuild = false;
313
+ }
314
+ return dispatched;
315
+ }
316
+ function _IsShaderReady(cs) {
317
+ if (cs.fastMode) {
318
+ return true;
319
+ }
320
+ if (!cs.isReady()) {
321
+ return false;
322
+ }
323
+ cs.fastMode = true;
324
+ // Binding setters mark the context dirty, but fastMode skips that check. Rebuild it on the first dispatch after each rebind.
325
+ cs.triggerContextRebuild = true;
326
+ return true;
327
+ }
328
+ /**
329
+ * WebGPU compute depth sorter for Gaussian Splatting. It reproduces the ordering of the CPU sort worker (back-to-front counting sort) entirely on the GPU,
330
+ * and writes the sorted splat indices in a vertex buffer ready to be used as the instanced `splatIndex` attributes ({@link GaussianSplattingGpuSortOutput}).
331
+ *
332
+ * Pipeline of a sort (all dispatches are enqueued on the engine's command encoder, without any CPU readback):
333
+ * 1. keys: for each active splat, compute the view depth and quantize it to a `keyBits`-bit key (farthest = smallest). Supports splat intervals,
334
+ * compound parts (per-part matrices) and SOG decoded means.
335
+ * 2. a stable LSD radix sort with 4-bit digits, `ceil(keyBits / 4)` passes of count, scan (2 levels) and scatter. No subgroup operation is required.
336
+ * 3. output: writes the sorted indices as float32, padding to a multiple of 16 with `vertexCount`.
337
+ *
338
+ * Usage constraints:
339
+ * - {@link sort} ends the current render pass: call it outside of any render pass (e.g. in `onBeforeRenderObservable` / `onBeforeCameraRenderObservable`).
340
+ * - Uniform-like data is written with queue writes, which take effect before the whole frame's commands. So call {@link sort} at most once per output and per frame, and do not
341
+ * change the source, the intervals or the part matrices between two sorts of the same frame.
342
+ * - If the textures given to {@link setSource} are recreated, call {@link setSource} again.
343
+ * - The compute shaders and the WebGPU compute engine extension are loaded by {@link GaussianSplattingGpuSorter.LoadDependenciesAsync}: await it before the first {@link sort}.
344
+ * Until it has completed, {@link sort} returns false without enqueuing anything.
345
+ * @experimental
346
+ */
347
+ export class GaussianSplattingGpuSorter {
348
+ /**
349
+ * Whether GPU sorting is available on an engine: a WebGPU engine with compute shader support.
350
+ * @param engine the engine
351
+ * @returns true if a {@link GaussianSplattingGpuSorter} can be created
352
+ */
353
+ static IsSupported(engine) {
354
+ return !!engine && engine.isWebGPU && !!engine.getCaps().supportComputeShaders;
355
+ }
356
+ /**
357
+ * Gets the maximum number of splats the sorter can sort on an engine.
358
+ * @param engine the engine
359
+ * @returns the maximum splat count
360
+ */
361
+ static GetMaxSupportedSplatCount(engine) {
362
+ return GetGaussianSplattingGpuSorterMaxSplatCount(engine);
363
+ }
364
+ /**
365
+ * Registers the WebGPU compute engine extension and loads the compute shaders of the sorter. The result is cached: calling it again returns the same promise.
366
+ * It must have completed before the first {@link sort} (which returns false until then). If loading fails, the promise rejects and the next call retries.
367
+ * @returns a promise resolved when the dependencies are ready
368
+ */
369
+ static async LoadDependenciesAsync() {
370
+ if (GaussianSplattingGpuSorter._DependenciesReady) {
371
+ return;
372
+ }
373
+ GaussianSplattingGpuSorter._DependenciesPromise ?? (GaussianSplattingGpuSorter._DependenciesPromise = (async () => {
374
+ try {
375
+ RegisterEnginesWebGPUExtensionsEngineComputeShader();
376
+ await Promise.all([
377
+ import("../../ShadersWGSL/gsSortKeys.compute.js"),
378
+ import("../../ShadersWGSL/gsSortCount.compute.js"),
379
+ import("../../ShadersWGSL/gsSortScanLocal.compute.js"),
380
+ import("../../ShadersWGSL/gsSortScanSums.compute.js"),
381
+ import("../../ShadersWGSL/gsSortScatter.compute.js"),
382
+ import("../../ShadersWGSL/gsSortOutput.compute.js"),
383
+ ]);
384
+ GaussianSplattingGpuSorter._DependenciesReady = true;
385
+ }
386
+ catch (e) {
387
+ GaussianSplattingGpuSorter._DependenciesPromise = null;
388
+ throw e;
389
+ }
390
+ })());
391
+ await GaussianSplattingGpuSorter._DependenciesPromise;
392
+ }
393
+ /**
394
+ * Creates a GPU sorter. Shaders are compiled asynchronously: {@link sort} returns false until they are ready.
395
+ * Await {@link GaussianSplattingGpuSorter.LoadDependenciesAsync} before the first {@link sort}.
396
+ * @param engine the WebGPU engine
397
+ * @param name debug name
398
+ * @param keyBits number of bits of the depth sort keys (8 to 24, default 16). Each 4 bits cost one radix pass; 16 bits is enough for most scenes.
399
+ */
400
+ constructor(engine, name = "GaussianSplattingGpuSorter", keyBits = DefaultKeyBits) {
401
+ this._vertexCount = 0;
402
+ this._textureWidth = 0;
403
+ this._centersTexture = null;
404
+ this._meansHighTexture = null;
405
+ this._partIndicesTexture = null;
406
+ this._meansMin = new Float32Array(4);
407
+ this._meansMax = new Float32Array(4);
408
+ this._boundsMin = null;
409
+ this._boundsMax = null;
410
+ this._partMatrices = null;
411
+ this._partCount = 0;
412
+ this._rawIntervals = null;
413
+ this._packedIntervals = null;
414
+ this._intervalCount = 0;
415
+ this._intervalsDirty = true;
416
+ this._intervalsValid = true;
417
+ this._activeCount = 0;
418
+ // Incremented whenever a buffer or texture bound to the compute shaders is created, replaced or released, so the shaders are only rebound when needed.
419
+ this._bindingsVersion = 0;
420
+ this._sortShadersBoundVersion = -1;
421
+ this._capacity = 0;
422
+ this._keysA = null;
423
+ this._keysB = null;
424
+ this._valsA = null;
425
+ this._valsB = null;
426
+ this._sumTable = null;
427
+ this._intervalsBuffer = null;
428
+ this._intervalsCapacity = 0;
429
+ this._passParams = [];
430
+ this._passParamsActiveCount = -1;
431
+ this._passData = new Uint32Array(4);
432
+ this._countCs = [];
433
+ this._scatterCs = [];
434
+ this._paramsData = new ArrayBuffer(ParamsByteSize);
435
+ this._paramsU32 = new Uint32Array(this._paramsData);
436
+ this._paramsF32 = new Float32Array(this._paramsData);
437
+ this._coefs = new Float32Array(4);
438
+ this._depthRange = { min: 0, max: 0 };
439
+ this._outputs = [];
440
+ this._disposed = false;
441
+ if (!GaussianSplattingGpuSorter.IsSupported(engine)) {
442
+ throw new Error("GaussianSplattingGpuSorter requires a WebGPU engine with compute shader support.");
443
+ }
444
+ // ComputeShader creates its compute context on construction, so the engine extension must be registered first.
445
+ RegisterEnginesWebGPUExtensionsEngineComputeShader();
446
+ this._engine = engine;
447
+ this._name = name;
448
+ this._keyBits = _ClampGpuSortKeyBits(keyBits);
449
+ this._passCount = _GetGpuSortPassCount(this._keyBits);
450
+ this._maxSplatCount = GetGaussianSplattingGpuSorterMaxSplatCount(engine);
451
+ const limits = this._engine.currentLimits;
452
+ this._maxIntervalCount = Math.floor(Math.min(limits?.maxStorageBufferBindingSize ?? DefaultMaxStorageBufferSize, limits?.maxBufferSize ?? DefaultMaxStorageBufferSize) / (2 * Uint32Array.BYTES_PER_ELEMENT));
453
+ const passBindings = { params: { group: 0, binding: 0 } };
454
+ this._chunkSums = new StorageBuffer(this._engine, MaxScanChunks * Uint32Array.BYTES_PER_ELEMENT, 3, name + "_chunkSums");
455
+ for (let pass = 0; pass < this._passCount; pass++) {
456
+ this._passParams.push(new StorageBuffer(this._engine, PassParamsByteSize, 3, name + "_passParams" + pass));
457
+ this._countCs.push(new ComputeShader(name + "_count" + pass, engine, "gsSortCount", {
458
+ bindingsMapping: { ...passBindings, keysIn: { group: 0, binding: 1 }, sumTable: { group: 0, binding: 2 } },
459
+ }));
460
+ this._scatterCs.push(new ComputeShader(name + "_scatter" + pass, engine, "gsSortScatter", {
461
+ bindingsMapping: {
462
+ ...passBindings,
463
+ keysIn: { group: 0, binding: 1 },
464
+ valsIn: { group: 0, binding: 2 },
465
+ keysOut: { group: 0, binding: 3 },
466
+ valsOut: { group: 0, binding: 4 },
467
+ sumTable: { group: 0, binding: 5 },
468
+ chunkSums: { group: 0, binding: 6 },
469
+ },
470
+ }));
471
+ }
472
+ this._scanLocalCs = new ComputeShader(name + "_scanLocal", engine, "gsSortScanLocal", {
473
+ bindingsMapping: { ...passBindings, sumTable: { group: 0, binding: 1 }, chunkSums: { group: 0, binding: 2 } },
474
+ });
475
+ this._scanSumsCs = new ComputeShader(name + "_scanSums", engine, "gsSortScanSums", { bindingsMapping: { ...passBindings, chunkSums: { group: 0, binding: 1 } } });
476
+ }
477
+ /**
478
+ * Number of splats rendered after applying the intervals (the number of keys sorted).
479
+ */
480
+ get activeCount() {
481
+ return this._activeCount;
482
+ }
483
+ /**
484
+ * Number of output slots (activeCount rounded up to a multiple of 16).
485
+ */
486
+ get paddedCount() {
487
+ return _GetGpuSortPaddedCount(this._activeCount);
488
+ }
489
+ /**
490
+ * Number of bits of the depth sort keys.
491
+ */
492
+ get keyBits() {
493
+ return this._keyBits;
494
+ }
495
+ /**
496
+ * Sets the splat data to sort.
497
+ * @param source the source textures and layout
498
+ * @returns false (and logs an error) if the source or active interval count exceeds {@link GaussianSplattingGpuSorter.GetMaxSupportedSplatCount}
499
+ */
500
+ setSource(source) {
501
+ if (source.vertexCount > this._maxSplatCount) {
502
+ Logger.Error(`${this._name}: ${source.vertexCount} splats exceeds the GPU sorter limit of ${this._maxSplatCount}.`);
503
+ return false;
504
+ }
505
+ this._vertexCount = source.vertexCount;
506
+ this._textureWidth = source.textureWidth;
507
+ this._bindingsVersion++;
508
+ this._centersTexture = source.centersTexture;
509
+ this._partIndicesTexture = source.partIndicesTexture ?? null;
510
+ this._meansHighTexture = source.sog?.meansHighTexture ?? null;
511
+ this._boundsMin = null;
512
+ this._boundsMax = null;
513
+ if (source.sog) {
514
+ this._meansMin.fill(0);
515
+ this._meansMax.fill(0);
516
+ this._boundsMin = new Float32Array(3);
517
+ this._boundsMax = new Float32Array(3);
518
+ for (let i = 0; i < 3; i++) {
519
+ this._meansMin[i] = source.sog.meansMin[i];
520
+ this._meansMax[i] = source.sog.meansMax[i];
521
+ this._boundsMin[i] = _DecodeGpuSortSogMean(source.sog.meansMin[i]);
522
+ this._boundsMax[i] = _DecodeGpuSortSogMean(source.sog.meansMax[i]);
523
+ }
524
+ }
525
+ else if (source.boundsMin && source.boundsMax) {
526
+ this._boundsMin = Float32Array.from(source.boundsMin);
527
+ this._boundsMax = Float32Array.from(source.boundsMax);
528
+ }
529
+ return this._refreshIntervals();
530
+ }
531
+ /**
532
+ * Sets the transform of each part of a compound mesh. Used instead of the world matrix given to {@link sort} when a part indices texture was set in {@link setSource}.
533
+ * The matrices are copied: call this again when they change.
534
+ * @param matrices one matrix per part, or a flat array of 16 floats per part, or null for a non-compound mesh
535
+ */
536
+ setPartMatrices(matrices) {
537
+ if (!matrices || matrices.length === 0) {
538
+ this._partCount = 0;
539
+ return;
540
+ }
541
+ const isFlat = typeof matrices[0] === "number";
542
+ const count = isFlat ? Math.floor(matrices.length / 16) : matrices.length;
543
+ if (!this._partMatrices || this._partMatrices.length < count * 16) {
544
+ this._partMatrices = new Float32Array(count * 16);
545
+ }
546
+ for (let i = 0; i < count; i++) {
547
+ for (let j = 0; j < 16; j++) {
548
+ this._partMatrices[i * 16 + j] = isFlat ? matrices[i * 16 + j] : matrices[i].m[j];
549
+ }
550
+ }
551
+ this._partCount = count;
552
+ }
553
+ /**
554
+ * Restricts the sort to ranges of source splats, like the CPU worker's `intervals` message.
555
+ * @param intervals flat `[start0, count0, start1, count1, ...]` (start, COUNT pairs), or null to sort every splat
556
+ * @returns false (and logs an error) if the packed intervals or padded active count exceed the scan or device storage-buffer limits.
557
+ * Overlapping intervals count each occurrence. Sorting is disabled until valid intervals or a valid source are set.
558
+ */
559
+ setIntervals(intervals) {
560
+ this._rawIntervals = intervals ? Uint32Array.from(intervals) : null;
561
+ return this._refreshIntervals();
562
+ }
563
+ /**
564
+ * Creates an output receiving the sorted indices of one view. Use one output per camera that is sorted independently.
565
+ * @returns the new output
566
+ */
567
+ createOutput() {
568
+ if (!this._intervalsValid) {
569
+ throw new Error(`${this._name}: cannot create an output for unsupported active intervals.`);
570
+ }
571
+ const output = new GaussianSplattingGpuSortOutput(this._engine, this._name + "_out" + this._outputs.length);
572
+ output._ensureCapacity(this.paddedCount, this._maxSplatCount);
573
+ this._outputs.push(output);
574
+ output._onDisposed = () => {
575
+ const index = this._outputs.indexOf(output);
576
+ if (index >= 0) {
577
+ this._outputs.splice(index, 1);
578
+ }
579
+ };
580
+ return output;
581
+ }
582
+ /**
583
+ * Enqueues the sort of the active splats for a view. Call it outside of any render pass, once per output and per frame.
584
+ * @param output the output receiving the sorted indices
585
+ * @param worldMatrix world matrix of the mesh (ignored for compound meshes, which use the part matrices)
586
+ * @param viewMatrix view matrix of the camera
587
+ * @param options handedness, camera position and depth range
588
+ * @returns false if nothing was enqueued (unsupported active intervals, shaders still compiling, no source, or no depth range), true otherwise
589
+ */
590
+ sort(output, worldMatrix, viewMatrix, options) {
591
+ if (this._disposed || !this._intervalsValid || !this._centersTexture || !GaussianSplattingGpuSorter._DependenciesReady) {
592
+ return false;
593
+ }
594
+ const sog = !!this._meansHighTexture;
595
+ const compound = !!this._partIndicesTexture && this._partCount > 0 && !!this._partMatrices;
596
+ const coefCount = compound ? this._partCount : 1;
597
+ const activeCount = this._activeCount;
598
+ const paddedCount = this.paddedCount;
599
+ this._ensureCapacity(Math.max(activeCount, MinCapacity));
600
+ output._ensureCapacity(paddedCount, this._maxSplatCount);
601
+ this._ensureIntervalsBuffer();
602
+ this._ensureCoefsBuffer(output, coefCount);
603
+ const keysCs = this._getKeysComputeShader(output, sog, compound);
604
+ this._bindResources(output, keysCs, sog, compound);
605
+ if (!this._isReady(keysCs, output)) {
606
+ return false;
607
+ }
608
+ const depthSign = options?.rightHanded ? -1 : 1;
609
+ const cameraPosition = options?.cameraPosition ?? null;
610
+ if (this._coefs.length < coefCount * 4) {
611
+ this._coefs = new Float32Array(coefCount * 4);
612
+ }
613
+ if (compound) {
614
+ const partMatrices = this._partMatrices;
615
+ for (let i = 0; i < coefCount; i++) {
616
+ _ComputeGpuSortDepthCoefficients(partMatrices, viewMatrix.m, depthSign, cameraPosition, this._coefs, i * 4, i * 16);
617
+ }
618
+ }
619
+ else {
620
+ _ComputeGpuSortDepthCoefficients(worldMatrix.m, viewMatrix.m, depthSign, cameraPosition, this._coefs, 0);
621
+ }
622
+ let range = options?.depthRange;
623
+ if (!range && this._boundsMin && this._boundsMax) {
624
+ range = _ComputeGpuSortDepthRange(this._coefs, coefCount, this._boundsMin, this._boundsMax, this._depthRange);
625
+ }
626
+ if (!range) {
627
+ if (!output._lastSortError) {
628
+ Logger.Error(`${this._name}: no depth range available. Provide options.depthRange or source bounds.`);
629
+ output._lastSortError = true;
630
+ }
631
+ return false;
632
+ }
633
+ output._lastSortError = false;
634
+ this._writeParams(output, coefCount, range.min, range.max);
635
+ output._coefsBuffer.update(this._coefs, 0, coefCount * 4 * Float32Array.BYTES_PER_ELEMENT);
636
+ this._writeIntervals();
637
+ this._writePassParams(activeCount);
638
+ if (activeCount > 0 && !this._dispatchSort(keysCs, activeCount)) {
639
+ return false;
640
+ }
641
+ if (!_Dispatch(output._outputCs, Math.ceil(paddedCount / WorkgroupSize))) {
642
+ return false;
643
+ }
644
+ output._sortedPaddedCount = paddedCount;
645
+ return true;
646
+ }
647
+ /**
648
+ * Releases all the GPU resources, including the outputs created by {@link createOutput}.
649
+ */
650
+ dispose() {
651
+ this._disposed = true;
652
+ const outputs = this._outputs.slice();
653
+ for (const output of outputs) {
654
+ output.dispose();
655
+ }
656
+ this._outputs.length = 0;
657
+ this._releaseSortBuffers();
658
+ this._intervalsBuffer?.dispose();
659
+ this._intervalsBuffer = null;
660
+ this._chunkSums.dispose();
661
+ for (const buffer of this._passParams) {
662
+ buffer.dispose();
663
+ }
664
+ this._passParams.length = 0;
665
+ this._centersTexture = null;
666
+ this._meansHighTexture = null;
667
+ this._partIndicesTexture = null;
668
+ }
669
+ _refreshIntervals() {
670
+ if (this._rawIntervals) {
671
+ const packed = _PackGpuSortIntervals(this._rawIntervals, this._vertexCount);
672
+ this._packedIntervals = packed.data;
673
+ this._intervalCount = packed.count;
674
+ this._activeCount = packed.total;
675
+ }
676
+ else {
677
+ this._packedIntervals = null;
678
+ this._intervalCount = 0;
679
+ this._activeCount = this._vertexCount;
680
+ }
681
+ this._intervalsDirty = true;
682
+ this._intervalsValid = this._activeCount <= this._maxSplatCount && this.paddedCount <= this._maxSplatCount;
683
+ if (!this._intervalsValid) {
684
+ Logger.Error(`${this._name}: ${this._activeCount} active splats exceeds the GPU sorter limit of ${this._maxSplatCount}.`);
685
+ }
686
+ if (Math.max(this._intervalCount, 2) > this._maxIntervalCount) {
687
+ this._intervalsValid = false;
688
+ Logger.Error(`${this._name}: ${this._intervalCount} intervals exceeds the GPU sorter limit of ${this._maxIntervalCount}.`);
689
+ }
690
+ return this._intervalsValid;
691
+ }
692
+ _releaseSortBuffers() {
693
+ this._keysA?.dispose();
694
+ this._keysB?.dispose();
695
+ this._valsA?.dispose();
696
+ this._valsB?.dispose();
697
+ this._sumTable?.dispose();
698
+ this._keysA = this._keysB = this._valsA = this._valsB = this._sumTable = null;
699
+ this._capacity = 0;
700
+ this._passParamsActiveCount = -1;
701
+ this._bindingsVersion++;
702
+ }
703
+ _ensureCapacity(needed) {
704
+ if (this._keysA && this._capacity >= needed) {
705
+ return;
706
+ }
707
+ const capacity = Math.max(needed, Math.min(Math.ceil(this._capacity * 1.5), this._maxSplatCount));
708
+ this._releaseSortBuffers();
709
+ this._capacity = capacity;
710
+ // Rounded to 4 elements: the scatter pass reads the keys and values as vec4u
711
+ const bytes = _RoundUp16(capacity) * Uint32Array.BYTES_PER_ELEMENT;
712
+ const create = (label, size) => new StorageBuffer(this._engine, size, 3, this._name + label);
713
+ this._keysA = create("_keysA", bytes);
714
+ this._keysB = create("_keysB", bytes);
715
+ this._valsA = create("_valsA", bytes);
716
+ this._valsB = create("_valsB", bytes);
717
+ this._sumTable = create("_sumTable", RadixBins * Math.ceil(capacity / SortBlockSize) * Uint32Array.BYTES_PER_ELEMENT);
718
+ }
719
+ _ensureIntervalsBuffer() {
720
+ const entries = Math.max(this._intervalCount, 2);
721
+ if (this._intervalsBuffer && this._intervalsCapacity >= entries) {
722
+ return;
723
+ }
724
+ this._intervalsBuffer?.dispose();
725
+ this._intervalsCapacity = Math.max(entries, Math.min(Math.ceil(this._intervalsCapacity * 1.5), this._maxIntervalCount));
726
+ this._intervalsBuffer = new StorageBuffer(this._engine, this._intervalsCapacity * 2 * Uint32Array.BYTES_PER_ELEMENT, 3, this._name + "_intervals");
727
+ this._intervalsDirty = true;
728
+ this._bindingsVersion++;
729
+ }
730
+ _ensureCoefsBuffer(output, coefCount) {
731
+ if (output._coefsBuffer && output._coefsCapacity >= coefCount) {
732
+ return;
733
+ }
734
+ output._coefsBuffer?.dispose();
735
+ output._coefsCapacity = Math.max(coefCount, 1);
736
+ output._coefsBuffer = new StorageBuffer(this._engine, output._coefsCapacity * 4 * Float32Array.BYTES_PER_ELEMENT, 3, this._name + "_coefs");
737
+ }
738
+ _getKeysComputeShader(output, sog, compound) {
739
+ const centersView = this._centersTexture?.getInternalTexture()?._hardwareTexture?.view ?? null;
740
+ const meansHighView = sog ? (this._meansHighTexture?.getInternalTexture()?._hardwareTexture?.view ?? null) : null;
741
+ const partIndicesView = compound ? (this._partIndicesTexture?.getInternalTexture()?._hardwareTexture?.view ?? null) : null;
742
+ if (!output._keysCs ||
743
+ output._keysCsSog !== sog ||
744
+ output._keysCsCompound !== compound ||
745
+ output._keysCsCentersView !== centersView ||
746
+ output._keysCsMeansHighView !== meansHighView ||
747
+ output._keysCsPartIndicesView !== partIndicesView) {
748
+ const bindingsMapping = {
749
+ params: { group: 0, binding: 0 },
750
+ intervals: { group: 0, binding: 1 },
751
+ coefs: { group: 0, binding: 2 },
752
+ keys: { group: 0, binding: 3 },
753
+ vals: { group: 0, binding: 4 },
754
+ centersTexture: { group: 0, binding: 5 },
755
+ };
756
+ const defines = [];
757
+ if (sog) {
758
+ bindingsMapping.meansUTexture = { group: 0, binding: 6 };
759
+ defines.push("#define USE_SOG");
760
+ }
761
+ if (compound) {
762
+ bindingsMapping.partIndicesTexture = { group: 0, binding: 7 };
763
+ defines.push("#define COMPOUND");
764
+ }
765
+ const key = `${sog ? "S" : ""}${compound ? "C" : ""}`;
766
+ output._keysCs = new ComputeShader(this._name + "_keys" + key, this._engine, "gsSortKeys", { bindingsMapping, defines, useExplicitComputePipelineLayout: true });
767
+ output._keysCsSog = sog;
768
+ output._keysCsCompound = compound;
769
+ output._keysCsCentersView = centersView;
770
+ output._keysCsMeansHighView = meansHighView;
771
+ output._keysCsPartIndicesView = partIndicesView;
772
+ }
773
+ return output._keysCs;
774
+ }
775
+ // Binds the resources of the shaders. The setters allocate a binding each call, so a shader is only bound again when one of its resources changed.
776
+ _bindResources(output, keysCs, sog, compound) {
777
+ if (this._sortShadersBoundVersion !== this._bindingsVersion) {
778
+ this._sortShadersBoundVersion = this._bindingsVersion;
779
+ this._bindSortShaders();
780
+ }
781
+ if (output._boundSorterVersion === this._bindingsVersion &&
782
+ output._boundBuffersVersion === output.buffersVersion &&
783
+ output._boundCoefsBuffer === output._coefsBuffer &&
784
+ output._boundKeysCs === keysCs) {
785
+ return;
786
+ }
787
+ output._boundSorterVersion = this._bindingsVersion;
788
+ output._boundBuffersVersion = output.buffersVersion;
789
+ output._boundCoefsBuffer = output._coefsBuffer;
790
+ output._boundKeysCs = keysCs;
791
+ keysCs.fastMode = false;
792
+ output._outputCs.fastMode = false;
793
+ keysCs.setStorageBuffer("params", output._paramsBuffer);
794
+ keysCs.setStorageBuffer("intervals", this._intervalsBuffer);
795
+ keysCs.setStorageBuffer("coefs", output._coefsBuffer);
796
+ keysCs.setStorageBuffer("keys", this._keysA);
797
+ keysCs.setStorageBuffer("vals", this._valsA);
798
+ keysCs.setTexture("centersTexture", this._centersTexture, false);
799
+ if (sog) {
800
+ keysCs.setTexture("meansUTexture", this._meansHighTexture, false);
801
+ }
802
+ if (compound) {
803
+ keysCs.setTexture("partIndicesTexture", this._partIndicesTexture, false);
804
+ }
805
+ // After the radix passes, the sorted values are in valsA for an even number of passes (the passes ping-pong between A and B), valsB otherwise.
806
+ output._outputCs.setStorageBuffer("params", output._paramsBuffer);
807
+ output._outputCs.setStorageBuffer("vals", (this._passCount & 1) === 0 ? this._valsA : this._valsB);
808
+ output._outputCs.setStorageBuffer("indexOut", output.buffer);
809
+ }
810
+ // The ping-pong buffers of each radix pass are the same for every view: pass 0 reads A and writes B, pass 1 reads B and writes A, and so on.
811
+ _bindSortShaders() {
812
+ let keysIn = this._keysA;
813
+ let valsIn = this._valsA;
814
+ let keysOut = this._keysB;
815
+ let valsOut = this._valsB;
816
+ for (let pass = 0; pass < this._passCount; pass++) {
817
+ const params = this._passParams[pass];
818
+ const count = this._countCs[pass];
819
+ count.fastMode = false;
820
+ count.setStorageBuffer("params", params);
821
+ count.setStorageBuffer("keysIn", keysIn);
822
+ count.setStorageBuffer("sumTable", this._sumTable);
823
+ const scatter = this._scatterCs[pass];
824
+ scatter.fastMode = false;
825
+ scatter.setStorageBuffer("params", params);
826
+ scatter.setStorageBuffer("keysIn", keysIn);
827
+ scatter.setStorageBuffer("valsIn", valsIn);
828
+ scatter.setStorageBuffer("keysOut", keysOut);
829
+ scatter.setStorageBuffer("valsOut", valsOut);
830
+ scatter.setStorageBuffer("sumTable", this._sumTable);
831
+ scatter.setStorageBuffer("chunkSums", this._chunkSums);
832
+ const keysTemp = keysIn;
833
+ keysIn = keysOut;
834
+ keysOut = keysTemp;
835
+ const valsTemp = valsIn;
836
+ valsIn = valsOut;
837
+ valsOut = valsTemp;
838
+ }
839
+ this._scanLocalCs.fastMode = false;
840
+ this._scanSumsCs.fastMode = false;
841
+ this._scanLocalCs.setStorageBuffer("params", this._passParams[0]);
842
+ this._scanLocalCs.setStorageBuffer("sumTable", this._sumTable);
843
+ this._scanLocalCs.setStorageBuffer("chunkSums", this._chunkSums);
844
+ this._scanSumsCs.setStorageBuffer("params", this._passParams[0]);
845
+ this._scanSumsCs.setStorageBuffer("chunkSums", this._chunkSums);
846
+ }
847
+ _isReady(keysCs, output) {
848
+ let ready = _IsShaderReady(keysCs) && _IsShaderReady(output._outputCs) && _IsShaderReady(this._scanLocalCs) && _IsShaderReady(this._scanSumsCs);
849
+ for (let pass = 0; pass < this._passCount && ready; pass++) {
850
+ ready = _IsShaderReady(this._countCs[pass]) && _IsShaderReady(this._scatterCs[pass]);
851
+ }
852
+ return ready;
853
+ }
854
+ _writeParams(output, coefCount, depthMin, depthMax) {
855
+ const u32 = this._paramsU32;
856
+ const f32 = this._paramsF32;
857
+ u32[0] = this._activeCount;
858
+ u32[1] = this._vertexCount;
859
+ u32[2] = this.paddedCount;
860
+ u32[3] = this._textureWidth;
861
+ u32[4] = coefCount;
862
+ u32[5] = this._intervalCount;
863
+ f32[6] = depthMax;
864
+ f32[7] = _ComputeGpuSortKeyScale(depthMin, depthMax, this._keyBits);
865
+ f32[8] = Math.pow(2, this._keyBits) - 1;
866
+ f32[9] = f32[10] = f32[11] = 0;
867
+ f32.set(this._meansMin, 12);
868
+ f32.set(this._meansMax, 16);
869
+ output._paramsBuffer.update(this._paramsData);
870
+ }
871
+ _writeIntervals() {
872
+ if (!this._intervalsDirty) {
873
+ return;
874
+ }
875
+ this._intervalsDirty = false;
876
+ if (this._packedIntervals && this._intervalCount > 0) {
877
+ this._intervalsBuffer.update(this._packedIntervals, 0, this._intervalCount * 2 * Uint32Array.BYTES_PER_ELEMENT);
878
+ }
879
+ }
880
+ _writePassParams(activeCount) {
881
+ if (this._passParamsActiveCount === activeCount) {
882
+ return;
883
+ }
884
+ this._passParamsActiveCount = activeCount;
885
+ const numBlocks = Math.ceil(activeCount / SortBlockSize);
886
+ const chunkCount = Math.ceil(numBlocks / BlocksPerScanChunk);
887
+ for (let pass = 0; pass < this._passCount; pass++) {
888
+ this._passData[0] = activeCount;
889
+ this._passData[1] = numBlocks;
890
+ this._passData[2] = pass * RadixBits;
891
+ this._passData[3] = chunkCount;
892
+ this._passParams[pass].update(this._passData);
893
+ }
894
+ }
895
+ _dispatchSort(keysCs, activeCount) {
896
+ const numBlocks = Math.ceil(activeCount / SortBlockSize);
897
+ const chunkCount = Math.ceil(numBlocks / BlocksPerScanChunk);
898
+ if (!_Dispatch(keysCs, Math.ceil(activeCount / WorkgroupSize))) {
899
+ return false;
900
+ }
901
+ for (let pass = 0; pass < this._passCount; pass++) {
902
+ _Dispatch(this._countCs[pass], numBlocks);
903
+ _Dispatch(this._scanLocalCs, chunkCount);
904
+ _Dispatch(this._scanSumsCs, 1);
905
+ _Dispatch(this._scatterCs[pass], numBlocks);
906
+ }
907
+ return true;
908
+ }
909
+ }
910
+ GaussianSplattingGpuSorter._DependenciesReady = false;
911
+ GaussianSplattingGpuSorter._DependenciesPromise = null;
912
+ //# sourceMappingURL=gaussianSplattingGpuSorter.js.map