• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 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 GrGLSLVarying_DEFINED
9 #define GrGLSLVarying_DEFINED
10 
11 #include "GrAllocator.h"
12 #include "GrGeometryProcessor.h"
13 #include "GrShaderVar.h"
14 #include "GrTypesPriv.h"
15 #include "glsl/GrGLSLProgramDataManager.h"
16 
17 class GrGLSLProgramBuilder;
18 
19 class GrGLSLVarying {
20 public:
vsVarying()21     bool vsVarying() const { return kVertToFrag_Varying == fVarying ||
22                                     kVertToGeo_Varying == fVarying; }
fsVarying()23     bool fsVarying() const { return kVertToFrag_Varying == fVarying ||
24                                     kGeoToFrag_Varying == fVarying; }
vsOut()25     const char* vsOut() const { return fVsOut; }
gsIn()26     const char* gsIn() const { return fGsIn; }
gsOut()27     const char* gsOut() const { return fGsOut; }
fsIn()28     const char* fsIn() const { return fFsIn; }
type()29     GrSLType type() const { return fType; }
30 
31 protected:
32     enum Varying {
33         kVertToFrag_Varying,
34         kVertToGeo_Varying,
35         kGeoToFrag_Varying,
36     };
37 
GrGLSLVarying(GrSLType type,Varying varying)38     GrGLSLVarying(GrSLType type, Varying varying)
39         : fVarying(varying), fType(type), fVsOut(nullptr), fGsIn(nullptr), fGsOut(nullptr),
40           fFsIn(nullptr) {}
41 
42     Varying fVarying;
43 
44 private:
45     GrSLType fType;
46     const char* fVsOut;
47     const char* fGsIn;
48     const char* fGsOut;
49     const char* fFsIn;
50 
51     friend class GrGLSLVaryingHandler;
52 };
53 
54 struct GrGLSLVertToFrag : public GrGLSLVarying {
GrGLSLVertToFragGrGLSLVertToFrag55     GrGLSLVertToFrag(GrSLType type)
56         : GrGLSLVarying(type, kVertToFrag_Varying) {}
57 };
58 
59 struct GrGLSLVertToGeo : public GrGLSLVarying {
GrGLSLVertToGeoGrGLSLVertToGeo60     GrGLSLVertToGeo(GrSLType type)
61         : GrGLSLVarying(type, kVertToGeo_Varying) {}
62 };
63 
64 struct GrGLSLGeoToFrag : public GrGLSLVarying {
GrGLSLGeoToFragGrGLSLGeoToFrag65     GrGLSLGeoToFrag(GrSLType type)
66         : GrGLSLVarying(type, kGeoToFrag_Varying) {}
67 };
68 
69 static const int kVaryingsPerBlock = 8;
70 
71 class GrGLSLVaryingHandler {
72 public:
GrGLSLVaryingHandler(GrGLSLProgramBuilder * program)73     explicit GrGLSLVaryingHandler(GrGLSLProgramBuilder* program)
74         : fVaryings(kVaryingsPerBlock)
75         , fVertexInputs(kVaryingsPerBlock)
76         , fVertexOutputs(kVaryingsPerBlock)
77         , fGeomInputs(kVaryingsPerBlock)
78         , fGeomOutputs(kVaryingsPerBlock)
79         , fFragInputs(kVaryingsPerBlock)
80         , fFragOutputs(kVaryingsPerBlock)
81         , fProgramBuilder(program)
82         , fDefaultInterpolationModifier(nullptr) {}
83 
~GrGLSLVaryingHandler()84     virtual ~GrGLSLVaryingHandler() {}
85 
86     /*
87      * Notifies the varying handler that this shader will never emit geometry in perspective and
88      * therefore does not require perspective-correct interpolation. When supported, this allows
89      * varyings to use the "noperspective" keyword, which means the GPU can use cheaper math for
90      * interpolation.
91      */
92     void setNoPerspective();
93 
94     /*
95      * addVarying allows fine grained control for setting up varyings between stages. Calling this
96      * functions will make sure all necessary decls are setup for the client. The client however is
97      * responsible for setting up all shader code (e.g "vOut = vIn;") If you just need to take an
98      * attribute and pass it through to an output value in a fragment shader, use
99      * addPassThroughAttribute.
100      * TODO convert most uses of addVarying to addPassThroughAttribute
101      */
102     void addVarying(const char* name,
103                     GrGLSLVarying* varying,
104                     GrSLPrecision precision = kDefault_GrSLPrecision) {
105         SkASSERT(GrSLTypeIsFloatType(varying->type())); // Integers must use addFlatVarying.
106         this->internalAddVarying(name, varying, precision, false /*flat*/);
107     }
108 
109     /*
110      * addFlatVarying sets up a varying whose value is constant across every fragment. The graphics
111      * pipeline will pull its value from the final vertex of the draw primitive (provoking vertex).
112      * Flat interpolation is not always supported and the user must check the caps before using.
113      * TODO: Some platforms can change the provoking vertex. Should we be resetting this knob?
114      */
115     void addFlatVarying(const char* name,
116                         GrGLSLVarying* varying,
117                         GrSLPrecision precision = kDefault_GrSLPrecision) {
118         this->internalAddVarying(name, varying, precision, true /*flat*/);
119     }
120 
121     /*
122      * The GP can use these calls to pass an attribute through all shaders directly to 'output' in
123      * the fragment shader.  Though these calls affect both the vertex shader and fragment shader,
124      * they expect 'output' to be defined in the fragment shader before the call is made. If there
125      * is a geometry shader, we will simply take the value of the varying from the first vertex and
126      * that will be set as the output varying for all emitted vertices.
127      * TODO it might be nicer behavior to have a flag to declare output inside these calls
128      */
129     void addPassThroughAttribute(const GrGeometryProcessor::Attribute*, const char* output,
130                                  GrSLPrecision = kDefault_GrSLPrecision);
131     void addFlatPassThroughAttribute(const GrGeometryProcessor::Attribute*, const char* output,
132                                      GrSLPrecision = kDefault_GrSLPrecision);
133 
134     void emitAttributes(const GrGeometryProcessor& gp);
135 
136     // This should be called once all attributes and varyings have been added to the
137     // GrGLSLVaryingHanlder and before getting/adding any of the declarations to the shaders.
138     void finalize();
139 
140     void getVertexDecls(SkString* inputDecls, SkString* outputDecls) const;
141     void getGeomDecls(SkString* inputDecls, SkString* outputDecls) const;
142     void getFragDecls(SkString* inputDecls, SkString* outputDecls) const;
143 
144 protected:
145     struct VaryingInfo {
146         GrSLType         fType;
147         GrSLPrecision    fPrecision;
148         bool             fIsFlat;
149         SkString         fVsOut;
150         SkString         fGsOut;
151         GrShaderFlags    fVisibility;
152     };
153 
154     typedef GrTAllocator<VaryingInfo> VaryingList;
155     typedef GrTAllocator<GrShaderVar> VarArray;
156     typedef GrGLSLProgramDataManager::VaryingHandle VaryingHandle;
157 
158     VaryingList    fVaryings;
159     VarArray       fVertexInputs;
160     VarArray       fVertexOutputs;
161     VarArray       fGeomInputs;
162     VarArray       fGeomOutputs;
163     VarArray       fFragInputs;
164     VarArray       fFragOutputs;
165 
166     // This is not owned by the class
167     GrGLSLProgramBuilder* fProgramBuilder;
168 
169 private:
170     void internalAddVarying(const char* name, GrGLSLVarying*, GrSLPrecision, bool flat);
171     void writePassThroughAttribute(const GrGeometryProcessor::Attribute*, const char* output,
172                                    const GrGLSLVarying&);
173 
174     void addAttribute(const GrShaderVar& var);
175 
176     virtual void onFinalize() = 0;
177 
178     // helper function for get*Decls
179     void appendDecls(const VarArray& vars, SkString* out) const;
180 
181     const char* fDefaultInterpolationModifier;
182 
183     friend class GrGLSLProgramBuilder;
184 };
185 
186 #endif
187