mirror of
https://github.com/KhronosGroup/OpenCL-CTS.git
synced 2026-03-25 08:19:02 +00:00
Dynamically Select -cl-std Option (#879)
* Dynamically select the `-cl-std` option on the basic `sizeof` and `wg_barrier` tests to be one of `CL1.X`, `CL2.0` or `CL3.0`. Use the most recent CL C standard supported on the device.
This commit is contained in:
@@ -29,6 +29,7 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
std::string slash = "\\";
|
std::string slash = "\\";
|
||||||
@@ -809,6 +810,43 @@ int create_single_kernel_helper(cl_context context,
|
|||||||
const char *buildOptions,
|
const char *buildOptions,
|
||||||
const bool openclCXX)
|
const bool openclCXX)
|
||||||
{
|
{
|
||||||
|
// For the logic that automatically adds -cl-std it is much cleaner if the
|
||||||
|
// build options have RAII. This buffer will store the potentially updated
|
||||||
|
// build options, in which case buildOptions will point at the string owned
|
||||||
|
// by this buffer.
|
||||||
|
std::string build_options_internal{ buildOptions ? buildOptions : "" };
|
||||||
|
|
||||||
|
// Check the build options for the -cl-std option.
|
||||||
|
if (!buildOptions || !strstr(buildOptions, "-cl-std"))
|
||||||
|
{
|
||||||
|
// If the build option isn't present add it using the latest OpenCL-C
|
||||||
|
// version supported by the device. This allows calling code to force a
|
||||||
|
// particular CL C version if it is required, but also means that
|
||||||
|
// callers need not specify a version if they want to assume the most
|
||||||
|
// recent CL C.
|
||||||
|
|
||||||
|
auto version = get_max_OpenCL_C_for_context(context);
|
||||||
|
|
||||||
|
std::string cl_std{};
|
||||||
|
if (version >= Version(3, 0))
|
||||||
|
{
|
||||||
|
cl_std = "-cl-std=CL3.0";
|
||||||
|
}
|
||||||
|
else if (version >= Version(2, 0) && version < Version(3, 0))
|
||||||
|
{
|
||||||
|
cl_std = "-cl-std=CL2.0";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If the -cl-std build option is not specified, the highest OpenCL
|
||||||
|
// C 1.x language version supported by each device is used when
|
||||||
|
// compiling the program for each device.
|
||||||
|
cl_std = "";
|
||||||
|
}
|
||||||
|
build_options_internal += ' ';
|
||||||
|
build_options_internal += cl_std;
|
||||||
|
buildOptions = build_options_internal.c_str();
|
||||||
|
}
|
||||||
int error;
|
int error;
|
||||||
// Create OpenCL C++ program
|
// Create OpenCL C++ program
|
||||||
if(openclCXX)
|
if(openclCXX)
|
||||||
@@ -1543,3 +1581,115 @@ int printDeviceHeader( cl_device_id device )
|
|||||||
|
|
||||||
return CL_SUCCESS;
|
return CL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Version get_device_cl_c_version(cl_device_id device)
|
||||||
|
{
|
||||||
|
// Get the device OpenCL version.
|
||||||
|
auto device_cl_version = get_device_cl_version(device);
|
||||||
|
|
||||||
|
// If the device version >= 3.0 it must support the
|
||||||
|
// CL_DEVICE_OPENCL_C_ALL_VERSIONS query from which we can extract the most
|
||||||
|
// recent CL C version supported by the device.
|
||||||
|
if (device_cl_version >= Version{ 3, 0 })
|
||||||
|
{
|
||||||
|
size_t opencl_c_all_versions_size_in_bytes{};
|
||||||
|
auto error =
|
||||||
|
clGetDeviceInfo(device, CL_DEVICE_OPENCL_C_ALL_VERSIONS, 0, nullptr,
|
||||||
|
&opencl_c_all_versions_size_in_bytes);
|
||||||
|
test_error_ret(
|
||||||
|
error, "clGetDeviceInfo failed for CL_DEVICE_OPENCL_C_ALL_VERSIONS",
|
||||||
|
(Version{ -1, 0 }));
|
||||||
|
std::vector<cl_name_version> name_versions(
|
||||||
|
opencl_c_all_versions_size_in_bytes / sizeof(cl_name_version));
|
||||||
|
error = clGetDeviceInfo(device, CL_DEVICE_OPENCL_C_ALL_VERSIONS,
|
||||||
|
opencl_c_all_versions_size_in_bytes,
|
||||||
|
name_versions.data(), nullptr);
|
||||||
|
test_error_ret(
|
||||||
|
error, "clGetDeviceInfo failed for CL_DEVICE_OPENCL_C_ALL_VERSIONS",
|
||||||
|
(Version{ -1, 0 }));
|
||||||
|
|
||||||
|
Version max_supported_cl_c_version{};
|
||||||
|
for (const auto &name_version : name_versions)
|
||||||
|
{
|
||||||
|
Version current_version{ CL_VERSION_MAJOR(name_version.version),
|
||||||
|
CL_VERSION_MINOR(name_version.version) };
|
||||||
|
max_supported_cl_c_version =
|
||||||
|
(current_version > max_supported_cl_c_version)
|
||||||
|
? current_version
|
||||||
|
: max_supported_cl_c_version;
|
||||||
|
}
|
||||||
|
return max_supported_cl_c_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The second special case is OpenCL-1.0 where CL_DEVICE_OPENCL_C_VERSION
|
||||||
|
// did not exist, but since this is just the first version we can
|
||||||
|
// return 1.0.
|
||||||
|
if (device_cl_version == Version{ 1, 0 })
|
||||||
|
{
|
||||||
|
return Version{ 1, 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise we know we have a 1.1 <= device_version <= 2.0 where all CL C
|
||||||
|
// versions are backwards compatible, hence querying with the
|
||||||
|
// CL_DEVICE_OPENCL_C_VERSION query must return the most recent supported
|
||||||
|
// OpenCL C version.
|
||||||
|
size_t opencl_c_version_size_in_bytes{};
|
||||||
|
auto error = clGetDeviceInfo(device, CL_DEVICE_OPENCL_C_VERSION, 0, nullptr,
|
||||||
|
&opencl_c_version_size_in_bytes);
|
||||||
|
test_error_ret(error,
|
||||||
|
"clGetDeviceInfo failed for CL_DEVICE_OPENCL_C_VERSION\n",
|
||||||
|
(Version{ -1, 0 }));
|
||||||
|
|
||||||
|
std::string opencl_c_version(opencl_c_version_size_in_bytes, '\0');
|
||||||
|
error =
|
||||||
|
clGetDeviceInfo(device, CL_DEVICE_OPENCL_C_VERSION,
|
||||||
|
opencl_c_version.size(), &opencl_c_version[0], nullptr);
|
||||||
|
|
||||||
|
test_error_ret(error,
|
||||||
|
"clGetDeviceInfo failed for CL_DEVICE_OPENCL_C_VERSION\n",
|
||||||
|
(Version{ -1, 0 }));
|
||||||
|
|
||||||
|
// Scrape out the major, minor pair from the string.
|
||||||
|
auto major = opencl_c_version[opencl_c_version.find('.') - 1];
|
||||||
|
auto minor = opencl_c_version[opencl_c_version.find('.') + 1];
|
||||||
|
|
||||||
|
return Version{ major - '0', minor - '0' };
|
||||||
|
}
|
||||||
|
|
||||||
|
Version get_max_OpenCL_C_for_context(cl_context context)
|
||||||
|
{
|
||||||
|
// Get all the devices in the context and find the maximum
|
||||||
|
// universally supported OpenCL C version.
|
||||||
|
size_t devices_size_in_bytes{};
|
||||||
|
auto error = clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, nullptr,
|
||||||
|
&devices_size_in_bytes);
|
||||||
|
test_error_ret(error, "clGetDeviceInfo failed for CL_CONTEXT_DEVICES",
|
||||||
|
(Version{ -1, 0 }));
|
||||||
|
std::vector<cl_device_id> devices(devices_size_in_bytes
|
||||||
|
/ sizeof(cl_device_id));
|
||||||
|
error = clGetContextInfo(context, CL_CONTEXT_DEVICES, devices_size_in_bytes,
|
||||||
|
devices.data(), nullptr);
|
||||||
|
auto current_version = get_device_cl_c_version(devices[0]);
|
||||||
|
std::for_each(std::next(devices.begin()), devices.end(),
|
||||||
|
[¤t_version](cl_device_id device) {
|
||||||
|
auto device_version = get_device_cl_c_version(device);
|
||||||
|
// OpenCL 3.0 is not backwards compatible with 2.0.
|
||||||
|
// If we have 3.0 and 2.0 in the same driver we
|
||||||
|
// use 1.2.
|
||||||
|
if (((device_version >= Version(2, 0)
|
||||||
|
&& device_version < Version(3, 0))
|
||||||
|
&& current_version >= Version(3, 0))
|
||||||
|
|| (device_version >= Version(3, 0)
|
||||||
|
&& (current_version >= Version(2, 0)
|
||||||
|
&& current_version < Version(3, 0))))
|
||||||
|
{
|
||||||
|
current_version = Version(1, 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current_version =
|
||||||
|
(std::min)(device_version, current_version);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return current_version;
|
||||||
|
}
|
||||||
|
|||||||
@@ -173,4 +173,12 @@ cl_device_fp_config get_default_rounding_mode( cl_device_id device );
|
|||||||
/* Prints out the standard device header for all tests given the device to print for */
|
/* Prints out the standard device header for all tests given the device to print for */
|
||||||
extern int printDeviceHeader( cl_device_id device );
|
extern int printDeviceHeader( cl_device_id device );
|
||||||
|
|
||||||
|
// Gets the latest (potentially non-backward compatible) OpenCL C version
|
||||||
|
// supported by the device.
|
||||||
|
Version get_device_cl_c_version(cl_device_id device);
|
||||||
|
|
||||||
|
// Gets the maximum universally supported OpenCL C version in a context, i.e.
|
||||||
|
// the OpenCL C version supported by all devices in a context.
|
||||||
|
Version get_max_OpenCL_C_for_context(cl_context context);
|
||||||
|
|
||||||
#endif // _kernelHelpers_h
|
#endif // _kernelHelpers_h
|
||||||
|
|||||||
@@ -49,13 +49,8 @@ cl_int get_type_size( cl_context context, cl_command_queue queue, const char *ty
|
|||||||
{
|
{
|
||||||
sizeof_kernel_code[0] = "#pragma OPENCL EXTENSION cl_khr_fp16 : enable\n";
|
sizeof_kernel_code[0] = "#pragma OPENCL EXTENSION cl_khr_fp16 : enable\n";
|
||||||
}
|
}
|
||||||
bool deviceLt20 = false;
|
cl_int err = create_single_kernel_helper_with_build_options(
|
||||||
Version version = get_device_cl_version(device);
|
context, &p, &k, 4, sizeof_kernel_code, "test_sizeof", nullptr);
|
||||||
if (version < Version(2,0)) {
|
|
||||||
deviceLt20 = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
cl_int err = create_single_kernel_helper_with_build_options(context, &p, &k, 4, sizeof_kernel_code, "test_sizeof", deviceLt20 ? "" : "-cl-std=CL2.0");
|
|
||||||
if( err )
|
if( err )
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,9 @@ test_wg_barrier(cl_device_id device, cl_context context, cl_command_queue queue,
|
|||||||
size_t max_threadgroup_size = 0;
|
size_t max_threadgroup_size = 0;
|
||||||
MTdata d;
|
MTdata d;
|
||||||
|
|
||||||
err = create_single_kernel_helper_with_build_options(context, &program, &kernel, 1, &wg_barrier_kernel_code, "compute_sum", "-cl-std=CL2.0" );
|
err = create_single_kernel_helper_with_build_options(
|
||||||
|
context, &program, &kernel, 1, &wg_barrier_kernel_code, "compute_sum",
|
||||||
|
nullptr);
|
||||||
test_error(err, "Failed to build kernel/program.");
|
test_error(err, "Failed to build kernel/program.");
|
||||||
|
|
||||||
err = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE,
|
err = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE,
|
||||||
|
|||||||
Reference in New Issue
Block a user