GLSL; return statement ...

Started by
11 comments, last by JohnnyCode 9 years, 1 month ago
Hello,

Simple question about GLSL and fragment shaders. May I return the "final color" early if I don't need to do any further processing in the void main function?

Consider the following example:


#version 330 core

out vec4 finalColor;

uniform float drawWireframe;

uniform vec4 materialColor;

vec4 fancyLightingFunction(vec4 colorToProcess) {

// Fancy lighting function here...

}

void main() {

if (drawWireframe == 1.0) finalColor = materialColor;

// May I call "return" here?

finalColor = fancyLightingFunction(materialColor);

}

Thank you for your time.
Advertisement

Simple question about GLSL and fragment shaders. May I return the "final color" early if I don't need to do any further processing in the void main function?

Yes you can but it will not save you from any precessing in fact. Strange but true. Once gpu arrives at fragment processing, it is just too pointless to omit few local computations at the data. Surprising?

I will add up, I think I was just too short. If you want to use a branch not for computational requirement, but for optimizing one, then it maybe might be possible that some optimization would result up if you branched by an uniform value. That might get rid of the branched routine call for entire draw call. But if you branch byt vertex atrribute value/texture fetch value/or any other draw data dependant volatile value, do not even do it unless it is for required computational issue .

Dynamic branching with modern gpu's aren't that slow anymore. In fact its common optimization to skip large blocks of code.

On older GPU's, I used the rule of thumb that a branch costs a dozen math instructions, so in the average case you need to be skipping more than a dozen instruction to get any benefit.

On modern GPUs, branching is almost free.

However, on every GPU, branching is done at SIMD granularity.
AMD GPUs process 64 pixels at a time, and NVidia process 32 at a time.
If one of those pixels enters an if statement, then the whole SIMD unit must enter the branch, meaning that up to 63 pixels will be wasting their time.
So: branches should be coherent in screen space - pixels that are close to each other should be likely to take the same branches.
Thank you for all of the feedback.

Since I am a beginner maybe my thinking isn't correct on this but I will share it in hopes of hearing what experts have to say on the matter:

I wanted to use one (1) shader for drawing such that I don't have to constantly switch shaders CPU-side. The shader would use float-based uniforms to chose whether to draw:
  • Wireframe
  • Skybox (using a texture2D sampler)
  • Standard shading (with different texture channels for ambient, diffuse, specular, emissive, etc.)
    • Within my standard shading model I plan to have the capability to calculate multiple lights and be able to position them, etc.
    • I would also have the capability to turn lighting "on" or "off" such that I can just show the ambient/diffuse textures without lighting calculations.
The method I was going about doing this was as shown in my OP as an example; if a "drawWireframe" uniform was equal to 1.0, use the wireframe section of code in my shader but if that uniform was 0.0 then do something else.

In my mind this was simpler than using multiple shaders as I am just altering the uniforms in memory but not changing shaders.

From what I read you should avoid changing shaders if you can.

Let me know if this makes sense and if my thinking is correct here.

Thank you.

As I understand, you may use "if(something < 0.1) discard;"

There is no point to bundle all those shaders that do totally different things to single shader. Swapping shader for thing like sky box is no brainer. You draw sky box one time per frame and sky box can cover millions of pixels.

From what I read you should avoid changing shaders if you can.

As a rule of thumb you should avoid unnecessarily changing render states or bound resources, yes... But you should also avoid unnecessary 'if' statements within shaders!

You're making every pixel much more expensive in order to save a little bit of CPU time.

From what I read you should avoid changing shaders if you can.

As a rule of thumb you should avoid unnecessarily changing render states or bound resources, yes... But you should also avoid unnecessary 'if' statements within shaders!

You're making every pixel much more expensive in order to save a little bit of CPU time.


I see; is there a happy medium inbetween where I can use one shader to do simple stuff like draw SkyBoxes/wireframes?

I understand what folks are saying here; but having multiple shaders just to do simple tasks like drawing skyboxes/wireframes/other simple stuff seems like a waste, no?

This topic is closed to new replies.

Advertisement