blob: 7fa8ba266c56ad079c85a60a347ee447a4784e2e [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
11#include "GrAllocator.h"
joshualittb0a8a372014-09-23 09:50:21 -070012#include "GrBackendProcessorFactory.h"
joshualitt30ba4362014-08-21 20:18:45 -070013#include "GrColor.h"
joshualittb0a8a372014-09-23 09:50:21 -070014#include "GrProcessor.h"
joshualitt30ba4362014-08-21 20:18:45 -070015#include "GrGLFragmentShaderBuilder.h"
16#include "GrGLGeometryShaderBuilder.h"
17#include "GrGLVertexShaderBuilder.h"
18#include "SkTypes.h"
joshualittb0a8a372014-09-23 09:50:21 -070019#include "gl/GrGLProcessor.h"
joshualitt30ba4362014-08-21 20:18:45 -070020#include "gl/GrGLProgramDesc.h"
21#include "gl/GrGLProgramEffects.h"
22#include "gl/GrGLSL.h"
23#include "gl/GrGLProgramDataManager.h"
24
25#include <stdarg.h>
26
27class GrGLContextInfo;
joshualittb0a8a372014-09-23 09:50:21 -070028class GrProcessorStage;
joshualitt30ba4362014-08-21 20:18:45 -070029class GrGLProgramDesc;
30
31/**
32 Contains all the incremental state of a shader as it is being built,as well as helpers to
33 manipulate that state.
34*/
35class GrGLProgramBuilder {
36public:
37 enum ShaderVisibility {
38 kVertex_Visibility = 0x1,
39 kGeometry_Visibility = 0x2,
40 kFragment_Visibility = 0x4,
41 };
42
43 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
kkinnunenec56e452014-08-25 22:21:16 -070044 typedef GrGLProgramDataManager::VaryingHandle VaryingHandle;
joshualitt30ba4362014-08-21 20:18:45 -070045
46 // Handles for program uniforms (other than per-effect uniforms)
47 struct BuiltinUniformHandles {
48 UniformHandle fViewMatrixUni;
49 UniformHandle fRTAdjustmentUni;
50 UniformHandle fColorUni;
51 UniformHandle fCoverageUni;
52
53 // We use the render target height to provide a y-down frag coord when specifying
54 // origin_upper_left is not supported.
55 UniformHandle fRTHeightUni;
56
57 // Uniforms for computing texture coords to do the dst-copy lookup
58 UniformHandle fDstCopyTopLeftUni;
59 UniformHandle fDstCopyScaleUni;
60 UniformHandle fDstCopySamplerUni;
61 };
62
63 struct UniformInfo {
64 GrGLShaderVar fVariable;
65 uint32_t fVisibility;
66 GrGLint fLocation;
67 };
68
69 // This uses an allocator rather than array so that the GrGLShaderVars don't move in memory
70 // after they are inserted. Users of GrGLShaderBuilder get refs to the vars and ptrs to their
71 // name strings. Otherwise, we'd have to hand out copies.
72 typedef GrTAllocator<UniformInfo> UniformInfoArray;
73
kkinnunenec56e452014-08-25 22:21:16 -070074 struct SeparableVaryingInfo {
75 GrGLShaderVar fVariable;
76 GrGLint fLocation;
77 };
78
79 typedef GrTAllocator<SeparableVaryingInfo> SeparableVaryingInfoArray;
80
joshualitt30ba4362014-08-21 20:18:45 -070081 /** Generates a shader program.
82 *
83 * The program implements what is specified in the stages given as input.
84 * After successful generation, the builder result objects are available
85 * to be used.
86 * @return true if generation was successful.
87 */
joshualittbd769d02014-09-04 08:56:46 -070088
joshualittb0a8a372014-09-23 09:50:21 -070089 bool genProgram(const GrGeometryStage* inGeometryProcessor,
90 const GrFragmentStage* inColorStages[],
91 const GrFragmentStage* inCoverageStages[]);
joshualitt30ba4362014-08-21 20:18:45 -070092
joshualittbd769d02014-09-04 08:56:46 -070093 GrGLProgramEffects* getGeometryProcessor() const {
94 SkASSERT(fProgramID); return fGeometryProcessor.get();
95 }
joshualitt30ba4362014-08-21 20:18:45 -070096 GrGLProgramEffects* getColorEffects() const { SkASSERT(fProgramID); return fColorEffects.get(); }
97 GrGLProgramEffects* getCoverageEffects() const { SkASSERT(fProgramID); return fCoverageEffects.get(); }
98 const BuiltinUniformHandles& getBuiltinUniformHandles() const {
99 SkASSERT(fProgramID);
100 return fUniformHandles;
101 }
102 GrGLuint getProgramID() const { SkASSERT(fProgramID); return fProgramID; }
103 bool hasVertexShader() const { SkASSERT(fProgramID); return !fFragOnly; }
104 int getTexCoordSetCount() const { SkASSERT(fProgramID); return fTexCoordSetCnt; }
105 const UniformInfoArray& getUniformInfos() const { return fUniforms; }
kkinnunenec56e452014-08-25 22:21:16 -0700106 const SeparableVaryingInfoArray& getSeparableVaryingInfos() const {
107 return fSeparableVaryingInfos;
108 }
joshualitt30ba4362014-08-21 20:18:45 -0700109
110 virtual ~GrGLProgramBuilder() {}
111
112 /** Add a uniform variable to the current program, that has visibility in one or more shaders.
113 visibility is a bitfield of ShaderVisibility values indicating from which shaders the
114 uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
115 supported at this time. The actual uniform name will be mangled. If outName is not NULL then
116 it will refer to the final uniform name after return. Use the addUniformArray variant to add
117 an array of uniforms. */
118 GrGLProgramDataManager::UniformHandle addUniform(uint32_t visibility,
119 GrSLType type,
120 const char* name,
121 const char** outName = NULL) {
122 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
123 }
124 GrGLProgramDataManager::UniformHandle addUniformArray(uint32_t visibility,
125 GrSLType type,
126 const char* name,
127 int arrayCount,
128 const char** outName = NULL);
129
130 const GrGLShaderVar& getUniformVariable(GrGLProgramDataManager::UniformHandle u) const {
131 return fUniforms[u.toShaderBuilderIndex()].fVariable;
132 }
133
134 /**
135 * Shortcut for getUniformVariable(u).c_str()
136 */
137 const char* getUniformCStr(GrGLProgramDataManager::UniformHandle u) const {
138 return this->getUniformVariable(u).c_str();
139 }
140
141 const GrGLContextInfo& ctxInfo() const;
142
143 GrGLFragmentShaderBuilder* getFragmentShaderBuilder() { return &fFS; }
kkinnunenec56e452014-08-25 22:21:16 -0700144 GrGpuGL* gpu() const { return fGpu; }
joshualitt30ba4362014-08-21 20:18:45 -0700145
146protected:
147 typedef GrTAllocator<GrGLShaderVar> VarArray;
egdaniel307796b2014-10-06 12:13:54 -0700148 GrGLProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
joshualitt30ba4362014-08-21 20:18:45 -0700149
egdaniel307796b2014-10-06 12:13:54 -0700150 const GrOptDrawState& optState() const { return fOptState; }
joshualitt30ba4362014-08-21 20:18:45 -0700151 const GrGLProgramDesc& desc() const { return fDesc; }
152
153 // Helper for emitEffects().
joshualittb0a8a372014-09-23 09:50:21 -0700154 void createAndEmitEffects(const GrFragmentStage* effectStages[],
joshualitt30ba4362014-08-21 20:18:45 -0700155 int effectCnt,
156 const GrGLProgramDesc::EffectKeyProvider&,
157 GrGLSLExpr4* inOutFSColor);
158
joshualitt23e280d2014-09-18 12:26:38 -0700159 /*
160 * A helper function called to emit the geometry processor as well as individual coverage
161 * and color stages. this will call into subclasses emit effect
162 */
joshualittb0a8a372014-09-23 09:50:21 -0700163 void emitEffect(const GrProcessorStage& effectStage,
joshualitt23e280d2014-09-18 12:26:38 -0700164 int effectIndex,
165 const GrGLProgramDesc::EffectKeyProvider& keyProvider,
166 GrGLSLExpr4* inColor,
167 GrGLSLExpr4* outColor);
168
169 /**
170 * Helper for emitEffect() in subclasses. Emits uniforms for an effect's texture accesses and
171 * appends the necessary data to the TextureSamplerArray* object so effects can add texture
172 * lookups to their code. This method is only meant to be called during the construction phase.
173 */
joshualittb0a8a372014-09-23 09:50:21 -0700174 void emitSamplers(const GrProcessor& effect,
175 GrGLProcessor::TextureSamplerArray* outSamplers);
joshualitt23e280d2014-09-18 12:26:38 -0700176
joshualitt30ba4362014-08-21 20:18:45 -0700177 // Generates a name for a variable. The generated string will be name prefixed by the prefix
178 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
179 // generating stage code.
180 void nameVariable(SkString* out, char prefix, const char* name);
181
182 virtual bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
183
184 virtual void bindProgramLocations(GrGLuint programId);
185 void resolveProgramLocations(GrGLuint programId);
186
187 void appendDecls(const VarArray&, SkString*) const;
188 void appendUniformDecls(ShaderVisibility, SkString*) const;
189
joshualitt30ba4362014-08-21 20:18:45 -0700190 class CodeStage : SkNoncopyable {
191 public:
192 CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {}
193
194 bool inStageCode() const {
195 this->validate();
bsalomon49f085d2014-09-05 13:34:00 -0700196 return SkToBool(fEffectStage);
joshualitt30ba4362014-08-21 20:18:45 -0700197 }
198
joshualittb0a8a372014-09-23 09:50:21 -0700199 const GrProcessorStage* effectStage() const {
joshualitt30ba4362014-08-21 20:18:45 -0700200 this->validate();
201 return fEffectStage;
202 }
203
204 int stageIndex() const {
205 this->validate();
206 return fCurrentIndex;
207 }
208
209 class AutoStageRestore : SkNoncopyable {
210 public:
joshualittb0a8a372014-09-23 09:50:21 -0700211 AutoStageRestore(CodeStage* codeStage, const GrProcessorStage* newStage) {
bsalomon49f085d2014-09-05 13:34:00 -0700212 SkASSERT(codeStage);
joshualitt30ba4362014-08-21 20:18:45 -0700213 fSavedIndex = codeStage->fCurrentIndex;
214 fSavedEffectStage = codeStage->fEffectStage;
215
216 if (NULL == newStage) {
217 codeStage->fCurrentIndex = -1;
218 } else {
219 codeStage->fCurrentIndex = codeStage->fNextIndex++;
220 }
221 codeStage->fEffectStage = newStage;
222
223 fCodeStage = codeStage;
224 }
225 ~AutoStageRestore() {
226 fCodeStage->fCurrentIndex = fSavedIndex;
227 fCodeStage->fEffectStage = fSavedEffectStage;
228 }
229 private:
230 CodeStage* fCodeStage;
231 int fSavedIndex;
joshualittb0a8a372014-09-23 09:50:21 -0700232 const GrProcessorStage* fSavedEffectStage;
joshualitt30ba4362014-08-21 20:18:45 -0700233 };
234 private:
235 void validate() const { SkASSERT((NULL == fEffectStage) == (-1 == fCurrentIndex)); }
236 int fNextIndex;
237 int fCurrentIndex;
joshualittb0a8a372014-09-23 09:50:21 -0700238 const GrProcessorStage* fEffectStage;
joshualitt23e280d2014-09-18 12:26:38 -0700239 };
240
joshualittb0a8a372014-09-23 09:50:21 -0700241 class GrGLProcessorEmitterInterface {
242 public:
243 virtual ~GrGLProcessorEmitterInterface() {}
244 virtual GrGLProcessor* createGLInstance() = 0;
245 virtual void emit(const GrProcessorKey& key,
246 const char* outColor,
247 const char* inColor,
248 const GrGLProcessor::TransformedCoordsArray& coords,
249 const GrGLProcessor::TextureSamplerArray& samplers) = 0;
250 };
251
252 class GrGLFragmentProcessorEmitter : public GrGLProcessorEmitterInterface {
253 public:
254 GrGLFragmentProcessorEmitter(GrGLProgramBuilder* builder)
255 : fBuilder(builder)
256 , fFragmentProcessor(NULL)
257 , fGLFragmentProcessor(NULL) {}
258 virtual ~GrGLFragmentProcessorEmitter() {}
259 void set(const GrFragmentProcessor* fp) {
260 SkASSERT(NULL == fFragmentProcessor);
261 fFragmentProcessor = fp;
262 }
263 virtual GrGLProcessor* createGLInstance() {
264 SkASSERT(fFragmentProcessor);
265 SkASSERT(NULL == fGLFragmentProcessor);
266 fGLFragmentProcessor =
267 fFragmentProcessor->getFactory().createGLInstance(*fFragmentProcessor);
268 return fGLFragmentProcessor;
269 }
270 virtual void emit(const GrProcessorKey& key,
271 const char* outColor,
272 const char* inColor,
273 const GrGLProcessor::TransformedCoordsArray& coords,
274 const GrGLProcessor::TextureSamplerArray& samplers) {
275 SkASSERT(fFragmentProcessor);
276 SkASSERT(fGLFragmentProcessor);
277 fGLFragmentProcessor->emitCode(fBuilder, *fFragmentProcessor, key, outColor, inColor,
278 coords, samplers);
279 // this will not leak because it hasa already been used by createGLInstance
280 fGLFragmentProcessor = NULL;
281 fFragmentProcessor = NULL;
282 }
283 private:
284 GrGLProgramBuilder* fBuilder;
285 const GrFragmentProcessor* fFragmentProcessor;
286 GrGLFragmentProcessor* fGLFragmentProcessor;
287 };
288
289 GrGLProcessorEmitterInterface* fEffectEmitter;
joshualitt23e280d2014-09-18 12:26:38 -0700290 CodeStage fCodeStage;
291 SkAutoTUnref<GrGLProgramEffects> fGeometryProcessor;
292 SkAutoTUnref<GrGLProgramEffects> fColorEffects;
293 SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
294 BuiltinUniformHandles fUniformHandles;
295 bool fFragOnly;
296 int fTexCoordSetCnt;
297 GrGLuint fProgramID;
298 GrGLFragmentShaderBuilder fFS;
299 SeparableVaryingInfoArray fSeparableVaryingInfos;
joshualitt249af152014-09-15 11:41:13 -0700300
joshualittbd769d02014-09-04 08:56:46 -0700301private:
joshualittb0a8a372014-09-23 09:50:21 -0700302 virtual void createAndEmitEffects(const GrGeometryStage* geometryProcessor,
303 const GrFragmentStage* colorStages[],
304 const GrFragmentStage* coverageStages[],
joshualitt23e280d2014-09-18 12:26:38 -0700305 GrGLSLExpr4* inputColor,
306 GrGLSLExpr4* inputCoverage) = 0;
307 /*
308 * Subclasses override emitEffect below to emit data and code for a specific single effect
joshualitt30ba4362014-08-21 20:18:45 -0700309 */
joshualittb0a8a372014-09-23 09:50:21 -0700310 virtual void emitEffect(const GrProcessorStage&,
311 const GrProcessorKey&,
joshualitt23e280d2014-09-18 12:26:38 -0700312 const char* outColor,
313 const char* inColor,
314 int stageIndex) = 0;
joshualittbd769d02014-09-04 08:56:46 -0700315
316 /*
joshualitt23e280d2014-09-18 12:26:38 -0700317 * Because we have fragment only builders, and those builders need to implement a subclass
318 * of program effects, we have to have base classes overload the program effects here
joshualittbd769d02014-09-04 08:56:46 -0700319 */
joshualitt23e280d2014-09-18 12:26:38 -0700320 virtual GrGLProgramEffects* getProgramEffects() = 0;
joshualitt30ba4362014-08-21 20:18:45 -0700321
322 /**
323 * Compiles all the shaders, links them into a program, and writes the program id to the output
324 * struct.
325 **/
326 bool finish();
327
joshualittb0a8a372014-09-23 09:50:21 -0700328 GrGLFragmentProcessorEmitter fGrProcessorEmitter;
329
egdaniel307796b2014-10-06 12:13:54 -0700330 const GrOptDrawState& fOptState;
joshualitt30ba4362014-08-21 20:18:45 -0700331 const GrGLProgramDesc& fDesc;
332 GrGpuGL* fGpu;
333 UniformInfoArray fUniforms;
334
335 friend class GrGLShaderBuilder;
336 friend class GrGLVertexShaderBuilder;
337 friend class GrGLFragmentShaderBuilder;
338 friend class GrGLGeometryShaderBuilder;
339};
340
joshualitt30ba4362014-08-21 20:18:45 -0700341#endif