@woosh/meep-engine 3.12.0 → 3.13.1
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/package.json +1 -1
- package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/ConvexHullShape3D.js +41 -25
- package/src/core/geom/3d/shape/PosedShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/PosedShape3D.js +7 -2
- package/src/engine/graphics3/decal/GPUDecalRenderer.js +3 -3
- package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
- package/src/engine/graphics3/decal/shader_decal_composite.js +4 -2
- package/src/engine/graphics3/highlight/GPUHighlightRenderer.d.ts.map +1 -1
- package/src/engine/graphics3/highlight/GPUHighlightRenderer.js +2 -3
- package/src/engine/graphics3/highlight/shader_highlight_outline.js +150 -150
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/shade/RENDERER_CONTRACT.md +2 -1
- package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.d.ts +18 -0
- package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.d.ts.map +1 -1
- package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.js +73 -0
- package/src/shade/device/PASS_ENCODER_PROPOSAL_2026_08_31.md +755 -0
- package/src/shade/device/ShadeGPUCommandContext.d.ts +10 -16
- package/src/shade/device/ShadeGPUCommandContext.d.ts.map +1 -1
- package/src/shade/device/ShadeGPUCommandContext.js +801 -994
- package/src/shade/device/pass/ShadeGPUComputePassEncoder.d.ts +107 -0
- package/src/shade/device/pass/ShadeGPUComputePassEncoder.d.ts.map +1 -0
- package/src/shade/device/pass/ShadeGPUComputePassEncoder.js +222 -0
- package/src/shade/device/pass/ShadeGPURenderPassEncoder.d.ts +168 -0
- package/src/shade/device/pass/ShadeGPURenderPassEncoder.d.ts.map +1 -0
- package/src/shade/device/pass/ShadeGPURenderPassEncoder.js +317 -0
- package/src/shade/device/timing/GPUTimerArray.d.ts +4 -9
- package/src/shade/device/timing/GPUTimerArray.d.ts.map +1 -1
- package/src/shade/device/timing/GPUTimerArray.js +261 -289
- package/src/shade/device/timing/GPU_PROFILER_PROPOSAL_2026_08_28.md +20 -2
- package/src/shade/device/timing/ShadeGPUContextProfiler.d.ts +59 -0
- package/src/shade/device/timing/ShadeGPUContextProfiler.d.ts.map +1 -0
- package/src/shade/device/timing/ShadeGPUContextProfiler.js +182 -0
- package/src/shade/device/timing/profile/GPUProfileSession.d.ts +4 -4
- package/src/shade/device/timing/profile/GPUProfileSession.js +4 -4
- 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 +3 -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 +3 -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 +3 -1
- package/src/shade/playground/skinned_blas_refit/verify_leaf_triangles.js +2 -2
- package/src/shade/playground/skinned_blas_refit/verify_traversal_reachability.js +2 -2
- package/src/shade/renderer/Renderer.d.ts +0 -6
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +0 -29
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
- package/src/shade/renderer/animation/GPUAnimationManager.js +1 -3
- package/src/shade/renderer/animation/shader_animation_tick.d.ts.map +1 -1
- package/src/shade/renderer/animation/shader_animation_tick.js +128 -125
- package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +8 -18
- 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 +100 -98
- 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 +215 -212
- package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_scatter.d.ts +1 -1
- 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 +135 -120
- 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 +77 -75
- 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 +375 -371
- package/src/shade/renderer/atmosphere/shader_transmittance_lut.js +3 -3
- package/src/shade/renderer/buffer/graph_inspect_gpu_buffer.js +1 -1
- package/src/shade/renderer/buffer/table/GPUDatabase.d.ts.map +1 -1
- package/src/shade/renderer/buffer/table/GPUDatabase.js +14 -19
- package/src/shade/renderer/buffer/table/gpu_table_element_upload_shader.d.ts.map +1 -1
- package/src/shade/renderer/buffer/table/gpu_table_element_upload_shader.js +7 -2
- package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.d.ts.map +1 -1
- package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.js +325 -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 +3 -1
- package/src/shade/renderer/deferred/shader_tonemap_HDR.d.ts.map +1 -1
- package/src/shade/renderer/deferred/shader_tonemap_HDR.js +4 -1
- package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.d.ts +2 -2
- package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.d.ts.map +1 -1
- package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.js +167 -167
- package/src/shade/renderer/fow/GPUFogOfWarRenderer.js +3 -3
- package/src/shade/renderer/fow/shader_fog_of_war.d.ts.map +1 -1
- package/src/shade/renderer/fow/shader_fog_of_war.js +3 -1
- package/src/shade/renderer/geometry/bvh/record_blas_refit.js +102 -102
- 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 +125 -121
- package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts.map +1 -1
- package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.js +766 -774
- 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 +72 -69
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +5 -10
- package/src/shade/renderer/geometry/sdf/shader_build_sdf.js +129 -129
- package/src/shade/renderer/geometry/sdf/shader_sdf_visualize.d.ts.map +1 -1
- package/src/shade/renderer/geometry/sdf/shader_sdf_visualize.js +5 -3
- package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_probes.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_probes.js +4 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_resolve_probes.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_resolve_probes.js +3 -1
- package/src/shade/renderer/global_illumination/clipmap/shader_update_clipmap_cascade.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/clipmap/shader_update_clipmap_cascade.js +114 -112
- package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lpv_store_sh.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lpv_store_sh.js +4 -1
- package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lvp_atlas_to_sh.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lvp_atlas_to_sh.js +187 -184
- package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_reduce_atlas_to_sh.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_reduce_atlas_to_sh.js +4 -1
- package/src/shade/renderer/global_illumination/sharc/SpatialHashRadianceCache.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/sharc/SpatialHashRadianceCache.js +6 -8
- package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_evict.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_evict.js +3 -1
- package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_update.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_update.js +3 -1
- package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +3 -3
- package/src/shade/renderer/gpu_primitive/bvh/PHASE1_HANDOVER.md +3 -3
- 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 +145 -142
- 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 +87 -82
- 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 +143 -140
- package/src/shade/renderer/gpu_primitive/bvh/verify_gpu_bvh_build.d.ts +2 -2
- package/src/shade/renderer/gpu_primitive/bvh/verify_gpu_bvh_build.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/verify_gpu_bvh_build.js +43 -8
- package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.js +4 -5
- 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 +88 -84
- 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 +194 -191
- package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
- package/src/shade/renderer/hiz/HierarchicalZBuffer.js +33 -69
- package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts.map +1 -1
- package/src/shade/renderer/hiz/shader_hzb_reduce_any.js +6 -1
- package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts.map +1 -1
- package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.js +23 -7
- package/src/shade/renderer/light/environment/execute_filter_environment_map.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/execute_filter_environment_map.js +1 -2
- package/src/shade/renderer/light/environment/shader_convolve_reflection_map.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/shader_convolve_reflection_map.js +6 -1
- package/src/shade/renderer/lightmap/bake/raster/graph_draw_lightmap_viz_buffer.d.ts.map +1 -1
- package/src/shade/renderer/lightmap/bake/raster/graph_draw_lightmap_viz_buffer.js +234 -219
- package/src/shade/renderer/lightmap/bake/raster/shader_lightmap_to_viz_buffer.js +2 -2
- package/src/shade/renderer/lightmap/bake/shader_lightmap_denoise_sh.js +191 -191
- package/src/shade/renderer/lightmap/bake/tile/shader_lightmap_accummulate_tile.d.ts.map +1 -1
- package/src/shade/renderer/lightmap/bake/tile/shader_lightmap_accummulate_tile.js +85 -82
- package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph_particles.js +5 -3
- package/src/shade/renderer/particles/prototypeParticleSystem.js +3 -4
- package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_emit.js +132 -117
- package/src/shade/renderer/particles/shaders/shader_particle_finalize.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_finalize.js +79 -77
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +111 -99
- package/src/shade/renderer/particles/sort/shader_particle_sort.d.ts.map +1 -1
- package/src/shade/renderer/particles/sort/shader_particle_sort.js +187 -158
- package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.d.ts.map +1 -1
- package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.js +7 -10
- package/src/shade/renderer/path_tracer/accumulating/shader_accumulating_path_tracer.d.ts.map +1 -1
- package/src/shade/renderer/path_tracer/accumulating/shader_accumulating_path_tracer.js +4 -1
- package/src/shade/renderer/postprocess/bloom/shader_bloom_mix.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/bloom/shader_bloom_mix.js +3 -1
- package/src/shade/renderer/postprocess/cas/shader_ffx_rcas.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/cas/shader_ffx_rcas.js +4 -2
- package/src/shade/renderer/postprocess/denoise/fragment_shader_denoise_ao.js +147 -147
- package/src/shade/renderer/postprocess/denoise/graph_atorus_denoise_luma.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/denoise/graph_atorus_denoise_luma.js +121 -119
- package/src/shade/renderer/postprocess/dof/gather/graph_postprocess_dof2.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/gather/graph_postprocess_dof2.js +1 -2
- package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_far.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_far.js +4 -1
- package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_near.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_near.js +4 -1
- package/src/shade/renderer/postprocess/dof/gather/shader_dof2_recombine.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/gather/shader_dof2_recombine.js +4 -1
- package/src/shade/renderer/postprocess/dof/gather/shader_dof2_setup.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/gather/shader_dof2_setup.js +4 -1
- package/src/shade/renderer/postprocess/dof/raymarch/graph_postprocess_dof.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/raymarch/graph_postprocess_dof.js +2 -4
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_composite.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_composite.js +4 -1
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_prefilter.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_prefilter.js +4 -1
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch.js +4 -1
- 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 +269 -266
- 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 +273 -270
- package/src/shade/renderer/postprocess/dof/shader_dof_autofocus.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/shader_dof_autofocus.js +4 -1
- package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.js +8 -11
- package/src/shade/renderer/postprocess/eye/shader_autoexposure_adapt.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/eye/shader_autoexposure_adapt.js +5 -1
- package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.js +11 -8
- package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.js +7 -8
- package/src/shade/renderer/postprocess/motion_blur/shader_motion_blur_reconstruct.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/motion_blur/shader_motion_blur_reconstruct.js +3 -1
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/postprocess/nss/shader_nss_concat.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/nss/shader_nss_concat.js +70 -68
- package/src/shade/renderer/postprocess/ssr/depth_max_shader.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/depth_max_shader.js +70 -68
- package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_IBL.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_IBL.js +3 -1
- package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_LPV.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_LPV.js +4 -1
- package/src/shade/renderer/postprocess/ssr/shader_downsample_encoded_normal.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/shader_downsample_encoded_normal.js +103 -101
- package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.js +4 -2
- package/src/shade/renderer/postprocess/ssr/ssr_trace_shader.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/ssr_trace_shader.js +3 -1
- package/src/shade/renderer/postprocess/taa/shader_taa.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/taa/shader_taa.js +4 -1
- package/src/shade/renderer/postprocess/upscale-dither/fragment_shader_upscale_dither.js +5 -5
- 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 +339 -341
- 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 +114 -109
- 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 +118 -115
- 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 +69 -65
- package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.js +722 -722
- package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +1 -9
- package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +1 -6
- package/src/shade/renderer/restir/di/graph_restir_di.d.ts.map +1 -1
- package/src/shade/renderer/restir/di/graph_restir_di.js +2 -3
- package/src/shade/renderer/restir/di/graph_restir_di_denoise.d.ts.map +1 -1
- package/src/shade/renderer/restir/di/graph_restir_di_denoise.js +1 -2
- 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 +139 -136
- 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 +131 -129
- 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 +101 -99
- package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.d.ts.map +1 -1
- package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.js +379 -383
- package/src/shade/renderer/scene/Mesh.d.ts.map +1 -1
- package/src/shade/renderer/scene/Mesh.js +4 -6
- 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 +147 -144
- package/src/shade/renderer/shader/ComputeShader.d.ts +2 -2
- package/src/shade/renderer/shader/ComputeShader.d.ts.map +1 -1
- package/src/shade/renderer/shader/ComputeShader.js +14 -17
- package/src/shade/renderer/shader/pass/RenderPassDescriptor.d.ts +2 -2
- package/src/shade/renderer/shader/pass/RenderPassDescriptor.d.ts.map +1 -1
- package/src/shade/renderer/shader/pass/RenderPassDescriptor.js +189 -189
- package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts.map +1 -1
- package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.js +3 -1
- package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts +16 -7
- package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +1342 -1326
- package/src/shade/renderer/shadow/map/Shadowmap.d.ts +13 -0
- package/src/shade/renderer/shadow/map/Shadowmap.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/Shadowmap.js +14 -0
- package/src/shade/renderer/shadow/map/ShadowmapDrawSelector.d.ts +79 -0
- package/src/shade/renderer/shadow/map/ShadowmapDrawSelector.d.ts.map +1 -0
- package/src/shade/renderer/shadow/map/ShadowmapDrawSelector.js +196 -0
- package/src/shade/renderer/shadow/map/ShadowmapRegistry.d.ts +91 -0
- package/src/shade/renderer/shadow/map/ShadowmapRegistry.d.ts.map +1 -0
- package/src/shade/renderer/shadow/map/ShadowmapRegistry.js +156 -0
- package/src/shade/renderer/shadow/map/shader/shader_shadowmap_remap_cube_to_octahedral.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/shader/shader_shadowmap_remap_cube_to_octahedral.js +5 -1
- package/src/shade/renderer/shadow/ray/shader_shadow_upscale.d.ts.map +1 -1
- package/src/shade/renderer/shadow/ray/shader_shadow_upscale.js +3 -1
- package/src/shade/renderer/shadow/ray/staged/gen/graph_gen_rays.js +73 -73
- package/src/shade/renderer/shadow/ray/staged/gen/shader_generate_rays.d.ts.map +1 -1
- package/src/shade/renderer/shadow/ray/staged/gen/shader_generate_rays.js +151 -148
- package/src/shade/renderer/shadow/ray/staged/trace/graph_trace_rays.d.ts.map +1 -1
- package/src/shade/renderer/shadow/ray/staged/trace/graph_trace_rays.js +4 -2
- package/src/shade/renderer/shadow/ray/staged/trace/shader_trace_rays.d.ts.map +1 -1
- package/src/shade/renderer/shadow/ray/staged/trace/shader_trace_rays.js +18 -4
- package/src/shade/renderer/shadow/sdf/cascade/CascadedSceneSDF.d.ts.map +1 -1
- package/src/shade/renderer/shadow/sdf/cascade/CascadedSceneSDF.js +7 -8
- package/src/shade/renderer/shadow/sdf/cascade/shader_build_scene_sdf_f32.d.ts.map +1 -1
- package/src/shade/renderer/shadow/sdf/cascade/shader_build_scene_sdf_f32.js +6 -2
- package/src/shade/renderer/shadow/sdf/cascade/shader_scene_sdf_debug_viz.d.ts.map +1 -1
- package/src/shade/renderer/shadow/sdf/cascade/shader_scene_sdf_debug_viz.js +129 -127
- package/src/shade/renderer/shadow/sdf/graph_draw_sdf_shadows.d.ts.map +1 -1
- package/src/shade/renderer/shadow/sdf/graph_draw_sdf_shadows.js +5 -3
- package/src/shade/renderer/texture/virtual/VirtualTextureManager.d.ts.map +1 -1
- package/src/shade/renderer/texture/virtual/VirtualTextureManager.js +2 -5
- 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 +233 -231
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +2 -4
- package/src/shade/wgsl/validate_wgsl_source.d.ts.map +1 -1
- package/src/shade/wgsl/validate_wgsl_source.js +8 -3
- package/src/shade/device/timing/profile/make_profiling_pass_encoder.d.ts +0 -21
- package/src/shade/device/timing/profile/make_profiling_pass_encoder.d.ts.map +0 -1
- package/src/shade/device/timing/profile/make_profiling_pass_encoder.js +0 -114
- package/src/shade/device/timing/profile/parse_workgroup_size.d.ts +0 -20
- package/src/shade/device/timing/profile/parse_workgroup_size.d.ts.map +0 -1
- package/src/shade/device/timing/profile/parse_workgroup_size.js +0 -43
|
@@ -1,290 +1,262 @@
|
|
|
1
|
-
import { assert } from "../../../core/assert.js";
|
|
2
|
-
import IdPool from "../../../core/IdPool.js";
|
|
3
|
-
|
|
4
|
-
export class GPUTimerArray {
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @type {GPUDevice}
|
|
8
|
-
*/
|
|
9
|
-
#device;
|
|
10
|
-
|
|
11
|
-
#size = 0;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* @type {GPUQuerySet}
|
|
15
|
-
*/
|
|
16
|
-
#query_set;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @type {GPUBuffer}
|
|
20
|
-
*/
|
|
21
|
-
#resolve_buffer;
|
|
22
|
-
/**
|
|
23
|
-
* @type {GPUBuffer}
|
|
24
|
-
*/
|
|
25
|
-
#results_buffer;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* @type {BigInt64Array}
|
|
29
|
-
*/
|
|
30
|
-
#results
|
|
31
|
-
|
|
32
|
-
#slots = new IdPool();
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
*
|
|
36
|
-
* @type {{type: string, label: string}[]}
|
|
37
|
-
*/
|
|
38
|
-
#slot_metadata = [];
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Passes that asked for a slot after the array ran out.
|
|
42
|
-
*
|
|
43
|
-
* Reported rather than swallowed. A profile capture instruments far more passes than a one-off
|
|
44
|
-
* debug frame does, and a silent shortfall reads downstream as "those passes were free".
|
|
45
|
-
*
|
|
46
|
-
* @type {number}
|
|
47
|
-
*/
|
|
48
|
-
#dropped_count = 0;
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* How many passes went untimed because {@link size} was too small for the frame.
|
|
52
|
-
*
|
|
53
|
-
* @returns {number}
|
|
54
|
-
*/
|
|
55
|
-
get dropped_count() {
|
|
56
|
-
return this.#dropped_count;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Claim a slot, or report that there is none.
|
|
61
|
-
*
|
|
62
|
-
* The bound check is the point. `IdPool` hands out ids indefinitely, and an id at or past
|
|
63
|
-
* {@link size} addresses a query index the query set does not have — which WebGPU rejects at
|
|
64
|
-
* the `beginRenderPass` that used it, blaming a pass that did nothing wrong and saying nothing
|
|
65
|
-
* about the one that exhausted the array.
|
|
66
|
-
*
|
|
67
|
-
* @param {string} label
|
|
68
|
-
* @param {string} type
|
|
69
|
-
* @return {number} slot id, or -1 when the array is full
|
|
70
|
-
*/
|
|
71
|
-
#bind_slot(label, type) {
|
|
72
|
-
|
|
73
|
-
if (this.#slots.peek() >= this.#size) {
|
|
74
|
-
this.#dropped_count++;
|
|
75
|
-
|
|
76
|
-
return -1;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const id = this.#slots.get();
|
|
80
|
-
|
|
81
|
-
this.#slot_metadata[id] = {
|
|
82
|
-
label,
|
|
83
|
-
type
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
return id;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* @param {string} label
|
|
91
|
-
* @param {string} type one of 'compute', 'render'
|
|
92
|
-
* @returns {GPUComputePassTimestampWrites|GPURenderPassTimestampWrites|undefined} undefined when
|
|
93
|
-
* there is no slot left, in which case the caller must leave `timestampWrites` off its
|
|
94
|
-
* descriptor — an untimed pass is the correct degradation, an invalid one is not
|
|
95
|
-
*/
|
|
96
|
-
#get_writes(label, type) {
|
|
97
|
-
|
|
98
|
-
const querySet = this.#query_set;
|
|
99
|
-
|
|
100
|
-
if (querySet === undefined) {
|
|
101
|
-
// same guard as `resolve` and `download_results`: with the feature withheld the timers
|
|
102
|
-
// go quiet rather than taking the frame down
|
|
103
|
-
return undefined;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const id = this.#bind_slot(label, type);
|
|
107
|
-
|
|
108
|
-
if (id === -1) {
|
|
109
|
-
return undefined;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const index0 = id * 2;
|
|
113
|
-
|
|
114
|
-
return {
|
|
115
|
-
querySet,
|
|
116
|
-
beginningOfPassWriteIndex: index0,
|
|
117
|
-
endOfPassWriteIndex: index0 + 1,
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
*
|
|
123
|
-
* @param {string} label
|
|
124
|
-
* @returns {GPUComputePassTimestampWrites|undefined} undefined when the array is full
|
|
125
|
-
*/
|
|
126
|
-
getComputeWrites(label) {
|
|
127
|
-
return this.#get_writes(label, 'compute');
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
*
|
|
132
|
-
* @param {string} label
|
|
133
|
-
* @returns {GPURenderPassTimestampWrites|undefined} undefined when the array is full
|
|
134
|
-
*/
|
|
135
|
-
getRenderWrites(label) {
|
|
136
|
-
return this.#get_writes(label, 'render');
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Visit every slot that was claimed this frame, in slot order, with its raw timestamps.
|
|
141
|
-
*
|
|
142
|
-
* Raw: nanoseconds as the device reported them, `BigInt`, unscaled.
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
* @param {(slot_id: number, label: string, type: string, t_begin: bigint, t_end: bigint) => void} visitor
|
|
148
|
-
* @returns {void}
|
|
149
|
-
*/
|
|
150
|
-
traverse_results(visitor) {
|
|
151
|
-
assert.isFunction(visitor, 'visitor');
|
|
152
|
-
|
|
153
|
-
const results = this.#results;
|
|
154
|
-
|
|
155
|
-
if (results === undefined) {
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
this.#slots.traverseUsed(slot_id => {
|
|
160
|
-
const meta = this.#slot_metadata[slot_id];
|
|
161
|
-
|
|
162
|
-
visitor(
|
|
163
|
-
slot_id,
|
|
164
|
-
meta.label,
|
|
165
|
-
meta.type,
|
|
166
|
-
results[slot_id * 2],
|
|
167
|
-
results[slot_id * 2 + 1]
|
|
168
|
-
);
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
*
|
|
174
|
-
* @param {GPUDevice} device
|
|
175
|
-
* @param {number} [size] number of query slots
|
|
176
|
-
*/
|
|
177
|
-
constructor(
|
|
178
|
-
device,
|
|
179
|
-
size = 1024
|
|
180
|
-
) {
|
|
181
|
-
assert.defined(device, 'device');
|
|
182
|
-
assert.isNonNegativeInteger(size, 'size');
|
|
183
|
-
|
|
184
|
-
this.#device = device;
|
|
185
|
-
|
|
186
|
-
this.#size = size;
|
|
187
|
-
|
|
188
|
-
// see GPUTimer: a withheld profiling feature makes the timers quiet, not fatal
|
|
189
|
-
if (!device.features.has('timestamp-query')) {
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
this.#query_set = device.createQuerySet({
|
|
194
|
-
type: 'timestamp',
|
|
195
|
-
count: size * 2
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
this.#resolve_buffer = device.createBuffer({
|
|
199
|
-
label: 'GPUTimerArray',
|
|
200
|
-
size: this.#size * 2 * 8, // start + end, 64bit uint
|
|
201
|
-
usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.COPY_SRC
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
this.#results_buffer = this.#device.createBuffer({
|
|
205
|
-
label: 'GPUTimerArray/results',
|
|
206
|
-
size: this.#size * 2 * 8,
|
|
207
|
-
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
this.#results = new BigInt64Array(size * 2);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
destroy() {
|
|
214
|
-
if (this.#query_set === undefined) {
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
this.#query_set.destroy();
|
|
219
|
-
this.#resolve_buffer.destroy();
|
|
220
|
-
this.#results_buffer.destroy();
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
*
|
|
225
|
-
* @param {GPUCommandEncoder} encoder
|
|
226
|
-
*/
|
|
227
|
-
resolve(encoder) {
|
|
228
|
-
|
|
229
|
-
if (this.#query_set === undefined) {
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
encoder.resolveQuerySet(this.#query_set, 0, this.#query_set.count, this.#resolve_buffer, 0);
|
|
234
|
-
encoder.copyBufferToBuffer(this.#resolve_buffer, 0, this.#results_buffer, 0);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
async download_results() {
|
|
238
|
-
|
|
239
|
-
const results_buffer = this.#results_buffer;
|
|
240
|
-
|
|
241
|
-
if (results_buffer === undefined) {
|
|
242
|
-
// Same guard as `resolve` and `destroy`: with the profiling feature withheld there is no
|
|
243
|
-
// query set and no buffers, and the timers are supposed to go quiet rather than take the
|
|
244
|
-
// frame down with them. Without it,
|
|
245
|
-
//
|
|
246
|
-
//
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* prepare tabular formatting for console output
|
|
265
|
-
* @returns {Object}
|
|
266
|
-
*/
|
|
267
|
-
results_to_console_table() {
|
|
268
|
-
const result = [];
|
|
269
|
-
|
|
270
|
-
this.#slots.traverseUsed(slot_id => {
|
|
271
|
-
const meta = this.#slot_metadata[slot_id];
|
|
272
|
-
const t_start = this.#results[slot_id * 2];
|
|
273
|
-
const t_end = this.#results[slot_id * 2 + 1];
|
|
274
|
-
|
|
275
|
-
const duration_ns = Number(t_end - t_start);
|
|
276
|
-
const duration_ms = duration_ns * 1e-6;
|
|
277
|
-
|
|
278
|
-
result.push({
|
|
279
|
-
label: meta.label,
|
|
280
|
-
type: meta.type,
|
|
281
|
-
duration_ms: duration_ms,
|
|
282
|
-
start: t_start,
|
|
283
|
-
end: t_end,
|
|
284
|
-
});
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
return result;
|
|
288
|
-
}
|
|
289
|
-
|
|
1
|
+
import { assert } from "../../../core/assert.js";
|
|
2
|
+
import IdPool from "../../../core/IdPool.js";
|
|
3
|
+
|
|
4
|
+
export class GPUTimerArray {
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @type {GPUDevice}
|
|
8
|
+
*/
|
|
9
|
+
#device;
|
|
10
|
+
|
|
11
|
+
#size = 0;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @type {GPUQuerySet}
|
|
15
|
+
*/
|
|
16
|
+
#query_set;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @type {GPUBuffer}
|
|
20
|
+
*/
|
|
21
|
+
#resolve_buffer;
|
|
22
|
+
/**
|
|
23
|
+
* @type {GPUBuffer}
|
|
24
|
+
*/
|
|
25
|
+
#results_buffer;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @type {BigInt64Array}
|
|
29
|
+
*/
|
|
30
|
+
#results
|
|
31
|
+
|
|
32
|
+
#slots = new IdPool();
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
*
|
|
36
|
+
* @type {{type: string, label: string}[]}
|
|
37
|
+
*/
|
|
38
|
+
#slot_metadata = [];
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Passes that asked for a slot after the array ran out.
|
|
42
|
+
*
|
|
43
|
+
* Reported rather than swallowed. A profile capture instruments far more passes than a one-off
|
|
44
|
+
* debug frame does, and a silent shortfall reads downstream as "those passes were free".
|
|
45
|
+
*
|
|
46
|
+
* @type {number}
|
|
47
|
+
*/
|
|
48
|
+
#dropped_count = 0;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* How many passes went untimed because {@link size} was too small for the frame.
|
|
52
|
+
*
|
|
53
|
+
* @returns {number}
|
|
54
|
+
*/
|
|
55
|
+
get dropped_count() {
|
|
56
|
+
return this.#dropped_count;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Claim a slot, or report that there is none.
|
|
61
|
+
*
|
|
62
|
+
* The bound check is the point. `IdPool` hands out ids indefinitely, and an id at or past
|
|
63
|
+
* {@link size} addresses a query index the query set does not have — which WebGPU rejects at
|
|
64
|
+
* the `beginRenderPass` that used it, blaming a pass that did nothing wrong and saying nothing
|
|
65
|
+
* about the one that exhausted the array.
|
|
66
|
+
*
|
|
67
|
+
* @param {string} label
|
|
68
|
+
* @param {string} type
|
|
69
|
+
* @return {number} slot id, or -1 when the array is full
|
|
70
|
+
*/
|
|
71
|
+
#bind_slot(label, type) {
|
|
72
|
+
|
|
73
|
+
if (this.#slots.peek() >= this.#size) {
|
|
74
|
+
this.#dropped_count++;
|
|
75
|
+
|
|
76
|
+
return -1;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const id = this.#slots.get();
|
|
80
|
+
|
|
81
|
+
this.#slot_metadata[id] = {
|
|
82
|
+
label,
|
|
83
|
+
type
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
return id;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @param {string} label
|
|
91
|
+
* @param {string} type one of 'compute', 'render'
|
|
92
|
+
* @returns {GPUComputePassTimestampWrites|GPURenderPassTimestampWrites|undefined} undefined when
|
|
93
|
+
* there is no slot left, in which case the caller must leave `timestampWrites` off its
|
|
94
|
+
* descriptor — an untimed pass is the correct degradation, an invalid one is not
|
|
95
|
+
*/
|
|
96
|
+
#get_writes(label, type) {
|
|
97
|
+
|
|
98
|
+
const querySet = this.#query_set;
|
|
99
|
+
|
|
100
|
+
if (querySet === undefined) {
|
|
101
|
+
// same guard as `resolve` and `download_results`: with the feature withheld the timers
|
|
102
|
+
// go quiet rather than taking the frame down
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const id = this.#bind_slot(label, type);
|
|
107
|
+
|
|
108
|
+
if (id === -1) {
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const index0 = id * 2;
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
querySet,
|
|
116
|
+
beginningOfPassWriteIndex: index0,
|
|
117
|
+
endOfPassWriteIndex: index0 + 1,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
*
|
|
123
|
+
* @param {string} label
|
|
124
|
+
* @returns {GPUComputePassTimestampWrites|undefined} undefined when the array is full
|
|
125
|
+
*/
|
|
126
|
+
getComputeWrites(label) {
|
|
127
|
+
return this.#get_writes(label, 'compute');
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
*
|
|
132
|
+
* @param {string} label
|
|
133
|
+
* @returns {GPURenderPassTimestampWrites|undefined} undefined when the array is full
|
|
134
|
+
*/
|
|
135
|
+
getRenderWrites(label) {
|
|
136
|
+
return this.#get_writes(label, 'render');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Visit every slot that was claimed this frame, in slot order, with its raw timestamps.
|
|
141
|
+
*
|
|
142
|
+
* Raw: nanoseconds as the device reported them, `BigInt`, unscaled. Rounding belongs to
|
|
143
|
+
* whoever is displaying them; a recording needs the values themselves, and the difference
|
|
144
|
+
* matters once quantization is in play — see the profiler's treatment of
|
|
145
|
+
* `timestamp_period_ns`.
|
|
146
|
+
*
|
|
147
|
+
* @param {(slot_id: number, label: string, type: string, t_begin: bigint, t_end: bigint) => void} visitor
|
|
148
|
+
* @returns {void}
|
|
149
|
+
*/
|
|
150
|
+
traverse_results(visitor) {
|
|
151
|
+
assert.isFunction(visitor, 'visitor');
|
|
152
|
+
|
|
153
|
+
const results = this.#results;
|
|
154
|
+
|
|
155
|
+
if (results === undefined) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
this.#slots.traverseUsed(slot_id => {
|
|
160
|
+
const meta = this.#slot_metadata[slot_id];
|
|
161
|
+
|
|
162
|
+
visitor(
|
|
163
|
+
slot_id,
|
|
164
|
+
meta.label,
|
|
165
|
+
meta.type,
|
|
166
|
+
results[slot_id * 2],
|
|
167
|
+
results[slot_id * 2 + 1]
|
|
168
|
+
);
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
*
|
|
174
|
+
* @param {GPUDevice} device
|
|
175
|
+
* @param {number} [size] number of query slots
|
|
176
|
+
*/
|
|
177
|
+
constructor(
|
|
178
|
+
device,
|
|
179
|
+
size = 1024
|
|
180
|
+
) {
|
|
181
|
+
assert.defined(device, 'device');
|
|
182
|
+
assert.isNonNegativeInteger(size, 'size');
|
|
183
|
+
|
|
184
|
+
this.#device = device;
|
|
185
|
+
|
|
186
|
+
this.#size = size;
|
|
187
|
+
|
|
188
|
+
// see GPUTimer: a withheld profiling feature makes the timers quiet, not fatal
|
|
189
|
+
if (!device.features.has('timestamp-query')) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
this.#query_set = device.createQuerySet({
|
|
194
|
+
type: 'timestamp',
|
|
195
|
+
count: size * 2
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
this.#resolve_buffer = device.createBuffer({
|
|
199
|
+
label: 'GPUTimerArray',
|
|
200
|
+
size: this.#size * 2 * 8, // start + end, 64bit uint
|
|
201
|
+
usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.COPY_SRC
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
this.#results_buffer = this.#device.createBuffer({
|
|
205
|
+
label: 'GPUTimerArray/results',
|
|
206
|
+
size: this.#size * 2 * 8,
|
|
207
|
+
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
this.#results = new BigInt64Array(size * 2);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
destroy() {
|
|
214
|
+
if (this.#query_set === undefined) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
this.#query_set.destroy();
|
|
219
|
+
this.#resolve_buffer.destroy();
|
|
220
|
+
this.#results_buffer.destroy();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
*
|
|
225
|
+
* @param {GPUCommandEncoder} encoder
|
|
226
|
+
*/
|
|
227
|
+
resolve(encoder) {
|
|
228
|
+
|
|
229
|
+
if (this.#query_set === undefined) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
encoder.resolveQuerySet(this.#query_set, 0, this.#query_set.count, this.#resolve_buffer, 0);
|
|
234
|
+
encoder.copyBufferToBuffer(this.#resolve_buffer, 0, this.#results_buffer, 0);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
async download_results() {
|
|
238
|
+
|
|
239
|
+
const results_buffer = this.#results_buffer;
|
|
240
|
+
|
|
241
|
+
if (results_buffer === undefined) {
|
|
242
|
+
// Same guard as `resolve` and `destroy`: with the profiling feature withheld there is no
|
|
243
|
+
// query set and no buffers, and the timers are supposed to go quiet rather than take the
|
|
244
|
+
// frame down with them. Without it, profiling on such a device raises an unhandled
|
|
245
|
+
// rejection out of `ShadeGPUContextProfiler.absorb`, which calls this unconditionally.
|
|
246
|
+
// `traverse_results` then visits nothing, which is what "quiet" means.
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
await results_buffer.mapAsync(GPUMapMode.READ)
|
|
251
|
+
|
|
252
|
+
const mapped = results_buffer.getMappedRange(
|
|
253
|
+
0, results_buffer.size,
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
this.#results.set(new BigInt64Array(mapped));
|
|
257
|
+
|
|
258
|
+
results_buffer.unmap();
|
|
259
|
+
|
|
260
|
+
}
|
|
261
|
+
|
|
290
262
|
}
|
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
Proposal, 2026-08-28. Decisions folded in 2026-08-29. Alex Goldring / Company Named Limited.
|
|
4
4
|
|
|
5
|
+
> **Partly superseded, 2026-08-31**, by
|
|
6
|
+
> [PASS_ENCODER_PROPOSAL_2026_08_31.md](../PASS_ENCODER_PROPOSAL_2026_08_31.md). The recording
|
|
7
|
+
> proxy of §6.2 hook 3 and M4 is now a pair of decorator classes; `enable_debug_timers`,
|
|
8
|
+
> `Renderer.add_debug_frame` and `Renderer.onFrameDebug` — which §6.1 kept — are gone, leaving the
|
|
9
|
+
> profiler as the only path. §§1–5 remain a record of the state this design was written against.
|
|
10
|
+
|
|
5
11
|
Scope: a **recording** side that ships with the engine, a **binary container** that carries a
|
|
6
12
|
capture, and an **inspector** web application under `packages/gpu-inspector-tool/` that reads the
|
|
7
13
|
container and nothing else.
|
|
@@ -628,8 +634,13 @@ Three things fall out of the caller owning it, and all three are why this is the
|
|
|
628
634
|
`frame_limit` reaching zero stops the session exactly as `stop()` does. Both resolve the same
|
|
629
635
|
promise, so a caller that wants "500 frames or until I say" writes one `await`.
|
|
630
636
|
|
|
631
|
-
|
|
632
|
-
and a different tool for a different question
|
|
637
|
+
~~`add_debug_frame` and `onFrameDebug` stay exactly as they are — cheap, synchronous, console-shaped,
|
|
638
|
+
and a different tool for a different question.~~
|
|
639
|
+
|
|
640
|
+
> **Reversed 2026-08-31.** They were not a different tool, they were a worse view of the same one
|
|
641
|
+
> reached through a second API — no graph-pass attribution, no workload, no pipeline identity — and
|
|
642
|
+
> `onFrameDebug` never acquired a subscriber. Removed; the profiler is the only path. "Profile the
|
|
643
|
+
> next N frames" is `new GPUProfileSession({ frame_limit: N })`.
|
|
633
644
|
|
|
634
645
|
### 6.2 The five hooks
|
|
635
646
|
|
|
@@ -809,6 +820,13 @@ renderer only while profiling. Dispatch and draw counts, pipeline identity, and
|
|
|
809
820
|
parsed from WGSL where it is a literal — an override expression records as *unknown*, which is not
|
|
810
821
|
the same as zero.
|
|
811
822
|
|
|
823
|
+
> **Reversed 2026-08-31.** The argument holds only while the wrapper is *conditional*; that is what
|
|
824
|
+
> makes a missing method silent. `ShadeGPUComputePassEncoder` / `ShadeGPURenderPassEncoder` wrap
|
|
825
|
+
> every pass, so a gap throws on the first frame of every build. The workgroup size now comes off
|
|
826
|
+
> `ComputePipelineDescriptor`, which reads it as its code is set, with the parser that resolves
|
|
827
|
+
> `const` references — a size it cannot read refuses to build the descriptor rather than recording
|
|
828
|
+
> as unknown.
|
|
829
|
+
|
|
812
830
|
No `PIPE` table in the end: a pass's pipeline label and workgroup size ride in its own workload
|
|
813
831
|
block, which costs a symbol reference and avoids a second id space.
|
|
814
832
|
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Everything one {@link ShadeGPUCommandContext} needs in order to be profiled: its timer array, the
|
|
3
|
+
* recorder its timings go to, and which query set it is within the frame.
|
|
4
|
+
*
|
|
5
|
+
* **It opens the passes itself.** Two values are needed at two different instants — the
|
|
6
|
+
* `timestampWrites` before the encoder exists, the {@link GPUProfileWork} after — and any shape that
|
|
7
|
+
* hands both back to the caller has to carry them across that gap. The predecessor carried them in a
|
|
8
|
+
* private field on the command context, consumed by whatever ran next, which is the kind of coupling
|
|
9
|
+
* that breaks the moment a line is inserted between the two halves. Handing the profiler the encoder
|
|
10
|
+
* collapses the gap: both values are produced and consumed inside one method and there is nothing to
|
|
11
|
+
* carry.
|
|
12
|
+
*
|
|
13
|
+
* Off by default and constructed only by `enable_profiling`, so a context that is not being profiled
|
|
14
|
+
* holds one null field and allocates no query set.
|
|
15
|
+
*
|
|
16
|
+
* @author Alex Goldring
|
|
17
|
+
* @copyright Company Named Limited (c) 2026
|
|
18
|
+
*/
|
|
19
|
+
export class ShadeGPUContextProfiler {
|
|
20
|
+
/**
|
|
21
|
+
* @param {GPUDevice} device
|
|
22
|
+
* @param {GPUFrameRecorder} recorder
|
|
23
|
+
* @param {number} query_set_id this context's index within the frame
|
|
24
|
+
*/
|
|
25
|
+
constructor(device: GPUDevice, recorder: GPUFrameRecorder, query_set_id: number);
|
|
26
|
+
/**
|
|
27
|
+
* Resolves after this context's timings have been read back and handed to the recorder.
|
|
28
|
+
*
|
|
29
|
+
* @returns {Promise<void>}
|
|
30
|
+
*/
|
|
31
|
+
get absorbed(): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* @param {GPUCommandEncoder} encoder
|
|
34
|
+
* @param {GPUComputePassDescriptor} [descriptor]
|
|
35
|
+
* @returns {ShadeGPUComputePassEncoder}
|
|
36
|
+
*/
|
|
37
|
+
begin_compute_pass(encoder: GPUCommandEncoder, descriptor?: GPUComputePassDescriptor): ShadeGPUComputePassEncoder;
|
|
38
|
+
/**
|
|
39
|
+
* @param {GPUCommandEncoder} encoder
|
|
40
|
+
* @param {GPURenderPassDescriptor} descriptor
|
|
41
|
+
* @returns {ShadeGPURenderPassEncoder}
|
|
42
|
+
*/
|
|
43
|
+
begin_render_pass(encoder: GPUCommandEncoder, descriptor: GPURenderPassDescriptor): ShadeGPURenderPassEncoder;
|
|
44
|
+
/**
|
|
45
|
+
* @param {GPUCommandEncoder} encoder
|
|
46
|
+
* @returns {void}
|
|
47
|
+
*/
|
|
48
|
+
resolve(encoder: GPUCommandEncoder): void;
|
|
49
|
+
/**
|
|
50
|
+
* Read the timings back and hand them to the recorder. Resolves {@link absorbed} either way.
|
|
51
|
+
*
|
|
52
|
+
* @returns {void}
|
|
53
|
+
*/
|
|
54
|
+
absorb(): void;
|
|
55
|
+
#private;
|
|
56
|
+
}
|
|
57
|
+
import { ShadeGPUComputePassEncoder } from "../pass/ShadeGPUComputePassEncoder.js";
|
|
58
|
+
import { ShadeGPURenderPassEncoder } from "../pass/ShadeGPURenderPassEncoder.js";
|
|
59
|
+
//# sourceMappingURL=ShadeGPUContextProfiler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ShadeGPUContextProfiler.d.ts","sourceRoot":"","sources":["../../../../../src/shade/device/timing/ShadeGPUContextProfiler.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;GAiBG;AACH;IA+BI;;;;OAIG;IACH,yEAFW,MAAM,EAchB;IAED;;;;OAIG;IACH,8BAEC;IAED;;;;OAIG;IACH,uFAFa,0BAA0B,CAYtC;IAED;;;;OAIG;IACH,oFAFa,yBAAyB,CAYrC;IAmCD;;;OAGG;IACH,qCAFa,IAAI,CAIhB;IAED;;;;OAIG;IACH,UAFa,IAAI,CAoBhB;;CACJ;2CApL0C,uCAAuC;0CACxC,sCAAsC"}
|