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