Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
Tags

Performance - SetMesh required every frame?

A topic by Scarlet String Studios created Oct 17, 2023 Views: 69 Replies: 2
Viewing posts 1 to 3

I'm working on a Switch port of my game, so I've been paying more attention to the profiler recently. I noticed that SetMesh gets called every frame, and there's a comment at like 1761 saying "TODO: make this only get called if something changed, or it's animating".

Figured I might as well ask: were you able to make progress on this? It seems like it would have a big impact on performance in some situations.

In this case, I have an ASCII art with a custom <c> gradient that's using a lot of CPU. In the editor, STM's Update method is eating up 2.5ms (sounds like a small number, but it drops the framerate on the Switch to 30 fps). Even with the ASCII disabled, the rest of the (non-animated) text is still taking 1ms on my desktop computer.

Now, the rest of the screen is static while this is happening, so the frame drops aren't super noticeable. But, it would be great if there were some optimization that could be done here, especially if calling SetMesh in Update is not really needed.

Developer

Hey!

So that note to myself has a bit of a long story...

Basically, SetMesh() is called every frame when there's an animated effect going on. If it's working as intended, it only gets enabled when an effect actually needs movement, so <c=rainbow> won't invoke it if the animation speed of the gradient is set to 0. This could be optimized further though, currently every time it calls SetMesh(), it rebuilds the mesh from stored data entirely. So it doesn't re-parse the entire string like Rebuild() does, but it does re-create the mesh with the appropriate time data. I *think* this could be improved if it checked which vertices actually needed to update position/color, and then only changed those. But ultimately, I didn't go with this because SetMesh() is already called every frame as STM reads out... so you'd end up with variable CPU load for a given string, and I thought it'd be better to just keep it consistent.

The actual end goal of this note is... someday I really want to make it so that all of STM's time-based effects are handled GPU-side instead of CPU-side. So the timing data would just be fed to STM's shader , and it'd just do it's thing automatically every frame, instead of STM needing to update anything. I'm still just waiting on the shader update I commissioned that will handle new dropshadows and outlines before I look further into this route, so I have something to build on. There's still a lot of things to consider with this method, too.

But also, for the current method there probably is way more that can be optimized, even while still updating every frame on CPU. I may have to take another deep-dive into that shortly to see if there's anything I missed that I'd know how to handle better today.


So until then, all I can really say is... cut down on animated effects or text box size, if possible. The animated effects are really just meant for text boxes about the size of the Paper Mario games at largest, so uuuuuusually a mesh of that size updating every frame isn't too bad, so it's been left as-is for the time being.

Hey, thanks for the detailed reply. I guess that makes sense — yeah, with a quick test, I can see that CreateMesh is called when I have an STM component with a <j> tag, and it stops if I remove the tag. I think the reason the non-animated text was taking 1ms for me was because I still had a custom <w> somewhere in there (so it was still calling SetMesh).

Anyway, I guess I'll leave this be for now. Those optimizations would be great, if you're able to figure it out. So far, because this is just UI text, the frame drops don't seem to be a huge deal, but I'll see if it becomes an issue in other situations later on.