SetPass / Batches vs. Vertex / Tri count

I work with a very large and highly detailed model (.fbx with 1GB file size, >35,000,000 verts). It uses 150 individual materials and shaders. The goal is to use it for VR in as high quality as possible. Reducing the FBX is not an option.

First of all, it’s currently running fine (minimum GTX970 / Quadro M6000), I don’t really have a problem here. I am combining meshes to reduce Batches (worst case) from ~6500 to ~2500. Object nodes get reduced from 6000 to 350. That’s all fine, I’m running at least at 45 fps in most situations in the VR headset.

The way I’m doing it is like this:

  • iterate through whole object to find leaf nodes with a mesh, collect them in an array

  • find different materials in “leaf”

  • create a 2-dimensional arrayList, so that all leaf nodes that share the same material are in one array

  • iterate through each of those “material arrays” to combine meshes, so that vertCount gets close to 65,535 in each gameobject

  • delete unused / old object nodes

That’s fine so far.

But there’s something that makes me wonder.
When I take a look at the statistics window I can see that while the Batches get reduced by a nice amount, the number of SetPass raise by ~15%. How can that be? See image below.

I made sure that my mesh combine method doesn’t make mistakes here - the vert count before and after are exactly the same, as reported by my script (GetComponent().mesh.vertexCount calculated over all leaf nodes).

So my question is:
Why does my SetPass raise in the statistics window by mesh combine?
I’d like to understand that.

2929413--216572--both.png

2 things I can imagine happening based on your description;

You’re talking about using “GetComponent().mesh.vertexCount”;
There is some dodgy behaviour when using MeshFilter.mesh and MeshRenderer.materials versus the shared versions, MeshFilter.sharedMesh and MeshRenderer.sharedMaterials. Non-shared ones do some instantiation to get unique meshes/materials. If you’ve assigned materials to the combined meshes via .material, this may prevent some of the batching. But they would still reference the same shader, so unity may have that optimized.

Are the no-mesh-combine results with normal static batching & marked static (where possible)? Static batching would also order draws by material IIRC, which reduces setpasses. If you’re combining the meshes at runtime you would lose this static batching. (Though there is the StaticBatchingUtility to use afterwards maybe?)

Awesome, that was the hint in the right direction.
When iterating through the materials I used
renderObj.GetComponent().mr.material
instead of
renderObj.GetComponent().mr.sharedMaterial
just one single time … and all materials were instanced from there on.

I didn’t check on material instancing, so I didn’t see that - now, all is using shared materials and SetPass is reduced as expected.
Thanks a ton! :slight_smile:

2930684--216712--setpass.png

2 Likes