blob: b7458b3e8fb8b850f728fc6530e5053d901cbcd3 [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"
bsalomon04ddf892014-11-19 12:36:22 -080017#include "../../GrOptDrawState.h"
bsalomonae59b772014-11-19 08:23:49 -080018#include "../../GrPendingFragmentStage.h"
joshualitt89c7a2e2014-10-10 14:11:59 -070019
joshualitt47bb3822014-10-07 16:43:25 -070020/*
21 * This is the base class for a series of interfaces. This base class *MUST* remain abstract with
22 * NO data members because it is used in multiple interface inheritance.
23 * Heirarchy:
24 * GrGLUniformBuilder
25 * / \
26 * GrGLFPBuilder GrGLGPBuilder
27 * \ /
28 * GrGLProgramBuilder(internal use only)
29 */
30class GrGLUniformBuilder {
joshualitt30ba4362014-08-21 20:18:45 -070031public:
32 enum ShaderVisibility {
bsalomon17168df2014-12-09 09:00:49 -080033 kVertex_Visibility = 1 << kVertex_GrShaderType,
34 kGeometry_Visibility = 1 << kGeometry_GrShaderType,
35 kFragment_Visibility = 1 << kFragment_GrShaderType,
joshualitt30ba4362014-08-21 20:18:45 -070036 };
37
joshualitt47bb3822014-10-07 16:43:25 -070038 virtual ~GrGLUniformBuilder() {}
39
joshualitt30ba4362014-08-21 20:18:45 -070040 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
joshualitt47bb3822014-10-07 16:43:25 -070041
42 /** Add a uniform variable to the current program, that has visibility in one or more shaders.
43 visibility is a bitfield of ShaderVisibility values indicating from which shaders the
44 uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
45 supported at this time. The actual uniform name will be mangled. If outName is not NULL then
46 it will refer to the final uniform name after return. Use the addUniformArray variant to add
47 an array of uniforms. */
48 virtual UniformHandle addUniform(uint32_t visibility,
49 GrSLType type,
50 const char* name,
51 const char** outName = NULL) = 0;
52 virtual UniformHandle addUniformArray(uint32_t visibility,
53 GrSLType type,
54 const char* name,
55 int arrayCount,
56 const char** outName = NULL) = 0;
57
58 virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const = 0;
59
60 /**
61 * Shortcut for getUniformVariable(u).c_str()
62 */
63 virtual const char* getUniformCStr(UniformHandle u) const = 0;
64
65 virtual const GrGLContextInfo& ctxInfo() const = 0;
66
67 virtual GrGpuGL* gpu() const = 0;
68
69 /*
70 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
71 */
72};
73
joshualitt74077b92014-10-24 11:26:03 -070074// TODO move this into GrGLGPBuilder and move them both out of this file
75class GrGLVarying {
76public:
77 bool vsVarying() const { return kVertToFrag_Varying == fVarying ||
78 kVertToGeo_Varying == fVarying; }
79 bool fsVarying() const { return kVertToFrag_Varying == fVarying ||
80 kGeoToFrag_Varying == fVarying; }
81 const char* vsOut() const { return fVsOut; }
82 const char* gsIn() const { return fGsIn; }
83 const char* gsOut() const { return fGsOut; }
84 const char* fsIn() const { return fFsIn; }
85
86protected:
87 enum Varying {
88 kVertToFrag_Varying,
89 kVertToGeo_Varying,
90 kGeoToFrag_Varying,
91 };
92
93 GrGLVarying(GrSLType type, Varying varying)
94 : fVarying(varying), fType(type), fVsOut(NULL), fGsIn(NULL), fGsOut(NULL),
95 fFsIn(NULL) {}
96
97 Varying fVarying;
98
99private:
100 GrSLType fType;
101 const char* fVsOut;
102 const char* fGsIn;
103 const char* fGsOut;
104 const char* fFsIn;
105
106 friend class GrGLVertexBuilder;
107 friend class GrGLGeometryBuilder;
108 friend class GrGLFragmentShaderBuilder;
109};
110
111struct GrGLVertToFrag : public GrGLVarying {
112 GrGLVertToFrag(GrSLType type)
113 : GrGLVarying(type, kVertToFrag_Varying) {}
114};
115
116struct GrGLVertToGeo : public GrGLVarying {
117 GrGLVertToGeo(GrSLType type)
118 : GrGLVarying(type, kVertToGeo_Varying) {}
119};
120
121struct GrGLGeoToFrag : public GrGLVarying {
122 GrGLGeoToFrag(GrSLType type)
123 : GrGLVarying(type, kGeoToFrag_Varying) {}
124};
125
joshualitt47bb3822014-10-07 16:43:25 -0700126/* a specialization of the above for GPs. Lets the user add uniforms, varyings, and VS / FS code */
127class GrGLGPBuilder : public virtual GrGLUniformBuilder {
128public:
joshualitt2dd1ae02014-12-03 06:24:10 -0800129 /*
130 * addVarying allows fine grained control for setting up varyings between stages. If you just
131 * need to take an attribute and pass it through to an output value in a fragment shader, use
132 * addPassThroughAttribute.
133 * TODO convert most uses of addVarying to addPassThroughAttribute
134 */
joshualitt74077b92014-10-24 11:26:03 -0700135 virtual void addVarying(const char* name,
136 GrGLVarying*,
joshualitt47bb3822014-10-07 16:43:25 -0700137 GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision) = 0;
138
joshualitt2dd1ae02014-12-03 06:24:10 -0800139 /*
140 * This call can be used by GP to pass an attribute through all shaders directly to 'output' in
141 * the fragment shader. Though this call effects both the vertex shader and fragment shader,
142 * it expects 'output' to be defined in the fragment shader before this call is made.
143 * TODO it might be nicer behavior to have a flag to declare output inside this call
144 */
145 virtual void addPassThroughAttribute(const GrGeometryProcessor::GrAttribute*,
146 const char* output) = 0;
147
joshualitt47bb3822014-10-07 16:43:25 -0700148 // TODO rename getFragmentBuilder
149 virtual GrGLGPFragmentBuilder* getFragmentShaderBuilder() = 0;
150 virtual GrGLVertexBuilder* getVertexShaderBuilder() = 0;
151
152 /*
153 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
154 */
155};
156
157/* a specializations for FPs. Lets the user add uniforms and FS code */
158class GrGLFPBuilder : public virtual GrGLUniformBuilder {
159public:
160 virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() = 0;
161
162 /*
163 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
164 */
165};
166
joshualitta5305a12014-10-10 17:47:00 -0700167struct GrGLInstalledProc;
168struct GrGLInstalledGeoProc;
169struct GrGLInstalledFragProc;
170struct GrGLInstalledFragProcs;
171
joshualitt47bb3822014-10-07 16:43:25 -0700172/*
173 * Please note - no diamond problems because of virtual inheritance. Also, both base classes
174 * are pure virtual with no data members. This is the base class for program building.
175 * Subclasses are nearly identical but each has their own way of emitting transforms. State for
176 * each of the elements of the shader pipeline, ie vertex, fragment, geometry, etc, lives in those
177 * respective builders
178*/
179class GrGLProgramBuilder : public GrGLGPBuilder,
180 public GrGLFPBuilder {
181public:
182 /** Generates a shader program.
183 *
184 * The program implements what is specified in the stages given as input.
185 * After successful generation, the builder result objects are available
186 * to be used.
187 * @return true if generation was successful.
188 */
joshualittdafa4d02014-12-04 08:59:10 -0800189 static GrGLProgram* CreateProgram(const GrOptDrawState&, GrGpuGL*);
joshualitt47bb3822014-10-07 16:43:25 -0700190
191 virtual UniformHandle addUniform(uint32_t visibility,
192 GrSLType type,
193 const char* name,
194 const char** outName = NULL) SK_OVERRIDE {
195 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
196 }
197 virtual UniformHandle addUniformArray(uint32_t visibility,
198 GrSLType type,
199 const char* name,
200 int arrayCount,
201 const char** outName = NULL) SK_OVERRIDE;
202
203 virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const SK_OVERRIDE {
204 return fUniforms[u.toShaderBuilderIndex()].fVariable;
205 }
206
207 virtual const char* getUniformCStr(UniformHandle u) const SK_OVERRIDE {
208 return this->getUniformVariable(u).c_str();
209 }
210
211 virtual const GrGLContextInfo& ctxInfo() const SK_OVERRIDE;
212
213 virtual GrGpuGL* gpu() const SK_OVERRIDE { return fGpu; }
214
joshualitt15988992014-10-09 15:04:05 -0700215 virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() SK_OVERRIDE { return &fFS; }
joshualitt47bb3822014-10-07 16:43:25 -0700216 virtual GrGLVertexBuilder* getVertexShaderBuilder() SK_OVERRIDE { return &fVS; }
217
joshualitta5305a12014-10-10 17:47:00 -0700218 virtual void addVarying(
joshualitta5305a12014-10-10 17:47:00 -0700219 const char* name,
joshualitt74077b92014-10-24 11:26:03 -0700220 GrGLVarying*,
joshualitta5305a12014-10-10 17:47:00 -0700221 GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision) SK_OVERRIDE;
joshualitt30ba4362014-08-21 20:18:45 -0700222
joshualitt2dd1ae02014-12-03 06:24:10 -0800223 virtual void addPassThroughAttribute(const GrGeometryProcessor::GrAttribute*,
224 const char* output) SK_OVERRIDE;
225
226
joshualitt30ba4362014-08-21 20:18:45 -0700227 // Handles for program uniforms (other than per-effect uniforms)
228 struct BuiltinUniformHandles {
229 UniformHandle fViewMatrixUni;
230 UniformHandle fRTAdjustmentUni;
231 UniformHandle fColorUni;
232 UniformHandle fCoverageUni;
233
234 // We use the render target height to provide a y-down frag coord when specifying
235 // origin_upper_left is not supported.
236 UniformHandle fRTHeightUni;
237
238 // Uniforms for computing texture coords to do the dst-copy lookup
239 UniformHandle fDstCopyTopLeftUni;
240 UniformHandle fDstCopyScaleUni;
241 UniformHandle fDstCopySamplerUni;
242 };
243
joshualittdb0d3ca2014-10-07 12:42:26 -0700244protected:
joshualitta5305a12014-10-10 17:47:00 -0700245 typedef GrGLProgramDataManager::UniformInfo UniformInfo;
246 typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
247
joshualitt79f8fae2014-10-28 17:59:26 -0700248 static GrGLProgramBuilder* CreateProgramBuilder(const GrOptDrawState&,
joshualitt47bb3822014-10-07 16:43:25 -0700249 bool hasGeometryProcessor,
250 GrGpuGL*);
251
joshualitt79f8fae2014-10-28 17:59:26 -0700252 GrGLProgramBuilder(GrGpuGL*, const GrOptDrawState&);
joshualitt30ba4362014-08-21 20:18:45 -0700253
egdaniel307796b2014-10-06 12:13:54 -0700254 const GrOptDrawState& optState() const { return fOptState; }
joshualitt79f8fae2014-10-28 17:59:26 -0700255 const GrProgramDesc& desc() const { return fDesc; }
256 const GrProgramDesc::KeyHeader& header() const { return fDesc.header(); }
joshualitt23e280d2014-09-18 12:26:38 -0700257
joshualitt30ba4362014-08-21 20:18:45 -0700258 // Generates a name for a variable. The generated string will be name prefixed by the prefix
259 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
260 // generating stage code.
261 void nameVariable(SkString* out, char prefix, const char* name);
egdaniel37b4d862014-11-03 10:07:07 -0800262 void setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor, GrGLSLExpr1* inputCoverage);
joshualitt2dd1ae02014-12-03 06:24:10 -0800263 // Generates a possibly mangled name for a stage variable and writes it to the fragment shader.
264 // If GrGLSLExpr4 has a valid name then it will use that instead
265 void nameExpression(GrGLSLExpr4*, const char* baseName);
joshualitt4973d9d2014-11-08 09:24:25 -0800266 void emitAndInstallProcs(GrGLSLExpr4* inputColor,
joshualitta5305a12014-10-10 17:47:00 -0700267 GrGLSLExpr4* inputCoverage);
268 void emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut);
joshualitt2dd1ae02014-12-03 06:24:10 -0800269 void emitAndInstallProc(const GrPendingFragmentStage&,
joshualitta5305a12014-10-10 17:47:00 -0700270 int index,
joshualitta5305a12014-10-10 17:47:00 -0700271 const GrGLSLExpr4& input,
272 GrGLSLExpr4* output);
273
joshualitt2dd1ae02014-12-03 06:24:10 -0800274 void emitAndInstallProc(const GrGeometryProcessor&,
275 GrGLSLExpr4* outputColor,
276 GrGLSLExpr4* outputCoverage);
277
joshualitta5305a12014-10-10 17:47:00 -0700278 // these emit functions help to keep the createAndEmitProcessors template general
bsalomonae59b772014-11-19 08:23:49 -0800279 void emitAndInstallProc(const GrPendingFragmentStage&,
joshualitta5305a12014-10-10 17:47:00 -0700280 const char* outColor,
281 const char* inColor);
282 void emitAndInstallProc(const GrGeometryProcessor&,
joshualitt2dd1ae02014-12-03 06:24:10 -0800283 const char* outColor,
284 const char* outCoverage);
285
joshualitt47bb3822014-10-07 16:43:25 -0700286 void verify(const GrGeometryProcessor&);
287 void verify(const GrFragmentProcessor&);
288 void emitSamplers(const GrProcessor&,
289 GrGLProcessor::TextureSamplerArray* outSamplers,
joshualitta5305a12014-10-10 17:47:00 -0700290 GrGLInstalledProc*);
joshualitt30ba4362014-08-21 20:18:45 -0700291
joshualitt47bb3822014-10-07 16:43:25 -0700292 // each specific program builder has a distinct transform and must override this function
bsalomonae59b772014-11-19 08:23:49 -0800293 virtual void emitTransforms(const GrPendingFragmentStage&,
joshualitt47bb3822014-10-07 16:43:25 -0700294 GrGLProcessor::TransformedCoordsArray* outCoords,
joshualitta5305a12014-10-10 17:47:00 -0700295 GrGLInstalledFragProc*);
joshualitt47bb3822014-10-07 16:43:25 -0700296 GrGLProgram* finalize();
297 void bindUniformLocations(GrGLuint programID);
298 bool checkLinkStatus(GrGLuint programID);
299 void resolveUniformLocations(GrGLuint programID);
joshualitt47bb3822014-10-07 16:43:25 -0700300 void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);
301 void cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs);
joshualitt30ba4362014-08-21 20:18:45 -0700302
joshualitt47bb3822014-10-07 16:43:25 -0700303 // Subclasses create different programs
304 virtual GrGLProgram* createProgram(GrGLuint programID);
305
joshualitt30ba4362014-08-21 20:18:45 -0700306 void appendUniformDecls(ShaderVisibility, SkString*) const;
307
joshualitt47bb3822014-10-07 16:43:25 -0700308 // reset is called by program creator between each processor's emit code. It increments the
309 // stage offset for variable name mangling, and also ensures verfication variables in the
310 // fragment shader are cleared.
311 void reset() {
312 this->enterStage();
313 this->addStage();
314 fFS.reset();
315 }
316 void addStage() { fStageIndex++; }
317
318 // This simple class exits the stage and then restores the stage when it goes out of scope
319 class AutoStageRestore {
joshualitt30ba4362014-08-21 20:18:45 -0700320 public:
joshualitt47bb3822014-10-07 16:43:25 -0700321 AutoStageRestore(GrGLProgramBuilder* pb)
322 : fPB(pb), fOutOfStage(pb->fOutOfStage) { pb->exitStage(); }
323 ~AutoStageRestore() { fPB->fOutOfStage = fOutOfStage; }
joshualittb0a8a372014-09-23 09:50:21 -0700324 private:
joshualitt47bb3822014-10-07 16:43:25 -0700325 GrGLProgramBuilder* fPB;
326 bool fOutOfStage;
joshualittb0a8a372014-09-23 09:50:21 -0700327 };
joshualitt47bb3822014-10-07 16:43:25 -0700328 class AutoStageAdvance {
joshualittdb0d3ca2014-10-07 12:42:26 -0700329 public:
joshualitt47bb3822014-10-07 16:43:25 -0700330 AutoStageAdvance(GrGLProgramBuilder* pb) : fPB(pb) { fPB->reset(); }
331 ~AutoStageAdvance() { fPB->exitStage(); }
joshualittdb0d3ca2014-10-07 12:42:26 -0700332 private:
joshualitt47bb3822014-10-07 16:43:25 -0700333 GrGLProgramBuilder* fPB;
334 };
335 void exitStage() { fOutOfStage = true; }
336 void enterStage() { fOutOfStage = false; }
337 int stageIndex() const { return fStageIndex; }
338
joshualitt4973d9d2014-11-08 09:24:25 -0800339 struct TransformVarying {
340 TransformVarying(const GrGLVarying& v, const char* uniName, const char* sourceCoords)
341 : fV(v), fUniName(uniName), fSourceCoords(sourceCoords) {}
342 GrGLVarying fV;
343 SkString fUniName;
344 SkString fSourceCoords;
345 };
346
joshualitt4973d9d2014-11-08 09:24:25 -0800347 const char* rtAdjustment() const { return "rtAdjustment"; }
348
joshualitt47bb3822014-10-07 16:43:25 -0700349 // number of each input/output type in a single allocation block, used by many builders
350 static const int kVarsPerBlock;
351
352 BuiltinUniformHandles fUniformHandles;
353 GrGLVertexBuilder fVS;
354 GrGLGeometryBuilder fGS;
355 GrGLFragmentShaderBuilder fFS;
356 bool fOutOfStage;
357 int fStageIndex;
358
joshualitta5305a12014-10-10 17:47:00 -0700359 GrGLInstalledGeoProc* fGeometryProcessor;
360 SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
joshualitt47bb3822014-10-07 16:43:25 -0700361
362 const GrOptDrawState& fOptState;
joshualitt79f8fae2014-10-28 17:59:26 -0700363 const GrProgramDesc& fDesc;
joshualitt47bb3822014-10-07 16:43:25 -0700364 GrGpuGL* fGpu;
365 UniformInfoArray fUniforms;
joshualitt4973d9d2014-11-08 09:24:25 -0800366 SkSTArray<16, TransformVarying, true> fCoordVaryings;
joshualitt47bb3822014-10-07 16:43:25 -0700367
368 friend class GrGLShaderBuilder;
369 friend class GrGLVertexBuilder;
370 friend class GrGLFragmentShaderBuilder;
371 friend class GrGLGeometryBuilder;
372};
373
374/**
joshualitta5305a12014-10-10 17:47:00 -0700375 * The below structs represent processors installed in programs. All processors can have texture
376 * samplers, but only frag processors have coord transforms, hence the need for different structs
joshualitt47bb3822014-10-07 16:43:25 -0700377 */
joshualitta5305a12014-10-10 17:47:00 -0700378struct GrGLInstalledProc {
379 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
joshualitt47bb3822014-10-07 16:43:25 -0700380
joshualitta5305a12014-10-10 17:47:00 -0700381 struct Sampler {
382 SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
383 UniformHandle fUniform;
384 int fTextureUnit;
385 };
386 SkSTArray<4, Sampler, true> fSamplers;
387};
joshualitt47bb3822014-10-07 16:43:25 -0700388
joshualitta5305a12014-10-10 17:47:00 -0700389struct GrGLInstalledGeoProc : public GrGLInstalledProc {
390 SkAutoTDelete<GrGLGeometryProcessor> fGLProc;
391};
joshualitt47bb3822014-10-07 16:43:25 -0700392
joshualitta5305a12014-10-10 17:47:00 -0700393struct GrGLInstalledFragProc : public GrGLInstalledProc {
joshualitt2dd1ae02014-12-03 06:24:10 -0800394 GrGLInstalledFragProc() : fGLProc(NULL) {}
joshualitt47bb3822014-10-07 16:43:25 -0700395 class ShaderVarHandle {
396 public:
397 bool isValid() const { return fHandle > -1; }
398 ShaderVarHandle() : fHandle(-1) {}
399 ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); }
400 int handle() const { SkASSERT(this->isValid()); return fHandle; }
401 UniformHandle convertToUniformHandle() {
402 SkASSERT(this->isValid());
403 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle);
404 }
joshualittdb0d3ca2014-10-07 12:42:26 -0700405
joshualitt47bb3822014-10-07 16:43:25 -0700406 private:
407 int fHandle;
408 };
joshualittdb0d3ca2014-10-07 12:42:26 -0700409
joshualitt47bb3822014-10-07 16:43:25 -0700410 struct Transform {
411 Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
412 ShaderVarHandle fHandle;
413 SkMatrix fCurrentValue;
414 GrSLType fType;
415 };
joshualittdb0d3ca2014-10-07 12:42:26 -0700416
joshualitta5305a12014-10-10 17:47:00 -0700417 SkAutoTDelete<GrGLFragmentProcessor> fGLProc;
418 SkSTArray<2, Transform, true> fTransforms;
joshualitta5305a12014-10-10 17:47:00 -0700419};
joshualittdb0d3ca2014-10-07 12:42:26 -0700420
joshualitta5305a12014-10-10 17:47:00 -0700421struct GrGLInstalledFragProcs : public SkRefCnt {
422 virtual ~GrGLInstalledFragProcs();
423 SkSTArray<8, GrGLInstalledFragProc*, true> fProcs;
joshualitt30ba4362014-08-21 20:18:45 -0700424};
425
joshualitt30ba4362014-08-21 20:18:45 -0700426#endif