blob: 612791e07807e5dbbabb5b3740e2f7563f98322e [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"
egdanielc2304142014-12-11 13:15:13 -080017#include "../GrGLXferProcessor.h"
bsalomon04ddf892014-11-19 12:36:22 -080018#include "../../GrOptDrawState.h"
bsalomonae59b772014-11-19 08:23:49 -080019#include "../../GrPendingFragmentStage.h"
joshualitt89c7a2e2014-10-10 14:11:59 -070020
joshualitt47bb3822014-10-07 16:43:25 -070021/*
22 * This is the base class for a series of interfaces. This base class *MUST* remain abstract with
23 * NO data members because it is used in multiple interface inheritance.
24 * Heirarchy:
25 * GrGLUniformBuilder
26 * / \
27 * GrGLFPBuilder GrGLGPBuilder
28 * \ /
29 * GrGLProgramBuilder(internal use only)
30 */
31class GrGLUniformBuilder {
joshualitt30ba4362014-08-21 20:18:45 -070032public:
33 enum ShaderVisibility {
bsalomon17168df2014-12-09 09:00:49 -080034 kVertex_Visibility = 1 << kVertex_GrShaderType,
35 kGeometry_Visibility = 1 << kGeometry_GrShaderType,
36 kFragment_Visibility = 1 << kFragment_GrShaderType,
joshualitt30ba4362014-08-21 20:18:45 -070037 };
38
joshualitt47bb3822014-10-07 16:43:25 -070039 virtual ~GrGLUniformBuilder() {}
40
joshualitt30ba4362014-08-21 20:18:45 -070041 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
joshualitt47bb3822014-10-07 16:43:25 -070042
43 /** Add a uniform variable to the current program, that has visibility in one or more shaders.
44 visibility is a bitfield of ShaderVisibility values indicating from which shaders the
45 uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
46 supported at this time. The actual uniform name will be mangled. If outName is not NULL then
47 it will refer to the final uniform name after return. Use the addUniformArray variant to add
48 an array of uniforms. */
bsalomon422f56f2014-12-09 10:18:12 -080049 UniformHandle addUniform(uint32_t visibility,
50 GrSLType type,
51 GrSLPrecision precision,
52 const char* name,
53 const char** outName = NULL) {
54 return this->addUniformArray(visibility, type, precision, name, 0, outName);
55 }
56
57 virtual UniformHandle addUniformArray(
58 uint32_t visibility,
59 GrSLType type,
60 GrSLPrecision precision,
61 const char* name,
62 int arrayCount,
63 const char** outName = NULL) = 0;
joshualitt47bb3822014-10-07 16:43:25 -070064
65 virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const = 0;
66
67 /**
68 * Shortcut for getUniformVariable(u).c_str()
69 */
70 virtual const char* getUniformCStr(UniformHandle u) const = 0;
71
72 virtual const GrGLContextInfo& ctxInfo() const = 0;
73
bsalomon861e1032014-12-16 07:33:49 -080074 virtual GrGLGpu* gpu() const = 0;
joshualitt47bb3822014-10-07 16:43:25 -070075
76 /*
77 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
78 */
79};
80
joshualitt74077b92014-10-24 11:26:03 -070081// TODO move this into GrGLGPBuilder and move them both out of this file
82class GrGLVarying {
83public:
84 bool vsVarying() const { return kVertToFrag_Varying == fVarying ||
85 kVertToGeo_Varying == fVarying; }
86 bool fsVarying() const { return kVertToFrag_Varying == fVarying ||
87 kGeoToFrag_Varying == fVarying; }
88 const char* vsOut() const { return fVsOut; }
89 const char* gsIn() const { return fGsIn; }
90 const char* gsOut() const { return fGsOut; }
91 const char* fsIn() const { return fFsIn; }
joshualittabb52a12015-01-13 15:02:10 -080092 GrSLType type() const { return fType; }
joshualitt74077b92014-10-24 11:26:03 -070093
94protected:
95 enum Varying {
96 kVertToFrag_Varying,
97 kVertToGeo_Varying,
98 kGeoToFrag_Varying,
99 };
100
101 GrGLVarying(GrSLType type, Varying varying)
102 : fVarying(varying), fType(type), fVsOut(NULL), fGsIn(NULL), fGsOut(NULL),
103 fFsIn(NULL) {}
104
105 Varying fVarying;
106
107private:
108 GrSLType fType;
109 const char* fVsOut;
110 const char* fGsIn;
111 const char* fGsOut;
112 const char* fFsIn;
113
114 friend class GrGLVertexBuilder;
115 friend class GrGLGeometryBuilder;
egdanielc2304142014-12-11 13:15:13 -0800116 friend class GrGLXferBuilder;
joshualitt74077b92014-10-24 11:26:03 -0700117 friend class GrGLFragmentShaderBuilder;
118};
119
120struct GrGLVertToFrag : public GrGLVarying {
121 GrGLVertToFrag(GrSLType type)
122 : GrGLVarying(type, kVertToFrag_Varying) {}
123};
124
125struct GrGLVertToGeo : public GrGLVarying {
126 GrGLVertToGeo(GrSLType type)
127 : GrGLVarying(type, kVertToGeo_Varying) {}
128};
129
130struct GrGLGeoToFrag : public GrGLVarying {
131 GrGLGeoToFrag(GrSLType type)
132 : GrGLVarying(type, kGeoToFrag_Varying) {}
133};
134
joshualitt47bb3822014-10-07 16:43:25 -0700135/* a specialization of the above for GPs. Lets the user add uniforms, varyings, and VS / FS code */
136class GrGLGPBuilder : public virtual GrGLUniformBuilder {
137public:
joshualitt2dd1ae02014-12-03 06:24:10 -0800138 /*
139 * addVarying allows fine grained control for setting up varyings between stages. If you just
140 * need to take an attribute and pass it through to an output value in a fragment shader, use
141 * addPassThroughAttribute.
142 * TODO convert most uses of addVarying to addPassThroughAttribute
143 */
joshualitt74077b92014-10-24 11:26:03 -0700144 virtual void addVarying(const char* name,
145 GrGLVarying*,
bsalomonc0bd6482014-12-09 10:04:14 -0800146 GrSLPrecision fsPrecision = kDefault_GrSLPrecision) = 0;
joshualitt47bb3822014-10-07 16:43:25 -0700147
joshualitt2dd1ae02014-12-03 06:24:10 -0800148 /*
149 * This call can be used by GP to pass an attribute through all shaders directly to 'output' in
150 * the fragment shader. Though this call effects both the vertex shader and fragment shader,
151 * it expects 'output' to be defined in the fragment shader before this call is made.
152 * TODO it might be nicer behavior to have a flag to declare output inside this call
153 */
joshualitt71c92602015-01-14 08:12:47 -0800154 virtual void addPassThroughAttribute(const GrGeometryProcessor::Attribute*,
joshualitt2dd1ae02014-12-03 06:24:10 -0800155 const char* output) = 0;
156
joshualitt47bb3822014-10-07 16:43:25 -0700157 // TODO rename getFragmentBuilder
158 virtual GrGLGPFragmentBuilder* getFragmentShaderBuilder() = 0;
159 virtual GrGLVertexBuilder* getVertexShaderBuilder() = 0;
160
161 /*
162 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
163 */
164};
165
166/* a specializations for FPs. Lets the user add uniforms and FS code */
167class GrGLFPBuilder : public virtual GrGLUniformBuilder {
168public:
169 virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() = 0;
170
171 /*
172 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
173 */
174};
175
egdanielc2304142014-12-11 13:15:13 -0800176/* a specializations for XPs. Lets the user add uniforms and FS code */
177class GrGLXPBuilder : public virtual GrGLUniformBuilder {
178public:
179 virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() = 0;
180
181 /*
182 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
183 */
184};
joshualittabb52a12015-01-13 15:02:10 -0800185
186/**
187 * The below struct represent processors installed in programs.
188 */
189template <class Proc>
190struct GrGLInstalledProc {
191 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
192
193 struct Sampler {
194 SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
195 UniformHandle fUniform;
196 int fTextureUnit;
197 };
198 SkSTArray<4, Sampler, true> fSamplers;
199 SkAutoTDelete<Proc> fGLProc;
200};
201
202typedef GrGLInstalledProc<GrGLPrimitiveProcessor> GrGLInstalledGeoProc;
203typedef GrGLInstalledProc<GrGLXferProcessor> GrGLInstalledXferProc;
204typedef GrGLInstalledProc<GrGLFragmentProcessor> GrGLInstalledFragProc;
205
206struct GrGLInstalledFragProcs : public SkRefCnt {
207 virtual ~GrGLInstalledFragProcs();
208 SkSTArray<8, GrGLInstalledFragProc*, true> fProcs;
209};
joshualitta5305a12014-10-10 17:47:00 -0700210
joshualitt47bb3822014-10-07 16:43:25 -0700211/*
212 * Please note - no diamond problems because of virtual inheritance. Also, both base classes
213 * are pure virtual with no data members. This is the base class for program building.
214 * Subclasses are nearly identical but each has their own way of emitting transforms. State for
215 * each of the elements of the shader pipeline, ie vertex, fragment, geometry, etc, lives in those
216 * respective builders
217*/
218class GrGLProgramBuilder : public GrGLGPBuilder,
egdanielc2304142014-12-11 13:15:13 -0800219 public GrGLFPBuilder,
220 public GrGLXPBuilder {
joshualitt47bb3822014-10-07 16:43:25 -0700221public:
joshualitt873ad0e2015-01-20 09:08:51 -0800222 typedef GrGpu::DrawArgs DrawArgs;
joshualitt47bb3822014-10-07 16:43:25 -0700223 /** Generates a shader program.
224 *
225 * The program implements what is specified in the stages given as input.
226 * After successful generation, the builder result objects are available
227 * to be used.
228 * @return true if generation was successful.
229 */
joshualitt873ad0e2015-01-20 09:08:51 -0800230 static GrGLProgram* CreateProgram(const DrawArgs&, GrGLGpu*);
joshualitt47bb3822014-10-07 16:43:25 -0700231
bsalomon422f56f2014-12-09 10:18:12 -0800232 UniformHandle addUniformArray(uint32_t visibility,
233 GrSLType type,
234 GrSLPrecision precision,
235 const char* name,
236 int arrayCount,
237 const char** outName) SK_OVERRIDE;
joshualitt47bb3822014-10-07 16:43:25 -0700238
bsalomon422f56f2014-12-09 10:18:12 -0800239 const GrGLShaderVar& getUniformVariable(UniformHandle u) const SK_OVERRIDE {
joshualitt47bb3822014-10-07 16:43:25 -0700240 return fUniforms[u.toShaderBuilderIndex()].fVariable;
241 }
242
bsalomon422f56f2014-12-09 10:18:12 -0800243 const char* getUniformCStr(UniformHandle u) const SK_OVERRIDE {
joshualitt47bb3822014-10-07 16:43:25 -0700244 return this->getUniformVariable(u).c_str();
245 }
246
bsalomon422f56f2014-12-09 10:18:12 -0800247 const GrGLContextInfo& ctxInfo() const SK_OVERRIDE;
joshualitt47bb3822014-10-07 16:43:25 -0700248
bsalomon861e1032014-12-16 07:33:49 -0800249 GrGLGpu* gpu() const SK_OVERRIDE { return fGpu; }
joshualitt47bb3822014-10-07 16:43:25 -0700250
bsalomon422f56f2014-12-09 10:18:12 -0800251 GrGLFPFragmentBuilder* getFragmentShaderBuilder() SK_OVERRIDE { return &fFS; }
252 GrGLVertexBuilder* getVertexShaderBuilder() SK_OVERRIDE { return &fVS; }
joshualitt47bb3822014-10-07 16:43:25 -0700253
bsalomon422f56f2014-12-09 10:18:12 -0800254 void addVarying(
joshualitta5305a12014-10-10 17:47:00 -0700255 const char* name,
joshualitt74077b92014-10-24 11:26:03 -0700256 GrGLVarying*,
bsalomonc0bd6482014-12-09 10:04:14 -0800257 GrSLPrecision fsPrecision = kDefault_GrSLPrecision) SK_OVERRIDE;
joshualitt30ba4362014-08-21 20:18:45 -0700258
joshualitt71c92602015-01-14 08:12:47 -0800259 void addPassThroughAttribute(const GrPrimitiveProcessor::Attribute*,
260 const char* output) SK_OVERRIDE;
joshualitt2dd1ae02014-12-03 06:24:10 -0800261
262
joshualitt30ba4362014-08-21 20:18:45 -0700263 // Handles for program uniforms (other than per-effect uniforms)
264 struct BuiltinUniformHandles {
joshualitt30ba4362014-08-21 20:18:45 -0700265 UniformHandle fRTAdjustmentUni;
joshualitt30ba4362014-08-21 20:18:45 -0700266
267 // We use the render target height to provide a y-down frag coord when specifying
268 // origin_upper_left is not supported.
269 UniformHandle fRTHeightUni;
270
271 // Uniforms for computing texture coords to do the dst-copy lookup
272 UniformHandle fDstCopyTopLeftUni;
273 UniformHandle fDstCopyScaleUni;
274 UniformHandle fDstCopySamplerUni;
275 };
276
joshualittdb0d3ca2014-10-07 12:42:26 -0700277protected:
joshualitta5305a12014-10-10 17:47:00 -0700278 typedef GrGLProgramDataManager::UniformInfo UniformInfo;
279 typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
280
joshualitt873ad0e2015-01-20 09:08:51 -0800281 static GrGLProgramBuilder* CreateProgramBuilder(const DrawArgs&, GrGLGpu*);
joshualitt47bb3822014-10-07 16:43:25 -0700282
joshualitt873ad0e2015-01-20 09:08:51 -0800283 GrGLProgramBuilder(GrGLGpu*, const DrawArgs&);
joshualitt30ba4362014-08-21 20:18:45 -0700284
joshualitt873ad0e2015-01-20 09:08:51 -0800285 const GrPrimitiveProcessor& primitiveProcessor() const { return *fArgs.fPrimitiveProcessor; }
286 const GrOptDrawState& optState() const { return *fArgs.fOptState; }
287 const GrProgramDesc& desc() const { return *fArgs.fDesc; }
288 const GrBatchTracker& batchTracker() const { return *fArgs.fBatchTracker; }
289 const GrProgramDesc::KeyHeader& header() const { return fArgs.fDesc->header(); }
joshualitt23e280d2014-09-18 12:26:38 -0700290
joshualitt30ba4362014-08-21 20:18:45 -0700291 // Generates a name for a variable. The generated string will be name prefixed by the prefix
292 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
293 // generating stage code.
294 void nameVariable(SkString* out, char prefix, const char* name);
joshualitt2dd1ae02014-12-03 06:24:10 -0800295 // Generates a possibly mangled name for a stage variable and writes it to the fragment shader.
296 // If GrGLSLExpr4 has a valid name then it will use that instead
297 void nameExpression(GrGLSLExpr4*, const char* baseName);
joshualitt4973d9d2014-11-08 09:24:25 -0800298 void emitAndInstallProcs(GrGLSLExpr4* inputColor,
joshualitta5305a12014-10-10 17:47:00 -0700299 GrGLSLExpr4* inputCoverage);
300 void emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut);
joshualitt2dd1ae02014-12-03 06:24:10 -0800301 void emitAndInstallProc(const GrPendingFragmentStage&,
joshualitta5305a12014-10-10 17:47:00 -0700302 int index,
joshualitta5305a12014-10-10 17:47:00 -0700303 const GrGLSLExpr4& input,
304 GrGLSLExpr4* output);
305
joshualitt9b989322014-12-15 14:16:27 -0800306 void emitAndInstallProc(const GrPrimitiveProcessor&,
joshualitt2dd1ae02014-12-03 06:24:10 -0800307 GrGLSLExpr4* outputColor,
308 GrGLSLExpr4* outputCoverage);
309
joshualitta5305a12014-10-10 17:47:00 -0700310 // these emit functions help to keep the createAndEmitProcessors template general
bsalomonae59b772014-11-19 08:23:49 -0800311 void emitAndInstallProc(const GrPendingFragmentStage&,
joshualittabb52a12015-01-13 15:02:10 -0800312 int index,
joshualitta5305a12014-10-10 17:47:00 -0700313 const char* outColor,
314 const char* inColor);
joshualitt9b989322014-12-15 14:16:27 -0800315 void emitAndInstallProc(const GrPrimitiveProcessor&,
joshualitt2dd1ae02014-12-03 06:24:10 -0800316 const char* outColor,
317 const char* outCoverage);
egdanielc2304142014-12-11 13:15:13 -0800318 void emitAndInstallXferProc(const GrXferProcessor&,
319 const GrGLSLExpr4& colorIn,
320 const GrGLSLExpr4& coverageIn);
joshualitt2dd1ae02014-12-03 06:24:10 -0800321
joshualitt9b989322014-12-15 14:16:27 -0800322 void verify(const GrPrimitiveProcessor&);
egdanielc2304142014-12-11 13:15:13 -0800323 void verify(const GrXferProcessor&);
joshualitt47bb3822014-10-07 16:43:25 -0700324 void verify(const GrFragmentProcessor&);
joshualittabb52a12015-01-13 15:02:10 -0800325 template <class Proc>
joshualitt47bb3822014-10-07 16:43:25 -0700326 void emitSamplers(const GrProcessor&,
327 GrGLProcessor::TextureSamplerArray* outSamplers,
joshualittabb52a12015-01-13 15:02:10 -0800328 GrGLInstalledProc<Proc>*);
joshualitt30ba4362014-08-21 20:18:45 -0700329
joshualitt47bb3822014-10-07 16:43:25 -0700330 GrGLProgram* finalize();
331 void bindUniformLocations(GrGLuint programID);
332 bool checkLinkStatus(GrGLuint programID);
333 void resolveUniformLocations(GrGLuint programID);
joshualitt47bb3822014-10-07 16:43:25 -0700334 void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);
335 void cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs);
joshualitt30ba4362014-08-21 20:18:45 -0700336
joshualitt47bb3822014-10-07 16:43:25 -0700337 // Subclasses create different programs
338 virtual GrGLProgram* createProgram(GrGLuint programID);
339
joshualitt30ba4362014-08-21 20:18:45 -0700340 void appendUniformDecls(ShaderVisibility, SkString*) const;
341
joshualitt47bb3822014-10-07 16:43:25 -0700342 // reset is called by program creator between each processor's emit code. It increments the
343 // stage offset for variable name mangling, and also ensures verfication variables in the
344 // fragment shader are cleared.
345 void reset() {
346 this->enterStage();
347 this->addStage();
348 fFS.reset();
349 }
350 void addStage() { fStageIndex++; }
351
352 // This simple class exits the stage and then restores the stage when it goes out of scope
353 class AutoStageRestore {
joshualitt30ba4362014-08-21 20:18:45 -0700354 public:
joshualitt47bb3822014-10-07 16:43:25 -0700355 AutoStageRestore(GrGLProgramBuilder* pb)
356 : fPB(pb), fOutOfStage(pb->fOutOfStage) { pb->exitStage(); }
357 ~AutoStageRestore() { fPB->fOutOfStage = fOutOfStage; }
joshualittb0a8a372014-09-23 09:50:21 -0700358 private:
joshualitt47bb3822014-10-07 16:43:25 -0700359 GrGLProgramBuilder* fPB;
360 bool fOutOfStage;
joshualittb0a8a372014-09-23 09:50:21 -0700361 };
joshualitt47bb3822014-10-07 16:43:25 -0700362 class AutoStageAdvance {
joshualittdb0d3ca2014-10-07 12:42:26 -0700363 public:
joshualitt47bb3822014-10-07 16:43:25 -0700364 AutoStageAdvance(GrGLProgramBuilder* pb) : fPB(pb) { fPB->reset(); }
365 ~AutoStageAdvance() { fPB->exitStage(); }
joshualittdb0d3ca2014-10-07 12:42:26 -0700366 private:
joshualitt47bb3822014-10-07 16:43:25 -0700367 GrGLProgramBuilder* fPB;
368 };
369 void exitStage() { fOutOfStage = true; }
370 void enterStage() { fOutOfStage = false; }
371 int stageIndex() const { return fStageIndex; }
372
joshualitt4973d9d2014-11-08 09:24:25 -0800373 const char* rtAdjustment() const { return "rtAdjustment"; }
374
joshualitt47bb3822014-10-07 16:43:25 -0700375 // number of each input/output type in a single allocation block, used by many builders
376 static const int kVarsPerBlock;
377
378 BuiltinUniformHandles fUniformHandles;
379 GrGLVertexBuilder fVS;
380 GrGLGeometryBuilder fGS;
381 GrGLFragmentShaderBuilder fFS;
382 bool fOutOfStage;
383 int fStageIndex;
384
joshualitta5305a12014-10-10 17:47:00 -0700385 GrGLInstalledGeoProc* fGeometryProcessor;
egdanielc2304142014-12-11 13:15:13 -0800386 GrGLInstalledXferProc* fXferProcessor;
joshualitta5305a12014-10-10 17:47:00 -0700387 SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
joshualitt47bb3822014-10-07 16:43:25 -0700388
joshualitt873ad0e2015-01-20 09:08:51 -0800389 const DrawArgs& fArgs;
bsalomon861e1032014-12-16 07:33:49 -0800390 GrGLGpu* fGpu;
joshualitt47bb3822014-10-07 16:43:25 -0700391 UniformInfoArray fUniforms;
joshualittabb52a12015-01-13 15:02:10 -0800392 GrGLPrimitiveProcessor::TransformsIn fCoordTransforms;
393 GrGLPrimitiveProcessor::TransformsOut fOutCoords;
joshualitt47bb3822014-10-07 16:43:25 -0700394
395 friend class GrGLShaderBuilder;
396 friend class GrGLVertexBuilder;
397 friend class GrGLFragmentShaderBuilder;
398 friend class GrGLGeometryBuilder;
399};
joshualitt30ba4362014-08-21 20:18:45 -0700400#endif