Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
MemoryCache.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2018 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "src/base/SkBase64.h"
9#include "src/core/SkMD5.h"
13
14#if defined(SK_VULKAN)
16#endif
17
18// Change this to 1 to log cache hits/misses/stores using SkDebugf.
19#define LOG_MEMORY_CACHE 0
20
21static SkString data_to_str(const SkData& data) {
22 size_t encodeLength = SkBase64::EncodedSize(data.size());
23 SkString str;
24 str.resize(encodeLength);
25 SkBase64::Encode(data.data(), data.size(), str.data());
26 static constexpr size_t kMaxLength = 60;
27 static constexpr char kTail[] = "...";
28 static const size_t kTailLen = strlen(kTail);
29 bool overlength = encodeLength > kMaxLength;
30 if (overlength) {
31 str = SkString(str.c_str(), kMaxLength - kTailLen);
32 str.append(kTail);
33 }
34 return str;
35}
36
37namespace sk_gpu_test {
38
40 auto result = fMap.find(key);
41 if (result == fMap.end()) {
42 if (LOG_MEMORY_CACHE) {
43 SkDebugf("Load Key: %s\n\tNot Found.\n\n", data_to_str(key).c_str());
44 }
45 ++fCacheMissCnt;
46 return nullptr;
47 }
48 if (LOG_MEMORY_CACHE) {
49 SkDebugf("Load Key: %s\n\tFound Data: %s\n\n", data_to_str(key).c_str(),
50 data_to_str(*result->second.fData).c_str());
51 }
52 result->second.fHitCount++;
53 return result->second.fData;
54}
55
56void MemoryCache::store(const SkData& key, const SkData& data, const SkString& description) {
57 if (LOG_MEMORY_CACHE) {
58 SkDebugf("Store Key: %s\n\tData: %s\n\n", data_to_str(key).c_str(),
59 data_to_str(data).c_str());
60 }
61 ++fCacheStoreCnt;
62 fMap[Key(key)] = Value(data, description);
63}
64
65void MemoryCache::writeShadersToDisk(const char* path, GrBackendApi api) {
66 if (GrBackendApi::kOpenGL != api && GrBackendApi::kVulkan != api) {
67 return;
68 }
69
70 for (auto it = fMap.begin(); it != fMap.end(); ++it) {
71 SkMD5 hash;
72 size_t bytesToHash = it->first.fKey->size();
73#if defined(SK_VULKAN)
74 if (GrBackendApi::kVulkan == api) {
75 // Vulkan stores two kinds of data in the cache (shaders and pipelines). The last four
76 // bytes of the key identify which one we have. We only want to extract shaders.
77 // Additionally, we don't want to hash the tag bytes, so we get the same keys as GL,
78 // which is good for cross-checking code generation and performance.
80 SkASSERT(bytesToHash >= sizeof(vkKeyType));
81 bytesToHash -= sizeof(vkKeyType);
82 memcpy(&vkKeyType, it->first.fKey->bytes() + bytesToHash, sizeof(vkKeyType));
84 continue;
85 }
86 }
87#endif
88 hash.write(it->first.fKey->bytes(), bytesToHash);
89 SkMD5::Digest digest = hash.finish();
91
93 std::string shaders[kGrShaderTypeCount];
94 const SkData* data = it->second.fData.get();
95 const SkString& description = it->second.fDescription;
96 SkReadBuffer reader(data->data(), data->size());
97 GrPersistentCacheUtils::GetType(&reader); // Shader type tag
99 interfacesIgnored, kGrShaderTypeCount);
100
101 // Even with the SPIR-V switches, it seems like we must use .spv, or malisc tries to
102 // run glslang on the input.
103 {
104 const char* ext = GrBackendApi::kOpenGL == api ? "frag" : "frag.spv";
105 SkString filename = SkStringPrintf("%s/%s.%s", path, md5.c_str(), ext);
106 SkFILEWStream file(filename.c_str());
107 file.write(shaders[kFragment_GrShaderType].c_str(),
108 shaders[kFragment_GrShaderType].size());
109 }
110 {
111 const char* ext = GrBackendApi::kOpenGL == api ? "vert" : "vert.spv";
112 SkString filename = SkStringPrintf("%s/%s.%s", path, md5.c_str(), ext);
113 SkFILEWStream file(filename.c_str());
114 file.write(shaders[kVertex_GrShaderType].c_str(),
115 shaders[kVertex_GrShaderType].size());
116 }
117
118 if (!description.isEmpty()) {
119 const char* ext = "key";
120 SkString filename = SkStringPrintf("%s/%s.%s", path, md5.c_str(), ext);
121 SkFILEWStream file(filename.c_str());
122 file.write(description.c_str(), description.size());
123 }
124 }
125}
126
127} // namespace sk_gpu_test
static SkMD5::Digest md5(const SkBitmap &bm)
Definition CodecTest.cpp:77
@ kFragment_GrShaderType
@ kVertex_GrShaderType
static const int kGrShaderTypeCount
GrBackendApi
Definition GrTypes.h:95
static SkString data_to_str(const SkData &data)
#define LOG_MEMORY_CACHE
#define SkASSERT(cond)
Definition SkAssert.h:116
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static uint32_t hash(const SkShaderBase::GradientInfo &v)
SK_API SkString static SkString SkStringPrintf()
Definition SkString.h:287
PersistentCacheKeyType
Definition GrVkGpu.h:184
@ kShader_PersistentCacheKeyType
Definition GrVkGpu.h:185
Definition SkMD5.h:19
size_t size() const
Definition SkString.h:131
const char * data() const
Definition SkString.h:132
bool isEmpty() const
Definition SkString.h:130
void append(const char text[])
Definition SkString.h:203
void resize(size_t len)
Definition SkString.cpp:374
const char * c_str() const
Definition SkString.h:133
void writeShadersToDisk(const char *path, GrBackendApi backend)
void store(const SkData &key, const SkData &data, const SkString &description) override
sk_sp< SkData > load(const SkData &key) override
GAsyncResult * result
bool UnpackCachedShaders(SkReadBuffer *reader, std::string shaders[], SkSL::Program::Interface interfaces[], int numInterfaces, ShaderMetadata *meta)
SkFourByteTag GetType(SkReadBuffer *reader)
static size_t EncodedSize(size_t srcDataLength)
Definition SkBase64.h:40
static size_t Encode(const void *src, size_t length, void *dst, const char *encode=nullptr)
Definition SkBase64.cpp:113
SkString toLowercaseHexString() const
Definition SkMD5.cpp:116