Skip to content

Commit

Permalink
[WPE] Add a soft limit to the amount of GPU memory BitmapTexturePool …
Browse files Browse the repository at this point in the history
…can hold

https://bugs.webkit.org/show_bug.cgi?id=271765

Reviewed by Carlos Garcia Campos.

Add a soft limit to the amount of memory that BitmapTexturePool can hold. When
the limit is reached, be more aggressive trying to release the stored textures.

* Source/WebCore/PlatformWPE.cmake:
* Source/WebCore/platform/graphics/texmap/BitmapTexturePool.cpp:
(WebCore::BitmapTexturePool::BitmapTexturePool):
(WebCore::BitmapTexturePool::acquireTexture):
(WebCore::BitmapTexturePool::scheduleReleaseUnusedTextures):
(WebCore::BitmapTexturePool::releaseUnusedTexturesTimerFired):
(WebCore::BitmapTexturePool::enterLimitExceededModeIfNeeded):
(WebCore::BitmapTexturePool::exitLimitExceededModeIfNeeded):
* Source/WebCore/platform/graphics/texmap/BitmapTexturePool.h:

Canonical link: https://commits.webkit.org/276997@main
  • Loading branch information
magomez committed Apr 3, 2024
1 parent 7e4ae4b commit eff294d
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 5 deletions.
8 changes: 8 additions & 0 deletions Source/WebCore/PlatformWPE.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,11 @@ if (ENABLE_SPEECH_SYNTHESIS)
${Flite_LIBRARIES}
)
endif ()

# This sets the maximum amount of memory that BitmapTexturePool can hold before being more
# aggressive trying to release the unused textures.
# Use a big value as the default size limit (80MB, enough for ten 1920x1080 layers).
# Embedded users will want to set this limit depending on the capabilities of their platform.
list(APPEND WebCore_PRIVATE_DEFINITIONS
BITMAP_TEXTURE_POOL_MAX_SIZE_IN_MB=80
)
61 changes: 56 additions & 5 deletions Source/WebCore/platform/graphics/texmap/BitmapTexturePool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,21 @@

namespace WebCore {

#if defined(BITMAP_TEXTURE_POOL_MAX_SIZE_IN_MB) && BITMAP_TEXTURE_POOL_MAX_SIZE_IN_MB > 0
static constexpr size_t poolSizeLimit = BITMAP_TEXTURE_POOL_MAX_SIZE_IN_MB * MB;
#else
static constexpr size_t poolSizeLimit = std::numeric_limits<size_t>::max();
#endif

static const Seconds releaseUnusedSecondsTolerance { 3_s };
static const Seconds releaseUnusedTexturesTimerInterval { 500_ms };
static const Seconds releaseUnusedSecondsToleranceOnLimitExceeded { 50_ms };
static const Seconds releaseUnusedTexturesTimerIntervalOnLimitExceeded { 200_ms };

BitmapTexturePool::BitmapTexturePool()
: m_releaseUnusedTexturesTimer(RunLoop::current(), this, &BitmapTexturePool::releaseUnusedTexturesTimerFired)
, m_releaseUnusedSecondsTolerance(releaseUnusedSecondsTolerance)
, m_releaseUnusedTexturesTimerInterval(releaseUnusedTexturesTimerInterval)
{
}

Expand All @@ -51,10 +61,14 @@ RefPtr<BitmapTexture> BitmapTexturePool::acquireTexture(const IntSize& size, Opt
if (selectedEntry == m_textures.end()) {
m_textures.append(Entry(BitmapTexture::create(size, flags)));
selectedEntry = &m_textures.last();
m_poolSize += size.unclampedArea();
} else
selectedEntry->m_texture->reset(size, flags);

enterLimitExceededModeIfNeeded();

scheduleReleaseUnusedTextures();

selectedEntry->markIsInUse();
return selectedEntry->m_texture.copyRef();
}
Expand All @@ -64,7 +78,7 @@ void BitmapTexturePool::scheduleReleaseUnusedTextures()
if (m_releaseUnusedTexturesTimer.isActive())
return;

m_releaseUnusedTexturesTimer.startOneShot(releaseUnusedTexturesTimerInterval);
m_releaseUnusedTexturesTimer.startOneShot(m_releaseUnusedTexturesTimerInterval);
}

void BitmapTexturePool::releaseUnusedTexturesTimerFired()
Expand All @@ -73,16 +87,53 @@ void BitmapTexturePool::releaseUnusedTexturesTimerFired()
return;

// Delete entries, which have been unused in releaseUnusedSecondsTolerance.
MonotonicTime minUsedTime = MonotonicTime::now() - releaseUnusedSecondsTolerance;

m_textures.removeAllMatching([&minUsedTime](const Entry& entry) {
return entry.canBeReleased(minUsedTime);
MonotonicTime minUsedTime = MonotonicTime::now() - m_releaseUnusedSecondsTolerance;

m_textures.removeAllMatching([this, &minUsedTime](const Entry& entry) {
if (entry.canBeReleased(minUsedTime)) {
m_poolSize -= entry.m_texture->size().unclampedArea();
return true;
}
return false;
});

exitLimitExceededModeIfNeeded();

if (!m_textures.isEmpty())
scheduleReleaseUnusedTextures();
}

void BitmapTexturePool::enterLimitExceededModeIfNeeded()
{
if (m_onLimitExceededMode)
return;

if (m_poolSize > poolSizeLimit) {
// If we allocated a new texture and this caused that we went over the size limit, enter limit exceeded mode,
// set values for tolerance and interval for this mode, and trigger an immediate request to release textures.
// While on limit exceeded mode, we are more aggressive releasing textures, by polling more often and keeping
// the unused textures in the pool for smaller periods of time.
m_onLimitExceededMode = true;
m_releaseUnusedSecondsTolerance = releaseUnusedSecondsToleranceOnLimitExceeded;
m_releaseUnusedTexturesTimerInterval = releaseUnusedTexturesTimerIntervalOnLimitExceeded;
m_releaseUnusedTexturesTimer.startOneShot(0_s);
}
}

void BitmapTexturePool::exitLimitExceededModeIfNeeded()
{
if (!m_onLimitExceededMode)
return;

// If we're in limit exceeded mode and the pool size has become smaller than the limit,
// exit the limit exceeded mode and set the default values for interval and tolerance again.
if (m_poolSize <= poolSizeLimit) {
m_onLimitExceededMode = false;
m_releaseUnusedSecondsTolerance = releaseUnusedSecondsTolerance;
m_releaseUnusedTexturesTimerInterval = releaseUnusedTexturesTimerInterval;
}
}

} // namespace WebCore

#endif // USE(TEXTURE_MAPPER)
6 changes: 6 additions & 0 deletions Source/WebCore/platform/graphics/texmap/BitmapTexturePool.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,15 @@ class BitmapTexturePool {
};

void scheduleReleaseUnusedTextures();
void enterLimitExceededModeIfNeeded();
void exitLimitExceededModeIfNeeded();

Vector<Entry> m_textures;
RunLoop::Timer m_releaseUnusedTexturesTimer;
uint64_t m_poolSize { 0 };
bool m_onLimitExceededMode { false };
Seconds m_releaseUnusedSecondsTolerance;
Seconds m_releaseUnusedTexturesTimerInterval;
};

} // namespace WebCore
Expand Down

0 comments on commit eff294d

Please sign in to comment.