Hi, I think I have determined that the Unity renderer is updating a limited number of shadow maps each frame. This is probably a good idea for performance, but I am trying to test the actual update speed when a lot of lights are moving at once. If the renderer only updates one or a few shadows each frame, that doesn’t give me an accurate idea of the real speed. I was wondering if there is a way to force all shadows to update each frame?
Are we talking the built in rendering paths, URP, or HDRP? Because the built in rendering paths and URP don’t do any shadow map caching and always re-render all real time shadow maps from scratch every frame.
If you’re talking about the HDRP, depending on what version of it you’re using there are options to change the behavior.
https://docs.unity.cn/Packages/com.unity.render-pipelines.high-definition@10.0/manual/Shadows-in-HDRP.html
I am talking about the built-in deferred renderer I think. Can the renderer be forced to update all shadows each frame?
It already does. It literally can’t do anything but update them every frame. Can you describe the issue you’re seeing?
I believe it is only rendering one or a a few each frame, because the framerate does not go down linearly as I add more lights.
…
That’s a pretty big leap from “my performance isn’t degrading linearly with each light” to “shadows must not be updating every frame”.
I’ll reiterate what I said above. The built in rendering paths, forward or deferred, always re-render every real time shadow map from scratch every frame. It does no shadow map caching, or any other technique that would allow for delayed updates. You can confirm this with the frame debugger. You’ll see each shadow casting light render that light’s shadow maps immediately prior to lighting the scene, every frame. However performance may not scale linearly as the current bottleneck for performance changes with the work. A small number of lights may be purely fill rate limited, beyond that you may become memory bandwidth, and even total memory limited. And at some point you may become CPU limited more than GPU limited.
How do you know this? That seems impossible based on the results I am seeing. If I create a scene with thousands of objects performance drops a lot with the first light, but stays about the same as I add additional lights. The best explanation is that the renderer cycles through and updates one light each frame.
Look for yourself with the Frame Debugger.
Window > Analysis > Frame Debugger
You can also look at the Profiler to see what’s expensive, at least on the CPU side (which is all the built in Profiler shows timing stats for, even the rendering times are 100% CPU time, not GPU). And you can use something like Nvidia Nsight or CodeXL to GPU profile a standalone project.
Okay, I am seeing 140 million polygons rendered in my test scene of 10 million polys.
I know shadow polygons are cheaper to render, but the scene polys seem much more expensive than the shadows.
I always hear people saying that point lights in Unity are slow. Why is that? Are they describing another type of situation?
Poly count doesn’t really matter. GPUs don’t really spend much time worrying about polygons, or triangles. It’s mostly vertices and pixels (aka fragments), the things shaders deal with.
Vertex count matters, but modern GPUs are stupidly fast at chewing through a lot of vertices.
The number of pixels rendered is usually the limiting factor, especially if they’re rendering a color value. Shadows & depth textures in general are very fast because the GPU never has to render any of the pixels, not really. The shaders output the depth, which GPUs can do without having to process the fragment shader. GPUs take the output of the vertex shader, which is the clip space position of a vertex, and calculates the screen coverage of each triangle. In calculating the coverage it also calculates the depth. Since it has the coverage and the depth value, that’s all it needs to output and it’s done.
Point lights are more expensive than spot or directional lights because a shadow casting point light requires rendering 6 shadow maps to construct a shadow cubemap with. Spot lights only ever need one, and directional lights use 1, 2, or 4 depending on if cascades are enabled or not.