@@ -669,6 +669,8 @@ void Callback(WGPUMapAsyncStatus status, void* userData)
669669 /// </remarks>
670670 private static bool ProbeComputeDispatch ( WebGPU api , WGPUDeviceImpl * device , WGPUQueueImpl * queue )
671671 {
672+ // The chunk-reset shader's single binding is one bump-allocators block, so the storage
673+ // buffer must be exactly that size for the bind-group layout's minimum binding size.
672674 nuint statusByteCount = ( nuint ) sizeof ( GpuSceneBumpAllocators ) ;
673675
674676 WGPUBufferImpl * storageBuffer = null ;
@@ -696,6 +698,8 @@ private static bool ProbeComputeDispatch(WebGPU api, WGPUDeviceImpl* device, WGP
696698 mappedAtCreation = 0U ,
697699 } ;
698700
701+ // The shader writes the storage buffer, the copy drains it into the mappable
702+ // readback buffer, and the map proves the whole chain executed on the adapter.
699703 storageBuffer = api . DeviceCreateBuffer ( device , in storageDescriptor ) ;
700704 readbackBuffer = api . DeviceCreateBuffer ( device , in readbackDescriptor ) ;
701705 if ( storageBuffer is null || readbackBuffer is null )
@@ -756,6 +760,7 @@ private static bool ProbeComputeDispatch(WebGPU api, WGPUDeviceImpl* device, WGP
756760 }
757761 }
758762
763+ // Bind-group creation copies the entries during the call, so stack storage is safe.
759764 WGPUBindGroupEntry * bindEntries = stackalloc WGPUBindGroupEntry [ 1 ] ;
760765 bindEntries [ 0 ] = new WGPUBindGroupEntry
761766 {
@@ -792,12 +797,16 @@ private static bool ProbeComputeDispatch(WebGPU api, WGPUDeviceImpl* device, WGP
792797 return false ;
793798 }
794799
800+ // The pass must be ended and released before the encoder can record the copy;
801+ // an open pass makes every later encoder command invalid.
795802 api . ComputePassEncoderSetPipeline ( pass , pipeline ) ;
796803 api . ComputePassEncoderSetBindGroup ( pass , 0 , bindGroup , 0 , null ) ;
797804 api . ComputePassEncoderDispatchWorkgroups ( pass , ChunkResetComputeShader . GetDispatchX ( ) , 1 , 1 ) ;
798805 api . ComputePassEncoderEnd ( pass ) ;
799806 api . ComputePassEncoderRelease ( pass ) ;
800807
808+ // Queue ordering guarantees the dispatch's writes are visible to the copy inside
809+ // the same submission, so no host-side synchronization sits between them.
801810 api . CommandEncoderCopyBufferToBuffer ( commandEncoder , storageBuffer , 0 , readbackBuffer , 0 , statusByteCount ) ;
802811
803812 WGPUCommandBufferDescriptor commandBufferDescriptor = default ;
@@ -812,6 +821,7 @@ private static bool ProbeComputeDispatch(WebGPU api, WGPUDeviceImpl* device, WGP
812821 }
813822 finally
814823 {
824+ // Releases run in reverse creation order so no object outlives one it references.
815825 if ( commandBuffer is not null )
816826 {
817827 api . CommandBufferRelease ( commandBuffer ) ;
@@ -875,6 +885,9 @@ private static bool ProbeSceneRenderReadback()
875885 DrawingBackendScene ? scene = null ;
876886 try
877887 {
888+ // A fill plus a blended layer is the smallest scene that records a layer
889+ // boundary into the retained command stream, so its replay drives the full
890+ // scheduling, fine, and composition pipeline the renderer uses.
878891 using ( WebGPURenderTarget sceneTarget = new ( 16 , 16 ) )
879892 using ( DrawingCanvas sceneCanvas = sceneTarget . CreateCanvas ( ) )
880893 {
0 commit comments