Poor performance for many MaterialPropertyBlock::SetVector(int, Vector4) calls

Hi Folks, I’m running some physics simulations on the CPU (might move it to the GPU if I can find a way to implement that later on) and in order to render the results, I have to update some material properties for some 1500ish sprites (all using the same material).

AFAIK the recommended method is to use MaterialPropertyBlock to update the relevant property, then set it on the renderer. I’ve done this but am quite peeved by the subpar performance this operation has with my ~1500ish calls.

I’m using an int to reference the property ID (not strings) and I’ve used the profiler to narrow it down to two single lines of code: MaterialPropertyBlock::SetVector() takes up 5.5% of my frame render time and SpriteRenderer::SetPropertyBlock() takes up 4.7%. Those numbers seem bananas high to me, even given the fact I’m calling them 15000 times per frame. The actual physics simulation itself costs me 9.7% in total, and that’s a single-threaded op on the CPU… it should absolutely not be costing me about the same to push the resulting Vector4s out to the GPU!

Is there anything I can do here to improve performance for large amounts of SetVector() and SetPropertyBlock() calls? Maybe there’s some way of batch updating/setting these properties or something I’m not aware of?

Can you use a compute shader / compute buffer to set this information rather than doing it on the CPU?

I will probably move this logic to a compute shader in the long run, but I’m not 100% sure it’s going to work, so I was hoping for a solution to help improve performance in the meantime and/or as a backup, in case the compute shader approach doesn’t work for some reason.

Another question is what render pipeline are you using? If you’re in builtin, MaterialPropertyBlocks are the way to go but in URP for example it breaks the SRP batcher and it’s more recommended to create separate materials for each object instead.

I’m using the builtin pipeline. Unfortunately for me, I rely on shader replacement and that’s only available in the builtin pipeline :confused: