1 /* 2 * Copyright 2019 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 #ifndef GrPersistentCacheEntry_DEFINED 9 #define GrPersistentCacheEntry_DEFINED 10 11 #include "include/core/SkData.h" 12 #include "include/private/GrTypesPriv.h" 13 #include "src/core/SkReader32.h" 14 #include "src/core/SkWriter32.h" 15 #include "src/sksl/SkSLString.h" 16 #include "src/sksl/ir/SkSLProgram.h" 17 18 // The GrPersistentCache stores opaque blobs, as far as clients are concerned. It's helpful to 19 // inspect certain kinds of cached data within our tools, so for those cases (GLSL, SPIR-V), we 20 // put the serialization logic here, to be shared by the backend code and the tool code. 21 namespace GrPersistentCacheUtils { 22 23 struct ShaderMetadata { 24 SkSL::Program::Settings* fSettings = nullptr; 25 SkTArray<SkSL::String> fAttributeNames; 26 bool fHasCustomColorOutput = false; 27 bool fHasSecondaryColorOutput = false; 28 }; 29 30 static inline sk_sp<SkData> PackCachedShaders(SkFourByteTag shaderType, 31 const SkSL::String shaders[], 32 const SkSL::Program::Inputs inputs[], 33 int numInputs, 34 const ShaderMetadata* meta = nullptr) { 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 SkWriter32 writer; 40 writer.write32(shaderType); 41 for (int i = 0; i < kGrShaderTypeCount; ++i) { 42 writer.writeString(shaders[i].c_str(), shaders[i].size()); 43 writer.writePad(&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->fFlipY); 50 writer.writeBool(meta->fSettings->fFragColorIsInOut); 51 writer.writeBool(meta->fSettings->fForceHighPrecision); 52 } 53 54 writer.writeInt(meta->fAttributeNames.count()); 55 for (const auto& attr : meta->fAttributeNames) { 56 writer.writeString(attr.c_str(), attr.size()); 57 } 58 59 writer.writeBool(meta->fHasCustomColorOutput); 60 writer.writeBool(meta->fHasSecondaryColorOutput); 61 } 62 return writer.snapshotAsData(); 63 } 64 65 static inline void UnpackCachedShaders(SkReader32* reader, 66 SkSL::String shaders[], 67 SkSL::Program::Inputs inputs[], 68 int numInputs, 69 ShaderMetadata* meta = nullptr) { 70 for (int i = 0; i < kGrShaderTypeCount; ++i) { 71 size_t stringLen = 0; 72 const char* string = reader->readString(&stringLen); 73 shaders[i] = SkSL::String(string, stringLen); 74 75 // GL, for example, only wants one set of Inputs 76 if (i < numInputs) { 77 reader->read(&inputs[i], sizeof(inputs[i])); 78 } else { 79 reader->skip(sizeof(SkSL::Program::Inputs)); 80 } 81 } 82 if (reader->readBool() && meta) { 83 SkASSERT(meta->fSettings != nullptr); 84 85 if (reader->readBool()) { 86 meta->fSettings->fFlipY = reader->readBool(); 87 meta->fSettings->fFragColorIsInOut = reader->readBool(); 88 meta->fSettings->fForceHighPrecision = reader->readBool(); 89 } 90 91 meta->fAttributeNames.resize(reader->readInt()); 92 for (int i = 0; i < meta->fAttributeNames.count(); ++i) { 93 size_t stringLen = 0; 94 const char* string = reader->readString(&stringLen); 95 meta->fAttributeNames[i] = SkSL::String(string, stringLen); 96 } 97 98 meta->fHasCustomColorOutput = reader->readBool(); 99 meta->fHasSecondaryColorOutput = reader->readBool(); 100 } 101 } 102 103 } 104 105 #endif 106