# What's more optimal - sampling one channel at a time or all channels at once?

I'm going through and optimizing some of my glsl code for a project, and have come across a scenario several times that I am not sure how best to optimize.

In summary - Is it faster to sample a texture once with .rgba vs 4 times with simply .r at the end?

Here's what I have now:

mat4 getLightProjectionMatrix(int lightIndex){
mat4 m;

m[0][0] = texelFetch( projMatricies , ivec2( 0 , lightIndex ) , 0 ).r;
m[0][1] = texelFetch( projMatricies , ivec2( 1 , lightIndex ) , 0 ).r;
m[0][2] = texelFetch( projMatricies , ivec2( 2 , lightIndex ) , 0 ).r;
m[0][3] = texelFetch( projMatricies , ivec2( 3 , lightIndex ) , 0 ).r;

m[1][0] = texelFetch( projMatricies , ivec2( 4 , lightIndex ) , 0 ).r;
m[1][1] = texelFetch( projMatricies , ivec2( 5 , lightIndex ) , 0 ).r;
m[1][2] = texelFetch( projMatricies , ivec2( 6 , lightIndex ) , 0 ).r;
m[1][3] = texelFetch( projMatricies , ivec2( 7 , lightIndex ) , 0 ).r;

m[2][0] = texelFetch( projMatricies , ivec2( 8 , lightIndex ) , 0 ).r;
m[2][1] = texelFetch( projMatricies , ivec2( 9 , lightIndex ) , 0 ).r;
m[2][2] = texelFetch( projMatricies , ivec2( 10 , lightIndex ) , 0 ).r;
m[2][3] = texelFetch( projMatricies , ivec2( 11 , lightIndex ) , 0 ).r;

m[3][0] = texelFetch( projMatricies , ivec2( 12 , lightIndex ) , 0 ).r;
m[3][1] = texelFetch( projMatricies , ivec2( 13 , lightIndex ) , 0 ).r;
m[3][2] = texelFetch( projMatricies , ivec2( 14 , lightIndex ) , 0 ).r;
m[3][3] = texelFetch( projMatricies , ivec2( 15 , lightIndex ) , 0 ).r;

return m;
}


Here's what I'm considering doing:

mat4 getLightProjectionMatrix(int lightIndex){
mat4 m;

vec4 A = texelFetch( projMatricies , ivec2( 0 , lightIndex ) , 0 ).rgba;
m[0][0] = A[0];
m[0][1] = A[1];
m[0][2] = A[2];
m[0][3] = A[3];

vec4 B = texelFetch( projMatricies , ivec2( 0 , lightIndex ) , 0 ).rgba;
m[1][0] = B[0];
m[1][1] = B[1];
m[1][2] = B[2];
m[1][3] = B[3];

vec4 C = texelFetch( projMatricies , ivec2( 0 , lightIndex ) , 0 ).rgba;
m[2][0] = C[0];
m[2][1] = C[1];
m[2][2] = C[2];
m[2][3] = C[3];

vec4 D = texelFetch( projMatricies , ivec2( 0 , lightIndex ) , 0 ).rgba;
m[3][0] = D[0];
m[3][1] = D[1];
m[3][2] = D[2];
m[3][3] = D[3];

return m;
}


Does the compiler know how to optimize both of these into the same thing in the end? or would it be more efficient to pack more data into a texture fetch no matter what?

Thanks!

• The compiler can't optimize them both into the same thing, as they don't do the same thing. The way the texture is set up on the application side also has to be changed to match. Commented May 18, 2020 at 21:04
• True, I forgot to mention that I'd also be changing the format of the texture being sampled from to accommodate 4 texture calls vs 16. Commented May 18, 2020 at 21:08
• Speaking of better optimization, why not set these matrices as uniforms? Commented May 18, 2020 at 21:35

It should be significantly faster to sample one RGBA value from one location in a texture than four R values from different locations in the texture.

• ok thank you for the clarity here - is it safe to assume then that if I had 4 texelFetch().r calls to the same location, this would be similar in speed to one texelFetch().rgba ? Commented May 18, 2020 at 21:12
• I’d expect the separate fetches to be slower, as @Isolin said—packing the values into one texture should mean you’re making the best possible use of the hardware. Commented May 20, 2020 at 0:25

I fully agree with all other replies and comments that rgba is definitely faster as it reduces the number of fetches from 16 to 4. You can even omit the per-element assignment:

//I also fixed the typo in Matric[i]es
m[0] = texelFetch( projMatrices , ivec2( 0 , lightIndex ) , 0 );
m[1] = texelFetch( projMatrices , ivec2( 1 , lightIndex ) , 0 );
m[2] = texelFetch( projMatrices , ivec2( 2 , lightIndex ) , 0 );
m[3] = texelFetch( projMatrices , ivec2( 3 , lightIndex ) , 0 );