• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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