Correct khr Extension Checks for Device Versions (#778)

* Correct khronos extension device version checks so that 2.0, 2.1 and
2.2 extensions are only require for devices versions < 3.0
(`cl_khr_3d_image_writes`, `cl_khr_image2d_from_buffer` and
`cl_khr_depth_images` are all optional for devices supporting
OpenCL-3.0).

* Remove `cl_khr_fp64` from list or required extensions for 2.0,
`cl_khr_fp64` is a required extension for OpenCL-1.2 devices if they
suport doubles. Check for support of `cl_khr_fp64` on 1.2 devices.

* Remove duplicated `cl_khr_byte_addressable_store` from list of 2.0
extensions. Since this is a 1.1 extension and all versions greater than
1.1 are backwards compatible with 1.1 this will be checked anyway.
This commit is contained in:
Jack Frankland
2020-05-20 14:16:37 +01:00
committed by GitHub
parent 4fbcd96e7f
commit f6b156d523

View File

@@ -1850,145 +1850,97 @@ int test_min_max_queue_properties(cl_device_id deviceID, cl_context context, cl_
int test_min_max_device_version(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) int test_min_max_device_version(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{ {
cl_int error, i; // Query for the device version.
cl_char buffer[ 4098 ]; Version device_cl_version = get_device_cl_version(deviceID);
size_t length; log_info("Returned version %s.\n", device_cl_version.to_string().c_str());
// Make sure 2.x devices support required extensions for 2.x
// Device version should fit the regex "OpenCL [0-9]+\.[0-9]+ *.*" // note: these extensions are **not** required for devices
error = clGetDeviceInfo( deviceID, CL_DEVICE_VERSION, sizeof( buffer ), buffer, &length ); // supporting OpenCL-3.0
test_error( error, "Unable to get device version string" ); const char *requiredExtensions2x[] = {
if( memcmp( buffer, "OpenCL ", strlen( "OpenCL " ) ) != 0 )
{
log_error( "ERROR: Initial part of device version string does not match required format! (returned: %s)\n", (char *)buffer );
return -1;
}
log_info("Returned version %s.\n", buffer);
char *p1 = (char *)buffer + strlen( "OpenCL " );
while( *p1 == ' ' )
p1++;
char *p2 = p1;
if( ! isdigit(*p2) )
{
log_error( "ERROR: Major revision number must follow space behind OpenCL! (returned %s)\n", (char*) buffer );
return -1;
}
while( isdigit( *p2 ) )
p2++;
if( *p2 != '.' )
{
log_error( "ERROR: Version number must contain a decimal point! (returned: %s)\n", (char *)buffer );
return -1;
}
char *p3 = p2 + 1;
if( ! isdigit(*p3) )
{
log_error( "ERROR: Minor revision number is missing or does not abut the decimal point! (returned %s)\n", (char*) buffer );
return -1;
}
while( isdigit( *p3 ) )
p3++;
if( *p3 != ' ' )
{
log_error( "ERROR: A space must appear after the minor version! (returned: %s)\n", (char *)buffer );
return -1;
}
*p2 = ' '; // Put in a space for atoi below.
p2++;
int major = atoi( p1 );
int minor = atoi( p2 );
int minor_revision = 2;
if( getenv("OPENCL_1_0_DEVICE"))
{
minor_revision = 0;
log_info( "WARNING: This test was run with OPENCL_1_0_DEVICE defined! This is not a OpenCL 1.1 or OpenCL 1.2 compatible device!!!\n" );
}
else if( getenv("OPENCL_1_1_DEVICE"))
{
minor_revision = 1;
log_info( "WARNING: This test was run with OPENCL_1_1_DEVICE defined! This is not a OpenCL 1.2 compatible device!!!\n" );
}
if( major * 10 + minor < 10 + minor_revision )
{
log_error( "ERROR: OpenCL device version returned is less than 1.%d! (Returned: %s)\n", minor_revision, (char *)buffer );
return -1;
}
// Sanity checks on the returned values
if( length != (strlen( (char *)buffer ) + 1 ))
{
log_error( "ERROR: Returned length of version string does not match actual length (actual: %d, returned: %d)\n", (int)strlen( (char *)buffer ), (int)length );
return -1;
}
// Make sure 2.0 devices support required extensions for 2.0
const char *requiredExtensions20[] =
{
"cl_khr_byte_addressable_store",
"cl_khr_3d_image_writes", "cl_khr_3d_image_writes",
"cl_khr_image2d_from_buffer", "cl_khr_image2d_from_buffer",
"cl_khr_depth_images", "cl_khr_depth_images",
"cl_khr_fp64",
}; };
// Make sure 1.1 devices support required extensions for 1.1 // Make sure 1.1 devices support required extensions for 1.1
const char *requiredExtensions[] = const char *requiredExtensions11[] = {
{
"cl_khr_global_int32_base_atomics", "cl_khr_global_int32_base_atomics",
"cl_khr_global_int32_extended_atomics", "cl_khr_global_int32_extended_atomics",
"cl_khr_local_int32_base_atomics", "cl_khr_local_int32_base_atomics",
"cl_khr_local_int32_extended_atomics", "cl_khr_local_int32_extended_atomics",
"cl_khr_byte_addressable_store", "cl_khr_byte_addressable_store",
NULL
}; };
if( major * 10 + minor >= 11 )
if (device_cl_version >= Version(1, 1))
{ {
log_info( "Checking for required extensions for OpenCL 1.1 and later devices...\n" ); log_info("Checking for required extensions for OpenCL 1.1 and later "
for( i = 0; NULL != requiredExtensions[i]; i++ ) "devices...\n");
for (int i = 0; i < ARRAY_SIZE(requiredExtensions11); i++)
{ {
if(!is_extension_available(deviceID, requiredExtensions[i])) if (!is_extension_available(deviceID, requiredExtensions11[i]))
{ {
log_error( "ERROR: Required extension for 1.1 and greater devices is not in extension string: %s\n", requiredExtensions[i] ); log_error("ERROR: Required extension for 1.1 and greater "
"devices is not in extension string: %s\n",
requiredExtensions11[i]);
return -1; return -1;
} }
else else
log_info( "\t%s\n", requiredExtensions[i] ); log_info("\t%s\n", requiredExtensions11[i]);
} }
if( major >= 2 ) if (device_cl_version >= Version(1, 2))
{ {
log_info( "Checking for required extensions for OpenCL 2.0 and later devices...\n" ); log_info("Checking for required extensions for OpenCL 1.2 and "
"later devices...\n");
// Check if double precision is supported, if it is, then check the extension "cl_khr_fp64" // The only required extension for an OpenCL-1.2 device is
cl_device_fp_config value; // cl_khr_fp64 and it is only required if double precision is
int numRequiredExtension20 = sizeof(requiredExtensions20)/sizeof(char *); // supported.
cl_device_fp_config doubles_supported;
error = clGetDeviceInfo( deviceID, CL_DEVICE_DOUBLE_FP_CONFIG, sizeof( value ), &value, 0 ); cl_int error = clGetDeviceInfo(deviceID, CL_DEVICE_DOUBLE_FP_CONFIG,
sizeof(doubles_supported),
&doubles_supported, 0);
test_error(error, "Unable to get device double fp config"); test_error(error, "Unable to get device double fp config");
if (doubles_supported)
// if double precision is not supported, then don't check extension "cl_khr_fp64"
numRequiredExtension20 -= (value == 0);
for( i = 0; i<numRequiredExtension20; i++ )
{ {
if(!is_extension_available(deviceID, requiredExtensions20[i])) if (!is_extension_available(deviceID, "cl_khr_fp64"))
{ {
log_error( "ERROR: Required extension for 2.0 and greater devices is not in extension string: %s\n", requiredExtensions20[i] ); log_error(
"ERROR: Required extension for 1.2 and greater devices "
"is not in extension string: cl_khr_fp64\n");
}
else
{
log_info("\t%s\n", "cl_khr_fp64");
}
}
}
if (device_cl_version >= Version(2, 0)
&& device_cl_version < Version(3, 0))
{
log_info("Checking for required extensions for OpenCL 2.0, 2.1 and "
"2.2 devices...\n");
for (int i = 0; i < ARRAY_SIZE(requiredExtensions2x); i++)
{
if (!is_extension_available(deviceID, requiredExtensions2x[i]))
{
log_error("ERROR: Required extension for 2.0, 2.1 and 2.2 "
"devices is not in extension string: %s\n",
requiredExtensions2x[i]);
return -1; return -1;
} }
else else
log_info( "\t%s\n", requiredExtensions20[i] ); {
log_info("\t%s\n", requiredExtensions2x[i]);
}
} }
} }
} }
else else
log_info( "WARNING: skipping required extension test -- OpenCL 1.0 device.\n" ); log_info("WARNING: skipping required extension test -- OpenCL 1.0 "
"device.\n");
return 0; return 0;
} }