From 574a4c153d8a3f42b2806848f5c23cbf55e18bbb Mon Sep 17 00:00:00 2001 From: egdaniel Date: Mon, 2 Nov 2015 06:22:44 -0800 Subject: [PATCH] Move shader compiling to ProgramBuilder and various ShaderBuilder cleanups. An additional positive of this CL is that GrGLShaderBuilder is now GL independent besides GrGLProgramBuilder BUG=skia: Review URL: https://codereview.chromium.org/1431433003 --- gm/dcshader.cpp | 1 + src/core/SkLightingShader.cpp | 1 + .../effects/GrXfermodeFragmentProcessor.cpp | 1 + src/gpu/gl/GrGLCaps.cpp | 4 ++ src/gpu/gl/GrGLGpu.cpp | 18 +++++- src/gpu/gl/GrGLGpu.h | 5 ++ src/gpu/gl/GrGLProgram.cpp | 1 + src/gpu/gl/GrGLProgramDesc.cpp | 3 +- .../gl/builders/GrGLFragmentShaderBuilder.cpp | 45 +++------------ .../gl/builders/GrGLFragmentShaderBuilder.h | 21 ++----- .../gl/builders/GrGLGeometryShaderBuilder.cpp | 5 -- .../gl/builders/GrGLGeometryShaderBuilder.h | 2 +- src/gpu/gl/builders/GrGLProgramBuilder.cpp | 31 +++++++++- src/gpu/gl/builders/GrGLProgramBuilder.h | 8 ++- src/gpu/gl/builders/GrGLShaderBuilder.cpp | 56 +++++-------------- src/gpu/gl/builders/GrGLShaderBuilder.h | 23 ++++---- .../gl/builders/GrGLVertexShaderBuilder.cpp | 10 ---- src/gpu/gl/builders/GrGLVertexShaderBuilder.h | 4 +- src/gpu/glsl/GrGLSLCaps.cpp | 1 + src/gpu/glsl/GrGLSLCaps.h | 10 ++++ tests/GLProgramsTest.cpp | 1 + 21 files changed, 120 insertions(+), 131 deletions(-) diff --git a/gm/dcshader.cpp b/gm/dcshader.cpp index d7eb3b518f..d1a9d4ca6f 100644 --- a/gm/dcshader.cpp +++ b/gm/dcshader.cpp @@ -11,6 +11,7 @@ #include "GrFragmentProcessor.h" #include "GrCoordTransform.h" #include "effects/GrXfermodeFragmentProcessor.h" +#include "gl/GrGLFragmentProcessor.h" #include "gl/builders/GrGLProgramBuilder.h" #include "glsl/GrGLSLProgramDataManager.h" #include "Resources.h" diff --git a/src/core/SkLightingShader.cpp b/src/core/SkLightingShader.cpp index d3d6a2849f..2d7000aefa 100644 --- a/src/core/SkLightingShader.cpp +++ b/src/core/SkLightingShader.cpp @@ -130,6 +130,7 @@ private: #include "GrCoordTransform.h" #include "GrFragmentProcessor.h" #include "GrTextureAccess.h" +#include "gl/GrGLFragmentProcessor.h" #include "gl/builders/GrGLProgramBuilder.h" #include "glsl/GrGLSLProgramDataManager.h" #include "SkGr.h" diff --git a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp index 895838f673..73343e75c4 100644 --- a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp +++ b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp @@ -9,6 +9,7 @@ #include "GrFragmentProcessor.h" #include "effects/GrConstColorProcessor.h" +#include "gl/GrGLFragmentProcessor.h" #include "gl/GrGLSLBlend.h" #include "gl/builders/GrGLProgramBuilder.h" #include "SkGrPriv.h" diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index 9879846ef2..1d25a2ca2f 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -591,6 +591,10 @@ void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo) { glslCaps->fVersionDeclString = get_glsl_version_decl_string(standard, glslCaps->fGLSLGeneration, fIsCoreProfile); + + if (kGLES_GrGLStandard == standard && k110_GrGLSLGeneration == glslCaps->fGLSLGeneration) { + glslCaps->fShaderDerivativeExtensionString = "GL_OES_standard_derivatives"; + } } bool GrGLCaps::hasPathRenderingSupport(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) { diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index a0809c1d7a..dc3ea0c3d7 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -2396,6 +2396,22 @@ static inline GrGLenum tile_to_gl_wrap(SkShader::TileMode tm) { return gWrapModes[tm]; } +const GrGLenum* GrGLGpu::GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps) { + if (caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(config)) { + if (caps.textureRedSupport()) { + static const GrGLenum gRedSmear[] = { GR_GL_RED, GR_GL_RED, GR_GL_RED, GR_GL_RED }; + return gRedSmear; + } else { + static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA, + GR_GL_ALPHA, GR_GL_ALPHA }; + return gAlphaSmear; + } + } else { + static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN, GR_GL_BLUE, GR_GL_ALPHA }; + return gStraight; + } +} + void GrGLGpu::bindTexture(int unitIdx, const GrTextureParams& params, GrGLTexture* texture) { SkASSERT(texture); @@ -2462,7 +2478,7 @@ void GrGLGpu::bindTexture(int unitIdx, const GrTextureParams& params, GrGLTextur newTexParams.fWrapS = tile_to_gl_wrap(params.getTileModeX()); newTexParams.fWrapT = tile_to_gl_wrap(params.getTileModeY()); memcpy(newTexParams.fSwizzleRGBA, - GrGLShaderBuilder::GetTexParamSwizzle(texture->config(), this->glCaps()), + GetTexParamSwizzle(texture->config(), this->glCaps()), sizeof(newTexParams.fSwizzleRGBA)); if (setAll || newTexParams.fMagFilter != oldTexParams.fMagFilter) { this->setTextureUnit(unitIdx); diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h index 396d488174..c10d79e744 100644 --- a/src/gpu/gl/GrGLGpu.h +++ b/src/gpu/gl/GrGLGpu.h @@ -128,6 +128,11 @@ public: bool isTestingOnlyBackendTexture(GrBackendObject id) const override; void deleteTestingOnlyBackendTexture(GrBackendObject id) const override; + /** If texture swizzling is available using tex parameters then it is preferred over mangling + the generated shader code. This potentially allows greater reuse of cached shaders. */ + static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps); + + private: GrGLGpu(GrGLContext* ctx, GrContext* context); diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index 552a0fb27f..23e0df731c 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -17,6 +17,7 @@ #include "GrPathProcessor.h" #include "GrPipeline.h" #include "GrXferProcessor.h" +#include "gl/GrGLFragmentProcessor.h" #include "SkXfermode.h" #define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X) diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp index 281f2c06a6..a232a63514 100644 --- a/src/gpu/gl/GrGLProgramDesc.cpp +++ b/src/gpu/gl/GrGLProgramDesc.cpp @@ -159,8 +159,7 @@ bool GrGLProgramDescBuilder::Build(GrProgramDesc* desc, if (pipeline.readsFragPosition()) { header->fFragPosKey = - GrGLFragmentShaderBuilder::KeyForFragmentPosition(pipeline.getRenderTarget(), - gpu->glCaps()); + GrGLFragmentShaderBuilder::KeyForFragmentPosition(pipeline.getRenderTarget()); } else { header->fFragPosKey = 0; } diff --git a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp index 6f049588f6..eea8850f8f 100644 --- a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp +++ b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp @@ -6,6 +6,7 @@ */ #include "GrGLFragmentShaderBuilder.h" +#include "GrRenderTarget.h" #include "GrGLProgramBuilder.h" #include "gl/GrGLGpu.h" #include "glsl/GrGLSL.h" @@ -59,26 +60,8 @@ static const char* specific_layout_qualifier_name(GrBlendEquation equation) { kGrBlendEquationCnt - kFirstAdvancedGrBlendEquation); } -GrGLFragmentShaderBuilder::DstReadKey -GrGLFragmentShaderBuilder::KeyForDstRead(const GrTexture* dstTexture, const GrGLCaps& caps) { - uint32_t key = kYesDstRead_DstReadKeyBit; - if (caps.glslCaps()->fbFetchSupport()) { - return key; - } - SkASSERT(dstTexture); - if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstTexture->config())) { - // The fact that the config is alpha-only must be considered when generating code. - key |= kUseAlphaConfig_DstReadKeyBit; - } - if (kTopLeft_GrSurfaceOrigin == dstTexture->origin()) { - key |= kTopLeftOrigin_DstReadKeyBit; - } - SkASSERT(static_cast(key) == key); - return static_cast(key); -} - GrGLFragmentShaderBuilder::FragPosKey -GrGLFragmentShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst, const GrGLCaps&) { +GrGLFragmentShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst) { if (kTopLeft_GrSurfaceOrigin == dst->origin()) { return kTopLeftFragPosRead_FragPosKey; } else { @@ -101,14 +84,12 @@ GrGLFragmentShaderBuilder::GrGLFragmentShaderBuilder(GrGLProgramBuilder* program bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) { switch (feature) { case kStandardDerivatives_GLSLFeature: { - GrGLGpu* gpu = fProgramBuilder->gpu(); - if (!gpu->glCaps().shaderCaps()->shaderDerivativeSupport()) { + if (!fProgramBuilder->glslCaps()->shaderDerivativeSupport()) { return false; } - if (kGLES_GrGLStandard == gpu->glStandard() && - k110_GrGLSLGeneration == gpu->glslGeneration()) { - this->addFeature(1 << kStandardDerivatives_GLSLFeature, - "GL_OES_standard_derivatives"); + const char* extension = fProgramBuilder->glslCaps()->shaderDerivativeExtensionString(); + if (extension) { + this->addFeature(1 << kStandardDerivatives_GLSLFeature, extension); } return true; } @@ -248,7 +229,7 @@ void GrGLFragmentShaderBuilder::enableSecondaryOutput() { // and vice versa, since it is not allowed to use a built-in gl_FragColor and a custom // output. The condition also co-incides with the condition in whici GLES SL 2.0 // requires the built-in gl_SecondaryFragColorEXT, where as 3.0 requires a custom output. - const GrGLSLCaps& caps = *fProgramBuilder->gpu()->glCaps().glslCaps(); + const GrGLSLCaps& caps = *fProgramBuilder->glslCaps(); if (caps.mustDeclareFragmentShaderOutput()) { fOutputs.push_back().set(kVec4f_GrSLType, GrGLSLShaderVar::kOut_TypeModifier, declared_secondary_color_output_name()); @@ -265,20 +246,10 @@ const char* GrGLFragmentShaderBuilder::getSecondaryColorOutputName() const { : "gl_SecondaryFragColorEXT"; } -bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId, - SkTDArray* shaderIds) { - this->versionDecl() = fProgramBuilder->glslCaps()->versionDeclString(); +void GrGLFragmentShaderBuilder::onFinalize() { GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, *fProgramBuilder->glslCaps(), &this->precisionQualifier()); - this->compileAndAppendLayoutQualifiers(); - fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kFragment_Visibility, - &this->uniforms()); - this->appendDecls(fInputs, &this->inputs()); - // We shouldn't have declared outputs on 1.10 - SkASSERT(k110_GrGLSLGeneration != fProgramBuilder->gpu()->glslGeneration() || fOutputs.empty()); - this->appendDecls(fOutputs, &this->outputs()); - return this->finalize(programId, GR_GL_FRAGMENT_SHADER, shaderIds); } void GrGLFragmentShaderBuilder::bindFragmentShaderLocations(GrGLuint programID) { diff --git a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h index ed92703a01..39ca5e7dad 100644 --- a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h +++ b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h @@ -10,8 +10,10 @@ #include "GrGLShaderBuilder.h" +#include "gl/GrGLTypes.h" #include "glsl/GrGLSLProcessorTypes.h" +class GrRenderTarget; class GrGLVarying; /* @@ -111,18 +113,12 @@ private: // TODO rename to Fragment Builder class GrGLFragmentShaderBuilder : public GrGLXPFragmentBuilder { public: - typedef uint8_t DstReadKey; typedef uint8_t FragPosKey; - /** Returns a key for adding code to read the dst texture color in service of effects that - require reading the dst. It must not return 0 because 0 indicates that there is no dst - texture at all (in which case this function should not be called). */ - static DstReadKey KeyForDstRead(const GrTexture* dsttexture, const GrGLCaps&); - /** Returns a key for reading the fragment location. This should only be called if there is an effect that will requires the fragment position. If the fragment position is not required, the key is 0. */ - static FragPosKey KeyForFragmentPosition(const GrRenderTarget* dst, const GrGLCaps&); + static FragPosKey KeyForFragmentPosition(const GrRenderTarget* dst); GrGLFragmentShaderBuilder(GrGLProgramBuilder* program, uint8_t fragPosKey); @@ -141,7 +137,6 @@ private: void enableSecondaryOutput(); const char* getPrimaryColorOutputName() const; const char* getSecondaryColorOutputName() const; - bool compileAndAttachShaders(GrGLuint programId, SkTDArray* shaderIds); void bindFragmentShaderLocations(GrGLuint programID); // As GLProcessors emit code, there are some conditions we need to verify. We use the below @@ -158,6 +153,8 @@ private: */ void addVarying(GrGLVarying*, GrSLPrecision); + void onFinalize() override; + /** * Features that should only be enabled by GrGLFragmentShaderBuilder itself. */ @@ -168,14 +165,6 @@ private: kLastGLSLPrivateFeature = kBlendFuncExtended_GLSLPrivateFeature }; - // Interpretation of DstReadKey when generating code - enum { - kNoDstRead_DstReadKey = 0, - kYesDstRead_DstReadKeyBit = 0x1, // Set if we do a dst-copy-read. - kUseAlphaConfig_DstReadKeyBit = 0x2, // Set if dst-copy config is alpha only. - kTopLeftOrigin_DstReadKeyBit = 0x4, // Set if dst-copy origin is top-left. - }; - // Interpretation of FragPosKey when generating code enum { kNoFragPosRead_FragPosKey = 0, // The fragment positition will not be needed. diff --git a/src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp b/src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp index f8e6389735..159b904f2c 100644 --- a/src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp +++ b/src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp @@ -37,8 +37,3 @@ void GrGLGeometryBuilder::addVarying(const char* name, GrSLPrecision precision, } } -bool GrGLGeometryBuilder::compileAndAttachShaders(GrGLuint programId, - SkTDArray* shaderIds) { - SkFAIL("Geometry shaders are not currently supported"); - return false; -} diff --git a/src/gpu/gl/builders/GrGLGeometryShaderBuilder.h b/src/gpu/gl/builders/GrGLGeometryShaderBuilder.h index 4fe8a23961..7691666a60 100644 --- a/src/gpu/gl/builders/GrGLGeometryShaderBuilder.h +++ b/src/gpu/gl/builders/GrGLGeometryShaderBuilder.h @@ -22,7 +22,7 @@ private: */ void addVarying(const char* name, GrSLPrecision precision, GrGLVarying*); - bool compileAndAttachShaders(GrGLuint programId, SkTDArray* shaderIds); + void onFinalize() override {} friend class GrGLProgramBuilder; diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp index 2afd3c4ab4..aca8e53f85 100644 --- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp +++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp @@ -13,11 +13,13 @@ #include "GrTexture.h" #include "SkRTConf.h" #include "SkTraceEvent.h" +#include "gl/GrGLFragmentProcessor.h" #include "gl/GrGLGeometryProcessor.h" #include "gl/GrGLGpu.h" #include "gl/GrGLProgram.h" #include "gl/GrGLSLPrettyPrint.h" #include "gl/GrGLXferProcessor.h" +#include "gl/builders/GrGLShaderStringBuilder.h" #include "glsl/GrGLSLCaps.h" #include "glsl/GrGLSLProgramDataManager.h" #include "glsl/GrGLSLTextureSampler.h" @@ -380,6 +382,28 @@ void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor, } } +bool GrGLProgramBuilder::compileAndAttachShaders(GrGLShaderBuilder& shader, + GrGLuint programId, + GrGLenum type, + SkTDArray* shaderIds) { + GrGLGpu* gpu = this->gpu(); + GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(), + programId, + type, + shader.fCompilerStrings.begin(), + shader.fCompilerStringLengths.begin(), + shader.fCompilerStrings.count(), + gpu->stats()); + + if (!shaderId) { + return false; + } + + *shaderIds->append() = shaderId; + + return true; +} + GrGLProgram* GrGLProgramBuilder::finalize() { // verify we can get a program id GrGLuint programID; @@ -390,8 +414,8 @@ GrGLProgram* GrGLProgramBuilder::finalize() { // compile shaders and bind attributes / uniforms SkTDArray shadersToDelete; - - if (!fVS.compileAndAttachShaders(programID, &shadersToDelete)) { + fVS.finalize(kVertex_Visibility); + if (!this->compileAndAttachShaders(fVS, programID, GR_GL_VERTEX_SHADER, &shadersToDelete)) { this->cleanupProgram(programID, shadersToDelete); return nullptr; } @@ -402,7 +426,8 @@ GrGLProgram* GrGLProgramBuilder::finalize() { fVS.bindVertexAttributes(programID); } - if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) { + fFS.finalize(kFragment_Visibility); + if (!this->compileAndAttachShaders(fFS, programID, GR_GL_FRAGMENT_SHADER, &shadersToDelete)) { this->cleanupProgram(programID, shadersToDelete); return nullptr; } diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h index 474544060b..e1525c42ef 100644 --- a/src/gpu/gl/builders/GrGLProgramBuilder.h +++ b/src/gpu/gl/builders/GrGLProgramBuilder.h @@ -11,6 +11,7 @@ #include "GrGLFragmentShaderBuilder.h" #include "GrGLGeometryShaderBuilder.h" #include "GrGLVertexShaderBuilder.h" +#include "gl/GrGLProgramDataManager.h" #include "glsl/GrGLSLProgramDataManager.h" #include "glsl/GrGLSLTextureSampler.h" #include "../GrGLPrimitiveProcessor.h" @@ -18,6 +19,7 @@ #include "../../GrPipeline.h" class GrFragmentProcessor; +class GrGLContextInfo; class GrGLSLCaps; // Enough precision to represent 1 / 2048 accurately in printf @@ -44,7 +46,7 @@ public: virtual ~GrGLUniformBuilder() {} typedef GrGLSLProgramDataManager::UniformHandle UniformHandle; - typedef GrGLProgramDataManager::SeparableVaryingHandle SeparableVaryingHandle; + typedef GrGLSLProgramDataManager::SeparableVaryingHandle SeparableVaryingHandle; /** Add a uniform variable to the current program, that has visibility in one or more shaders. visibility is a bitfield of ShaderVisibility values indicating from which shaders the @@ -334,6 +336,10 @@ protected: GrGLSLTextureSampler::TextureSamplerArray* outSamplers, GrGLInstalledProc*); + bool compileAndAttachShaders(GrGLShaderBuilder& shader, + GrGLuint programId, + GrGLenum type, + SkTDArray* shaderIds); GrGLProgram* finalize(); virtual void bindProgramResourceLocations(GrGLuint programID); bool checkLinkStatus(GrGLuint programID); diff --git a/src/gpu/gl/builders/GrGLShaderBuilder.cpp b/src/gpu/gl/builders/GrGLShaderBuilder.cpp index 991ac91176..95607ecabe 100644 --- a/src/gpu/gl/builders/GrGLShaderBuilder.cpp +++ b/src/gpu/gl/builders/GrGLShaderBuilder.cpp @@ -6,11 +6,8 @@ */ #include "GrGLShaderBuilder.h" -#include "GrGLProgramBuilder.h" -#include "GrGLShaderStringBuilder.h" -#include "gl/GrGLCaps.h" -#include "gl/GrGLContext.h" #include "gl/GrGLGpu.h" +#include "gl/builders/GrGLProgramBuilder.h" #include "glsl/GrGLSLCaps.h" #include "glsl/GrGLSLShaderVar.h" #include "glsl/GrGLSLTextureSampler.h" @@ -123,23 +120,6 @@ void GrGLShaderBuilder::appendTextureLookupAndModulate(const char* modulation, this->codeAppend((GrGLSLExpr4(modulation) * GrGLSLExpr4(lookup)).c_str()); } - -const GrGLenum* GrGLShaderBuilder::GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps) { - if (caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(config)) { - if (caps.textureRedSupport()) { - static const GrGLenum gRedSmear[] = { GR_GL_RED, GR_GL_RED, GR_GL_RED, GR_GL_RED }; - return gRedSmear; - } else { - static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA, - GR_GL_ALPHA, GR_GL_ALPHA }; - return gAlphaSmear; - } - } else { - static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN, GR_GL_BLUE, GR_GL_ALPHA }; - return gStraight; - } -} - void GrGLShaderBuilder::addFeature(uint32_t featureBit, const char* extensionName) { if (!(featureBit & fFeaturesAddedMask)) { this->extensions().appendf("#extension %s: require\n", extensionName); @@ -168,8 +148,8 @@ void GrGLShaderBuilder::appendTextureLookup(const char* samplerName, } void GrGLShaderBuilder::addLayoutQualifier(const char* param, InterfaceQualifier interface) { - SkASSERT(fProgramBuilder->gpu()->glslGeneration() >= k330_GrGLSLGeneration || - fProgramBuilder->gpu()->glCaps().glslCaps()->mustEnableAdvBlendEqs()); + SkASSERT(fProgramBuilder->glslCaps()->generation() >= k330_GrGLSLGeneration || + fProgramBuilder->glslCaps()->mustEnableAdvBlendEqs()); fLayoutParams[interface].push_back() = param; } @@ -194,9 +174,17 @@ void GrGLShaderBuilder::compileAndAppendLayoutQualifiers() { GR_STATIC_ASSERT(SK_ARRAY_COUNT(interfaceQualifierNames) == kLastInterfaceQualifier + 1); } -bool -GrGLShaderBuilder::finalize(GrGLuint programId, GrGLenum type, SkTDArray* shaderIds) { +void GrGLShaderBuilder::finalize(uint32_t visibility) { SkASSERT(!fFinalized); + this->versionDecl() = fProgramBuilder->glslCaps()->versionDeclString(); + this->compileAndAppendLayoutQualifiers(); + fProgramBuilder->appendUniformDecls((GrGLProgramBuilder::ShaderVisibility) visibility, + &this->uniforms()); + this->appendDecls(fInputs, &this->inputs()); + SkASSERT(k110_GrGLSLGeneration != fProgramBuilder->glslCaps()->generation() || + fOutputs.empty()); + this->appendDecls(fOutputs, &this->outputs()); + this->onFinalize(); // append the 'footer' to code this->code().append("}"); @@ -205,22 +193,6 @@ GrGLShaderBuilder::finalize(GrGLuint programId, GrGLenum type, SkTDArraygpu(); - GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(), - programId, - type, - fCompilerStrings.begin(), - fCompilerStringLengths.begin(), - fCompilerStrings.count(), - gpu->stats()); - fFinalized = true; - - if (!shaderId) { - return false; - } - - *shaderIds->append() = shaderId; - - return true; } + diff --git a/src/gpu/gl/builders/GrGLShaderBuilder.h b/src/gpu/gl/builders/GrGLShaderBuilder.h index b5efbf4f89..2daea1515b 100644 --- a/src/gpu/gl/builders/GrGLShaderBuilder.h +++ b/src/gpu/gl/builders/GrGLShaderBuilder.h @@ -8,16 +8,12 @@ #ifndef GrGLShaderBuilder_DEFINED #define GrGLShaderBuilder_DEFINED -#include "SkTArray.h" -#include "gl/GrGLFragmentProcessor.h" -#include "gl/GrGLProgramDesc.h" -#include "gl/GrGLProgramDataManager.h" -#include "gl/GrGLTypes.h" +#include "GrAllocator.h" +#include "glsl/GrGLSLShaderVar.h" +#include "SkTDArray.h" #include -class GrGLCaps; -class GrGLContextInfo; class GrGLProgramBuilder; class GrGLSLTextureSampler; @@ -27,6 +23,7 @@ class GrGLSLTextureSampler; class GrGLShaderBuilder { public: GrGLShaderBuilder(GrGLProgramBuilder* program); + virtual ~GrGLShaderBuilder() {} void addInput(const GrGLSLShaderVar& input) { fInputs.push_back(input); } void addOutput(const GrGLSLShaderVar& output) { fOutputs.push_back(output); } @@ -65,10 +62,6 @@ public: const char* coordName, GrSLType coordType = kVec2f_GrSLType); - /** If texture swizzling is available using tex parameters then it is preferred over mangling - the generated shader code. This potentially allows greater reuse of cached shaders. */ - static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps); - /** * Called by GrGLProcessors to add code to one of the shaders. */ @@ -101,6 +94,11 @@ public: const char* body, SkString* outName); + /* + * Combines the various parts of the shader to create a single finalized shader string. + */ + void finalize(uint32_t visibility); + /* * Get parent builder for adding uniforms */ @@ -173,7 +171,8 @@ protected: SkString& functions() { return fShaderStrings[kFunctions]; } SkString& main() { return fShaderStrings[kMain]; } SkString& code() { return fShaderStrings[fCodeIndex]; } - bool finalize(GrGLuint programId, GrGLenum type, SkTDArray* shaderIds); + + virtual void onFinalize() = 0; enum { kVersionDecl, diff --git a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp index c1a7dee56a..f19d63fffa 100644 --- a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp +++ b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp @@ -87,16 +87,6 @@ void GrGLVertexBuilder::bindVertexAttributes(GrGLuint programID) { return; } -bool -GrGLVertexBuilder::compileAndAttachShaders(GrGLuint programId, SkTDArray* shaderIds) { - this->versionDecl() = fProgramBuilder->glslCaps()->versionDeclString(); - this->compileAndAppendLayoutQualifiers(); - fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kVertex_Visibility, &this->uniforms()); - this->appendDecls(fInputs, &this->inputs()); - this->appendDecls(fOutputs, &this->outputs()); - return this->finalize(programId, GR_GL_VERTEX_SHADER, shaderIds); -} - bool GrGLVertexBuilder::addAttribute(const GrShaderVar& var) { SkASSERT(GrShaderVar::kAttribute_TypeModifier == var.getTypeModifier()); for (int i = 0; i < fInputs.count(); ++i) { diff --git a/src/gpu/gl/builders/GrGLVertexShaderBuilder.h b/src/gpu/gl/builders/GrGLVertexShaderBuilder.h index dc38ff2a32..81aebd41b8 100644 --- a/src/gpu/gl/builders/GrGLVertexShaderBuilder.h +++ b/src/gpu/gl/builders/GrGLVertexShaderBuilder.h @@ -9,6 +9,7 @@ #define GrGLVertexShader_DEFINED #include "GrGLShaderBuilder.h" +#include "gl/GrGLTypes.h" #include "GrGeometryProcessor.h" class GrGLVarying; @@ -38,11 +39,12 @@ private: * private helpers for compilation by GrGLProgramBuilder */ void bindVertexAttributes(GrGLuint programID); - bool compileAndAttachShaders(GrGLuint programId, SkTDArray* shaderIds); // an internal call which checks for uniquness of a var before adding it to the list of inputs bool addAttribute(const GrShaderVar& var); + void onFinalize() override {} + const char* fRtAdjustName; friend class GrGLProgramBuilder; diff --git a/src/gpu/glsl/GrGLSLCaps.cpp b/src/gpu/glsl/GrGLSLCaps.cpp index fef5ab377c..54d041e3a0 100755 --- a/src/gpu/glsl/GrGLSLCaps.cpp +++ b/src/gpu/glsl/GrGLSLCaps.cpp @@ -21,6 +21,7 @@ GrGLSLCaps::GrGLSLCaps(const GrContextOptions& options) { fCanUseAnyFunctionInShader = true; fForceHighPrecisionNDSTransform = false; fVersionDeclString = nullptr; + fShaderDerivativeExtensionString = nullptr; fFBFetchColorName = nullptr; fFBFetchExtensionString = nullptr; fAdvBlendEqInteraction = kNotSupported_AdvBlendEqInteraction; diff --git a/src/gpu/glsl/GrGLSLCaps.h b/src/gpu/glsl/GrGLSLCaps.h index 4d6f580667..f93ef2766d 100755 --- a/src/gpu/glsl/GrGLSLCaps.h +++ b/src/gpu/glsl/GrGLSLCaps.h @@ -74,6 +74,14 @@ public: bool forceHighPrecisionNDSTransform() const { return fForceHighPrecisionNDSTransform; } + // Returns the string of an extension that must be enabled in the shader to support + // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling + // this function, the caller should check that shaderDerivativeSupport exists. + const char* shaderDerivativeExtensionString() const { + SkASSERT(this->shaderDerivativeSupport()); + return fShaderDerivativeExtensionString; + } + GrGLSLGeneration generation() const { return fGLSLGeneration; } /** @@ -94,6 +102,8 @@ private: const char* fVersionDeclString; + const char* fShaderDerivativeExtensionString; + const char* fFBFetchColorName; const char* fFBFetchExtensionString; diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp index a22ccd0be8..14dfdce6d5 100644 --- a/tests/GLProgramsTest.cpp +++ b/tests/GLProgramsTest.cpp @@ -30,6 +30,7 @@ #include "effects/GrPorterDuffXferProcessor.h" #include "effects/GrXfermodeFragmentProcessor.h" +#include "gl/GrGLFragmentProcessor.h" #include "gl/GrGLGpu.h" #include "gl/GrGLPathRendering.h" #include "gl/builders/GrGLProgramBuilder.h"