PERFORMANCE degrades NON-LINEARLY as artboard.draw() calls increase
Hardware: Firefox 133.0, NVIDIA 4070 SUPER, Intel i7-13700KF, 165hz monitor
Rive Package: @rive-app/webgl-advanced 2.21.6
Bug Source: https://github.com/RiveDegradation/RiveDegradation.github.io
Interactive Demo: https://rivedegradation.github.io/
Expected Behaviour:
Rendering an artboard X times should decrease performance linearly as x increases.
2 x artboard.draw() calls -> 165 FPS
3 x artboard.draw() calls -> 164 FPS
4 x artboard.draw() calls -> 163 FPS
.. etc ...
Actual Behaviour:
When using Firefox, performance degrades non-linearly when rendering an artboard multiple times.
Specifically:
2 x artboard.draw() calls -> 165 FPS
3 x artboard.draw() calls -> 165 FPS (now with regular frame time spikes)
4 x artboard.draw() calls -> 60 FPS 🚨🚨🚨🚨
Clearly a bug since 25 x artboard.draw() calls take the same as 4X!!! It's a quantic jump :)
Hopes and Dreams:
I'm still waiting on my previous one. I'm getting a little desperate as we're supposed to use Rive in production and ship a product by the beginning of Jan, but these performance bugs are killing us.
I understand you get a lot of bug reports from people not knowing how to use your code, but these are quite serious :(
Important Update: Chrome shows similar signs of performance non-linearly degrading, it just takes more draw calls.
I also made a video showing performance degradation in Chrome:
Yeah, this is the perfect place to post something like this, thanks.
I'm on an M2 Mac and in Firefox I don't see a drop from 120fps until a reach 20, but when I do, it's a steep drop.
This is outside my area of expertise so let me grab someone from the devrel team.
I just noticed that you're using `webgl-advanced`. The webgl2-advanced
package uses the Rive Renderer which is going to be a lot more performant.
Hey
The reason I asked is that it doesn't feel like I'm making a proper bug report, but more like I'm asking support in the community forums. It's hard to know whether bugs actually get a jira ticket. As someone trying to use Rive for a complex client project, this shakes my confidence in being able to actually ship. I really appreciate that you often respond quite quickly, but the pipeline from bug to solution is not transparent.
As per your feedback:
1) Unfortunately the webgl2-advanced uses a WebGL2RenderingContext. (Or at least I assume so) The people who will play this client project have old machines which might not support it. That said, this is not really a matter of "performance" per se and this behaviour should be investigated regardless.
2) The fact of the matter is - it's strange that the drop is so steep. Doubly so for a Windows computer with the specs I listed. A drop like this is the sign of something being wrong, especially after 4 draw calls. This is quite serious because, once again, the client project we have to ship will run on much less performant computers.
Thank you!
Yes, any bugs that get reported here get a ticket for engineering. This case is unique because webgl2, which uses the Rive Renderer, should replace webgl in almost every scenario.
As far as compatibility, I ran some tests in November using Mac Sierra (2016) and Windows 7 (2009) and here are the oldest browsers that support Rive’s newest features:
Chrome desktop v80 (released feb 2019)
Firefox v78 (2020) supports basic Rive files, v90 (2021) supports all features
Edge v80 (2020)
Opera 67 (2020)
We were also able to run Rive’s latest features on the following devices:
iPhone xs (2018) - Safari & Chrome
Pixel 3 (2018) - Chrome, edge, and Firefox
I did a little digging and it looks like most computers newer than 2015 will have GPU that supports these features. Do you anticipate users having hardware older than this?
Unfortunately our client's target audience is 55 years old with ancient machines.
That said, the issue here is "moving over to webgl2" isn't a fix to webgl having such a major bug.
If webgl is not supported and we're not supposed to use it, then perhaps the documentation should be changed to reflect that?
I did a little more digging into this and I think this is actually a browser limitation. Many browsers actually limit the number of webgl contexts you can add to a page to prevent excessive resource consumption.
If you want many instances, you actually want to use canvas-advanced
instead. The other option is to use a single webgl canvas with multiple Rive graphics loaded into it. Here are our docs regarding when you should use one vs the other: https://rive.app/community/doc/canvas-vs-webgl/docanjXoQ1uT
Here's what it says about canvas:
Great for displaying many animated canvases concurrently on the screen. This is ideal for when you want to render lists or grids of Rive animations on the screen, as there is no context limit by the browser (as opposed to WebGL)
And webgl:
Most browsers limit the number of concurrent WebGL contexts by page/domain. Using Rive, this means that the browser limit impacts the number of
new Rive({...})
instances created.If you're planning on displaying Rive content in a list/grid or many times on the same page, it's up to you to manage the lifecycle of the provided context and
canvas
element. If you need to display many animations (i.e grids/lists), consider using the@rive-app/canvas
package which uses theCanvasRenderingContext2D
renderer and does not have a context limitation, or consider the@rive-app/webgl-advanced
package, which will allow you to display multiple Rive graphics on one canvas with full control over the render loop.
One other thing to consider:
useOffscreenRenderer?
- (optional) Boolean flag to determine whether to use a shared offscreen WebGL context rather than create its own WebGL context for this instance of Rive. This is only relevant for the@rive-app/webgl
package. If you are displaying multiple Rive animations, it is highly encouraged to set this flag totrue
. Defaults tofalse
.
Hey
1) I am not instancing the Rive renderer more than once. I’m using the low level runtime, so it only creates one instance of the renderer and one webgl canvas context. The advise you linked applies to people using the non-advanced version, which creates a separate instance of your renderer for every .riv file. This is not the situation, as I am handling the renderer instancing by hand. I am simply calling artboard.draw() multiple times. The documentation you linked does mention this “or consider the @rive-app/webgl-advanced”, which is what I am using.
2) useOffscreenRender is only relevant when you have other parts of your site / app competing for more webgl contexts. You need to use it to avoid your browsing denying you futher WebGL contexts. As I mentioned, there’s only one context in this case, so it does not apply. Even if this were a fix, It’s also not a feature that’s supported in older devices.
I appreciate the suggestions, but the problem is a low level problem of your renderer, not a misuse of the codebase or a misunderstanding of the documentation. The source repository I linked should show that clearly.
Could you update me on the bug ticket in your tracker? Have some engineers tried reproducing this?
Thanks in advance!
I will also add that if the problem was an overabundance of webgl resources (it’s not), you would not see the same rendering cost between 4 artboard draw calls and 25 draw calls. It would drecrease furthermore between 4 and 25 draw calls.
The fact that the performance drops suddently after 3 draw calls, but then remains the same for 25 is a clear indicator that something’s going very, very wrong.
On another note, I’ll repeat my feedback over increasing visibility over bug reports. I hope I don’t sound like too much of an asshole :)
Right now there’s no way for me to know if this bug is being investigated or not. Will it be fixed? Will it be marked as “won’t fix”? Who knows! There’s no way for me as a professional game developer to rely on this technology if I have (a) no transparency over what’s treated seriously as a bug and what’s not and (b) no way to fix it myself.
We had to abandon the idea of making the game entirely in TypeScript for this reason, and I left my plans of making an open source TypeScript game engine with a rive renderer upended. We had to suddenly rush and switch to Unity because we have no idea whether our concerns would be heard.
This is not a criticism towards you, but towards this pipeline. If everyone from a new javascript junior developer to a 15+ years senior C++ game engine programmer has to post in a forum with little to no transparency over bug tracking, then obviously this happens. I thought about using github issues’ tracker, but I don’t see much activity there.
I hope this comes across as constructive criticism from a professional developer rather than a lame complaint. Rive is awesome technology, but not having proper bug tracking seriously hinders using this in game dev.
Sorry, you're right that my last response was unrelated. I was looking at too many things at once. :)
I just pulled down your repo, upgraded to the latest versions of webgl
and webgl2
and am still seeing the steep drop. With webgl2
you don't see the drop until you have around 100 instances, but it still happens.
I'm still working with the rendering team who are going to be the best people to look into something like this. I'll let you know when we have news.
By the way, you're also welcome to post bugs in GitHub. It may look quiet, but the engineers are in there every day.