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