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
joshualittdb0d3ca2014-10-07 12:42:26 -070011#include "GrAllocator.h"
12#include "GrBackendProcessorFactory.h"
13#include "GrColor.h"
14#include "GrProcessor.h"
joshualitt30ba4362014-08-21 20:18:45 -070015#include "GrGLFragmentShaderBuilder.h"
16#include "GrGLGeometryShaderBuilder.h"
17#include "GrGLVertexShaderBuilder.h"
joshualittdb0d3ca2014-10-07 12:42:26 -070018#include "SkTypes.h"
19#include "gl/GrGLProcessor.h"
20#include "gl/GrGLProgramDesc.h"
21#include "gl/GrGLProgramEffects.h"
22#include "gl/GrGLSL.h"
23#include "gl/GrGLProgramDataManager.h"
joshualitt30ba4362014-08-21 20:18:45 -070024
joshualittdb0d3ca2014-10-07 12:42:26 -070025#include <stdarg.h>
joshualitt30ba4362014-08-21 20:18:45 -070026
joshualittdb0d3ca2014-10-07 12:42:26 -070027class GrGLContextInfo;
28class GrProcessorStage;
29class 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 {
joshualitt30ba4362014-08-21 20:18:45 -070036public:
37 enum ShaderVisibility {
38 kVertex_Visibility = 0x1,
39 kGeometry_Visibility = 0x2,
40 kFragment_Visibility = 0x4,
41 };
42
43 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
joshualittdb0d3ca2014-10-07 12:42:26 -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
joshualittdb0d3ca2014-10-07 12:42:26 -070063 struct UniformInfo {
64 GrGLShaderVar fVariable;
65 uint32_t fVisibility;
66 GrGLint fLocation;
67 };
joshualittfe1233c2014-10-07 12:16:35 -070068
joshualittdb0d3ca2014-10-07 12:42:26 -070069 // 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
74 struct SeparableVaryingInfo {
75 GrGLShaderVar fVariable;
76 GrGLint fLocation;
77 };
78
79 typedef GrTAllocator<SeparableVaryingInfo> SeparableVaryingInfoArray;
80
81 /** 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 */
88
89 bool genProgram(const GrGeometryStage* inGeometryProcessor,
90 const GrFragmentStage* inColorStages[],
91 const GrFragmentStage* inCoverageStages[]);
92
93 GrGLProgramEffects* getGeometryProcessor() const {
94 SkASSERT(fProgramID); return fGeometryProcessor.get();
95 }
96 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; }
106 const SeparableVaryingInfoArray& getSeparableVaryingInfos() const {
107 return fSeparableVaryingInfos;
108 }
109
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; }
144 GrGpuGL* gpu() const { return fGpu; }
145
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; }
joshualittdb0d3ca2014-10-07 12:42:26 -0700152
153 // Helper for emitEffects().
154 void createAndEmitEffects(const GrFragmentStage* effectStages[],
155 int effectCnt,
156 const GrGLProgramDesc::EffectKeyProvider&,
157 GrGLSLExpr4* inOutFSColor);
158
159 /*
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 */
163 void emitEffect(const GrProcessorStage& effectStage,
164 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 */
174 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
joshualittdb0d3ca2014-10-07 12:42:26 -0700182 virtual bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
joshualitt30ba4362014-08-21 20:18:45 -0700183
joshualittdb0d3ca2014-10-07 12:42:26 -0700184 virtual void bindProgramLocations(GrGLuint programId);
185 void resolveProgramLocations(GrGLuint programId);
joshualitt30ba4362014-08-21 20:18:45 -0700186
joshualittdb0d3ca2014-10-07 12:42:26 -0700187 void appendDecls(const VarArray&, SkString*) const;
joshualitt30ba4362014-08-21 20:18:45 -0700188 void appendUniformDecls(ShaderVisibility, SkString*) const;
189
joshualittdb0d3ca2014-10-07 12:42:26 -0700190 class CodeStage : SkNoncopyable {
joshualitt30ba4362014-08-21 20:18:45 -0700191 public:
joshualittdb0d3ca2014-10-07 12:42:26 -0700192 CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {}
joshualittfe1233c2014-10-07 12:16:35 -0700193
joshualittdb0d3ca2014-10-07 12:42:26 -0700194 bool inStageCode() const {
195 this->validate();
196 return SkToBool(fEffectStage);
joshualittb0a8a372014-09-23 09:50:21 -0700197 }
joshualittfe1233c2014-10-07 12:16:35 -0700198
joshualittdb0d3ca2014-10-07 12:42:26 -0700199 const GrProcessorStage* effectStage() const {
200 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:
211 AutoStageRestore(CodeStage* codeStage, const GrProcessorStage* newStage) {
212 SkASSERT(codeStage);
213 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;
232 const GrProcessorStage* fSavedEffectStage;
233 };
joshualittb0a8a372014-09-23 09:50:21 -0700234 private:
joshualittdb0d3ca2014-10-07 12:42:26 -0700235 void validate() const { SkASSERT((NULL == fEffectStage) == (-1 == fCurrentIndex)); }
236 int fNextIndex;
237 int fCurrentIndex;
238 const GrProcessorStage* fEffectStage;
joshualittb0a8a372014-09-23 09:50:21 -0700239 };
240
joshualittdb0d3ca2014-10-07 12:42:26 -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;
joshualittfe1233c2014-10-07 12:16:35 -0700250 };
joshualitt249af152014-09-15 11:41:13 -0700251
joshualittdb0d3ca2014-10-07 12:42:26 -0700252 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 };
joshualittbd769d02014-09-04 08:56:46 -0700288
joshualittdb0d3ca2014-10-07 12:42:26 -0700289 GrGLProcessorEmitterInterface* fEffectEmitter;
290 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;
300
301private:
302 virtual void createAndEmitEffects(const GrGeometryStage* geometryProcessor,
303 const GrFragmentStage* colorStages[],
304 const GrFragmentStage* coverageStages[],
305 GrGLSLExpr4* inputColor,
306 GrGLSLExpr4* inputCoverage) = 0;
307 /*
308 * Subclasses override emitEffect below to emit data and code for a specific single effect
309 */
310 virtual void emitEffect(const GrProcessorStage&,
311 const GrProcessorKey&,
312 const char* outColor,
313 const char* inColor,
314 int stageIndex) = 0;
315
316 /*
317 * 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
319 */
320 virtual GrGLProgramEffects* getProgramEffects() = 0;
321
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
328 GrGLFragmentProcessorEmitter fGrProcessorEmitter;
329
330 const GrOptDrawState& fOptState;
331 const GrGLProgramDesc& fDesc;
332 GrGpuGL* fGpu;
333 UniformInfoArray fUniforms;
joshualitt30ba4362014-08-21 20:18:45 -0700334
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