OLD | NEW |
---|---|
(Empty) | |
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 "GrBackendProcessorFactory.h" | |
12 #include "GrColor.h" | |
13 #include "GrTypesPriv.h" | |
14 #include "SkChecksum.h" | |
15 | |
16 class GrGpuGL; | |
17 | |
18 /** This class describes a program to generate. It also serves as a program cach e key. Very little | |
19 of this is GL-specific. The GL-specific parts could be factored out into a s ubclass. */ | |
20 class GrProgramDesc { | |
21 public: | |
22 // Creates an uninitialized key that must be populated populated by GrGpu::b uildKey() | |
bsalomon
2014/10/23 19:47:19
::buildProgramDesc now, right?
| |
23 GrProgramDesc() {} | |
24 | |
25 // Returns this as a uint32_t array to be used as a key in the program cache . | |
26 const uint32_t* asKey() const { | |
27 return reinterpret_cast<const uint32_t*>(fKey.begin()); | |
28 } | |
29 | |
30 // Gets the number of bytes in asKey(). It will be a 4-byte aligned value. W hen comparing two | |
31 // keys the size of either key can be used with memcmp() since the lengths t hemselves begin the | |
32 // keys and thus the memcmp will exit early if the keys are of different len gths. | |
33 uint32_t keyLength() const { return *this->atOffset<uint32_t, kLengthOffset> (); } | |
34 | |
35 // Gets the a checksum of the key. Can be used as a hash value for a fast lo okup in a cache. | |
36 uint32_t getChecksum() const { return *this->atOffset<uint32_t, kChecksumOff set>(); } | |
37 | |
38 GrProgramDesc& operator= (const GrProgramDesc& other) { | |
39 size_t keyLength = other.keyLength(); | |
40 fKey.reset(keyLength); | |
41 memcpy(fKey.begin(), other.fKey.begin(), keyLength); | |
42 return *this; | |
43 } | |
44 | |
45 bool operator== (const GrProgramDesc& other) const { | |
46 // The length is masked as a hint to the compiler that the address will be 4 byte aligned. | |
47 return 0 == memcmp(this->asKey(), other.asKey(), this->keyLength() & ~0x 3); | |
48 } | |
49 | |
50 bool operator!= (const GrProgramDesc& other) const { | |
51 return !(*this == other); | |
52 } | |
53 | |
54 static bool Less(const GrProgramDesc& a, const GrProgramDesc& b) { | |
55 return memcmp(a.asKey(), b.asKey(), a.keyLength() & ~0x3) < 0; | |
56 } | |
57 | |
58 | |
59 /////////////////////////////////////////////////////////////////////////// | |
60 /// @name Stage Output Types | |
61 //// | |
62 | |
63 enum PrimaryOutputType { | |
64 // Modulate color and coverage, write result as the color output. | |
65 kModulate_PrimaryOutputType, | |
66 // Combines the coverage, dst, and color as coverage * color + (1 - cove rage) * dst. This | |
67 // can only be set if fDstReadKey is non-zero. | |
68 kCombineWithDst_PrimaryOutputType, | |
69 | |
70 kPrimaryOutputTypeCnt, | |
71 }; | |
72 | |
73 enum SecondaryOutputType { | |
74 // There is no secondary output | |
75 kNone_SecondaryOutputType, | |
76 // Writes coverage as the secondary output. Only set if dual source blen ding is supported | |
77 // and primary output is kModulate. | |
78 kCoverage_SecondaryOutputType, | |
79 // Writes coverage * (1 - colorA) as the secondary output. Only set if d ual source blending | |
80 // is supported and primary output is kModulate. | |
81 kCoverageISA_SecondaryOutputType, | |
82 // Writes coverage * (1 - colorRGBA) as the secondary output. Only set i f dual source | |
83 // blending is supported and primary output is kModulate. | |
84 kCoverageISC_SecondaryOutputType, | |
85 | |
86 kSecondaryOutputTypeCnt, | |
87 }; | |
88 | |
89 // Specifies where the initial color comes from before the stages are applie d. | |
90 enum ColorInput { | |
91 kAllOnes_ColorInput, | |
92 kAttribute_ColorInput, | |
93 kUniform_ColorInput, | |
94 | |
95 kColorInputCnt | |
96 }; | |
97 | |
98 struct KeyHeader { | |
99 uint8_t fDstReadKey; // set by GrGLShaderBuilder i f there | |
100 // are effects that must read the dst. | |
101 // Otherwise, 0. | |
102 uint8_t fFragPosKey; // set by GrGLShaderBuilder i f there are | |
103 // effects that read the frag ment position. | |
104 // Otherwise, 0. | |
105 | |
106 SkBool8 fEmitsPointSize; | |
107 | |
108 ColorInput fColorInput : 8; | |
109 ColorInput fCoverageInput : 8; | |
110 | |
111 PrimaryOutputType fPrimaryOutputType : 8; | |
112 SecondaryOutputType fSecondaryOutputType : 8; | |
113 | |
114 int8_t fPositionAttributeIndex; | |
115 int8_t fLocalCoordAttributeIndex; | |
116 int8_t fColorAttributeIndex; | |
117 int8_t fCoverageAttributeIndex; | |
118 | |
119 SkBool8 fHasGeometryProcessor; | |
120 int8_t fColorEffectCnt; | |
121 int8_t fCoverageEffectCnt; | |
122 }; | |
123 | |
124 | |
125 bool hasGeometryProcessor() const { | |
126 return SkToBool(this->header().fHasGeometryProcessor); | |
127 } | |
128 | |
129 int numColorEffects() const { | |
130 return this->header().fColorEffectCnt; | |
131 } | |
132 | |
133 int numCoverageEffects() const { | |
134 return this->header().fCoverageEffectCnt; | |
135 } | |
136 | |
137 int numTotalEffects() const { return this->numColorEffects() + this->numCove rageEffects(); } | |
138 | |
139 // This should really only be used internally, base classes should return th eir own headers | |
140 const KeyHeader& header() const { return *this->atOffset<KeyHeader, kHeaderO ffset>(); } | |
141 | |
142 /** Used to provide effects' keys to their emitCode() function. */ | |
143 class ProcKeyProvider { | |
144 public: | |
145 enum ProcessorType { | |
146 kGeometry_ProcessorType, | |
147 kFragment_ProcessorType, | |
148 }; | |
149 | |
150 ProcKeyProvider(const GrProgramDesc* desc, ProcessorType type, int effec tOffset) | |
151 : fDesc(desc), fBaseIndex(0), fEffectOffset(effectOffset) { | |
152 switch (type) { | |
153 case kGeometry_ProcessorType: | |
154 // there can be only one | |
155 fBaseIndex = 0; | |
156 break; | |
157 case kFragment_ProcessorType: | |
158 fBaseIndex = desc->hasGeometryProcessor() ? 1 : 0; | |
159 break; | |
160 } | |
161 } | |
162 | |
163 GrProcessorKey get(int index) const { | |
164 const uint16_t* offsetsAndLengths = reinterpret_cast<const uint16_t* >( | |
165 fDesc->fKey.begin() + fEffectOffset); | |
166 // We store two uint16_ts per effect, one for the offset to the effe ct's key and one for | |
167 // its length. Here we just need the offset. | |
168 uint16_t offset = offsetsAndLengths[2 * (fBaseIndex + index) + 0]; | |
169 uint16_t length = offsetsAndLengths[2 * (fBaseIndex + index) + 1]; | |
170 // Currently effects must add to the key in units of uint32_t. | |
171 SkASSERT(0 == (length % sizeof(uint32_t))); | |
172 return GrProcessorKey(reinterpret_cast<const uint32_t*>(fDesc->fKey. begin() + offset), | |
173 length / sizeof(uint32_t)); | |
174 } | |
175 private: | |
176 const GrProgramDesc* fDesc; | |
177 int fBaseIndex; | |
178 int fEffectOffset; | |
179 }; | |
180 | |
181 // A struct to communicate descriptor information to the program descriptor builder | |
182 struct DescInfo { | |
183 int positionAttributeIndex() const { | |
184 return fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBin ding]; | |
185 } | |
186 int localCoordAttributeIndex() const { | |
187 return fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribB inding]; | |
188 } | |
189 int colorVertexAttributeIndex() const { | |
190 return fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBindin g]; | |
191 } | |
192 int coverageVertexAttributeIndex() const { | |
193 return fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBin ding]; | |
194 } | |
195 bool hasLocalCoordAttribute() const { | |
196 return -1 != fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexA ttribBinding]; | |
197 } | |
198 bool hasColorVertexAttribute() const { | |
199 return -1 != fFixedFunctionVertexAttribIndices[kColor_GrVertexAttrib Binding]; | |
200 } | |
201 bool hasCoverageVertexAttribute() const { | |
202 return -1 != fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAtt ribBinding]; | |
203 } | |
204 | |
205 // This is simply a different representation of info in fVertexAttribs a nd thus does | |
bsalomon
2014/10/23 19:47:19
comment seems out of place now.
| |
206 // not need to be compared in op==. | |
207 int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindin gCnt]; | |
208 | |
209 // These flags are needed to protect the code from creating an unused un iform color/coverage | |
210 // which will cause shader compiler errors. | |
211 bool fInputColorIsUsed; | |
212 bool fInputCoverageIsUsed; | |
213 | |
214 // These flags give aggregated info on the effect stages that are used w hen building programs. | |
bsalomon
2014/10/23 19:47:19
wrap
| |
215 bool fReadsDst; | |
216 bool fReadsFragPosition; | |
217 bool fRequiresLocalCoordAttrib; | |
218 | |
219 // Fragment shader color outputs | |
220 GrProgramDesc::PrimaryOutputType fPrimaryOutputType : 8; | |
221 GrProgramDesc::SecondaryOutputType fSecondaryOutputType : 8; | |
222 }; | |
223 | |
224 private: | |
225 template<typename T, size_t OFFSET> T* atOffset() { | |
226 return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.begin()) + O FFSET); | |
227 } | |
228 | |
229 template<typename T, size_t OFFSET> const T* atOffset() const { | |
230 return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.begin( )) + OFFSET); | |
231 } | |
232 | |
233 void finalize() { | |
234 int keyLength = fKey.count(); | |
235 SkASSERT(0 == (keyLength % 4)); | |
236 *(this->atOffset<uint32_t, GrProgramDesc::kLengthOffset>()) = SkToU32(ke yLength); | |
237 | |
238 uint32_t* checksum = this->atOffset<uint32_t, GrProgramDesc::kChecksumOf fset>(); | |
239 *checksum = 0; | |
240 *checksum = SkChecksum::Compute(reinterpret_cast<uint32_t*>(fKey.begin() ), keyLength); | |
241 } | |
242 | |
243 // The key, stored in fKey, is composed of five parts: | |
bsalomon
2014/10/23 19:47:19
Maybe change 4 and 5 to just be "backend-specific
| |
244 // 1. uint32_t for total key length. | |
245 // 2. uint32_t for a checksum. | |
246 // 3. Header struct defined above. Also room for extensions to the header | |
247 // 4. An array of offsets to effect keys and their sizes (see 5). uint16_t f or each | |
248 // offset and size. | |
249 // 5. per-effect keys. Each effect's key is a variable length array of uint3 2_t. | |
250 enum KeyOffsets { | |
251 // Part 1. | |
252 kLengthOffset = 0, | |
253 // Part 2. | |
254 kChecksumOffset = kLengthOffset + sizeof(uint32_t), | |
255 // Part 3. | |
256 kHeaderOffset = kChecksumOffset + sizeof(uint32_t), | |
257 kHeaderSize = SkAlign4(2 * sizeof(KeyHeader)), | |
258 // Part 4. | |
259 // This is the offset in the overall key to the array of per-effect offs et,length pairs. | |
260 kEffectKeyOffsetsAndLengthOffset = kHeaderOffset + kHeaderSize, | |
bsalomon
2014/10/23 19:47:20
This seems wrong now to have here now, right?
| |
261 }; | |
262 | |
263 enum { | |
264 kMaxPreallocEffects = 8, | |
265 kIntsPerEffect = 4, // This is an overestimate of the average ef fect key size. | |
266 kPreAllocSize = kEffectKeyOffsetsAndLengthOffset + | |
267 kMaxPreallocEffects * sizeof(uint32_t) * kIntsPerEffect, | |
268 }; | |
269 | |
270 SkSTArray<kPreAllocSize, uint8_t, true> fKey; | |
271 | |
272 friend class GrGLProgramDescBuilder; | |
273 }; | |
274 | |
275 #endif | |
OLD | NEW |