2 * Copyright 2014 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #ifndef GrGLProgramBuilder_DEFINED
9 #define GrGLProgramBuilder_DEFINED
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"
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.
27 * GrGLFPBuilder GrGLGPBuilder
29 * GrGLProgramBuilder(internal use only)
31 class GrGLUniformBuilder {
33 enum ShaderVisibility {
34 kVertex_Visibility = 1 << kVertex_GrShaderType,
35 kGeometry_Visibility = 1 << kGeometry_GrShaderType,
36 kFragment_Visibility = 1 << kFragment_GrShaderType,
39 virtual ~GrGLUniformBuilder() {}
41 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
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,
51 GrSLPrecision precision,
53 const char** outName = NULL) {
54 return this->addUniformArray(visibility, type, precision, name, 0, outName);
57 virtual UniformHandle addUniformArray(
60 GrSLPrecision precision,
63 const char** outName = NULL) = 0;
65 virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const = 0;
68 * Shortcut for getUniformVariable(u).c_str()
70 virtual const char* getUniformCStr(UniformHandle u) const = 0;
72 virtual const GrGLContextInfo& ctxInfo() const = 0;
74 virtual GrGLGpu* gpu() const = 0;
77 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
81 // TODO move this into GrGLGPBuilder and move them both out of this file
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; }
101 GrGLVarying(GrSLType type, Varying varying)
102 : fVarying(varying), fType(type), fVsOut(NULL), fGsIn(NULL), fGsOut(NULL),
114 friend class GrGLVertexBuilder;
115 friend class GrGLGeometryBuilder;
116 friend class GrGLXferBuilder;
117 friend class GrGLFragmentShaderBuilder;
120 struct GrGLVertToFrag : public GrGLVarying {
121 GrGLVertToFrag(GrSLType type)
122 : GrGLVarying(type, kVertToFrag_Varying) {}
125 struct GrGLVertToGeo : public GrGLVarying {
126 GrGLVertToGeo(GrSLType type)
127 : GrGLVarying(type, kVertToGeo_Varying) {}
130 struct GrGLGeoToFrag : public GrGLVarying {
131 GrGLGeoToFrag(GrSLType type)
132 : GrGLVarying(type, kGeoToFrag_Varying) {}
135 /* a specialization of the above for GPs. Lets the user add uniforms, varyings, and VS / FS code */
136 class GrGLGPBuilder : public virtual GrGLUniformBuilder {
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
144 virtual void addVarying(const char* name,
146 GrSLPrecision fsPrecision = kDefault_GrSLPrecision) = 0;
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
154 virtual void addPassThroughAttribute(const GrGeometryProcessor::Attribute*,
155 const char* output) = 0;
157 // TODO rename getFragmentBuilder
158 virtual GrGLGPFragmentBuilder* getFragmentShaderBuilder() = 0;
159 virtual GrGLVertexBuilder* getVertexShaderBuilder() = 0;
162 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
166 /* a specializations for FPs. Lets the user add uniforms and FS code */
167 class GrGLFPBuilder : public virtual GrGLUniformBuilder {
169 virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() = 0;
172 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
176 /* a specializations for XPs. Lets the user add uniforms and FS code */
177 class GrGLXPBuilder : public virtual GrGLUniformBuilder {
179 virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() = 0;
182 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
187 * The below struct represent processors installed in programs.
189 template <class Proc>
190 struct GrGLInstalledProc {
191 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
194 SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
195 UniformHandle fUniform;
198 SkSTArray<4, Sampler, true> fSamplers;
199 SkAutoTDelete<Proc> fGLProc;
202 typedef GrGLInstalledProc<GrGLPrimitiveProcessor> GrGLInstalledGeoProc;
203 typedef GrGLInstalledProc<GrGLXferProcessor> GrGLInstalledXferProc;
204 typedef GrGLInstalledProc<GrGLFragmentProcessor> GrGLInstalledFragProc;
206 struct GrGLInstalledFragProcs : public SkRefCnt {
207 virtual ~GrGLInstalledFragProcs();
208 SkSTArray<8, GrGLInstalledFragProc*, true> fProcs;
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
218 class GrGLProgramBuilder : public GrGLGPBuilder,
219 public GrGLFPBuilder,
220 public GrGLXPBuilder {
222 typedef GrGpu::DrawArgs DrawArgs;
223 /** Generates a shader program.
225 * The program implements what is specified in the stages given as input.
226 * After successful generation, the builder result objects are available
228 * @return true if generation was successful.
230 static GrGLProgram* CreateProgram(const DrawArgs&, GrGLGpu*);
232 UniformHandle addUniformArray(uint32_t visibility,
234 GrSLPrecision precision,
237 const char** outName) override;
239 const GrGLShaderVar& getUniformVariable(UniformHandle u) const override {
240 return fUniforms[u.toShaderBuilderIndex()].fVariable;
243 const char* getUniformCStr(UniformHandle u) const override {
244 return this->getUniformVariable(u).c_str();
247 const GrGLContextInfo& ctxInfo() const override;
249 GrGLGpu* gpu() const override { return fGpu; }
251 GrGLFPFragmentBuilder* getFragmentShaderBuilder() override { return &fFS; }
252 GrGLVertexBuilder* getVertexShaderBuilder() override { return &fVS; }
257 GrSLPrecision fsPrecision = kDefault_GrSLPrecision) override;
259 void addPassThroughAttribute(const GrPrimitiveProcessor::Attribute*,
260 const char* output) override;
263 // Handles for program uniforms (other than per-effect uniforms)
264 struct BuiltinUniformHandles {
265 UniformHandle fRTAdjustmentUni;
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;
273 typedef GrGLProgramDataManager::UniformInfo UniformInfo;
274 typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
276 static GrGLProgramBuilder* CreateProgramBuilder(const DrawArgs&, GrGLGpu*);
278 GrGLProgramBuilder(GrGLGpu*, const DrawArgs&);
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(); }
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 void emitAndInstallProcs(GrGLSLExpr4* inputColor,
294 GrGLSLExpr4* inputCoverage);
295 void emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut);
296 void emitAndInstallProc(const GrPendingFragmentStage&,
298 const GrGLSLExpr4& input,
299 GrGLSLExpr4* output);
301 void emitAndInstallProc(const GrPrimitiveProcessor&,
302 GrGLSLExpr4* outputColor,
303 GrGLSLExpr4* outputCoverage);
305 // these emit functions help to keep the createAndEmitProcessors template general
306 void emitAndInstallProc(const GrPendingFragmentStage&,
308 const char* outColor,
309 const char* inColor);
310 void emitAndInstallProc(const GrPrimitiveProcessor&,
311 const char* outColor,
312 const char* outCoverage);
313 void emitAndInstallXferProc(const GrXferProcessor&,
314 const GrGLSLExpr4& colorIn,
315 const GrGLSLExpr4& coverageIn);
317 void verify(const GrPrimitiveProcessor&);
318 void verify(const GrXferProcessor&);
319 void verify(const GrFragmentProcessor&);
320 template <class Proc>
321 void emitSamplers(const GrProcessor&,
322 GrGLProcessor::TextureSamplerArray* outSamplers,
323 GrGLInstalledProc<Proc>*);
325 GrGLProgram* finalize();
326 void bindUniformLocations(GrGLuint programID);
327 bool checkLinkStatus(GrGLuint programID);
328 void resolveUniformLocations(GrGLuint programID);
329 void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);
330 void cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs);
332 // Subclasses create different programs
333 virtual GrGLProgram* createProgram(GrGLuint programID);
335 void appendUniformDecls(ShaderVisibility, SkString*) const;
337 // reset is called by program creator between each processor's emit code. It increments the
338 // stage offset for variable name mangling, and also ensures verfication variables in the
339 // fragment shader are cleared.
345 void addStage() { fStageIndex++; }
347 // This simple class exits the stage and then restores the stage when it goes out of scope
348 class AutoStageRestore {
350 AutoStageRestore(GrGLProgramBuilder* pb)
351 : fPB(pb), fOutOfStage(pb->fOutOfStage) { pb->exitStage(); }
352 ~AutoStageRestore() { fPB->fOutOfStage = fOutOfStage; }
354 GrGLProgramBuilder* fPB;
357 class AutoStageAdvance {
359 AutoStageAdvance(GrGLProgramBuilder* pb)
362 // Each output to the fragment processor gets its own code section
363 fPB->fFS.nextStage();
365 ~AutoStageAdvance() { fPB->exitStage(); }
367 GrGLProgramBuilder* fPB;
369 void exitStage() { fOutOfStage = true; }
370 void enterStage() { fOutOfStage = false; }
371 int stageIndex() const { return fStageIndex; }
373 const char* rtAdjustment() const { return "rtAdjustment"; }
375 // number of each input/output type in a single allocation block, used by many builders
376 static const int kVarsPerBlock;
378 BuiltinUniformHandles fUniformHandles;
379 GrGLVertexBuilder fVS;
380 GrGLGeometryBuilder fGS;
381 GrGLFragmentShaderBuilder fFS;
385 GrGLInstalledGeoProc* fGeometryProcessor;
386 GrGLInstalledXferProc* fXferProcessor;
387 SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
389 const DrawArgs& fArgs;
391 UniformInfoArray fUniforms;
392 GrGLPrimitiveProcessor::TransformsIn fCoordTransforms;
393 GrGLPrimitiveProcessor::TransformsOut fOutCoords;
395 friend class GrGLShaderBuilder;
396 friend class GrGLVertexBuilder;
397 friend class GrGLFragmentShaderBuilder;
398 friend class GrGLGeometryBuilder;