• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
~GrGLUniformBuilder()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:
vsVarying()84     bool vsVarying() const { return kVertToFrag_Varying == fVarying ||
85                                     kVertToGeo_Varying == fVarying; }
fsVarying()86     bool fsVarying() const { return kVertToFrag_Varying == fVarying ||
87                                     kGeoToFrag_Varying == fVarying; }
vsOut()88     const char* vsOut() const { return fVsOut; }
gsIn()89     const char* gsIn() const { return fGsIn; }
gsOut()90     const char* gsOut() const { return fGsOut; }
fsIn()91     const char* fsIn() const { return fFsIn; }
type()92     GrSLType type() const { return fType; }
93 
94 protected:
95     enum Varying {
96         kVertToFrag_Varying,
97         kVertToGeo_Varying,
98         kGeoToFrag_Varying,
99     };
100 
GrGLVarying(GrSLType type,Varying varying)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 {
GrGLVertToFragGrGLVertToFrag121     GrGLVertToFrag(GrSLType type)
122         : GrGLVarying(type, kVertToFrag_Varying) {}
123 };
124 
125 struct GrGLVertToGeo : public GrGLVarying {
GrGLVertToGeoGrGLVertToGeo126     GrGLVertToGeo(GrSLType type)
127         : GrGLVarying(type, kVertToGeo_Varying) {}
128 };
129 
130 struct GrGLGeoToFrag : public GrGLVarying {
GrGLGeoToFragGrGLGeoToFrag131     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 
getUniformVariable(UniformHandle u)239     const GrGLShaderVar& getUniformVariable(UniformHandle u) const override {
240         return fUniforms[u.toShaderBuilderIndex()].fVariable;
241     }
242 
getUniformCStr(UniformHandle u)243     const char* getUniformCStr(UniformHandle u) const override {
244         return this->getUniformVariable(u).c_str();
245     }
246 
247     const GrGLContextInfo& ctxInfo() const override;
248 
gpu()249     GrGLGpu* gpu() const override { return fGpu; }
250 
getFragmentShaderBuilder()251     GrGLXPFragmentBuilder* getFragmentShaderBuilder() override { return &fFS; }
getVertexShaderBuilder()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 
primitiveProcessor()280     const GrPrimitiveProcessor& primitiveProcessor() const { return *fArgs.fPrimitiveProcessor; }
pipeline()281     const GrPipeline& pipeline() const { return *fArgs.fPipeline; }
desc()282     const GrProgramDesc& desc() const { return *fArgs.fDesc; }
batchTracker()283     const GrBatchTracker& batchTracker() const { return *fArgs.fBatchTracker; }
header()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.
reset()339     void reset() {
340         this->enterStage();
341         this->addStage();
342         fFS.reset();
343     }
addStage()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:
AutoStageRestore(GrGLProgramBuilder * pb)349         AutoStageRestore(GrGLProgramBuilder* pb)
350             : fPB(pb), fOutOfStage(pb->fOutOfStage) { pb->exitStage(); }
~AutoStageRestore()351         ~AutoStageRestore() { fPB->fOutOfStage = fOutOfStage; }
352     private:
353         GrGLProgramBuilder* fPB;
354         bool fOutOfStage;
355     };
356     class AutoStageAdvance {
357     public:
AutoStageAdvance(GrGLProgramBuilder * pb)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         }
~AutoStageAdvance()364         ~AutoStageAdvance() { fPB->exitStage(); }
365     private:
366         GrGLProgramBuilder* fPB;
367     };
exitStage()368     void exitStage() { fOutOfStage = true; }
enterStage()369     void enterStage() { fOutOfStage = false; }
stageIndex()370     int stageIndex() const { return fStageIndex; }
371 
rtAdjustment()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