blob: 1b6c904036ce15a004e15cf1cbd0398fd4a261bf [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"
bsalomonae59b772014-11-19 08:23:49 -080017#include "../../GrPendingFragmentStage.h"
joshualitt89c7a2e2014-10-10 14:11:59 -070018
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
joshualitt74077b92014-10-24 11:26:03 -070073// TODO move this into GrGLGPBuilder and move them both out of this file
74class GrGLVarying {
75public:
76 bool vsVarying() const { return kVertToFrag_Varying == fVarying ||
77 kVertToGeo_Varying == fVarying; }
78 bool fsVarying() const { return kVertToFrag_Varying == fVarying ||
79 kGeoToFrag_Varying == fVarying; }
80 const char* vsOut() const { return fVsOut; }
81 const char* gsIn() const { return fGsIn; }
82 const char* gsOut() const { return fGsOut; }
83 const char* fsIn() const { return fFsIn; }
84
85protected:
86 enum Varying {
87 kVertToFrag_Varying,
88 kVertToGeo_Varying,
89 kGeoToFrag_Varying,
90 };
91
92 GrGLVarying(GrSLType type, Varying varying)
93 : fVarying(varying), fType(type), fVsOut(NULL), fGsIn(NULL), fGsOut(NULL),
94 fFsIn(NULL) {}
95
96 Varying fVarying;
97
98private:
99 GrSLType fType;
100 const char* fVsOut;
101 const char* fGsIn;
102 const char* fGsOut;
103 const char* fFsIn;
104
105 friend class GrGLVertexBuilder;
106 friend class GrGLGeometryBuilder;
107 friend class GrGLFragmentShaderBuilder;
108};
109
110struct GrGLVertToFrag : public GrGLVarying {
111 GrGLVertToFrag(GrSLType type)
112 : GrGLVarying(type, kVertToFrag_Varying) {}
113};
114
115struct GrGLVertToGeo : public GrGLVarying {
116 GrGLVertToGeo(GrSLType type)
117 : GrGLVarying(type, kVertToGeo_Varying) {}
118};
119
120struct GrGLGeoToFrag : public GrGLVarying {
121 GrGLGeoToFrag(GrSLType type)
122 : GrGLVarying(type, kGeoToFrag_Varying) {}
123};
124
joshualitt47bb3822014-10-07 16:43:25 -0700125/* a specialization of the above for GPs. Lets the user add uniforms, varyings, and VS / FS code */
126class GrGLGPBuilder : public virtual GrGLUniformBuilder {
127public:
joshualitt74077b92014-10-24 11:26:03 -0700128 virtual void addVarying(const char* name,
129 GrGLVarying*,
joshualitt47bb3822014-10-07 16:43:25 -0700130 GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision) = 0;
131
132 // TODO rename getFragmentBuilder
133 virtual GrGLGPFragmentBuilder* getFragmentShaderBuilder() = 0;
134 virtual GrGLVertexBuilder* getVertexShaderBuilder() = 0;
135
136 /*
137 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
138 */
139};
140
141/* a specializations for FPs. Lets the user add uniforms and FS code */
142class GrGLFPBuilder : public virtual GrGLUniformBuilder {
143public:
144 virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() = 0;
145
146 /*
147 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
148 */
149};
150
joshualitta5305a12014-10-10 17:47:00 -0700151struct GrGLInstalledProc;
152struct GrGLInstalledGeoProc;
153struct GrGLInstalledFragProc;
154struct GrGLInstalledFragProcs;
155
joshualitt47bb3822014-10-07 16:43:25 -0700156/*
157 * Please note - no diamond problems because of virtual inheritance. Also, both base classes
158 * are pure virtual with no data members. This is the base class for program building.
159 * Subclasses are nearly identical but each has their own way of emitting transforms. State for
160 * each of the elements of the shader pipeline, ie vertex, fragment, geometry, etc, lives in those
161 * respective builders
162*/
163class GrGLProgramBuilder : public GrGLGPBuilder,
164 public GrGLFPBuilder {
165public:
166 /** Generates a shader program.
167 *
168 * The program implements what is specified in the stages given as input.
169 * After successful generation, the builder result objects are available
170 * to be used.
171 * @return true if generation was successful.
172 */
joshualitt79f8fae2014-10-28 17:59:26 -0700173 static GrGLProgram* CreateProgram(const GrOptDrawState&, GrGpu::DrawType, GrGpuGL*);
joshualitt47bb3822014-10-07 16:43:25 -0700174
175 virtual UniformHandle addUniform(uint32_t visibility,
176 GrSLType type,
177 const char* name,
178 const char** outName = NULL) SK_OVERRIDE {
179 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
180 }
181 virtual UniformHandle addUniformArray(uint32_t visibility,
182 GrSLType type,
183 const char* name,
184 int arrayCount,
185 const char** outName = NULL) SK_OVERRIDE;
186
187 virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const SK_OVERRIDE {
188 return fUniforms[u.toShaderBuilderIndex()].fVariable;
189 }
190
191 virtual const char* getUniformCStr(UniformHandle u) const SK_OVERRIDE {
192 return this->getUniformVariable(u).c_str();
193 }
194
195 virtual const GrGLContextInfo& ctxInfo() const SK_OVERRIDE;
196
197 virtual GrGpuGL* gpu() const SK_OVERRIDE { return fGpu; }
198
joshualitt15988992014-10-09 15:04:05 -0700199 virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() SK_OVERRIDE { return &fFS; }
joshualitt47bb3822014-10-07 16:43:25 -0700200 virtual GrGLVertexBuilder* getVertexShaderBuilder() SK_OVERRIDE { return &fVS; }
201
joshualitta5305a12014-10-10 17:47:00 -0700202 virtual void addVarying(
joshualitta5305a12014-10-10 17:47:00 -0700203 const char* name,
joshualitt74077b92014-10-24 11:26:03 -0700204 GrGLVarying*,
joshualitta5305a12014-10-10 17:47:00 -0700205 GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision) SK_OVERRIDE;
joshualitt30ba4362014-08-21 20:18:45 -0700206
207 // Handles for program uniforms (other than per-effect uniforms)
208 struct BuiltinUniformHandles {
209 UniformHandle fViewMatrixUni;
210 UniformHandle fRTAdjustmentUni;
211 UniformHandle fColorUni;
212 UniformHandle fCoverageUni;
213
214 // We use the render target height to provide a y-down frag coord when specifying
215 // origin_upper_left is not supported.
216 UniformHandle fRTHeightUni;
217
218 // Uniforms for computing texture coords to do the dst-copy lookup
219 UniformHandle fDstCopyTopLeftUni;
220 UniformHandle fDstCopyScaleUni;
221 UniformHandle fDstCopySamplerUni;
222 };
223
joshualittdb0d3ca2014-10-07 12:42:26 -0700224protected:
joshualitt79f8fae2014-10-28 17:59:26 -0700225 typedef GrProgramDesc::ProcKeyProvider ProcKeyProvider;
joshualitta5305a12014-10-10 17:47:00 -0700226 typedef GrGLProgramDataManager::UniformInfo UniformInfo;
227 typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
228
joshualitt79f8fae2014-10-28 17:59:26 -0700229 static GrGLProgramBuilder* CreateProgramBuilder(const GrOptDrawState&,
joshualitt47bb3822014-10-07 16:43:25 -0700230 GrGpu::DrawType,
231 bool hasGeometryProcessor,
232 GrGpuGL*);
233
joshualitt79f8fae2014-10-28 17:59:26 -0700234 GrGLProgramBuilder(GrGpuGL*, const GrOptDrawState&);
joshualitt30ba4362014-08-21 20:18:45 -0700235
egdaniel307796b2014-10-06 12:13:54 -0700236 const GrOptDrawState& optState() const { return fOptState; }
joshualitt79f8fae2014-10-28 17:59:26 -0700237 const GrProgramDesc& desc() const { return fDesc; }
238 const GrProgramDesc::KeyHeader& header() const { return fDesc.header(); }
joshualitt23e280d2014-09-18 12:26:38 -0700239
joshualitt30ba4362014-08-21 20:18:45 -0700240 // Generates a name for a variable. The generated string will be name prefixed by the prefix
241 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
242 // generating stage code.
243 void nameVariable(SkString* out, char prefix, const char* name);
egdaniel37b4d862014-11-03 10:07:07 -0800244 void setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor, GrGLSLExpr1* inputCoverage);
joshualitt4973d9d2014-11-08 09:24:25 -0800245 void emitAndInstallProcs(GrGLSLExpr4* inputColor,
joshualitta5305a12014-10-10 17:47:00 -0700246 GrGLSLExpr4* inputCoverage);
247 void emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut);
248 template <class Proc>
249 void emitAndInstallProc(const Proc&,
250 int index,
joshualitt79f8fae2014-10-28 17:59:26 -0700251 const ProcKeyProvider&,
joshualitta5305a12014-10-10 17:47:00 -0700252 const GrGLSLExpr4& input,
253 GrGLSLExpr4* output);
254
255 // these emit functions help to keep the createAndEmitProcessors template general
bsalomonae59b772014-11-19 08:23:49 -0800256 void emitAndInstallProc(const GrPendingFragmentStage&,
joshualitta5305a12014-10-10 17:47:00 -0700257 const GrProcessorKey&,
258 const char* outColor,
259 const char* inColor);
260 void emitAndInstallProc(const GrGeometryProcessor&,
261 const GrProcessorKey&,
joshualitt4973d9d2014-11-08 09:24:25 -0800262 const char* outCoverage,
263 const char* inCoverage);
joshualitt47bb3822014-10-07 16:43:25 -0700264 void verify(const GrGeometryProcessor&);
265 void verify(const GrFragmentProcessor&);
266 void emitSamplers(const GrProcessor&,
267 GrGLProcessor::TextureSamplerArray* outSamplers,
joshualitta5305a12014-10-10 17:47:00 -0700268 GrGLInstalledProc*);
joshualitt30ba4362014-08-21 20:18:45 -0700269
joshualitt47bb3822014-10-07 16:43:25 -0700270 // each specific program builder has a distinct transform and must override this function
bsalomonae59b772014-11-19 08:23:49 -0800271 virtual void emitTransforms(const GrPendingFragmentStage&,
joshualitt47bb3822014-10-07 16:43:25 -0700272 GrGLProcessor::TransformedCoordsArray* outCoords,
joshualitta5305a12014-10-10 17:47:00 -0700273 GrGLInstalledFragProc*);
joshualitt47bb3822014-10-07 16:43:25 -0700274 GrGLProgram* finalize();
275 void bindUniformLocations(GrGLuint programID);
276 bool checkLinkStatus(GrGLuint programID);
277 void resolveUniformLocations(GrGLuint programID);
joshualitt47bb3822014-10-07 16:43:25 -0700278 void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);
279 void cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs);
joshualitt30ba4362014-08-21 20:18:45 -0700280
joshualitt47bb3822014-10-07 16:43:25 -0700281 // Subclasses create different programs
282 virtual GrGLProgram* createProgram(GrGLuint programID);
283
joshualitt30ba4362014-08-21 20:18:45 -0700284 void appendUniformDecls(ShaderVisibility, SkString*) const;
285
joshualitt47bb3822014-10-07 16:43:25 -0700286 // reset is called by program creator between each processor's emit code. It increments the
287 // stage offset for variable name mangling, and also ensures verfication variables in the
288 // fragment shader are cleared.
289 void reset() {
290 this->enterStage();
291 this->addStage();
292 fFS.reset();
293 }
294 void addStage() { fStageIndex++; }
295
296 // This simple class exits the stage and then restores the stage when it goes out of scope
297 class AutoStageRestore {
joshualitt30ba4362014-08-21 20:18:45 -0700298 public:
joshualitt47bb3822014-10-07 16:43:25 -0700299 AutoStageRestore(GrGLProgramBuilder* pb)
300 : fPB(pb), fOutOfStage(pb->fOutOfStage) { pb->exitStage(); }
301 ~AutoStageRestore() { fPB->fOutOfStage = fOutOfStage; }
joshualittb0a8a372014-09-23 09:50:21 -0700302 private:
joshualitt47bb3822014-10-07 16:43:25 -0700303 GrGLProgramBuilder* fPB;
304 bool fOutOfStage;
joshualittb0a8a372014-09-23 09:50:21 -0700305 };
joshualitt47bb3822014-10-07 16:43:25 -0700306 class AutoStageAdvance {
joshualittdb0d3ca2014-10-07 12:42:26 -0700307 public:
joshualitt47bb3822014-10-07 16:43:25 -0700308 AutoStageAdvance(GrGLProgramBuilder* pb) : fPB(pb) { fPB->reset(); }
309 ~AutoStageAdvance() { fPB->exitStage(); }
joshualittdb0d3ca2014-10-07 12:42:26 -0700310 private:
joshualitt47bb3822014-10-07 16:43:25 -0700311 GrGLProgramBuilder* fPB;
312 };
313 void exitStage() { fOutOfStage = true; }
314 void enterStage() { fOutOfStage = false; }
315 int stageIndex() const { return fStageIndex; }
316
joshualitt4973d9d2014-11-08 09:24:25 -0800317 struct TransformVarying {
318 TransformVarying(const GrGLVarying& v, const char* uniName, const char* sourceCoords)
319 : fV(v), fUniName(uniName), fSourceCoords(sourceCoords) {}
320 GrGLVarying fV;
321 SkString fUniName;
322 SkString fSourceCoords;
323 };
324
325 void addCoordVarying(const char* name, GrGLVarying* v, const char* uniName,
326 const char* sourceCoords) {
327 this->addVarying(name, v);
328 fCoordVaryings.push_back(TransformVarying(*v, uniName, sourceCoords));
329 }
330
331 const char* rtAdjustment() const { return "rtAdjustment"; }
332
joshualitt47bb3822014-10-07 16:43:25 -0700333 // number of each input/output type in a single allocation block, used by many builders
334 static const int kVarsPerBlock;
335
336 BuiltinUniformHandles fUniformHandles;
337 GrGLVertexBuilder fVS;
338 GrGLGeometryBuilder fGS;
339 GrGLFragmentShaderBuilder fFS;
340 bool fOutOfStage;
341 int fStageIndex;
342
joshualitta5305a12014-10-10 17:47:00 -0700343 GrGLInstalledGeoProc* fGeometryProcessor;
344 SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
joshualitt47bb3822014-10-07 16:43:25 -0700345
346 const GrOptDrawState& fOptState;
joshualitt79f8fae2014-10-28 17:59:26 -0700347 const GrProgramDesc& fDesc;
joshualitt47bb3822014-10-07 16:43:25 -0700348 GrGpuGL* fGpu;
349 UniformInfoArray fUniforms;
joshualitt4973d9d2014-11-08 09:24:25 -0800350 SkSTArray<16, TransformVarying, true> fCoordVaryings;
joshualitt47bb3822014-10-07 16:43:25 -0700351
352 friend class GrGLShaderBuilder;
353 friend class GrGLVertexBuilder;
354 friend class GrGLFragmentShaderBuilder;
355 friend class GrGLGeometryBuilder;
356};
357
358/**
joshualitta5305a12014-10-10 17:47:00 -0700359 * The below structs represent processors installed in programs. All processors can have texture
360 * samplers, but only frag processors have coord transforms, hence the need for different structs
joshualitt47bb3822014-10-07 16:43:25 -0700361 */
joshualitta5305a12014-10-10 17:47:00 -0700362struct GrGLInstalledProc {
363 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
joshualitt47bb3822014-10-07 16:43:25 -0700364
joshualitta5305a12014-10-10 17:47:00 -0700365 struct Sampler {
366 SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
367 UniformHandle fUniform;
368 int fTextureUnit;
369 };
370 SkSTArray<4, Sampler, true> fSamplers;
371};
joshualitt47bb3822014-10-07 16:43:25 -0700372
joshualitta5305a12014-10-10 17:47:00 -0700373struct GrGLInstalledGeoProc : public GrGLInstalledProc {
374 SkAutoTDelete<GrGLGeometryProcessor> fGLProc;
375};
joshualitt47bb3822014-10-07 16:43:25 -0700376
joshualitta5305a12014-10-10 17:47:00 -0700377struct GrGLInstalledFragProc : public GrGLInstalledProc {
378 GrGLInstalledFragProc(bool useLocalCoords) : fGLProc(NULL), fLocalCoordAttrib(useLocalCoords) {}
joshualitt47bb3822014-10-07 16:43:25 -0700379 class ShaderVarHandle {
380 public:
381 bool isValid() const { return fHandle > -1; }
382 ShaderVarHandle() : fHandle(-1) {}
383 ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); }
384 int handle() const { SkASSERT(this->isValid()); return fHandle; }
385 UniformHandle convertToUniformHandle() {
386 SkASSERT(this->isValid());
387 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle);
388 }
joshualittdb0d3ca2014-10-07 12:42:26 -0700389
joshualitt47bb3822014-10-07 16:43:25 -0700390 private:
391 int fHandle;
392 };
joshualittdb0d3ca2014-10-07 12:42:26 -0700393
joshualitt47bb3822014-10-07 16:43:25 -0700394 struct Transform {
395 Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
396 ShaderVarHandle fHandle;
397 SkMatrix fCurrentValue;
398 GrSLType fType;
399 };
joshualittdb0d3ca2014-10-07 12:42:26 -0700400
joshualitta5305a12014-10-10 17:47:00 -0700401 SkAutoTDelete<GrGLFragmentProcessor> fGLProc;
402 SkSTArray<2, Transform, true> fTransforms;
403 bool fLocalCoordAttrib;
404};
joshualittdb0d3ca2014-10-07 12:42:26 -0700405
joshualitta5305a12014-10-10 17:47:00 -0700406struct GrGLInstalledFragProcs : public SkRefCnt {
407 virtual ~GrGLInstalledFragProcs();
408 SkSTArray<8, GrGLInstalledFragProc*, true> fProcs;
joshualitt30ba4362014-08-21 20:18:45 -0700409};
410
joshualitt30ba4362014-08-21 20:18:45 -0700411#endif