1
$\begingroup$

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!

$\endgroup$
  • $\begingroup$ 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. $\endgroup$ – Nathan Reed May 18 at 21:04
  • $\begingroup$ 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. $\endgroup$ – Lucas Morgan May 18 at 21:08
  • 1
    $\begingroup$ Speaking of better optimization, why not set these matrices as uniforms? $\endgroup$ – narthex May 18 at 21:35
3
$\begingroup$

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.

| improve this answer | |
$\endgroup$
  • $\begingroup$ 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 ? $\endgroup$ – Lucas Morgan May 18 at 21:12
  • $\begingroup$ 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. $\endgroup$ – Noah Witherspoon May 20 at 0:25
3
$\begingroup$

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 );
| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.