blob: 973ae5e07820a1e24cb228980983f4d0500d8c44 [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 */
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
347 void addCoordVarying(const char* name, GrGLVarying* v, const char* uniName,
348 const char* sourceCoords) {
349 this->addVarying(name, v);
350 fCoordVaryings.push_back(TransformVarying(*v, uniName, sourceCoords));
351 }
352
353 const char* rtAdjustment() const { return "rtAdjustment"; }
354
joshualitt47bb3822014-10-07 16:43:25 -0700355 // number of each input/output type in a single allocation block, used by many builders
356 static const int kVarsPerBlock;
357
358 BuiltinUniformHandles fUniformHandles;
359 GrGLVertexBuilder fVS;
360 GrGLGeometryBuilder fGS;
361 GrGLFragmentShaderBuilder fFS;
362 bool fOutOfStage;
363 int fStageIndex;
364
joshualitta5305a12014-10-10 17:47:00 -0700365 GrGLInstalledGeoProc* fGeometryProcessor;
366 SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
joshualitt47bb3822014-10-07 16:43:25 -0700367
368 const GrOptDrawState& fOptState;
joshualitt79f8fae2014-10-28 17:59:26 -0700369 const GrProgramDesc& fDesc;
joshualitt47bb3822014-10-07 16:43:25 -0700370 GrGpuGL* fGpu;
371 UniformInfoArray fUniforms;
joshualitt4973d9d2014-11-08 09:24:25 -0800372 SkSTArray<16, TransformVarying, true> fCoordVaryings;
joshualitt47bb3822014-10-07 16:43:25 -0700373
374 friend class GrGLShaderBuilder;
375 friend class GrGLVertexBuilder;
376 friend class GrGLFragmentShaderBuilder;
377 friend class GrGLGeometryBuilder;
378};
379
380/**
joshualitta5305a12014-10-10 17:47:00 -0700381 * The below structs represent processors installed in programs. All processors can have texture
382 * samplers, but only frag processors have coord transforms, hence the need for different structs
joshualitt47bb3822014-10-07 16:43:25 -0700383 */
joshualitta5305a12014-10-10 17:47:00 -0700384struct GrGLInstalledProc {
385 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
joshualitt47bb3822014-10-07 16:43:25 -0700386
joshualitta5305a12014-10-10 17:47:00 -0700387 struct Sampler {
388 SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
389 UniformHandle fUniform;
390 int fTextureUnit;
391 };
392 SkSTArray<4, Sampler, true> fSamplers;
393};
joshualitt47bb3822014-10-07 16:43:25 -0700394
joshualitta5305a12014-10-10 17:47:00 -0700395struct GrGLInstalledGeoProc : public GrGLInstalledProc {
396 SkAutoTDelete<GrGLGeometryProcessor> fGLProc;
397};
joshualitt47bb3822014-10-07 16:43:25 -0700398
joshualitta5305a12014-10-10 17:47:00 -0700399struct GrGLInstalledFragProc : public GrGLInstalledProc {
joshualitt2dd1ae02014-12-03 06:24:10 -0800400 GrGLInstalledFragProc() : fGLProc(NULL) {}
joshualitt47bb3822014-10-07 16:43:25 -0700401 class ShaderVarHandle {
402 public:
403 bool isValid() const { return fHandle > -1; }
404 ShaderVarHandle() : fHandle(-1) {}
405 ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); }
406 int handle() const { SkASSERT(this->isValid()); return fHandle; }
407 UniformHandle convertToUniformHandle() {
408 SkASSERT(this->isValid());
409 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle);
410 }
joshualittdb0d3ca2014-10-07 12:42:26 -0700411
joshualitt47bb3822014-10-07 16:43:25 -0700412 private:
413 int fHandle;
414 };
joshualittdb0d3ca2014-10-07 12:42:26 -0700415
joshualitt47bb3822014-10-07 16:43:25 -0700416 struct Transform {
417 Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
418 ShaderVarHandle fHandle;
419 SkMatrix fCurrentValue;
420 GrSLType fType;
421 };
joshualittdb0d3ca2014-10-07 12:42:26 -0700422
joshualitta5305a12014-10-10 17:47:00 -0700423 SkAutoTDelete<GrGLFragmentProcessor> fGLProc;
424 SkSTArray<2, Transform, true> fTransforms;
joshualitta5305a12014-10-10 17:47:00 -0700425};
joshualittdb0d3ca2014-10-07 12:42:26 -0700426
joshualitta5305a12014-10-10 17:47:00 -0700427struct GrGLInstalledFragProcs : public SkRefCnt {
428 virtual ~GrGLInstalledFragProcs();
429 SkSTArray<8, GrGLInstalledFragProc*, true> fProcs;
joshualitt30ba4362014-08-21 20:18:45 -0700430};
431
joshualitt30ba4362014-08-21 20:18:45 -0700432#endif