meta: Support GenerateMipmaps on 2DArray textures.
authorKenneth Graunke <kenneth@whitecape.org>
Thu, 6 Mar 2014 05:02:06 +0000 (21:02 -0800)
committerKenneth Graunke <kenneth@whitecape.org>
Sat, 8 Mar 2014 06:45:17 +0000 (22:45 -0800)
This is largely a matter of looping over the number of slices/layers,
and not minifying depth (presumably that code exists for the unfinished
3D texture support).

Normally, I would have made the loop over array slices the outermost
loop.  I suspect that would make it trickier to support 3D textures
someday, though, so I didn't.  The advantage is that we would only have
one BufferData call per slice, rather than one per miplevel and slice.

However, a GenerateMipmaps microbenchmark indicates that either way is
basically just as fast.  So I'm not sure it's worth bothering.

Improves performance in a GenerateMipmaps microbenchmark by nearly 5x.

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Matt Turner <mattst88@gmail.com>
Reviewed-by: Anuj Phogat <anuj.phogat@gmail.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
src/mesa/drivers/common/meta_generate_mipmap.c

index 6ca6f228976d47965096adea6e2efda1acf95f07..d9535d99ace4cc3cfcb579bcbfddf5e8d9554506 100644 (file)
@@ -94,9 +94,7 @@ fallback_required(struct gl_context *ctx, GLenum target,
    GLenum status;
 
    /* check for fallbacks */
-   if (target == GL_TEXTURE_3D ||
-       target == GL_TEXTURE_1D_ARRAY ||
-       target == GL_TEXTURE_2D_ARRAY) {
+   if (target == GL_TEXTURE_3D || target == GL_TEXTURE_1D_ARRAY) {
       _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
                        "glGenerateMipmap() to %s target\n",
                        _mesa_lookup_enum_by_nr(target));
@@ -186,7 +184,6 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
                                       ctx->Extensions.ARB_fragment_shader;
    GLenum faceTarget;
    GLuint dstLevel;
-   const GLint slice = 0;
    GLuint samplerSave;
 
    if (fallback_required(ctx, target, texObj)) {
@@ -254,15 +251,6 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
    /* Silence valgrind warnings about reading uninitialized stack. */
    memset(verts, 0, sizeof(verts));
 
-   /* Setup texture coordinates */
-   _mesa_meta_setup_texture_coords(faceTarget,
-                                   slice,
-                                   0, 0, 1, /* width, height never used here */
-                                   verts[0].tex,
-                                   verts[1].tex,
-                                   verts[2].tex,
-                                   verts[3].tex);
-
    /* setup vertex positions */
    verts[0].x = -1.0F;
    verts[0].y = -1.0F;
@@ -273,16 +261,13 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
    verts[3].x = -1.0F;
    verts[3].y =  1.0F;
 
-   /* upload vertex data */
-   _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts),
-                       verts, GL_DYNAMIC_DRAW_ARB);
-
    /* texture is already locked, unlock now */
    _mesa_unlock_texture(ctx, texObj);
 
    for (dstLevel = baseLevel + 1; dstLevel <= maxLevel; dstLevel++) {
       const struct gl_texture_image *srcImage;
       const GLuint srcLevel = dstLevel - 1;
+      GLuint layer;
       GLsizei srcWidth, srcHeight, srcDepth;
       GLsizei dstWidth, dstHeight, dstDepth;
 
@@ -297,7 +282,7 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
       /* new dst size */
       dstWidth = minify(srcWidth, 1);
       dstHeight = minify(srcHeight, 1);
-      dstDepth = minify(srcDepth, 1);
+      dstDepth = target == GL_TEXTURE_3D ? minify(srcDepth, 1) : srcDepth;
 
       if (dstWidth == srcImage->Width &&
           dstHeight == srcImage->Height &&
@@ -325,25 +310,39 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
       /* limit minification to src level */
       _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel);
 
-      bind_fbo_image(texObj, faceTarget, dstLevel, 0);
-
-      _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
-
-      /* sanity check */
-      if (_mesa_CheckFramebufferStatus(GL_FRAMEBUFFER) !=
-          GL_FRAMEBUFFER_COMPLETE) {
-         _mesa_problem(ctx, "Unexpected incomplete framebuffer in "
-                       "_mesa_meta_GenerateMipmap()");
-         break;
-      }
-
-      assert(dstWidth == ctx->DrawBuffer->Width);
-      assert(dstHeight == ctx->DrawBuffer->Height);
-
       /* setup viewport */
       _mesa_set_viewport(ctx, 0, 0, 0, dstWidth, dstHeight);
-
-      _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+      _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0);
+
+      for (layer = 0; layer < dstDepth; ++layer) {
+         /* Setup texture coordinates */
+         _mesa_meta_setup_texture_coords(faceTarget,
+                                         layer,
+                                         0, 0, 1, /* width, height never used here */
+                                         verts[0].tex,
+                                         verts[1].tex,
+                                         verts[2].tex,
+                                         verts[3].tex);
+
+         /* upload vertex data */
+         _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts),
+                          verts, GL_DYNAMIC_DRAW_ARB);
+
+         bind_fbo_image(texObj, faceTarget, dstLevel, layer);
+
+         /* sanity check */
+         if (_mesa_CheckFramebufferStatus(GL_FRAMEBUFFER) !=
+             GL_FRAMEBUFFER_COMPLETE) {
+            _mesa_problem(ctx, "Unexpected incomplete framebuffer in "
+                          "_mesa_meta_GenerateMipmap()");
+            break;
+         }
+
+         assert(dstWidth == ctx->DrawBuffer->Width);
+         assert(dstHeight == ctx->DrawBuffer->Height);
+
+         _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+      }
    }
 
    _mesa_lock_texture(ctx, texObj); /* relock */