blob: 76f7ae97c37df5c5091712cb75767da81e6b84bc [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 {
33 kVertex_Visibility = 0x1,
34 kGeometry_Visibility = 0x2,
35 kFragment_Visibility = 0x4,
36 };
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 */
joshualitt79f8fae2014-10-28 17:59:26 -0700189 static GrGLProgram* CreateProgram(const GrOptDrawState&, GrGpu::DrawType, 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 GrGpu::DrawType,
250 bool hasGeometryProcessor,
251 GrGpuGL*);
252
joshualitt79f8fae2014-10-28 17:59:26 -0700253 GrGLProgramBuilder(GrGpuGL*, const GrOptDrawState&);
joshualitt30ba4362014-08-21 20:18:45 -0700254
egdaniel307796b2014-10-06 12:13:54 -0700255 const GrOptDrawState& optState() const { return fOptState; }
joshualitt79f8fae2014-10-28 17:59:26 -0700256 const GrProgramDesc& desc() const { return fDesc; }
257 const GrProgramDesc::KeyHeader& header() const { return fDesc.header(); }
joshualitt23e280d2014-09-18 12:26:38 -0700258
joshualitt30ba4362014-08-21 20:18:45 -0700259 // Generates a name for a variable. The generated string will be name prefixed by the prefix
260 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
261 // generating stage code.
262 void nameVariable(SkString* out, char prefix, const char* name);
egdaniel37b4d862014-11-03 10:07:07 -0800263 void setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor, GrGLSLExpr1* inputCoverage);
joshualitt2dd1ae02014-12-03 06:24:10 -0800264 // Generates a possibly mangled name for a stage variable and writes it to the fragment shader.
265 // If GrGLSLExpr4 has a valid name then it will use that instead
266 void nameExpression(GrGLSLExpr4*, const char* baseName);
joshualitt4973d9d2014-11-08 09:24:25 -0800267 void emitAndInstallProcs(GrGLSLExpr4* inputColor,
joshualitta5305a12014-10-10 17:47:00 -0700268 GrGLSLExpr4* inputCoverage);
269 void emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut);
joshualitt2dd1ae02014-12-03 06:24:10 -0800270 void emitAndInstallProc(const GrPendingFragmentStage&,
joshualitta5305a12014-10-10 17:47:00 -0700271 int index,
joshualitta5305a12014-10-10 17:47:00 -0700272 const GrGLSLExpr4& input,
273 GrGLSLExpr4* output);
274
joshualitt2dd1ae02014-12-03 06:24:10 -0800275 void emitAndInstallProc(const GrGeometryProcessor&,
276 GrGLSLExpr4* outputColor,
277 GrGLSLExpr4* outputCoverage);
278
joshualitta5305a12014-10-10 17:47:00 -0700279 // these emit functions help to keep the createAndEmitProcessors template general
bsalomonae59b772014-11-19 08:23:49 -0800280 void emitAndInstallProc(const GrPendingFragmentStage&,
joshualitta5305a12014-10-10 17:47:00 -0700281 const char* outColor,
282 const char* inColor);
283 void emitAndInstallProc(const GrGeometryProcessor&,
joshualitt2dd1ae02014-12-03 06:24:10 -0800284 const char* outColor,
285 const char* outCoverage);
286
joshualitt47bb3822014-10-07 16:43:25 -0700287 void verify(const GrGeometryProcessor&);
288 void verify(const GrFragmentProcessor&);
289 void emitSamplers(const GrProcessor&,
290 GrGLProcessor::TextureSamplerArray* outSamplers,
joshualitta5305a12014-10-10 17:47:00 -0700291 GrGLInstalledProc*);
joshualitt30ba4362014-08-21 20:18:45 -0700292
joshualitt47bb3822014-10-07 16:43:25 -0700293 // each specific program builder has a distinct transform and must override this function
bsalomonae59b772014-11-19 08:23:49 -0800294 virtual void emitTransforms(const GrPendingFragmentStage&,
joshualitt47bb3822014-10-07 16:43:25 -0700295 GrGLProcessor::TransformedCoordsArray* outCoords,
joshualitta5305a12014-10-10 17:47:00 -0700296 GrGLInstalledFragProc*);
joshualitt47bb3822014-10-07 16:43:25 -0700297 GrGLProgram* finalize();
298 void bindUniformLocations(GrGLuint programID);
299 bool checkLinkStatus(GrGLuint programID);
300 void resolveUniformLocations(GrGLuint programID);
joshualitt47bb3822014-10-07 16:43:25 -0700301 void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);
302 void cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs);
joshualitt30ba4362014-08-21 20:18:45 -0700303
joshualitt47bb3822014-10-07 16:43:25 -0700304 // Subclasses create different programs
305 virtual GrGLProgram* createProgram(GrGLuint programID);
306
joshualitt30ba4362014-08-21 20:18:45 -0700307 void appendUniformDecls(ShaderVisibility, SkString*) const;
308
joshualitt47bb3822014-10-07 16:43:25 -0700309 // reset is called by program creator between each processor's emit code. It increments the
310 // stage offset for variable name mangling, and also ensures verfication variables in the
311 // fragment shader are cleared.
312 void reset() {
313 this->enterStage();
314 this->addStage();
315 fFS.reset();
316 }
317 void addStage() { fStageIndex++; }
318
319 // This simple class exits the stage and then restores the stage when it goes out of scope
320 class AutoStageRestore {
joshualitt30ba4362014-08-21 20:18:45 -0700321 public:
joshualitt47bb3822014-10-07 16:43:25 -0700322 AutoStageRestore(GrGLProgramBuilder* pb)
323 : fPB(pb), fOutOfStage(pb->fOutOfStage) { pb->exitStage(); }
324 ~AutoStageRestore() { fPB->fOutOfStage = fOutOfStage; }
joshualittb0a8a372014-09-23 09:50:21 -0700325 private:
joshualitt47bb3822014-10-07 16:43:25 -0700326 GrGLProgramBuilder* fPB;
327 bool fOutOfStage;
joshualittb0a8a372014-09-23 09:50:21 -0700328 };
joshualitt47bb3822014-10-07 16:43:25 -0700329 class AutoStageAdvance {
joshualittdb0d3ca2014-10-07 12:42:26 -0700330 public:
joshualitt47bb3822014-10-07 16:43:25 -0700331 AutoStageAdvance(GrGLProgramBuilder* pb) : fPB(pb) { fPB->reset(); }
332 ~AutoStageAdvance() { fPB->exitStage(); }
joshualittdb0d3ca2014-10-07 12:42:26 -0700333 private:
joshualitt47bb3822014-10-07 16:43:25 -0700334 GrGLProgramBuilder* fPB;
335 };
336 void exitStage() { fOutOfStage = true; }
337 void enterStage() { fOutOfStage = false; }
338 int stageIndex() const { return fStageIndex; }
339
joshualitt4973d9d2014-11-08 09:24:25 -0800340 struct TransformVarying {
341 TransformVarying(const GrGLVarying& v, const char* uniName, const char* sourceCoords)
342 : fV(v), fUniName(uniName), fSourceCoords(sourceCoords) {}
343 GrGLVarying fV;
344 SkString fUniName;
345 SkString fSourceCoords;
346 };
347
348 void addCoordVarying(const char* name, GrGLVarying* v, const char* uniName,
349 const char* sourceCoords) {
350 this->addVarying(name, v);
351 fCoordVaryings.push_back(TransformVarying(*v, uniName, sourceCoords));
352 }
353
354 const char* rtAdjustment() const { return "rtAdjustment"; }
355
joshualitt47bb3822014-10-07 16:43:25 -0700356 // number of each input/output type in a single allocation block, used by many builders
357 static const int kVarsPerBlock;
358
359 BuiltinUniformHandles fUniformHandles;
360 GrGLVertexBuilder fVS;
361 GrGLGeometryBuilder fGS;
362 GrGLFragmentShaderBuilder fFS;
363 bool fOutOfStage;
364 int fStageIndex;
365
joshualitta5305a12014-10-10 17:47:00 -0700366 GrGLInstalledGeoProc* fGeometryProcessor;
367 SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
joshualitt47bb3822014-10-07 16:43:25 -0700368
369 const GrOptDrawState& fOptState;
joshualitt79f8fae2014-10-28 17:59:26 -0700370 const GrProgramDesc& fDesc;
joshualitt47bb3822014-10-07 16:43:25 -0700371 GrGpuGL* fGpu;
372 UniformInfoArray fUniforms;
joshualitt4973d9d2014-11-08 09:24:25 -0800373 SkSTArray<16, TransformVarying, true> fCoordVaryings;
joshualitt47bb3822014-10-07 16:43:25 -0700374
375 friend class GrGLShaderBuilder;
376 friend class GrGLVertexBuilder;
377 friend class GrGLFragmentShaderBuilder;
378 friend class GrGLGeometryBuilder;
379};
380
381/**
joshualitta5305a12014-10-10 17:47:00 -0700382 * The below structs represent processors installed in programs. All processors can have texture
383 * samplers, but only frag processors have coord transforms, hence the need for different structs
joshualitt47bb3822014-10-07 16:43:25 -0700384 */
joshualitta5305a12014-10-10 17:47:00 -0700385struct GrGLInstalledProc {
386 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
joshualitt47bb3822014-10-07 16:43:25 -0700387
joshualitta5305a12014-10-10 17:47:00 -0700388 struct Sampler {
389 SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
390 UniformHandle fUniform;
391 int fTextureUnit;
392 };
393 SkSTArray<4, Sampler, true> fSamplers;
394};
joshualitt47bb3822014-10-07 16:43:25 -0700395
joshualitta5305a12014-10-10 17:47:00 -0700396struct GrGLInstalledGeoProc : public GrGLInstalledProc {
397 SkAutoTDelete<GrGLGeometryProcessor> fGLProc;
398};
joshualitt47bb3822014-10-07 16:43:25 -0700399
joshualitta5305a12014-10-10 17:47:00 -0700400struct GrGLInstalledFragProc : public GrGLInstalledProc {
joshualitt2dd1ae02014-12-03 06:24:10 -0800401 GrGLInstalledFragProc() : fGLProc(NULL) {}
joshualitt47bb3822014-10-07 16:43:25 -0700402 class ShaderVarHandle {
403 public:
404 bool isValid() const { return fHandle > -1; }
405 ShaderVarHandle() : fHandle(-1) {}
406 ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); }
407 int handle() const { SkASSERT(this->isValid()); return fHandle; }
408 UniformHandle convertToUniformHandle() {
409 SkASSERT(this->isValid());
410 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle);
411 }
joshualittdb0d3ca2014-10-07 12:42:26 -0700412
joshualitt47bb3822014-10-07 16:43:25 -0700413 private:
414 int fHandle;
415 };
joshualittdb0d3ca2014-10-07 12:42:26 -0700416
joshualitt47bb3822014-10-07 16:43:25 -0700417 struct Transform {
418 Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
419 ShaderVarHandle fHandle;
420 SkMatrix fCurrentValue;
421 GrSLType fType;
422 };
joshualittdb0d3ca2014-10-07 12:42:26 -0700423
joshualitta5305a12014-10-10 17:47:00 -0700424 SkAutoTDelete<GrGLFragmentProcessor> fGLProc;
425 SkSTArray<2, Transform, true> fTransforms;
joshualitta5305a12014-10-10 17:47:00 -0700426};
joshualittdb0d3ca2014-10-07 12:42:26 -0700427
joshualitta5305a12014-10-10 17:47:00 -0700428struct GrGLInstalledFragProcs : public SkRefCnt {
429 virtual ~GrGLInstalledFragProcs();
430 SkSTArray<8, GrGLInstalledFragProc*, true> fProcs;
joshualitt30ba4362014-08-21 20:18:45 -0700431};
432
joshualitt30ba4362014-08-21 20:18:45 -0700433#endif