Compute Shader SamplerState confusion

The Unity docs say that compute shaders are written in basic HLSL, but I have some problems declaring samplers.

Example:

Texture3D<float4> myTex : register(t0);
RWTexture3D<float4> myUAV : register (u0); 
SamplerState linearSamp : register(s0);

and then using:

float4 c = myTex.SampleLevel(linearSamp, myTexCoord, 0);
myUAV[dtID] = c;

gives the following error:

Should I use a built-in sampler or initialize it in some specific way?

Thanks for any suggestions.

Reading the DirectCompute documentation further, I came accross the “mips” operator. Would it be equivalent to the SampleLevel operation?

Yeah, for samplers you have to follow some special rules, the reason being that “textures” and “samplers” aren’t separated in Unity. I’ll add this to the docs, but the rules for compute shaders are:

  • Either use same as texture name, with “sampler” in front (e.g. Texture2D MyTex; SamplerState samplerMyTex). In this case, sampler will be initialized to that texture’s filter/wrap/aniso settings.

  • Or use one of “predefined” samplers; name has to have “Linear” or “Point” (for filter mode) and “Clamp” or “Repeat” (for wrap mode). Example, “MyLinearClampSampler” - this will have linear filter and clamp wrap mode.

5 Likes

Hey Aras,

None of those samplers are working for me. I have:

Texture3D NoiseTex;

and samplerNoiseTex isn’t working, nor is MyLinearClampSampler, etc.

Do I still have to declare them?

In case you’re still having trouble sampling in compute shaders (and for future travellers of this thread): make sure you specify which mipmap level should be used (LOD). (So in compute shaders you’ll want to use SampleLevel, in stead of Sample.)

Yes you do have to declare them, i.e.
Texture3D NoiseTex;
SamplerState samplerNoiseTex;

Would have never figured this out. 7 years later, thanks Aras!

[EDIT] : I found this in the documentation

1 Like

Still relevant in URP it seems…

I’m hitting a

Fragment program 'frag': Unrecognized sampler 'sampler_repeatedtexture' - does not match any texture and is not a recognized inline name (should contain filter and wrap modes).

and don’t know why.

There’s

TEXTURE2D(_ClampedTexture);
SAMPLER(sampler_ClampedTexture);
TEXTURE2D(_RepeatedTexture);
SAMPLER(sampler_RepeatedTexture);

in place as it should, and I’m trying to call

SAMPLE_TEXTURE2D(_ClampedTexture, sampler_RepeatedTexture, IN.uv0.xy);

to sample the texture with another sampler…

Is the shader compiler doing “magic” in the background and removing samplers in the actual compiled code? From the generated code it looks alright…

The error shows it written in all lowercase though. Maybe that’s just an error quirk but maybe you had it written like that at first and it hasn’t recompiled?
This should be working fine, this is exactly how it’s used in their shaders too. Have you restarted Unity and reimported the shader as a test? And if so the error repeats itself on reimport?

Yep, that error stays around. My first instinct was also to rename the property to lowercase (_repeatedtexture) instead, but the error persists, also after restarts and library clear.

It seems that the actual reason for this failing is that the shader compiler strips out the texture when it’s not accessed, and when doing so also strips out the sampler, thus resulting in “totally ok code but the compilation result is still broken”. Not sure if that’s a bug or “by design”; accessing the sampler but not the texture is surely an edge case.

1 Like

I’m not sure how you’re both accessing the texture to get the error, but also supposedly it isn’t being accessed when the shader compiler looks at the code… Are you saying you have the sampling of it inside of keyword/shader_feature block, and you’re only turning that keyword on at runtime in build? Because that would make sense as unused variants are stripped, which is what multi_compile avoids.

If you are not using the _RepeatedTexture texture, then yes it will be removed as part of compilation. So effectively you’re left with a sampler that has no idea which texture it should get the sampling settings from, since the texture is gone.

1 Like

I got this in 2023, playing with #pragma multi_compile
As Aras said, looks like the sampler can’t find its texture, because the texture gets optimized-away.

Luckily for me, I didn’t need to have it belong to any texture, just had to have it as Bilinear+Repeat
So I used SamplerState my_sampler_RepeatPoint; as described at the bottom of

1 Like