I think I get what you're trying to ask. I assume your primary concern are the non-uniform variables defined outside of main()
:
float left;
float right;
float mscaled;
float xn;
float xm;
Let's take a look at how the GPU and GLSL work. The GPU does not have a stack or a call activation records. There is not a way to simulate scope or local variablaes in GLSL like a C compiler can do on most CPUs. All that exists are the registers, which are either uniform registers, shader stage inputs, outputs, and the local register file unique to that shader invocation.
In other words, as there is no such thing as a function or the stack or a heap, all variables declared anywhere live in a register. Whether they're local to some scope in GLSL or global to the whole file makes no difference. They're just registers.
However, the register allocator is not part of the GLSL standard. Different OpenGL implementations can have varying levels of quality when it comes to converting high-level GLSL code into the low-level machine code the GPU understands. One of the more complicated parts of a compiler (GLSL or otherwise) is register allocation. This is the part of the compiler that determines which registers a given variable occupies. C has it a bit harder as it usually has to deal with very tiny register files (especially on x86) and it has to deal with register spilling (moving variables to the stack) and aliasing (saving variables back to RAM before calling functions) and odd instructions which demand the output be in a particular register (x86's idiv
for instance). GPUs have a large-ish register file on account of having no stack or heap, so the allocator can be simpler.
However, the register file is not infinite. If you have more variables than registers supported by your hardware the compiler will have to try fit all your variables in the registers. This usually requires some form of liveness range checking. That is, if you use a variable xn
for one calculation then never use it again, the compiler can determine this and then know that the register occupied by xn
could be used by another variable later on, thus allowing more variables than there are registers (so long as there's not too many live variables at once).
The compiler might not do this, however. It doesn't have. Or it might do it only in some cases. Scopes given simpler compilers a much easier problem to solve. All the registers allocated to local function variables can be reused after that function exits because it knows the variables are dead. Global variables have no such easy guarantee. Hence, some less capable compilers may not optimize their lifetimes as well, and the global variables will always eat up a register. This won't make anything slower but it may on some drivers limit the size of the shader you can write.
In general, I would highly recommend keeping all variables localized. Keep the definition as close to the use of the variable as makes sense. This applies to all programming languages, not just GLSL. I would also recommend making every "variable" const in every case you possible can. It can again be a hint to certain less-capable compilers that certain optimizations are possible, and more importantly, it makes your code more self-documenting and easy to maintain.
And of course, here's your obligatory "just profile to test and find out for sure" advice. Write your shader with and without your globals and profile it. Any and all performance advice online should be mistrusted and assumed to either be steeped in supposition or out of date.
main()
function? Are your values actually global variables (uniforms or attributes in GLSL parlance) or constant values? \$\endgroup\$