• 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 "include/private/gpu/ganesh/GrTypesPriv.h"
12 #include "src/base/SkTBlockList.h"
13 #include "src/gpu/ganesh/GrShaderVar.h"
14 #include "src/gpu/ganesh/glsl/GrGLSLProgramDataManager.h"
15 
16 class GrGeometryProcessor;
17 class GrGLSLProgramBuilder;
18 
19 #ifdef SK_DEBUG
is_matrix(SkSLType type)20 static bool is_matrix(SkSLType type) {
21     switch (type) {
22         case SkSLType::kFloat2x2:
23         case SkSLType::kFloat3x3:
24         case SkSLType::kFloat4x4:
25         case SkSLType::kHalf2x2:
26         case SkSLType::kHalf3x3:
27         case SkSLType::kHalf4x4:
28             return true;
29         default:
30             return false;
31     }
32 }
33 #endif
34 
35 class GrGLSLVarying {
36 public:
37     enum class Scope {
38         kVertToFrag,
39         kVertToGeo,
40         kGeoToFrag
41     };
42 
43     GrGLSLVarying() = default;
44     GrGLSLVarying(SkSLType type, Scope scope = Scope::kVertToFrag)
fType(type)45         : fType(type)
46         , fScope(scope) {
47         // Metal doesn't support varying matrices, so we disallow them everywhere for consistency
48         SkASSERT(!is_matrix(type));
49     }
50 
51     void reset(SkSLType type, Scope scope = Scope::kVertToFrag) {
52         // Metal doesn't support varying matrices, so we disallow them everywhere for consistency
53         SkASSERT(!is_matrix(type));
54         *this = GrGLSLVarying();
55         fType = type;
56         fScope = scope;
57     }
58 
type()59     SkSLType type() const { return fType; }
scope()60     Scope scope() const { return fScope; }
isInVertexShader()61     bool isInVertexShader() const { return Scope::kGeoToFrag != fScope; }
isInFragmentShader()62     bool isInFragmentShader() const { return Scope::kVertToGeo != fScope; }
63 
vsOut()64     const char* vsOut() const { SkASSERT(this->isInVertexShader()); return fVsOut; }
fsIn()65     const char* fsIn() const { SkASSERT(this->isInFragmentShader()); return fFsIn; }
66 
vsOutVar()67     GrShaderVar vsOutVar() const {
68         SkASSERT(this->isInVertexShader());
69         return GrShaderVar(this->vsOut(), fType, GrShaderVar::TypeModifier::Out);
70     }
71 
fsInVar()72     GrShaderVar fsInVar() const {
73         SkASSERT(this->isInFragmentShader());
74         return GrShaderVar(this->fsIn(), fType, GrShaderVar::TypeModifier::In);
75     }
76 
77 private:
78     SkSLType fType = SkSLType::kVoid;
79     Scope fScope = Scope::kVertToFrag;
80     const char* fVsOut = nullptr;
81     const char* fFsIn = nullptr;
82 
83     friend class GrGLSLVaryingHandler;
84 };
85 
86 static const int kVaryingsPerBlock = 8;
87 
88 class GrGLSLVaryingHandler {
89 public:
GrGLSLVaryingHandler(GrGLSLProgramBuilder * program)90     explicit GrGLSLVaryingHandler(GrGLSLProgramBuilder* program)
91         : fVaryings(kVaryingsPerBlock)
92         , fVertexInputs(kVaryingsPerBlock)
93         , fVertexOutputs(kVaryingsPerBlock)
94         , fFragInputs(kVaryingsPerBlock)
95         , fFragOutputs(kVaryingsPerBlock)
96         , fProgramBuilder(program)
97         , fDefaultInterpolationModifier(nullptr) {}
98 
~GrGLSLVaryingHandler()99     virtual ~GrGLSLVaryingHandler() {}
100 
101     /**
102      * Notifies the varying handler that this shader will never emit geometry in perspective and
103      * therefore does not require perspective-correct interpolation. When supported, this allows
104      * varyings to use the "noperspective" keyword, which means the GPU can use cheaper math for
105      * interpolation.
106      */
107     void setNoPerspective();
108 
109     enum class Interpolation {
110         kInterpolated,
111         kCanBeFlat, // Use "flat" if it will be faster.
112         kMustBeFlat // Use "flat" even if it is known to be slow.
113     };
114 
115     /**
116      * addVarying allows fine grained control for setting up varyings between stages. Calling this
117      * function will make sure all necessary decls are setup for the client. The client however is
118      * responsible for setting up all shader code (e.g "vOut = vIn;") If you just need to take an
119      * attribute and pass it through to an output value in a fragment shader, use
120      * addPassThroughAttribute.
121      * TODO convert most uses of addVarying to addPassThroughAttribute
122      */
123     void addVarying(const char* name, GrGLSLVarying* varying,
124                     Interpolation = Interpolation::kInterpolated);
125 
126     /**
127      * The GP can use these calls to pass a vertex shader variable directly to 'output' in the
128      * fragment shader. Though this adds code to vertex and fragment stages, 'output' is expected to
129      * be defined in the fragment shader before the call is made.
130      * TODO it might be nicer behavior to have a flag to declare output inside these calls
131      */
132     void addPassThroughAttribute(const GrShaderVar& vsVar,
133                                  const char* output,
134                                  Interpolation = Interpolation::kInterpolated);
135 
136     void emitAttributes(const GrGeometryProcessor&);
137 
138     // This should be called once all attributes and varyings have been added to the
139     // GrGLSLVaryingHanlder and before getting/adding any of the declarations to the shaders.
140     void finalize();
141 
142     void getVertexDecls(SkString* inputDecls, SkString* outputDecls) const;
143     void getFragDecls(SkString* inputDecls, SkString* outputDecls) const;
144 
145 protected:
146     struct VaryingInfo {
147         SkSLType         fType;
148         bool             fIsFlat;
149         SkString         fVsOut;
150         GrShaderFlags    fVisibility;
151     };
152 
153     typedef SkTBlockList<VaryingInfo> VaryingList;
154     typedef SkTBlockList<GrShaderVar> VarArray;
155 
156     VaryingList    fVaryings;
157     VarArray       fVertexInputs;
158     VarArray       fVertexOutputs;
159     VarArray       fFragInputs;
160     VarArray       fFragOutputs;
161 
162     // This is not owned by the class
163     GrGLSLProgramBuilder* fProgramBuilder;
164 
165 private:
166     void addAttribute(const GrShaderVar& var);
167 
168     virtual void onFinalize() = 0;
169 
170     // helper function for get*Decls
171     void appendDecls(const VarArray& vars, SkString* out) const;
172 
173     const char* fDefaultInterpolationModifier;
174 
175     friend class GrGLSLProgramBuilder;
176 };
177 
178 #endif
179