Firefox performance loss when using createGraphics buffer as a texture
Most appropriate sub-area of p5.js?
- [ ] Accessibility (Web Accessibility)
- [ ] Build tools and processes
- [ ] Color
- [ ] Core/Environment/Rendering
- [ ] Data
- [ ] DOM
- [ ] Events
- [ ] Friendly error system
- [ ] Image
- [ ] IO (Input/Output)
- [ ] Localization
- [ ] Math
- [ ] Unit Testing
- [ ] Typography
- [ ] Utilities
- [x] WebGL
- [ ] Other (specify if possible)
Details about the bug:
- p5.js version: 1.3.0
- Web browser and version: Firefox 87.0, Chrome 89.0.4389.90
- Operating System: MacOs 10.14.6
- Steps to reproduce this:
When drawing a WebGL scene to a buffer created via createGraphics and then using the buffer as a texture on a plane in the main canvas, there is a large unexpected performance loss on Firefox and Safari (v.s. Chrome). Reducing the texture size increases performance, but for post-FX shader uses (for example) this is not really a viable workaround.
Here's a sketch to demonstrate: https://editor.p5js.org/Gnomeski/sketches/EUq4S03Qm
This is my first time using Github, I hope this is the right place for this. Thanks for all the good work!
Welcome! 👋 Thanks for opening your first issue here! And to ensure the community is able to respond to your issue, be sure to follow the issue template if you haven't already.
Thank you! I am able to reproduce.
If anyone is able to run some performance tests and narrow down where this performance loss is occurring that would be great.
Hey! A core part of the performance here is that data is being sent to the GPU more often than necessary to keep the texture updated. Chrome might optimize this by allowing different WebGL contexts to secretly access each other's resources on the GPU (not sure though, just speculation) but it seems that on Firefox this isn't the case.
Some options:
- If your graphic doesn't change content, try saving a p5.Image of it with
img = yourGraphic.get(). p5 knows that images can't update every frame (unless you manuallyupdatePixels()) so once the data is loaded on the GPU, it will never need to be sent again. - Instead of using a graphic, use a framebuffer, which is sort of like a graphic in native WebGL, but it lives within the same WebGL context, so no data transfer is needed in order to use it as a texture. I have a library for p5 for drawing to framebuffers to do this, but it isn't available in native p5 yet. (Maybe watch https://github.com/processing/p5.js/issues/5571 for progress on R&D for that!)
Thank you @davepagurek , my project is currently on hold, but once I get back to it I'll give it a go with a framebuffer. Appreciate the help and the links 🙏
I'm going to mark this as closed now that framebuffers have been added to p5. That should have more reliable performance across browsers. Feel free to continue the discussion if any new information comes up! 🙂