intel: When making a new teximage miptree, make a full one.
If we hit this path, we're level 1+ and the base level got allocated as a single level instead of a full tree (so we don't match intelObj->mt). This tries to recover from that so that we end up with 2 allocations and 1 validation blit (old -> new) instead of allocations equal to number of levels and levels - 1 blits.
This commit is contained in:
@@ -56,11 +56,11 @@ logbase2(int n)
|
|||||||
* 0)..(1x1). Consider pruning this tree at a validation if the
|
* 0)..(1x1). Consider pruning this tree at a validation if the
|
||||||
* saving is worth it.
|
* saving is worth it.
|
||||||
*/
|
*/
|
||||||
static void
|
static struct intel_mipmap_tree *
|
||||||
guess_and_alloc_mipmap_tree(struct intel_context *intel,
|
intel_miptree_create_for_teximage(struct intel_context *intel,
|
||||||
struct intel_texture_object *intelObj,
|
struct intel_texture_object *intelObj,
|
||||||
struct intel_texture_image *intelImage,
|
struct intel_texture_image *intelImage,
|
||||||
GLboolean expect_accelerated_upload)
|
GLboolean expect_accelerated_upload)
|
||||||
{
|
{
|
||||||
GLuint firstLevel;
|
GLuint firstLevel;
|
||||||
GLuint lastLevel;
|
GLuint lastLevel;
|
||||||
@@ -73,70 +73,71 @@ guess_and_alloc_mipmap_tree(struct intel_context *intel,
|
|||||||
DBG("%s\n", __FUNCTION__);
|
DBG("%s\n", __FUNCTION__);
|
||||||
|
|
||||||
if (intelImage->base.Border)
|
if (intelImage->base.Border)
|
||||||
return;
|
return NULL;
|
||||||
|
|
||||||
if (intelImage->level > intelObj->base.BaseLevel &&
|
if (intelImage->level > intelObj->base.BaseLevel &&
|
||||||
(intelImage->base.Width == 1 ||
|
(intelImage->base.Width == 1 ||
|
||||||
(intelObj->base.Target != GL_TEXTURE_1D &&
|
(intelObj->base.Target != GL_TEXTURE_1D &&
|
||||||
intelImage->base.Height == 1) ||
|
intelImage->base.Height == 1) ||
|
||||||
(intelObj->base.Target == GL_TEXTURE_3D &&
|
(intelObj->base.Target == GL_TEXTURE_3D &&
|
||||||
intelImage->base.Depth == 1)))
|
intelImage->base.Depth == 1))) {
|
||||||
return;
|
/* For this combination, we're at some lower mipmap level and
|
||||||
|
* some important dimension is 1. We can't extrapolate up to a
|
||||||
|
* likely base level width/height/depth for a full mipmap stack
|
||||||
|
* from this info, so just allocate this one level.
|
||||||
|
*/
|
||||||
|
firstLevel = intelImage->level;
|
||||||
|
lastLevel = intelImage->level;
|
||||||
|
} else {
|
||||||
|
/* 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;
|
||||||
|
|
||||||
/* If this image disrespects BaseLevel, allocate from level zero.
|
/* Figure out image dimensions at start level. */
|
||||||
* Usually BaseLevel == 0, so it's unlikely to happen.
|
for (i = intelImage->level; i > firstLevel; i--) {
|
||||||
*/
|
width <<= 1;
|
||||||
if (intelImage->level < intelObj->base.BaseLevel)
|
if (height != 1)
|
||||||
firstLevel = 0;
|
height <<= 1;
|
||||||
else
|
if (depth != 1)
|
||||||
firstLevel = intelObj->base.BaseLevel;
|
depth <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Guess a reasonable value for lastLevel. This is probably going
|
||||||
/* Figure out image dimensions at start level.
|
* to be wrong fairly often and might mean that we have to look at
|
||||||
*/
|
* resizable buffers, or require that buffers implement lazy
|
||||||
for (i = intelImage->level; i > firstLevel; i--) {
|
* pagetable arrangements.
|
||||||
width <<= 1;
|
*/
|
||||||
if (height != 1)
|
if ((intelObj->base.MinFilter == GL_NEAREST ||
|
||||||
height <<= 1;
|
intelObj->base.MinFilter == GL_LINEAR) &&
|
||||||
if (depth != 1)
|
intelImage->level == firstLevel &&
|
||||||
depth <<= 1;
|
(intel->gen < 4 || firstLevel == 0)) {
|
||||||
|
lastLevel = firstLevel;
|
||||||
|
} else {
|
||||||
|
lastLevel = firstLevel + logbase2(MAX2(MAX2(width, height), depth));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Guess a reasonable value for lastLevel. This is probably going
|
|
||||||
* to be wrong fairly often and might mean that we have to look at
|
|
||||||
* resizable buffers, or require that buffers implement lazy
|
|
||||||
* pagetable arrangements.
|
|
||||||
*/
|
|
||||||
if ((intelObj->base.MinFilter == GL_NEAREST ||
|
|
||||||
intelObj->base.MinFilter == GL_LINEAR) &&
|
|
||||||
intelImage->level == firstLevel &&
|
|
||||||
(intel->gen < 4 || firstLevel == 0)) {
|
|
||||||
lastLevel = firstLevel;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
lastLevel = firstLevel + logbase2(MAX2(MAX2(width, height), depth));
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(!intelObj->mt);
|
|
||||||
if (_mesa_is_format_compressed(intelImage->base.TexFormat))
|
if (_mesa_is_format_compressed(intelImage->base.TexFormat))
|
||||||
comp_byte = intel_compressed_num_bytes(intelImage->base.TexFormat);
|
comp_byte = intel_compressed_num_bytes(intelImage->base.TexFormat);
|
||||||
|
|
||||||
texelBytes = _mesa_get_format_bytes(intelImage->base.TexFormat);
|
texelBytes = _mesa_get_format_bytes(intelImage->base.TexFormat);
|
||||||
|
|
||||||
intelObj->mt = intel_miptree_create(intel,
|
return intel_miptree_create(intel,
|
||||||
intelObj->base.Target,
|
intelObj->base.Target,
|
||||||
intelImage->base._BaseFormat,
|
intelImage->base._BaseFormat,
|
||||||
intelImage->base.InternalFormat,
|
intelImage->base.InternalFormat,
|
||||||
firstLevel,
|
firstLevel,
|
||||||
lastLevel,
|
lastLevel,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
depth,
|
depth,
|
||||||
texelBytes,
|
texelBytes,
|
||||||
comp_byte,
|
comp_byte,
|
||||||
expect_accelerated_upload);
|
expect_accelerated_upload);
|
||||||
|
|
||||||
DBG("%s - success\n", __FUNCTION__);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -344,41 +345,29 @@ intelTexImage(struct gl_context * ctx,
|
|||||||
texImage->Data = NULL;
|
texImage->Data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
assert(!intelImage->mt);
|
||||||
|
|
||||||
if (intelObj->mt &&
|
if (intelObj->mt &&
|
||||||
intel_miptree_match_image(intelObj->mt, &intelImage->base)) {
|
intel_miptree_match_image(intelObj->mt, &intelImage->base)) {
|
||||||
|
/* Use an existing miptree when possible */
|
||||||
intel_miptree_reference(&intelImage->mt, intelObj->mt);
|
intel_miptree_reference(&intelImage->mt, intelObj->mt);
|
||||||
assert(intelImage->mt);
|
assert(intelImage->mt);
|
||||||
} else if (intelImage->base.Border == 0) {
|
} 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Didn't fit in the object miptree, but it's suitable for inclusion in
|
/* 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.
|
* 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.
|
* It'll get moved into the object miptree at validate time.
|
||||||
*/
|
*/
|
||||||
intelImage->mt = intel_miptree_create(intel, target,
|
intelImage->mt = intel_miptree_create_for_teximage(intel, intelObj,
|
||||||
baseFormat,
|
intelImage,
|
||||||
internalFormat,
|
pixels == NULL);
|
||||||
level, level,
|
|
||||||
width, height, depth,
|
|
||||||
texelBytes,
|
|
||||||
comp_byte, pixels == NULL);
|
|
||||||
|
|
||||||
|
/* Even if the object currently has a mipmap tree associated
|
||||||
|
* with it, this one is a more likely candidate to represent the
|
||||||
|
* whole object since our level didn't fit what was there
|
||||||
|
* before, and any lower levels would fit into our miptree.
|
||||||
|
*/
|
||||||
|
if (intelImage->mt)
|
||||||
|
intel_miptree_reference(&intelObj->mt, intelImage->mt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PBO fastpaths:
|
/* PBO fastpaths:
|
||||||
|
Reference in New Issue
Block a user