xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrPersistentCacheUtils.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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