/* * Copyright © 2012 Blaž Tomažič * * 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(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), "%s", config->build_options); free(old); } if(env.clc_version > 10) { //If -cl-std was already in config->build_options, use what the test requested if (!strstr(build_options, "-cl-std")){ 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); } } 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; }