1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2018 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#ifndef MemoryCache_DEFINED
9cb93a386Sopenharmony_ci#define MemoryCache_DEFINED
10cb93a386Sopenharmony_ci
11cb93a386Sopenharmony_ci#include "include/core/SkData.h"
12cb93a386Sopenharmony_ci#include "include/gpu/GrContextOptions.h"
13cb93a386Sopenharmony_ci#include "include/private/SkChecksum.h"
14cb93a386Sopenharmony_ci
15cb93a386Sopenharmony_ci#include <unordered_map>
16cb93a386Sopenharmony_ci
17cb93a386Sopenharmony_cinamespace sk_gpu_test {
18cb93a386Sopenharmony_ci
19cb93a386Sopenharmony_ci/**
20cb93a386Sopenharmony_ci * This class can be used to maintain an in memory record of all programs cached by GrContext.
21cb93a386Sopenharmony_ci * It can be shared by multiple GrContexts so long as those GrContexts are created with the same
22cb93a386Sopenharmony_ci * options and will have the same GrCaps (e.g. same backend, same GL context creation parameters,
23cb93a386Sopenharmony_ci * ...).
24cb93a386Sopenharmony_ci */
25cb93a386Sopenharmony_ciclass MemoryCache : public GrContextOptions::PersistentCache {
26cb93a386Sopenharmony_cipublic:
27cb93a386Sopenharmony_ci    MemoryCache() = default;
28cb93a386Sopenharmony_ci    MemoryCache(const MemoryCache&) = delete;
29cb93a386Sopenharmony_ci    MemoryCache& operator=(const MemoryCache&) = delete;
30cb93a386Sopenharmony_ci    void reset() {
31cb93a386Sopenharmony_ci        this->resetCacheStats();
32cb93a386Sopenharmony_ci        fMap.clear();
33cb93a386Sopenharmony_ci    }
34cb93a386Sopenharmony_ci
35cb93a386Sopenharmony_ci    sk_sp<SkData> load(const SkData& key) override;
36cb93a386Sopenharmony_ci    void store(const SkData& key, const SkData& data, const SkString& description) override;
37cb93a386Sopenharmony_ci    int numCacheMisses() const { return fCacheMissCnt; }
38cb93a386Sopenharmony_ci    int numCacheStores() const { return fCacheStoreCnt; }
39cb93a386Sopenharmony_ci    void resetCacheStats() {
40cb93a386Sopenharmony_ci        fCacheMissCnt = 0;
41cb93a386Sopenharmony_ci        fCacheStoreCnt = 0;
42cb93a386Sopenharmony_ci    }
43cb93a386Sopenharmony_ci
44cb93a386Sopenharmony_ci    void writeShadersToDisk(const char* path, GrBackendApi backend);
45cb93a386Sopenharmony_ci
46cb93a386Sopenharmony_ci    template <typename Fn>
47cb93a386Sopenharmony_ci    void foreach(Fn&& fn) {
48cb93a386Sopenharmony_ci        for (auto it = fMap.begin(); it != fMap.end(); ++it) {
49cb93a386Sopenharmony_ci            fn(it->first.fKey, it->second.fData, it->second.fDescription, it->second.fHitCount);
50cb93a386Sopenharmony_ci        }
51cb93a386Sopenharmony_ci    }
52cb93a386Sopenharmony_ci
53cb93a386Sopenharmony_ciprivate:
54cb93a386Sopenharmony_ci    struct Key {
55cb93a386Sopenharmony_ci        Key() = default;
56cb93a386Sopenharmony_ci        Key(const SkData& key) : fKey(SkData::MakeWithCopy(key.data(), key.size())) {}
57cb93a386Sopenharmony_ci        Key(const Key& that) = default;
58cb93a386Sopenharmony_ci        Key& operator=(const Key&) = default;
59cb93a386Sopenharmony_ci        bool operator==(const Key& that) const {
60cb93a386Sopenharmony_ci            return that.fKey->size() == fKey->size() &&
61cb93a386Sopenharmony_ci                   !memcmp(fKey->data(), that.fKey->data(), that.fKey->size());
62cb93a386Sopenharmony_ci        }
63cb93a386Sopenharmony_ci        sk_sp<const SkData> fKey;
64cb93a386Sopenharmony_ci    };
65cb93a386Sopenharmony_ci
66cb93a386Sopenharmony_ci    struct Value {
67cb93a386Sopenharmony_ci        Value() = default;
68cb93a386Sopenharmony_ci        Value(const SkData& data, const SkString& description)
69cb93a386Sopenharmony_ci            : fData(SkData::MakeWithCopy(data.data(), data.size()))
70cb93a386Sopenharmony_ci            , fDescription(description)
71cb93a386Sopenharmony_ci            , fHitCount(1) {}
72cb93a386Sopenharmony_ci        Value(const Value& that) = default;
73cb93a386Sopenharmony_ci        Value& operator=(const Value&) = default;
74cb93a386Sopenharmony_ci
75cb93a386Sopenharmony_ci        sk_sp<SkData> fData;
76cb93a386Sopenharmony_ci        SkString      fDescription;
77cb93a386Sopenharmony_ci        int           fHitCount;
78cb93a386Sopenharmony_ci    };
79cb93a386Sopenharmony_ci
80cb93a386Sopenharmony_ci    struct Hash {
81cb93a386Sopenharmony_ci        using argument_type = Key;
82cb93a386Sopenharmony_ci        using result_type = uint32_t;
83cb93a386Sopenharmony_ci        uint32_t operator()(const Key& key) const {
84cb93a386Sopenharmony_ci            return key.fKey ? SkOpts::hash_fn(key.fKey->data(), key.fKey->size(), 0) : 0;
85cb93a386Sopenharmony_ci        }
86cb93a386Sopenharmony_ci    };
87cb93a386Sopenharmony_ci
88cb93a386Sopenharmony_ci    int fCacheMissCnt = 0;
89cb93a386Sopenharmony_ci    int fCacheStoreCnt = 0;
90cb93a386Sopenharmony_ci    std::unordered_map<Key, Value, Hash> fMap;
91cb93a386Sopenharmony_ci};
92cb93a386Sopenharmony_ci
93cb93a386Sopenharmony_ci}  // namespace sk_gpu_test
94cb93a386Sopenharmony_ci
95cb93a386Sopenharmony_ci#endif
96