Loading libs/hwui/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ cc_defaults { "libft2", "libminikin", "libandroidfw", "libcrypto", ], static_libs: [ "libEGL_blobCache", Loading libs/hwui/pipeline/skia/ShaderCache.cpp +50 −6 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ #include <algorithm> #include <log/log.h> #include <thread> #include <array> #include <openssl/sha.h> #include "FileBlobCache.h" #include "Properties.h" #include "utils/TraceUtils.h" Loading @@ -41,7 +43,40 @@ ShaderCache& ShaderCache::get() { return sCache; } void ShaderCache::initShaderDiskCache() { bool ShaderCache::validateCache(const void* identity, ssize_t size) { if (nullptr == identity && size == 0) return true; if (nullptr == identity || size < 0) { if (CC_UNLIKELY(Properties::debugLevel & kDebugCaches)) { ALOGW("ShaderCache::validateCache invalid cache identity"); } mBlobCache->clear(); return false; } SHA256_CTX ctx; SHA256_Init(&ctx); SHA256_Update(&ctx, identity, size); mIDHash.resize(SHA256_DIGEST_LENGTH); SHA256_Final(mIDHash.data(), &ctx); std::array<uint8_t, SHA256_DIGEST_LENGTH> hash; auto key = sIDKey; auto loaded = mBlobCache->get(&key, sizeof(key), hash.data(), hash.size()); if (loaded && std::equal(hash.begin(), hash.end(), mIDHash.begin())) return true; if (CC_UNLIKELY(Properties::debugLevel & kDebugCaches)) { ALOGW("ShaderCache::validateCache cache validation fails"); } mBlobCache->clear(); return false; } void ShaderCache::initShaderDiskCache(const void* identity, ssize_t size) { ATRACE_NAME("initShaderDiskCache"); std::lock_guard<std::mutex> lock(mMutex); Loading @@ -50,6 +85,7 @@ void ShaderCache::initShaderDiskCache() { // desktop / laptop GPUs. Thus, disable the shader disk cache for emulator builds. if (!Properties::runningInEmulator && mFilename.length() > 0) { mBlobCache.reset(new FileBlobCache(maxKeySize, maxValueSize, maxTotalSize, mFilename)); validateCache(identity, size); mInitialized = true; } } Loading Loading @@ -104,6 +140,18 @@ sk_sp<SkData> ShaderCache::load(const SkData& key) { return SkData::MakeFromMalloc(valueBuffer, valueSize); } void ShaderCache::saveToDiskLocked() { ATRACE_NAME("ShaderCache::saveToDiskLocked"); if (mInitialized && mBlobCache && mSavePending) { if (mIDHash.size()) { auto key = sIDKey; mBlobCache->set(&key, sizeof(key), mIDHash.data(), mIDHash.size()); } mBlobCache->writeToFile(); } mSavePending = false; } void ShaderCache::store(const SkData& key, const SkData& data) { ATRACE_NAME("ShaderCache::store"); std::lock_guard<std::mutex> lock(mMutex); Loading @@ -129,11 +177,7 @@ void ShaderCache::store(const SkData& key, const SkData& data) { std::thread deferredSaveThread([this]() { sleep(mDeferredSaveDelay); std::lock_guard<std::mutex> lock(mMutex); ATRACE_NAME("ShaderCache::saveToDisk"); if (mInitialized && mBlobCache) { mBlobCache->writeToFile(); } mSavePending = false; saveToDiskLocked(); }); deferredSaveThread.detach(); } Loading libs/hwui/pipeline/skia/ShaderCache.h +41 −5 Original line number Diff line number Diff line Loading @@ -40,12 +40,21 @@ public: ANDROID_API static ShaderCache& get(); /** * "initShaderDiskCache" loads the serialized cache contents from disk and puts the ShaderCache * into an initialized state, such that it is able to insert and retrieve entries from the * cache. This should be called when HWUI pipeline is initialized. When not in the initialized * state the load and store methods will return without performing any cache operations. * initShaderDiskCache" loads the serialized cache contents from disk, * optionally checks that the on-disk cache matches a provided identity, * and puts the ShaderCache into an initialized state, such that it is * able to insert and retrieve entries from the cache. If identity is * non-null and validation fails, the cache is initialized but contains * no data. If size is less than zero, the cache is initilaized but * contains no data. * * This should be called when HWUI pipeline is initialized. When not in * the initialized state the load and store methods will return without * performing any cache operations. */ virtual void initShaderDiskCache(); virtual void initShaderDiskCache(const void *identity, ssize_t size); virtual void initShaderDiskCache() { initShaderDiskCache(nullptr, 0); } /** * "setFilename" sets the name of the file that should be used to store Loading Loading @@ -82,6 +91,19 @@ private: */ BlobCache* getBlobCacheLocked(); /** * "validateCache" updates the cache to match the given identity. If the * cache currently has the wrong identity, all entries in the cache are cleared. */ bool validateCache(const void* identity, ssize_t size); /** * "saveToDiskLocked" attemps to save the current contents of the cache to * disk. If the identity hash exists, we will insert the identity hash into * the cache for next validation. */ void saveToDiskLocked(); /** * "mInitialized" indicates whether the ShaderCache is in the initialized * state. It is initialized to false at construction time, and gets set to Loading Loading @@ -110,6 +132,15 @@ private: */ std::string mFilename; /** * "mIDHash" is the current identity hash for the cache validation. It is * initialized to an empty vector at construction time, and its content is * generated in the call of the validateCache method. An empty vector * indicates that cache validation is not performed, and the hash should * not be stored on disk. */ std::vector<uint8_t> mIDHash; /** * "mSavePending" indicates whether or not a deferred save operation is * pending. Each time a key/value pair is inserted into the cache via Loading Loading @@ -140,6 +171,11 @@ private: */ static ShaderCache sCache; /** * "sIDKey" is the cache key of the identity hash */ static constexpr uint8_t sIDKey = 0; friend class ShaderCacheTestUtils; //used for unit testing }; Loading libs/hwui/renderthread/CacheManager.cpp +4 −3 Original line number Diff line number Diff line Loading @@ -50,7 +50,6 @@ CacheManager::CacheManager(const DisplayInfo& display) : mMaxSurfaceArea(display mVectorDrawableAtlas = new skiapipeline::VectorDrawableAtlas( mMaxSurfaceArea / 2, skiapipeline::VectorDrawableAtlas::StorageMode::disallowSharedSurface); skiapipeline::ShaderCache::get().initShaderDiskCache(); } void CacheManager::reset(sk_sp<GrContext> context) { Loading Loading @@ -103,7 +102,7 @@ public: } }; void CacheManager::configureContext(GrContextOptions* contextOptions) { void CacheManager::configureContext(GrContextOptions* contextOptions, const void* identity, ssize_t size) { contextOptions->fAllowPathMaskCaching = true; float screenMP = mMaxSurfaceArea / 1024.0f / 1024.0f; Loading Loading @@ -133,7 +132,9 @@ void CacheManager::configureContext(GrContextOptions* contextOptions) { contextOptions->fExecutor = mTaskProcessor.get(); } contextOptions->fPersistentCache = &skiapipeline::ShaderCache::get(); auto& cache = skiapipeline::ShaderCache::get(); cache.initShaderDiskCache(identity, size); contextOptions->fPersistentCache = &cache; contextOptions->fGpuPathRenderers &= ~GpuPathRenderers::kCoverageCounting; } Loading libs/hwui/renderthread/CacheManager.h +1 −1 Original line number Diff line number Diff line Loading @@ -44,7 +44,7 @@ class CacheManager { public: enum class TrimMemoryMode { Complete, UiHidden }; void configureContext(GrContextOptions* context); void configureContext(GrContextOptions* context, const void* identity, ssize_t size); void trimMemory(TrimMemoryMode mode); void trimStaleResources(); void dumpMemoryUsage(String8& log, const RenderState* renderState = nullptr); Loading Loading
libs/hwui/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ cc_defaults { "libft2", "libminikin", "libandroidfw", "libcrypto", ], static_libs: [ "libEGL_blobCache", Loading
libs/hwui/pipeline/skia/ShaderCache.cpp +50 −6 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ #include <algorithm> #include <log/log.h> #include <thread> #include <array> #include <openssl/sha.h> #include "FileBlobCache.h" #include "Properties.h" #include "utils/TraceUtils.h" Loading @@ -41,7 +43,40 @@ ShaderCache& ShaderCache::get() { return sCache; } void ShaderCache::initShaderDiskCache() { bool ShaderCache::validateCache(const void* identity, ssize_t size) { if (nullptr == identity && size == 0) return true; if (nullptr == identity || size < 0) { if (CC_UNLIKELY(Properties::debugLevel & kDebugCaches)) { ALOGW("ShaderCache::validateCache invalid cache identity"); } mBlobCache->clear(); return false; } SHA256_CTX ctx; SHA256_Init(&ctx); SHA256_Update(&ctx, identity, size); mIDHash.resize(SHA256_DIGEST_LENGTH); SHA256_Final(mIDHash.data(), &ctx); std::array<uint8_t, SHA256_DIGEST_LENGTH> hash; auto key = sIDKey; auto loaded = mBlobCache->get(&key, sizeof(key), hash.data(), hash.size()); if (loaded && std::equal(hash.begin(), hash.end(), mIDHash.begin())) return true; if (CC_UNLIKELY(Properties::debugLevel & kDebugCaches)) { ALOGW("ShaderCache::validateCache cache validation fails"); } mBlobCache->clear(); return false; } void ShaderCache::initShaderDiskCache(const void* identity, ssize_t size) { ATRACE_NAME("initShaderDiskCache"); std::lock_guard<std::mutex> lock(mMutex); Loading @@ -50,6 +85,7 @@ void ShaderCache::initShaderDiskCache() { // desktop / laptop GPUs. Thus, disable the shader disk cache for emulator builds. if (!Properties::runningInEmulator && mFilename.length() > 0) { mBlobCache.reset(new FileBlobCache(maxKeySize, maxValueSize, maxTotalSize, mFilename)); validateCache(identity, size); mInitialized = true; } } Loading Loading @@ -104,6 +140,18 @@ sk_sp<SkData> ShaderCache::load(const SkData& key) { return SkData::MakeFromMalloc(valueBuffer, valueSize); } void ShaderCache::saveToDiskLocked() { ATRACE_NAME("ShaderCache::saveToDiskLocked"); if (mInitialized && mBlobCache && mSavePending) { if (mIDHash.size()) { auto key = sIDKey; mBlobCache->set(&key, sizeof(key), mIDHash.data(), mIDHash.size()); } mBlobCache->writeToFile(); } mSavePending = false; } void ShaderCache::store(const SkData& key, const SkData& data) { ATRACE_NAME("ShaderCache::store"); std::lock_guard<std::mutex> lock(mMutex); Loading @@ -129,11 +177,7 @@ void ShaderCache::store(const SkData& key, const SkData& data) { std::thread deferredSaveThread([this]() { sleep(mDeferredSaveDelay); std::lock_guard<std::mutex> lock(mMutex); ATRACE_NAME("ShaderCache::saveToDisk"); if (mInitialized && mBlobCache) { mBlobCache->writeToFile(); } mSavePending = false; saveToDiskLocked(); }); deferredSaveThread.detach(); } Loading
libs/hwui/pipeline/skia/ShaderCache.h +41 −5 Original line number Diff line number Diff line Loading @@ -40,12 +40,21 @@ public: ANDROID_API static ShaderCache& get(); /** * "initShaderDiskCache" loads the serialized cache contents from disk and puts the ShaderCache * into an initialized state, such that it is able to insert and retrieve entries from the * cache. This should be called when HWUI pipeline is initialized. When not in the initialized * state the load and store methods will return without performing any cache operations. * initShaderDiskCache" loads the serialized cache contents from disk, * optionally checks that the on-disk cache matches a provided identity, * and puts the ShaderCache into an initialized state, such that it is * able to insert and retrieve entries from the cache. If identity is * non-null and validation fails, the cache is initialized but contains * no data. If size is less than zero, the cache is initilaized but * contains no data. * * This should be called when HWUI pipeline is initialized. When not in * the initialized state the load and store methods will return without * performing any cache operations. */ virtual void initShaderDiskCache(); virtual void initShaderDiskCache(const void *identity, ssize_t size); virtual void initShaderDiskCache() { initShaderDiskCache(nullptr, 0); } /** * "setFilename" sets the name of the file that should be used to store Loading Loading @@ -82,6 +91,19 @@ private: */ BlobCache* getBlobCacheLocked(); /** * "validateCache" updates the cache to match the given identity. If the * cache currently has the wrong identity, all entries in the cache are cleared. */ bool validateCache(const void* identity, ssize_t size); /** * "saveToDiskLocked" attemps to save the current contents of the cache to * disk. If the identity hash exists, we will insert the identity hash into * the cache for next validation. */ void saveToDiskLocked(); /** * "mInitialized" indicates whether the ShaderCache is in the initialized * state. It is initialized to false at construction time, and gets set to Loading Loading @@ -110,6 +132,15 @@ private: */ std::string mFilename; /** * "mIDHash" is the current identity hash for the cache validation. It is * initialized to an empty vector at construction time, and its content is * generated in the call of the validateCache method. An empty vector * indicates that cache validation is not performed, and the hash should * not be stored on disk. */ std::vector<uint8_t> mIDHash; /** * "mSavePending" indicates whether or not a deferred save operation is * pending. Each time a key/value pair is inserted into the cache via Loading Loading @@ -140,6 +171,11 @@ private: */ static ShaderCache sCache; /** * "sIDKey" is the cache key of the identity hash */ static constexpr uint8_t sIDKey = 0; friend class ShaderCacheTestUtils; //used for unit testing }; Loading
libs/hwui/renderthread/CacheManager.cpp +4 −3 Original line number Diff line number Diff line Loading @@ -50,7 +50,6 @@ CacheManager::CacheManager(const DisplayInfo& display) : mMaxSurfaceArea(display mVectorDrawableAtlas = new skiapipeline::VectorDrawableAtlas( mMaxSurfaceArea / 2, skiapipeline::VectorDrawableAtlas::StorageMode::disallowSharedSurface); skiapipeline::ShaderCache::get().initShaderDiskCache(); } void CacheManager::reset(sk_sp<GrContext> context) { Loading Loading @@ -103,7 +102,7 @@ public: } }; void CacheManager::configureContext(GrContextOptions* contextOptions) { void CacheManager::configureContext(GrContextOptions* contextOptions, const void* identity, ssize_t size) { contextOptions->fAllowPathMaskCaching = true; float screenMP = mMaxSurfaceArea / 1024.0f / 1024.0f; Loading Loading @@ -133,7 +132,9 @@ void CacheManager::configureContext(GrContextOptions* contextOptions) { contextOptions->fExecutor = mTaskProcessor.get(); } contextOptions->fPersistentCache = &skiapipeline::ShaderCache::get(); auto& cache = skiapipeline::ShaderCache::get(); cache.initShaderDiskCache(identity, size); contextOptions->fPersistentCache = &cache; contextOptions->fGpuPathRenderers &= ~GpuPathRenderers::kCoverageCounting; } Loading
libs/hwui/renderthread/CacheManager.h +1 −1 Original line number Diff line number Diff line Loading @@ -44,7 +44,7 @@ class CacheManager { public: enum class TrimMemoryMode { Complete, UiHidden }; void configureContext(GrContextOptions* context); void configureContext(GrContextOptions* context, const void* identity, ssize_t size); void trimMemory(TrimMemoryMode mode); void trimStaleResources(); void dumpMemoryUsage(String8& log, const RenderState* renderState = nullptr); Loading