10
$\begingroup$

When using textures in GLSL, it is best to calculate the final texture coordinates in the vertex shader and hand them over to the fragment shader using varyings. Example with a simple flip in the y coordinate:

// Vertex shader
attribute vec2 texture;
varying highp vec2 texCoord;
// ...
void main() {
    texCoord = vec2(texture.x, 1.0-texture.y);
    // ...
}

// Fragment shader
varying highp vec2 textureCoordinates;
uniform sampler2D tex;
// ...
void main() {
    highp vec4 texColor = texture2D(tex, texCoord);
    // ...
}

If the flip in the y coordinate, or an even simpler operation like adding vec2(0.5) to the texture coordinate is performed in the fragment shader the texture access is much slower. Why?


As a note, e.g. blending two textures, using a weighted sum of them, is much cheaper in terms of time and also needs to be done for each pixel, so the computation of the texture coordinate itself does not seem to be that costly.

$\endgroup$
  • 1
    $\begingroup$ My guess would be that if the UV coords are calculated in VS, the texture unit can start to prefetch them while the PS is starting. If they're calculated in the PS, the texture unit has to wait first. $\endgroup$ – RichieSams Aug 16 '15 at 14:41
  • 2
    $\begingroup$ Fwiw this is called a "dependant texture read", in case it helps your search. $\endgroup$ – Alan Wolfe Aug 16 '15 at 14:51
  • $\begingroup$ Do you have some measurements showing the perf difference? I actually wouldn't expect there to be much difference at all; texture fetch latency should swamp a few ALU ops. BTW, dependent texture reads are where there are two (or more) texture reads, with the coordinates for the second dependent on the output of the first. Those are slower because of the strict ordering required between the two texture reads. $\endgroup$ – Nathan Reed Aug 16 '15 at 17:58
  • $\begingroup$ Well, any operation done in the fragment shader will be more expensive then in the vertex shader. Each triangle takes 3 invocations of a vertex shader, but it might take orders of magnitude more invocations of the fragment shader, depending on its screen size. $\endgroup$ – glampert Aug 17 '15 at 1:13
  • $\begingroup$ @NathanReed I don't think you have to limit "dependent texture reads" to just those that come from a previous texture access. I'd probably also include any coordinates computed in the frag shader, as opposed to those that can be determined merely from the linear (well, hyperbolic with perspective) interpolation of vertex attributes. $\endgroup$ – Simon F Aug 18 '15 at 10:15
11
$\begingroup$

What you're talking about is commonly called "dependent texture reads" in the mobile development community. It's an implementation detail of certain hardware, and therefore it really depends on the GPU as to whether or not it has any performance implications. Typically it's something you see brought up for PowerVR GPU's in Apple hardware, since it was explicitly mentioned in both Imagination and Apple documentation. If I recall correctly, the issue basically came from hardware in the GPU that would start to pre-fetch textures before the fragment shader even began running, so that it could do a better job of hiding the latency. The docs I linked mention that it's no longer an issue on Series6 hardware, so at least on newer Apple hardware it's not something that you have to worry about. I'm honestly not sure about other mobile GPU's, since that's not my area of expertise. You should try and consult their documentation to find out for sure.

If you decide to do some Google searches on this issue, be aware that you'll probably find some older material that's talking about dependent texture fetches on older desktop hardware. Basic in the early days of pixel/fragment shaders, the term "dependent texture fetch" referred to using a UV address that relied on a previous texture fetch. The classic example was bump-mapped environment map rendering, where you wanted to use a reflection vector based on the normal map in order to sample the environment map. On this older hardware there was some major performance implications, and I think it wasn't even supported on some very old GPU's. With modern GPU's the hardware and the shader ISA is much more generalized, and so the performance situation is much more complicated.

$\endgroup$
  • $\begingroup$ By the way: I experienced that on an iPad 3. So maybe this is actually hardware specific. $\endgroup$ – Nero Aug 18 '15 at 17:18

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.