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