[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