15

I see a lot of shader code on the internet where PI is simply defined as an approximate decimal near the top of the code. In general I try to let computers take care of doing math for me instead of approximating values with constants (i.e. (1./3.) instead of 0.333)

Pi seems like one of those things that would be easier to just use intrinsic functions like the radians() for.

I've heard that creating and destroying variables can be expensive in shader world, and I'm curious what the tradeoffs might be for using radians(180) inline in code instead of

#define PI 3.1415926538

at the top and then PI inline.

Thanks!

3
  • 4
    How much time does it take to execute radians(180)? How many times are you executing it? #define is very nearly cost-free at runtime, and you're not creating a new variable each time you use it. Commented Aug 9, 2016 at 20:53
  • Good questions. Be careful about presuming answers. Many languages inline functions, unroll loops, and convert predictable calculations to constants for you. Be sure you know what GLSL actually does before you jump to conclusions. When it doubt, just make it readable. I'll fix it if I have to. I'd rather see you define a function called pi() then spread radians(180) all over the place. Commented Aug 10, 2016 at 3:03
  • Hi, I don't know what the costs are, that's why I'm asking :). A constant definition at the top of a program in C/C++ is one thing, but I'm not sure (i don't know) that it's equally cost-free in GLSL, where the program gets run literally millions of times in parallel every second. For example: the intrinsic radians function may take less time to parse/execute at runtime than memory access for a stored value. The point about readability is well taken though.
    – florian
    Commented Aug 10, 2016 at 7:38

1 Answer 1

8

A define results basically in the same thing as typing out the complete value on each place, for all the compiler cares. Very cheap and no runtime cost.

When you use the radians function, best case scenario the shader compiler will recognise the possible optimisation and replace it with the actual value at compile time (wich will basically result in the same thing as using the define). Worst case scenario it will result in calculating the value on each occurrence at runtime.

In the case of glsl it is a bit tricky to make any assumptions on what the compiler will do since typically you don't know what compiler you are targetting when writing your code. It is also not easy to predict what runtime cost using radians() will bring you without actually benchmarking for each gpu.

This is probably why most of the time the safest option, the define, is chosen. This will guarantee the most optimal result.

1
  • 3
    "In the case of glsl it is a bit tricky to make any assumptions on what the compiler will do since typically you don't know what compiler you are targeting." Not true in Vulkan and modern opengl, where you compile the sharers using glslangvalidator. Its opensource and you can see the resultant bytecode, so you can figure out exactly how the compiler optimized it.
    – Krupip
    Commented Jun 4, 2018 at 18:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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