diff mbox

glsl-1.10: extend to test arrays of arrays

Message ID 1399338646-1783-1-git-send-email-t_arceri@yahoo.com.au
State New
Headers show

Commit Message

'Timothy Arceri' via Patchwork Forward May 6, 2014, 1:10 a.m. UTC
Extends the varying packing tests to support
testing arrays of arrays

Signed-off-by: Timothy Arceri <t_arceri@yahoo.com.au>
---
 tests/all.py                                       |   2 +-
 .../glsl-1.10/execution/varying-packing/simple.c   | 158 ++++++++++++++-------
 2 files changed, 109 insertions(+), 51 deletions(-)

Comments

'Timothy Arceri' via Patchwork Forward May 22, 2014, 10:29 a.m. UTC | #1
Bump. Anyone able to take a look over this? I understand that arrays of
arrays is not really a glsl-1.10 test by this test also contains tests
for 1.20 and 1.30 so I figured I'd add arrays of arrays too rather than
duplicating the code elsewhere.


On Tue, 2014-05-06 at 11:10 +1000, Timothy Arceri wrote:
> Extends the varying packing tests to support
> testing arrays of arrays
> 
> Signed-off-by: Timothy Arceri <t_arceri@yahoo.com.au>
> ---
>  tests/all.py                                       |   2 +-
>  .../glsl-1.10/execution/varying-packing/simple.c   | 158 ++++++++++++++-------
>  2 files changed, 109 insertions(+), 51 deletions(-)
> 
> diff --git a/tests/all.py b/tests/all.py
> index 1e1aa3d..b59aaa4 100644
> --- a/tests/all.py
> +++ b/tests/all.py
> @@ -1159,7 +1159,7 @@ spec['glsl-1.10']['execution']['varying-packing'] = Group()
>  for type in ['int', 'uint', 'float', 'vec2', 'vec3', 'vec4', 'ivec2', 'ivec3',
>               'ivec4', 'uvec2', 'uvec3', 'uvec4', 'mat2', 'mat3', 'mat4',
>               'mat2x3', 'mat2x4', 'mat3x2', 'mat3x4', 'mat4x2', 'mat4x3']:
> -    for arrayspec in ['array', 'separate']:
> +    for arrayspec in ['array', 'separate', 'arrays_of_arrays']:
>          cmdline = 'simple {0} {1}'.format(type, arrayspec)
>          spec['glsl-1.10']['execution']['varying-packing'][cmdline] = \
>              concurrent_test('varying-packing-' + cmdline)
> diff --git a/tests/spec/glsl-1.10/execution/varying-packing/simple.c b/tests/spec/glsl-1.10/execution/varying-packing/simple.c
> index f7fd648..4d6cbba 100644
> --- a/tests/spec/glsl-1.10/execution/varying-packing/simple.c
> +++ b/tests/spec/glsl-1.10/execution/varying-packing/simple.c
> @@ -97,6 +97,8 @@
>   */
>  #include "piglit-util-gl-common.h"
>  
> +static const int inner_dim_size = 2;
> +
>  PIGLIT_GL_TEST_CONFIG_BEGIN
>  
>  	config.supports_gl_compat_version = 10;
> @@ -115,6 +117,14 @@ enum base_type
>  	BASE_TYPE_INT,
>  };
>  
> +enum test_array_type
> +{
> +	SEPARATE,
> +	ARRAY,
> +	ARRAYS_OF_ARRAYS,
> +};
> +
> +
>  static const char *
>  get_base_type_name(enum base_type t)
>  {
> @@ -189,7 +199,8 @@ const struct type_desc *all_types[] = {
>  struct varying_desc
>  {
>  	const struct type_desc *type;
> -	unsigned array_elems;
> +	unsigned one_dim_array_elems;
> +	unsigned two_dim_array_elems;
>  };
>  
>  /**
> @@ -198,12 +209,12 @@ struct varying_desc
>   */
>  static GLint
>  get_shader(bool is_vs, unsigned glsl_version, int num_varyings,
> -	   struct varying_desc *varyings)
> +	   struct varying_desc *varyings, enum test_array_type array_type)
>  {
>  	GLuint shader;
>  	char *full_text = malloc(1000 * 100 + num_varyings);
>  	char *text = full_text;
> -	unsigned i, j, k, l;
> +	unsigned i, j, k, l, m;
>  	const char *varying_keyword;
>  	unsigned offset = 0;
>  	GLenum shader_type = is_vs ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER;
> @@ -218,16 +229,24 @@ get_shader(bool is_vs, unsigned glsl_version, int num_varyings,
>  	}
>  
>  	text += sprintf(text, "#version %u\n", glsl_version);
> +	if (array_type == ARRAYS_OF_ARRAYS)
> +		text += sprintf(text, "#extension GL_ARB_arrays_of_arrays: enable\n");
>  	text += sprintf(text, "uniform int i;\n");
>  	for (i = 0; i < num_varyings; ++i) {
>  		const char *opt_flat_keyword = "";
>  		if (varyings[i].type->base != BASE_TYPE_FLOAT)
>  			opt_flat_keyword = "flat ";
> -		if (varyings[i].array_elems != 0) {
> +		if (varyings[i].two_dim_array_elems != 0) {
> +			text += sprintf(text, "%s%s %s var%u[%u][%u];\n",
> +					opt_flat_keyword, varying_keyword,
> +					varyings[i].type->name, i,
> +					inner_dim_size,
> +					varyings[i].two_dim_array_elems);
> +		} else if (varyings[i].one_dim_array_elems != 0) {
>  			text += sprintf(text, "%s%s %s var%u[%u];\n",
>  					opt_flat_keyword, varying_keyword,
>  					varyings[i].type->name, i,
> -					varyings[i].array_elems);
> +					varyings[i].one_dim_array_elems);
>  		} else {
>  			text += sprintf(text, "%s%s %s var%u;\n",
>  					opt_flat_keyword, varying_keyword,
> @@ -243,37 +262,47 @@ get_shader(bool is_vs, unsigned glsl_version, int num_varyings,
>  	else
>  		text += sprintf(text, "  bool failed = false;\n");
>  	for (i = 0; i < num_varyings; ++i) {
> -		unsigned array_loop_bound = varyings[i].array_elems;
> +		unsigned array_loop_bound;
> +		unsigned inner_array_loop_bound = 1;
>  		const char *base_type_name
>  			= get_base_type_name(varyings[i].type->base);
> +		if (varyings[i].two_dim_array_elems != 0) {
> +			inner_array_loop_bound = inner_dim_size;
> +			array_loop_bound = varyings[i].two_dim_array_elems;
> +		} else
> +			array_loop_bound = varyings[i].one_dim_array_elems;
>  		if (array_loop_bound == 0)
>  			array_loop_bound = 1;
> -		for (j = 0; j < array_loop_bound; ++j) {
> -			for (k = 0; k < varyings[i].type->num_cols; ++k) {
> -				for (l = 0; l < varyings[i].type->num_rows; ++l) {
> -					text += sprintf(text, "  ");
> -					if (!is_vs)
> -						text += sprintf(text, "if (");
> -					text += sprintf(text, "var%u", i);
> -					if (varyings[i].array_elems)
> -						text += sprintf(text, "[%u]", j);
> -					if (varyings[i].type->num_cols > 1)
> -						text += sprintf(text, "[%u]", k);
> -					if (varyings[i].type->num_rows > 1)
> -						text += sprintf(text, "[%u]", l);
> -					if (is_vs)
> -						text += sprintf(text, " = ");
> -					else
> -						text += sprintf(text, " != ");
> -					text += sprintf(text, "%s(i + %u)",
> -							base_type_name,
> -							offset++);
> -					if (is_vs) {
> -						text += sprintf(text, ";\n");
> -					} else {
> -						text += sprintf(text,
> -								")\n"
> -								"    failed = true;\n");
> +		for (j = 0; j < inner_array_loop_bound; ++j) {
> +			for (k = 0; k < array_loop_bound; ++k) {
> +				for (l = 0; l < varyings[i].type->num_cols; ++l) {
> +					for (m = 0; m < varyings[i].type->num_rows; ++m) {
> +						text += sprintf(text, "  ");
> +						if (!is_vs)
> +							text += sprintf(text, "if (");
> +						text += sprintf(text, "var%u", i);
> +						if (varyings[i].two_dim_array_elems)
> +							text += sprintf(text, "[%u]", j);
> +						if (varyings[i].one_dim_array_elems || varyings[i].two_dim_array_elems)
> +							text += sprintf(text, "[%u]", k);
> +						if (varyings[i].type->num_cols > 1)
> +							text += sprintf(text, "[%u]", l);
> +						if (varyings[i].type->num_rows > 1)
> +							text += sprintf(text, "[%u]", m);
> +						if (is_vs)
> +							text += sprintf(text, " = ");
> +						else
> +							text += sprintf(text, " != ");
> +						text += sprintf(text, "%s(i + %u)",
> +								base_type_name,
> +								offset++);
> +						if (is_vs) {
> +							text += sprintf(text, ";\n");
> +						} else {
> +							text += sprintf(text,
> +									")\n"
> +									"    failed = true;\n");
> +						}
>  					}
>  				}
>  			}
> @@ -302,7 +331,8 @@ get_shader(bool is_vs, unsigned glsl_version, int num_varyings,
>   */
>  static unsigned
>  choose_varyings(struct varying_desc *varyings,
> -		const struct type_desc *test_type, GLboolean test_array,
> +		const struct type_desc *test_type,
> +		enum test_array_type array_type,
>  		unsigned max_varying_floats)
>  {
>  	unsigned num_varyings = 0;
> @@ -310,24 +340,43 @@ choose_varyings(struct varying_desc *varyings,
>  		= test_type->num_cols * test_type->num_rows;
>  	unsigned num_test_varyings
>  		= max_varying_floats / components_in_test_type;
> +	unsigned num_two_dim_test_varyings
> +		 = num_test_varyings / inner_dim_size;
> +	unsigned num_extra_arrays = 0;
>  	unsigned num_extra_varyings
>  		= max_varying_floats
>  		- num_test_varyings * components_in_test_type;
>  	unsigned i;
> -	if (test_array) {
> +	if (array_type == ARRAYS_OF_ARRAYS) {
>  		varyings[num_varyings].type = test_type;
> -		varyings[num_varyings].array_elems = num_test_varyings;
> +		varyings[num_varyings].two_dim_array_elems = num_two_dim_test_varyings;
> +		varyings[num_varyings].one_dim_array_elems = 0;
> +		num_extra_arrays
> +			= num_test_varyings - (num_two_dim_test_varyings * inner_dim_size);
> +		++num_varyings;
> +		if (num_extra_arrays > 0) {
> +			varyings[num_varyings].type = test_type;
> +			varyings[num_varyings].two_dim_array_elems = 0;
> +			varyings[num_varyings].one_dim_array_elems = num_extra_arrays;
> +			++num_varyings;
> +		}
> +	} else if (array_type == ARRAY) {
> +		varyings[num_varyings].type = test_type;
> +		varyings[num_varyings].two_dim_array_elems = 0;
> +		varyings[num_varyings].one_dim_array_elems = num_test_varyings;
>  		++num_varyings;
>  	} else {
>  		for (i = 0; i < num_test_varyings; ++i) {
>  			varyings[num_varyings].type = test_type;
> -			varyings[num_varyings].array_elems = 0;
> +			varyings[num_varyings].two_dim_array_elems = 0;
> +			varyings[num_varyings].one_dim_array_elems = 0;
>  			++num_varyings;
>  		}
>  	}
>  	for (i = 0; i < num_extra_varyings; ++i) {
>  		varyings[num_varyings].type = &float_type;
> -		varyings[num_varyings].array_elems = 0;
> +		varyings[num_varyings].two_dim_array_elems = 0;
> +		varyings[num_varyings].one_dim_array_elems = 0;
>  		++num_varyings;
>  	}
>  
> @@ -344,6 +393,8 @@ print_usage_and_exit(const char *prog_name)
>  		printf("    %s\n", all_types[i]->name);
>  	printf("  and <arrayspec> is one of:\n"
>  	       "    array: test using an array of the above type\n"
> +	       "    arrays_of_arrays: test using a multidimensional array"
> +	       " of the above type\n"
>  	       "    separate: test using separately declared varyings\n");
>  	piglit_report_result(PIGLIT_FAIL);
>  }
> @@ -353,10 +404,11 @@ piglit_init(int argc, char **argv)
>  {
>  	unsigned i;
>  	const struct type_desc *test_type;
> -	GLboolean test_array;
> +	enum test_array_type array_type;
>  	GLint max_varying_floats;
>  	struct varying_desc *varyings;
>  	unsigned num_varyings;
> +	unsigned glsl_version;
>  	GLuint vs, fs;
>  
>  	if (argc != 3)
> @@ -365,29 +417,35 @@ piglit_init(int argc, char **argv)
>  		if (strcmp(argv[1], all_types[i]->name) == 0)
>  			break;
>  	}
> -	if (all_types[i])
> +	if (all_types[i]) {
>  		test_type = all_types[i];
> -	else
> +		glsl_version = test_type->glsl_version_required;
> +	} else
>  		print_usage_and_exit(argv[0]);
>  	if (strcmp(argv[2], "array") == 0)
> -		test_array = GL_TRUE;
> +		array_type = ARRAY;
>  	else if (strcmp(argv[2], "separate") == 0)
> -		test_array = GL_FALSE;
> -	else
> +		array_type = SEPARATE;
> +	else if (strcmp(argv[2], "arrays_of_arrays") == 0) {
> +		array_type = ARRAYS_OF_ARRAYS;
> +		piglit_require_extension("GL_ARB_arrays_of_arrays");
> +		if (glsl_version < 120)
> +			glsl_version = 120;
> +	} else
>  		print_usage_and_exit(argv[0]);
>  
>  	piglit_require_gl_version(20);
> -	piglit_require_GLSL_version(test_type->glsl_version_required);
> +	piglit_require_GLSL_version(glsl_version);
>  	glGetIntegerv(GL_MAX_VARYING_FLOATS, &max_varying_floats);
>  
>  	varyings = malloc(sizeof(*varyings) * max_varying_floats);
> -	num_varyings = choose_varyings(varyings, test_type,
> -				       test_array, max_varying_floats);
> +	num_varyings = choose_varyings(varyings, test_type, array_type,
> +				       max_varying_floats);
>  
> -	vs = get_shader(true, test_type->glsl_version_required,
> -			num_varyings, varyings);
> -	fs = get_shader(false, test_type->glsl_version_required,
> -			num_varyings, varyings);
> +	vs = get_shader(true, glsl_version,
> +			num_varyings, varyings, array_type);
> +	fs = get_shader(false, glsl_version,
> +			num_varyings, varyings, array_type);
>  	prog = piglit_link_simple_program(vs, fs);
>  	i_location = glGetUniformLocation(prog, "i");
>  	free(varyings);
diff mbox

Patch

diff --git a/tests/all.py b/tests/all.py
index 1e1aa3d..b59aaa4 100644
--- a/tests/all.py
+++ b/tests/all.py
@@ -1159,7 +1159,7 @@  spec['glsl-1.10']['execution']['varying-packing'] = Group()
 for type in ['int', 'uint', 'float', 'vec2', 'vec3', 'vec4', 'ivec2', 'ivec3',
              'ivec4', 'uvec2', 'uvec3', 'uvec4', 'mat2', 'mat3', 'mat4',
              'mat2x3', 'mat2x4', 'mat3x2', 'mat3x4', 'mat4x2', 'mat4x3']:
-    for arrayspec in ['array', 'separate']:
+    for arrayspec in ['array', 'separate', 'arrays_of_arrays']:
         cmdline = 'simple {0} {1}'.format(type, arrayspec)
         spec['glsl-1.10']['execution']['varying-packing'][cmdline] = \
             concurrent_test('varying-packing-' + cmdline)
diff --git a/tests/spec/glsl-1.10/execution/varying-packing/simple.c b/tests/spec/glsl-1.10/execution/varying-packing/simple.c
index f7fd648..4d6cbba 100644
--- a/tests/spec/glsl-1.10/execution/varying-packing/simple.c
+++ b/tests/spec/glsl-1.10/execution/varying-packing/simple.c
@@ -97,6 +97,8 @@ 
  */
 #include "piglit-util-gl-common.h"
 
+static const int inner_dim_size = 2;
+
 PIGLIT_GL_TEST_CONFIG_BEGIN
 
 	config.supports_gl_compat_version = 10;
@@ -115,6 +117,14 @@  enum base_type
 	BASE_TYPE_INT,
 };
 
+enum test_array_type
+{
+	SEPARATE,
+	ARRAY,
+	ARRAYS_OF_ARRAYS,
+};
+
+
 static const char *
 get_base_type_name(enum base_type t)
 {
@@ -189,7 +199,8 @@  const struct type_desc *all_types[] = {
 struct varying_desc
 {
 	const struct type_desc *type;
-	unsigned array_elems;
+	unsigned one_dim_array_elems;
+	unsigned two_dim_array_elems;
 };
 
 /**
@@ -198,12 +209,12 @@  struct varying_desc
  */
 static GLint
 get_shader(bool is_vs, unsigned glsl_version, int num_varyings,
-	   struct varying_desc *varyings)
+	   struct varying_desc *varyings, enum test_array_type array_type)
 {
 	GLuint shader;
 	char *full_text = malloc(1000 * 100 + num_varyings);
 	char *text = full_text;
-	unsigned i, j, k, l;
+	unsigned i, j, k, l, m;
 	const char *varying_keyword;
 	unsigned offset = 0;
 	GLenum shader_type = is_vs ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER;
@@ -218,16 +229,24 @@  get_shader(bool is_vs, unsigned glsl_version, int num_varyings,
 	}
 
 	text += sprintf(text, "#version %u\n", glsl_version);
+	if (array_type == ARRAYS_OF_ARRAYS)
+		text += sprintf(text, "#extension GL_ARB_arrays_of_arrays: enable\n");
 	text += sprintf(text, "uniform int i;\n");
 	for (i = 0; i < num_varyings; ++i) {
 		const char *opt_flat_keyword = "";
 		if (varyings[i].type->base != BASE_TYPE_FLOAT)
 			opt_flat_keyword = "flat ";
-		if (varyings[i].array_elems != 0) {
+		if (varyings[i].two_dim_array_elems != 0) {
+			text += sprintf(text, "%s%s %s var%u[%u][%u];\n",
+					opt_flat_keyword, varying_keyword,
+					varyings[i].type->name, i,
+					inner_dim_size,
+					varyings[i].two_dim_array_elems);
+		} else if (varyings[i].one_dim_array_elems != 0) {
 			text += sprintf(text, "%s%s %s var%u[%u];\n",
 					opt_flat_keyword, varying_keyword,
 					varyings[i].type->name, i,
-					varyings[i].array_elems);
+					varyings[i].one_dim_array_elems);
 		} else {
 			text += sprintf(text, "%s%s %s var%u;\n",
 					opt_flat_keyword, varying_keyword,
@@ -243,37 +262,47 @@  get_shader(bool is_vs, unsigned glsl_version, int num_varyings,
 	else
 		text += sprintf(text, "  bool failed = false;\n");
 	for (i = 0; i < num_varyings; ++i) {
-		unsigned array_loop_bound = varyings[i].array_elems;
+		unsigned array_loop_bound;
+		unsigned inner_array_loop_bound = 1;
 		const char *base_type_name
 			= get_base_type_name(varyings[i].type->base);
+		if (varyings[i].two_dim_array_elems != 0) {
+			inner_array_loop_bound = inner_dim_size;
+			array_loop_bound = varyings[i].two_dim_array_elems;
+		} else
+			array_loop_bound = varyings[i].one_dim_array_elems;
 		if (array_loop_bound == 0)
 			array_loop_bound = 1;
-		for (j = 0; j < array_loop_bound; ++j) {
-			for (k = 0; k < varyings[i].type->num_cols; ++k) {
-				for (l = 0; l < varyings[i].type->num_rows; ++l) {
-					text += sprintf(text, "  ");
-					if (!is_vs)
-						text += sprintf(text, "if (");
-					text += sprintf(text, "var%u", i);
-					if (varyings[i].array_elems)
-						text += sprintf(text, "[%u]", j);
-					if (varyings[i].type->num_cols > 1)
-						text += sprintf(text, "[%u]", k);
-					if (varyings[i].type->num_rows > 1)
-						text += sprintf(text, "[%u]", l);
-					if (is_vs)
-						text += sprintf(text, " = ");
-					else
-						text += sprintf(text, " != ");
-					text += sprintf(text, "%s(i + %u)",
-							base_type_name,
-							offset++);
-					if (is_vs) {
-						text += sprintf(text, ";\n");
-					} else {
-						text += sprintf(text,
-								")\n"
-								"    failed = true;\n");
+		for (j = 0; j < inner_array_loop_bound; ++j) {
+			for (k = 0; k < array_loop_bound; ++k) {
+				for (l = 0; l < varyings[i].type->num_cols; ++l) {
+					for (m = 0; m < varyings[i].type->num_rows; ++m) {
+						text += sprintf(text, "  ");
+						if (!is_vs)
+							text += sprintf(text, "if (");
+						text += sprintf(text, "var%u", i);
+						if (varyings[i].two_dim_array_elems)
+							text += sprintf(text, "[%u]", j);
+						if (varyings[i].one_dim_array_elems || varyings[i].two_dim_array_elems)
+							text += sprintf(text, "[%u]", k);
+						if (varyings[i].type->num_cols > 1)
+							text += sprintf(text, "[%u]", l);
+						if (varyings[i].type->num_rows > 1)
+							text += sprintf(text, "[%u]", m);
+						if (is_vs)
+							text += sprintf(text, " = ");
+						else
+							text += sprintf(text, " != ");
+						text += sprintf(text, "%s(i + %u)",
+								base_type_name,
+								offset++);
+						if (is_vs) {
+							text += sprintf(text, ";\n");
+						} else {
+							text += sprintf(text,
+									")\n"
+									"    failed = true;\n");
+						}
 					}
 				}
 			}
@@ -302,7 +331,8 @@  get_shader(bool is_vs, unsigned glsl_version, int num_varyings,
  */
 static unsigned
 choose_varyings(struct varying_desc *varyings,
-		const struct type_desc *test_type, GLboolean test_array,
+		const struct type_desc *test_type,
+		enum test_array_type array_type,
 		unsigned max_varying_floats)
 {
 	unsigned num_varyings = 0;
@@ -310,24 +340,43 @@  choose_varyings(struct varying_desc *varyings,
 		= test_type->num_cols * test_type->num_rows;
 	unsigned num_test_varyings
 		= max_varying_floats / components_in_test_type;
+	unsigned num_two_dim_test_varyings
+		 = num_test_varyings / inner_dim_size;
+	unsigned num_extra_arrays = 0;
 	unsigned num_extra_varyings
 		= max_varying_floats
 		- num_test_varyings * components_in_test_type;
 	unsigned i;
-	if (test_array) {
+	if (array_type == ARRAYS_OF_ARRAYS) {
 		varyings[num_varyings].type = test_type;
-		varyings[num_varyings].array_elems = num_test_varyings;
+		varyings[num_varyings].two_dim_array_elems = num_two_dim_test_varyings;
+		varyings[num_varyings].one_dim_array_elems = 0;
+		num_extra_arrays
+			= num_test_varyings - (num_two_dim_test_varyings * inner_dim_size);
+		++num_varyings;
+		if (num_extra_arrays > 0) {
+			varyings[num_varyings].type = test_type;
+			varyings[num_varyings].two_dim_array_elems = 0;
+			varyings[num_varyings].one_dim_array_elems = num_extra_arrays;
+			++num_varyings;
+		}
+	} else if (array_type == ARRAY) {
+		varyings[num_varyings].type = test_type;
+		varyings[num_varyings].two_dim_array_elems = 0;
+		varyings[num_varyings].one_dim_array_elems = num_test_varyings;
 		++num_varyings;
 	} else {
 		for (i = 0; i < num_test_varyings; ++i) {
 			varyings[num_varyings].type = test_type;
-			varyings[num_varyings].array_elems = 0;
+			varyings[num_varyings].two_dim_array_elems = 0;
+			varyings[num_varyings].one_dim_array_elems = 0;
 			++num_varyings;
 		}
 	}
 	for (i = 0; i < num_extra_varyings; ++i) {
 		varyings[num_varyings].type = &float_type;
-		varyings[num_varyings].array_elems = 0;
+		varyings[num_varyings].two_dim_array_elems = 0;
+		varyings[num_varyings].one_dim_array_elems = 0;
 		++num_varyings;
 	}
 
@@ -344,6 +393,8 @@  print_usage_and_exit(const char *prog_name)
 		printf("    %s\n", all_types[i]->name);
 	printf("  and <arrayspec> is one of:\n"
 	       "    array: test using an array of the above type\n"
+	       "    arrays_of_arrays: test using a multidimensional array"
+	       " of the above type\n"
 	       "    separate: test using separately declared varyings\n");
 	piglit_report_result(PIGLIT_FAIL);
 }
@@ -353,10 +404,11 @@  piglit_init(int argc, char **argv)
 {
 	unsigned i;
 	const struct type_desc *test_type;
-	GLboolean test_array;
+	enum test_array_type array_type;
 	GLint max_varying_floats;
 	struct varying_desc *varyings;
 	unsigned num_varyings;
+	unsigned glsl_version;
 	GLuint vs, fs;
 
 	if (argc != 3)
@@ -365,29 +417,35 @@  piglit_init(int argc, char **argv)
 		if (strcmp(argv[1], all_types[i]->name) == 0)
 			break;
 	}
-	if (all_types[i])
+	if (all_types[i]) {
 		test_type = all_types[i];
-	else
+		glsl_version = test_type->glsl_version_required;
+	} else
 		print_usage_and_exit(argv[0]);
 	if (strcmp(argv[2], "array") == 0)
-		test_array = GL_TRUE;
+		array_type = ARRAY;
 	else if (strcmp(argv[2], "separate") == 0)
-		test_array = GL_FALSE;
-	else
+		array_type = SEPARATE;
+	else if (strcmp(argv[2], "arrays_of_arrays") == 0) {
+		array_type = ARRAYS_OF_ARRAYS;
+		piglit_require_extension("GL_ARB_arrays_of_arrays");
+		if (glsl_version < 120)
+			glsl_version = 120;
+	} else
 		print_usage_and_exit(argv[0]);
 
 	piglit_require_gl_version(20);
-	piglit_require_GLSL_version(test_type->glsl_version_required);
+	piglit_require_GLSL_version(glsl_version);
 	glGetIntegerv(GL_MAX_VARYING_FLOATS, &max_varying_floats);
 
 	varyings = malloc(sizeof(*varyings) * max_varying_floats);
-	num_varyings = choose_varyings(varyings, test_type,
-				       test_array, max_varying_floats);
+	num_varyings = choose_varyings(varyings, test_type, array_type,
+				       max_varying_floats);
 
-	vs = get_shader(true, test_type->glsl_version_required,
-			num_varyings, varyings);
-	fs = get_shader(false, test_type->glsl_version_required,
-			num_varyings, varyings);
+	vs = get_shader(true, glsl_version,
+			num_varyings, varyings, array_type);
+	fs = get_shader(false, glsl_version,
+			num_varyings, varyings, array_type);
 	prog = piglit_link_simple_program(vs, fs);
 	i_location = glGetUniformLocation(prog, "i");
 	free(varyings);