How to debug set pass calls?

Is there anyway to debug why a particular object is triggering a set pass call?

I have a scene with 5 materials (no instances of materials) and different meshes, but I am getting around 50 set pass calls. I haven’t yet been able to figure out why it is happening, and it doesn’t make any sense to me.

As I understand, a set pass call should only be triggered with material changes.

I am mostly concerned about this because I believe that lowering the set pass calls will make a bigger difference than lowering draw calls right now.

Even odder, it seems some objects cause two set pass calls…

Check out the Frame Debugger under Windows > Analysis. A single object with a single material can very easily generate 6 set pass calls alone if your scene has a single shadow casting directional light and post processing enabled. With no post processing, it’ll be at least 3 per object with a shadow casting directional light. A single additional shadow casting light can add several more. It’ll be more obvious once you open up the frame debugger though.

Yeah, so I spent a good amount of time debugging today. It still isn’t very obvious to me. At first it seemed it was due to opaque sorting, but no, not the case, although setting it to none did help. The other thing is that I am using only light probes. Not even lightmaps (not in this test scene, anyway). I am still not sure what is going on. There shouldn’t be any material changes between draw calls except for 5 or so due to the 5 unique materials. But they are all sorted by materials now as I turned off opaque sorting on the camera and adjusted the materials to have different render queues. And I verified in the frame debugger they are sorted by material.

Really appreciate your help btw :slight_smile:

Unity will choose to sort things separately for all sorts of reasons. Light probes are one reason why batching / set pass calls may be higher since each object needs to be rendered uniquely since each object’s probe data will be unique. So I can imagine Unity stops attempting to keep the same materials rendering one after another in favor of reducing fill rate (attempting to draw larger / closer objects sooner than further objects).

The reality is 50 set pass calls is nothing. For mobile hardware there’s this long standing wisdom than you should keep the “draw calls below 100”. The problem with that wisdom is it dates to mobile devices from 10 years ago, and draw calls themselves were never the expensive thing hence why Unity shows set pass calls (which are somewhat important). But modern PCs and consoles can easily do thousands, if not tens of thousands of set pass calls, without it adversely affecting performance. Call of Duty titles on the Xbox 360 apparently averaged over 30,000 set pass calls. Mobile devices the number is in the several hundred range. The only time it’s really an issue is for mobile VR, and even then it’s in the multiple hundred range.

2 Likes

hmm, just trying to figure out why performance is trash right now. Feels a bit like a black box. Verts are high ~190K, but not that high. Draw calls are ~300. We are using the standard shader for most things. idk…

I mean I have experienced similar as I had a previous voxel based project I was working on in metal where I had up to 10K draw calls but all using one material. It ran right at 60 FPS on an iPhone X. Verts were probably around 1.5 mil with a vertex color diffuse shader.

So it just feels off that things are running slow rn in what I think would be a simpler project. Maybe the standard shader is to blame?

Unity’s profiling tools are only really going to help you understand what’s slow on the CPU side, and give you limited visibility on what the CPU side of things is asking the GPU to do. You’ll need to use an external GPU frame capture / profiler to see what’s taking so long on the GPU itself (if that is indeed where things are being slow). XCode has one built in if you’re looking at the iPhone X performance, though I’ve not done iOS dev for 6 years now so I can’t really help there.

If you want to try looking at exactly what’s happening on the Mac (just to get an idea of what to look at), you can try this:

Wanted to come back and say I finally got GPU Frame Capture working on iOS that night and I did some profiling. Turns out using the built in unity color grading was taking between 8 to ~11.5 ms per frame on my iPhone X!!! I had heard it was expensive but didn’t think it would be that expensive. So we are looking for more performant options now. Thanks for your help once again @bgolus !!

1 Like