Generic question regarding how GPUs work.

Hi there

Is there a difference in performance/memory consumption in the two scenarios:

  1. Clone 1 rock GameObject 100 times
  2. Create 100 rocks procedurally

Assuming that both scenarios end up using the same amount of Verts/Tris and same amount of textures, does the GPU care?

Thanks

I’m assuming that we don’t have any scripts - just a graphics scene.

Well let’s say the rocks are cloned or procedurally created at design time in the unity editor with either copy pasting or a “rock generator” script. Once the game is built, the script is no longer in the build.

There’s a lot of little things here that can change the answer.

However lets say you’ve placed several rocks in the editor, all using the same material, and all set to use “Batching Static” vs those exact same rocks as a single mesh manually created via a script in the editor either using the built in Mesh.CombineMeshes() or a custom script. Lets also assume all of the rocks are visible in the camera, and no occlusion culling, no frustum culling.

In this case the single mesh will be faster. Static batching also combines everything into a single mesh, but it still draws each rock “individually” on the GPU by telling the GPU to draw a specific range of vertices at a time. This is faster than actually rendering them individually (ie: with batching disabled), and allows for individual rocks to be toggled or culled at runtime. Depending on the complexity of the scene and the hardware being used the cost of culling and rendering “individually” can be more expensive than just rendering the entire combined mesh if any part is visible. It might also be faster if you have a lot of complex batched meshes to be able to do culling on them.

So, the answer is yes … to both, depending on a lot of factors.

Unity also has dynamic batching, which is similar to static batching, but works on smaller groups (limited by vertex count and vertex complexity, ie: if they need color, normals, uvs, etc). If the entire group of meshes can be dynamically batched into a single mesh vs statically batched the cost to render on the GPU might actually be faster with dynamic batching, but the CPU cost of the dynamic batching and uploading the new mesh to the GPU make it overall slower 100% of the time.

The other option that appeared recently is instancing. If you disable static batching on the game objects and use a material that supports instancing (and running on hardware that supports instancing) than this can be faster than static batching or a combined mesh. It can also be slower in some cases, but if you have 100 of the same rock mesh then instancing should be faster. Static and dynamic batching has the benefit of only needing the same material to be used, where instancing needs the same material and the same mesh.

1 Like

The best way is to use GPU Instancing with the Graphics.DrawMeshInstanced method. That will ensure your rocks are all drawn in a single draw call, which will offer you the best performance.

1 Like

Thanks a lot @bgolus and @ShilohGames - very helpful information! :slight_smile:

Your saying static batching 100 rocks still requires 100 draw calls?

Kind of, yes. I suspect that particular detail is a bit platform specific. On PC w/ DirectX I believe they’re using multiple DrawIndexed calls, so technically yes, but multiple DrawIndexed calls can be made in a row nearly for free and are only part of what is meant when we say “a draw call”. On the CPU you have to tell the GPU you want to render a specific mesh, in the form of a list of vertices and vertex attributes, with a specific material, in the form of each specific shader stage and properties, and then a final “draw call” that is a literal “draw x number of vertices using the currently set data”, but all that setup before the draw call is the expensive part for the CPU side. So when we talk about “a draw call” were actually talking about all of that setup and the final draw call, which in the case of static batching is multiple actual calls of the draw method.