简体   繁体   中英

How do you efficiently manage texture memory in OpenGLES on Android?

I am loading textures into OpenGLES on Android and maintaining a reference to the generated id in a HashMap.

At a given point in time not all textures that have been loaded will be in use, but may be used at a later point in time, therefore if the device has enough free memory I'd like to keep the textures loaded.

However, if the device starts running low on memory I would like to delete any textures that are not in use since they can always be reloaded later if they're required.

I've tried a few methodologies for handling this scenario.

1. Respond to system memory warnings

If the application receives a memory warning, then it will identify which textures are not in use and schedule for those textures to be deleted.

This method did work reasonably well.

2. Use Soft References

In this approach the application would maintain a List<SoftReference<Texture>> where the Texture class is a wrapper around the id that was returned when a given texture was loaded into OpenGLES.

If a given Texture is not in use at a given point in time then only a SoftReference would exist to this Texture and thus if the garbage collector deemed it necessary it could reclaim this memory and the finalize method on the Texture class would schedule for this texture to be deleted.

This approach seemed ideal based upon the description of SoftReference in the Java documentation , since they would only be reclaimed when more memory was required.

Soft reference objects, which are cleared at the discretion of the garbage collector in response to memory demand. Soft references are most often used to implement memory-sensitive caches.

However, the Android implementation of SoftReference does not work like this: since Android 9 as the garbage collector is more aggressive and the soft references are reclaimed almost immediately regardless of whether the device is low on memory.

3. Use LruCache

The Android documentation advises against using SoftReference in a cache implementation and to use a LruCache instead. However, the LruCache poses some drawbacks.

Firstly, you have to specifying the maximum size of the cache. It isn't obvious what to set the cache size to: ideally it'd just automatically be set as high as possible while still being a good citizen. If it's set too small, it might be constantly reloading textures unnecessarily.

Secondly, a Texture may be removed from the cache which is currently in use and thus may be deleted from OpenGLES and then display as a missing texture to the user.

Is there a better way to maintain a cache of textures in OpenGL and be responsive to low memory scenarios (besides just deleting textures upon memory warnings)?

Talking about best practices, large caches (that can take all the memory) with OpenGL ids for textures are rarely used. Actually it's worth to have only a few textures to render in the scene at one moment. More textures you have in the scene, more texture switches you need to do in frame. It costs. Texture atlases were developed many years ago to reduce number of texture switches. However, atlases still can take a lot of memory.

With development of hardware capabilities and user expectations, texture atlases evolved into virtual/mega/sparse textures + texture data streaming for the cases of high memory usage. The idea is to use virtual memory approach and load/unload blocks of one very large texture in real-time. It has some drawbacks, good discussion about it can be found here . LRU cache can be built on top of it to tell what blocks are required at the moment.

Of course, engines can preload many textures (sparse or usual ones) and unload it after usage, eg as a part of dynamic loading of open world in a game. These textures aren't used for rendering simultaneously, and no one waits until they take all the memory to start unloading. The eviction algorithm here is highly dependant on particular app, even though maximum cache size in Mb is widely used practice here.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM