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