1/* 2 * Copyright 2014 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 "GrGLProgramBuilder.h" 9 10#include "gl/GrGLGeometryProcessor.h" 11#include "gl/GrGLGpu.h" 12#include "gl/GrGLPathProcessor.h" 13#include "gl/GrGLProgram.h" 14#include "gl/GrGLSLPrettyPrint.h" 15#include "gl/GrGLUniformHandle.h" 16#include "gl/GrGLXferProcessor.h" 17#include "GrAutoLocaleSetter.h" 18#include "GrCoordTransform.h" 19#include "GrGLProgramBuilder.h" 20#include "GrTexture.h" 21#include "SkRTConf.h" 22#include "SkTraceEvent.h" 23 24#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X) 25#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X) 26 27/////////////////////////////////////////////////////////////////////////////////////////////////// 28 29class GrGLNvprProgramBuilder : public GrGLProgramBuilder { 30public: 31 GrGLNvprProgramBuilder(GrGLGpu* gpu, const DrawArgs& args) 32 : INHERITED(gpu, args) {} 33 34 GrGLProgram* createProgram(GrGLuint programID) override { 35 // this is just for nvpr es, which has separable varyings that are plugged in after 36 // building 37 GrGLPathProcessor* pathProc = 38 static_cast<GrGLPathProcessor*>(fGeometryProcessor->fGLProc.get()); 39 pathProc->resolveSeparableVaryings(fGpu, programID); 40 return SkNEW_ARGS(GrGLNvprProgram, (fGpu, this->desc(), fUniformHandles, programID, 41 fUniforms, 42 fGeometryProcessor, 43 fXferProcessor, fFragmentProcessors.get())); 44 } 45 46private: 47 typedef GrGLProgramBuilder INHERITED; 48}; 49 50 51 52////////////////////////////////////////////////////////////////////////////// 53 54const int GrGLProgramBuilder::kVarsPerBlock = 8; 55 56GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gpu) { 57 GrAutoLocaleSetter als("C"); 58 59 // create a builder. This will be handed off to effects so they can use it to add 60 // uniforms, varyings, textures, etc 61 SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(args, gpu)); 62 63 GrGLProgramBuilder* pb = builder.get(); 64 65 // TODO: Once all stages can handle taking a float or vec4 and correctly handling them we can 66 // seed correctly here 67 GrGLSLExpr4 inputColor; 68 GrGLSLExpr4 inputCoverage; 69 70 if (!pb->emitAndInstallProcs(&inputColor, &inputCoverage)) { 71 return NULL; 72 } 73 74 return pb->finalize(); 75} 76 77GrGLProgramBuilder* GrGLProgramBuilder::CreateProgramBuilder(const DrawArgs& args, 78 GrGLGpu* gpu) { 79 if (args.fPrimitiveProcessor->isPathRendering()) { 80 SkASSERT(gpu->glCaps().shaderCaps()->pathRenderingSupport() && 81 !args.fPrimitiveProcessor->willUseGeoShader() && 82 args.fPrimitiveProcessor->numAttribs() == 0); 83 return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, args)); 84 } else { 85 return SkNEW_ARGS(GrGLProgramBuilder, (gpu, args)); 86 } 87} 88 89///////////////////////////////////////////////////////////////////////////// 90 91GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const DrawArgs& args) 92 : fVS(this) 93 , fGS(this) 94 , fFS(this, args.fDesc->header().fFragPosKey) 95 , fOutOfStage(true) 96 , fStageIndex(-1) 97 , fGeometryProcessor(NULL) 98 , fXferProcessor(NULL) 99 , fArgs(args) 100 , fGpu(gpu) 101 , fUniforms(kVarsPerBlock) { 102} 103 104void GrGLProgramBuilder::addVarying(const char* name, 105 GrGLVarying* varying, 106 GrSLPrecision fsPrecision) { 107 SkASSERT(varying); 108 if (varying->vsVarying()) { 109 fVS.addVarying(name, varying); 110 } 111 if (this->primitiveProcessor().willUseGeoShader()) { 112 fGS.addVarying(name, varying); 113 } 114 if (varying->fsVarying()) { 115 fFS.addVarying(varying, fsPrecision); 116 } 117} 118 119void GrGLProgramBuilder::addPassThroughAttribute(const GrPrimitiveProcessor::Attribute* input, 120 const char* output) { 121 GrSLType type = GrVertexAttribTypeToSLType(input->fType); 122 GrGLVertToFrag v(type); 123 this->addVarying(input->fName, &v); 124 fVS.codeAppendf("%s = %s;", v.vsOut(), input->fName); 125 fFS.codeAppendf("%s = %s;", output, v.fsIn()); 126} 127 128void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name) { 129 if ('\0' == prefix) { 130 *out = name; 131 } else { 132 out->printf("%c%s", prefix, name); 133 } 134 if (!fOutOfStage) { 135 if (out->endsWith('_')) { 136 // Names containing "__" are reserved. 137 out->append("x"); 138 } 139 out->appendf("_Stage%d", fStageIndex); 140 } 141} 142 143GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray( 144 uint32_t visibility, 145 GrSLType type, 146 GrSLPrecision precision, 147 const char* name, 148 int count, 149 const char** outName) { 150 SkASSERT(name && strlen(name)); 151 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFragment_Visibility); 152 SkASSERT(0 == (~kVisibilityMask & visibility)); 153 SkASSERT(0 != visibility); 154 SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsFloatType(type)); 155 156 UniformInfo& uni = fUniforms.push_back(); 157 uni.fVariable.setType(type); 158 uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); 159 // TODO this is a bit hacky, lets think of a better way. Basically we need to be able to use 160 // the uniform view matrix name in the GP, and the GP is immutable so it has to tell the PB 161 // exactly what name it wants to use for the uniform view matrix. If we prefix anythings, then 162 // the names will mismatch. I think the correct solution is to have all GPs which need the 163 // uniform view matrix, they should upload the view matrix in their setData along with regular 164 // uniforms. 165 char prefix = 'u'; 166 if ('u' == name[0]) { 167 prefix = '\0'; 168 } 169 this->nameVariable(uni.fVariable.accessName(), prefix, name); 170 uni.fVariable.setArrayCount(count); 171 uni.fVisibility = visibility; 172 uni.fVariable.setPrecision(precision); 173 174 if (outName) { 175 *outName = uni.fVariable.c_str(); 176 } 177 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1); 178} 179 180void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility, 181 SkString* out) const { 182 for (int i = 0; i < fUniforms.count(); ++i) { 183 if (fUniforms[i].fVisibility & visibility) { 184 fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out); 185 out->append(";\n"); 186 } 187 } 188} 189 190const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const { 191 return fGpu->ctxInfo(); 192} 193 194bool GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage) { 195 // First we loop over all of the installed processors and collect coord transforms. These will 196 // be sent to the GrGLPrimitiveProcessor in its emitCode function 197 const GrPrimitiveProcessor& primProc = this->primitiveProcessor(); 198 int totalTextures = primProc.numTextures(); 199 const int maxTextureUnits = fGpu->glCaps().maxFragmentTextureUnits(); 200 SkSTArray<8, GrGLProcessor::TransformedCoordsArray> outCoords; 201 for (int i = 0; i < this->pipeline().numFragmentStages(); i++) { 202 const GrFragmentProcessor* processor = this->pipeline().getFragmentStage(i).processor(); 203 SkSTArray<2, const GrCoordTransform*, true>& procCoords = fCoordTransforms.push_back(); 204 for (int t = 0; t < processor->numTransforms(); t++) { 205 procCoords.push_back(&processor->coordTransform(t)); 206 } 207 208 totalTextures += processor->numTextures(); 209 if (totalTextures >= maxTextureUnits) { 210 GrContextDebugf(fGpu->getContext(), "Program would use too many texture units\n"); 211 return false; 212 } 213 } 214 215 this->emitAndInstallProc(primProc, inputColor, inputCoverage); 216 217 fFragmentProcessors.reset(SkNEW(GrGLInstalledFragProcs)); 218 int numProcs = this->pipeline().numFragmentStages(); 219 this->emitAndInstallFragProcs(0, this->pipeline().numColorFragmentStages(), inputColor); 220 this->emitAndInstallFragProcs(this->pipeline().numColorFragmentStages(), numProcs, 221 inputCoverage); 222 this->emitAndInstallXferProc(*this->pipeline().getXferProcessor(), *inputColor, *inputCoverage); 223 return true; 224} 225 226void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, 227 int numProcs, 228 GrGLSLExpr4* inOut) { 229 for (int e = procOffset; e < numProcs; ++e) { 230 GrGLSLExpr4 output; 231 const GrPendingFragmentStage& stage = this->pipeline().getFragmentStage(e); 232 this->emitAndInstallProc(stage, e, *inOut, &output); 233 *inOut = output; 234 } 235} 236 237void GrGLProgramBuilder::nameExpression(GrGLSLExpr4* output, const char* baseName) { 238 // create var to hold stage result. If we already have a valid output name, just use that 239 // otherwise create a new mangled one. This name is only valid if we are reordering stages 240 // and have to tell stage exactly where to put its output. 241 SkString outName; 242 if (output->isValid()) { 243 outName = output->c_str(); 244 } else { 245 this->nameVariable(&outName, '\0', baseName); 246 } 247 fFS.codeAppendf("vec4 %s;", outName.c_str()); 248 *output = outName; 249} 250 251// TODO Processors cannot output zeros because an empty string is all 1s 252// the fix is to allow effects to take the GrGLSLExpr4 directly 253void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& proc, 254 int index, 255 const GrGLSLExpr4& input, 256 GrGLSLExpr4* output) { 257 // Program builders have a bit of state we need to clear with each effect 258 AutoStageAdvance adv(this); 259 this->nameExpression(output, "output"); 260 261 // Enclose custom code in a block to avoid namespace conflicts 262 SkString openBrace; 263 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name()); 264 fFS.codeAppend(openBrace.c_str()); 265 266 this->emitAndInstallProc(proc, index, output->c_str(), input.isOnes() ? NULL : input.c_str()); 267 268 fFS.codeAppend("}"); 269} 270 271void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& proc, 272 GrGLSLExpr4* outputColor, 273 GrGLSLExpr4* outputCoverage) { 274 // Program builders have a bit of state we need to clear with each effect 275 AutoStageAdvance adv(this); 276 this->nameExpression(outputColor, "outputColor"); 277 this->nameExpression(outputCoverage, "outputCoverage"); 278 279 // Enclose custom code in a block to avoid namespace conflicts 280 SkString openBrace; 281 openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name()); 282 fFS.codeAppend(openBrace.c_str()); 283 284 this->emitAndInstallProc(proc, outputColor->c_str(), outputCoverage->c_str()); 285 286 fFS.codeAppend("}"); 287} 288 289void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& fs, 290 int index, 291 const char* outColor, 292 const char* inColor) { 293 GrGLInstalledFragProc* ifp = SkNEW(GrGLInstalledFragProc); 294 295 const GrFragmentProcessor& fp = *fs.processor(); 296 ifp->fGLProc.reset(fp.createGLInstance()); 297 298 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(fp.numTextures()); 299 this->emitSamplers(fp, &samplers, ifp); 300 301 ifp->fGLProc->emitCode(this, fp, outColor, inColor, fOutCoords[index], samplers); 302 303 // We have to check that effects and the code they emit are consistent, ie if an effect 304 // asks for dst color, then the emit code needs to follow suit 305 verify(fp); 306 fFragmentProcessors->fProcs.push_back(ifp); 307} 308 309void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& gp, 310 const char* outColor, 311 const char* outCoverage) { 312 SkASSERT(!fGeometryProcessor); 313 fGeometryProcessor = SkNEW(GrGLInstalledGeoProc); 314 315 const GrBatchTracker& bt = this->batchTracker(); 316 fGeometryProcessor->fGLProc.reset(gp.createGLInstance(bt, *fGpu->glCaps().glslCaps())); 317 318 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(gp.numTextures()); 319 this->emitSamplers(gp, &samplers, fGeometryProcessor); 320 321 GrGLGeometryProcessor::EmitArgs args(this, gp, bt, outColor, outCoverage, samplers, 322 fCoordTransforms, &fOutCoords); 323 fGeometryProcessor->fGLProc->emitCode(args); 324 325 // We have to check that effects and the code they emit are consistent, ie if an effect 326 // asks for dst color, then the emit code needs to follow suit 327 verify(gp); 328} 329 330void GrGLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp, 331 const GrGLSLExpr4& colorIn, 332 const GrGLSLExpr4& coverageIn) { 333 // Program builders have a bit of state we need to clear with each effect 334 AutoStageAdvance adv(this); 335 336 SkASSERT(!fXferProcessor); 337 fXferProcessor = SkNEW(GrGLInstalledXferProc); 338 339 fXferProcessor->fGLProc.reset(xp.createGLInstance()); 340 341 // Enable dual source secondary output if we have one 342 if (xp.hasSecondaryOutput()) { 343 fFS.enableSecondaryOutput(); 344 } 345 346 // On any post 1.10 GLSL supporting GPU, we declare custom output 347 if (k110_GrGLSLGeneration != fFS.fProgramBuilder->gpu()->glslGeneration()) { 348 fFS.enableCustomOutput(); 349 } 350 351 SkString openBrace; 352 openBrace.printf("{ // Xfer Processor: %s\n", xp.name()); 353 fFS.codeAppend(openBrace.c_str()); 354 355 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(xp.numTextures()); 356 this->emitSamplers(xp, &samplers, fXferProcessor); 357 358 GrGLXferProcessor::EmitArgs args(this, xp, colorIn.c_str(), coverageIn.c_str(), 359 fFS.getPrimaryColorOutputName(), 360 fFS.getSecondaryColorOutputName(), samplers); 361 fXferProcessor->fGLProc->emitCode(args); 362 363 // We have to check that effects and the code they emit are consistent, ie if an effect 364 // asks for dst color, then the emit code needs to follow suit 365 verify(xp); 366 fFS.codeAppend("}"); 367} 368 369void GrGLProgramBuilder::verify(const GrPrimitiveProcessor& gp) { 370 SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition()); 371} 372 373void GrGLProgramBuilder::verify(const GrXferProcessor& xp) { 374 SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor()); 375} 376 377void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) { 378 SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition()); 379} 380 381template <class Proc> 382void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor, 383 GrGLProcessor::TextureSamplerArray* outSamplers, 384 GrGLInstalledProc<Proc>* ip) { 385 int numTextures = processor.numTextures(); 386 ip->fSamplers.push_back_n(numTextures); 387 SkString name; 388 for (int t = 0; t < numTextures; ++t) { 389 name.printf("Sampler%d", t); 390 ip->fSamplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Visibility, 391 kSampler2D_GrSLType, kDefault_GrSLPrecision, 392 name.c_str()); 393 SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler, 394 (ip->fSamplers[t].fUniform, processor.textureAccess(t))); 395 } 396} 397 398GrGLProgram* GrGLProgramBuilder::finalize() { 399 // verify we can get a program id 400 GrGLuint programID; 401 GL_CALL_RET(programID, CreateProgram()); 402 if (0 == programID) { 403 return NULL; 404 } 405 406 // compile shaders and bind attributes / uniforms 407 SkTDArray<GrGLuint> shadersToDelete; 408 409 if (!fVS.compileAndAttachShaders(programID, &shadersToDelete)) { 410 this->cleanupProgram(programID, shadersToDelete); 411 return NULL; 412 } 413 414 // NVPR actually requires a vertex shader to compile 415 bool useNvpr = primitiveProcessor().isPathRendering(); 416 if (!useNvpr) { 417 fVS.bindVertexAttributes(programID); 418 } 419 420 if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) { 421 this->cleanupProgram(programID, shadersToDelete); 422 return NULL; 423 } 424 425 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL; 426 if (usingBindUniform) { 427 this->bindUniformLocations(programID); 428 } 429 fFS.bindFragmentShaderLocations(programID); 430 GL_CALL(LinkProgram(programID)); 431 432 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds. 433 bool checkLinked = !fGpu->ctxInfo().isChromium(); 434#ifdef SK_DEBUG 435 checkLinked = true; 436#endif 437 if (checkLinked) { 438 checkLinkStatus(programID); 439 } 440 if (!usingBindUniform) { 441 this->resolveUniformLocations(programID); 442 } 443 444 this->cleanupShaders(shadersToDelete); 445 446 return this->createProgram(programID); 447} 448 449void GrGLProgramBuilder::bindUniformLocations(GrGLuint programID) { 450 int count = fUniforms.count(); 451 for (int i = 0; i < count; ++i) { 452 GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_str())); 453 fUniforms[i].fLocation = i; 454 } 455} 456 457bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) { 458 GrGLint linked = GR_GL_INIT_ZERO; 459 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked)); 460 if (!linked) { 461 GrGLint infoLen = GR_GL_INIT_ZERO; 462 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen)); 463 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger 464 if (infoLen > 0) { 465 // retrieve length even though we don't need it to workaround 466 // bug in chrome cmd buffer param validation. 467 GrGLsizei length = GR_GL_INIT_ZERO; 468 GL_CALL(GetProgramInfoLog(programID, 469 infoLen+1, 470 &length, 471 (char*)log.get())); 472 SkDebugf("%s", (char*)log.get()); 473 } 474 SkDEBUGFAIL("Error linking program"); 475 GL_CALL(DeleteProgram(programID)); 476 programID = 0; 477 } 478 return SkToBool(linked); 479} 480 481void GrGLProgramBuilder::resolveUniformLocations(GrGLuint programID) { 482 int count = fUniforms.count(); 483 for (int i = 0; i < count; ++i) { 484 GrGLint location; 485 GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str())); 486 fUniforms[i].fLocation = location; 487 } 488} 489 490void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) { 491 GL_CALL(DeleteProgram(programID)); 492 cleanupShaders(shaderIDs); 493} 494void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) { 495 for (int i = 0; i < shaderIDs.count(); ++i) { 496 GL_CALL(DeleteShader(shaderIDs[i])); 497 } 498} 499 500GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) { 501 return SkNEW_ARGS(GrGLProgram, (fGpu, this->desc(), fUniformHandles, programID, fUniforms, 502 fGeometryProcessor, fXferProcessor, fFragmentProcessors.get())); 503} 504 505/////////////////////////////////////////////////////////////////////////////////////////////////// 506 507GrGLInstalledFragProcs::~GrGLInstalledFragProcs() { 508 int numProcs = fProcs.count(); 509 for (int e = 0; e < numProcs; ++e) { 510 SkDELETE(fProcs[e]); 511 } 512} 513