Règles à virgule flottante
Direct3D prend en charge plusieurs représentations à virgule flottante. Tous les calculs à virgule flottante fonctionnent sous un sous-ensemble défini des règles ieee 754 32 bits à virgule flottante simple précision.
Règles à virgule flottante 32 bits
Il existe deux ensembles de règles : celles qui sont conformes à IEEE-754 et celles qui s’écartent de la norme.
Règles IEEE-754 respectées
Certaines de ces règles sont une option unique où IEEE-754 offre des choix.
Diviser par 0 produit +/- INF, à l’exception de 0/0, ce qui entraîne naN.
log of (+/-) 0 produit -INF.
le journal d’une valeur négative (autre que -0) produit NaN.
La racine carrée réciproque (rsq) ou la racine carrée (sqrt) d’un nombre négatif produit naN.
L’exception est -0 ; sqrt(-0) produit -0, et rsq(-0) produit -INF.
INF - INF = NaN
(+/-) INF / (+/-)INF = NaN
(+/-) INF * 0 = NaN
NaN (any OP) any-value = NaN
Les comparaisons EQ, GT, GE, LT et LE, lorsque l’un ou l’autre opérandes est NaN retourne FALSE.
Les comparaisons ignorent le signe 0 (donc +0 est égal à -0).
La comparaison NE, lorsque l’opérande ou les deux opérandes est NaN retourne TRUE.
Les comparaisons de n’importe quelle valeur non NaN par rapport à +/- INF retournent le résultat correct.
Écarts ou exigences supplémentaires des règles IEEE-754
IEEE-754 nécessite des opérations à virgule flottante pour produire un résultat qui est la valeur la plus représentée à un résultat infiniment précis, appelé round-to-near-even.
Direct3D 11 et up définissent la même exigence que IEEE-754 : les opérations à virgule flottante 32 bits produisent un résultat qui se trouve dans 0,5 unité-last-place (ULP) du résultat infiniment précis. Cela signifie que, par exemple, le matériel est autorisé à tronquer les résultats en 32 bits plutôt que d’effectuer des opérations round-to-near-even, car cela entraînerait une erreur d’au plus 0,5 ULP. Cette règle s’applique uniquement à l’ajout, à la soustraction et à la multiplication.
Les versions antérieures de Direct3D définissent une exigence plus faible que IEEE-754 : les opérations à virgule flottante 32 bits produisent un résultat qui se trouve dans une unité de dernière place (1 ULP) du résultat infiniment précis. Cela signifie que, par exemple, le matériel est autorisé à tronquer les résultats en 32 bits plutôt que d’effectuer des opérations round-to-near-even, car cela entraînerait une erreur d’au plus un ULP.
Il n’existe aucune prise en charge des exceptions à virgule flottante, des bits d’état ou des pièges.
Les dénorms sont vidés pour signer zéro sur l’entrée et la sortie de toute opération mathématique à virgule flottante. Les exceptions sont effectuées pour toute opération d’E/S ou de déplacement de données qui ne manipule pas les données.
Les états qui contiennent des valeurs à virgule flottante, telles que Viewport MinDepth/MaxDepth ou BorderColor, peuvent être fournis en tant que valeurs dénormées et peuvent ou ne pas être vidés avant que le matériel les utilise.
Les dénorms de vidage min ou max des opérations à des fins de comparaison, mais le résultat peut ou non être dénormé.
L’entrée NaN d’une opération produit toujours NaN en sortie. Mais le modèle de bits exact du NaN n’est pas nécessaire pour rester le même (sauf si l’opération est une instruction de déplacement brut , qui ne modifie pas les données.)
Les opérations minimales ou maximales pour lesquelles un seul opérande est NaN renvoient l’autre opérande en conséquence (contrairement aux règles de comparaison que nous avons examinées précédemment). Il s’agit d’une règle IEEE 754R.
La spécification IEEE-754R pour les opérations min et max à virgule flottante indique que si l’une des entrées à min ou max est une valeur QNaN silencieuse, le résultat de l’opération est l’autre paramètre. Par exemple :
min(x,QNaN) == min(QNaN,x) == x (same for max)
Une révision de la spécification IEEE-754R a adopté un comportement différent pour min et max lorsqu’une entrée est une valeur SNaN « signaling » par rapport à une valeur QNaN :
min(x,SNaN) == min(SNaN,x) == QNaN (same for max)
En règle générale, Direct3D suit les normes pour l’arithmétique : IEEE-754 et IEEE-754R. Mais dans ce cas, nous avons un écart.
Les règles arithmétiques dans Direct3D 10 et versions ultérieures ne font aucune distinction entre les valeurs NaN silencieuses et signalant (QNaN et SNaN). Toutes les valeurs NaN sont gérées de la même façon. Dans le cas de min et de max, le comportement Direct3D pour n’importe quelle valeur NaN est semblable à la façon dont QNaN est géré dans la définition IEEE-754R. (Pour l’exhaustivité : si les deux entrées sont NaN, une valeur NaN est retournée.)
Une autre règle IEEE 754R est que min(-0,+0) == min(+0,-0) == -0 et max(-0,+0) == max(+0,-0) == +0, qui respecte le signe, contrairement aux règles de comparaison pour zéro signé (comme nous l’avons vu précédemment). Direct3D recommande le comportement IEEE 754R ici, mais ne l’applique pas ; il est possible que le résultat de la comparaison des zéros dépende de l’ordre des paramètres, à l’aide d’une comparaison qui ignore les signes.
x*1.0f entraîne toujours x (à l’exception du dénorm vidé).
x/1.0f entraîne toujours x (à l’exception du dénorm vidé).
x +/- 0.0f entraîne toujours x (à l’exception du dénorm vidé). Mais -0 + 0 = +0.
Les opérations fusionnées (telles que mad, dp3) produisent des résultats qui ne sont pas moins précis que le pire ordre de série possible d’évaluation de l’expansion non fusionnée de l’opération. La définition du pire ordre possible, à des fins de tolérance, n’est pas une définition fixe pour une opération fusionnée donnée ; elle dépend des valeurs particulières des entrées. Les étapes individuelles de l’expansion non fusionnée sont toutes autorisées 1 tolérance ULP (ou pour toutes les instructions Direct3D appelle avec une tolérance lax supérieure à 1 ULP, plus la tolérance lax est autorisée).
Les opérations fusionnées respectent les mêmes règles NaN que les opérations non fusionnées.
sqrt et rcp ont une tolérance ULP 1. Les instructions réciproques et réciproques de racine carrée, rcp et rsq, ont leurs propres exigences de précision détendues distinctes.
Multipliez et divisez chaque opération au niveau de précision à virgule flottante 32 bits (précision à 0,5 ULP pour multiplication, 1,0 ULP pour réciproque). Si x/y est implémenté directement, les résultats doivent être d’une précision supérieure ou égale à une méthode en deux étapes.
Règles à virgule flottante 64 bits (double précision)
Les pilotes matériels et d’affichage prennent éventuellement en charge le virgule flottante double précision. Pour indiquer la prise en charge, lorsque vous appelez ID3D11Device ::CheckFeatureSupport avec D3D11_FEATURE_DOUBLES, le pilote définit DoublePrecisionFloatShaderOps de D3D11_FEATURE_DATA_DOUBLES sur TRUE. Le pilote et le matériel doivent ensuite prendre en charge toutes les instructions à virgule flottante double précision.
Les instructions de double précision suivent les exigences de comportement IEEE 754R.
La prise en charge de la génération de valeurs dénormalisées est requise pour les données de double précision (aucun comportement de vidage à zéro). De même, les instructions ne lisent pas les données dénormalisées en tant que zéro signé, elles respectent la valeur denorm.
Règles à virgule flottante 16 bits
Direct3D prend également en charge les représentations 16 bits de nombres à virgule flottante.
Format :
- 1 bits de signe (s) à la position du bit MSB
- 5 bits d’exposant biaisé (e)
- 10 bits de fraction (f), avec un bit masqué supplémentaire
Une valeur float16 (v) suit les règles suivantes :
- si e == 31 et f != 0, alors v est NaN indépendamment de s
- si e == 31 et f == 0, puis v = (-1)s*infinity (infini signé)
- si e est compris entre 0 et 31, alors v = (-1)s*2(e-15)*(1.f)
- si e == 0 et f != 0, puis v = (-1)s*2(e-14)*(0.f) (nombres dénormalisés)
- si e == 0 et f == 0, puis v = (-1)s*0 (zéro signé)
Les règles à virgule flottante 32 bits sont également conservées pour les nombres à virgule flottante 16 bits, ajustées pour la disposition de bits décrite précédemment. Des exceptions s’appliquent :
- Précision : les opérations non fusionnées sur des nombres à virgule flottante 16 bits produisent un résultat qui est la valeur la plus représentée à un résultat infiniment précis (arrondi au plus proche même, par IEEE-754, appliqué à des valeurs 16 bits). Les règles à virgule flottante 32 bits respectent la tolérance 1 ULP, les règles à virgule flottante 16 bits respectent 0,5 ULP pour les opérations non fusionnées et 0,6 ULP pour les opérations fusionnées.
- Les nombres à virgule flottante 16 bits conservent les dénorms.
Règles à virgule flottante 11 bits et 10 bits
Direct3D prend également en charge les formats à virgule flottante 11 bits et 10 bits.
Format :
- Aucun bit de signe
- 5 bits d’exposant biaisé (e)
- 6 bits de fraction (f) pour un format 11 bits, 5 bits de fraction (f) pour un format 10 bits, avec un bit masqué supplémentaire dans les deux cas.
Une valeur float11/float10 (v) suit les règles suivantes :
- si e == 31 et f != 0, alors v est NaN
- si e == 31 et f == 0, puis v = +infini
- si e est compris entre 0 et 31, alors v = 2(e-15)*(1.f)
- si e == 0 et f != 0, puis v = *2(e-14)*(0.f) (nombres dénormalisés)
- si e == 0 et f == 0, puis v = 0 (zéro)
Les règles à virgule flottante 32 bits sont également conservées pour les nombres à virgule flottante 11 bits et 10 bits, ajustés pour la disposition de bits décrite précédemment. Les exceptions incluent :
- Précision : les règles à virgule flottante 32 bits respectent 0,5 ULP.
- Les nombres à virgule flottante 10/11 bits conservent les dénorms.
- Toute opération qui entraînerait un nombre inférieur à zéro est limitée à zéro.
Rubriques connexes