blob: 0862bc4ffa53d8629c3092684e464721335cbe5c [file] [log] [blame]
egdaniel8dcdedc2015-11-11 06:27:20 -08001/*
2 * Copyright 2015 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 "glsl/GrGLSLProgramBuilder.h"
9
egdanielfa896322016-01-13 12:19:30 -080010#include "GrPipeline.h"
Brian Salomon739c5bf2016-11-07 09:53:44 -050011#include "GrTexturePriv.h"
egdanielfa896322016-01-13 12:19:30 -080012#include "glsl/GrGLSLFragmentProcessor.h"
13#include "glsl/GrGLSLGeometryProcessor.h"
egdaniel9f1d4152016-02-10 09:50:38 -080014#include "glsl/GrGLSLVarying.h"
egdanielfa896322016-01-13 12:19:30 -080015#include "glsl/GrGLSLXferProcessor.h"
16
egdaniel8dcdedc2015-11-11 06:27:20 -080017const int GrGLSLProgramBuilder::kVarsPerBlock = 8;
18
egdaniel0e1853c2016-03-17 11:35:45 -070019GrGLSLProgramBuilder::GrGLSLProgramBuilder(const GrPipeline& pipeline,
20 const GrPrimitiveProcessor& primProc,
21 const GrProgramDesc& desc)
egdaniel8dcdedc2015-11-11 06:27:20 -080022 : fVS(this)
23 , fGS(this)
cdalton28f45b92016-03-07 13:58:26 -080024 , fFS(this)
egdaniel8dcdedc2015-11-11 06:27:20 -080025 , fStageIndex(-1)
egdaniel0e1853c2016-03-17 11:35:45 -070026 , fPipeline(pipeline)
27 , fPrimProc(primProc)
28 , fDesc(desc)
egdanielfa896322016-01-13 12:19:30 -080029 , fGeometryProcessor(nullptr)
cdalton9c3f1432016-03-11 10:07:37 -080030 , fXferProcessor(nullptr)
cdalton9c3f1432016-03-11 10:07:37 -080031 , fNumVertexSamplers(0)
32 , fNumGeometrySamplers(0)
33 , fNumFragmentSamplers(0) {
34}
35
36void GrGLSLProgramBuilder::addFeature(GrShaderFlags shaders,
37 uint32_t featureBit,
38 const char* extensionName) {
39 if (shaders & kVertex_GrShaderFlag) {
40 fVS.addFeature(featureBit, extensionName);
41 }
42 if (shaders & kGeometry_GrShaderFlag) {
43 SkASSERT(this->glslCaps()->geometryShaderSupport());
44 fGS.addFeature(featureBit, extensionName);
45 }
46 if (shaders & kFragment_GrShaderFlag) {
47 fFS.addFeature(featureBit, extensionName);
48 }
egdanielfa896322016-01-13 12:19:30 -080049}
50
51bool GrGLSLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor,
cdalton9c3f1432016-03-11 10:07:37 -080052 GrGLSLExpr4* inputCoverage) {
egdanielfa896322016-01-13 12:19:30 -080053 // First we loop over all of the installed processors and collect coord transforms. These will
54 // be sent to the GrGLSLPrimitiveProcessor in its emitCode function
55 const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
egdanielfa896322016-01-13 12:19:30 -080056
egdanielfa896322016-01-13 12:19:30 -080057 this->emitAndInstallPrimProc(primProc, inputColor, inputCoverage);
58
bsalomona624bf32016-09-20 09:12:47 -070059 this->emitAndInstallFragProcs(inputColor, inputCoverage);
halcanary9d524f22016-03-29 09:03:52 -070060 if (primProc.getPixelLocalStorageState() !=
ethannicholas22793252016-01-30 09:59:10 -080061 GrPixelLocalStorageState::kDraw_GrPixelLocalStorageState) {
halcanary9d524f22016-03-29 09:03:52 -070062 this->emitAndInstallXferProc(this->pipeline().getXferProcessor(), *inputColor,
ethannicholas22793252016-01-30 09:59:10 -080063 *inputCoverage, this->pipeline().ignoresCoverage(),
64 primProc.getPixelLocalStorageState());
65 this->emitFSOutputSwizzle(this->pipeline().getXferProcessor().hasSecondaryOutput());
66 }
cdalton9c3f1432016-03-11 10:07:37 -080067
68 return this->checkSamplerCounts();
egdanielfa896322016-01-13 12:19:30 -080069}
70
71void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& proc,
72 GrGLSLExpr4* outputColor,
73 GrGLSLExpr4* outputCoverage) {
74 // Program builders have a bit of state we need to clear with each effect
75 AutoStageAdvance adv(this);
76 this->nameExpression(outputColor, "outputColor");
77 this->nameExpression(outputCoverage, "outputCoverage");
78
dvonbeck9b03e7b2016-08-01 11:01:56 -070079 const char* distanceVectorName = nullptr;
80 if (this->fPipeline.usesDistanceVectorField() && proc.implementsDistanceVector()) {
robertphillips05a4cf52016-09-08 09:02:43 -070081 // Each individual user (FP) of the distance vector must be able to handle having this
82 // variable be undeclared. There is no single default value that will yield a reasonable
83 // result for all users.
dvonbeck9b03e7b2016-08-01 11:01:56 -070084 distanceVectorName = fFS.distanceVectorName();
dvonbeckee920632016-08-11 14:17:59 -070085 fFS.codeAppend( "// Normalized vector to the closest geometric edge (in device space)\n");
dvonbeck84bca782016-08-08 11:47:12 -070086 fFS.codeAppend( "// Distance to the edge encoded in the z-component\n");
jvanverth6c177a12016-08-17 07:59:41 -070087 fFS.codeAppendf("vec4 %s;", distanceVectorName);
dvonbeck9b03e7b2016-08-01 11:01:56 -070088 }
89
egdanielfa896322016-01-13 12:19:30 -080090 // Enclose custom code in a block to avoid namespace conflicts
91 SkString openBrace;
92 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name());
93 fFS.codeAppend(openBrace.c_str());
94 fVS.codeAppendf("// Primitive Processor %s\n", proc.name());
95
96 SkASSERT(!fGeometryProcessor);
97 fGeometryProcessor = proc.createGLSLInstance(*this->glslCaps());
98
egdaniel09aa1fc2016-04-20 07:09:46 -070099 SkSTArray<4, SamplerHandle> texSamplers(proc.numTextures());
100 SkSTArray<2, SamplerHandle> bufferSamplers(proc.numBuffers());
cdalton74b8d322016-04-11 14:47:28 -0700101 this->emitSamplers(proc, &texSamplers, &bufferSamplers);
egdanielfa896322016-01-13 12:19:30 -0800102
bsalomona624bf32016-09-20 09:12:47 -0700103 GrGLSLPrimitiveProcessor::FPCoordTransformHandler transformHandler(fPipeline,
104 &fTransformedCoordVars);
egdanielfa896322016-01-13 12:19:30 -0800105 GrGLSLGeometryProcessor::EmitArgs args(&fVS,
106 &fFS,
107 this->varyingHandler(),
108 this->uniformHandler(),
109 this->glslCaps(),
110 proc,
111 outputColor->c_str(),
112 outputCoverage->c_str(),
dvonbeck9b03e7b2016-08-01 11:01:56 -0700113 distanceVectorName,
egdaniel09aa1fc2016-04-20 07:09:46 -0700114 texSamplers.begin(),
115 bufferSamplers.begin(),
bsalomona624bf32016-09-20 09:12:47 -0700116 &transformHandler);
egdanielfa896322016-01-13 12:19:30 -0800117 fGeometryProcessor->emitCode(args);
118
119 // We have to check that effects and the code they emit are consistent, ie if an effect
120 // asks for dst color, then the emit code needs to follow suit
cdalton87332102016-02-26 12:22:02 -0800121 SkDEBUGCODE(verify(proc);)
egdanielfa896322016-01-13 12:19:30 -0800122
123 fFS.codeAppend("}");
124}
125
bsalomona624bf32016-09-20 09:12:47 -0700126void GrGLSLProgramBuilder::emitAndInstallFragProcs(GrGLSLExpr4* color, GrGLSLExpr4* coverage) {
127 int transformedCoordVarsIdx = 0;
128 GrGLSLExpr4** inOut = &color;
129 for (int i = 0; i < this->pipeline().numFragmentProcessors(); ++i) {
130 if (i == this->pipeline().numColorFragmentProcessors()) {
131 inOut = &coverage;
132 }
egdanielfa896322016-01-13 12:19:30 -0800133 GrGLSLExpr4 output;
134 const GrFragmentProcessor& fp = this->pipeline().getFragmentProcessor(i);
bsalomona624bf32016-09-20 09:12:47 -0700135 this->emitAndInstallFragProc(fp, i, transformedCoordVarsIdx, **inOut, &output);
136 GrFragmentProcessor::Iter iter(&fp);
137 while (const GrFragmentProcessor* fp = iter.next()) {
138 transformedCoordVarsIdx += fp->numCoordTransforms();
139 }
140 **inOut = output;
egdanielfa896322016-01-13 12:19:30 -0800141 }
142}
143
144// TODO Processors cannot output zeros because an empty string is all 1s
145// the fix is to allow effects to take the GrGLSLExpr4 directly
146void GrGLSLProgramBuilder::emitAndInstallFragProc(const GrFragmentProcessor& fp,
147 int index,
bsalomona624bf32016-09-20 09:12:47 -0700148 int transformedCoordVarsIdx,
egdanielfa896322016-01-13 12:19:30 -0800149 const GrGLSLExpr4& input,
150 GrGLSLExpr4* output) {
151 // Program builders have a bit of state we need to clear with each effect
152 AutoStageAdvance adv(this);
153 this->nameExpression(output, "output");
154
155 // Enclose custom code in a block to avoid namespace conflicts
156 SkString openBrace;
157 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, fp.name());
158 fFS.codeAppend(openBrace.c_str());
159
160 GrGLSLFragmentProcessor* fragProc = fp.createGLSLInstance();
161
bsalomonb58a2b42016-09-26 06:55:02 -0700162 SkSTArray<4, SamplerHandle> textureSamplerArray(fp.numTextures());
163 SkSTArray<2, SamplerHandle> bufferSamplerArray(fp.numBuffers());
164 GrFragmentProcessor::Iter iter(&fp);
165 while (const GrFragmentProcessor* subFP = iter.next()) {
166 this->emitSamplers(*subFP, &textureSamplerArray, &bufferSamplerArray);
167 }
egdanielfa896322016-01-13 12:19:30 -0800168
bsalomona624bf32016-09-20 09:12:47 -0700169 const GrShaderVar* coordVars = fTransformedCoordVars.begin() + transformedCoordVarsIdx;
170 GrGLSLFragmentProcessor::TransformedCoordVars coords(&fp, coordVars);
bsalomonb58a2b42016-09-26 06:55:02 -0700171 GrGLSLFragmentProcessor::TextureSamplers textureSamplers(&fp, textureSamplerArray.begin());
172 GrGLSLFragmentProcessor::BufferSamplers bufferSamplers(&fp, bufferSamplerArray.begin());
egdanielfa896322016-01-13 12:19:30 -0800173 GrGLSLFragmentProcessor::EmitArgs args(&fFS,
174 this->uniformHandler(),
175 this->glslCaps(),
176 fp,
177 output->c_str(),
178 input.isOnes() ? nullptr : input.c_str(),
bsalomona624bf32016-09-20 09:12:47 -0700179 coords,
bsalomonb58a2b42016-09-26 06:55:02 -0700180 textureSamplers,
181 bufferSamplers,
dvonbeck9b03e7b2016-08-01 11:01:56 -0700182 this->primitiveProcessor().implementsDistanceVector());
183
egdanielfa896322016-01-13 12:19:30 -0800184 fragProc->emitCode(args);
185
186 // We have to check that effects and the code they emit are consistent, ie if an effect
187 // asks for dst color, then the emit code needs to follow suit
cdalton87332102016-02-26 12:22:02 -0800188 SkDEBUGCODE(verify(fp);)
egdanielfa896322016-01-13 12:19:30 -0800189 fFragmentProcessors.push_back(fragProc);
190
191 fFS.codeAppend("}");
192}
193
194void GrGLSLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp,
195 const GrGLSLExpr4& colorIn,
196 const GrGLSLExpr4& coverageIn,
ethannicholas22793252016-01-30 09:59:10 -0800197 bool ignoresCoverage,
198 GrPixelLocalStorageState plsState) {
egdanielfa896322016-01-13 12:19:30 -0800199 // Program builders have a bit of state we need to clear with each effect
200 AutoStageAdvance adv(this);
201
202 SkASSERT(!fXferProcessor);
203 fXferProcessor = xp.createGLSLInstance();
204
205 // Enable dual source secondary output if we have one
206 if (xp.hasSecondaryOutput()) {
207 fFS.enableSecondaryOutput();
208 }
209
210 if (this->glslCaps()->mustDeclareFragmentShaderOutput()) {
211 fFS.enableCustomOutput();
212 }
213
214 SkString openBrace;
215 openBrace.printf("{ // Xfer Processor: %s\n", xp.name());
216 fFS.codeAppend(openBrace.c_str());
217
egdaniel09aa1fc2016-04-20 07:09:46 -0700218 SkSTArray<4, SamplerHandle> texSamplers(xp.numTextures());
219 SkSTArray<2, SamplerHandle> bufferSamplers(xp.numBuffers());
cdalton74b8d322016-04-11 14:47:28 -0700220 this->emitSamplers(xp, &texSamplers, &bufferSamplers);
egdanielfa896322016-01-13 12:19:30 -0800221
ethannicholas22793252016-01-30 09:59:10 -0800222 bool usePLSDstRead = (plsState == GrPixelLocalStorageState::kFinish_GrPixelLocalStorageState);
egdanielfa896322016-01-13 12:19:30 -0800223 GrGLSLXferProcessor::EmitArgs args(&fFS,
224 this->uniformHandler(),
225 this->glslCaps(),
226 xp, colorIn.c_str(),
227 ignoresCoverage ? nullptr : coverageIn.c_str(),
228 fFS.getPrimaryColorOutputName(),
229 fFS.getSecondaryColorOutputName(),
egdaniel09aa1fc2016-04-20 07:09:46 -0700230 texSamplers.begin(),
231 bufferSamplers.begin(),
ethannicholas22793252016-01-30 09:59:10 -0800232 usePLSDstRead);
egdanielfa896322016-01-13 12:19:30 -0800233 fXferProcessor->emitCode(args);
234
235 // We have to check that effects and the code they emit are consistent, ie if an effect
236 // asks for dst color, then the emit code needs to follow suit
cdalton87332102016-02-26 12:22:02 -0800237 SkDEBUGCODE(verify(xp);)
egdanielfa896322016-01-13 12:19:30 -0800238 fFS.codeAppend("}");
239}
240
cdalton9c3f1432016-03-11 10:07:37 -0800241void GrGLSLProgramBuilder::emitSamplers(const GrProcessor& processor,
egdaniel09aa1fc2016-04-20 07:09:46 -0700242 SkTArray<SamplerHandle>* outTexSamplers,
243 SkTArray<SamplerHandle>* outBufferSamplers) {
cdalton9c3f1432016-03-11 10:07:37 -0800244 SkString name;
cdalton74b8d322016-04-11 14:47:28 -0700245 int numTextures = processor.numTextures();
cdalton9c3f1432016-03-11 10:07:37 -0800246 for (int t = 0; t < numTextures; ++t) {
247 const GrTextureAccess& access = processor.textureAccess(t);
Brian Salomon739c5bf2016-11-07 09:53:44 -0500248 GrSLType samplerType = access.getTexture()->texturePriv().samplerType();
egdaniel990dbc82016-07-13 14:09:30 -0700249 if (kTextureExternalSampler_GrSLType == samplerType) {
cdalton9c3f1432016-03-11 10:07:37 -0800250 const char* externalFeatureString = this->glslCaps()->externalTextureExtensionString();
251 // We shouldn't ever create a GrGLTexture that requires external sampler type
252 SkASSERT(externalFeatureString);
cdalton74b8d322016-04-11 14:47:28 -0700253 this->addFeature(access.getVisibility(),
cdalton9c3f1432016-03-11 10:07:37 -0800254 1 << GrGLSLShaderBuilder::kExternalTexture_GLSLPrivateFeature,
255 externalFeatureString);
256 }
bsalomonb58a2b42016-09-26 06:55:02 -0700257 name.printf("TextureSampler_%d", outTexSamplers->count());
cdalton74b8d322016-04-11 14:47:28 -0700258 this->emitSampler(samplerType, access.getTexture()->config(),
259 name.c_str(), access.getVisibility(), outTexSamplers);
cdalton9c3f1432016-03-11 10:07:37 -0800260 }
cdalton74b8d322016-04-11 14:47:28 -0700261
262 if (int numBuffers = processor.numBuffers()) {
263 SkASSERT(this->glslCaps()->texelBufferSupport());
264 GrShaderFlags texelBufferVisibility = kNone_GrShaderFlags;
265
266 for (int b = 0; b < numBuffers; ++b) {
267 const GrBufferAccess& access = processor.bufferAccess(b);
bsalomonb58a2b42016-09-26 06:55:02 -0700268 name.printf("BufferSampler_%d", outBufferSamplers->count());
csmartdalton22458032016-11-16 11:28:16 -0700269 this->emitSampler(kBufferSampler_GrSLType, access.texelConfig(), name.c_str(),
cdalton74b8d322016-04-11 14:47:28 -0700270 access.visibility(), outBufferSamplers);
271 texelBufferVisibility |= access.visibility();
272 }
273
274 if (const char* extension = this->glslCaps()->texelBufferExtensionString()) {
275 this->addFeature(texelBufferVisibility,
276 1 << GrGLSLShaderBuilder::kTexelBuffer_GLSLPrivateFeature,
277 extension);
278 }
279 }
280}
281
282void GrGLSLProgramBuilder::emitSampler(GrSLType samplerType,
283 GrPixelConfig config,
284 const char* name,
285 GrShaderFlags visibility,
egdaniel09aa1fc2016-04-20 07:09:46 -0700286 SkTArray<SamplerHandle>* outSamplers) {
cdalton74b8d322016-04-11 14:47:28 -0700287 if (visibility & kVertex_GrShaderFlag) {
288 ++fNumVertexSamplers;
289 }
290 if (visibility & kGeometry_GrShaderFlag) {
291 SkASSERT(this->primitiveProcessor().willUseGeoShader());
292 ++fNumGeometrySamplers;
293 }
294 if (visibility & kFragment_GrShaderFlag) {
295 ++fNumFragmentSamplers;
296 }
297 GrSLPrecision precision = this->glslCaps()->samplerPrecision(config, visibility);
egdaniel09aa1fc2016-04-20 07:09:46 -0700298 SamplerHandle handle = this->uniformHandler()->addSampler(visibility,
299 config,
300 samplerType,
301 precision,
302 name);
303 outSamplers->emplace_back(handle);
cdalton9c3f1432016-03-11 10:07:37 -0800304}
305
egdanielfa896322016-01-13 12:19:30 -0800306void GrGLSLProgramBuilder::emitFSOutputSwizzle(bool hasSecondaryOutput) {
307 // Swizzle the fragment shader outputs if necessary.
308 GrSwizzle swizzle;
309 swizzle.setFromKey(this->desc().header().fOutputSwizzle);
310 if (swizzle != GrSwizzle::RGBA()) {
311 fFS.codeAppendf("%s = %s.%s;", fFS.getPrimaryColorOutputName(),
312 fFS.getPrimaryColorOutputName(),
313 swizzle.c_str());
314 if (hasSecondaryOutput) {
315 fFS.codeAppendf("%s = %s.%s;", fFS.getSecondaryColorOutputName(),
316 fFS.getSecondaryColorOutputName(),
317 swizzle.c_str());
318 }
319 }
320}
321
cdalton9c3f1432016-03-11 10:07:37 -0800322bool GrGLSLProgramBuilder::checkSamplerCounts() {
323 const GrGLSLCaps& glslCaps = *this->glslCaps();
324 if (fNumVertexSamplers > glslCaps.maxVertexSamplers()) {
325 GrCapsDebugf(this->caps(), "Program would use too many vertex samplers\n");
326 return false;
327 }
328 if (fNumGeometrySamplers > glslCaps.maxGeometrySamplers()) {
329 GrCapsDebugf(this->caps(), "Program would use too many geometry samplers\n");
330 return false;
331 }
332 if (fNumFragmentSamplers > glslCaps.maxFragmentSamplers()) {
333 GrCapsDebugf(this->caps(), "Program would use too many fragment samplers\n");
334 return false;
335 }
336 // If the same sampler is used in two different shaders, it counts as two combined samplers.
337 int numCombinedSamplers = fNumVertexSamplers + fNumGeometrySamplers + fNumFragmentSamplers;
338 if (numCombinedSamplers > glslCaps.maxCombinedSamplers()) {
339 GrCapsDebugf(this->caps(), "Program would use too many combined samplers\n");
340 return false;
341 }
342 return true;
343}
344
cdalton87332102016-02-26 12:22:02 -0800345#ifdef SK_DEBUG
egdanielfa896322016-01-13 12:19:30 -0800346void GrGLSLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
cdalton87332102016-02-26 12:22:02 -0800347 SkASSERT(fFS.usedProcessorFeatures() == gp.requiredFeatures());
egdanielfa896322016-01-13 12:19:30 -0800348}
349
350void GrGLSLProgramBuilder::verify(const GrXferProcessor& xp) {
cdalton87332102016-02-26 12:22:02 -0800351 SkASSERT(fFS.usedProcessorFeatures() == xp.requiredFeatures());
egdanielfa896322016-01-13 12:19:30 -0800352 SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor());
353}
354
355void GrGLSLProgramBuilder::verify(const GrFragmentProcessor& fp) {
cdalton87332102016-02-26 12:22:02 -0800356 SkASSERT(fFS.usedProcessorFeatures() == fp.requiredFeatures());
egdaniel8dcdedc2015-11-11 06:27:20 -0800357}
cdalton87332102016-02-26 12:22:02 -0800358#endif
egdaniel8dcdedc2015-11-11 06:27:20 -0800359
360void GrGLSLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name, bool mangle) {
361 if ('\0' == prefix) {
362 *out = name;
363 } else {
364 out->printf("%c%s", prefix, name);
365 }
366 if (mangle) {
367 if (out->endsWith('_')) {
368 // Names containing "__" are reserved.
369 out->append("x");
370 }
371 out->appendf("_Stage%d%s", fStageIndex, fFS.getMangleString().c_str());
372 }
373}
374
egdanielfa896322016-01-13 12:19:30 -0800375void GrGLSLProgramBuilder::nameExpression(GrGLSLExpr4* output, const char* baseName) {
376 // create var to hold stage result. If we already have a valid output name, just use that
377 // otherwise create a new mangled one. This name is only valid if we are reordering stages
378 // and have to tell stage exactly where to put its output.
379 SkString outName;
380 if (output->isValid()) {
381 outName = output->c_str();
382 } else {
383 this->nameVariable(&outName, '\0', baseName);
384 }
385 fFS.codeAppendf("vec4 %s;", outName.c_str());
386 *output = outName;
387}
388
cdalton5e58cee2016-02-11 12:49:47 -0800389void GrGLSLProgramBuilder::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
egdaniel7ea439b2015-12-03 09:20:44 -0800390 this->uniformHandler()->appendUniformDecls(visibility, out);
391}
392
egdaniel09aa1fc2016-04-20 07:09:46 -0700393const GrGLSLSampler& GrGLSLProgramBuilder::getSampler(SamplerHandle handle) const {
394 return this->uniformHandler()->getSampler(handle);
395}
396
egdaniel7ea439b2015-12-03 09:20:44 -0800397void GrGLSLProgramBuilder::addRTAdjustmentUniform(GrSLPrecision precision,
398 const char* name,
399 const char** outName) {
400 SkASSERT(!fUniformHandles.fRTAdjustmentUni.isValid());
401 fUniformHandles.fRTAdjustmentUni =
cdalton5e58cee2016-02-11 12:49:47 -0800402 this->uniformHandler()->addUniform(kVertex_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800403 kVec4f_GrSLType,
404 precision,
405 name,
406 outName);
407}
408
409void GrGLSLProgramBuilder::addRTHeightUniform(const char* name, const char** outName) {
410 SkASSERT(!fUniformHandles.fRTHeightUni.isValid());
411 GrGLSLUniformHandler* uniformHandler = this->uniformHandler();
412 fUniformHandles.fRTHeightUni =
cdalton5e58cee2016-02-11 12:49:47 -0800413 uniformHandler->internalAddUniformArray(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800414 kFloat_GrSLType, kDefault_GrSLPrecision,
415 name, false, 0, outName);
egdaniel8dcdedc2015-11-11 06:27:20 -0800416}
417
egdanielfa896322016-01-13 12:19:30 -0800418void GrGLSLProgramBuilder::cleanupFragmentProcessors() {
419 for (int i = 0; i < fFragmentProcessors.count(); ++i) {
420 delete fFragmentProcessors[i];
421 }
422}
423
egdaniel9f1d4152016-02-10 09:50:38 -0800424void GrGLSLProgramBuilder::finalizeShaders() {
425 this->varyingHandler()->finalize();
cdalton5e58cee2016-02-11 12:49:47 -0800426 fVS.finalize(kVertex_GrShaderFlag);
427 fFS.finalize(kFragment_GrShaderFlag);
egdaniel9f1d4152016-02-10 09:50:38 -0800428}