-
-
Notifications
You must be signed in to change notification settings - Fork 35.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WebGL2: Asynchronous Readback with PIXEL_PACK_BUFFERs #22779
Comments
I am incredibly interested in this. Is there a possibility to accelerate implementation of this feature with for example a bounty? |
I am not sure how to best integrate the approach for general use cases, but I am successfully retrieving pixel values by integrating the https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/WebGL_best_practices The pixel buffer input https://github.com/kainino0x/getBufferSubDataAsync-Demo/blob/master/index.html I modified the I apologize for not providing a more robust solution, but I thought this info might be helpful. It would be exciting to experiment with a |
Thanks to the advice here! mrdoob/three.js#22779 (comment)
@snsie Thank you for the tips! Following your instructions, I was able to get Async Readback working in my TetSim with these changes: zalo/TetSim@9696c2e It results in a dramatic performance improvement when reading texture data back from the GPU! (Especially on Mobile/iOS!) I didn't try too many things, but the spooky(?) thing about it is that it only seems to work if it's called right after the last |
Alright, let's try to get this feature live, so others can utilize it as well.
I imagine you were bouncing render targets, so if you don't call
Yes, this is something to be considered. However, we should allow for the user to readback more than a single An internal pool of on-demand I should have enough to prep an initial PR for this feature, however I'm unsure about setting a proper fence sync API to be used alongside the rest of the lib, or if the sync procedure should be considered stand-alone just for |
I'm a bit biased toward GPGPU uses, but my ideal would be that the current The primary upgrades are that it:
At the moment, I believe it has some rough edges (hard-codes to 4 outputs, comments out gl_FragColor -> pc_FragColor define for no reason, doesn't have an updated read-me block, and other misc. style issues etc.) A lot of these could probably get picked up and resolved while porting the current GPGPU examples to it. I haven't had the time lately to wrap it together into a nice PR, but anyone is free to take the code and modify + submit it it for that (or any other) purpose. (I can see how it might also be desirable to do Async Readback from non-GPGPU render textures, so I suppose the functionality could also live deeper in three.js and generalize back to my use-case...) |
I can only say that it's best to start with something simple that can be enhanced over time. Try to not over-engineer the feature. The advantage of |
This is really needed feature! I'm using Wish to see this in three.js :) |
Will experiment with a proposal PR for this feature, this weekend. I have been running a test build in a personal project for a while and I feel like it could fit well into our API. Will be good to test on as many devices as possible, to account for Polyfill needs and edge-cases. |
@sciecode any luck? |
Well, sort of. I noticed that the approach I used only works because I respect a few rules, which aren't necessarily things that other users might want to follow. Let me break down the procedure to illustrate what's happening. The main goal I set was to keep the API similar the current WebGLRenderer.readRenderTargetPixels. In WebGL 1, this blocks the main thread and guarantees that every call is gonna always be executed in the same animation frame that it was called. Which is why it acts so slow, but also why we have guarantees that every However, the async version works a bit differently. In order to prevent the main thread from being blocking, we introduce a fence command in the pipeline. This means, we have to opportunity to probe if this fence command was executed, and only after the fence is returned, we then procede with a blocking read-back of the specialized The tricky part here is reliably making sure that each In Mozilla's best practices, they probe the fence command by looping a If anyone has an idea of how to circumvent this limitation, I open to suggestions. If this is not super important, then I can push my version as an initial PR of this feature. |
Thinking a bit more about it, I believe we might be fine using the described API. As long as the use-case is not a split CPU/GPU computation in a single frame. For example, performing some computation on the GPU and using that information in the same frame for a later computation on the CPU. Which is far from being a common use of Three.js. Even in that case, using the synchronous version would still be a possibility. I think I'll move forwards with a PR, and if users request support for the use-case, we can try to devise a better solution to support it. I'll do my best to work on the PR during the weekend, sorry for the delay @mrdoob. |
I think it would dramatically increase the efficiency of GPU picking, as currently (in our use case in giro3D), we need to render 3 differents passes to collect all the data for picking, and the main thread is frozen while |
I am incredibly interested in this too, especially in GPU picking. |
Can this PR be merged or updated? |
Are you able to use the |
Is your feature request related to a problem? Please describe.
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
WebGLMultipleRenderTargets
). This GPGPU suite is nearly complete, but it's missing a performant way of reading texture data back from the GPU.renderer.readRenderTargetPixels()
waits for a sync with the GPU before the download starts, costing tens of milliseconds per-call on PC and more on mobile.Describe the solution you'd like
WebGL2 adds the ability to bind
_gl.PIXEL_PACK_BUFFER
s, which allow for asynchronous readback from the GPU Texture Buffers, largely eliminating the performance impact of GPU -> Code. This should open up all kinds of GPU Physics (and other GPGPU) Solutions.Describe alternatives you've considered
Luma.gl implemented async readback a few years ago
Babylon.js also has some functionality for this
(One implementation in Babylon...)
Unity has a similar mechanism for this
Additional context
My immediate use-case would be to speed up this GPU Finite Element Modelling simulation.
If I can get everything running fast a stable on all platforms, I'd also like to contribute a new GPUComputationRenderer (which would support
WebGLMultipleRenderTargets
and separate the concept of "passes" from "variables", allowing for multiple passes over the same data).The text was updated successfully, but these errors were encountered: