Pourquoi l'accès aux textures est-il beaucoup plus lent lors du calcul des coordonnées de texture dans le fragment shader?

11

Lorsque vous utilisez des textures dans GLSL, il est préférable de calculer les coordonnées de texture finales dans le vertex shader et de les remettre au fragment shader à l'aide de varyings. Exemple avec un simple retournement dans la coordonnée y:

// 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);
    // ...
}

Si le retournement dans la coordonnée y, ou une opération encore plus simple comme l'ajout vec2(0.5)à la coordonnée de texture est effectuée dans le fragment shader, l'accès à la texture est beaucoup plus lent. Pourquoi?


Remarque: par exemple, le mélange de deux textures, en utilisant une somme pondérée d'entre elles, est beaucoup moins cher en termes de temps et doit également être effectué pour chaque pixel, de sorte que le calcul de la coordonnée de texture elle-même ne semble pas être si coûteux.

Nero
la source
1
Je suppose que si les coordonnées UV sont calculées en VS, l'unité de texture peut commencer à les extraire pendant le démarrage du PS. S'ils sont calculés dans le PS, l'unité de texture doit d'abord attendre.
RichieSams
2
Fwiw cela s'appelle une "lecture de texture dépendante", au cas où cela aiderait votre recherche.
Alan Wolfe
Avez-vous des mesures montrant la différence de performance? En fait, je ne m'attendrais pas à ce qu'il y ait beaucoup de différence; la latence de récupération de texture devrait submerger quelques opérations ALU. BTW, les lectures de texture dépendantes sont là où il y a deux (ou plus) lectures de texture, les coordonnées de la seconde dépendant de la sortie de la première. Celles-ci sont plus lentes en raison de l'ordre strict requis entre les deux lectures de texture.
Nathan Reed
Eh bien, toute opération effectuée dans le shader de fragments sera plus coûteuse que dans le vertex shader. Chaque triangle prend 3 invocations d'un vertex shader, mais cela peut prendre des ordres de grandeur plus d'invocations du fragment shader, selon sa taille d'écran.
glampert
@NathanReed Je ne pense pas que vous ayez à limiter les "lectures de texture dépendante" à celles qui proviennent d'un accès à une texture précédente. J'inclurais probablement également toutes les coordonnées calculées dans le shader de frag, par opposition à celles qui peuvent être déterminées simplement à partir de l'interpolation linéaire (enfin, hyperbolique avec perspective) des attributs de sommet.
Simon F

Réponses:

11

Ce dont vous parlez est communément appelé "lectures de texture dépendantes" dans la communauté du développement mobile. C'est un détail d'implémentation de certains matériels, et donc cela dépend vraiment du GPU pour savoir s'il a ou non des implications en termes de performances. En général, c'est quelque chose que vous voyez soulevé pour les GPU PowerVR dans le matériel Apple, car il a été explicitement mentionné dans Imagination et AppleDocumentation. Si je me souviens bien, le problème venait essentiellement du matériel du GPU qui commencerait à pré-récupérer les textures avant même que le shader de fragment ne commence à s'exécuter, afin qu'il puisse mieux masquer la latence. Les documents que j'ai liés mentionnent que ce n'est plus un problème sur le matériel Series6, donc au moins sur le matériel Apple plus récent, ce n'est pas quelque chose dont vous devez vous inquiéter. Honnêtement, je ne suis pas sûr des autres GPU mobiles, car ce n'est pas mon domaine d'expertise. Vous devriez essayer de consulter leur documentation pour en être sûr.

Si vous décidez de faire des recherches Google sur ce problème, sachez que vous trouverez probablement des documents plus anciens qui parlent de récupérations de texture dépendantes sur du matériel de bureau plus ancien. Basique au début des shaders de pixels / fragments, le terme «extraction de texture dépendante» faisait référence à l'utilisation d'une adresse UV qui reposait sur une extraction de texture précédente. L'exemple classique était le rendu de carte d'environnement bump-mappé, où vous vouliez utiliser un vecteur de réflexion basé sur la carte normale afin d'échantillonner la carte d'environnement. Sur ce matériel plus ancien, il y avait des implications de performances majeures, et je pense qu'il n'était même pas pris en charge sur certains très anciens GPU. Avec les GPU modernes, le matériel et le shader ISA sont beaucoup plus généralisés, et donc la situation des performances est beaucoup plus compliquée.

MJP
la source
Soit dit en passant: j'ai vécu cela sur un iPad 3. Alors, c'est peut-être en fait spécifique au matériel.
Nero