blob: a44fa91090969622692cb7be284d5abf53f2f915 [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 */
joshualitt79f8fae2014-10-28 17:59:26 -0700172 static GrGLProgram* CreateProgram(const GrOptDrawState&, GrGpu::DrawType, GrGpuGL*);
joshualitt47bb3822014-10-07 16:43:25 -0700173
174 virtual UniformHandle addUniform(uint32_t visibility,
175 GrSLType type,
176 const char* name,
177 const char** outName = NULL) SK_OVERRIDE {
178 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
179 }
180 virtual UniformHandle addUniformArray(uint32_t visibility,
181 GrSLType type,
182 const char* name,
183 int arrayCount,
184 const char** outName = NULL) SK_OVERRIDE;
185
186 virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const SK_OVERRIDE {
187 return fUniforms[u.toShaderBuilderIndex()].fVariable;
188 }
189
190 virtual const char* getUniformCStr(UniformHandle u) const SK_OVERRIDE {
191 return this->getUniformVariable(u).c_str();
192 }
193
194 virtual const GrGLContextInfo& ctxInfo() const SK_OVERRIDE;
195
196 virtual GrGpuGL* gpu() const SK_OVERRIDE { return fGpu; }
197
joshualitt15988992014-10-09 15:04:05 -0700198 virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() SK_OVERRIDE { return &fFS; }
joshualitt47bb3822014-10-07 16:43:25 -0700199 virtual GrGLVertexBuilder* getVertexShaderBuilder() SK_OVERRIDE { return &fVS; }
200
joshualitta5305a12014-10-10 17:47:00 -0700201 virtual void addVarying(
joshualitta5305a12014-10-10 17:47:00 -0700202 const char* name,
joshualitt74077b92014-10-24 11:26:03 -0700203 GrGLVarying*,
joshualitta5305a12014-10-10 17:47:00 -0700204 GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision) SK_OVERRIDE;
joshualitt30ba4362014-08-21 20:18:45 -0700205
206 // Handles for program uniforms (other than per-effect uniforms)
207 struct BuiltinUniformHandles {
208 UniformHandle fViewMatrixUni;
209 UniformHandle fRTAdjustmentUni;
210 UniformHandle fColorUni;
211 UniformHandle fCoverageUni;
212
213 // We use the render target height to provide a y-down frag coord when specifying
214 // origin_upper_left is not supported.
215 UniformHandle fRTHeightUni;
216
217 // Uniforms for computing texture coords to do the dst-copy lookup
218 UniformHandle fDstCopyTopLeftUni;
219 UniformHandle fDstCopyScaleUni;
220 UniformHandle fDstCopySamplerUni;
221 };
222
joshualittdb0d3ca2014-10-07 12:42:26 -0700223protected:
joshualitt79f8fae2014-10-28 17:59:26 -0700224 typedef GrProgramDesc::ProcKeyProvider ProcKeyProvider;
joshualitta5305a12014-10-10 17:47:00 -0700225 typedef GrGLProgramDataManager::UniformInfo UniformInfo;
226 typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
227
joshualitt79f8fae2014-10-28 17:59:26 -0700228 static GrGLProgramBuilder* CreateProgramBuilder(const GrOptDrawState&,
joshualitt47bb3822014-10-07 16:43:25 -0700229 GrGpu::DrawType,
230 bool hasGeometryProcessor,
231 GrGpuGL*);
232
joshualitt79f8fae2014-10-28 17:59:26 -0700233 GrGLProgramBuilder(GrGpuGL*, const GrOptDrawState&);
joshualitt30ba4362014-08-21 20:18:45 -0700234
egdaniel307796b2014-10-06 12:13:54 -0700235 const GrOptDrawState& optState() const { return fOptState; }
joshualitt79f8fae2014-10-28 17:59:26 -0700236 const GrProgramDesc& desc() const { return fDesc; }
237 const GrProgramDesc::KeyHeader& header() const { return fDesc.header(); }
joshualitt23e280d2014-09-18 12:26:38 -0700238
joshualitt30ba4362014-08-21 20:18:45 -0700239 // Generates a name for a variable. The generated string will be name prefixed by the prefix
240 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
241 // generating stage code.
242 void nameVariable(SkString* out, char prefix, const char* name);
egdaniel37b4d862014-11-03 10:07:07 -0800243 void setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor, GrGLSLExpr1* inputCoverage);
joshualitt4973d9d2014-11-08 09:24:25 -0800244 void emitAndInstallProcs(GrGLSLExpr4* inputColor,
joshualitta5305a12014-10-10 17:47:00 -0700245 GrGLSLExpr4* inputCoverage);
246 void emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut);
247 template <class Proc>
248 void emitAndInstallProc(const Proc&,
249 int index,
joshualitt79f8fae2014-10-28 17:59:26 -0700250 const ProcKeyProvider&,
joshualitta5305a12014-10-10 17:47:00 -0700251 const GrGLSLExpr4& input,
252 GrGLSLExpr4* output);
253
254 // these emit functions help to keep the createAndEmitProcessors template general
255 void emitAndInstallProc(const GrFragmentStage&,
256 const GrProcessorKey&,
257 const char* outColor,
258 const char* inColor);
259 void emitAndInstallProc(const GrGeometryProcessor&,
260 const GrProcessorKey&,
joshualitt4973d9d2014-11-08 09:24:25 -0800261 const char* outCoverage,
262 const char* inCoverage);
joshualitt47bb3822014-10-07 16:43:25 -0700263 void verify(const GrGeometryProcessor&);
264 void verify(const GrFragmentProcessor&);
265 void emitSamplers(const GrProcessor&,
266 GrGLProcessor::TextureSamplerArray* outSamplers,
joshualitta5305a12014-10-10 17:47:00 -0700267 GrGLInstalledProc*);
joshualitt30ba4362014-08-21 20:18:45 -0700268
joshualitt47bb3822014-10-07 16:43:25 -0700269 // each specific program builder has a distinct transform and must override this function
joshualitta5305a12014-10-10 17:47:00 -0700270 virtual void emitTransforms(const GrFragmentStage&,
joshualitt47bb3822014-10-07 16:43:25 -0700271 GrGLProcessor::TransformedCoordsArray* outCoords,
joshualitta5305a12014-10-10 17:47:00 -0700272 GrGLInstalledFragProc*);
joshualitt47bb3822014-10-07 16:43:25 -0700273 GrGLProgram* finalize();
274 void bindUniformLocations(GrGLuint programID);
275 bool checkLinkStatus(GrGLuint programID);
276 void resolveUniformLocations(GrGLuint programID);
joshualitt47bb3822014-10-07 16:43:25 -0700277 void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);
278 void cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs);
joshualitt30ba4362014-08-21 20:18:45 -0700279
joshualitt47bb3822014-10-07 16:43:25 -0700280 // Subclasses create different programs
281 virtual GrGLProgram* createProgram(GrGLuint programID);
282
joshualitt30ba4362014-08-21 20:18:45 -0700283 void appendUniformDecls(ShaderVisibility, SkString*) const;
284
joshualitt47bb3822014-10-07 16:43:25 -0700285 // reset is called by program creator between each processor's emit code. It increments the
286 // stage offset for variable name mangling, and also ensures verfication variables in the
287 // fragment shader are cleared.
288 void reset() {
289 this->enterStage();
290 this->addStage();
291 fFS.reset();
292 }
293 void addStage() { fStageIndex++; }
294
295 // This simple class exits the stage and then restores the stage when it goes out of scope
296 class AutoStageRestore {
joshualitt30ba4362014-08-21 20:18:45 -0700297 public:
joshualitt47bb3822014-10-07 16:43:25 -0700298 AutoStageRestore(GrGLProgramBuilder* pb)
299 : fPB(pb), fOutOfStage(pb->fOutOfStage) { pb->exitStage(); }
300 ~AutoStageRestore() { fPB->fOutOfStage = fOutOfStage; }
joshualittb0a8a372014-09-23 09:50:21 -0700301 private:
joshualitt47bb3822014-10-07 16:43:25 -0700302 GrGLProgramBuilder* fPB;
303 bool fOutOfStage;
joshualittb0a8a372014-09-23 09:50:21 -0700304 };
joshualitt47bb3822014-10-07 16:43:25 -0700305 class AutoStageAdvance {
joshualittdb0d3ca2014-10-07 12:42:26 -0700306 public:
joshualitt47bb3822014-10-07 16:43:25 -0700307 AutoStageAdvance(GrGLProgramBuilder* pb) : fPB(pb) { fPB->reset(); }
308 ~AutoStageAdvance() { fPB->exitStage(); }
joshualittdb0d3ca2014-10-07 12:42:26 -0700309 private:
joshualitt47bb3822014-10-07 16:43:25 -0700310 GrGLProgramBuilder* fPB;
311 };
312 void exitStage() { fOutOfStage = true; }
313 void enterStage() { fOutOfStage = false; }
314 int stageIndex() const { return fStageIndex; }
315
joshualitt4973d9d2014-11-08 09:24:25 -0800316 struct TransformVarying {
317 TransformVarying(const GrGLVarying& v, const char* uniName, const char* sourceCoords)
318 : fV(v), fUniName(uniName), fSourceCoords(sourceCoords) {}
319 GrGLVarying fV;
320 SkString fUniName;
321 SkString fSourceCoords;
322 };
323
324 void addCoordVarying(const char* name, GrGLVarying* v, const char* uniName,
325 const char* sourceCoords) {
326 this->addVarying(name, v);
327 fCoordVaryings.push_back(TransformVarying(*v, uniName, sourceCoords));
328 }
329
330 const char* rtAdjustment() const { return "rtAdjustment"; }
331
joshualitt47bb3822014-10-07 16:43:25 -0700332 // number of each input/output type in a single allocation block, used by many builders
333 static const int kVarsPerBlock;
334
335 BuiltinUniformHandles fUniformHandles;
336 GrGLVertexBuilder fVS;
337 GrGLGeometryBuilder fGS;
338 GrGLFragmentShaderBuilder fFS;
339 bool fOutOfStage;
340 int fStageIndex;
341
joshualitta5305a12014-10-10 17:47:00 -0700342 GrGLInstalledGeoProc* fGeometryProcessor;
343 SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
joshualitt47bb3822014-10-07 16:43:25 -0700344
345 const GrOptDrawState& fOptState;
joshualitt79f8fae2014-10-28 17:59:26 -0700346 const GrProgramDesc& fDesc;
joshualitt47bb3822014-10-07 16:43:25 -0700347 GrGpuGL* fGpu;
348 UniformInfoArray fUniforms;
joshualitt4973d9d2014-11-08 09:24:25 -0800349 SkSTArray<16, TransformVarying, true> fCoordVaryings;
joshualitt47bb3822014-10-07 16:43:25 -0700350
351 friend class GrGLShaderBuilder;
352 friend class GrGLVertexBuilder;
353 friend class GrGLFragmentShaderBuilder;
354 friend class GrGLGeometryBuilder;
355};
356
357/**
joshualitta5305a12014-10-10 17:47:00 -0700358 * The below structs represent processors installed in programs. All processors can have texture
359 * samplers, but only frag processors have coord transforms, hence the need for different structs
joshualitt47bb3822014-10-07 16:43:25 -0700360 */
joshualitta5305a12014-10-10 17:47:00 -0700361struct GrGLInstalledProc {
362 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
joshualitt47bb3822014-10-07 16:43:25 -0700363
joshualitta5305a12014-10-10 17:47:00 -0700364 struct Sampler {
365 SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
366 UniformHandle fUniform;
367 int fTextureUnit;
368 };
369 SkSTArray<4, Sampler, true> fSamplers;
370};
joshualitt47bb3822014-10-07 16:43:25 -0700371
joshualitta5305a12014-10-10 17:47:00 -0700372struct GrGLInstalledGeoProc : public GrGLInstalledProc {
373 SkAutoTDelete<GrGLGeometryProcessor> fGLProc;
374};
joshualitt47bb3822014-10-07 16:43:25 -0700375
joshualitta5305a12014-10-10 17:47:00 -0700376struct GrGLInstalledFragProc : public GrGLInstalledProc {
377 GrGLInstalledFragProc(bool useLocalCoords) : fGLProc(NULL), fLocalCoordAttrib(useLocalCoords) {}
joshualitt47bb3822014-10-07 16:43:25 -0700378 class ShaderVarHandle {
379 public:
380 bool isValid() const { return fHandle > -1; }
381 ShaderVarHandle() : fHandle(-1) {}
382 ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); }
383 int handle() const { SkASSERT(this->isValid()); return fHandle; }
384 UniformHandle convertToUniformHandle() {
385 SkASSERT(this->isValid());
386 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle);
387 }
joshualittdb0d3ca2014-10-07 12:42:26 -0700388
joshualitt47bb3822014-10-07 16:43:25 -0700389 private:
390 int fHandle;
391 };
joshualittdb0d3ca2014-10-07 12:42:26 -0700392
joshualitt47bb3822014-10-07 16:43:25 -0700393 struct Transform {
394 Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
395 ShaderVarHandle fHandle;
396 SkMatrix fCurrentValue;
397 GrSLType fType;
398 };
joshualittdb0d3ca2014-10-07 12:42:26 -0700399
joshualitta5305a12014-10-10 17:47:00 -0700400 SkAutoTDelete<GrGLFragmentProcessor> fGLProc;
401 SkSTArray<2, Transform, true> fTransforms;
402 bool fLocalCoordAttrib;
403};
joshualittdb0d3ca2014-10-07 12:42:26 -0700404
joshualitta5305a12014-10-10 17:47:00 -0700405struct GrGLInstalledFragProcs : public SkRefCnt {
406 virtual ~GrGLInstalledFragProcs();
407 SkSTArray<8, GrGLInstalledFragProc*, true> fProcs;
joshualitt30ba4362014-08-21 20:18:45 -0700408};
409
joshualitt30ba4362014-08-21 20:18:45 -0700410#endif