mirror of
https://github.com/KhronosGroup/OpenCL-CTS.git
synced 2026-03-19 06:09:01 +00:00
Use float<->half conversion routines from the OpenCL headers (#884)
* Use float<->half conversion routines from the OpenCL headers Fixes #870 Signed-off-by: Kevin Petit <kevin.petit@arm.com> * Use cl_half_from_double * Fix windows build errors * Fix more build errors * Code formatting * Remove TEST class
This commit is contained in:
@@ -14,11 +14,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
#include "helpers.h"
|
||||
#include "../harness/imageHelpers.h"
|
||||
|
||||
// convert_float_to_half and convert_half_to_float may be found in test_conformance/images/image_helpers.cpp
|
||||
cl_ushort convert_float_to_half( cl_float f );
|
||||
cl_float convert_half_to_float( cl_ushort h );
|
||||
#include "harness/imageHelpers.h"
|
||||
|
||||
#if defined( __APPLE__ )
|
||||
#include <OpenGL/glu.h>
|
||||
|
||||
@@ -961,49 +961,6 @@ const char *GetGLFormatName( GLenum format )
|
||||
}
|
||||
}
|
||||
|
||||
cl_ushort float2half_rte( float f )
|
||||
{
|
||||
union{ float f; cl_uint u; } u = {f};
|
||||
cl_uint sign = (u.u >> 16) & 0x8000;
|
||||
float x = fabsf(f);
|
||||
|
||||
//Nan
|
||||
if( x != x )
|
||||
{
|
||||
u.u >>= (24-11);
|
||||
u.u &= 0x7fff;
|
||||
u.u |= 0x0200; //silence the NaN
|
||||
return u.u | sign;
|
||||
}
|
||||
|
||||
// overflow
|
||||
if( x >= MAKE_HEX_FLOAT(0x1.ffep15f, 0x1ffeL, 3) )
|
||||
return 0x7c00 | sign;
|
||||
|
||||
// underflow
|
||||
if( x <= MAKE_HEX_FLOAT(0x1.0p-25f, 0x1L, -25) )
|
||||
return sign; // The halfway case can return 0x0001 or 0. 0 is even.
|
||||
|
||||
// very small
|
||||
if( x < MAKE_HEX_FLOAT(0x1.8p-24f, 0x18L, -28) )
|
||||
return sign | 1;
|
||||
|
||||
// half denormal
|
||||
if( x < MAKE_HEX_FLOAT(0x1.0p-14f, 0x1L, -14) )
|
||||
{
|
||||
u.f = x * MAKE_HEX_FLOAT(0x1.0p-125f, 0x1L, -125);
|
||||
return sign | u.u;
|
||||
}
|
||||
|
||||
u.f *= MAKE_HEX_FLOAT(0x1.0p13f, 0x1L, 13);
|
||||
u.u &= 0x7f800000;
|
||||
x += u.f;
|
||||
u.f = x - u.f;
|
||||
u.f *= MAKE_HEX_FLOAT(0x1.0p-112f, 0x1L, -112);
|
||||
|
||||
return (u.u >> (24-11)) | sign;
|
||||
}
|
||||
|
||||
void* CreateRandomData( ExplicitType type, size_t count, MTdata d )
|
||||
{
|
||||
switch(type)
|
||||
@@ -1100,7 +1057,8 @@ void* CreateRandomData( ExplicitType type, size_t count, MTdata d )
|
||||
|
||||
for( size_t i = 0; i < count; i++ )
|
||||
{
|
||||
p[ i ] = float2half_rte(get_random_float( 0.f, 1.f, d ));
|
||||
p[i] = cl_half_from_float(get_random_float(0.f, 1.f, d),
|
||||
CL_HALF_RTE);
|
||||
}
|
||||
|
||||
return (void*)p;
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
#include "parseParameters.h"
|
||||
|
||||
#include <CL/cl_half.h>
|
||||
|
||||
const char *IGetErrorString( int clErrorCode )
|
||||
{
|
||||
switch( clErrorCode )
|
||||
@@ -287,7 +289,6 @@ const char *GetDataVectorString( void *dataBuffer, size_t typeSize, size_t vecSi
|
||||
#endif
|
||||
|
||||
static float Ulp_Error_Half_Float( float test, double reference );
|
||||
static inline float half2float( cl_ushort half );
|
||||
|
||||
// taken from math tests
|
||||
#define HALF_MIN_EXP -13
|
||||
@@ -334,49 +335,9 @@ static float Ulp_Error_Half_Float( float test, double reference )
|
||||
return (float) scalbn( testVal - reference, ulp_exp );
|
||||
}
|
||||
|
||||
// Taken from vLoadHalf test
|
||||
static inline float half2float( cl_ushort us )
|
||||
{
|
||||
uint32_t u = us;
|
||||
uint32_t sign = (u << 16) & 0x80000000;
|
||||
int32_t exponent = (u & 0x7c00) >> 10;
|
||||
uint32_t mantissa = (u & 0x03ff) << 13;
|
||||
union{ unsigned int u; float f;}uu;
|
||||
|
||||
if( exponent == 0 )
|
||||
{
|
||||
if( mantissa == 0 )
|
||||
return sign ? -0.0f : 0.0f;
|
||||
|
||||
int shift = __builtin_clz( mantissa ) - 8;
|
||||
exponent -= shift-1;
|
||||
mantissa <<= shift;
|
||||
mantissa &= 0x007fffff;
|
||||
}
|
||||
else
|
||||
if( exponent == 31)
|
||||
{
|
||||
uu.u = mantissa | sign;
|
||||
if( mantissa )
|
||||
uu.u |= 0x7fc00000;
|
||||
else
|
||||
uu.u |= 0x7f800000;
|
||||
|
||||
return uu.f;
|
||||
}
|
||||
|
||||
exponent += 127 - 15;
|
||||
exponent <<= 23;
|
||||
|
||||
exponent |= mantissa;
|
||||
uu.u = exponent | sign;
|
||||
|
||||
return uu.f;
|
||||
}
|
||||
|
||||
float Ulp_Error_Half( cl_ushort test, float reference )
|
||||
{
|
||||
return Ulp_Error_Half_Float( half2float(test), reference );
|
||||
return Ulp_Error_Half_Float(cl_half_to_float(test), reference);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -30,9 +30,6 @@
|
||||
|
||||
RoundingMode gFloatToHalfRoundingMode = kDefaultRoundingMode;
|
||||
|
||||
static cl_ushort float2half_rte( float f );
|
||||
static cl_ushort float2half_rtz( float f );
|
||||
|
||||
cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT;
|
||||
bool gTestRounding = false;
|
||||
double
|
||||
@@ -911,72 +908,12 @@ int get_format_min_int( cl_image_format *format )
|
||||
}
|
||||
}
|
||||
|
||||
float convert_half_to_float( unsigned short halfValue )
|
||||
{
|
||||
// We have to take care of a few special cases, but in general, we just extract
|
||||
// the same components from the half that exist in the float and re-stuff them
|
||||
// For a description of the actual half format, see http://en.wikipedia.org/wiki/Half_precision
|
||||
// Note: we store these in 32-bit ints to make the bit manipulations easier later
|
||||
int sign = ( halfValue >> 15 ) & 0x0001;
|
||||
int exponent = ( halfValue >> 10 ) & 0x001f;
|
||||
int mantissa = ( halfValue ) & 0x03ff;
|
||||
|
||||
// Note: we use a union here to be able to access the bits of a float directly
|
||||
union
|
||||
{
|
||||
unsigned int bits;
|
||||
float floatValue;
|
||||
} outFloat;
|
||||
|
||||
// Special cases first
|
||||
if( exponent == 0 )
|
||||
{
|
||||
if( mantissa == 0 )
|
||||
{
|
||||
// If both exponent and mantissa are 0, the number is +/- 0
|
||||
outFloat.bits = sign << 31;
|
||||
return outFloat.floatValue; // Already done!
|
||||
}
|
||||
|
||||
// If exponent is 0, it's a denormalized number, so we renormalize it
|
||||
// Note: this is not terribly efficient, but oh well
|
||||
while( ( mantissa & 0x00000400 ) == 0 )
|
||||
{
|
||||
mantissa <<= 1;
|
||||
exponent--;
|
||||
}
|
||||
|
||||
// The first bit is implicit, so we take it off and inc the exponent accordingly
|
||||
exponent++;
|
||||
mantissa &= ~(0x00000400);
|
||||
}
|
||||
else if( exponent == 31 ) // Special-case "numbers"
|
||||
{
|
||||
// If the exponent is 31, it's a special case number (+/- infinity or NAN).
|
||||
// If the mantissa is 0, it's infinity, else it's NAN, but in either case, the packing
|
||||
// method is the same
|
||||
outFloat.bits = ( sign << 31 ) | 0x7f800000 | ( mantissa << 13 );
|
||||
return outFloat.floatValue;
|
||||
}
|
||||
|
||||
// Plain ol' normalized number, so adjust to the ranges a 32-bit float expects and repack
|
||||
exponent += ( 127 - 15 );
|
||||
mantissa <<= 13;
|
||||
|
||||
outFloat.bits = ( sign << 31 ) | ( exponent << 23 ) | mantissa;
|
||||
return outFloat.floatValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
cl_ushort convert_float_to_half( float f )
|
||||
{
|
||||
switch( gFloatToHalfRoundingMode )
|
||||
{
|
||||
case kRoundToNearestEven:
|
||||
return float2half_rte( f );
|
||||
case kRoundTowardZero:
|
||||
return float2half_rtz( f );
|
||||
case kRoundToNearestEven: return cl_half_from_float(f, CL_HALF_RTE);
|
||||
case kRoundTowardZero: return cl_half_from_float(f, CL_HALF_RTZ);
|
||||
default:
|
||||
log_error( "ERROR: Test internal error -- unhandled or unknown float->half rounding mode.\n" );
|
||||
exit(-1);
|
||||
@@ -985,173 +922,6 @@ cl_ushort convert_float_to_half( float f )
|
||||
|
||||
}
|
||||
|
||||
cl_ushort float2half_rte( float f )
|
||||
{
|
||||
union{ float f; cl_uint u; } u = {f};
|
||||
cl_uint sign = (u.u >> 16) & 0x8000;
|
||||
float x = fabsf(f);
|
||||
|
||||
//Nan
|
||||
if( x != x )
|
||||
{
|
||||
u.u >>= (24-11);
|
||||
u.u &= 0x7fff;
|
||||
u.u |= 0x0200; //silence the NaN
|
||||
return u.u | sign;
|
||||
}
|
||||
|
||||
// overflow
|
||||
if( x >= MAKE_HEX_FLOAT(0x1.ffep15f, 0x1ffeL, 3) )
|
||||
return 0x7c00 | sign;
|
||||
|
||||
// underflow
|
||||
if( x <= MAKE_HEX_FLOAT(0x1.0p-25f, 0x1L, -25) )
|
||||
return sign; // The halfway case can return 0x0001 or 0. 0 is even.
|
||||
|
||||
// very small
|
||||
if( x < MAKE_HEX_FLOAT(0x1.8p-24f, 0x18L, -28) )
|
||||
return sign | 1;
|
||||
|
||||
// half denormal
|
||||
if( x < MAKE_HEX_FLOAT(0x1.0p-14f, 0x1L, -14) )
|
||||
{
|
||||
u.f = x * MAKE_HEX_FLOAT(0x1.0p-125f, 0x1L, -125);
|
||||
return sign | u.u;
|
||||
}
|
||||
|
||||
u.f *= MAKE_HEX_FLOAT(0x1.0p13f, 0x1L, 13);
|
||||
u.u &= 0x7f800000;
|
||||
x += u.f;
|
||||
u.f = x - u.f;
|
||||
u.f *= MAKE_HEX_FLOAT(0x1.0p-112f, 0x1L, -112);
|
||||
|
||||
return (u.u >> (24-11)) | sign;
|
||||
}
|
||||
|
||||
cl_ushort float2half_rtz( float f )
|
||||
{
|
||||
union{ float f; cl_uint u; } u = {f};
|
||||
cl_uint sign = (u.u >> 16) & 0x8000;
|
||||
float x = fabsf(f);
|
||||
|
||||
//Nan
|
||||
if( x != x )
|
||||
{
|
||||
u.u >>= (24-11);
|
||||
u.u &= 0x7fff;
|
||||
u.u |= 0x0200; //silence the NaN
|
||||
return u.u | sign;
|
||||
}
|
||||
|
||||
// overflow
|
||||
if( x >= MAKE_HEX_FLOAT(0x1.0p16f, 0x1L, 16) )
|
||||
{
|
||||
if( x == INFINITY )
|
||||
return 0x7c00 | sign;
|
||||
|
||||
return 0x7bff | sign;
|
||||
}
|
||||
|
||||
// underflow
|
||||
if( x < MAKE_HEX_FLOAT(0x1.0p-24f, 0x1L, -24) )
|
||||
return sign; // The halfway case can return 0x0001 or 0. 0 is even.
|
||||
|
||||
// half denormal
|
||||
if( x < MAKE_HEX_FLOAT(0x1.0p-14f, 0x1L, -14) )
|
||||
{
|
||||
x *= MAKE_HEX_FLOAT(0x1.0p24f, 0x1L, 24);
|
||||
return (cl_ushort)((int) x | sign);
|
||||
}
|
||||
|
||||
u.u &= 0xFFFFE000U;
|
||||
u.u -= 0x38000000U;
|
||||
|
||||
return (u.u >> (24-11)) | sign;
|
||||
}
|
||||
|
||||
class TEST
|
||||
{
|
||||
public:
|
||||
TEST();
|
||||
};
|
||||
|
||||
static TEST t;
|
||||
void __vstore_half_rte(float f, size_t index, uint16_t *p)
|
||||
{
|
||||
union{ unsigned int u; float f;} u;
|
||||
|
||||
u.f = f;
|
||||
unsigned short r = (u.u >> 16) & 0x8000;
|
||||
u.u &= 0x7fffffff;
|
||||
if( u.u >= 0x33000000U )
|
||||
{
|
||||
if( u.u >= 0x47800000 )
|
||||
{
|
||||
if( u.u <= 0x7f800000 )
|
||||
r |= 0x7c00;
|
||||
else
|
||||
{
|
||||
r |= 0x7e00 | ( (u.u >> 13) & 0x3ff );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float x = u.f;
|
||||
if( u.u < 0x38800000 )
|
||||
u.u = 0x3f000000;
|
||||
else
|
||||
u.u += 0x06800000;
|
||||
u.u &= 0x7f800000U;
|
||||
x += u.f;
|
||||
x -= u.f;
|
||||
u.f = x * MAKE_HEX_FLOAT(0x1.0p-112f, 0x1L, -112);
|
||||
u.u >>= 13;
|
||||
r |= (unsigned short) u.u;
|
||||
}
|
||||
}
|
||||
|
||||
((unsigned short*)p)[index] = r;
|
||||
}
|
||||
|
||||
TEST::TEST()
|
||||
{
|
||||
return;
|
||||
union
|
||||
{
|
||||
float f;
|
||||
uint32_t i;
|
||||
} test;
|
||||
uint16_t control, myval;
|
||||
|
||||
log_info(" &&&&&&&&&&&&&&&&&&&&&&&&&&&& TESTING HALFS &&&&&&&&&&&&&&&&&&&&\n" );
|
||||
test.i = 0;
|
||||
do
|
||||
{
|
||||
if( ( test.i & 0xffffff ) == 0 )
|
||||
{
|
||||
if( ( test.i & 0xfffffff ) == 0 )
|
||||
log_info( "*" );
|
||||
else
|
||||
log_info( "." );
|
||||
fflush(stdout);
|
||||
}
|
||||
__vstore_half_rte( test.f, 0, &control );
|
||||
myval = convert_float_to_half( test.f );
|
||||
if( myval != control )
|
||||
{
|
||||
log_info( "\n******** ERROR: MyVal %04x control %04x source %12.24f\n", myval, control, test.f );
|
||||
log_info( " source bits: %08x %a\n", test.i, test.f );
|
||||
float t, c;
|
||||
c = convert_half_to_float( control );
|
||||
t = convert_half_to_float( myval );
|
||||
log_info( " converted control: %12.24f myval: %12.24f\n", c, t );
|
||||
}
|
||||
test.i++;
|
||||
} while( test.i != 0 );
|
||||
log_info("\n &&&&&&&&&&&&&&&&&&&&&&&&&&&& TESTING HALFS &&&&&&&&&&&&&&&&&&&&\n" );
|
||||
|
||||
}
|
||||
|
||||
cl_ulong get_image_size( image_descriptor const *imageInfo )
|
||||
{
|
||||
cl_ulong imageSize;
|
||||
@@ -1497,7 +1267,7 @@ void read_image_pixel_float( void *imageData, image_descriptor *imageInfo,
|
||||
{
|
||||
cl_ushort *dPtr = (cl_ushort *)ptr;
|
||||
for( i = 0; i < channelCount; i++ )
|
||||
tempData[ i ] = convert_half_to_float( dPtr[ i ] );
|
||||
tempData[i] = cl_half_to_float(dPtr[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2617,11 +2387,11 @@ void pack_image_pixel( float *srcVector, const cl_image_format *imageFormat, voi
|
||||
{
|
||||
case kRoundToNearestEven:
|
||||
for( unsigned int i = 0; i < channelCount; i++ )
|
||||
ptr[ i ] = float2half_rte( srcVector[ i ] );
|
||||
ptr[i] = cl_half_from_float(srcVector[i], CL_HALF_RTE);
|
||||
break;
|
||||
case kRoundTowardZero:
|
||||
for( unsigned int i = 0; i < channelCount; i++ )
|
||||
ptr[ i ] = float2half_rtz( srcVector[ i ] );
|
||||
ptr[i] = cl_half_from_float(srcVector[i], CL_HALF_RTZ);
|
||||
break;
|
||||
default:
|
||||
log_error( "ERROR: Test internal error -- unhandled or unknown float->half rounding mode.\n" );
|
||||
@@ -3070,8 +2840,8 @@ int DetectFloatToHalfRoundingMode( cl_command_queue q ) // Returns CL_SUCCESS
|
||||
cl_ushort rtz_ref[count*4];
|
||||
for( size_t i = 0; i < 4 * count; i++ )
|
||||
{
|
||||
rte_ref[i] = float2half_rte( inp[i] );
|
||||
rtz_ref[i] = float2half_rtz( inp[i] );
|
||||
rte_ref[i] = cl_half_from_float(inp[i], CL_HALF_RTE);
|
||||
rtz_ref[i] = cl_half_from_float(inp[i], CL_HALF_RTZ);
|
||||
}
|
||||
|
||||
// Verify that we got something in either rtz or rte mode
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
#include "rounding_mode.h"
|
||||
#include "clImageHelper.h"
|
||||
|
||||
#include <CL/cl_half.h>
|
||||
|
||||
extern cl_device_type gDeviceType;
|
||||
extern bool gTestRounding;
|
||||
|
||||
@@ -154,7 +156,6 @@ size_t compute_mip_level_offset( image_descriptor * imageInfo , size_t lod);
|
||||
template <class T> void read_image_pixel( void *imageData, image_descriptor *imageInfo,
|
||||
int x, int y, int z, T *outData, int lod )
|
||||
{
|
||||
float convert_half_to_float( unsigned short halfValue );
|
||||
size_t width_lod = imageInfo->width, height_lod = imageInfo->height, depth_lod = imageInfo->depth, slice_pitch_lod = 0/*imageInfo->slicePitch*/ , row_pitch_lod = 0/*imageInfo->rowPitch*/;
|
||||
width_lod = ( imageInfo->width >> lod) ?( imageInfo->width >> lod):1;
|
||||
|
||||
@@ -278,7 +279,7 @@ template <class T> void read_image_pixel( void *imageData, image_descriptor *ima
|
||||
{
|
||||
cl_ushort *dPtr = (cl_ushort *)ptr;
|
||||
for( i = 0; i < get_format_channel_count( format ); i++ )
|
||||
tempData[ i ] = (T)convert_half_to_float( dPtr[ i ] );
|
||||
tempData[i] = (T)cl_half_to_float(dPtr[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -638,6 +639,7 @@ protected:
|
||||
size_t mVecSize;
|
||||
};
|
||||
|
||||
extern cl_ushort convert_float_to_half(float f);
|
||||
extern int DetectFloatToHalfRoundingMode( cl_command_queue ); // Returns CL_SUCCESS on success
|
||||
|
||||
// sign bit: don't care, exponent: maximum value, significand: non-zero
|
||||
@@ -649,9 +651,6 @@ static int inline is_half_denorm( cl_ushort half ){ return IsHalfSubnormal( half
|
||||
// sign bit: don't care, exponent: zero, significand: zero
|
||||
static int inline is_half_zero( cl_ushort half ){ return ( half & 0x7fff ) == 0; }
|
||||
|
||||
cl_ushort convert_float_to_half( cl_float f );
|
||||
cl_float convert_half_to_float( cl_ushort h );
|
||||
|
||||
extern double sRGBmap(float fc);
|
||||
|
||||
#endif // _imageHelpers_h
|
||||
|
||||
Reference in New Issue
Block a user