[Mesa-dev] [PATCH 09/11] meta: Support GenerateMipmaps on 2DArray textures.

Ian Romanick idr at freedesktop.org
Fri Mar 7 01:24:51 PST 2014


On 03/06/2014 12:47 PM, Kenneth Graunke wrote:
> 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.

A future todo (maybe a NewbieProject?) is to do this in one pass using
GL_AMD_vertex_shader_layer + instanced rendering.

> Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
> ---
>  src/mesa/drivers/common/meta_generate_mipmap.c | 69 +++++++++++++-------------
>  1 file changed, 34 insertions(+), 35 deletions(-)
> 
> diff --git a/src/mesa/drivers/common/meta_generate_mipmap.c b/src/mesa/drivers/common/meta_generate_mipmap.c
> index 6ca6f22..d9535d9 100644
> --- a/src/mesa/drivers/common/meta_generate_mipmap.c
> +++ b/src/mesa/drivers/common/meta_generate_mipmap.c
> @@ -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 */



More information about the mesa-dev mailing list