blob: e6180cc36d865cdff66359ca0ccc46dc3d9fe66c [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:
joshualitt74077b92014-10-24 11:26:03 -0700129 virtual void addVarying(const char* name,
130 GrGLVarying*,
joshualitt47bb3822014-10-07 16:43:25 -0700131 GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision) = 0;
132
133 // TODO rename getFragmentBuilder
134 virtual GrGLGPFragmentBuilder* getFragmentShaderBuilder() = 0;
135 virtual GrGLVertexBuilder* getVertexShaderBuilder() = 0;
136
137 /*
138 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
139 */
140};
141
142/* a specializations for FPs. Lets the user add uniforms and FS code */
143class GrGLFPBuilder : public virtual GrGLUniformBuilder {
144public:
145 virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() = 0;
146
147 /*
148 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
149 */
150};
151
joshualitta5305a12014-10-10 17:47:00 -0700152struct GrGLInstalledProc;
153struct GrGLInstalledGeoProc;
154struct GrGLInstalledFragProc;
155struct GrGLInstalledFragProcs;
156
joshualitt47bb3822014-10-07 16:43:25 -0700157/*
158 * Please note - no diamond problems because of virtual inheritance. Also, both base classes
159 * are pure virtual with no data members. This is the base class for program building.
160 * Subclasses are nearly identical but each has their own way of emitting transforms. State for
161 * each of the elements of the shader pipeline, ie vertex, fragment, geometry, etc, lives in those
162 * respective builders
163*/
164class GrGLProgramBuilder : public GrGLGPBuilder,
165 public GrGLFPBuilder {
166public:
167 /** Generates a shader program.
168 *
169 * The program implements what is specified in the stages given as input.
170 * After successful generation, the builder result objects are available
171 * to be used.
172 * @return true if generation was successful.
173 */
joshualitt79f8fae2014-10-28 17:59:26 -0700174 static GrGLProgram* CreateProgram(const GrOptDrawState&, GrGpu::DrawType, GrGpuGL*);
joshualitt47bb3822014-10-07 16:43:25 -0700175
176 virtual UniformHandle addUniform(uint32_t visibility,
177 GrSLType type,
178 const char* name,
179 const char** outName = NULL) SK_OVERRIDE {
180 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
181 }
182 virtual UniformHandle addUniformArray(uint32_t visibility,
183 GrSLType type,
184 const char* name,
185 int arrayCount,
186 const char** outName = NULL) SK_OVERRIDE;
187
188 virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const SK_OVERRIDE {
189 return fUniforms[u.toShaderBuilderIndex()].fVariable;
190 }
191
192 virtual const char* getUniformCStr(UniformHandle u) const SK_OVERRIDE {
193 return this->getUniformVariable(u).c_str();
194 }
195
196 virtual const GrGLContextInfo& ctxInfo() const SK_OVERRIDE;
197
198 virtual GrGpuGL* gpu() const SK_OVERRIDE { return fGpu; }
199
joshualitt15988992014-10-09 15:04:05 -0700200 virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() SK_OVERRIDE { return &fFS; }
joshualitt47bb3822014-10-07 16:43:25 -0700201 virtual GrGLVertexBuilder* getVertexShaderBuilder() SK_OVERRIDE { return &fVS; }
202
joshualitta5305a12014-10-10 17:47:00 -0700203 virtual void addVarying(
joshualitta5305a12014-10-10 17:47:00 -0700204 const char* name,
joshualitt74077b92014-10-24 11:26:03 -0700205 GrGLVarying*,
joshualitta5305a12014-10-10 17:47:00 -0700206 GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision) SK_OVERRIDE;
joshualitt30ba4362014-08-21 20:18:45 -0700207
208 // Handles for program uniforms (other than per-effect uniforms)
209 struct BuiltinUniformHandles {
210 UniformHandle fViewMatrixUni;
211 UniformHandle fRTAdjustmentUni;
212 UniformHandle fColorUni;
213 UniformHandle fCoverageUni;
214
215 // We use the render target height to provide a y-down frag coord when specifying
216 // origin_upper_left is not supported.
217 UniformHandle fRTHeightUni;
218
219 // Uniforms for computing texture coords to do the dst-copy lookup
220 UniformHandle fDstCopyTopLeftUni;
221 UniformHandle fDstCopyScaleUni;
222 UniformHandle fDstCopySamplerUni;
223 };
224
joshualittdb0d3ca2014-10-07 12:42:26 -0700225protected:
joshualitt79f8fae2014-10-28 17:59:26 -0700226 typedef GrProgramDesc::ProcKeyProvider ProcKeyProvider;
joshualitta5305a12014-10-10 17:47:00 -0700227 typedef GrGLProgramDataManager::UniformInfo UniformInfo;
228 typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
229
joshualitt79f8fae2014-10-28 17:59:26 -0700230 static GrGLProgramBuilder* CreateProgramBuilder(const GrOptDrawState&,
joshualitt47bb3822014-10-07 16:43:25 -0700231 GrGpu::DrawType,
232 bool hasGeometryProcessor,
233 GrGpuGL*);
234
joshualitt79f8fae2014-10-28 17:59:26 -0700235 GrGLProgramBuilder(GrGpuGL*, const GrOptDrawState&);
joshualitt30ba4362014-08-21 20:18:45 -0700236
egdaniel307796b2014-10-06 12:13:54 -0700237 const GrOptDrawState& optState() const { return fOptState; }
joshualitt79f8fae2014-10-28 17:59:26 -0700238 const GrProgramDesc& desc() const { return fDesc; }
239 const GrProgramDesc::KeyHeader& header() const { return fDesc.header(); }
joshualitt23e280d2014-09-18 12:26:38 -0700240
joshualitt30ba4362014-08-21 20:18:45 -0700241 // Generates a name for a variable. The generated string will be name prefixed by the prefix
242 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
243 // generating stage code.
244 void nameVariable(SkString* out, char prefix, const char* name);
egdaniel37b4d862014-11-03 10:07:07 -0800245 void setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor, GrGLSLExpr1* inputCoverage);
joshualitt4973d9d2014-11-08 09:24:25 -0800246 void emitAndInstallProcs(GrGLSLExpr4* inputColor,
joshualitta5305a12014-10-10 17:47:00 -0700247 GrGLSLExpr4* inputCoverage);
248 void emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut);
249 template <class Proc>
250 void emitAndInstallProc(const Proc&,
251 int index,
joshualitt79f8fae2014-10-28 17:59:26 -0700252 const ProcKeyProvider&,
joshualitta5305a12014-10-10 17:47:00 -0700253 const GrGLSLExpr4& input,
254 GrGLSLExpr4* output);
255
256 // these emit functions help to keep the createAndEmitProcessors template general
bsalomonae59b772014-11-19 08:23:49 -0800257 void emitAndInstallProc(const GrPendingFragmentStage&,
joshualitta5305a12014-10-10 17:47:00 -0700258 const GrProcessorKey&,
259 const char* outColor,
260 const char* inColor);
261 void emitAndInstallProc(const GrGeometryProcessor&,
262 const GrProcessorKey&,
joshualitt4973d9d2014-11-08 09:24:25 -0800263 const char* outCoverage,
264 const char* inCoverage);
joshualitt47bb3822014-10-07 16:43:25 -0700265 void verify(const GrGeometryProcessor&);
266 void verify(const GrFragmentProcessor&);
267 void emitSamplers(const GrProcessor&,
268 GrGLProcessor::TextureSamplerArray* outSamplers,
joshualitta5305a12014-10-10 17:47:00 -0700269 GrGLInstalledProc*);
joshualitt30ba4362014-08-21 20:18:45 -0700270
joshualitt47bb3822014-10-07 16:43:25 -0700271 // each specific program builder has a distinct transform and must override this function
bsalomonae59b772014-11-19 08:23:49 -0800272 virtual void emitTransforms(const GrPendingFragmentStage&,
joshualitt47bb3822014-10-07 16:43:25 -0700273 GrGLProcessor::TransformedCoordsArray* outCoords,
joshualitta5305a12014-10-10 17:47:00 -0700274 GrGLInstalledFragProc*);
joshualitt47bb3822014-10-07 16:43:25 -0700275 GrGLProgram* finalize();
276 void bindUniformLocations(GrGLuint programID);
277 bool checkLinkStatus(GrGLuint programID);
278 void resolveUniformLocations(GrGLuint programID);
joshualitt47bb3822014-10-07 16:43:25 -0700279 void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);
280 void cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs);
joshualitt30ba4362014-08-21 20:18:45 -0700281
joshualitt47bb3822014-10-07 16:43:25 -0700282 // Subclasses create different programs
283 virtual GrGLProgram* createProgram(GrGLuint programID);
284
joshualitt30ba4362014-08-21 20:18:45 -0700285 void appendUniformDecls(ShaderVisibility, SkString*) const;
286
joshualitt47bb3822014-10-07 16:43:25 -0700287 // reset is called by program creator between each processor's emit code. It increments the
288 // stage offset for variable name mangling, and also ensures verfication variables in the
289 // fragment shader are cleared.
290 void reset() {
291 this->enterStage();
292 this->addStage();
293 fFS.reset();
294 }
295 void addStage() { fStageIndex++; }
296
297 // This simple class exits the stage and then restores the stage when it goes out of scope
298 class AutoStageRestore {
joshualitt30ba4362014-08-21 20:18:45 -0700299 public:
joshualitt47bb3822014-10-07 16:43:25 -0700300 AutoStageRestore(GrGLProgramBuilder* pb)
301 : fPB(pb), fOutOfStage(pb->fOutOfStage) { pb->exitStage(); }
302 ~AutoStageRestore() { fPB->fOutOfStage = fOutOfStage; }
joshualittb0a8a372014-09-23 09:50:21 -0700303 private:
joshualitt47bb3822014-10-07 16:43:25 -0700304 GrGLProgramBuilder* fPB;
305 bool fOutOfStage;
joshualittb0a8a372014-09-23 09:50:21 -0700306 };
joshualitt47bb3822014-10-07 16:43:25 -0700307 class AutoStageAdvance {
joshualittdb0d3ca2014-10-07 12:42:26 -0700308 public:
joshualitt47bb3822014-10-07 16:43:25 -0700309 AutoStageAdvance(GrGLProgramBuilder* pb) : fPB(pb) { fPB->reset(); }
310 ~AutoStageAdvance() { fPB->exitStage(); }
joshualittdb0d3ca2014-10-07 12:42:26 -0700311 private:
joshualitt47bb3822014-10-07 16:43:25 -0700312 GrGLProgramBuilder* fPB;
313 };
314 void exitStage() { fOutOfStage = true; }
315 void enterStage() { fOutOfStage = false; }
316 int stageIndex() const { return fStageIndex; }
317
joshualitt4973d9d2014-11-08 09:24:25 -0800318 struct TransformVarying {
319 TransformVarying(const GrGLVarying& v, const char* uniName, const char* sourceCoords)
320 : fV(v), fUniName(uniName), fSourceCoords(sourceCoords) {}
321 GrGLVarying fV;
322 SkString fUniName;
323 SkString fSourceCoords;
324 };
325
326 void addCoordVarying(const char* name, GrGLVarying* v, const char* uniName,
327 const char* sourceCoords) {
328 this->addVarying(name, v);
329 fCoordVaryings.push_back(TransformVarying(*v, uniName, sourceCoords));
330 }
331
332 const char* rtAdjustment() const { return "rtAdjustment"; }
333
joshualitt47bb3822014-10-07 16:43:25 -0700334 // number of each input/output type in a single allocation block, used by many builders
335 static const int kVarsPerBlock;
336
337 BuiltinUniformHandles fUniformHandles;
338 GrGLVertexBuilder fVS;
339 GrGLGeometryBuilder fGS;
340 GrGLFragmentShaderBuilder fFS;
341 bool fOutOfStage;
342 int fStageIndex;
343
joshualitta5305a12014-10-10 17:47:00 -0700344 GrGLInstalledGeoProc* fGeometryProcessor;
345 SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
joshualitt47bb3822014-10-07 16:43:25 -0700346
347 const GrOptDrawState& fOptState;
joshualitt79f8fae2014-10-28 17:59:26 -0700348 const GrProgramDesc& fDesc;
joshualitt47bb3822014-10-07 16:43:25 -0700349 GrGpuGL* fGpu;
350 UniformInfoArray fUniforms;
joshualitt4973d9d2014-11-08 09:24:25 -0800351 SkSTArray<16, TransformVarying, true> fCoordVaryings;
joshualitt47bb3822014-10-07 16:43:25 -0700352
353 friend class GrGLShaderBuilder;
354 friend class GrGLVertexBuilder;
355 friend class GrGLFragmentShaderBuilder;
356 friend class GrGLGeometryBuilder;
357};
358
359/**
joshualitta5305a12014-10-10 17:47:00 -0700360 * The below structs represent processors installed in programs. All processors can have texture
361 * samplers, but only frag processors have coord transforms, hence the need for different structs
joshualitt47bb3822014-10-07 16:43:25 -0700362 */
joshualitta5305a12014-10-10 17:47:00 -0700363struct GrGLInstalledProc {
364 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
joshualitt47bb3822014-10-07 16:43:25 -0700365
joshualitta5305a12014-10-10 17:47:00 -0700366 struct Sampler {
367 SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
368 UniformHandle fUniform;
369 int fTextureUnit;
370 };
371 SkSTArray<4, Sampler, true> fSamplers;
372};
joshualitt47bb3822014-10-07 16:43:25 -0700373
joshualitta5305a12014-10-10 17:47:00 -0700374struct GrGLInstalledGeoProc : public GrGLInstalledProc {
375 SkAutoTDelete<GrGLGeometryProcessor> fGLProc;
376};
joshualitt47bb3822014-10-07 16:43:25 -0700377
joshualitta5305a12014-10-10 17:47:00 -0700378struct GrGLInstalledFragProc : public GrGLInstalledProc {
379 GrGLInstalledFragProc(bool useLocalCoords) : fGLProc(NULL), fLocalCoordAttrib(useLocalCoords) {}
joshualitt47bb3822014-10-07 16:43:25 -0700380 class ShaderVarHandle {
381 public:
382 bool isValid() const { return fHandle > -1; }
383 ShaderVarHandle() : fHandle(-1) {}
384 ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); }
385 int handle() const { SkASSERT(this->isValid()); return fHandle; }
386 UniformHandle convertToUniformHandle() {
387 SkASSERT(this->isValid());
388 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle);
389 }
joshualittdb0d3ca2014-10-07 12:42:26 -0700390
joshualitt47bb3822014-10-07 16:43:25 -0700391 private:
392 int fHandle;
393 };
joshualittdb0d3ca2014-10-07 12:42:26 -0700394
joshualitt47bb3822014-10-07 16:43:25 -0700395 struct Transform {
396 Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
397 ShaderVarHandle fHandle;
398 SkMatrix fCurrentValue;
399 GrSLType fType;
400 };
joshualittdb0d3ca2014-10-07 12:42:26 -0700401
joshualitta5305a12014-10-10 17:47:00 -0700402 SkAutoTDelete<GrGLFragmentProcessor> fGLProc;
403 SkSTArray<2, Transform, true> fTransforms;
404 bool fLocalCoordAttrib;
405};
joshualittdb0d3ca2014-10-07 12:42:26 -0700406
joshualitta5305a12014-10-10 17:47:00 -0700407struct GrGLInstalledFragProcs : public SkRefCnt {
408 virtual ~GrGLInstalledFragProcs();
409 SkSTArray<8, GrGLInstalledFragProc*, true> fProcs;
joshualitt30ba4362014-08-21 20:18:45 -0700410};
411
joshualitt30ba4362014-08-21 20:18:45 -0700412#endif