From a91f03165335267bda7cf04ae5ffb60c1362f017 Mon Sep 17 00:00:00 2001 From: "commit-bot@chromium.org" Date: Fri, 6 Sep 2013 20:19:56 +0000 Subject: Add a requiresVertexShader method to GrGLEffect Adds requiresVertexShader to GrGLEffect and updates the necessary effects to override it and return true. Also reworks GrGLProgram and GrGLShaderBuilder so the program creates all the GL effects at the beginning, and determines if it needs a vertex shader before creating the shader builder. R=bsalomon@google.com Author: cdalton@nvidia.com Review URL: https://chromiumcodereview.appspot.com/23471008 git-svn-id: http://skia.googlecode.com/svn/trunk@11140 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/gpu/gl/GrGLEffect.h | 7 ++++ src/gpu/gl/GrGLEffectMatrix.cpp | 1 + src/gpu/gl/GrGLProgram.cpp | 79 +++++++++++++++++++++++++++------------- src/gpu/gl/GrGLProgram.h | 8 ++++ src/gpu/gl/GrGLShaderBuilder.cpp | 32 +++++++--------- src/gpu/gl/GrGLShaderBuilder.h | 40 ++++++++++---------- 6 files changed, 103 insertions(+), 64 deletions(-) (limited to 'src/gpu/gl') diff --git a/src/gpu/gl/GrGLEffect.h b/src/gpu/gl/GrGLEffect.h index 5df22811c4..2d7258e026 100644 --- a/src/gpu/gl/GrGLEffect.h +++ b/src/gpu/gl/GrGLEffect.h @@ -51,6 +51,13 @@ public: virtual ~GrGLEffect(); + /** Called when GrGLProgram is about to create its GrGLShaderBuilder. When possible, effects + should handle programs that don't have a vertex shader. But if an effect requires special + vertex processing that can't be accomplished with the fixed pipeline, it can override this + method and return true to guarantee the GrGLShaderBuilder in emitCode has a VertexBuilder. + */ + virtual bool requiresVertexShader(const GrDrawEffect&) const { return false; } + /** Called when the program stage should insert its code into the shaders. The code in each shader will be in its own block ({}) and so locally scoped names will not collide across stages. diff --git a/src/gpu/gl/GrGLEffectMatrix.cpp b/src/gpu/gl/GrGLEffectMatrix.cpp index 7530b5911a..ef3812e0fb 100644 --- a/src/gpu/gl/GrGLEffectMatrix.cpp +++ b/src/gpu/gl/GrGLEffectMatrix.cpp @@ -48,6 +48,7 @@ GrSLType GrGLEffectMatrix::emitCode(GrGLShaderBuilder* builder, SkString* fsCoordName, SkString* vsCoordName, const char* suffix) { + // TODO: Handle vertexless shaders here before we start enabling them. GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder->getVertexBuilder(); SkASSERT(NULL != vertexBuilder); diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index ac9794d4d5..ebc57827c5 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -446,10 +446,32 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[], SkASSERT(0 == fProgramID); const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); + bool hasExplicitLocalCoords = -1 != header.fLocalCoordAttributeIndex; - bool needsVertexShader = true; + // Get the coeffs for the Mode-based color filter, determine if color is needed. + SkXfermode::Coeff colorCoeff; + SkXfermode::Coeff filterColorCoeff; + SkAssertResult( + SkXfermode::ModeAsCoeff(static_cast(header.fColorFilterXfermode), + &filterColorCoeff, + &colorCoeff)); + bool needColor, needFilterColor; + need_blend_inputs(filterColorCoeff, colorCoeff, &needFilterColor, &needColor); - GrGLShaderBuilder builder(fGpu->ctxInfo(), fUniformManager, fDesc, needsVertexShader); + // Create the GL effects. + bool hasVertexShaderEffects = false; + + SkTArray colorDrawEffects(needColor ? fDesc.numColorEffects() : 0); + if (needColor) { + this->buildGLEffects(&GrGLProgram::fColorEffects, colorStages, fDesc.numColorEffects(), + hasExplicitLocalCoords, &colorDrawEffects, &hasVertexShaderEffects); + } + + SkTArray coverageDrawEffects(fDesc.numCoverageEffects()); + this->buildGLEffects(&GrGLProgram::fCoverageEffects, coverageStages, fDesc.numCoverageEffects(), + hasExplicitLocalCoords, &coverageDrawEffects, &hasVertexShaderEffects); + + GrGLShaderBuilder builder(fGpu->ctxInfo(), fUniformManager, fDesc, hasVertexShaderEffects); if (GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder.getVertexBuilder()) { const char* viewMName; @@ -486,16 +508,6 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[], SkString inColor; GrSLConstantVec knownColorValue = this->genInputColor(&builder, &inColor); - // Get the coeffs for the Mode-based color filter, determine if color is needed. - SkXfermode::Coeff colorCoeff; - SkXfermode::Coeff filterColorCoeff; - SkAssertResult( - SkXfermode::ModeAsCoeff(static_cast(header.fColorFilterXfermode), - &filterColorCoeff, - &colorCoeff)); - bool needColor, needFilterColor; - need_blend_inputs(filterColorCoeff, colorCoeff, &needFilterColor, &needColor); - // used in order for builder to return the per-stage uniform handles. typedef SkTArray* UniHandleArrayPtr; int maxColorOrCovEffectCnt = GrMax(fDesc.numColorEffects(), fDesc.numCoverageEffects()); @@ -504,20 +516,17 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[], if (needColor) { for (int e = 0; e < fDesc.numColorEffects(); ++e) { + glEffects[e] = fColorEffects[e].fGLEffect; effectUniformArrays[e] = &fColorEffects[e].fSamplerUnis; } - builder.emitEffects(colorStages, + builder.emitEffects(glEffects.get(), + colorDrawEffects.begin(), fDesc.effectKeys(), fDesc.numColorEffects(), &inColor, &knownColorValue, - effectUniformArrays.get(), - glEffects.get()); - - for (int e = 0; e < fDesc.numColorEffects(); ++e) { - fColorEffects[e].fGLEffect = glEffects[e]; - } + effectUniformArrays.get()); } // Insert the color filter. This will soon be replaced by a color effect. @@ -548,19 +557,17 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[], GrSLConstantVec knownCoverageValue = this->genInputCoverage(&builder, &inCoverage); for (int e = 0; e < fDesc.numCoverageEffects(); ++e) { + glEffects[e] = fCoverageEffects[e].fGLEffect; effectUniformArrays[e] = &fCoverageEffects[e].fSamplerUnis; } - builder.emitEffects(coverageStages, + builder.emitEffects(glEffects.get(), + coverageDrawEffects.begin(), fDesc.getEffectKeys() + fDesc.numColorEffects(), fDesc.numCoverageEffects(), &inCoverage, &knownCoverageValue, - effectUniformArrays.get(), - glEffects.get()); - for (int e = 0; e < fDesc.numCoverageEffects(); ++e) { - fCoverageEffects[e].fGLEffect = glEffects[e]; - } + effectUniformArrays.get()); // discard if coverage is zero if (header.fDiscardIfZeroCoverage && kOnes_GrSLConstantVec != knownCoverageValue) { @@ -689,6 +696,28 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[], return true; } +void GrGLProgram::buildGLEffects(SkTArray GrGLProgram::* effectSet, + const GrEffectStage* stages[], + int count, + bool hasExplicitLocalCoords, + SkTArray* drawEffects, + bool* hasVertexShaderEffects) { + for (int e = 0; e < count; ++e) { + SkASSERT(NULL != stages[e] && NULL != stages[e]->getEffect()); + + const GrEffectStage& stage = *stages[e]; + SkNEW_APPEND_TO_TARRAY(drawEffects, GrDrawEffect, (stage, hasExplicitLocalCoords)); + + const GrDrawEffect& drawEffect = (*drawEffects)[e]; + GrGLEffect* effect = (this->*effectSet)[e].fGLEffect = + (*stage.getEffect())->getFactory().createGLInstance(drawEffect); + + if (!*hasVertexShaderEffects && effect->requiresVertexShader(drawEffect)) { + *hasVertexShaderEffects = true; + } + } +} + bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& builder, bool bindColorOut, bool bindDualSrcOut) { diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h index 4a16b0cf4c..bef2ecf544 100644 --- a/src/gpu/gl/GrGLProgram.h +++ b/src/gpu/gl/GrGLProgram.h @@ -178,6 +178,14 @@ private: void genGeometryShader(GrGLShaderBuilder::VertexBuilder* vertexBuilder) const; + // Creates a set of GrGLEffects and GrGLDrawEffects. + void buildGLEffects(SkTArray GrGLProgram::* effectSet, + const GrEffectStage* stages[], + int count, + bool hasExplicitLocalCoords, + SkTArray* drawEffects, + bool* hasVertexShaderEffects); + // Creates a GL program ID, binds shader attributes to GL vertex attrs, and links the program bool bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& builder, bool bindColorOut, diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp index e62bfdebe8..5e00d7f1bb 100644 --- a/src/gpu/gl/GrGLShaderBuilder.cpp +++ b/src/gpu/gl/GrGLShaderBuilder.cpp @@ -94,7 +94,7 @@ static const char kDstCopyColorName[] = "_dstColor"; GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo, GrGLUniformManager& uniformManager, const GrGLProgramDesc& desc, - bool needsVertexShader) + bool hasVertexShaderEffects) : fUniforms(kVarsPerBlock) , fCtxInfo(ctxInfo) , fUniformManager(uniformManager) @@ -106,9 +106,8 @@ GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo, const GrGLProgramDesc::KeyHeader& header = desc.getHeader(); - if (needsVertexShader) { - fVertexBuilder.reset(SkNEW_ARGS(VertexBuilder, (this, desc))); - } + // TODO: go vertexless when possible. + fVertexBuilder.reset(SkNEW_ARGS(VertexBuilder, (this, desc))); // Emit code to read the dst copy textue if necessary. if (kNoDstRead_DstReadKey != header.fDstReadKey && @@ -217,7 +216,7 @@ void GrGLShaderBuilder::nameVariable(SkString* out, char prefix, const char* nam const char* GrGLShaderBuilder::dstColor() { if (fCodeStage.inStageCode()) { - const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect(); + const GrEffectRef& effect = *fCodeStage.effect(); if (!effect->willReadDstColor()) { GrDebugCrash("GrGLEffect asked for dst color but its generating GrEffect " "did not request access."); @@ -363,7 +362,7 @@ GrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t vi const char* GrGLShaderBuilder::fragmentPosition() { if (fCodeStage.inStageCode()) { - const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect(); + const GrEffectRef& effect = *fCodeStage.effect(); if (!effect->willReadFragmentPosition()) { GrDebugCrash("GrGLEffect asked for frag position but its generating GrEffect " "did not request access."); @@ -500,24 +499,23 @@ void GrGLShaderBuilder::finished(GrGLuint programID) { } void GrGLShaderBuilder::emitEffects( - const GrEffectStage* effectStages[], + GrGLEffect* const glEffects[], + const GrDrawEffect drawEffects[], const GrBackendEffectFactory::EffectKey effectKeys[], int effectCnt, SkString* fsInOutColor, GrSLConstantVec* fsInOutColorKnownValue, - SkTArray* effectSamplerHandles[], - GrGLEffect* glEffects[]) { + SkTArray* effectSamplerHandles[]) { bool effectEmitted = false; SkString inColor = *fsInOutColor; SkString outColor; for (int e = 0; e < effectCnt; ++e) { - SkASSERT(NULL != effectStages[e] && NULL != effectStages[e]->getEffect()); - const GrEffectStage& stage = *effectStages[e]; - const GrEffectRef& effect = *stage.getEffect(); + const GrDrawEffect& drawEffect = drawEffects[e]; + const GrEffectRef& effect = *drawEffect.effect(); - CodeStage::AutoStageRestore csar(&fCodeStage, &stage); + CodeStage::AutoStageRestore csar(&fCodeStage, &effect); int numTextures = effect->numTextures(); SkSTArray<8, GrGLShaderBuilder::TextureSampler> textureSamplers; @@ -526,11 +524,9 @@ void GrGLShaderBuilder::emitEffects( textureSamplers[t].init(this, &effect->textureAccess(t), t); effectSamplerHandles[e]->push_back(textureSamplers[t].fSamplerUniform); } - GrDrawEffect drawEffect(stage, fVertexBuilder.get() - && fVertexBuilder->hasExplicitLocalCoords()); - int numAttributes = stage.getVertexAttribIndexCount(); - const int* attributeIndices = stage.getVertexAttribIndices(); + int numAttributes = drawEffect.getVertexAttribIndexCount(); + const int* attributeIndices = drawEffect.getVertexAttribIndices(); SkSTArray attributeNames; for (int a = 0; a < numAttributes; ++a) { // TODO: Make addAttribute mangle the name. @@ -542,8 +538,6 @@ void GrGLShaderBuilder::emitEffects( attributeName); } - glEffects[e] = effect->getFactory().createGLInstance(drawEffect); - if (kZeros_GrSLConstantVec == *fsInOutColorKnownValue) { // Effects have no way to communicate zeros, they treat an empty string as ones. this->nameVariable(&inColor, '\0', "input"); diff --git a/src/gpu/gl/GrGLShaderBuilder.h b/src/gpu/gl/GrGLShaderBuilder.h index 28f1b3822a..42df62ac45 100644 --- a/src/gpu/gl/GrGLShaderBuilder.h +++ b/src/gpu/gl/GrGLShaderBuilder.h @@ -107,7 +107,7 @@ public: GrGLShaderBuilder(const GrGLContextInfo&, GrGLUniformManager&, const GrGLProgramDesc&, - bool needsVertexShader); + bool hasVertexShaderEffects); /** * Use of these features may require a GLSL extension to be enabled. Shaders may not compile @@ -256,13 +256,13 @@ public: * glEffects array is updated to contain the GrGLEffect generated for each entry in * effectStages. */ - void emitEffects(const GrEffectStage* effectStages[], + void emitEffects(GrGLEffect* const glEffects[], + const GrDrawEffect drawEffects[], const GrBackendEffectFactory::EffectKey effectKeys[], int effectCnt, SkString* inOutFSColor, GrSLConstantVec* fsInOutColorKnownValue, - SkTArray* effectSamplerHandles[], - GrGLEffect* glEffects[]); + SkTArray* effectSamplerHandles[]); GrGLUniformManager::UniformHandle getRTHeightUniform() const { return fRTHeightUniform; } GrGLUniformManager::UniformHandle getDstCopyTopLeftUniform() const { @@ -388,16 +388,16 @@ private: private: class CodeStage : GrNoncopyable { public: - CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {} + CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffect(NULL) {} bool inStageCode() const { this->validate(); - return NULL != fEffectStage; + return NULL != fEffect; } - const GrEffectStage* effectStage() const { + const GrEffectRef* effect() const { this->validate(); - return fEffectStage; + return fEffect; } int stageIndex() const { @@ -407,34 +407,34 @@ private: class AutoStageRestore : GrNoncopyable { public: - AutoStageRestore(CodeStage* codeStage, const GrEffectStage* newStage) { + AutoStageRestore(CodeStage* codeStage, const GrEffectRef* effect) { SkASSERT(NULL != codeStage); fSavedIndex = codeStage->fCurrentIndex; - fSavedEffectStage = codeStage->fEffectStage; + fSavedEffect = codeStage->fEffect; - if (NULL == newStage) { + if (NULL == effect) { codeStage->fCurrentIndex = -1; } else { codeStage->fCurrentIndex = codeStage->fNextIndex++; } - codeStage->fEffectStage = newStage; + codeStage->fEffect = effect; fCodeStage = codeStage; } ~AutoStageRestore() { fCodeStage->fCurrentIndex = fSavedIndex; - fCodeStage->fEffectStage = fSavedEffectStage; + fCodeStage->fEffect = fSavedEffect; } private: - CodeStage* fCodeStage; - int fSavedIndex; - const GrEffectStage* fSavedEffectStage; + CodeStage* fCodeStage; + int fSavedIndex; + const GrEffectRef* fSavedEffect; }; private: - void validate() const { SkASSERT((NULL == fEffectStage) == (-1 == fCurrentIndex)); } - int fNextIndex; - int fCurrentIndex; - const GrEffectStage* fEffectStage; + void validate() const { SkASSERT((NULL == fEffect) == (-1 == fCurrentIndex)); } + int fNextIndex; + int fCurrentIndex; + const GrEffectRef* fEffect; } fCodeStage; /** -- cgit v1.2.3