mirror of
https://github.com/KhronosGroup/OpenCL-CTS.git
synced 2026-03-19 14:09:03 +00:00
The maintenance of the conformance tests is moving to Github. This commit contains all the changes that have been done in Gitlab since the first public release of the conformance tests. Signed-off-by: Kevin Petit <kevin.petit@arm.com>
390 lines
12 KiB
C
390 lines
12 KiB
C
//
|
|
// 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 <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include "procs.h"
|
|
|
|
|
|
|
|
cl_int get_type_size( cl_context context, cl_command_queue queue, const char *type, cl_ulong *size )
|
|
{
|
|
const char *sizeof_kernel_code[4] =
|
|
{
|
|
"", /* optional pragma string */
|
|
"__kernel __attribute__((reqd_work_group_size(1,1,1))) void test_sizeof(__global uint *dst) \n"
|
|
"{\n"
|
|
" dst[0] = (uint) sizeof( ", type, " );\n"
|
|
"}\n"
|
|
};
|
|
|
|
cl_program p;
|
|
cl_kernel k;
|
|
cl_mem m;
|
|
cl_uint temp;
|
|
|
|
if ( strncmp(type, "double", 6) == 0)
|
|
sizeof_kernel_code[0] = "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n";
|
|
|
|
cl_int err = create_single_kernel_helper( context, &p, &k, 4, sizeof_kernel_code, "test_sizeof" );
|
|
if( err )
|
|
return err;
|
|
|
|
m = clCreateBuffer( context, CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, sizeof( cl_ulong ), size, &err );
|
|
if( NULL == m )
|
|
{
|
|
clReleaseProgram( p );
|
|
clReleaseKernel( k );
|
|
log_error("\nclCreateBuffer FAILED\n");
|
|
return err;
|
|
}
|
|
|
|
err = clSetKernelArg( k, 0, sizeof( cl_mem ), &m );
|
|
if( err )
|
|
{
|
|
clReleaseProgram( p );
|
|
clReleaseKernel( k );
|
|
clReleaseMemObject( m );
|
|
log_error("\nclSetKernelArg FAILED\n");
|
|
return err;
|
|
}
|
|
|
|
err = clEnqueueTask( queue, k, 0, NULL, NULL );
|
|
clReleaseProgram( p );
|
|
clReleaseKernel( k );
|
|
if( err )
|
|
{
|
|
clReleaseMemObject( m );
|
|
log_error( "\nclEnqueueTask FAILED\n" );
|
|
return err;
|
|
}
|
|
|
|
err = clEnqueueReadBuffer( queue, m, CL_TRUE, 0, sizeof( cl_uint ), &temp, 0, NULL, NULL );
|
|
clReleaseMemObject( m );
|
|
if( err )
|
|
log_error( "\nclEnqueueReadBuffer FAILED\n" );
|
|
|
|
*size = (cl_ulong) temp;
|
|
|
|
return err;
|
|
}
|
|
|
|
typedef struct size_table
|
|
{
|
|
const char *name;
|
|
cl_ulong size;
|
|
cl_ulong cl_size;
|
|
}size_table;
|
|
|
|
const size_table scalar_table[] =
|
|
{
|
|
// Fixed size entries from table 6.1
|
|
{ "char", 1, sizeof( cl_char ) },
|
|
{ "uchar", 1, sizeof( cl_uchar) },
|
|
{ "unsigned char", 1, sizeof( cl_uchar) },
|
|
{ "short", 2, sizeof( cl_short) },
|
|
{ "ushort", 2, sizeof( cl_ushort) },
|
|
{ "unsigned short", 2, sizeof( cl_ushort) },
|
|
{ "int", 4, sizeof( cl_int ) },
|
|
{ "uint", 4, sizeof( cl_uint) },
|
|
{ "unsigned int", 4, sizeof( cl_uint) },
|
|
{ "float", 4, sizeof( cl_float) },
|
|
{ "long", 8, sizeof( cl_long ) },
|
|
{ "ulong", 8, sizeof( cl_ulong) },
|
|
{ "unsigned long", 8, sizeof( cl_ulong) }
|
|
};
|
|
|
|
const size_table vector_table[] =
|
|
{
|
|
// Fixed size entries from table 6.1
|
|
{ "char", 1, sizeof( cl_char ) },
|
|
{ "uchar", 1, sizeof( cl_uchar) },
|
|
{ "short", 2, sizeof( cl_short) },
|
|
{ "ushort", 2, sizeof( cl_ushort) },
|
|
{ "int", 4, sizeof( cl_int ) },
|
|
{ "uint", 4, sizeof( cl_uint) },
|
|
{ "float", 4, sizeof( cl_float) },
|
|
{ "long", 8, sizeof( cl_long ) },
|
|
{ "ulong", 8, sizeof( cl_ulong) }
|
|
};
|
|
|
|
const char *ptr_table[] =
|
|
{
|
|
"global void*",
|
|
"size_t",
|
|
"sizeof(int)", // check return type of sizeof
|
|
"ptrdiff_t"
|
|
};
|
|
|
|
const char *other_types[] =
|
|
{
|
|
"event_t",
|
|
"image2d_t",
|
|
"image3d_t",
|
|
"sampler_t"
|
|
};
|
|
|
|
static int IsPowerOfTwo( cl_ulong x ){ return 0 == (x & (x-1)); }
|
|
|
|
int test_sizeof(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
|
|
{
|
|
size_t i, j;
|
|
cl_ulong test;
|
|
cl_uint ptr_size = CL_UINT_MAX;
|
|
cl_int err = CL_SUCCESS;
|
|
|
|
// Check address space size
|
|
err = clGetDeviceInfo(device, CL_DEVICE_ADDRESS_BITS, sizeof(ptr_size), &ptr_size, NULL);
|
|
if( err || ptr_size > 64)
|
|
{
|
|
log_error( "FAILED: Unable to get CL_DEVICE_ADDRESS_BITS for device %p\n", device );
|
|
return -1;
|
|
}
|
|
log_info( "\tCL_DEVICE_ADDRESS_BITS = %u\n", ptr_size );
|
|
ptr_size /= 8;
|
|
|
|
// Test standard scalar sizes
|
|
for( i = 0; i < sizeof( scalar_table ) / sizeof( scalar_table[0] ); i++ )
|
|
{
|
|
if( ! gHasLong &&
|
|
(0 == strcmp(scalar_table[i].name, "long") ||
|
|
0 == strcmp(scalar_table[i].name, "ulong") ||
|
|
0 == strcmp(scalar_table[i].name, "unsigned long")))
|
|
{
|
|
log_info("\nLongs are not supported by this device. Skipping test.\t");
|
|
continue;
|
|
}
|
|
|
|
test = CL_ULONG_MAX;
|
|
err = get_type_size( context, queue, scalar_table[i].name, &test );
|
|
if( err )
|
|
return err;
|
|
if( test != scalar_table[i].size )
|
|
{
|
|
log_error( "\nFAILED: Type %s has size %lld, but expected size %lld!\n", scalar_table[i].name, test, scalar_table[i].size );
|
|
return -1;
|
|
}
|
|
if( test != scalar_table[i].cl_size )
|
|
{
|
|
log_error( "\nFAILED: Type %s has size %lld, but cl_ size is %lld!\n", scalar_table[i].name, test, scalar_table[i].cl_size );
|
|
return -2;
|
|
}
|
|
log_info( "%16s", scalar_table[i].name );
|
|
}
|
|
log_info( "\n" );
|
|
|
|
// Test standard vector sizes
|
|
for( j = 2; j <= 16; j *= 2 )
|
|
{
|
|
// For each vector size, iterate through types
|
|
for( i = 0; i < sizeof( vector_table ) / sizeof( vector_table[0] ); i++ )
|
|
{
|
|
if( !gHasLong &&
|
|
(0 == strcmp(vector_table[i].name, "long") ||
|
|
0 == strcmp(vector_table[i].name, "ulong")))
|
|
{
|
|
log_info("\nLongs are not supported by this device. Skipping test.\t");
|
|
continue;
|
|
}
|
|
|
|
char name[32];
|
|
sprintf( name, "%s%ld", vector_table[i].name, j );
|
|
|
|
test = CL_ULONG_MAX;
|
|
err = get_type_size( context, queue, name, &test );
|
|
if( err )
|
|
return err;
|
|
if( test != j * vector_table[i].size )
|
|
{
|
|
log_error( "\nFAILED: Type %s has size %lld, but expected size %lld!\n", name, test, j * vector_table[i].size );
|
|
return -1;
|
|
}
|
|
if( test != j * vector_table[i].cl_size )
|
|
{
|
|
log_error( "\nFAILED: Type %s has size %lld, but cl_ size is %lld!\n", name, test, j * vector_table[i].cl_size );
|
|
return -2;
|
|
}
|
|
log_info( "%16s", name );
|
|
}
|
|
log_info( "\n" );
|
|
}
|
|
|
|
//Check that pointer sizes are correct
|
|
for( i = 0; i < sizeof( ptr_table ) / sizeof( ptr_table[0] ); i++ )
|
|
{
|
|
test = CL_ULONG_MAX;
|
|
err = get_type_size( context, queue, ptr_table[i], &test );
|
|
if( err )
|
|
return err;
|
|
if( test != ptr_size )
|
|
{
|
|
log_error( "\nFAILED: Type %s has size %lld, but expected size %u!\n", ptr_table[i], test, ptr_size );
|
|
return -1;
|
|
}
|
|
log_info( "%16s", ptr_table[i] );
|
|
}
|
|
|
|
// Check that intptr_t is large enough
|
|
test = CL_ULONG_MAX;
|
|
err = get_type_size( context, queue, "intptr_t", &test );
|
|
if( err )
|
|
return err;
|
|
if( test < ptr_size )
|
|
{
|
|
log_error( "\nFAILED: intptr_t has size %lld, but must be at least %u!\n", test, ptr_size );
|
|
return -1;
|
|
}
|
|
if( ! IsPowerOfTwo( test ) )
|
|
{
|
|
log_error( "\nFAILED: sizeof(intptr_t) is %lld, but must be a power of two!\n", test );
|
|
return -2;
|
|
}
|
|
log_info( "%16s", "intptr_t" );
|
|
|
|
// Check that uintptr_t is large enough
|
|
test = CL_ULONG_MAX;
|
|
err = get_type_size( context, queue, "uintptr_t", &test );
|
|
if( err )
|
|
return err;
|
|
if( test < ptr_size )
|
|
{
|
|
log_error( "\nFAILED: uintptr_t has size %lld, but must be at least %u!\n", test, ptr_size );
|
|
return -1;
|
|
}
|
|
if( ! IsPowerOfTwo( test ) )
|
|
{
|
|
log_error( "\nFAILED: sizeof(uintptr_t) is %lld, but must be a power of two!\n", test );
|
|
return -2;
|
|
}
|
|
log_info( "%16s\n", "uintptr_t" );
|
|
|
|
//Check that other types are powers of two
|
|
for( i = 0; i < sizeof( other_types ) / sizeof( other_types[0] ); i++ )
|
|
{
|
|
if( 0 == strcmp(other_types[i], "image2d_t") &&
|
|
checkForImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED)
|
|
{
|
|
log_info("\nimages are not supported by this device. Skipping test.\t");
|
|
continue;
|
|
}
|
|
|
|
if( gIsEmbedded &&
|
|
0 == strcmp(other_types[i], "image3d_t") &&
|
|
checkFor3DImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED)
|
|
{
|
|
log_info("\n3D images are not supported by this device. Skipping test.\t");
|
|
continue;
|
|
}
|
|
|
|
if( 0 == strcmp(other_types[i], "sampler_t") &&
|
|
checkForImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED)
|
|
{
|
|
log_info("\nimages are not supported by this device. Skipping test.\t");
|
|
continue;
|
|
}
|
|
|
|
test = CL_ULONG_MAX;
|
|
err = get_type_size( context, queue, other_types[i], &test );
|
|
if( err )
|
|
return err;
|
|
if( ! IsPowerOfTwo( test ) )
|
|
{
|
|
log_error( "\nFAILED: Type %s has size %lld, which is not a power of two (section 6.1.5)!\n", other_types[i], test );
|
|
return -1;
|
|
}
|
|
log_info( "%16s", other_types[i] );
|
|
}
|
|
log_info( "\n" );
|
|
|
|
|
|
//Check double
|
|
if( is_extension_available( device, "cl_khr_fp64" ) )
|
|
{
|
|
log_info( "\tcl_khr_fp64:" );
|
|
test = CL_ULONG_MAX;
|
|
err = get_type_size( context, queue, "double", &test );
|
|
if( err )
|
|
return err;
|
|
if( test != 8 )
|
|
{
|
|
log_error( "\nFAILED: double has size %lld, but must be 8!\n", test );
|
|
return -1;
|
|
}
|
|
log_info( "%16s", "double" );
|
|
|
|
// Test standard vector sizes
|
|
for( j = 2; j <= 16; j *= 2 )
|
|
{
|
|
char name[32];
|
|
sprintf( name, "double%ld", j );
|
|
|
|
test = CL_ULONG_MAX;
|
|
err = get_type_size( context, queue, name, &test );
|
|
if( err )
|
|
return err;
|
|
if( test != 8*j )
|
|
{
|
|
log_error( "\nFAILED: %s has size %lld, but must be %ld!\n", name, test, 8 * j);
|
|
return -1;
|
|
}
|
|
log_info( "%16s", name );
|
|
}
|
|
log_info( "\n" );
|
|
}
|
|
|
|
//Check half
|
|
if( is_extension_available( device, "cl_khr_fp16" ) )
|
|
{
|
|
log_info( "\tcl_khr_fp16:" );
|
|
test = CL_ULONG_MAX;
|
|
err = get_type_size( context, queue, "half", &test );
|
|
if( err )
|
|
return err;
|
|
if( test != 2 )
|
|
{
|
|
log_error( "\nFAILED: half has size %lld, but must be 2!\n", test );
|
|
return -1;
|
|
}
|
|
log_info( "%16s", "half" );
|
|
|
|
// Test standard vector sizes
|
|
for( j = 2; j <= 16; j *= 2 )
|
|
{
|
|
char name[32];
|
|
sprintf( name, "half%ld", j );
|
|
|
|
test = CL_ULONG_MAX;
|
|
err = get_type_size( context, queue, name, &test );
|
|
if( err )
|
|
return err;
|
|
if( test != 2*j )
|
|
{
|
|
log_error( "\nFAILED: %s has size %lld, but must be %ld!\n", name, test, 2 * j);
|
|
return -1;
|
|
}
|
|
log_info( "%16s", name );
|
|
}
|
|
log_info( "\n" );
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|