diff options
Diffstat (limited to 'tests/util/piglit-framework-cl-program.c')
-rw-r--r-- | tests/util/piglit-framework-cl-program.c | 372 |
1 files changed, 372 insertions, 0 deletions
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; +} |