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\$
5
  • \$\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, 2014 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, 2014 at 21:52
  • 2
    \$\begingroup\$ Can you show the entire shader? \$\endgroup\$
    – Roy T.
    Sep 14, 2014 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, 2014 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, 2014 at 9:30

2 Answers 2

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.

\$\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.

\$\endgroup\$
1
  • 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, 2014 at 7:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .