J'essaie de comprendre les fonctions dFdx et dFdy dans GLSL.
Je comprends ce qui suit:
Je ne comprends pas à quoi le taux de changement fait référence. Est-ce le taux de changement des coordonnées des fragments?
Serait-il possible que vous puissiez trouver le taux de variation d'un variable arbitraire entre deux invocations du fragment shader? Les invocations de shader "lisent-elles" des variables des invocations voisines? Pour un exemple (simpliste):
// invokation for fragment 1
float x = 1.0;
float d = dFdx(x);
// invokation for fragment next to fragment 1 along the x axis.
float x = 2.0;
float d = dFdx(x);
Serait-il respectivement -1,0 et 1,0?
Pour comprendre le fonctionnement de ces instructions, il est utile de comprendre l'architecture d'exécution de base des GPU et la façon dont les programmes de fragments sont mappés à cette architecture.
Les GPU exécutent un tas de threads en "étape de verrouillage" sur le même programme, chaque thread ayant son propre ensemble de registres. Il récupère donc une instruction, puis exécute cette instruction N fois, une fois pour chaque thread en cours d'exécution. Pour gérer les branches conditionnelles et autres, ils ont également un "masque actif" pour le groupe de threads en cours d'exécution. Les threads qui ne sont pas actifs dans le masque ne s'exécutent pas réellement (donc leurs registres ne changent pas). Chaque fois qu'il existe une branche conditionnelle ou une jointure (cible de branche), le masque de thread est modifié de manière appropriée.
Désormais, lorsqu'un programme de fragments est exécuté, les fragments à exécuter sont organisés en "quads" - 2x2 carrés de 4 pixels qui s'exécutent toujours ensemble dans un groupe de threads. Chaque thread du groupe connaît sa propre coordonnée de pixels et peut facilement trouver la coordonnée du pixel adjacent dans le quad en retournant le bit le plus bas de la coordonnée x (ou y).
Lorsque le GPU exécute une instruction DDX ou DDY, ce qui se produit est qu'il jette un œil aux registres du thread pour le pixel adjacent et effectue une soustraction avec la valeur du pixel actuel - soustrayant la valeur de la coordonnée la plus élevée (bit le plus bas 1 ) à partir du plus bas (bit le plus bas 0).
Cela a des implications si vous utilisez dFdx
ou dFdy
dans une branche conditionnelle - si l'un des threads d'un quad est actif tandis que l'autre ne l'est pas, le GPU continuera à regarder le registre de le thread inactif, qui pourrait avoir une ancienne valeur, donc le résultat pourrait être n'importe quoi.