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