On 07/20/2016 02:45 AM, Alejandro Piñeiro wrote:
On 13/07/16 23:47, Brian Paul wrote:
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.

I just tested with intel i965 Haswell, and it also works fine. Looks
good to me, but I have a small question below.

---
  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);

Any reason to change the texcoords?

Not especially. I wanted to sample from the center slice of the texture to make sure it was filled in correctly. But r=1 should accomplish that too.

R-b?

-Brian


        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]);
+}


_______________________________________________
Piglit mailing list
Piglit@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/piglit


_______________________________________________
Piglit mailing list
Piglit@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/piglit

Reply via email to