Is your game rendering more geometry than your GPU can handle? Here, let me show you a few steps to check if your geometry is causing a performance bottleneck on your players' GPU.
In this blog post, I'll share with you:
- What geometry complexity is and how it affects your players.
- How to check if geometry complexity is a bottleneck to your game performance.
Steps to simplify your geometry to boost your game performance.
Remember last week?
Following our plan, today's topic is about a specific GPU Performance Pillar...
We are about to cover the famous performance area of Geometry Complexity.
The Game Guru's Performance Pillars - GPU Performance
Why is geometry complexity important for you?
Well, you know games...
Sometimes they're happy.
Sometimes they're screaming "this lame game doesn't run 144 fps, gimme my money back".
But those comments don't necessarily help you find your performance bottlenecks, do they?
Those you have to find yourself.
Performance bottlenecks come in different sizes and colors, depending on the current scene and on the hardware of your players.
It's your responsibility to find the exact origin of your performance bottlenecks.
And geometry complexity is one of these potential bottlenecks... one that severely affects your GPU ðŸ˜‰
Once you finish reading this post, you'll be able to answer these two questions:
- Is geometry causing a bottleneck in my game?
- Good. How do I fix it?
What is Geometry Complexity?
We all want astonishing visuals in our games.
And geometry is the basic foundation for all the visuals of your game, no matter your style.
It doesn't matter if you're developing a 3d game or a 2d game.
It's all vertices and triangles, i.e. geometry.
Wireframe Mode - Displaying Geometry
Each vertex is a point in (object) space.
And each vertex has often more data to it than just the position, such as UV0, UV1, colors and the such.
More vertex attributes means more you require more memory bandwidth. That, in turn, means less frame-rate and more power drain.
Warmer hands in winter, that's it.
Geometry complexity is basically the amount of vertices and triangles you're pushing to your GPU. That includes attributes.
So, what happens when we push too much geometry to the GPU?
Consequences of Geometry Complexity
If you're pushing too many vertices, then you're overwhelming your GPU's vertex shading units.
And your Render Thread.
And your memory.
And your battery.
And your wallet
Pushing too many vertices will slow down your game, as you're forcing your GPU to fetch shitloads of data (memory bandwidth) that you then have to process (arithmetic operations).
Overdo it and it'll require more time than 144 fps allows, resulting in wasted players' crocodile tears.
Now, if you keep your timings under control, you'll keep your players happy. And your boss.
This is why specializing on game performance is so important nowadays.
For your players... and for you.
So, how would you go about finding if your game is vertex-bound?
Is Your Unity Game Performance Vertex-Bound?
Let's say your game is running at 20 FPS and your boss is breathing down your neck.
You don't like that sensation, you're about to take action to fix this problem for good.
You have a hunch that your vertex count is causing this, but you want to confirm it.
What do you do?
→ Just drastically reduce the vertex count and see if that massively increases your framerate.
That sounds reasonable... But it's easier said than done.
Luckily, we have great tools to help out.
Before we get into the tools, let me say this...
The ideal approach involves doing one extra step before all of this.
Ideally, we'd want to simplify the rest of the game first to make sure our bottleneck is indeed coming from the vertex stage.
That means, temporarily getting rid of the cost of different stages:
- CPU: disable AI, physics, networking, animations, audio; reduce draw calls.
- GPU: reduce render resolution, reduce texture max sizes to 32, change materials' shaders to unlit color.
If you get rid of all other expensive parts and your game is still not performing, then you can be sure it's due to complexity.
Otherwise, you can't be 100% sure, because the bottleneck could come from another place.
Let's see an example.
Here's a profiler capture showing a geometry bottleneck (zoom if necessary):
Profiling Session Showing Vertex-Count Bottleneck
Almost no CPU overhead.
The main and render threads are just sitting idle, waiting for the GPU to finish.
So, ideally, here's what you have to do:
- Profile your game with simple subsystems and complex geometry.
- Reduce your geometry complexity.
- Profile your game with simple subsystems and simple geometry.
- Compare both versions.
If your frame-rate increases substantially with simpler geometry, then you have a winner.
Now the tricky part...
How to simplify your geometry?
How to Reduce Unity Vertex Count With Simplygon
The traditional way is having an artist who simplifies the models' geometry for you in the original 3d modeling software.
While that's the method that gives you the best visuals, that's also the most expensive, especially for testing bottlenecks.
You know what it takes to find an artist (or time for it) if you're an indie developer: money, tears and blood.
Sometimes, good&done is better than perfect&late.
That said, let me show you one of my favorite tools...
Give a warm welcome to Simplygon, the latest addition to the official Gamedev Guru's Essential Tools List.
Here's How Simplygon Will Conquer Your Heart
- It automatically simplifies your meshes...
- based on a a few simple parameters, and...
- It's free (for most use cases).
- It's easy.
- It's fast.
High-poly mesh in, low-poly mesh out.
As simple as that.
Here's an example:
From 6 million vertices to about 2k vertices in under 2 minutes.
Heck, it even creates the normals for you.
Sure, there are no words to say how ugly is the simplified mesh. But the original mesh was dreadful, anyway ðŸ˜‰
Jokes apart, I used very aggressive settings.
And here is the important bit: for Unity performance analysis, we don't need it pretty meshes
We just need meshes with similar shapes, while featuring a drastically reduced number of vertices.
That's because we don't want to alter the shape of the models to avoid adding more testing variables.
Once you have a simpler mesh, you have two options to make change your meshes in your scene:
- You can replace the high poly version with the low poly version, or...
- You can use LOD Groups to alternate between them depending on the camera distance.
Profiling Session With Simple Geometry Showing No Bottlenecks
That was indeed our bottleneck.
Sure, you lose quality, but remember...
You can combat quality loss by complicating your fragment shaders with normal maps, parallax mapping, etc..
For the more advanced users, here're a few ideas for you:
- Use tesselation to reduce the memory bandwidth
- Use impostor rendering to simplify it down to 2 triangles at long distances. The Amplify Impostors package does it well for you (affiliate link).
- You now know that performance bottlenecks are different in each scene and in each platform.
- It's important that you find the exact origin of your game bottlenecks.
- Find if your game is vertex-bound by checking if your frame-rate increases substantially after reducing your vertex count.
- Ideally, compare it with other subsystems being cheap.
- Reduce your vertex-count manually or with tools like Simplygon.
- Think of introducing LOD Groups to dynamically switch between more complex and simpler geometry.
This post is part of the Unity Performance Pillars series and is based on the Unity Performance Checklist.
Get your Unity Performance Checklist now to boost your game performance so you avoid nasty 1-star reviews.
Next week, I'll show you a few tricks regarding memory optimization.
So make sure you read the memory section of the checklist ahead!