From 5b3eb7538cd9ceb967b6e9e765896183e7c2c4d4 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 10 Jan 2011 10:01:12 -0800 Subject: [PATCH] Revert "intel: Always allocate miptrees from level 0, not tObj->BaseLevel." This reverts commit 7ce6517f3ac41bf770ab39aba4509d4f535ef663. This reverts commit d60145d06d999c5c76000499e6fa9351e11d17fa. I was wrong about which generations supported baselevel adjustment -- it's just gen4, nothing earlier. This meant that i915 would have never used the mag filter when baselevel != 0. Not a severe bug, but not an intentional regression. I think we can fix the performance issue another way. --- src/mesa/drivers/dri/i915/i915_tex_layout.c | 22 +-- src/mesa/drivers/dri/i965/brw_tex_layout.c | 4 +- .../drivers/dri/i965/brw_wm_sampler_state.c | 11 +- .../drivers/dri/i965/brw_wm_surface_state.c | 10 +- .../drivers/dri/intel/intel_mipmap_tree.c | 17 ++- .../drivers/dri/intel/intel_mipmap_tree.h | 6 +- src/mesa/drivers/dri/intel/intel_tex.h | 6 - src/mesa/drivers/dri/intel/intel_tex_image.c | 125 +++++++++++++----- src/mesa/drivers/dri/intel/intel_tex_layout.c | 6 +- .../drivers/dri/intel/intel_tex_validate.c | 27 ++-- 10 files changed, 152 insertions(+), 82 deletions(-) diff --git a/src/mesa/drivers/dri/i915/i915_tex_layout.c b/src/mesa/drivers/dri/i915/i915_tex_layout.c index f3a9fd4828d..6e4512129cd 100644 --- a/src/mesa/drivers/dri/i915/i915_tex_layout.c +++ b/src/mesa/drivers/dri/i915/i915_tex_layout.c @@ -127,7 +127,7 @@ i915_miptree_layout_cube(struct intel_context *intel, mt->total_width = dim * 2; mt->total_height = dim * 4; - for (level = 0; level < mt->levels; level++) { + for (level = mt->first_level; level <= mt->last_level; level++) { intel_miptree_set_level_info(mt, level, 6, 0, 0, lvlWidth, lvlHeight, @@ -141,12 +141,12 @@ i915_miptree_layout_cube(struct intel_context *intel, GLuint y = initial_offsets[face][1] * dim; GLuint d = dim; - for (level = 0; level < mt->levels; level++) { + for (level = mt->first_level; level <= mt->last_level; level++) { intel_miptree_set_image_offset(mt, level, face, x, y); if (d == 0) - printf("cube mipmap %d/%d (%d) is 0x0\n", - face, level, mt->levels); + printf("cube mipmap %d/%d (%d..%d) is 0x0\n", + face, level, mt->first_level, mt->last_level); d >>= 1; x += step_offsets[face][0] * d; @@ -170,7 +170,7 @@ i915_miptree_layout_3d(struct intel_context *intel, mt->total_width = mt->width0; /* XXX: hardware expects/requires 9 levels at minimum. */ - for (level = 0; level < MAX2(9, mt->levels); level++) { + for (level = mt->first_level; level <= MAX2(8, mt->last_level); level++) { intel_miptree_set_level_info(mt, level, depth, 0, mt->total_height, width, height, depth); @@ -183,7 +183,7 @@ i915_miptree_layout_3d(struct intel_context *intel, /* Fixup depth image_offsets: */ depth = mt->depth0; - for (level = 0; level < mt->levels; level++) { + for (level = mt->first_level; level <= mt->last_level; level++) { GLuint i; for (i = 0; i < depth; i++) { intel_miptree_set_image_offset(mt, level, i, @@ -213,7 +213,7 @@ i915_miptree_layout_2d(struct intel_context *intel, mt->total_width = mt->width0; mt->total_height = 0; - for (level = 0; level < mt->levels; level++) { + for (level = mt->first_level; level <= mt->last_level; level++) { intel_miptree_set_level_info(mt, level, 1, 0, mt->total_height, width, height, 1); @@ -345,7 +345,7 @@ i945_miptree_layout_cube(struct intel_context *intel, mt->total_height = 4; /* Set all the levels to effectively occupy the whole rectangular region. */ - for (level = 0; level < mt->levels; level++) { + for (level = mt->first_level; level <= mt->last_level; level++) { intel_miptree_set_level_info(mt, level, 6, 0, 0, lvlWidth, lvlHeight, 1); @@ -361,12 +361,12 @@ i945_miptree_layout_cube(struct intel_context *intel, if (dim == 4 && face >= 4) { y = mt->total_height - 4; x = (face - 4) * 8; - } else if (dim < 4 && face > 0) { + } else if (dim < 4 && (face > 0 || mt->first_level > 0)) { y = mt->total_height - 4; x = face * 8; } - for (level = 0; level < mt->levels; level++) { + for (level = mt->first_level; level <= mt->last_level; level++) { intel_miptree_set_image_offset(mt, level, face, x, y); d >>= 1; @@ -429,7 +429,7 @@ i945_miptree_layout_3d(struct intel_context *intel, pack_x_pitch = mt->total_width; pack_x_nr = 1; - for (level = 0; level < mt->levels; level++) { + for (level = mt->first_level; level <= mt->last_level; level++) { GLint x = 0; GLint y = 0; GLint q, j; diff --git a/src/mesa/drivers/dri/i965/brw_tex_layout.c b/src/mesa/drivers/dri/i965/brw_tex_layout.c index 66adc49cc94..9ac0713a1d3 100644 --- a/src/mesa/drivers/dri/i965/brw_tex_layout.c +++ b/src/mesa/drivers/dri/i965/brw_tex_layout.c @@ -67,7 +67,7 @@ GLboolean brw_miptree_layout(struct intel_context *intel, i945_miptree_layout_2d(intel, mt, tiling, 6); - for (level = 0; level < mt->levels; level++) { + for (level = mt->first_level; level <= mt->last_level; level++) { for (q = 0; q < 6; q++) { intel_miptree_set_image_offset(mt, level, q, 0, q * qpitch); } @@ -101,7 +101,7 @@ GLboolean brw_miptree_layout(struct intel_context *intel, pack_x_pitch = width; pack_x_nr = 1; - for (level = 0; level < mt->levels; level++) { + for (level = mt->first_level ; level <= mt->last_level ; level++) { GLuint nr_images = mt->target == GL_TEXTURE_3D ? depth : 6; GLint x = 0; GLint y = 0; diff --git a/src/mesa/drivers/dri/i965/brw_wm_sampler_state.c b/src/mesa/drivers/dri/i965/brw_wm_sampler_state.c index f830e256268..30672b4251b 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_sampler_state.c +++ b/src/mesa/drivers/dri/i965/brw_wm_sampler_state.c @@ -115,7 +115,6 @@ struct wm_sampler_key { struct wm_sampler_entry { GLenum tex_target; GLenum wrap_r, wrap_s, wrap_t; - uint32_t base_level; float maxlod, minlod; float lod_bias; float max_aniso; @@ -244,7 +243,14 @@ static void brw_update_sampler_state(struct brw_context *brw, sampler->ss0.lod_preclamp = 1; /* OpenGL mode */ sampler->ss0.default_color_mode = 0; /* OpenGL/DX10 mode */ - sampler->ss0.base_level = U_FIXED(key->base_level, 1); + /* Set BaseMipLevel, MaxLOD, MinLOD: + * + * XXX: I don't think that using firstLevel, lastLevel works, + * because we always setup the surface state as if firstLevel == + * level zero. Probably have to subtract firstLevel from each of + * these: + */ + sampler->ss0.base_level = U_FIXED(0, 1); sampler->ss1.max_lod = U_FIXED(CLAMP(key->maxlod, 0, 13), 6); sampler->ss1.min_lod = U_FIXED(CLAMP(key->minlod, 0, 13), 6); @@ -286,7 +292,6 @@ brw_wm_sampler_populate_key(struct brw_context *brw, entry->wrap_s = texObj->WrapS; entry->wrap_t = texObj->WrapT; - entry->base_level = texObj->BaseLevel; entry->maxlod = texObj->MaxLod; entry->minlod = texObj->MinLod; entry->lod_bias = texUnit->LodBias + texObj->LodBias; diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c index 4570af66cd9..e921d8a9a1d 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c +++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c @@ -196,15 +196,15 @@ brw_update_texture_surface( struct gl_context *ctx, GLuint unit ) /* surf.ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */ surf.ss1.base_addr = intelObj->mt->region->buffer->offset; /* reloc */ - /* mip_count is #levels - 1 */ surf.ss2.mip_count = intelObj->_MaxLevel - tObj->BaseLevel; - surf.ss2.width = intelObj->mt->width0 - 1; - surf.ss2.height = intelObj->mt->height0 - 1; + surf.ss2.width = firstImage->Width - 1; + surf.ss2.height = firstImage->Height - 1; brw_set_surface_tiling(&surf, intelObj->mt->region->tiling); surf.ss3.pitch = (intelObj->mt->region->pitch * intelObj->mt->cpp) - 1; - surf.ss3.depth = intelObj->mt->depth0 - 1; - surf.ss4.min_lod = tObj->BaseLevel; + surf.ss3.depth = firstImage->Depth - 1; + surf.ss4.min_lod = 0; + if (tObj->Target == GL_TEXTURE_CUBE_MAP) { surf.ss0.cube_pos_x = 1; surf.ss0.cube_pos_y = 1; diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index 2ced6ac86b2..a3409274fb7 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -56,7 +56,8 @@ static struct intel_mipmap_tree * intel_miptree_create_internal(struct intel_context *intel, GLenum target, GLenum internal_format, - GLuint levels, + GLuint first_level, + GLuint last_level, GLuint width0, GLuint height0, GLuint depth0, GLuint cpp, GLuint compress_byte, @@ -65,14 +66,15 @@ intel_miptree_create_internal(struct intel_context *intel, GLboolean ok; struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1); - DBG("%s target %s format %s levels %d <-- %p\n", __FUNCTION__, + DBG("%s target %s format %s level %d..%d <-- %p\n", __FUNCTION__, _mesa_lookup_enum_by_nr(target), _mesa_lookup_enum_by_nr(internal_format), - levels, mt); + first_level, last_level, mt); mt->target = target_to_target(target); mt->internal_format = internal_format; - mt->levels = levels; + mt->first_level = first_level; + mt->last_level = last_level; mt->width0 = width0; mt->height0 = height0; mt->depth0 = depth0; @@ -104,7 +106,8 @@ intel_miptree_create(struct intel_context *intel, GLenum target, GLenum base_format, GLenum internal_format, - GLuint levels, + GLuint first_level, + GLuint last_level, GLuint width0, GLuint height0, GLuint depth0, GLuint cpp, GLuint compress_byte, @@ -123,7 +126,7 @@ intel_miptree_create(struct intel_context *intel, } mt = intel_miptree_create_internal(intel, target, internal_format, - levels, width0, + first_level, last_level, width0, height0, depth0, cpp, compress_byte, tiling); /* @@ -161,7 +164,7 @@ intel_miptree_create_for_region(struct intel_context *intel, struct intel_mipmap_tree *mt; mt = intel_miptree_create_internal(intel, target, internal_format, - 1, + 0, 0, region->width, region->height, 1, region->cpp, compress_byte, I915_TILING_NONE); diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h index 4bb90bf4ac6..760a8bce601 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h @@ -93,7 +93,8 @@ struct intel_mipmap_tree GLenum target; GLenum internal_format; - GLuint levels; + GLuint first_level; + GLuint last_level; GLuint width0, height0, depth0; /**< Level zero image dimensions */ GLuint cpp; @@ -123,7 +124,8 @@ struct intel_mipmap_tree *intel_miptree_create(struct intel_context *intel, GLenum target, GLenum base_format, GLenum internal_format, - GLuint levels, + GLuint first_level, + GLuint last_level, GLuint width0, GLuint height0, GLuint depth0, diff --git a/src/mesa/drivers/dri/intel/intel_tex.h b/src/mesa/drivers/dri/intel/intel_tex.h index 7c76bd48c60..6552ed0d332 100644 --- a/src/mesa/drivers/dri/intel/intel_tex.h +++ b/src/mesa/drivers/dri/intel/intel_tex.h @@ -65,10 +65,4 @@ void intel_tex_unmap_images(struct intel_context *intel, int intel_compressed_num_bytes(GLuint mesaFormat); -struct intel_mipmap_tree * -intel_miptree_create_for_teximage(struct intel_context *intel, - struct intel_texture_object *intelObj, - struct intel_texture_image *intelImage, - GLboolean expect_accelerated_upload); - #endif diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c index 3b173bc257e..450c3ceee6f 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_image.c +++ b/src/mesa/drivers/dri/intel/intel_tex_image.c @@ -45,12 +45,24 @@ logbase2(int n) return log2; } -struct intel_mipmap_tree * -intel_miptree_create_for_teximage(struct intel_context *intel, - struct intel_texture_object *intelObj, - struct intel_texture_image *intelImage, - GLboolean expect_accelerated_upload) + +/* Otherwise, store it in memory if (Border != 0) or (any dimension == + * 1). + * + * Otherwise, if max_level >= level >= min_level, create tree with + * space for textures from min_level down to max_level. + * + * Otherwise, create tree with space for textures from (level + * 0)..(1x1). Consider pruning this tree at a validation if the + * saving is worth it. + */ +static void +guess_and_alloc_mipmap_tree(struct intel_context *intel, + struct intel_texture_object *intelObj, + struct intel_texture_image *intelImage, + GLboolean expect_accelerated_upload) { + GLuint firstLevel; GLuint lastLevel; GLuint width = intelImage->base.Width; GLuint height = intelImage->base.Height; @@ -61,11 +73,28 @@ intel_miptree_create_for_teximage(struct intel_context *intel, DBG("%s\n", __FUNCTION__); if (intelImage->base.Border) - return NULL; + return; + + if (intelImage->level > intelObj->base.BaseLevel && + (intelImage->base.Width == 1 || + (intelObj->base.Target != GL_TEXTURE_1D && + intelImage->base.Height == 1) || + (intelObj->base.Target == GL_TEXTURE_3D && + intelImage->base.Depth == 1))) + return; + + /* If this image disrespects BaseLevel, allocate from level zero. + * Usually BaseLevel == 0, so it's unlikely to happen. + */ + if (intelImage->level < intelObj->base.BaseLevel) + firstLevel = 0; + else + firstLevel = intelObj->base.BaseLevel; + /* Figure out image dimensions at start level. */ - for (i = intelImage->level; i > 0; i--) { + for (i = intelImage->level; i > firstLevel; i--) { width <<= 1; if (height != 1) height <<= 1; @@ -80,29 +109,34 @@ intel_miptree_create_for_teximage(struct intel_context *intel, */ if ((intelObj->base.MinFilter == GL_NEAREST || intelObj->base.MinFilter == GL_LINEAR) && - intelImage->level == 0) { - lastLevel = 0; + intelImage->level == firstLevel && + (intel->gen < 4 || firstLevel == 0)) { + lastLevel = firstLevel; } else { - lastLevel = logbase2(MAX2(MAX2(width, height), depth)); + lastLevel = firstLevel + logbase2(MAX2(MAX2(width, height), depth)); } + assert(!intelObj->mt); if (_mesa_is_format_compressed(intelImage->base.TexFormat)) comp_byte = intel_compressed_num_bytes(intelImage->base.TexFormat); texelBytes = _mesa_get_format_bytes(intelImage->base.TexFormat); - return intel_miptree_create(intel, - intelObj->base.Target, - intelImage->base._BaseFormat, - intelImage->base.InternalFormat, - lastLevel + 1, - width, - height, - depth, - texelBytes, - comp_byte, - expect_accelerated_upload); + intelObj->mt = intel_miptree_create(intel, + intelObj->base.Target, + intelImage->base._BaseFormat, + intelImage->base.InternalFormat, + firstLevel, + lastLevel, + width, + height, + depth, + texelBytes, + comp_byte, + expect_accelerated_upload); + + DBG("%s - success\n", __FUNCTION__); } @@ -310,23 +344,41 @@ intelTexImage(struct gl_context * ctx, texImage->Data = NULL; } - if (intelObj->mt && intel_miptree_match_image(intelObj->mt, - &intelImage->base)) { - intel_miptree_reference(&intelImage->mt, intelObj->mt); - } else { - intel_miptree_release(intel, &intelImage->mt); - intelImage->mt = intel_miptree_create_for_teximage(intel, intelObj, - intelImage, - pixels == NULL); - if (!intelImage->mt) { + if (!intelObj->mt) { + guess_and_alloc_mipmap_tree(intel, intelObj, intelImage, pixels == NULL); + if (!intelObj->mt) { DBG("guess_and_alloc_mipmap_tree: failed\n"); } + } + + assert(!intelImage->mt); + + if (intelObj->mt && + intel_miptree_match_image(intelObj->mt, &intelImage->base)) { + + intel_miptree_reference(&intelImage->mt, intelObj->mt); + assert(intelImage->mt); + } else if (intelImage->base.Border == 0) { + int comp_byte = 0; + GLuint texelBytes = _mesa_get_format_bytes(intelImage->base.TexFormat); + GLenum baseFormat = _mesa_get_format_base_format(intelImage->base.TexFormat); + if (_mesa_is_format_compressed(intelImage->base.TexFormat)) { + comp_byte = + intel_compressed_num_bytes(intelImage->base.TexFormat); + } - /* Speculatively set up the object with this miptree so that the - * later levels can just load into the miptree we just made. + /* Didn't fit in the object miptree, but it's suitable for inclusion in + * a miptree, so create one just for our level and store it in the image. + * It'll get moved into the object miptree at validate time. */ - if (!intelObj->mt && intelImage->mt) - intel_miptree_reference(&intelObj->mt, intelImage->mt); + intelImage->mt = intel_miptree_create(intel, target, + baseFormat, + internalFormat, + level, level, + width, height, depth, + texelBytes, + comp_byte, pixels == NULL); + } /* PBO fastpaths: @@ -345,7 +397,10 @@ intelTexImage(struct gl_context * ctx, * performance (in particular when intel_region_cow() is * required). */ - if (intelImage->mt->levels == 1) { + if (intelObj->mt == intelImage->mt && + intelObj->mt->first_level == level && + intelObj->mt->last_level == level) { + if (try_pbo_zcopy(intel, intelImage, unpack, internalFormat, width, height, format, type, pixels)) { diff --git a/src/mesa/drivers/dri/intel/intel_tex_layout.c b/src/mesa/drivers/dri/intel/intel_tex_layout.c index 540ef36a415..d39733b6c5a 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_layout.c +++ b/src/mesa/drivers/dri/intel/intel_tex_layout.c @@ -86,7 +86,7 @@ void i945_miptree_layout_2d(struct intel_context *intel, * constraints of mipmap placement push the right edge of the * 2nd mipmap out past the width of its parent. */ - if (mt->levels > 1) { + if (mt->first_level != mt->last_level) { GLuint mip1_width; if (mt->compressed) { @@ -104,7 +104,7 @@ void i945_miptree_layout_2d(struct intel_context *intel, mt->total_height = 0; - for (level = 0; level < mt->levels; level++) { + for ( level = mt->first_level ; level <= mt->last_level ; level++ ) { GLuint img_height; intel_miptree_set_level_info(mt, level, nr_images, x, y, width, @@ -123,7 +123,7 @@ void i945_miptree_layout_2d(struct intel_context *intel, /* Layout_below: step right after second mipmap. */ - if (level == 1) { + if (level == mt->first_level + 1) { x += ALIGN(width, align_w); } else { diff --git a/src/mesa/drivers/dri/intel/intel_tex_validate.c b/src/mesa/drivers/dri/intel/intel_tex_validate.c index 31c0a83ae34..ab8aba31fe0 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_validate.c +++ b/src/mesa/drivers/dri/intel/intel_tex_validate.c @@ -104,7 +104,8 @@ intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit) */ if (firstImage->mt && firstImage->mt != intelObj->mt && - firstImage->mt->levels >= intelObj->_MaxLevel) { + firstImage->mt->first_level <= tObj->BaseLevel && + firstImage->mt->last_level >= intelObj->_MaxLevel) { if (intelObj->mt) intel_miptree_release(intel, &intelObj->mt); @@ -131,10 +132,11 @@ intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit) if (intelObj->mt && (intelObj->mt->target != intelObj->base.Target || intelObj->mt->internal_format != firstImage->base.InternalFormat || - intelObj->mt->levels <= intelObj->_MaxLevel || - intelObj->mt->width0 != firstImage->mt->width0 || - intelObj->mt->height0 != firstImage->mt->height0 || - intelObj->mt->depth0 != firstImage->mt->depth0 || + intelObj->mt->first_level != tObj->BaseLevel || + intelObj->mt->last_level != intelObj->_MaxLevel || + intelObj->mt->width0 != firstImage->base.Width || + intelObj->mt->height0 != firstImage->base.Height || + intelObj->mt->depth0 != firstImage->base.Depth || intelObj->mt->cpp != cpp || intelObj->mt->compressed != _mesa_is_format_compressed(firstImage->base.TexFormat))) { intel_miptree_release(intel, &intelObj->mt); @@ -144,9 +146,18 @@ intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit) /* May need to create a new tree: */ if (!intelObj->mt) { - intelObj->mt = intel_miptree_create_for_teximage(intel, intelObj, - firstImage, - GL_TRUE); + intelObj->mt = intel_miptree_create(intel, + intelObj->base.Target, + firstImage->base._BaseFormat, + firstImage->base.InternalFormat, + tObj->BaseLevel, + intelObj->_MaxLevel, + firstImage->base.Width, + firstImage->base.Height, + firstImage->base.Depth, + cpp, + comp_byte, + GL_TRUE); } /* Pull in any images not in the object's tree: -- 2.30.2