<p dir="auto">While working on the <code class="notranslate">EXRExporter</code> implementation, I realized that we do not have an option for async readbacks using <code class="notranslate">gl.readPixels</code>. This option becomes available on WebGL2 contexts with specialized fencing for determining when data is ready to be read, and a new buffer type of <code class="notranslate">PIXEL_PACK_BUFFER</code>.</p>
<p dir="auto">I can't overstate how important this feature is. It's used in plenty of real user applications, from gpu-picking, render processing, general purpose GPU computing, so on and so forth. The main setback for most of these is how WebGL1 readPixels blocking nature completely kills performance and use in real-time applications.</p>
<p dir="auto"><a href="https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/WebGL_best_practices#use_non-blocking_async_data_readback" rel="nofollow">MDN WebGL best practices</a> has a great section about how this process can be done. I believe we should be looking into integrating this alternative workflow into our GL2 renderer.</p>
<p dir="auto">The main concern is introducing fences for the first time into threejs' workflow. We could just handle specific fences on methods that expect them. or we could setup a proper internal interface for fences that could be expanded and used in other aspects of the library, like shader linking and compiling, framebuffer completing, etc. However, that's a much larger endeavour.</p>
<p dir="auto">I'm willing to work on a PR for this feature, but I would like to discuss options and decide what's the best course of action. So I encourage others to chime in with suggestions.</p>
<p dir="auto"><strong>Is your feature request related to a problem? Please describe.</strong></p>
<p dir="auto">WebGL2 (which is now supported by all modern browsers) offers powerful General Purpose GPU capabilities.  three.js already implements an impressive array of these features (like <code class="notranslate">WebGLMultipleRenderTargets</code>).   This GPGPU suite is nearly complete, but it's missing a performant way of reading texture data back from the GPU.  <code class="notranslate">renderer.readRenderTargetPixels()</code> waits for a sync with the GPU before the download starts, costing tens of milliseconds per-call on PC and more on mobile.</p>
<p dir="auto"><strong>Describe the solution you'd like</strong></p>
<p dir="auto">WebGL2 adds the ability to bind <code class="notranslate">_gl.PIXEL_PACK_BUFFER</code>s, which allow for asynchronous readback from the GPU Texture Buffers, largely eliminating the performance impact of GPU -&gt; Code.     This should open up all kinds of GPU Physics (and other GPGPU) Solutions.</p>
<p dir="auto"><strong>Describe alternatives you've considered</strong></p>
<p dir="auto"><a href="https://github.com/visgl/luma.gl/pull/450" data-hovercard-type="pull_request" data-hovercard-url="/visgl/luma.gl/pull/450/hovercard">Luma.gl implemented async readback a few years ago</a><br>
<a href="https://forum.babylonjs.com/t/speeding-up-readpixels/12739/" rel="nofollow">Babylon.js also has some functionality for this</a><br>
(<a href="https://forum.babylonjs.com/t/read-pixels-from-texture-asynchronously/19371/9" rel="nofollow">One implementation in Babylon...</a>)<br>
<a href="https://docs.unity3d.com/ScriptReference/Rendering.AsyncGPUReadback.html" rel="nofollow">Unity has a similar mechanism for this</a></p>
<p dir="auto"><strong>Additional context</strong></p>
<p dir="auto">My immediate use-case would be to speed up this <a href="https://zalo.github.io/TetSim/" rel="nofollow">GPU Finite Element Modelling simulation</a>.<br>
If I can get everything running fast a stable on all platforms, I'd also like to contribute a new GPUComputationRenderer (which would support <code class="notranslate">WebGLMultipleRenderTargets</code> and separate the concept of "passes" from "variables", allowing for multiple passes over the same data).</p>