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 "src/gpu/glsl/GrGLSLProgramBuilder.h" 9 10 #include <memory> 11 12 #include "src/gpu/GrCaps.h" 13 #include "src/gpu/GrFragmentProcessor.h" 14 #include "src/gpu/GrGeometryProcessor.h" 15 #include "src/gpu/GrPipeline.h" 16 #include "src/gpu/GrRenderTarget.h" 17 #include "src/gpu/GrShaderCaps.h" 18 #include "src/gpu/GrTexture.h" 19 #include "src/gpu/GrXferProcessor.h" 20 #include "src/gpu/effects/GrTextureEffect.h" 21 #include "src/gpu/glsl/GrGLSLVarying.h" 22 #include "src/sksl/SkSLCompiler.h" 23 #include "src/sksl/dsl/priv/DSLFPs.h" 24 25 const int GrGLSLProgramBuilder::kVarsPerBlock = 8; 26 GrGLSLProgramBuilder(const GrProgramDesc & desc,const GrProgramInfo & programInfo)27 GrGLSLProgramBuilder::GrGLSLProgramBuilder(const GrProgramDesc& desc, 28 const GrProgramInfo& programInfo) 29 : fVS(this) 30 , fFS(this) 31 , fDesc(desc) 32 , fProgramInfo(programInfo) 33 , fNumFragmentSamplers(0) {} 34 35 GrGLSLProgramBuilder::~GrGLSLProgramBuilder() = default; 36 addFeature(GrShaderFlags shaders,uint32_t featureBit,const char * extensionName)37 void GrGLSLProgramBuilder::addFeature(GrShaderFlags shaders, 38 uint32_t featureBit, 39 const char* extensionName) { 40 if (shaders & kVertex_GrShaderFlag) { 41 fVS.addFeature(featureBit, extensionName); 42 } 43 if (shaders & kFragment_GrShaderFlag) { 44 fFS.addFeature(featureBit, extensionName); 45 } 46 } 47 emitAndInstallProcs()48 bool GrGLSLProgramBuilder::emitAndInstallProcs() { 49 // First we loop over all of the installed processors and collect coord transforms. These will 50 // be sent to the ProgramImpl in its emitCode function 51 SkSL::dsl::Start(this->shaderCompiler()); 52 SkString inputColor; 53 SkString inputCoverage; 54 if (!this->emitAndInstallPrimProc(&inputColor, &inputCoverage)) { 55 return false; 56 } 57 if (!this->emitAndInstallDstTexture()) { 58 return false; 59 } 60 if (!this->emitAndInstallFragProcs(&inputColor, &inputCoverage)) { 61 return false; 62 } 63 if (!this->emitAndInstallXferProc(inputColor, inputCoverage)) { 64 return false; 65 } 66 fGPImpl->emitTransformCode(&fVS, this->uniformHandler()); 67 SkSL::dsl::End(); 68 69 return this->checkSamplerCounts(); 70 } 71 emitAndInstallPrimProc(SkString * outputColor,SkString * outputCoverage)72 bool GrGLSLProgramBuilder::emitAndInstallPrimProc(SkString* outputColor, SkString* outputCoverage) { 73 const GrGeometryProcessor& geomProc = this->geometryProcessor(); 74 75 // Program builders have a bit of state we need to clear with each effect 76 this->advanceStage(); 77 this->nameExpression(outputColor, "outputColor"); 78 this->nameExpression(outputCoverage, "outputCoverage"); 79 80 SkASSERT(!fUniformHandles.fRTAdjustmentUni.isValid()); 81 GrShaderFlags rtAdjustVisibility; 82 if (geomProc.willUseTessellationShaders()) { 83 rtAdjustVisibility = kTessEvaluation_GrShaderFlag; 84 } else { 85 rtAdjustVisibility = kVertex_GrShaderFlag; 86 } 87 fUniformHandles.fRTAdjustmentUni = this->uniformHandler()->addUniform( 88 nullptr, rtAdjustVisibility, kFloat4_GrSLType, SkSL::Compiler::RTADJUST_NAME); 89 90 fFS.codeAppendf("// Stage %d, %s\n", fStageIndex, geomProc.name()); 91 fVS.codeAppendf("// Primitive Processor %s\n", geomProc.name()); 92 93 SkASSERT(!fGPImpl); 94 fGPImpl = geomProc.makeProgramImpl(*this->shaderCaps()); 95 96 SkAutoSTArray<4, SamplerHandle> texSamplers(geomProc.numTextureSamplers()); 97 for (int i = 0; i < geomProc.numTextureSamplers(); ++i) { 98 SkString name; 99 name.printf("TextureSampler_%d", i); 100 const auto& sampler = geomProc.textureSampler(i); 101 texSamplers[i] = this->emitSampler(geomProc.textureSampler(i).backendFormat(), 102 sampler.samplerState(), 103 sampler.swizzle(), 104 name.c_str()); 105 if (!texSamplers[i].isValid()) { 106 return false; 107 } 108 } 109 110 GrGeometryProcessor::ProgramImpl::EmitArgs args(&fVS, 111 &fFS, 112 this->varyingHandler(), 113 this->uniformHandler(), 114 this->shaderCaps(), 115 geomProc, 116 outputColor->c_str(), 117 outputCoverage->c_str(), 118 texSamplers.get()); 119 fFPCoordsMap = fGPImpl->emitCode(args, this->pipeline()); 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(geomProc);) 124 125 return true; 126 } 127 emitAndInstallFragProcs(SkString * color,SkString * coverage)128 bool GrGLSLProgramBuilder::emitAndInstallFragProcs(SkString* color, SkString* coverage) { 129 int fpCount = this->pipeline().numFragmentProcessors(); 130 SkASSERT(fFPImpls.empty()); 131 fFPImpls.reserve(fpCount); 132 for (int i = 0; i < fpCount; ++i) { 133 SkString* inOut = this->pipeline().isColorFragmentProcessor(i) ? color : coverage; 134 SkString output; 135 const GrFragmentProcessor& fp = this->pipeline().getFragmentProcessor(i); 136 fFPImpls.push_back(fp.makeProgramImpl()); 137 output = this->emitFragProc(fp, *fFPImpls.back(), *inOut, output); 138 if (output.isEmpty()) { 139 return false; 140 } 141 *inOut = std::move(output); 142 } 143 return true; 144 } 145 emitFragProc(const GrFragmentProcessor & fp,GrFragmentProcessor::ProgramImpl & impl,const SkString & input,SkString output)146 SkString GrGLSLProgramBuilder::emitFragProc(const GrFragmentProcessor& fp, 147 GrFragmentProcessor::ProgramImpl& impl, 148 const SkString& input, 149 SkString output) { 150 SkASSERT(input.size()); 151 152 // Program builders have a bit of state we need to clear with each effect 153 this->advanceStage(); 154 this->nameExpression(&output, "output"); 155 fFS.codeAppendf("half4 %s;", output.c_str()); 156 bool ok = true; 157 fp.visitWithImpls([&, samplerIdx = 0](const GrFragmentProcessor& fp, 158 GrFragmentProcessor::ProgramImpl& impl) mutable { 159 if (auto* te = fp.asTextureEffect()) { 160 SkString name; 161 name.printf("TextureSampler_%d", samplerIdx++); 162 163 GrSamplerState samplerState = te->samplerState(); 164 const GrBackendFormat& format = te->view().proxy()->backendFormat(); 165 GrSwizzle swizzle = te->view().swizzle(); 166 SamplerHandle handle = this->emitSampler(format, samplerState, swizzle, name.c_str()); 167 if (!handle.isValid()) { 168 ok = false; 169 return; 170 } 171 static_cast<GrTextureEffect::Impl&>(impl).setSamplerHandle(handle); 172 } 173 }, impl); 174 if (!ok) { 175 return {}; 176 } 177 178 this->writeFPFunction(fp, impl); 179 180 if (fp.isBlendFunction()) { 181 fFS.codeAppendf( 182 "%s = %s(%s, half4(1));", output.c_str(), impl.functionName(), input.c_str()); 183 } else { 184 fFS.codeAppendf("%s = %s(%s);", output.c_str(), impl.functionName(), input.c_str()); 185 } 186 187 // We have to check that effects and the code they emit are consistent, ie if an effect asks 188 // for dst color, then the emit code needs to follow suit 189 SkDEBUGCODE(verify(fp);) 190 191 return output; 192 } 193 writeChildFPFunctions(const GrFragmentProcessor & fp,GrFragmentProcessor::ProgramImpl & impl)194 void GrGLSLProgramBuilder::writeChildFPFunctions(const GrFragmentProcessor& fp, 195 GrFragmentProcessor::ProgramImpl& impl) { 196 fSubstageIndices.push_back(0); 197 for (int i = 0; i < impl.numChildProcessors(); ++i) { 198 GrFragmentProcessor::ProgramImpl* childImpl = impl.childProcessor(i); 199 if (!childImpl) { 200 continue; 201 } 202 203 const GrFragmentProcessor* childFP = fp.childProcessor(i); 204 SkASSERT(childFP); 205 206 this->writeFPFunction(*childFP, *childImpl); 207 ++fSubstageIndices.back(); 208 } 209 fSubstageIndices.pop_back(); 210 } 211 writeFPFunction(const GrFragmentProcessor & fp,GrFragmentProcessor::ProgramImpl & impl)212 void GrGLSLProgramBuilder::writeFPFunction(const GrFragmentProcessor& fp, 213 GrFragmentProcessor::ProgramImpl& impl) { 214 constexpr const char* kDstColor = "_dst"; 215 const char* const inputColor = fp.isBlendFunction() ? "_src" : "_input"; 216 const char* sampleCoords = "_coords"; 217 fFS.nextStage(); 218 // Conceptually, an FP is always sampled at a particular coordinate. However, if it is only 219 // sampled by a chain of uniform matrix expressions (or legacy coord transforms), the value that 220 // would have been passed to _coords is lifted to the vertex shader and 221 // varying. In that case it uses that variable and we do not pass a second argument for _coords. 222 GrShaderVar params[3]; 223 int numParams = 0; 224 225 params[numParams++] = GrShaderVar(inputColor, kHalf4_GrSLType); 226 227 if (fp.isBlendFunction()) { 228 // Blend functions take a dest color as input. 229 params[numParams++] = GrShaderVar(kDstColor, kHalf4_GrSLType); 230 } 231 232 if (this->fragmentProcessorHasCoordsParam(&fp)) { 233 params[numParams++] = GrShaderVar(sampleCoords, kFloat2_GrSLType); 234 } else { 235 // Either doesn't use coords at all or sampled through a chain of passthrough/matrix 236 // samples usages. In the latter case the coords are emitted in the vertex shader as a 237 // varying, so this only has to access it. Add a float2 _coords variable that maps to the 238 // associated varying and replaces the absent 2nd argument to the fp's function. 239 GrShaderVar varying = fFPCoordsMap[&fp].coordsVarying; 240 241 switch (varying.getType()) { 242 case kVoid_GrSLType: 243 SkASSERT(!fp.usesSampleCoordsDirectly()); 244 break; 245 case kFloat2_GrSLType: 246 // Just point the local coords to the varying 247 sampleCoords = varying.getName().c_str(); 248 break; 249 case kFloat3_GrSLType: 250 // Must perform the perspective divide in the frag shader based on the 251 // varying, and since we won't actually have a function parameter for local 252 // coords, add it as a local variable. 253 fFS.codeAppendf("float2 %s = %s.xy / %s.z;\n", 254 sampleCoords, 255 varying.getName().c_str(), 256 varying.getName().c_str()); 257 break; 258 default: 259 SkDEBUGFAILF("Unexpected varying type for coord: %s %d\n", 260 varying.getName().c_str(), 261 (int)varying.getType()); 262 break; 263 } 264 } 265 266 SkASSERT(numParams <= (int)SK_ARRAY_COUNT(params)); 267 268 // First, emit every child's function. This needs to happen (even for children that aren't 269 // sampled), so that all of the expected uniforms are registered. 270 this->writeChildFPFunctions(fp, impl); 271 GrFragmentProcessor::ProgramImpl::EmitArgs args(&fFS, 272 this->uniformHandler(), 273 this->shaderCaps(), 274 fp, 275 inputColor, 276 kDstColor, 277 sampleCoords); 278 279 impl.emitCode(args); 280 impl.setFunctionName(fFS.getMangledFunctionName(args.fFp.name())); 281 282 fFS.emitFunction(kHalf4_GrSLType, 283 impl.functionName(), 284 SkMakeSpan(params, numParams), 285 fFS.code().c_str()); 286 fFS.deleteStage(); 287 } 288 emitAndInstallDstTexture()289 bool GrGLSLProgramBuilder::emitAndInstallDstTexture() { 290 fDstTextureOrigin = kTopLeft_GrSurfaceOrigin; 291 292 const GrSurfaceProxyView& dstView = this->pipeline().dstProxyView(); 293 if (this->pipeline().usesDstTexture()) { 294 // Set up a sampler handle for the destination texture. 295 GrTextureProxy* dstTextureProxy = dstView.asTextureProxy(); 296 SkASSERT(dstTextureProxy); 297 const GrSwizzle& swizzle = dstView.swizzle(); 298 fDstTextureSamplerHandle = this->emitSampler(dstTextureProxy->backendFormat(), 299 GrSamplerState(), swizzle, "DstTextureSampler"); 300 if (!fDstTextureSamplerHandle.isValid()) { 301 return false; 302 } 303 fDstTextureOrigin = dstView.origin(); 304 SkASSERT(dstTextureProxy->textureType() != GrTextureType::kExternal); 305 306 // Declare a _dstColor global variable which samples from the dest-texture sampler at the 307 // top of the fragment shader. 308 const char* dstTextureCoordsName; 309 fUniformHandles.fDstTextureCoordsUni = this->uniformHandler()->addUniform( 310 /*owner=*/nullptr, 311 kFragment_GrShaderFlag, 312 kHalf4_GrSLType, 313 "DstTextureCoords", 314 &dstTextureCoordsName); 315 fFS.codeAppend("// Read color from copy of the destination\n"); 316 fFS.codeAppendf("half2 _dstTexCoord = (half2(sk_FragCoord.xy) - %s.xy) * %s.zw;\n", 317 dstTextureCoordsName, dstTextureCoordsName); 318 if (fDstTextureOrigin == kBottomLeft_GrSurfaceOrigin) { 319 fFS.codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;\n"); 320 } 321 const char* dstColor = fFS.dstColor(); 322 SkString dstColorDecl = SkStringPrintf("half4 %s;", dstColor); 323 fFS.definitionAppend(dstColorDecl.c_str()); 324 fFS.codeAppendf("%s = ", dstColor); 325 fFS.appendTextureLookup(fDstTextureSamplerHandle, "_dstTexCoord"); 326 fFS.codeAppend(";\n"); 327 } else if (this->pipeline().usesDstInputAttachment()) { 328 // Set up an input attachment for the destination texture. 329 const GrSwizzle& swizzle = dstView.swizzle(); 330 fDstTextureSamplerHandle = this->emitInputSampler(swizzle, "DstTextureInput"); 331 if (!fDstTextureSamplerHandle.isValid()) { 332 return false; 333 } 334 335 // Populate the _dstColor variable by loading from the input attachment at the top of the 336 // fragment shader. 337 fFS.codeAppend("// Read color from input attachment\n"); 338 const char* dstColor = fFS.dstColor(); 339 SkString dstColorDecl = SkStringPrintf("half4 %s;", dstColor); 340 fFS.definitionAppend(dstColorDecl.c_str()); 341 fFS.codeAppendf("%s = ", dstColor); 342 fFS.appendInputLoad(fDstTextureSamplerHandle); 343 fFS.codeAppend(";\n"); 344 } 345 346 return true; 347 } 348 emitAndInstallXferProc(const SkString & colorIn,const SkString & coverageIn)349 bool GrGLSLProgramBuilder::emitAndInstallXferProc(const SkString& colorIn, 350 const SkString& coverageIn) { 351 // Program builders have a bit of state we need to clear with each effect 352 this->advanceStage(); 353 354 SkASSERT(!fXPImpl); 355 const GrXferProcessor& xp = this->pipeline().getXferProcessor(); 356 fXPImpl = xp.makeProgramImpl(); 357 358 // Enable dual source secondary output if we have one 359 if (xp.hasSecondaryOutput()) { 360 fFS.enableSecondaryOutput(); 361 } 362 363 if (this->shaderCaps()->mustDeclareFragmentShaderOutput()) { 364 fFS.enableCustomOutput(); 365 } 366 367 SkString openBrace; 368 openBrace.printf("{ // Xfer Processor: %s\n", xp.name()); 369 fFS.codeAppend(openBrace.c_str()); 370 371 SkString finalInColor = colorIn.size() ? colorIn : SkString("float4(1)"); 372 373 GrXferProcessor::ProgramImpl::EmitArgs args( 374 &fFS, 375 this->uniformHandler(), 376 this->shaderCaps(), 377 xp, 378 finalInColor.c_str(), 379 coverageIn.size() ? coverageIn.c_str() : "float4(1)", 380 fFS.getPrimaryColorOutputName(), 381 fFS.getSecondaryColorOutputName(), 382 fDstTextureSamplerHandle, 383 fDstTextureOrigin, 384 this->pipeline().writeSwizzle()); 385 fXPImpl->emitCode(args); 386 387 // We have to check that effects and the code they emit are consistent, ie if an effect 388 // asks for dst color, then the emit code needs to follow suit 389 SkDEBUGCODE(verify(xp);) 390 fFS.codeAppend("}"); 391 return true; 392 } 393 emitSampler(const GrBackendFormat & backendFormat,GrSamplerState state,const GrSwizzle & swizzle,const char * name)394 GrGLSLProgramBuilder::SamplerHandle GrGLSLProgramBuilder::emitSampler( 395 const GrBackendFormat& backendFormat, GrSamplerState state, const GrSwizzle& swizzle, 396 const char* name) { 397 ++fNumFragmentSamplers; 398 return this->uniformHandler()->addSampler(backendFormat, state, swizzle, name, 399 this->shaderCaps()); 400 } 401 emitInputSampler(const GrSwizzle & swizzle,const char * name)402 GrGLSLProgramBuilder::SamplerHandle GrGLSLProgramBuilder::emitInputSampler(const GrSwizzle& swizzle, 403 const char* name) { 404 return this->uniformHandler()->addInputSampler(swizzle, name); 405 } 406 checkSamplerCounts()407 bool GrGLSLProgramBuilder::checkSamplerCounts() { 408 const GrShaderCaps& shaderCaps = *this->shaderCaps(); 409 if (fNumFragmentSamplers > shaderCaps.maxFragmentSamplers()) { 410 GrCapsDebugf(this->caps(), "Program would use too many fragment samplers\n"); 411 return false; 412 } 413 return true; 414 } 415 416 #ifdef SK_DEBUG verify(const GrGeometryProcessor & geomProc)417 void GrGLSLProgramBuilder::verify(const GrGeometryProcessor& geomProc) { 418 SkASSERT(!fFS.fHasReadDstColorThisStage_DebugOnly); 419 } 420 verify(const GrFragmentProcessor & fp)421 void GrGLSLProgramBuilder::verify(const GrFragmentProcessor& fp) { 422 SkASSERT(fp.willReadDstColor() == fFS.fHasReadDstColorThisStage_DebugOnly); 423 } 424 verify(const GrXferProcessor & xp)425 void GrGLSLProgramBuilder::verify(const GrXferProcessor& xp) { 426 SkASSERT(xp.willReadDstColor() == fFS.fHasReadDstColorThisStage_DebugOnly); 427 } 428 #endif 429 getMangleSuffix() const430 SkString GrGLSLProgramBuilder::getMangleSuffix() const { 431 SkASSERT(fStageIndex >= 0); 432 SkString suffix; 433 suffix.printf("_S%d", fStageIndex); 434 for (auto c : fSubstageIndices) { 435 suffix.appendf("_c%d", c); 436 } 437 return suffix; 438 } 439 nameVariable(char prefix,const char * name,bool mangle)440 SkString GrGLSLProgramBuilder::nameVariable(char prefix, const char* name, bool mangle) { 441 SkString out; 442 if ('\0' == prefix) { 443 out = name; 444 } else { 445 out.printf("%c%s", prefix, name); 446 } 447 if (mangle) { 448 SkString suffix = this->getMangleSuffix(); 449 // Names containing "__" are reserved; add "x" if needed to avoid consecutive underscores. 450 const char *underscoreSplitter = out.endsWith('_') ? "x" : ""; 451 out.appendf("%s%s", underscoreSplitter, suffix.c_str()); 452 } 453 return out; 454 } 455 nameExpression(SkString * output,const char * baseName)456 void GrGLSLProgramBuilder::nameExpression(SkString* output, const char* baseName) { 457 // Name a variable to hold stage result. If we already have a valid output name, use that as-is; 458 // otherwise, create a new mangled one. 459 if (output->isEmpty()) { 460 *output = this->nameVariable(/*prefix=*/'\0', baseName); 461 } 462 } 463 appendUniformDecls(GrShaderFlags visibility,SkString * out) const464 void GrGLSLProgramBuilder::appendUniformDecls(GrShaderFlags visibility, SkString* out) const { 465 this->uniformHandler()->appendUniformDecls(visibility, out); 466 } 467 addRTFlipUniform(const char * name)468 void GrGLSLProgramBuilder::addRTFlipUniform(const char* name) { 469 SkASSERT(!fUniformHandles.fRTFlipUni.isValid()); 470 GrGLSLUniformHandler* uniformHandler = this->uniformHandler(); 471 fUniformHandles.fRTFlipUni = 472 uniformHandler->internalAddUniformArray(nullptr, 473 kFragment_GrShaderFlag, 474 kFloat2_GrSLType, 475 name, 476 false, 477 0, 478 nullptr); 479 } 480 fragmentProcessorHasCoordsParam(const GrFragmentProcessor * fp)481 bool GrGLSLProgramBuilder::fragmentProcessorHasCoordsParam(const GrFragmentProcessor* fp) { 482 return fFPCoordsMap[fp].hasCoordsParam; 483 } 484 finalizeShaders()485 void GrGLSLProgramBuilder::finalizeShaders() { 486 this->varyingHandler()->finalize(); 487 fVS.finalize(kVertex_GrShaderFlag); 488 fFS.finalize(kFragment_GrShaderFlag); 489 } 490