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;
}
Example #2
0
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;
}
Example #3
0
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;
}