[Piglit] [PATCH] Add test case to verify large textures are handled correctly in mesa

Anuj Phogat anuj.phogat at gmail.com
Thu Mar 15 12:20:57 PDT 2012


On Tue, Feb 28, 2012 at 12:26 PM, Anuj Phogat <anuj.phogat at gmail.com> wrote:

> This test tries to create the maximum supported texture using
> gltexImage1D/2D/3D functions and later modifies it using
> glTexSubImage1D/2D/3D functions.
>
> At the moment Intel driver throws GL_OUT_OF_MEMORY and an assertion
> failure / a segmentation fault with large textures.
>
> Test reproduces the errors reported in:
> https://bugs.freedesktop.org/show_bug.cgi?id=44970
> https://bugs.freedesktop.org/show_bug.cgi?id=46303
>
> Signed-off-by: Anuj Phogat <anuj.phogat at gmail.com>
> ---
> V3: Added the test using proxy textures, deleted redundant code,
>    data array allocation based on size returned
>
> V4: Continue testing with other formats if ARB_texture_float is not
> present.
>    Moved the test case to tests/texturing with an appropriate name.
>    Removed the loop which was testing with a number of large textures.
>    Added GL_OUT_OF_MEMORY as an expected error.
>    Added GL_TEXTURE_RECTANGLE in texture target array.
>
> ToDo: getMaxTarget, getProxyTarget and isValidTexSize functions can be
> added
>      as piglit utility functions in piglit-util-gl.c
>      I will do it in a separate patch.
>
>  tests/all.tests                    |    1 +
>  tests/texturing/CMakeLists.gl.txt  |    1 +
>  tests/texturing/max-texture-size.c |  460
> ++++++++++++++++++++++++++++++++++++
>  3 files changed, 462 insertions(+), 0 deletions(-)
>  create mode 100644 tests/texturing/max-texture-size.c
>
> diff --git a/tests/all.tests b/tests/all.tests
> index e4d56b8..ca15f5d 100644
> --- a/tests/all.tests
> +++ b/tests/all.tests
> @@ -679,6 +679,7 @@ add_plain_test(texturing, 'lodbias')
>  add_plain_test(texturing, 'lodclamp')
>  add_plain_test(texturing, 'lodclamp-between')
>  add_plain_test(texturing, 'lodclamp-between-max')
> +add_plain_test(texturing, 'max-texture-size')
>  add_plain_test(texturing, 'mipmap-setup')
>  add_plain_test(texturing, 'rg-draw-pixels')
>  add_plain_test(texturing, 'rg-teximage-01')
> diff --git a/tests/texturing/CMakeLists.gl.txt
> b/tests/texturing/CMakeLists.gl.txt
> index 6e12cc0..df44239 100644
> --- a/tests/texturing/CMakeLists.gl.txt
> +++ b/tests/texturing/CMakeLists.gl.txt
> @@ -38,6 +38,7 @@ add_executable (lodbias lodbias.c)
>  add_executable (lodclamp lodclamp.c)
>  add_executable (lodclamp-between lodclamp-between.c)
>  add_executable (lodclamp-between-max lodclamp-between-max.c)
> +add_executable (max-texture-size max-texture-size.c)
>  add_executable (mipmap-setup mipmap-setup.c)
>  add_executable (rg-draw-pixels rg-draw-pixels.c)
>  add_executable (rg-teximage-01 rg-teximage-01.c rg-teximage-common.c)
> diff --git a/tests/texturing/max-texture-size.c
> b/tests/texturing/max-texture-size.c
> new file mode 100644
> index 0000000..17ab06c
> --- /dev/null
> +++ b/tests/texturing/max-texture-size.c
> @@ -0,0 +1,460 @@
> +/* 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 max-texture-size.c
> + * Verify that large textures are handled properly in mesa driver.
> + *
> + * This test works by calling glTexImage1D/2D/3D and glTexSubImage1D/2D/3D
> + * functions with different texture targets. Each texture target is tested
> + * with maximum supported texture size.
> + * All the calls to glTexImage2D() and glTexSubImage2D() should ensure no
> + * segmentation fault / assertion failure in mesa driver.
> + *
> + * This test case reproduces the errors reported in:
> + * 1. https://bugs.freedesktop.org/show_bug.cgi?id=44970
> + *    Use GL_TEXTURE_2D and GL_RGBA16
> + *
> + * 2. https://bugs.freedesktop.org/show_bug.cgi?id=46303
> + *
> + * GL_OUT_OF_MEMORY is an expected GL error in this tesyt case.
> + *
> + * \Author Anuj Phogat <anuj.phogat at gmail.com>
> + */
> +
> +#include "piglit-util.h"
> +#define COLOR_COMPONENTS 4 /*GL_RGBA*/
> +
> +int piglit_width = 100, piglit_height = 100;
> +int piglit_window_mode = GLUT_RGBA | GLUT_DOUBLE;
> +
> +GLenum target[] = {
> +       GL_TEXTURE_1D,
> +       GL_TEXTURE_2D,
> +       GL_TEXTURE_RECTANGLE,
> +       GL_TEXTURE_CUBE_MAP,
> +       GL_TEXTURE_3D,
> +       };
> +
> +GLenum internalformat[] = {
> +       GL_RGBA8,
> +       GL_RGBA16,
> +       GL_RGBA32F,
> +       };
> +
> +static GLenum
> +getMaxTarget(GLenum target)
> +{
> +       switch(target) {
> +       case GL_TEXTURE_1D:
> +       case GL_TEXTURE_2D:
> +               return GL_MAX_TEXTURE_SIZE;
> +       case GL_TEXTURE_3D:
> +               return GL_MAX_3D_TEXTURE_SIZE;
> +       case GL_TEXTURE_CUBE_MAP_ARB:
> +               return GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB;
> +       case GL_TEXTURE_RECTANGLE:
> +               return GL_MAX_RECTANGLE_TEXTURE_SIZE;
> +       case GL_RENDERBUFFER_EXT:
> +               return GL_MAX_RENDERBUFFER_SIZE_EXT;
> +       default:
> +               printf ("Invalid texture target\n");
> +               return 0;
> +       }
> +}
> +
> +static GLenum
> +getProxyTarget(GLenum target)
> +{
> +       switch(target) {
> +       case GL_TEXTURE_1D:
> +               return GL_PROXY_TEXTURE_1D;
> +       case GL_TEXTURE_2D:
> +               return GL_PROXY_TEXTURE_2D;
> +       case GL_TEXTURE_3D:
> +               return GL_PROXY_TEXTURE_3D;
> +       case GL_TEXTURE_CUBE_MAP:
> +               return GL_PROXY_TEXTURE_CUBE_MAP;
> +       case GL_TEXTURE_RECTANGLE:
> +               return GL_PROXY_TEXTURE_RECTANGLE;
> +       default:
> +               printf ("No proxy target for this texture target\n");
> +               return 0;
> +       }
> +}
> +
> +static bool
> +isValidTexSize(GLenum target, GLenum internalFormat, int sideLength)
> +{
> +       GLint texWidth;
> +       GLenum proxyTarget = getProxyTarget(target);
> +
> +       switch(proxyTarget) {
> +       case GL_PROXY_TEXTURE_1D:
> +               glTexImage1D(proxyTarget, 0, internalFormat, sideLength, 0,
> +                            GL_RGBA, GL_FLOAT, 0);
> +               break;
> +       case GL_PROXY_TEXTURE_2D:
> +       case GL_PROXY_TEXTURE_RECTANGLE:
> +       case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
> +               glTexImage2D(proxyTarget, 0, internalFormat, sideLength,
> +                            sideLength, 0, GL_RGBA, GL_FLOAT, 0);
> +               break;
> +       case GL_PROXY_TEXTURE_3D:
> +               glTexImage3D(proxyTarget, 0, internalFormat, sideLength,
> +                            sideLength, sideLength, 0, GL_RGBA, GL_FLOAT,
> 0);
> +               break;
> +       default:
> +               printf ("Invalid  proxy texture target");
> +       }
> +
> +       glGetTexLevelParameteriv(proxyTarget, 0, GL_TEXTURE_WIDTH,
> &texWidth);
> +       return texWidth == sideLength;
> +}
> +
> +static GLfloat *
> +initTexData (GLenum target, int sideLength)
> +{
> +       uint64_t nPixels;
> +       if (target == GL_TEXTURE_1D)
> +               nPixels = (uint64_t)(sideLength);
> +       else if (target == GL_TEXTURE_2D ||
> +                target == GL_TEXTURE_RECTANGLE ||
> +                target == GL_TEXTURE_CUBE_MAP)
> +               nPixels = (uint64_t)(sideLength) *
> +                         (uint64_t)(sideLength);
> +       else if (target == GL_TEXTURE_3D)
> +               nPixels = (uint64_t)(sideLength) *
> +                         (uint64_t)(sideLength) *
> +                         (uint64_t)(sideLength);
> +
> +       /* Allocate sufficiently large data array and initialize to zero */
> +       return ((GLfloat *) calloc(nPixels * COLOR_COMPONENTS,
> sizeof(float)));
> +}
> +
> +static GLboolean
> +ValidateTexSize (GLenum target,  GLenum internalformat, bool useProxy)
> +{
> +       int maxSide, k;
> +       GLfloat *pixels = NULL;
> +       GLenum err = GL_NO_ERROR;
> +
> +       /* Query the largest supported texture size */
> +       glGetIntegerv(getMaxTarget(target), &maxSide);
> +
> +       if (!useProxy) {
> +               printf("%s, Internal Format = %s, Largest Texture Size ="
> +                      " %d\n", piglit_get_gl_enum_name(target),
> +                      piglit_get_gl_enum_name(internalformat),
> +                      maxSide);
> +               /* Allocate and initialize texture data array */
> +               pixels = initTexData(target, maxSide);
> +
> +               if ( pixels == NULL) {
> +                       printf("Error allocating texture data array\n");
> +                       piglit_report_result(PIGLIT_SKIP);
> +               }
> +       }
> +       else {
> +               /* Compute largest supported texture size using proxy
> textures */
> +               while(isValidTexSize(target, internalformat, maxSide))
> +                       maxSide *= 2;
> +               /* First unsupported size */
> +               while(!isValidTexSize(target, internalformat, maxSide))
> +                       maxSide /= 2;
> +               while(isValidTexSize(target, internalformat, maxSide))
> +                       maxSide += 1;
> +               /* Last supported texture size */
> +               maxSide -= 1;
> +               printf("%s, Internal Format = %s, Largest Texture Size ="
> +                      " %d\n",
> piglit_get_gl_enum_name(getProxyTarget(target)),
> +                      piglit_get_gl_enum_name(internalformat),
> +                      maxSide);
> +       }
> +
> +       switch (target) {
> +       case GL_TEXTURE_1D:
> +               //printf("Width = %d, Height = 1, Depth =  1\n", maxSide);
> +               if (!useProxy) {
> +                       glTexImage1D(target, 0, internalformat, maxSide,
> +                                    0, GL_RGBA, GL_FLOAT, NULL);
> +
> +                       err = glGetError();
> +                       /* Report a GL error other than GL_OUT_OF_MEMORY */
> +                       if (err != GL_NO_ERROR && err != GL_OUT_OF_MEMORY)
> {
> +                               free(pixels);
> +                               printf("Unexpected GL error: 0x%x\n", err);
> +                               return false;
> +                       }
> +
> +                       glTexSubImage1D(target, 0, 0, maxSide/2, GL_RGBA,
> +                                       GL_FLOAT, pixels);
> +
> +                       err = glGetError();
> +                       /* Report a GL error other than GL_OUT_OF_MEMORY */
> +                       if (err != GL_NO_ERROR && err != GL_OUT_OF_MEMORY)
> {
> +                               free(pixels);
> +                               printf("Unexpected GL error: 0x%x\n", err);
> +                               return false;
> +                       }
> +               }
> +               else {
> +                       glTexImage1D(GL_PROXY_TEXTURE_1D, 0,
> internalformat,
> +                                    maxSide, 0, GL_RGBA, GL_FLOAT, NULL);
> +
> +                       err = glGetError();
> +                       /* Report a GL error other than GL_OUT_OF_MEMORY */
> +                       if (err != GL_NO_ERROR && err != GL_OUT_OF_MEMORY)
> {
> +                               printf("Unexpected GL error: 0x%x\n", err);
> +                               return false;
> +                       }
> +               }
> +               break;
> +
> +       case GL_TEXTURE_2D:
> +               //printf("Width = %d, Height = %d, Depth =  1\n", maxSide,
> +               //       maxSide);
> +               if(!useProxy) {
> +                       glTexImage2D(target, 0, internalformat, maxSide,
> +                                    maxSide, 0, GL_RGBA, GL_FLOAT, NULL);
> +
> +                       err = glGetError();
> +                       /* Report a GL error other than GL_OUT_OF_MEMORY */
> +                       if (err != GL_NO_ERROR && err != GL_OUT_OF_MEMORY)
> {
> +                               free(pixels);
> +                               printf("Unexpected GL error: 0x%x\n", err);
> +                               return false;
> +                       }
> +
> +                       glTexSubImage2D(target, 0, 0, 0, maxSide/2,
> maxSide/2,
> +                                       GL_RGBA, GL_FLOAT, pixels);
> +
> +                       err = glGetError();
> +                       /* Report a GL error other than GL_OUT_OF_MEMORY */
> +                       if (err != GL_NO_ERROR && err != GL_OUT_OF_MEMORY)
> {
> +                               free(pixels);
> +                               printf("Unexpected GL error: 0x%x\n", err);
> +                               return false;
> +                       }
> +               }
> +
> +               else {
> +                       glTexImage2D(GL_PROXY_TEXTURE_2D, 0,
> internalformat,
> +                                    maxSide, maxSide, 0, GL_RGBA,
> GL_FLOAT,
> +                                    NULL);
> +
> +                       err = glGetError();
> +                       /* Report a GL error other than GL_OUT_OF_MEMORY */
> +                       if (err != GL_NO_ERROR && err != GL_OUT_OF_MEMORY)
> {
> +                               printf("Unexpected GL error: 0x%x\n", err);
> +                               return false;
> +                       }
> +               }
> +               break;
> +
> +       case GL_TEXTURE_RECTANGLE:
> +               glTexImage2D(target, 0, internalformat, maxSide,
> +                            maxSide, 0, GL_RGBA, GL_FLOAT, NULL);
> +
> +               err = glGetError();
> +               /* Report a GL error other than GL_OUT_OF_MEMORY */
> +               if (err != GL_NO_ERROR && err != GL_OUT_OF_MEMORY) {
> +                       printf("Unexpected GL error: 0x%x\n", err);
> +                       return false;
> +               }
> +               break;
> +
> +       case GL_TEXTURE_3D:
> +               //printf("Width = %d, Height = %d, Depth =  %d\n", maxSide,
> +               //       maxSide, maxSide);
> +               if(!useProxy) {
> +                       glTexImage3D(target, 0, internalformat, maxSide,
> +                                    maxSide, maxSide, 0, GL_RGBA,
> GL_FLOAT,
> +                                    NULL);
> +
> +                       err = glGetError();
> +                       /* Report a GL error other than GL_OUT_OF_MEMORY */
> +                       if (err != GL_NO_ERROR && err != GL_OUT_OF_MEMORY)
> {
> +                               printf("Unexpected GL error: 0x%x\n", err);
> +                               free(pixels);
> +                               return false;
> +                       }
> +
> +                       glTexSubImage3D(target, 0, 0, 0, 0, maxSide/2,
> +                                       maxSide/2, maxSide/2, GL_RGBA,
> +                                       GL_FLOAT, pixels);
> +                       err = glGetError();
> +                       /* Report a GL error other than GL_OUT_OF_MEMORY */
> +                       if (err != GL_NO_ERROR && err != GL_OUT_OF_MEMORY)
> {
> +                               free(pixels);
> +                               printf("Unexpected GL error: 0x%x\n", err);
> +                               return false;
> +                       }
> +               }
> +               else {
> +                       glTexImage3D(GL_PROXY_TEXTURE_3D, 0,
> internalformat,
> +                                    maxSide, maxSide, maxSide, 0, GL_RGBA,
> +                                    GL_FLOAT, NULL);
> +
> +                       err = glGetError();
> +                       if (err == GL_OUT_OF_MEMORY)
> +                               return true;
> +
> +                       /* Report a GL error other than GL_OUT_OF_MEMORY */
> +                       if (err != GL_NO_ERROR) {
> +                               printf("Unexpected GL error: 0x%x\n", err);
> +                               return false;
> +                       }
> +               }
> +               break;
> +
> +       case GL_TEXTURE_CUBE_MAP_ARB:
> +               //printf("Width = %d, Height = %d, Depth =  1\n", maxSide,
> +               //       maxSide);
> +               if (!useProxy) {
> +                       for (k = 0; k < 6; k++) {
> +                               glTexImage2D(
> +                               GL_TEXTURE_CUBE_MAP_POSITIVE_X + k,
> +                               0, internalformat, maxSide, maxSide, 0,
> +                               GL_RGBA, GL_FLOAT, NULL);
> +
> +                               err = glGetError();
> +                               /* Report a GL error other than
> GL_OUT_OF_MEMORY */
> +                               if (err != GL_NO_ERROR && err !=
> GL_OUT_OF_MEMORY) {
> +                                       printf("Unexpected GL error:
> 0x%x\n", err);
> +                                       free(pixels);
> +                                       return false;
> +                               }
> +                       }
> +
> +                       for (k = 0; k < 6; k++) {
> +                               glTexSubImage2D(
> +                               GL_TEXTURE_CUBE_MAP_POSITIVE_X + k,
> +                               0, 0, 0, maxSide/2, maxSide/2, GL_RGBA,
> +                               GL_FLOAT, pixels);
> +
> +                               err = glGetError();
> +                               if (err == GL_OUT_OF_MEMORY) {
> +                                       free(pixels);
> +                                       return true;
> +                               }
> +
> +                               /* Report a GL error other than
> GL_OUT_OF_MEMORY */
> +                               if (err != GL_NO_ERROR && err !=
> GL_OUT_OF_MEMORY) {
> +                                       printf("Unexpected GL error:
> 0x%x\n", err);
> +                                       free(pixels);
> +                                       return false;
> +                               }
> +                       }
> +               }
> +               else {
> +                       glTexImage2D(GL_PROXY_TEXTURE_CUBE_MAP, 0,
> +                       internalformat, maxSide, maxSide, 0,
> +                       GL_RGBA, GL_FLOAT, NULL);
> +
> +                       err = glGetError();
> +                       /* Report a GL error other than GL_OUT_OF_MEMORY */
> +                       if (err != GL_NO_ERROR && err != GL_OUT_OF_MEMORY)
> {
> +                               printf("Unexpected GL error: 0x%x\n", err);
> +                               return false;
> +                       }
> +               }
> +               break;
> +       }
> +       if (pixels)
> +               free(pixels);
> +       /* If execution reaches this point, return true */
> +       return true;
> +}
> +
> +void
> +piglit_init(int argc, char **argv)
> +{
> +       GLuint tex;
> +       GLboolean pass = true;
> +       int i, j;
> +
> +       glMatrixMode(GL_PROJECTION);
> +       glPushMatrix();
> +       glLoadIdentity();
> +       glOrtho(0, piglit_width, 0, piglit_height, -1, 1);
> +       glMatrixMode(GL_MODELVIEW);
> +       glPushMatrix();
> +       glLoadIdentity();
> +       glClearColor(0.2, 0.2, 0.2, 1.0);
> +       glClear(GL_COLOR_BUFFER_BIT);
> +
> +       for ( i = 0; i < ARRAY_SIZE(target); i++) {
> +
> +               glGenTextures(1, &tex);
> +               glBindTexture(target[i], tex);
> +               glTexParameteri(target[i], GL_TEXTURE_MIN_FILTER,
> GL_NEAREST);
> +               glTexParameteri(target[i], GL_TEXTURE_MAG_FILTER,
> GL_NEAREST);
> +
> +               for (j = 0; j < ARRAY_SIZE(internalformat); j++) {
> +                       /* Skip floating point formats if
> GL_ARB_texture_float
> +                        * is not supported
> +                        */
> +                       if ((internalformat[j] == GL_RGBA16F ||
> +                           internalformat[j] == GL_RGBA32F) &&
> +                           !piglit_is_extension_supported(
> +                           "GL_ARB_texture_float"))
> +                               continue;
> +                       /* Test using proxy textures */
> +                        pass = ValidateTexSize (target[i],
>  internalformat[j], true)
> +                               && pass;
> +               }
> +               glDeleteTextures(1, &tex);
> +       }
> +
> +       printf("\n");
> +
> +       for ( i = 0; i < ARRAY_SIZE(target); i++) {
> +
> +               glGenTextures(1, &tex);
> +               glBindTexture(target[i], tex);
> +               glTexParameteri(target[i], GL_TEXTURE_MIN_FILTER,
> GL_NEAREST);
> +               glTexParameteri(target[i], GL_TEXTURE_MAG_FILTER,
> GL_NEAREST);
> +
> +               for (j = 0; j < ARRAY_SIZE(internalformat); j++) {
> +
> +                       if (internalformat[j] == GL_RGBA16F ||
> +                           internalformat[j] == GL_RGBA32F)
> +
> piglit_require_extension("GL_ARB_texture_float");
> +
> +                       /* Test with out proxy textures*/
> +                       pass = ValidateTexSize (target[i],
>  internalformat[j], false)
> +                              && pass;
> +               }
> +       }
> +
> +       printf("\n");
> +
> +       piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
> +}
> +
> +enum
> +piglit_result
> +piglit_display(void)
> +{
> +       return PIGLIT_FAIL;
> +}
> --
> 1.7.7.6
>
> Brian, does this test still takes long time to finish on nvidia? I 'll
push it if there are no pending issues.

Thanks
Anuj
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/piglit/attachments/20120315/4542f6a3/attachment-0001.html>


More information about the Piglit mailing list