varying-packing: add arrays of arrays support

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

Commit Message

'Timothy Arceri' via Patchwork Forward April 26, 2015, 6:13 a.m.
V3: rebase and test double types

V2: renamed variables from 'inner' that should have been 'outer'
---
 tests/all.py                                       |   4 +-
 .../glsl-1.10/execution/varying-packing/simple.c   | 137 +++++++++++++++------
 2 files changed, 100 insertions(+), 41 deletions(-)

Comments

'Timothy Arceri' via Patchwork Forward May 12, 2015, 9:31 p.m. | #1
Anyone brave enough to to give this a quick review? It's been on the
list since mid last year I'd really like to push it so I can move on :)

Thanks,
Tim


On Sun, 2015-04-26 at 16:13 +1000, Timothy Arceri wrote:
> V3: rebase and test double types
> 
> V2: renamed variables from 'inner' that should have been 'outer'
> ---
>  tests/all.py                                       |   4 +-
>  .../glsl-1.10/execution/varying-packing/simple.c   | 137 +++++++++++++++------
>  2 files changed, 100 insertions(+), 41 deletions(-)
> 
> diff --git a/tests/all.py b/tests/all.py
> index 18124b7..85b622f 100755
> --- a/tests/all.py
> +++ b/tests/all.py
> @@ -1290,7 +1290,7 @@ with profile.group_manager(
>                    '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']:
>              g(['varying-packing-simple', type_, arrayspec],
>                'simple {} {}'.format(type_, arrayspec))
>  
> @@ -2062,7 +2062,7 @@ with profile.group_manager(
>      for type in ['double', 'dvec2', 'dvec3', 'dvec4', 'dmat2', 'dmat3',
>                   'dmat4', 'dmat2x3', 'dmat2x4', 'dmat3x2', 'dmat3x4',
>                   'dmat4x2', 'dmat4x3']:
> -        for arrayspec in ['array', 'separate']:
> +        for arrayspec in ['array', 'separate', 'arrays_of_arrays']:
>              g(['varying-packing-simple', type, arrayspec],
>                'simple {0} {1}'.format(type, arrayspec))
>  
> 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 e9935c7..2b1c010 100644
> --- a/tests/spec/glsl-1.10/execution/varying-packing/simple.c
> +++ b/tests/spec/glsl-1.10/execution/varying-packing/simple.c
> @@ -100,6 +100,8 @@
>  static void
>  parse_args(int argc, char *argv[], struct piglit_gl_test_config *config);
>  
> +static const int outer_dim_size = 2;
> +
>  PIGLIT_GL_TEST_CONFIG_BEGIN
>  
>  	config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;
> @@ -118,6 +120,13 @@ enum base_type
>  	BASE_TYPE_DOUBLE,
>  };
>  
> +enum test_array_type
> +{
> +	SEPARATE,
> +	ARRAY,
> +	ARRAYS_OF_ARRAYS,
> +};
> +
>  static const char *
>  get_base_type_name(enum base_type t)
>  {
> @@ -219,7 +228,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;
>  };
>  
>  /**
> @@ -228,12 +238,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;
> @@ -249,6 +259,8 @@ 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");
>  	for (i = 0; i < num_varyings; ++i) {
>  		const char *opt_flat_keyword = "";
>  		if (!fp64 && varyings[i].type->base == BASE_TYPE_DOUBLE) {
> @@ -257,11 +269,17 @@ get_shader(bool is_vs, unsigned glsl_version, int num_varyings,
>  		}
>  		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%03u[%u][%u];\n",
> +					opt_flat_keyword, varying_keyword,
> +					varyings[i].type->name, i,
> +					outer_dim_size,
> +					varyings[i].two_dim_array_elems);
> +		} else if (varyings[i].one_dim_array_elems != 0) {
>  			text += sprintf(text, "%s%s %s var%03u[%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%03u;\n",
>  					opt_flat_keyword, varying_keyword,
> @@ -282,31 +300,42 @@ 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 outer_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) {
> +			outer_array_loop_bound = outer_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, "failed = failed || ");
> -					text += sprintf(text, "var%03u", 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);\n",
> -							base_type_name,
> -							offset++);
> +		for (j = 0; j < outer_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, "failed = failed || ");
> +						text += sprintf(text, "var%03u", 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);\n",
> +								base_type_name,
> +								offset++);
> +					}
>  				}
>  			}
>  		}
> @@ -334,7 +363,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;
> @@ -343,24 +373,43 @@ choose_varyings(struct varying_desc *varyings,
>  		= test_type->num_cols * test_type->num_rows * element_size;
>  	unsigned num_test_varyings
>  		= max_varying_floats / components_in_test_type;
> +	unsigned num_two_dim_test_varyings
> +		 = num_test_varyings / outer_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 * outer_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;
>  	}
>  
> @@ -377,6 +426,8 @@ NORETURN 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);
>  }
> @@ -414,36 +465,44 @@ parse_args(int argc, char *argv[], struct piglit_gl_test_config *config)
>  void
>  piglit_init(int argc, char **argv)
>  {
> -	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)
>  		print_usage_and_exit(argv[0]);
>  
> +	glsl_version = test_type->glsl_version_required;
> +
>  	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);
>  	if (test_type->base == BASE_TYPE_DOUBLE)
>  		piglit_require_extension("GL_ARB_gpu_shader_fp64");
>  	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);
> +				       array_type, max_varying_floats);
>  
>  	vs = get_shader(true, test_type->glsl_version_required,
> -			num_varyings, varyings);
> +			num_varyings, varyings, array_type);
>  	fs = get_shader(false, test_type->glsl_version_required,
> -			num_varyings, varyings);
> +			num_varyings, varyings, array_type);
>  	prog = piglit_link_simple_program(vs, fs);
>  	i_location = glGetUniformLocation(prog, "i");
>  	free(varyings);
'Timothy Arceri' via Patchwork Forward May 13, 2015, 12:52 p.m. | #2
On Tue, 2015-05-12 at 17:34 -0400, Ilia Mirkin wrote:
> Perhaps in the absence of a brave enough soul to look at this, could you
> 

Thanks for the suggestions.

> (a) confirm that the generated shaders don't change at all for the
> non-arrays-of-arrays cases or alternatively post the differences

To be sure I printed the shaders out to file before and after the
change, doing a diff on them shows no differences.

The only tests that I didn't compare were the double tests as the Intel
drive doesn't support them yet and I couldn't get piglit to stop
skipping them.
But there shouldn't be any issue with them.


> (b) post a couple of sample arrays-of-arrays shaders that are
> generated by the new logic

Here are a couple of examples of the new logic in action. The first one
is the best example as it shows how things are handled when not all the
varyings fit in the multidimensional array.

-------------------------------------------------------------------
mat3x2 arrays of arrays
-------------------------------------------------------------------
#version 120
#extension GL_ARB_arrays_of_arrays: enable
varying mat2x3 var000[2][10];
varying mat2x3 var001[1];
varying float var002;
varying float var003;
uniform int i;

void main()
{
  gl_Position = gl_Vertex;
  var000[0][0][0][0] = float(i + 0);
  var000[0][0][0][1] = float(i + 1);
  var000[0][0][0][2] = float(i + 2);
  var000[0][0][1][0] = float(i + 3);
  var000[0][0][1][1] = float(i + 4);
  var000[0][0][1][2] = float(i + 5);
  var000[0][1][0][0] = float(i + 6);
  var000[0][1][0][1] = float(i + 7);
  var000[0][1][0][2] = float(i + 8);
  var000[0][1][1][0] = float(i + 9);
  var000[0][1][1][1] = float(i + 10);
  var000[0][1][1][2] = float(i + 11);
  var000[0][2][0][0] = float(i + 12);
  var000[0][2][0][1] = float(i + 13);
  var000[0][2][0][2] = float(i + 14);
  var000[0][2][1][0] = float(i + 15);
  var000[0][2][1][1] = float(i + 16);
  var000[0][2][1][2] = float(i + 17);
  var000[0][3][0][0] = float(i + 18);
  var000[0][3][0][1] = float(i + 19);
  var000[0][3][0][2] = float(i + 20);
  var000[0][3][1][0] = float(i + 21);
  var000[0][3][1][1] = float(i + 22);
  var000[0][3][1][2] = float(i + 23);
  var000[0][4][0][0] = float(i + 24);
  var000[0][4][0][1] = float(i + 25);
  var000[0][4][0][2] = float(i + 26);
  var000[0][4][1][0] = float(i + 27);
  var000[0][4][1][1] = float(i + 28);
  var000[0][4][1][2] = float(i + 29);
  var000[0][5][0][0] = float(i + 30);
  var000[0][5][0][1] = float(i + 31);
  var000[0][5][0][2] = float(i + 32);
  var000[0][5][1][0] = float(i + 33);
  var000[0][5][1][1] = float(i + 34);
  var000[0][5][1][2] = float(i + 35);
  var000[0][6][0][0] = float(i + 36);
  var000[0][6][0][1] = float(i + 37);
  var000[0][6][0][2] = float(i + 38);
  var000[0][6][1][0] = float(i + 39);
  var000[0][6][1][1] = float(i + 40);
  var000[0][6][1][2] = float(i + 41);
  var000[0][7][0][0] = float(i + 42);
  var000[0][7][0][1] = float(i + 43);
  var000[0][7][0][2] = float(i + 44);
  var000[0][7][1][0] = float(i + 45);
  var000[0][7][1][1] = float(i + 46);
  var000[0][7][1][2] = float(i + 47);
  var000[0][8][0][0] = float(i + 48);
  var000[0][8][0][1] = float(i + 49);
  var000[0][8][0][2] = float(i + 50);
  var000[0][8][1][0] = float(i + 51);
  var000[0][8][1][1] = float(i + 52);
  var000[0][8][1][2] = float(i + 53);
  var000[0][9][0][0] = float(i + 54);
  var000[0][9][0][1] = float(i + 55);
  var000[0][9][0][2] = float(i + 56);
  var000[0][9][1][0] = float(i + 57);
  var000[0][9][1][1] = float(i + 58);
  var000[0][9][1][2] = float(i + 59);
  var000[1][0][0][0] = float(i + 60);
  var000[1][0][0][1] = float(i + 61);
  var000[1][0][0][2] = float(i + 62);
  var000[1][0][1][0] = float(i + 63);
  var000[1][0][1][1] = float(i + 64);
  var000[1][0][1][2] = float(i + 65);
  var000[1][1][0][0] = float(i + 66);
  var000[1][1][0][1] = float(i + 67);
  var000[1][1][0][2] = float(i + 68);
  var000[1][1][1][0] = float(i + 69);
  var000[1][1][1][1] = float(i + 70);
  var000[1][1][1][2] = float(i + 71);
  var000[1][2][0][0] = float(i + 72);
  var000[1][2][0][1] = float(i + 73);
  var000[1][2][0][2] = float(i + 74);
  var000[1][2][1][0] = float(i + 75);
  var000[1][2][1][1] = float(i + 76);
  var000[1][2][1][2] = float(i + 77);
  var000[1][3][0][0] = float(i + 78);
  var000[1][3][0][1] = float(i + 79);
  var000[1][3][0][2] = float(i + 80);
  var000[1][3][1][0] = float(i + 81);
  var000[1][3][1][1] = float(i + 82);
  var000[1][3][1][2] = float(i + 83);
  var000[1][4][0][0] = float(i + 84);
  var000[1][4][0][1] = float(i + 85);
  var000[1][4][0][2] = float(i + 86);
  var000[1][4][1][0] = float(i + 87);
  var000[1][4][1][1] = float(i + 88);
  var000[1][4][1][2] = float(i + 89);
  var000[1][5][0][0] = float(i + 90);
  var000[1][5][0][1] = float(i + 91);
  var000[1][5][0][2] = float(i + 92);
  var000[1][5][1][0] = float(i + 93);
  var000[1][5][1][1] = float(i + 94);
  var000[1][5][1][2] = float(i + 95);
  var000[1][6][0][0] = float(i + 96);
  var000[1][6][0][1] = float(i + 97);
  var000[1][6][0][2] = float(i + 98);
  var000[1][6][1][0] = float(i + 99);
  var000[1][6][1][1] = float(i + 100);
  var000[1][6][1][2] = float(i + 101);
  var000[1][7][0][0] = float(i + 102);
  var000[1][7][0][1] = float(i + 103);
  var000[1][7][0][2] = float(i + 104);
  var000[1][7][1][0] = float(i + 105);
  var000[1][7][1][1] = float(i + 106);
  var000[1][7][1][2] = float(i + 107);
  var000[1][8][0][0] = float(i + 108);
  var000[1][8][0][1] = float(i + 109);
  var000[1][8][0][2] = float(i + 110);
  var000[1][8][1][0] = float(i + 111);
  var000[1][8][1][1] = float(i + 112);
  var000[1][8][1][2] = float(i + 113);
  var000[1][9][0][0] = float(i + 114);
  var000[1][9][0][1] = float(i + 115);
  var000[1][9][0][2] = float(i + 116);
  var000[1][9][1][0] = float(i + 117);
  var000[1][9][1][1] = float(i + 118);
  var000[1][9][1][2] = float(i + 119);
  var001[0][0][0] = float(i + 120);
  var001[0][0][1] = float(i + 121);
  var001[0][0][2] = float(i + 122);
  var001[0][1][0] = float(i + 123);
  var001[0][1][1] = float(i + 124);
  var001[0][1][2] = float(i + 125);
  var002 = float(i + 126);
  var003 = float(i + 127);
}
#version 120
#extension GL_ARB_arrays_of_arrays: enable
varying mat2x3 var000[2][10];
varying mat2x3 var001[1];
varying float var002;
varying float var003;
uniform int i;

void main()
{
  bool failed = false;
  failed = failed || var000[0][0][0][0] != float(i + 0);
  failed = failed || var000[0][0][0][1] != float(i + 1);
  failed = failed || var000[0][0][0][2] != float(i + 2);
  failed = failed || var000[0][0][1][0] != float(i + 3);
  failed = failed || var000[0][0][1][1] != float(i + 4);
  failed = failed || var000[0][0][1][2] != float(i + 5);
  failed = failed || var000[0][1][0][0] != float(i + 6);
  failed = failed || var000[0][1][0][1] != float(i + 7);
  failed = failed || var000[0][1][0][2] != float(i + 8);
  failed = failed || var000[0][1][1][0] != float(i + 9);
  failed = failed || var000[0][1][1][1] != float(i + 10);
  failed = failed || var000[0][1][1][2] != float(i + 11);
  failed = failed || var000[0][2][0][0] != float(i + 12);
  failed = failed || var000[0][2][0][1] != float(i + 13);
  failed = failed || var000[0][2][0][2] != float(i + 14);
  failed = failed || var000[0][2][1][0] != float(i + 15);
  failed = failed || var000[0][2][1][1] != float(i + 16);
  failed = failed || var000[0][2][1][2] != float(i + 17);
  failed = failed || var000[0][3][0][0] != float(i + 18);
  failed = failed || var000[0][3][0][1] != float(i + 19);
  failed = failed || var000[0][3][0][2] != float(i + 20);
  failed = failed || var000[0][3][1][0] != float(i + 21);
  failed = failed || var000[0][3][1][1] != float(i + 22);
  failed = failed || var000[0][3][1][2] != float(i + 23);
  failed = failed || var000[0][4][0][0] != float(i + 24);
  failed = failed || var000[0][4][0][1] != float(i + 25);
  failed = failed || var000[0][4][0][2] != float(i + 26);
  failed = failed || var000[0][4][1][0] != float(i + 27);
  failed = failed || var000[0][4][1][1] != float(i + 28);
  failed = failed || var000[0][4][1][2] != float(i + 29);
  failed = failed || var000[0][5][0][0] != float(i + 30);
  failed = failed || var000[0][5][0][1] != float(i + 31);
  failed = failed || var000[0][5][0][2] != float(i + 32);
  failed = failed || var000[0][5][1][0] != float(i + 33);
  failed = failed || var000[0][5][1][1] != float(i + 34);
  failed = failed || var000[0][5][1][2] != float(i + 35);
  failed = failed || var000[0][6][0][0] != float(i + 36);
  failed = failed || var000[0][6][0][1] != float(i + 37);
  failed = failed || var000[0][6][0][2] != float(i + 38);
  failed = failed || var000[0][6][1][0] != float(i + 39);
  failed = failed || var000[0][6][1][1] != float(i + 40);
  failed = failed || var000[0][6][1][2] != float(i + 41);
  failed = failed || var000[0][7][0][0] != float(i + 42);
  failed = failed || var000[0][7][0][1] != float(i + 43);
  failed = failed || var000[0][7][0][2] != float(i + 44);
  failed = failed || var000[0][7][1][0] != float(i + 45);
  failed = failed || var000[0][7][1][1] != float(i + 46);
  failed = failed || var000[0][7][1][2] != float(i + 47);
  failed = failed || var000[0][8][0][0] != float(i + 48);
  failed = failed || var000[0][8][0][1] != float(i + 49);
  failed = failed || var000[0][8][0][2] != float(i + 50);
  failed = failed || var000[0][8][1][0] != float(i + 51);
  failed = failed || var000[0][8][1][1] != float(i + 52);
  failed = failed || var000[0][8][1][2] != float(i + 53);
  failed = failed || var000[0][9][0][0] != float(i + 54);
  failed = failed || var000[0][9][0][1] != float(i + 55);
  failed = failed || var000[0][9][0][2] != float(i + 56);
  failed = failed || var000[0][9][1][0] != float(i + 57);
  failed = failed || var000[0][9][1][1] != float(i + 58);
  failed = failed || var000[0][9][1][2] != float(i + 59);
  failed = failed || var000[1][0][0][0] != float(i + 60);
  failed = failed || var000[1][0][0][1] != float(i + 61);
  failed = failed || var000[1][0][0][2] != float(i + 62);
  failed = failed || var000[1][0][1][0] != float(i + 63);
  failed = failed || var000[1][0][1][1] != float(i + 64);
  failed = failed || var000[1][0][1][2] != float(i + 65);
  failed = failed || var000[1][1][0][0] != float(i + 66);
  failed = failed || var000[1][1][0][1] != float(i + 67);
  failed = failed || var000[1][1][0][2] != float(i + 68);
  failed = failed || var000[1][1][1][0] != float(i + 69);
  failed = failed || var000[1][1][1][1] != float(i + 70);
  failed = failed || var000[1][1][1][2] != float(i + 71);
  failed = failed || var000[1][2][0][0] != float(i + 72);
  failed = failed || var000[1][2][0][1] != float(i + 73);
  failed = failed || var000[1][2][0][2] != float(i + 74);
  failed = failed || var000[1][2][1][0] != float(i + 75);
  failed = failed || var000[1][2][1][1] != float(i + 76);
  failed = failed || var000[1][2][1][2] != float(i + 77);
  failed = failed || var000[1][3][0][0] != float(i + 78);
  failed = failed || var000[1][3][0][1] != float(i + 79);
  failed = failed || var000[1][3][0][2] != float(i + 80);
  failed = failed || var000[1][3][1][0] != float(i + 81);
  failed = failed || var000[1][3][1][1] != float(i + 82);
  failed = failed || var000[1][3][1][2] != float(i + 83);
  failed = failed || var000[1][4][0][0] != float(i + 84);
  failed = failed || var000[1][4][0][1] != float(i + 85);
  failed = failed || var000[1][4][0][2] != float(i + 86);
  failed = failed || var000[1][4][1][0] != float(i + 87);
  failed = failed || var000[1][4][1][1] != float(i + 88);
  failed = failed || var000[1][4][1][2] != float(i + 89);
  failed = failed || var000[1][5][0][0] != float(i + 90);
  failed = failed || var000[1][5][0][1] != float(i + 91);
  failed = failed || var000[1][5][0][2] != float(i + 92);
  failed = failed || var000[1][5][1][0] != float(i + 93);
  failed = failed || var000[1][5][1][1] != float(i + 94);
  failed = failed || var000[1][5][1][2] != float(i + 95);
  failed = failed || var000[1][6][0][0] != float(i + 96);
  failed = failed || var000[1][6][0][1] != float(i + 97);
  failed = failed || var000[1][6][0][2] != float(i + 98);
  failed = failed || var000[1][6][1][0] != float(i + 99);
  failed = failed || var000[1][6][1][1] != float(i + 100);
  failed = failed || var000[1][6][1][2] != float(i + 101);
  failed = failed || var000[1][7][0][0] != float(i + 102);
  failed = failed || var000[1][7][0][1] != float(i + 103);
  failed = failed || var000[1][7][0][2] != float(i + 104);
  failed = failed || var000[1][7][1][0] != float(i + 105);
  failed = failed || var000[1][7][1][1] != float(i + 106);
  failed = failed || var000[1][7][1][2] != float(i + 107);
  failed = failed || var000[1][8][0][0] != float(i + 108);
  failed = failed || var000[1][8][0][1] != float(i + 109);
  failed = failed || var000[1][8][0][2] != float(i + 110);
  failed = failed || var000[1][8][1][0] != float(i + 111);
  failed = failed || var000[1][8][1][1] != float(i + 112);
  failed = failed || var000[1][8][1][2] != float(i + 113);
  failed = failed || var000[1][9][0][0] != float(i + 114);
  failed = failed || var000[1][9][0][1] != float(i + 115);
  failed = failed || var000[1][9][0][2] != float(i + 116);
  failed = failed || var000[1][9][1][0] != float(i + 117);
  failed = failed || var000[1][9][1][1] != float(i + 118);
  failed = failed || var000[1][9][1][2] != float(i + 119);
  failed = failed || var001[0][0][0] != float(i + 120);
  failed = failed || var001[0][0][1] != float(i + 121);
  failed = failed || var001[0][0][2] != float(i + 122);
  failed = failed || var001[0][1][0] != float(i + 123);
  failed = failed || var001[0][1][1] != float(i + 124);
  failed = failed || var001[0][1][2] != float(i + 125);
  failed = failed || var002 != float(i + 126);
  failed = failed || var003 != float(i + 127);
  if (failed)
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
  else
    gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}





---------------------------------------------------------------------------
vec2 arrays of arrays
---------------------------------------------------------------------------
#version 110
#extension GL_ARB_arrays_of_arrays: enable
varying vec2 var000[2][32];
uniform int i;

void main()
{
  gl_Position = gl_Vertex;
  var000[0][0][0] = float(i + 0);
  var000[0][0][1] = float(i + 1);
  var000[0][1][0] = float(i + 2);
  var000[0][1][1] = float(i + 3);
  var000[0][2][0] = float(i + 4);
  var000[0][2][1] = float(i + 5);
  var000[0][3][0] = float(i + 6);
  var000[0][3][1] = float(i + 7);
  var000[0][4][0] = float(i + 8);
  var000[0][4][1] = float(i + 9);
  var000[0][5][0] = float(i + 10);
  var000[0][5][1] = float(i + 11);
  var000[0][6][0] = float(i + 12);
  var000[0][6][1] = float(i + 13);
  var000[0][7][0] = float(i + 14);
  var000[0][7][1] = float(i + 15);
  var000[0][8][0] = float(i + 16);
  var000[0][8][1] = float(i + 17);
  var000[0][9][0] = float(i + 18);
  var000[0][9][1] = float(i + 19);
  var000[0][10][0] = float(i + 20);
  var000[0][10][1] = float(i + 21);
  var000[0][11][0] = float(i + 22);
  var000[0][11][1] = float(i + 23);
  var000[0][12][0] = float(i + 24);
  var000[0][12][1] = float(i + 25);
  var000[0][13][0] = float(i + 26);
  var000[0][13][1] = float(i + 27);
  var000[0][14][0] = float(i + 28);
  var000[0][14][1] = float(i + 29);
  var000[0][15][0] = float(i + 30);
  var000[0][15][1] = float(i + 31);
  var000[0][16][0] = float(i + 32);
  var000[0][16][1] = float(i + 33);
  var000[0][17][0] = float(i + 34);
  var000[0][17][1] = float(i + 35);
  var000[0][18][0] = float(i + 36);
  var000[0][18][1] = float(i + 37);
  var000[0][19][0] = float(i + 38);
  var000[0][19][1] = float(i + 39);
  var000[0][20][0] = float(i + 40);
  var000[0][20][1] = float(i + 41);
  var000[0][21][0] = float(i + 42);
  var000[0][21][1] = float(i + 43);
  var000[0][22][0] = float(i + 44);
  var000[0][22][1] = float(i + 45);
  var000[0][23][0] = float(i + 46);
  var000[0][23][1] = float(i + 47);
  var000[0][24][0] = float(i + 48);
  var000[0][24][1] = float(i + 49);
  var000[0][25][0] = float(i + 50);
  var000[0][25][1] = float(i + 51);
  var000[0][26][0] = float(i + 52);
  var000[0][26][1] = float(i + 53);
  var000[0][27][0] = float(i + 54);
  var000[0][27][1] = float(i + 55);
  var000[0][28][0] = float(i + 56);
  var000[0][28][1] = float(i + 57);
  var000[0][29][0] = float(i + 58);
  var000[0][29][1] = float(i + 59);
  var000[0][30][0] = float(i + 60);
  var000[0][30][1] = float(i + 61);
  var000[0][31][0] = float(i + 62);
  var000[0][31][1] = float(i + 63);
  var000[1][0][0] = float(i + 64);
  var000[1][0][1] = float(i + 65);
  var000[1][1][0] = float(i + 66);
  var000[1][1][1] = float(i + 67);
  var000[1][2][0] = float(i + 68);
  var000[1][2][1] = float(i + 69);
  var000[1][3][0] = float(i + 70);
  var000[1][3][1] = float(i + 71);
  var000[1][4][0] = float(i + 72);
  var000[1][4][1] = float(i + 73);
  var000[1][5][0] = float(i + 74);
  var000[1][5][1] = float(i + 75);
  var000[1][6][0] = float(i + 76);
  var000[1][6][1] = float(i + 77);
  var000[1][7][0] = float(i + 78);
  var000[1][7][1] = float(i + 79);
  var000[1][8][0] = float(i + 80);
  var000[1][8][1] = float(i + 81);
  var000[1][9][0] = float(i + 82);
  var000[1][9][1] = float(i + 83);
  var000[1][10][0] = float(i + 84);
  var000[1][10][1] = float(i + 85);
  var000[1][11][0] = float(i + 86);
  var000[1][11][1] = float(i + 87);
  var000[1][12][0] = float(i + 88);
  var000[1][12][1] = float(i + 89);
  var000[1][13][0] = float(i + 90);
  var000[1][13][1] = float(i + 91);
  var000[1][14][0] = float(i + 92);
  var000[1][14][1] = float(i + 93);
  var000[1][15][0] = float(i + 94);
  var000[1][15][1] = float(i + 95);
  var000[1][16][0] = float(i + 96);
  var000[1][16][1] = float(i + 97);
  var000[1][17][0] = float(i + 98);
  var000[1][17][1] = float(i + 99);
  var000[1][18][0] = float(i + 100);
  var000[1][18][1] = float(i + 101);
  var000[1][19][0] = float(i + 102);
  var000[1][19][1] = float(i + 103);
  var000[1][20][0] = float(i + 104);
  var000[1][20][1] = float(i + 105);
  var000[1][21][0] = float(i + 106);
  var000[1][21][1] = float(i + 107);
  var000[1][22][0] = float(i + 108);
  var000[1][22][1] = float(i + 109);
  var000[1][23][0] = float(i + 110);
  var000[1][23][1] = float(i + 111);
  var000[1][24][0] = float(i + 112);
  var000[1][24][1] = float(i + 113);
  var000[1][25][0] = float(i + 114);
  var000[1][25][1] = float(i + 115);
  var000[1][26][0] = float(i + 116);
  var000[1][26][1] = float(i + 117);
  var000[1][27][0] = float(i + 118);
  var000[1][27][1] = float(i + 119);
  var000[1][28][0] = float(i + 120);
  var000[1][28][1] = float(i + 121);
  var000[1][29][0] = float(i + 122);
  var000[1][29][1] = float(i + 123);
  var000[1][30][0] = float(i + 124);
  var000[1][30][1] = float(i + 125);
  var000[1][31][0] = float(i + 126);
  var000[1][31][1] = float(i + 127);
}
#version 110
#extension GL_ARB_arrays_of_arrays: enable
varying vec2 var000[2][32];
uniform int i;

void main()
{
  bool failed = false;
  failed = failed || var000[0][0][0] != float(i + 0);
  failed = failed || var000[0][0][1] != float(i + 1);
  failed = failed || var000[0][1][0] != float(i + 2);
  failed = failed || var000[0][1][1] != float(i + 3);
  failed = failed || var000[0][2][0] != float(i + 4);
  failed = failed || var000[0][2][1] != float(i + 5);
  failed = failed || var000[0][3][0] != float(i + 6);
  failed = failed || var000[0][3][1] != float(i + 7);
  failed = failed || var000[0][4][0] != float(i + 8);
  failed = failed || var000[0][4][1] != float(i + 9);
  failed = failed || var000[0][5][0] != float(i + 10);
  failed = failed || var000[0][5][1] != float(i + 11);
  failed = failed || var000[0][6][0] != float(i + 12);
  failed = failed || var000[0][6][1] != float(i + 13);
  failed = failed || var000[0][7][0] != float(i + 14);
  failed = failed || var000[0][7][1] != float(i + 15);
  failed = failed || var000[0][8][0] != float(i + 16);
  failed = failed || var000[0][8][1] != float(i + 17);
  failed = failed || var000[0][9][0] != float(i + 18);
  failed = failed || var000[0][9][1] != float(i + 19);
  failed = failed || var000[0][10][0] != float(i + 20);
  failed = failed || var000[0][10][1] != float(i + 21);
  failed = failed || var000[0][11][0] != float(i + 22);
  failed = failed || var000[0][11][1] != float(i + 23);
  failed = failed || var000[0][12][0] != float(i + 24);
  failed = failed || var000[0][12][1] != float(i + 25);
  failed = failed || var000[0][13][0] != float(i + 26);
  failed = failed || var000[0][13][1] != float(i + 27);
  failed = failed || var000[0][14][0] != float(i + 28);
  failed = failed || var000[0][14][1] != float(i + 29);
  failed = failed || var000[0][15][0] != float(i + 30);
  failed = failed || var000[0][15][1] != float(i + 31);
  failed = failed || var000[0][16][0] != float(i + 32);
  failed = failed || var000[0][16][1] != float(i + 33);
  failed = failed || var000[0][17][0] != float(i + 34);
  failed = failed || var000[0][17][1] != float(i + 35);
  failed = failed || var000[0][18][0] != float(i + 36);
  failed = failed || var000[0][18][1] != float(i + 37);
  failed = failed || var000[0][19][0] != float(i + 38);
  failed = failed || var000[0][19][1] != float(i + 39);
  failed = failed || var000[0][20][0] != float(i + 40);
  failed = failed || var000[0][20][1] != float(i + 41);
  failed = failed || var000[0][21][0] != float(i + 42);
  failed = failed || var000[0][21][1] != float(i + 43);
  failed = failed || var000[0][22][0] != float(i + 44);
  failed = failed || var000[0][22][1] != float(i + 45);
  failed = failed || var000[0][23][0] != float(i + 46);
  failed = failed || var000[0][23][1] != float(i + 47);
  failed = failed || var000[0][24][0] != float(i + 48);
  failed = failed || var000[0][24][1] != float(i + 49);
  failed = failed || var000[0][25][0] != float(i + 50);
  failed = failed || var000[0][25][1] != float(i + 51);
  failed = failed || var000[0][26][0] != float(i + 52);
  failed = failed || var000[0][26][1] != float(i + 53);
  failed = failed || var000[0][27][0] != float(i + 54);
  failed = failed || var000[0][27][1] != float(i + 55);
  failed = failed || var000[0][28][0] != float(i + 56);
  failed = failed || var000[0][28][1] != float(i + 57);
  failed = failed || var000[0][29][0] != float(i + 58);
  failed = failed || var000[0][29][1] != float(i + 59);
  failed = failed || var000[0][30][0] != float(i + 60);
  failed = failed || var000[0][30][1] != float(i + 61);
  failed = failed || var000[0][31][0] != float(i + 62);
  failed = failed || var000[0][31][1] != float(i + 63);
  failed = failed || var000[1][0][0] != float(i + 64);
  failed = failed || var000[1][0][1] != float(i + 65);
  failed = failed || var000[1][1][0] != float(i + 66);
  failed = failed || var000[1][1][1] != float(i + 67);
  failed = failed || var000[1][2][0] != float(i + 68);
  failed = failed || var000[1][2][1] != float(i + 69);
  failed = failed || var000[1][3][0] != float(i + 70);
  failed = failed || var000[1][3][1] != float(i + 71);
  failed = failed || var000[1][4][0] != float(i + 72);
  failed = failed || var000[1][4][1] != float(i + 73);
  failed = failed || var000[1][5][0] != float(i + 74);
  failed = failed || var000[1][5][1] != float(i + 75);
  failed = failed || var000[1][6][0] != float(i + 76);
  failed = failed || var000[1][6][1] != float(i + 77);
  failed = failed || var000[1][7][0] != float(i + 78);
  failed = failed || var000[1][7][1] != float(i + 79);
  failed = failed || var000[1][8][0] != float(i + 80);
  failed = failed || var000[1][8][1] != float(i + 81);
  failed = failed || var000[1][9][0] != float(i + 82);
  failed = failed || var000[1][9][1] != float(i + 83);
  failed = failed || var000[1][10][0] != float(i + 84);
  failed = failed || var000[1][10][1] != float(i + 85);
  failed = failed || var000[1][11][0] != float(i + 86);
  failed = failed || var000[1][11][1] != float(i + 87);
  failed = failed || var000[1][12][0] != float(i + 88);
  failed = failed || var000[1][12][1] != float(i + 89);
  failed = failed || var000[1][13][0] != float(i + 90);
  failed = failed || var000[1][13][1] != float(i + 91);
  failed = failed || var000[1][14][0] != float(i + 92);
  failed = failed || var000[1][14][1] != float(i + 93);
  failed = failed || var000[1][15][0] != float(i + 94);
  failed = failed || var000[1][15][1] != float(i + 95);
  failed = failed || var000[1][16][0] != float(i + 96);
  failed = failed || var000[1][16][1] != float(i + 97);
  failed = failed || var000[1][17][0] != float(i + 98);
  failed = failed || var000[1][17][1] != float(i + 99);
  failed = failed || var000[1][18][0] != float(i + 100);
  failed = failed || var000[1][18][1] != float(i + 101);
  failed = failed || var000[1][19][0] != float(i + 102);
  failed = failed || var000[1][19][1] != float(i + 103);
  failed = failed || var000[1][20][0] != float(i + 104);
  failed = failed || var000[1][20][1] != float(i + 105);
  failed = failed || var000[1][21][0] != float(i + 106);
  failed = failed || var000[1][21][1] != float(i + 107);
  failed = failed || var000[1][22][0] != float(i + 108);
  failed = failed || var000[1][22][1] != float(i + 109);
  failed = failed || var000[1][23][0] != float(i + 110);
  failed = failed || var000[1][23][1] != float(i + 111);
  failed = failed || var000[1][24][0] != float(i + 112);
  failed = failed || var000[1][24][1] != float(i + 113);
  failed = failed || var000[1][25][0] != float(i + 114);
  failed = failed || var000[1][25][1] != float(i + 115);
  failed = failed || var000[1][26][0] != float(i + 116);
  failed = failed || var000[1][26][1] != float(i + 117);
  failed = failed || var000[1][27][0] != float(i + 118);
  failed = failed || var000[1][27][1] != float(i + 119);
  failed = failed || var000[1][28][0] != float(i + 120);
  failed = failed || var000[1][28][1] != float(i + 121);
  failed = failed || var000[1][29][0] != float(i + 122);
  failed = failed || var000[1][29][1] != float(i + 123);
  failed = failed || var000[1][30][0] != float(i + 124);
  failed = failed || var000[1][30][1] != float(i + 125);
  failed = failed || var000[1][31][0] != float(i + 126);
  failed = failed || var000[1][31][1] != float(i + 127);
  if (failed)
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
  else
    gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}

Patch hide | download patch | download mbox

diff --git a/tests/all.py b/tests/all.py
index 18124b7..85b622f 100755
--- a/tests/all.py
+++ b/tests/all.py
@@ -1290,7 +1290,7 @@  with profile.group_manager(
                   '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']:
             g(['varying-packing-simple', type_, arrayspec],
               'simple {} {}'.format(type_, arrayspec))
 
@@ -2062,7 +2062,7 @@  with profile.group_manager(
     for type in ['double', 'dvec2', 'dvec3', 'dvec4', 'dmat2', 'dmat3',
                  'dmat4', 'dmat2x3', 'dmat2x4', 'dmat3x2', 'dmat3x4',
                  'dmat4x2', 'dmat4x3']:
-        for arrayspec in ['array', 'separate']:
+        for arrayspec in ['array', 'separate', 'arrays_of_arrays']:
             g(['varying-packing-simple', type, arrayspec],
               'simple {0} {1}'.format(type, arrayspec))
 
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 e9935c7..2b1c010 100644
--- a/tests/spec/glsl-1.10/execution/varying-packing/simple.c
+++ b/tests/spec/glsl-1.10/execution/varying-packing/simple.c
@@ -100,6 +100,8 @@ 
 static void
 parse_args(int argc, char *argv[], struct piglit_gl_test_config *config);
 
+static const int outer_dim_size = 2;
+
 PIGLIT_GL_TEST_CONFIG_BEGIN
 
 	config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;
@@ -118,6 +120,13 @@  enum base_type
 	BASE_TYPE_DOUBLE,
 };
 
+enum test_array_type
+{
+	SEPARATE,
+	ARRAY,
+	ARRAYS_OF_ARRAYS,
+};
+
 static const char *
 get_base_type_name(enum base_type t)
 {
@@ -219,7 +228,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;
 };
 
 /**
@@ -228,12 +238,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;
@@ -249,6 +259,8 @@  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");
 	for (i = 0; i < num_varyings; ++i) {
 		const char *opt_flat_keyword = "";
 		if (!fp64 && varyings[i].type->base == BASE_TYPE_DOUBLE) {
@@ -257,11 +269,17 @@  get_shader(bool is_vs, unsigned glsl_version, int num_varyings,
 		}
 		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%03u[%u][%u];\n",
+					opt_flat_keyword, varying_keyword,
+					varyings[i].type->name, i,
+					outer_dim_size,
+					varyings[i].two_dim_array_elems);
+		} else if (varyings[i].one_dim_array_elems != 0) {
 			text += sprintf(text, "%s%s %s var%03u[%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%03u;\n",
 					opt_flat_keyword, varying_keyword,
@@ -282,31 +300,42 @@  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 outer_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) {
+			outer_array_loop_bound = outer_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, "failed = failed || ");
-					text += sprintf(text, "var%03u", 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);\n",
-							base_type_name,
-							offset++);
+		for (j = 0; j < outer_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, "failed = failed || ");
+						text += sprintf(text, "var%03u", 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);\n",
+								base_type_name,
+								offset++);
+					}
 				}
 			}
 		}
@@ -334,7 +363,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;
@@ -343,24 +373,43 @@  choose_varyings(struct varying_desc *varyings,
 		= test_type->num_cols * test_type->num_rows * element_size;
 	unsigned num_test_varyings
 		= max_varying_floats / components_in_test_type;
+	unsigned num_two_dim_test_varyings
+		 = num_test_varyings / outer_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 * outer_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;
 	}
 
@@ -377,6 +426,8 @@  NORETURN 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);
 }
@@ -414,36 +465,44 @@  parse_args(int argc, char *argv[], struct piglit_gl_test_config *config)
 void
 piglit_init(int argc, char **argv)
 {
-	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)
 		print_usage_and_exit(argv[0]);
 
+	glsl_version = test_type->glsl_version_required;
+
 	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);
 	if (test_type->base == BASE_TYPE_DOUBLE)
 		piglit_require_extension("GL_ARB_gpu_shader_fp64");
 	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);
+				       array_type, max_varying_floats);
 
 	vs = get_shader(true, test_type->glsl_version_required,
-			num_varyings, varyings);
+			num_varyings, varyings, array_type);
 	fs = get_shader(false, test_type->glsl_version_required,
-			num_varyings, varyings);
+			num_varyings, varyings, array_type);
 	prog = piglit_link_simple_program(vs, fs);
 	i_location = glGetUniformLocation(prog, "i");
 	free(varyings);