blob: 48902d41ca31f135da632e20fb4db75a5a9c0fd3 [file] [log] [blame]
egdaniel0eafe792015-11-20 14:01:22 -08001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/private/GrTypesPriv.h"
Michael Ludwigc1ed11d2021-08-24 11:49:55 -040012#include "src/core/SkTBlockList.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "src/gpu/GrShaderVar.h"
14#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
egdaniel0eafe792015-11-20 14:01:22 -080015
Brian Salomon48959462021-08-11 13:01:06 -040016class GrGeometryProcessor;
egdaniel0eafe792015-11-20 14:01:22 -080017class GrGLSLProgramBuilder;
18
Ethan Nicholas56b4e3d2019-01-08 09:34:40 -050019#ifdef SK_DEBUG
20static bool is_matrix(GrSLType type) {
21 switch (type) {
22 case kFloat2x2_GrSLType:
23 case kFloat3x3_GrSLType:
24 case kFloat4x4_GrSLType:
25 case kHalf2x2_GrSLType:
26 case kHalf3x3_GrSLType:
27 case kHalf4x4_GrSLType:
28 return true;
29 default:
30 return false;
31 }
32}
33#endif
34
egdaniel0eafe792015-11-20 14:01:22 -080035class GrGLSLVarying {
36public:
Chris Dalton27372882017-12-08 13:34:21 -070037 enum class Scope {
38 kVertToFrag,
39 kVertToGeo,
40 kGeoToFrag
egdaniel0eafe792015-11-20 14:01:22 -080041 };
42
Chris Dalton90e8fb12017-12-22 02:24:53 -070043 GrGLSLVarying() = default;
Ethan Nicholas56b4e3d2019-01-08 09:34:40 -050044 GrGLSLVarying(GrSLType type, Scope scope = Scope::kVertToFrag)
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 }
egdaniel0eafe792015-11-20 14:01:22 -080050
Chris Dalton90e8fb12017-12-22 02:24:53 -070051 void reset(GrSLType type, Scope scope = Scope::kVertToFrag) {
Ethan Nicholas56b4e3d2019-01-08 09:34:40 -050052 // Metal doesn't support varying matrices, so we disallow them everywhere for consistency
53 SkASSERT(!is_matrix(type));
Chris Dalton90e8fb12017-12-22 02:24:53 -070054 *this = GrGLSLVarying();
55 fType = type;
56 fScope = scope;
57 }
58
Chris Dalton27372882017-12-08 13:34:21 -070059 GrSLType type() const { return fType; }
60 Scope scope() const { return fScope; }
61 bool isInVertexShader() const { return Scope::kGeoToFrag != fScope; }
62 bool isInFragmentShader() const { return Scope::kVertToGeo != fScope; }
63
64 const char* vsOut() const { SkASSERT(this->isInVertexShader()); return fVsOut; }
Chris Dalton27372882017-12-08 13:34:21 -070065 const char* fsIn() const { SkASSERT(this->isInFragmentShader()); return fFsIn; }
egdaniel0eafe792015-11-20 14:01:22 -080066
Brian Salomon6b7ec002021-07-12 13:54:24 -040067 GrShaderVar vsOutVar() const {
68 SkASSERT(this->isInVertexShader());
69 return GrShaderVar(this->vsOut(), fType, GrShaderVar::TypeModifier::Out);
70 }
71
72 GrShaderVar fsInVar() const {
73 SkASSERT(this->isInFragmentShader());
74 return GrShaderVar(this->fsIn(), fType, GrShaderVar::TypeModifier::In);
75 }
76
egdaniel0eafe792015-11-20 14:01:22 -080077private:
Chris Dalton90e8fb12017-12-22 02:24:53 -070078 GrSLType fType = kVoid_GrSLType;
79 Scope fScope = Scope::kVertToFrag;
Chris Dalton27372882017-12-08 13:34:21 -070080 const char* fVsOut = nullptr;
Chris Dalton27372882017-12-08 13:34:21 -070081 const char* fFsIn = nullptr;
egdaniel0eafe792015-11-20 14:01:22 -080082
83 friend class GrGLSLVaryingHandler;
84};
85
egdaniel0eafe792015-11-20 14:01:22 -080086static const int kVaryingsPerBlock = 8;
87
88class GrGLSLVaryingHandler {
89public:
90 explicit GrGLSLVaryingHandler(GrGLSLProgramBuilder* program)
cdaltonc08f1962016-02-12 12:14:06 -080091 : fVaryings(kVaryingsPerBlock)
92 , fVertexInputs(kVaryingsPerBlock)
egdaniel0eafe792015-11-20 14:01:22 -080093 , fVertexOutputs(kVaryingsPerBlock)
egdaniel0eafe792015-11-20 14:01:22 -080094 , fFragInputs(kVaryingsPerBlock)
95 , fFragOutputs(kVaryingsPerBlock)
cdaltonc08f1962016-02-12 12:14:06 -080096 , fProgramBuilder(program)
97 , fDefaultInterpolationModifier(nullptr) {}
egdaniel0eafe792015-11-20 14:01:22 -080098
egdanielb80ec8b2016-02-09 09:54:43 -080099 virtual ~GrGLSLVaryingHandler() {}
100
Brian Salomon48959462021-08-11 13:01:06 -0400101 /**
cdaltonc08f1962016-02-12 12:14:06 -0800102 * 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();
egdaniel0eafe792015-11-20 14:01:22 -0800108
Chris Dalton7b046312018-02-02 11:06:30 -0700109 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
Brian Salomon48959462021-08-11 13:01:06 -0400115 /**
egdaniel0eafe792015-11-20 14:01:22 -0800116 * addVarying allows fine grained control for setting up varyings between stages. Calling this
Robert Phillipsf95b1752017-08-31 08:56:07 -0400117 * function will make sure all necessary decls are setup for the client. The client however is
egdaniel0eafe792015-11-20 14:01:22 -0800118 * 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 */
Chris Dalton7b046312018-02-02 11:06:30 -0700123 void addVarying(const char* name, GrGLSLVarying* varying,
124 Interpolation = Interpolation::kInterpolated);
cdaltonc08f1962016-02-12 12:14:06 -0800125
Brian Salomon48959462021-08-11 13:01:06 -0400126 /**
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
Brian Osman99ddd2a2021-08-27 11:21:12 -0400129 * be defined in the fragment shader before the call is made.
cdaltonc08f1962016-02-12 12:14:06 -0800130 * TODO it might be nicer behavior to have a flag to declare output inside these calls
egdaniel0eafe792015-11-20 14:01:22 -0800131 */
Brian Salomon48959462021-08-11 13:01:06 -0400132 void addPassThroughAttribute(const GrShaderVar& vsVar,
133 const char* output,
Chris Dalton7b046312018-02-02 11:06:30 -0700134 Interpolation = Interpolation::kInterpolated);
egdaniel0eafe792015-11-20 14:01:22 -0800135
Robert Phillips787fd9d2021-03-22 14:48:09 -0400136 void emitAttributes(const GrGeometryProcessor&);
egdaniel0eafe792015-11-20 14:01:22 -0800137
egdanielb80ec8b2016-02-09 09:54:43 -0800138 // 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
egdaniel0eafe792015-11-20 14:01:22 -0800142 void getVertexDecls(SkString* inputDecls, SkString* outputDecls) const;
egdaniel0eafe792015-11-20 14:01:22 -0800143 void getFragDecls(SkString* inputDecls, SkString* outputDecls) const;
cdaltonc08f1962016-02-12 12:14:06 -0800144
egdaniel0eafe792015-11-20 14:01:22 -0800145protected:
cdaltonc08f1962016-02-12 12:14:06 -0800146 struct VaryingInfo {
147 GrSLType fType;
cdaltonc08f1962016-02-12 12:14:06 -0800148 bool fIsFlat;
149 SkString fVsOut;
cdaltonc08f1962016-02-12 12:14:06 -0800150 GrShaderFlags fVisibility;
151 };
152
Michael Ludwigc1ed11d2021-08-24 11:49:55 -0400153 typedef SkTBlockList<VaryingInfo> VaryingList;
154 typedef SkTBlockList<GrShaderVar> VarArray;
cdaltonc08f1962016-02-12 12:14:06 -0800155
156 VaryingList fVaryings;
157 VarArray fVertexInputs;
158 VarArray fVertexOutputs;
cdaltonc08f1962016-02-12 12:14:06 -0800159 VarArray fFragInputs;
160 VarArray fFragOutputs;
egdaniel0eafe792015-11-20 14:01:22 -0800161
162 // This is not owned by the class
163 GrGLSLProgramBuilder* fProgramBuilder;
164
165private:
egdaniel0eafe792015-11-20 14:01:22 -0800166 void addAttribute(const GrShaderVar& var);
167
egdanielb80ec8b2016-02-09 09:54:43 -0800168 virtual void onFinalize() = 0;
169
egdaniel0eafe792015-11-20 14:01:22 -0800170 // helper function for get*Decls
171 void appendDecls(const VarArray& vars, SkString* out) const;
172
cdaltonc08f1962016-02-12 12:14:06 -0800173 const char* fDefaultInterpolationModifier;
174
egdaniel0eafe792015-11-20 14:01:22 -0800175 friend class GrGLSLProgramBuilder;
176};
177
178#endif