Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(86)

Side by Side Diff: src/gpu/gl/builders/GrGLProgramBuilder.cpp

Issue 491673002: Initial refactor of shaderbuilder (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Rebase Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
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 #include "gl/GrGLProgram.h"
9 #include "gl/GrGLSLPrettyPrint.h"
10 #include "gl/GrGLUniformHandle.h"
11 #include "GrCoordTransform.h"
12 #include "GrDrawEffect.h"
13 #include "../GrGpuGL.h"
14 #include "GrGLFragmentShaderBuilder.h"
15 #include "GrGLProgramBuilder.h"
16 #include "GrTexture.h"
17 #include "GrGLVertexShaderBuilder.h"
18 #include "SkRTConf.h"
19 #include "SkTraceEvent.h"
20
21 namespace {
22 #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
23 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
24
25 // number of each input/output type in a single allocation block
26 static const int kVarsPerBlock = 8;
27
28 // ES2 FS only guarantees mediump and lowp support
29 static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar: :kMedium_Precision;
30 }
31
32 //////////////////////////////////////////////////////////////////////////////// ///////////////////
33
34 bool GrGLProgramBuilder::genProgram(const GrEffectStage* colorStages[],
35 const GrEffectStage* coverageStages[]) {
36 const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader();
37
38 fFS.emitCodeBeforeEffects();
39
40 ///////////////////////////////////////////////////////////////////////////
41 // get the initial color and coverage to feed into the first effect in each effect chain
42
43 GrGLSLExpr4 inputColor;
44 GrGLSLExpr4 inputCoverage;
45
46 if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) {
47 const char* name;
48 fUniformHandles.fColorUni =
49 this->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec4f_Gr SLType, "Color",
50 &name);
51 inputColor = GrGLSLExpr4(name);
52 }
53
54 if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
55 const char* name;
56 fUniformHandles.fCoverageUni =
57 this->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec4f_Gr SLType, "Coverage",
58 &name);
59 inputCoverage = GrGLSLExpr4(name);
60 } else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fCoverageInput) {
61 inputCoverage = GrGLSLExpr4(1);
62 }
63
64 this->emitCodeBeforeEffects(&inputColor, &inputCoverage);
65
66 ///////////////////////////////////////////////////////////////////////////
67 // emit the per-effect code for both color and coverage effects
68
69 GrGLProgramDesc::EffectKeyProvider colorKeyProvider(
70 &this->desc(), GrGLProgramDesc::EffectKeyProvider::kColor_EffectType);
71 fColorEffects.reset(this->createAndEmitEffects(colorStages,
72 this->desc().numColorEffects( ),
73 colorKeyProvider,
74 &inputColor));
75
76 GrGLProgramDesc::EffectKeyProvider coverageKeyProvider(
77 &this->desc(), GrGLProgramDesc::EffectKeyProvider::kCoverage_EffectType) ;
78 fCoverageEffects.reset(this->createAndEmitEffects(coverageStages,
79 this->desc().numCoverageEf fects(),
80 coverageKeyProvider,
81 &inputCoverage));
82
83 this->emitCodeAfterEffects();
84
85 fFS.emitCodeAfterEffects(inputColor, inputCoverage);
86
87 if (!this->finish()) {
88 return false;
89 }
90
91 return true;
92 }
93
94 //////////////////////////////////////////////////////////////////////////////
95
96 GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu,
97 const GrGLProgramDesc& desc)
98 : fFragOnly(!desc.getHeader().fHasVertexCode && gpu->shouldUseFixedFunctionT exturing())
99 , fTexCoordSetCnt(0)
100 , fProgramID(0)
101 , fFS(this, desc)
102 , fDesc(desc)
103 , fGpu(gpu)
104 , fUniforms(kVarsPerBlock) {
105 }
106
107 void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* na me) {
108 if ('\0' == prefix) {
109 *out = name;
110 } else {
111 out->printf("%c%s", prefix, name);
112 }
113 if (fCodeStage.inStageCode()) {
114 if (out->endsWith('_')) {
115 // Names containing "__" are reserved.
116 out->append("x");
117 }
118 out->appendf("_Stage%d", fCodeStage.stageIndex());
119 }
120 }
121
122 GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(uint32 _t visibility,
123 GrSLTyp e type,
124 const c har* name,
125 int cou nt,
126 const c har** outName) {
127 SkASSERT(name && strlen(name));
128 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFr agment_Visibility);
129 SkASSERT(0 == (~kVisibilityMask & visibility));
130 SkASSERT(0 != visibility);
131
132 UniformInfo& uni = fUniforms.push_back();
133 uni.fVariable.setType(type);
134 uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
135 this->nameVariable(uni.fVariable.accessName(), 'u', name);
136 uni.fVariable.setArrayCount(count);
137 uni.fVisibility = visibility;
138
139 // If it is visible in both the VS and FS, the precision must match.
140 // We declare a default FS precision, but not a default VS. So set the var
141 // to use the default FS precision.
142 if ((kVertex_Visibility | kFragment_Visibility) == visibility) {
143 // the fragment and vertex precisions must match
144 uni.fVariable.setPrecision(kDefaultFragmentPrecision);
145 }
146
147 if (NULL != outName) {
148 *outName = uni.fVariable.c_str();
149 }
150 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUnifor ms.count() - 1);
151 }
152
153 void GrGLProgramBuilder::appendDecls(const VarArray& vars, SkString* out) const {
154 for (int i = 0; i < vars.count(); ++i) {
155 vars[i].appendDecl(this->ctxInfo(), out);
156 out->append(";\n");
157 }
158 }
159
160 void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility,
161 SkString* out) const {
162 for (int i = 0; i < fUniforms.count(); ++i) {
163 if (fUniforms[i].fVisibility & visibility) {
164 fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out);
165 out->append(";\n");
166 }
167 }
168 }
169
170 void GrGLProgramBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* program EffectsBuilder,
171 const GrEffectStage* effectStages[] ,
172 int effectCnt,
173 const GrGLProgramDesc::EffectKeyPro vider& keyProvider,
174 GrGLSLExpr4* fsInOutColor) {
175 bool effectEmitted = false;
176
177 GrGLSLExpr4 inColor = *fsInOutColor;
178 GrGLSLExpr4 outColor;
179
180 for (int e = 0; e < effectCnt; ++e) {
181 SkASSERT(NULL != effectStages[e] && NULL != effectStages[e]->getEffect() );
182 const GrEffectStage& stage = *effectStages[e];
183
184 CodeStage::AutoStageRestore csar(&fCodeStage, &stage);
185
186 if (inColor.isZeros()) {
187 SkString inColorName;
188
189 // Effects have no way to communicate zeros, they treat an empty str ing as ones.
190 this->nameVariable(&inColorName, '\0', "input");
191 fFS.codeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColor.c_ str());
192 inColor = inColorName;
193 }
194
195 // create var to hold stage result
196 SkString outColorName;
197 this->nameVariable(&outColorName, '\0', "output");
198 fFS.codeAppendf("\tvec4 %s;\n", outColorName.c_str());
199 outColor = outColorName;
200
201
202 programEffectsBuilder->emitEffect(stage,
203 keyProvider.get(e),
204 outColor.c_str(),
205 inColor.isOnes() ? NULL : inColor.c_st r(),
206 fCodeStage.stageIndex());
207
208 inColor = outColor;
209 effectEmitted = true;
210 }
211
212 if (effectEmitted) {
213 *fsInOutColor = outColor;
214 }
215 }
216
217 bool GrGLProgramBuilder::finish() {
218 SkASSERT(0 == fProgramID);
219 GL_CALL_RET(fProgramID, CreateProgram());
220 if (!fProgramID) {
221 return false;
222 }
223
224 SkTDArray<GrGLuint> shadersToDelete;
225
226 if (!this->compileAndAttachShaders(fProgramID, &shadersToDelete)) {
227 GL_CALL(DeleteProgram(fProgramID));
228 return false;
229 }
230
231 this->bindProgramLocations(fProgramID);
232
233 GL_CALL(LinkProgram(fProgramID));
234
235 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
236 bool checkLinked = !fGpu->ctxInfo().isChromium();
237 #ifdef SK_DEBUG
238 checkLinked = true;
239 #endif
240 if (checkLinked) {
241 GrGLint linked = GR_GL_INIT_ZERO;
242 GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked));
243 if (!linked) {
244 GrGLint infoLen = GR_GL_INIT_ZERO;
245 GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen));
246 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debug ger
247 if (infoLen > 0) {
248 // retrieve length even though we don't need it to workaround
249 // bug in chrome cmd buffer param validation.
250 GrGLsizei length = GR_GL_INIT_ZERO;
251 GL_CALL(GetProgramInfoLog(fProgramID,
252 infoLen+1,
253 &length,
254 (char*)log.get()));
255 GrPrintf((char*)log.get());
256 }
257 SkDEBUGFAIL("Error linking program");
258 GL_CALL(DeleteProgram(fProgramID));
259 fProgramID = 0;
260 return false;
261 }
262 }
263
264 this->resolveProgramLocations(fProgramID);
265
266 for (int i = 0; i < shadersToDelete.count(); ++i) {
267 GL_CALL(DeleteShader(shadersToDelete[i]));
268 }
269
270 return true;
271 }
272
273 bool GrGLProgramBuilder::compileAndAttachShaders(GrGLuint programId, SkTDArray<G rGLuint>* shaderIds) const {
274 return fFS.compileAndAttachShaders(programId, shaderIds);
275 }
276
277 void GrGLProgramBuilder::bindProgramLocations(GrGLuint programId) {
278 fFS.bindProgramLocations(programId);
279
280 // skbug.com/2056
281 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
282 if (usingBindUniform) {
283 int count = fUniforms.count();
284 for (int i = 0; i < count; ++i) {
285 GL_CALL(BindUniformLocation(programId, i, fUniforms[i].fVariable.c_s tr()));
286 fUniforms[i].fLocation = i;
287 }
288 }
289 }
290
291 void GrGLProgramBuilder::resolveProgramLocations(GrGLuint programId) {
292 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
293 if (!usingBindUniform) {
294 int count = fUniforms.count();
295 for (int i = 0; i < count; ++i) {
296 GrGLint location;
297 GL_CALL_RET(location,
298 GetUniformLocation(programId, fUniforms[i].fVariable.c_s tr()));
299 fUniforms[i].fLocation = location;
300 }
301 }
302 }
303
304 const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const {
305 return fGpu->ctxInfo();
306 }
307
308 ////////////////////////////////////////////////////////////////////////////////
309
310 GrGLFullProgramBuilder::GrGLFullProgramBuilder(GrGpuGL* gpu,
311 const GrGLProgramDesc& desc)
312 : INHERITED(gpu, desc)
313 , fGS(this)
314 , fVS(this) {
315 }
316
317 void GrGLFullProgramBuilder::emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExp r4* coverage) {
318 fVS.emitCodeBeforeEffects(color, coverage);
319 }
320
321 void GrGLFullProgramBuilder::emitCodeAfterEffects() {
322 fVS.emitCodeAfterEffects();
323 }
324
325 void GrGLFullProgramBuilder::addVarying(GrSLType type,
326 const char* name,
327 const char** vsOutName,
328 const char** fsInName) {
329 fVS.addVarying(type, name, vsOutName);
330
331 SkString* fsInputName = fVS.fOutputs.back().accessName();
332
333 #if GR_GL_EXPERIMENTAL_GS
334 if (desc().getHeader().fExperimentalGS) {
335 // TODO let the caller use these names
336 fGS.addVarying(type, fsInputName->c_str(), NULL);
337 fsInputName = fGS.fOutputs.back().accessName();
338 }
339 #endif
340 fFS.addVarying(type, fsInputName->c_str(), fsInName);
341 }
342
343 GrGLProgramEffects* GrGLFullProgramBuilder::createAndEmitEffects(
344 const GrEffectStage* effectStages[],
345 int effectCnt,
346 const GrGLProgramDesc::EffectKeyProvider& keyProvider,
347 GrGLSLExpr4* inOutFSColor) {
348
349 GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, effectCnt);
350 this->INHERITED::createAndEmitEffects(&programEffectsBuilder,
351 effectStages,
352 effectCnt,
353 keyProvider,
354 inOutFSColor);
355 return programEffectsBuilder.finish();
356 }
357
358 bool GrGLFullProgramBuilder::compileAndAttachShaders(GrGLuint programId,
359 SkTDArray<GrGLuint>* shader Ids) const {
360 return INHERITED::compileAndAttachShaders(programId, shaderIds)
361 && fVS.compileAndAttachShaders(programId, shaderIds)
362 #if GR_GL_EXPERIMENTAL_GS
363 && (!desc().getHeader().fExperimentalGS
364 || fGS.compileAndAttachShaders(programId, shaderIds))
365 #endif
366 ;
367 }
368
369 void GrGLFullProgramBuilder::bindProgramLocations(GrGLuint programId) {
370 fVS.bindProgramLocations(programId);
371 INHERITED::bindProgramLocations(programId);
372 }
373
374 ////////////////////////////////////////////////////////////////////////////////
375
376 GrGLFragmentOnlyProgramBuilder::GrGLFragmentOnlyProgramBuilder(GrGpuGL* gpu,
377 const GrGLProgram Desc& desc)
378 : INHERITED(gpu, desc) {
379 SkASSERT(!desc.getHeader().fHasVertexCode);
380 SkASSERT(gpu->glCaps().pathRenderingSupport());
381 SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorIn put);
382 SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverag eInput);
383 }
384
385 int GrGLFragmentOnlyProgramBuilder::addTexCoordSets(int count) {
386 int firstFreeCoordSet = fTexCoordSetCnt;
387 fTexCoordSetCnt += count;
388 SkASSERT(gpu()->glCaps().maxFixedFunctionTextureCoords() >= fTexCoordSetCnt) ;
389 return firstFreeCoordSet;
390 }
391
392 GrGLProgramEffects* GrGLFragmentOnlyProgramBuilder::createAndEmitEffects(
393 const GrEffectStage* effectStages[],
394 int effectCnt,
395 const GrGLProgramDesc::EffectKeyProvider& keyProvider,
396 GrGLSLExpr4* inOutFSColor) {
397
398 GrGLPathTexGenProgramEffectsBuilder pathTexGenEffectsBuilder(this,
399 effectCnt);
400 this->INHERITED::createAndEmitEffects(&pathTexGenEffectsBuilder,
401 effectStages,
402 effectCnt,
403 keyProvider,
404 inOutFSColor);
405 return pathTexGenEffectsBuilder.finish();
406 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698