blob: 83687ee3ce744eae9a19b747bedc45d3435636d6 [file] [log] [blame]
//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "procs.h"
#define TEST_VALUE_POSITIVE( string_name, name, value ) \
{ \
if (name < value) { \
log_error("FAILED: " string_name ": " #name " < " #value "\n"); \
errors++;\
} else { \
log_info("\t" string_name ": " #name " >= " #value "\n"); \
} \
}
#define TEST_VALUE_NEGATIVE( string_name, name, value ) \
{ \
if (name > value) { \
log_error("FAILED: " string_name ": " #name " > " #value "\n"); \
errors++;\
} else { \
log_info("\t" string_name ": " #name " <= " #value "\n"); \
} \
}
#define TEST_VALUE_EQUAL_LITERAL( string_name, name, value ) \
{ \
if (name != value) { \
log_error("FAILED: " string_name ": " #name " != " #value "\n"); \
errors++;\
} else { \
log_info("\t" string_name ": " #name " = " #value "\n"); \
} \
}
#define TEST_VALUE_EQUAL( string_name, name, value ) \
{ \
if (name != value) { \
log_error("FAILED: " string_name ": " #name " != %a (%17.21g)\n", value, value); \
errors++;\
} else { \
log_info("\t" string_name ": " #name " = %a (%17.21g)\n", value, value); \
} \
}
int test_host_numeric_constants(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
int errors = 0;
TEST_VALUE_EQUAL_LITERAL( "CL_CHAR_BIT", CL_CHAR_BIT, 8)
TEST_VALUE_EQUAL_LITERAL( "CL_SCHAR_MAX", CL_SCHAR_MAX, 127)
TEST_VALUE_EQUAL_LITERAL( "CL_SCHAR_MIN", CL_SCHAR_MIN, (-127-1))
TEST_VALUE_EQUAL_LITERAL( "CL_CHAR_MAX", CL_CHAR_MAX, CL_SCHAR_MAX)
TEST_VALUE_EQUAL_LITERAL( "CL_CHAR_MIN", CL_CHAR_MIN, CL_SCHAR_MIN)
TEST_VALUE_EQUAL_LITERAL( "CL_UCHAR_MAX", CL_UCHAR_MAX, 255)
TEST_VALUE_EQUAL_LITERAL( "CL_SHRT_MAX", CL_SHRT_MAX, 32767)
TEST_VALUE_EQUAL_LITERAL( "CL_SHRT_MIN", CL_SHRT_MIN, (-32767-1))
TEST_VALUE_EQUAL_LITERAL( "CL_USHRT_MAX", CL_USHRT_MAX, 65535)
TEST_VALUE_EQUAL_LITERAL( "CL_INT_MAX", CL_INT_MAX, 2147483647)
TEST_VALUE_EQUAL_LITERAL( "CL_INT_MIN", CL_INT_MIN, (-2147483647-1))
TEST_VALUE_EQUAL_LITERAL( "CL_UINT_MAX", CL_UINT_MAX, 0xffffffffU)
TEST_VALUE_EQUAL_LITERAL( "CL_LONG_MAX", CL_LONG_MAX, ((cl_long) 0x7FFFFFFFFFFFFFFFLL))
TEST_VALUE_EQUAL_LITERAL( "CL_LONG_MIN", CL_LONG_MIN, ((cl_long) -0x7FFFFFFFFFFFFFFFLL - 1LL))
TEST_VALUE_EQUAL_LITERAL( "CL_ULONG_MAX", CL_ULONG_MAX, ((cl_ulong) 0xFFFFFFFFFFFFFFFFULL))
TEST_VALUE_EQUAL_LITERAL( "CL_FLT_DIG", CL_FLT_DIG, 6)
TEST_VALUE_EQUAL_LITERAL( "CL_FLT_MANT_DIG", CL_FLT_MANT_DIG, 24)
TEST_VALUE_EQUAL_LITERAL( "CL_FLT_MAX_10_EXP", CL_FLT_MAX_10_EXP, +38)
TEST_VALUE_EQUAL_LITERAL( "CL_FLT_MAX_EXP", CL_FLT_MAX_EXP, +128)
TEST_VALUE_EQUAL_LITERAL( "CL_FLT_MIN_10_EXP", CL_FLT_MIN_10_EXP, -37)
TEST_VALUE_EQUAL_LITERAL( "CL_FLT_MIN_EXP", CL_FLT_MIN_EXP, -125)
TEST_VALUE_EQUAL_LITERAL( "CL_FLT_RADIX", CL_FLT_RADIX, 2)
TEST_VALUE_EQUAL_LITERAL( "CL_FLT_MAX", CL_FLT_MAX, MAKE_HEX_FLOAT( 0x1.fffffep127f, 0x1fffffeL, 103))
TEST_VALUE_EQUAL_LITERAL( "CL_FLT_MIN", CL_FLT_MIN, MAKE_HEX_FLOAT(0x1.0p-126f, 0x1L, -126))
TEST_VALUE_EQUAL_LITERAL( "CL_FLT_EPSILON", CL_FLT_EPSILON, MAKE_HEX_FLOAT(0x1.0p-23f, 0x1L, -23))
TEST_VALUE_EQUAL_LITERAL( "CL_DBL_DIG", CL_DBL_DIG, 15)
TEST_VALUE_EQUAL_LITERAL( "CL_DBL_MANT_DIG", CL_DBL_MANT_DIG, 53)
TEST_VALUE_EQUAL_LITERAL( "CL_DBL_MAX_10_EXP", CL_DBL_MAX_10_EXP, +308)
TEST_VALUE_EQUAL_LITERAL( "CL_DBL_MAX_EXP", CL_DBL_MAX_EXP, +1024)
TEST_VALUE_EQUAL_LITERAL( "CL_DBL_MIN_10_EXP", CL_DBL_MIN_10_EXP, -307)
TEST_VALUE_EQUAL_LITERAL( "CL_DBL_MIN_EXP", CL_DBL_MIN_EXP, -1021)
TEST_VALUE_EQUAL_LITERAL( "CL_DBL_RADIX", CL_DBL_RADIX, 2)
TEST_VALUE_EQUAL( "CL_DBL_MAX", CL_DBL_MAX, MAKE_HEX_DOUBLE(0x1.fffffffffffffp1023, 0x1fffffffffffffLL, 971))
TEST_VALUE_EQUAL( "CL_DBL_MIN", CL_DBL_MIN, MAKE_HEX_DOUBLE(0x1.0p-1022, 0x1LL, -1022))
TEST_VALUE_EQUAL( "CL_DBL_EPSILON", CL_DBL_EPSILON, MAKE_HEX_DOUBLE(0x1.0p-52, 0x1LL, -52))
TEST_VALUE_EQUAL( "CL_M_E", CL_M_E, MAKE_HEX_DOUBLE(0x1.5bf0a8b145769p+1, 0x15bf0a8b145769LL, -51) );
TEST_VALUE_EQUAL( "CL_M_LOG2E", CL_M_LOG2E, MAKE_HEX_DOUBLE(0x1.71547652b82fep+0, 0x171547652b82feLL, -52) );
TEST_VALUE_EQUAL( "CL_M_LOG10E", CL_M_LOG10E, MAKE_HEX_DOUBLE(0x1.bcb7b1526e50ep-2, 0x1bcb7b1526e50eLL, -54) );
TEST_VALUE_EQUAL( "CL_M_LN2", CL_M_LN2, MAKE_HEX_DOUBLE(0x1.62e42fefa39efp-1, 0x162e42fefa39efLL, -53) );
TEST_VALUE_EQUAL( "CL_M_LN10", CL_M_LN10, MAKE_HEX_DOUBLE(0x1.26bb1bbb55516p+1, 0x126bb1bbb55516LL, -51) );
TEST_VALUE_EQUAL( "CL_M_PI", CL_M_PI, MAKE_HEX_DOUBLE(0x1.921fb54442d18p+1, 0x1921fb54442d18LL, -51) );
TEST_VALUE_EQUAL( "CL_M_PI_2", CL_M_PI_2, MAKE_HEX_DOUBLE(0x1.921fb54442d18p+0, 0x1921fb54442d18LL, -52) );
TEST_VALUE_EQUAL( "CL_M_PI_4", CL_M_PI_4, MAKE_HEX_DOUBLE(0x1.921fb54442d18p-1, 0x1921fb54442d18LL, -53) );
TEST_VALUE_EQUAL( "CL_M_1_PI", CL_M_1_PI, MAKE_HEX_DOUBLE(0x1.45f306dc9c883p-2, 0x145f306dc9c883LL, -54) );
TEST_VALUE_EQUAL( "CL_M_2_PI", CL_M_2_PI, MAKE_HEX_DOUBLE(0x1.45f306dc9c883p-1, 0x145f306dc9c883LL, -53) );
TEST_VALUE_EQUAL( "CL_M_2_SQRTPI", CL_M_2_SQRTPI, MAKE_HEX_DOUBLE(0x1.20dd750429b6dp+0, 0x120dd750429b6dLL, -52) );
TEST_VALUE_EQUAL( "CL_M_SQRT2", CL_M_SQRT2, MAKE_HEX_DOUBLE(0x1.6a09e667f3bcdp+0, 0x16a09e667f3bcdLL, -52) );
TEST_VALUE_EQUAL( "CL_M_SQRT1_2", CL_M_SQRT1_2, MAKE_HEX_DOUBLE(0x1.6a09e667f3bcdp-1, 0x16a09e667f3bcdLL, -53) );
TEST_VALUE_EQUAL( "CL_M_E_F", CL_M_E_F, MAKE_HEX_FLOAT(0x1.5bf0a8p+1f, 0x15bf0a8L, -23));
TEST_VALUE_EQUAL( "CL_M_LOG2E_F", CL_M_LOG2E_F, MAKE_HEX_FLOAT(0x1.715476p+0f, 0x1715476L, -24));
TEST_VALUE_EQUAL( "CL_M_LOG10E_F", CL_M_LOG10E_F, MAKE_HEX_FLOAT(0x1.bcb7b2p-2f, 0x1bcb7b2L, -26));
TEST_VALUE_EQUAL( "CL_M_LN2_F", CL_M_LN2_F, MAKE_HEX_FLOAT(0x1.62e43p-1f, 0x162e43L, -21) );
TEST_VALUE_EQUAL( "CL_M_LN10_F", CL_M_LN10_F, MAKE_HEX_FLOAT(0x1.26bb1cp+1f, 0x126bb1cL, -23));
TEST_VALUE_EQUAL( "CL_M_PI_F", CL_M_PI_F, MAKE_HEX_FLOAT(0x1.921fb6p+1f, 0x1921fb6L, -23));
TEST_VALUE_EQUAL( "CL_M_PI_2_F", CL_M_PI_2_F, MAKE_HEX_FLOAT(0x1.921fb6p+0f, 0x1921fb6L, -24));
TEST_VALUE_EQUAL( "CL_M_PI_4_F", CL_M_PI_4_F, MAKE_HEX_FLOAT(0x1.921fb6p-1f, 0x1921fb6L, -25));
TEST_VALUE_EQUAL( "CL_M_1_PI_F", CL_M_1_PI_F, MAKE_HEX_FLOAT(0x1.45f306p-2f, 0x145f306L, -26));
TEST_VALUE_EQUAL( "CL_M_2_PI_F", CL_M_2_PI_F, MAKE_HEX_FLOAT(0x1.45f306p-1f, 0x145f306L, -25));
TEST_VALUE_EQUAL( "CL_M_2_SQRTPI_F", CL_M_2_SQRTPI_F,MAKE_HEX_FLOAT(0x1.20dd76p+0f, 0x120dd76L, -24));
TEST_VALUE_EQUAL( "CL_M_SQRT2_F", CL_M_SQRT2_F, MAKE_HEX_FLOAT(0x1.6a09e6p+0f, 0x16a09e6L, -24));
TEST_VALUE_EQUAL( "CL_M_SQRT1_2_F", CL_M_SQRT1_2_F, MAKE_HEX_FLOAT(0x1.6a09e6p-1f, 0x16a09e6L, -25));
return errors;
}
const char *kernel_int_float[] = {
"__kernel void test( __global float *float_out, __global int *int_out, __global uint *uint_out) \n"
"{\n"
" int_out[0] = CHAR_BIT;\n"
" int_out[1] = SCHAR_MAX;\n"
" int_out[2] = SCHAR_MIN;\n"
" int_out[3] = CHAR_MAX;\n"
" int_out[4] = CHAR_MIN;\n"
" int_out[5] = UCHAR_MAX;\n"
" int_out[6] = SHRT_MAX;\n"
" int_out[7] = SHRT_MIN;\n"
" int_out[8] = USHRT_MAX;\n"
" int_out[9] = INT_MAX;\n"
" int_out[10] = INT_MIN;\n"
" uint_out[0] = UINT_MAX;\n"
" int_out[11] = FLT_DIG;\n"
" int_out[12] = FLT_MANT_DIG;\n"
" int_out[13] = FLT_MAX_10_EXP;\n"
" int_out[14] = FLT_MAX_EXP;\n"
" int_out[15] = FLT_MIN_10_EXP;\n"
" int_out[16] = FLT_MIN_EXP;\n"
" int_out[17] = FLT_RADIX;\n"
"#ifdef __IMAGE_SUPPORT__\n"
" int_out[18] = __IMAGE_SUPPORT__;\n"
"#else\n"
" int_out[18] = 0xf00baa;\n"
"#endif\n"
" float_out[0] = FLT_MAX;\n"
" float_out[1] = FLT_MIN;\n"
" float_out[2] = FLT_EPSILON;\n"
" float_out[3] = M_E_F;\n"
" float_out[4] = M_LOG2E_F;\n"
" float_out[5] = M_LOG10E_F;\n"
" float_out[6] = M_LN2_F;\n"
" float_out[7] = M_LN10_F;\n"
" float_out[8] = M_PI_F;\n"
" float_out[9] = M_PI_2_F;\n"
" float_out[10] = M_PI_4_F;\n"
" float_out[11] = M_1_PI_F;\n"
" float_out[12] = M_2_PI_F;\n"
" float_out[13] = M_2_SQRTPI_F;\n"
" float_out[14] = M_SQRT2_F;\n"
" float_out[15] = M_SQRT1_2_F;\n"
"}\n"
};
const char *kernel_long[] = {
"__kernel void test(__global long *long_out, __global ulong *ulong_out) \n"
"{\n"
" long_out[0] = LONG_MAX;\n"
" long_out[1] = LONG_MIN;\n"
" ulong_out[0] = ULONG_MAX;\n"
"}\n"
};
const char *kernel_double[] = {
"#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"
"__kernel void test( __global double *double_out, __global long *long_out ) \n "
"{\n"
" long_out[0] = DBL_DIG;\n"
" long_out[1] = DBL_MANT_DIG;\n"
" long_out[2] = DBL_MAX_10_EXP;\n"
" long_out[3] = DBL_MAX_EXP;\n"
" long_out[4] = DBL_MIN_10_EXP;\n"
" long_out[5] = DBL_MIN_EXP;\n"
" long_out[6] = DBL_RADIX;\n"
" double_out[0] = DBL_MAX;\n"
" double_out[1] = DBL_MIN;\n"
" double_out[2] = DBL_EPSILON;\n"
" double_out[3] = M_E;\n"
" double_out[4] = M_LOG2E;\n"
" double_out[5] = M_LOG10E;\n"
" double_out[6] = M_LN2;\n"
" double_out[7] = M_LN10;\n"
" double_out[8] = M_PI;\n"
" double_out[9] = M_PI_2;\n"
" double_out[10] = M_PI_4;\n"
" double_out[11] = M_1_PI;\n"
" double_out[12] = M_2_PI;\n"
" double_out[13] = M_2_SQRTPI;\n"
" double_out[14] = M_SQRT2;\n"
" double_out[15] = M_SQRT1_2;\n"
"}\n"
};
int test_kernel_numeric_constants(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
int error, errors = 0;
// clProgramWrapper program;
// clKernelWrapper kernel;
// clMemWrapper streams[3];
cl_program program;
cl_kernel kernel;
cl_mem streams[3];
size_t threads[] = {1,1,1};
cl_float float_out[16];
cl_int int_out[19];
cl_uint uint_out[1];
cl_long long_out[7];
cl_ulong ulong_out[1];
cl_double double_out[16];
/** INTs and FLOATs **/
// Create the kernel
if( create_single_kernel_helper( context, &program, &kernel, 1, kernel_int_float, "test" ) != 0 )
{
return -1;
}
/* Create some I/O streams */
streams[0] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(float_out),
NULL, &error);
test_error( error, "Creating test array failed" );
streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(int_out),
NULL, &error);
test_error( error, "Creating test array failed" );
streams[2] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(uint_out),
NULL, &error);
test_error( error, "Creating test array failed" );
error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1]);
test_error( error, "Unable to set indexed kernel arguments" );
error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0]);
test_error( error, "Unable to set indexed kernel arguments" );
error = clSetKernelArg(kernel, 2, sizeof( streams[2] ), &streams[2]);
test_error( error, "Unable to set indexed kernel arguments" );
error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL );
test_error( error, "Kernel execution failed" );
error = clEnqueueReadBuffer( queue, streams[0], CL_TRUE, 0, sizeof(float_out), (void*)float_out, 0, NULL, NULL );
test_error( error, "Unable to get result data" );
error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(int_out), (void*)int_out, 0, NULL, NULL );
test_error( error, "Unable to get result data" );
error = clEnqueueReadBuffer( queue, streams[2], CL_TRUE, 0, sizeof(uint_out), (void*)uint_out, 0, NULL, NULL );
test_error( error, "Unable to get result data" );
TEST_VALUE_EQUAL_LITERAL( "CHAR_BIT", int_out[0], 8)
TEST_VALUE_EQUAL_LITERAL( "SCHAR_MAX", int_out[1], 127)
TEST_VALUE_EQUAL_LITERAL( "SCHAR_MIN", int_out[2], (-127-1))
TEST_VALUE_EQUAL_LITERAL( "CHAR_MAX", int_out[3], CL_SCHAR_MAX)
TEST_VALUE_EQUAL_LITERAL( "CHAR_MIN", int_out[4], CL_SCHAR_MIN)
TEST_VALUE_EQUAL_LITERAL( "UCHAR_MAX", int_out[5], 255)
TEST_VALUE_EQUAL_LITERAL( "SHRT_MAX", int_out[6], 32767)
TEST_VALUE_EQUAL_LITERAL( "SHRT_MIN",int_out[7], (-32767-1))
TEST_VALUE_EQUAL_LITERAL( "USHRT_MAX", int_out[8], 65535)
TEST_VALUE_EQUAL_LITERAL( "INT_MAX", int_out[9], 2147483647)
TEST_VALUE_EQUAL_LITERAL( "INT_MIN", int_out[10], (-2147483647-1))
TEST_VALUE_EQUAL_LITERAL( "UINT_MAX", uint_out[0], 0xffffffffU)
TEST_VALUE_EQUAL_LITERAL( "FLT_DIG", int_out[11], 6)
TEST_VALUE_EQUAL_LITERAL( "FLT_MANT_DIG", int_out[12], 24)
TEST_VALUE_EQUAL_LITERAL( "FLT_MAX_10_EXP", int_out[13], +38)
TEST_VALUE_EQUAL_LITERAL( "FLT_MAX_EXP", int_out[14], +128)
TEST_VALUE_EQUAL_LITERAL( "FLT_MIN_10_EXP", int_out[15], -37)
TEST_VALUE_EQUAL_LITERAL( "FLT_MIN_EXP", int_out[16], -125)
TEST_VALUE_EQUAL_LITERAL( "FLT_RADIX", int_out[17], 2)
TEST_VALUE_EQUAL( "FLT_MAX", float_out[0], MAKE_HEX_FLOAT(0x1.fffffep127f, 0x1fffffeL, 103))
TEST_VALUE_EQUAL( "FLT_MIN", float_out[1], MAKE_HEX_FLOAT(0x1.0p-126f, 0x1L, -126))
TEST_VALUE_EQUAL( "FLT_EPSILON", float_out[2], MAKE_HEX_FLOAT(0x1.0p-23f, 0x1L, -23))
TEST_VALUE_EQUAL( "M_E_F", float_out[3], CL_M_E_F )
TEST_VALUE_EQUAL( "M_LOG2E_F", float_out[4], CL_M_LOG2E_F )
TEST_VALUE_EQUAL( "M_LOG10E_F", float_out[5], CL_M_LOG10E_F )
TEST_VALUE_EQUAL( "M_LN2_F", float_out[6], CL_M_LN2_F )
TEST_VALUE_EQUAL( "M_LN10_F", float_out[7], CL_M_LN10_F )
TEST_VALUE_EQUAL( "M_PI_F", float_out[8], CL_M_PI_F )
TEST_VALUE_EQUAL( "M_PI_2_F", float_out[9], CL_M_PI_2_F )
TEST_VALUE_EQUAL( "M_PI_4_F", float_out[10], CL_M_PI_4_F )
TEST_VALUE_EQUAL( "M_1_PI_F", float_out[11], CL_M_1_PI_F )
TEST_VALUE_EQUAL( "M_2_PI_F", float_out[12], CL_M_2_PI_F )
TEST_VALUE_EQUAL( "M_2_SQRTPI_F", float_out[13], CL_M_2_SQRTPI_F )
TEST_VALUE_EQUAL( "M_SQRT2_F", float_out[14], CL_M_SQRT2_F )
TEST_VALUE_EQUAL( "M_SQRT1_2_F", float_out[15], CL_M_SQRT1_2_F )
// We need to check these values against what we know is supported on the device
if( checkForImageSupport( deviceID ) == 0 )
{ // has images
// If images are supported, the constant should have been defined to the value 1
if( int_out[18] == 0xf00baa )
{
log_error( "FAILURE: __IMAGE_SUPPORT__ undefined even though images are supported\n" );
return -1;
}
else if( int_out[18] != 1 )
{
log_error( "FAILURE: __IMAGE_SUPPORT__ defined, but to the wrong value (defined as %d, spec states it should be 1)\n", int_out[18] );
return -1;
}
}
else
{ // no images
// If images aren't supported, the constant should be undefined
if( int_out[18] != 0xf00baa )
{
log_error( "FAILURE: __IMAGE_SUPPORT__ defined to value %d even though images aren't supported", int_out[18] );
return -1;
}
}
log_info( "\t__IMAGE_SUPPORT__: %d\n", int_out[18]);
clReleaseMemObject(streams[0]); streams[0] = NULL;
clReleaseMemObject(streams[1]); streams[1] = NULL;
clReleaseMemObject(streams[2]); streams[2] = NULL;
clReleaseKernel(kernel); kernel = NULL;
clReleaseProgram(program); program = NULL;
/** LONGs **/
if(!gHasLong) {
log_info("Longs not supported; skipping long tests.\n");
}
else
{
// Create the kernel
if( create_single_kernel_helper( context, &program, &kernel, 1, kernel_long, "test" ) != 0 )
{
return -1;
}
streams[0] = clCreateBuffer(context, CL_MEM_READ_WRITE,
sizeof(long_out), NULL, &error);
test_error( error, "Creating test array failed" );
streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE,
sizeof(ulong_out), NULL, &error);
test_error( error, "Creating test array failed" );
error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1]);
test_error( error, "Unable to set indexed kernel arguments" );
error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0]);
test_error( error, "Unable to set indexed kernel arguments" );
error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL );
test_error( error, "Kernel execution failed" );
error = clEnqueueReadBuffer( queue, streams[0], CL_TRUE, 0, sizeof(long_out), &long_out, 0, NULL, NULL );
test_error( error, "Unable to get result data" );
error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(ulong_out), &ulong_out, 0, NULL, NULL );
test_error( error, "Unable to get result data" );
TEST_VALUE_EQUAL_LITERAL( "LONG_MAX", long_out[0], ((cl_long) 0x7FFFFFFFFFFFFFFFLL))
TEST_VALUE_EQUAL_LITERAL( "LONG_MIN", long_out[1], ((cl_long) -0x7FFFFFFFFFFFFFFFLL - 1LL))
TEST_VALUE_EQUAL_LITERAL( "ULONG_MAX", ulong_out[0], ((cl_ulong) 0xFFFFFFFFFFFFFFFFULL))
clReleaseMemObject(streams[0]); streams[0] = NULL;
clReleaseMemObject(streams[1]); streams[1] = NULL;
clReleaseKernel(kernel); kernel = NULL;
clReleaseProgram(program); program = NULL;
}
/** DOUBLEs **/
if(!is_extension_available(deviceID, "cl_khr_fp64")) {
log_info("Extension cl_khr_fp64 not supported; skipping double tests.\n");
}
else
{
// Create the kernel
if( create_single_kernel_helper( context, &program, &kernel, 1, kernel_double, "test" ) != 0 )
{
return -1;
}
streams[0] = clCreateBuffer(context, CL_MEM_READ_WRITE,
sizeof(double_out), NULL, &error);
test_error( error, "Creating test array failed" );
streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE,
sizeof(long_out), NULL, &error);
test_error( error, "Creating test array failed" );
error = clSetKernelArg(kernel, 1, sizeof( streams[1] ), &streams[1]);
test_error( error, "Unable to set indexed kernel arguments" );
error = clSetKernelArg(kernel, 0, sizeof( streams[0] ), &streams[0]);
test_error( error, "Unable to set indexed kernel arguments" );
error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL );
test_error( error, "Kernel execution failed" );
error = clEnqueueReadBuffer( queue, streams[0], CL_TRUE, 0, sizeof(double_out), &double_out, 0, NULL, NULL );
test_error( error, "Unable to get result data" );
error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, sizeof(long_out), &long_out, 0, NULL, NULL );
test_error( error, "Unable to get result data" );
TEST_VALUE_EQUAL_LITERAL( "DBL_DIG", long_out[0], 15)
TEST_VALUE_EQUAL_LITERAL( "DBL_MANT_DIG", long_out[1], 53)
TEST_VALUE_EQUAL_LITERAL( "DBL_MAX_10_EXP", long_out[2], +308)
TEST_VALUE_EQUAL_LITERAL( "DBL_MAX_EXP", long_out[3], +1024)
TEST_VALUE_EQUAL_LITERAL( "DBL_MIN_10_EXP", long_out[4], -307)
TEST_VALUE_EQUAL_LITERAL( "DBL_MIN_EXP", long_out[5], -1021)
TEST_VALUE_EQUAL_LITERAL( "DBL_RADIX", long_out[6], 2)
TEST_VALUE_EQUAL( "DBL_MAX", double_out[0], MAKE_HEX_DOUBLE(0x1.fffffffffffffp1023, 0x1fffffffffffffLL, 971))
TEST_VALUE_EQUAL( "DBL_MIN", double_out[1], MAKE_HEX_DOUBLE(0x1.0p-1022, 0x1LL, -1022))
TEST_VALUE_EQUAL( "DBL_EPSILON", double_out[2], MAKE_HEX_DOUBLE(0x1.0p-52, 0x1LL, -52))
//TEST_VALUE_EQUAL( "M_E", double_out[3], CL_M_E )
TEST_VALUE_EQUAL( "M_LOG2E", double_out[4], CL_M_LOG2E )
TEST_VALUE_EQUAL( "M_LOG10E", double_out[5], CL_M_LOG10E )
TEST_VALUE_EQUAL( "M_LN2", double_out[6], CL_M_LN2 )
TEST_VALUE_EQUAL( "M_LN10", double_out[7], CL_M_LN10 )
TEST_VALUE_EQUAL( "M_PI", double_out[8], CL_M_PI )
TEST_VALUE_EQUAL( "M_PI_2", double_out[9], CL_M_PI_2 )
TEST_VALUE_EQUAL( "M_PI_4", double_out[10], CL_M_PI_4 )
TEST_VALUE_EQUAL( "M_1_PI", double_out[11], CL_M_1_PI )
TEST_VALUE_EQUAL( "M_2_PI", double_out[12], CL_M_2_PI )
TEST_VALUE_EQUAL( "M_2_SQRTPI", double_out[13], CL_M_2_SQRTPI )
TEST_VALUE_EQUAL( "M_SQRT2", double_out[14], CL_M_SQRT2 )
TEST_VALUE_EQUAL( "M_SQRT1_2", double_out[15], CL_M_SQRT1_2 )
clReleaseMemObject(streams[0]); streams[0] = NULL;
clReleaseMemObject(streams[1]); streams[1] = NULL;
clReleaseKernel(kernel); kernel = NULL;
clReleaseProgram(program); program = NULL;
}
error = clFinish(queue);
test_error(error, "clFinish failed");
return errors;
}
const char *kernel_constant_limits[] = {
"__kernel void test( __global int *intOut, __global float *floatOut ) \n"
"{\n"
" intOut[0] = isinf( MAXFLOAT ) ? 1 : 0;\n"
" intOut[1] = isnormal( MAXFLOAT ) ? 1 : 0;\n"
" intOut[2] = isnan( MAXFLOAT ) ? 1 : 0;\n"
" intOut[3] = sizeof( MAXFLOAT );\n"
" intOut[4] = ( MAXFLOAT == FLT_MAX ) ? 1 : 0;\n"
// " intOut[5] = ( MAXFLOAT == CL_FLT_MAX ) ? 1 : 0;\n"
" intOut[6] = ( MAXFLOAT == MAXFLOAT ) ? 1 : 0;\n"
" intOut[7] = ( MAXFLOAT == 0x1.fffffep127f ) ? 1 : 0;\n"
" floatOut[0] = MAXFLOAT;\n"
"}\n"
};
const char *kernel_constant_extended_limits[] = {
"__kernel void test( __global int *intOut, __global float *floatOut ) \n"
"{\n"
" intOut[0] = ( INFINITY == HUGE_VALF ) ? 1 : 0;\n"
" intOut[1] = sizeof( INFINITY );\n"
" intOut[2] = isinf( INFINITY ) ? 1 : 0;\n"
" intOut[3] = isnormal( INFINITY ) ? 1 : 0;\n"
" intOut[4] = isnan( INFINITY ) ? 1 : 0;\n"
" intOut[5] = ( INFINITY > MAXFLOAT ) ? 1 : 0;\n"
" intOut[6] = ( -INFINITY < -MAXFLOAT ) ? 1 : 0;\n"
" intOut[7] = ( ( MAXFLOAT + MAXFLOAT ) == INFINITY ) ? 1 : 0;\n"
" intOut[8] = ( nextafter( MAXFLOAT, INFINITY ) == INFINITY ) ? 1 : 0;\n"
" intOut[9] = ( nextafter( -MAXFLOAT, -INFINITY ) == -INFINITY ) ? 1 : 0;\n"
" intOut[10] = ( INFINITY == INFINITY ) ? 1 : 0;\n"
" intOut[11] = ( as_uint( INFINITY ) == 0x7f800000 ) ? 1 : 0;\n"
" floatOut[0] = INFINITY;\n"
"\n"
" intOut[12] = sizeof( HUGE_VALF );\n"
" intOut[13] = ( HUGE_VALF == INFINITY ) ? 1 : 0;\n"
" floatOut[1] = HUGE_VALF;\n"
"\n"
" intOut[14] = ( NAN == NAN ) ? 1 : 0;\n"
" intOut[15] = ( NAN != NAN ) ? 1 : 0;\n"
" intOut[16] = isnan( NAN ) ? 1 : 0;\n"
" intOut[17] = isinf( NAN ) ? 1 : 0;\n"
" intOut[18] = isnormal( NAN ) ? 1 : 0;\n"
" intOut[19] = ( ( as_uint( NAN ) & 0x7fffffff ) > 0x7f800000 ) ? 1 : 0;\n"
" intOut[20] = sizeof( NAN );\n"
" floatOut[2] = NAN;\n"
"\n"
" intOut[21] = isnan( INFINITY / INFINITY ) ? 1 : 0;\n"
" intOut[22] = isnan( INFINITY - INFINITY ) ? 1 : 0;\n"
" intOut[23] = isnan( 0.f / 0.f ) ? 1 : 0;\n"
" intOut[24] = isnan( INFINITY * 0.f ) ? 1 : 0;\n"
" intOut[25] = ( INFINITY == NAN ); \n"
" intOut[26] = ( -INFINITY == NAN ); \n"
" intOut[27] = ( INFINITY > NAN ); \n"
" intOut[28] = ( -INFINITY < NAN ); \n"
" intOut[29] = ( INFINITY != NAN ); \n"
" intOut[30] = ( NAN > INFINITY ); \n"
" intOut[31] = ( NAN < -INFINITY ); \n"
"}\n"
};
const char *kernel_constant_double_limits[] = {
"#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"
"__kernel void test( __global int *intOut, __global double *doubleOut ) \n"
"{\n"
" intOut[0] = sizeof( HUGE_VAL );\n"
" intOut[1] = ( HUGE_VAL == INFINITY ) ? 1 : 0;\n"
" intOut[2] = isinf( HUGE_VAL ) ? 1 : 0;\n"
" intOut[3] = isnormal( HUGE_VAL ) ? 1 : 0;\n"
" intOut[4] = isnan( HUGE_VAL ) ? 1 : 0;\n"
" intOut[5] = ( HUGE_VAL == HUGE_VALF ) ? 1 : 0;\n"
" intOut[6] = ( as_ulong( HUGE_VAL ) == 0x7ff0000000000000UL ) ? 1 : 0;\n"
" doubleOut[0] = HUGE_VAL;\n"
"}\n"
};
#define TEST_FLOAT_ASSERTION( a, msg, f ) if( !( a ) ) { log_error( "ERROR: Float constant failed requirement: %s (bitwise value is 0x%8.8x)\n", msg, *( (uint32_t *)&f ) ); return -1; }
#define TEST_DOUBLE_ASSERTION( a, msg, f ) if( !( a ) ) { log_error( "ERROR: Double constant failed requirement: %s (bitwise value is 0x%16.16llx)\n", msg, *( (uint64_t *)&f ) ); return -1; }
int test_kernel_limit_constants(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
int error;
size_t threads[] = {1,1,1};
clMemWrapper intStream, floatStream, doubleStream;
cl_int intOut[ 32 ];
cl_float floatOut[ 3 ];
cl_double doubleOut[ 1 ];
/* Create some I/O streams */
intStream = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(intOut), NULL,
&error);
test_error( error, "Creating test array failed" );
floatStream = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(floatOut),
NULL, &error);
test_error( error, "Creating test array failed" );
// Stage 1: basic limits on MAXFLOAT
{
clProgramWrapper program;
clKernelWrapper kernel;
if( create_single_kernel_helper( context, &program, &kernel, 1, kernel_constant_limits, "test" ) != 0 )
{
return -1;
}
error = clSetKernelArg( kernel, 0, sizeof( intStream ), &intStream );
test_error( error, "Unable to set indexed kernel arguments" );
error = clSetKernelArg( kernel, 1, sizeof( floatStream ), &floatStream );
test_error( error, "Unable to set indexed kernel arguments" );
error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL );
test_error( error, "Kernel execution failed" );
error = clEnqueueReadBuffer( queue, intStream, CL_TRUE, 0, sizeof(intOut), intOut, 0, NULL, NULL );
test_error( error, "Unable to get result data" );
error = clEnqueueReadBuffer( queue, floatStream, CL_TRUE, 0, sizeof(floatOut), floatOut, 0, NULL, NULL );
test_error( error, "Unable to get result data" );
// Test MAXFLOAT properties
TEST_FLOAT_ASSERTION( intOut[0] == 0, "isinf( MAXFLOAT ) = false", floatOut[0] )
TEST_FLOAT_ASSERTION( intOut[1] == 1, "isnormal( MAXFLOAT ) = true", floatOut[0] )
TEST_FLOAT_ASSERTION( intOut[2] == 0, "isnan( MAXFLOAT ) = false", floatOut[0] )
TEST_FLOAT_ASSERTION( intOut[3] == 4, "sizeof( MAXFLOAT ) = 4", floatOut[0] )
TEST_FLOAT_ASSERTION( intOut[4] == 1, "MAXFLOAT = FLT_MAX", floatOut[0] )
TEST_FLOAT_ASSERTION( floatOut[0] == CL_FLT_MAX, "MAXFLOAT = CL_FLT_MAX", floatOut[0] )
TEST_FLOAT_ASSERTION( intOut[6] == 1, "MAXFLOAT = MAXFLOAT", floatOut[0] )
TEST_FLOAT_ASSERTION( floatOut[0] == MAKE_HEX_FLOAT( 0x1.fffffep127f, 0x1fffffeL, 103), "MAXFLOAT = 0x1.fffffep127f", floatOut[0] )
}
// Stage 2: INFINITY and NAN
char profileStr[128] = "";
error = clGetDeviceInfo( deviceID, CL_DEVICE_PROFILE, sizeof( profileStr ), &profileStr, NULL );
test_error( error, "Unable to run INFINITY/NAN tests (unable to get CL_DEVICE_PROFILE" );
bool testInfNan = true;
if( strcmp( profileStr, "EMBEDDED_PROFILE" ) == 0 )
{
// We test if we're not an embedded profile, OR if the inf/nan flag in the config is set
cl_device_fp_config single = 0;
error = clGetDeviceInfo( deviceID, CL_DEVICE_SINGLE_FP_CONFIG, sizeof( single ), &single, NULL );
test_error( error, "Unable to run INFINITY/NAN tests (unable to get FP_CONFIG bits)" );
if( ( single & CL_FP_INF_NAN ) == 0 )
{
log_info( "Skipping INFINITY and NAN tests on embedded device (INF/NAN not supported on this device)" );
testInfNan = false;
}
}
if( testInfNan )
{
clProgramWrapper program;
clKernelWrapper kernel;
if( create_single_kernel_helper( context, &program, &kernel, 1, kernel_constant_extended_limits, "test" ) != 0 )
{
return -1;
}
error = clSetKernelArg( kernel, 0, sizeof( intStream ), &intStream );
test_error( error, "Unable to set indexed kernel arguments" );
error = clSetKernelArg( kernel, 1, sizeof( floatStream ), &floatStream );
test_error( error, "Unable to set indexed kernel arguments" );
error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL );
test_error( error, "Kernel execution failed" );
error = clEnqueueReadBuffer( queue, intStream, CL_TRUE, 0, sizeof(intOut), intOut, 0, NULL, NULL );
test_error( error, "Unable to get result data" );
error = clEnqueueReadBuffer( queue, floatStream, CL_TRUE, 0, sizeof(floatOut), floatOut, 0, NULL, NULL );
test_error( error, "Unable to get result data" );
TEST_FLOAT_ASSERTION( intOut[0] == 1, "INFINITY == HUGE_VALF", intOut[0] )
TEST_FLOAT_ASSERTION( intOut[1] == 4, "sizeof( INFINITY ) == 4", intOut[1] )
TEST_FLOAT_ASSERTION( intOut[2] == 1, "isinf( INFINITY ) == true", intOut[2] )
TEST_FLOAT_ASSERTION( intOut[3] == 0, "isnormal( INFINITY ) == false", intOut[3] )
TEST_FLOAT_ASSERTION( intOut[4] == 0, "isnan( INFINITY ) == false", intOut[4] )
TEST_FLOAT_ASSERTION( intOut[5] == 1, "INFINITY > MAXFLOAT", intOut[5] )
TEST_FLOAT_ASSERTION( intOut[6] == 1, "-INFINITY < -MAXFLOAT", intOut[6] )
TEST_FLOAT_ASSERTION( intOut[7] == 1, "( MAXFLOAT + MAXFLOAT ) == INFINITY", intOut[7] )
TEST_FLOAT_ASSERTION( intOut[8] == 1, "nextafter( MAXFLOAT, INFINITY ) == INFINITY", intOut[8] )
TEST_FLOAT_ASSERTION( intOut[9] == 1, "nextafter( -MAXFLOAT, -INFINITY ) == -INFINITY", intOut[9] )
TEST_FLOAT_ASSERTION( intOut[10] == 1, "INFINITY = INFINITY", intOut[10] )
TEST_FLOAT_ASSERTION( intOut[11] == 1, "asuint( INFINITY ) == 0x7f800000", intOut[11] )
TEST_FLOAT_ASSERTION( *( (uint32_t *)&floatOut[0] ) == 0x7f800000, "asuint( INFINITY ) == 0x7f800000", floatOut[0] )
TEST_FLOAT_ASSERTION( floatOut[1] == INFINITY, "INFINITY == INFINITY", floatOut[1] )
TEST_FLOAT_ASSERTION( intOut[12] == 4, "sizeof( HUGE_VALF ) == 4", intOut[12] )
TEST_FLOAT_ASSERTION( intOut[13] == 1, "HUGE_VALF == INFINITY", intOut[13] )
TEST_FLOAT_ASSERTION( floatOut[1] == HUGE_VALF, "HUGE_VALF == HUGE_VALF", floatOut[1] )
TEST_FLOAT_ASSERTION( intOut[14] == 0, "(NAN == NAN) = false", intOut[14] )
TEST_FLOAT_ASSERTION( intOut[15] == 1, "(NAN != NAN) = true", intOut[15] )
TEST_FLOAT_ASSERTION( intOut[16] == 1, "isnan( NAN ) = true", intOut[16] )
TEST_FLOAT_ASSERTION( intOut[17] == 0, "isinf( NAN ) = false", intOut[17] )
TEST_FLOAT_ASSERTION( intOut[18] == 0, "isnormal( NAN ) = false", intOut[18] )
TEST_FLOAT_ASSERTION( intOut[19] == 1, "( as_uint( NAN ) & 0x7fffffff ) > 0x7f800000", intOut[19] )
TEST_FLOAT_ASSERTION( intOut[20] == 4, "sizeof( NAN ) = 4", intOut[20] )
TEST_FLOAT_ASSERTION( ( *( (uint32_t *)&floatOut[2] ) & 0x7fffffff ) > 0x7f800000, "( as_uint( NAN ) & 0x7fffffff ) > 0x7f800000", floatOut[2] )
TEST_FLOAT_ASSERTION( intOut[ 21 ] == 1, "isnan( INFINITY / INFINITY ) = true", intOut[ 21 ] )
TEST_FLOAT_ASSERTION( intOut[ 22 ] == 1, "isnan( INFINITY - INFINITY ) = true", intOut[ 22 ] )
TEST_FLOAT_ASSERTION( intOut[ 23 ] == 1, "isnan( 0.f / 0.f ) = true", intOut[ 23 ] )
TEST_FLOAT_ASSERTION( intOut[ 24 ] == 1, "isnan( INFINITY * 0.f ) = true", intOut[ 24 ] )
TEST_FLOAT_ASSERTION( intOut[ 25 ] == 0, "( INFINITY == NAN ) = false", intOut[ 25 ] )
TEST_FLOAT_ASSERTION( intOut[ 26 ] == 0, "(-INFINITY == NAN ) = false", intOut[ 26 ] )
TEST_FLOAT_ASSERTION( intOut[ 27 ] == 0, "( INFINITY > NAN ) = false", intOut[ 27 ] )
TEST_FLOAT_ASSERTION( intOut[ 28 ] == 0, "(-INFINITY < NAN ) = false", intOut[ 28 ] )
TEST_FLOAT_ASSERTION( intOut[ 29 ] == 1, "( INFINITY != NAN ) = true", intOut[ 29 ] )
TEST_FLOAT_ASSERTION( intOut[ 30 ] == 0, "( NAN < INFINITY ) = false", intOut[ 30 ] )
TEST_FLOAT_ASSERTION( intOut[ 31 ] == 0, "( NAN > -INFINITY ) = false", intOut[ 31 ] )
}
// Stage 3: limits on HUGE_VAL (double)
if( !is_extension_available( deviceID, "cl_khr_fp64" ) )
log_info( "Note: Skipping double HUGE_VAL tests (doubles unsupported on device)\n" );
else
{
cl_device_fp_config config = 0;
error = clGetDeviceInfo( deviceID, CL_DEVICE_DOUBLE_FP_CONFIG, sizeof( config ), &config, NULL );
test_error( error, "Unable to run INFINITY/NAN tests (unable to get double FP_CONFIG bits)" );
if( ( config & CL_FP_INF_NAN ) == 0 )
log_info( "Skipping HUGE_VAL tests (INF/NAN not supported on this device)" );
else
{
clProgramWrapper program;
clKernelWrapper kernel;
if( create_single_kernel_helper( context, &program, &kernel, 1, kernel_constant_double_limits, "test" ) != 0 )
{
return -1;
}
doubleStream = clCreateBuffer(context, CL_MEM_READ_WRITE,
sizeof(doubleOut), NULL, &error);
test_error( error, "Creating test array failed" );
error = clSetKernelArg( kernel, 0, sizeof( intStream ), &intStream );
test_error( error, "Unable to set indexed kernel arguments" );
error = clSetKernelArg( kernel, 1, sizeof( doubleStream ), &doubleStream );
test_error( error, "Unable to set indexed kernel arguments" );
error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL );
test_error( error, "Kernel execution failed" );
error = clEnqueueReadBuffer( queue, intStream, CL_TRUE, 0, sizeof(intOut), intOut, 0, NULL, NULL );
test_error( error, "Unable to get result data" );
error = clEnqueueReadBuffer( queue, doubleStream, CL_TRUE, 0, sizeof(doubleOut), doubleOut, 0, NULL, NULL );
test_error( error, "Unable to get result data" );
TEST_DOUBLE_ASSERTION( intOut[0] == 8, "sizeof( HUGE_VAL ) = 8", intOut[0] )
TEST_DOUBLE_ASSERTION( intOut[1] == 1, "HUGE_VAL = INFINITY", intOut[1] )
TEST_DOUBLE_ASSERTION( intOut[2] == 1, "isinf( HUGE_VAL ) = true", intOut[2] )
TEST_DOUBLE_ASSERTION( intOut[3] == 0, "isnormal( HUGE_VAL ) = false", intOut[3] )
TEST_DOUBLE_ASSERTION( intOut[4] == 0, "isnan( HUGE_VAL ) = false", intOut[4] )
TEST_DOUBLE_ASSERTION( intOut[5] == 1, "HUGE_VAL = HUGE_VAL", intOut[5] )
TEST_DOUBLE_ASSERTION( intOut[6] == 1, "as_ulong( HUGE_VAL ) = 0x7ff0000000000000UL", intOut[6] )
TEST_DOUBLE_ASSERTION( *( (uint64_t *)&doubleOut[0] ) == 0x7ff0000000000000ULL, "as_ulong( HUGE_VAL ) = 0x7ff0000000000000UL", doubleOut[0] )
}
}
return 0;
}