[Impeller] dont generate final 1x1 mip level to work around Adreno GPU bug (#161192)

Generating the final 1x1 mip level of a texture causes the entire
texture to become corrupted on some Adreno GPUs.

https://github.com/flutter/flutter/issues/160441
https://github.com/flutter/flutter/issues/159876
https://github.com/flutter/flutter/issues/160587
This commit is contained in:
Jonah Williams 2025-01-06 16:44:52 -08:00 committed by GitHub
parent 16b9fe049d
commit 434ca754e3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 18 additions and 5 deletions

View File

@ -578,11 +578,11 @@ TEST(GeometryTest, QuaternionVectorMultiply) {
}
TEST(GeometryTest, CanGenerateMipCounts) {
ASSERT_EQ((Size{128, 128}.MipCount()), 7u);
ASSERT_EQ((Size{128, 256}.MipCount()), 8u);
ASSERT_EQ((Size{128, 130}.MipCount()), 8u);
ASSERT_EQ((Size{128, 257}.MipCount()), 9u);
ASSERT_EQ((Size{257, 128}.MipCount()), 9u);
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);

View File

@ -131,12 +131,25 @@ struct TSize {
static_cast<Type>(std::ceil(other.height))};
}
/// 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()) {
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;
}
return std::max(result, minimum_mip);
}
};