7
\$\begingroup\$

My fragment shader was significantly slowed down by a recent change, and I've been trying to understand why.

I isolated the main slow-down to accessing a single particular uniform float. If I include this line:

float not_used = my_uniform;

then the shader runs more than twice as slowly as it does without this line. The not_used float is never referenced again.

Why would this be happening? I hope to understand it so that I can try to come up with a workaround that runs more quickly.

I'm running this on a mac with Intel HD Graphics 3000. I'm measuring the performance by making OpenGL timestamp queries before and after executing my glDraw calls and looking at the ms intervals. I can provide more specs / details if it would be helpful in diagnosing the problem.

\$\endgroup\$
  • \$\begingroup\$ You are measuring performance wrong. Draw calls may be buffered, so you must call glFinish() or your buffer swapping functions, so the code actually gets executed. Also a decent glsl compiler should remove any unused uniforms from your code. \$\endgroup\$ – akaltar Sep 13 '14 at 21:14
  • \$\begingroup\$ @akaltar, I'm measuring performance on the GPU side by using gl{Begin,End}Query with GL_TIME_ELAPSED as the metric. This setup is designed to take into account the way OpenGL commands are executed asynchronously with the CPU. See opengl.org/registry/specs/ARB/timer_query.txt \$\endgroup\$ – Tyler Sep 13 '14 at 21:52
  • 2
    \$\begingroup\$ Can you show the entire shader? \$\endgroup\$ – Roy T. Sep 14 '14 at 7:55
  • \$\begingroup\$ basically impossible in its current form. every compiler on the planet optimizes out unused variables. or maybe not if you use Mesa with some kind of debug flag and in software implementation. but you are on Mac so the glsl compiler is some version of llvm embedded in the driver. Or, your shader was doing nothing before, and it does one access to a uniform that is optimized out now. so the difference is a measure noise. you can only check FPS difference when measuring GPU rendering perf. \$\endgroup\$ – v.oddou Nov 20 '14 at 7:47
  • 2
    \$\begingroup\$ @Tyler Twice as slow compared to what? 16/32 ms or 0.001/0.002ms? Also, is the uniform value a nice round number (0,1,2,-1 etc.)? There's a possibility that the GPU tries to recompile the shader if the uniform has a conveniently optimizable value (for example, having 0 in calculations would disable some of them completely and having 1 would remove uniform reads and multiplications). \$\endgroup\$ – snake5 Nov 20 '14 at 9:30
2
\$\begingroup\$

Are you using glGetUniformLocation to get the uniform's location? If the uniform has been optimized out, this function will return -1, then when you give the -1 as the location argument to glUniform1f, nothing will be sent to the shader and this will likely save some time.

|improve this answer|||||
\$\endgroup\$
-2
\$\begingroup\$

Sounds like an alignment or memory size issue. Perhaps with this one increased float your memory needs are being bumped up to some magic number that slows down the MAC (I don't use MACs myself) but most likely it is causing an alignment issue.

Consider a C++ type structure in pseudo code:

struct myStruct {
    char x;
    int y;
}

If this structure is allowed to be created normally with an int size of 4 bytes and a char size of 1 byte the structure would be 8 bytes, not the expected 5 bytes. This is because if a word (4 bytes in 32 bit systems) is not aligned on a 4 byte boundary then more work has to be done by the CPU to move this word around. It is a single assembly instruction to move a word (int in this case) if it is properly aligned. If it is not properly aligned then half the word is moved, a pointer is changed and then the other half and this slows things down. So, a structure will normally try to properly align itself when compiled.

If you were to do something like #pragma packed which would remove the unused padding bytes the size would be the expected 5 bytes and things would be slower.

So, I think you need to look at where you are declaring that float and what is declared immediately before it and after it to find out where your possible memory alignment issues are coming from.

|improve this answer|||||
\$\endgroup\$
  • 3
    \$\begingroup\$ there don't exist such alignment issues on GPU. they are basic RISCs DSPs and dont allow misaligned reads. Moreover, uniform variables are stored in constant buffers, which fit in registers during a thread execution. \$\endgroup\$ – v.oddou Nov 20 '14 at 7:49

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.