blob: 40e5a43dedeeae8abe398cf45c2640dfbbbb25ca [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
Brian Salomon94efbf52016-11-29 13:43:05 -050010#include "GrCaps.h"
egdanielfa896322016-01-13 12:19:30 -080011#include "GrPipeline.h"
Brian Salomon94efbf52016-11-29 13:43:05 -050012#include "GrShaderCaps.h"
Brian Salomon739c5bf2016-11-07 09:53:44 -050013#include "GrTexturePriv.h"
egdanielfa896322016-01-13 12:19:30 -080014#include "glsl/GrGLSLFragmentProcessor.h"
15#include "glsl/GrGLSLGeometryProcessor.h"
egdaniel9f1d4152016-02-10 09:50:38 -080016#include "glsl/GrGLSLVarying.h"
egdanielfa896322016-01-13 12:19:30 -080017#include "glsl/GrGLSLXferProcessor.h"
18
egdaniel8dcdedc2015-11-11 06:27:20 -080019const int GrGLSLProgramBuilder::kVarsPerBlock = 8;
20
egdaniel0e1853c2016-03-17 11:35:45 -070021GrGLSLProgramBuilder::GrGLSLProgramBuilder(const GrPipeline& pipeline,
22 const GrPrimitiveProcessor& primProc,
23 const GrProgramDesc& desc)
egdaniel8dcdedc2015-11-11 06:27:20 -080024 : fVS(this)
25 , fGS(this)
cdalton28f45b92016-03-07 13:58:26 -080026 , fFS(this)
egdaniel8dcdedc2015-11-11 06:27:20 -080027 , fStageIndex(-1)
egdaniel0e1853c2016-03-17 11:35:45 -070028 , fPipeline(pipeline)
29 , fPrimProc(primProc)
30 , fDesc(desc)
egdanielfa896322016-01-13 12:19:30 -080031 , fGeometryProcessor(nullptr)
cdalton9c3f1432016-03-11 10:07:37 -080032 , fXferProcessor(nullptr)
cdalton9c3f1432016-03-11 10:07:37 -080033 , fNumVertexSamplers(0)
34 , fNumGeometrySamplers(0)
Brian Salomonf9f45122016-11-29 11:59:17 -050035 , fNumFragmentSamplers(0)
36 , fNumVertexImageStorages(0)
37 , fNumGeometryImageStorages(0)
38 , fNumFragmentImageStorages(0) {
cdalton9c3f1432016-03-11 10:07:37 -080039}
40
41void GrGLSLProgramBuilder::addFeature(GrShaderFlags shaders,
42 uint32_t featureBit,
43 const char* extensionName) {
44 if (shaders & kVertex_GrShaderFlag) {
45 fVS.addFeature(featureBit, extensionName);
46 }
47 if (shaders & kGeometry_GrShaderFlag) {
csmartdalton276cc412016-11-21 11:55:00 -070048 SkASSERT(this->primitiveProcessor().willUseGeoShader());
cdalton9c3f1432016-03-11 10:07:37 -080049 fGS.addFeature(featureBit, extensionName);
50 }
51 if (shaders & kFragment_GrShaderFlag) {
52 fFS.addFeature(featureBit, extensionName);
53 }
egdanielfa896322016-01-13 12:19:30 -080054}
55
56bool GrGLSLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor,
cdalton9c3f1432016-03-11 10:07:37 -080057 GrGLSLExpr4* inputCoverage) {
egdanielfa896322016-01-13 12:19:30 -080058 // First we loop over all of the installed processors and collect coord transforms. These will
59 // be sent to the GrGLSLPrimitiveProcessor in its emitCode function
60 const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
egdanielfa896322016-01-13 12:19:30 -080061
egdanielfa896322016-01-13 12:19:30 -080062 this->emitAndInstallPrimProc(primProc, inputColor, inputCoverage);
63
bsalomona624bf32016-09-20 09:12:47 -070064 this->emitAndInstallFragProcs(inputColor, inputCoverage);
halcanary9d524f22016-03-29 09:03:52 -070065 if (primProc.getPixelLocalStorageState() !=
ethannicholas22793252016-01-30 09:59:10 -080066 GrPixelLocalStorageState::kDraw_GrPixelLocalStorageState) {
halcanary9d524f22016-03-29 09:03:52 -070067 this->emitAndInstallXferProc(this->pipeline().getXferProcessor(), *inputColor,
ethannicholas22793252016-01-30 09:59:10 -080068 *inputCoverage, this->pipeline().ignoresCoverage(),
69 primProc.getPixelLocalStorageState());
70 this->emitFSOutputSwizzle(this->pipeline().getXferProcessor().hasSecondaryOutput());
71 }
cdalton9c3f1432016-03-11 10:07:37 -080072
Brian Salomonf9f45122016-11-29 11:59:17 -050073 return this->checkSamplerCounts() && this->checkImageStorageCounts();
egdanielfa896322016-01-13 12:19:30 -080074}
75
76void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& proc,
77 GrGLSLExpr4* outputColor,
78 GrGLSLExpr4* outputCoverage) {
79 // Program builders have a bit of state we need to clear with each effect
80 AutoStageAdvance adv(this);
81 this->nameExpression(outputColor, "outputColor");
82 this->nameExpression(outputCoverage, "outputCoverage");
83
dvonbeck9b03e7b2016-08-01 11:01:56 -070084 const char* distanceVectorName = nullptr;
85 if (this->fPipeline.usesDistanceVectorField() && proc.implementsDistanceVector()) {
robertphillips05a4cf52016-09-08 09:02:43 -070086 // Each individual user (FP) of the distance vector must be able to handle having this
87 // variable be undeclared. There is no single default value that will yield a reasonable
88 // result for all users.
dvonbeck9b03e7b2016-08-01 11:01:56 -070089 distanceVectorName = fFS.distanceVectorName();
dvonbeckee920632016-08-11 14:17:59 -070090 fFS.codeAppend( "// Normalized vector to the closest geometric edge (in device space)\n");
dvonbeck84bca782016-08-08 11:47:12 -070091 fFS.codeAppend( "// Distance to the edge encoded in the z-component\n");
jvanverth6c177a12016-08-17 07:59:41 -070092 fFS.codeAppendf("vec4 %s;", distanceVectorName);
dvonbeck9b03e7b2016-08-01 11:01:56 -070093 }
94
egdanielfa896322016-01-13 12:19:30 -080095 // Enclose custom code in a block to avoid namespace conflicts
96 SkString openBrace;
97 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name());
98 fFS.codeAppend(openBrace.c_str());
99 fVS.codeAppendf("// Primitive Processor %s\n", proc.name());
100
101 SkASSERT(!fGeometryProcessor);
Brian Salomon94efbf52016-11-29 13:43:05 -0500102 fGeometryProcessor = proc.createGLSLInstance(*this->shaderCaps());
egdanielfa896322016-01-13 12:19:30 -0800103
Brian Salomonf9f45122016-11-29 11:59:17 -0500104 SkSTArray<4, SamplerHandle> texSamplers(proc.numTextureSamplers());
105 SkSTArray<2, SamplerHandle> bufferSamplers(proc.numBuffers());
106 SkSTArray<2, ImageStorageHandle> imageStorages(proc.numImageStorages());
107 this->emitSamplersAndImageStorages(proc, &texSamplers, &bufferSamplers, &imageStorages);
egdanielfa896322016-01-13 12:19:30 -0800108
bsalomona624bf32016-09-20 09:12:47 -0700109 GrGLSLPrimitiveProcessor::FPCoordTransformHandler transformHandler(fPipeline,
110 &fTransformedCoordVars);
egdanielfa896322016-01-13 12:19:30 -0800111 GrGLSLGeometryProcessor::EmitArgs args(&fVS,
csmartdalton276cc412016-11-21 11:55:00 -0700112 proc.willUseGeoShader() ? &fGS : nullptr,
egdanielfa896322016-01-13 12:19:30 -0800113 &fFS,
114 this->varyingHandler(),
115 this->uniformHandler(),
Brian Salomon94efbf52016-11-29 13:43:05 -0500116 this->shaderCaps(),
egdanielfa896322016-01-13 12:19:30 -0800117 proc,
118 outputColor->c_str(),
119 outputCoverage->c_str(),
dvonbeck9b03e7b2016-08-01 11:01:56 -0700120 distanceVectorName,
egdaniel09aa1fc2016-04-20 07:09:46 -0700121 texSamplers.begin(),
122 bufferSamplers.begin(),
Brian Salomonf9f45122016-11-29 11:59:17 -0500123 imageStorages.begin(),
bsalomona624bf32016-09-20 09:12:47 -0700124 &transformHandler);
egdanielfa896322016-01-13 12:19:30 -0800125 fGeometryProcessor->emitCode(args);
126
127 // We have to check that effects and the code they emit are consistent, ie if an effect
128 // asks for dst color, then the emit code needs to follow suit
cdalton87332102016-02-26 12:22:02 -0800129 SkDEBUGCODE(verify(proc);)
egdanielfa896322016-01-13 12:19:30 -0800130
131 fFS.codeAppend("}");
132}
133
bsalomona624bf32016-09-20 09:12:47 -0700134void GrGLSLProgramBuilder::emitAndInstallFragProcs(GrGLSLExpr4* color, GrGLSLExpr4* coverage) {
135 int transformedCoordVarsIdx = 0;
136 GrGLSLExpr4** inOut = &color;
137 for (int i = 0; i < this->pipeline().numFragmentProcessors(); ++i) {
138 if (i == this->pipeline().numColorFragmentProcessors()) {
139 inOut = &coverage;
140 }
egdanielfa896322016-01-13 12:19:30 -0800141 GrGLSLExpr4 output;
142 const GrFragmentProcessor& fp = this->pipeline().getFragmentProcessor(i);
bsalomona624bf32016-09-20 09:12:47 -0700143 this->emitAndInstallFragProc(fp, i, transformedCoordVarsIdx, **inOut, &output);
144 GrFragmentProcessor::Iter iter(&fp);
145 while (const GrFragmentProcessor* fp = iter.next()) {
146 transformedCoordVarsIdx += fp->numCoordTransforms();
147 }
148 **inOut = output;
egdanielfa896322016-01-13 12:19:30 -0800149 }
150}
151
152// TODO Processors cannot output zeros because an empty string is all 1s
153// the fix is to allow effects to take the GrGLSLExpr4 directly
154void GrGLSLProgramBuilder::emitAndInstallFragProc(const GrFragmentProcessor& fp,
155 int index,
bsalomona624bf32016-09-20 09:12:47 -0700156 int transformedCoordVarsIdx,
egdanielfa896322016-01-13 12:19:30 -0800157 const GrGLSLExpr4& input,
158 GrGLSLExpr4* output) {
159 // Program builders have a bit of state we need to clear with each effect
160 AutoStageAdvance adv(this);
161 this->nameExpression(output, "output");
162
163 // Enclose custom code in a block to avoid namespace conflicts
164 SkString openBrace;
165 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, fp.name());
166 fFS.codeAppend(openBrace.c_str());
167
168 GrGLSLFragmentProcessor* fragProc = fp.createGLSLInstance();
169
Brian Salomon0bbecb22016-11-17 11:38:22 -0500170 SkSTArray<4, SamplerHandle> textureSamplerArray(fp.numTextureSamplers());
bsalomonb58a2b42016-09-26 06:55:02 -0700171 SkSTArray<2, SamplerHandle> bufferSamplerArray(fp.numBuffers());
Brian Salomonf9f45122016-11-29 11:59:17 -0500172 SkSTArray<2, ImageStorageHandle> imageStorageArray(fp.numImageStorages());
bsalomonb58a2b42016-09-26 06:55:02 -0700173 GrFragmentProcessor::Iter iter(&fp);
174 while (const GrFragmentProcessor* subFP = iter.next()) {
Brian Salomonf9f45122016-11-29 11:59:17 -0500175 this->emitSamplersAndImageStorages(*subFP, &textureSamplerArray, &bufferSamplerArray,
176 &imageStorageArray);
bsalomonb58a2b42016-09-26 06:55:02 -0700177 }
egdanielfa896322016-01-13 12:19:30 -0800178
bsalomona624bf32016-09-20 09:12:47 -0700179 const GrShaderVar* coordVars = fTransformedCoordVars.begin() + transformedCoordVarsIdx;
180 GrGLSLFragmentProcessor::TransformedCoordVars coords(&fp, coordVars);
bsalomonb58a2b42016-09-26 06:55:02 -0700181 GrGLSLFragmentProcessor::TextureSamplers textureSamplers(&fp, textureSamplerArray.begin());
182 GrGLSLFragmentProcessor::BufferSamplers bufferSamplers(&fp, bufferSamplerArray.begin());
Brian Salomonf9f45122016-11-29 11:59:17 -0500183 GrGLSLFragmentProcessor::ImageStorages imageStorages(&fp, imageStorageArray.begin());
egdanielfa896322016-01-13 12:19:30 -0800184 GrGLSLFragmentProcessor::EmitArgs args(&fFS,
185 this->uniformHandler(),
Brian Salomon94efbf52016-11-29 13:43:05 -0500186 this->shaderCaps(),
egdanielfa896322016-01-13 12:19:30 -0800187 fp,
188 output->c_str(),
189 input.isOnes() ? nullptr : input.c_str(),
bsalomona624bf32016-09-20 09:12:47 -0700190 coords,
bsalomonb58a2b42016-09-26 06:55:02 -0700191 textureSamplers,
192 bufferSamplers,
Brian Salomonf9f45122016-11-29 11:59:17 -0500193 imageStorages,
dvonbeck9b03e7b2016-08-01 11:01:56 -0700194 this->primitiveProcessor().implementsDistanceVector());
195
egdanielfa896322016-01-13 12:19:30 -0800196 fragProc->emitCode(args);
197
198 // We have to check that effects and the code they emit are consistent, ie if an effect
199 // asks for dst color, then the emit code needs to follow suit
cdalton87332102016-02-26 12:22:02 -0800200 SkDEBUGCODE(verify(fp);)
egdanielfa896322016-01-13 12:19:30 -0800201 fFragmentProcessors.push_back(fragProc);
202
203 fFS.codeAppend("}");
204}
205
206void GrGLSLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp,
207 const GrGLSLExpr4& colorIn,
208 const GrGLSLExpr4& coverageIn,
ethannicholas22793252016-01-30 09:59:10 -0800209 bool ignoresCoverage,
210 GrPixelLocalStorageState plsState) {
egdanielfa896322016-01-13 12:19:30 -0800211 // Program builders have a bit of state we need to clear with each effect
212 AutoStageAdvance adv(this);
213
214 SkASSERT(!fXferProcessor);
215 fXferProcessor = xp.createGLSLInstance();
216
217 // Enable dual source secondary output if we have one
218 if (xp.hasSecondaryOutput()) {
219 fFS.enableSecondaryOutput();
220 }
221
Brian Salomon94efbf52016-11-29 13:43:05 -0500222 if (this->shaderCaps()->mustDeclareFragmentShaderOutput()) {
egdanielfa896322016-01-13 12:19:30 -0800223 fFS.enableCustomOutput();
224 }
225
226 SkString openBrace;
227 openBrace.printf("{ // Xfer Processor: %s\n", xp.name());
228 fFS.codeAppend(openBrace.c_str());
229
Brian Salomonf9f45122016-11-29 11:59:17 -0500230 SkSTArray<4, SamplerHandle> texSamplers(xp.numTextureSamplers());
231 SkSTArray<2, SamplerHandle> bufferSamplers(xp.numBuffers());
232 SkSTArray<2, ImageStorageHandle> imageStorageArray(xp.numImageStorages());
233 this->emitSamplersAndImageStorages(xp, &texSamplers, &bufferSamplers, &imageStorageArray);
egdanielfa896322016-01-13 12:19:30 -0800234
ethannicholas22793252016-01-30 09:59:10 -0800235 bool usePLSDstRead = (plsState == GrPixelLocalStorageState::kFinish_GrPixelLocalStorageState);
egdanielfa896322016-01-13 12:19:30 -0800236 GrGLSLXferProcessor::EmitArgs args(&fFS,
237 this->uniformHandler(),
Brian Salomon94efbf52016-11-29 13:43:05 -0500238 this->shaderCaps(),
egdanielfa896322016-01-13 12:19:30 -0800239 xp, colorIn.c_str(),
240 ignoresCoverage ? nullptr : coverageIn.c_str(),
241 fFS.getPrimaryColorOutputName(),
242 fFS.getSecondaryColorOutputName(),
egdaniel09aa1fc2016-04-20 07:09:46 -0700243 texSamplers.begin(),
244 bufferSamplers.begin(),
Brian Salomonf9f45122016-11-29 11:59:17 -0500245 imageStorageArray.begin(),
ethannicholas22793252016-01-30 09:59:10 -0800246 usePLSDstRead);
egdanielfa896322016-01-13 12:19:30 -0800247 fXferProcessor->emitCode(args);
248
249 // We have to check that effects and the code they emit are consistent, ie if an effect
250 // asks for dst color, then the emit code needs to follow suit
cdalton87332102016-02-26 12:22:02 -0800251 SkDEBUGCODE(verify(xp);)
egdanielfa896322016-01-13 12:19:30 -0800252 fFS.codeAppend("}");
253}
254
Brian Salomonf9f45122016-11-29 11:59:17 -0500255void GrGLSLProgramBuilder::emitSamplersAndImageStorages(
256 const GrProcessor& processor,
257 SkTArray<SamplerHandle>* outTexSamplerHandles,
258 SkTArray<SamplerHandle>* outBufferSamplerHandles,
259 SkTArray<ImageStorageHandle>* outImageStorageHandles) {
cdalton9c3f1432016-03-11 10:07:37 -0800260 SkString name;
Brian Salomon0bbecb22016-11-17 11:38:22 -0500261 int numTextureSamplers = processor.numTextureSamplers();
262 for (int t = 0; t < numTextureSamplers; ++t) {
263 const GrProcessor::TextureSampler& sampler = processor.textureSampler(t);
Brian Salomonf9f45122016-11-29 11:59:17 -0500264 name.printf("TextureSampler_%d", outTexSamplerHandles->count());
Brian Salomondb4183d2016-11-17 12:48:40 -0500265 GrSLType samplerType = sampler.texture()->texturePriv().samplerType();
egdaniel990dbc82016-07-13 14:09:30 -0700266 if (kTextureExternalSampler_GrSLType == samplerType) {
Brian Salomon94efbf52016-11-29 13:43:05 -0500267 const char* externalFeatureString =
268 this->shaderCaps()->externalTextureExtensionString();
cdalton9c3f1432016-03-11 10:07:37 -0800269 // We shouldn't ever create a GrGLTexture that requires external sampler type
270 SkASSERT(externalFeatureString);
Brian Salomondb4183d2016-11-17 12:48:40 -0500271 this->addFeature(sampler.visibility(),
cdalton9c3f1432016-03-11 10:07:37 -0800272 1 << GrGLSLShaderBuilder::kExternalTexture_GLSLPrivateFeature,
273 externalFeatureString);
274 }
Brian Salomonf9f45122016-11-29 11:59:17 -0500275 this->emitSampler(samplerType, sampler.texture()->config(), name.c_str(),
276 sampler.visibility(), outTexSamplerHandles);
277
cdalton9c3f1432016-03-11 10:07:37 -0800278 }
cdalton74b8d322016-04-11 14:47:28 -0700279
280 if (int numBuffers = processor.numBuffers()) {
Brian Salomon94efbf52016-11-29 13:43:05 -0500281 SkASSERT(this->shaderCaps()->texelBufferSupport());
cdalton74b8d322016-04-11 14:47:28 -0700282 GrShaderFlags texelBufferVisibility = kNone_GrShaderFlags;
283
284 for (int b = 0; b < numBuffers; ++b) {
Brian Salomonb014cca2016-11-18 11:39:15 -0500285 const GrProcessor::BufferAccess& access = processor.bufferAccess(b);
Brian Salomonf9f45122016-11-29 11:59:17 -0500286 name.printf("BufferSampler_%d", outBufferSamplerHandles->count());
csmartdalton22458032016-11-16 11:28:16 -0700287 this->emitSampler(kBufferSampler_GrSLType, access.texelConfig(), name.c_str(),
Brian Salomonf9f45122016-11-29 11:59:17 -0500288 access.visibility(), outBufferSamplerHandles);
cdalton74b8d322016-04-11 14:47:28 -0700289 texelBufferVisibility |= access.visibility();
290 }
291
Brian Salomon94efbf52016-11-29 13:43:05 -0500292 if (const char* extension = this->shaderCaps()->texelBufferExtensionString()) {
cdalton74b8d322016-04-11 14:47:28 -0700293 this->addFeature(texelBufferVisibility,
294 1 << GrGLSLShaderBuilder::kTexelBuffer_GLSLPrivateFeature,
295 extension);
296 }
297 }
Brian Salomonf9f45122016-11-29 11:59:17 -0500298 int numImageStorages = processor.numImageStorages();
299 for (int i = 0; i < numImageStorages; ++i) {
300 const GrProcessor::ImageStorageAccess& imageStorageAccess = processor.imageStorageAccess(i);
301 name.printf("Image_%d", outImageStorageHandles->count());
302 this->emitImageStorage(imageStorageAccess, name.c_str(), outImageStorageHandles);
303 }
cdalton74b8d322016-04-11 14:47:28 -0700304}
305
306void GrGLSLProgramBuilder::emitSampler(GrSLType samplerType,
307 GrPixelConfig config,
308 const char* name,
309 GrShaderFlags visibility,
Brian Salomonf9f45122016-11-29 11:59:17 -0500310 SkTArray<SamplerHandle>* outSamplerHandles) {
cdalton74b8d322016-04-11 14:47:28 -0700311 if (visibility & kVertex_GrShaderFlag) {
312 ++fNumVertexSamplers;
313 }
314 if (visibility & kGeometry_GrShaderFlag) {
315 SkASSERT(this->primitiveProcessor().willUseGeoShader());
316 ++fNumGeometrySamplers;
317 }
318 if (visibility & kFragment_GrShaderFlag) {
319 ++fNumFragmentSamplers;
320 }
Brian Salomon94efbf52016-11-29 13:43:05 -0500321 GrSLPrecision precision = this->shaderCaps()->samplerPrecision(config, visibility);
322 GrSwizzle swizzle = this->shaderCaps()->configTextureSwizzle(config);
Brian Salomonf9f45122016-11-29 11:59:17 -0500323 outSamplerHandles->emplace_back(this->uniformHandler()->addSampler(visibility,
324 swizzle,
325 samplerType,
326 precision,
327 name));
328}
329
330void GrGLSLProgramBuilder::emitImageStorage(const GrProcessor::ImageStorageAccess& access,
331 const char* name,
332 SkTArray<ImageStorageHandle>* outImageStorageHandles) {
333 if (access.visibility() & kVertex_GrShaderFlag) {
334 ++fNumVertexImageStorages;
335 }
336 if (access.visibility() & kGeometry_GrShaderFlag) {
337 SkASSERT(this->primitiveProcessor().willUseGeoShader());
338 ++fNumGeometryImageStorages;
339 }
340 if (access.visibility() & kFragment_GrShaderFlag) {
341 ++fNumFragmentImageStorages;
342 }
343 GrSLType uniformType = access.texture()->texturePriv().imageStorageType();
344 ImageStorageHandle handle = this->uniformHandler()->addImageStorage(access.visibility(),
345 uniformType, access.format(), access.memoryModel(), access.restrict(), access.ioType(),
346 name);
347 outImageStorageHandles->emplace_back(handle);
cdalton9c3f1432016-03-11 10:07:37 -0800348}
349
egdanielfa896322016-01-13 12:19:30 -0800350void GrGLSLProgramBuilder::emitFSOutputSwizzle(bool hasSecondaryOutput) {
351 // Swizzle the fragment shader outputs if necessary.
352 GrSwizzle swizzle;
353 swizzle.setFromKey(this->desc().header().fOutputSwizzle);
354 if (swizzle != GrSwizzle::RGBA()) {
355 fFS.codeAppendf("%s = %s.%s;", fFS.getPrimaryColorOutputName(),
356 fFS.getPrimaryColorOutputName(),
357 swizzle.c_str());
358 if (hasSecondaryOutput) {
359 fFS.codeAppendf("%s = %s.%s;", fFS.getSecondaryColorOutputName(),
360 fFS.getSecondaryColorOutputName(),
361 swizzle.c_str());
362 }
363 }
364}
365
cdalton9c3f1432016-03-11 10:07:37 -0800366bool GrGLSLProgramBuilder::checkSamplerCounts() {
Brian Salomon94efbf52016-11-29 13:43:05 -0500367 const GrShaderCaps& glslCaps = *this->shaderCaps();
cdalton9c3f1432016-03-11 10:07:37 -0800368 if (fNumVertexSamplers > glslCaps.maxVertexSamplers()) {
369 GrCapsDebugf(this->caps(), "Program would use too many vertex samplers\n");
370 return false;
371 }
372 if (fNumGeometrySamplers > glslCaps.maxGeometrySamplers()) {
373 GrCapsDebugf(this->caps(), "Program would use too many geometry samplers\n");
374 return false;
375 }
376 if (fNumFragmentSamplers > glslCaps.maxFragmentSamplers()) {
377 GrCapsDebugf(this->caps(), "Program would use too many fragment samplers\n");
378 return false;
379 }
380 // If the same sampler is used in two different shaders, it counts as two combined samplers.
381 int numCombinedSamplers = fNumVertexSamplers + fNumGeometrySamplers + fNumFragmentSamplers;
382 if (numCombinedSamplers > glslCaps.maxCombinedSamplers()) {
383 GrCapsDebugf(this->caps(), "Program would use too many combined samplers\n");
384 return false;
385 }
386 return true;
387}
388
Brian Salomonf9f45122016-11-29 11:59:17 -0500389bool GrGLSLProgramBuilder::checkImageStorageCounts() {
Brian Salomon94efbf52016-11-29 13:43:05 -0500390 const GrShaderCaps& glslCaps = *this->shaderCaps();
Brian Salomonf9f45122016-11-29 11:59:17 -0500391 if (fNumVertexImageStorages > glslCaps.maxVertexImageStorages()) {
392 GrCapsDebugf(this->caps(), "Program would use too many vertex images\n");
393 return false;
394 }
395 if (fNumGeometryImageStorages > glslCaps.maxGeometryImageStorages()) {
396 GrCapsDebugf(this->caps(), "Program would use too many geometry images\n");
397 return false;
398 }
399 if (fNumFragmentImageStorages > glslCaps.maxFragmentImageStorages()) {
400 GrCapsDebugf(this->caps(), "Program would use too many fragment images\n");
401 return false;
402 }
403 // If the same image is used in two different shaders, it counts as two combined images.
404 int numCombinedImages = fNumVertexImageStorages + fNumGeometryImageStorages +
405 fNumFragmentImageStorages;
406 if (numCombinedImages > glslCaps.maxCombinedImageStorages()) {
407 GrCapsDebugf(this->caps(), "Program would use too many combined images\n");
408 return false;
409 }
410 return true;
411}
412
cdalton87332102016-02-26 12:22:02 -0800413#ifdef SK_DEBUG
egdanielfa896322016-01-13 12:19:30 -0800414void GrGLSLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
cdalton87332102016-02-26 12:22:02 -0800415 SkASSERT(fFS.usedProcessorFeatures() == gp.requiredFeatures());
egdanielfa896322016-01-13 12:19:30 -0800416}
417
418void GrGLSLProgramBuilder::verify(const GrXferProcessor& xp) {
cdalton87332102016-02-26 12:22:02 -0800419 SkASSERT(fFS.usedProcessorFeatures() == xp.requiredFeatures());
egdanielfa896322016-01-13 12:19:30 -0800420 SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor());
421}
422
423void GrGLSLProgramBuilder::verify(const GrFragmentProcessor& fp) {
cdalton87332102016-02-26 12:22:02 -0800424 SkASSERT(fFS.usedProcessorFeatures() == fp.requiredFeatures());
egdaniel8dcdedc2015-11-11 06:27:20 -0800425}
cdalton87332102016-02-26 12:22:02 -0800426#endif
egdaniel8dcdedc2015-11-11 06:27:20 -0800427
428void GrGLSLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name, bool mangle) {
429 if ('\0' == prefix) {
430 *out = name;
431 } else {
432 out->printf("%c%s", prefix, name);
433 }
434 if (mangle) {
435 if (out->endsWith('_')) {
436 // Names containing "__" are reserved.
437 out->append("x");
438 }
439 out->appendf("_Stage%d%s", fStageIndex, fFS.getMangleString().c_str());
440 }
441}
442
egdanielfa896322016-01-13 12:19:30 -0800443void GrGLSLProgramBuilder::nameExpression(GrGLSLExpr4* output, const char* baseName) {
444 // create var to hold stage result. If we already have a valid output name, just use that
445 // otherwise create a new mangled one. This name is only valid if we are reordering stages
446 // and have to tell stage exactly where to put its output.
447 SkString outName;
448 if (output->isValid()) {
449 outName = output->c_str();
450 } else {
451 this->nameVariable(&outName, '\0', baseName);
452 }
453 fFS.codeAppendf("vec4 %s;", outName.c_str());
454 *output = outName;
455}
456
cdalton5e58cee2016-02-11 12:49:47 -0800457void GrGLSLProgramBuilder::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
egdaniel7ea439b2015-12-03 09:20:44 -0800458 this->uniformHandler()->appendUniformDecls(visibility, out);
459}
460
461void GrGLSLProgramBuilder::addRTAdjustmentUniform(GrSLPrecision precision,
462 const char* name,
463 const char** outName) {
464 SkASSERT(!fUniformHandles.fRTAdjustmentUni.isValid());
465 fUniformHandles.fRTAdjustmentUni =
cdalton5e58cee2016-02-11 12:49:47 -0800466 this->uniformHandler()->addUniform(kVertex_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800467 kVec4f_GrSLType,
468 precision,
469 name,
470 outName);
471}
472
473void GrGLSLProgramBuilder::addRTHeightUniform(const char* name, const char** outName) {
474 SkASSERT(!fUniformHandles.fRTHeightUni.isValid());
475 GrGLSLUniformHandler* uniformHandler = this->uniformHandler();
476 fUniformHandles.fRTHeightUni =
cdalton5e58cee2016-02-11 12:49:47 -0800477 uniformHandler->internalAddUniformArray(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800478 kFloat_GrSLType, kDefault_GrSLPrecision,
479 name, false, 0, outName);
egdaniel8dcdedc2015-11-11 06:27:20 -0800480}
481
egdanielfa896322016-01-13 12:19:30 -0800482void GrGLSLProgramBuilder::cleanupFragmentProcessors() {
483 for (int i = 0; i < fFragmentProcessors.count(); ++i) {
484 delete fFragmentProcessors[i];
485 }
486}
487
egdaniel9f1d4152016-02-10 09:50:38 -0800488void GrGLSLProgramBuilder::finalizeShaders() {
489 this->varyingHandler()->finalize();
cdalton5e58cee2016-02-11 12:49:47 -0800490 fVS.finalize(kVertex_GrShaderFlag);
csmartdalton276cc412016-11-21 11:55:00 -0700491 if (this->primitiveProcessor().willUseGeoShader()) {
Brian Salomon94efbf52016-11-29 13:43:05 -0500492 SkASSERT(this->shaderCaps()->geometryShaderSupport());
csmartdalton276cc412016-11-21 11:55:00 -0700493 fGS.finalize(kGeometry_GrShaderFlag);
494 }
cdalton5e58cee2016-02-11 12:49:47 -0800495 fFS.finalize(kFragment_GrShaderFlag);
egdaniel9f1d4152016-02-10 09:50:38 -0800496}