Que fait réellement ddx (hlsl)?

17

Je suis un peu confus. La documentation officielle ( http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588(v=vs.85).aspx ) dit que ddx (entrée) est la dérivée partielle de l'entrée avec respect à la "coordonnée x de l'espace d'écran".

Mon calcul est très bien, mais comment peut-il savoir d'où vient l'entrée? Si je lui passais une fonction, très bien, je peux imaginer ce que ça ferait, mais la dérivée d'un nombre est toujours nulle ...?

Est-ce juste une mise à l'échelle? Comme, cela serait redimensionné à un dixième de sa taille à cette distance, donc il renvoie un dixième? Mais alors il n'a pas besoin d'une entrée ...

Quelqu'un peut-il expliquer rapidement ce qui se passe réellement?

Richard Rast
la source
2
ddxet ddyfaites de la magie que vous ne pouvez pas faire vous-même. Ils ont accès à des informations supplémentaires à partir du pipeline de pixellisation que vous ne pouvez pas acquérir à partir d'un pixel shader. Je ne sais pas exactement quelle formule ils utilisent; J'ai été amené à croire qu'ils utilisent une technique d'estimation, mais je n'en suis pas sûr.
Sean Middleditch du
C'est profondément bizarre, mais quand même. Que représente réellement ddx (5)? S'il indique .1, comment dois-je interpréter cela? Ou -6?
Richard Rast
1
ddx(5)est un peu inutile. Utilisez-le avec une valeur d'entrée, et cela vous donnera la dérivée de cette valeur par rapport aux pixels voisins dans un bloc. Encore une fois, je ne sais pas avec précision comment il calcule les valeurs, mais demander la dérivée d'une non-entrée peut bien être un comportement non défini et produire des ordures. Voir fgiesen.wordpress.com/2011/07/10/… pour plus d'informations que je ne peux fournir.
Sean Middleditch
Je ne suis pas sûr mais il se pourrait bien que le compilateur HLSL fasse en fait une différenciation symbolique complète de l'expression que vous passez au ddx / ddy. blogs.msdn.com/b/chuckw/archive/2011/03/08/… research.microsoft.com/pubs/146019/…
Ziriax
Qu'est ce que ça fait? La SEULE chose un peu raisonnable, évidemment.
MickLH

Réponses:

32

En interne, les GPU n'exécutent jamais une instance d'un pixel shader à la fois. Au niveau de granularité le plus fin, ils exécutent toujours 32 à 64 pixels en même temps en utilisant une architecture SIMD. Dans ce cadre, les pixels sont en outre organisés en 2x2 quads, de sorte que chaque groupe de 4 pixels consécutifs dans le vecteur SIMD correspond à un bloc de 2x2 pixels à l'écran.

Les dérivés sont calculés en prenant les différences entre les pixels d'un quadruple. Par exemple, ddxsoustraira les valeurs des pixels du côté gauche du quadruple des valeurs du côté droit et ddysoustraira les pixels du bas des pixels du haut. Les différences peuvent ensuite être renvoyées sous forme de dérivée aux quatre pixels du quadruple.

Étant donné que le pixel shader s'exécute dans SIMD, il est garanti que la valeur correspondante est dans le même registre en même temps pour tous les pixels du quad. Donc, quelle que soit l'expression ou la valeur que vous mettez ddxou ddy, elle sera évaluée dans les quatre pixels du quad, puis les valeurs des différents pixels soustraites comme décrit ci-dessus.

Donc, prendre la dérivée d'une valeur constante donnera zéro (comme vous vous attendez du calcul, non?) Parce que c'est la même valeur constante dans les quatre pixels.

Notez également qu'il existe des dérivés "grossiers" et "fins", ddx_coarse/ ddy_coarseet ddx_fine/ ddy_fine. Une explication de la distinction est donnée ici . Tout simplement ddx/ ddysont des alias pour les versions grossières.

BTW, la raison pour laquelle cette fonctionnalité existe est que les GPU doivent prendre en interne des dérivées des coordonnées de texture afin de faire une sélection mipmap et un filtrage anisotrope. Comme le matériel a quand même besoin de la capacité (vous pouvez utiliser n'importe quelle expression arbitraire pour les coordonnées de texture dans un shader), il était assez facile de l'exposer directement aux programmeurs de shader.

Nathan Reed
la source
+1; J'ai trouvé cela utile lors de l'application d'un effet de perturbation à une texture; les texcoords perturbés ont donné une certaine distorsion des couleurs, mais l'utilisation de tex2Dgrad avec des dérivés des texcoords originaux (non perturbés) a donné un résultat non déformé.
Maximus Minimus
D'accord, après réflexion, je pense avoir compris ma confusion. Dans mon esprit, ddxfonctionne comme toutes les autres fonctions d'un langage de programmation traditionnel; vous évaluez l'entrée, la transformez en un flottant ou autre, puis vous lui faites la fonction extérieure ( ddx). Mais c'est différent: il prend la chaîne d' entrée , l'évalue à plusieurs endroits, calcule une dérivée et rapporte le résultat. C'est à peu près ça?
Richard Rast
1
@RichardRast Right. Vous pouvez penser ddxà opérer sur l' expression que vous lui passez plutôt que sur la valeur .
Nathan Reed
Mais voyez, c'est assez bizarre que cela devrait être dans la documentation. Je ne peux penser à aucun autre moment dans ma vie de programmation où cela a été le cas.
Richard Rast
Nathan Reed a mentionné que les GPU utilisent ces fonctions pour la sélection de mipmap. Vous pouvez également les utiliser pour forcer le GPU à sélectionner le niveau mipmap souhaité ou pour empêcher les artefacts d'une sélection de niveau mip incorrecte. Le processus est décrit aux pages 163 et 164 du Shader X3.
JamesHoux