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