• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/private/GrTypesPriv.h"
12 #include "include/private/SkTArray.h"
13 #include "include/private/SkTo.h"
14 
15 class GrCaps;
16 class GrProgramInfo;
17 class GrRenderTarget;
18 class GrShaderCaps;
19 
20 /** This class is used to generate a generic program cache key. The Dawn, Metal and Vulkan
21  *  backends derive backend-specific versions which add additional information.
22  */
23 class GrProgramDesc {
24 public:
GrProgramDesc(const GrProgramDesc & other)25     GrProgramDesc(const GrProgramDesc& other) : fKey(other.fKey) {}   // for SkLRUCache
26 
isValid()27     bool isValid() const { return !fKey.empty(); }
28 
29     // Returns this as a uint32_t array to be used as a key in the program cache.
asKey()30     const uint32_t* asKey() const {
31         return reinterpret_cast<const uint32_t*>(fKey.begin());
32     }
33 
34     // Gets the number of bytes in asKey(). It will be a 4-byte aligned value.
keyLength()35     uint32_t keyLength() const {
36         SkASSERT(0 == (fKey.count() % 4));
37         return fKey.count();
38     }
39 
40     GrProgramDesc& operator= (const GrProgramDesc& other) {
41         uint32_t keyLength = other.keyLength();
42         fKey.reset(SkToInt(keyLength));
43         memcpy(fKey.begin(), other.fKey.begin(), keyLength);
44         return *this;
45     }
46 
47     bool operator== (const GrProgramDesc& that) const {
48         if (this->keyLength() != that.keyLength()) {
49             return false;
50         }
51 
52         SkASSERT(SkIsAlign4(this->keyLength()));
53         int l = this->keyLength() >> 2;
54         const uint32_t* aKey = this->asKey();
55         const uint32_t* bKey = that.asKey();
56         for (int i = 0; i < l; ++i) {
57             if (aKey[i] != bKey[i]) {
58                 return false;
59             }
60         }
61         return true;
62     }
63 
64     bool operator!= (const GrProgramDesc& other) const {
65         return !(*this == other);
66     }
67 
initialKeyLength()68     uint32_t initialKeyLength() const { return this->header().fInitialKeyLength; }
69 
70 protected:
71     friend class GrDawnCaps;
72     friend class GrD3DCaps;
73     friend class GrGLCaps;
74     friend class GrMockCaps;
75     friend class GrMtlCaps;
76     friend class GrVkCaps;
77 
78     friend class GrGLGpu; // for ProgramCache to access BuildFromData
79 
80     // Creates an uninitialized key that must be populated by Build
GrProgramDesc()81     GrProgramDesc() {}
82 
83     /**
84      * Builds a program descriptor.
85      *
86      * @param desc          The built descriptor
87      * @param renderTarget  The target of the draw
88      * @param programInfo   Program information need to build the key
89      * @param caps          the caps
90      **/
91     static bool Build(GrProgramDesc*, const GrRenderTarget*, const GrProgramInfo&, const GrCaps&);
92 
93     // This is strictly an OpenGL call since the other backends have additional data in their
94     // keys
BuildFromData(GrProgramDesc * desc,const void * keyData,size_t keyLength)95     static bool BuildFromData(GrProgramDesc* desc, const void* keyData, size_t keyLength) {
96         if (!SkTFitsIn<int>(keyLength)) {
97             return false;
98         }
99         desc->fKey.reset(SkToInt(keyLength));
100         memcpy(desc->fKey.begin(), keyData, keyLength);
101         return true;
102     }
103 
104     // TODO: this should be removed and converted to just data added to the key
105     struct KeyHeader {
106         // Set to uniquely identify any swizzling of the shader's output color(s).
107         uint16_t fOutputSwizzle;
108         uint8_t fColorFragmentProcessorCnt; // Can be packed into 4 bits if required.
109         uint8_t fCoverageFragmentProcessorCnt;
110         // Set to uniquely identify the rt's origin, or 0 if the shader does not require this info.
111         uint32_t fSurfaceOriginKey : 2;
112         uint32_t fProcessorFeatures : 1;
113         uint32_t fSnapVerticesToPixelCenters : 1;
114         uint32_t fHasPointSize : 1;
115         // This is the key size (in bytes) after core key construction. It doesn't include any
116         // portions added by the platform-specific backends.
117         uint32_t fInitialKeyLength : 27;
118     };
119     static_assert(sizeof(KeyHeader) == 8);
120 
header()121     const KeyHeader& header() const { return *this->atOffset<KeyHeader, kHeaderOffset>(); }
122 
atOffset()123     template<typename T, size_t OFFSET> T* atOffset() {
124         return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET);
125     }
126 
atOffset()127     template<typename T, size_t OFFSET> const T* atOffset() const {
128         return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET);
129     }
130 
131     // The key, stored in fKey, is composed of two parts:
132     // 1. Header struct defined above.
133     // 2. A Backend specific payload which includes the per-processor keys.
134     enum KeyOffsets {
135         kHeaderOffset = 0,
136         kHeaderSize = SkAlign4(sizeof(KeyHeader)),
137         // This is the offset into the backenend specific part of the key, which includes
138         // per-processor keys.
139         kProcessorKeysOffset = kHeaderOffset + kHeaderSize,
140     };
141 
142     enum {
143         kMaxPreallocProcessors = 8,
144         kIntsPerProcessor      = 4,    // This is an overestimate of the average effect key size.
145         kPreAllocSize = kHeaderOffset + kHeaderSize +
146                         kMaxPreallocProcessors * sizeof(uint32_t) * kIntsPerProcessor,
147     };
148 
key()149     SkSTArray<kPreAllocSize, uint8_t, true>& key() { return fKey; }
150 
151 private:
152     SkSTArray<kPreAllocSize, uint8_t, true> fKey;
153 };
154 
155 #endif
156