Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Speed of cos() and sin() function in GLSL shaders?

I'm interested in information about the speed of sin() and cos() in Open GL Shader Language.

The GLSL Specification Document indicates that:

The built-in functions basically fall into three categories:

  • ...
  • ...
  • They represent an operation graphics hardware is likely to accelerate at some point. The trigonometry functions fall into this category.

EDIT:

As has been pointed out, counting clock cycles of individual operations like sin() and cos() doesn't really tell the whole performance story.

So to clarify my question, what I'm really interested in is whether it's worthwhile to optimize away sin() and cos() calls for common cases.

For example, in my application it'll be very common for the argument to be 0. So does something like this make sense:

float sina, cosa;

if ( rotation == 0 )
{
   sina = 0;
   cosa = 1;
}
else
{
   sina = sin( rotation );
   cosa = cos( rotation );
}

Or will the GLSL compiler or the sin() and cos() implementations take care of optimizations like that for me?

like image 202
ulmangt Avatar asked Apr 14 '12 15:04

ulmangt


People also ask

How does GLSL shaders work?

A GLSL fragment shader controls the entire behavior of the GPU between the rasterizer and the blending hardware. That shader does all the work to compute a color, and the color it generates is exactly what is fed to the blending stage of the pipeline.

What is the difference between HLSL and GLSL?

In GLSL, you apply modifiers (qualifiers) to a global shader variable declaration to give that variable a specific behavior in your shaders. In HLSL, you don't need these modifiers because you define the flow of the shader with the arguments that you pass to your shader and that you return from your shader.

Does OpenGL use GLSL?

The OpenGL Shading Language (GLSL) is the principal shading language for OpenGL.

Does Blender support GLSL?

Blender supports vertex and fragment shaders in GLSL (i.e. “GLSL programs”; not to be confused with the built-in “GLSL material” or “GLSL shading”).


4 Answers

For example, in my application it'll be very common for the argument to be 0. So does something like this make sense:

No.

Your compiler will do one of two things.

  1. It will issue an actual conditional branch. In the best possible case, if 0 is a value that is coherent locally (such that groups of shaders will often hit 0 or non-zero together), then you might get improved performance.
  2. It will evaluate both sides of the condition, and only store the result for the correct one of them. In which case, you've gained nothing.

In general, it's not a good idea to use conditional logic to dance around small performance like this. It needs to be really big to be worthwhile, like a discard or something.

Also, do note that floating-point equivalence is not likely to work. Not unless you actually pass a uniform or vertex attribute containing exactly 0.0 to the shader. Even interpolating between 0 and non-zero will likely never produce exactly 0 for any fragment.

like image 132
Nicol Bolas Avatar answered Oct 23 '22 16:10

Nicol Bolas


This is a good question. I too wondered this.

Google'd links say cos and sin are single-cycle on mainstream cards since 2005 or so.

like image 38
Will Avatar answered Oct 23 '22 15:10

Will


You'd have to test this out yourself, but I'm pretty sure that branching in a shader is far more expensive than a sin or cos calculation. GLSL compilers are pretty good about optimizing shaders, worrying about this is premature optimization. If you later find that, through your entire program, your shaders are the bottleneck, then you can worry about optimizing this.

If you want to take a look at the assembly code of your shader for a specific platform, I would recommend AMD GPU ShaderAnalyzer.

like image 5
Robert Rouhani Avatar answered Oct 23 '22 16:10

Robert Rouhani


Not sure if this answers your question, but it's very difficult to tell you how many clocks/slots an instruction takes as it depends very much on the GPU. Usually it's a single cycle. But even if not, the compiler may rearrange the order of instruction execution to hide the true cost. It's certainly slower to use texture lookups for sin/cos as it is to execute the instructions.

like image 2
Robinson Avatar answered Oct 23 '22 16:10

Robinson