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