Sign in to follow this  
WiredCat

C++ cant find a match for 16 bit float and how to convert 32 bit float to 16 bit one

Recommended Posts

I need to make a floating point texture howevere device i program to uses only 16 bit floating point textures so i need somehow to put the data there.

problem is i cant find any specification that defines 16 bit float.

 

one guy told me that its named half well compiler says theres no such thing ;]

so basically i want to convert float * arr32bit; to something * arr16bit;

 

 

i think simple casting should do the work but who knows...

Share this post


Link to post
Share on other sites
device i program to

 

How about saying which device that is? Presumably there should be a library you use which defines types and functions which operate on those types. Since C++ itself doesn't know what a half-float is it must be implemented at the library level. For example, the NVidia Half-float extension for OpenGL.

Share this post


Link to post
Share on other sites

well i though c++ has it ;] 

 

im trying to do that on sony xperia j with android 4.1.2 it uses ogles 2

 

im digging through 

https://www.khronos.org/registry/gles/extensions/OES/OES_texture_float.txt

to find any corresponding definition of 16 bit float but cant find anythign usable.

 

 

 

 

now i am wondering if i could just create an empty texture of 16bit float and write 32 bit float to it with fragment shader so it will somehow put a 16 bit flaot pixel there

 

 

thanks

Edited by WiredCat

Share this post


Link to post
Share on other sites


now i am wondering if i could just create an empty texture of 16bit float and write 32 bit float to it with fragment shader so it will somehow put a 16 bit flaot pixel there

OpenGL converts texture data as you uploaded it (via [tt]glTexImage[/tt]).

 

If you specify an internal format that is 16-bit float, and a format and type matching your 32-bit float image data, the driver will perform the necessary conversion.

Share this post


Link to post
Share on other sites

C++ itself doesn't define a 16-bit float type as far as I know, though I can imagine there are platform-specific tool-chains that might support them (Lots of DSPs use 24bit floats and their compilers support them, presumably).

 

You see 16bit floats mostly in things like GLSL/HLSL shaders, or an API like OpenGL ES might provide a library type and conversions.

 

You can also do the conversion yourself by banging bits if your intent is to simply upload them to a device that handles them naively. I don't think you can just truncate the mantissa/exponent , but the math is straight forward if a bit exacting.

Share this post


Link to post
Share on other sites

I've been using this code written by Mike Acton from Insomniac to convert between float and *half*.

 

You might need to change inline to __inline or the extension from .c to .cpp when working with visual studio.

 

You can use a union to convert float to/from uint32_t:

 

 
union Helper
{
    float f;
    uint32_t u;
};
 
Helper helper;
helper.f = 5.0f;

uint16_t h = half_from_float(helper.u);
 
//and back
 
helper.u = half_to_float(h);
 
float y = helper.f;
 
 

Share this post


Link to post
Share on other sites
For large amounts of data, there are also SIMD intrinsics that can do this:

half -> float: _mm_cvtph_ps and _mm256_cvtph_ps
float -> half: _mm_cvtps_ph and _mm256_cvtps_ph
see https://software.intel.com/sites/landingpage/IntrinsicsGuide/

Oh, I just noticed you aren't doing this on a PC. But some ARM processors support similar conversion functions. See for example: https://gcc.gnu.org/onlinedocs/gcc/Half-Precision.html

Share this post


Link to post
Share on other sites

Just letting glTexImage do the conversion should be the easiest and most compatible way to do it, which could be important if you target android.

 

You don't know the combination of cpu and gpu the customer will have in their phone, and what float format they expect, so instead of handling all cases, just let the driver do it.

Edited by Olof Hedman

Share this post


Link to post
Share on other sites

I use a branchless table-driven implementation by Jeroen van der Zijp (http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf) which some time ago I wrapped into a class to make it as convenient as a regular float.

 

The conversions in both directions are two-liners, and the combined size of all of the lookup tables is less than 10K.

http://homepages.vodafone.co.nz/~tawa47a/Malc/Useful_Classes.htm

It's probably nearly functionally identical to Aressera's

 

Edit: Bah, Jeroen van der Zijp's original link is now not working for me.

 

Edit2: Christian Rau has since produced an even more complete version here, which is clearly also based on Jeroen's work, but is more complete than mine, with template meta-programming to avoid unnecessary conversions and such:

http://half.sourceforge.net/

Probably best just to use that one.

Edited by iMalc

Share this post


Link to post
Share on other sites

i just wonder how opengl can know that i input float i know that i can deifine that i want to convert my input to half floats but how do opengl knows that i put there floats not bytes or whatever that is and iterates through array properly

Share this post


Link to post
Share on other sites

i just wonder how opengl can know that i input float i know that i can deifine that i want to convert my input to half floats but how do opengl knows that i put there floats not bytes or whatever that is and iterates through array properly

 

It knows because you tell it, through the "type" argument to glTexImage. (make sure you don't lie to it ;) )

Edited by Olof Hedman

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this