blob: 6141058152b88546f12bb9c2aefc29eb9c151a73 [file] [log] [blame]
joshualitt30ba4362014-08-21 20:18:45 -07001/*
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
joshualitt30ba4362014-08-21 20:18:45 -070011#include "GrGLFragmentShaderBuilder.h"
12#include "GrGLGeometryShaderBuilder.h"
13#include "GrGLVertexShaderBuilder.h"
joshualitt47bb3822014-10-07 16:43:25 -070014#include "../GrGLProgramDataManager.h"
15#include "../GrGLUniformHandle.h"
joshualitt30ba4362014-08-21 20:18:45 -070016
joshualitt89c7a2e2014-10-10 14:11:59 -070017class GrGLInstalledProcessors;
18
joshualitt47bb3822014-10-07 16:43:25 -070019/*
20 * This is the base class for a series of interfaces. This base class *MUST* remain abstract with
21 * NO data members because it is used in multiple interface inheritance.
22 * Heirarchy:
23 * GrGLUniformBuilder
24 * / \
25 * GrGLFPBuilder GrGLGPBuilder
26 * \ /
27 * GrGLProgramBuilder(internal use only)
28 */
29class GrGLUniformBuilder {
joshualitt30ba4362014-08-21 20:18:45 -070030public:
31 enum ShaderVisibility {
32 kVertex_Visibility = 0x1,
33 kGeometry_Visibility = 0x2,
34 kFragment_Visibility = 0x4,
35 };
36
joshualitt47bb3822014-10-07 16:43:25 -070037 virtual ~GrGLUniformBuilder() {}
38
joshualitt30ba4362014-08-21 20:18:45 -070039 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
joshualitt47bb3822014-10-07 16:43:25 -070040
41 /** Add a uniform variable to the current program, that has visibility in one or more shaders.
42 visibility is a bitfield of ShaderVisibility values indicating from which shaders the
43 uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
44 supported at this time. The actual uniform name will be mangled. If outName is not NULL then
45 it will refer to the final uniform name after return. Use the addUniformArray variant to add
46 an array of uniforms. */
47 virtual UniformHandle addUniform(uint32_t visibility,
48 GrSLType type,
49 const char* name,
50 const char** outName = NULL) = 0;
51 virtual UniformHandle addUniformArray(uint32_t visibility,
52 GrSLType type,
53 const char* name,
54 int arrayCount,
55 const char** outName = NULL) = 0;
56
57 virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const = 0;
58
59 /**
60 * Shortcut for getUniformVariable(u).c_str()
61 */
62 virtual const char* getUniformCStr(UniformHandle u) const = 0;
63
64 virtual const GrGLContextInfo& ctxInfo() const = 0;
65
66 virtual GrGpuGL* gpu() const = 0;
67
68 /*
69 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
70 */
71};
72
73/* a specialization of the above for GPs. Lets the user add uniforms, varyings, and VS / FS code */
74class GrGLGPBuilder : public virtual GrGLUniformBuilder {
75public:
76 virtual void addVarying(GrSLType type,
77 const char* name,
78 const char** vsOutName = NULL,
79 const char** fsInName = NULL,
80 GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision) = 0;
81
82 // TODO rename getFragmentBuilder
83 virtual GrGLGPFragmentBuilder* getFragmentShaderBuilder() = 0;
84 virtual GrGLVertexBuilder* getVertexShaderBuilder() = 0;
85
86 /*
87 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
88 */
89};
90
91/* a specializations for FPs. Lets the user add uniforms and FS code */
92class GrGLFPBuilder : public virtual GrGLUniformBuilder {
93public:
94 virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() = 0;
95
96 /*
97 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
98 */
99};
100
101/*
102 * Please note - no diamond problems because of virtual inheritance. Also, both base classes
103 * are pure virtual with no data members. This is the base class for program building.
104 * Subclasses are nearly identical but each has their own way of emitting transforms. State for
105 * each of the elements of the shader pipeline, ie vertex, fragment, geometry, etc, lives in those
106 * respective builders
107*/
108class GrGLProgramBuilder : public GrGLGPBuilder,
109 public GrGLFPBuilder {
110public:
111 /** Generates a shader program.
112 *
113 * The program implements what is specified in the stages given as input.
114 * After successful generation, the builder result objects are available
115 * to be used.
116 * @return true if generation was successful.
117 */
118 static GrGLProgram* CreateProgram(const GrOptDrawState&,
119 const GrGLProgramDesc&,
120 GrGpu::DrawType,
joshualitt89c7a2e2014-10-10 14:11:59 -0700121 const GrGeometryStage* inGeometryProcessor,
122 const GrFragmentStage* inColorStages[],
123 const GrFragmentStage* inCoverageStages[],
joshualitt47bb3822014-10-07 16:43:25 -0700124 GrGpuGL* gpu);
125
126 virtual UniformHandle addUniform(uint32_t visibility,
127 GrSLType type,
128 const char* name,
129 const char** outName = NULL) SK_OVERRIDE {
130 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
131 }
132 virtual UniformHandle addUniformArray(uint32_t visibility,
133 GrSLType type,
134 const char* name,
135 int arrayCount,
136 const char** outName = NULL) SK_OVERRIDE;
137
138 virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const SK_OVERRIDE {
139 return fUniforms[u.toShaderBuilderIndex()].fVariable;
140 }
141
142 virtual const char* getUniformCStr(UniformHandle u) const SK_OVERRIDE {
143 return this->getUniformVariable(u).c_str();
144 }
145
146 virtual const GrGLContextInfo& ctxInfo() const SK_OVERRIDE;
147
148 virtual GrGpuGL* gpu() const SK_OVERRIDE { return fGpu; }
149
joshualitt15988992014-10-09 15:04:05 -0700150 virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() SK_OVERRIDE { return &fFS; }
joshualitt47bb3822014-10-07 16:43:25 -0700151 virtual GrGLVertexBuilder* getVertexShaderBuilder() SK_OVERRIDE { return &fVS; }
152
joshualitt89c7a2e2014-10-10 14:11:59 -0700153 virtual void addVarying(GrSLType type,
154 const char* name,
155 const char** vsOutName = NULL,
156 const char** fsInName = NULL,
157 GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision);
joshualitt30ba4362014-08-21 20:18:45 -0700158
159 // Handles for program uniforms (other than per-effect uniforms)
160 struct BuiltinUniformHandles {
161 UniformHandle fViewMatrixUni;
162 UniformHandle fRTAdjustmentUni;
163 UniformHandle fColorUni;
164 UniformHandle fCoverageUni;
165
166 // We use the render target height to provide a y-down frag coord when specifying
167 // origin_upper_left is not supported.
168 UniformHandle fRTHeightUni;
169
170 // Uniforms for computing texture coords to do the dst-copy lookup
171 UniformHandle fDstCopyTopLeftUni;
172 UniformHandle fDstCopyScaleUni;
173 UniformHandle fDstCopySamplerUni;
174 };
175
joshualittdb0d3ca2014-10-07 12:42:26 -0700176protected:
joshualitt47bb3822014-10-07 16:43:25 -0700177 static GrGLProgramBuilder* CreateProgramBuilder(const GrGLProgramDesc&,
178 const GrOptDrawState&,
179 GrGpu::DrawType,
180 bool hasGeometryProcessor,
181 GrGpuGL*);
182
egdaniel307796b2014-10-06 12:13:54 -0700183 GrGLProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
joshualitt30ba4362014-08-21 20:18:45 -0700184
egdaniel307796b2014-10-06 12:13:54 -0700185 const GrOptDrawState& optState() const { return fOptState; }
joshualitt30ba4362014-08-21 20:18:45 -0700186 const GrGLProgramDesc& desc() const { return fDesc; }
joshualitt47bb3822014-10-07 16:43:25 -0700187 const GrGLProgramDesc::KeyHeader& header() const { return fDesc.getHeader(); }
joshualitt23e280d2014-09-18 12:26:38 -0700188
joshualitt30ba4362014-08-21 20:18:45 -0700189 // Generates a name for a variable. The generated string will be name prefixed by the prefix
190 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
191 // generating stage code.
192 void nameVariable(SkString* out, char prefix, const char* name);
joshualitt47bb3822014-10-07 16:43:25 -0700193 void setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage);
joshualitt89c7a2e2014-10-10 14:11:59 -0700194 void createAndEmitProcessors(const GrGeometryStage* geometryProcessor,
195 const GrFragmentStage* colorStages[],
196 const GrFragmentStage* coverageStages[],
197 GrGLSLExpr4* inputColor,
198 GrGLSLExpr4* inputCoverage);
199 template <class ProcessorStage>
200 void createAndEmitProcessors(const ProcessorStage*[],
201 int effectCnt,
202 const GrGLProgramDesc::EffectKeyProvider&,
203 GrGLSLExpr4* fsInOutColor,
204 GrGLInstalledProcessors*);
joshualitt47bb3822014-10-07 16:43:25 -0700205 void verify(const GrGeometryProcessor&);
206 void verify(const GrFragmentProcessor&);
207 void emitSamplers(const GrProcessor&,
208 GrGLProcessor::TextureSamplerArray* outSamplers,
joshualitt89c7a2e2014-10-10 14:11:59 -0700209 GrGLInstalledProcessors*);
joshualitt30ba4362014-08-21 20:18:45 -0700210
joshualitt47bb3822014-10-07 16:43:25 -0700211 // each specific program builder has a distinct transform and must override this function
joshualitt89c7a2e2014-10-10 14:11:59 -0700212 virtual void emitTransforms(const GrProcessorStage&,
joshualitt47bb3822014-10-07 16:43:25 -0700213 GrGLProcessor::TransformedCoordsArray* outCoords,
joshualitt89c7a2e2014-10-10 14:11:59 -0700214 GrGLInstalledProcessors*);
joshualitt47bb3822014-10-07 16:43:25 -0700215 GrGLProgram* finalize();
216 void bindUniformLocations(GrGLuint programID);
217 bool checkLinkStatus(GrGLuint programID);
218 void resolveUniformLocations(GrGLuint programID);
joshualitt89c7a2e2014-10-10 14:11:59 -0700219
joshualitt47bb3822014-10-07 16:43:25 -0700220 void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);
221 void cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs);
joshualitt30ba4362014-08-21 20:18:45 -0700222
joshualitt47bb3822014-10-07 16:43:25 -0700223 // Subclasses create different programs
224 virtual GrGLProgram* createProgram(GrGLuint programID);
225
joshualitt30ba4362014-08-21 20:18:45 -0700226 void appendUniformDecls(ShaderVisibility, SkString*) const;
227
joshualitt47bb3822014-10-07 16:43:25 -0700228 // reset is called by program creator between each processor's emit code. It increments the
229 // stage offset for variable name mangling, and also ensures verfication variables in the
230 // fragment shader are cleared.
231 void reset() {
232 this->enterStage();
233 this->addStage();
234 fFS.reset();
235 }
236 void addStage() { fStageIndex++; }
237
238 // This simple class exits the stage and then restores the stage when it goes out of scope
239 class AutoStageRestore {
joshualitt30ba4362014-08-21 20:18:45 -0700240 public:
joshualitt47bb3822014-10-07 16:43:25 -0700241 AutoStageRestore(GrGLProgramBuilder* pb)
242 : fPB(pb), fOutOfStage(pb->fOutOfStage) { pb->exitStage(); }
243 ~AutoStageRestore() { fPB->fOutOfStage = fOutOfStage; }
joshualittb0a8a372014-09-23 09:50:21 -0700244 private:
joshualitt47bb3822014-10-07 16:43:25 -0700245 GrGLProgramBuilder* fPB;
246 bool fOutOfStage;
joshualittb0a8a372014-09-23 09:50:21 -0700247 };
joshualitt47bb3822014-10-07 16:43:25 -0700248 class AutoStageAdvance {
joshualittdb0d3ca2014-10-07 12:42:26 -0700249 public:
joshualitt47bb3822014-10-07 16:43:25 -0700250 AutoStageAdvance(GrGLProgramBuilder* pb) : fPB(pb) { fPB->reset(); }
251 ~AutoStageAdvance() { fPB->exitStage(); }
joshualittdb0d3ca2014-10-07 12:42:26 -0700252 private:
joshualitt47bb3822014-10-07 16:43:25 -0700253 GrGLProgramBuilder* fPB;
254 };
255 void exitStage() { fOutOfStage = true; }
256 void enterStage() { fOutOfStage = false; }
257 int stageIndex() const { return fStageIndex; }
258
joshualitt89c7a2e2014-10-10 14:11:59 -0700259 typedef GrGLProgramDesc::EffectKeyProvider EffectKeyProvider;
260 typedef GrGLProgramDataManager::UniformInfo UniformInfo;
261 typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
262
joshualitt47bb3822014-10-07 16:43:25 -0700263 // number of each input/output type in a single allocation block, used by many builders
264 static const int kVarsPerBlock;
265
266 BuiltinUniformHandles fUniformHandles;
267 GrGLVertexBuilder fVS;
268 GrGLGeometryBuilder fGS;
269 GrGLFragmentShaderBuilder fFS;
270 bool fOutOfStage;
271 int fStageIndex;
272
joshualitt89c7a2e2014-10-10 14:11:59 -0700273 SkAutoTUnref<GrGLInstalledProcessors> fGeometryProcessor;
274 SkAutoTUnref<GrGLInstalledProcessors> fColorEffects;
275 SkAutoTUnref<GrGLInstalledProcessors> fCoverageEffects;
joshualitt47bb3822014-10-07 16:43:25 -0700276
277 const GrOptDrawState& fOptState;
278 const GrGLProgramDesc& fDesc;
279 GrGpuGL* fGpu;
280 UniformInfoArray fUniforms;
281
282 friend class GrGLShaderBuilder;
283 friend class GrGLVertexBuilder;
284 friend class GrGLFragmentShaderBuilder;
285 friend class GrGLGeometryBuilder;
286};
287
288/**
joshualitt89c7a2e2014-10-10 14:11:59 -0700289 * This class encapsulates an array of GrGLProcessors and their supporting data (coord transforms
290 * and textures). It is built by GrGLProgramBuilder, then used to manage the necessary GL
291 * state and shader uniforms in GLPrograms. Its just Plain old data, and as such is entirely public
292 *
293 * TODO We really don't need this class to have an array of processors. It makes sense for it
294 * to just have one, also break out the transforms
joshualitt47bb3822014-10-07 16:43:25 -0700295 */
joshualitt89c7a2e2014-10-10 14:11:59 -0700296class GrGLInstalledProcessors : public SkRefCnt {
297public:
298 GrGLInstalledProcessors(int reserveCount, bool hasExplicitLocalCoords = false)
299 : fGLProcessors(reserveCount)
300 , fSamplers(reserveCount)
301 , fTransforms(reserveCount)
302 , fHasExplicitLocalCoords(hasExplicitLocalCoords) {
303 }
joshualitt47bb3822014-10-07 16:43:25 -0700304
joshualitt89c7a2e2014-10-10 14:11:59 -0700305 virtual ~GrGLInstalledProcessors();
joshualitt47bb3822014-10-07 16:43:25 -0700306
joshualitt89c7a2e2014-10-10 14:11:59 -0700307 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
joshualitt47bb3822014-10-07 16:43:25 -0700308
joshualitt89c7a2e2014-10-10 14:11:59 -0700309 struct Sampler {
310 SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
311 UniformHandle fUniform;
312 int fTextureUnit;
313 };
314
joshualitt47bb3822014-10-07 16:43:25 -0700315 class ShaderVarHandle {
316 public:
317 bool isValid() const { return fHandle > -1; }
318 ShaderVarHandle() : fHandle(-1) {}
319 ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); }
320 int handle() const { SkASSERT(this->isValid()); return fHandle; }
321 UniformHandle convertToUniformHandle() {
322 SkASSERT(this->isValid());
323 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle);
324 }
joshualittdb0d3ca2014-10-07 12:42:26 -0700325
joshualitt47bb3822014-10-07 16:43:25 -0700326 private:
327 int fHandle;
328 };
joshualittdb0d3ca2014-10-07 12:42:26 -0700329
joshualitt47bb3822014-10-07 16:43:25 -0700330 struct Transform {
331 Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
332 ShaderVarHandle fHandle;
333 SkMatrix fCurrentValue;
334 GrSLType fType;
335 };
joshualittdb0d3ca2014-10-07 12:42:26 -0700336
joshualitt89c7a2e2014-10-10 14:11:59 -0700337 void addEffect(GrGLProcessor* effect) { fGLProcessors.push_back(effect); }
338 SkTArray<Sampler, true>& addSamplers() { return fSamplers.push_back(); }
339 SkTArray<Transform, true>& addTransforms() { return fTransforms.push_back(); }
joshualittdb0d3ca2014-10-07 12:42:26 -0700340
joshualitt89c7a2e2014-10-10 14:11:59 -0700341 SkTArray<GrGLProcessor*> fGLProcessors;
342 SkTArray<SkSTArray<4, Sampler, true> > fSamplers;
343 SkTArray<SkSTArray<2, Transform, true> > fTransforms;
344 bool fHasExplicitLocalCoords;
345
346 friend class GrGLShaderBuilder;
347 friend class GrGLVertexShaderBuilder;
348 friend class GrGLFragmentShaderBuilder;
349 friend class GrGLGeometryShaderBuilder;
joshualitt30ba4362014-08-21 20:18:45 -0700350};
351
joshualitt30ba4362014-08-21 20:18:45 -0700352#endif