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

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

Powered by Google App Engine
This is Rietveld 408576698