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