Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0a874d25 authored by Sean Callanan's avatar Sean Callanan Committed by Android (Google) Code Review
Browse files

Merge "Add cache validation to ensure the validity"

parents f66fddf4 9f959556
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ cc_defaults {
        "libft2",
        "libminikin",
        "libandroidfw",
        "libcrypto",
    ],
    static_libs: [
        "libEGL_blobCache",
+50 −6
Original line number Diff line number Diff line
@@ -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"
@@ -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);

@@ -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;
    }
}
@@ -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);
@@ -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();
    }
+41 −5
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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
@@ -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
};

+4 −3
Original line number Diff line number Diff line
@@ -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) {
@@ -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;
@@ -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;
}

+1 −1
Original line number Diff line number Diff line
@@ -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