[Piglit] [PATCH 7/7] cl-program-tester: Add gentype option to config section

Tom Stellard tom at stellard.net
Mon Sep 30 07:47:46 PDT 2013


From: Tom Stellard <thomas.stellard at amd.com>

The gentype option allows a test file to specify a list of types and
vector sizes to be used for each test.  cl-program-tester will run each
test once for each comibnation of type and vector size.

This makes it possible to write a generic test that can be run on a
number of different data types.  The macro _PIGLIT_GENTYPE is used to
specify which types in the kernel will be generic and it will be replaced
with the current type for each test run.

This patch also adds the kernel-args.cl test which demonstrates how to
use the new gentype option.
---
 tests/cl/doc_program.cl                  |  11 +-
 tests/cl/doc_program.program_test        |  10 ++
 tests/cl/program/execute/kernel-args.cl  |  19 ++
 tests/cl/program/program-tester.c        | 157 ++++++++++++++++-
 tests/util/piglit-framework-cl-program.c | 288 +++++++++++++++++++------------
 tests/util/piglit-framework-cl-program.h |  43 +++++
 tests/util/piglit-framework-cl.c         |  12 ++
 tests/util/piglit-util-cl.h              |   3 +-
 8 files changed, 420 insertions(+), 123 deletions(-)
 create mode 100644 tests/cl/program/execute/kernel-args.cl

diff --git a/tests/cl/doc_program.cl b/tests/cl/doc_program.cl
index 84e92ee..7f7fee2 100644
--- a/tests/cl/doc_program.cl
+++ b/tests/cl/doc_program.cl
@@ -30,7 +30,16 @@ expect_test_fail: true       # Expect that tests will fail (arguments won't chec
 dimensions: 3                # Number of dimensions for ND kernel (default: 1)
 global_size: 10 10 10        # Global work size for ND kernel (default: 1 0 0)
 local_size:   2  2  2        # Local work size for ND kernel (default: NULL)
-
+gentype: char uchar 2 3      # List of types to test with.  If set, the program test will
+                             # run once for each combination of type and vector size and
+                             # the macro _PIGLIT_GENTYPE will set to the current type being
+                             # tested.
+                             # The accepted types are: char, uchar, short, ushort, int, uint,
+                             #                         long, ulong, float, double
+                             # The accepted vector sizes are: 1, 2, 3, 4, 8, 16 and
+                             # s -> Use only scalar sizes (1)
+                             # v -> Use only vector sizes (2, 3, 4, 8, 16)
+                             # n -> Use all sizes (1, 2, 3, 4, 8, 16)
 
 # Execution tests #
 
diff --git a/tests/cl/doc_program.program_test b/tests/cl/doc_program.program_test
index 3ff67a6..5139255 100644
--- a/tests/cl/doc_program.program_test
+++ b/tests/cl/doc_program.program_test
@@ -27,6 +27,16 @@ expect_test_fail: true       # Expect that tests will fail (arguments won't chec
 dimensions: 3                # Number of dimensions for ND kernel (default: 1)
 global_size: 10 10 10        # Global work size for ND kernel (default: 1 0 0)
 local_size:   2  2  2        # Local work size for ND kernel (default: NULL)
+gentype: char uchar 2 3      # List of types to test with.  If set, the program test will
+                             # run once for each combination of type and vector size and
+                             # the macro _PIGLIT_GENTYPE will set to the current type being
+                             # tested.
+                             # The accepted types are: char, uchar, short, ushort, int, uint,
+                             #                         long, ulong, float, double
+                             # The accepted vector sizes are: 1, 2, 3, 4, 8, 16 and
+                             # s -> Use only scalar sizes (1)
+                             # v -> Use only vector sizes (2, 3, 4, 8, 16)
+                             # n -> Use all sizes (1, 2, 3, 4, 8, 16)
 
 #program_source_file: "program.cl"  # Program source file path to use as source (relative to this file)
 #program_binary_file: "program.bin" # Program binary file path to use as binary (relative to this file)
diff --git a/tests/cl/program/execute/kernel-args.cl b/tests/cl/program/execute/kernel-args.cl
new file mode 100644
index 0000000..1923d3e
--- /dev/null
+++ b/tests/cl/program/execute/kernel-args.cl
@@ -0,0 +1,19 @@
+/*!
+[config]
+dimensions: 1
+global_size: 1 0 0
+kernel_name: test
+gentype: char uchar short ushort int uint float n
+
+[test]
+name: A
+arg_out: 0 buffer gentype[2] 1 2
+arg_in:  1 gentype 1
+arg_in:  2 gentype 2
+
+!*/
+
+kernel void test(global _PIGLIT_GENTYPE *out, _PIGLIT_GENTYPE in, _PIGLIT_GENTYPE in2) {
+	out[0] = in;
+	out[1] = in2;
+}
diff --git a/tests/cl/program/program-tester.c b/tests/cl/program/program-tester.c
index fbfeb7b..d65548c 100644
--- a/tests/cl/program/program-tester.c
+++ b/tests/cl/program/program-tester.c
@@ -104,6 +104,7 @@
 #define REGEX_TYPE_UINT       REGEX_DEFINE_TYPE("uint")
 #define REGEX_TYPE_LONG       REGEX_DEFINE_TYPE("long")
 #define REGEX_TYPE_ULONG      REGEX_DEFINE_TYPE("ulong")
+#define REGEX_TYPE_GENTYPE    "gentype"
 // half is defined as unsigned short and C can't read/write its value.
 // Also half is only used as a storage format unless device supports
 // cl_khr_fp16
@@ -117,7 +118,7 @@
 #define REGEX_TYPE  REGEX_TYPE_CHAR "|" REGEX_TYPE_UCHAR "|" \
                     REGEX_TYPE_SHORT "|" REGEX_TYPE_USHORT "|" \
                     REGEX_TYPE_INT "|" REGEX_TYPE_UINT "|" REGEX_TYPE_LONG "|" \
-                    REGEX_TYPE_ULONG "|" REGEX_TYPE_FLOAT
+                    REGEX_TYPE_ULONG "|" REGEX_TYPE_FLOAT "|" REGEX_TYPE_GENTYPE
 
 /*
  * Value argument:
@@ -833,8 +834,35 @@ get_section_content(const char* src, char** content)
 	return size;
 }
 
+static void* vectorize_value(int* array, int type_size, int buffer_length,
+                            int vec_elements)
+{
+	unsigned i;
+	char* newarray;
+	unsigned in_mem_vec_elements;
+	/* Special case for vec3 buffer since they are aligned to 4 dwords
+	 * in memory.
+	 */
+	if (buffer_length == 0) {
+		in_mem_vec_elements = vec_elements;
+	} else {
+		in_mem_vec_elements = piglit_cl_get_num_mem_elements(vec_elements);
+	}
+	newarray = calloc(type_size, buffer_length * in_mem_vec_elements);
+	for (i = 0; i < buffer_length; i++){
+		int j;
+		for (j = 0; j < vec_elements; j++) {
+			memcpy(newarray + (i * type_size * in_mem_vec_elements) + (j * type_size),
+			array + i, type_size);
+		}
+	}
+	free(array);
+	return newarray;
+}
+
 void
-get_test_arg_value(struct test_arg* test_arg, const char* value, size_t length)
+get_test_arg_value(struct test_arg* test_arg, const char* value, size_t length,
+			unsigned gentype_size, unsigned gentype_elements)
 {
 	size_t i; // index in array
 	size_t c; // component in element
@@ -876,10 +904,16 @@ get_test_arg_value(struct test_arg* test_arg, const char* value, size_t length)
 		CASE(PIGLIT_CL_TYPE_LONG,   cl_long,    get_int_array,    int_array)
 		CASE(PIGLIT_CL_TYPE_ULONG,  cl_ulong,   get_uint_array,   uint_array)
 		CASE(PIGLIT_CL_TYPE_FLOAT,  cl_float,   get_float_array,  float_array)
+		CASE(PIGLIT_CL_TYPE_GENTYPE, cl_uint,   get_uint_array,   uint_array)
 	}
 
 #undef CASE
 
+	if (test_arg->cl_type == PIGLIT_CL_TYPE_GENTYPE) {
+		test_arg->value = vectorize_value(test_arg->value, gentype_size,
+					test_arg->length, gentype_elements);
+	}
+
 	free(int_array);
 	free(uint_array);
 	free(float_array);
@@ -984,6 +1018,7 @@ get_test_arg(const char* src, struct test* test, bool arg_in)
 	ELSEIF(REGEX_TYPE_LONG,   PIGLIT_CL_TYPE_LONG)
 	ELSEIF(REGEX_TYPE_ULONG,  PIGLIT_CL_TYPE_ULONG)
 	ELSEIF(REGEX_TYPE_FLOAT,  PIGLIT_CL_TYPE_FLOAT)
+	ELSEIF(REGEX_TYPE_GENTYPE, PIGLIT_CL_TYPE_GENTYPE)
 
 #undef IF
 #undef ELSEIF
@@ -1084,6 +1119,72 @@ get_test_arg(const char* src, struct test* test, bool arg_in)
 	}
 }
 
+static uint32_t
+parse_gentype(char *gentype_str)
+{
+	char *type;
+	uint32_t gentype;
+	while ((type = strtok(gentype_str, " "))) {
+		char *endptr;
+		int length;
+		/* strtok requres that the first paramter be NULL for all
+		 * calls after the fist. */
+		gentype_str = NULL;
+		length = strtol(type, &endptr, 0);
+		if (endptr != type) {
+			switch (length) {
+			case  1: gentype |= GENLEN_1;  break;
+			case  2: gentype |= GENLEN_2;  break;
+			case  3: gentype |= GENLEN_3;  break;
+			case  4: gentype |= GENLEN_4;  break;
+			case  8: gentype |= GENLEN_8;  break;
+			case 16: gentype |= GENLEN_16; break;
+			default:
+				fprintf(stderr, "%d is not a valid gentype length\n", length);
+				exit_report_result(PIGLIT_FAIL);
+				break;
+			}
+			continue;
+		}
+
+		/* The token is not an integer, so we have a type name or
+		 * a special identifier.
+		 */
+
+		if (!strcmp(type, "char")) {
+			gentype |= GENTYPE_CHAR;
+		} else if (!strcmp(type, "uchar")) {
+			gentype |= GENTYPE_UCHAR;
+		} else if (!strcmp(type, "short")) {
+			gentype |= GENTYPE_SHORT;
+		} else if (!strcmp(type, "ushort")) {
+			gentype |= GENTYPE_USHORT;
+		} else if (!strcmp(type, "int")) {
+			gentype |= GENTYPE_INT;
+		} else if (!strcmp(type, "uint")) {
+			gentype |= GENTYPE_UINT;
+		} else if (!strcmp(type, "long")) {
+			gentype |= GENTYPE_LONG;
+		} else if (!strcmp(type, "ulong")) {
+			gentype |= GENTYPE_ULONG;
+		} else if (!strcmp(type, "float")) {
+			gentype |= GENTYPE_FLOAT;
+		} else if (!strcmp(type, "double")) {
+			gentype |= GENTYPE_DOUBLE;
+		} else if (!strcmp(type, "s")) {
+			gentype |= GENLEN_SCALAR;
+		} else if (!strcmp(type, "v")) {
+			gentype |= GENLEN_VECTOR;
+		} else if (!strcmp(type, "n")) {
+			gentype |= GENLEN_SCALAR | GENLEN_VECTOR;
+		} else {
+			fprintf(stderr, "%s is not a valid gentype type\n");
+			exit_report_result(PIGLIT_FAIL);
+		}
+	}
+	return gentype;
+}
+
 /**
  * Helper function for parsing a test name and checking for illegal characters.
  */
@@ -1316,6 +1417,11 @@ parse_config(const char* config_str,
 					} else {
 						local_work_size_null = true;
 					}
+				} else if (regex_match(key, "^gentype$")) {
+					if (!regex_match(value, REGEX_FULL_MATCH(REGEX_NULL))) {
+						config->gentype = parse_gentype(value);
+					}
+
 				} else {
 					fprintf(stderr,
 					        "Invalid configuration, key '%s' does not belong to a [config] section: %s\n",
@@ -1653,6 +1759,7 @@ check_test_arg_value(struct test_arg test_arg,
 		CASEI(PIGLIT_CL_TYPE_LONG,   "long",   cl_long)
 		CASEU(PIGLIT_CL_TYPE_ULONG,  "ulong",  cl_ulong)
 		CASEF(PIGLIT_CL_TYPE_FLOAT,  "float",  cl_float)
+		CASEI(PIGLIT_CL_TYPE_GENTYPE, "gentype", cl_int)
 	}
 
 #undef CASEF
@@ -1714,13 +1821,20 @@ test_kernel(const struct piglit_cl_program_test_config* config,
 	for(j = 0; j < test.num_args_in; j++) {
 		bool arg_set = false;
 		struct test_arg test_arg = test.args_in[j];
+		unsigned arg_size = test_arg.vec_elements * piglit_cl_type_get_size(test_arg.cl_type);
+		if (test_arg.cl_type == PIGLIT_CL_TYPE_GENTYPE) {
+			test_arg.size_in_mem = test_arg.length * env->gentype_size *
+					piglit_cl_get_num_mem_elements(env->gentype_elements);
+			arg_size = test_arg.length * env->gentype_size * env->gentype_elements;
+		}
 
 		switch(test_arg.type) {
 		case TEST_ARG_VALUE:
-			get_test_arg_value(&test_arg, test_arg.raw_value, test_arg.vec_elements);
+			get_test_arg_value(&test_arg, test_arg.raw_value, test_arg.vec_elements,
+					env->gentype_size, env->gentype_elements);
 			arg_set = piglit_cl_set_kernel_arg(kernel,
 			                                   test_arg.index,
-							   test_arg.vec_elements * piglit_cl_type_get_size(test_arg.cl_type),
+							   arg_size,
 			                                   test_arg.value);
 			break;
 		case TEST_ARG_BUFFER: {
@@ -1737,11 +1851,13 @@ test_kernel(const struct piglit_cl_program_test_config* config,
 
 					get_test_arg_value(&test_arg,
 					                   repeat_value_str,
-					                   get_array_length(repeat_value_str));
+					                   get_array_length(repeat_value_str),
+							   env->gentype_size, env->gentype_elements);
 				} else {
 					get_test_arg_value(&test_arg,
 					                   test_arg.raw_value,
-						           test_arg.length * test_arg.vec_elements);
+						           test_arg.length * test_arg.vec_elements,
+							   env->gentype_size, env->gentype_elements);
 				}
 				buffer_arg.buffer = piglit_cl_create_buffer(env->context,
 				                                            CL_MEM_READ_WRITE,
@@ -1787,6 +1903,12 @@ test_kernel(const struct piglit_cl_program_test_config* config,
 	for(j = 0; j < test.num_args_out; j++) {
 		bool arg_set = false;
 		struct test_arg test_arg = test.args_out[j];
+		if (test_arg.cl_type == PIGLIT_CL_TYPE_GENTYPE) {
+			test_arg.size_in_mem = (test_arg.length * env->gentype_size * env->gentype_elements);
+			test_arg.size_in_mem = test_arg.length * env->gentype_size *
+				(env->gentype_elements == 3 ? 4 : env->gentype_elements);
+		}
+					printf("test_arg.size is %u\n", test_arg.size_in_mem);
 
 		switch(test_arg.type) {
 		case TEST_ARG_VALUE:
@@ -1864,6 +1986,10 @@ test_kernel(const struct piglit_cl_program_test_config* config,
 		int k;
 		bool arg_valid = false;
 		struct test_arg test_arg = test.args_out[j];
+		if (test_arg.cl_type == PIGLIT_CL_TYPE_GENTYPE) {
+			test_arg.size_in_mem = test_arg.length * env->gentype_size *
+				piglit_cl_get_num_mem_elements(env->gentype_elements);
+		}
 
 		switch(test_arg.type) {
 		case TEST_ARG_VALUE:
@@ -1871,6 +1997,7 @@ test_kernel(const struct piglit_cl_program_test_config* config,
 			break;
 		case TEST_ARG_BUFFER: {
 			struct buffer_arg buffer_arg;
+			void* read_value;
 
 			/* Find the right buffer */
 			for(k = 0; k < num_buffer_args; k++) {
@@ -1889,19 +2016,31 @@ test_kernel(const struct piglit_cl_program_test_config* config,
 
 					get_test_arg_value(&test_arg,
 					                   repeat_value_str,
-					                   get_array_length(repeat_value_str));
+					                   get_array_length(repeat_value_str),
+							   env->gentype_size, env->gentype_elements);
 				} else {
 					get_test_arg_value(&test_arg,
 					                   test_arg.raw_value,
-						           test_arg.length * test_arg.vec_elements);
+						           test_arg.length * test_arg.vec_elements,
+							   env->gentype_size, env->gentype_elements);
+				}
+				if (test_arg.cl_type == PIGLIT_CL_TYPE_GENTYPE) {
+					/* GENTYPE comparisons always assume an integer array,
+					 * so we need to makre sure the output pointer
+					 * is aligned to 4 bytes and also initialized to
+					 * zero.
+					 */
+					read_value = calloc(1, test_arg.size_in_mem + (4 - (test_arg.size_in_mem %4)));
+				} else {
+					read_value = malloc(test_arg.size_in_mem);
 				}
-				void* read_value = malloc(test_arg.size_in_mem);
 
 				if(piglit_cl_read_buffer(env->context->command_queues[0],
 					                     buffer_arg.buffer,
 					                     0,
 					                     test_arg.size_in_mem,
 					                     read_value)) {
+					unsigned i;
 					arg_valid = true;
 					if(check_test_arg_value(test_arg, read_value)) {
 						printf(" Argument %u: PASS%s\n",
diff --git a/tests/util/piglit-framework-cl-program.c b/tests/util/piglit-framework-cl-program.c
index 417405d..24badae 100644
--- a/tests/util/piglit-framework-cl-program.c
+++ b/tests/util/piglit-framework-cl-program.c
@@ -119,6 +119,131 @@ void piglit_cl_program_test_init(const int argc,
 	}
 }
 
+enum piglit_result build_and_execute_program(
+	const int argc,
+	const char **argv,
+	struct piglit_cl_program_test_env *env,
+	struct piglit_cl_program_test_config* config,
+	char *build_options)
+{
+	enum piglit_result result;
+	unsigned i;
+	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);
+	}
+
+	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;
+		}
+	}
+
+	/* 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);
+
+	return result;
+}
+
 /* Run by piglit_cl_framework_run() */
 enum piglit_result
 piglit_cl_program_test_run(const int argc,
@@ -128,7 +253,7 @@ piglit_cl_program_test_run(const int argc,
                            cl_platform_id platform_id,
                            cl_device_id device_id)
 {
-	enum piglit_result result;
+	enum piglit_result result = PIGLIT_PASS;
 
 	struct piglit_cl_program_test_config* config = void_config;
 	struct piglit_cl_program_test_env env = {
@@ -143,6 +268,9 @@ piglit_cl_program_test_run(const int argc,
 		.program = NULL,
 
 		.kernel = NULL,
+
+		.gentype_size = 0,
+		.gentype_elements = 0
 	};
 
 	int i;
@@ -231,106 +359,55 @@ piglit_cl_program_test_run(const int argc,
 		}
 	}
 
-	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);
+	if (!config->gentype) {
+		result = build_and_execute_program(argc, argv, &env, config, build_options);
+	} else {
+		char define[50];
+		const char *type_str;
+		const char *len_str;
+		unsigned type_i, len_i;
+		for (type_i = GENTYPE_START; type_i <= GENTYPE_END; ++type_i) {
+			unsigned gentype_size, gentype_elements;
+			unsigned type_bit = (1 << type_i);
+			if (!(config->gentype & type_bit)) {
+				continue;
 			}
-		} 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);
+			switch(type_bit) {
+			case GENTYPE_CHAR: type_str = "char"; gentype_size = 1; break;
+			case GENTYPE_UCHAR: type_str = "uchar"; gentype_size = 1; break;
+			case GENTYPE_SHORT: type_str = "short"; gentype_size = 2; break;
+			case GENTYPE_USHORT: type_str = "ushort"; gentype_size = 2; break;
+			case GENTYPE_INT: type_str = "int"; gentype_size = 4; break;
+			case GENTYPE_UINT: type_str = "uint"; gentype_size = 4; break;
+			case GENTYPE_LONG: type_str = "long"; gentype_size = 8; break;
+			case GENTYPE_ULONG: type_str = "ulong"; gentype_size = 8; break;
+			case GENTYPE_FLOAT: type_str = "float"; gentype_size = 4; break;
+			case GENTYPE_DOUBLE: type_str = "double"; gentype_size = 8; break;
+			default: assert(!"Unkown type."); break;
+			}
+			for (len_i = GENLEN_START; len_i <= GENLEN_END; ++len_i) {
+				unsigned len_bit = (1 << len_i);
+				char *new_build_options;
+				if (!(config->gentype & len_bit)) {
+					continue;
+				}
+				switch(len_bit) {
+				default: len_str = ""; gentype_elements = 1; break;
+				case GENLEN_2: len_str = "2"; gentype_elements = 2; break;
+				case GENLEN_3: len_str = "3"; gentype_elements = 3; break;
+				case GENLEN_4: len_str = "4"; gentype_elements = 4; break;
+				case GENLEN_8: len_str = "8"; gentype_elements = 8; break;
+				case GENLEN_16: len_str = "16"; gentype_elements = 16; break;
+				}
+				sprintf(define, " -D_PIGLIT_GENTYPE=%s%s",
+							type_str, len_str);
+				new_build_options = malloc(sizeof(define) + strlen(build_options) + 1);
+				sprintf(new_build_options, "%s%s", build_options, define);
+				env.gentype_size = gentype_size;
+				env.gentype_elements = gentype_elements;
+				piglit_merge_result(&result, build_and_execute_program(argc, argv, &env, config, new_build_options));
+				free(new_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;
 		}
 	}
 
@@ -339,19 +416,6 @@ piglit_cl_program_test_run(const int argc,
 		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);
 
diff --git a/tests/util/piglit-framework-cl-program.h b/tests/util/piglit-framework-cl-program.h
index bf15d3d..3131604 100644
--- a/tests/util/piglit-framework-cl-program.h
+++ b/tests/util/piglit-framework-cl-program.h
@@ -27,6 +27,43 @@
 
 #include "piglit-framework-cl.h"
 
+#define GENTYPE_START  0
+#define GENTYPE_END    9
+#define GENLEN_START  10
+#define GENLEN_END    15
+
+#define GENTYPE_CHAR   (1 << 0)
+#define GENTYPE_UCHAR  (1 << 1)
+#define GENTYPE_SHORT  (1 << 2)
+#define GENTYPE_USHORT (1 << 3)
+#define GENTYPE_INT    (1 << 4)
+#define GENTYPE_UINT   (1 << 5)
+#define GENTYPE_LONG   (1 << 6)
+#define GENTYPE_ULONG  (1 << 7)
+#define GENTYPE_FLOAT  (1 << 8)
+#define GENTYPE_DOUBLE (1 << 9)
+#define GENLEN_1      (1 << 10)
+#define GENLEN_2      (1 << 11)
+#define GENLEN_3      (1 << 12)
+#define GENLEN_4      (1 << 13)
+#define GENLEN_8      (1 << 14)
+#define GENLEN_16     (1 << 15)
+
+#define GENTYPE_SIGNED_INTEGER \
+  (GENTYPE_CHAR | GENTYPE_SHORT | GENTYPE_INT | GENTYPE_LONG)
+#define GENTYPE_UNSIGNED_INTEGER \
+  (GENTYPE_UCHAR | GENTYPE_USHORT | GENTYPE_UINT | GENTYPE_ULONG)
+#define GENTYPE_INTEGER \
+  (GENTYPE_SIGNED_INTEGER | GENTYPE_UNSIGNED_INTEGER)
+
+#define GENLEN_SCALAR \
+  (GENLEN_1)
+#define GENLEN_VECTOR \
+  (GENLEN_2 | GENLEN_3 | GENLEN_4 | GENLEN_8 | GENLEN_16)
+#define GENTYPE \
+  (GENTYPE_INTEGER | GENTYPE_FLOAT | GENLEN_SCALAR)
+#define GENTYPEN \
+  (GENTYPE | GENLEN_VECTOR)
 
 typedef const struct piglit_cl_program_test_config
                      piglit_cl_program_test_config_t;
@@ -87,6 +124,9 @@ PIGLIT_CL_DEFINE_TEST_CONFIG_BEGIN(struct piglit_cl_program_test_config)
 	char* kernel_name; /**< Create kernel(s) for program.
 	                        Conflicts with both \c expect_build_fail==TRUE and
 	                        \c build_only==TRUE. (optional) */
+	uint32_t gentype; /**< Bitfield of types to test.  For each bit set the
+                               program will be compiled with
+                               -D_PIGLIT_GENTYPE=type and exucted. */
 
 PIGLIT_CL_DEFINE_TEST_CONFIG_END
 
@@ -153,6 +193,9 @@ struct piglit_cl_program_test_env {
 	                       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.*/
+
+	unsigned gentype_size;
+	unsigned gentype_elements;
 };
 
 
diff --git a/tests/util/piglit-framework-cl.c b/tests/util/piglit-framework-cl.c
index 241dd42..2e887ce 100644
--- a/tests/util/piglit-framework-cl.c
+++ b/tests/util/piglit-framework-cl.c
@@ -86,6 +86,12 @@ bool check_platform_extensions(cl_platform_id platform_id, char* extensions)
 {
 	char* pch;
 
+	/* Initial calling strtok with a NULL argument may have undefined results if
+	 * strtok() was previously used by this program.
+	 */
+	if (!extensions) {
+		return true;
+	}
 	pch = strtok(extensions, " ");
 	while(pch != NULL) {
 		if(   strlen(pch) > 0
@@ -108,6 +114,12 @@ bool check_device_extensions(cl_device_id device_id, char* extensions)
 {
 	char* pch;
 
+	/* Initial calling strtok with a NULL argument may have undefined results if
+	 * strtok() was previously used by this program.
+	 */
+	if (!extensions) {
+		return true;
+	}
 	pch = strtok(extensions, " ");
 	while(pch != NULL) {
 		if(   strlen(pch) > 0
diff --git a/tests/util/piglit-util-cl.h b/tests/util/piglit-util-cl.h
index b392359..78d3229 100644
--- a/tests/util/piglit-util-cl.h
+++ b/tests/util/piglit-util-cl.h
@@ -56,7 +56,8 @@ enum piglit_cl_type {
 	PIGLIT_CL_TYPE_LONG,
 	PIGLIT_CL_TYPE_ULONG,
 	PIGLIT_CL_TYPE_FLOAT,
-	PIGLIT_CL_TYPE_DOUBLE
+	PIGLIT_CL_TYPE_DOUBLE,
+	PIGLIT_CL_TYPE_GENTYPE
 };
 
 /**
-- 
1.7.11.4



More information about the Piglit mailing list