• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2013 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 GrGeometryProcessor_DEFINED
9 #define GrGeometryProcessor_DEFINED
10 
11 #include "src/gpu/GrColor.h"
12 #include "src/gpu/GrNonAtomicRef.h"
13 #include "src/gpu/GrProcessor.h"
14 #include "src/gpu/GrShaderVar.h"
15 #include "src/gpu/GrSwizzle.h"
16 
17 class GrGLSLGeometryProcessor;
18 class GrGLSLUniformHandler;
19 
20 /**
21  * The GrGeometryProcessor represents some kind of geometric primitive.  This includes the shape
22  * of the primitive and the inherent color of the primitive.  The GrGeometryProcessor is
23  * responsible for providing a color and coverage input into the Ganesh rendering pipeline. Through
24  * optimization, Ganesh may decide a different color, no color, and / or no coverage are required
25  * from the GrGeometryProcessor, so the GrGeometryProcessor must be able to support this
26  * functionality.
27  *
28  * There are two feedback loops between the GrFragmentProcessors, the GrXferProcessor, and the
29  * GrGeometryProcessor. These loops run on the CPU and to determine known properties of the final
30  * color and coverage inputs to the GrXferProcessor in order to perform optimizations that preserve
31  * correctness. The GrDrawOp seeds these loops with initial color and coverage, in its
32  * getProcessorAnalysisInputs implementation. These seed values are processed by the
33  * subsequent stages of the rendering pipeline and the output is then fed back into the GrDrawOp
34  * in the applyPipelineOptimizations call, where the op can use the information to inform
35  * decisions about GrGeometryProcessor creation.
36  *
37  * Note that all derived classes should hide their constructors and provide a Make factory
38  * function that takes an arena (except for Tesselation-specific classes). This is because
39  * geometry processors can be created in either the record-time or flush-time arenas which
40  * define their lifetimes (i.e., a DDLs life time in the first case and a single flush in
41  * the second case).
42  *
43  * TODO: This class does not really need to be ref counted. Instances should be allocated using
44  * GrOpFlushState's arena and destroyed when the arena is torn down.
45  */
46 class GrGeometryProcessor : public GrProcessor, public GrNonAtomicRef<GrGeometryProcessor> {
47 public:
48     class TextureSampler;
49 
50     /** Describes a vertex or instance attribute. */
51     class Attribute {
52     public:
53         constexpr Attribute() = default;
Attribute(const char * name,GrVertexAttribType cpuType,GrSLType gpuType)54         constexpr Attribute(const char* name,
55                             GrVertexAttribType cpuType,
56                             GrSLType gpuType)
57                 : fName(name), fCPUType(cpuType), fGPUType(gpuType) {
58             SkASSERT(name && gpuType != kVoid_GrSLType);
59         }
60         constexpr Attribute(const Attribute&) = default;
61 
62         Attribute& operator=(const Attribute&) = default;
63 
isInitialized()64         constexpr bool isInitialized() const { return fGPUType != kVoid_GrSLType; }
65 
name()66         constexpr const char* name() const { return fName; }
cpuType()67         constexpr GrVertexAttribType cpuType() const { return fCPUType; }
gpuType()68         constexpr GrSLType           gpuType() const { return fGPUType; }
69 
70         inline constexpr size_t size() const;
sizeAlign4()71         constexpr size_t sizeAlign4() const { return SkAlign4(this->size()); }
72 
asShaderVar()73         GrShaderVar asShaderVar() const {
74             return {fName, fGPUType, GrShaderVar::TypeModifier::In};
75         }
76 
77     private:
78         const char* fName = nullptr;
79         GrVertexAttribType fCPUType = kFloat_GrVertexAttribType;
80         GrSLType fGPUType = kVoid_GrSLType;
81     };
82 
83     class Iter {
84     public:
Iter()85         Iter() : fCurr(nullptr), fRemaining(0) {}
Iter(const Iter & iter)86         Iter(const Iter& iter) : fCurr(iter.fCurr), fRemaining(iter.fRemaining) {}
87         Iter& operator= (const Iter& iter) {
88             fCurr = iter.fCurr;
89             fRemaining = iter.fRemaining;
90             return *this;
91         }
Iter(const Attribute * attrs,int count)92         Iter(const Attribute* attrs, int count) : fCurr(attrs), fRemaining(count) {
93             this->skipUninitialized();
94         }
95 
96         bool operator!=(const Iter& that) const { return fCurr != that.fCurr; }
97         const Attribute& operator*() const { return *fCurr; }
98         void operator++() {
99             if (fRemaining) {
100                 fRemaining--;
101                 fCurr++;
102                 this->skipUninitialized();
103             }
104         }
105 
106     private:
skipUninitialized()107         void skipUninitialized() {
108             if (!fRemaining) {
109                 fCurr = nullptr;
110             } else {
111                 while (!fCurr->isInitialized()) {
112                     ++fCurr;
113                 }
114             }
115         }
116 
117         const Attribute* fCurr;
118         int fRemaining;
119     };
120 
121     class AttributeSet {
122     public:
begin()123         Iter begin() const { return Iter(fAttributes, fCount); }
end()124         Iter end() const { return Iter(); }
125 
count()126         int count() const { return fCount; }
stride()127         size_t stride() const { return fStride; }
128 
129     private:
130         friend class GrGeometryProcessor;
131 
init(const Attribute * attrs,int count)132         void init(const Attribute* attrs, int count) {
133             fAttributes = attrs;
134             fRawCount = count;
135             fCount = 0;
136             fStride = 0;
137             for (int i = 0; i < count; ++i) {
138                 if (attrs[i].isInitialized()) {
139                     fCount++;
140                     fStride += attrs[i].sizeAlign4();
141                 }
142             }
143         }
144 
145         const Attribute* fAttributes = nullptr;
146         int              fRawCount = 0;
147         int              fCount = 0;
148         size_t           fStride = 0;
149     };
150 
151     GrGeometryProcessor(ClassID);
152 
numTextureSamplers()153     int numTextureSamplers() const { return fTextureSamplerCnt; }
154     const TextureSampler& textureSampler(int index) const;
numVertexAttributes()155     int numVertexAttributes() const { return fVertexAttributes.fCount; }
vertexAttributes()156     const AttributeSet& vertexAttributes() const { return fVertexAttributes; }
numInstanceAttributes()157     int numInstanceAttributes() const { return fInstanceAttributes.fCount; }
instanceAttributes()158     const AttributeSet& instanceAttributes() const { return fInstanceAttributes; }
159 
hasVertexAttributes()160     bool hasVertexAttributes() const { return SkToBool(fVertexAttributes.fCount); }
hasInstanceAttributes()161     bool hasInstanceAttributes() const { return SkToBool(fInstanceAttributes.fCount); }
162 
163     /**
164      * A common practice is to populate the the vertex/instance's memory using an implicit array of
165      * structs. In this case, it is best to assert that:
166      *     stride == sizeof(struct)
167      */
vertexStride()168     size_t vertexStride() const { return fVertexAttributes.fStride; }
instanceStride()169     size_t instanceStride() const { return fInstanceAttributes.fStride; }
170 
willUseTessellationShaders()171     bool willUseTessellationShaders() const {
172         return fShaders & (kTessControl_GrShaderFlag | kTessEvaluation_GrShaderFlag);
173     }
174 
willUseGeoShader()175     bool willUseGeoShader() const {
176         return fShaders & kGeometry_GrShaderFlag;
177     }
178 
179     /**
180      * Computes a key for the transforms owned by an FP based on the shader code that will be
181      * emitted by the primitive processor to implement them.
182      */
183     static uint32_t ComputeCoordTransformsKey(const GrFragmentProcessor& fp);
184 
185     static constexpr int kCoordTransformKeyBits = 4;
186 
187     /**
188      * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this geometry
189      * processor's GL backend implementation.
190      *
191      * TODO: A better name for this function  would be "compute" instead of "get".
192      */
193     virtual void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
194 
195 
getAttributeKey(GrProcessorKeyBuilder * b)196     void getAttributeKey(GrProcessorKeyBuilder* b) const {
197         // Ensure that our CPU and GPU type fields fit together in a 32-bit value, and we never
198         // collide with the "uninitialized" value.
199         static_assert(kGrVertexAttribTypeCount < (1 << 8), "");
200         static_assert(kGrSLTypeCount           < (1 << 8), "");
201 
202         auto add_attributes = [=](const Attribute* attrs, int attrCount) {
203             for (int i = 0; i < attrCount; ++i) {
204                 const Attribute& attr = attrs[i];
205                 b->appendComment(attr.isInitialized() ? attr.name() : "unusedAttr");
206                 b->addBits(8, attr.isInitialized() ? attr.cpuType() : 0xff, "attrType");
207                 b->addBits(8, attr.isInitialized() ? attr.gpuType() : 0xff, "attrGpuType");
208             }
209         };
210         b->add32(fVertexAttributes.fRawCount, "numVertexAttributes");
211         add_attributes(fVertexAttributes.fAttributes, fVertexAttributes.fRawCount);
212         b->add32(fInstanceAttributes.fRawCount, "numInstanceAttributes");
213         add_attributes(fInstanceAttributes.fAttributes, fInstanceAttributes.fRawCount);
214     }
215 
216     /** Returns a new instance of the appropriate *GL* implementation class
217         for the given GrProcessor; caller is responsible for deleting
218         the object. */
219     virtual GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const = 0;
220 
221 protected:
222     // GPs that need to use either float or ubyte colors can just call this to get a correctly
223     // configured Attribute struct
MakeColorAttribute(const char * name,bool wideColor)224     static Attribute MakeColorAttribute(const char* name, bool wideColor) {
225         return { name,
226                  wideColor ? kFloat4_GrVertexAttribType : kUByte4_norm_GrVertexAttribType,
227                  kHalf4_GrSLType };
228     }
229 
setVertexAttributes(const Attribute * attrs,int attrCount)230     void setVertexAttributes(const Attribute* attrs, int attrCount) {
231         fVertexAttributes.init(attrs, attrCount);
232     }
setInstanceAttributes(const Attribute * attrs,int attrCount)233     void setInstanceAttributes(const Attribute* attrs, int attrCount) {
234         SkASSERT(attrCount >= 0);
235         fInstanceAttributes.init(attrs, attrCount);
236     }
setWillUseTessellationShaders()237     void setWillUseTessellationShaders() {
238         fShaders |= kTessControl_GrShaderFlag | kTessEvaluation_GrShaderFlag;
239     }
setWillUseGeoShader()240     void setWillUseGeoShader() { fShaders |= kGeometry_GrShaderFlag; }
setTextureSamplerCnt(int cnt)241     void setTextureSamplerCnt(int cnt) {
242         SkASSERT(cnt >= 0);
243         fTextureSamplerCnt = cnt;
244     }
245 
246     /**
247      * Helper for implementing onTextureSampler(). E.g.:
248      * return IthTexureSampler(i, fMyFirstSampler, fMySecondSampler, fMyThirdSampler);
249      */
250     template <typename... Args>
IthTextureSampler(int i,const TextureSampler & samp0,const Args &...samps)251     static const TextureSampler& IthTextureSampler(int i, const TextureSampler& samp0,
252                                                    const Args&... samps) {
253         return (0 == i) ? samp0 : IthTextureSampler(i - 1, samps...);
254     }
255     inline static const TextureSampler& IthTextureSampler(int i);
256 
257 private:
onTextureSampler(int)258     virtual const TextureSampler& onTextureSampler(int) const { return IthTextureSampler(0); }
259 
260     GrShaderFlags fShaders = kVertex_GrShaderFlag | kFragment_GrShaderFlag;
261 
262     AttributeSet fVertexAttributes;
263     AttributeSet fInstanceAttributes;
264 
265     int fTextureSamplerCnt = 0;
266     using INHERITED = GrProcessor;
267 };
268 
269 //////////////////////////////////////////////////////////////////////////////
270 
271 /**
272  * Used to capture the properties of the GrTextureProxies required/expected by a primitiveProcessor
273  * along with an associated GrSamplerState. The actual proxies used are stored in either the
274  * fixed or dynamic state arrays. TextureSamplers don't perform any coord manipulation to account
275  * for texture origin.
276  */
277 class GrGeometryProcessor::TextureSampler {
278 public:
279     TextureSampler() = default;
280 
281     TextureSampler(GrSamplerState, const GrBackendFormat&, const GrSwizzle&);
282 
283     TextureSampler(const TextureSampler&) = delete;
284     TextureSampler& operator=(const TextureSampler&) = delete;
285 
286     void reset(GrSamplerState, const GrBackendFormat&, const GrSwizzle&);
287 
backendFormat()288     const GrBackendFormat& backendFormat() const { return fBackendFormat; }
textureType()289     GrTextureType textureType() const { return fBackendFormat.textureType(); }
290 
samplerState()291     GrSamplerState samplerState() const { return fSamplerState; }
swizzle()292     const GrSwizzle& swizzle() const { return fSwizzle; }
293 
isInitialized()294     bool isInitialized() const { return fIsInitialized; }
295 
296 private:
297     GrSamplerState  fSamplerState;
298     GrBackendFormat fBackendFormat;
299     GrSwizzle       fSwizzle;
300     bool            fIsInitialized = false;
301 };
302 
IthTextureSampler(int i)303 const GrGeometryProcessor::TextureSampler& GrGeometryProcessor::IthTextureSampler(int i) {
304     SK_ABORT("Illegal texture sampler index");
305     static const TextureSampler kBogus;
306     return kBogus;
307 }
308 
309 //////////////////////////////////////////////////////////////////////////////
310 
311 /**
312  * Returns the size of the attrib type in bytes.
313  * This was moved from include/private/GrTypesPriv.h in service of Skia dependents that build
314  * with C++11.
315  */
GrVertexAttribTypeSize(GrVertexAttribType type)316 static constexpr inline size_t GrVertexAttribTypeSize(GrVertexAttribType type) {
317     switch (type) {
318         case kFloat_GrVertexAttribType:
319             return sizeof(float);
320         case kFloat2_GrVertexAttribType:
321             return 2 * sizeof(float);
322         case kFloat3_GrVertexAttribType:
323             return 3 * sizeof(float);
324         case kFloat4_GrVertexAttribType:
325             return 4 * sizeof(float);
326         case kHalf_GrVertexAttribType:
327             return sizeof(uint16_t);
328         case kHalf2_GrVertexAttribType:
329             return 2 * sizeof(uint16_t);
330         case kHalf4_GrVertexAttribType:
331             return 4 * sizeof(uint16_t);
332         case kInt2_GrVertexAttribType:
333             return 2 * sizeof(int32_t);
334         case kInt3_GrVertexAttribType:
335             return 3 * sizeof(int32_t);
336         case kInt4_GrVertexAttribType:
337             return 4 * sizeof(int32_t);
338         case kByte_GrVertexAttribType:
339             return 1 * sizeof(char);
340         case kByte2_GrVertexAttribType:
341             return 2 * sizeof(char);
342         case kByte4_GrVertexAttribType:
343             return 4 * sizeof(char);
344         case kUByte_GrVertexAttribType:
345             return 1 * sizeof(char);
346         case kUByte2_GrVertexAttribType:
347             return 2 * sizeof(char);
348         case kUByte4_GrVertexAttribType:
349             return 4 * sizeof(char);
350         case kUByte_norm_GrVertexAttribType:
351             return 1 * sizeof(char);
352         case kUByte4_norm_GrVertexAttribType:
353             return 4 * sizeof(char);
354         case kShort2_GrVertexAttribType:
355             return 2 * sizeof(int16_t);
356         case kShort4_GrVertexAttribType:
357             return 4 * sizeof(int16_t);
358         case kUShort2_GrVertexAttribType: // fall through
359         case kUShort2_norm_GrVertexAttribType:
360             return 2 * sizeof(uint16_t);
361         case kInt_GrVertexAttribType:
362             return sizeof(int32_t);
363         case kUint_GrVertexAttribType:
364             return sizeof(uint32_t);
365         case kUShort_norm_GrVertexAttribType:
366             return sizeof(uint16_t);
367         case kUShort4_norm_GrVertexAttribType:
368             return 4 * sizeof(uint16_t);
369     }
370     // GCC fails because SK_ABORT evaluates to non constexpr. clang and cl.exe think this is
371     // unreachable and don't complain.
372 #if defined(__clang__) || !defined(__GNUC__)
373     SK_ABORT("Unsupported type conversion");
374 #endif
375     return 0;
376 }
377 
size()378 constexpr size_t GrGeometryProcessor::Attribute::size() const {
379     return GrVertexAttribTypeSize(fCPUType);
380 }
381 
382 #endif
383