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

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

Issue 611653002: Cleanup of shader building system (Closed) Base URL: https://skia.googlesource.com/skia.git@solo_gp
Patch Set: Created 6 years, 2 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/GrGLShaderBuilder.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2014 Google Inc. 2 * Copyright 2014 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "GrGLProgramBuilder.h"
9 #include "gl/GrGLGeometryProcessor.h"
8 #include "gl/GrGLProgram.h" 10 #include "gl/GrGLProgram.h"
9 #include "gl/GrGLSLPrettyPrint.h" 11 #include "gl/GrGLSLPrettyPrint.h"
10 #include "gl/GrGLUniformHandle.h" 12 #include "gl/GrGLUniformHandle.h"
13 #include "../GrGpuGL.h"
11 #include "GrCoordTransform.h" 14 #include "GrCoordTransform.h"
12 #include "../GrGpuGL.h" 15 #include "GrGLLegacyNvprProgramBuilder.h"
13 #include "GrGLFragmentShaderBuilder.h" 16 #include "GrGLNvprProgramBuilder.h"
14 #include "GrGLProgramBuilder.h" 17 #include "GrGLProgramBuilder.h"
15 #include "GrTexture.h" 18 #include "GrTexture.h"
16 #include "GrGLVertexShaderBuilder.h"
17 #include "SkRTConf.h" 19 #include "SkRTConf.h"
18 #include "SkTraceEvent.h" 20 #include "SkTraceEvent.h"
19 21
20 namespace {
21 #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X) 22 #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
22 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X) 23 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
23 24
24 // number of each input/output type in a single allocation block
25 static const int kVarsPerBlock = 8;
26
27 // ES2 FS only guarantees mediump and lowp support 25 // ES2 FS only guarantees mediump and lowp support
28 static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar: :kMedium_Precision; 26 static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar: :kMedium_Precision;
29 }
30
31 //////////////////////////////////////////////////////////////////////////////// ///////////////////
32
33 bool GrGLProgramBuilder::genProgram(const GrGeometryStage* geometryProcessor,
34 const GrFragmentStage* colorStages[],
35 const GrFragmentStage* 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 } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fColorInput) {
55 inputColor = GrGLSLExpr4(1);
56 }
57
58 if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
59 const char* name;
60 fUniformHandles.fCoverageUni =
61 this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
62 kVec4f_GrSLType,
63 "Coverage",
64 &name);
65 inputCoverage = GrGLSLExpr4(name);
66 } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) {
67 inputCoverage = GrGLSLExpr4(1);
68 }
69
70 // Subclasses drive effect emitting
71 this->createAndEmitEffects(geometryProcessor, colorStages, coverageStages, & inputColor,
72 &inputCoverage);
73
74 fFS.emitCodeAfterEffects(inputColor, inputCoverage);
75
76 if (!this->finish()) {
77 return false;
78 }
79
80 return true;
81 }
82 27
83 ////////////////////////////////////////////////////////////////////////////// 28 //////////////////////////////////////////////////////////////////////////////
84 29
30 const int GrGLProgramBuilder::kVarsPerBlock = 8;
31
32 GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState,
33 const GrGLProgramDesc& desc,
34 GrGpu::DrawType drawType,
35 const GrGeometryStage* geometryPr ocessor,
36 const GrFragmentStage* colorStage s[],
37 const GrFragmentStage* coverageSt ages[],
38 GrGpuGL* gpu) {
39 // create a builder. This will be handed off to effects so they can use it to add
40 // uniforms, varyings, textures, etc
41 SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(desc,
42 optState,
43 drawType,
44 SkToBool(geom etryProcessor),
45 gpu));
46
47 GrGLProgramBuilder* pb = builder.get();
48 const GrGLProgramDesc::KeyHeader& header = pb->header();
49
50 // emit code to read the dst copy texture, if necessary
51 if (GrGLFragmentShaderBuilder::kNoDstRead_DstReadKey != header.fDstReadKey
52 && !gpu->glCaps().fbFetchSupport()) {
53 pb->fFS.emitCodeToReadDstTexture();
54 }
55
56 // get the initial color and coverage to feed into the first effect in each effect chain
57 GrGLSLExpr4 inputColor, inputCoverage;
58 pb->setupUniformColorAndCoverageIfNeeded(&inputColor, &inputCoverage);
59
60 // if we have a vertex shader(we don't only if we are using NVPR or NVPR ES) , then we may have
61 // to setup a few more things like builtin vertex attributes
62 bool hasVertexShader = !header.fUseFragShaderOnly;
63 if (hasVertexShader) {
64 pb->fVS.setupLocalCoords();
65 pb->fVS.transformGLToSkiaCoords();
66 if (header.fEmitsPointSize) {
67 pb->fVS.codeAppend("gl_PointSize = 1.0;");
68 }
69 if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) {
70 pb->fVS.setupBuiltinVertexAttribute("Color", &inputColor);
71 }
72 if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) {
73 pb->fVS.setupBuiltinVertexAttribute("Coverage", &inputCoverage);
74 }
75 }
76
77 pb->createAndEmitProcessors(geometryProcessor, colorStages, coverageStages, &inputColor,
78 &inputCoverage);
79
80 if (hasVertexShader) {
81 pb->fVS.transformSkiaToGLCoords();
82 }
83
84 // write the secondary color output if necessary
85 if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType ) {
86 pb->fFS.enableSecondaryOutput(inputColor, inputCoverage);
87 }
88
89 pb->fFS.combineColorAndCoverage(inputColor, inputCoverage);
90
91 return pb->finalize();
92 }
93
94 GrGLProgramBuilder*
95 GrGLProgramBuilder::CreateProgramBuilder(const GrGLProgramDesc& desc,
96 const GrOptDrawState& optState,
97 GrGpu::DrawType drawType,
98 bool hasGeometryProcessor,
99 GrGpuGL* gpu) {
100 if (desc.getHeader().fUseFragShaderOnly) {
101 SkASSERT(gpu->glCaps().pathRenderingSupport());
102 SkASSERT(gpu->glPathRendering()->texturingMode() ==
103 GrGLPathRendering::FixedFunction_TexturingMode);
104 SkASSERT(!hasGeometryProcessor);
105 return SkNEW_ARGS(GrGLLegacyNvprProgramBuilder, (gpu, optState, desc));
106 } else if (GrGpu::IsPathRenderingDrawType(drawType)) {
107 SkASSERT(gpu->glCaps().pathRenderingSupport());
108 SkASSERT(gpu->glPathRendering()->texturingMode() ==
109 GrGLPathRendering::SeparableShaders_TexturingMode);
110 SkASSERT(!hasGeometryProcessor);
111 return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, optState, desc));
112 } else {
113 return SkNEW_ARGS(GrGLProgramBuilder, (gpu, optState, desc));
114 }
115 }
116
117 /////////////////////////////////////////////////////////////////////////////
118
85 GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, const GrOptDrawState& optSt ate, 119 GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, const GrOptDrawState& optSt ate,
86 const GrGLProgramDesc& desc) 120 const GrGLProgramDesc& desc)
87 : fEffectEmitter(NULL) 121 : fVS(this)
88 , fFragOnly(SkToBool(desc.getHeader().fUseFragShaderOnly)) 122 , fGS(this)
89 , fTexCoordSetCnt(0)
90 , fProgramID(0)
91 , fFS(this, desc) 123 , fFS(this, desc)
92 , fSeparableVaryingInfos(kVarsPerBlock) 124 , fOutOfStage(true)
93 , fGrProcessorEmitter(this) 125 , fStageIndex(-1)
94 , fOptState(optState) 126 , fOptState(optState)
95 , fDesc(desc) 127 , fDesc(desc)
96 , fGpu(gpu) 128 , fGpu(gpu)
97 , fUniforms(kVarsPerBlock) { 129 , fUniforms(kVarsPerBlock) {
98 } 130 }
99 131
132 void GrGLProgramBuilder::addVarying(GrSLType type,
133 const char* name,
134 const char** vsOutName,
135 const char** fsInName,
136 GrGLShaderVar::Precision fsPrecision) {
137 SkString* fsInputName = fVS.addVarying(type, name, vsOutName);
138 fFS.addVarying(type, fsInputName->c_str(), fsInName, fsPrecision);
139 }
140
100 void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* na me) { 141 void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* na me) {
101 if ('\0' == prefix) { 142 if ('\0' == prefix) {
102 *out = name; 143 *out = name;
103 } else { 144 } else {
104 out->printf("%c%s", prefix, name); 145 out->printf("%c%s", prefix, name);
105 } 146 }
106 if (fCodeStage.inStageCode()) { 147 if (!fOutOfStage) {
107 if (out->endsWith('_')) { 148 if (out->endsWith('_')) {
108 // Names containing "__" are reserved. 149 // Names containing "__" are reserved.
109 out->append("x"); 150 out->append("x");
110 } 151 }
111 out->appendf("_Stage%d", fCodeStage.stageIndex()); 152 out->appendf("_Stage%d", fStageIndex);
112 } 153 }
113 } 154 }
114 155
115 GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(uint32 _t visibility, 156 GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(uint32 _t visibility,
116 GrSLTy pe type, 157 GrSLTy pe type,
117 const char* name, 158 const char* name,
118 int co unt, 159 int co unt,
119 const char** outName) { 160 const char** outName) {
120 SkASSERT(name && strlen(name)); 161 SkASSERT(name && strlen(name));
121 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFr agment_Visibility); 162 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFr agment_Visibility);
(...skipping 14 matching lines...) Expand all
136 // the fragment and vertex precisions must match 177 // the fragment and vertex precisions must match
137 uni.fVariable.setPrecision(kDefaultFragmentPrecision); 178 uni.fVariable.setPrecision(kDefaultFragmentPrecision);
138 } 179 }
139 180
140 if (outName) { 181 if (outName) {
141 *outName = uni.fVariable.c_str(); 182 *outName = uni.fVariable.c_str();
142 } 183 }
143 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUnifor ms.count() - 1); 184 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUnifor ms.count() - 1);
144 } 185 }
145 186
146 void GrGLProgramBuilder::appendDecls(const VarArray& vars, SkString* out) const {
147 for (int i = 0; i < vars.count(); ++i) {
148 vars[i].appendDecl(this->ctxInfo(), out);
149 out->append(";\n");
150 }
151 }
152
153 void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility, 187 void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility,
154 SkString* out) const { 188 SkString* out) const {
155 for (int i = 0; i < fUniforms.count(); ++i) { 189 for (int i = 0; i < fUniforms.count(); ++i) {
156 if (fUniforms[i].fVisibility & visibility) { 190 if (fUniforms[i].fVisibility & visibility) {
157 fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out); 191 fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out);
158 out->append(";\n"); 192 out->append(";\n");
159 } 193 }
160 } 194 }
161 } 195 }
162 196
163 void GrGLProgramBuilder::createAndEmitEffects(const GrFragmentStage* effectStage s[], 197 const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const {
164 int effectCnt, 198 return fGpu->ctxInfo();
165 const GrGLProgramDesc::EffectKeyPr ovider& keyProvider, 199 }
166 GrGLSLExpr4* fsInOutColor) { 200
201 void GrGLProgramBuilder::setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* input Color,
202 GrGLSLExpr4* input Coverage) {
203 const GrGLProgramDesc::KeyHeader& header = this->header();
204 if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) {
205 const char* name;
206 fUniformHandles.fColorUni =
207 this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
208 kVec4f_GrSLType,
209 "Color",
210 &name);
211 *inputColor = GrGLSLExpr4(name);
212 } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fColorInput) {
213 *inputColor = GrGLSLExpr4(1);
214 }
215 if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
216 const char* name;
217 fUniformHandles.fCoverageUni =
218 this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
219 kVec4f_GrSLType,
220 "Coverage",
221 &name);
222 *inputCoverage = GrGLSLExpr4(name);
223 } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) {
224 *inputCoverage = GrGLSLExpr4(1);
225 }
226 }
227
228 void GrGLProgramBuilder::createAndEmitProcessors(const GrGeometryStage* geometry Processor,
229 const GrFragmentStage* colorSta ges[],
230 const GrFragmentStage* coverage Stages[],
231 GrGLSLExpr4* inputColor,
232 GrGLSLExpr4* inputCoverage) {
233 bool useLocalCoords = fVS.hasExplicitLocalCoords();
234
235 EffectKeyProvider colorKeyProvider(&fDesc, EffectKeyProvider::kColor_EffectT ype);
236 int numColorEffects = fDesc.numColorEffects();
237 GrGLInstalledProcessors* ip = SkNEW_ARGS(GrGLInstalledProcessors, (numColorE ffects,
238 useLocalC oords));
239 this->createAndEmitProcessors<GrFragmentStage>(colorStages, numColorEffects, colorKeyProvider,
240 inputColor, ip);
241 fColorEffects.reset(ip);
242
243 if (geometryProcessor) {
244 fVS.emitAttributes(*geometryProcessor->getProcessor());
245 EffectKeyProvider gpKeyProvider(&fDesc, EffectKeyProvider::kGeometryProc essor_EffectType);
246 ip = SkNEW_ARGS(GrGLInstalledProcessors, (1, useLocalCoords));
247 this->createAndEmitProcessors<GrGeometryStage>(&geometryProcessor, 1, gp KeyProvider,
248 inputCoverage, ip);
249 fGeometryProcessor.reset(ip);
250 }
251
252 EffectKeyProvider coverageKeyProvider(&fDesc, EffectKeyProvider::kCoverage_E ffectType);
253 int numCoverageEffects = fDesc.numCoverageEffects();
254 ip = SkNEW_ARGS(GrGLInstalledProcessors, (numCoverageEffects, useLocalCoords ));
255 this->createAndEmitProcessors<GrFragmentStage>(coverageStages, numCoverageEf fects,
256 coverageKeyProvider, inputCov erage, ip);
257 fCoverageEffects.reset(ip);
258 }
259
260 template <class ProcessorStage>
261 void GrGLProgramBuilder::createAndEmitProcessors(const ProcessorStage* processSt ages[],
262 int effectCnt,
263 const EffectKeyProvider& keyPro vider,
264 GrGLSLExpr4* fsInOutColor,
265 GrGLInstalledProcessors* instal ledProcessors) {
167 bool effectEmitted = false; 266 bool effectEmitted = false;
168 267
169 GrGLSLExpr4 inColor = *fsInOutColor; 268 GrGLSLExpr4 inColor = *fsInOutColor;
170 GrGLSLExpr4 outColor; 269 GrGLSLExpr4 outColor;
171 270
172 for (int e = 0; e < effectCnt; ++e) { 271 for (int e = 0; e < effectCnt; ++e) {
173 fGrProcessorEmitter.set(effectStages[e]->getFragmentProcessor()); 272 // Program builders have a bit of state we need to clear with each effec t
174 fEffectEmitter = &fGrProcessorEmitter; 273 AutoStageAdvance adv(this);
175 // calls into the subclass to emit the actual effect into the program ef fect object 274 const ProcessorStage& stage = *processStages[e];
176 this->emitEffect(*effectStages[e], e, keyProvider, &inColor, &outColor); 275 SkASSERT(stage.getProcessor());
276
277 if (inColor.isZeros()) {
278 SkString inColorName;
279
280 // Effects have no way to communicate zeros, they treat an empty str ing as ones.
281 this->nameVariable(&inColorName, '\0', "input");
282 fFS.codeAppendf("vec4 %s = %s;", inColorName.c_str(), inColor.c_str( ));
283 inColor = inColorName;
284 }
285
286 // create var to hold stage result
287 SkString outColorName;
288 this->nameVariable(&outColorName, '\0', "output");
289 fFS.codeAppendf("vec4 %s;", outColorName.c_str());
290 outColor = outColorName;
291
292 SkASSERT(installedProcessors);
293 const typename ProcessorStage::Processor& processor = *stage.getProcesso r();
294 SkSTArray<2, GrGLProcessor::TransformedCoords> coords(processor.numTrans forms());
295 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(processor.numTextur es());
296
297 this->emitTransforms(stage, &coords, installedProcessors);
298 this->emitSamplers(processor, &samplers, installedProcessors);
299
300 typename ProcessorStage::GLProcessor* glEffect =
301 processor.getFactory().createGLInstance(processor);
302 installedProcessors->addEffect(glEffect);
303
304 // Enclose custom code in a block to avoid namespace conflicts
305 SkString openBrace;
306 openBrace.printf("{ // Stage %d: %s\n", fStageIndex, glEffect->name());
307 fFS.codeAppend(openBrace.c_str());
308 fVS.codeAppend(openBrace.c_str());
309
310 glEffect->emitCode(this, processor, keyProvider.get(e), outColor.c_str() ,
311 inColor.isOnes() ? NULL : inColor.c_str(), coords, sa mplers);
312
313 // We have to check that effects and the code they emit are consistent, ie if an effect
314 // asks for dst color, then the emit code needs to follow suit
315 verify(processor);
316 fFS.codeAppend("}");
317 fVS.codeAppend("}");
318
319 inColor = outColor;
177 effectEmitted = true; 320 effectEmitted = true;
178 } 321 }
179 322
180 if (effectEmitted) { 323 if (effectEmitted) {
181 *fsInOutColor = outColor; 324 *fsInOutColor = outColor;
182 } 325 }
183 } 326 }
184 327
185 void GrGLProgramBuilder::emitEffect(const GrProcessorStage& effectStage, 328 void GrGLProgramBuilder::verify(const GrGeometryProcessor& gp) {
186 int effectIndex, 329 SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition());
187 const GrGLProgramDesc::EffectKeyProvider& ke yProvider,
188 GrGLSLExpr4* inColor,
189 GrGLSLExpr4* outColor) {
190 SkASSERT(effectStage.getProcessor());
191 CodeStage::AutoStageRestore csar(&fCodeStage, &effectStage);
192
193 if (inColor->isZeros()) {
194 SkString inColorName;
195
196 // Effects have no way to communicate zeros, they treat an empty string as ones.
197 this->nameVariable(&inColorName, '\0', "input");
198 fFS.codeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColor->c_str ());
199 *inColor = inColorName;
200 }
201
202 // create var to hold stage result
203 SkString outColorName;
204 this->nameVariable(&outColorName, '\0', "output");
205 fFS.codeAppendf("\tvec4 %s;\n", outColorName.c_str());
206 *outColor = outColorName;
207
208 this->emitEffect(effectStage, keyProvider.get(effectIndex), outColor->c_str( ),
209 inColor->isOnes() ? NULL : inColor->c_str(), fCodeStage.sta geIndex());
210
211 *inColor = *outColor;
212 } 330 }
213 331
214 void GrGLProgramBuilder::emitSamplers(const GrProcessor& effect, 332 void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) {
215 GrGLProcessor::TextureSamplerArray* outSam plers) { 333 SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition());
216 SkTArray<GrGLProgramEffects::Sampler, true>& samplers = 334 SkASSERT(fFS.hasReadDstColor() == fp.willReadDstColor());
217 this->getProgramEffects()->addSamplers(); 335 }
218 int numTextures = effect.numTextures(); 336
337 void GrGLProgramBuilder::emitTransforms(const GrProcessorStage& effectStage,
338 GrGLProcessor::TransformedCoordsArray* o utCoords,
339 GrGLInstalledProcessors* installedProces sors) {
340 SkTArray<GrGLInstalledProcessors::Transform, true>& transforms =
341 installedProcessors->addTransforms();
342 const GrProcessor* effect = effectStage.getProcessor();
343 int numTransforms = effect->numTransforms();
344 transforms.push_back_n(numTransforms);
345
346 for (int t = 0; t < numTransforms; t++) {
347 const char* uniName = "StageMatrix";
348 GrSLType varyingType =
349 effectStage.isPerspectiveCoordTransform(t, fVS.hasExplicitLocalC oords()) ?
350 kVec3f_GrSLType :
351 kVec2f_GrSLType;
352
353 SkString suffixedUniName;
354 if (0 != t) {
355 suffixedUniName.append(uniName);
356 suffixedUniName.appendf("_%i", t);
357 uniName = suffixedUniName.c_str();
358 }
359 transforms[t].fHandle = this->addUniform(GrGLProgramBuilder::kVertex_Vis ibility,
360 kMat33f_GrSLType,
361 uniName,
362 &uniName).toShaderBuilderIndex( );
363
364 const char* varyingName = "MatrixCoord";
365 SkString suffixedVaryingName;
366 if (0 != t) {
367 suffixedVaryingName.append(varyingName);
368 suffixedVaryingName.appendf("_%i", t);
369 varyingName = suffixedVaryingName.c_str();
370 }
371 const char* vsVaryingName;
372 const char* fsVaryingName;
373 this->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingNam e);
374
375 const GrGLShaderVar& coords =
376 kPosition_GrCoordSet == effect->coordTransform(t).sourceCoords() ?
377 fVS.positionAttribute() :
378 fVS.localCoordsAttribute();
379
380 // varying = matrix * coords (logically)
381 SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingTyp e);
382 if (kVec2f_GrSLType == varyingType) {
383 fVS.codeAppendf("%s = (%s * vec3(%s, 1)).xy;",
384 vsVaryingName, uniName, coords.c_str());
385 } else {
386 fVS.codeAppendf("%s = %s * vec3(%s, 1);",
387 vsVaryingName, uniName, coords.c_str());
388 }
389 SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords,
390 (SkString(fsVaryingName), varyingType));
391 }
392 }
393
394 void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor,
395 GrGLProcessor::TextureSamplerArray* outSam plers,
396 GrGLInstalledProcessors* installedProcesso rs) {
397 SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = installedProces sors->addSamplers();
398 int numTextures = processor.numTextures();
219 samplers.push_back_n(numTextures); 399 samplers.push_back_n(numTextures);
220 SkString name; 400 SkString name;
221 for (int t = 0; t < numTextures; ++t) { 401 for (int t = 0; t < numTextures; ++t) {
222 name.printf("Sampler%d", t); 402 name.printf("Sampler%d", t);
223 samplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Vi sibility, 403 samplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Vi sibility,
224 kSampler2D_GrSLType, 404 kSampler2D_GrSLType,
225 name.c_str()); 405 name.c_str());
226 SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler, 406 SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler,
227 (samplers[t].fUniform, effect.textureAccess(t))); 407 (samplers[t].fUniform, processor.textureAccess(t) ));
228 } 408 }
229 } 409 }
230 410
231 bool GrGLProgramBuilder::finish() { 411 GrGLProgram* GrGLProgramBuilder::finalize() {
232 SkASSERT(0 == fProgramID); 412 // verify we can get a program id
233 GL_CALL_RET(fProgramID, CreateProgram()); 413 GrGLuint programID;
234 if (!fProgramID) { 414 GL_CALL_RET(programID, CreateProgram());
235 return false; 415 if (0 == programID) {
416 return NULL;
236 } 417 }
237 418
419 // compile shaders and bind attributes / uniforms
238 SkTDArray<GrGLuint> shadersToDelete; 420 SkTDArray<GrGLuint> shadersToDelete;
239 421 if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) {
240 if (!this->compileAndAttachShaders(fProgramID, &shadersToDelete)) { 422 this->cleanupProgram(programID, shadersToDelete);
241 GL_CALL(DeleteProgram(fProgramID)); 423 return NULL;
242 return false;
243 } 424 }
244 425 if (!this->header().fUseFragShaderOnly) {
245 this->bindProgramLocations(fProgramID); 426 if (!fVS.compileAndAttachShaders(programID, &shadersToDelete)) {
246 427 this->cleanupProgram(programID, shadersToDelete);
247 GL_CALL(LinkProgram(fProgramID)); 428 return NULL;
429 }
430 fVS.bindVertexAttributes(programID);
431 }
432 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
433 if (usingBindUniform) {
434 this->bindUniformLocations(programID);
435 }
436 fFS.bindFragmentShaderLocations(programID);
437 GL_CALL(LinkProgram(programID));
248 438
249 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds. 439 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
250 bool checkLinked = !fGpu->ctxInfo().isChromium(); 440 bool checkLinked = !fGpu->ctxInfo().isChromium();
251 #ifdef SK_DEBUG 441 #ifdef SK_DEBUG
252 checkLinked = true; 442 checkLinked = true;
253 #endif 443 #endif
254 if (checkLinked) { 444 if (checkLinked) {
255 GrGLint linked = GR_GL_INIT_ZERO; 445 checkLinkStatus(programID);
256 GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked)); 446 }
257 if (!linked) { 447 if (!usingBindUniform) {
258 GrGLint infoLen = GR_GL_INIT_ZERO; 448 this->resolveUniformLocations(programID);
259 GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen));
260 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debug ger
261 if (infoLen > 0) {
262 // retrieve length even though we don't need it to workaround
263 // bug in chrome cmd buffer param validation.
264 GrGLsizei length = GR_GL_INIT_ZERO;
265 GL_CALL(GetProgramInfoLog(fProgramID,
266 infoLen+1,
267 &length,
268 (char*)log.get()));
269 GrPrintf((char*)log.get());
270 }
271 SkDEBUGFAIL("Error linking program");
272 GL_CALL(DeleteProgram(fProgramID));
273 fProgramID = 0;
274 return false;
275 }
276 } 449 }
277 450
278 this->resolveProgramLocations(fProgramID); 451 this->cleanupShaders(shadersToDelete);
279 452
280 for (int i = 0; i < shadersToDelete.count(); ++i) { 453 return this->createProgram(programID);
281 GL_CALL(DeleteShader(shadersToDelete[i]));
282 }
283
284 return true;
285 } 454 }
286 455
287 bool GrGLProgramBuilder::compileAndAttachShaders(GrGLuint programId, 456 void GrGLProgramBuilder::bindUniformLocations(GrGLuint programID) {
288 SkTDArray<GrGLuint>* shaderIds) const { 457 int count = fUniforms.count();
289 return fFS.compileAndAttachShaders(programId, shaderIds); 458 for (int i = 0; i < count; ++i) {
290 } 459 GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_str() ));
291 460 fUniforms[i].fLocation = i;
292 void GrGLProgramBuilder::bindProgramLocations(GrGLuint programId) {
293 fFS.bindProgramLocations(programId);
294
295 // skbug.com/2056
296 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
297 if (usingBindUniform) {
298 int count = fUniforms.count();
299 for (int i = 0; i < count; ++i) {
300 GL_CALL(BindUniformLocation(programId, i, fUniforms[i].fVariable.c_s tr()));
301 fUniforms[i].fLocation = i;
302 }
303 } 461 }
304 } 462 }
305 463
306 void GrGLProgramBuilder::resolveProgramLocations(GrGLuint programId) { 464 bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
307 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL; 465 GrGLint linked = GR_GL_INIT_ZERO;
308 if (!usingBindUniform) { 466 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
309 int count = fUniforms.count(); 467 if (!linked) {
310 for (int i = 0; i < count; ++i) { 468 GrGLint infoLen = GR_GL_INIT_ZERO;
311 GrGLint location; 469 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
312 GL_CALL_RET(location, 470 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
313 GetUniformLocation(programId, fUniforms[i].fVariable.c_s tr())); 471 if (infoLen > 0) {
314 fUniforms[i].fLocation = location; 472 // retrieve length even though we don't need it to workaround
473 // bug in chrome cmd buffer param validation.
474 GrGLsizei length = GR_GL_INIT_ZERO;
475 GL_CALL(GetProgramInfoLog(programID,
476 infoLen+1,
477 &length,
478 (char*)log.get()));
479 GrPrintf((char*)log.get());
315 } 480 }
481 SkDEBUGFAIL("Error linking program");
482 GL_CALL(DeleteProgram(programID));
483 programID = 0;
316 } 484 }
485 return SkToBool(linked);
486 }
317 487
318 int count = fSeparableVaryingInfos.count(); 488 void GrGLProgramBuilder::resolveUniformLocations(GrGLuint programID) {
489 int count = fUniforms.count();
319 for (int i = 0; i < count; ++i) { 490 for (int i = 0; i < count; ++i) {
320 GrGLint location; 491 GrGLint location;
321 GL_CALL_RET(location, 492 GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariab le.c_str()));
322 GetProgramResourceLocation(programId, 493 fUniforms[i].fLocation = location;
323 GR_GL_FRAGMENT_INPUT,
324 fSeparableVaryingInfos[i].fVariab le.c_str()));
325 fSeparableVaryingInfos[i].fLocation = location;
326 } 494 }
327 } 495 }
328 496
329 const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const { 497 void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGL uint>& shaderIDs) {
330 return fGpu->ctxInfo(); 498 GL_CALL(DeleteProgram(programID));
499 cleanupShaders(shaderIDs);
331 } 500 }
501 void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
502 for (int i = 0; i < shaderIDs.count(); ++i) {
503 GL_CALL(DeleteShader(shaderIDs[i]));
504 }
505 }
506
507 GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
508 return SkNEW_ARGS(GrGLProgram, (fGpu, fDesc, fUniformHandles, programID, fUn iforms,
509 fGeometryProcessor, fColorEffects, fCoverage Effects));
510 }
511
512 ////////////////////////////////////////////////////////////////////////////////
513
514 GrGLInstalledProcessors::~GrGLInstalledProcessors() {
515 int numEffects = fGLProcessors.count();
516 for (int e = 0; e < numEffects; ++e) {
517 SkDELETE(fGLProcessors[e]);
518 }
519 }
OLDNEW
« no previous file with comments | « src/gpu/gl/builders/GrGLProgramBuilder.h ('k') | src/gpu/gl/builders/GrGLShaderBuilder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698