Home | History | Annotate | Download | only in builders
      1 /*
      2  * Copyright 2014 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 GrGLProgramBuilder_DEFINED
      9 #define GrGLProgramBuilder_DEFINED
     10 
     11 #include "GrGLFragmentShaderBuilder.h"
     12 #include "GrGLGeometryShaderBuilder.h"
     13 #include "GrGLVertexShaderBuilder.h"
     14 #include "../GrGLProgramDataManager.h"
     15 #include "../GrGLUniformHandle.h"
     16 #include "../GrGLPrimitiveProcessor.h"
     17 #include "../GrGLXferProcessor.h"
     18 #include "../../GrPendingFragmentStage.h"
     19 #include "../../GrPipeline.h"
     20 
     21 /*
     22  * This is the base class for a series of interfaces.  This base class *MUST* remain abstract with
     23  * NO data members because it is used in multiple interface inheritance.
     24  * Heirarchy:
     25  *                      GrGLUniformBuilder
     26  *                     /                  \
     27  *                GrGLFPBuilder       GrGLGPBuilder
     28  *                     \                  /
     29  *                     GrGLProgramBuilder(internal use only)
     30  */
     31 class GrGLUniformBuilder {
     32 public:
     33     enum ShaderVisibility {
     34         kVertex_Visibility   = 1 << kVertex_GrShaderType,
     35         kGeometry_Visibility = 1 << kGeometry_GrShaderType,
     36         kFragment_Visibility = 1 << kFragment_GrShaderType,
     37     };
     38 
     39     virtual ~GrGLUniformBuilder() {}
     40 
     41     typedef GrGLProgramDataManager::UniformHandle UniformHandle;
     42 
     43     /** Add a uniform variable to the current program, that has visibility in one or more shaders.
     44         visibility is a bitfield of ShaderVisibility values indicating from which shaders the
     45         uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
     46         supported at this time. The actual uniform name will be mangled. If outName is not NULL then
     47         it will refer to the final uniform name after return. Use the addUniformArray variant to add
     48         an array of uniforms. */
     49     UniformHandle addUniform(uint32_t visibility,
     50                              GrSLType type,
     51                              GrSLPrecision precision,
     52                              const char* name,
     53                              const char** outName = NULL) {
     54         return this->addUniformArray(visibility, type, precision, name, 0, outName);
     55     }
     56 
     57     virtual UniformHandle addUniformArray(
     58         uint32_t visibility,
     59         GrSLType type,
     60         GrSLPrecision precision,
     61         const char* name,
     62         int arrayCount,
     63         const char** outName = NULL) = 0;
     64 
     65     virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const = 0;
     66 
     67     /**
     68      * Shortcut for getUniformVariable(u).c_str()
     69      */
     70     virtual const char* getUniformCStr(UniformHandle u) const = 0;
     71 
     72     virtual const GrGLContextInfo& ctxInfo() const = 0;
     73 
     74     virtual GrGLGpu* gpu() const = 0;
     75 
     76     /*
     77      * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
     78      */
     79 };
     80 
     81 // TODO move this into GrGLGPBuilder and move them both out of this file
     82 class GrGLVarying {
     83 public:
     84     bool vsVarying() const { return kVertToFrag_Varying == fVarying ||
     85                                     kVertToGeo_Varying == fVarying; }
     86     bool fsVarying() const { return kVertToFrag_Varying == fVarying ||
     87                                     kGeoToFrag_Varying == fVarying; }
     88     const char* vsOut() const { return fVsOut; }
     89     const char* gsIn() const { return fGsIn; }
     90     const char* gsOut() const { return fGsOut; }
     91     const char* fsIn() const { return fFsIn; }
     92     GrSLType type() const { return fType; }
     93 
     94 protected:
     95     enum Varying {
     96         kVertToFrag_Varying,
     97         kVertToGeo_Varying,
     98         kGeoToFrag_Varying,
     99     };
    100 
    101     GrGLVarying(GrSLType type, Varying varying)
    102         : fVarying(varying), fType(type), fVsOut(NULL), fGsIn(NULL), fGsOut(NULL),
    103           fFsIn(NULL) {}
    104 
    105     Varying fVarying;
    106 
    107 private:
    108     GrSLType fType;
    109     const char* fVsOut;
    110     const char* fGsIn;
    111     const char* fGsOut;
    112     const char* fFsIn;
    113 
    114     friend class GrGLVertexBuilder;
    115     friend class GrGLGeometryBuilder;
    116     friend class GrGLXferBuilder;
    117     friend class GrGLFragmentShaderBuilder;
    118 };
    119 
    120 struct GrGLVertToFrag : public GrGLVarying {
    121     GrGLVertToFrag(GrSLType type)
    122         : GrGLVarying(type, kVertToFrag_Varying) {}
    123 };
    124 
    125 struct GrGLVertToGeo : public GrGLVarying {
    126     GrGLVertToGeo(GrSLType type)
    127         : GrGLVarying(type, kVertToGeo_Varying) {}
    128 };
    129 
    130 struct GrGLGeoToFrag : public GrGLVarying {
    131     GrGLGeoToFrag(GrSLType type)
    132         : GrGLVarying(type, kGeoToFrag_Varying) {}
    133 };
    134 
    135 /* a specialization of the above for GPs.  Lets the user add uniforms, varyings, and VS / FS code */
    136 class GrGLGPBuilder : public virtual GrGLUniformBuilder {
    137 public:
    138     /*
    139      * addVarying allows fine grained control for setting up varyings between stages.  If you just
    140      * need to take an attribute and pass it through to an output value in a fragment shader, use
    141      * addPassThroughAttribute.
    142      * TODO convert most uses of addVarying to addPassThroughAttribute
    143      */
    144     virtual void addVarying(const char* name,
    145                             GrGLVarying*,
    146                             GrSLPrecision fsPrecision = kDefault_GrSLPrecision) = 0;
    147 
    148     /*
    149      * This call can be used by GP to pass an attribute through all shaders directly to 'output' in
    150      * the fragment shader.  Though this call effects both the vertex shader and fragment shader,
    151      * it expects 'output' to be defined in the fragment shader before this call is made.
    152      * TODO it might be nicer behavior to have a flag to declare output inside this call
    153      */
    154     virtual void addPassThroughAttribute(const GrGeometryProcessor::Attribute*,
    155                                          const char* output) = 0;
    156 
    157     // TODO rename getFragmentBuilder
    158     virtual GrGLFragmentBuilder* getFragmentShaderBuilder() = 0;
    159     virtual GrGLVertexBuilder* getVertexShaderBuilder() = 0;
    160 
    161     /*
    162      * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
    163      */
    164 };
    165 
    166 /* a specializations for FPs. Lets the user add uniforms and FS code */
    167 class GrGLFPBuilder : public virtual GrGLUniformBuilder {
    168 public:
    169     virtual GrGLFragmentBuilder* getFragmentShaderBuilder() = 0;
    170 
    171     /*
    172      * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
    173      */
    174 };
    175 
    176 /* a specializations for XPs. Lets the user add uniforms and FS code */
    177 class GrGLXPBuilder : public virtual GrGLUniformBuilder {
    178 public:
    179     virtual GrGLXPFragmentBuilder* getFragmentShaderBuilder() = 0;
    180 
    181     /*
    182      * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
    183      */
    184 };
    185 
    186 /**
    187  * The below struct represent processors installed in programs.
    188  */
    189 template <class Proc>
    190 struct GrGLInstalledProc {
    191      typedef GrGLProgramDataManager::UniformHandle UniformHandle;
    192 
    193      struct Sampler {
    194          SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
    195          UniformHandle  fUniform;
    196          int            fTextureUnit;
    197      };
    198      SkSTArray<4, Sampler, true> fSamplers;
    199      SkAutoTDelete<Proc> fGLProc;
    200 };
    201 
    202 typedef GrGLInstalledProc<GrGLPrimitiveProcessor> GrGLInstalledGeoProc;
    203 typedef GrGLInstalledProc<GrGLXferProcessor> GrGLInstalledXferProc;
    204 typedef GrGLInstalledProc<GrGLFragmentProcessor> GrGLInstalledFragProc;
    205 
    206 struct GrGLInstalledFragProcs : public SkRefCnt {
    207     virtual ~GrGLInstalledFragProcs();
    208     SkSTArray<8, GrGLInstalledFragProc*, true> fProcs;
    209 };
    210 
    211 /*
    212  * Please note - no diamond problems because of virtual inheritance.  Also, both base classes
    213  * are pure virtual with no data members.  This is the base class for program building.
    214  * Subclasses are nearly identical but each has their own way of emitting transforms.  State for
    215  * each of the elements of the shader pipeline, ie vertex, fragment, geometry, etc, lives in those
    216  * respective builders
    217 */
    218 class GrGLProgramBuilder : public GrGLGPBuilder,
    219                            public GrGLFPBuilder,
    220                            public GrGLXPBuilder {
    221 public:
    222     typedef GrGpu::DrawArgs DrawArgs;
    223     /** Generates a shader program.
    224      *
    225      * The program implements what is specified in the stages given as input.
    226      * After successful generation, the builder result objects are available
    227      * to be used.
    228      * @return true if generation was successful.
    229      */
    230     static GrGLProgram* CreateProgram(const DrawArgs&, GrGLGpu*);
    231 
    232     UniformHandle addUniformArray(uint32_t visibility,
    233                                   GrSLType type,
    234                                   GrSLPrecision precision,
    235                                   const char* name,
    236                                   int arrayCount,
    237                                   const char** outName) override;
    238 
    239     const GrGLShaderVar& getUniformVariable(UniformHandle u) const override {
    240         return fUniforms[u.toShaderBuilderIndex()].fVariable;
    241     }
    242 
    243     const char* getUniformCStr(UniformHandle u) const override {
    244         return this->getUniformVariable(u).c_str();
    245     }
    246 
    247     const GrGLContextInfo& ctxInfo() const override;
    248 
    249     GrGLGpu* gpu() const override { return fGpu; }
    250 
    251     GrGLXPFragmentBuilder* getFragmentShaderBuilder() override { return &fFS; }
    252     GrGLVertexBuilder* getVertexShaderBuilder() override { return &fVS; }
    253 
    254     void addVarying(
    255             const char* name,
    256             GrGLVarying*,
    257             GrSLPrecision fsPrecision = kDefault_GrSLPrecision) override;
    258 
    259     void addPassThroughAttribute(const GrPrimitiveProcessor::Attribute*,
    260                                  const char* output) override;
    261 
    262 
    263     // Handles for program uniforms (other than per-effect uniforms)
    264     struct BuiltinUniformHandles {
    265         UniformHandle       fRTAdjustmentUni;
    266 
    267         // We use the render target height to provide a y-down frag coord when specifying
    268         // origin_upper_left is not supported.
    269         UniformHandle       fRTHeightUni;
    270     };
    271 
    272 protected:
    273     typedef GrGLProgramDataManager::UniformInfo UniformInfo;
    274     typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
    275 
    276     static GrGLProgramBuilder* CreateProgramBuilder(const DrawArgs&, GrGLGpu*);
    277 
    278     GrGLProgramBuilder(GrGLGpu*, const DrawArgs&);
    279 
    280     const GrPrimitiveProcessor& primitiveProcessor() const { return *fArgs.fPrimitiveProcessor; }
    281     const GrPipeline& pipeline() const { return *fArgs.fPipeline; }
    282     const GrProgramDesc& desc() const { return *fArgs.fDesc; }
    283     const GrBatchTracker& batchTracker() const { return *fArgs.fBatchTracker; }
    284     const GrProgramDesc::KeyHeader& header() const { return fArgs.fDesc->header(); }
    285 
    286     // Generates a name for a variable. The generated string will be name prefixed by the prefix
    287     // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
    288     // generating stage code.
    289     void nameVariable(SkString* out, char prefix, const char* name);
    290     // Generates a possibly mangled name for a stage variable and writes it to the fragment shader.
    291     // If GrGLSLExpr4 has a valid name then it will use that instead
    292     void nameExpression(GrGLSLExpr4*, const char* baseName);
    293     bool emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage);
    294     void emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut);
    295     void emitAndInstallProc(const GrPendingFragmentStage&,
    296                             int index,
    297                             const GrGLSLExpr4& input,
    298                             GrGLSLExpr4* output);
    299 
    300     void emitAndInstallProc(const GrPrimitiveProcessor&,
    301                             GrGLSLExpr4* outputColor,
    302                             GrGLSLExpr4* outputCoverage);
    303 
    304     // these emit functions help to keep the createAndEmitProcessors template general
    305     void emitAndInstallProc(const GrPendingFragmentStage&,
    306                             int index,
    307                             const char* outColor,
    308                             const char* inColor);
    309     void emitAndInstallProc(const GrPrimitiveProcessor&,
    310                             const char* outColor,
    311                             const char* outCoverage);
    312     void emitAndInstallXferProc(const GrXferProcessor&,
    313                                 const GrGLSLExpr4& colorIn,
    314                                 const GrGLSLExpr4& coverageIn);
    315 
    316     void verify(const GrPrimitiveProcessor&);
    317     void verify(const GrXferProcessor&);
    318     void verify(const GrFragmentProcessor&);
    319     template <class Proc>
    320     void emitSamplers(const GrProcessor&,
    321                       GrGLProcessor::TextureSamplerArray* outSamplers,
    322                       GrGLInstalledProc<Proc>*);
    323 
    324     GrGLProgram* finalize();
    325     void bindUniformLocations(GrGLuint programID);
    326     bool checkLinkStatus(GrGLuint programID);
    327     void resolveUniformLocations(GrGLuint programID);
    328     void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);
    329     void cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs);
    330 
    331     // Subclasses create different programs
    332     virtual GrGLProgram* createProgram(GrGLuint programID);
    333 
    334     void appendUniformDecls(ShaderVisibility, SkString*) const;
    335 
    336     // reset is called by program creator between each processor's emit code.  It increments the
    337     // stage offset for variable name mangling, and also ensures verfication variables in the
    338     // fragment shader are cleared.
    339     void reset() {
    340         this->enterStage();
    341         this->addStage();
    342         fFS.reset();
    343     }
    344     void addStage() { fStageIndex++; }
    345 
    346     // This simple class exits the stage and then restores the stage when it goes out of scope
    347     class AutoStageRestore {
    348     public:
    349         AutoStageRestore(GrGLProgramBuilder* pb)
    350             : fPB(pb), fOutOfStage(pb->fOutOfStage) { pb->exitStage(); }
    351         ~AutoStageRestore() { fPB->fOutOfStage = fOutOfStage; }
    352     private:
    353         GrGLProgramBuilder* fPB;
    354         bool fOutOfStage;
    355     };
    356     class AutoStageAdvance {
    357     public:
    358         AutoStageAdvance(GrGLProgramBuilder* pb)
    359             : fPB(pb) {
    360             fPB->reset();
    361             // Each output to the fragment processor gets its own code section
    362             fPB->fFS.nextStage();
    363         }
    364         ~AutoStageAdvance() { fPB->exitStage(); }
    365     private:
    366         GrGLProgramBuilder* fPB;
    367     };
    368     void exitStage() { fOutOfStage = true; }
    369     void enterStage() { fOutOfStage = false; }
    370     int stageIndex() const { return fStageIndex; }
    371 
    372     const char* rtAdjustment() const { return "rtAdjustment"; }
    373 
    374     // number of each input/output type in a single allocation block, used by many builders
    375     static const int kVarsPerBlock;
    376 
    377     BuiltinUniformHandles fUniformHandles;
    378     GrGLVertexBuilder fVS;
    379     GrGLGeometryBuilder fGS;
    380     GrGLFragmentShaderBuilder fFS;
    381     bool fOutOfStage;
    382     int fStageIndex;
    383 
    384     GrGLInstalledGeoProc* fGeometryProcessor;
    385     GrGLInstalledXferProc* fXferProcessor;
    386     SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
    387 
    388     const DrawArgs& fArgs;
    389     GrGLGpu* fGpu;
    390     UniformInfoArray fUniforms;
    391     GrGLPrimitiveProcessor::TransformsIn fCoordTransforms;
    392     GrGLPrimitiveProcessor::TransformsOut fOutCoords;
    393 
    394     friend class GrGLShaderBuilder;
    395     friend class GrGLVertexBuilder;
    396     friend class GrGLFragmentShaderBuilder;
    397     friend class GrGLGeometryBuilder;
    398 };
    399 #endif
    400