Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "GrGLProgramBuilder.h" | 8 #include "GrGLProgramBuilder.h" |
| 9 | 9 |
| 10 #include "gl/GrGLGeometryProcessor.h" | 10 #include "gl/GrGLGeometryProcessor.h" |
| 11 #include "gl/GrGLGpu.h" | 11 #include "gl/GrGLGpu.h" |
| 12 #include "gl/GrGLPathProcessor.h" | 12 #include "gl/GrGLPathProcessor.h" |
| 13 #include "gl/GrGLProgram.h" | 13 #include "gl/GrGLProgram.h" |
| 14 #include "gl/GrGLSLPrettyPrint.h" | 14 #include "gl/GrGLSLPrettyPrint.h" |
| 15 #include "gl/GrGLUniformHandle.h" | 15 #include "gl/GrGLUniformHandle.h" |
| 16 #include "gl/GrGLXferProcessor.h" | 16 #include "gl/GrGLXferProcessor.h" |
| 17 #include "GrAutoLocaleSetter.h" | 17 #include "GrAutoLocaleSetter.h" |
| 18 #include "GrCoordTransform.h" | 18 #include "GrCoordTransform.h" |
| 19 #include "GrGLPathProgramBuilder.h" | |
| 19 #include "GrGLProgramBuilder.h" | 20 #include "GrGLProgramBuilder.h" |
| 20 #include "GrTexture.h" | 21 #include "GrTexture.h" |
| 21 #include "SkRTConf.h" | 22 #include "SkRTConf.h" |
| 22 #include "SkTraceEvent.h" | 23 #include "SkTraceEvent.h" |
| 23 | 24 |
| 24 #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X) | 25 #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 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X) |
| 26 | 27 |
| 27 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
| 28 | |
| 29 class GrGLNvprProgramBuilder : public GrGLProgramBuilder { | |
| 30 public: | |
| 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 plugg ed 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 | |
| 46 private: | |
| 47 typedef GrGLProgramBuilder INHERITED; | |
| 48 }; | |
| 49 | |
| 50 | |
| 51 | |
| 52 ////////////////////////////////////////////////////////////////////////////// | |
| 53 | |
| 54 const int GrGLProgramBuilder::kVarsPerBlock = 8; | 28 const int GrGLProgramBuilder::kVarsPerBlock = 8; |
| 55 | 29 |
| 56 GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gp u) { | 30 GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gp u) { |
| 57 GrAutoLocaleSetter als("C"); | 31 GrAutoLocaleSetter als("C"); |
| 58 | 32 |
| 59 // create a builder. This will be handed off to effects so they can use it to add | 33 // create a builder. This will be handed off to effects so they can use it to add |
| 60 // uniforms, varyings, textures, etc | 34 // uniforms, varyings, textures, etc |
| 61 SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(args, gpu)); | 35 SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(args, gpu)); |
| 62 | 36 |
| 63 GrGLProgramBuilder* pb = builder.get(); | 37 GrGLProgramBuilder* pb = builder.get(); |
| 64 | 38 |
| 65 // TODO: Once all stages can handle taking a float or vec4 and correctly han dling them we can | 39 // TODO: Once all stages can handle taking a float or vec4 and correctly han dling them we can |
| 66 // seed correctly here | 40 // seed correctly here |
| 67 GrGLSLExpr4 inputColor; | 41 GrGLSLExpr4 inputColor; |
| 68 GrGLSLExpr4 inputCoverage; | 42 GrGLSLExpr4 inputCoverage; |
| 69 | 43 |
| 70 if (!pb->emitAndInstallProcs(&inputColor, &inputCoverage)) { | 44 if (!pb->emitAndInstallProcs(&inputColor, &inputCoverage)) { |
| 71 return NULL; | 45 return NULL; |
| 72 } | 46 } |
| 73 | 47 |
| 74 return pb->finalize(); | 48 return pb->finalize(); |
| 75 } | 49 } |
| 76 | 50 |
| 77 GrGLProgramBuilder* GrGLProgramBuilder::CreateProgramBuilder(const DrawArgs& arg s, | 51 GrGLProgramBuilder* GrGLProgramBuilder::CreateProgramBuilder(const DrawArgs& arg s, |
| 78 GrGLGpu* gpu) { | 52 GrGLGpu* gpu) { |
| 79 if (args.fPrimitiveProcessor->isPathRendering()) { | 53 if (args.fPrimitiveProcessor->isPathRendering()) { |
| 80 SkASSERT(gpu->glCaps().shaderCaps()->pathRenderingSupport() && | 54 SkASSERT(gpu->glCaps().shaderCaps()->pathRenderingSupport() && |
| 81 !args.fPrimitiveProcessor->willUseGeoShader() && | 55 !args.fPrimitiveProcessor->willUseGeoShader() && |
| 82 args.fPrimitiveProcessor->numAttribs() == 0); | 56 args.fPrimitiveProcessor->numAttribs() == 0); |
| 83 return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, args)); | 57 return SkNEW_ARGS(GrGLPathProgramBuilder, (gpu, args)); |
| 84 } else { | 58 } else { |
| 85 return SkNEW_ARGS(GrGLProgramBuilder, (gpu, args)); | 59 return SkNEW_ARGS(GrGLProgramBuilder, (gpu, args)); |
| 86 } | 60 } |
| 87 } | 61 } |
| 88 | 62 |
| 89 ///////////////////////////////////////////////////////////////////////////// | 63 ///////////////////////////////////////////////////////////////////////////// |
| 90 | 64 |
| 91 GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const DrawArgs& args) | 65 GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const DrawArgs& args) |
| 92 : fVS(this) | 66 : fVS(this) |
| 93 , fGS(this) | 67 , fGS(this) |
| 94 , fFS(this, args.fDesc->header().fFragPosKey) | 68 , fFS(this, args.fDesc->header().fFragPosKey) |
| 95 , fOutOfStage(true) | 69 , fOutOfStage(true) |
| 96 , fStageIndex(-1) | 70 , fStageIndex(-1) |
| 97 , fGeometryProcessor(NULL) | 71 , fGeometryProcessor(NULL) |
| 98 , fXferProcessor(NULL) | 72 , fXferProcessor(NULL) |
| 99 , fArgs(args) | 73 , fArgs(args) |
| 100 , fGpu(gpu) | 74 , fGpu(gpu) |
| 101 , fUniforms(kVarsPerBlock) { | 75 , fUniforms(kVarsPerBlock) { |
| 76 | |
|
joshualitt
2015/06/23 14:07:24
extra newline
Kimmo Kinnunen
2015/06/25 12:38:11
Done.
| |
| 102 } | 77 } |
| 103 | 78 |
| 104 void GrGLProgramBuilder::addVarying(const char* name, | 79 void GrGLProgramBuilder::addVarying(const char* name, |
| 105 GrGLVarying* varying, | 80 GrGLVarying* varying, |
| 106 GrSLPrecision fsPrecision) { | 81 GrSLPrecision fsPrecision) { |
| 107 SkASSERT(varying); | 82 SkASSERT(varying); |
| 108 if (varying->vsVarying()) { | 83 if (varying->vsVarying()) { |
| 109 fVS.addVarying(name, varying); | 84 fVS.addVarying(name, varying); |
| 110 } | 85 } |
| 111 if (this->primitiveProcessor().willUseGeoShader()) { | 86 if (this->primitiveProcessor().willUseGeoShader()) { |
| 112 fGS.addVarying(name, varying); | 87 fGS.addVarying(name, varying); |
| 113 } | 88 } |
| 114 if (varying->fsVarying()) { | 89 if (varying->fsVarying()) { |
| 115 fFS.addVarying(varying, fsPrecision); | 90 fFS.addVarying(varying, fsPrecision); |
| 116 } | 91 } |
| 117 } | 92 } |
| 118 | 93 |
| 119 void GrGLProgramBuilder::addPassThroughAttribute(const GrPrimitiveProcessor::Att ribute* input, | 94 void GrGLProgramBuilder::addPassThroughAttribute(const GrPrimitiveProcessor::Att ribute* input, |
| 120 const char* output) { | 95 const char* output) { |
| 121 GrSLType type = GrVertexAttribTypeToSLType(input->fType); | 96 GrSLType type = GrVertexAttribTypeToSLType(input->fType); |
| 122 GrGLVertToFrag v(type); | 97 GrGLVertToFrag v(type); |
| 123 this->addVarying(input->fName, &v); | 98 this->addVarying(input->fName, &v); |
| 124 fVS.codeAppendf("%s = %s;", v.vsOut(), input->fName); | 99 fVS.codeAppendf("%s = %s;", v.vsOut(), input->fName); |
| 125 fFS.codeAppendf("%s = %s;", output, v.fsIn()); | 100 fFS.codeAppendf("%s = %s;", output, v.fsIn()); |
| 126 } | 101 } |
| 127 | 102 |
| 103 GrGLProgramBuilder::SeparableVaryingHandle GrGLProgramBuilder::addSeparableVaryi ng(const char*, | |
| 104 GrGLVertToFrag*, | |
| 105 GrSLPrecision) { | |
| 106 // This call is not used for non-NVPR backends. However, the polymorphism be tween | |
| 107 // GrPrimitiveProcessor, GrGLPrimitiveProcessor and GrGLProgramBuilder does not allow for | |
| 108 // a system where GrGLPathProcessor would be able to refer to a primitive-sp ecific builder | |
| 109 // that would understand separable varyings. Thus separable varyings need to be present | |
| 110 // early in the inheritance chain of builders. | |
| 111 SkASSERT(false); | |
| 112 return SeparableVaryingHandle(); | |
| 113 } | |
| 114 | |
| 128 void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* na me) { | 115 void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* na me) { |
| 129 if ('\0' == prefix) { | 116 if ('\0' == prefix) { |
| 130 *out = name; | 117 *out = name; |
| 131 } else { | 118 } else { |
| 132 out->printf("%c%s", prefix, name); | 119 out->printf("%c%s", prefix, name); |
| 133 } | 120 } |
| 134 if (!fOutOfStage) { | 121 if (!fOutOfStage) { |
| 135 if (out->endsWith('_')) { | 122 if (out->endsWith('_')) { |
| 136 // Names containing "__" are reserved. | 123 // Names containing "__" are reserved. |
| 137 out->append("x"); | 124 out->append("x"); |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 414 bool useNvpr = primitiveProcessor().isPathRendering(); | 401 bool useNvpr = primitiveProcessor().isPathRendering(); |
| 415 if (!useNvpr) { | 402 if (!useNvpr) { |
| 416 fVS.bindVertexAttributes(programID); | 403 fVS.bindVertexAttributes(programID); |
| 417 } | 404 } |
| 418 | 405 |
| 419 if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) { | 406 if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) { |
| 420 this->cleanupProgram(programID, shadersToDelete); | 407 this->cleanupProgram(programID, shadersToDelete); |
| 421 return NULL; | 408 return NULL; |
| 422 } | 409 } |
| 423 | 410 |
| 424 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL; | 411 this->bindProgramResourceLocations(programID); |
| 425 if (usingBindUniform) { | 412 |
| 426 this->bindUniformLocations(programID); | |
| 427 } | |
| 428 fFS.bindFragmentShaderLocations(programID); | |
| 429 GL_CALL(LinkProgram(programID)); | 413 GL_CALL(LinkProgram(programID)); |
| 430 | 414 |
| 431 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds. | 415 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds. |
| 432 bool checkLinked = kChromium_GrGLDriver != fGpu->ctxInfo().driver(); | 416 bool checkLinked = kChromium_GrGLDriver != fGpu->ctxInfo().driver(); |
| 433 #ifdef SK_DEBUG | 417 #ifdef SK_DEBUG |
| 434 checkLinked = true; | 418 checkLinked = true; |
| 435 #endif | 419 #endif |
| 436 if (checkLinked) { | 420 if (checkLinked) { |
| 437 checkLinkStatus(programID); | 421 checkLinkStatus(programID); |
| 438 } | 422 } |
| 439 if (!usingBindUniform) { | 423 this->resolveProgramResourceLocations(programID); |
| 440 this->resolveUniformLocations(programID); | |
| 441 } | |
| 442 | 424 |
| 443 this->cleanupShaders(shadersToDelete); | 425 this->cleanupShaders(shadersToDelete); |
| 444 | 426 |
| 445 return this->createProgram(programID); | 427 return this->createProgram(programID); |
| 446 } | 428 } |
| 447 | 429 |
| 448 void GrGLProgramBuilder::bindUniformLocations(GrGLuint programID) { | 430 void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) { |
| 449 int count = fUniforms.count(); | 431 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL; |
| 450 for (int i = 0; i < count; ++i) { | 432 if (usingBindUniform) { |
| 451 GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_str() )); | 433 int count = fUniforms.count(); |
| 452 fUniforms[i].fLocation = i; | 434 for (int i = 0; i < count; ++i) { |
| 435 GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_s tr())); | |
| 436 fUniforms[i].fLocation = i; | |
| 437 } | |
| 453 } | 438 } |
| 439 | |
| 440 fFS.bindFragmentShaderLocations(programID); | |
| 454 } | 441 } |
| 455 | 442 |
| 456 bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) { | 443 bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) { |
| 457 GrGLint linked = GR_GL_INIT_ZERO; | 444 GrGLint linked = GR_GL_INIT_ZERO; |
| 458 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked)); | 445 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked)); |
| 459 if (!linked) { | 446 if (!linked) { |
| 460 GrGLint infoLen = GR_GL_INIT_ZERO; | 447 GrGLint infoLen = GR_GL_INIT_ZERO; |
| 461 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen)); | 448 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen)); |
| 462 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger | 449 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger |
| 463 if (infoLen > 0) { | 450 if (infoLen > 0) { |
| 464 // retrieve length even though we don't need it to workaround | 451 // retrieve length even though we don't need it to workaround |
| 465 // bug in chrome cmd buffer param validation. | 452 // bug in chrome cmd buffer param validation. |
| 466 GrGLsizei length = GR_GL_INIT_ZERO; | 453 GrGLsizei length = GR_GL_INIT_ZERO; |
| 467 GL_CALL(GetProgramInfoLog(programID, | 454 GL_CALL(GetProgramInfoLog(programID, |
| 468 infoLen+1, | 455 infoLen+1, |
| 469 &length, | 456 &length, |
| 470 (char*)log.get())); | 457 (char*)log.get())); |
| 471 SkDebugf("%s", (char*)log.get()); | 458 SkDebugf("%s", (char*)log.get()); |
| 472 } | 459 } |
| 473 SkDEBUGFAIL("Error linking program"); | 460 SkDEBUGFAIL("Error linking program"); |
| 474 GL_CALL(DeleteProgram(programID)); | 461 GL_CALL(DeleteProgram(programID)); |
| 475 programID = 0; | 462 programID = 0; |
| 476 } | 463 } |
| 477 return SkToBool(linked); | 464 return SkToBool(linked); |
| 478 } | 465 } |
| 479 | 466 |
| 480 void GrGLProgramBuilder::resolveUniformLocations(GrGLuint programID) { | 467 void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID) { |
| 481 int count = fUniforms.count(); | 468 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL; |
| 482 for (int i = 0; i < count; ++i) { | 469 if (!usingBindUniform) { |
| 483 GrGLint location; | 470 int count = fUniforms.count(); |
| 484 GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariab le.c_str())); | 471 for (int i = 0; i < count; ++i) { |
| 485 fUniforms[i].fLocation = location; | 472 GrGLint location; |
| 473 GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVa riable.c_str())); | |
| 474 fUniforms[i].fLocation = location; | |
| 475 } | |
| 486 } | 476 } |
| 487 } | 477 } |
| 488 | 478 |
| 489 void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGL uint>& shaderIDs) { | 479 void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGL uint>& shaderIDs) { |
| 490 GL_CALL(DeleteProgram(programID)); | 480 GL_CALL(DeleteProgram(programID)); |
| 491 cleanupShaders(shaderIDs); | 481 cleanupShaders(shaderIDs); |
| 492 } | 482 } |
| 493 void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) { | 483 void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) { |
| 494 for (int i = 0; i < shaderIDs.count(); ++i) { | 484 for (int i = 0; i < shaderIDs.count(); ++i) { |
| 495 GL_CALL(DeleteShader(shaderIDs[i])); | 485 GL_CALL(DeleteShader(shaderIDs[i])); |
| 496 } | 486 } |
| 497 } | 487 } |
| 498 | 488 |
| 499 GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) { | 489 GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) { |
| 500 return SkNEW_ARGS(GrGLProgram, (fGpu, this->desc(), fUniformHandles, program ID, fUniforms, | 490 return SkNEW_ARGS(GrGLProgram, (fGpu, this->desc(), fUniformHandles, program ID, fUniforms, |
| 501 fGeometryProcessor, fXferProcessor, fFragmen tProcessors.get())); | 491 fGeometryProcessor, fXferProcessor, fFragmen tProcessors.get())); |
| 502 } | 492 } |
| 503 | 493 |
| 504 //////////////////////////////////////////////////////////////////////////////// /////////////////// | 494 //////////////////////////////////////////////////////////////////////////////// /////////////////// |
| 505 | 495 |
| 506 GrGLInstalledFragProcs::~GrGLInstalledFragProcs() { | 496 GrGLInstalledFragProcs::~GrGLInstalledFragProcs() { |
| 507 int numProcs = fProcs.count(); | 497 int numProcs = fProcs.count(); |
| 508 for (int e = 0; e < numProcs; ++e) { | 498 for (int e = 0; e < numProcs; ++e) { |
| 509 SkDELETE(fProcs[e]); | 499 SkDELETE(fProcs[e]); |
| 510 } | 500 } |
| 511 } | 501 } |
| OLD | NEW |