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:
Kévin Petit
2020-08-14 13:50:14 +01:00
committed by GitHub
parent 655d83db80
commit ed50fcad2d
15 changed files with 64 additions and 941 deletions

View File

@@ -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>

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -23,6 +23,7 @@
#include "../funcs_test_utils.hpp"
#include "half_utils.hpp"
#include <CL/cl_half.h>
// Generates cl_half input
std::vector<cl_half> generate_half_input(size_t count,
@@ -36,7 +37,7 @@ std::vector<cl_half> generate_half_input(size_t count,
std::uniform_real_distribution<cl_float> dis(min, max);
for(auto& i : input)
{
i = float2half_rte(dis(gen));
i = cl_half_from_float(dis(gen), CL_HALF_RTE);
}
input.insert(input.begin(), special_cases.begin(), special_cases.end());

View File

@@ -51,86 +51,4 @@ inline int clz(INT_TYPE x)
} // namespace detail
inline cl_float half2float(cl_half us)
{
uint32_t u = us;
uint32_t sign = (u << 16) & 0x80000000;
int32_t exponent = (u & 0x7c00) >> 10;
uint32_t mantissa = (u & 0x03ff) << 13;
union{ cl_uint u; cl_float f;}uu;
if( exponent == 0 )
{
if( mantissa == 0 )
return sign ? -0.0f : 0.0f;
int shift = detail::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;
}
inline cl_ushort float2half_rte(cl_float f)
{
union{ cl_float f; cl_uint u; } u = {f};
cl_uint sign = (u.u >> 16) & 0x8000;
cl_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;
}
#endif // TEST_CONFORMANCE_CLCPP_HALF_UTILS_HPP

View File

@@ -23,6 +23,8 @@
#include "common.hpp"
#include <CL/cl_half.h>
// -----------------------------------------------------------------------------------
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
// -----------------------------------------------------------------------------------
@@ -263,7 +265,7 @@ struct vload_half_func : public unary_func<
Iterator temp = x + static_cast<diff_type>(offset * N);
for(size_t i = 0; i < N; i++)
{
r.s[i] = half2float(*temp);
r.s[i] = cl_half_to_float(*temp);
temp++;
}
return r;
@@ -309,7 +311,7 @@ struct vloada_half_func : public unary_func<
Iterator temp = x + static_cast<diff_type>(offset * alignment);
for(size_t i = 0; i < N; i++)
{
r.s[i] = half2float(*temp);
r.s[i] = cl_half_to_float(*temp);
temp++;
}
return r;

View File

@@ -16,9 +16,6 @@
#ifndef TEST_CONFORMANCE_CLCPP_VLOAD_VSTORE_FUNCS_VSTORE_FUNCS_HPP
#define TEST_CONFORMANCE_CLCPP_VLOAD_VSTORE_FUNCS_VSTORE_FUNCS_HPP
#include "../common.hpp"
#include "../funcs_test_utils.hpp"
#include <iterator>
#include "../common.hpp"
@@ -26,6 +23,8 @@
#include "common.hpp"
#include <CL/cl_half.h>
// -----------------------------------------------------------------------------------
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
// -----------------------------------------------------------------------------------
@@ -240,7 +239,7 @@ struct vstore_half_func : public unary_func<
result_type r;
for(size_t i = 0; i < N; i++)
{
r.s[i] = float2half_rte(in.s[i]);
r.s[i] = cl_half_from_float(in.s[i], CL_HALF_RTE);
}
return r;
}
@@ -287,7 +286,7 @@ struct vstorea_half_func : public unary_func<
result_type r;
for(size_t i = 0; i < N; i++)
{
r.s[i] = float2half_rte(in.s[i]);
r.s[i] = cl_half_from_float(in.s[i], CL_HALF_RTE);
}
return r;
}

View File

@@ -368,7 +368,7 @@ char * convert_to_expected( void * inputBuffer, size_t numPixels, ExplicitType i
cl_float *outData = new cl_float[ numPixels * channelNum ];
for( size_t i = 0; i < numPixels * channelNum; i++ )
{
outData[ i ] = convert_half_to_float(src[ i ]);
outData[i] = cl_half_to_float(src[i]);
}
return (char *)outData;
}

View File

@@ -20,44 +20,7 @@
#include "cl_utils.h"
#include "tests.h"
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;
}
#include <CL/cl_half.h>
int Test_vLoadHalf_private( cl_device_id device, bool aligned )
{
@@ -482,8 +445,7 @@ int Test_vLoadHalf_private( cl_device_id device, bool aligned )
//create the reference result
const unsigned short *s = (const unsigned short *)gIn_half;
float *d = (float *)gOut_single_reference;
for( j = 0; j < count; j++ )
d[j] = half2float( s[j] );
for (j = 0; j < count; j++) d[j] = cl_half_to_float(s[j]);
//Check the vector lengths
for( vectorSize = minVectorSize; vectorSize < kLastVectorSizeToTest; vectorSize++)

View File

@@ -21,6 +21,8 @@
#include "cl_utils.h"
#include "tests.h"
#include <CL/cl_half.h>
typedef struct ComputeReferenceInfoF_
{
float *x;
@@ -208,406 +210,44 @@ CheckD(cl_uint jid, cl_uint tid, void *userInfo)
return ret;
}
static cl_ushort float2half_rte( float f );
static cl_ushort float2half_rtz( float f );
static cl_ushort float2half_rtp( float f );
static cl_ushort float2half_rtn( float f );
static cl_ushort double2half_rte( double f );
static cl_ushort double2half_rtz( double f );
static cl_ushort double2half_rtp( double f );
static cl_ushort double2half_rtn( double f );
static cl_ushort
float2half_rte( float f )
static 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;
return cl_half_from_float(f, CL_HALF_RTE);
}
static cl_ushort
float2half_rtz( float f )
static 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;
return cl_half_from_float(f, CL_HALF_RTZ);
}
static cl_ushort
float2half_rtp( float f )
static cl_ushort float2half_rtp(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( f > MAKE_HEX_FLOAT(0x1.ffcp15f, 0x1ffcL, 3) )
return 0x7c00;
if( f <= MAKE_HEX_FLOAT(-0x1.0p16f, -0x1L, 16) )
{
if( f == -INFINITY )
return 0xfc00;
return 0xfbff;
}
// underflow
if( x < MAKE_HEX_FLOAT(0x1.0p-24f, 0x1L, -24) )
{
if( f > 0 )
return 1;
return sign;
}
// half denormal
if( x < MAKE_HEX_FLOAT(0x1.0p-14f, 0x1L, -14) )
{
x *= MAKE_HEX_FLOAT(0x1.0p24f, 0x1L, 24);
int r = (int) x;
r += (float) r != x && f > 0.0f;
return (cl_ushort)( r | sign);
}
float g = u.f;
u.u &= 0xFFFFE000U;
if( g > u.f )
u.u += 0x00002000U;
u.u -= 0x38000000U;
return (u.u >> (24-11)) | sign;
return cl_half_from_float(f, CL_HALF_RTP);
}
static cl_ushort
float2half_rtn( float f )
static cl_ushort float2half_rtn(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( f >= MAKE_HEX_FLOAT(0x1.0p16f, 0x1L, 16) )
{
if( f == INFINITY )
return 0x7c00;
return 0x7bff;
}
if( f < MAKE_HEX_FLOAT(-0x1.ffcp15f, -0x1ffcL, 3) )
return 0xfc00;
// underflow
if( x < MAKE_HEX_FLOAT(0x1.0p-24f, 0x1L, -24) )
{
if( f < 0 )
return 0x8001;
return sign;
}
// half denormal
if( x < MAKE_HEX_FLOAT(0x1.0p-14f, 0x1L, -14) )
{
x *= MAKE_HEX_FLOAT(0x1.0p24f, 0x1L, 24);
int r = (int) x;
r += (float) r != x && f < 0.0f;
return (cl_ushort)( r | sign);
}
u.u &= 0xFFFFE000U;
if( u.f > f )
u.u += 0x00002000U;
u.u -= 0x38000000U;
return (u.u >> (24-11)) | sign;
return cl_half_from_float(f, CL_HALF_RTN);
}
static cl_ushort
double2half_rte( double f )
static cl_ushort double2half_rte(double f)
{
union{ double f; cl_ulong u; } u = {f};
cl_ulong sign = (u.u >> 48) & 0x8000;
double x = fabs(f);
//Nan
if( x != x )
{
u.u >>= (53-11);
u.u &= 0x7fff;
u.u |= 0x0200; //silence the NaN
return u.u | sign;
}
// overflow
if( x >= MAKE_HEX_DOUBLE(0x1.ffep15, 0x1ffeLL, 3) )
return 0x7c00 | sign;
// underflow
if( x <= MAKE_HEX_DOUBLE(0x1.0p-25, 0x1LL, -25) )
return sign; // The halfway case can return 0x0001 or 0. 0 is even.
// very small
if( x < MAKE_HEX_DOUBLE(0x1.8p-24, 0x18LL, -28) )
return sign | 1;
// half denormal
if( x < MAKE_HEX_DOUBLE(0x1.0p-14, 0x1LL, -14) )
{
u.f = x * MAKE_HEX_DOUBLE(0x1.0p-1050, 0x1LL, -1050);
return sign | u.u;
}
u.f *= MAKE_HEX_DOUBLE(0x1.0p42, 0x1LL, 42);
u.u &= 0x7ff0000000000000ULL;
x += u.f;
u.f = x - u.f;
u.f *= MAKE_HEX_DOUBLE(0x1.0p-1008, 0x1LL, -1008);
return (u.u >> (53-11)) | sign;
return cl_half_from_double(f, CL_HALF_RTE);
}
static cl_ushort
double2half_rtz( double f )
static cl_ushort double2half_rtz(double f)
{
union{ double f; cl_ulong u; } u = {f};
cl_ulong sign = (u.u >> 48) & 0x8000;
double x = fabs(f);
//Nan
if( x != x )
{
u.u >>= (53-11);
u.u &= 0x7fff;
u.u |= 0x0200; //silence the NaN
return u.u | sign;
}
if( x == INFINITY )
return 0x7c00 | sign;
// overflow
if( x >= MAKE_HEX_DOUBLE(0x1.0p16, 0x1LL, 16) )
return 0x7bff | sign;
// underflow
if( x < MAKE_HEX_DOUBLE(0x1.0p-24, 0x1LL, -24) )
return sign; // The halfway case can return 0x0001 or 0. 0 is even.
// half denormal
if( x < MAKE_HEX_DOUBLE(0x1.0p-14, 0x1LL, -14) )
{
x *= MAKE_HEX_FLOAT(0x1.0p24f, 0x1L, 24);
return (cl_ushort)((int) x | sign);
}
u.u &= 0xFFFFFC0000000000ULL;
u.u -= 0x3F00000000000000ULL;
return (u.u >> (53-11)) | sign;
return cl_half_from_double(f, CL_HALF_RTZ);
}
static cl_ushort
double2half_rtp( double f )
static cl_ushort double2half_rtp(double f)
{
union{ double f; cl_ulong u; } u = {f};
cl_ulong sign = (u.u >> 48) & 0x8000;
double x = fabs(f);
//Nan
if( x != x )
{
u.u >>= (53-11);
u.u &= 0x7fff;
u.u |= 0x0200; //silence the NaN
return u.u | sign;
}
// overflow
if( f > MAKE_HEX_DOUBLE(0x1.ffcp15, 0x1ffcLL, 3) )
return 0x7c00;
if( f <= MAKE_HEX_DOUBLE(-0x1.0p16, -0x1LL, 16) )
{
if( f == -INFINITY )
return 0xfc00;
return 0xfbff;
}
// underflow
if( x < MAKE_HEX_DOUBLE(0x1.0p-24, 0x1LL, -24) )
{
if( f > 0 )
return 1;
return sign;
}
// half denormal
if( x < MAKE_HEX_DOUBLE(0x1.0p-14, 0x1LL, -14) )
{
x *= MAKE_HEX_FLOAT(0x1.0p24f, 0x1L, 24);
int r = (int) x;
if( 0 == sign )
r += (double) r != x;
return (cl_ushort)( r | sign);
}
double g = u.f;
u.u &= 0xFFFFFC0000000000ULL;
if( g != u.f && 0 == sign)
u.u += 0x0000040000000000ULL;
u.u -= 0x3F00000000000000ULL;
return (u.u >> (53-11)) | sign;
return cl_half_from_double(f, CL_HALF_RTP);
}
static cl_ushort
double2half_rtn( double f )
static cl_ushort double2half_rtn(double f)
{
union{ double f; cl_ulong u; } u = {f};
cl_ulong sign = (u.u >> 48) & 0x8000;
double x = fabs(f);
//Nan
if( x != x )
{
u.u >>= (53-11);
u.u &= 0x7fff;
u.u |= 0x0200; //silence the NaN
return u.u | sign;
}
// overflow
if( f >= MAKE_HEX_DOUBLE(0x1.0p16, 0x1LL, 16) )
{
if( f == INFINITY )
return 0x7c00;
return 0x7bff;
}
if( f < MAKE_HEX_DOUBLE(-0x1.ffcp15, -0x1ffcLL, 3) )
return 0xfc00;
// underflow
if( x < MAKE_HEX_DOUBLE(0x1.0p-24, 0x1LL, -24) )
{
if( f < 0 )
return 0x8001;
return sign;
}
// half denormal
if( x < MAKE_HEX_DOUBLE(0x1.0p-14, 0x1LL, -14) )
{
x *= MAKE_HEX_DOUBLE(0x1.0p24, 0x1LL, 24);
int r = (int) x;
if( sign )
r += (double) r != x;
return (cl_ushort)( r | sign);
}
double g = u.f;
u.u &= 0xFFFFFC0000000000ULL;
if( g < u.f && sign)
u.u += 0x0000040000000000ULL;
u.u -= 0x3F00000000000000ULL;
return (u.u >> (53-11)) | sign;
return cl_half_from_double(f, CL_HALF_RTN);
}
int test_vstore_half( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements )

View File

@@ -17,6 +17,7 @@
#include <stdlib.h>
#include "harness/errorHelpers.h"
#include "harness/imageHelpers.h"
#include "harness/kernelHelpers.h"
#include "utils.h"

View File

@@ -16,10 +16,13 @@
#include "utils.h"
#include "harness/errorHelpers.h"
#include "harness/imageHelpers.h"
#include "harness/rounding_mode.h"
#include <math.h>
#include <CL/cl_half.h>
static RoundingMode gFloatToHalfRoundingMode = kDefaultRoundingMode;
@@ -772,14 +775,18 @@ bool DataCompare( TSurfaceFormat surfaceFormat, cl_channel_type type, const std:
{
for(unsigned planeIdx = 0; planeIdx < channelNum; ++planeIdx)
{
float test = convert_half_to_float(dataTest.at(offset + j * channelNum + planeIdx));
float ref = convert_half_to_float(dataExp.at(offset + j * channelNum + planeIdx));
if (abs(test - ref) > epsilon)
{
log_error("Tested image is different than reference (x,y,plane) = (%i,%i,%i), test value = %f, expected value = %f\n",
j, i, planeIdx, test, ref);
return false;
}
float test = cl_half_to_float(
dataTest.at(offset + j * channelNum + planeIdx));
float ref = cl_half_to_float(
dataExp.at(offset + j * channelNum + planeIdx));
if (abs(test - ref) > epsilon)
{
log_error(
"Tested image is different than reference (x,y,plane) = "
"(%i,%i,%i), test value = %f, expected value = %f\n",
j, i, planeIdx, test, ref);
return false;
}
}
}
}
@@ -1554,90 +1561,6 @@ bool MediaSurfaceCreate(cl_dx9_media_adapter_type_khr adapterType, unsigned int
return true;
}
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;
}
cl_int deviceExistForCLTest(cl_platform_id platform,
cl_dx9_media_adapter_type_khr media_adapters_type,
void *media_adapters,

View File

@@ -163,12 +163,5 @@ void SurfaceFormatToString(TSurfaceFormat surfaceFormat, std::string &str );
bool MediaSurfaceCreate(cl_dx9_media_adapter_type_khr adapterType, unsigned int width, unsigned int height, TSurfaceFormat surfaceFormat,
CDeviceWrapper &device, std::auto_ptr<CSurfaceWrapper> &surface, bool sharedHandle, void **objectSharedHandle);
//imported from image helpers
cl_ushort float2half_rte( float f );
cl_ushort float2half_rtz( float f );
cl_ushort convert_float_to_half( float f );
float convert_half_to_float( unsigned short halfValue );
int DetectFloatToHalfRoundingMode( cl_command_queue );
cl_int deviceExistForCLTest(cl_platform_id platform,cl_dx9_media_adapter_type_khr media_adapters_type,void *media_adapters,CResult &result,TSharedHandleType sharedHandle=SHARED_HANDLE_DISABLED);
#endif // __UTILS_KHR_MEDIA_H