[Piglit] [PATCH] ARB_texture_gather: add initial execution test

Chris Forbes chrisf at ijw.co.nz
Sat Aug 10 03:10:37 PDT 2013


This test exercises combinations of:
- Shader stage vs/fs
- Offsetting
- Component count, up to implementation-defined limit
- Swizzling
- Unsigned normalized vs float type

The test works by numbering the texels, and ensuring that the four
texels sampled by textureGather*() are those we expect.

Not exercised yet:
- Integer textures
- Samplers other than sampler2D
- Other interesting internalformats [DEPTH_COMPONENT, etc]
- Addressing modes other than WRAP.

Signed-off-by: Chris Forbes <chrisf at ijw.co.nz>
---
 tests/all.tests                           |  19 ++
 tests/texturing/shaders/CMakeLists.gl.txt |   1 +
 tests/texturing/shaders/textureGather.c   | 309 ++++++++++++++++++++++++++++++
 3 files changed, 329 insertions(+)
 create mode 100644 tests/texturing/shaders/textureGather.c

diff --git a/tests/all.tests b/tests/all.tests
index a914a2a..68e89e2 100644
--- a/tests/all.tests
+++ b/tests/all.tests
@@ -969,6 +969,25 @@ for stage in ['vs', 'gs', 'fs']:
 	for sampler in samplers_atm:
 		spec['ARB_texture_multisample/textureSize/' + stage + '-textureSize-' + sampler] = concurrent_test('textureSize ' + stage + ' ' + sampler)
 
+# Group ARB_texture_gather
+arb_texture_gather = Group()
+spec['ARB_texture_gather'] = arb_texture_gather
+for stage in ['vs', 'fs']:
+    for comps in ['r', 'rg', 'rgb', 'rgba']:
+        for swiz in ['red', 'green', 'blue', 'alpha'][:len(comps)] + ['', 'zero', 'one']:
+            for type in ['', 'float']:
+                for func in ['textureGather', 'textureGatherOffset']:
+                    testname = '%s/%s-%s-%s-%s' % (
+                        func, stage, comps,
+                        swiz if len(swiz) else 'none',
+                        type if len(type) else 'unorm')
+                    cmd = 'textureGather %s %s %s %s %s' % (
+                        stage,
+                        'offset' if func == 'textureGatherOffset' else '',
+                        comps, swiz, type
+                        )
+                    arb_texture_gather[testname] = concurrent_test(cmd)
+
 # Group AMD_shader_stencil_export
 spec['AMD_shader_stencil_export'] = Group()
 import_glsl_parser_tests(spec['AMD_shader_stencil_export'],
diff --git a/tests/texturing/shaders/CMakeLists.gl.txt b/tests/texturing/shaders/CMakeLists.gl.txt
index 7210c1c..6e4e9a7 100644
--- a/tests/texturing/shaders/CMakeLists.gl.txt
+++ b/tests/texturing/shaders/CMakeLists.gl.txt
@@ -12,3 +12,4 @@ link_libraries (
 
 piglit_add_executable (textureSize textureSize.c common.c)
 piglit_add_executable (texelFetch texelFetch.c common.c)
+piglit_add_executable (textureGather textureGather.c)
diff --git a/tests/texturing/shaders/textureGather.c b/tests/texturing/shaders/textureGather.c
new file mode 100644
index 0000000..9a92fd9
--- /dev/null
+++ b/tests/texturing/shaders/textureGather.c
@@ -0,0 +1,309 @@
+#include "piglit-util-gl-common.h"
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+	config.supports_gl_compat_version = 11;
+	config.supports_gl_core_version = 31;
+
+	config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+#define TEXTURE_WIDTH 32
+#define TEXTURE_HEIGHT 32
+
+enum { NONE, VS, FS } stage = NONE;
+bool use_offset = false;
+int components = 0;
+int swizzle = -1;
+bool use_float = false;
+
+GLenum internalformat_for_components[] = { GL_R16, GL_RG16, GL_RGB16, GL_RGBA16 };
+GLenum internalformat_for_components_f[] = { GL_R32F, GL_RG32F, GL_RGB32F, GL_RGBA32F };
+GLenum format_for_components[] = { GL_RED, GL_RG, GL_RGB, GL_RGBA };
+GLenum swizzles[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_ZERO, GL_ONE };
+
+unsigned char *pixels;
+float *expected;
+
+enum piglit_result
+piglit_display(void)
+{
+	int i, j;
+	bool pass = true;
+
+	glViewport(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT);
+
+	if (swizzle >= 0) {
+		GLint sw[] = { swizzles[swizzle], GL_ZERO, GL_ZERO, GL_ZERO };
+		glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, sw);
+	}
+
+	if (stage == FS)
+		glDrawArrays(GL_TRIANGLES, 0, 6);
+	else
+		glDrawArrays(GL_POINTS, 0, TEXTURE_WIDTH * TEXTURE_HEIGHT);
+
+	for (j = 0; j < TEXTURE_HEIGHT; j++)
+		for (i = 0; i < TEXTURE_WIDTH; i++) {
+			float *pe = &expected[4 * (j * TEXTURE_WIDTH + i)];
+			pass = piglit_probe_pixel_rgba(i, j, pe) && pass;
+		}
+
+	piglit_present_results();
+
+	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+/* TODO:
+ * Test mipmap selection (always selects base level)
+ * Test invariance under sampler weirdness
+ * Test other sampler types: gsampler2D|gsampler2DArray|gsamplerCube|gsamplerCubeArray
+ * Test GS texturing too -- Paul?
+ */
+
+static unsigned char
+pixel_value(int i, int j)
+{
+	if (swizzle == 4)
+		return 0;
+	if (swizzle == 5)
+		return 255;
+
+	if (use_offset) {
+		/* apply texel offset */
+		i += TEXTURE_WIDTH + -8;
+		j += TEXTURE_HEIGHT + 7;
+	}
+
+	/* WRAP at border */
+	i %= TEXTURE_WIDTH;
+	j %= TEXTURE_HEIGHT;
+
+	return i + j * TEXTURE_WIDTH;
+}
+
+static float
+norm_value(int x)
+{
+	return (float)x / 255.0f;
+}
+
+static void
+make_image(int num_channels, int use_channel)
+{
+	unsigned char *pp = pixels;
+	int i, j, ch;
+
+	for (j = 0; j < TEXTURE_HEIGHT; j++)
+		for (i = 0; i < TEXTURE_WIDTH; i++)
+			for (ch = 0; ch < num_channels; ch++)
+				*pp++ = (ch == use_channel) ? (i+j*TEXTURE_WIDTH) : 128;
+}
+
+static void
+make_expected(void)
+{
+	float *pe = expected;
+	int i, j;
+
+	for (j = 0; j < TEXTURE_HEIGHT; j++)
+		for (i = 0; i < TEXTURE_WIDTH; i++) {
+			*pe++ = norm_value(pixel_value(i, j + 1));
+			*pe++ = norm_value(pixel_value(i + 1, j + 1));
+			*pe++ = norm_value(pixel_value(i + 1, j));
+			*pe++ = norm_value(pixel_value(i, j));
+		}
+}
+
+static void
+upload_verts(void)
+{
+	if (stage == VS) {
+		float v[4 * TEXTURE_WIDTH * TEXTURE_HEIGHT], *pv = v;
+		int i, j;
+		for (j = 0; j < TEXTURE_HEIGHT; j++)
+			for (i = 0; i < TEXTURE_WIDTH; i++) {
+				*pv++ = (i + 0.5f) * 2 / TEXTURE_WIDTH - 1;
+				*pv++ = (j + 0.5f) * 2 / TEXTURE_HEIGHT - 1;
+				*pv++ = 0;
+				*pv++ = 1;
+			}
+		glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
+	}
+	else {
+		static const float verts[] = {
+			-1, -1, 0, 1,		-1, 1, 0, 1,	1, 1, 0, 1,
+			-1, -1, 0, 1,		1, 1, 0, 1,		1, -1, 0, 1,
+		};
+		glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
+	}
+}
+
+void
+do_requires(void)
+{
+	int max_components;
+	piglit_require_GLSL_version(130);
+	piglit_require_extension("GL_ARB_texture_gather");
+
+	/* check whether component count will actually work */
+	glGetIntegerv(GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB, &max_components);
+	if (components > max_components) {
+		printf("Test requires gather from texture with %d components;"
+		       "This implementation only supports %d\n",
+			   components, max_components);
+		piglit_report_result(PIGLIT_SKIP);
+	}
+
+	/* if we are trying to swizzle, check that we can! */
+	if (swizzle != -1)
+		piglit_require_extension("GL_EXT_texture_swizzle");
+}
+
+void
+do_setup(void)
+{
+	GLuint tex;
+	GLint vs, fs, prog;
+	GLint sampler_loc;
+	GLuint vbo;
+	char *vs_code, *fs_code;
+
+	pixels = malloc(components * sizeof(unsigned char) * TEXTURE_WIDTH * TEXTURE_HEIGHT);
+	expected = malloc(4 * sizeof(float) * TEXTURE_WIDTH * TEXTURE_HEIGHT);
+
+	glGenTextures(1, &tex);
+	glBindTexture(GL_TEXTURE_2D, tex);
+
+	make_image(components, swizzle >= 0 ? swizzle : 0);
+	make_expected();
+
+	glTexImage2D(GL_TEXTURE_2D, 0,
+	             use_float
+				     ? internalformat_for_components_f[components-1]
+					 : internalformat_for_components[components-1],
+	             TEXTURE_WIDTH, TEXTURE_HEIGHT,
+	             0, format_for_components[components-1],
+				 GL_UNSIGNED_BYTE, pixels);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+	if (stage == VS) {
+		asprintf(&vs_code, "#version 130\n"
+				"#extension GL_ARB_explicit_attrib_location: require\n"
+				"#extension GL_ARB_texture_gather: require\n"
+				"\n"
+				"layout(location=0) in vec4 pos;\n"
+				"uniform sampler2D s;\n"
+				"out vec4 c;\n"
+				"\n"
+				"void main() {\n"
+				"	gl_Position = pos;\n"
+				"	c = textureGather%s(s, 0.5 * pos.xy + vec2(0.5) %s);\n"
+				"}\n",
+				use_offset ? "Offset" : "",
+				use_offset ? ", ivec2(-8,7)" : "");
+		asprintf(&fs_code,
+				"#version 130\n"
+				"\n"
+				"in vec4 c;\n"
+				"\n"
+				"void main() {\n"
+				"	gl_FragColor = c;\n"
+				"}\n");
+	}
+	else {
+		asprintf(&vs_code,
+				"#version 130\n"
+				"#extension GL_ARB_explicit_attrib_location: require\n"
+				"layout(location=0) in vec4 pos;\n"
+				"\n"
+				"void main() {\n"
+				"	gl_Position = pos;\n"
+				"}\n");
+		asprintf(&fs_code,
+				"#version 130\n"
+				"#extension GL_ARB_texture_gather: require\n"
+				"\n"
+				"uniform sampler2D s;\n"
+				"\n"
+				"void main() {\n"
+				"	gl_FragColor = textureGather%s(s, gl_FragCoord.xy / vec2(32, 32) %s);\n"
+				"}\n",
+				use_offset ? "Offset" : "",
+				use_offset ? ", ivec2(-8,7)" : "");
+	}
+
+	vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vs_code);
+	fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fs_code);
+
+	if (!vs || !fs) {
+		printf("Failed compiling shader.\n");
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	prog = piglit_link_simple_program(vs, fs);
+
+	if (!prog) {
+		printf("Failed linking shader.\n");
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	glUseProgram(prog);
+    sampler_loc = glGetUniformLocation(prog, "s");
+	glUniform1i(sampler_loc, 0);
+
+	if (!piglit_check_gl_error(GL_NO_ERROR)) {
+		printf("Error in init\n");
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	if (piglit_get_gl_version() >= 31) {
+		GLuint vao;
+		glGenVertexArrays(1, &vao);
+		glBindVertexArray(vao);
+	}
+
+	glGenBuffers(1, &vbo);
+	glBindBuffer(GL_ARRAY_BUFFER, vbo);
+	upload_verts();
+	glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
+	glEnableVertexAttribArray(0);
+}
+
+void
+fail_with_usage(void)
+{
+	printf("Usage: textureGather vs|fs [offset] r|rg|rgb|rgba [red|green|blue|alpha|zero|one] [float]\n");
+	piglit_report_result(PIGLIT_SKIP);
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+	int i;
+	for (i = 1; i < argc; i++) {
+		char *opt = argv[i];
+		if (!strcmp(opt, "vs")) stage = VS;
+		else if (!strcmp(opt, "fs")) stage = FS;
+		else if (!strcmp(opt, "offset")) use_offset = true;
+		else if (!strcmp(opt, "r")) components = 1;
+		else if (!strcmp(opt, "rg")) components = 2;
+		else if (!strcmp(opt, "rgb")) components = 3;
+		else if (!strcmp(opt, "rgba")) components = 4;
+		else if (!strcmp(opt, "red")) swizzle = 0;
+		else if (!strcmp(opt, "green")) swizzle = 1;
+		else if (!strcmp(opt, "blue")) swizzle = 2;
+		else if (!strcmp(opt, "alpha")) swizzle = 3;
+		else if (!strcmp(opt, "zero")) swizzle = 4;
+		else if (!strcmp(opt, "one")) swizzle = 5;
+		else if (!strcmp(opt, "float")) use_float = true;
+	}
+
+	if (stage == NONE) fail_with_usage();
+	if (components == 0) fail_with_usage();
+
+	do_requires();
+	do_setup();
+}
-- 
1.8.3.4



More information about the Piglit mailing list