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 #ifndef skgpu_KeyBuilder_DEFINED 9 #define skgpu_KeyBuilder_DEFINED 10 11 #include "include/core/SkString.h" 12 #include "include/private/base/SkTArray.h" 13 14 namespace skgpu { 15 16 class KeyBuilder { 17 public: KeyBuilder(SkTArray<uint32_t,true> * data)18 KeyBuilder(SkTArray<uint32_t, true>* data) : fData(data) {} 19 ~KeyBuilder()20 virtual ~KeyBuilder() { 21 // Ensure that flush was called before we went out of scope 22 SkASSERT(fBitsUsed == 0); 23 } 24 addBits(uint32_t numBits,uint32_t val,std::string_view label)25 virtual void addBits(uint32_t numBits, uint32_t val, std::string_view label) { 26 SkASSERT(numBits > 0 && numBits <= 32); 27 SkASSERT(numBits == 32 || (val < (1u << numBits))); 28 29 fCurValue |= (val << fBitsUsed); 30 fBitsUsed += numBits; 31 32 if (fBitsUsed >= 32) { 33 // Overflow, start a new working value 34 fData->push_back(fCurValue); 35 uint32_t excess = fBitsUsed - 32; 36 fCurValue = excess ? (val >> (numBits - excess)) : 0; 37 fBitsUsed = excess; 38 } 39 40 SkASSERT(fCurValue < (1u << fBitsUsed)); 41 } 42 addBytes(uint32_t numBytes,const void * data,std::string_view label)43 void addBytes(uint32_t numBytes, const void* data, std::string_view label) { 44 const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data); 45 for (; numBytes --> 0; bytes++) { 46 this->addBits(8, *bytes, label); 47 } 48 } 49 addBool(bool b,std::string_view label)50 void addBool(bool b, std::string_view label) { 51 this->addBits(1, b, label); 52 } 53 54 void add32(uint32_t v, std::string_view label = "unknown") { 55 this->addBits(32, v, label); 56 } 57 appendComment(const char * comment)58 virtual void appendComment(const char* comment) {} 59 60 // Introduces a word-boundary in the key. Must be called before using the key with any cache, 61 // but can also be called to create a break between generic data and backend-specific data. flush()62 void flush() { 63 if (fBitsUsed) { 64 fData->push_back(fCurValue); 65 fCurValue = 0; 66 fBitsUsed = 0; 67 } 68 } 69 70 private: 71 SkTArray<uint32_t, true>* fData; 72 uint32_t fCurValue = 0; 73 uint32_t fBitsUsed = 0; // ... in current value 74 }; 75 76 class StringKeyBuilder : public KeyBuilder { 77 public: StringKeyBuilder(SkTArray<uint32_t,true> * data)78 StringKeyBuilder(SkTArray<uint32_t, true>* data) : KeyBuilder(data) {} 79 addBits(uint32_t numBits,uint32_t val,std::string_view label)80 void addBits(uint32_t numBits, uint32_t val, std::string_view label) override { 81 KeyBuilder::addBits(numBits, val, label); 82 fDescription.appendf("%.*s: %u\n", (int)label.size(), label.data(), val); 83 } 84 appendComment(const char * comment)85 void appendComment(const char* comment) override { 86 fDescription.appendf("%s\n", comment); 87 } 88 description()89 SkString description() const { return fDescription; } 90 91 private: 92 SkString fDescription; 93 }; 94 95 } // namespace skgpu 96 97 #endif // skgpu_KeyBuilder_DEFINED 98