From fe1233c3f12f81bb675718516bbb32f72af726ec Mon Sep 17 00:00:00 2001 From: joshualitt Date: Tue, 7 Oct 2014 12:16:35 -0700 Subject: Cleanup of shader building system this is a huge refactor and cleanup of the gl shader building system in Skia. The entire shader building pipeline is now part of GrGLProgramCreator, which takes a gp, and some fps, and creates a program. I added some subclasses of GrGLProgram to handle the eccentricities of Nvpr/Nvpres. Outside of the builders folder and GrGLPrograms, this change is basically just a rename solo gp BUG=skia: Review URL: https://codereview.chromium.org/611653002 --- src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp | 337 ++++++++++------------ 1 file changed, 157 insertions(+), 180 deletions(-) (limited to 'src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp') diff --git a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp index 4266d9fc43..488d07b8db 100644 --- a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp +++ b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp @@ -10,15 +10,15 @@ #include "GrGLProgramBuilder.h" #include "../GrGpuGL.h" -namespace { -#define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X) -#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X) +#define GL_CALL(X) GR_GL_CALL(fProgramBuilder->gpu()->glInterface(), X) +#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fProgramBuilder->gpu()->glInterface(), R, X) + // ES2 FS only guarantees mediump and lowp support static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision; -static const char kDstCopyColorName[] = "_dstColor"; -inline const char* declared_color_output_name() { return "fsColorOut"; } -inline const char* dual_source_output_name() { return "dualSourceOut"; } -inline void append_default_precision_qualifier(GrGLShaderVar::Precision p, +const char* GrGLFragmentShaderBuilder::kDstCopyColorName = "_dstColor"; +static const char* declared_color_output_name() { return "fsColorOut"; } +static const char* dual_source_output_name() { return "dualSourceOut"; } +static void append_default_precision_qualifier(GrGLShaderVar::Precision p, GrGLStandard standard, SkString* str) { // Desktop GLSL has added precision qualifiers but they don't do anything. @@ -40,10 +40,10 @@ inline void append_default_precision_qualifier(GrGLShaderVar::Precision p, } } } -} -GrGLFragmentShaderBuilder::DstReadKey GrGLFragmentShaderBuilder::KeyForDstRead( - const GrTexture* dstCopy, const GrGLCaps& caps) { +GrGLFragmentShaderBuilder::DstReadKey +GrGLFragmentShaderBuilder::KeyForDstRead(const GrTexture* dstCopy, + const GrGLCaps& caps) { uint32_t key = kYesDstRead_DstReadKeyBit; if (caps.fbFetchSupport()) { return key; @@ -60,8 +60,9 @@ GrGLFragmentShaderBuilder::DstReadKey GrGLFragmentShaderBuilder::KeyForDstRead( return static_cast(key); } -GrGLFragmentShaderBuilder::FragPosKey GrGLFragmentShaderBuilder::KeyForFragmentPosition( - const GrRenderTarget* dst, const GrGLCaps&) { +GrGLFragmentShaderBuilder::FragPosKey +GrGLFragmentShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst, + const GrGLCaps&) { if (kTopLeft_GrSurfaceOrigin == dst->origin()) { return kTopLeftFragPosRead_FragPosKey; } else { @@ -75,33 +76,9 @@ GrGLFragmentShaderBuilder::GrGLFragmentShaderBuilder(GrGLProgramBuilder* program , fHasCustomColorOutput(false) , fHasSecondaryOutput(false) , fSetupFragPosition(false) - , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey){ -} - -const char* GrGLFragmentShaderBuilder::dstColor() { - if (fProgramBuilder->fCodeStage.inStageCode()) { - const GrProcessor* effect = fProgramBuilder->fCodeStage.effectStage()->getProcessor(); - // TODO GPs can't read dst color, and full program builder only returns a pointer to the - // base fragment shader builder which does not have this function. Unfortunately, - // the code stage class only has a GrProcessor pointer so this is required for the time - // being - if (!static_cast(effect)->willReadDstColor()) { - SkDEBUGFAIL("GrGLProcessor asked for dst color but its generating GrProcessor " - "did not request access."); - return ""; - } - } - - GrGpuGL* gpu = fProgramBuilder->gpu(); - if (gpu->glCaps().fbFetchSupport()) { - this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1), - gpu->glCaps().fbFetchExtensionString()); - return gpu->glCaps().fbFetchColorName(); - } else if (fProgramBuilder->fUniformHandles.fDstCopySamplerUni.isValid()) { - return kDstCopyColorName; - } else { - return ""; - } + , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey) + , fHasReadDstColor(false) + , fHasReadFragmentPosition(false) { } bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) { @@ -140,15 +117,7 @@ SkString GrGLFragmentShaderBuilder::ensureFSCoords2D( } const char* GrGLFragmentShaderBuilder::fragmentPosition() { - GrGLProgramBuilder::CodeStage* cs = &fProgramBuilder->fCodeStage; - if (cs->inStageCode()) { - const GrProcessor* effect = cs->effectStage()->getProcessor(); - if (!effect->willReadFragmentPosition()) { - SkDEBUGFAIL("GrGLProcessor asked for frag position but its generating GrProcessor " - "did not request access."); - return ""; - } - } + fHasReadFragmentPosition = true; GrGpuGL* gpu = fProgramBuilder->gpu(); // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers @@ -175,16 +144,15 @@ const char* GrGLFragmentShaderBuilder::fragmentPosition() { static const char* kCoordName = "fragCoordYDown"; if (!fSetupFragPosition) { // temporarily change the stage index because we're inserting non-stage code. - GrGLProgramBuilder::CodeStage::AutoStageRestore csar(cs, NULL); - + GrGLProgramBuilder::AutoStageRestore asr(fProgramBuilder); SkASSERT(!fProgramBuilder->fUniformHandles.fRTHeightUni.isValid()); const char* rtHeightName; fProgramBuilder->fUniformHandles.fRTHeightUni = fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, - kFloat_GrSLType, - "RTHeight", - &rtHeightName); + kFloat_GrSLType, + "RTHeight", + &rtHeightName); // Using glFragCoord.zw for the last two components tickles an Adreno driver bug that // causes programs to fail to link. Making this function return a vec2() didn't fix the @@ -198,24 +166,133 @@ const char* GrGLFragmentShaderBuilder::fragmentPosition() { } } -void GrGLFragmentShaderBuilder::addVarying(GrSLType type, - const char* name, - const char** fsInName, - GrGLShaderVar::Precision fsPrecision) { - fInputs.push_back().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, name, fsPrecision); - if (fsInName) { - *fsInName = name; +const char* GrGLFragmentShaderBuilder::dstColor() { + fHasReadDstColor = true; + + GrGpuGL* gpu = fProgramBuilder->gpu(); + if (gpu->glCaps().fbFetchSupport()) { + this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1), + gpu->glCaps().fbFetchExtensionString()); + return gpu->glCaps().fbFetchColorName(); + } else if (fProgramBuilder->fUniformHandles.fDstCopySamplerUni.isValid()) { + return kDstCopyColorName; + } else { + return ""; } } -void GrGLFragmentShaderBuilder::bindProgramLocations(GrGLuint programId) { - GrGpuGL* gpu = fProgramBuilder->gpu(); - if (fHasCustomColorOutput) { - GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name())); +void GrGLFragmentShaderBuilder::emitCodeToReadDstTexture() { + bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & fProgramBuilder->header().fDstReadKey); + const char* dstCopyTopLeftName; + const char* dstCopyCoordScaleName; + const char* dstCopySamplerName; + uint32_t configMask; + if (SkToBool(kUseAlphaConfig_DstReadKeyBit & fProgramBuilder->header().fDstReadKey)) { + configMask = kA_GrColorComponentFlag; + } else { + configMask = kRGBA_GrColorComponentFlags; } - if (fHasSecondaryOutput) { - GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_name())); + fProgramBuilder->fUniformHandles.fDstCopySamplerUni = + fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, + kSampler2D_GrSLType, + "DstCopySampler", + &dstCopySamplerName); + fProgramBuilder->fUniformHandles.fDstCopyTopLeftUni = + fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, + kVec2f_GrSLType, + "DstCopyUpperLeft", + &dstCopyTopLeftName); + fProgramBuilder->fUniformHandles.fDstCopyScaleUni = + fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, + kVec2f_GrSLType, + "DstCopyCoordScale", + &dstCopyCoordScaleName); + const char* fragPos = this->fragmentPosition(); + + this->codeAppend("// Read color from copy of the destination.\n"); + this->codeAppendf("vec2 _dstTexCoord = (%s.xy - %s) * %s;", + fragPos, dstCopyTopLeftName, dstCopyCoordScaleName); + if (!topDown) { + this->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;"); + } + this->codeAppendf("vec4 %s = ", GrGLFragmentShaderBuilder::kDstCopyColorName); + this->appendTextureLookup(dstCopySamplerName, + "_dstTexCoord", + configMask, + "rgba"); + this->codeAppend(";"); +} + +void GrGLFragmentShaderBuilder::enableCustomOutput() { + SkASSERT(!fHasCustomColorOutput); + fHasCustomColorOutput = true; + fOutputs.push_back().set(kVec4f_GrSLType, + GrGLShaderVar::kOut_TypeModifier, + declared_color_output_name()); +} + +void GrGLFragmentShaderBuilder::enableSecondaryOutput() { + SkASSERT(!fHasSecondaryOutput); + fHasSecondaryOutput = true; + fOutputs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kOut_TypeModifier, + dual_source_output_name()); +} + +const char* GrGLFragmentShaderBuilder::getPrimaryColorOutputName() const { + return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor"; +} + +const char* GrGLFragmentShaderBuilder::getSecondaryColorOutputName() const { + return dual_source_output_name(); +} + +void GrGLFragmentShaderBuilder::enableSecondaryOutput(const GrGLSLExpr4& inputColor, + const GrGLSLExpr4& inputCoverage) { + this->enableSecondaryOutput(); + const char* secondaryOutputName = this->getSecondaryColorOutputName(); + GrGLSLExpr4 coeff(1); + switch (fProgramBuilder->header().fSecondaryOutputType) { + case GrOptDrawState::kCoverage_SecondaryOutputType: + break; + case GrOptDrawState::kCoverageISA_SecondaryOutputType: + // Get (1-A) into coeff + coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inputColor.a()); + break; + case GrOptDrawState::kCoverageISC_SecondaryOutputType: + // Get (1-RGBA) into coeff + coeff = GrGLSLExpr4(1) - inputColor; + break; + default: + SkFAIL("Unexpected Secondary Output"); + } + // Get coeff * coverage into modulate and then write that to the dual source output. + this->codeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inputCoverage).c_str()); +} + +void GrGLFragmentShaderBuilder::combineColorAndCoverage(const GrGLSLExpr4& inputColor, + const GrGLSLExpr4& inputCoverage) { + GrGLSLExpr4 fragColor = inputColor * inputCoverage; + switch (fProgramBuilder->header().fPrimaryOutputType) { + case GrOptDrawState::kModulate_PrimaryOutputType: + break; + case GrOptDrawState::kCombineWithDst_PrimaryOutputType: + { + // Tack on "+(1-coverage)dst onto the frag color. + GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inputCoverage; + GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(this->dstColor()); + fragColor = fragColor + dstContribution; + } + break; + default: + SkFAIL("Unknown Primary Output"); + } + + // On any post 1.10 GLSL supporting GPU, we declare custom output + if (k110_GrGLSLGeneration != fProgramBuilder->gpu()->glslGeneration()) { + this->enableCustomOutput(); } + + this->codeAppendf("\t%s = %s;\n", this->getPrimaryColorOutputName(), fragColor.c_str()); } bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId, @@ -227,10 +304,10 @@ bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId, gpu->glStandard(), &fragShaderSrc); fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kFragment_Visibility, &fragShaderSrc); - fProgramBuilder->appendDecls(fInputs, &fragShaderSrc); + this->appendDecls(fInputs, &fragShaderSrc); // We shouldn't have declared outputs on 1.10 SkASSERT(k110_GrGLSLGeneration != gpu->glslGeneration() || fOutputs.empty()); - fProgramBuilder->appendDecls(fOutputs, &fragShaderSrc); + this->appendDecls(fOutputs, &fragShaderSrc); fragShaderSrc.append(fFunctions); fragShaderSrc.append("void main() {\n"); fragShaderSrc.append(fCode); @@ -248,121 +325,21 @@ bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId, return true; } -void GrGLFragmentShaderBuilder::emitCodeBeforeEffects() { - const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader(); - GrGpuGL* gpu = fProgramBuilder->gpu(); - - /////////////////////////////////////////////////////////////////////////// - // emit code to read the dst copy texture, if necessary - if (kNoDstRead_DstReadKey != header.fDstReadKey && !gpu->glCaps().fbFetchSupport()) { - bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey); - const char* dstCopyTopLeftName; - const char* dstCopyCoordScaleName; - const char* dstCopySamplerName; - uint32_t configMask; - if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) { - configMask = kA_GrColorComponentFlag; - } else { - configMask = kRGBA_GrColorComponentFlags; - } - fProgramBuilder->fUniformHandles.fDstCopySamplerUni = - fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, - kSampler2D_GrSLType, - "DstCopySampler", - &dstCopySamplerName); - fProgramBuilder->fUniformHandles.fDstCopyTopLeftUni = - fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, - kVec2f_GrSLType, - "DstCopyUpperLeft", - &dstCopyTopLeftName); - fProgramBuilder->fUniformHandles.fDstCopyScaleUni = - fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, - kVec2f_GrSLType, - "DstCopyCoordScale", - &dstCopyCoordScaleName); - const char* fragPos = fragmentPosition(); - - this->codeAppend("// Read color from copy of the destination.\n"); - this->codeAppendf("vec2 _dstTexCoord = (%s.xy - %s) * %s;", - fragPos, dstCopyTopLeftName, dstCopyCoordScaleName); - if (!topDown) { - this->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;"); - } - this->codeAppendf("vec4 %s = ", kDstCopyColorName); - this->appendTextureLookup(dstCopySamplerName, - "_dstTexCoord", - configMask, - "rgba"); - this->codeAppend(";"); - } - - if (k110_GrGLSLGeneration != gpu->glslGeneration()) { - fOutputs.push_back().set(kVec4f_GrSLType, - GrGLShaderVar::kOut_TypeModifier, - declared_color_output_name()); - fHasCustomColorOutput = true; - } -} - -void GrGLFragmentShaderBuilder::emitCodeAfterEffects(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage) { - const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader(); - - /////////////////////////////////////////////////////////////////////////// - // write the secondary color output if necessary - if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType) { - const char* secondaryOutputName = this->enableSecondaryOutput(); - GrGLSLExpr4 coeff(1); - switch (header.fSecondaryOutputType) { - case GrOptDrawState::kCoverage_SecondaryOutputType: - break; - case GrOptDrawState::kCoverageISA_SecondaryOutputType: - // Get (1-A) into coeff - coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inputColor.a()); - break; - case GrOptDrawState::kCoverageISC_SecondaryOutputType: - // Get (1-RGBA) into coeff - coeff = GrGLSLExpr4(1) - inputColor; - break; - default: - SkFAIL("Unexpected Secondary Output"); - } - // Get coeff * coverage into modulate and then write that to the dual source output. - codeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inputCoverage).c_str()); +void GrGLFragmentShaderBuilder::bindFragmentShaderLocations(GrGLuint programID) { + if (fHasCustomColorOutput) { + GL_CALL(BindFragDataLocation(programID, 0, declared_color_output_name())); } - - /////////////////////////////////////////////////////////////////////////// - // combine color and coverage as frag color - - // Get "color * coverage" into fragColor - GrGLSLExpr4 fragColor = inputColor * inputCoverage; - switch (header.fPrimaryOutputType) { - case GrOptDrawState::kModulate_PrimaryOutputType: - break; - case GrOptDrawState::kCombineWithDst_PrimaryOutputType: - { - // Tack on "+(1-coverage)dst onto the frag color. - GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inputCoverage; - GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(dstColor()); - fragColor = fragColor + dstContribution; - } - break; - default: - SkFAIL("Unknown Primary Output"); + if (fHasSecondaryOutput) { + GL_CALL(BindFragDataLocationIndexed(programID, 0, 1, dual_source_output_name())); } - codeAppendf("\t%s = %s;\n", this->getColorOutputName(), fragColor.c_str()); } -const char* GrGLFragmentShaderBuilder::enableSecondaryOutput() { - if (!fHasSecondaryOutput) { - fOutputs.push_back().set(kVec4f_GrSLType, - GrGLShaderVar::kOut_TypeModifier, - dual_source_output_name()); - fHasSecondaryOutput = true; +void GrGLFragmentShaderBuilder::addVarying(GrSLType type, + const char* name, + const char** fsInName, + GrGLShaderVar::Precision fsPrecision) { + fInputs.push_back().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, name, fsPrecision); + if (fsInName) { + *fsInName = name; } - return dual_source_output_name(); } - -const char* GrGLFragmentShaderBuilder::getColorOutputName() const { - return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor"; -} - -- cgit v1.2.3