Home | History | Annotate | Download | only in glsl
      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     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 
     31 protected:
     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 
     44 private:
     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 
     54 struct GrGLSLVertToFrag : public GrGLSLVarying {
     55     GrGLSLVertToFrag(GrSLType type)
     56         : GrGLSLVarying(type, kVertToFrag_Varying) {}
     57 };
     58 
     59 struct GrGLSLVertToGeo : public GrGLSLVarying {
     60     GrGLSLVertToGeo(GrSLType type)
     61         : GrGLSLVarying(type, kVertToGeo_Varying) {}
     62 };
     63 
     64 struct GrGLSLGeoToFrag : public GrGLSLVarying {
     65     GrGLSLGeoToFrag(GrSLType type)
     66         : GrGLSLVarying(type, kGeoToFrag_Varying) {}
     67 };
     68 
     69 static const int kVaryingsPerBlock = 8;
     70 
     71 class GrGLSLVaryingHandler {
     72 public:
     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 
    144 protected:
    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<GrShaderVar> 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 
    169 private:
    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