En Unreal, ¿cuáles son las diferencias entre el flotador de C ++ y FFloat32?

17

He estado tratando de aprender algunos aspectos más profundos de UE4 y mientras leía muchos códigos de ejemplos y también la base del motor, noté que a veces las personas (y el código fuente) usan la floatprimitiva C ++ estándar , pero a veces usan la implementación personalizada de UE4 FFloat32.

Luego tuve curiosidad: cuando programo un juego con Unreal, ¿cuáles son las diferencias entre el uso de esas 2 opciones y, posiblemente, cuáles son los principales casos en los que uno debería abandonar la primitiva C ++ estándar a favor de la implementación del motor?

Kim Shutter
fuente
1
Me interesaría leer los ejemplos que has encontrado que realmente utilizas FFloat32.
@JoshPetrie Algunos de ellos estaban fuera de línea, una pareja estaba en línea. Tan pronto como tenga tiempo en casa, los buscaré para compartir
Kim Shutter

Respuestas:

17

float, está bien, un punto flotante C ++. FFloat32es una estructura que representa un flotador, así como (a través de una unión) los campos de bits descompuestos para las partes de signo, mantisa y exponente de ese flotador.

Por lo general, nunca debe usar, FFloat32excepto cuando:

  • está utilizando alguna API que espera un FFloat32(estos son muy raros) o
  • necesita hacer algún tipo de piratería de bajo nivel con un valor de coma flotante (también bastante raro en estos días)

No es que FFloat32sea malo , per se, es que realmente no le ofrece nada que necesite para el uso de punto flotante de uso general.

Es menos común que un viejo simple float, que tiene un impacto de legibilidad menor (otros pueden no saber de inmediato para qué sirve de un vistazo). Tampoco se convierte implícitamente, por floatlo que escribirás something.FloatValuemucho, lo que tampoco es un gran problema, pero podría ser tedioso.

Finalmente, su uso de uniones y campos de bits no es portátil y está definido por la implementación (ver más abajo). Este no es su problema, es el trabajo de Epic asegurarse de que el tipo esté estructurado de modo que sea utilizable para todas las implementaciones compatibles, pero es una fuente potencial de errores si no detectan un problema con la implementación del tipo cuando un nuevo compilador La versión se publica o se agrega a la lista de compiladores compatibles.

Entonces, a menos que tenga la necesidad de jugar con los bits individuales en la representación de coma flotante, probablemente debería evitarlo FFloat32(su primo FFloat16puede tener un poco más de utilidad ya que no hay un tipo de coma flotante C ++ estándar de 16 bits).

Solía ​​ser común manipular flotadores a través de representaciones enteras de sus componentes para " velocidad ". Las computadoras modernas eliminan gran parte de esa necesidad de muchas plataformas, y las diversas técnicas de tipografía que podrían usarse para hacer este tipo de cosas pueden ser realmente perjudiciales para el rendimiento o la corrección en cualquier caso.

Debería ser revelador que una búsqueda en el repositorio GitHub de Unreal revela muy pocos usos del FFloat32tipo. Todos ellos están en la definición de FFloat32sí mismos o en la definición de FFloat16.


Específicamente, FFloat32hace dos cosas que llama el estándar C ++. Eso:

  • le permite actuar como si más de un miembro del sindicato estuviera activo al mismo tiempo; se espera que escriba en los miembros de coma flotante y lea de uno de los miembros enteros (9.5.1, [class.union])
  • espera que la asignación de campo de bits dentro de la unión coincida con la asignación de bits de un valor de coma flotante IEEE; sin embargo, la asignación y alineación de los miembros del campo de bits dentro de un tipo de clase está definida por la implementación (9.6.1, [class.bit])

fuente
Unreal no está escrito en C ++ estándar, está escrito para los compiladores particulares para los que está escrito, por lo tanto, siempre que hagan lo esperado, el estándar es irrelevante.
user253751
Esperaría que esos campos de bits sean bastante portátiles incluso en C / C ++ estándar, ya que están definidos por un estándar IEEE, y cualquier compilador que use un diseño diferente nofloat obtendría una marca roja compatible con IEEE 754 (y problemas de compatibilidad con muchos programas existentes) )
Dmitry Grigoryev
3
El problema (pedante) es que el orden escrito de esos campos de bits puede coincidir con el estándar IEEE, pero el compilador de C ++ puede reordenarlos o realinearlos. Sin embargo, esta es solo una pequeña nota al pie de página ya que tratar con eso es el trabajo de Epic; deben monitorear cada nueva versión del compilador para verificar que el tipo funcione correctamente.
@JoshPetrie Punto tomado, gracias por la aclaración.
Dmitry Grigoryev
1
@JustinLardinois Pero FFloat32 contiene un floatmiembro en el sindicato, por lo que si en floatrealidad es mayor que 32 bits, el total también FFloat32lo será, ya que el sindicato debe ser lo suficientemente grande como para contener al miembro más grande. En los casos en que los flotantes sean mayores de cuatro bytes, Epic tendrá que modificar también las partes de campo de bits de la unión para abordar eso, de lo contrario no asignarán el flotante completo.