Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(742)

Side by Side Diff: src/gpu/GrProgramDesc.h

Issue 674543004: OptState owns program descriptor (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: feedback inc Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2013 Google Inc. 2 * Copyright 2014 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #ifndef GrGLProgramDesc_DEFINED 8 #ifndef GrProgramDesc_DEFINED
9 #define GrGLProgramDesc_DEFINED 9 #define GrProgramDesc_DEFINED
10 10
11 #include "GrGLProcessor.h" 11 #include "GrColor.h"
12 #include "GrDrawState.h"
13 #include "GrGpu.h" 12 #include "GrGpu.h"
14 #include "GrOptDrawState.h" 13 #include "GrTypesPriv.h"
15 14
16 class GrGpuGL; 15 class GrGpuGL;
17 16
18 /** This class describes a program to generate. It also serves as a program cach e key. Very little 17 /** 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. */ 18 of this is GL-specific. The GL-specific parts could be factored out into a s ubclass. */
20 class GrGLProgramDesc { 19 class GrProgramDesc {
21 public: 20 public:
22 GrGLProgramDesc() {} 21 // Dummy constructor creates a zombie descriptor
bsalomon 2014/10/23 18:10:30 This seems like an unhelpful comment. Can you eith
23 GrGLProgramDesc(const GrGLProgramDesc& desc) { *this = desc; } 22 GrProgramDesc() {}
24 23
25 // Returns this as a uint32_t array to be used as a key in the program cache . 24 // Returns this as a uint32_t array to be used as a key in the program cache .
26 const uint32_t* asKey() const { 25 const uint32_t* asKey() const {
27 return reinterpret_cast<const uint32_t*>(fKey.begin()); 26 return reinterpret_cast<const uint32_t*>(fKey.begin());
28 } 27 }
29 28
30 // Gets the number of bytes in asKey(). It will be a 4-byte aligned value. W hen comparing two 29 // 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 30 // 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. 31 // 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> (); } 32 uint32_t keyLength() const { return *this->atOffset<uint32_t, kLengthOffset> (); }
34 33
35 // Gets the a checksum of the key. Can be used as a hash value for a fast lo okup in a cache. 34 // 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>(); } 35 uint32_t getChecksum() const { return *this->atOffset<uint32_t, kChecksumOff set>(); }
37 36
38 /** 37 GrProgramDesc& operator= (const GrProgramDesc& other) {
39 * Builds a program descriptor from a GrOptDrawState. Whether the primitive type is points, and 38 size_t keyLength = other.keyLength();
40 * the caps of the GrGpuGL are also inputs. It also outputs the color and co verage stages 39 fKey.reset(keyLength);
41 * referenced by the generated descriptor. Coverage stages from the drawStat e may be treated as 40 memcpy(fKey.begin(), other.fKey.begin(), keyLength);
42 * color stages in the output. 41 return *this;
43 */
44 static bool Build(const GrOptDrawState&,
45 GrGpu::DrawType,
46 GrGpuGL*,
47 const GrDeviceCoordTexture*,
48 GrGLProgramDesc*);
49
50 bool hasGeometryProcessor() const {
51 return SkToBool(this->getHeader().fHasGeometryProcessor);
52 } 42 }
53 43
54 int numColorEffects() const { 44 bool operator== (const GrProgramDesc& other) const {
55 return this->getHeader().fColorEffectCnt;
56 }
57
58 int numCoverageEffects() const {
59 return this->getHeader().fCoverageEffectCnt;
60 }
61
62 int numTotalEffects() const { return this->numColorEffects() + this->numCove rageEffects(); }
63
64 GrGLProgramDesc& operator= (const GrGLProgramDesc& other);
65
66 bool operator== (const GrGLProgramDesc& other) const {
67 // The length is masked as a hint to the compiler that the address will be 4 byte aligned. 45 // The length is masked as a hint to the compiler that the address will be 4 byte aligned.
68 return 0 == memcmp(this->asKey(), other.asKey(), this->keyLength() & ~0x 3); 46 return 0 == memcmp(this->asKey(), other.asKey(), this->keyLength() & ~0x 3);
69 } 47 }
70 48
71 bool operator!= (const GrGLProgramDesc& other) const { 49 bool operator!= (const GrProgramDesc& other) const {
72 return !(*this == other); 50 return !(*this == other);
73 } 51 }
74 52
75 static bool Less(const GrGLProgramDesc& a, const GrGLProgramDesc& b) { 53 static bool Less(const GrProgramDesc& a, const GrProgramDesc& b) {
76 return memcmp(a.asKey(), b.asKey(), a.keyLength() & ~0x3) < 0; 54 return memcmp(a.asKey(), b.asKey(), a.keyLength() & ~0x3) < 0;
77 } 55 }
78 56
79 private: 57
58 ///////////////////////////////////////////////////////////////////////////
59 /// @name Stage Output Types
60 ////
61
62 enum PrimaryOutputType {
63 // Modulate color and coverage, write result as the color output.
64 kModulate_PrimaryOutputType,
65 // Combines the coverage, dst, and color as coverage * color + (1 - cove rage) * dst. This
66 // can only be set if fDstReadKey is non-zero.
67 kCombineWithDst_PrimaryOutputType,
68
69 kPrimaryOutputTypeCnt,
70 };
71
72 enum SecondaryOutputType {
73 // There is no secondary output
74 kNone_SecondaryOutputType,
75 // Writes coverage as the secondary output. Only set if dual source blen ding is supported
76 // and primary output is kModulate.
77 kCoverage_SecondaryOutputType,
78 // Writes coverage * (1 - colorA) as the secondary output. Only set if d ual source blending
79 // is supported and primary output is kModulate.
80 kCoverageISA_SecondaryOutputType,
81 // Writes coverage * (1 - colorRGBA) as the secondary output. Only set i f dual source
82 // blending is supported and primary output is kModulate.
83 kCoverageISC_SecondaryOutputType,
84
85 kSecondaryOutputTypeCnt,
86 };
87
80 // Specifies where the initial color comes from before the stages are applie d. 88 // Specifies where the initial color comes from before the stages are applie d.
81 enum ColorInput { 89 enum ColorInput {
82 kAllOnes_ColorInput, 90 kAllOnes_ColorInput,
83 kAttribute_ColorInput, 91 kAttribute_ColorInput,
84 kUniform_ColorInput, 92 kUniform_ColorInput,
85 93
86 kColorInputCnt 94 kColorInputCnt
87 }; 95 };
88 96
89 struct KeyHeader { 97 struct KeyHeader {
90 uint8_t fDstReadKey; // set by GrGLShaderBuil der if there 98 uint8_t fDstReadKey; // set by GrGLShaderBuil der if there
bsalomon 2014/10/23 18:10:30 Not broken by your change, but the alignment in he
91 // are effects that must read the dst. 99 // are effects that must read the dst.
92 // Otherwise, 0. 100 // Otherwise, 0.
93 uint8_t fFragPosKey; // set by GrGLShaderBuil der if there are 101 uint8_t fFragPosKey; // set by GrGLShaderBuil der if there are
94 // effects that read the fragment position. 102 // effects that read the fragment position.
95 // Otherwise, 0. 103 // Otherwise, 0.
96 104
97 SkBool8 fUseFragShaderOnly;
98 SkBool8 fEmitsPointSize; 105 SkBool8 fEmitsPointSize;
99 106
100 ColorInput fColorInput : 8; 107 ColorInput fColorInput : 8;
101 ColorInput fCoverageInput : 8; 108 ColorInput fCoverageInput : 8;
102 109
103 GrOptDrawState::PrimaryOutputType fPrimaryOutputType : 8; 110 PrimaryOutputType fPrimaryOutputType : 8;
104 GrOptDrawState::SecondaryOutputType fSecondaryOutputType : 8; 111 SecondaryOutputType fSecondaryOutputType : 8;
105 112
106 int8_t fPositionAttributeIndex; 113 int8_t fPositionAttributeIndex;
107 int8_t fLocalCoordAttributeIndex; 114 int8_t fLocalCoordAttributeIndex;
108 int8_t fColorAttributeIndex; 115 int8_t fColorAttributeIndex;
109 int8_t fCoverageAttributeIndex; 116 int8_t fCoverageAttributeIndex;
110 117
111 SkBool8 fHasGeometryProcessor; 118 SkBool8 fHasGeometryProcessor;
112 int8_t fColorEffectCnt; 119 int8_t fColorEffectCnt;
113 int8_t fCoverageEffectCnt; 120 int8_t fCoverageEffectCnt;
114 }; 121 };
115 122
116 // The key, stored in fKey, is composed of five parts:
117 // 1. uint32_t for total key length.
118 // 2. uint32_t for a checksum.
119 // 3. Header struct defined above.
120 // 4. An array of offsets to effect keys and their sizes (see 5). uint16_t f or each
121 // offset and size.
122 // 5. per-effect keys. Each effect's key is a variable length array of uint3 2_t.
123 enum {
124 // Part 1.
125 kLengthOffset = 0,
126 // Part 2.
127 kChecksumOffset = kLengthOffset + sizeof(uint32_t),
128 // Part 3.
129 kHeaderOffset = kChecksumOffset + sizeof(uint32_t),
130 kHeaderSize = SkAlign4(sizeof(KeyHeader)),
131 // Part 4.
132 // This is the offset in the overall key to the array of per-effect offs et,length pairs.
133 kEffectKeyOffsetsAndLengthOffset = kHeaderOffset + kHeaderSize,
134 };
135 123
136 template<typename T, size_t OFFSET> T* atOffset() { 124 bool hasGeometryProcessor() const {
137 return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.begin()) + O FFSET); 125 return SkToBool(this->header().fHasGeometryProcessor);
138 } 126 }
139 127
140 template<typename T, size_t OFFSET> const T* atOffset() const { 128 int numColorEffects() const {
141 return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.begin( )) + OFFSET); 129 return this->header().fColorEffectCnt;
142 } 130 }
143 131
144 KeyHeader* header() { return this->atOffset<KeyHeader, kHeaderOffset>(); } 132 int numCoverageEffects() const {
133 return this->header().fCoverageEffectCnt;
134 }
145 135
146 // a helper class to handle getting an individual processor's key 136 int numTotalEffects() const { return this->numColorEffects() + this->numCove rageEffects(); }
147 template <class ProcessorKeyBuilder>
148 static bool BuildStagedProcessorKey(const typename ProcessorKeyBuilder::Stag edProcessor& stage,
149 const GrGLCaps& caps,
150 bool requiresLocalCoordAttrib,
151 GrGLProgramDesc* desc,
152 int* offsetAndSizeIndex);
153 void finalize();
154 137
155 const KeyHeader& getHeader() const { return *this->atOffset<KeyHeader, kHead erOffset>(); } 138 // This should really only be used internally, base classes should return th eir own headers
139 const KeyHeader& header() const { return *this->atOffset<KeyHeader, kHeaderO ffset>(); }
156 140
157 /** Used to provide effects' keys to their emitCode() function. */ 141 /** Used to provide effects' keys to their emitCode() function. */
158 class ProcKeyProvider { 142 class ProcKeyProvider {
159 public: 143 public:
160 enum ProcessorType { 144 enum ProcessorType {
161 kGeometry_ProcessorType, 145 kGeometry_ProcessorType,
162 kFragment_ProcessorType, 146 kFragment_ProcessorType,
163 }; 147 };
164 148
165 ProcKeyProvider(const GrGLProgramDesc* desc, ProcessorType type) 149 ProcKeyProvider(const GrProgramDesc* desc, ProcessorType type, int effec tOffset)
166 : fDesc(desc), fBaseIndex(0) { 150 : fDesc(desc), fBaseIndex(0), fEffectOffset(effectOffset) {
167 switch (type) { 151 switch (type) {
168 case kGeometry_ProcessorType: 152 case kGeometry_ProcessorType:
169 // there can be only one 153 // there can be only one
170 fBaseIndex = 0; 154 fBaseIndex = 0;
171 break; 155 break;
172 case kFragment_ProcessorType: 156 case kFragment_ProcessorType:
173 fBaseIndex = desc->hasGeometryProcessor() ? 1 : 0; 157 fBaseIndex = desc->hasGeometryProcessor() ? 1 : 0;
174 break; 158 break;
175 } 159 }
176 } 160 }
177 161
178 GrProcessorKey get(int index) const { 162 GrProcessorKey get(int index) const {
179 const uint16_t* offsetsAndLengths = reinterpret_cast<const uint16_t* >( 163 const uint16_t* offsetsAndLengths = reinterpret_cast<const uint16_t* >(
180 fDesc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset); 164 fDesc->fKey.begin() + fEffectOffset);
181 // We store two uint16_ts per effect, one for the offset to the effe ct's key and one for 165 // We store two uint16_ts per effect, one for the offset to the effe ct's key and one for
182 // its length. Here we just need the offset. 166 // its length. Here we just need the offset.
183 uint16_t offset = offsetsAndLengths[2 * (fBaseIndex + index) + 0]; 167 uint16_t offset = offsetsAndLengths[2 * (fBaseIndex + index) + 0];
184 uint16_t length = offsetsAndLengths[2 * (fBaseIndex + index) + 1]; 168 uint16_t length = offsetsAndLengths[2 * (fBaseIndex + index) + 1];
185 // Currently effects must add to the key in units of uint32_t. 169 // Currently effects must add to the key in units of uint32_t.
186 SkASSERT(0 == (length % sizeof(uint32_t))); 170 SkASSERT(0 == (length % sizeof(uint32_t)));
187 return GrProcessorKey(reinterpret_cast<const uint32_t*>(fDesc->fKey. begin() + offset), 171 return GrProcessorKey(reinterpret_cast<const uint32_t*>(fDesc->fKey. begin() + offset),
188 length / sizeof(uint32_t)); 172 length / sizeof(uint32_t));
189 } 173 }
190 private: 174 private:
191 const GrGLProgramDesc* fDesc; 175 const GrProgramDesc* fDesc;
192 int fBaseIndex; 176 int fBaseIndex;
177 int fEffectOffset;
178 };
179
180 protected:
181
182 template<typename T, size_t OFFSET> T* atOffset() {
183 return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.begin()) + O FFSET);
184 }
185
186 template<typename T, size_t OFFSET> const T* atOffset() const {
187 return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.begin( )) + OFFSET);
188 }
189 // The key, stored in fKey, is composed of five parts:
190 // 1. uint32_t for total key length.
191 // 2. uint32_t for a checksum.
192 // 3. Header struct defined above., also room for derived class headers.
193 // 4. An array of offsets to effect keys and their sizes (see 5). uint16_t f or each
194 // offset and size.
195 // 5. per-effect keys. Each effect's key is a variable length array of uint3 2_t.
196 enum KeyOffsets {
197 // Part 1.
198 kLengthOffset = 0,
199 // Part 2.
200 kChecksumOffset = kLengthOffset + sizeof(uint32_t),
201 // Part 3.
202 kHeaderOffset = kChecksumOffset + sizeof(uint32_t),
203 kHeaderSize = SkAlign4(2 * sizeof(KeyHeader)),
204 // Part 4.
205 // This is the offset in the overall key to the array of per-effect offs et,length pairs.
206 kEffectKeyOffsetsAndLengthOffset = kHeaderOffset + kHeaderSize,
193 }; 207 };
194 208
195 enum { 209 enum {
196 kMaxPreallocEffects = 8, 210 kMaxPreallocEffects = 8,
197 kIntsPerEffect = 4, // This is an overestimate of the average ef fect key size. 211 kIntsPerEffect = 4, // This is an overestimate of the average ef fect key size.
198 kPreAllocSize = kEffectKeyOffsetsAndLengthOffset + 212 kPreAllocSize = kEffectKeyOffsetsAndLengthOffset +
199 kMaxPreallocEffects * sizeof(uint32_t) * kIntsPerEffect, 213 kMaxPreallocEffects * sizeof(uint32_t) * kIntsPerEffect,
200 }; 214 };
201 215
202 SkSTArray<kPreAllocSize, uint8_t, true> fKey; 216 SkSTArray<kPreAllocSize, uint8_t, true> fKey;
203 217
204 // GrGLProgram and GrGLShaderBuilder read the private fields to generate cod e. TODO: Split out 218 friend class GrGLProgramDesc;
205 // part of GrGLShaderBuilder that is used by effects so that this header doe sn't need to be
206 // visible to GrGLProcessors. Then make public accessors as necessary and re move friends.
207 friend class GrGLProgram;
208 friend class GrGLProgramBuilder;
209 friend class GrGLLegacyNvprProgramBuilder;
210 friend class GrGLVertexBuilder;
211 friend class GrGLFragmentShaderBuilder;
212 friend class GrGLGeometryBuilder;
213 }; 219 };
214 220
215 #endif 221 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698