2 * Copyright 2014 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #ifndef GrGLProgramBuilder_DEFINED
9 #define GrGLProgramBuilder_DEFINED
11 #include "GrGLFragmentShaderBuilder.h"
12 #include "GrGLGeometryShaderBuilder.h"
13 #include "GrGLVertexShaderBuilder.h"
14 #include "../GrGLProgramDataManager.h"
15 #include "../GrGLUniformHandle.h"
16 #include "../GrGLGeometryProcessor.h"
19 * This is the base class for a series of interfaces. This base class *MUST* remain abstract with
20 * NO data members because it is used in multiple interface inheritance.
24 * GrGLFPBuilder GrGLGPBuilder
26 * GrGLProgramBuilder(internal use only)
28 class GrGLUniformBuilder {
30 enum ShaderVisibility {
31 kVertex_Visibility = 0x1,
32 kGeometry_Visibility = 0x2,
33 kFragment_Visibility = 0x4,
36 virtual ~GrGLUniformBuilder() {}
38 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
40 /** Add a uniform variable to the current program, that has visibility in one or more shaders.
41 visibility is a bitfield of ShaderVisibility values indicating from which shaders the
42 uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
43 supported at this time. The actual uniform name will be mangled. If outName is not NULL then
44 it will refer to the final uniform name after return. Use the addUniformArray variant to add
45 an array of uniforms. */
46 virtual UniformHandle addUniform(uint32_t visibility,
49 const char** outName = NULL) = 0;
50 virtual UniformHandle addUniformArray(uint32_t visibility,
54 const char** outName = NULL) = 0;
56 virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const = 0;
59 * Shortcut for getUniformVariable(u).c_str()
61 virtual const char* getUniformCStr(UniformHandle u) const = 0;
63 virtual const GrGLContextInfo& ctxInfo() const = 0;
65 virtual GrGpuGL* gpu() const = 0;
68 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
72 // TODO move this into GrGLGPBuilder and move them both out of this file
75 bool vsVarying() const { return kVertToFrag_Varying == fVarying ||
76 kVertToGeo_Varying == fVarying; }
77 bool fsVarying() const { return kVertToFrag_Varying == fVarying ||
78 kGeoToFrag_Varying == fVarying; }
79 const char* vsOut() const { return fVsOut; }
80 const char* gsIn() const { return fGsIn; }
81 const char* gsOut() const { return fGsOut; }
82 const char* fsIn() const { return fFsIn; }
91 GrGLVarying(GrSLType type, Varying varying)
92 : fVarying(varying), fType(type), fVsOut(NULL), fGsIn(NULL), fGsOut(NULL),
104 friend class GrGLVertexBuilder;
105 friend class GrGLGeometryBuilder;
106 friend class GrGLFragmentShaderBuilder;
109 struct GrGLVertToFrag : public GrGLVarying {
110 GrGLVertToFrag(GrSLType type)
111 : GrGLVarying(type, kVertToFrag_Varying) {}
114 struct GrGLVertToGeo : public GrGLVarying {
115 GrGLVertToGeo(GrSLType type)
116 : GrGLVarying(type, kVertToGeo_Varying) {}
119 struct GrGLGeoToFrag : public GrGLVarying {
120 GrGLGeoToFrag(GrSLType type)
121 : GrGLVarying(type, kGeoToFrag_Varying) {}
124 /* a specialization of the above for GPs. Lets the user add uniforms, varyings, and VS / FS code */
125 class GrGLGPBuilder : public virtual GrGLUniformBuilder {
127 virtual void addVarying(const char* name,
129 GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision) = 0;
131 // TODO rename getFragmentBuilder
132 virtual GrGLGPFragmentBuilder* getFragmentShaderBuilder() = 0;
133 virtual GrGLVertexBuilder* getVertexShaderBuilder() = 0;
136 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
140 /* a specializations for FPs. Lets the user add uniforms and FS code */
141 class GrGLFPBuilder : public virtual GrGLUniformBuilder {
143 virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() = 0;
146 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
150 struct GrGLInstalledProc;
151 struct GrGLInstalledGeoProc;
152 struct GrGLInstalledFragProc;
153 struct GrGLInstalledFragProcs;
156 * Please note - no diamond problems because of virtual inheritance. Also, both base classes
157 * are pure virtual with no data members. This is the base class for program building.
158 * Subclasses are nearly identical but each has their own way of emitting transforms. State for
159 * each of the elements of the shader pipeline, ie vertex, fragment, geometry, etc, lives in those
160 * respective builders
162 class GrGLProgramBuilder : public GrGLGPBuilder,
163 public GrGLFPBuilder {
165 /** Generates a shader program.
167 * The program implements what is specified in the stages given as input.
168 * After successful generation, the builder result objects are available
170 * @return true if generation was successful.
172 static GrGLProgram* CreateProgram(const GrOptDrawState&, GrGpu::DrawType, GrGpuGL*);
174 virtual UniformHandle addUniform(uint32_t visibility,
177 const char** outName = NULL) SK_OVERRIDE {
178 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
180 virtual UniformHandle addUniformArray(uint32_t visibility,
184 const char** outName = NULL) SK_OVERRIDE;
186 virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const SK_OVERRIDE {
187 return fUniforms[u.toShaderBuilderIndex()].fVariable;
190 virtual const char* getUniformCStr(UniformHandle u) const SK_OVERRIDE {
191 return this->getUniformVariable(u).c_str();
194 virtual const GrGLContextInfo& ctxInfo() const SK_OVERRIDE;
196 virtual GrGpuGL* gpu() const SK_OVERRIDE { return fGpu; }
198 virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() SK_OVERRIDE { return &fFS; }
199 virtual GrGLVertexBuilder* getVertexShaderBuilder() SK_OVERRIDE { return &fVS; }
201 virtual void addVarying(
204 GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision) SK_OVERRIDE;
206 // Handles for program uniforms (other than per-effect uniforms)
207 struct BuiltinUniformHandles {
208 UniformHandle fViewMatrixUni;
209 UniformHandle fRTAdjustmentUni;
210 UniformHandle fColorUni;
211 UniformHandle fCoverageUni;
213 // We use the render target height to provide a y-down frag coord when specifying
214 // origin_upper_left is not supported.
215 UniformHandle fRTHeightUni;
217 // Uniforms for computing texture coords to do the dst-copy lookup
218 UniformHandle fDstCopyTopLeftUni;
219 UniformHandle fDstCopyScaleUni;
220 UniformHandle fDstCopySamplerUni;
224 typedef GrProgramDesc::ProcKeyProvider ProcKeyProvider;
225 typedef GrGLProgramDataManager::UniformInfo UniformInfo;
226 typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
228 static GrGLProgramBuilder* CreateProgramBuilder(const GrOptDrawState&,
230 bool hasGeometryProcessor,
233 GrGLProgramBuilder(GrGpuGL*, const GrOptDrawState&);
235 const GrOptDrawState& optState() const { return fOptState; }
236 const GrProgramDesc& desc() const { return fDesc; }
237 const GrProgramDesc::KeyHeader& header() const { return fDesc.header(); }
239 // Generates a name for a variable. The generated string will be name prefixed by the prefix
240 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
241 // generating stage code.
242 void nameVariable(SkString* out, char prefix, const char* name);
243 void setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor, GrGLSLExpr1* inputCoverage);
244 void emitAndInstallProcs(const GrOptDrawState& optState,
245 GrGLSLExpr4* inputColor,
246 GrGLSLExpr4* inputCoverage);
247 void emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut);
248 template <class Proc>
249 void emitAndInstallProc(const Proc&,
251 const ProcKeyProvider&,
252 const GrGLSLExpr4& input,
253 GrGLSLExpr4* output);
255 // these emit functions help to keep the createAndEmitProcessors template general
256 void emitAndInstallProc(const GrFragmentStage&,
257 const GrProcessorKey&,
258 const char* outColor,
259 const char* inColor);
260 void emitAndInstallProc(const GrGeometryProcessor&,
261 const GrProcessorKey&,
262 const char* outColor,
263 const char* inColor);
264 void verify(const GrGeometryProcessor&);
265 void verify(const GrFragmentProcessor&);
266 void emitSamplers(const GrProcessor&,
267 GrGLProcessor::TextureSamplerArray* outSamplers,
270 // each specific program builder has a distinct transform and must override this function
271 virtual void emitTransforms(const GrFragmentStage&,
272 GrGLProcessor::TransformedCoordsArray* outCoords,
273 GrGLInstalledFragProc*);
274 GrGLProgram* finalize();
275 void bindUniformLocations(GrGLuint programID);
276 bool checkLinkStatus(GrGLuint programID);
277 void resolveUniformLocations(GrGLuint programID);
278 void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);
279 void cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs);
281 // Subclasses create different programs
282 virtual GrGLProgram* createProgram(GrGLuint programID);
284 void appendUniformDecls(ShaderVisibility, SkString*) const;
286 // reset is called by program creator between each processor's emit code. It increments the
287 // stage offset for variable name mangling, and also ensures verfication variables in the
288 // fragment shader are cleared.
294 void addStage() { fStageIndex++; }
296 // This simple class exits the stage and then restores the stage when it goes out of scope
297 class AutoStageRestore {
299 AutoStageRestore(GrGLProgramBuilder* pb)
300 : fPB(pb), fOutOfStage(pb->fOutOfStage) { pb->exitStage(); }
301 ~AutoStageRestore() { fPB->fOutOfStage = fOutOfStage; }
303 GrGLProgramBuilder* fPB;
306 class AutoStageAdvance {
308 AutoStageAdvance(GrGLProgramBuilder* pb) : fPB(pb) { fPB->reset(); }
309 ~AutoStageAdvance() { fPB->exitStage(); }
311 GrGLProgramBuilder* fPB;
313 void exitStage() { fOutOfStage = true; }
314 void enterStage() { fOutOfStage = false; }
315 int stageIndex() const { return fStageIndex; }
317 // number of each input/output type in a single allocation block, used by many builders
318 static const int kVarsPerBlock;
320 BuiltinUniformHandles fUniformHandles;
321 GrGLVertexBuilder fVS;
322 GrGLGeometryBuilder fGS;
323 GrGLFragmentShaderBuilder fFS;
327 GrGLInstalledGeoProc* fGeometryProcessor;
328 SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
330 const GrOptDrawState& fOptState;
331 const GrProgramDesc& fDesc;
333 UniformInfoArray fUniforms;
335 friend class GrGLShaderBuilder;
336 friend class GrGLVertexBuilder;
337 friend class GrGLFragmentShaderBuilder;
338 friend class GrGLGeometryBuilder;
342 * The below structs represent processors installed in programs. All processors can have texture
343 * samplers, but only frag processors have coord transforms, hence the need for different structs
345 struct GrGLInstalledProc {
346 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
349 SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
350 UniformHandle fUniform;
353 SkSTArray<4, Sampler, true> fSamplers;
356 struct GrGLInstalledGeoProc : public GrGLInstalledProc {
357 SkAutoTDelete<GrGLGeometryProcessor> fGLProc;
360 struct GrGLInstalledFragProc : public GrGLInstalledProc {
361 GrGLInstalledFragProc(bool useLocalCoords) : fGLProc(NULL), fLocalCoordAttrib(useLocalCoords) {}
362 class ShaderVarHandle {
364 bool isValid() const { return fHandle > -1; }
365 ShaderVarHandle() : fHandle(-1) {}
366 ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); }
367 int handle() const { SkASSERT(this->isValid()); return fHandle; }
368 UniformHandle convertToUniformHandle() {
369 SkASSERT(this->isValid());
370 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle);
378 Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
379 ShaderVarHandle fHandle;
380 SkMatrix fCurrentValue;
384 SkAutoTDelete<GrGLFragmentProcessor> fGLProc;
385 SkSTArray<2, Transform, true> fTransforms;
386 bool fLocalCoordAttrib;
389 struct GrGLInstalledFragProcs : public SkRefCnt {
390 virtual ~GrGLInstalledFragProcs();
391 SkSTArray<8, GrGLInstalledFragProc*, true> fProcs;