Weird "Only instancing constant buffers can have struct variables" error

When using Dx11 unity for some reason modified shader compiler so that any non-instancing cbuffer will produce a compilation error, at least on 2021.3 LTS.

As it turns out “instancing cbuffer” is one that has name beginning with ‘UnityInstancing_’. So workaround is to just add that prefix to cbuffer and it will actually “just work” with Shader.SetGlobalConstantBuffer and friends it seems (at least seems to work so far?)

Now, I understand this is done for compatibility reasons (probably? as always?), but using cbuffers is important for performance and is advised on nvidia’s blog for one (How About Constant Buffers? | NVIDIA Developer)

I would appreciate if you removed this restriction for platforms that don’t care for it, or turned it into a warning.

1 Like

The restriction is only on structs as part of constant buffers. You absolutely can use cbuffers, just not with structs inside.
Please don’t try to work around this by adding a “UnityInstancing_” prefix to the name. It changes the behaviour.

This makes no sense to have this restrictions in newer unity versions though, since we can set constant buffers directly. Before you would have problems because there was no Shader.SetStruct but it isn’t needed and I have hard time understanding how do I not use structs when I need to put array of things into cbuffer.
Like Light in NVIDIA’s example, in my case its even worse and I don’t see expressing this properly without structs

struct TerrainMaterial
{
    float4 scaleTiling;
       
    int albedoTexture;
    int normalTexture;
    int maskTexture;
    int _pad;
       
    float normalStrength;
    float metallic;
    float smoothness;
    int _pad2;
};

struct TerrainMaterialTable
{
    int   mainIndex;
    int   triplanarIndex;
    int   blendIndex;
    float blend;
};

cbuffer UnityInstancing_TerrainMaterialInfoList_CBuffer
{
    uniform TerrainMaterialTable PT_MaterialTable[32];
    uniform TerrainMaterial      PT_MaterialDesc [24];
};

Might want to remove level of indirection but still better to have this as structs

Maybe. We’d need to double-check if that’s really the case.

I appreciate that. To be precise I meant that Shader.SetGlobalConstantBuffer allows you to work with structs as it basically just copies bytes directly. While its not very safe as in you can get alignment wrong, it is still possible

Will be waiting for update :slight_smile:

So… Any news? This keeps being annoying limitation with seemingly no good reason for it

Hi!
I checked and it may be that this restriction is not needed anymore, but it will be a feature request, not a bug fix.

That’s understandable. But I assume this means you won’t be able to add this to 2022.3? :frowning:

You’re correct, it’s unlikely.

any updates here?

@joshuacwilde Not yet. It’s a relatively low priority feature request.

Please add it to Unity 6. How long can it take to just disable compiler error anyway

Yeah, that bothers me too. Because it’s not that rare when you need to store array of structs into a constant buffer. Especially blocker when porting from plain DX11. Since DX11 supports it perfectly, there’s no real reason to limit that. Alignment issues should be addressed by the user (e.g author of the shader).

1 Like

This should really just be fixed and added to the next Unity release as it’s just a unneccessary compiler restriction. It makes using cbuffers properly very hard, because any variables declared in them are accessible to the global shader namespace. (Eg if you include 2 cbuffers with the same variable names, you will get errors)

It’s very common in rendering code to group data in a cbuffer behind a struct, so you only have to worry about the struct variable itself having a unique name, and you can then access it’s properties easily.

Eg struct AtmosphereProperties{}, CameraProperties{}, and then in your shader code:

float3 transmittance = exp(-atmosphere.Scatter * t); etc. (Instead of a global variable named Scatter)

Unity has had a lot of good graphics code improvements but unnecessary restrictions like this are holding it back. I’ve been developing a custom SRP for my own games for a while and it’s frustrating having to work around restrictions like this, whereas a very simple C++ engine with HLSL would allow me to bypass all these issues.

(Another annoying omission: Dual source blending

Unity 6 is in beta, which means features don’t go in.

It can take a while, depending on what side effects it can have. This path has been explicitly disabled, which means there’s literally no test coverage for how it behaves.

1 Like

Even if it isn’t making it to Unity 6.0 out-of-the-gate, would this feature request be covered (or could be covered) under this scope? It’s a feature already “In Progress” on the roadmap “to officially support the DirectX Shader Compiler in order to supplement (or entirely replace) the existing FXC shader compilation path currently in use.” specifically calling out the current lack of support for using the experimental DirectX Shader Compiler backend with DirectX11 and OpenGL ES, such that this would add support for (at least) those targets.
https://portal.productboard.com/8ufdwj59ehtmsvxenjumxo82/c/1829-dxc-shader-compilation-and-shader-model-6-support