Why does GLSL use integers for texture fetches?

Started by
2 comments, last by Matias Goldberg 7 years, 11 months ago

After reading AMD's presentation about the GCN architecture, which states that integer divisions cost multiple cycles, and unsigned integer divisions are much faster, I changed my data types to "uint" where appropriate, since I do not use negative values in most cases anyways.

However, all variants of texelFetch only accept ivec2/ivec3. What is the reason for this? From what I can see, unsigned integers would be much more appropriate.

I do not know about any extensions which has a special handling for negative texture integer coordinate values,

so, is there any reason the texture coordinates are not unsigned?

Advertisement

First up, GL is extremely abstracted from the hardware, and is often internally inconsistent to boot... so the realities of AMD hardware are pretty irrelevant, especially as GLSL is from 2004 and GCN is from 2011.

so, is there any reason the texture coordinates are not unsigned?

As a guess - a lot of software project guidelines actually recommend to avoid using unsigned types completely. Only having a single integer type can make APIs and code simpler, as there's no need to think about what kind of integer you're working with. Similarly, certain languages just have a single 'number' type that encompasses both integers and floats... I'm personally not a fan (I use uint x as a shorthand for assert(x >= 0)), but I understand the argument and have worked on some code-bases that use this guideline.

It's interesting that some of the older system values are unnecessarily signed - e.g. int gl_VertexID -- but some newer ones are unsigned -- e.g. uvec3 gl_NumWorkGroups -- but that this trend is not consistent -- e.g. ivec3 gl_MaxComputeWorkGroupSize... :(

You can always just cast freely between int and uint though.

tl;dr; Because bad calls were made.

"I AM ZE EMPRAH OPENGL 3.3 THE CORE, I DEMAND FROM THEE ZE SHADERZ AND MATRIXEZ"

My journals: dustArtemis ECS framework and Making a Terrain Generator

TBH I thought it was a bad call. And I still think it is.

However I found one instance where the fetch being an int was useful instead of being an uint: Clamp to edge emulation.
I needed my fetches to clamp to edge; so typical code would look like this:


ivec2 xy = some_value - another_value;
xy = clamp( xy, 0, textureResolution.xy );
float val = texelFetch( myTex, xy ).x;

This code would not work as intended if "xy" were to be uvec2, because values below 0 would wrap, and hence clamped to textureResolution (the other edge!) instead of clamping to 0. It would be the same as doing xy = min( xy, textureResolution.xy );

However, I'm like Hodgman: I prefer unsigned integers because we're addressing memory here, and negative memory makes no sense, and I prefer assert( x < elemSize ) over assert( x >= 0 && x < elemSize );
This case I talk about (clamp to edge) can simply be solved through explicit casts. IMO ints here have more trouble than benefits.

This topic is closed to new replies.

Advertisement