In Unreal, quali sono le differenze tra float di C ++ e FFloat32?


17

Ho cercato di imparare alcuni aspetti più profondi di UE4 e durante la lettura di molti codici di esempi e anche la base di origine del motore, ho notato che a volte le persone (e il codice stesso) usano la floatprimitiva standard C ++ , ma a volte usano l'implementazione personalizzata di UE4 FFloat32.

Poi mi sono incuriosito: durante la programmazione di un gioco con Unreal, quali sono le differenze tra l'utilizzo di quelle 2 opzioni e forse quali sono i casi principali in cui si dovrebbe abbandonare la primitiva C ++ standard a favore dell'implementazione del motore?


1
Sarei interessato a leggere gli esempi che hai trovato che effettivamente utilizzano FFloat32.

@JoshPetrie Alcuni di loro erano off-line, un paio erano online. Non appena avrò tempo a casa, li cercherò di condividere
Kim Shutter il

Risposte:


17

float, va bene, un virgola mobile C ++. FFloat32è una struttura che rappresenta un galleggiante e (tramite un'unione) i bitfield decomposti per il segno, la mantissa e le parti esponenti di quel galleggiante.

Generalmente non dovresti mai usare FFloat32tranne quando:

  • stai usando alcune API che FFloat32prevedono un (sono molto rare) o
  • devi fare qualche tipo di hacking di bit di basso livello con un valore in virgola mobile (anche abbastanza raro in questi giorni)

Non FFloat32è male , di per sé, è solo che non ti offre davvero tutto ciò di cui potresti aver bisogno per l'utilizzo in virgola mobile per scopi generici.

È meno comune di un semplice vecchio float, che ha un impatto di leggibilità minore (altri potrebbero non sapere immediatamente a cosa servono a colpo d'occhio). Inoltre, non si converte in floatmodo implicito, quindi digiterai something.FloatValuemolto, il che non è un grosso problema, ma potrebbe diventare noioso.

Infine, il suo utilizzo di sindacati e bitfield è non portatile e definito dall'implementazione (vedi sotto). Questo non è un tuo problema, è compito di Epic assicurarsi che il tipo sia strutturato in modo che sia utilizzabile per tutte le implementazioni supportate, ma è una potenziale fonte di bug se non riescono a rilevare un problema con l'implementazione del tipo quando un nuovo compilatore la versione viene rilasciata o aggiunta all'elenco dei compilatori supportati.

Quindi, a meno che tu non abbia bisogno di giocare con i singoli bit nella rappresentazione in virgola mobile, probabilmente dovresti semplicemente evitarlo FFloat32(suo cugino FFloat16, potrebbe avere un po 'più di utilità in quanto non esiste un tipo a virgola mobile C ++ standard a 16 bit).

Era comune manipolare i float tramite rappresentazioni intere dei loro componenti per " velocità ". I computer moderni ovviano a gran parte del bisogno di molte piattaforme e le varie tecniche di punzonatura che potrebbero essere utilizzate per fare questo genere di cose possono in realtà essere dannose per le prestazioni o la correttezza in ogni caso.

Dovrebbe dire che una ricerca nel repository GitHub di Unreal rivela pochissimi usi del FFloat32tipo. Tutti sono nella definizione di FFloat32se stesso o nella definizione di FFloat16.


In particolare, FFloat32fa due cose che lo standard C ++ chiama. It:

  • ti consente di agire come se più di un membro del sindacato è attivo contemporaneamente; ci si aspetta che scriviate ai membri in virgola mobile e leggiate da uno dei membri interi (9.5.1, [class.union])
  • si aspetta che l'allocazione dei bitfield all'interno dell'Unione corrisponda a quella dell'allocazione dei bit di un valore IEEE in virgola mobile; tuttavia, l'allocazione e l'allineamento dei membri bitfield all'interno di un tipo di classe sono definiti dall'implementazione (9.6.1, [class.bit])

Unreal non è scritto in C ++ standard, è scritto per i compilatori particolari per cui è scritto, quindi fintanto che fanno la cosa prevista lo standard è irrilevante.
user253751

Mi aspetto che quei bitfield siano abbastanza portatili anche in C / C ++ standard, poiché sono definiti da uno standard IEEE, e qualsiasi compilatore che utilizza un layout diverso nonfloat otterrebbe un segno rosso conforme a IEEE 754 (e problemi di compatibilità con molti software esistenti ).
Dmitry Grigoryev,

3
Il problema (pedante) è che l'ordine scritto di quei campi di bit potrebbe corrispondere allo standard IEEE, ma il compilatore C ++ potrebbe riordinarli o riallinearli. Questa è solo una nota a piè di pagina, sebbene trattarsi di questo sia il lavoro di Epic; dovrebbero monitorare ogni nuova versione del compilatore per verificare che il tipo funzioni correttamente.

@JoshPetrie Punto preso, grazie per il chiarimento.
Dmitry Grigoryev,

1
@JustinLardinois Ma FFloat32 contiene un floatmembro nell'unione, quindi se in floatrealtà è maggiore di 32 bit, lo FFloat32sarà anche il totale poiché l'unione deve essere abbastanza grande da contenere il membro più grande. Nei casi in cui i float siano più grandi di quattro byte, Epic avrà dovuto modificare anche le parti bitfield dell'unione per risolverlo, altrimenti non mapperanno il float completo.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.