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; }
enum piglit_result piglit_cl_test(const int argc, const char** argv, const struct piglit_cl_api_test_config* config, const struct piglit_cl_api_test_env* env) { enum piglit_result result = PIGLIT_PASS; int i; cl_int errNo; cl_uint num_devices; cl_device_id* devices; cl_context cl_ctx; bool found_invalid_platform = false; cl_platform_id* platform_ids; unsigned int num_platform_ids; cl_platform_id invalid_platform_id; //TODO: test also CL_CONTEXT_INTEROP_USER_SYNC cl_context_properties context_properties[] = { CL_CONTEXT_PLATFORM, (cl_context_properties)env->platform_id, 0 }; cl_context_properties invalid_context_properties[] = { CL_DEVICE_NAME, (cl_context_properties)env->platform_id, 0 }; cl_context_properties invalid_platform_context_properties[] = { CL_CONTEXT_PLATFORM, (cl_context_properties)NULL, 0 }; cl_context_properties multiple_platform_context_properties[] = { CL_CONTEXT_PLATFORM, (cl_context_properties)env->platform_id, CL_CONTEXT_PLATFORM, (cl_context_properties)env->platform_id, 0 }; /* Find invalid platform_id */ invalid_platform_id = 0; num_platform_ids = piglit_cl_get_platform_ids(&platform_ids); while(!found_invalid_platform) { found_invalid_platform = true; invalid_platform_id = (cl_platform_id)1; for(i = 0; i < num_platform_ids; i++) { if(invalid_platform_id == platform_ids[i]) { found_invalid_platform = false; break; } } } free(platform_ids); invalid_platform_context_properties[1] = (cl_context_properties)invalid_platform_id; /*** Normal usage ***/ /* get device ids */ num_devices = piglit_cl_get_device_ids(env->platform_id, CL_DEVICE_TYPE_ALL, &devices); /* * Create context. * Try creating context from 1 to num_devices devices. */ for(i = 1; i <= num_devices; i++) { test(context_properties, i, devices, NULL, NULL, CL_SUCCESS, &result, "Create context"); //TODO: test callback functions } /*** Errors ***/ /* * CL_INVALID_PLATFORM if properties is NULL and no platform * could be selected or if platform value specified in properties * is not a valid platform. * * Note: Can not test implementation-defined behaviour on * NULL context_properties. */ cl_ctx = clCreateContext(invalid_platform_context_properties, num_devices, devices, NULL, NULL, &errNo); if( errNo != CL_INVALID_PLATFORM #if defined(CL_VERSION_1_1) && errNo != CL_INVALID_PROPERTY #endif ) { test(invalid_platform_context_properties, num_devices, devices, NULL, NULL, CL_INVALID_PLATFORM, &result, "Trigger CL_INVALID_PLATFORM if platform value specified in properties is not a valid platform"); #if defined(CL_VERSION_1_1) printf("Another valid expected CL error: %d\n", CL_INVALID_PROPERTY); #endif piglit_merge_result(&result, PIGLIT_FAIL); } else if (cl_ctx != NULL) { test(invalid_platform_context_properties, num_devices, devices, NULL, NULL, CL_INVALID_PLATFORM, &result, "Trigger CL_INVALID_PLATFORM if platform value specified in properties is not a valid platform"); } /* * CL_INVALID_VALUE if context property name in properties is * not a supported property name; if devices is NULL; if * num_devices is equal to zero; or if pfn_notify is NULL but * user_data is not NULL. * * Version: 1.0 * * CL_INVALID_VALUE if devices is NULL; if num_devices is equal * to zero; or if pfn_notify is NULL but user_data is not NULL. * * Version: 1.1 */ if(env->version <= 10) { test(invalid_context_properties, num_devices, devices, NULL, NULL, CL_INVALID_VALUE, &result, "Trigger CL_INVALID_VALUE if context property name in properties is not a supported property name"); } test(context_properties, num_devices, NULL, NULL, NULL, CL_INVALID_VALUE, &result, "Trigger CL_INVALID_VALUE if devices is NULL"); test(context_properties, 0, devices, NULL, NULL, CL_INVALID_VALUE, &result, "Trigger CL_INVALID_VALUE if num_devices is equal to zero"); test(context_properties, num_devices, devices, NULL, &context_properties, CL_INVALID_VALUE, &result, "Trigger CL_INVALID_VALUE if pfn_notify is NULL but user_data is not NULL"); /* * CL_INVALID_PROPERTY if context property name in properties * is not a supported property name, if the value specified for * a supported property name is not valid, or if the same * property name is specified more than once. * * Version: 1.1 * * Note: 'if the value specified for a supported property name is * not valid' was already tested */ #if defined(CL_VERSION_1_1) if(env->version >= 11) { test(invalid_context_properties, num_devices, devices, NULL, NULL, CL_INVALID_PROPERTY, &result, "Trigger CL_INVALID_PROPERTY if context property name in poperties is not a supported property name"); test(multiple_platform_context_properties, num_devices, devices, NULL, NULL, CL_INVALID_PROPERTY, &result, "Trigger CL_INVALID_PROPERTY if the same property is specified more than once"); } #endif /* * CL_INVALID_DEVICE if devices contains an invalid device * or are not associated with the specified platform. * * TODO: implement */ /* * CL_DEVICE_NOT_AVAILABLE if a device in devices is currently * not available even though the device was returned by clGetDeviceIDs. * * Note: Can not test */ free(devices); return result; }
enum piglit_result piglit_cl_test(const int argc, const char** argv, const struct piglit_cl_api_test_config* config, const struct piglit_cl_api_test_env* env) { enum piglit_result result = PIGLIT_PASS; int i; int mask; cl_int errNo; cl_context cl_ctx; cl_command_queue command_queue; cl_uint num_devices; cl_device_id* devices; cl_command_queue_properties mixed_command_queue_properties[4] = {CL_QUEUE_PROPERTIES, 0, 0, 0}; cl_context_properties context_properties[] = { CL_CONTEXT_PLATFORM, (cl_context_properties)env->platform_id, 0 }; int num_command_queue_properties = PIGLIT_CL_ENUM_NUM(cl_command_queue_properties, env->version); const cl_command_queue_properties* command_queue_properties = PIGLIT_CL_ENUM_ARRAY(cl_command_queue_properties); /*** Normal usage ***/ /* create context */ cl_ctx = clCreateContext(context_properties, 1, &env->device_id, NULL, NULL, &errNo); if(errNo == CL_DEVICE_NOT_FOUND) { fprintf(stderr, "No available devices.\n"); return PIGLIT_SKIP; } if(!piglit_cl_check_error(errNo, CL_SUCCESS)) { fprintf(stderr, "Failed (error code: %s): Create context.\n", piglit_cl_get_error_name(errNo)); return PIGLIT_FAIL; } /* * For each command queue properties mix. * There are 2^(num_command_queue_properties)-1 possible options. */ for(mask = 0; mask < (1 << num_command_queue_properties); mask++) { mixed_command_queue_properties[1] = get_mixed_command_queue_properties(mask, command_queue_properties); if (properties_forbidden(mixed_command_queue_properties[1], env)) continue; #if defined CL_VERSION_2_0 if (env->version >= 20) { command_queue = clCreateCommandQueueWithProperties( cl_ctx, env->device_id, mixed_command_queue_properties, &errNo); } else #endif //CL_VERSION_2_0 { command_queue = clCreateCommandQueue(cl_ctx, env->device_id, mixed_command_queue_properties[1], &errNo); } if(errNo != CL_SUCCESS && errNo != CL_INVALID_QUEUE_PROPERTIES) { piglit_cl_check_error(errNo, CL_SUCCESS); fprintf(stderr, "Failed (error code: %s): Create command queue using 0x%X as command queue properties.\n", piglit_cl_get_error_name(errNo), (unsigned int)mixed_command_queue_properties[1]); piglit_merge_result(&result, PIGLIT_FAIL); } clReleaseCommandQueue(command_queue); } /*** Errors ***/ /* * CL_INVALID_CONTEXT if context is not a valid context. */ clCreateCommandQueue(NULL, env->device_id, 0, &errNo); if(!piglit_cl_check_error(errNo, CL_INVALID_CONTEXT)) { fprintf(stderr, "Failed (error code: %s): Trigger CL_INVALID_CONTEXT if contest is not a valid context.\n", piglit_cl_get_error_name(errNo)); piglit_merge_result(&result, PIGLIT_FAIL); } /* * CL_INVALID_DEVICE if device is not a valid device or is * not associated with context. */ clCreateCommandQueue(cl_ctx, NULL, 0, &errNo); if(!piglit_cl_check_error(errNo, CL_INVALID_DEVICE)) { fprintf(stderr, "Failed (error code: %s): Trigger CL_INVALID_DEVICE if device is not a valid device.\n", piglit_cl_get_error_name(errNo)); piglit_merge_result(&result, PIGLIT_FAIL); } num_devices = piglit_cl_get_device_ids(env->platform_id, CL_DEVICE_TYPE_ALL, &devices); for(i = 0; i < num_devices; i++) { if(devices[i] != env->device_id) { clCreateCommandQueue(cl_ctx, devices[i], 0, &errNo); if(!piglit_cl_check_error(errNo, CL_INVALID_DEVICE)) { fprintf(stderr, "Failed (error code: %s): Trigger CL_INVALID_DEVICE if device that is not associated with context.\n", piglit_cl_get_error_name(errNo)); piglit_merge_result(&result, PIGLIT_FAIL); } } } free(devices); /* * CL_INVALID_VALUE if values specified in properties are not valid. */ clCreateCommandQueue(cl_ctx, env->device_id, 0XFFFFFFFF, &errNo); if(!piglit_cl_check_error(errNo, CL_INVALID_VALUE)) { fprintf(stderr, "Failed (error code: %s): Trigger CL_INVALID_VALUE if values specified in properties are not valid.\n", piglit_cl_get_error_name(errNo)); piglit_merge_result(&result, PIGLIT_FAIL); } /* * CL_INVALID_QUEUE_PROPERTIES if values specified in properties * are valid but are not supported by the device. * * Note: already tested in 'normal usage' section */ clReleaseContext(cl_ctx); return result; }
/* 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; }