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

Kenneth Graunke kenneth at whitecape.org
Tue Dec 6 13:23:55 PST 2011


This exhaustively tests all 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/texturing/CMakeLists.txt            |    1 +
 tests/texturing/shaders/CMakeLists.gl.txt |   16 ++
 tests/texturing/shaders/CMakeLists.txt    |    1 +
 tests/texturing/shaders/common.c          |  288 +++++++++++++++++++++++++++++
 tests/texturing/shaders/common.h          |  101 ++++++++++
 tests/texturing/shaders/textureSize.c     |  282 ++++++++++++++++++++++++++++
 7 files changed, 694 insertions(+), 0 deletions(-)
 create mode 100644 tests/texturing/shaders/CMakeLists.gl.txt
 create mode 100644 tests/texturing/shaders/CMakeLists.txt
 create mode 100644 tests/texturing/shaders/common.c
 create mode 100644 tests/texturing/shaders/common.h
 create mode 100644 tests/texturing/shaders/textureSize.c

diff --git a/tests/all.tests b/tests/all.tests
index 68a379c..5907174 100644
--- a/tests/all.tests
+++ b/tests/all.tests
@@ -881,6 +881,11 @@ import_glsl_parser_tests(spec['glsl-1.30'],
 			 os.path.join(generatedTestDir, 'spec', 'glsl-1.30'),
 			 ['compiler'])
 spec['glsl-1.30']['execution'] = Group()
+spec['glsl-1.30']['execution']['textureSize'] = Group()
+for stage in ['vs', 'fs']:
+	# textureSize():
+	for sampler in ['sampler1D', 'sampler2D', 'sampler3D', 'samplerCube', 'sampler1DShadow', 'sampler2DShadow', 'samplerCubeShadow', 'sampler1DArray', 'sampler2DArray', 'sampler1DArrayShadow', 'sampler2DArrayShadow', 'isampler1D', 'isampler2D', 'isampler3D', 'isamplerCube', 'isampler1DArray', 'isampler2DArray', 'usampler1D', 'usampler2D', 'usampler3D', 'usamplerCube', 'usampler1DArray', 'usampler2DArray']:
+		spec['glsl-1.30']['execution']['textureSize'][stage + '-textureSize-' + sampler] = 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/texturing/CMakeLists.txt b/tests/texturing/CMakeLists.txt
index 144a306..1bc9f55 100644
--- a/tests/texturing/CMakeLists.txt
+++ b/tests/texturing/CMakeLists.txt
@@ -1 +1,2 @@
+add_subdirectory (shaders)
 piglit_include_target_api()
diff --git a/tests/texturing/shaders/CMakeLists.gl.txt b/tests/texturing/shaders/CMakeLists.gl.txt
new file mode 100644
index 0000000..e54760f
--- /dev/null
+++ b/tests/texturing/shaders/CMakeLists.gl.txt
@@ -0,0 +1,16 @@
+include_directories(
+	${GLEXT_INCLUDE_DIR}
+	${OPENGL_INCLUDE_PATH}
+	${GLUT_INCLUDE_DIR}
+	${piglit_SOURCE_DIR}/tests/mesa/util
+	${piglit_SOURCE_DIR}/tests/util
+)
+
+link_libraries (
+	piglitutil
+	${OPENGL_gl_LIBRARY}
+	${OPENGL_glu_LIBRARY}
+	${GLUT_glut_LIBRARY}
+)
+
+add_executable (textureSize textureSize.c common.c)
diff --git a/tests/texturing/shaders/CMakeLists.txt b/tests/texturing/shaders/CMakeLists.txt
new file mode 100644
index 0000000..144a306
--- /dev/null
+++ b/tests/texturing/shaders/CMakeLists.txt
@@ -0,0 +1 @@
+piglit_include_target_api()
diff --git a/tests/texturing/shaders/common.c b/tests/texturing/shaders/common.c
new file mode 100644
index 0000000..d5cc45d
--- /dev/null
+++ b/tests/texturing/shaders/common.c
@@ -0,0 +1,288 @@
+/*
+ * 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 common.c
+ *
+ * Helper functions for GLSL 1.30+ texturing tests.
+ */
+#include "common.h"
+
+/**
+ * Load a miplevel's texel data via glTexImage.
+ *
+ * \param level         The miplevel to be loaded (0 <= level <= miplevels)
+ * \param level_image   The data to be loaded.
+ *
+ * This function assumes that select_sampler() and compute_miplevel_info()
+ * have already been called.
+ */
+void
+upload_miplevel_data(GLenum target, int level, void *level_image)
+{
+	const GLenum format          = sampler.format;
+	const GLenum internal_format = sampler.internal_format;
+	const GLenum data_type       = sampler.data_type;
+
+	switch (target) {
+	case GL_TEXTURE_1D:
+		glTexImage1D(GL_TEXTURE_1D, level, internal_format,
+			     level_size[level][0],
+			     0, format, data_type, level_image);
+		break;
+	case GL_TEXTURE_2D:
+	case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+	case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+	case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+	case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+	case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+	case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+		glTexImage2D(target, level, internal_format,
+			     level_size[level][0], level_size[level][1],
+			     0, format, data_type, level_image);
+		break;
+	case GL_TEXTURE_3D:
+	case GL_TEXTURE_2D_ARRAY:
+		glTexImage3D(target, level, internal_format,
+			     level_size[level][0],
+			     level_size[level][1],
+			     level_size[level][2],
+			     0, format, data_type, level_image);
+		break;
+	case GL_TEXTURE_1D_ARRAY:
+		glTexImage2D(GL_TEXTURE_1D_ARRAY, level, internal_format,
+			     level_size[level][0], level_size[level][2],
+			     0, format, data_type, level_image);
+		break;
+	default:
+		assert(!"Not implemented yet.");
+		break;
+	}
+}
+
+
+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));
+}
+
+/**
+ * Compute the number of miplevels, as well as the dimensions (width, height,
+ * depth/number of array slices) of each level.
+ *
+ * This function assumes base_size is already set.
+ */
+void
+compute_miplevel_info()
+{
+	int i, l;
+	bool is_array = is_array_sampler();
+
+	/* Compute the number of miplevels */
+	miplevels = (int) log2f(max3(base_size[0], base_size[1], base_size[2])) + 1;
+
+	/* Compute the size of each miplevel */
+	level_size = malloc(miplevels * sizeof(int *));
+
+	level_size[0] = malloc(3 * sizeof(int));
+	memcpy(level_size[0], base_size, 3 * sizeof(int));
+	for (l = 1; l < miplevels; l++) {
+		level_size[l] = malloc(3 * sizeof(int));
+
+		for (i = 0; i < 3 - is_array; i++)
+			level_size[l][i] = max2(level_size[l-1][i] / 2, 1);
+
+		if (is_array)
+			level_size[l][2] = base_size[2];
+	}
+}
+
+bool
+has_height()
+{
+	return sampler.target == GL_TEXTURE_2D ||
+	       sampler.target == GL_TEXTURE_3D ||
+	       sampler.target == GL_TEXTURE_2D_ARRAY ||
+	       sampler.target == GL_TEXTURE_RECTANGLE;
+}
+
+bool
+has_slices()
+{
+	return is_array_sampler() || sampler.target == GL_TEXTURE_3D;
+}
+
+bool
+is_array_sampler()
+{
+	return sampler.target == GL_TEXTURE_1D_ARRAY ||
+	       sampler.target == GL_TEXTURE_2D_ARRAY ||
+	       sampler.target == GL_TEXTURE_CUBE_MAP_ARRAY;
+}
+
+bool
+is_shadow_sampler()
+{
+	return sampler.format == GL_DEPTH_COMPONENT;
+}
+
+/**
+ * Check if a given command line argument is a valid GLSL sampler type.
+ * If so, infer dimensionality and data format based on the name.
+ *
+ * Returns \c true if \p name was a valid sampler.
+ */
+bool
+select_sampler(const char *name)
+{
+	int i;
+	bool found = false;
+	struct {
+		const char *name;
+		GLenum type;
+		GLenum target;
+	} samplers[] = {
+		{ "sampler1D",              GL_SAMPLER_1D,                          GL_TEXTURE_1D,            },
+		{ "sampler2D",              GL_SAMPLER_2D,                          GL_TEXTURE_2D,            },
+		{ "sampler3D",              GL_SAMPLER_3D,                          GL_TEXTURE_3D,            },
+		{ "samplerCube",            GL_SAMPLER_CUBE,                        GL_TEXTURE_CUBE_MAP       },
+		{ "sampler2DRect",          GL_SAMPLER_2D_RECT,                     GL_TEXTURE_RECTANGLE      },
+		{ "sampler1DArray",         GL_SAMPLER_1D_ARRAY,                    GL_TEXTURE_1D_ARRAY       },
+		{ "sampler2DArray",         GL_SAMPLER_2D_ARRAY,                    GL_TEXTURE_2D_ARRAY       },
+		{ "samplerCubeArray",       GL_SAMPLER_CUBE_MAP_ARRAY,              GL_TEXTURE_CUBE_MAP_ARRAY },
+
+		{ "sampler1DShadow",        GL_SAMPLER_1D_SHADOW,                   GL_TEXTURE_1D             },
+		{ "sampler2DShadow",        GL_SAMPLER_2D_SHADOW,                   GL_TEXTURE_2D             },
+		{ "samplerCubeShadow",      GL_SAMPLER_CUBE_SHADOW,                 GL_TEXTURE_CUBE_MAP       },
+		{ "sampler2DRectShadow",    GL_SAMPLER_2D_RECT_SHADOW,              GL_TEXTURE_RECTANGLE      },
+		{ "sampler1DArrayShadow",   GL_SAMPLER_1D_ARRAY_SHADOW,             GL_TEXTURE_1D_ARRAY       },
+		{ "sampler2DArrayShadow",   GL_SAMPLER_1D_ARRAY_SHADOW,             GL_TEXTURE_2D_ARRAY       },
+		{ "samplerCubeArrayShadow", GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW,       GL_TEXTURE_CUBE_MAP_ARRAY },
+
+		{ "isampler1D",             GL_INT_SAMPLER_1D,                      GL_TEXTURE_1D             },
+		{ "isampler2D",             GL_INT_SAMPLER_2D,                      GL_TEXTURE_2D             },
+		{ "isampler3D",             GL_INT_SAMPLER_3D,                      GL_TEXTURE_3D             },
+		{ "isamplerCube",           GL_INT_SAMPLER_CUBE,                    GL_TEXTURE_CUBE_MAP       },
+		{ "isampler2DRect",         GL_INT_SAMPLER_2D_RECT,                 GL_TEXTURE_RECTANGLE      },
+		{ "isampler1DArray",        GL_INT_SAMPLER_1D_ARRAY,                GL_TEXTURE_1D_ARRAY       },
+		{ "isampler2DArray",        GL_INT_SAMPLER_2D_ARRAY,                GL_TEXTURE_2D_ARRAY       },
+		{ "isamplerCubeArray",      GL_INT_SAMPLER_CUBE_MAP_ARRAY,          GL_TEXTURE_CUBE_MAP_ARRAY },
+
+		{ "usampler1D",             GL_UNSIGNED_INT_SAMPLER_1D,             GL_TEXTURE_1D             },
+		{ "usampler2D",             GL_UNSIGNED_INT_SAMPLER_2D,             GL_TEXTURE_2D             },
+		{ "usampler3D",             GL_UNSIGNED_INT_SAMPLER_3D,             GL_TEXTURE_3D             },
+		{ "usamplerCube",           GL_UNSIGNED_INT_SAMPLER_CUBE,           GL_TEXTURE_CUBE_MAP       },
+		{ "usampler2DRect",         GL_UNSIGNED_INT_SAMPLER_2D_RECT,        GL_TEXTURE_RECTANGLE      },
+		{ "usampler1DArray",        GL_UNSIGNED_INT_SAMPLER_1D_ARRAY,       GL_TEXTURE_1D_ARRAY       },
+		{ "usampler2DArray",        GL_UNSIGNED_INT_SAMPLER_2D_ARRAY,       GL_TEXTURE_2D_ARRAY       },
+		{ "usamplerCubeArray",      GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY, GL_TEXTURE_CUBE_MAP_ARRAY },
+	};
+
+	for (i = 0; i < ARRAY_SIZE(samplers); i++) {
+		if (strcmp(samplers[i].name, name) == 0) {
+			found = true;
+			break;
+		}
+	}
+
+	if (!found)
+		return false;
+
+	sampler.name = name;
+	sampler.type = samplers[i].type;
+	sampler.target = samplers[i].target;
+
+	if (name[0] == 'i') {
+		sampler.data_type = GL_INT;
+		sampler.format = GL_RGBA_INTEGER;
+		sampler.internal_format = GL_RGBA32I;
+		sampler.return_type = "ivec4";
+	} else if (name[0] == 'u') {
+		sampler.data_type = GL_UNSIGNED_INT;
+		sampler.format = GL_RGBA_INTEGER;
+		sampler.internal_format = GL_RGBA32UI;
+		sampler.return_type = "uvec4";
+	} else if (strchr(name, 'w')) {
+		/* Shadow Sampler */
+		sampler.data_type = GL_FLOAT;
+		sampler.format = GL_DEPTH_COMPONENT;
+		sampler.internal_format = GL_DEPTH_COMPONENT;
+		sampler.return_type = "float";
+	} else {
+		sampler.data_type = GL_FLOAT;
+		sampler.format = GL_RGBA;
+		sampler.internal_format = GL_RGBA32F;
+		sampler.return_type = "vec4";
+	}
+
+	return true;
+}
+
+/**
+ * Ensures the driver supports the required extensions, GL, and GLSL versions.
+ * If it doesn't, report PIGLIT_SKIP and exit the test.
+ */
+void
+require_GL_features(enum shader_target test_stage)
+{
+	int tex_units;
+
+	piglit_require_GLSL_version(130);
+
+	switch (sampler.internal_format) {
+	case GL_RGBA32I:
+	case GL_RGBA32UI:
+		piglit_require_extension("GL_EXT_texture_integer");
+		break;
+	case GL_RGBA32F:
+		piglit_require_extension("GL_ARB_texture_float");
+		break;
+	}
+
+	switch (sampler.target) {
+	case GL_TEXTURE_CUBE_MAP_ARRAY:
+		piglit_require_extension("GL_ARB_texture_cube_map_array");
+		/* fallthrough */
+	case GL_TEXTURE_1D_ARRAY:
+	case GL_TEXTURE_2D_ARRAY:
+		piglit_require_extension("GL_EXT_texture_array");
+		break;
+	case GL_TEXTURE_CUBE_MAP:
+		if (is_shadow_sampler())
+			piglit_require_gl_version(30);
+		break;
+	case GL_TEXTURE_RECTANGLE:
+		piglit_require_extension("GL_ARB_texture_rectangle");
+		break;
+	}
+
+	/* If testing in the VS, check for VS texture units */
+	glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &tex_units);
+	if (test_stage == VS && tex_units <= 0)
+		piglit_report_result(PIGLIT_SKIP);
+}
diff --git a/tests/texturing/shaders/common.h b/tests/texturing/shaders/common.h
new file mode 100644
index 0000000..c25bf2c
--- /dev/null
+++ b/tests/texturing/shaders/common.h
@@ -0,0 +1,101 @@
+/*
+ * 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 common.h
+ *
+ * Common structures and functions used for GLSL 1.30+ texturing tests.
+ */
+#pragma once
+#define _GNU_SOURCE
+#include "piglit-util.h"
+
+/**
+ * Texture miplevel info:
+ *  @{
+ *
+ * The total number of miplevels:
+ */
+int miplevels;
+
+/** Size of the base level */
+int base_size[3];
+
+/**
+ * Multidimensional array containing the dimensions of each miplevel, indexed
+ * by miplevel and then x/y/z.  For example, miplevel[0][1] is the height of
+ * miplevel 0, while miplevel[5][2] is the number of slices in miplevel 5.
+ */
+int **level_size;
+/** @} */
+
+struct sampler_info
+{
+	/** GLSL sampler name (such as "usampler2DArray"). */
+	const char *name;
+
+	/** GLSL sampler return type: vec4, ivec4, uvec4, or float. */
+	const char *return_type;
+
+	/** GL sampler type (such as GL_UNSIGNED_INT_SAMPLER_2D_ARRAY). */
+	GLenum type;
+
+	/** GL texture target (such as GL_TEXTURE_2D_ARRAY). */
+	GLenum target;
+
+	/** Texture format data type: GL_FLOAT, GL_INT, or GL_UNSIGNED_INT. */
+	GLenum data_type;
+
+	/** Texture format: GL_RGBA, GL_RGBA_INTEGER, or GL_DEPTH_COMPONENT */
+	GLenum format;
+
+	/**
+	 * Texture internal format: GL_RGBA32F, GL_RGBA32I, GL_RGBA32UI, or
+	 * GL_DEPTH_COMPONENT.
+	 */
+	GLenum internal_format;
+} sampler;
+
+/**
+ * Which shader stage to test
+ */
+enum shader_target {
+	UNKNOWN,
+	VS,
+	FS,
+	GS
+};
+
+float max2(float x, float y);
+
+bool has_height();
+bool has_slices();
+
+bool is_array_sampler();
+bool is_shadow_sampler();
+
+void upload_miplevel_data(GLenum target, int level, void *level_image);
+void compute_miplevel_info();
+void require_GL_features(enum shader_target test_stage);
+bool select_sampler(const char *name);
+
diff --git a/tests/texturing/shaders/textureSize.c b/tests/texturing/shaders/textureSize.c
new file mode 100644
index 0000000..4184458
--- /dev/null
+++ b/tests/texturing/shaders/textureSize.c
@@ -0,0 +1,282 @@
+/*
+ * 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+ textureSize() built-in function.
+ *
+ * The test covers:
+ * - All pipeline stages (VS, FS)
+ * - Sampler data types (floating point, signed integer, unsigned integer)
+ * - Sampler 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 "textureSize" binary takes two arguments: shader stage and sampler type.
+ *
+ * For example:
+ * ./bin/textureSize fs sampler1DArrayShadow
+ * ./bin/textureSize vs usamplerCube
+ */
+#include "common.h"
+
+int piglit_width = 150, piglit_height = 30;
+int piglit_window_mode = GLUT_RGBA | GLUT_DOUBLE;
+
+static int lod_location;
+
+/**
+ * Returns the number of components expected from textureSize().
+ */
+int
+sampler_size()
+{
+	switch (sampler.target) {
+	case GL_TEXTURE_1D:
+		return 1;
+	case GL_TEXTURE_2D:
+	case GL_TEXTURE_1D_ARRAY:
+	case GL_TEXTURE_CUBE_MAP:
+	case GL_TEXTURE_RECTANGLE:
+		return 2;
+	case GL_TEXTURE_3D:
+	case GL_TEXTURE_2D_ARRAY:
+		return 3;
+	case GL_TEXTURE_CUBE_MAP_ARRAY:
+		assert(!"Not implemented yet.");
+	default:
+		assert(!"Should not get here.");
+		return 0;
+	}
+}
+
+enum piglit_result
+piglit_display()
+{
+	bool pass = true;
+	int i, l;
+	const int size = sampler_size();
+
+	glClearColor(0.5, 0.5, 0.5, 1.0);
+	glClear(GL_COLOR_BUFFER_BIT);
+
+	/* Draw consecutive squares for each mipmap level */
+	for (l = 0; l < miplevels; l++) {
+		const int x = 10 + l * 20;
+		float expected_color[4];
+		expected_color[0] = 0.01 * level_size[l][0];
+		if (sampler.target == GL_TEXTURE_1D_ARRAY) {
+			expected_color[1] = 0.01 * level_size[l][2];
+		} else {
+			for (i = 1; i < size; i++)
+				expected_color[i] = 0.01 * level_size[l][i];
+		}
+		expected_color[3] = 1.0;
+
+		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);
+	}
+
+	piglit_present_results();
+
+	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+/**
+ * Set the size of the texture's base level.
+ */
+void
+set_base_size()
+{
+	if (sampler.target == GL_TEXTURE_CUBE_MAP) {
+		/* Cube face width/height must be the same size. */
+		base_size[0] = base_size[1] = 65;
+		base_size[2] = 1;
+	} else {
+		base_size[0] = 65;
+		base_size[1] = has_height() ? 32 : 1;
+		base_size[2] = has_slices() ? 40 : 1;
+	}
+}
+
+void
+generate_texture()
+{
+	int l, i;
+	GLuint tex;
+	const GLenum target = sampler.target;
+
+	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);
+
+	for (l = 0; l < miplevels; l++) {
+		if (target == GL_TEXTURE_CUBE_MAP) {
+			for (i = 0; i < 6; i++) {
+				GLenum f = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
+				upload_miplevel_data(f, l, NULL);
+			}
+		} else {
+			upload_miplevel_data(sampler.target, l, NULL);
+		}
+	}
+}
+
+
+int
+generate_GLSL(enum shader_target test_stage)
+{
+	int vs, fs;
+
+	static char *vs_code;
+	static char *fs_code;
+
+	static const char *zeroes[3] = { "", "0, ", "0, 0, " };
+
+	const int size = sampler_size();
+
+	switch (test_stage) {
+	case VS:
+		asprintf(&vs_code,
+			 "#version 130\n"
+			 "#define ivec1 int\n"
+			 "uniform int lod;\n"
+			 "uniform %s tex;\n"
+			 "flat out ivec%d size;\n"
+			 "void main()\n"
+			 "{\n"
+			 "    size = textureSize(tex, lod);\n"
+			 "    gl_Position = gl_Vertex;\n"
+			 "}\n",
+			 sampler.name, size);
+		asprintf(&fs_code,
+			 "#version 130\n"
+			 "#define ivec1 int\n"
+			 "#define vec1 float\n"
+			 "flat in ivec%d size;\n"
+			 "void main()\n"
+			 "{\n"
+			 "    gl_FragColor = vec4(0.01 * size,%s 1);\n"
+			 "}\n",
+			 size, zeroes[3 - size]);
+		break;
+	case FS:
+		asprintf(&vs_code,
+			 "#version 130\n"
+			 "void main()\n"
+			 "{\n"
+			 "    gl_Position = gl_Vertex;\n"
+			 "}\n");
+		asprintf(&fs_code,
+			 "#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, size, zeroes[3 - 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
+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 sampler_found = false;
+
+	for (i = 1; i < argc; i++) {
+		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;
+			}
+		}
+
+		/* Maybe it's the sampler type? */
+		if (!sampler_found && (sampler_found = select_sampler(argv[i])))
+			continue;
+
+		fail_and_show_usage();
+	}
+
+	if (test_stage == UNKNOWN || !sampler_found)
+		fail_and_show_usage();
+
+	/* Not implemented yet */
+	assert(sampler.target != GL_TEXTURE_CUBE_MAP_ARRAY &&
+	       sampler.target != GL_TEXTURE_RECTANGLE);
+
+	require_GL_features(test_stage);
+
+	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);
+
+	/* Create textures and set miplevel info */
+	set_base_size();
+	compute_miplevel_info();
+	generate_texture();
+}
-- 
1.7.7.3



More information about the Piglit mailing list