1 /*
2 * Copyright 2021 Google LLC
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/gpu/ganesh/GrPersistentCacheUtils.h"
9
10 #include "src/core/SkReadBuffer.h"
11 #include "src/core/SkWriteBuffer.h"
12 #include "src/sksl/SkSLProgramSettings.h"
13 #include "src/sksl/SkSLString.h"
14
15 namespace GrPersistentCacheUtils {
16
17 static constexpr int kCurrentVersion = 12;
18
GetCurrentVersion()19 int GetCurrentVersion() {
20 // The persistent cache stores a copy of the SkSL::Program::Interface struct. If you alter the
21 // Program::Interface struct in any way, you must increment kCurrentVersion to invalidate the
22 // outdated persistent cache files. The KnownSkSLProgramInterface struct must also be updated
23 // to match the new contents of Program::Interface.
24 struct KnownSkSLProgramInterface {
25 bool useLastFragColor;
26 bool useRTFlipUniform;
27 bool outputSecondaryColor;
28 };
29 static_assert(sizeof(SkSL::Program::Interface) == sizeof(KnownSkSLProgramInterface));
30
31 return kCurrentVersion;
32 }
33
PackCachedShaders(SkFourByteTag shaderType,const std::string shaders[],const SkSL::Program::Interface interfaces[],int numInterfaces,const ShaderMetadata * meta)34 sk_sp<SkData> PackCachedShaders(SkFourByteTag shaderType,
35 const std::string shaders[],
36 const SkSL::Program::Interface interfaces[],
37 int numInterfaces,
38 const ShaderMetadata* meta) {
39 // For consistency (so tools can blindly pack and unpack cached shaders), we always write
40 // kGrShaderTypeCount interfaces. If the backend gives us fewer, we just replicate the last one.
41 SkASSERT(numInterfaces >= 1 && numInterfaces <= kGrShaderTypeCount);
42
43 SkBinaryWriteBuffer writer({});
44 writer.writeInt(kCurrentVersion);
45 writer.writeUInt(shaderType);
46 for (int i = 0; i < kGrShaderTypeCount; ++i) {
47 writer.writeByteArray(shaders[i].c_str(), shaders[i].size());
48 writer.writePad32(&interfaces[std::min(i, numInterfaces - 1)],
49 sizeof(SkSL::Program::Interface));
50 }
51 writer.writeBool(SkToBool(meta));
52 if (meta) {
53 writer.writeBool(SkToBool(meta->fSettings));
54 if (meta->fSettings) {
55 writer.writeBool(meta->fSettings->fForceNoRTFlip);
56 writer.writeBool(meta->fSettings->fFragColorIsInOut);
57 writer.writeBool(meta->fSettings->fForceHighPrecision);
58 writer.writeBool(meta->fSettings->fUsePushConstants);
59 }
60
61 writer.writeInt(meta->fAttributeNames.size());
62 for (const auto& attr : meta->fAttributeNames) {
63 writer.writeByteArray(attr.c_str(), attr.size());
64 }
65
66 writer.writeBool(meta->fHasSecondaryColorOutput);
67
68 if (meta->fPlatformData) {
69 writer.writeByteArray(meta->fPlatformData->data(), meta->fPlatformData->size());
70 }
71 }
72 return writer.snapshotAsData();
73 }
74
GetType(SkReadBuffer * reader)75 SkFourByteTag GetType(SkReadBuffer* reader) {
76 constexpr SkFourByteTag kInvalidTag = ~0;
77 int version = reader->readInt();
78 SkFourByteTag typeTag = reader->readUInt();
79 return reader->validate(version == kCurrentVersion) ? typeTag : kInvalidTag;
80 }
81
UnpackCachedShaders(SkReadBuffer * reader,std::string shaders[],SkSL::Program::Interface interfaces[],int numInterfaces,ShaderMetadata * meta)82 bool UnpackCachedShaders(SkReadBuffer* reader,
83 std::string shaders[],
84 SkSL::Program::Interface interfaces[],
85 int numInterfaces,
86 ShaderMetadata* meta) {
87 for (int i = 0; i < kGrShaderTypeCount; ++i) {
88 size_t shaderLen = 0;
89 const char* shaderBuf = static_cast<const char*>(reader->skipByteArray(&shaderLen));
90 if (shaderBuf) {
91 shaders[i].assign(shaderBuf, shaderLen);
92 }
93
94 // GL, for example, only wants one Interface
95 if (i < numInterfaces) {
96 reader->readPad32(&interfaces[i], sizeof(interfaces[i]));
97 } else {
98 reader->skip(sizeof(SkSL::Program::Interface));
99 }
100 }
101 if (reader->readBool() && meta) {
102 SkASSERT(meta->fSettings != nullptr);
103
104 if (reader->readBool()) {
105 meta->fSettings->fForceNoRTFlip = reader->readBool();
106 meta->fSettings->fFragColorIsInOut = reader->readBool();
107 meta->fSettings->fForceHighPrecision = reader->readBool();
108 meta->fSettings->fUsePushConstants = reader->readBool();
109 }
110
111 meta->fAttributeNames.resize(reader->readInt());
112 for (auto& attr : meta->fAttributeNames) {
113 size_t attrLen = 0;
114 const char* attrName = static_cast<const char*>(reader->skipByteArray(&attrLen));
115 if (attrName) {
116 attr.assign(attrName, attrLen);
117 }
118 }
119
120 meta->fHasSecondaryColorOutput = reader->readBool();
121
122 // a given platform will be responsible for reading its data
123 }
124
125 if (!reader->isValid()) {
126 for (int i = 0; i < kGrShaderTypeCount; ++i) {
127 shaders[i].clear();
128 }
129 }
130 return reader->isValid();
131 }
132
133 } // namespace GrPersistentCacheUtils
134