blob: 37e678fefb884608b7a6b91650987f8bd87f843c [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 */
154 virtual void addPassThroughAttribute(const GrGeometryProcessor::GrAttribute*,
155 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:
222 /** Generates a shader program.
223 *
224 * The program implements what is specified in the stages given as input.
225 * After successful generation, the builder result objects are available
226 * to be used.
227 * @return true if generation was successful.
228 */
bsalomon861e1032014-12-16 07:33:49 -0800229 static GrGLProgram* CreateProgram(const GrOptDrawState&, GrGLGpu*);
joshualitt47bb3822014-10-07 16:43:25 -0700230
bsalomon422f56f2014-12-09 10:18:12 -0800231 UniformHandle addUniformArray(uint32_t visibility,
232 GrSLType type,
233 GrSLPrecision precision,
234 const char* name,
235 int arrayCount,
236 const char** outName) SK_OVERRIDE;
joshualitt47bb3822014-10-07 16:43:25 -0700237
bsalomon422f56f2014-12-09 10:18:12 -0800238 const GrGLShaderVar& getUniformVariable(UniformHandle u) const SK_OVERRIDE {
joshualitt47bb3822014-10-07 16:43:25 -0700239 return fUniforms[u.toShaderBuilderIndex()].fVariable;
240 }
241
bsalomon422f56f2014-12-09 10:18:12 -0800242 const char* getUniformCStr(UniformHandle u) const SK_OVERRIDE {
joshualitt47bb3822014-10-07 16:43:25 -0700243 return this->getUniformVariable(u).c_str();
244 }
245
bsalomon422f56f2014-12-09 10:18:12 -0800246 const GrGLContextInfo& ctxInfo() const SK_OVERRIDE;
joshualitt47bb3822014-10-07 16:43:25 -0700247
bsalomon861e1032014-12-16 07:33:49 -0800248 GrGLGpu* gpu() const SK_OVERRIDE { return fGpu; }
joshualitt47bb3822014-10-07 16:43:25 -0700249
bsalomon422f56f2014-12-09 10:18:12 -0800250 GrGLFPFragmentBuilder* getFragmentShaderBuilder() SK_OVERRIDE { return &fFS; }
251 GrGLVertexBuilder* getVertexShaderBuilder() SK_OVERRIDE { return &fVS; }
joshualitt47bb3822014-10-07 16:43:25 -0700252
bsalomon422f56f2014-12-09 10:18:12 -0800253 void addVarying(
joshualitta5305a12014-10-10 17:47:00 -0700254 const char* name,
joshualitt74077b92014-10-24 11:26:03 -0700255 GrGLVarying*,
bsalomonc0bd6482014-12-09 10:04:14 -0800256 GrSLPrecision fsPrecision = kDefault_GrSLPrecision) SK_OVERRIDE;
joshualitt30ba4362014-08-21 20:18:45 -0700257
bsalomon422f56f2014-12-09 10:18:12 -0800258 void addPassThroughAttribute(const GrGeometryProcessor::GrAttribute*,
joshualitt2dd1ae02014-12-03 06:24:10 -0800259 const char* output) SK_OVERRIDE;
260
261
joshualitt30ba4362014-08-21 20:18:45 -0700262 // Handles for program uniforms (other than per-effect uniforms)
263 struct BuiltinUniformHandles {
joshualitt30ba4362014-08-21 20:18:45 -0700264 UniformHandle fRTAdjustmentUni;
joshualitt30ba4362014-08-21 20:18:45 -0700265
266 // We use the render target height to provide a y-down frag coord when specifying
267 // origin_upper_left is not supported.
268 UniformHandle fRTHeightUni;
269
270 // Uniforms for computing texture coords to do the dst-copy lookup
271 UniformHandle fDstCopyTopLeftUni;
272 UniformHandle fDstCopyScaleUni;
273 UniformHandle fDstCopySamplerUni;
274 };
275
joshualittdb0d3ca2014-10-07 12:42:26 -0700276protected:
joshualitta5305a12014-10-10 17:47:00 -0700277 typedef GrGLProgramDataManager::UniformInfo UniformInfo;
278 typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
279
joshualittabb52a12015-01-13 15:02:10 -0800280 static GrGLProgramBuilder* CreateProgramBuilder(const GrOptDrawState&, GrGLGpu*);
joshualitt47bb3822014-10-07 16:43:25 -0700281
bsalomon861e1032014-12-16 07:33:49 -0800282 GrGLProgramBuilder(GrGLGpu*, const GrOptDrawState&);
joshualitt30ba4362014-08-21 20:18:45 -0700283
egdaniel307796b2014-10-06 12:13:54 -0700284 const GrOptDrawState& optState() const { return fOptState; }
joshualitt79f8fae2014-10-28 17:59:26 -0700285 const GrProgramDesc& desc() const { return fDesc; }
286 const GrProgramDesc::KeyHeader& header() const { return fDesc.header(); }
joshualitt23e280d2014-09-18 12:26:38 -0700287
joshualitt30ba4362014-08-21 20:18:45 -0700288 // Generates a name for a variable. The generated string will be name prefixed by the prefix
289 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
290 // generating stage code.
291 void nameVariable(SkString* out, char prefix, const char* name);
joshualitt2dd1ae02014-12-03 06:24:10 -0800292 // Generates a possibly mangled name for a stage variable and writes it to the fragment shader.
293 // If GrGLSLExpr4 has a valid name then it will use that instead
294 void nameExpression(GrGLSLExpr4*, const char* baseName);
joshualitt4973d9d2014-11-08 09:24:25 -0800295 void emitAndInstallProcs(GrGLSLExpr4* inputColor,
joshualitta5305a12014-10-10 17:47:00 -0700296 GrGLSLExpr4* inputCoverage);
297 void emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut);
joshualitt2dd1ae02014-12-03 06:24:10 -0800298 void emitAndInstallProc(const GrPendingFragmentStage&,
joshualitta5305a12014-10-10 17:47:00 -0700299 int index,
joshualitta5305a12014-10-10 17:47:00 -0700300 const GrGLSLExpr4& input,
301 GrGLSLExpr4* output);
302
joshualitt9b989322014-12-15 14:16:27 -0800303 void emitAndInstallProc(const GrPrimitiveProcessor&,
joshualitt2dd1ae02014-12-03 06:24:10 -0800304 GrGLSLExpr4* outputColor,
305 GrGLSLExpr4* outputCoverage);
306
joshualitta5305a12014-10-10 17:47:00 -0700307 // these emit functions help to keep the createAndEmitProcessors template general
bsalomonae59b772014-11-19 08:23:49 -0800308 void emitAndInstallProc(const GrPendingFragmentStage&,
joshualittabb52a12015-01-13 15:02:10 -0800309 int index,
joshualitta5305a12014-10-10 17:47:00 -0700310 const char* outColor,
311 const char* inColor);
joshualitt9b989322014-12-15 14:16:27 -0800312 void emitAndInstallProc(const GrPrimitiveProcessor&,
joshualitt2dd1ae02014-12-03 06:24:10 -0800313 const char* outColor,
314 const char* outCoverage);
egdanielc2304142014-12-11 13:15:13 -0800315 void emitAndInstallXferProc(const GrXferProcessor&,
316 const GrGLSLExpr4& colorIn,
317 const GrGLSLExpr4& coverageIn);
joshualitt2dd1ae02014-12-03 06:24:10 -0800318
joshualitt9b989322014-12-15 14:16:27 -0800319 void verify(const GrPrimitiveProcessor&);
egdanielc2304142014-12-11 13:15:13 -0800320 void verify(const GrXferProcessor&);
joshualitt47bb3822014-10-07 16:43:25 -0700321 void verify(const GrFragmentProcessor&);
joshualittabb52a12015-01-13 15:02:10 -0800322 template <class Proc>
joshualitt47bb3822014-10-07 16:43:25 -0700323 void emitSamplers(const GrProcessor&,
324 GrGLProcessor::TextureSamplerArray* outSamplers,
joshualittabb52a12015-01-13 15:02:10 -0800325 GrGLInstalledProc<Proc>*);
joshualitt30ba4362014-08-21 20:18:45 -0700326
joshualitt47bb3822014-10-07 16:43:25 -0700327 GrGLProgram* finalize();
328 void bindUniformLocations(GrGLuint programID);
329 bool checkLinkStatus(GrGLuint programID);
330 void resolveUniformLocations(GrGLuint programID);
joshualitt47bb3822014-10-07 16:43:25 -0700331 void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);
332 void cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs);
joshualitt30ba4362014-08-21 20:18:45 -0700333
joshualitt47bb3822014-10-07 16:43:25 -0700334 // Subclasses create different programs
335 virtual GrGLProgram* createProgram(GrGLuint programID);
336
joshualitt30ba4362014-08-21 20:18:45 -0700337 void appendUniformDecls(ShaderVisibility, SkString*) const;
338
joshualitt47bb3822014-10-07 16:43:25 -0700339 // reset is called by program creator between each processor's emit code. It increments the
340 // stage offset for variable name mangling, and also ensures verfication variables in the
341 // fragment shader are cleared.
342 void reset() {
343 this->enterStage();
344 this->addStage();
345 fFS.reset();
346 }
347 void addStage() { fStageIndex++; }
348
349 // This simple class exits the stage and then restores the stage when it goes out of scope
350 class AutoStageRestore {
joshualitt30ba4362014-08-21 20:18:45 -0700351 public:
joshualitt47bb3822014-10-07 16:43:25 -0700352 AutoStageRestore(GrGLProgramBuilder* pb)
353 : fPB(pb), fOutOfStage(pb->fOutOfStage) { pb->exitStage(); }
354 ~AutoStageRestore() { fPB->fOutOfStage = fOutOfStage; }
joshualittb0a8a372014-09-23 09:50:21 -0700355 private:
joshualitt47bb3822014-10-07 16:43:25 -0700356 GrGLProgramBuilder* fPB;
357 bool fOutOfStage;
joshualittb0a8a372014-09-23 09:50:21 -0700358 };
joshualitt47bb3822014-10-07 16:43:25 -0700359 class AutoStageAdvance {
joshualittdb0d3ca2014-10-07 12:42:26 -0700360 public:
joshualitt47bb3822014-10-07 16:43:25 -0700361 AutoStageAdvance(GrGLProgramBuilder* pb) : fPB(pb) { fPB->reset(); }
362 ~AutoStageAdvance() { fPB->exitStage(); }
joshualittdb0d3ca2014-10-07 12:42:26 -0700363 private:
joshualitt47bb3822014-10-07 16:43:25 -0700364 GrGLProgramBuilder* fPB;
365 };
366 void exitStage() { fOutOfStage = true; }
367 void enterStage() { fOutOfStage = false; }
368 int stageIndex() const { return fStageIndex; }
369
joshualitt4973d9d2014-11-08 09:24:25 -0800370 const char* rtAdjustment() const { return "rtAdjustment"; }
371
joshualitt47bb3822014-10-07 16:43:25 -0700372 // number of each input/output type in a single allocation block, used by many builders
373 static const int kVarsPerBlock;
374
375 BuiltinUniformHandles fUniformHandles;
376 GrGLVertexBuilder fVS;
377 GrGLGeometryBuilder fGS;
378 GrGLFragmentShaderBuilder fFS;
379 bool fOutOfStage;
380 int fStageIndex;
381
joshualitta5305a12014-10-10 17:47:00 -0700382 GrGLInstalledGeoProc* fGeometryProcessor;
egdanielc2304142014-12-11 13:15:13 -0800383 GrGLInstalledXferProc* fXferProcessor;
joshualitta5305a12014-10-10 17:47:00 -0700384 SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
joshualitt47bb3822014-10-07 16:43:25 -0700385
386 const GrOptDrawState& fOptState;
joshualitt79f8fae2014-10-28 17:59:26 -0700387 const GrProgramDesc& fDesc;
bsalomon861e1032014-12-16 07:33:49 -0800388 GrGLGpu* fGpu;
joshualitt47bb3822014-10-07 16:43:25 -0700389 UniformInfoArray fUniforms;
joshualittabb52a12015-01-13 15:02:10 -0800390 GrGLPrimitiveProcessor::TransformsIn fCoordTransforms;
391 GrGLPrimitiveProcessor::TransformsOut fOutCoords;
joshualitt47bb3822014-10-07 16:43:25 -0700392
393 friend class GrGLShaderBuilder;
394 friend class GrGLVertexBuilder;
395 friend class GrGLFragmentShaderBuilder;
396 friend class GrGLGeometryBuilder;
397};
joshualitt30ba4362014-08-21 20:18:45 -0700398#endif