1 /* 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 10 #include "GrCaps.h" 11 #include "GrPipeline.h" 12 #include "GrShaderCaps.h" 13 #include "GrTexturePriv.h" 14 #include "glsl/GrGLSLFragmentProcessor.h" 15 #include "glsl/GrGLSLGeometryProcessor.h" 16 #include "glsl/GrGLSLVarying.h" 17 #include "glsl/GrGLSLXferProcessor.h" 18 #include "SkSLCompiler.h" 19 20 const int GrGLSLProgramBuilder::kVarsPerBlock = 8; 21 22 GrGLSLProgramBuilder::GrGLSLProgramBuilder(const GrPipeline& pipeline, 23 const GrPrimitiveProcessor& primProc, 24 GrProgramDesc* desc) 25 : fVS(this) 26 , fGS(this) 27 , fFS(this) 28 , fStageIndex(-1) 29 , fPipeline(pipeline) 30 , fPrimProc(primProc) 31 , fDesc(desc) 32 , fGeometryProcessor(nullptr) 33 , fXferProcessor(nullptr) 34 , fNumVertexSamplers(0) 35 , fNumGeometrySamplers(0) 36 , fNumFragmentSamplers(0) { 37 } 38 39 void GrGLSLProgramBuilder::addFeature(GrShaderFlags shaders, 40 uint32_t featureBit, 41 const char* extensionName) { 42 if (shaders & kVertex_GrShaderFlag) { 43 fVS.addFeature(featureBit, extensionName); 44 } 45 if (shaders & kGeometry_GrShaderFlag) { 46 SkASSERT(this->primitiveProcessor().willUseGeoShader()); 47 fGS.addFeature(featureBit, extensionName); 48 } 49 if (shaders & kFragment_GrShaderFlag) { 50 fFS.addFeature(featureBit, extensionName); 51 } 52 } 53 54 bool GrGLSLProgramBuilder::emitAndInstallProcs() { 55 // First we loop over all of the installed processors and collect coord transforms. These will 56 // be sent to the GrGLSLPrimitiveProcessor in its emitCode function 57 const GrPrimitiveProcessor& primProc = this->primitiveProcessor(); 58 59 SkString inputColor; 60 SkString inputCoverage; 61 this->emitAndInstallPrimProc(primProc, &inputColor, &inputCoverage); 62 this->emitAndInstallFragProcs(&inputColor, &inputCoverage); 63 this->emitAndInstallXferProc(inputColor, inputCoverage); 64 this->emitFSOutputSwizzle(this->pipeline().getXferProcessor().hasSecondaryOutput()); 65 66 return this->checkSamplerCounts(); 67 } 68 69 void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& proc, 70 SkString* outputColor, 71 SkString* outputCoverage) { 72 // Program builders have a bit of state we need to clear with each effect 73 AutoStageAdvance adv(this); 74 this->nameExpression(outputColor, "outputColor"); 75 this->nameExpression(outputCoverage, "outputCoverage"); 76 77 SkASSERT(!fUniformHandles.fRTAdjustmentUni.isValid()); 78 GrShaderFlags rtAdjustVisibility; 79 if (proc.willUseGeoShader()) { 80 rtAdjustVisibility = kGeometry_GrShaderFlag; 81 } else { 82 rtAdjustVisibility = kVertex_GrShaderFlag; 83 } 84 fUniformHandles.fRTAdjustmentUni = this->uniformHandler()->addUniform( 85 rtAdjustVisibility, 86 kFloat4_GrSLType, 87 SkSL::Compiler::RTADJUST_NAME); 88 const char* rtAdjustName = 89 this->uniformHandler()->getUniformCStr(fUniformHandles.fRTAdjustmentUni); 90 91 // Enclose custom code in a block to avoid namespace conflicts 92 SkString openBrace; 93 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name()); 94 fFS.codeAppend(openBrace.c_str()); 95 fVS.codeAppendf("// Primitive Processor %s\n", proc.name()); 96 97 SkASSERT(!fGeometryProcessor); 98 fGeometryProcessor.reset(proc.createGLSLInstance(*this->shaderCaps())); 99 100 SkSTArray<4, SamplerHandle> texSamplers(proc.numTextureSamplers()); 101 SkSTArray<2, TexelBufferHandle> texelBuffers(proc.numBuffers()); 102 this->emitSamplers(proc, &texSamplers, &texelBuffers); 103 104 GrGLSLPrimitiveProcessor::FPCoordTransformHandler transformHandler(fPipeline, 105 &fTransformedCoordVars); 106 GrGLSLGeometryProcessor::EmitArgs args(&fVS, 107 proc.willUseGeoShader() ? &fGS : nullptr, 108 &fFS, 109 this->varyingHandler(), 110 this->uniformHandler(), 111 this->shaderCaps(), 112 proc, 113 outputColor->c_str(), 114 outputCoverage->c_str(), 115 rtAdjustName, 116 texSamplers.begin(), 117 texelBuffers.begin(), 118 &transformHandler); 119 fGeometryProcessor->emitCode(args); 120 121 // We have to check that effects and the code they emit are consistent, ie if an effect 122 // asks for dst color, then the emit code needs to follow suit 123 SkDEBUGCODE(verify(proc);) 124 125 fFS.codeAppend("}"); 126 } 127 128 void GrGLSLProgramBuilder::emitAndInstallFragProcs(SkString* color, SkString* coverage) { 129 int transformedCoordVarsIdx = 0; 130 SkString** inOut = &color; 131 for (int i = 0; i < this->pipeline().numFragmentProcessors(); ++i) { 132 if (i == this->pipeline().numColorFragmentProcessors()) { 133 inOut = &coverage; 134 } 135 SkString output; 136 const GrFragmentProcessor& fp = this->pipeline().getFragmentProcessor(i); 137 output = this->emitAndInstallFragProc(fp, i, transformedCoordVarsIdx, **inOut, output); 138 GrFragmentProcessor::Iter iter(&fp); 139 while (const GrFragmentProcessor* fp = iter.next()) { 140 transformedCoordVarsIdx += fp->numCoordTransforms(); 141 } 142 **inOut = output; 143 } 144 } 145 146 // TODO Processors cannot output zeros because an empty string is all 1s 147 // the fix is to allow effects to take the SkString directly 148 SkString GrGLSLProgramBuilder::emitAndInstallFragProc(const GrFragmentProcessor& fp, 149 int index, 150 int transformedCoordVarsIdx, 151 const SkString& input, 152 SkString output) { 153 SkASSERT(input.size()); 154 // Program builders have a bit of state we need to clear with each effect 155 AutoStageAdvance adv(this); 156 this->nameExpression(&output, "output"); 157 158 // Enclose custom code in a block to avoid namespace conflicts 159 SkString openBrace; 160 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, fp.name()); 161 fFS.codeAppend(openBrace.c_str()); 162 163 GrGLSLFragmentProcessor* fragProc = fp.createGLSLInstance(); 164 165 SkSTArray<4, SamplerHandle> textureSamplerArray(fp.numTextureSamplers()); 166 SkSTArray<2, TexelBufferHandle> texelBufferArray(fp.numBuffers()); 167 GrFragmentProcessor::Iter iter(&fp); 168 while (const GrFragmentProcessor* subFP = iter.next()) { 169 this->emitSamplers(*subFP, &textureSamplerArray, &texelBufferArray); 170 } 171 172 const GrShaderVar* coordVars = fTransformedCoordVars.begin() + transformedCoordVarsIdx; 173 GrGLSLFragmentProcessor::TransformedCoordVars coords(&fp, coordVars); 174 GrGLSLFragmentProcessor::TextureSamplers textureSamplers(&fp, textureSamplerArray.begin()); 175 GrGLSLFragmentProcessor::TexelBuffers texelBuffers(&fp, texelBufferArray.begin()); 176 GrGLSLFragmentProcessor::EmitArgs args(&fFS, 177 this->uniformHandler(), 178 this->shaderCaps(), 179 fp, 180 output.c_str(), 181 input.c_str(), 182 coords, 183 textureSamplers, 184 texelBuffers); 185 186 fragProc->emitCode(args); 187 188 // We have to check that effects and the code they emit are consistent, ie if an effect 189 // asks for dst color, then the emit code needs to follow suit 190 SkDEBUGCODE(verify(fp);) 191 fFragmentProcessors.push_back(fragProc); 192 193 fFS.codeAppend("}"); 194 return output; 195 } 196 197 void GrGLSLProgramBuilder::emitAndInstallXferProc(const SkString& colorIn, 198 const SkString& coverageIn) { 199 // Program builders have a bit of state we need to clear with each effect 200 AutoStageAdvance adv(this); 201 202 SkASSERT(!fXferProcessor); 203 const GrXferProcessor& xp = fPipeline.getXferProcessor(); 204 fXferProcessor.reset(xp.createGLSLInstance()); 205 206 // Enable dual source secondary output if we have one 207 if (xp.hasSecondaryOutput()) { 208 fFS.enableSecondaryOutput(); 209 } 210 211 if (this->shaderCaps()->mustDeclareFragmentShaderOutput()) { 212 fFS.enableCustomOutput(); 213 } 214 215 SkString openBrace; 216 openBrace.printf("{ // Xfer Processor: %s\n", xp.name()); 217 fFS.codeAppend(openBrace.c_str()); 218 219 SamplerHandle dstTextureSamplerHandle; 220 GrSurfaceOrigin dstTextureOrigin = kTopLeft_GrSurfaceOrigin; 221 222 if (GrTexture* dstTexture = fPipeline.peekDstTexture()) { 223 // GrProcessor::TextureSampler sampler(dstTexture); 224 SkString name("DstTextureSampler"); 225 dstTextureSamplerHandle = 226 this->emitSampler(dstTexture->texturePriv().samplerType(), dstTexture->config(), 227 "DstTextureSampler", kFragment_GrShaderFlag); 228 dstTextureOrigin = fPipeline.dstTextureProxy()->origin(); 229 SkASSERT(kTextureExternalSampler_GrSLType != dstTexture->texturePriv().samplerType()); 230 } 231 232 GrGLSLXferProcessor::EmitArgs args(&fFS, 233 this->uniformHandler(), 234 this->shaderCaps(), 235 xp, 236 colorIn.size() ? colorIn.c_str() : "float4(1)", 237 coverageIn.size() ? coverageIn.c_str() : "float4(1)", 238 fFS.getPrimaryColorOutputName(), 239 fFS.getSecondaryColorOutputName(), 240 dstTextureSamplerHandle, 241 dstTextureOrigin); 242 fXferProcessor->emitCode(args); 243 244 // We have to check that effects and the code they emit are consistent, ie if an effect 245 // asks for dst color, then the emit code needs to follow suit 246 SkDEBUGCODE(verify(xp);) 247 fFS.codeAppend("}"); 248 } 249 250 void GrGLSLProgramBuilder::emitSamplers( 251 const GrResourceIOProcessor& processor, 252 SkTArray<SamplerHandle>* outTexSamplerHandles, 253 SkTArray<TexelBufferHandle>* outTexelBufferHandles) { 254 SkString name; 255 int numTextureSamplers = processor.numTextureSamplers(); 256 for (int t = 0; t < numTextureSamplers; ++t) { 257 const GrResourceIOProcessor::TextureSampler& sampler = processor.textureSampler(t); 258 name.printf("TextureSampler_%d", outTexSamplerHandles->count()); 259 GrSLType samplerType = sampler.peekTexture()->texturePriv().samplerType(); 260 if (kTextureExternalSampler_GrSLType == samplerType) { 261 const char* externalFeatureString = 262 this->shaderCaps()->externalTextureExtensionString(); 263 // We shouldn't ever create a GrGLTexture that requires external sampler type 264 SkASSERT(externalFeatureString); 265 this->addFeature(sampler.visibility(), 266 1 << GrGLSLShaderBuilder::kExternalTexture_GLSLPrivateFeature, 267 externalFeatureString); 268 } 269 outTexSamplerHandles->emplace_back(this->emitSampler( 270 samplerType, sampler.peekTexture()->config(), name.c_str(), sampler.visibility())); 271 } 272 if (int numBuffers = processor.numBuffers()) { 273 SkASSERT(this->shaderCaps()->texelBufferSupport()); 274 GrShaderFlags texelBufferVisibility = kNone_GrShaderFlags; 275 276 for (int b = 0; b < numBuffers; ++b) { 277 const GrResourceIOProcessor::BufferAccess& access = processor.bufferAccess(b); 278 name.printf("TexelBuffer_%d", outTexelBufferHandles->count()); 279 outTexelBufferHandles->emplace_back( 280 this->emitTexelBuffer(access.texelConfig(), name.c_str(), access.visibility())); 281 texelBufferVisibility |= access.visibility(); 282 } 283 284 if (const char* extension = this->shaderCaps()->texelBufferExtensionString()) { 285 this->addFeature(texelBufferVisibility, 286 1 << GrGLSLShaderBuilder::kTexelBuffer_GLSLPrivateFeature, 287 extension); 288 } 289 } 290 } 291 292 void GrGLSLProgramBuilder::updateSamplerCounts(GrShaderFlags visibility) { 293 if (visibility & kVertex_GrShaderFlag) { 294 ++fNumVertexSamplers; 295 } 296 if (visibility & kGeometry_GrShaderFlag) { 297 SkASSERT(this->primitiveProcessor().willUseGeoShader()); 298 ++fNumGeometrySamplers; 299 } 300 if (visibility & kFragment_GrShaderFlag) { 301 ++fNumFragmentSamplers; 302 } 303 } 304 305 GrGLSLProgramBuilder::SamplerHandle GrGLSLProgramBuilder::emitSampler(GrSLType samplerType, 306 GrPixelConfig config, 307 const char* name, 308 GrShaderFlags visibility) { 309 this->updateSamplerCounts(visibility); 310 GrSLPrecision precision = GrSLSamplerPrecision(config); 311 GrSwizzle swizzle = this->shaderCaps()->configTextureSwizzle(config); 312 return this->uniformHandler()->addSampler(visibility, swizzle, samplerType, precision, name); 313 } 314 315 GrGLSLProgramBuilder::TexelBufferHandle GrGLSLProgramBuilder::emitTexelBuffer( 316 GrPixelConfig config, const char* name, GrShaderFlags visibility) { 317 this->updateSamplerCounts(visibility); 318 GrSLPrecision precision = GrSLSamplerPrecision(config); 319 return this->uniformHandler()->addTexelBuffer(visibility, precision, name); 320 } 321 322 void GrGLSLProgramBuilder::emitFSOutputSwizzle(bool hasSecondaryOutput) { 323 // Swizzle the fragment shader outputs if necessary. 324 GrSwizzle swizzle; 325 swizzle.setFromKey(this->desc()->header().fOutputSwizzle); 326 if (swizzle != GrSwizzle::RGBA()) { 327 fFS.codeAppendf("%s = %s.%s;", fFS.getPrimaryColorOutputName(), 328 fFS.getPrimaryColorOutputName(), 329 swizzle.c_str()); 330 if (hasSecondaryOutput) { 331 fFS.codeAppendf("%s = %s.%s;", fFS.getSecondaryColorOutputName(), 332 fFS.getSecondaryColorOutputName(), 333 swizzle.c_str()); 334 } 335 } 336 } 337 338 bool GrGLSLProgramBuilder::checkSamplerCounts() { 339 const GrShaderCaps& shaderCaps = *this->shaderCaps(); 340 if (fNumVertexSamplers > shaderCaps.maxVertexSamplers()) { 341 GrCapsDebugf(this->caps(), "Program would use too many vertex samplers\n"); 342 return false; 343 } 344 if (fNumGeometrySamplers > shaderCaps.maxGeometrySamplers()) { 345 GrCapsDebugf(this->caps(), "Program would use too many geometry samplers\n"); 346 return false; 347 } 348 if (fNumFragmentSamplers > shaderCaps.maxFragmentSamplers()) { 349 GrCapsDebugf(this->caps(), "Program would use too many fragment samplers\n"); 350 return false; 351 } 352 // If the same sampler is used in two different shaders, it counts as two combined samplers. 353 int numCombinedSamplers = fNumVertexSamplers + fNumGeometrySamplers + fNumFragmentSamplers; 354 if (numCombinedSamplers > shaderCaps.maxCombinedSamplers()) { 355 GrCapsDebugf(this->caps(), "Program would use too many combined samplers\n"); 356 return false; 357 } 358 return true; 359 } 360 361 #ifdef SK_DEBUG 362 void GrGLSLProgramBuilder::verify(const GrPrimitiveProcessor& gp) { 363 } 364 365 void GrGLSLProgramBuilder::verify(const GrXferProcessor& xp) { 366 SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor()); 367 } 368 369 void GrGLSLProgramBuilder::verify(const GrFragmentProcessor& fp) { 370 } 371 #endif 372 373 void GrGLSLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name, bool mangle) { 374 if ('\0' == prefix) { 375 *out = name; 376 } else { 377 out->printf("%c%s", prefix, name); 378 } 379 if (mangle) { 380 if (out->endsWith('_')) { 381 // Names containing "__" are reserved. 382 out->append("x"); 383 } 384 out->appendf("_Stage%d%s", fStageIndex, fFS.getMangleString().c_str()); 385 } 386 } 387 388 void GrGLSLProgramBuilder::nameExpression(SkString* output, const char* baseName) { 389 // create var to hold stage result. If we already have a valid output name, just use that 390 // otherwise create a new mangled one. This name is only valid if we are reordering stages 391 // and have to tell stage exactly where to put its output. 392 SkString outName; 393 if (output->size()) { 394 outName = output->c_str(); 395 } else { 396 this->nameVariable(&outName, '\0', baseName); 397 } 398 fFS.codeAppendf("half4 %s;", outName.c_str()); 399 *output = outName; 400 } 401 402 void GrGLSLProgramBuilder::appendUniformDecls(GrShaderFlags visibility, SkString* out) const { 403 this->uniformHandler()->appendUniformDecls(visibility, out); 404 } 405 406 void GrGLSLProgramBuilder::addRTHeightUniform(const char* name) { 407 SkASSERT(!fUniformHandles.fRTHeightUni.isValid()); 408 GrGLSLUniformHandler* uniformHandler = this->uniformHandler(); 409 fUniformHandles.fRTHeightUni = 410 uniformHandler->internalAddUniformArray(kFragment_GrShaderFlag, 411 kHalf_GrSLType, kDefault_GrSLPrecision, 412 name, false, 0, nullptr); 413 } 414 415 void GrGLSLProgramBuilder::cleanupFragmentProcessors() { 416 for (int i = 0; i < fFragmentProcessors.count(); ++i) { 417 delete fFragmentProcessors[i]; 418 } 419 } 420 421 void GrGLSLProgramBuilder::finalizeShaders() { 422 this->varyingHandler()->finalize(); 423 fVS.finalize(kVertex_GrShaderFlag); 424 if (this->primitiveProcessor().willUseGeoShader()) { 425 SkASSERT(this->shaderCaps()->geometryShaderSupport()); 426 fGS.finalize(kGeometry_GrShaderFlag); 427 } 428 fFS.finalize(kFragment_GrShaderFlag); 429 } 430