From: Topi Pohjolainen Date: Tue, 15 Nov 2016 20:27:12 +0000 (+0200) Subject: i965/miptree: Don't shrink textures when augmenting for more levels X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ca84e190a446bbc29c3ef2864ba4ea5c7358a89a;p=mesa.git i965/miptree: Don't shrink textures when augmenting for more levels This was detected when examining CCS_E failures with piglit test: "fbo-generatemipmap-formats". Test creates a 2D texture with dimensions 293x277. It manually loops over all levels and calls glTexImage2D(). Level one triggers creation of full miptree: intel_alloc_texture_image_buffer() realizes that there is only one level in the miptree and calls intel_miptree_create_for_teximage() to re-allocate the miptree with all 9 levels. However, the end result is a miptree with level zero dimensions of 292x276. Related, and possibly calling for treatment of its own is mip-map generation: After calling glTexImage2D() against every level test continues by replacing content for levels one to eight with data derived from level zero by calling glGenerateMipmapEXT(). This results into the miptree being allocated anew for every level: Mip-map generation goes thru meta which ends up validating the texture (brw_validate_textures()->intel_finalize_mipmap_tree()-> intel_miptree_match_image()) where one finds texture with base level size 292:276. This results into new miptree being created for the npot size 293:277. Only here intel_finalize_mipmap_tree() is asked for only one level, and therefore such is created. Generation for level one in turn finds right base level size but only one level when two is needed. And the same goes on for all eight levels. This patch prevents the shrink maintaining the NPOT size of 293x277. Signed-off-by: Topi Pohjolainen Reviewed-by: Jason Ekstrand --- diff --git a/src/mesa/drivers/dri/i965/intel_tex_image.c b/src/mesa/drivers/dri/i965/intel_tex_image.c index 4454e53916a..cbff58a6a84 100644 --- a/src/mesa/drivers/dri/i965/intel_tex_image.c +++ b/src/mesa/drivers/dri/i965/intel_tex_image.c @@ -29,6 +29,22 @@ #define FILE_DEBUG_FLAG DEBUG_TEXTURE +/* Make sure one doesn't end up shrinking base level zero unnecessarily. + * Determining the base level dimension by shifting higher level dimension + * ends up in off-by-one value in case base level has NPOT size (for example, + * 293 != 146 << 1). + * Choose the original base level dimension when shifted dimensions agree. + * Otherwise assume real resize is intended and use the new shifted value. + */ +static unsigned +get_base_dim(unsigned old_base_dim, unsigned new_level_dim, unsigned level) +{ + const unsigned old_level_dim = old_base_dim >> level; + const unsigned new_base_dim = new_level_dim << level; + + return old_level_dim == new_level_dim ? old_base_dim : new_base_dim; +} + /* Work back from the specified level of the image to the baselevel and create a * miptree of that size. */ @@ -40,6 +56,8 @@ intel_miptree_create_for_teximage(struct brw_context *brw, { GLuint lastLevel; int width, height, depth; + const struct intel_mipmap_tree *old_mt = intelObj->mt; + const unsigned level = intelImage->base.Base.Level; intel_get_image_dims(&intelImage->base.Base, &width, &height, &depth); @@ -51,20 +69,23 @@ intel_miptree_create_for_teximage(struct brw_context *brw, case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: case GL_TEXTURE_RECTANGLE: case GL_TEXTURE_EXTERNAL_OES: - assert(intelImage->base.Base.Level == 0); + assert(level == 0); break; case GL_TEXTURE_3D: - depth <<= intelImage->base.Base.Level; + depth = old_mt ? get_base_dim(old_mt->logical_depth0, depth, level) : + depth << level; /* Fall through */ case GL_TEXTURE_2D: case GL_TEXTURE_2D_ARRAY: case GL_TEXTURE_CUBE_MAP: case GL_TEXTURE_CUBE_MAP_ARRAY: - height <<= intelImage->base.Base.Level; + height = old_mt ? get_base_dim(old_mt->logical_height0, height, level) : + height << level; /* Fall through */ case GL_TEXTURE_1D: case GL_TEXTURE_1D_ARRAY: - width <<= intelImage->base.Base.Level; + width = old_mt ? get_base_dim(old_mt->logical_width0, width, level) : + width << level; break; default: unreachable("Unexpected target");