@woosh/meep-engine 3.11.2 → 3.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -18
- package/build/bundle-worker-terrain.js +1 -1
- package/editor/SelectionVisualizer.js +127 -127
- package/editor/entity_world_bounds.js +27 -27
- package/editor/particles/rebuildParticleEmitter.js +31 -31
- package/editor/process/SymbolicDisplayProcess.js +1 -1
- package/editor/process/symbolic/CameraSymbolicDisplay.js +146 -146
- package/editor/process/symbolic/LightSymbolicDisplay.js +172 -172
- package/editor/prototypeEditorShell.js +156 -156
- package/editor/selection/editor_pick.js +130 -130
- package/editor/selection/screen_rect_frustum.js +119 -119
- package/editor/tools/v2/TransformControls.js +971 -971
- package/package.json +1 -1
- package/src/engine/Engine.d.ts +3 -3
- package/src/engine/Engine.d.ts.map +1 -1
- package/src/engine/Engine.js +726 -726
- package/src/engine/EngineHarness.d.ts +1 -1
- package/src/engine/EngineHarness.js +590 -590
- package/src/engine/ecs/HIERARCHY_REVIEW.md +717 -717
- package/src/engine/ecs/terrain/ecs/BuildLightTexture.d.ts +1 -1
- package/src/engine/ecs/terrain/ecs/BuildLightTexture.js +27 -27
- package/src/engine/ecs/terrain/ecs/Terrain.d.ts +1 -5
- package/src/engine/ecs/terrain/ecs/Terrain.d.ts.map +1 -1
- package/src/engine/ecs/terrain/ecs/Terrain.js +790 -790
- package/src/engine/ecs/terrain/util/loadVisibleTerrainTiles.js +129 -129
- package/src/engine/graphics/ecs/camera/camera_find_active.d.ts +1 -1
- package/src/engine/graphics/ecs/camera/camera_find_active.js +28 -28
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.d.ts +1 -1
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +428 -428
- package/src/engine/graphics/ecs/water/Water.d.ts +1 -1
- package/src/engine/graphics/ecs/water/Water.js +104 -104
- package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts +1 -1
- package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js +1 -1
- package/src/engine/graphics3/AnimationGraphSystem.d.ts +65 -0
- package/src/engine/graphics3/AnimationGraphSystem.d.ts.map +1 -0
- package/src/engine/graphics3/AnimationGraphSystem.js +329 -0
- package/src/engine/graphics3/AnimationGraphSystem3.d.ts +6 -61
- package/src/engine/graphics3/AnimationGraphSystem3.d.ts.map +1 -1
- package/src/engine/graphics3/AnimationGraphSystem3.js +6 -325
- package/src/engine/graphics3/AnimationSystem.d.ts +76 -0
- package/src/engine/graphics3/AnimationSystem.d.ts.map +1 -0
- package/src/engine/graphics3/AnimationSystem.js +352 -0
- package/src/engine/graphics3/AnimationSystem3.d.ts +6 -72
- package/src/engine/graphics3/AnimationSystem3.d.ts.map +1 -1
- package/src/engine/graphics3/AnimationSystem3.js +6 -348
- package/src/engine/graphics3/CameraSystem.d.ts +49 -0
- package/src/engine/graphics3/CameraSystem.d.ts.map +1 -0
- package/src/engine/graphics3/CameraSystem.js +170 -0
- package/src/engine/graphics3/CameraSystem3.d.ts +6 -45
- package/src/engine/graphics3/CameraSystem3.d.ts.map +1 -1
- package/src/engine/graphics3/CameraSystem3.js +6 -166
- package/src/engine/graphics3/DebugDrawSystem.d.ts +72 -0
- package/src/engine/graphics3/DebugDrawSystem.d.ts.map +1 -0
- package/src/engine/graphics3/DebugDrawSystem.js +205 -0
- package/src/engine/graphics3/DebugDrawSystem3.d.ts +6 -68
- package/src/engine/graphics3/DebugDrawSystem3.d.ts.map +1 -1
- package/src/engine/graphics3/DebugDrawSystem3.js +6 -201
- package/src/engine/graphics3/DecalSystem.d.ts +81 -0
- package/src/engine/graphics3/DecalSystem.d.ts.map +1 -0
- package/src/engine/graphics3/DecalSystem.js +441 -0
- package/src/engine/graphics3/DecalSystem3.d.ts +6 -77
- package/src/engine/graphics3/DecalSystem3.d.ts.map +1 -1
- package/src/engine/graphics3/DecalSystem3.js +6 -437
- package/src/engine/graphics3/FogOfWarSystem.d.ts +74 -0
- package/src/engine/graphics3/FogOfWarSystem.d.ts.map +1 -0
- package/src/engine/graphics3/FogOfWarSystem.js +265 -0
- package/src/engine/graphics3/FogOfWarSystem3.d.ts +6 -70
- package/src/engine/graphics3/FogOfWarSystem3.d.ts.map +1 -1
- package/src/engine/graphics3/FogOfWarSystem3.js +6 -261
- package/src/engine/graphics3/GraphicsEngine.d.ts +340 -0
- package/src/engine/graphics3/GraphicsEngine.d.ts.map +1 -0
- package/src/engine/graphics3/GraphicsEngine.js +790 -0
- package/src/engine/graphics3/GraphicsEngine3.d.ts +6 -336
- package/src/engine/graphics3/GraphicsEngine3.d.ts.map +1 -1
- package/src/engine/graphics3/GraphicsEngine3.js +6 -786
- package/src/engine/graphics3/HighlightSystem.d.ts +82 -0
- package/src/engine/graphics3/HighlightSystem.d.ts.map +1 -0
- package/src/engine/graphics3/HighlightSystem.js +241 -0
- package/src/engine/graphics3/HighlightSystem3.d.ts +6 -78
- package/src/engine/graphics3/HighlightSystem3.d.ts.map +1 -1
- package/src/engine/graphics3/HighlightSystem3.js +6 -237
- package/src/engine/graphics3/LightSystem.d.ts +40 -0
- package/src/engine/graphics3/LightSystem.d.ts.map +1 -0
- package/src/engine/graphics3/LightSystem.js +211 -0
- package/src/engine/graphics3/LightSystem3.d.ts +6 -36
- package/src/engine/graphics3/LightSystem3.d.ts.map +1 -1
- package/src/engine/graphics3/LightSystem3.js +6 -207
- package/src/engine/graphics3/MeshSystem.d.ts +106 -0
- package/src/engine/graphics3/MeshSystem.d.ts.map +1 -0
- package/src/engine/graphics3/MeshSystem.js +647 -0
- package/src/engine/graphics3/MeshSystem3.d.ts +6 -102
- package/src/engine/graphics3/MeshSystem3.d.ts.map +1 -1
- package/src/engine/graphics3/MeshSystem3.js +6 -642
- package/src/engine/graphics3/ParticipatingMedia.d.ts +2 -2
- package/src/engine/graphics3/ParticipatingMedia.js +203 -203
- package/src/engine/graphics3/ParticipatingMediaSystem.d.ts +87 -0
- package/src/engine/graphics3/ParticipatingMediaSystem.d.ts.map +1 -0
- package/src/engine/graphics3/ParticipatingMediaSystem.js +184 -0
- package/src/engine/graphics3/ParticipatingMediaSystem3.d.ts +6 -83
- package/src/engine/graphics3/ParticipatingMediaSystem3.d.ts.map +1 -1
- package/src/engine/graphics3/ParticipatingMediaSystem3.js +6 -180
- package/src/engine/graphics3/ParticleEmitterSystem.d.ts +76 -0
- package/src/engine/graphics3/ParticleEmitterSystem.d.ts.map +1 -0
- package/src/engine/graphics3/ParticleEmitterSystem.js +289 -0
- package/src/engine/graphics3/ParticleEmitterSystem3.d.ts +6 -72
- package/src/engine/graphics3/ParticleEmitterSystem3.d.ts.map +1 -1
- package/src/engine/graphics3/ParticleEmitterSystem3.js +6 -285
- package/src/engine/graphics3/PathDisplaySystem.d.ts +70 -0
- package/src/engine/graphics3/PathDisplaySystem.d.ts.map +1 -0
- package/src/engine/graphics3/PathDisplaySystem.js +309 -0
- package/src/engine/graphics3/PathDisplaySystem3.d.ts +6 -66
- package/src/engine/graphics3/PathDisplaySystem3.d.ts.map +1 -1
- package/src/engine/graphics3/PathDisplaySystem3.js +6 -305
- package/src/engine/graphics3/Pickable.d.ts +1 -1
- package/src/engine/graphics3/Pickable.js +65 -65
- package/src/engine/graphics3/PickingQuery.d.ts +1 -1
- package/src/engine/graphics3/PickingQuery.js +48 -48
- package/src/engine/graphics3/PickingSystem.d.ts +67 -0
- package/src/engine/graphics3/PickingSystem.d.ts.map +1 -0
- package/src/engine/graphics3/PickingSystem.js +273 -0
- package/src/engine/graphics3/PickingSystem3.d.ts +6 -63
- package/src/engine/graphics3/PickingSystem3.d.ts.map +1 -1
- package/src/engine/graphics3/PickingSystem3.js +6 -269
- package/src/engine/graphics3/ShadedGeometrySystem.d.ts +47 -0
- package/src/engine/graphics3/ShadedGeometrySystem.d.ts.map +1 -0
- package/src/engine/graphics3/ShadedGeometrySystem.js +169 -0
- package/src/engine/graphics3/ShadedGeometrySystem3.d.ts +6 -43
- package/src/engine/graphics3/ShadedGeometrySystem3.d.ts.map +1 -1
- package/src/engine/graphics3/ShadedGeometrySystem3.js +6 -165
- package/src/engine/graphics3/TerrainSystem.d.ts +80 -0
- package/src/engine/graphics3/TerrainSystem.d.ts.map +1 -0
- package/src/engine/graphics3/TerrainSystem.js +566 -0
- package/src/engine/graphics3/TerrainSystem3.d.ts +6 -76
- package/src/engine/graphics3/TerrainSystem3.d.ts.map +1 -1
- package/src/engine/graphics3/TerrainSystem3.js +6 -562
- package/src/engine/graphics3/TooltipComponentSystem.d.ts +65 -0
- package/src/engine/graphics3/TooltipComponentSystem.d.ts.map +1 -0
- package/src/engine/graphics3/TooltipComponentSystem.js +328 -0
- package/src/engine/graphics3/TooltipComponentSystem3.d.ts +6 -61
- package/src/engine/graphics3/TooltipComponentSystem3.d.ts.map +1 -1
- package/src/engine/graphics3/TooltipComponentSystem3.js +6 -324
- package/src/engine/graphics3/Trail3DSystem.d.ts +73 -0
- package/src/engine/graphics3/Trail3DSystem.d.ts.map +1 -0
- package/src/engine/graphics3/Trail3DSystem.js +221 -0
- package/src/engine/graphics3/Trail3DSystem3.d.ts +6 -69
- package/src/engine/graphics3/Trail3DSystem3.d.ts.map +1 -1
- package/src/engine/graphics3/Trail3DSystem3.js +6 -217
- package/src/engine/graphics3/VolumetricLightMap.d.ts +2 -2
- package/src/engine/graphics3/VolumetricLightMap.js +2 -2
- package/src/engine/graphics3/VolumetricLightMapSystem.d.ts +98 -0
- package/src/engine/graphics3/VolumetricLightMapSystem.d.ts.map +1 -0
- package/src/engine/graphics3/VolumetricLightMapSystem.js +261 -0
- package/src/engine/graphics3/VolumetricLightMapSystem3.d.ts +6 -94
- package/src/engine/graphics3/VolumetricLightMapSystem3.d.ts.map +1 -1
- package/src/engine/graphics3/VolumetricLightMapSystem3.js +10 -261
- package/src/engine/graphics3/WaterSystem.d.ts +59 -0
- package/src/engine/graphics3/WaterSystem.d.ts.map +1 -0
- package/src/engine/graphics3/WaterSystem.js +293 -0
- package/src/engine/graphics3/WaterSystem3.d.ts +6 -55
- package/src/engine/graphics3/WaterSystem3.d.ts.map +1 -1
- package/src/engine/graphics3/WaterSystem3.js +6 -289
- package/src/engine/graphics3/animation/AnimationGraphController.d.ts +1 -1
- package/src/engine/graphics3/animation/AnimationGraphController.js +518 -518
- package/src/engine/graphics3/animation/ClipListPlayer.d.ts +1 -1
- package/src/engine/graphics3/animation/ClipListPlayer.js +263 -263
- package/src/engine/graphics3/animation/ClipPlayback.d.ts +2 -2
- package/src/engine/graphics3/animation/ClipPlayback.js +84 -84
- package/src/engine/graphics3/decal/graph_build_decal_clusters.d.ts.map +1 -1
- package/src/engine/graphics3/decal/graph_build_decal_clusters.js +6 -8
- package/src/engine/graphics3/decal/shader_cluster_assign_decals.d.ts +0 -7
- package/src/engine/graphics3/decal/shader_cluster_assign_decals.d.ts.map +1 -1
- package/src/engine/graphics3/decal/shader_cluster_assign_decals.js +1 -1
- package/src/engine/graphics3/decal/shader_cull_decals_frustum.d.ts +0 -4
- package/src/engine/graphics3/decal/shader_cull_decals_frustum.d.ts.map +1 -1
- package/src/engine/graphics3/decal/shader_cull_decals_frustum.js +1 -1
- package/src/engine/graphics3/highlight/pack_highlight_table.d.ts +2 -2
- package/src/engine/graphics3/highlight/pack_highlight_table.d.ts.map +1 -1
- package/src/engine/graphics3/highlight/pack_highlight_table.js +74 -74
- package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts +1 -1
- package/src/engine/graphics3/pose/query_entity_node_world_pose.js +101 -101
- package/src/engine/graphics3/preview/make_model_thumbnail.d.ts +3 -3
- package/src/engine/graphics3/preview/make_model_thumbnail.d.ts.map +1 -1
- package/src/engine/graphics3/preview/make_model_thumbnail.js +48 -48
- package/src/engine/graphics3/shade_camera_projection_ray.d.ts +1 -1
- package/src/engine/graphics3/shade_camera_projection_ray.js +77 -77
- package/src/engine/graphics3/shade_node_to_entity_composition.d.ts +1 -1
- package/src/engine/graphics3/shade_node_to_entity_composition.js +84 -84
- package/src/shade/descriptor/pipeline/PipelineLayoutDescriptor.d.ts +16 -2
- package/src/shade/descriptor/pipeline/PipelineLayoutDescriptor.d.ts.map +1 -1
- package/src/shade/descriptor/pipeline/PipelineLayoutDescriptor.js +28 -4
- package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.d.ts +1 -1
- package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.d.ts.map +1 -1
- package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.js +5 -2
- package/src/shade/device/IMMEDIATE_DATA_PLAN_2026_08_28.md +564 -451
- package/src/shade/device/ShadeGPUCommandContext.d.ts +18 -2
- package/src/shade/device/ShadeGPUCommandContext.d.ts.map +1 -1
- package/src/shade/device/ShadeGPUCommandContext.js +994 -940
- package/src/shade/device/immediate_data_supported.d.ts +33 -0
- package/src/shade/device/immediate_data_supported.d.ts.map +1 -0
- package/src/shade/device/immediate_data_supported.js +53 -0
- package/src/shade/device/mock/SoftwareGPUCommandEncoder.d.ts +18 -0
- package/src/shade/device/mock/SoftwareGPUCommandEncoder.d.ts.map +1 -1
- package/src/shade/device/mock/SoftwareGPUCommandEncoder.js +24 -0
- package/src/shade/device/mock/SoftwareGPUComputePassEncoder.d.ts +7 -0
- package/src/shade/device/mock/SoftwareGPUComputePassEncoder.d.ts.map +1 -1
- package/src/shade/device/mock/SoftwareGPUComputePassEncoder.js +49 -1
- package/src/shade/device/mock/SoftwareGPUDevice.d.ts.map +1 -1
- package/src/shade/device/mock/SoftwareGPUDevice.js +20 -2
- package/src/shade/device/mock/SoftwareGPUImmediateData.d.ts +65 -0
- package/src/shade/device/mock/SoftwareGPUImmediateData.d.ts.map +1 -0
- package/src/shade/device/mock/SoftwareGPUImmediateData.js +160 -0
- package/src/shade/device/mock/SoftwareGPURenderPassEncoder.d.ts +7 -0
- package/src/shade/device/mock/SoftwareGPURenderPassEncoder.d.ts.map +1 -1
- package/src/shade/device/mock/SoftwareGPURenderPassEncoder.js +50 -0
- package/src/shade/device/mock/pipeline_immediate_size.d.ts +11 -0
- package/src/shade/device/mock/pipeline_immediate_size.d.ts.map +1 -0
- package/src/shade/device/mock/pipeline_immediate_size.js +18 -0
- package/src/shade/device/pipeline/PipelineLayoutManager.d.ts.map +1 -1
- package/src/shade/device/pipeline/PipelineLayoutManager.js +1 -0
- package/src/shade/playground/skinned_blas_refit/shader_blas_audit_leaf_triangles.d.ts.map +1 -1
- package/src/shade/playground/skinned_blas_refit/shader_blas_audit_leaf_triangles.js +0 -1
- package/src/shade/playground/skinned_blas_refit/shader_blas_audit_points.d.ts.map +1 -1
- package/src/shade/playground/skinned_blas_refit/shader_blas_audit_points.js +0 -1
- package/src/shade/playground/skinned_blas_refit/shader_blas_audit_visibility.d.ts.map +1 -1
- package/src/shade/playground/skinned_blas_refit/shader_blas_audit_visibility.js +133 -134
- package/src/shade/playground/skinned_blas_refit/verify_leaf_triangles.js +202 -202
- package/src/shade/playground/skinned_blas_refit/verify_traversal_reachability.js +249 -249
- package/src/shade/renderer/GraphicsContext.d.ts +9 -2
- package/src/shade/renderer/GraphicsContext.d.ts.map +1 -1
- package/src/shade/renderer/GraphicsContext.js +13 -1
- package/src/shade/renderer/STATIC_GRAPHICS_ENGINE_ASSETS.js +1 -1
- package/src/shade/renderer/animation/pose/PosePlayback.d.ts +2 -1
- package/src/shade/renderer/animation/pose/PosePlayback.d.ts.map +1 -1
- package/src/shade/renderer/animation/pose/PosePlayback.js +2 -1
- package/src/shade/renderer/animation/shader_animation_apply.d.ts.map +1 -1
- package/src/shade/renderer/animation/shader_animation_apply.js +128 -129
- package/src/shade/renderer/animation/shader_animation_pose_resolve.d.ts.map +1 -1
- package/src/shade/renderer/animation/shader_animation_pose_resolve.js +176 -177
- package/src/shade/renderer/animation/shader_animation_tick.d.ts.map +1 -1
- package/src/shade/renderer/animation/shader_animation_tick.js +125 -126
- package/src/shade/renderer/animation/skinning/bounds_refresh/shader_geometry_sphere_derive.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/bounds_refresh/shader_geometry_sphere_derive.js +98 -99
- package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_reduce.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_reduce.js +212 -213
- package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_scatter.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_scatter.js +120 -121
- package/src/shade/renderer/animation/skinning/bounds_refresh/shader_skinned_mesh_bounds_refresh.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/bounds_refresh/shader_skinned_mesh_bounds_refresh.js +75 -76
- package/src/shade/renderer/animation/skinning/shader_meshlet_apply_skinning.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/shader_meshlet_apply_skinning.js +371 -372
- package/src/shade/renderer/animation/skinning/shader_skin_matrix_prep.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/shader_skin_matrix_prep.js +104 -105
- package/src/shade/renderer/atmosphere/GPUSky.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/GPUSky.js +145 -142
- package/src/shade/renderer/atmosphere/MULTISCATTER_LUT_CONFIG.d.ts +34 -0
- package/src/shade/renderer/atmosphere/MULTISCATTER_LUT_CONFIG.d.ts.map +1 -0
- package/src/shade/renderer/atmosphere/MULTISCATTER_LUT_CONFIG.js +36 -0
- package/src/shade/renderer/atmosphere/SAMPLER_SKY_LUT.d.ts +20 -0
- package/src/shade/renderer/atmosphere/SAMPLER_SKY_LUT.d.ts.map +1 -0
- package/src/shade/renderer/atmosphere/SAMPLER_SKY_LUT.js +25 -0
- package/src/shade/renderer/atmosphere/chunk_get_multiscatter_values.d.ts +14 -1
- package/src/shade/renderer/atmosphere/chunk_get_multiscatter_values.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/chunk_get_multiscatter_values.js +163 -177
- package/src/shade/renderer/atmosphere/chunk_multiscatter_sample_direction.d.ts +20 -0
- package/src/shade/renderer/atmosphere/chunk_multiscatter_sample_direction.d.ts.map +1 -0
- package/src/shade/renderer/atmosphere/chunk_multiscatter_sample_direction.js +46 -0
- package/src/shade/renderer/atmosphere/chunk_sample_multiscatter_lut.d.ts +11 -1
- package/src/shade/renderer/atmosphere/chunk_sample_multiscatter_lut.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/chunk_sample_multiscatter_lut.js +57 -27
- package/src/shade/renderer/atmosphere/chunk_sample_transmittance_lut.d.ts +19 -1
- package/src/shade/renderer/atmosphere/chunk_sample_transmittance_lut.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/chunk_sample_transmittance_lut.js +69 -33
- package/src/shade/renderer/atmosphere/chunk_sky_lut_compute_uv.d.ts +13 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_compute_uv.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/chunk_sky_lut_compute_uv.js +35 -35
- package/src/shade/renderer/atmosphere/chunk_sky_lut_params.d.ts +13 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_params.d.ts.map +1 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_params.js +38 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_texel_to_unit.d.ts +17 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_texel_to_unit.d.ts.map +1 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_texel_to_unit.js +29 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_uv.d.ts +21 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_uv.d.ts.map +1 -0
- package/src/shade/renderer/atmosphere/chunk_sky_lut_uv.js +42 -0
- package/src/shade/renderer/atmosphere/shader_multiscatter_lut.d.ts +2 -2
- package/src/shade/renderer/atmosphere/shader_multiscatter_lut.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/shader_multiscatter_lut.js +164 -84
- package/src/shade/renderer/atmosphere/shader_sky_irradiance_lut.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/shader_sky_irradiance_lut.js +215 -204
- package/src/shade/renderer/atmosphere/shader_transmittance_lut.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/shader_transmittance_lut.js +79 -67
- package/src/shade/renderer/buffer/graph_inspect_gpu_buffer.js +136 -136
- package/src/shade/renderer/buffer/table/GPUDatabase.d.ts.map +1 -1
- package/src/shade/renderer/buffer/table/GPUDatabase.js +2 -3
- package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.js +319 -319
- package/src/shade/renderer/buffer/util/shader_buffer_copy_storage_to_storage.d.ts.map +1 -1
- package/src/shade/renderer/buffer/util/shader_buffer_copy_storage_to_storage.js +41 -42
- package/src/shade/renderer/buffer/util/shader_buffer_intra_copy_regions.d.ts.map +1 -1
- package/src/shade/renderer/buffer/util/shader_buffer_intra_copy_regions.js +83 -84
- package/src/shade/renderer/dynamic/shader_dynamic_mesh.d.ts.map +1 -1
- package/src/shade/renderer/dynamic/shader_dynamic_mesh.js +177 -170
- package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +918 -918
- package/src/shade/renderer/geometry/bvh/record_blas_refit.js +4 -4
- package/src/shade/renderer/geometry/bvh/shader_blas_refit_leaf_bounds.d.ts.map +1 -1
- package/src/shade/renderer/geometry/bvh/shader_blas_refit_leaf_bounds.js +121 -122
- package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.js +774 -774
- package/src/shade/renderer/geometry/meshlet/shader_meshlet_metadata_address_patch.d.ts +1 -1
- package/src/shade/renderer/geometry/meshlet/shader_meshlet_metadata_address_patch.d.ts.map +1 -1
- package/src/shade/renderer/geometry/meshlet/shader_meshlet_metadata_address_patch.js +69 -70
- package/src/shade/renderer/global_illumination/lpv/placement/graph_generate_probe_locations.js +367 -367
- package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lvp_atlas_to_sh.js +184 -184
- package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +1115 -1115
- package/src/shade/renderer/gpu_primitive/bvh/graph_bvh_build_lbvh.js +217 -217
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.js +142 -143
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.js +0 -1
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_refit.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_refit.js +140 -141
- package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.js +0 -1
- package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.js +0 -1
- package/src/shade/renderer/light/cluster/cull/graph_cull_lights.d.ts.map +1 -1
- package/src/shade/renderer/light/cluster/cull/graph_cull_lights.js +191 -198
- package/src/shade/renderer/light/cluster/cull/shader_cull_lights_frustum.d.ts +0 -6
- package/src/shade/renderer/light/cluster/cull/shader_cull_lights_frustum.d.ts.map +1 -1
- package/src/shade/renderer/light/cluster/cull/shader_cull_lights_frustum.js +120 -120
- package/src/shade/renderer/light/cluster/cull/shader_cull_lights_hzb.d.ts +0 -4
- package/src/shade/renderer/light/cluster/cull/shader_cull_lights_hzb.d.ts.map +1 -1
- package/src/shade/renderer/light/cluster/cull/shader_cull_lights_hzb.js +112 -112
- package/src/shade/renderer/light/cluster/graph_assign_clsuters.d.ts.map +1 -1
- package/src/shade/renderer/light/cluster/graph_assign_clsuters.js +10 -9
- package/src/shade/renderer/light/cluster/shader_cluster_assign_lights.d.ts +0 -6
- package/src/shade/renderer/light/cluster/shader_cluster_assign_lights.d.ts.map +1 -1
- package/src/shade/renderer/light/cluster/shader_cluster_assign_lights.js +1 -1
- package/src/shade/renderer/lightmap/bake/raster/shader_lightmap_to_viz_buffer.js +222 -222
- package/src/shade/renderer/lightmap/bake/tile/shader_lightmap_tile_composit.js +81 -81
- package/src/shade/renderer/material/GPUMaterialContext.js +380 -380
- package/src/shade/renderer/material/standard/fragment_gbuffer_vt.js +169 -169
- package/src/shade/renderer/object_property/shader_object_property_process.d.ts.map +1 -1
- package/src/shade/renderer/object_property/shader_object_property_process.js +83 -84
- package/src/shade/renderer/object_property/shader_refresh_all_mesh_bounds.d.ts.map +1 -1
- package/src/shade/renderer/object_property/shader_refresh_all_mesh_bounds.js +57 -58
- package/src/shade/renderer/particles/prototypeParticleSystem.js +2 -3
- package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_emit.js +117 -118
- package/src/shade/renderer/particles/shaders/shader_particle_finalize.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_finalize.js +77 -79
- package/src/shade/renderer/particles/shaders/shader_particle_render.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_render.js +190 -183
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +99 -100
- package/src/shade/renderer/particles/sort/shader_particle_sort.d.ts.map +1 -1
- package/src/shade/renderer/particles/sort/shader_particle_sort.js +158 -161
- package/src/shade/renderer/path_tracer/graph_path_trace_scene.js +184 -184
- package/src/shade/renderer/postprocess/denoise/graph_atorus_denoise_luma.js +119 -119
- package/src/shade/renderer/postprocess/dof/raymarch/graph_postprocess_dof.js +3 -4
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.js +266 -267
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.js +270 -271
- package/src/shade/renderer/postprocess/gtao/GTAO.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/gtao/GTAO.js +4 -0
- package/src/shade/renderer/postprocess/nss/shader_nss_concat.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/nss/shader_nss_concat.js +68 -69
- package/src/shade/renderer/postprocess/nss/shader_nss_conv_layer.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/nss/shader_nss_conv_layer.js +225 -226
- package/src/shade/renderer/postprocess/nss/shader_nss_extract_feedback.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/nss/shader_nss_extract_feedback.js +49 -50
- package/src/shade/renderer/postprocess/nss/shader_nss_postprocess.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/nss/shader_nss_postprocess.js +291 -292
- package/src/shade/renderer/postprocess/nss/shader_nss_preprocess.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/nss/shader_nss_preprocess.js +230 -231
- package/src/shade/renderer/postprocess/ssr/reproject/shader_ffx_denoiser_reflections_reproject.d.ts +16 -2
- package/src/shade/renderer/postprocess/ssr/reproject/shader_ffx_denoiser_reflections_reproject.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/reproject/shader_ffx_denoiser_reflections_reproject.js +12 -12
- package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +341 -345
- package/src/shade/renderer/rasterize/bucket/shader_count_meshlets_by_material.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/shader_count_meshlets_by_material.js +68 -69
- package/src/shade/renderer/rasterize/bucket/shader_make_meshlet_indirect_draw_commands_by_material.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/shader_make_meshlet_indirect_draw_commands_by_material.js +59 -60
- package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.d.ts +0 -2
- package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.js +57 -57
- package/src/shade/renderer/rasterize/bucket/shader_sort_meshlets_by_material.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/shader_sort_meshlets_by_material.js +64 -65
- package/src/shade/renderer/rasterize/compute/graph_mesh_frustum_cull.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/compute/graph_mesh_frustum_cull.js +168 -169
- package/src/shade/renderer/rasterize/compute/graph_mesh_sphere_cull.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/compute/graph_mesh_sphere_cull.js +160 -161
- package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.js +109 -110
- package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.js +115 -116
- package/src/shade/renderer/rasterize/expand/bucket/mesh/shader_instances_classify_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/bucket/mesh/shader_instances_classify_bucket.js +139 -140
- package/src/shade/renderer/rasterize/expand/bucket/mesh/shader_instances_count_by_rasterization_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/bucket/mesh/shader_instances_count_by_rasterization_bucket.js +91 -92
- package/src/shade/renderer/rasterize/expand/bucket/mesh/shader_instances_rasterization_bucket_sort.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/bucket/mesh/shader_instances_rasterization_bucket_sort.js +88 -89
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_count_by_rasterization_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_count_by_rasterization_bucket.js +90 -91
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.js +65 -66
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_rasterization_bucket_sort.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_rasterization_bucket_sort.js +89 -90
- package/src/shade/renderer/rasterize/expand/graph_mesh_filter_one_way.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/graph_mesh_filter_one_way.js +169 -170
- package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.js +7 -3
- package/src/shade/renderer/rasterize/expand/mesh/shader_mesh_expand_to_meshlets_prefix.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/mesh/shader_mesh_expand_to_meshlets_prefix.js +89 -90
- package/src/shade/renderer/rasterize/expand/mesh/shader_meshes_to_meshlet_counts.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/mesh/shader_meshes_to_meshlet_counts.js +61 -62
- package/src/shade/renderer/rasterize/expand/pass1/filter_meshlets.2-way.compute.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/pass1/filter_meshlets.2-way.compute.js +153 -154
- package/src/shade/renderer/rasterize/fast/graph_extract_meshes_from_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/fast/graph_extract_meshes_from_bucket.js +77 -81
- package/src/shade/renderer/rasterize/native/depth/shadow_rasterization_alpha_tested_pass_descriptor.js +144 -144
- package/src/shade/renderer/rasterize/native/depth/shadow_rasterization_pass_descriptor.js +88 -88
- package/src/shade/renderer/rasterize/native/oit/shader_oit_generate_moments.js +217 -217
- package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments.js +179 -179
- package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments_ibl.js +178 -178
- package/src/shade/renderer/rasterize/native/viz/viz_rasterization_alpha_tested_pass_descriptor.js +194 -194
- package/src/shade/renderer/rasterize/native/viz/viz_rasterization_opaque_pass_descriptor.js +76 -76
- package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.js +5 -1
- package/src/shade/renderer/restir/di/shader_restir_di_denoise.d.ts.map +1 -1
- package/src/shade/renderer/restir/di/shader_restir_di_denoise.js +136 -137
- package/src/shade/renderer/restir/di/shader_restir_di_resample.d.ts.map +1 -1
- package/src/shade/renderer/restir/di/shader_restir_di_resample.js +129 -130
- package/src/shade/renderer/restir/di/shader_restir_di_resolve.d.ts.map +1 -1
- package/src/shade/renderer/restir/di/shader_restir_di_resolve.js +99 -100
- package/src/shade/renderer/restir/di/shader_restir_di_spatial.d.ts.map +1 -1
- package/src/shade/renderer/restir/di/shader_restir_di_spatial.js +116 -117
- package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.js +383 -383
- package/src/shade/renderer/scene/hierarchy/graph_scene_update_transform_hierarchy_naive.js +123 -123
- package/src/shade/renderer/scene/hierarchy/shader_nodes_record_input_positions.d.ts.map +1 -1
- package/src/shade/renderer/scene/hierarchy/shader_nodes_record_input_positions.js +64 -65
- package/src/shade/renderer/scene/hierarchy/shader_nodes_update_transform_hierarchy.d.ts.map +1 -1
- package/src/shade/renderer/scene/hierarchy/shader_nodes_update_transform_hierarchy.js +372 -373
- package/src/shade/renderer/scene/hierarchy/shader_nodes_update_transform_hierarchy_naive.d.ts.map +1 -1
- package/src/shade/renderer/scene/hierarchy/shader_nodes_update_transform_hierarchy_naive.js +111 -112
- package/src/shade/renderer/scene/shader_bvh_extract_instance_leaves.d.ts.map +1 -1
- package/src/shade/renderer/scene/shader_bvh_extract_instance_leaves.js +0 -1
- package/src/shade/renderer/shader/ComputeShader.d.ts +24 -3
- package/src/shade/renderer/shader/ComputeShader.d.ts.map +1 -1
- package/src/shade/renderer/shader/ComputeShader.js +350 -292
- package/src/shade/renderer/shader/ImageShader.d.ts.map +1 -1
- package/src/shade/renderer/shader/ImageShader.js +217 -214
- package/src/shade/renderer/shader/ShaderDescriptor.d.ts +5 -0
- package/src/shade/renderer/shader/ShaderDescriptor.d.ts.map +1 -1
- package/src/shade/renderer/shader/ShaderDescriptor.js +46 -0
- package/src/shade/renderer/shader/chunk/atmosphere/ATMOSPHERE_RADII_DECLARATION.d.ts +18 -0
- package/src/shade/renderer/shader/chunk/atmosphere/ATMOSPHERE_RADII_DECLARATION.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/atmosphere/ATMOSPHERE_RADII_DECLARATION.js +32 -0
- package/src/shade/renderer/shader/chunk/atmosphere/PLANET_CENTER_DECLARATION.d.ts +7 -0
- package/src/shade/renderer/shader/chunk/atmosphere/PLANET_CENTER_DECLARATION.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/atmosphere/PLANET_CENTER_DECLARATION.js +17 -6
- package/src/shade/renderer/shader/chunk/atmosphere/chunk_atmosphere_ray_bounds.d.ts +21 -0
- package/src/shade/renderer/shader/chunk/atmosphere/chunk_atmosphere_ray_bounds.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/atmosphere/chunk_atmosphere_ray_bounds.js +69 -0
- package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_contains_aabb3.d.ts +9 -0
- package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_contains_aabb3.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_contains_aabb3.js +22 -0
- package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_from_transformed_corners.d.ts +16 -0
- package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_from_transformed_corners.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_from_transformed_corners.js +41 -0
- package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_m4.d.ts +11 -0
- package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_m4.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_m4.js +15 -19
- package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_plane_matrix.d.ts +23 -0
- package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_plane_matrix.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_plane_matrix.js +44 -0
- package/src/shade/renderer/shader/chunk/geometry/octahedron/chunk_uv_octahedral_unit_decode.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/geometry/octahedron/chunk_uv_octahedral_unit_decode.js +1 -4
- package/src/shade/renderer/shader/compiler/CodeChunk.d.ts +7 -1
- package/src/shade/renderer/shader/compiler/CodeChunk.d.ts.map +1 -1
- package/src/shade/renderer/shader/compiler/CodeChunk.js +37 -2
- package/src/shade/renderer/shader/graph/compute/compute_binding_read_names.d.ts.map +1 -1
- package/src/shade/renderer/shader/graph/compute/compute_binding_read_names.js +6 -0
- package/src/shade/renderer/shader/graph/compute/graph_compute_indirect_pass.js +1 -1
- package/src/shade/renderer/shader/graph/compute/graph_compute_pass.js +1 -1
- package/src/shade/renderer/shader/graph/graph_image_pass.js +1 -1
- package/src/shade/renderer/shader/graph/graph_prepare_bindings.d.ts.map +1 -1
- package/src/shade/renderer/shader/graph/graph_prepare_bindings.js +7 -0
- package/src/shade/renderer/shader/graph/graph_prepare_pass_input_data.d.ts +3 -1
- package/src/shade/renderer/shader/graph/graph_prepare_pass_input_data.d.ts.map +1 -1
- package/src/shade/renderer/shader/graph/graph_prepare_pass_input_data.js +12 -1
- package/src/shade/renderer/shader/pass/RenderPassDescriptor.d.ts.map +1 -1
- package/src/shade/renderer/shader/pass/RenderPassDescriptor.js +1 -0
- package/src/shade/renderer/shader/resource/IMMEDIATE_DATA.d.ts +21 -0
- package/src/shade/renderer/shader/resource/IMMEDIATE_DATA.d.ts.map +1 -0
- package/src/shade/renderer/shader/resource/IMMEDIATE_DATA.js +21 -0
- package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts +59 -1
- package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts.map +1 -1
- package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.js +195 -2
- package/src/shade/renderer/shader/type/type_has_arrays.d.ts +14 -0
- package/src/shade/renderer/shader/type/type_has_arrays.d.ts.map +1 -0
- package/src/shade/renderer/shader/type/type_has_arrays.js +33 -0
- package/src/shade/renderer/shader/util/compute_infer_workgroup_size_from_source.d.ts +47 -0
- package/src/shade/renderer/shader/util/compute_infer_workgroup_size_from_source.d.ts.map +1 -0
- package/src/shade/renderer/shader/util/compute_infer_workgroup_size_from_source.js +448 -0
- package/src/shade/renderer/shadow/map/csm/graph_csm_setup_cascades.js +3 -3
- package/src/shade/renderer/shadow/ray/staged/gen/graph_gen_rays.js +3 -3
- package/src/shade/renderer/shadow/ray/staged/trace/graph_trace_rays.js +2 -2
- package/src/shade/renderer/shadow/sdf/cascade/CascadedSceneSDF.js +4 -4
- package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.d.ts.map +1 -1
- package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.js +231 -232
- package/src/shade/renderer/view/GPUViewSkyContext.d.ts.map +1 -1
- package/src/shade/renderer/view/GPUViewSkyContext.js +169 -173
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.js +1 -1
- package/src/shade/renderer/volumetrics/NOTES.md +238 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_local_light_shadow.js +145 -145
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sun_optical_depth.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sun_optical_depth.js +38 -15
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts +14 -2
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +591 -577
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.d.ts +17 -0
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.js +20 -2
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_participating_media.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_participating_media.js +29 -18
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_scattering_lut.js +260 -260
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_sun_shadow_volume.d.ts +53 -3
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_sun_shadow_volume.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_sun_shadow_volume.js +175 -59
- package/src/shade/renderer/volumetrics/taa/shader_volumetrics_taa.d.ts +0 -2
- package/src/shade/renderer/volumetrics/taa/shader_volumetrics_taa.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/taa/shader_volumetrics_taa.js +17 -6
- package/src/shade/renderer/water/shader_water.js +246 -246
- package/src/shade/vitest.setup.mjs +1 -1
- package/src/shade/wgsl/emulator/ComputeShaderEmulator.js +291 -291
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +8 -1
- package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLLanguageCore.js +1325 -1297
- package/src/view/minimap/Minimap.d.ts +2 -2
- package/src/view/minimap/Minimap.d.ts.map +1 -1
- package/src/view/minimap/Minimap.js +225 -225
- package/src/view/minimap/dom/MinimapCameraView.d.ts +3 -3
- package/src/view/minimap/dom/MinimapCameraView.d.ts.map +1 -1
- package/src/view/minimap/dom/MinimapCameraView.js +206 -206
- package/src/shade/renderer/shadow/map/csm/shader/shader_setup_cascades.d.ts +0 -3
- package/src/shade/renderer/shadow/map/csm/shader/shader_setup_cascades.d.ts.map +0 -1
- package/src/shade/renderer/shadow/map/csm/shader/shader_setup_cascades.js +0 -20
- package/src/shade/renderer/volumetrics/VOLUMETRICS_WORKGROUP_RESOLUTION.d.ts +0 -2
- package/src/shade/renderer/volumetrics/VOLUMETRICS_WORKGROUP_RESOLUTION.d.ts.map +0 -1
- package/src/shade/renderer/volumetrics/VOLUMETRICS_WORKGROUP_RESOLUTION.js +0 -1
|
@@ -1,373 +1,372 @@
|
|
|
1
|
-
import { atomic_u32, u32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
|
|
2
|
-
import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
|
|
3
|
-
import { COLLECTION_U32_STRUCT_READ } from "../../gpu_primitive/COLLECTION_U32_STRUCT_READ.js";
|
|
4
|
-
import { chunk_scene_database_access_rw } from "../chunk_scene_database_access.js";
|
|
5
|
-
import { NODE3D_SCENE_ID } from "../NODE3D_STRUCT.js";
|
|
6
|
-
import { chunk_mat4_compose_transform } from "../../shader/chunk/geometry/mat4/chunk_mat4_compose_transform.js";
|
|
7
|
-
import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
|
|
8
|
-
import { ComputeShader } from "../../shader/ComputeShader.js";
|
|
9
|
-
import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
|
|
10
|
-
import { TRANSFORM_HIERARCHY_PARTITION_SIZE } from "./TRANSFORM_HIERARCHY_PARTITION_SIZE.js";
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Maximum depth of parent chain a thread walks via the local-fallback
|
|
14
|
-
* path. Sized to `PARTITION_SIZE` so any thread is guaranteed enough
|
|
15
|
-
* steps to escape its own tile: once the walk crosses a tile boundary,
|
|
16
|
-
* the fast-path read of `published_globals` can take over. A smaller
|
|
17
|
-
* bound silently truncates in-input chains that live entirely inside
|
|
18
|
-
* one tile (e.g. a 1024-bone chain laid out sequentially); chains
|
|
19
|
-
* deeper than `PARTITION_SIZE` *within a single tile* will still
|
|
20
|
-
* truncate, but that's a contrived case worth raising the bound for
|
|
21
|
-
* if it ever shows up in a real workload.
|
|
22
|
-
*
|
|
23
|
-
* @type {number}
|
|
24
|
-
*/
|
|
25
|
-
const MAX_PARENT_WALK = TRANSFORM_HIERARCHY_PARTITION_SIZE;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* How many times a stuck workgroup spins reading a predecessor tile's
|
|
29
|
-
* spine flag before falling back to walking the parent chain via local
|
|
30
|
-
* matrices. A higher value gives the predecessor more time to publish
|
|
31
|
-
* its `global` — useful when the predecessor is doing real work — at
|
|
32
|
-
* the cost of latency when it's actually stalled.
|
|
33
|
-
*
|
|
34
|
-
* @type {number}
|
|
35
|
-
*/
|
|
36
|
-
const MAX_SPIN_COUNT = 4;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Per-tile spine slot states. Mirrors the FLAG_NOT_READY / FLAG_INCLUSIVE
|
|
40
|
-
* convention from the prefix-scan CSDLDF shader, minus FLAG_READY — we
|
|
41
|
-
* don't have an intermediate "I have a partial value" state, since each
|
|
42
|
-
* tile either has fully written all its `global`s or hasn't.
|
|
43
|
-
*/
|
|
44
|
-
const FLAG_NOT_READY = 0;
|
|
45
|
-
const FLAG_INCLUSIVE = 1;
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* The CSDLDF-style ("Chained Scan with Decoupled Lookback Decoupled
|
|
49
|
-
* Fallback") propagation pass for scene-graph node transforms.
|
|
50
|
-
*
|
|
51
|
-
* **Inputs**
|
|
52
|
-
* - `input`: COLLECTION_U32 of node IDs to update. Assumed
|
|
53
|
-
* *partially* topologically sorted — nodes at lower depth come
|
|
54
|
-
* earlier — but the shader doesn't trust this beyond using it for
|
|
55
|
-
* the lookback fast path; correctness doesn't depend on it.
|
|
56
|
-
* - `scene_database`: the GPUDatabase backing store; we read each
|
|
57
|
-
* node's `local` and `parent` fields and overwrite `global`.
|
|
58
|
-
* - `node_to_tile`: a lookup populated by the setup shader. Slot
|
|
59
|
-
* `node_id` is `0` if `node_id` is not in the input (its `global`
|
|
60
|
-
* is trusted as-is), or `position + 1` if it is. Position indexes
|
|
61
|
-
* `published_globals`; tile is derived as `position / PARTITION`
|
|
62
|
-
* for the spine check.
|
|
63
|
-
* - `spine`: per-tile flag, `FLAG_INCLUSIVE` once that tile has
|
|
64
|
-
* finished publishing all of its nodes' `global`s atomically.
|
|
65
|
-
* - `published_globals`: per-input-position atomic mat4 buffer.
|
|
66
|
-
* Cross-tile readers consume from here, NOT from
|
|
67
|
-
* `scene_database.global`. See the "Memory ordering" section
|
|
68
|
-
* below for why.
|
|
69
|
-
*
|
|
70
|
-
* **Per-thread work**
|
|
71
|
-
*
|
|
72
|
-
* One thread per input position. Each thread walks its node's parent
|
|
73
|
-
* chain accumulating the cumulative transform left-multiplied by each
|
|
74
|
-
* ancestor's `local`. The walk terminates as soon as we hit any of:
|
|
75
|
-
* - `parent == NODE3D_SCENE_ID` — reached the scene root, walk stops
|
|
76
|
-
* here. Top-level nodes inherit row 0, and `0` is the natural
|
|
77
|
-
* value of a freshly-zeroed buffer, so this sentinel doubles as a
|
|
78
|
-
* "no further ancestor" marker.
|
|
79
|
-
* - parent is *not* in the input — its `global` is trusted (stable
|
|
80
|
-
* this dispatch), read it directly from `scene_database`,
|
|
81
|
-
* prepend, stop.
|
|
82
|
-
* - parent is in an *earlier* tile and that tile's spine slot is
|
|
83
|
-
* `FLAG_INCLUSIVE` — read parent's mat4 from `published_globals`
|
|
84
|
-
* (atomic loads, see ordering note), prepend, stop.
|
|
85
|
-
*
|
|
86
|
-
* If the spine isn't ready yet, we spin a bounded number of times then
|
|
87
|
-
* **fall back** to the slow path: prepend `parent.local` and step up to
|
|
88
|
-
* the parent's parent. The fallback is always correct: `local` matrices
|
|
89
|
-
* are stable this dispatch (only `global` is being rewritten), so the
|
|
90
|
-
* walk is independent of any other workgroup's progress.
|
|
91
|
-
*
|
|
92
|
-
* After every thread in the workgroup has finished publishing its
|
|
93
|
-
* `global` to `published_globals` and to `scene_database` (a
|
|
94
|
-
* `workgroupBarrier` ensures this), thread 0 atomically stores
|
|
95
|
-
* `FLAG_INCLUSIVE` to this tile's spine slot. The release point for
|
|
96
|
-
* cross-tile readers is the spine flag.
|
|
97
|
-
*
|
|
98
|
-
* **Memory ordering — trusts WGSL SeqCst across separate atomic words.**
|
|
99
|
-
*
|
|
100
|
-
* The Decoupled Fallback paper (Smith/Levien/Owens, SPAA '25, §4.3)
|
|
101
|
-
* specifically AVOIDS this pattern: it packs tile state into the same
|
|
102
|
-
* atomic word as the data via "atomic splitting", because *relaxed*
|
|
103
|
-
* atomics — which the paper assumes — don't order non-atomic stores
|
|
104
|
-
* relative to atomic stores across separate memory locations. WGSL
|
|
105
|
-
* atomics are spec'd as sequentially consistent (not relaxed), so a
|
|
106
|
-
* separate atomic flag DOES order earlier atomic data stores via the
|
|
107
|
-
* single global total order on atomic operations. We rely on that here
|
|
108
|
-
* because atomic-splitting a 64-byte mat4 means ~32 atomic_u32 per
|
|
109
|
-
* published global with state bits per word — roughly 2× the memory
|
|
110
|
-
* traffic of "data atomics + flag atomic".
|
|
111
|
-
*
|
|
112
|
-
* Why we accept the risk: this feature isn't shipping yet, the primary
|
|
113
|
-
* Dawn backends (Vulkan/Metal/D3D12) translate WGSL atomics to
|
|
114
|
-
* backend-equivalent SeqCst operations, and we expect spec conformance
|
|
115
|
-
* to tighten. If real-world testing on Apple/ARM (which the paper
|
|
116
|
-
* specifically benchmarks as FPG-lacking) shows visibility violations,
|
|
117
|
-
* the fix is to switch `published_globals` to atomic-splitting style:
|
|
118
|
-
* pack the mat4 across more atomic words, each carrying state bits in
|
|
119
|
-
* its high bits, and have the reader verify all words agree on
|
|
120
|
-
* INCLUSIVE before trusting the value (paper §4.3, Figure 5).
|
|
121
|
-
*
|
|
122
|
-
* Failure mode if SeqCst is broken: a reader sees the spine flag as
|
|
123
|
-
* INCLUSIVE but reads stale (or zero) entries from `published_globals`,
|
|
124
|
-
* propagating a wrong world transform with no fallback safety net (the
|
|
125
|
-
* fallback only fires on FLAG_NOT_READY, not on a stale-but-flagged
|
|
126
|
-
* read).
|
|
127
|
-
*
|
|
128
|
-
* @see graph_prefix_scan_csdldf — same lookback / fallback shape.
|
|
129
|
-
* @type {ComputeShader}
|
|
130
|
-
*/
|
|
131
|
-
const resources = new ShaderResourceSetDescriptor();
|
|
132
|
-
resources.createGroup()
|
|
133
|
-
.addStorageBuffer("input", COLLECTION_U32_STRUCT_READ)
|
|
134
|
-
.addStorageBuffer("scene_database", WebGPUArray.from(u32), true)
|
|
135
|
-
.addStorageBuffer("node_to_tile", WebGPUArray.from(u32))
|
|
136
|
-
.addStorageBuffer("spine", WebGPUArray.from(atomic_u32), true)
|
|
137
|
-
.addStorageBuffer("published_globals", WebGPUArray.from(atomic_u32), true);
|
|
138
|
-
|
|
139
|
-
const body = CodeChunk.from(
|
|
140
|
-
//language=WGSL
|
|
141
|
-
`
|
|
142
|
-
const SCENE_NODE: u32 = ${NODE3D_SCENE_ID}u;
|
|
143
|
-
|
|
144
|
-
const NOT_IN_INPUT: u32 = 0u;
|
|
145
|
-
|
|
146
|
-
const FLAG_NOT_READY: u32 = ${FLAG_NOT_READY}u;
|
|
147
|
-
const FLAG_INCLUSIVE: u32 = ${FLAG_INCLUSIVE}u;
|
|
148
|
-
|
|
149
|
-
const MAX_PARENT_WALK: u32 = ${MAX_PARENT_WALK}u;
|
|
150
|
-
const MAX_SPIN_COUNT: u32 = ${MAX_SPIN_COUNT}u;
|
|
151
|
-
|
|
152
|
-
const PARTITION_SIZE: u32 = ${TRANSFORM_HIERARCHY_PARTITION_SIZE}u;
|
|
153
|
-
|
|
154
|
-
// 16 f32 columns-major; a mat4x4<f32> is published as 16 atomic_u32
|
|
155
|
-
// entries starting at \`pos * MAT4_STRIDE\`.
|
|
156
|
-
const MAT4_STRIDE: u32 = 16u;
|
|
157
|
-
|
|
158
|
-
// Atomically publish \`m\` to slot \`pos\` of \`published_globals\`. Stores
|
|
159
|
-
// columns 0..3 in order, x..w within each column. Pair with
|
|
160
|
-
// \`read_published_global\` on the reader side. The 16 atomicStores are
|
|
161
|
-
// individually ordered relative to subsequent atomic operations by WGSL
|
|
162
|
-
// SeqCst — see header doc for why we rely on that.
|
|
163
|
-
fn publish_global(pos: u32, m: mat4x4<f32>) {
|
|
164
|
-
let base = pos * MAT4_STRIDE;
|
|
165
|
-
atomicStore(&published_globals[base + 0u], bitcast<u32>(m[0].x));
|
|
166
|
-
atomicStore(&published_globals[base + 1u], bitcast<u32>(m[0].y));
|
|
167
|
-
atomicStore(&published_globals[base + 2u], bitcast<u32>(m[0].z));
|
|
168
|
-
atomicStore(&published_globals[base + 3u], bitcast<u32>(m[0].w));
|
|
169
|
-
atomicStore(&published_globals[base + 4u], bitcast<u32>(m[1].x));
|
|
170
|
-
atomicStore(&published_globals[base + 5u], bitcast<u32>(m[1].y));
|
|
171
|
-
atomicStore(&published_globals[base + 6u], bitcast<u32>(m[1].z));
|
|
172
|
-
atomicStore(&published_globals[base + 7u], bitcast<u32>(m[1].w));
|
|
173
|
-
atomicStore(&published_globals[base + 8u], bitcast<u32>(m[2].x));
|
|
174
|
-
atomicStore(&published_globals[base + 9u], bitcast<u32>(m[2].y));
|
|
175
|
-
atomicStore(&published_globals[base + 10u], bitcast<u32>(m[2].z));
|
|
176
|
-
atomicStore(&published_globals[base + 11u], bitcast<u32>(m[2].w));
|
|
177
|
-
atomicStore(&published_globals[base + 12u], bitcast<u32>(m[3].x));
|
|
178
|
-
atomicStore(&published_globals[base + 13u], bitcast<u32>(m[3].y));
|
|
179
|
-
atomicStore(&published_globals[base + 14u], bitcast<u32>(m[3].z));
|
|
180
|
-
atomicStore(&published_globals[base + 15u], bitcast<u32>(m[3].w));
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// Reads a previously-published mat4 from \`published_globals\`. Caller
|
|
184
|
-
// must have already observed FLAG_INCLUSIVE on the parent's tile spine
|
|
185
|
-
// slot — that observation is what serializes these atomicLoads against
|
|
186
|
-
// the publishing workgroup's atomicStores.
|
|
187
|
-
fn read_published_global(pos: u32) -> mat4x4<f32> {
|
|
188
|
-
let base = pos * MAT4_STRIDE;
|
|
189
|
-
return mat4x4<f32>(
|
|
190
|
-
vec4<f32>(
|
|
191
|
-
bitcast<f32>(atomicLoad(&published_globals[base + 0u])),
|
|
192
|
-
bitcast<f32>(atomicLoad(&published_globals[base + 1u])),
|
|
193
|
-
bitcast<f32>(atomicLoad(&published_globals[base + 2u])),
|
|
194
|
-
bitcast<f32>(atomicLoad(&published_globals[base + 3u])),
|
|
195
|
-
),
|
|
196
|
-
vec4<f32>(
|
|
197
|
-
bitcast<f32>(atomicLoad(&published_globals[base + 4u])),
|
|
198
|
-
bitcast<f32>(atomicLoad(&published_globals[base + 5u])),
|
|
199
|
-
bitcast<f32>(atomicLoad(&published_globals[base + 6u])),
|
|
200
|
-
bitcast<f32>(atomicLoad(&published_globals[base + 7u])),
|
|
201
|
-
),
|
|
202
|
-
vec4<f32>(
|
|
203
|
-
bitcast<f32>(atomicLoad(&published_globals[base + 8u])),
|
|
204
|
-
bitcast<f32>(atomicLoad(&published_globals[base + 9u])),
|
|
205
|
-
bitcast<f32>(atomicLoad(&published_globals[base + 10u])),
|
|
206
|
-
bitcast<f32>(atomicLoad(&published_globals[base + 11u])),
|
|
207
|
-
),
|
|
208
|
-
vec4<f32>(
|
|
209
|
-
bitcast<f32>(atomicLoad(&published_globals[base + 12u])),
|
|
210
|
-
bitcast<f32>(atomicLoad(&published_globals[base + 13u])),
|
|
211
|
-
bitcast<f32>(atomicLoad(&published_globals[base + 14u])),
|
|
212
|
-
bitcast<f32>(atomicLoad(&published_globals[base + 15u])),
|
|
213
|
-
),
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
@compute @workgroup_size(${TRANSFORM_HIERARCHY_PARTITION_SIZE})
|
|
218
|
-
fn main(
|
|
219
|
-
@builtin(global_invocation_id) gid: vec3<u32>,
|
|
220
|
-
@builtin(local_invocation_id) lid: vec3<u32>,
|
|
221
|
-
@builtin(workgroup_id) wid: vec3<u32>,
|
|
222
|
-
) {
|
|
223
|
-
let pos = gid.x;
|
|
224
|
-
let my_tile = wid.x;
|
|
225
|
-
|
|
226
|
-
// Threads beyond input.count still need to participate in the
|
|
227
|
-
// workgroupBarrier below (uniform control flow), but they don't do
|
|
228
|
-
// any work and don't read or write \`global\`.
|
|
229
|
-
let in_range = pos < input.count;
|
|
230
|
-
|
|
231
|
-
if(in_range){
|
|
232
|
-
let node_id = input.elements[pos];
|
|
233
|
-
|
|
234
|
-
var node = scene_read_node_rw(&scene_database, node_id);
|
|
235
|
-
|
|
236
|
-
// Capture this node's current \`global\` as last frame's
|
|
237
|
-
// value, before the new compose overwrites it later in this
|
|
238
|
-
// function. The full transforms row was just loaded above —
|
|
239
|
-
// reading the field here is free, and writing prev_global
|
|
240
|
-
// ahead of the new global means downstream consumers reading
|
|
241
|
-
// both (motion-vector generation, TAA) never see a window
|
|
242
|
-
// where prev and current describe the same frame.
|
|
243
|
-
scene_write_node_prev_global(&scene_database, node_id, node.global);
|
|
244
|
-
|
|
245
|
-
// acc accumulates ancestor.local * ... * parent.local * node.local
|
|
246
|
-
// (a correct world-space transform once we hit a trusted ancestor
|
|
247
|
-
// or root). The local transform isn't stored as a matrix — we
|
|
248
|
-
// build it on the fly from the node's TRS triplet.
|
|
249
|
-
var acc = mat4_compose_transform(node.local_translation, node.local_rotation, node.local_scale);
|
|
250
|
-
var parent_id = node.parent;
|
|
251
|
-
|
|
252
|
-
// Walk up the parent chain. Each iteration either commits — by
|
|
253
|
-
// prepending a trusted parent.global onto the accumulator and
|
|
254
|
-
// breaking — or falls back: prepends parent.local and steps to
|
|
255
|
-
// the next ancestor.
|
|
256
|
-
var walk_steps = 0u;
|
|
257
|
-
loop {
|
|
258
|
-
if(parent_id == SCENE_NODE){
|
|
259
|
-
// Reached the scene root — acc IS the world transform.
|
|
260
|
-
// The scene's TRS is composed implicitly here by stopping
|
|
261
|
-
// before reading row 0; if a future scene-level pose is
|
|
262
|
-
// wanted, replace the break with a read+prepend of the
|
|
263
|
-
// scene's compose.
|
|
264
|
-
break;
|
|
265
|
-
}
|
|
266
|
-
if(walk_steps >= MAX_PARENT_WALK){
|
|
267
|
-
break; // bail out on pathological depth
|
|
268
|
-
}
|
|
269
|
-
walk_steps = walk_steps + 1u;
|
|
270
|
-
|
|
271
|
-
let slot = node_to_tile[parent_id];
|
|
272
|
-
|
|
273
|
-
if(slot == NOT_IN_INPUT){
|
|
274
|
-
// Parent isn't being updated this dispatch. Whatever
|
|
275
|
-
// \`global\` is on the database is what downstream
|
|
276
|
-
// consumers will see — use it.
|
|
277
|
-
let parent = scene_read_node_rw(&scene_database, parent_id);
|
|
278
|
-
acc = parent.global * acc;
|
|
279
|
-
break;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
let parent_pos = slot - 1u; // undo the +1 encoding
|
|
283
|
-
let parent_tile = parent_pos / PARTITION_SIZE; // tile derived from position
|
|
284
|
-
|
|
285
|
-
if(parent_tile < my_tile){
|
|
286
|
-
// Parent's tile must have published before us — but it
|
|
287
|
-
// might still be in flight. Spin briefly on the spine
|
|
288
|
-
// flag; if we time out, fall back to walking via
|
|
289
|
-
// parent.local. The fallback is always correct, just
|
|
290
|
-
// potentially redundant work.
|
|
291
|
-
var spin = 0u;
|
|
292
|
-
var got_inclusive = false;
|
|
293
|
-
loop {
|
|
294
|
-
if(atomicLoad(&spine[parent_tile]) == FLAG_INCLUSIVE){
|
|
295
|
-
got_inclusive = true;
|
|
296
|
-
break;
|
|
297
|
-
}
|
|
298
|
-
spin = spin + 1u;
|
|
299
|
-
if(spin >= MAX_SPIN_COUNT){
|
|
300
|
-
break;
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
if(got_inclusive){
|
|
305
|
-
// Spine flag observed INCLUSIVE → WGSL SeqCst's total
|
|
306
|
-
// order on atomics guarantees the publishing
|
|
307
|
-
// workgroup's atomicStores into published_globals are
|
|
308
|
-
// visible to these atomicLoads. Read via the atomic
|
|
309
|
-
// buffer, NOT scene_database.global (which is a
|
|
310
|
-
// non-atomic view and not ordered against the flag).
|
|
311
|
-
acc = read_published_global(parent_pos) * acc;
|
|
312
|
-
break;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
// Fallback / parent in same-or-later tile: walk via local.
|
|
317
|
-
// (The "later tile" case shouldn't hit with strict
|
|
318
|
-
// topological ordering, but if it does, walking via local
|
|
319
|
-
// is still correct.)
|
|
320
|
-
let parent = scene_read_node_rw(&scene_database, parent_id);
|
|
321
|
-
let parent_local = mat4_compose_transform(parent.local_translation, parent.local_rotation, parent.local_scale);
|
|
322
|
-
acc = parent_local * acc;
|
|
323
|
-
parent_id = parent.parent;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
// Atomic publish first — these 16 atomicStores into
|
|
327
|
-
// published_globals[pos] are what the spine flag's atomicStore
|
|
328
|
-
// (below) releases to other tiles via WGSL's SeqCst order on
|
|
329
|
-
// atomic operations.
|
|
330
|
-
publish_global(pos, acc);
|
|
331
|
-
|
|
332
|
-
// Mirror to the database for downstream non-atomic consumers
|
|
333
|
-
// (rendering, raymarching, etc., reading scene_database.global
|
|
334
|
-
// after this dispatch's command-buffer barrier). Only the
|
|
335
|
-
// "global" field is written: the whole-struct write that used
|
|
336
|
-
// to live here was a hazard — if "scene_read_node_rw" above
|
|
337
|
-
// ever returned zeros for any reason (buffer not yet uploaded,
|
|
338
|
-
// page-lookup race, anything), "node.local_T/R/S" would be
|
|
339
|
-
// zero and the writeback would *persist* those zeros into the
|
|
340
|
-
// row. The next frame's hierarchy reads the persisted zeros,
|
|
341
|
-
// composes a zero matrix, propagates it down — every
|
|
342
|
-
// descendant collapses to the origin and stays there. Touching
|
|
343
|
-
// only "global" means a transient stale read can't poison
|
|
344
|
-
// local_TRS.
|
|
345
|
-
scene_write_node_global(&scene_database, node_id, acc);
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
// Publish: every thread in this workgroup has finished its
|
|
349
|
-
// atomicStores into published_globals by the barrier. Thread 0's
|
|
350
|
-
// atomicStore on the spine slot is the single release point — any
|
|
351
|
-
// other workgroup that observes FLAG_INCLUSIVE on this slot is
|
|
352
|
-
// guaranteed (under WGSL SeqCst) to see all 16 published_globals
|
|
353
|
-
// atomicStores from any thread of this workgroup.
|
|
354
|
-
workgroupBarrier();
|
|
355
|
-
if(lid.x == 0u){
|
|
356
|
-
atomicStore(&spine[my_tile], FLAG_INCLUSIVE);
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
`, [
|
|
360
|
-
chunk_scene_database_access_rw,
|
|
361
|
-
chunk_mat4_compose_transform,
|
|
362
|
-
]);
|
|
363
|
-
|
|
364
|
-
/**
|
|
365
|
-
* @see {@link graph_nodes_update_transform_hierarchy} — frame-graph harness.
|
|
366
|
-
* @type {ComputeShader}
|
|
367
|
-
*/
|
|
368
|
-
export const shader_nodes_update_transform_hierarchy = ComputeShader.from({
|
|
369
|
-
label: "SceneGraph/UpdateTransformHierarchy",
|
|
370
|
-
body,
|
|
371
|
-
resources,
|
|
372
|
-
|
|
373
|
-
});
|
|
1
|
+
import { atomic_u32, u32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
|
|
2
|
+
import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
|
|
3
|
+
import { COLLECTION_U32_STRUCT_READ } from "../../gpu_primitive/COLLECTION_U32_STRUCT_READ.js";
|
|
4
|
+
import { chunk_scene_database_access_rw } from "../chunk_scene_database_access.js";
|
|
5
|
+
import { NODE3D_SCENE_ID } from "../NODE3D_STRUCT.js";
|
|
6
|
+
import { chunk_mat4_compose_transform } from "../../shader/chunk/geometry/mat4/chunk_mat4_compose_transform.js";
|
|
7
|
+
import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
|
|
8
|
+
import { ComputeShader } from "../../shader/ComputeShader.js";
|
|
9
|
+
import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
|
|
10
|
+
import { TRANSFORM_HIERARCHY_PARTITION_SIZE } from "./TRANSFORM_HIERARCHY_PARTITION_SIZE.js";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Maximum depth of parent chain a thread walks via the local-fallback
|
|
14
|
+
* path. Sized to `PARTITION_SIZE` so any thread is guaranteed enough
|
|
15
|
+
* steps to escape its own tile: once the walk crosses a tile boundary,
|
|
16
|
+
* the fast-path read of `published_globals` can take over. A smaller
|
|
17
|
+
* bound silently truncates in-input chains that live entirely inside
|
|
18
|
+
* one tile (e.g. a 1024-bone chain laid out sequentially); chains
|
|
19
|
+
* deeper than `PARTITION_SIZE` *within a single tile* will still
|
|
20
|
+
* truncate, but that's a contrived case worth raising the bound for
|
|
21
|
+
* if it ever shows up in a real workload.
|
|
22
|
+
*
|
|
23
|
+
* @type {number}
|
|
24
|
+
*/
|
|
25
|
+
const MAX_PARENT_WALK = TRANSFORM_HIERARCHY_PARTITION_SIZE;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* How many times a stuck workgroup spins reading a predecessor tile's
|
|
29
|
+
* spine flag before falling back to walking the parent chain via local
|
|
30
|
+
* matrices. A higher value gives the predecessor more time to publish
|
|
31
|
+
* its `global` — useful when the predecessor is doing real work — at
|
|
32
|
+
* the cost of latency when it's actually stalled.
|
|
33
|
+
*
|
|
34
|
+
* @type {number}
|
|
35
|
+
*/
|
|
36
|
+
const MAX_SPIN_COUNT = 4;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Per-tile spine slot states. Mirrors the FLAG_NOT_READY / FLAG_INCLUSIVE
|
|
40
|
+
* convention from the prefix-scan CSDLDF shader, minus FLAG_READY — we
|
|
41
|
+
* don't have an intermediate "I have a partial value" state, since each
|
|
42
|
+
* tile either has fully written all its `global`s or hasn't.
|
|
43
|
+
*/
|
|
44
|
+
const FLAG_NOT_READY = 0;
|
|
45
|
+
const FLAG_INCLUSIVE = 1;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The CSDLDF-style ("Chained Scan with Decoupled Lookback Decoupled
|
|
49
|
+
* Fallback") propagation pass for scene-graph node transforms.
|
|
50
|
+
*
|
|
51
|
+
* **Inputs**
|
|
52
|
+
* - `input`: COLLECTION_U32 of node IDs to update. Assumed
|
|
53
|
+
* *partially* topologically sorted — nodes at lower depth come
|
|
54
|
+
* earlier — but the shader doesn't trust this beyond using it for
|
|
55
|
+
* the lookback fast path; correctness doesn't depend on it.
|
|
56
|
+
* - `scene_database`: the GPUDatabase backing store; we read each
|
|
57
|
+
* node's `local` and `parent` fields and overwrite `global`.
|
|
58
|
+
* - `node_to_tile`: a lookup populated by the setup shader. Slot
|
|
59
|
+
* `node_id` is `0` if `node_id` is not in the input (its `global`
|
|
60
|
+
* is trusted as-is), or `position + 1` if it is. Position indexes
|
|
61
|
+
* `published_globals`; tile is derived as `position / PARTITION`
|
|
62
|
+
* for the spine check.
|
|
63
|
+
* - `spine`: per-tile flag, `FLAG_INCLUSIVE` once that tile has
|
|
64
|
+
* finished publishing all of its nodes' `global`s atomically.
|
|
65
|
+
* - `published_globals`: per-input-position atomic mat4 buffer.
|
|
66
|
+
* Cross-tile readers consume from here, NOT from
|
|
67
|
+
* `scene_database.global`. See the "Memory ordering" section
|
|
68
|
+
* below for why.
|
|
69
|
+
*
|
|
70
|
+
* **Per-thread work**
|
|
71
|
+
*
|
|
72
|
+
* One thread per input position. Each thread walks its node's parent
|
|
73
|
+
* chain accumulating the cumulative transform left-multiplied by each
|
|
74
|
+
* ancestor's `local`. The walk terminates as soon as we hit any of:
|
|
75
|
+
* - `parent == NODE3D_SCENE_ID` — reached the scene root, walk stops
|
|
76
|
+
* here. Top-level nodes inherit row 0, and `0` is the natural
|
|
77
|
+
* value of a freshly-zeroed buffer, so this sentinel doubles as a
|
|
78
|
+
* "no further ancestor" marker.
|
|
79
|
+
* - parent is *not* in the input — its `global` is trusted (stable
|
|
80
|
+
* this dispatch), read it directly from `scene_database`,
|
|
81
|
+
* prepend, stop.
|
|
82
|
+
* - parent is in an *earlier* tile and that tile's spine slot is
|
|
83
|
+
* `FLAG_INCLUSIVE` — read parent's mat4 from `published_globals`
|
|
84
|
+
* (atomic loads, see ordering note), prepend, stop.
|
|
85
|
+
*
|
|
86
|
+
* If the spine isn't ready yet, we spin a bounded number of times then
|
|
87
|
+
* **fall back** to the slow path: prepend `parent.local` and step up to
|
|
88
|
+
* the parent's parent. The fallback is always correct: `local` matrices
|
|
89
|
+
* are stable this dispatch (only `global` is being rewritten), so the
|
|
90
|
+
* walk is independent of any other workgroup's progress.
|
|
91
|
+
*
|
|
92
|
+
* After every thread in the workgroup has finished publishing its
|
|
93
|
+
* `global` to `published_globals` and to `scene_database` (a
|
|
94
|
+
* `workgroupBarrier` ensures this), thread 0 atomically stores
|
|
95
|
+
* `FLAG_INCLUSIVE` to this tile's spine slot. The release point for
|
|
96
|
+
* cross-tile readers is the spine flag.
|
|
97
|
+
*
|
|
98
|
+
* **Memory ordering — trusts WGSL SeqCst across separate atomic words.**
|
|
99
|
+
*
|
|
100
|
+
* The Decoupled Fallback paper (Smith/Levien/Owens, SPAA '25, §4.3)
|
|
101
|
+
* specifically AVOIDS this pattern: it packs tile state into the same
|
|
102
|
+
* atomic word as the data via "atomic splitting", because *relaxed*
|
|
103
|
+
* atomics — which the paper assumes — don't order non-atomic stores
|
|
104
|
+
* relative to atomic stores across separate memory locations. WGSL
|
|
105
|
+
* atomics are spec'd as sequentially consistent (not relaxed), so a
|
|
106
|
+
* separate atomic flag DOES order earlier atomic data stores via the
|
|
107
|
+
* single global total order on atomic operations. We rely on that here
|
|
108
|
+
* because atomic-splitting a 64-byte mat4 means ~32 atomic_u32 per
|
|
109
|
+
* published global with state bits per word — roughly 2× the memory
|
|
110
|
+
* traffic of "data atomics + flag atomic".
|
|
111
|
+
*
|
|
112
|
+
* Why we accept the risk: this feature isn't shipping yet, the primary
|
|
113
|
+
* Dawn backends (Vulkan/Metal/D3D12) translate WGSL atomics to
|
|
114
|
+
* backend-equivalent SeqCst operations, and we expect spec conformance
|
|
115
|
+
* to tighten. If real-world testing on Apple/ARM (which the paper
|
|
116
|
+
* specifically benchmarks as FPG-lacking) shows visibility violations,
|
|
117
|
+
* the fix is to switch `published_globals` to atomic-splitting style:
|
|
118
|
+
* pack the mat4 across more atomic words, each carrying state bits in
|
|
119
|
+
* its high bits, and have the reader verify all words agree on
|
|
120
|
+
* INCLUSIVE before trusting the value (paper §4.3, Figure 5).
|
|
121
|
+
*
|
|
122
|
+
* Failure mode if SeqCst is broken: a reader sees the spine flag as
|
|
123
|
+
* INCLUSIVE but reads stale (or zero) entries from `published_globals`,
|
|
124
|
+
* propagating a wrong world transform with no fallback safety net (the
|
|
125
|
+
* fallback only fires on FLAG_NOT_READY, not on a stale-but-flagged
|
|
126
|
+
* read).
|
|
127
|
+
*
|
|
128
|
+
* @see graph_prefix_scan_csdldf — same lookback / fallback shape.
|
|
129
|
+
* @type {ComputeShader}
|
|
130
|
+
*/
|
|
131
|
+
const resources = new ShaderResourceSetDescriptor();
|
|
132
|
+
resources.createGroup()
|
|
133
|
+
.addStorageBuffer("input", COLLECTION_U32_STRUCT_READ)
|
|
134
|
+
.addStorageBuffer("scene_database", WebGPUArray.from(u32), true)
|
|
135
|
+
.addStorageBuffer("node_to_tile", WebGPUArray.from(u32))
|
|
136
|
+
.addStorageBuffer("spine", WebGPUArray.from(atomic_u32), true)
|
|
137
|
+
.addStorageBuffer("published_globals", WebGPUArray.from(atomic_u32), true);
|
|
138
|
+
|
|
139
|
+
const body = CodeChunk.from(
|
|
140
|
+
//language=WGSL
|
|
141
|
+
`
|
|
142
|
+
const SCENE_NODE: u32 = ${NODE3D_SCENE_ID}u;
|
|
143
|
+
|
|
144
|
+
const NOT_IN_INPUT: u32 = 0u;
|
|
145
|
+
|
|
146
|
+
const FLAG_NOT_READY: u32 = ${FLAG_NOT_READY}u;
|
|
147
|
+
const FLAG_INCLUSIVE: u32 = ${FLAG_INCLUSIVE}u;
|
|
148
|
+
|
|
149
|
+
const MAX_PARENT_WALK: u32 = ${MAX_PARENT_WALK}u;
|
|
150
|
+
const MAX_SPIN_COUNT: u32 = ${MAX_SPIN_COUNT}u;
|
|
151
|
+
|
|
152
|
+
const PARTITION_SIZE: u32 = ${TRANSFORM_HIERARCHY_PARTITION_SIZE}u;
|
|
153
|
+
|
|
154
|
+
// 16 f32 columns-major; a mat4x4<f32> is published as 16 atomic_u32
|
|
155
|
+
// entries starting at \`pos * MAT4_STRIDE\`.
|
|
156
|
+
const MAT4_STRIDE: u32 = 16u;
|
|
157
|
+
|
|
158
|
+
// Atomically publish \`m\` to slot \`pos\` of \`published_globals\`. Stores
|
|
159
|
+
// columns 0..3 in order, x..w within each column. Pair with
|
|
160
|
+
// \`read_published_global\` on the reader side. The 16 atomicStores are
|
|
161
|
+
// individually ordered relative to subsequent atomic operations by WGSL
|
|
162
|
+
// SeqCst — see header doc for why we rely on that.
|
|
163
|
+
fn publish_global(pos: u32, m: mat4x4<f32>) {
|
|
164
|
+
let base = pos * MAT4_STRIDE;
|
|
165
|
+
atomicStore(&published_globals[base + 0u], bitcast<u32>(m[0].x));
|
|
166
|
+
atomicStore(&published_globals[base + 1u], bitcast<u32>(m[0].y));
|
|
167
|
+
atomicStore(&published_globals[base + 2u], bitcast<u32>(m[0].z));
|
|
168
|
+
atomicStore(&published_globals[base + 3u], bitcast<u32>(m[0].w));
|
|
169
|
+
atomicStore(&published_globals[base + 4u], bitcast<u32>(m[1].x));
|
|
170
|
+
atomicStore(&published_globals[base + 5u], bitcast<u32>(m[1].y));
|
|
171
|
+
atomicStore(&published_globals[base + 6u], bitcast<u32>(m[1].z));
|
|
172
|
+
atomicStore(&published_globals[base + 7u], bitcast<u32>(m[1].w));
|
|
173
|
+
atomicStore(&published_globals[base + 8u], bitcast<u32>(m[2].x));
|
|
174
|
+
atomicStore(&published_globals[base + 9u], bitcast<u32>(m[2].y));
|
|
175
|
+
atomicStore(&published_globals[base + 10u], bitcast<u32>(m[2].z));
|
|
176
|
+
atomicStore(&published_globals[base + 11u], bitcast<u32>(m[2].w));
|
|
177
|
+
atomicStore(&published_globals[base + 12u], bitcast<u32>(m[3].x));
|
|
178
|
+
atomicStore(&published_globals[base + 13u], bitcast<u32>(m[3].y));
|
|
179
|
+
atomicStore(&published_globals[base + 14u], bitcast<u32>(m[3].z));
|
|
180
|
+
atomicStore(&published_globals[base + 15u], bitcast<u32>(m[3].w));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Reads a previously-published mat4 from \`published_globals\`. Caller
|
|
184
|
+
// must have already observed FLAG_INCLUSIVE on the parent's tile spine
|
|
185
|
+
// slot — that observation is what serializes these atomicLoads against
|
|
186
|
+
// the publishing workgroup's atomicStores.
|
|
187
|
+
fn read_published_global(pos: u32) -> mat4x4<f32> {
|
|
188
|
+
let base = pos * MAT4_STRIDE;
|
|
189
|
+
return mat4x4<f32>(
|
|
190
|
+
vec4<f32>(
|
|
191
|
+
bitcast<f32>(atomicLoad(&published_globals[base + 0u])),
|
|
192
|
+
bitcast<f32>(atomicLoad(&published_globals[base + 1u])),
|
|
193
|
+
bitcast<f32>(atomicLoad(&published_globals[base + 2u])),
|
|
194
|
+
bitcast<f32>(atomicLoad(&published_globals[base + 3u])),
|
|
195
|
+
),
|
|
196
|
+
vec4<f32>(
|
|
197
|
+
bitcast<f32>(atomicLoad(&published_globals[base + 4u])),
|
|
198
|
+
bitcast<f32>(atomicLoad(&published_globals[base + 5u])),
|
|
199
|
+
bitcast<f32>(atomicLoad(&published_globals[base + 6u])),
|
|
200
|
+
bitcast<f32>(atomicLoad(&published_globals[base + 7u])),
|
|
201
|
+
),
|
|
202
|
+
vec4<f32>(
|
|
203
|
+
bitcast<f32>(atomicLoad(&published_globals[base + 8u])),
|
|
204
|
+
bitcast<f32>(atomicLoad(&published_globals[base + 9u])),
|
|
205
|
+
bitcast<f32>(atomicLoad(&published_globals[base + 10u])),
|
|
206
|
+
bitcast<f32>(atomicLoad(&published_globals[base + 11u])),
|
|
207
|
+
),
|
|
208
|
+
vec4<f32>(
|
|
209
|
+
bitcast<f32>(atomicLoad(&published_globals[base + 12u])),
|
|
210
|
+
bitcast<f32>(atomicLoad(&published_globals[base + 13u])),
|
|
211
|
+
bitcast<f32>(atomicLoad(&published_globals[base + 14u])),
|
|
212
|
+
bitcast<f32>(atomicLoad(&published_globals[base + 15u])),
|
|
213
|
+
),
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
@compute @workgroup_size(${TRANSFORM_HIERARCHY_PARTITION_SIZE})
|
|
218
|
+
fn main(
|
|
219
|
+
@builtin(global_invocation_id) gid: vec3<u32>,
|
|
220
|
+
@builtin(local_invocation_id) lid: vec3<u32>,
|
|
221
|
+
@builtin(workgroup_id) wid: vec3<u32>,
|
|
222
|
+
) {
|
|
223
|
+
let pos = gid.x;
|
|
224
|
+
let my_tile = wid.x;
|
|
225
|
+
|
|
226
|
+
// Threads beyond input.count still need to participate in the
|
|
227
|
+
// workgroupBarrier below (uniform control flow), but they don't do
|
|
228
|
+
// any work and don't read or write \`global\`.
|
|
229
|
+
let in_range = pos < input.count;
|
|
230
|
+
|
|
231
|
+
if(in_range){
|
|
232
|
+
let node_id = input.elements[pos];
|
|
233
|
+
|
|
234
|
+
var node = scene_read_node_rw(&scene_database, node_id);
|
|
235
|
+
|
|
236
|
+
// Capture this node's current \`global\` as last frame's
|
|
237
|
+
// value, before the new compose overwrites it later in this
|
|
238
|
+
// function. The full transforms row was just loaded above —
|
|
239
|
+
// reading the field here is free, and writing prev_global
|
|
240
|
+
// ahead of the new global means downstream consumers reading
|
|
241
|
+
// both (motion-vector generation, TAA) never see a window
|
|
242
|
+
// where prev and current describe the same frame.
|
|
243
|
+
scene_write_node_prev_global(&scene_database, node_id, node.global);
|
|
244
|
+
|
|
245
|
+
// acc accumulates ancestor.local * ... * parent.local * node.local
|
|
246
|
+
// (a correct world-space transform once we hit a trusted ancestor
|
|
247
|
+
// or root). The local transform isn't stored as a matrix — we
|
|
248
|
+
// build it on the fly from the node's TRS triplet.
|
|
249
|
+
var acc = mat4_compose_transform(node.local_translation, node.local_rotation, node.local_scale);
|
|
250
|
+
var parent_id = node.parent;
|
|
251
|
+
|
|
252
|
+
// Walk up the parent chain. Each iteration either commits — by
|
|
253
|
+
// prepending a trusted parent.global onto the accumulator and
|
|
254
|
+
// breaking — or falls back: prepends parent.local and steps to
|
|
255
|
+
// the next ancestor.
|
|
256
|
+
var walk_steps = 0u;
|
|
257
|
+
loop {
|
|
258
|
+
if(parent_id == SCENE_NODE){
|
|
259
|
+
// Reached the scene root — acc IS the world transform.
|
|
260
|
+
// The scene's TRS is composed implicitly here by stopping
|
|
261
|
+
// before reading row 0; if a future scene-level pose is
|
|
262
|
+
// wanted, replace the break with a read+prepend of the
|
|
263
|
+
// scene's compose.
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
if(walk_steps >= MAX_PARENT_WALK){
|
|
267
|
+
break; // bail out on pathological depth
|
|
268
|
+
}
|
|
269
|
+
walk_steps = walk_steps + 1u;
|
|
270
|
+
|
|
271
|
+
let slot = node_to_tile[parent_id];
|
|
272
|
+
|
|
273
|
+
if(slot == NOT_IN_INPUT){
|
|
274
|
+
// Parent isn't being updated this dispatch. Whatever
|
|
275
|
+
// \`global\` is on the database is what downstream
|
|
276
|
+
// consumers will see — use it.
|
|
277
|
+
let parent = scene_read_node_rw(&scene_database, parent_id);
|
|
278
|
+
acc = parent.global * acc;
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
let parent_pos = slot - 1u; // undo the +1 encoding
|
|
283
|
+
let parent_tile = parent_pos / PARTITION_SIZE; // tile derived from position
|
|
284
|
+
|
|
285
|
+
if(parent_tile < my_tile){
|
|
286
|
+
// Parent's tile must have published before us — but it
|
|
287
|
+
// might still be in flight. Spin briefly on the spine
|
|
288
|
+
// flag; if we time out, fall back to walking via
|
|
289
|
+
// parent.local. The fallback is always correct, just
|
|
290
|
+
// potentially redundant work.
|
|
291
|
+
var spin = 0u;
|
|
292
|
+
var got_inclusive = false;
|
|
293
|
+
loop {
|
|
294
|
+
if(atomicLoad(&spine[parent_tile]) == FLAG_INCLUSIVE){
|
|
295
|
+
got_inclusive = true;
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
spin = spin + 1u;
|
|
299
|
+
if(spin >= MAX_SPIN_COUNT){
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if(got_inclusive){
|
|
305
|
+
// Spine flag observed INCLUSIVE → WGSL SeqCst's total
|
|
306
|
+
// order on atomics guarantees the publishing
|
|
307
|
+
// workgroup's atomicStores into published_globals are
|
|
308
|
+
// visible to these atomicLoads. Read via the atomic
|
|
309
|
+
// buffer, NOT scene_database.global (which is a
|
|
310
|
+
// non-atomic view and not ordered against the flag).
|
|
311
|
+
acc = read_published_global(parent_pos) * acc;
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Fallback / parent in same-or-later tile: walk via local.
|
|
317
|
+
// (The "later tile" case shouldn't hit with strict
|
|
318
|
+
// topological ordering, but if it does, walking via local
|
|
319
|
+
// is still correct.)
|
|
320
|
+
let parent = scene_read_node_rw(&scene_database, parent_id);
|
|
321
|
+
let parent_local = mat4_compose_transform(parent.local_translation, parent.local_rotation, parent.local_scale);
|
|
322
|
+
acc = parent_local * acc;
|
|
323
|
+
parent_id = parent.parent;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Atomic publish first — these 16 atomicStores into
|
|
327
|
+
// published_globals[pos] are what the spine flag's atomicStore
|
|
328
|
+
// (below) releases to other tiles via WGSL's SeqCst order on
|
|
329
|
+
// atomic operations.
|
|
330
|
+
publish_global(pos, acc);
|
|
331
|
+
|
|
332
|
+
// Mirror to the database for downstream non-atomic consumers
|
|
333
|
+
// (rendering, raymarching, etc., reading scene_database.global
|
|
334
|
+
// after this dispatch's command-buffer barrier). Only the
|
|
335
|
+
// "global" field is written: the whole-struct write that used
|
|
336
|
+
// to live here was a hazard — if "scene_read_node_rw" above
|
|
337
|
+
// ever returned zeros for any reason (buffer not yet uploaded,
|
|
338
|
+
// page-lookup race, anything), "node.local_T/R/S" would be
|
|
339
|
+
// zero and the writeback would *persist* those zeros into the
|
|
340
|
+
// row. The next frame's hierarchy reads the persisted zeros,
|
|
341
|
+
// composes a zero matrix, propagates it down — every
|
|
342
|
+
// descendant collapses to the origin and stays there. Touching
|
|
343
|
+
// only "global" means a transient stale read can't poison
|
|
344
|
+
// local_TRS.
|
|
345
|
+
scene_write_node_global(&scene_database, node_id, acc);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Publish: every thread in this workgroup has finished its
|
|
349
|
+
// atomicStores into published_globals by the barrier. Thread 0's
|
|
350
|
+
// atomicStore on the spine slot is the single release point — any
|
|
351
|
+
// other workgroup that observes FLAG_INCLUSIVE on this slot is
|
|
352
|
+
// guaranteed (under WGSL SeqCst) to see all 16 published_globals
|
|
353
|
+
// atomicStores from any thread of this workgroup.
|
|
354
|
+
workgroupBarrier();
|
|
355
|
+
if(lid.x == 0u){
|
|
356
|
+
atomicStore(&spine[my_tile], FLAG_INCLUSIVE);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
`, [
|
|
360
|
+
chunk_scene_database_access_rw,
|
|
361
|
+
chunk_mat4_compose_transform,
|
|
362
|
+
]);
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* @see {@link graph_nodes_update_transform_hierarchy} — frame-graph harness.
|
|
366
|
+
* @type {ComputeShader}
|
|
367
|
+
*/
|
|
368
|
+
export const shader_nodes_update_transform_hierarchy = ComputeShader.from({
|
|
369
|
+
label: "SceneGraph/UpdateTransformHierarchy",
|
|
370
|
+
body,
|
|
371
|
+
resources,
|
|
372
|
+
});
|