1 /* 2 * Copyright 2014 Google Inc. 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 GrProgramDesc_DEFINED 9 #define GrProgramDesc_DEFINED 10 11 #include "include/core/SkString.h" 12 #include "include/private/base/SkAlign.h" 13 #include "include/private/base/SkTArray.h" 14 #include "include/private/base/SkTFitsIn.h" 15 #include "include/private/base/SkTo.h" 16 17 #include <cstdint> 18 #include <cstring> 19 20 class GrCaps; 21 class GrProgramInfo; 22 23 /** This class is used to generate a generic program cache key. The Dawn, Metal and Vulkan 24 * backends derive backend-specific versions which add additional information. 25 */ 26 class GrProgramDesc { 27 public: 28 GrProgramDesc(const GrProgramDesc& other) = default; 29 GrProgramDesc& operator=(const GrProgramDesc &other) = default; 30 isValid()31 bool isValid() const { return !fKey.empty(); } reset()32 void reset() { *this = GrProgramDesc{}; } 33 34 // Returns this as a uint32_t array to be used as a key in the program cache. asKey()35 const uint32_t* asKey() const { 36 return fKey.data(); 37 } 38 39 // Gets the number of bytes in asKey(). It will be a 4-byte aligned value. keyLength()40 uint32_t keyLength() const { 41 return SkToU32(fKey.size() * sizeof(uint32_t)); 42 } 43 44 bool operator== (const GrProgramDesc& that) const { 45 return this->fKey == that.fKey; 46 } 47 48 bool operator!= (const GrProgramDesc& other) const { 49 return !(*this == other); 50 } 51 initialKeyLength()52 uint32_t initialKeyLength() const { return fInitialKeyLength; } 53 54 // TODO(skia:11372): Incorporate this into caps interface (part of makeDesc, or a parallel 55 // function), so other backends can include their information in the description. 56 static SkString Describe(const GrProgramInfo&, const GrCaps&); 57 58 protected: 59 friend class GrDawnCaps; 60 friend class GrD3DCaps; 61 friend class GrGLCaps; 62 friend class GrMockCaps; 63 friend class GrMtlCaps; 64 friend class GrVkCaps; 65 66 friend class GrGLGpu; // for ProgramCache to access BuildFromData 67 friend class GrMtlResourceProvider; // for PipelineStateCache to access BuildFromData 68 69 // Creates an uninitialized key that must be populated by Build GrProgramDesc()70 GrProgramDesc() {} 71 72 /** 73 * Builds a program descriptor. 74 * 75 * @param desc The built descriptor 76 * @param programInfo Program information need to build the key 77 * @param caps the caps 78 **/ 79 static void Build(GrProgramDesc*, const GrProgramInfo&, const GrCaps&); 80 81 // This is strictly an OpenGL call since the other backends have additional data in their keys. BuildFromData(GrProgramDesc * desc,const void * keyData,size_t keyLength)82 static bool BuildFromData(GrProgramDesc* desc, const void* keyData, size_t keyLength) { 83 if (!SkTFitsIn<int>(keyLength) || !SkIsAlign4(keyLength)) { 84 return false; 85 } 86 desc->fKey.reset(SkToInt(keyLength / 4)); 87 memcpy(desc->fKey.begin(), keyData, keyLength); 88 return true; 89 } 90 91 static constexpr size_t kHeaderSize = 1; // "header" in ::Build 92 static constexpr size_t kMaxPreallocProcessors = 8; 93 // This is an overestimate of the average effect key size. 94 static constexpr size_t kIntsPerProcessor = 4; 95 static constexpr size_t kPreAllocSize = 96 kHeaderSize + kMaxPreallocProcessors * kIntsPerProcessor; 97 98 using KeyType = skia_private::STArray<kPreAllocSize, uint32_t, true>; 99 key()100 KeyType* key() { return &fKey; } 101 102 private: 103 skia_private::STArray<kPreAllocSize, uint32_t, true> fKey; 104 uint32_t fInitialKeyLength = 0; 105 }; 106 107 #endif 108