[Impeller] limit mipmap generation (#165357)

Fixes https://github.com/flutter/flutter/issues/161283

When generating mipmaps, as soon as we hit a dimension (x,y) of 1, stop
generating mipmaps. This is done by changing the mip computation to use
min instead of max - but also adds a short circuit too.
This commit is contained in:
Jonah Williams 2025-03-18 08:41:11 -07:00 committed by GitHub
parent 7efef421ae
commit 6328b7ea08
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 16 additions and 25 deletions

View File

@ -578,16 +578,16 @@ TEST(GeometryTest, QuaternionVectorMultiply) {
}
TEST(GeometryTest, CanGenerateMipCounts) {
ASSERT_EQ((Size{128, 128}.MipCount()), 6u);
ASSERT_EQ((Size{128, 256}.MipCount()), 7u);
ASSERT_EQ((Size{128, 130}.MipCount()), 7u);
ASSERT_EQ((Size{128, 257}.MipCount()), 8u);
ASSERT_EQ((Size{257, 128}.MipCount()), 8u);
ASSERT_EQ((Size{128, 0}.MipCount()), 1u);
ASSERT_EQ((Size{128, -25}.MipCount()), 1u);
ASSERT_EQ((Size{-128, 25}.MipCount()), 1u);
ASSERT_EQ((Size{1, 1}.MipCount()), 1u);
ASSERT_EQ((Size{0, 0}.MipCount()), 1u);
EXPECT_EQ((Size{128, 128}.MipCount()), 7u);
EXPECT_EQ((Size{128, 256}.MipCount()), 7u);
EXPECT_EQ((Size{128, 130}.MipCount()), 7u);
EXPECT_EQ((Size{128, 257}.MipCount()), 7u);
EXPECT_EQ((Size{257, 128}.MipCount()), 7u);
EXPECT_EQ((Size{128, 0}.MipCount()), 1u);
EXPECT_EQ((Size{128, -25}.MipCount()), 1u);
EXPECT_EQ((Size{-128, 25}.MipCount()), 1u);
EXPECT_EQ((Size{1, 1}.MipCount()), 1u);
EXPECT_EQ((Size{0, 0}.MipCount()), 1u);
}
TEST(GeometryTest, CanConvertTTypesExplicitly) {

View File

@ -134,24 +134,12 @@ struct TSize {
}
/// Return the mip count of the texture.
///
/// Note: does not count the final 1x1 mip level, both for practical reasons
/// and to workaround driver bugs.
constexpr size_t MipCount() const {
constexpr size_t minimum_mip = 1u;
if (IsEmpty()) {
if (IsEmpty() || width <= 0 || height <= 0) {
return minimum_mip;
}
size_t result = std::max(ceil(log2(width)), ceil(log2(height)));
// This check avoids creating 1x1 mip levels, which are both pointless
// and cause rendering problems on some Adreno GPUs.
// See:
// * https://github.com/flutter/flutter/issues/160441
// * https://github.com/flutter/flutter/issues/159876
// * https://github.com/flutter/flutter/issues/160587
if (result > 1) {
result -= 1;
}
size_t result = std::min(log2(width), log2(height));
return std::max(result, minimum_mip);
}
};

View File

@ -403,7 +403,7 @@ bool BlitPassVK::OnGenerateMipmapCommand(std::shared_ptr<Texture> texture,
const auto size = src.GetTextureDescriptor().size;
uint32_t mip_count = src.GetTextureDescriptor().mip_count;
if (mip_count < 2u || workarounds_.broken_mipmap_generation) {
if (mip_count < 2u) {
return true;
}
@ -478,6 +478,9 @@ bool BlitPassVK::OnGenerateMipmapCommand(std::shared_ptr<Texture> texture,
width = width / 2;
height = height / 2;
if (width <= 1 || height <= 1) {
break;
}
// offsets[0] is origin.
blit.dstOffsets[1].x = std::max<int32_t>(width, 1u);