blob: 9d8e7e0ac9657ee6844d7b43a85c925be0305143 [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"
joshualitta5305a12014-10-10 17:47:00 -070016#include "../GrGLGeometryProcessor.h"
joshualitt89c7a2e2014-10-10 14:11:59 -070017
joshualitt47bb3822014-10-07 16:43:25 -070018/*
19 * This is the base class for a series of interfaces. This base class *MUST* remain abstract with
20 * NO data members because it is used in multiple interface inheritance.
21 * Heirarchy:
22 * GrGLUniformBuilder
23 * / \
24 * GrGLFPBuilder GrGLGPBuilder
25 * \ /
26 * GrGLProgramBuilder(internal use only)
27 */
28class GrGLUniformBuilder {
joshualitt30ba4362014-08-21 20:18:45 -070029public:
30 enum ShaderVisibility {
31 kVertex_Visibility = 0x1,
32 kGeometry_Visibility = 0x2,
33 kFragment_Visibility = 0x4,
34 };
35
joshualitt47bb3822014-10-07 16:43:25 -070036 virtual ~GrGLUniformBuilder() {}
37
joshualitt30ba4362014-08-21 20:18:45 -070038 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
joshualitt47bb3822014-10-07 16:43:25 -070039
40 /** Add a uniform variable to the current program, that has visibility in one or more shaders.
41 visibility is a bitfield of ShaderVisibility values indicating from which shaders the
42 uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
43 supported at this time. The actual uniform name will be mangled. If outName is not NULL then
44 it will refer to the final uniform name after return. Use the addUniformArray variant to add
45 an array of uniforms. */
46 virtual UniformHandle addUniform(uint32_t visibility,
47 GrSLType type,
48 const char* name,
49 const char** outName = NULL) = 0;
50 virtual UniformHandle addUniformArray(uint32_t visibility,
51 GrSLType type,
52 const char* name,
53 int arrayCount,
54 const char** outName = NULL) = 0;
55
56 virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const = 0;
57
58 /**
59 * Shortcut for getUniformVariable(u).c_str()
60 */
61 virtual const char* getUniformCStr(UniformHandle u) const = 0;
62
63 virtual const GrGLContextInfo& ctxInfo() const = 0;
64
65 virtual GrGpuGL* gpu() const = 0;
66
67 /*
68 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
69 */
70};
71
joshualitt74077b92014-10-24 11:26:03 -070072// TODO move this into GrGLGPBuilder and move them both out of this file
73class GrGLVarying {
74public:
75 bool vsVarying() const { return kVertToFrag_Varying == fVarying ||
76 kVertToGeo_Varying == fVarying; }
77 bool fsVarying() const { return kVertToFrag_Varying == fVarying ||
78 kGeoToFrag_Varying == fVarying; }
79 const char* vsOut() const { return fVsOut; }
80 const char* gsIn() const { return fGsIn; }
81 const char* gsOut() const { return fGsOut; }
82 const char* fsIn() const { return fFsIn; }
83
84protected:
85 enum Varying {
86 kVertToFrag_Varying,
87 kVertToGeo_Varying,
88 kGeoToFrag_Varying,
89 };
90
91 GrGLVarying(GrSLType type, Varying varying)
92 : fVarying(varying), fType(type), fVsOut(NULL), fGsIn(NULL), fGsOut(NULL),
93 fFsIn(NULL) {}
94
95 Varying fVarying;
96
97private:
98 GrSLType fType;
99 const char* fVsOut;
100 const char* fGsIn;
101 const char* fGsOut;
102 const char* fFsIn;
103
104 friend class GrGLVertexBuilder;
105 friend class GrGLGeometryBuilder;
106 friend class GrGLFragmentShaderBuilder;
107};
108
109struct GrGLVertToFrag : public GrGLVarying {
110 GrGLVertToFrag(GrSLType type)
111 : GrGLVarying(type, kVertToFrag_Varying) {}
112};
113
114struct GrGLVertToGeo : public GrGLVarying {
115 GrGLVertToGeo(GrSLType type)
116 : GrGLVarying(type, kVertToGeo_Varying) {}
117};
118
119struct GrGLGeoToFrag : public GrGLVarying {
120 GrGLGeoToFrag(GrSLType type)
121 : GrGLVarying(type, kGeoToFrag_Varying) {}
122};
123
joshualitt47bb3822014-10-07 16:43:25 -0700124/* a specialization of the above for GPs. Lets the user add uniforms, varyings, and VS / FS code */
125class GrGLGPBuilder : public virtual GrGLUniformBuilder {
126public:
joshualitt74077b92014-10-24 11:26:03 -0700127 virtual void addVarying(const char* name,
128 GrGLVarying*,
joshualitt47bb3822014-10-07 16:43:25 -0700129 GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision) = 0;
130
131 // TODO rename getFragmentBuilder
132 virtual GrGLGPFragmentBuilder* getFragmentShaderBuilder() = 0;
133 virtual GrGLVertexBuilder* getVertexShaderBuilder() = 0;
134
135 /*
136 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
137 */
138};
139
140/* a specializations for FPs. Lets the user add uniforms and FS code */
141class GrGLFPBuilder : public virtual GrGLUniformBuilder {
142public:
143 virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() = 0;
144
145 /*
146 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
147 */
148};
149
joshualitta5305a12014-10-10 17:47:00 -0700150struct GrGLInstalledProc;
151struct GrGLInstalledGeoProc;
152struct GrGLInstalledFragProc;
153struct GrGLInstalledFragProcs;
154
joshualitt47bb3822014-10-07 16:43:25 -0700155/*
156 * Please note - no diamond problems because of virtual inheritance. Also, both base classes
157 * are pure virtual with no data members. This is the base class for program building.
158 * Subclasses are nearly identical but each has their own way of emitting transforms. State for
159 * each of the elements of the shader pipeline, ie vertex, fragment, geometry, etc, lives in those
160 * respective builders
161*/
162class GrGLProgramBuilder : public GrGLGPBuilder,
163 public GrGLFPBuilder {
164public:
165 /** Generates a shader program.
166 *
167 * The program implements what is specified in the stages given as input.
168 * After successful generation, the builder result objects are available
169 * to be used.
170 * @return true if generation was successful.
171 */
172 static GrGLProgram* CreateProgram(const GrOptDrawState&,
173 const GrGLProgramDesc&,
174 GrGpu::DrawType,
joshualitt47bb3822014-10-07 16:43:25 -0700175 GrGpuGL* gpu);
176
177 virtual UniformHandle addUniform(uint32_t visibility,
178 GrSLType type,
179 const char* name,
180 const char** outName = NULL) SK_OVERRIDE {
181 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
182 }
183 virtual UniformHandle addUniformArray(uint32_t visibility,
184 GrSLType type,
185 const char* name,
186 int arrayCount,
187 const char** outName = NULL) SK_OVERRIDE;
188
189 virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const SK_OVERRIDE {
190 return fUniforms[u.toShaderBuilderIndex()].fVariable;
191 }
192
193 virtual const char* getUniformCStr(UniformHandle u) const SK_OVERRIDE {
194 return this->getUniformVariable(u).c_str();
195 }
196
197 virtual const GrGLContextInfo& ctxInfo() const SK_OVERRIDE;
198
199 virtual GrGpuGL* gpu() const SK_OVERRIDE { return fGpu; }
200
joshualitt15988992014-10-09 15:04:05 -0700201 virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() SK_OVERRIDE { return &fFS; }
joshualitt47bb3822014-10-07 16:43:25 -0700202 virtual GrGLVertexBuilder* getVertexShaderBuilder() SK_OVERRIDE { return &fVS; }
203
joshualitta5305a12014-10-10 17:47:00 -0700204 virtual void addVarying(
joshualitta5305a12014-10-10 17:47:00 -0700205 const char* name,
joshualitt74077b92014-10-24 11:26:03 -0700206 GrGLVarying*,
joshualitta5305a12014-10-10 17:47:00 -0700207 GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision) SK_OVERRIDE;
joshualitt30ba4362014-08-21 20:18:45 -0700208
209 // Handles for program uniforms (other than per-effect uniforms)
210 struct BuiltinUniformHandles {
211 UniformHandle fViewMatrixUni;
212 UniformHandle fRTAdjustmentUni;
213 UniformHandle fColorUni;
214 UniformHandle fCoverageUni;
215
216 // We use the render target height to provide a y-down frag coord when specifying
217 // origin_upper_left is not supported.
218 UniformHandle fRTHeightUni;
219
220 // Uniforms for computing texture coords to do the dst-copy lookup
221 UniformHandle fDstCopyTopLeftUni;
222 UniformHandle fDstCopyScaleUni;
223 UniformHandle fDstCopySamplerUni;
224 };
225
joshualittdb0d3ca2014-10-07 12:42:26 -0700226protected:
joshualitta5305a12014-10-10 17:47:00 -0700227 typedef GrGLProgramDesc::ProcKeyProvider ProcKeyProvider;
228 typedef GrGLProgramDataManager::UniformInfo UniformInfo;
229 typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
230
joshualitt47bb3822014-10-07 16:43:25 -0700231 static GrGLProgramBuilder* CreateProgramBuilder(const GrGLProgramDesc&,
232 const GrOptDrawState&,
233 GrGpu::DrawType,
234 bool hasGeometryProcessor,
235 GrGpuGL*);
236
egdaniel307796b2014-10-06 12:13:54 -0700237 GrGLProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
joshualitt30ba4362014-08-21 20:18:45 -0700238
egdaniel307796b2014-10-06 12:13:54 -0700239 const GrOptDrawState& optState() const { return fOptState; }
joshualitt30ba4362014-08-21 20:18:45 -0700240 const GrGLProgramDesc& desc() const { return fDesc; }
joshualitt47bb3822014-10-07 16:43:25 -0700241 const GrGLProgramDesc::KeyHeader& header() const { return fDesc.getHeader(); }
joshualitt23e280d2014-09-18 12:26:38 -0700242
joshualitt30ba4362014-08-21 20:18:45 -0700243 // Generates a name for a variable. The generated string will be name prefixed by the prefix
244 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
245 // generating stage code.
246 void nameVariable(SkString* out, char prefix, const char* name);
joshualitt47bb3822014-10-07 16:43:25 -0700247 void setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage);
joshualitta5305a12014-10-10 17:47:00 -0700248 void emitAndInstallProcs(const GrOptDrawState& optState,
249 GrGLSLExpr4* inputColor,
250 GrGLSLExpr4* inputCoverage);
251 void emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut);
252 template <class Proc>
253 void emitAndInstallProc(const Proc&,
254 int index,
255 const ProcKeyProvider,
256 const GrGLSLExpr4& input,
257 GrGLSLExpr4* output);
258
259 // these emit functions help to keep the createAndEmitProcessors template general
260 void emitAndInstallProc(const GrFragmentStage&,
261 const GrProcessorKey&,
262 const char* outColor,
263 const char* inColor);
264 void emitAndInstallProc(const GrGeometryProcessor&,
265 const GrProcessorKey&,
266 const char* outColor,
267 const char* inColor);
joshualitt47bb3822014-10-07 16:43:25 -0700268 void verify(const GrGeometryProcessor&);
269 void verify(const GrFragmentProcessor&);
270 void emitSamplers(const GrProcessor&,
271 GrGLProcessor::TextureSamplerArray* outSamplers,
joshualitta5305a12014-10-10 17:47:00 -0700272 GrGLInstalledProc*);
joshualitt30ba4362014-08-21 20:18:45 -0700273
joshualitt47bb3822014-10-07 16:43:25 -0700274 // each specific program builder has a distinct transform and must override this function
joshualitta5305a12014-10-10 17:47:00 -0700275 virtual void emitTransforms(const GrFragmentStage&,
joshualitt47bb3822014-10-07 16:43:25 -0700276 GrGLProcessor::TransformedCoordsArray* outCoords,
joshualitta5305a12014-10-10 17:47:00 -0700277 GrGLInstalledFragProc*);
joshualitt47bb3822014-10-07 16:43:25 -0700278 GrGLProgram* finalize();
279 void bindUniformLocations(GrGLuint programID);
280 bool checkLinkStatus(GrGLuint programID);
281 void resolveUniformLocations(GrGLuint programID);
joshualitt47bb3822014-10-07 16:43:25 -0700282 void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);
283 void cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs);
joshualitt30ba4362014-08-21 20:18:45 -0700284
joshualitt47bb3822014-10-07 16:43:25 -0700285 // Subclasses create different programs
286 virtual GrGLProgram* createProgram(GrGLuint programID);
287
joshualitt30ba4362014-08-21 20:18:45 -0700288 void appendUniformDecls(ShaderVisibility, SkString*) const;
289
joshualitt47bb3822014-10-07 16:43:25 -0700290 // reset is called by program creator between each processor's emit code. It increments the
291 // stage offset for variable name mangling, and also ensures verfication variables in the
292 // fragment shader are cleared.
293 void reset() {
294 this->enterStage();
295 this->addStage();
296 fFS.reset();
297 }
298 void addStage() { fStageIndex++; }
299
300 // This simple class exits the stage and then restores the stage when it goes out of scope
301 class AutoStageRestore {
joshualitt30ba4362014-08-21 20:18:45 -0700302 public:
joshualitt47bb3822014-10-07 16:43:25 -0700303 AutoStageRestore(GrGLProgramBuilder* pb)
304 : fPB(pb), fOutOfStage(pb->fOutOfStage) { pb->exitStage(); }
305 ~AutoStageRestore() { fPB->fOutOfStage = fOutOfStage; }
joshualittb0a8a372014-09-23 09:50:21 -0700306 private:
joshualitt47bb3822014-10-07 16:43:25 -0700307 GrGLProgramBuilder* fPB;
308 bool fOutOfStage;
joshualittb0a8a372014-09-23 09:50:21 -0700309 };
joshualitt47bb3822014-10-07 16:43:25 -0700310 class AutoStageAdvance {
joshualittdb0d3ca2014-10-07 12:42:26 -0700311 public:
joshualitt47bb3822014-10-07 16:43:25 -0700312 AutoStageAdvance(GrGLProgramBuilder* pb) : fPB(pb) { fPB->reset(); }
313 ~AutoStageAdvance() { fPB->exitStage(); }
joshualittdb0d3ca2014-10-07 12:42:26 -0700314 private:
joshualitt47bb3822014-10-07 16:43:25 -0700315 GrGLProgramBuilder* fPB;
316 };
317 void exitStage() { fOutOfStage = true; }
318 void enterStage() { fOutOfStage = false; }
319 int stageIndex() const { return fStageIndex; }
320
joshualitt47bb3822014-10-07 16:43:25 -0700321 // number of each input/output type in a single allocation block, used by many builders
322 static const int kVarsPerBlock;
323
324 BuiltinUniformHandles fUniformHandles;
325 GrGLVertexBuilder fVS;
326 GrGLGeometryBuilder fGS;
327 GrGLFragmentShaderBuilder fFS;
328 bool fOutOfStage;
329 int fStageIndex;
330
joshualitta5305a12014-10-10 17:47:00 -0700331 GrGLInstalledGeoProc* fGeometryProcessor;
332 SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
joshualitt47bb3822014-10-07 16:43:25 -0700333
334 const GrOptDrawState& fOptState;
335 const GrGLProgramDesc& fDesc;
336 GrGpuGL* fGpu;
337 UniformInfoArray fUniforms;
338
339 friend class GrGLShaderBuilder;
340 friend class GrGLVertexBuilder;
341 friend class GrGLFragmentShaderBuilder;
342 friend class GrGLGeometryBuilder;
343};
344
345/**
joshualitta5305a12014-10-10 17:47:00 -0700346 * The below structs represent processors installed in programs. All processors can have texture
347 * samplers, but only frag processors have coord transforms, hence the need for different structs
joshualitt47bb3822014-10-07 16:43:25 -0700348 */
joshualitta5305a12014-10-10 17:47:00 -0700349struct GrGLInstalledProc {
350 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
joshualitt47bb3822014-10-07 16:43:25 -0700351
joshualitta5305a12014-10-10 17:47:00 -0700352 struct Sampler {
353 SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
354 UniformHandle fUniform;
355 int fTextureUnit;
356 };
357 SkSTArray<4, Sampler, true> fSamplers;
358};
joshualitt47bb3822014-10-07 16:43:25 -0700359
joshualitta5305a12014-10-10 17:47:00 -0700360struct GrGLInstalledGeoProc : public GrGLInstalledProc {
361 SkAutoTDelete<GrGLGeometryProcessor> fGLProc;
362};
joshualitt47bb3822014-10-07 16:43:25 -0700363
joshualitta5305a12014-10-10 17:47:00 -0700364struct GrGLInstalledFragProc : public GrGLInstalledProc {
365 GrGLInstalledFragProc(bool useLocalCoords) : fGLProc(NULL), fLocalCoordAttrib(useLocalCoords) {}
joshualitt47bb3822014-10-07 16:43:25 -0700366 class ShaderVarHandle {
367 public:
368 bool isValid() const { return fHandle > -1; }
369 ShaderVarHandle() : fHandle(-1) {}
370 ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); }
371 int handle() const { SkASSERT(this->isValid()); return fHandle; }
372 UniformHandle convertToUniformHandle() {
373 SkASSERT(this->isValid());
374 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle);
375 }
joshualittdb0d3ca2014-10-07 12:42:26 -0700376
joshualitt47bb3822014-10-07 16:43:25 -0700377 private:
378 int fHandle;
379 };
joshualittdb0d3ca2014-10-07 12:42:26 -0700380
joshualitt47bb3822014-10-07 16:43:25 -0700381 struct Transform {
382 Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
383 ShaderVarHandle fHandle;
384 SkMatrix fCurrentValue;
385 GrSLType fType;
386 };
joshualittdb0d3ca2014-10-07 12:42:26 -0700387
joshualitta5305a12014-10-10 17:47:00 -0700388 SkAutoTDelete<GrGLFragmentProcessor> fGLProc;
389 SkSTArray<2, Transform, true> fTransforms;
390 bool fLocalCoordAttrib;
391};
joshualittdb0d3ca2014-10-07 12:42:26 -0700392
joshualitta5305a12014-10-10 17:47:00 -0700393struct GrGLInstalledFragProcs : public SkRefCnt {
394 virtual ~GrGLInstalledFragProcs();
395 SkSTArray<8, GrGLInstalledFragProc*, true> fProcs;
joshualitt30ba4362014-08-21 20:18:45 -0700396};
397
joshualitt30ba4362014-08-21 20:18:45 -0700398#endif