I want to have a better understanding of how to create shaders with optimal performance and realize where some bottlenecks can occur.

Is it usually favorable (when possible) to delegate most of the work to the VertexShader since in certain situations it may only need to process a few vertices vs. having the Fragment process the same thing potentially on thousands of pixels?

For example, if I have scrolling UV values for a texture, is it best that I pass this scroll amount in the Vertex-Shader so that it adjusts the start UV + scroll UV to a Variant register for the Fragment to read, or to just use a Fragment Constant with the scroll UV amount stored in it which will be added with the start UV's read from a Variant register?

Is passing values to one kind of Constant register (Vertex vs. Fragment) faster than the other?


This is going to be one of those "it depends" answers, so let's get that over with first: "it depends".

The objective here is not to reduce workload in one stage but to balance workload across all stages. That's what keeps your pipeline pumping nicely without each stage needing to go idle while waiting on the previous stage to complete.

So - with specific reference to your question - if your fragment shader is currently fairly lightweight but your vertex shader is already doing a lot of work, you would put the extra work in your fragment shader. Conversely the opposite is also the case.

A further consideration is that sometimes putting work in the vertex shader is just not acceptable on quality grounds. An example would be a sine wave or a sqrt calculation - the results of these will not linearly interpolate well, so if your output is dependent on them you want to put them in your fragment shader.

Regarding constants, sometimes the vertex shader can be faster and sometimes it makes no difference at all. Updating fragment shader constants can sometimes cause a full pipeline flush if the update requires a new shader to be uploaded (see http://tomsdxfaq.blogspot.com/2006_04_01_archive.html#114482755569486635 for a discussion around this) but this shouldn't really be the case with modern hardware.

As always the correct answer is - profile, determine if it's a bottleneck, then address it, but not before.

  • 3
    \$\begingroup\$ Just need to update this to note that with modern hardware becoming more and more ubiquitous the concept of "shader stages" is kinda redundant. It still holds if you're targetting anything older, and it may still be valid for mobile hardware though. \$\endgroup\$ – Maximus Minimus Feb 20 '13 at 23:33

Of course, this highly depends where your bottlenecks are. If your application is geometry-limited, offloading work to the fragment shader (or doing additional work at effectively no cost) might be a good idea, if it is fill-limited offloading work to the vertex shader is a good idea. If it is CPU-limited, it might even be an idea to move some work from CPU into shaders.

That said, nowadays most applications are usually fill-limited (if not CPU-limited). This is on the one hand due to the usually much more complicated effects done in the fragment shader than in the vertex shader and the fragment shader's dependence on steadily increasing screen resolutions. And on the other hand due to the fact, that you usually simply have fewer vertices than fragments and a triangle should usually cover more than three pixels. So in general it is usually a good idea to make the vertex shader help out the fragment shader as good as it can, in the same way as it is usually a good idea to precompute per-object data as much as possible and make it uniforms instead of doing things for every vertex (if possible, of course).

And to your last question: It shouldn't make a difference, in fact vertex and fragment shader (and all the others) share their uniforms/constants.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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