Partager via


Conversion de types de données

Les sections suivantes décrivent comment Direct3D gère les conversions entre les types de données.

Terminologie du type de données

L’ensemble de termes suivant est ensuite utilisé pour caractériser différentes conversions de format.

Terme Définition
SNORM Entier normalisé signé, ce qui signifie que pour un nombre de complément n bits 2, la valeur maximale signifie 1,0f (par exemple, la valeur 5 bits 01111 est mappée à 1,0f) et la valeur minimale signifie -1.0f (par exemple, la valeur 5 bits 10000 correspond à -1.0f). En outre, le deuxième nombre minimal est mappé à -1.0f (par exemple, la valeur 5 bits 10001 correspond à -1.0f). Il existe donc deux représentations entières pour -1.0f. Il existe une représentation unique pour 0.0f et une représentation unique pour 1.0f. Cela entraîne un ensemble de représentations entières pour les valeurs à virgule flottante uniformément espacées dans la plage (-1.0f... 0,0f), ainsi qu’un ensemble complémentaire de représentations pour les nombres de la plage (0,0f... 1.0f)
UNORM Entier normalisé non signé, ce qui signifie que pour un nombre à n bits, tous les 0 signifient 0,0f, et tous les 1 signifient 1,0f. Une séquence de valeurs à virgule flottante uniformément espacées de 0,0f à 1,0f est représentée. par exemple, un UNORM 2 bits représente 0.0f, 1/3, 2/3 et 1.0f.
SINT Entier signé. entier de complément 2. par exemple, un SINT 3 bits représente les valeurs intégrales -4, -3, -2, -1, 0, 1, 2, 3.
UINT Entier non signé. par exemple, un UINT 3 bits représente les valeurs intégrales 0, 1, 2, 3, 4, 5, 6, 7.
FLOAT Valeur à virgule flottante dans l’une des représentations définies par Direct3D.
SRVB Similaire à UNORM, dans ce cas pour un nombre n bits, tous les 0 signifient 0,0f et tous les 1 signifie 1,0f. Toutefois, contrairement à UNORM, avec SRVB la séquence d’encodages entiers non signés entre tous les 0 à tous les 1 représentent une progression non linéaire dans l’interprétation à virgule flottante des nombres, entre 0,0f et 1,0f. À peu près, si cette progression non linéaire, SRVB, est affichée sous forme de séquence de couleurs, elle apparaît comme une rampe linéaire de niveaux de luminosité à un observateur « moyen », sous des conditions d’affichage « moyenne », sur un écran de qualité « moyenne ». Pour plus d’informations, reportez-vous à la norme de couleur SRVB, CEI 61996-2-1, à la CEI (Commission électrotechnique internationale).

 

Les termes ci-dessus sont souvent utilisés comme « Modificateurs de nom de format », où ils décrivent à la fois la façon dont les données sont disposées en mémoire et la conversion à effectuer dans le chemin d’accès de transport (éventuellement y compris le filtrage) de la mémoire vers ou à partir d’une unité de pipeline telle qu’un nuanceur.

Conversions de nombres à virgule flottante

Chaque fois qu’une conversion à virgule flottante entre différentes représentations se produit, y compris vers ou depuis des représentations sans virgule flottante, les règles suivantes s’appliquent.

Conversion d’une représentation de plage supérieure en représentation de plage inférieure

  • L’arrondi à zéro est utilisé lors de la conversion vers un autre format à virgule flottante. Si la cible est un format entier ou à virgule fixe, l’arrondi au nombre pair entier le plus proche est utilisé, sauf si la conversion est explicitement documentée comme utilisant un autre comportement d’arrondi, tel que l’arrondi au nombre le plus proche pour FLOAT to SNORM, FLOAT to UNORM ou FLOAT to SRVB. D’autres exceptions sont les instructions de nuanceur ftoi et ftou, qui utilisent l’arrondi à zéro. Enfin, les conversions de virgule flottante vers fixe utilisées par l’échantillonneur de texture et le rastériseur ont une tolérance spécifiée mesurée dans Unité à la dernière place à partir d’un idéal infiniment précis.
  • Pour des valeurs sources supérieures à la plage dynamique d’un format cible de plage inférieure (par exemple, une grande valeur flottante 32 bits est écrite dans un RenderTarget flottant 16 bits), le résultat est la plus grande valeur pouvant être représentée (correctement signée), NON compris l’infini signé (en raison de l’arrondi à zéro décrit ci-dessus).
  • NaN dans un format de plage supérieur sera converti en la représentation de NaN au format de plage inférieur si la représentation de NaN existe dans le format de plage inférieur. Si le format inférieur n’a pas de représentation de NaN, le résultat est 0.
  • INF dans un format de plage supérieur sera converti en INF au format de plage inférieur si disponible. Si le format inférieur n’a pas de représentation de INF, il est converti en la valeur maximale pouvant être représentée. Le signe est conservé s’il est disponible dans le format cible.
  • Denorm dans un format de plage plus élevé sera converti en la représentation de Denorm au format de plage inférieure si disponible dans le format de plage inférieure et si la conversion est possible, sinon le résultat est 0. Le bit de signe est conservé s’il est disponible au format cible.

Conversion d’une représentation de plage inférieure en représentation de plage supérieure

  • NaN dans un format de plage inférieur sera converti en la représentation de NaN au format de plage supérieur s’il est disponible dans le format de plage supérieur. Si le format de plage supérieur n’a pas de représentation de NaN, il est converti en 0.
  • INF dans un format de plage inférieur sera converti en la représentation de INF au format de plage supérieur s’il est disponible dans le format de plage supérieur. Si le format supérieur n’a pas de représentation de INF, il est converti en la valeur maximale pouvant être représentée (MAX_FLOAT dans ce format). Le signe est conservé s’il est disponible dans le format cible.
  • Denorm dans un format de plage inférieur sera converti en la représentation normalisée au format de plage supérieur si possible, ou en la représentation de Denorm au format de plage supérieur si la représentation de Denorm existe. En cas d’échec, si le format de plage supérieur n’a pas de représentation Denorm, il est converti en 0. Le signe est conservé s’il est disponible dans le format cible. Notez que les nombres flottants 32 bits sont comptabilisés sous la forme d’un format sans représentation Denorm (car les Denorms dans les opérations sur les nombres à virgule flottante 32 bits sont vidés pour signer la valeur 0 conservée).

Conversion d’entiers

Le tableau suivant décrit les conversions de différentes représentations décrites ci-dessus vers d’autres représentations. Seules les conversions qui se produisent réellement dans Direct3D sont affichées.

Avec des entiers, sauf indication contraire, toutes les conversions vers/depuis des représentations entières en représentations flottantes décrites ci-dessous sont effectuées exactement.

Type de données sources Type de données de destination Règle de conversion
SNORM FLOAT

Étant donné une valeur entière sur n bits représentant la plage signée [-1.0f à 1.0f], la conversion en virgule flottante est la suivante.

  • La valeur la plus négative correspond à -1.0f. par exemple, la valeur 5 bits 10000 correspond à -1.0f.
  • Chaque autre valeur est convertie en float (appelez-la c), puis result = c * (1.0f / (2⁽ⁿ⁻¹⁾-1)). Par exemple, la valeur 5 bits 10001 est convertie en -15.0f, puis divisée par 15.0f, ce qui génère -1.0f.
FLOAT SNORM

Étant donné un nombre à virgule flottante, la conversion en valeur entière à n bits représentant la plage signée [-1.0f à 1.0f] est la suivante.

  • Laissez c représenter la valeur de départ.
  • Si c est NaN, le résultat est 0.
  • Si c > 1.0f, y compris INF, il est limité à 1,0f.
  • Si c < -1.0f, y compris -INF, il est limité à -1.0f.
  • Convertir de l’échelle flottante à l’échelle entière : c = c * (2ⁿ⁻¹-1).
  • Convertissez en entier comme suit.
    • Si c >= 0, c = c + 0,5f, sinon, c = c - 0,5f.
    • Supprimez la fraction décimale et la valeur flottante restante (intégrale) est directement convertie en entier.

Cette conversion est autorisée à une tolérance de D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_Unit-Last-Place Unit-Last-Place (côté entier). Cela signifie qu’après la conversion d’une échelle float en échelle entière, toute valeur comprise dans D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit-Last-Place d’une valeur de format cible pouvant être représentée est autorisée à être mappée à cette valeur. L’exigence supplémentaire d’invertabilité des données garantit que la conversion n’est pas obtenue dans la plage et que toutes les valeurs de sortie sont accessibles. (Dans les constantes présentées ici, xx doit être remplacé par la version Direct3D, par exemple 10, 11 ou 12.)

UNORM FLOAT

La valeur n-bit de départ est convertie en valeur à virgule flottante (0.0f, 1.0f, 2.0f, etc.) puis divisée par (2ⁿ-1).

FLOAT UNORM

Laissez c représenter la valeur de départ.

  • Si c est NaN, le résultat est 0.
  • Si c > 1.0f, y compris INF, il est limité à 1,0f.
  • Si c < 0.0f, y compris -INF, il est limité à 0,0f.
  • Convertir de l’échelle flottante à l’échelle entière : c = c * (2ⁿ-1).
  • Convertir en entier.
    • c = c + 0,5f.
    • La fraction décimale est supprimée et la valeur flottante restante (intégrale) est convertie directement en entier.

Cette conversion est autorisée à une tolérance de D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit-Last-Place (côté entier). Cela signifie qu’après la conversion d’une échelle float en échelle entière, toute valeur comprise dans D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit-Last-Place d’une valeur de format cible pouvant être représentée est autorisée à être mappée à cette valeur. L’exigence supplémentaire d’invertabilité des données garantit que la conversion n’est pas obtenue dans la plage et que toutes les valeurs de sortie sont accessibles.

SRVB FLOAT

Voici la conversion SRVB idéale en FLOAT.

  • Prenez la valeur à n bits de départ, convertissez-la en valeur flottante (0.0f, 1.0f, 2.0f, etc.) ; appelez-la c.
  • c = c * (1.0f / (2ⁿ-1))
  • Si (c < = D3Dxx_SRGB_TO_FLOAT_THRESHOLD) puis : result = c / D3Dxx_SRGB_TO_FLOAT_DENOMINATOR_1, sinon : result = ((c + D3D xx_SRGB_TO_FLOAT_OFFSET)/D3Dxx_SRGB_TO_FLOAT_DENOMINATOR_2)D3Dxx_SRGB_TO_FLOAT_EXPONENT

Cette conversion est autorisée à une tolérance de D3Dxx_SRGB_TO_FLOAT_TOLERANCE_IN_ULP Unit-Last-Place (côté SRVB).

FLOAT SRVB

Voici la conversion FLOAT -> SRVB idéale.

En supposant que le composant de couleur SRVB cible a n bits :

  • Supposons que la valeur de départ soit c.
  • Si c est NaN, le résultat est 0.
  • Si c > 1.0f, y compris INF, est limité à 1,0f.
  • Si c < 0.0f, y compris -INF, il est limité à 0,0f.
  • Si (c <= D3Dxx_FLOAT_TO_SRGB_THRESHOLD) puis : c = D3Dxx_FLOAT_TO_SRGB_SCALE_1 * c, sinon : c = D3Dxx_FLOAT_TO_SRGB_SCALE_2 * c(D3Dxx_FLOAT_TO_SRGB_EXPONENT_NUMERATOR/D3Dxx_FLOAT_TO_SRGB_EXPONENT_DENOMINATOR) - D3Dxx_FLOAT_TO_SRGB_OFFSET
  • Convertir de l’échelle flottante à l’échelle entière : c = c * (2ⁿ-1).
  • Convertir en entier :
    • c = c + 0,5f.
    • La fraction décimale est supprimée et la valeur flottante restante (intégrale) est convertie directement en entier.

Cette conversion est autorisée à une tolérance de D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit-Last-Place (côté entier). Cela signifie qu’après la conversion d’une échelle float en échelle entière, toute valeur comprise dans D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit-Last-Place d’une valeur de format cible pouvant être représentée est autorisée à être mappée à cette valeur. L’exigence supplémentaire d’invertabilité des données garantit que la conversion n’est pas obtenue dans la plage et que toutes les valeurs de sortie sont accessibles.

SINT SINT avec plus de bits

Pour effectuer une conversion de SINT en SINT avec plus de bits, le bit le plus significatif (MSB) du numéro de départ est « sign-extended » vers les bits supplémentaires disponibles dans le format cible.

UINT SINT avec plus de bits

Pour effectuer une conversion de UINT en SINT avec plus de bits, le nombre est copié dans les bits les moins significatifs (LSB) du format cible et les MSB supplémentaires sont remplis avec 0.

SINT UINT avec plus de bits

Pour effectuer une conversion de SINT en UINT avec plus de bits : si elle est négative, la valeur est limitée à 0. Sinon, le nombre est copié dans les TSAG du format cible et les MSB supplémentaires sont remplis avec 0.

UINT UINT avec plus de bits

Pour convertir UINT en UINT avec plus de bits, le nombre est copié dans les TSAG du format cible et les MSB supplémentaires sont remplis avec 0.

SINT ou UINT SINT ou UINT avec des bits inférieurs ou égaux

Pour effectuer une conversion d’un SINT ou UINT en SINT ou UINT avec des bits inférieurs ou égaux (et/ou une modification de la signature), la valeur de départ est simplement limitée à la plage du format cible.

 

Conversion d’entier à virgule fixe

Les entiers à virgule fixe sont simplement des entiers d’une taille de quelques bits qui ont une virgule décimale implicite à un emplacement fixe.

Le type de données « entier » omniprésent est un cas spécial d’un entier à virgule fixe avec la décimale à la fin du nombre.

Les représentations numériques à virgule fixe sont caractérisées par : i.f, où i est le nombre de bits entiers et f est le nombre de bits fractionnaires. par exemple, 16,8 signifie 16 bits entiers suivis de 8 bits de fraction. La partie entière est stockée dans le complément de 2, au moins comme défini ici (bien qu’elle puisse également être définie pour les entiers non signés). La partie fractionnaire est stockée sous forme non signée. La partie fractionnaire représente toujours la fraction positive entre les deux valeurs intégrales les plus proches, en commençant par la plus négative.

Les opérations d’addition et de soustraction sur les nombres à points fixes sont effectuées simplement à l’aide d’une arithmétique d’entier standard, sans aucune considération pour laquelle les décimales implicites se trouvent. L’ajout de 1 à un nombre fixe de 16,8 signifie simplement ajouter 256, car la décimale est de 8 places à partir de la fin la moins significative du nombre. D’autres opérations telles que la multiplication peuvent être effectuées tout simplement à l’aide d’une arithmétique entière, à condition que l’effet sur la décimale fixe soit pris en compte. Par exemple, la multiplication de deux entiers de 16,8 à l’aide d’une multiplication d’entiers produit un résultat de 32,16.

Les représentations entières à virgule fixe sont utilisées de deux manières dans Direct3D.

  • Les positions de vertex post-clippées dans le rastériseur sont alignées sur un virgule fixe, pour répartir uniformément la précision dans la zone RenderTarget. De nombreuses opérations du rastériseur, par exemple l’élimination de face, se produisent sur des positions alignées à virgule fixe, tandis que d’autres opérations, telles que la configuration de l’interpolateur d’attribut, utilisent des positions qui ont été converties en virgule flottante à partir des positions alignées à virgule fixe.
  • Les coordonnées de texture pour les opérations d’échantillonnage sont alignées sur une virgule fixe (après avoir été mises à l’échelle par taille de texture), pour répartir uniformément la précision entre l’espace de texture, en choisissant les emplacements/pondérations des appuis de filtre. Les valeurs de poids sont reconverties en virgule flottante avant l’exécution de l’arithmétique de filtrage réelle.
Type de données sources Type de données de destination Règle de conversion
FLOAT Entier à virgule fixe

Voici la procédure générale permettant de convertir un nombre à virgule flottante n en un entier à virgule fixe i.f, où i est le nombre de bits entiers (signés) et f est le nombre de bits fractionnaires.

  • Compute FixedMin = -2⁽ⁱ⁻¹⁾
  • Compute FixedMax = 2⁽ⁱ⁻¹⁾ - 2(-f)
  • Si n est un naN, résultat = 0 ; si n est +Inf, result = FixedMax*2f ; if n is -Inf, result = FixedMin*2f
  • Si n >= FixedMax, result = Fixedmax*2f ; if n <= FixedMin, result = FixedMin*2f
  • Sinon, calculez n*2f et convertissez en entier.

Les implémentations sont autorisées D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP tolérance Unit-Last-Place dans le résultat entier, au lieu de la valeur infiniment précise n*2f après la dernière étape ci-dessus.

Entier à virgule fixe FLOAT

Supposons que la représentation à virgule fixe spécifique convertie en flottante ne contient pas plus de 24 bits d’informations au total, dont pas plus de 23 bits dans le composant fractionnaire. Supposons qu’un nombre à virgule fixe donné, fxp, soit au format i.f (bits d’entier i, fraction de bits f). La conversion en float est semblable au pseudocode suivant.

float result = (float)(fxp >> f) + // extract integer

((float)(fxp & (2f - 1)) / (2f)); // extract fraction

 

Annexes