sampler2D_half in 4.1

Hello everyone,

I noticed in the release notes for 4.1 that Unity now supports the keywords “sampler2D_half” and “sampler2D_float” for mobile precision. I checked out the results inside the compiled shaders and saw that “sampler2D” results in the same code as “sampler2D_float”.

(And incidentally, it looks like just using “sampler” does not cause a compiler error, but causes shader optimization to fail!)

Anyway, in my pursuit to make my shaders run as efficiently as possible, I’m looking at using sampler2D_half, but I don’t feel like a fully understand the implications. Since it cuts down on the precision of the sampler, would it cause a texture to become blurry or pixels to be dropped during sampling? Or does it put limits on the size of the texture that you can use?

I guess I understand that using sampler2D_half should have performance benefits, but I haven’t yet been able to observe what the tradeoff is.

sampler2D_half should result in a mediump sampler being used by GLES2.0. mediump stands for medium precision, highp for high precision. It refers to the bit depth of the values returned by a texture lookup with that sampler. Like the difference between half and float. You could see that as the number of possible colors, or as the minimum possible ‘jump’ in value.

An example of an artifact caused by extremely low precision is called color banding.

Using lower precision might be faster, although you should always test it on the devices you’re targeting. I’m not sure what precision Sampler2D results in (even with #pragma debug, I still see all texture sampling as Cg), perhaps it’s chosen by the compiler.

So, if we’re pulling stuff from a texture to fixed precision (or lowp, in GLSL) - it’d be faster to do this from sampler2D_half as the precision conversion would be less expensive (half to fixed is cheaper than float to fixed? should the texture variable stay at half rather than be reduced to fixed?).

I haven’t found a way to easily test things like this at a quantifiable level, on or off mobile hardware.

I’ve generally been given the impression that “lower precision = faster execution”, though I could imagine some conversion between formats causing a performance problem.

On the other hand, there might be little to no performance issue, since stuffing a float or half into a fixed might just truncate the value, or putting a fixed or half into a float just adds empty bits. It would be interesting to hear if anyone has seen issues with this.

um, it is actually quite a different way around
if you get your simple texture it will have 32bits color info - which is 8bits per component which is quite exactly lowp.
BUT if you use fp texture - stuff gets complicated ;-). E.g. for sampling depth texture lowp brings awful results.
Basically (well, cutting lots of crap) the difference is:
if you have

it will be:

and

will be:

1 Like

Textures themselves are usually only 8 bits per channel, but aren’t the filtered values higher-precision?

So this is simply a Unity compiler optimisation?

Meaning

sampler2d tex;
fixed4 color = tex2d(tex, uv);

simply becomes

sampler2d tex;
lowp vec4 color = tex2d(tex, uv);

because there’s no precision swap taking place?

yes
also - if you dont trust me (i wouldnt ;-)) you can always check generated code ;-)))

Yes, I just wasn’t sure if this was a driver/hardware thing or software thing. Thanks for clearing it up :slight_smile:

noone knows what happens internally, but by glsl spec texture2d will return data in same prec as sampler.
so (adding some details to my example)
sampler2d tex; → uniform sampler2D tex; [in code]
and
sampler2d_half tex; → uniform mediump sampler2D tex; [in code]
effectively dictating the proper prec of texture2d return value.