[Piglit] [PATCH] tex3d-maxsize: rewrite to be more robust and do more testing
Brian Paul
brianp at vmware.com
Wed Jul 13 21:47:53 UTC 2016
1. It seems with NVIDIA's driver that using a proxy texture isn't a
sure fire way to know that a given texture format/size can actually be
created. Update the find_max_tex3d_size() function to actually try
creating a texture with glTexImage3D/glTexStorage3D and see if it
works.
2. Improve the speed of texture initialization by copying the first
3D slice to the other slices with glCopyImageSubData().
3. Use glTexStorage3D when GL_ARB_texture_storage is supported.
4. In addition to GL_RGBA8, test GL_INTENSITY8 and GL_RGBA32F formats.
5. Before testing the largest possible texture, try a couple smaller
sizes as a sanity check.
6. Loosen the piglit probe tolerance by one bit to account for inaccuracy
caused by GL_NEAREST filtering.
Tested with NVIDIA driver, VMware driver and llvmpipe.
---
tests/texturing/tex3d-maxsize.c | 285 +++++++++++++++++++++++++++++-----------
1 file changed, 211 insertions(+), 74 deletions(-)
diff --git a/tests/texturing/tex3d-maxsize.c b/tests/texturing/tex3d-maxsize.c
index e168d14..60c9c63 100644
--- a/tests/texturing/tex3d-maxsize.c
+++ b/tests/texturing/tex3d-maxsize.c
@@ -30,31 +30,88 @@
PIGLIT_GL_TEST_CONFIG_BEGIN
- config.supports_gl_compat_version = 10;
+ config.supports_gl_compat_version = 12;
config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE;
PIGLIT_GL_TEST_CONFIG_END
-static const char *TestName = "tex3d-maxsize";
+
+static GLint MaxSize;
+
+
+
+/**
+ * Compute size (in megabytes) of a texture of the given dimensions and
+ * internal format.
+ */
+static unsigned
+tex_size(GLenum internalFormat, int width, int height, int depth)
+{
+ uint64_t sz;
+
+ sz = (uint64_t) width * (uint64_t) height * (uint64_t) depth;
+
+ switch (internalFormat) {
+ case GL_INTENSITY8:
+ sz *= 1;
+ break;
+ case GL_RGBA8:
+ sz *= 4;
+ break;
+ case GL_RGBA32F:
+ sz *= 16;
+ break;
+ default:
+ assert(!"Unexpected internalFormat");
+ }
+
+ return (unsigned) (sz / (uint64_t) (1024 * 1024));
+}
+
+
+/**
+ * Allocate a 1-level 3D texture.
+ */
+static void
+alloc_tex3d(GLenum target, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth)
+{
+ if (target == GL_TEXTURE_3D) {
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ }
+
+ if (piglit_is_extension_supported("GL_ARB_texture_storage")) {
+ glTexStorage3D(target, 1, internalFormat,
+ width, height, depth);
+ }
+ else {
+ glTexImage3D(target, 0, internalFormat,
+ width, height, depth, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ }
+}
/*
* Use proxy texture to find largest possible 3D texture size.
*/
static void
-find_max_tex3d_size(GLint initSize, GLint *width, GLint *height, GLint *depth)
+find_max_tex3d_size(GLenum internalFormat,
+ GLint initSize, GLint *width, GLint *height, GLint *depth)
{
GLint dim = 0, w, h, d, pw, ph, pd;
+ piglit_check_gl_error(GL_NO_ERROR);
+
w = h = d = initSize;
while (w >= 1 && h >= 1 && d >= 1) {
/* try proxy image */
const int level = 0;
- glTexImage3D(GL_PROXY_TEXTURE_3D, level, GL_RGBA8,
- w, h, d, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ alloc_tex3d(GL_PROXY_TEXTURE_3D, internalFormat, w, h, d);
glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, level,
GL_TEXTURE_WIDTH, &pw);
@@ -63,12 +120,40 @@ find_max_tex3d_size(GLint initSize, GLint *width, GLint *height, GLint *depth)
glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, level,
GL_TEXTURE_DEPTH, &pd);
+ if (!piglit_check_gl_error(GL_NO_ERROR)) {
+ printf("Unexpected error during texture proxy test.\n");
+ piglit_report_result(PIGLIT_FAIL);
+ }
+
if (pw == w && ph == h && pd == d) {
- /* success! */
- *width = w;
- *height = h;
- *depth = d;
- return;
+ /* this size should be supported, but test it to
+ * be sure.
+ */
+ GLuint tex;
+ GLenum err;
+
+ /* Create a texture object for the non-proxy texture below */
+ glGenTextures(1, &tex);
+ glBindTexture(GL_TEXTURE_3D, tex);
+ alloc_tex3d(GL_TEXTURE_3D, internalFormat, w, h, d);
+
+ err = glGetError();
+
+ glDeleteTextures(1, &tex);
+
+ if (err == GL_NO_ERROR) {
+ /* success! */
+ *width = w;
+ *height = h;
+ *depth = d;
+ return;
+ }
+ else {
+ printf("Note: proxy texture of size "
+ "%d x %d x %d worked, but actual "
+ "glTexImage3D call failed!\n",
+ w, h, d);
+ }
}
/* halve one of the dimensions and try again */
@@ -84,70 +169,39 @@ find_max_tex3d_size(GLint initSize, GLint *width, GLint *height, GLint *depth)
}
-enum piglit_result
-piglit_display(void)
+/**
+ * Create a 3D texture of the given format and size, draw a textured quad
+ * with that texture, and check results.
+ */
+static bool
+test_render(GLenum internalFormat, int width, int height, int depth)
{
- GLuint tex;
- GLint maxsize, width, height, depth;
- GLenum err;
+ static const float c1[4] = {0.25, 0.25, 0.25, 1.0};
+ static const float c2[4] = {0.75, 0.75, 0.75, 1.0};
+ bool pass = true;
char *data;
int i, j;
- GLboolean pass = GL_TRUE;
- float c1[4] = {0.25, 0.25, 0.25, 1.0};
- float c2[4] = {0.75, 0.75, 0.75, 1.0};
-
- piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
+ GLuint tex;
+ unsigned mbytes = tex_size(internalFormat, width, height, depth);
- glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &maxsize);
+ printf("Testing %d x %d x %d %s (%u MB) texture\n",
+ width, height, depth,
+ piglit_get_gl_enum_name(internalFormat), mbytes);
+ fflush(stdout);
- /* Create the texture. */
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_3D, tex);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- if (glGetError())
- return PIGLIT_FAIL;
-
- glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, maxsize, maxsize, maxsize, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-
- err = glGetError();
-
- if (err == GL_OUT_OF_MEMORY) {
+ alloc_tex3d(GL_TEXTURE_3D, internalFormat, width, height, depth);
- /* use proxy texture to find working max texture size */
- width = height = depth = 0;
- find_max_tex3d_size(maxsize, &width, &height, &depth);
-
- printf("Max 3D texture size: %d x %d x %d\n",
- width, height, depth);
- fflush(stdout);
-
- glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, width, height, depth, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- err = glGetError();
-
- if (err == GL_OUT_OF_MEMORY)
- return PIGLIT_PASS;
- }
- else {
- /* the max 3D texture size actually worked */
- width = height = depth = maxsize;
- }
-
- if (err != GL_NO_ERROR) {
- printf("%s: unexpected glTexImage3D error: 0x%x\n",
- TestName, err);
- return PIGLIT_FAIL;
+ if (!piglit_check_gl_error(GL_NO_ERROR)) {
+ printf("Creating texture failed in test_render().\n");
+ pass = false;
+ goto end;
}
- if (0)
- printf("max 3D texture size = %d x %d x %d\n",
- width, height, depth);
-
/* Set its pixels, slice by slice. */
data = malloc(width * height * 4);
- for (j = 0; j < height; j++)
+ for (j = 0; j < height; j++) {
for (i = 0; i < width; i++) {
int a = (j * width + i) * 4;
data[a+0] =
@@ -155,26 +209,45 @@ piglit_display(void)
data[a+2] =
data[a+3] = (i * 255) / (width - 1);
}
+ }
- for (i = 0; i < depth; i++) {
- glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, i, width, height, 1,
+ if (piglit_is_extension_supported("GL_ARB_copy_image")) {
+ /* load 0th slice */
+ glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0,
+ width, height, 1,
GL_RGBA, GL_UNSIGNED_BYTE, data);
+
+ /* copy 0th slice to other slices (should be faster) */
+ for (i = 1; i < depth; i++) {
+ glCopyImageSubData(tex, GL_TEXTURE_3D, 0, 0, 0, 0,
+ tex, GL_TEXTURE_3D, 0, 0, 0, i,
+ width, height, 1);
+ }
+ }
+ else {
+ /* load each slice with glTexSubImage3D */
+ for (i = 0; i < depth; i++) {
+ glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, i,
+ width, height, 1,
+ GL_RGBA, GL_UNSIGNED_BYTE, data);
+ }
}
free(data);
+ glClear(GL_COLOR_BUFFER_BIT);
+
/* Now try basic rendering. */
glEnable(GL_TEXTURE_3D);
glBegin(GL_QUADS);
- glTexCoord3f(0, 0, 1);
+ glTexCoord3f(0, 0, 0.5);
glVertex2f(0, 0);
- glTexCoord3f(0, 1, 1);
+ glTexCoord3f(0, 1, 0.5);
glVertex2f(0, piglit_height);
- glTexCoord3f(1, 1, 1);
+ glTexCoord3f(1, 1, 0.5);
glVertex2f(piglit_width, piglit_height);
- glTexCoord3f(1, 0, 1);
+ glTexCoord3f(1, 0, 0.5);
glVertex2f(piglit_width, 0);
glEnd();
- glDeleteTextures(1, &tex);
pass = piglit_probe_pixel_rgb(piglit_width * 1 / 4,
piglit_height * 1 / 4, c1) && pass;
@@ -187,17 +260,81 @@ piglit_display(void)
piglit_present_results();
if (!pass) {
- printf("%s: failed at size %d x %d x %d\n", TestName,
- width, height, depth);
+ printf("rendering failed with %d x %d x %d %s texture\n",
+ width, height, depth,
+ piglit_get_gl_enum_name(internalFormat));
+ }
+
+end:
+ glDeleteTextures(1, &tex);
+
+ return pass;
+}
+
+
+static bool
+test_3d_tex_format(GLenum internalFormat)
+{
+ GLint width, height, depth;
+ bool pass = true;
+ unsigned mbytes;
+
+ piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
+
+ /* use proxy texture to find actual max texture size */
+ width = height = depth = 0;
+ find_max_tex3d_size(internalFormat, MaxSize,
+ &width, &height, &depth);
+
+ mbytes = tex_size(internalFormat, width, height, depth);
+ printf("Actual max 3D texture size for %s: %d x %d x %d (%u MB)\n",
+ piglit_get_gl_enum_name(internalFormat),
+ width, height, depth, mbytes);
+
+ /* first, try some smaller res 3D texture rendering */
+ pass = test_render(internalFormat, width, height, depth/4);
+ pass = test_render(internalFormat, width, height, depth/2) && pass;
+
+ /* test largest 3D texture size */
+ pass = test_render(internalFormat, width, height, depth) && pass;
+
+ return pass;
+}
+
+
+enum piglit_result
+piglit_display(void)
+{
+ bool pass;
+
+ glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &MaxSize);
+ printf("GL_MAX_3D_TEXTURE_SIZE = %d\n", MaxSize);
+
+ pass = test_3d_tex_format(GL_INTENSITY8);
+
+ pass = test_3d_tex_format(GL_RGBA8) && pass;
+
+ if (piglit_is_extension_supported("GL_ARB_texture_float")) {
+ pass = test_3d_tex_format(GL_RGBA32F) && pass;
}
return pass ? PIGLIT_PASS : PIGLIT_FAIL;
}
+
void piglit_init(int argc, char **argv)
{
- piglit_require_gl_version(12);
-
glDisable(GL_DITHER);
-}
+ /* Set the tolerance a little looser since we're using GL_NEAREST
+ * texture sampling. GL_NEAREST is fastest for software rendering.
+ * We probably wouldn't have to loosen the tolerance if we used
+ * GL_LINEAR filtering.
+ */
+ piglit_set_tolerance_for_bits(7, 7, 7, 7);
+ printf("Probe tolerance: %f, %f, %f, %f\n",
+ piglit_tolerance[0],
+ piglit_tolerance[1],
+ piglit_tolerance[2],
+ piglit_tolerance[3]);
+}
--
1.9.1
More information about the Piglit
mailing list