[Piglit] [PATCH] Test rendering to various miplevels of depth and stencil textures.

Paul Berry stereotype441 at gmail.com
Tue Apr 24 10:39:04 PDT 2012


This patch adds a new test, "depthstencil-render-miplevels", which
verifies that we can render to all miplevels of depth and stencil
textures.  It exposes two bugs in Mesa's current i965 driver:

- Miptree offsets aren't being calculated correctly for HiZ and
  separate stencil buffers, causing miplevels to overlap in those
  buffers.

- When binding the same texture to the GL_DEPTH_ATTACHMENT and
  GL_STENCIL_ATTACHMENT points, Mesa is trying to share internal data
  structures even if the miplevels don't match; as a result,
  transitioning from one miplevel to another doesn't work.

The test is capable of running at any texture size (including
non-power-of-two texture sizes).  However, because of some GPU hang
bugs in Mesa's current i965 driver, I've limited it to test at a
texture size of 1024x1024 for now.
---
 tests/all.tests                                   |   17 +
 tests/texturing/CMakeLists.gl.txt                 |    1 +
 tests/texturing/depthstencil-render-miplevels.cpp |  349 +++++++++++++++++++++
 3 files changed, 367 insertions(+), 0 deletions(-)
 create mode 100644 tests/texturing/depthstencil-render-miplevels.cpp

diff --git a/tests/all.tests b/tests/all.tests
index bd16c42..dc746bc 100644
--- a/tests/all.tests
+++ b/tests/all.tests
@@ -725,6 +725,23 @@ add_plain_test(texturing, 'texture-packed-formats')
 add_plain_test(texturing, 'texture-rg')
 add_plain_test(texturing, 'tex-srgb')
 
+# Note: for a reasonably thorough test we should be testing a variety
+# of texture sizes, some of which are not powers of two.  For i965, a
+# particularly mean set of test sizes would be (146, 292, 585, 1024),
+# since this exercises all possible combinations of buffer alignments.
+#
+# However, existing i965 driver bugs cause GPU hangs for sizes 146,
+# 292, and 585.  So, as a temporary measure, just test a size of 1024.
+for texture_size in (1024,):
+        for test_type in ('stencil', 'depth_x', 'depth', 'd16',
+                          'depth_x_and_stencil', 'depth_and_stencil',
+                          'stencil_and_depth_x', 'stencil_and_depth',
+                          'depth_stencil_shared', 'stencil_depth_shared',
+                          'depth_stencil_single_binding'):
+                test_name = 'depthstencil-render-miplevels {0} {1}'.format(
+                        texture_size, test_type)
+                texturing[test_name] = PlainExecTest(test_name + ' -auto')
+
 def texwrap_test(args):
 	test = PlainExecTest(args + ['-fbo'])
 	test.runConcurrent = True
diff --git a/tests/texturing/CMakeLists.gl.txt b/tests/texturing/CMakeLists.gl.txt
index 6246a02..37b8bc7 100644
--- a/tests/texturing/CMakeLists.gl.txt
+++ b/tests/texturing/CMakeLists.gl.txt
@@ -24,6 +24,7 @@ IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
 ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
 piglit_add_executable (cubemap cubemap.c)
 piglit_add_executable (depth-level-clamp depth-level-clamp.c)
+piglit_add_executable (depthstencil-render-miplevels depthstencil-render-miplevels.cpp)
 piglit_add_executable (gen-compressed-teximage gen-compressed-teximage.c)
 piglit_add_executable (gen-nonzero-unit gen-nonzero-unit.c)
 piglit_add_executable (gen-teximage gen-teximage.c)
diff --git a/tests/texturing/depthstencil-render-miplevels.cpp b/tests/texturing/depthstencil-render-miplevels.cpp
new file mode 100644
index 0000000..4b818ec
--- /dev/null
+++ b/tests/texturing/depthstencil-render-miplevels.cpp
@@ -0,0 +1,349 @@
+/*
+ * Copyright © 2012 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 depthstencil-render-miplevels.cpp
+ *
+ * Test that data rendered to depth and stencil textures
+ * always lands at the correct miplevel.
+ *
+ * This test operates by creating a set of texture buffers, attaching
+ * them to a framebuffer one miplevel at a time, and rendering
+ * different data into each miplevel.  Then it verifies, using
+ * glReadPixels, that the correct data appears at each miplevel.
+ *
+ * This is useful in diagnosing bugs such as:
+ *
+ * - Incorrect miplevels being attached to the framebuffer
+ *
+ * - Miplevels being laid out incorrectly in memory (e.g. in an
+ *   overlapping fashion)
+ *
+ * Usage: depthstencil-render-miplevels <texture_size> <buffer_combination>
+ *
+ *  buffer_combination:          buffer attachments:
+ *  stencil                      stencil->DEPTH_STENCIL
+ *  depth_x                      depth->DEPTH_STENCIL
+ *  depth                        depth->DEPTH_COMPONENT
+ *  d16                          depth->DEPTH_COMPONENT16
+ *  depth_x_and_stencil          depth->DEPTH_STENCIL, stencil->DEPTH_STENCIL
+ *  stencil_and_depth_x          (as above, but stencil attached first)
+ *  depth_and_stencil            depth->DEPTH_COMPONENT, stencil->DEPTH_STENCIL
+ *  stencil_and_depth            (as above, but stencil attached first)
+ *  depth_stencil_shared         depth->DEPTH_STENCIL<-stencil
+ *  stencil_depth_shared         (as above, but stencil attached first)
+ *  depth_stencil_single_binding depth_stencil->DEPTH_STENCIL
+ *
+ * Note: the buffer attachments are diagrammed above as
+ * "attachment_point->BUFFER_TYPE".  So, for example:
+ *
+ * - "depth->DEPTH_COMPONENT, stencil->DEPTH_STENCIL" means there is a
+ *   texture of type GL_DEPTH_COMPONENT attached to
+ *   GL_DEPTH_ATTACHMENT, and a separate texture of type
+ *   GL_DEPTH_STENCIL attached to GL_STENCIL_ATTACHMENT.
+ *
+ * - "depth->DEPTH_STENCIL<-stencil" means there is a single texture
+ *   of type GL_DEPTH_STENCIL attached to both GL_DEPTH_ATTACHMENT and
+ *   GL_STENCIL_ATTACHMENT.
+ *
+ * - "depth_stencil->DEPTH_STENCIL" means there is a single texture of
+ *   type GL_DEPTH_STENCIL attached to the attachment point
+ *   GL_DEPTH_STENCIL_ATTACHMENT.
+ */
+
+#include "piglit-util.h"
+
+int piglit_width = 16;
+int piglit_height = 16;
+int piglit_window_mode = GLUT_RGBA;
+
+namespace {
+
+GLuint color_tex;
+GLuint depth_tex;
+GLuint stencil_tex;
+bool attach_depth = false;
+bool attach_stencil = false;
+bool shared_attachment = false;
+bool attach_together = false;
+bool attach_stencil_first = false;
+bool depth_attachment_lacks_stencil = false;
+bool depth_attachment_16bit = false;
+int miplevel0_size;
+int max_miplevel;
+
+/**
+ * Create a mipmapped texture with the given dimensions and internal format.
+ */
+GLuint
+create_mipmapped_tex(GLenum internal_format)
+{
+	GLenum format = internal_format == GL_DEPTH_COMPONENT16
+		? GL_DEPTH_COMPONENT : internal_format;
+	GLenum type = format == GL_DEPTH_STENCIL
+		? GL_UNSIGNED_INT_24_8 : GL_UNSIGNED_BYTE;
+	GLuint tex;
+	glGenTextures(1, &tex);
+	glBindTexture(GL_TEXTURE_2D, tex);
+	for (int level = 0; level <= max_miplevel; ++level) {
+		int dim = miplevel0_size >> level;
+		glTexImage2D(GL_TEXTURE_2D, level, internal_format,
+			     dim, dim,
+			     0,
+			     format, type, NULL);
+		if (!piglit_check_gl_error(GL_NO_ERROR))
+			piglit_report_result(PIGLIT_FAIL);
+	}
+	return tex;
+}
+
+/**
+ * Attach the proper miplevel of each texture to the framebuffer
+ */
+void
+set_up_framebuffer_for_miplevel(int level)
+{
+	glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
+			       GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+			       color_tex, level);
+	if (attach_together) {
+		glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
+				       GL_DEPTH_STENCIL_ATTACHMENT,
+				       GL_TEXTURE_2D, depth_tex, level);
+	} else if (attach_stencil_first) {
+		glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
+				       GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
+				       stencil_tex, level);
+		glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
+				       GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
+				       depth_tex, level);
+	} else {
+		if (attach_depth) {
+			glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
+					       GL_DEPTH_ATTACHMENT,
+					       GL_TEXTURE_2D,
+					       depth_tex, level);
+		}
+		if (attach_stencil) {
+			glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
+					       GL_STENCIL_ATTACHMENT,
+					       GL_TEXTURE_2D,
+					       stencil_tex, level);
+		}
+	}
+
+	/* Some implementations don't support certain buffer
+	 * combinations, and that's ok, provided that the
+	 * implementation reports GL_FRAMEBUFFER_UNSUPPORTED.
+	 * However, if the buffer combination was supported at
+	 * miplevel 0, it should be supported at all miplevels.
+	 */
+	GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
+	if (status == GL_FRAMEBUFFER_UNSUPPORTED && level == 0) {
+		printf("This buffer combination is unsupported\n");
+		piglit_report_result(PIGLIT_SKIP);
+	} else if (status != GL_FRAMEBUFFER_COMPLETE) {
+		printf("FBO incomplete at miplevel %d\n", level);
+		piglit_report_result(PIGLIT_FAIL);
+	}
+}
+
+/**
+ * Using glClear, set the contents of the depth and stencil buffers
+ * (if present) to a value that is unique to this miplevel.
+ */
+void
+populate_miplevel(int level)
+{
+	float float_value = float(level + 1) / (max_miplevel + 1);
+	GLbitfield clear_mask = 0;
+
+	if (attach_depth) {
+		glClearDepth(float_value);
+		clear_mask |= GL_DEPTH_BUFFER_BIT;
+	}
+	if (attach_stencil) {
+		glClearStencil(level + 1);
+		clear_mask |= GL_STENCIL_BUFFER_BIT;
+	}
+
+	glClear(clear_mask);
+}
+
+/**
+ * Test that every pixel in the depth and stencil buffers (if present)
+ * is equal to the value set by populate_miplevel.
+ */
+bool
+test_miplevel(int level)
+{
+	bool pass = true;
+	int dim = miplevel0_size >> level;
+	float float_value = float(level + 1) / (max_miplevel + 1);
+
+	if (attach_depth) {
+		printf("Probing miplevel %d depth\n", level);
+		pass = piglit_probe_rect_depth(0, 0, dim, dim, float_value)
+			&& pass;
+	}
+
+	if (attach_stencil) {
+		printf("Probing miplevel %d stencil\n", level);
+		pass = piglit_probe_rect_stencil(0, 0, dim, dim, level + 1)
+			&& pass;
+	}
+
+	return pass;
+}
+
+void
+print_usage_and_exit(char *prog_name)
+{
+	printf("Usage: %s <texture_size> <buffer_combination>\n"
+	       "    buffer_combination:          buffer attachments:\n"
+	       "    stencil                      stencil->DEPTH_STENCIL\n"
+	       "    depth_x                      depth->DEPTH_STENCIL\n"
+	       "    depth                        depth->DEPTH_COMPONENT\n"
+	       "    depth_x_and_stencil          depth->DEPTH_STENCIL, stencil->DEPTH_STENCIL\n"
+	       "    stencil_and_depth_x          (as above, but stencil attached first)\n"
+	       "    depth_and_stencil            depth->DEPTH_COMPONENT, stencil->DEPTH_STENCIL\n"
+	       "    stencil_and_depth            (as above, but stencil attached first)\n"
+	       "    depth_stencil_shared         depth->DEPTH_STENCIL<-stencil\n"
+	       "    stencil_depth_shared         (as above, but stencil attached first)\n"
+	       "    depth_stencil_single_binding depth/stencil->DEPTH_STENCIL\n",
+	       prog_name);
+	piglit_report_result(PIGLIT_FAIL);
+}
+
+extern "C" void
+piglit_init(int argc, char **argv)
+{
+	if (argc != 3) {
+		print_usage_and_exit(argv[0]);
+	}
+
+	/* argv[1]: texture size */
+	{
+		char *endptr = NULL;
+		miplevel0_size = strtol(argv[1], &endptr, 0);
+		if (endptr != argv[1] + strlen(argv[1]))
+			print_usage_and_exit(argv[0]);
+
+		/* Now figure out the appropriate value of max_miplevel for this size. */
+		max_miplevel = 0;
+		while ((miplevel0_size >> (max_miplevel + 1)) > 0)
+			++max_miplevel;
+	}
+
+	/* argv[2]: buffer combination */
+	if (strcmp(argv[2], "stencil") == 0) {
+		attach_stencil = true;
+	} else if (strcmp(argv[2], "depth_x") == 0) {
+		attach_depth = true;
+	} else if (strcmp(argv[2], "depth") == 0) {
+		attach_depth = true;
+		depth_attachment_lacks_stencil = true;
+	} else if (strcmp(argv[2], "d16") == 0) {
+		attach_depth = true;
+		depth_attachment_lacks_stencil = true;
+		depth_attachment_16bit = true;
+	} else if (strcmp(argv[2], "depth_x_and_stencil") == 0) {
+		attach_depth = true;
+		attach_stencil = true;
+	} else if (strcmp(argv[2], "depth_and_stencil") == 0) {
+		attach_depth = true;
+		attach_stencil = true;
+		depth_attachment_lacks_stencil = true;
+	} else if (strcmp(argv[2], "stencil_and_depth_x") == 0) {
+		attach_depth = true;
+		attach_stencil = true;
+		attach_stencil_first = true;
+	} else if (strcmp(argv[2], "stencil_and_depth") == 0) {
+		attach_depth = true;
+		attach_stencil = true;
+		attach_stencil_first = true;
+		depth_attachment_lacks_stencil = true;
+	} else if (strcmp(argv[2], "depth_stencil_shared") == 0) {
+		attach_depth = true;
+		attach_stencil = true;
+		shared_attachment = true;
+	} else if (strcmp(argv[2], "stencil_depth_shared") == 0) {
+		attach_depth = true;
+		attach_stencil = true;
+		shared_attachment = true;
+		attach_stencil_first = true;
+	} else if (strcmp(argv[2], "depth_stencil_single_binding") == 0) {
+		attach_depth = true;
+		attach_stencil = true;
+		shared_attachment = true;
+		attach_together = true;
+	} else {
+		print_usage_and_exit(argv[0]);
+	}
+
+	bool pass = true;
+
+	color_tex = create_mipmapped_tex(GL_RGBA);
+
+	if (attach_depth) {
+		if (depth_attachment_16bit) {
+			depth_tex = create_mipmapped_tex(GL_DEPTH_COMPONENT16);
+		} else if (depth_attachment_lacks_stencil) {
+			depth_tex = create_mipmapped_tex(GL_DEPTH_COMPONENT);
+		} else {
+			depth_tex = create_mipmapped_tex(GL_DEPTH_STENCIL);
+		}
+	}
+
+	if (attach_stencil) {
+		if (shared_attachment) {
+			stencil_tex = depth_tex;
+		} else {
+			stencil_tex = create_mipmapped_tex(GL_DEPTH_STENCIL);
+		}
+	}
+
+	GLuint fbo;
+	glGenFramebuffers(1, &fbo);
+	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
+	glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
+
+	for (int level = 0; level <= max_miplevel; ++level) {
+		set_up_framebuffer_for_miplevel(level);
+		populate_miplevel(level);
+	}
+	for (int level = 0; level <= max_miplevel; ++level) {
+		set_up_framebuffer_for_miplevel(level);
+		pass = test_miplevel(level) && pass;
+	}
+
+	piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
+}
+
+extern "C" enum piglit_result
+piglit_display()
+{
+	/* Should never be reached */
+	return PIGLIT_FAIL;
+}
+
+};
-- 
1.7.7.6



More information about the Piglit mailing list