Line data Source code
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:
21 0 : bool vsVarying() const { return kVertToFrag_Varying == fVarying ||
22 0 : kVertToGeo_Varying == fVarying; }
23 0 : bool fsVarying() const { return kVertToFrag_Varying == fVarying ||
24 0 : kGeoToFrag_Varying == fVarying; }
25 0 : const char* vsOut() const { return fVsOut; }
26 : const char* gsIn() const { return fGsIn; }
27 : const char* gsOut() const { return fGsOut; }
28 0 : const char* fsIn() const { return fFsIn; }
29 0 : GrSLType type() const { return fType; }
30 :
31 : protected:
32 : enum Varying {
33 : kVertToFrag_Varying,
34 : kVertToGeo_Varying,
35 : kGeoToFrag_Varying,
36 : };
37 :
38 0 : GrGLSLVarying(GrSLType type, Varying varying)
39 0 : : fVarying(varying), fType(type), fVsOut(nullptr), fGsIn(nullptr), fGsOut(nullptr),
40 0 : 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 {
55 0 : GrGLSLVertToFrag(GrSLType type)
56 0 : : GrGLSLVarying(type, kVertToFrag_Varying) {}
57 : };
58 :
59 : struct GrGLSLVertToGeo : public GrGLSLVarying {
60 : GrGLSLVertToGeo(GrSLType type)
61 : : GrGLSLVarying(type, kVertToGeo_Varying) {}
62 : };
63 :
64 : struct GrGLSLGeoToFrag : public GrGLSLVarying {
65 : GrGLSLGeoToFrag(GrSLType type)
66 : : GrGLSLVarying(type, kGeoToFrag_Varying) {}
67 : };
68 :
69 : static const int kVaryingsPerBlock = 8;
70 :
71 : class GrGLSLVaryingHandler {
72 : public:
73 0 : explicit GrGLSLVaryingHandler(GrGLSLProgramBuilder* program)
74 0 : : fVaryings(kVaryingsPerBlock)
75 : , fVertexInputs(kVaryingsPerBlock)
76 : , fVertexOutputs(kVaryingsPerBlock)
77 : , fGeomInputs(kVaryingsPerBlock)
78 : , fGeomOutputs(kVaryingsPerBlock)
79 : , fFragInputs(kVaryingsPerBlock)
80 : , fFragOutputs(kVaryingsPerBlock)
81 : , fProgramBuilder(program)
82 0 : , fDefaultInterpolationModifier(nullptr) {}
83 :
84 0 : 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 0 : void addVarying(const char* name,
103 : GrGLSLVarying* varying,
104 : GrSLPrecision precision = kDefault_GrSLPrecision) {
105 0 : SkASSERT(GrSLTypeIsFloatType(varying->type())); // Integers must use addFlatVarying.
106 0 : this->internalAddVarying(name, varying, precision, false /*flat*/);
107 0 : }
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 0 : void addFlatVarying(const char* name,
116 : GrGLSLVarying* varying,
117 : GrSLPrecision precision = kDefault_GrSLPrecision) {
118 0 : this->internalAddVarying(name, varying, precision, true /*flat*/);
119 0 : }
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 0 : 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
|