Per Material Properties with SRP batcher

I've been working on some shaders is SRP and am now facing a feature that requires per instance data.
I have defined everything in the UnityPerMaterial Cbuffer and the shaders are fully SRP Batcher compatible.
But the question is, how do I get per instance data into the SRP Batcher without breaking the batching?
I know that GPU Instancing is not compatible, so MaterialPropertyBlocks won't work.
Is there a way to use the SRP Batching with this in any way or do I need to refer to global data arrays?

What do you mean by per instance data?

The term "instance" gets used in a lot of different ways throughout Unity. GPU instancing for example, which as you mentioned the Shader Graph doesn't support. The other cases I'm aware that aren't for GPU instancing of are all just using multiple unique materials, or otherwise overriding a material property at runtime internally. And for those you do just need to have the property be set to be per material.

If your question is "but how do I use it with Graphics.Draw*()" the answer is those are almost all forms of GPU instancing, which Shader Graph doesn't support, so you can't use them and Shader Graph together (easily).

Sorry if I wasn't fully clear with my question.
The shader is handwritten, but I only support the SRP Batching so I'm using the
CBUFFER_START(UnityPerMaterial) tags. How does the SRP Batcher handle shaders that are written with GPU Instancing? Do they fall back to the only rendering pipeline?

With "per instance data" I mean having property overrides for one mesh that shares the same material as another similar to how MaterialPropertyBlocks work with GPU instancing on runtime. Of course, I don't want to just change the values and create "Instances" of the material but I haven't found a way to override properties any other way.

[quote=“lukasleder”, post:3, topic: 866661]
How does the SRP Batcher handle shaders that are written with GPU Instancing?
[/quote]
It doesn’t.

If something is rendered using GPU instancing, it isn’t using the SRP Batcher, and vice versa. The SRP Batcher is intended as a replacement for GPU instancing that is more versatile and more performant (in the general use case).

If you want to use GPU instancing, don’t bother with any of the various SRP Batcher requirements and use material property blocks on the renderers, or use the DrawMeshInstanced() functions along with either preset data arrays or buffers.

"If something is rendered using GPU instancing, it isn't using the SRP Batcher, and vice versa. The SRP Batcher is intended as a replacement for GPU instancing that is more versatile and more performant (in the general use case).
"
So the SRP Batcher has no support at all for per mesh property overrides then?
Thanks for the insight! Then I'll probably just use some global arrays as I only need to support a few custom data providers at a time or I'll switch to the good old GPU Instancing.

[quote=“lukasleder”, post:5, topic: 866661]
So the SRP Batcher has no support at all for per mesh property overrides then?
[/quote]
It does … via unique materials.

Rendering 10k of the same mesh, each with a unique material, is only maybe 10% slower than doing the same with material property blocks and GPU instancing.

The crazy thing is the SRP Batcher basically just as fast if all 10k meshes all unique. And it is actually faster than GPU instancing if you’re changing the per object properties every frame, at least on the CPU (GPU side for either is no different) if you’re doing instancing via material property blocks on individual game objects. Manually instancing via DrawMeshInstanced() makes GPU instancing slightly faster on the CPU, but doesn’t change the fact that the SRP Batcher is almost as fast.

It feels wrong to just make a bajillion unique materials, but it really does “just work”.

1 Like