diff options
author | Brian Paul <brianp@vmware.com> | 2016-07-13 14:02:11 -0600 |
---|---|---|
committer | Brian Paul <brianp@vmware.com> | 2016-07-26 09:26:39 -0600 |
commit | dcbe509ee2eff8578216487d0392524ba931e489 (patch) | |
tree | 23937b0b396106b52c6025eefd856e11762c71a8 /tests/texturing/tex3d-maxsize.c | |
parent | 3cdff435cdbafefd557d542f1b96feab3047fbf6 (diff) |
tex3d-maxsize: rewrite to be more robust and do more testing
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.
Reviewed-by: Alejandro PiƱeiro <apinheiro@igalia.com>
Diffstat (limited to 'tests/texturing/tex3d-maxsize.c')
-rw-r--r-- | tests/texturing/tex3d-maxsize.c | 285 |
1 files changed, 211 insertions, 74 deletions
diff --git a/tests/texturing/tex3d-maxsize.c b/tests/texturing/tex3d-maxsize.c index e168d1471..60c9c63a7 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]); +} |