summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorBlaž Tomažič <blaz.tomazic@gmail.com>2012-08-29 21:31:10 +0200
committerBlaž Tomažič <blaz.tomazic@gmail.com>2012-09-05 14:56:00 +0200
commit5ce701941127e8e05ec67ca87c429e74c1744db6 (patch)
tree63a4ab783861026325ce768ef684be5b186aeae7 /tests
parente51ff1b6d966cb4eb7449775e3b7161eed4c206f (diff)
util-cl: Add OpenCL testing framework
The framework is composed of 1 main part and 3 different sub-parts. Each test is linked to this framework and calls the piglit_cl_framework_run function. The main part is in piglit-framework-cl.* files. The header contains definitions to implement each specific test type. The source file's piglit_cl_framework_run function is called by each test of any type. This file then parses program and environment variables, and depending on test configuration, runs the test on selected platforms and devices. The other 3 sub-parts are tests types implementations: Custom, API and Program. Each one is used to create tests that benefit from different functionality. Here each header file contains definitions to implement an OpenCL test and each source file handles the specific options used in test configurtation. Signed-off-by: Blaž Tomažič <blaz.tomazic@gmail.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/util/piglit-framework-cl-api.c212
-rw-r--r--tests/util/piglit-framework-cl-api.h149
-rw-r--r--tests/util/piglit-framework-cl-custom.c61
-rw-r--r--tests/util/piglit-framework-cl-custom.h122
-rw-r--r--tests/util/piglit-framework-cl-program.c372
-rw-r--r--tests/util/piglit-framework-cl-program.h159
-rw-r--r--tests/util/piglit-framework-cl.c554
-rw-r--r--tests/util/piglit-framework-cl.h354
8 files changed, 1983 insertions, 0 deletions
diff --git a/tests/util/piglit-framework-cl-api.c b/tests/util/piglit-framework-cl-api.c
new file mode 100644
index 000000000..dbd5be772
--- /dev/null
+++ b/tests/util/piglit-framework-cl-api.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright © 2012 Blaž Tomažič <blaz.tomazic@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "piglit-framework-cl-api.h"
+
+/* Default test configuration values */
+const struct piglit_cl_api_test_config PIGLIT_CL_DEFAULT_API_TEST_CONFIG = {
+ .version_min = 0,
+ .version_max = 0,
+
+ .create_context = false,
+
+ .program_source = NULL,
+ .build_options = NULL
+};
+
+/* Return default values for test configuration */
+const void*
+piglit_cl_get_empty_api_test_config()
+{
+ return &PIGLIT_CL_DEFAULT_API_TEST_CONFIG;
+}
+
+/* Check configuration */
+void piglit_cl_api_test_init(const int argc,
+ const char** argv,
+ void* void_config)
+{
+ struct piglit_cl_api_test_config* config = void_config;
+
+ /* Run test's init */
+ if(config->_init_test != NULL) {
+ config->_init_test(argc, argv, void_config);
+ }
+
+ // version_min
+ if(config->version_min == 0) {
+ config->version_min = 10;
+ }
+ if(config->version_min <= 0) {
+ fprintf(stderr, "Invalid configuration, version_min is %d.\n",
+ config->version_min);
+ piglit_report_result(PIGLIT_WARN);
+ }
+ if(config->version_min > PIGLIT_CL_VERSION) {
+ fprintf(stderr, "Piglit was compiled with lower OpenCL version (%d.%d) than version_min: %d.\n",
+ PIGLIT_CL_VERSION/10, PIGLIT_CL_VERSION%10,
+ config->version_min);
+ piglit_report_result(PIGLIT_WARN);
+ }
+ // version_max
+ if(config->version_max < 0) {
+ fprintf(stderr, "Invalid configuration, version_max is %d.\n",
+ config->version_max);
+ piglit_report_result(PIGLIT_WARN);
+ }
+ if(config->version_max > 0 && config->version_max < config->version_min) {
+ fprintf(stderr, "Invalid configuration, version_max (%d) is lower than version_min (%d).\n",
+ config->version_max, config->version_min);
+ piglit_report_result(PIGLIT_WARN);
+ }
+ // create_context
+ if( config->create_context
+ && !(config->run_per_device || config->run_per_platform)) {
+ printf("Invalid configuration, create_context can only be used with run_per_platform or run_per_device.\n");
+ piglit_report_result(PIGLIT_WARN);
+ }
+ // program_source
+ if( config->program_source != NULL
+ && !(config->run_per_device || config->run_per_platform)) {
+ printf("Invalid configuration, program_source can only be used with run_per_platform or run_per_device.\n");
+ piglit_report_result(PIGLIT_WARN);
+ }
+ if(config->program_source != NULL && !config->create_context) {
+ config->create_context = true;
+ }
+ // build options
+ if(config->build_options != NULL && config->program_source == NULL) {
+ fprintf(stderr, "Invalid configuration, build_options can only be used with program_source.\n");
+ piglit_report_result(PIGLIT_WARN);
+ }
+}
+
+/* Set environment and run test */
+enum piglit_result
+piglit_cl_api_test_run(const int argc,
+ const char** argv,
+ void* void_config,
+ int version,
+ cl_platform_id platform_id,
+ cl_device_id device_id)
+{
+ enum piglit_result result;
+
+ struct piglit_cl_api_test_config* config = void_config;
+ struct piglit_cl_api_test_env env;
+
+ piglit_cl_context context = NULL;
+ cl_program program = NULL;
+
+ /* Check version to test against */
+ if(version < config->version_min) {
+ printf("Trying to run test with version (%d.%d) lower than version_min: %d\n",
+ version/10, version%10,
+ config->version_min);
+ return PIGLIT_SKIP;
+ }
+ if(config->version_max > 0 && version > config->version_max) {
+ /*
+ * If version was not provided on the command line
+ * lower it to version_max.
+ */
+ if(piglit_cl_get_version_arg(argc, argv) == 0) {
+ printf("# Lowering version to %d.%d because of version_max.\n",
+ config->version_max/10, config->version_max%10);
+ version = config->version_max;
+ } else {
+ printf("Trying to run test with version (%d.%d) higher than version_max: %d\n",
+ version/10, version%10,
+ config->version_max);
+ return PIGLIT_SKIP;
+ }
+ }
+
+ /* Create context */
+ if(config->create_context) {
+ if(config->run_per_platform) {
+ unsigned int num_devices;
+ cl_device_id* device_ids;
+
+ num_devices = piglit_cl_get_device_ids(platform_id,
+ CL_DEVICE_TYPE_ALL,
+ &device_ids);
+
+ context = piglit_cl_create_context(platform_id,
+ device_ids,
+ num_devices);
+
+ free(device_ids);
+ } else { // config->run_per_device
+ context = piglit_cl_create_context(platform_id, &device_id, 1);
+ }
+
+ if(context == NULL) {
+ return PIGLIT_FAIL;
+ }
+ }
+
+ /* Create and build program */
+ if(config->program_source != NULL) {
+ if(config->build_options != NULL) {
+ program = piglit_cl_build_program_with_source(context,
+ 1,
+ &config->program_source,
+ config->build_options);
+ } else {
+ program = piglit_cl_build_program_with_source(context,
+ 1,
+ &config->program_source,
+ "");
+ }
+
+ if(program == NULL) {
+ return PIGLIT_FAIL;
+ }
+ }
+
+
+ /* Set environment */
+ env.platform_id = platform_id;
+ env.device_id = device_id;
+ env.context = context;
+ env.version = version;
+ env.program = program;
+
+
+ /* Run the actual test */
+ result = config->_api_test(argc, argv, config, &env);
+
+
+ /* Release program */
+ if(config->program_source != NULL) {
+ clReleaseProgram(program);
+ }
+
+ /* Release context */
+ if(config->create_context) {
+ piglit_cl_release_context(context);
+ }
+
+ return result;
+}
diff --git a/tests/util/piglit-framework-cl-api.h b/tests/util/piglit-framework-cl-api.h
new file mode 100644
index 000000000..c94e5f031
--- /dev/null
+++ b/tests/util/piglit-framework-cl-api.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright © 2012 Blaž Tomažič <blaz.tomazic@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#pragma once
+#ifndef PIGLIT_FRAMEWORK_CL_API_H
+#define PIGLIT_FRAMEWORK_CL_API_H
+
+#include "piglit-framework-cl.h"
+
+
+typedef const struct piglit_cl_api_test_config piglit_cl_api_test_config_t;
+typedef const struct piglit_cl_api_test_env piglit_cl_api_test_env_t;
+
+/**
+ * \brief Definition of API test function.
+ *
+ * Every test must implement this function.
+ *
+ * @param argc Argument count passed to \c main().
+ * @param argv Argument vector passed to \c main().
+ * @param config Test configuration.
+ * @param env Test environment.
+ * @return Result of test.
+*/
+typedef enum piglit_result
+ piglit_cl_api_test_t(const int argc,
+ const char** argv,
+ piglit_cl_api_test_config_t* config,
+ piglit_cl_api_test_env_t* env);
+
+/**
+ * \struct piglit_cl_api_test_config
+ *
+ * \brief Test configuration for API tests.
+ */
+PIGLIT_CL_DEFINE_TEST_CONFIG_BEGIN(struct piglit_cl_api_test_config)
+
+ piglit_cl_api_test_t* _api_test; /**< API test function. (internal) */
+ piglit_cl_test_init_t* _init_test; /**< API test init function.
+ (internal) */
+
+ int version_min; /**< Minimum version required. (optional) */
+ int version_max; /**< Maximum version supported. (optional) */
+
+ bool create_context; /**< Create helper context on each run. Depends on
+ \c run_per_device or \c run_per_platform.
+ (optional)*/
+
+ char* program_source; /**< Source to create and build a program on each run.
+ Depends on \c run_per_device or
+ \c run_per_platform and conflicts
+ \c create_context=FALSE. (optional)*/
+ char* build_options; /**< Build options for program. Depends on
+ \c program_source. (optional)*/
+
+PIGLIT_CL_DEFINE_TEST_CONFIG_END
+
+piglit_cl_get_empty_test_config_t piglit_cl_get_empty_api_test_config;
+piglit_cl_test_init_t piglit_cl_api_test_init;
+piglit_cl_test_run_t piglit_cl_api_test_run;
+
+/**
+ * \def PIGLIT_CL_API_TEST_CONFIG_BEGIN
+ *
+ * Extension of \c PIGLIT_CL_TEST_CONFIG_BEGIN macro to be used by
+ * API tests.
+ * This macro must be used to create an API test configuration
+ * instance and must be followed by \c PIGLIT_CL_TEST_API_CONFIG_END macro.
+ *
+ * In beetween \c PIGLIT_CL_API_TEST_CONFIG_BEGIN and
+ * \c PIGLIT_CL_API_TEST_CONFIG_END macros you can set the test
+ * configuration values.
+ *
+ */
+/**
+ * \def PIGLIT_CL_API_TEST_CONFIG_END
+ *
+ * Extension of \c PIGLIT_CL_TEST_CONFIG_END macro to be used by
+ * API tests. It defines function prototypes for functions used by
+ * an API test.
+ * This macro must be used to create a test configuration instance
+ * and must follow \c PIGLIT_CL_API_TEST_CONFIG_BEGIN macro.
+ *
+ */
+#define PIGLIT_CL_API_TEST_CONFIG_BEGIN \
+ piglit_cl_api_test_t piglit_cl_test; \
+ \
+ PIGLIT_CL_TEST_CONFIG_BEGIN(struct piglit_cl_api_test_config, \
+ piglit_cl_get_empty_api_test_config, \
+ piglit_cl_api_test_run)
+
+#define PIGLIT_CL_API_TEST_CONFIG_END \
+ config._api_test = piglit_cl_test; \
+ config._init_test = config.init_func; \
+ config.init_func = piglit_cl_api_test_init; \
+ \
+ PIGLIT_CL_TEST_CONFIG_END
+
+/**
+* \brief Environment for API tests.
+*
+* Defines environment used by API tests.
+*/
+struct piglit_cl_api_test_env {
+ int version; /**< Version of OpenCL to test against.
+ Holds valid version if \c run_per_platform
+ or \c run_per_device is \c true. */
+ cl_platform_id platform_id; /**< OpenCL platform id.
+ Holds valid platform id if
+ \c run_per_platform or \c run_per_device is
+ \c true. */
+ cl_device_id device_id; /**< OpenCL device id.
+ Holds valid device id if \c run_per_device is
+ \c true. */
+
+ piglit_cl_context context; /**< Generated helper context.
+ It is generated only if \c create_context
+ and one of \c run_per_device or
+ \c run_per_platform is \c true. Or if
+ \c program_source is defined.*/
+
+ cl_program program; /**< OpenCL program.
+ Holds valid program if \c program_source is a
+ NULL-terminated string and one of \c run_per_device
+ or \c run_per_platform is \c true.*/
+};
+
+
+#endif //PIGLIT_FRAMEWORK_CL_API_H
diff --git a/tests/util/piglit-framework-cl-custom.c b/tests/util/piglit-framework-cl-custom.c
new file mode 100644
index 000000000..36d0e69e8
--- /dev/null
+++ b/tests/util/piglit-framework-cl-custom.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright © 2012 Blaž Tomažič <blaz.tomazic@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "piglit-framework-cl-custom.h"
+
+/* Default test configuration values */
+const struct piglit_cl_custom_test_config
+ PIGLIT_CL_DEFAULT_CUSTOM_TEST_CONFIG = {
+};
+
+/* Return default values for test configuration */
+const void*
+piglit_cl_get_empty_custom_test_config()
+{
+ return &PIGLIT_CL_DEFAULT_CUSTOM_TEST_CONFIG;
+}
+
+/* Set environment and run test */
+enum piglit_result
+piglit_cl_custom_test_run(const int argc,
+ const char** argv,
+ void* void_config,
+ int version,
+ cl_platform_id platform_id,
+ cl_device_id device_id)
+{
+ enum piglit_result result;
+
+ struct piglit_cl_custom_test_config* config = void_config;
+ struct piglit_cl_custom_test_env env;
+
+ /* Set environment */
+ env.platform_id = platform_id;
+ env.device_id = device_id;
+ env.version = version;
+
+ /* Run the actual test */
+ result = config->_custom_test(argc, argv, config, &env);
+
+ return result;
+}
diff --git a/tests/util/piglit-framework-cl-custom.h b/tests/util/piglit-framework-cl-custom.h
new file mode 100644
index 000000000..d6b2b38c1
--- /dev/null
+++ b/tests/util/piglit-framework-cl-custom.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright © 2012 Blaž Tomažič <blaz.tomazic@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#pragma once
+#ifndef PIGLIT_FRAMEWORK_CL_CUSTOM_H
+#define PIGLIT_FRAMEWORK_CL_CUSTOM_H
+
+#include "piglit-framework-cl.h"
+
+
+typedef const struct piglit_cl_custom_test_config
+ piglit_cl_custom_test_config_t;
+typedef const struct piglit_cl_custom_test_env
+ piglit_cl_custom_test_env_t;
+
+/**
+ * \brief Definition of CUSTOM test function.
+ *
+ * Every test must implement this function.
+ *
+ * @param argc Argument count passed to \c main().
+ * @param argv Argument vector passed to \c main().
+ * @param config Test configuration.
+ * @param env Test environment.
+ * @return Result of test.
+*/
+typedef enum piglit_result
+ piglit_cl_custom_test_t(const int argc,
+ const char** argv,
+ piglit_cl_custom_test_config_t* config,
+ piglit_cl_custom_test_env_t* env);
+
+/**
+ * \struct piglit_cl_custom_test_config
+ *
+ * \brief Test configuration for CUSTOM tests.
+ */
+PIGLIT_CL_DEFINE_TEST_CONFIG_BEGIN(struct piglit_cl_custom_test_config)
+
+ piglit_cl_custom_test_t* _custom_test; /**< CUSTOM test function.
+ (internal) */
+
+PIGLIT_CL_DEFINE_TEST_CONFIG_END
+
+piglit_cl_get_empty_test_config_t piglit_cl_get_empty_custom_test_config;
+piglit_cl_test_run_t piglit_cl_custom_test_run;
+
+/**
+ * \def PIGLIT_CL_CUSTOM_TEST_CONFIG_BEGIN
+ *
+ * Extension of \c PIGLIT_CL_TEST_CONFIG_BEGIN macro to be used by
+ * CUSTOM tests.
+ * This macro must be used to create an CUSTOM test configuration
+ * instance and must be followed by \c PIGLIT_CL_TEST_CUSTOM_CONFIG_END macro.
+ *
+ * In beetween \c PIGLIT_CL_CUSTOM_TEST_CONFIG_BEGIN and
+ * \c PIGLIT_CL_CUSTOM_TEST_CONFIG_END macros you can set the test
+ * configuration values.
+ *
+ */
+/**
+ * \def PIGLIT_CL_CUSTOM_TEST_CONFIG_END
+ *
+ * Extension of \c PIGLIT_CL_TEST_CONFIG_END macro to be used by
+ * CUSTOM tests. It defines function prototypes for functions used by
+ * an CUSTOM test.
+ * This macro must be used to create a test configuration instance
+ * and must follow \c PIGLIT_CL_CUSTOM_TEST_CONFIG_BEGIN macro.
+ *
+ */
+#define PIGLIT_CL_CUSTOM_TEST_CONFIG_BEGIN \
+ piglit_cl_custom_test_t piglit_cl_test; \
+ \
+ PIGLIT_CL_TEST_CONFIG_BEGIN(struct piglit_cl_custom_test_config, \
+ piglit_cl_get_empty_custom_test_config, \
+ piglit_cl_custom_test_run)
+
+#define PIGLIT_CL_CUSTOM_TEST_CONFIG_END \
+ config._custom_test = piglit_cl_test; \
+ \
+ PIGLIT_CL_TEST_CONFIG_END
+
+/**
+* \brief Environment for CUSTOM tests.
+*
+* Defines environment used by CUSTOM tests.
+*/
+struct piglit_cl_custom_test_env {
+ int version; /**< Version of OpenCL to test against.
+ Holds valid version if \c run_per_platform
+ or \c run_per_device is \c true. */
+ cl_platform_id platform_id; /**< OpenCL platform id.
+ Holds valid platform id if
+ \c run_per_platform or \c run_per_device
+ is \c true. */
+ cl_device_id device_id; /**< OpenCL device id.
+ Holds valid device id if \c run_per_device is
+ \c true. */
+};
+
+
+#endif //PIGLIT_FRAMEWORK_CL_CUSTOM_H
diff --git a/tests/util/piglit-framework-cl-program.c b/tests/util/piglit-framework-cl-program.c
new file mode 100644
index 000000000..f504bae72
--- /dev/null
+++ b/tests/util/piglit-framework-cl-program.c
@@ -0,0 +1,372 @@
+/*
+ * Copyright © 2012 Blaž Tomažič <blaz.tomazic@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "piglit-framework-cl-program.h"
+
+
+/* Default test configuration values */
+const struct piglit_cl_program_test_config
+ PIGLIT_CL_DEFAULT_PROGRAM_TEST_CONFIG = {
+ .clc_version_min = 0,
+ .clc_version_max = 0,
+
+ .program_source = NULL,
+ .program_source_file = NULL,
+ .program_binary = NULL,
+ .program_binary_file = NULL,
+
+ .build_options = NULL,
+ .expect_build_fail = false,
+
+ .kernel_name = NULL,
+};
+
+/* Return default values for test configuration */
+const void*
+piglit_cl_get_empty_program_test_config()
+{
+ return &PIGLIT_CL_DEFAULT_PROGRAM_TEST_CONFIG;
+}
+
+/* Check configuration */
+void piglit_cl_program_test_init(const int argc,
+ const char** argv,
+ void* void_config)
+{
+ struct piglit_cl_program_test_config* config = void_config;
+
+ /* Run test's init */
+ if(config->_init_test != NULL) {
+ config->_init_test(argc, argv, void_config);
+ }
+
+ /* Check that config is valid */
+ // run_per_device, run_per_platform
+ if(!(config->run_per_device || config->run_per_platform)) {
+ fprintf(stderr, "Invalid configuration, neither run_per_device nor run_per_platform is set to true.\n");
+ piglit_report_result(PIGLIT_WARN);
+ }
+ // clc_version_min
+ if(config->clc_version_min == 0) {
+ config->clc_version_min = 10;
+ }
+ if(config->clc_version_min <= 0) {
+ fprintf(stderr, "Invalid configuration, clc_version_min is %d.\n",
+ config->clc_version_min);
+ piglit_report_result(PIGLIT_WARN);
+ }
+ // clc_version_max
+ if(config->clc_version_max < 0) {
+ fprintf(stderr, "Invalid configuration, clc_version_max is %d.\n",
+ config->clc_version_max);
+ piglit_report_result(PIGLIT_WARN);
+ }
+ if( config->clc_version_max > 0
+ && config->clc_version_max < config->clc_version_min) {
+ fprintf(stderr, "Invalid configuration, clc_version_max (%d) is lower than clc_version_min (%d).\n",
+ config->clc_version_max, config->clc_version_min);
+ piglit_report_result(PIGLIT_WARN);
+ }
+ // program_*
+ if(!( /* one must be different than NULL */
+ ( config->program_source != NULL
+ || config->program_source_file != NULL
+ || config->program_binary != NULL
+ || config->program_binary_file != NULL
+ )
+ && /* the other three must be NULL */
+ ( ( config->program_source_file == NULL
+ && config->program_binary == NULL
+ && config->program_binary_file == NULL)
+ || ( config->program_source == NULL
+ && config->program_binary == NULL
+ && config->program_binary_file == NULL)
+ || ( config->program_source == NULL
+ && config->program_source_file == NULL
+ && config->program_binary_file == NULL)
+ || ( config->program_source == NULL
+ && config->program_source_file == NULL
+ && config->program_binary == NULL)
+ )
+ )) {
+ fprintf(stderr, "Invalid configuration, one and only one of program_* must be defined.\n");
+ piglit_report_result(PIGLIT_WARN);
+ }
+ // build_fail and kernel_name
+ if(config->expect_build_fail && config->kernel_name != NULL) {
+ fprintf(stderr, "Invalid configuration, kernel_name cannot be defined when build_fail is true.\n");
+ piglit_report_result(PIGLIT_WARN);
+ }
+}
+
+/* Run by piglit_cl_framework_run() */
+enum piglit_result
+piglit_cl_program_test_run(const int argc,
+ const char** argv,
+ void* void_config,
+ int version,
+ cl_platform_id platform_id,
+ cl_device_id device_id)
+{
+ enum piglit_result result;
+
+ struct piglit_cl_program_test_config* config = void_config;
+ struct piglit_cl_program_test_env env = {
+ .version = version,
+ .clc_version = 0,
+
+ .platform_id = NULL,
+ .device_id = NULL,
+
+ .context = NULL,
+
+ .program = NULL,
+
+ .kernel = NULL,
+ };
+
+ int i;
+ char* build_options = malloc(1 * sizeof(char));
+ unsigned int num_devices;
+ cl_device_id* device_ids;
+
+ build_options[0] = '\0';
+
+ /* Set environment */
+ env.platform_id = platform_id;
+ env.device_id = device_id;
+ env.version = version;
+
+ /* Get device ids */
+ if(config->run_per_platform) {
+ num_devices = piglit_cl_get_device_ids(platform_id,
+ CL_DEVICE_TYPE_ALL,
+ &device_ids);
+ }
+
+ /* Check OpenCL C version to test against */
+ if(config->run_per_platform) {
+ for(i = 0; i < num_devices; i++) {
+ int device_clc_version =
+ piglit_cl_get_device_cl_c_version(device_ids[i]);
+
+ if(device_clc_version < env.clc_version || env.clc_version == 0) {
+ env.clc_version = device_clc_version;
+ }
+ }
+ } else { // config->run_per_device
+ env.clc_version = piglit_cl_get_device_cl_c_version(device_id);
+ }
+ if(env.clc_version > version) {
+ printf("# Lowering OpenCL C version to %d.%d because of OpenCL version.\n",
+ version/10, version%10);
+ env.clc_version = version;
+ }
+ if( config->clc_version_max > 0
+ && env.clc_version > config->clc_version_max) {
+ printf("# Lowering OpenCL C version to %d.%d because of clc_version_max.\n",
+ config->clc_version_max/10, config->clc_version_max%10);
+ env.clc_version = config->clc_version_max;
+ }
+ if(env.clc_version < config->clc_version_min) {
+ printf("Trying to run test with OpenCL C version (%d.%d) ""lower than clc_version_min: %d\n",
+ env.clc_version/10, env.clc_version%10,
+ config->clc_version_min);
+ return PIGLIT_SKIP;
+ }
+
+ printf("# OpenCL C version: %d.%d\n",
+ env.clc_version/10, env.clc_version%10);
+
+ /* Create context */
+ if(config->run_per_platform) {
+ env.context = piglit_cl_create_context(platform_id, device_ids,
+ num_devices);
+ } else { // config->run_per_device
+ env.context = piglit_cl_create_context(platform_id, &device_id, 1);
+ }
+
+ if(env.context == NULL) {
+ return PIGLIT_FAIL;
+ }
+
+ /* Set build options */
+ if(version > 10) {
+ char* template = "-cl-std=CL%d.%d ";
+ char* old = build_options;
+ build_options = malloc((strlen(old) + strlen(template) + 1) * sizeof(char));
+ strcpy(build_options, old);
+ sprintf(build_options+strlen(old), template, env.clc_version/10,
+ env.clc_version%10);
+ free(old);
+ }
+ if(env.clc_version <= 10) {
+ char* template = "-D CL_VERSION_1_0=100 ";
+ char* old = build_options;
+ build_options = malloc((strlen(old) + strlen(template) + 1) * sizeof(char));
+ strcpy(build_options, old);
+ sprintf(build_options+strlen(old), template);
+ free(old);
+ }
+ if(env.clc_version <= 11) {
+ char* template = "-D __OPENCL_C_VERSION__=1%d0 ";
+ char* old = build_options;
+ build_options = malloc((strlen(old) + strlen(template) + 1) * sizeof(char));
+ strcpy(build_options, old);
+ sprintf(build_options+strlen(old), template, env.clc_version%10);
+ free(old);
+ }
+ if(config->build_options != NULL) {
+ char* old = build_options;
+ build_options = malloc((strlen(old) + strlen(config->build_options) + 1) * sizeof(char));
+ strcpy(build_options, old);
+ sprintf(build_options+strlen(old), config->build_options);
+ free(old);
+ }
+
+ printf("# Build options: %s\n", build_options);
+
+ /* Create and build program */
+ if(config->program_source != NULL) {
+ if(!config->expect_build_fail) {
+ env.program = piglit_cl_build_program_with_source(env.context,
+ 1,
+ &config->program_source,
+ build_options);
+ } else {
+ env.program = piglit_cl_fail_build_program_with_source(env.context,
+ 1,
+ &config->program_source,
+ build_options);
+ }
+ } else if(config->program_source_file != NULL) {
+ unsigned int size;
+ char* program_source;
+
+ program_source = piglit_load_text_file(config->program_source_file, &size);
+ if(program_source != NULL && size > 0) {
+ if(!config->expect_build_fail) {
+ env.program = piglit_cl_build_program_with_source(env.context,
+ 1,
+ &program_source,
+ build_options);
+ } else {
+ env.program = piglit_cl_fail_build_program_with_source(env.context,
+ 1,
+ &program_source,
+ build_options);
+ }
+ } else {
+ fprintf(stderr, "Program source file %s does not exists or is empty\n",
+ config->program_source_file);
+ return PIGLIT_WARN;
+ }
+ free(program_source);
+ } else if(config->program_binary != NULL) {
+ size_t length = strlen((char*)config->program_binary);
+
+ if(!config->expect_build_fail) {
+ env.program = piglit_cl_build_program_with_binary(env.context,
+ &length,
+ &config->program_binary,
+ build_options);
+ } else {
+ env.program = piglit_cl_fail_build_program_with_binary(env.context,
+ &length,
+ &config->program_binary,
+ build_options);
+ }
+ } else if(config->program_binary_file != NULL) {
+ unsigned int length;
+ size_t* lengths = malloc(sizeof(size_t) * env.context->num_devices);
+ unsigned char** program_binaries = malloc(sizeof(unsigned char**) * env.context->num_devices);
+
+ ((char**)program_binaries)[0] =
+ piglit_load_text_file(config->program_binary_file, &length);
+ lengths[0] = length;
+ for(i = 1; i < env.context->num_devices; i++) {
+ lengths[i] = lengths[0];
+ program_binaries[i] = program_binaries[0];
+ }
+
+ if(((char**)program_binaries)[0] != NULL && length > 0) {
+ if(!config->expect_build_fail) {
+ env.program = piglit_cl_build_program_with_binary(env.context,
+ lengths,
+ program_binaries,
+ build_options);
+ } else {
+ env.program = piglit_cl_fail_build_program_with_binary(env.context,
+ lengths,
+ program_binaries,
+ build_options);
+ }
+ } else {
+ fprintf(stderr, "Program binary file %s does not exists or is empty\n",
+ config->program_source_file);
+ return PIGLIT_WARN;
+ }
+
+ free(program_binaries[0]);
+ free(program_binaries);
+ free(lengths);
+ }
+
+ free(build_options);
+
+ if(env.program == NULL) {
+ return PIGLIT_FAIL;
+ }
+
+ /* Create kernel(s) */
+ if(config->kernel_name != NULL) {
+ env.kernel = piglit_cl_create_kernel(env.program, config->kernel_name);
+
+ if(env.kernel == NULL) {
+ return PIGLIT_FAIL;
+ }
+ }
+
+ /* Release retrieved device IDs */
+ if(config->run_per_platform) {
+ free(device_ids);
+ }
+
+
+ /* Run the actual test */
+ result = config->_program_test(argc, argv, config, &env);
+
+
+ /* Release kernel(s) */
+ if(env.kernel != NULL) {
+ clReleaseKernel(env.kernel);
+ }
+
+ /* Release program */
+ clReleaseProgram(env.program);
+
+ /* Release context */
+ piglit_cl_release_context(env.context);
+
+ return result;
+}
diff --git a/tests/util/piglit-framework-cl-program.h b/tests/util/piglit-framework-cl-program.h
new file mode 100644
index 000000000..bf15d3db5
--- /dev/null
+++ b/tests/util/piglit-framework-cl-program.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright © 2012 Blaž Tomažič <blaz.tomazic@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#pragma once
+#ifndef PIGLIT_FRAMEWORK_CL_PROGRAM_H
+#define PIGLIT_FRAMEWORK_CL_PROGRAM_H
+
+#include "piglit-framework-cl.h"
+
+
+typedef const struct piglit_cl_program_test_config
+ piglit_cl_program_test_config_t;
+typedef const struct piglit_cl_program_test_env
+ piglit_cl_program_test_env_t;
+
+/**
+ * \brief Definition of PROGRAM test function.
+ *
+ * Every test must implement this function.
+ *
+ * @param argc Argument count passed to \c main().
+ * @param argv Argument vector passed to \c main().
+ * @param config Test configuration.
+ * @param env Test environment.
+ * @return Result of test.
+*/
+typedef enum piglit_result
+piglit_cl_program_test_t(const int argc,
+ const char** argv,
+ piglit_cl_program_test_config_t* config,
+ piglit_cl_program_test_env_t* env);
+
+/**
+ * \struct piglit_cl_program_test_config
+ *
+ * \brief Test configuration for PROGRAM tests.
+ *
+ * \note One of \c run_per_platform or \c run_per_device must be \c true.
+ * \note One of \c program_* must be true.
+ */
+PIGLIT_CL_DEFINE_TEST_CONFIG_BEGIN(struct piglit_cl_program_test_config)
+
+ piglit_cl_program_test_t* _program_test; /**< Program test function.
+ (internal) */
+ piglit_cl_test_init_t* _init_test; /**< Program test init function.
+ (internal) */
+
+ int clc_version_min; /**< Minimum OpenCL C version required. (optional) */
+ int clc_version_max; /**< Maximum OpenCL C version supported. (optional) */
+
+ char* program_source; /**< Source to create and build a program on each run.
+ Conflicts with other \c program_*. (optional) */
+ char* program_source_file; /**< Source file from which to read, create and
+ build a program on each run. Conflicts with
+ other \c program_*. (optional) */
+ unsigned char* program_binary; /**< Binary to create and build a program on
+ each run. Conflicts with other
+ \c program_*. (optional) */
+ char* program_binary_file; /**< Binary file from which to read, create and
+ build a program on each run. Conflicts with
+ other \c program_*. (optional) */
+
+ char* build_options; /**< Build options for program. (optional) */
+ bool expect_build_fail; /**< Expect building of a program to fail.
+ (optional) */
+
+ char* kernel_name; /**< Create kernel(s) for program.
+ Conflicts with both \c expect_build_fail==TRUE and
+ \c build_only==TRUE. (optional) */
+
+PIGLIT_CL_DEFINE_TEST_CONFIG_END
+
+piglit_cl_get_empty_test_config_t piglit_cl_get_empty_program_test_config;
+piglit_cl_test_init_t piglit_cl_program_test_init;
+piglit_cl_test_run_t piglit_cl_program_test_run;
+
+/**
+ * \def PIGLIT_CL_PROGRAM_TEST_CONFIG_BEGIN
+ *
+ * Extension of \c PIGLIT_CL_TEST_CONFIG_BEGIN macro to be used by
+ * PROGRAM tests.
+ * This macro must be used to create a PROGRAM test configuration
+ * instance and must be followed by \c PIGLIT_CL_TEST_PROGRAM_CONFIG_END macro.
+ *
+ * In beetween \c PIGLIT_CL_PROGRAM_TEST_CONFIG_BEGIN and
+ * \c PIGLIT_CL_PROGRAM_TEST_CONFIG_END macros you can set the test
+ * configuration values.
+ *
+ */
+/**
+ * \def PIGLIT_CL_PROGRAM_TEST_CONFIG_END
+ *
+ * Extension of \c PIGLIT_CL_TEST_CONFIG_END macro to be used by
+ * PROGRAM tests. It defines function prototypes for functions used by
+ * a PROGRAM test.
+ * This macro must be used to create a test configuration instance
+ * and must follow \c PIGLIT_CL_PROGRAM_TEST_CONFIG_BEGIN macro.
+ *
+ */
+#define PIGLIT_CL_PROGRAM_TEST_CONFIG_BEGIN \
+ piglit_cl_program_test_t piglit_cl_test; \
+ \
+ PIGLIT_CL_TEST_CONFIG_BEGIN(struct piglit_cl_program_test_config, \
+ piglit_cl_get_empty_program_test_config, \
+ piglit_cl_program_test_run)
+
+#define PIGLIT_CL_PROGRAM_TEST_CONFIG_END \
+ config._program_test = piglit_cl_test; \
+ config._init_test = config.init_func; \
+ config.init_func = piglit_cl_program_test_init; \
+ \
+ PIGLIT_CL_TEST_CONFIG_END
+
+/**
+* \brief Environment for PROGRAM tests.
+*
+* Defines environment used by PROGRAM tests.
+*/
+struct piglit_cl_program_test_env {
+ int version; /**< Version of OpenCL to test against. */
+ int clc_version; /**< Version of OpenCL C to test against. */
+
+ cl_platform_id platform_id; /**< OpenCL platform id. */
+ cl_device_id device_id; /**< OpenCL device id.
+ Holds valid device id if \c run_per_device is
+ \c true. */
+
+ piglit_cl_context context; /**< Generated helper context. */
+
+ cl_program program; /**< OpenCL program. */
+
+ cl_kernel kernel; /**< OpenCL kernel.
+ Holds valid kernel if \c kernel_name is a
+ NULL-terminated string, \c run_per_device is \c true,
+ and \c expect_build_fail is \c false.*/
+};
+
+
+#endif //PIGLIT_FRAMEWORK_CL_PROGRAM_H
diff --git a/tests/util/piglit-framework-cl.c b/tests/util/piglit-framework-cl.c
new file mode 100644
index 000000000..deddc8d0f
--- /dev/null
+++ b/tests/util/piglit-framework-cl.c
@@ -0,0 +1,554 @@
+/*
+ * Copyright © 2012 Blaž Tomažič <blaz.tomazic@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <regex.h>
+
+#include "piglit-framework-cl.h"
+
+
+/* Default test header configuration values */
+const struct piglit_cl_test_config_header
+ PIGLIT_CL_DEFAULT_TEST_CONFIG_HEADER = {
+ ._filename = "",
+ .name = NULL,
+
+ .run_per_platform = false,
+ .run_per_device = false,
+
+ .platform_regex = NULL,
+ .device_regex = NULL,
+
+ .require_platform_extensions = NULL,
+ .require_device_extensions = NULL,
+
+ .init_func = NULL,
+ .clean_func = NULL,
+};
+
+
+/* Print test configuration */
+static void
+print_test_info(const struct piglit_cl_test_config_header* config,
+ int version,
+ const cl_platform_id platform_id,
+ const cl_device_id device_id) {
+ if(config->run_per_platform || config->run_per_device) {
+ char* platform_name;
+
+ platform_name = piglit_cl_get_platform_info(platform_id,
+ CL_PLATFORM_NAME);
+
+ printf("# Running on:\n"
+ "# Platform: %s\n",
+ platform_name);
+
+ if(config->run_per_device) {
+ char* device_name = piglit_cl_get_device_info(device_id,
+ CL_DEVICE_NAME);
+
+ printf("# Device: %s\n", device_name);
+
+ free(device_name);
+ }
+
+ printf("# OpenCL version: %d.%d\n", version/10, version%10);
+
+ free(platform_name);
+ } else {
+ // print nothing
+ }
+}
+
+/* Check extensions */
+
+bool check_platform_extensions(cl_platform_id platform_id, char* extensions)
+{
+ char* pch;
+
+ pch = strtok(extensions, " ");
+ while(pch != NULL) {
+ if( strlen(pch) > 0
+ && !piglit_cl_is_platform_extension_supported(platform_id, pch)) {
+ char* platform_name = piglit_cl_get_platform_info(platform_id,
+ CL_PLATFORM_NAME);
+ printf("\n# Skipping platform %s because extension %s is not supported.\n\n",
+ platform_name,
+ pch);
+ free(platform_name);
+ return false;
+ }
+ pch = strtok(NULL, " ");
+ }
+
+ return true;
+}
+
+bool check_device_extensions(cl_device_id device_id, char* extensions)
+{
+ char* pch;
+
+ pch = strtok(extensions, " ");
+ while(pch != NULL) {
+ if( strlen(pch) > 0
+ && !piglit_cl_is_device_extension_supported(device_id, pch)) {
+ char* device_name = piglit_cl_get_device_info(device_id,
+ CL_DEVICE_NAME);
+ printf("\n# Skipping device %s because extension %s is not supported.\n\n",
+ device_name,
+ pch);
+ free(device_name);
+ return false;
+ }
+ pch = strtok(NULL, " ");
+ }
+
+ return true;
+}
+
+/* Run the test(s) */
+int piglit_cl_framework_run(int argc, char** argv)
+{
+ enum piglit_result result = PIGLIT_SKIP;
+
+ int version = 0;
+ cl_platform_id platform_id = NULL;
+ cl_device_id device_id = NULL;
+
+ /* Get test configuration */
+ struct piglit_cl_test_config_header *config =
+ piglit_cl_get_test_config(argc,
+ (const char**)argv,
+ &PIGLIT_CL_DEFAULT_TEST_CONFIG_HEADER);
+
+ /* Check that config is valid */
+ // run_per_platform, run_per_device
+ if(config->run_per_platform && config->run_per_device) {
+ fprintf(stderr,
+ "Invalid configuration, only one of run_per_platform and run_per_device can be true.\n");
+ piglit_report_result(PIGLIT_WARN);
+ }
+
+ /* Init */
+ if(config->init_func != NULL) {
+ config->init_func(argc, (const char**)argv, config);
+ }
+
+ /* Print test name and file */
+ printf("## Test: %s (%s) ##\n\n", config->name != NULL ? config->name : "",
+ config->_filename);
+
+ /* Get version to test against */
+ version = piglit_cl_get_version_arg(argc, (const char **)argv);
+ if(version > 0) {
+ if(version > PIGLIT_CL_VERSION) {
+ printf("Piglit was compiled with lower OpenCL version (%d.%d) than version argument: %d.%d.\n",
+ PIGLIT_CL_VERSION/10, PIGLIT_CL_VERSION%10,
+ version/10, version%10);
+ piglit_report_result(PIGLIT_SKIP);
+ }
+ } else {
+ /*
+ * If version was not provided on the command line, set it to
+ * the version against which Piglit was compiled (PIGLIT_CL_VERSION)
+ */
+ version = PIGLIT_CL_VERSION;
+ }
+
+ /* Run the actual test */
+ if(!(config->run_per_platform || config->run_per_device)) {
+ print_test_info(config, version, NULL, NULL);
+ result = config->_test_run(argc, (const char**)argv, (void*)config,
+ version, NULL, NULL);
+ } else {
+ /* Run tests per platform or device */
+ int i;
+ regex_t platform_regex;
+ regex_t device_regex;
+
+ bool platform_defined;
+ unsigned int num_platforms;
+ cl_platform_id* platform_ids;
+
+ /* Create regexes */
+ if( config->platform_regex != NULL
+ && regcomp(&platform_regex, config->platform_regex, REG_EXTENDED | REG_NEWLINE)) {
+ fprintf(stderr,
+ "Regex to filter platforms is invalid, ignoring it.\n");
+ regcomp(&platform_regex, "", REG_EXTENDED | REG_NEWLINE);
+ piglit_merge_result(&result, PIGLIT_WARN);
+ }
+ if( config->device_regex != NULL
+ && regcomp(&device_regex, config->device_regex, REG_EXTENDED | REG_NEWLINE)) {
+ fprintf(stderr,
+ "Regex to filter devices is invalid, ignoring it.\n");
+ regcomp(&device_regex, "", REG_EXTENDED | REG_NEWLINE);
+ piglit_merge_result(&result, PIGLIT_WARN);
+ }
+
+ /* check for command-line/environment platform */
+ platform_defined = piglit_cl_get_platform_arg(argc, (const char**)argv,
+ &platform_id);
+
+ /* generate platforms list */
+ if(platform_defined) {
+ /* use platform defined by command-line/environment */
+ num_platforms = 1;
+ platform_ids = malloc(sizeof(cl_platform_id));
+ platform_ids[0] = platform_id;
+ } else {
+ /* use all available platforms */
+ num_platforms = piglit_cl_get_platform_ids(&platform_ids);
+ }
+
+ /* execute test for each platform in platforms list */
+ for(i = 0; i < num_platforms; i++) {
+ int final_version = version;
+ int platform_version;
+
+ platform_id = platform_ids[i];
+
+ /* Filter platform */
+ if(config->platform_regex != NULL) {
+ char* platform_name;
+
+ platform_name = piglit_cl_get_platform_info(platform_id,
+ CL_PLATFORM_NAME);
+ if(regexec(&platform_regex, platform_name, 0, NULL, 0)) {
+ printf("\n# Skipping platform %s because it does not match platform_regex.\n\n",
+ platform_name);
+ free(platform_name);
+ continue;
+ }
+ free(platform_name);
+ }
+
+ /* Check platform extensions */
+ if(!check_platform_extensions(platform_id, config->require_platform_extensions)) {
+ continue;
+ }
+
+ /* Get platform version */
+ platform_version = piglit_cl_get_platform_version(platform_id);
+
+ if(config->run_per_platform) {
+ /* Check platform version */
+ if(platform_version < final_version) {
+ printf("# Platform supporting only version %d.%d. Running test on that version.\n",
+ platform_version/10, platform_version%10);
+ final_version = platform_version;
+ }
+
+ /* run test on platform */
+ print_test_info(config, final_version, platform_id, NULL);
+ piglit_merge_result(&result,
+ config->_test_run(argc,
+ (const char**)argv,
+ (void*)config,
+ final_version,
+ platform_id,
+ NULL));
+ } else { //config->run_per_device
+ int j;
+
+ bool device_defined;
+ unsigned int num_devices;
+ cl_device_id* device_ids;
+
+ /* check for command-line/environment device */
+ device_defined = piglit_cl_get_device_arg(argc,
+ (const char**)argv,
+ platform_id,
+ &device_id);
+
+ /* generate devices list */
+ if(device_defined) {
+ /* use device defined by command-line/environment */
+ num_devices = 1;
+ device_ids = malloc(sizeof(cl_device_id));
+ device_ids[0] = device_id;
+ } else {
+ /* use all available devices */
+ num_devices = piglit_cl_get_device_ids(platform_id,
+ CL_DEVICE_TYPE_ALL,
+ &device_ids);
+ }
+
+ /* run tests per each device */
+ for(j = 0; j < num_devices; j++) {
+ int device_version;
+
+ device_id = device_ids[j];
+
+ /* Filter device */
+ if(config->device_regex != NULL) {
+ char* device_name;
+
+ device_name = piglit_cl_get_device_info(device_id,
+ CL_DEVICE_NAME);
+ if(regexec(&device_regex, device_name, 0, NULL, 0)) {
+ printf("\n# Skipping device %s because it does not match device_regex.\n\n",
+ device_name);
+ free(device_name);
+ continue;
+ }
+ free(device_name);
+ }
+
+ /* Check device extensions */
+ if(!check_device_extensions(device_id, config->require_device_extensions)) {
+ continue;
+ }
+
+ /* Check platform version */
+ if(platform_version < final_version) {
+ printf("# Platform supporting only version %d.%d. Running test on that version.\n",
+ platform_version/10, platform_version%10);
+ final_version = platform_version;
+ }
+ /* Check device version */
+ device_version = piglit_cl_get_device_version(device_id);
+ if(device_version < final_version) {
+ printf("# Device supporting only version %d.%d. Running test on that version.\n",
+ device_version/10, device_version%10);
+ final_version = device_version;
+ }
+
+ print_test_info(config, version, platform_id, device_id);
+ piglit_merge_result(&result,
+ config->_test_run(argc,
+ (const char**)argv,
+ (void*)config,
+ final_version,
+ platform_id,
+ device_id));
+ }
+
+ free(device_ids);
+ }
+ }
+
+ if(config->platform_regex != NULL) {
+ regfree(&platform_regex);
+ }
+ if(config->device_regex != NULL) {
+ regfree(&device_regex);
+ }
+
+ free(platform_ids);
+ }
+
+ /* Clean */
+ if(config->clean_func != NULL) {
+ config->clean_func(argc, (const char**)argv, config);
+ }
+
+ /* Report merged result */
+ printf("# Result:\n");
+ piglit_report_result(result);
+
+ /* UNREACHED */
+ return 1;
+}
+
+/* Get command-line/environment variables */
+
+const char*
+piglit_cl_get_arg_value(const int argc, const char *argv[], const char* arg)
+{
+ int i;
+ char* full_arg = calloc(strlen(arg) + 2, sizeof(char));
+ full_arg = strcpy(full_arg, "-");
+ full_arg = strcat(full_arg, arg);
+
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], full_arg)) {
+ if ((i+1) >= argc) {
+ fprintf(stderr,
+ "Argument error: %s requires a value\n",
+ full_arg);
+ free(full_arg);
+ piglit_report_result(PIGLIT_WARN);
+ } else {
+ free(full_arg);
+ return argv[i+1];
+ }
+ }
+ }
+
+ free(full_arg);
+ return NULL;
+}
+
+const char*
+piglit_cl_get_unnamed_arg(const int argc, const char *argv[], int index)
+{
+ int i;
+ int count = 0;
+
+ for (i = 1; i < argc; i++) {
+ if (strncmp(argv[i], "-", 1)) {
+ count++;
+ if((count - 1) == index) {
+ return argv[i];
+ }
+ } else {
+ i++;
+ }
+ }
+
+ return NULL;
+}
+
+bool
+piglit_cl_is_arg_defined(const int argc, const char *argv[], const char* arg)
+{
+ int i;
+ char* full_arg = calloc(strlen(arg) + 2, sizeof(char));
+ full_arg = strcpy(full_arg, "-");
+ full_arg = strcat(full_arg, arg);
+
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], full_arg)) {
+ free(full_arg);
+ return true;
+ }
+ }
+
+ free(full_arg);
+ return false;
+}
+
+int
+piglit_cl_get_version_arg(int argc, const char** argv)
+{
+ int version_major = 0;
+ int version_minor = 0;
+
+ const char* version_str;
+
+ /* First check argument then environment */
+ version_str = piglit_cl_get_arg_value(argc, argv, "version");
+ if(version_str == NULL) {
+ version_str = getenv("PIGLIT_CL_VERSION");
+ }
+
+ if(version_str != NULL) {
+ if(sscanf(version_str, "%i.%i", &version_major, &version_minor) != 2) {
+ version_major = 0;
+ version_minor = 0;
+ }
+ }
+
+ return version_major*10 + version_minor;
+}
+
+bool
+piglit_cl_get_platform_arg(const int argc, const char** argv,
+ cl_platform_id* platform_id)
+{
+ int i;
+ const char* arg_value;
+
+ /* First check argument then environment */
+ arg_value = piglit_cl_get_arg_value(argc, argv, "platform");
+ if(arg_value == NULL) {
+ arg_value = getenv("PIGLIT_CL_PLATFORM");
+ }
+
+ if(arg_value != NULL) {
+ unsigned int num_platforms;
+ cl_platform_id* platform_ids;
+
+ num_platforms = piglit_cl_get_platform_ids(&platform_ids);
+
+ for(i = 0; i < num_platforms; i++) {
+ char* platform_name = piglit_cl_get_platform_info(platform_ids[i],
+ CL_PLATFORM_NAME);
+
+ if(!strncmp(arg_value, platform_name, strlen(arg_value))) {
+ *platform_id = platform_ids[i];
+
+ free(platform_ids);
+ free(platform_name);
+ return true;
+ }
+
+ free(platform_name);
+ }
+
+ free(platform_ids);
+ fprintf(stderr,
+ "Could not find platform: %s\n",
+ arg_value);
+ piglit_report_result(PIGLIT_WARN);
+ }
+
+ return false;
+}
+
+bool
+piglit_cl_get_device_arg(const int argc, const char** argv,
+ cl_platform_id platform_id, cl_device_id* device_id)
+{
+ int i;
+ const char* arg_value;
+
+ /* First check argument then environment */
+ arg_value = piglit_cl_get_arg_value(argc, argv, "device");
+ if(arg_value == NULL) {
+ arg_value = getenv("PIGLIT_CL_DEVICE");
+ }
+
+ if(arg_value != NULL) {
+ unsigned int num_devices;
+ cl_device_id* device_ids;
+
+ num_devices = piglit_cl_get_device_ids(platform_id,
+ CL_DEVICE_TYPE_ALL,
+ &device_ids);
+
+ for(i = 0; i < num_devices; i++) {
+ char* device_name = piglit_cl_get_device_info(device_ids[i],
+ CL_DEVICE_NAME);
+
+ if(!strncmp(arg_value, device_name, strlen(arg_value))) {
+ *device_id = device_ids[i];
+
+ free(device_ids);
+ free(device_name);
+ return true;
+ }
+
+ free(device_name);
+ }
+
+ free(device_ids);
+ fprintf(stderr,
+ "Could not find device: %s\n",
+ arg_value);
+ piglit_report_result(PIGLIT_WARN);
+ }
+
+ return false;
+}
diff --git a/tests/util/piglit-framework-cl.h b/tests/util/piglit-framework-cl.h
new file mode 100644
index 000000000..c1fa0ff62
--- /dev/null
+++ b/tests/util/piglit-framework-cl.h
@@ -0,0 +1,354 @@
+/*
+ * Copyright © 2012 Blaž Tomažič <blaz.tomazic@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#pragma once
+#ifndef PIGLIT_FRAMEWORK_CL_H
+#define PIGLIT_FRAMEWORK_CL_H
+
+#include "piglit-util-cl.h"
+
+
+struct piglit_cl_test_config_header;
+
+/**
+ * \brief Get an empty test configuration with default values.
+ *
+ * Every test runner must have this function defined.
+ */
+typedef const void* piglit_cl_get_empty_test_config_t();
+
+/**
+ * \brief Run the test with selected config and environment.
+ *
+ * Every test runner must have this function defined.
+ *
+ * \note This function can be called multiple times.
+ *
+ * @param argc Argument count passed to \c main().
+ * @param argv Argument vector passed to \c main().
+ * @param config Test configuration.
+ * @param platform_id OpenCL platform id. Valid if \c config->run_per_platform
+ * is \c true.
+ * @param device_id OpenCL device id. Valid if \c config->run_per_device is
+ * \c true.
+ * @return Result of test.
+ */
+typedef enum piglit_result piglit_cl_test_run_t(const int argc,
+ const char** argv,
+ void* config,
+ int version,
+ cl_platform_id platform_id,
+ cl_device_id device_id);
+
+/**
+ * \brief Initialize test configuration.
+ *
+ * Type definition for a function that is passed to \c config.init_func. This
+ * function is intended to be used to fill the \c config when there needs to
+ * be some input processing.
+ *
+ * \note This function is called once before running test(s).
+ *
+ * @param argc Argument count passed to \c main().
+ * @param argv Argument vector passed to \c main().
+ * @param config Test configuration.
+ */
+typedef void piglit_cl_test_init_t(const int argc,
+ const char** argv,
+ void* config);
+/**
+ * \brief Clean environment.
+ *
+ * Type definition for a function that is passed to \c config.clean_func. This
+ * function is intended to be used to clean memory after finishing all tests.
+ *
+ * \note This function is called once after running test(s).
+ *
+ * @param argc Argument count passed to \c main().
+ * @param argv Argument vector passed to \c main().
+ * @param config Test configuration.
+ */
+typedef void piglit_cl_test_clean_t(const int argc,
+ const char** argv,
+ void* config);
+
+
+#define PIGLIT_CL_TEST_CONFIG_HEADER \
+ char* _filename; /**< Read-only test filename. (internal) */ \
+ piglit_cl_test_run_t* _test_run; \
+ /**< Function pointer to run the test. (internal) */ \
+ \
+ char* name; /**< Name of test. (optional) */ \
+ \
+ bool run_per_platform; /**< Run test per platform. (optional) */ \
+ bool run_per_device; /**< Run test per device. (optional) */ \
+ \
+ char* platform_regex; \
+ /**< Regex to filter platforms (optional) */ \
+ char* device_regex; \
+ /**< Regex to filter devices (optional) */ \
+ \
+ char* require_platform_extensions; \
+ /**< Space-separated list of required platform extensions
+ (optional) */ \
+ char* require_device_extensions; \
+ /**< Space-separated list of required device extensions
+ (optional) */ \
+ \
+ piglit_cl_test_init_t* init_func; \
+ /**< Function pointer to initialize environment. (optional) */ \
+ piglit_cl_test_clean_t* clean_func; \
+ /**< Function pointer to clean environment. (optional) */
+
+/**
+ * \brief OpenCL test configuration header.
+ *
+ * Every Piglit OpenCL test configuration has this fields. They are
+ * defined at the beginning of the test configuration struct.
+ */
+struct piglit_cl_test_config_header {
+ PIGLIT_CL_TEST_CONFIG_HEADER
+};
+
+/**
+ * \brief Get test configuration.
+ *
+ * Every test has this function defined.
+ */
+extern void*
+piglit_cl_get_test_config(const int argc,
+ const char** argv,
+ const struct piglit_cl_test_config_header* config_header);
+
+/**
+ * \def PIGLIT_CL_TEST_CONFIG_BEGIN(test_config_struct_t)
+ *
+ * This macro must be used to create a test configuration instance
+ * and must be followed by \c PIGLIT_CL_TEST_CONFIG_END macro.
+ * It defines the first part of \c piglit_cl_get_test_config function
+ * that is used to retrieve the test configuration, set default
+ * values to it and implement main function.
+ *
+ * In beetween \c PIGLIT_CL_TEST_CONFIG_BEGIN and
+ * \c PIGLIT_CL_TEST_CONFIG_END macros you can set values of fields
+ * defined in \c test_config_struct_t type.
+ *
+ * \pre \c test_config_struct_t must be defined by
+ * \c PIGLIT_CL_DEFINE_TEST_CONFIG_BEGIN and
+ * \c PIGLIT_CL_DEFINE_TEST_CONFIG_END
+ *
+ * \pre \c get_empty_test_config_f must have type
+ * \c piglit_cl_get_empty_test_config_t
+ *
+ * \pre \c test_run_f must have type
+ * \c piglit_cl_test_run_t
+ *
+ */
+/**
+ * \def PIGLIT_CL_TEST_CONFIG_END
+ *
+ * This macro must be used to create a test configuration instance
+ * and must follow \c PIGLIT_CL_TEST_CONFIG_BEGIN macro.
+ * It defines the last part of \c piglit_cl_get_test_config function
+ * that is used to retrieve the test configuration, set default
+ * values to it and implement main function.
+ */
+#define PIGLIT_CL_TEST_CONFIG_BEGIN(test_config_struct_t, \
+ get_empty_test_config_f, \
+ test_run_f) \
+ \
+ test_config_struct_t config; \
+ \
+ void* \
+ piglit_cl_get_test_config( \
+ const int argc, \
+ const char** argv, \
+ const struct piglit_cl_test_config_header* config_header_ptr) \
+ { \
+ piglit_cl_get_empty_test_config_t* _get_empty_config = \
+ get_empty_test_config_f; /*for compile time check*/ \
+ \
+ memcpy(&config, \
+ _get_empty_config(), \
+ sizeof(test_config_struct_t)); \
+ memcpy(&config, \
+ config_header_ptr, \
+ sizeof(struct piglit_cl_test_config_header)); \
+ \
+ config._test_run = test_run_f; \
+ config._filename = __FILE__;
+
+ /* Here goes the configuration of the test */
+
+#define PIGLIT_CL_TEST_CONFIG_END \
+ \
+ return &config; \
+ } \
+ \
+ int main(int argc, char** argv) \
+ { \
+ return piglit_cl_framework_run(argc, argv); \
+ }
+
+/**
+ * \def PIGLIT_CL_DEFINE_TEST_CONFIG_BEGIN(test_config_struct_t)
+ *
+ * This macro must be used by each test configuration definition
+ * and must be followed by \c PIGLIT_CL_DEFINE_TEST_CONFIG_END macro.
+ * It defines the first part \c test_config_struct_t type with first bytes
+ * set to \c piglit_cl_text_config_header.
+ *
+ * In beetween \c PIGLIT_CL_DEFINE_TEST_CONFIG_BEGIN and
+ * \c PIGLIT_CL_DEFINE_TEST_CONFIG_END macros you can define additional
+ * fields used by the tests.
+ *
+ * The name of test configuration type is manipulated by
+ * \c test_config_struct_t macro argument.
+ *
+ */
+/**
+ * \def PIGLIT_CL_DEFINE_TEST_CONFIG_END
+ *
+ * This macro must be used by each test configuration definition
+ * and must follow \c PIGLIT_CL_DEFINE_TEST_CONFIG_BEGIN macro.
+ * It defines the last part of \c test_config_struct_t type.
+ *
+ */
+#define PIGLIT_CL_DEFINE_TEST_CONFIG_BEGIN(test_config_struct_t) \
+ \
+ test_config_struct_t { \
+ PIGLIT_CL_TEST_CONFIG_HEADER
+
+ /* Here goes the test configuration definition */
+
+#define PIGLIT_CL_DEFINE_TEST_CONFIG_END \
+ \
+ };
+
+
+/**
+ * \brief Called from \c main function of each test.
+ *
+ * Each test has a definition of a \c main function
+ * in its configuration. The only thing that \c main does
+ * is to call this function.
+ *
+ * @param argc Argument count passed to \c main().
+ * @param argv Argument vector passed to \c main().
+ */
+int
+piglit_cl_framework_run(int argc, char** argv);
+
+
+/* Get command-line arguments */
+
+/**
+ * \brief Check if argument \c arg was passed to program.
+ *
+ * @param argc Argument count passed to \c main().
+ * @param argv Argument vector passed to \c main().
+ * @param arg String of argument to check.
+ * @return \c true if argument was passed to program.
+ */
+bool
+piglit_cl_is_arg_defined(int argc, const char** argv, const char* arg);
+
+/**
+ * \brief Get argument value passed to program.
+ *
+ * Get value passed after argument \c "-arg".
+ *
+ * @param argc Argument count passed to \c main().
+ * @param argv Argument vector passed to \c main().
+ * @param arg Argument to retrieve.
+ * @return Returns value passed by argument or NULL.
+ */
+const char*
+piglit_cl_get_arg_value(const int argc, const char** argv, const char* arg);
+
+/**
+ * \brief Get unnamed argument value passed to program.
+ *
+ * Get value index-th (zero based) unnamed argument passed to program.
+ *
+ * @param argc Argument count passed to \c main().
+ * @param argv Argument vector passed to \c main().
+ * @param index Index of argument to retrieve
+ * @return Returns value passed by argument or NULL.
+ */
+const char*
+piglit_cl_get_unnamed_arg(const int argc, const char** argv, int index);
+
+/**
+ * \brief Get version passed to program.
+ *
+ * Get value passed after argument "-version". If version
+ * argument is not defined use PIGLIT_CL_VERSION environment
+ * variable.
+ *
+ * @param argc Argument count passed to \c main().
+ * @param argv Argument vector passed to \c main().
+ * @return Version passed to program.
+ */
+int
+piglit_cl_get_version_arg(int argc, const char** argv);
+
+/**
+ * \brief Get platform id passed to program.
+ *
+ * Return a platform id with its name starting with value
+ * of argument passed after argument "-platform". If platform
+ * argument is not defined use PIGLIT_CL_PLATFORM environment
+ * variable.
+ *
+ * @param argc Argument count passed to \c main().
+ * @param argv Argument vector passed to \c main().
+ * @param platform_id Returns platform id.
+ * @return \c true if platform was passed to program.
+ */
+bool
+piglit_cl_get_platform_arg(const int argc,
+ const char** argv,
+ cl_platform_id* platform_id);
+
+/**
+ * \brief Get device id passed to program.
+ *
+ * Return a device id with its name starting with value
+ * of argument passed after argument "-device". If device
+ * argument is not defined use PIGLIT_CL_DEVICE environment
+ * variable.
+ *
+ * @param argc Argument count passed to \c main().
+ * @param argv Argument vector passed to \c main().
+ * @param platform_id Platform on which the device should be searched.
+ * @param device_id Returns device id.
+ * @return \c true if device was passed to program.
+ */
+bool
+piglit_cl_get_device_arg(const int argc,
+ const char** argv,
+ cl_platform_id platform_id,
+ cl_device_id* device_id);
+
+#endif //PIGLIT_FRAMEWORK_CL_H