Added Scene.pickAsync for non GPU blocking picking #12983
Draft
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
Scene.pick is internally using gl.readPixels that performs a synchronous GPU readback which is blocking the main render thread and very costly especially on low end GPUs. With WebGL2 a non GPU blocking method is available that uses PBO and Sync operations to asynchronously readback the pixels data without blocking.
Reference: https://registry.khronos.org/webgl/specs/latest/2.0/
Section: 3.7.10 Reading back pixels
This PR implements support for this and exposes it under a new API method Scene.pickAsync -> Promise
Asynchronous picking gives precedence to the rendering over returning the pick information. This introduces a slight delay compared to using the blocking pick method. Depending on what you prefer there might be value in having both options available in API.
Example
Demo
Browser: Microsoft Edge Version 141.0.3537.71 (Official build) (64-bit)
GPU: ANGLE (Intel, Intel(R) Arc(TM) Pro Graphics (0x00007D55) Direct3D11 vs_5_0 ps_5_0, D3D11)
edge_sync_async.mp4
Profiling results
As seen in the synchronous picking (left), readpixels can stall for longer time than it takes to render the entire frame. In this example 46% of the total execution time is taken by readpixels.
In the asynchronous example (right) the bottleneck is the actual frame rendering which makes more sense.
Issue number and link
#630
Testing plan
Author checklist
CONTRIBUTORS.md
CHANGES.md
with a short summary of my change