[Piglit] [PATCH 1/2] Add a new comprehensive test for textureSize().

Ian Romanick idr at freedesktop.org
Fri Nov 18 16:15:58 PST 2011


On 11/17/2011 10:48 PM, Kenneth Graunke wrote:
> This exhaustively tests of GLSL 1.30's textureSize variants, both in the
> vertex and fragment shaders.  It covers:
> - Sampler data type (floating point, signed integer, unsigned integer)
> - Dimensionality (1D, 2D, 3D, Cube, 1DArray, 2DArray)
> - Color and shadow samplers
> - Mipmapped textures
> - Non-power-of-two textures
>
> It doesn't cover texture format variations.  In fact, the test never
> actually provides any content for the textures, because it should be
> irrelevant for textureSize(), is easier to program, and also extra mean.
>
> The new "textureSize" binary takes two arguments: shader stage and
> sampler type.  For example:
>
> ./bin/textureSize fs sampler1DArrayShadow
> ./bin/textureSize vs usamplerCube
>
> Signed-off-by: Kenneth Graunke<kenneth at whitecape.org>
> ---
>   tests/all.tests                                  |    5 +
>   tests/spec/glsl-1.30/execution/CMakeLists.gl.txt |    1 +
>   tests/spec/glsl-1.30/execution/textureSize.c     |  327 ++++++++++++++++++++++

I think the test code should live somewhere else.  In later GL versions, 
cubemap arrays are added, new shader stages are added, etc.  We can use 
this same test for those features as well.  Putting the code somewhere 
"common" and listing the tests (in all.tests) under glsl-1.30 or gl-3.0 
seems like the right answer.

>   3 files changed, 333 insertions(+), 0 deletions(-)
>   create mode 100644 tests/spec/glsl-1.30/execution/textureSize.c
>
> diff --git a/tests/all.tests b/tests/all.tests
> index 48ce2cb..ddfc42a 100644
> --- a/tests/all.tests
> +++ b/tests/all.tests
> @@ -872,6 +872,11 @@ import_glsl_parser_tests(spec['glsl-1.30'],
>   			 os.path.join(generatedTestDir, 'spec', 'glsl-1.30'),
>   			 ['compiler'])
>   spec['glsl-1.30']['execution'] = Group()
> +sampler_types = ['sampler1D', 'sampler2D', 'samplerCube', 'sampler1DShadow', 'sampler2DShadow', 'sampler1DArray', 'sampler2DArray', 'sampler1DArrayShadow', 'sampler2DArrayShadow', 'isampler1D', 'isampler2D', 'isamplerCube', 'isampler1DArray', 'isampler2DArray', 'usampler1D', 'usampler2D', 'usamplerCube', 'usampler1DArray', 'usampler2DArray']
> +for stage in ['vs', 'fs']:
> +	for sampler in sampler_types:
> +		test_name = stage + '-textureSize-' + sampler
> +		spec['glsl-1.30']['execution'][test_name] = PlainExecTest(['textureSize', stage, sampler, '-auto', '-fbo'])
>   add_plain_test(spec['glsl-1.30']['execution'], 'fs-textureSize-2D')
>   add_plain_test(spec['glsl-1.30']['execution'], 'fs-texelFetch-2D')
>   add_plain_test(spec['glsl-1.30']['execution'], 'fs-texelFetchOffset-2D')
> diff --git a/tests/spec/glsl-1.30/execution/CMakeLists.gl.txt b/tests/spec/glsl-1.30/execution/CMakeLists.gl.txt
> index c9a816d..d80bebe 100644
> --- a/tests/spec/glsl-1.30/execution/CMakeLists.gl.txt
> +++ b/tests/spec/glsl-1.30/execution/CMakeLists.gl.txt
> @@ -16,6 +16,7 @@ link_libraries (
>   add_executable (fs-textureSize-2D fs-textureSize-2D.c)
>   add_executable (fs-texelFetch-2D fs-texelFetch-2D.c)
>   add_executable (fs-texelFetchOffset-2D fs-texelFetchOffset-2D.c)
> +add_executable (textureSize textureSize.c)
>   IF (NOT MSVC)
>   	add_executable (isinf-and-isnan isinf-and-isnan.c)
>   ENDIF (NOT MSVC)
> diff --git a/tests/spec/glsl-1.30/execution/textureSize.c b/tests/spec/glsl-1.30/execution/textureSize.c
> new file mode 100644
> index 0000000..dcde354
> --- /dev/null
> +++ b/tests/spec/glsl-1.30/execution/textureSize.c
> @@ -0,0 +1,327 @@
> +/*
> + * Copyright © 2011 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + */
> +
> +/**
> + * \file textureSize.c
> + *
> + * Tests the GLSL 1.30 built-in function textureSize().
> + *
> + * Creates a mipmapped 64x32 2D texture and draws a series of squares whose
> + * color contains the width (red) and height (green) of each mipmap level.
> + */
> +#include "piglit-util.h"
> +
> +int piglit_width = 150, piglit_height = 30;
> +int piglit_window_mode = GLUT_RGBA | GLUT_DOUBLE;
> +
> +#define BS 500
> +static char vs_code[BS];
> +static char fs_code[BS];
> +
> +static int lod_location;
> +
> +/** Array containing the dimensions of the texture */
> +int tex_size[3] = { 65, 32, 0 };
> +int miplevels;
> +
> +enum shader_target {
> +	UNKNOWN,
> +	VS,
> +	FS
> +};
> +
> +struct sampler_info {
> +	const char *name;
> +	int size;
> +	GLenum gl_target;
> +	bool shadow;
> +};
> +
> +const struct sampler_info *sampler = NULL;
> +
> +static float max2(float x, float y) { return (x>  y) ? x : y; }
> +static float max3(float x, float y, float z) { return max2(x, max2(y, z)); }
> +
> +enum piglit_result
> +piglit_display()
> +{
> +	bool pass = true;
> +	int is_array = sampler->gl_target == GL_TEXTURE_1D_ARRAY ||
> +		       sampler->gl_target == GL_TEXTURE_2D_ARRAY;
> +	int i, l;
> +
> +	glClearColor(0.5, 0.5, 0.5, 1.0);
> +	glClear(GL_COLOR_BUFFER_BIT);
> +
> +	int level_size[3] = { 1, 1, 1 };
> +	for (i = 0; i<  sampler->size; i++)
> +		level_size[i] = tex_size[i];
> +
> +	/* Draw consecutive squares for each mipmap level */
> +	for (l = 0; l<  miplevels; l++) {
> +		const int x = 10 + l * 20;
> +		float expected_color[4] = { 0.0, 0.0, 0.0, 1.0 };
> +		for (i = 0; i<  sampler->size; i++)
> +			expected_color[i] = 0.01 * level_size[i];
> +
> +		piglit_Uniform1i(lod_location, l);
> +		glViewport(x, 10, 10, 10);
> +		piglit_draw_rect(-1, -1, 2, 2);
> +
> +		pass&= piglit_probe_rect_rgba(x, 10, 10, 10, expected_color);
> +
> +		/* For arrays, the # of slices never changes; don't divide */
> +		for (i = 0; i<  sampler->size - is_array; i++)
> +			level_size[i] = max2(level_size[i] / 2, 1);
> +	}
> +
> +	piglit_present_results();
> +
> +	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
> +}
> +
> +void
> +generate_texture()
> +{
> +	int i;
> +	GLuint tex;
> +	GLenum target = sampler->gl_target;
> +	GLenum format = sampler->shadow ? GL_DEPTH_COMPONENT : GL_RGBA;
> +
> +	glActiveTexture(GL_TEXTURE0);
> +
> +	glGenTextures(1,&tex);
> +	glBindTexture(target, tex);
> +	glEnable(target);
> +	glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
> +	glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
> +	glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
> +	glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
> +
> +	switch (sampler->gl_target) {
> +	case GL_TEXTURE_1D:
> +		glTexImage1D(GL_TEXTURE_1D, 0, format,
> +			     tex_size[0],
> +			     0, format, GL_FLOAT, NULL);
> +		break;
> +	case GL_TEXTURE_2D:
> +		glTexImage2D(GL_TEXTURE_2D, 0, format,
> +			     tex_size[0], tex_size[1],
> +			     0, format, GL_FLOAT, NULL);
> +		break;
> +	case GL_TEXTURE_3D:
> +		tex_size[2] = 64;
> +		glTexImage3D(GL_TEXTURE_3D, 0, format,
> +			     tex_size[0], tex_size[1], tex_size[2],
> +			     0, format, GL_FLOAT, NULL);
> +		break;
> +	case GL_TEXTURE_CUBE_MAP:
> +		/* Cube face width/height must be the same */
> +		tex_size[1] = tex_size[0];
> +		for (i = 0; i<  6; i++) {
> +			glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0,
> +				     format, tex_size[0], tex_size[1], 0,
> +				     format, GL_FLOAT, NULL);
> +		}
> +		break;
> +	case GL_TEXTURE_1D_ARRAY:
> +		tex_size[0] = 64;
> +		tex_size[1] = 40;
> +		glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, format,
> +			     tex_size[0], tex_size[1],
> +			     0, format, GL_FLOAT, NULL);
> +		break;
> +	case GL_TEXTURE_2D_ARRAY:
> +		tex_size[2] = 40;
> +		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, format,
> +			     tex_size[0], tex_size[1], tex_size[2],
> +			     0, format, GL_FLOAT, NULL);
> +		break;
> +	}
> +	glGenerateMipmap(target);
> +
> +	miplevels = (int) log2f(max3(tex_size[0], tex_size[1], tex_size[2]))+1;
> +
> +	for (i = sampler->size; i<  3; i++)
> +		tex_size[i] = 0;

Why not memset the whole thing at the top?

> +}
> +
> +
> +int
> +generate_GLSL(enum shader_target test_stage)
> +{
> +	int vs, fs;
> +	static const char *zeros[3] = { "", "0, ", "0, 0, " };
> +	assert(sampler->size>= 1&&  sampler->size<= 3);
> +
> +	switch (test_stage) {
> +	case VS:
> +		snprintf(vs_code, BS,
> +			 "#version 130\n"
> +			 "#define vec1 float\n"
> +			 "uniform int lod;\n"
> +			 "uniform %s tex;\n"
> +			 "out vec%d size;\n"

                           flat out ivec%d size;

Right?

> +			 "void main()\n"
> +			 "{\n"
> +			 "    size = textureSize(tex, lod);\n"

Doesn't this give an int-to-float implicit conversion error?

> +			 "    gl_Position = gl_Vertex;\n"
> +			 "}\n",
> +			 sampler->name, sampler->size);
> +		snprintf(fs_code, BS,
> +			 "#version 130\n"
> +			 "#define vec1 float\n"
> +			 "in vec%d size;\n"
> +			 "void main()\n"
> +			 "{\n"
> +			 "    gl_FragColor = vec4(0.01 * size,%s 1);\n"
> +			 "}\n",
> +			 sampler->size, zeros[3 - sampler->size]);
> +		break;
> +	case FS:
> +		snprintf(vs_code, BS,
> +			 "#version 130\n"
> +			 "void main()\n"
> +			 "{\n"
> +			 "    gl_Position = gl_Vertex;\n"
> +			 "}\n");
> +		snprintf(fs_code, BS,
> +			 "#version 130\n"
> +			 "#define ivec1 int\n"
> +			 "uniform int lod;\n"
> +			 "uniform %s tex;\n"
> +			 "void main()\n"
> +			 "{\n"
> +			 "    ivec%d size = textureSize(tex, lod);\n"
> +			 "    gl_FragColor = vec4(0.01 * size,%s 1);\n"
> +			 "}\n",
> +			 sampler->name, sampler->size, zeros[3-sampler->size]);
> +		break;
> +	default:
> +		assert(!"Should not get here.");
> +		break;
> +	}
> +
> +	vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vs_code);
> +	fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fs_code);
> +	return piglit_link_simple_program(vs, fs);
> +}
> +
> +void
> +select_sampler(char *name)
> +{
> +	int i;
> +	static const struct sampler_info samplers[] =
> +	{
> +		{ "sampler1D",            1, GL_TEXTURE_1D,       false },
> +		{ "sampler2D",            2, GL_TEXTURE_2D,       false },
> +		{ "sampler3D",            3, GL_TEXTURE_3D,       false },
                    samplerRectARB

> +		{ "samplerCube",          2, GL_TEXTURE_CUBE_MAP, false },
> +		{ "sampler1DShadow",      1, GL_TEXTURE_1D,       true },
> +		{ "sampler2DShadow",      2, GL_TEXTURE_2D,       true },
> +		{ "samplerCubeShadow",    2, GL_TEXTURE_CUBE_MAP, true },

                    samplerRectShadowARB

> +		{ "sampler1DArray",       2, GL_TEXTURE_1D_ARRAY, false },
> +		{ "sampler2DArray",       3, GL_TEXTURE_2D_ARRAY, false },
> +		{ "sampler1DArrayShadow", 2, GL_TEXTURE_1D_ARRAY, true},
> +		{ "sampler2DArrayShadow", 3, GL_TEXTURE_2D_ARRAY, true}
> +	};
> +
> +	for (i = 0; i<  ARRAY_SIZE(samplers); i++) {
> +		if (strcmp(samplers[i].name, name) == 0) {
> +			sampler =&samplers[i];
> +			return;
> +		}
> +	}
> +}
> +
> +void
> +fail_and_show_usage()
> +{
> +	printf("Usage: textureSize<vs|fs>  <sampler type>  [piglit args...]\n");
> +	piglit_report_result(PIGLIT_SKIP);
> +}
> +
> +void
> +piglit_init(int argc, char **argv)
> +{
> +	int prog;
> +	int tex_location;
> +	int i;
> +	enum shader_target test_stage = UNKNOWN;
> +	bool integer_format = false;
> +
> +	piglit_require_GLSL_version(130);
> +
> +	for (i = 1; i<  argc; i++) {
> +		/* Ignore piglit arguments like -auto and -fbo */
> +		if (argv[i][0] == '-')
> +			continue;

Don't these get consumed before piglit_init is called?  I've never seen 
another test do this.

> +
> +		if (test_stage == UNKNOWN) {
> +			/* Maybe it's the shader stage? */
> +			if (strcmp(argv[i], "vs") == 0) {
> +				test_stage = VS;
> +				continue;
> +			} else if (strcmp(argv[i], "fs") == 0) {
> +				test_stage = FS;
> +				continue;
> +			}
> +		}
> +
> +		if (sampler == NULL) {
> +			/* Maybe it's the sampler type? */
> +			if (argv[i][0] == 'i' || argv[i][0] == 'u') {
> +				integer_format = true;
> +				select_sampler(argv[i] + 1);
> +			} else {
> +				integer_format = false;
> +				select_sampler(argv[i]);
> +			}
> +
> +			if (sampler != NULL)
> +				continue;
> +		}
> +
> +		fail_and_show_usage();
> +	}
> +
> +	if (test_stage == UNKNOWN || sampler == NULL)
> +		fail_and_show_usage();
> +
> +	/* Skip if the driver doesn't export VS texture units */
> +	glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,&i);
> +	if (test_stage == VS&&  i<= 0)
> +		piglit_report_result(PIGLIT_SKIP);
> +
> +	prog = generate_GLSL(test_stage);
> +
> +	tex_location = piglit_GetUniformLocation(prog, "tex");
> +	lod_location = piglit_GetUniformLocation(prog, "lod");
> +	piglit_UseProgram(prog);
> +	piglit_Uniform1i(tex_location, 0);
> +
> +	if (integer_format&&  sampler->shadow)
> +		piglit_report_result(PIGLIT_SKIP);
> +
> +	generate_texture();
> +}


More information about the Piglit mailing list