Dans Unreal, quelles sont les différences entre le float de C ++ et FFloat32?

17

J'ai essayé d'apprendre certains aspects plus profonds de UE4 et en lisant de nombreux exemples de codes et également la base source du moteur, j'ai remarqué que parfois les gens (et le code source même) utilisent la floatprimitive C ++ standard , mais utilisent parfois l'implémentation personnalisée de UE4 FFloat32.

Ensuite, je suis devenu curieux: lors de la programmation d'un jeu avec Unreal, quelles sont les différences entre l'utilisation de ces 2 options et éventuellement quels sont les principaux cas où l'on devrait abandonner la primitive C ++ standard en faveur de l'implémentation du moteur?

Kim Shutter
la source
1
Je serais intéressé à lire les exemples que vous avez trouvés et qui utilisent réellement FFloat32.
@JoshPetrie Certains d'entre eux étaient hors ligne, un couple était en ligne. Dès que j'aurai du temps à la maison, je les chercherai à partager
Kim Shutter

Réponses:

17

float, est bien, une virgule flottante C ++. FFloat32est une structure qui représente un flotteur ainsi que (via une union) les champs de bits décomposés pour le signe, la mantisse et les parties exposantes de ce flotteur.

Vous ne devez généralement jamais utiliser FFloat32sauf lorsque:

  • vous utilisez une API qui attend un FFloat32(ce sont très rares) ou
  • vous devez faire une sorte de piratage de bits de bas niveau avec une valeur en virgule flottante (également assez rare de nos jours)

Ce n'est pas FFloat32est mauvais , en soi, il est juste que ça n'a pas vraiment vous offrir tout ce dont vous auriez besoin pour usage général flottant utilisation ponctuelle.

Il est moins courant qu'un ancien simple float, ce qui a un impact mineur sur la lisibilité (d'autres peuvent ne pas savoir immédiatement à quoi il sert en un coup d'œil). Il ne se convertit pas non plus implicitement en floatdonc vous taperez something.FloatValuebeaucoup, ce qui n'est pas non plus un gros problème, mais pourrait devenir fastidieux.

Enfin, son utilisation des unions et des champs de bits est non portable et définie par l'implémentation (voir ci-dessous). Ce n'est pas votre problème, c'est le travail d'Epic de s'assurer que le type est structuré de manière à ce qu'il soit utilisable pour toutes les implémentations prises en charge, mais c'est une source potentielle de bogues s'ils ne parviennent pas à résoudre un problème avec l'implémentation du type lorsqu'un nouveau compilateur version est publiée ou ajoutée à la liste des compilateurs pris en charge.

Donc, à moins que vous n'ayez besoin de jouer avec les bits individuels dans la représentation en virgule flottante, vous devriez probablement éviter FFloat32(son cousin FFloat16, peut avoir un peu plus d'utilité car il n'y a pas de type à virgule flottante C ++ 16 bits standard).

Autrefois, il était courant de manipuler des flotteurs via des représentations entières de leurs composants pour la " vitesse ". Les ordinateurs modernes évitent une grande partie de ce besoin pour de nombreuses plates-formes, et les diverses techniques de punition de type qui pourraient être utilisées pour faire ce genre de chose peuvent en fait nuire aux performances ou à l'exactitude en tout état de cause.

Il devrait être révélateur qu'une recherche dans le référentiel GitHub d'Unreal révèle très peu d'utilisations du FFloat32type. Tous sont dans la définition de FFloat32soi ou dans la définition de FFloat16.


Plus précisément, FFloat32fait deux choses que la norme C ++ appelle. Il:

  • vous permet d'agir comme si plus d'un membre du syndicat était actif à la fois; vous devez écrire sur les membres à virgule flottante et lire à partir de l'un des membres entiers (9.5.1, [class.union])
  • attend que l'allocation de champ de bits au sein de l'union corresponde à celle de l'allocation de bits d'une valeur à virgule flottante IEEE; cependant, l'allocation et l'alignement des membres du champ binaire au sein d'un type de classe est défini par l'implémentation (9.6.1, [class.bit])

la source
Unreal n'est pas écrit en C ++ standard, il est écrit pour les compilateurs particuliers pour lesquels il est écrit, donc tant qu'ils font la chose attendue, la norme n'est pas pertinente.
user253751
Je m'attendrais à ce que ces champs de bits soient assez portables, même en C / C ++ standard, car ils sont définis par une norme IEEE, et tout compilateur utilisant une disposition différente floatne recevrait pas de marque rouge conforme IEEE 754 (et des problèmes de compatibilité avec de nombreux logiciels existants ).
Dmitry Grigoryev
3
Le problème (pédant) est que l'ordre écrit de ces champs de bits peut correspondre à la norme IEEE, mais le compilateur C ++ peut les réorganiser ou les réaligner. Ce n'est qu'une note de bas de page mineure, car traiter de cela est le travail d'Epic; ils doivent surveiller chaque nouvelle version du compilateur pour vérifier que le type fonctionne correctement.
@JoshPetrie Point pris, merci pour la clarification.
Dmitry Grigoryev du
1
@JustinLardinois Mais FFloat32 contient un floatmembre dans l'union, donc s'il floatest en réalité plus grand que 32 bits, la valeur globale le FFloat32sera également puisque l'union doit être suffisamment grande pour contenir le plus grand membre. Dans les cas où les flottants sont plus grands que quatre octets, Epic devra également modifier les parties de champ de bits de l'union pour y remédier, sinon ils ne mapperont pas le flotteur complet.