From bfb3e4aa2c791759e8df0c3fbf6478c563e0d11d Mon Sep 17 00:00:00 2001 From: Radek Szymanski Date: Wed, 22 May 2019 18:31:01 +0100 Subject: [PATCH] cl21: Add minimal required version functionality (#270) This adds functionality to define minimal required version through the ADD_TEST* macros. Tests that don't meet the version requirement will be skipped. By default the minimal required version is set to 1.0, subsequent patches will set the appropriate version for each of the tests. Signed-off-by: Radek Szymanski --- test_common/harness/errorHelpers.h | 15 ++++++++ test_common/harness/testHarness.c | 38 ++++++++++++++++--- test_common/harness/testHarness.h | 29 +++++++++++++- .../test_common/harness/errorHelpers.h | 15 ++++++++ .../test_common/harness/testHarness.c | 35 +++++++++++++++++ .../test_common/harness/testHarness.h | 29 +++++++++++++- test_conformance/spirv_new/main.cpp | 1 + 7 files changed, 153 insertions(+), 9 deletions(-) diff --git a/test_common/harness/errorHelpers.h b/test_common/harness/errorHelpers.h index 95b66366..e85a53fe 100644 --- a/test_common/harness/errorHelpers.h +++ b/test_common/harness/errorHelpers.h @@ -16,6 +16,8 @@ #ifndef _errorHelpers_h #define _errorHelpers_h +#include + #ifdef __APPLE__ #include #else @@ -97,6 +99,19 @@ extern "C" { #define test_failure_warning_ret(errCode, expectedErrCode, msg, retValue) { if( errCode != expectedErrCode ) { print_failure_warning( errCode, expectedErrCode, msg ); warnings++ ; } } #define print_failure_warning(errCode, expectedErrCode, msg) log_error( "WARNING: %s! (Got %s, expected %s from %s:%d)\n", msg, IGetErrorString( errCode ), IGetErrorString( expectedErrCode ), __FILE__, __LINE__ ); +#define ASSERT_SUCCESS(expr, msg) \ + do \ + { \ + cl_int _temp_retval = (expr); \ + if (_temp_retval != CL_SUCCESS) \ + { \ + std::stringstream ss; \ + ss << "ERROR: " << msg << "=" << IGetErrorString(_temp_retval) \ + << " at " << __FILE__ << ":" << __LINE__ << "\n"; \ + throw std::runtime_error(ss.str()); \ + } \ + } while (0) + extern const char *IGetErrorString( int clErrorCode ); extern float Ulp_Error_Half( cl_ushort test, float reference ); diff --git a/test_common/harness/testHarness.c b/test_common/harness/testHarness.c index edb5eb91..ab029b37 100644 --- a/test_common/harness/testHarness.c +++ b/test_common/harness/testHarness.c @@ -17,6 +17,9 @@ #include "compat.h" #include #include +#include +#include +#include #include "threadTesting.h" #include "errorHelpers.h" #include "kernelHelpers.h" @@ -703,11 +706,12 @@ test_status callSingleTestFunction( test_definition test, cl_device_id deviceToU log_info( "%s...\n", test.name ); fflush( stdout ); - error = check_opencl_version_with_testname(test.name, deviceToUse); - if( error != CL_SUCCESS ) - { - print_missing_feature( error, test.name ); - return TEST_SKIP; + const Version device_version = get_device_cl_version(deviceToUse); + if (test.min_version > device_version) + { + log_info("%s skipped (requires at least version %s, but the device reports version %s)\n", + test.name, test.min_version.to_string().c_str(), device_version.to_string().c_str()); + return TEST_SKIP; } error = check_functions_for_offline_compiler(test.name, deviceToUse); @@ -894,4 +898,28 @@ cl_device_id GetOpposingDevice( cl_device_id device ) return NULL; } +Version get_device_cl_version(cl_device_id device) +{ + size_t str_size; + cl_int err = clGetDeviceInfo(device, CL_DEVICE_VERSION, 0, NULL, &str_size); + ASSERT_SUCCESS(err, "clGetDeviceInfo"); + std::vector str(str_size); + err = clGetDeviceInfo(device, CL_DEVICE_VERSION, str_size, str.data(), NULL); + ASSERT_SUCCESS(err, "clGetDeviceInfo"); + + if (strstr(str.data(), "OpenCL 1.0") != NULL) + return Version(1, 0); + else if (strstr(str.data(), "OpenCL 1.1") != NULL) + return Version(1, 1); + else if (strstr(str.data(), "OpenCL 1.2") != NULL) + return Version(1, 2); + else if (strstr(str.data(), "OpenCL 2.0") != NULL) + return Version(2, 0); + else if (strstr(str.data(), "OpenCL 2.1") != NULL) + return Version(2, 1); + else if (strstr(str.data(), "OpenCL 2.2") != NULL) + return Version(2, 2); + + throw std::runtime_error(std::string("Unknown OpenCL version: ") + str.data()); +} diff --git a/test_common/harness/testHarness.h b/test_common/harness/testHarness.h index b988d679..9067d555 100644 --- a/test_common/harness/testHarness.h +++ b/test_common/harness/testHarness.h @@ -18,6 +18,8 @@ #include "threadTesting.h" #include "clImageHelper.h" +#include +#include #include @@ -25,15 +27,36 @@ extern "C" { #endif -#define ADD_TEST(fn) {test_##fn, #fn} -#define NOT_IMPLEMENTED_TEST(fn) {NULL, #fn} +#define ADD_TEST(fn) {test_##fn, #fn, Version(1, 0)} +#define ADD_TEST_VERSION(fn, ver) {test_##fn, #fn, ver} +#define NOT_IMPLEMENTED_TEST(fn) {NULL, #fn, Version(0, 0)} #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +class Version +{ +public: + Version() : m_major(0), m_minor(0) {} + Version(int major, int minor) : m_major(major), m_minor(minor) {} + bool operator>(const Version& rhs) const { return to_int() > rhs.to_int(); } + int to_int() const { return m_major * 10 + m_minor; } + std::string to_string() const + { + std::stringstream ss; + ss << m_major << "." << m_minor; + return ss.str(); + } + +private: + int m_major; + int m_minor; +}; + typedef struct test_definition { basefn func; const char* name; + Version min_version; } test_definition; @@ -99,6 +122,8 @@ extern cl_device_type GetDeviceType( cl_device_id ); // is the only device available, the SAME device is returned, so check! extern cl_device_id GetOpposingDevice( cl_device_id device ); +Version get_device_cl_version(cl_device_id device); + extern int gFlushDenormsToZero; // This is set to 1 if the device does not support denorms (CL_FP_DENORM) extern int gInfNanSupport; // This is set to 1 if the device supports infinities and NaNs diff --git a/test_conformance/compatibility/test_common/harness/errorHelpers.h b/test_conformance/compatibility/test_common/harness/errorHelpers.h index 9b5d7097..54e73b07 100644 --- a/test_conformance/compatibility/test_common/harness/errorHelpers.h +++ b/test_conformance/compatibility/test_common/harness/errorHelpers.h @@ -16,6 +16,8 @@ #ifndef _errorHelpers_h #define _errorHelpers_h +#include + #ifdef __APPLE__ #include #else @@ -85,6 +87,19 @@ extern "C" { #define test_failure_warning_ret(errCode, expectedErrCode, msg, retValue) { if( errCode != expectedErrCode ) { print_failure_warning( errCode, expectedErrCode, msg ); warnings++ ; } } #define print_failure_warning(errCode, expectedErrCode, msg) log_error( "WARNING: %s! (Got %s, expected %s from %s:%d)\n", msg, IGetErrorString( errCode ), IGetErrorString( expectedErrCode ), __FILE__, __LINE__ ); +#define ASSERT_SUCCESS(expr, msg) \ + do \ + { \ + cl_int _temp_retval = (expr); \ + if (_temp_retval != CL_SUCCESS) \ + { \ + std::stringstream ss; \ + ss << "ERROR: " << msg << "=" << IGetErrorString(_temp_retval) \ + << " at " << __FILE__ << ":" << __LINE__ << "\n"; \ + throw std::runtime_error(ss.str()); \ + } \ + } while (0) + extern const char *IGetErrorString( int clErrorCode ); extern float Ulp_Error_Half( cl_ushort test, float reference ); diff --git a/test_conformance/compatibility/test_common/harness/testHarness.c b/test_conformance/compatibility/test_common/harness/testHarness.c index 2762dbeb..95b57f09 100644 --- a/test_conformance/compatibility/test_common/harness/testHarness.c +++ b/test_conformance/compatibility/test_common/harness/testHarness.c @@ -23,6 +23,9 @@ #endif #include +#include +#include +#include #include "threadTesting.h" #include "errorHelpers.h" #include "kernelHelpers.h" @@ -701,6 +704,14 @@ test_status callSingleTestFunction( test_definition test, cl_device_id deviceToU log_info( "%s...\n", test.name ); fflush( stdout ); + const Version device_version = get_device_cl_version(deviceToUse); + if (test.min_version > device_version) + { + log_info("%s skipped (requires at least version %s, but the device reports version %s)\n", + test.name, test.min_version.to_string().c_str(), device_version.to_string().c_str()); + return TEST_SKIP; + } + if( test.func == NULL ) { // Skip unimplemented test, can happen when all of the tests are selected @@ -881,4 +892,28 @@ cl_device_id GetOpposingDevice( cl_device_id device ) return NULL; } +Version get_device_cl_version(cl_device_id device) +{ + size_t str_size; + cl_int err = clGetDeviceInfo(device, CL_DEVICE_VERSION, 0, NULL, &str_size); + ASSERT_SUCCESS(err, "clGetDeviceInfo"); + std::vector str(str_size); + err = clGetDeviceInfo(device, CL_DEVICE_VERSION, str_size, str.data(), NULL); + ASSERT_SUCCESS(err, "clGetDeviceInfo"); + + if (strstr(str.data(), "OpenCL 1.0") != NULL) + return Version(1, 0); + else if (strstr(str.data(), "OpenCL 1.1") != NULL) + return Version(1, 1); + else if (strstr(str.data(), "OpenCL 1.2") != NULL) + return Version(1, 2); + else if (strstr(str.data(), "OpenCL 2.0") != NULL) + return Version(2, 0); + else if (strstr(str.data(), "OpenCL 2.1") != NULL) + return Version(2, 1); + else if (strstr(str.data(), "OpenCL 2.2") != NULL) + return Version(2, 2); + + throw std::runtime_error(std::string("Unknown OpenCL version: ") + str.data()); +} diff --git a/test_conformance/compatibility/test_common/harness/testHarness.h b/test_conformance/compatibility/test_common/harness/testHarness.h index a3bf9f4e..0a86d8dd 100644 --- a/test_conformance/compatibility/test_common/harness/testHarness.h +++ b/test_conformance/compatibility/test_common/harness/testHarness.h @@ -18,20 +18,43 @@ #include "threadTesting.h" #include "clImageHelper.h" +#include +#include #ifdef __cplusplus extern "C" { #endif -#define ADD_TEST(fn) {test_##fn, #fn} -#define NOT_IMPLEMENTED_TEST(fn) {NULL, #fn} +#define ADD_TEST(fn) {test_##fn, #fn, Version(1, 0)} +#define ADD_TEST_VERSION(fn, ver) {test_##fn, #fn, ver} +#define NOT_IMPLEMENTED_TEST(fn) {NULL, #fn, Version(0, 0)} #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +class Version +{ +public: + Version() : m_major(0), m_minor(0) {} + Version(int major, int minor) : m_major(major), m_minor(minor) {} + bool operator>(const Version& rhs) const { return to_int() > rhs.to_int(); } + int to_int() const { return m_major * 10 + m_minor; } + std::string to_string() const + { + std::stringstream ss; + ss << m_major << "." << m_minor; + return ss.str(); + } + +private: + int m_major; + int m_minor; +}; + typedef struct test_definition { basefn func; const char* name; + Version min_version; } test_definition; typedef enum test_status @@ -96,6 +119,8 @@ extern cl_device_type GetDeviceType( cl_device_id ); // is the only device available, the SAME device is returned, so check! extern cl_device_id GetOpposingDevice( cl_device_id device ); +Version get_device_cl_version(cl_device_id device); + extern int gFlushDenormsToZero; // This is set to 1 if the device does not support denorms (CL_FP_DENORM) extern int gInfNanSupport; // This is set to 1 if the device supports infinities and NaNs diff --git a/test_conformance/spirv_new/main.cpp b/test_conformance/spirv_new/main.cpp index a08bbe37..81e2dd12 100644 --- a/test_conformance/spirv_new/main.cpp +++ b/test_conformance/spirv_new/main.cpp @@ -79,6 +79,7 @@ void spirvTestsRegistry::addTestClass(baseTestClass *test, const char *testName) test_definition testDef; testDef.func = test->getFunction(); testDef.name = testName; + testDef.min_version = Version(2, 1); testDefinitions.push_back(testDef); }