diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrPathProcessor.cpp | 7 | ||||
-rw-r--r-- | src/gpu/batches/GrPLSPathRenderer.cpp | 4 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.cpp | 18 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 68 | ||||
-rw-r--r-- | src/gpu/gl/GrGLVaryingHandler.cpp | 10 | ||||
-rw-r--r-- | src/gpu/gl/GrGLVaryingHandler.h | 7 | ||||
-rwxr-xr-x | src/gpu/glsl/GrGLSLCaps.cpp | 6 | ||||
-rwxr-xr-x | src/gpu/glsl/GrGLSLCaps.h | 12 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp | 2 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLFragmentShaderBuilder.h | 16 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLGeometryProcessor.cpp | 3 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLShaderBuilder.h | 14 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLShaderVar.h | 36 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLVarying.cpp | 128 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLVarying.h | 82 |
15 files changed, 286 insertions, 127 deletions
diff --git a/src/gpu/GrPathProcessor.cpp b/src/gpu/GrPathProcessor.cpp index cb33010f7e..1d70dea289 100644 --- a/src/gpu/GrPathProcessor.cpp +++ b/src/gpu/GrPathProcessor.cpp @@ -22,13 +22,18 @@ public: const GrGLSLCaps&, GrProcessorKeyBuilder* b) { b->add32(SkToInt(pathProc.overrides().readsColor()) | - SkToInt(pathProc.overrides().readsCoverage()) << 16); + (SkToInt(pathProc.overrides().readsCoverage()) << 1) | + (SkToInt(pathProc.viewMatrix().hasPerspective()) << 2)); } void emitCode(EmitArgs& args) override { GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; const GrPathProcessor& pathProc = args.fGP.cast<GrPathProcessor>(); + if (!pathProc.viewMatrix().hasPerspective()) { + args.fVaryingHandler->setNoPerspective(); + } + // emit transforms this->emitTransforms(args.fVaryingHandler, args.fTransformsIn, args.fTransformsOut); diff --git a/src/gpu/batches/GrPLSPathRenderer.cpp b/src/gpu/batches/GrPLSPathRenderer.cpp index b4f6ce4210..faadd6d49b 100644 --- a/src/gpu/batches/GrPLSPathRenderer.cpp +++ b/src/gpu/batches/GrPLSPathRenderer.cpp @@ -328,7 +328,7 @@ public: delta3.vsOut(), v3.vsOut(), v1.vsOut(), v1.vsOut(), v3.vsOut()); GrGLSLVertToFrag windings(kInt_GrSLType); - varyingHandler->addVarying("windings", &windings, kLow_GrSLPrecision); + varyingHandler->addFlatVarying("windings", &windings, kLow_GrSLPrecision); vsBuilder->codeAppendf("%s = %s;", windings.vsOut(), te.inWindings()->fName); @@ -513,7 +513,7 @@ public: ep1.vsOut()); GrGLSLVertToFrag windings(kInt_GrSLType); - varyingHandler->addVarying("windings", &windings, kLow_GrSLPrecision); + varyingHandler->addFlatVarying("windings", &windings, kLow_GrSLPrecision); vsBuilder->codeAppendf("%s = %s;", windings.vsOut(), qe.inWindings()->fName); diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index 79bb22efac..6dc5ee8c4f 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -596,6 +596,24 @@ void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo) { glslCaps->fBindlessTextureSupport = ctxInfo.hasExtension("GL_NV_bindless_texture"); + if (kGL_GrGLStandard == standard) { + glslCaps->fFlatInterpolationSupport = ctxInfo.glslGeneration() >= k130_GrGLSLGeneration; + } else { + glslCaps->fFlatInterpolationSupport = + ctxInfo.glslGeneration() >= k330_GrGLSLGeneration; // This is the value for GLSL ES 3.0. + } + + if (kGL_GrGLStandard == standard) { + glslCaps->fNoPerspectiveInterpolationSupport = + ctxInfo.glslGeneration() >= k130_GrGLSLGeneration; + } else { + if (ctxInfo.hasExtension("GL_NV_shader_noperspective_interpolation")) { + glslCaps->fNoPerspectiveInterpolationSupport = true; + glslCaps->fNoPerspectiveInterpolationExtensionString = + "GL_NV_shader_noperspective_interpolation"; + } + } + // Adreno GPUs have a tendency to drop tiles when there is a divide-by-zero in a shader glslCaps->fDropsTileOnZeroDivide = kQualcomm_GrGLVendor == ctxInfo.vendor(); diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index b9a5ee9837..be315dab1e 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -285,7 +285,8 @@ GrGLGpu::~GrGLGpu() { } void GrGLGpu::createPLSSetupProgram() { - const char* version = this->glCaps().glslCaps()->versionDeclString(); + const GrGLSLCaps* glslCaps = this->glCaps().glslCaps(); + const char* version = glslCaps->versionDeclString(); GrGLSLShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kAttribute_TypeModifier); GrGLSLShaderVar uTexCoordXform("u_texCoordXform", kVec4f_GrSLType, @@ -295,13 +296,19 @@ void GrGLGpu::createPLSSetupProgram() { GrGLSLShaderVar vTexCoord("v_texCoord", kVec2f_GrSLType, GrShaderVar::kVaryingOut_TypeModifier); SkString vshaderTxt(version); - aVertex.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); + if (glslCaps->noperspectiveInterpolationSupport()) { + if (const char* extension = glslCaps->noperspectiveInterpolationExtensionString()) { + vshaderTxt.appendf("#extension %s : require\n", extension); + } + vTexCoord.addModifier("noperspective"); + } + aVertex.appendDecl(glslCaps, &vshaderTxt); vshaderTxt.append(";"); - uTexCoordXform.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); + uTexCoordXform.appendDecl(glslCaps, &vshaderTxt); vshaderTxt.append(";"); - uPosXform.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); + uPosXform.appendDecl(glslCaps, &vshaderTxt); vshaderTxt.append(";"); - vTexCoord.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); + vTexCoord.appendDecl(glslCaps, &vshaderTxt); vshaderTxt.append(";"); vshaderTxt.append( @@ -313,17 +320,20 @@ void GrGLGpu::createPLSSetupProgram() { ); SkString fshaderTxt(version); + if (glslCaps->noperspectiveInterpolationSupport()) { + if (const char* extension = glslCaps->noperspectiveInterpolationExtensionString()) { + fshaderTxt.appendf("#extension %s : require\n", extension); + } + } fshaderTxt.append("#extension "); - fshaderTxt.append(this->glCaps().glslCaps()->fbFetchExtensionString()); + fshaderTxt.append(glslCaps->fbFetchExtensionString()); fshaderTxt.append(" : require\n"); fshaderTxt.append("#extension GL_EXT_shader_pixel_local_storage : require\n"); - GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, - *this->glCaps().glslCaps(), - &fshaderTxt); + GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, *glslCaps, &fshaderTxt); vTexCoord.setTypeModifier(GrShaderVar::kVaryingIn_TypeModifier); - vTexCoord.appendDecl(this->glCaps().glslCaps(), &fshaderTxt); + vTexCoord.appendDecl(glslCaps, &fshaderTxt); fshaderTxt.append(";"); - uTexture.appendDecl(this->glCaps().glslCaps(), &fshaderTxt); + uTexture.appendDecl(glslCaps, &fshaderTxt); fshaderTxt.append(";"); fshaderTxt.appendf( @@ -3300,7 +3310,8 @@ void GrGLGpu::createCopyPrograms() { for (size_t i = 0; i < SK_ARRAY_COUNT(fCopyPrograms); ++i) { fCopyPrograms[i].fProgram = 0; } - const char* version = this->glCaps().glslCaps()->versionDeclString(); + const GrGLSLCaps* glslCaps = this->glCaps().glslCaps(); + const char* version = glslCaps->versionDeclString(); static const GrSLType kSamplerTypes[3] = { kSampler2D_GrSLType, kSamplerExternal_GrSLType, kSampler2DRect_GrSLType }; SkASSERT(3 == SK_ARRAY_COUNT(fCopyPrograms)); @@ -3326,13 +3337,20 @@ void GrGLGpu::createCopyPrograms() { GrShaderVar::kOut_TypeModifier); SkString vshaderTxt(version); - aVertex.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); + if (glslCaps->noperspectiveInterpolationSupport()) { + if (const char* extension = glslCaps->noperspectiveInterpolationExtensionString()) { + vshaderTxt.appendf("#extension %s : require\n", extension); + } + vTexCoord.addModifier("noperspective"); + } + + aVertex.appendDecl(glslCaps, &vshaderTxt); vshaderTxt.append(";"); - uTexCoordXform.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); + uTexCoordXform.appendDecl(glslCaps, &vshaderTxt); vshaderTxt.append(";"); - uPosXform.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); + uPosXform.appendDecl(glslCaps, &vshaderTxt); vshaderTxt.append(";"); - vTexCoord.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); + vTexCoord.appendDecl(glslCaps, &vshaderTxt); vshaderTxt.append(";"); vshaderTxt.append( @@ -3345,21 +3363,25 @@ void GrGLGpu::createCopyPrograms() { ); SkString fshaderTxt(version); + if (glslCaps->noperspectiveInterpolationSupport()) { + if (const char* extension = glslCaps->noperspectiveInterpolationExtensionString()) { + fshaderTxt.appendf("#extension %s : require\n", extension); + } + } if (kSamplerTypes[i] == kSamplerExternal_GrSLType) { fshaderTxt.appendf("#extension %s : require\n", - this->glCaps().glslCaps()->externalTextureExtensionString()); + glslCaps->externalTextureExtensionString()); } - GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, - *this->glCaps().glslCaps(), + GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, *glslCaps, &fshaderTxt); vTexCoord.setTypeModifier(GrShaderVar::kVaryingIn_TypeModifier); - vTexCoord.appendDecl(this->glCaps().glslCaps(), &fshaderTxt); + vTexCoord.appendDecl(glslCaps, &fshaderTxt); fshaderTxt.append(";"); - uTexture.appendDecl(this->glCaps().glslCaps(), &fshaderTxt); + uTexture.appendDecl(glslCaps, &fshaderTxt); fshaderTxt.append(";"); const char* fsOutName; - if (this->glCaps().glslCaps()->mustDeclareFragmentShaderOutput()) { - oFragColor.appendDecl(this->glCaps().glslCaps(), &fshaderTxt); + if (glslCaps->mustDeclareFragmentShaderOutput()) { + oFragColor.appendDecl(glslCaps, &fshaderTxt); fshaderTxt.append(";"); fsOutName = oFragColor.c_str(); } else { diff --git a/src/gpu/gl/GrGLVaryingHandler.cpp b/src/gpu/gl/GrGLVaryingHandler.cpp index b27a9960ec..a2d4e9d1b9 100644 --- a/src/gpu/gl/GrGLVaryingHandler.cpp +++ b/src/gpu/gl/GrGLVaryingHandler.cpp @@ -24,8 +24,14 @@ GrGLSLVaryingHandler::VaryingHandle GrGLVaryingHandler::addPathProcessingVarying glPB->fArgs.fPrimitiveProcessor->numAttribs() == 0); #endif this->addVarying(name, v, fsPrecision); - VaryingInfo& varyingInfo = fPathProcVaryingInfos.push_back(); - varyingInfo.fVariable = fFragInputs.back(); + auto varyingInfo = fPathProcVaryingInfos.push_back(); varyingInfo.fLocation = fPathProcVaryingInfos.count() - 1; return VaryingHandle(varyingInfo.fLocation); } + +void GrGLVaryingHandler::onFinalize() { + SkASSERT(fPathProcVaryingInfos.empty() || fPathProcVaryingInfos.count() == fFragInputs.count()); + for (int i = 0; i < fPathProcVaryingInfos.count(); ++i) { + fPathProcVaryingInfos[i].fVariable = fFragInputs[i]; + } +} diff --git a/src/gpu/gl/GrGLVaryingHandler.h b/src/gpu/gl/GrGLVaryingHandler.h index fe8c3dca69..c4e5ba457e 100644 --- a/src/gpu/gl/GrGLVaryingHandler.h +++ b/src/gpu/gl/GrGLVaryingHandler.h @@ -24,12 +24,9 @@ public: GrSLPrecision fsPrecision = kDefault_GrSLPrecision); private: - void onFinalize() override {} + void onFinalize() override; - typedef GrGLProgramDataManager::VaryingInfo VaryingInfo; - typedef GrGLProgramDataManager::VaryingInfoArray VaryingInfoArray; - - VaryingInfoArray fPathProcVaryingInfos; + GrGLProgramDataManager::VaryingInfoArray fPathProcVaryingInfos; friend class GrGLProgramBuilder; diff --git a/src/gpu/glsl/GrGLSLCaps.cpp b/src/gpu/glsl/GrGLSLCaps.cpp index c82d8333df..ba99be57e2 100755 --- a/src/gpu/glsl/GrGLSLCaps.cpp +++ b/src/gpu/glsl/GrGLSLCaps.cpp @@ -23,11 +23,14 @@ GrGLSLCaps::GrGLSLCaps(const GrContextOptions& options) { fCanUseAnyFunctionInShader = true; fCanUseMinAndAbsTogether = true; fMustForceNegatedAtanParamToFloat = false; + fFlatInterpolationSupport = false; + fNoPerspectiveInterpolationSupport = false; fVersionDeclString = nullptr; fShaderDerivativeExtensionString = nullptr; fFragCoordConventionsExtensionString = nullptr; fSecondaryOutputExtensionString = nullptr; fExternalTextureExtensionString = nullptr; + fNoPerspectiveInterpolationExtensionString = nullptr; fFBFetchColorName = nullptr; fFBFetchExtensionString = nullptr; fAdvBlendEqInteraction = kNotSupported_AdvBlendEqInteraction; @@ -58,6 +61,9 @@ SkString GrGLSLCaps::dump() const { r.appendf("Can use min() and abs() together: %s\n", (fCanUseMinAndAbsTogether ? "YES" : "NO")); r.appendf("Must force negated atan param to float: %s\n", (fMustForceNegatedAtanParamToFloat ? "YES" : "NO")); + r.appendf("Flat interpolation support: %s\n", (fFlatInterpolationSupport ? "YES" : "NO")); + r.appendf("No perspective interpolation support: %s\n", (fNoPerspectiveInterpolationSupport ? + "YES" : "NO")); r.appendf("Advanced blend equation interaction: %s\n", kAdvBlendEqInteractionStr[fAdvBlendEqInteraction]); return r; diff --git a/src/gpu/glsl/GrGLSLCaps.h b/src/gpu/glsl/GrGLSLCaps.h index 060539645e..2f87f66850 100755 --- a/src/gpu/glsl/GrGLSLCaps.h +++ b/src/gpu/glsl/GrGLSLCaps.h @@ -54,6 +54,10 @@ public: bool dropsTileOnZeroDivide() const { return fDropsTileOnZeroDivide; } + bool flatInterpolationSupport() const { return fFlatInterpolationSupport; } + + bool noperspectiveInterpolationSupport() const { return fNoPerspectiveInterpolationSupport; } + AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; } bool mustEnableAdvBlendEqs() const { @@ -105,6 +109,11 @@ public: return fExternalTextureExtensionString; } + const char* noperspectiveInterpolationExtensionString() const { + SkASSERT(this->noperspectiveInterpolationSupport()); + return fNoPerspectiveInterpolationExtensionString; + } + /** * Given a texture's config, this determines what swizzle must be appended to accesses to the * texture in generated shader code. Swizzling may be implemented in texture parameters or a @@ -137,6 +146,8 @@ private: bool fBindlessTextureSupport : 1; bool fUsesPrecisionModifiers : 1; bool fCanUseAnyFunctionInShader : 1; + bool fFlatInterpolationSupport : 1; + bool fNoPerspectiveInterpolationSupport : 1; // Used for specific driver bug work arounds bool fCanUseMinAndAbsTogether : 1; @@ -148,6 +159,7 @@ private: const char* fFragCoordConventionsExtensionString; const char* fSecondaryOutputExtensionString; const char* fExternalTextureExtensionString; + const char* fNoPerspectiveInterpolationExtensionString; const char* fFBFetchColorName; const char* fFBFetchExtensionString; diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp index 7ec18a23e8..8651827841 100644 --- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp +++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp @@ -176,7 +176,7 @@ const char* GrGLSLFragmentShaderBuilder::dstColor() { const GrGLSLCaps* glslCaps = fProgramBuilder->glslCaps(); if (glslCaps->fbFetchSupport()) { - this->addFeature(1 << (GrGLSLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1), + this->addFeature(1 << kFramebufferFetch_GLSLPrivateFeature, glslCaps->fbFetchExtensionString()); // Some versions of this extension string require declaring custom color output on ES 3.0+ diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h index e998458158..a437a194ca 100644 --- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h +++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h @@ -32,9 +32,8 @@ public: * if code is added that uses one of these features without calling enableFeature() */ enum GLSLFeature { - kStandardDerivatives_GLSLFeature = 0, - kPixelLocalStorage_GLSLFeature = 1, - kLastGLSLFeature = kPixelLocalStorage_GLSLFeature + kStandardDerivatives_GLSLFeature = kLastGLSLPrivateFeature + 1, + kPixelLocalStorage_GLSLFeature }; /** @@ -168,17 +167,6 @@ private: void onFinalize() override; - /** - * Features that should only be enabled by GrGLSLFragmentShaderBuilder itself. - */ - enum GLSLPrivateFeature { - kFragCoordConventions_GLSLPrivateFeature = kLastGLSLFeature + 1, - kBlendEquationAdvanced_GLSLPrivateFeature, - kBlendFuncExtended_GLSLPrivateFeature, - kExternalTexture_GLSLPrivateFeature, - kLastGLSLPrivateFeature = kBlendFuncExtended_GLSLPrivateFeature - }; - // Interpretation of FragPosKey when generating code enum { kNoFragPosRead_FragPosKey = 0, // The fragment positition will not be needed. diff --git a/src/gpu/glsl/GrGLSLGeometryProcessor.cpp b/src/gpu/glsl/GrGLSLGeometryProcessor.cpp index b8951be551..f7dba820a0 100644 --- a/src/gpu/glsl/GrGLSLGeometryProcessor.cpp +++ b/src/gpu/glsl/GrGLSLGeometryProcessor.cpp @@ -19,6 +19,9 @@ void GrGLSLGeometryProcessor::emitCode(EmitArgs& args) { GrGPArgs gpArgs; this->onEmitCode(args, &gpArgs); vBuilder->transformToNormalizedDeviceSpace(gpArgs.fPositionVar); + if (kVec2f_GrSLType == gpArgs.fPositionVar.getType()) { + args.fVaryingHandler->setNoPerspective(); + } } void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb, diff --git a/src/gpu/glsl/GrGLSLShaderBuilder.h b/src/gpu/glsl/GrGLSLShaderBuilder.h index 5c3408e704..bc3b4ca717 100644 --- a/src/gpu/glsl/GrGLSLShaderBuilder.h +++ b/src/gpu/glsl/GrGLSLShaderBuilder.h @@ -142,6 +142,19 @@ protected: typedef GrTAllocator<GrGLSLShaderVar> VarArray; void appendDecls(const VarArray& vars, SkString* out) const; + /** + * Features that should only be enabled internally by the builders. + */ + enum GLSLPrivateFeature { + kFragCoordConventions_GLSLPrivateFeature, + kBlendEquationAdvanced_GLSLPrivateFeature, + kBlendFuncExtended_GLSLPrivateFeature, + kExternalTexture_GLSLPrivateFeature, + kFramebufferFetch_GLSLPrivateFeature, + kNoPerspectiveInterpolation_GLSLPrivateFeature, + kLastGLSLPrivateFeature = kNoPerspectiveInterpolation_GLSLPrivateFeature + }; + /* * A general function which enables an extension in a shader if the feature bit is not present */ @@ -215,6 +228,7 @@ protected: friend class GrGLSLProgramBuilder; friend class GrGLProgramBuilder; + friend class GrGLSLVaryingHandler; // to access noperspective interpolation feature. friend class GrGLPathProgramBuilder; // to access fInputs. friend class GrVkProgramBuilder; }; diff --git a/src/gpu/glsl/GrGLSLShaderVar.h b/src/gpu/glsl/GrGLSLShaderVar.h index e26a75c096..bdd36f3763 100644 --- a/src/gpu/glsl/GrGLSLShaderVar.h +++ b/src/gpu/glsl/GrGLSLShaderVar.h @@ -51,7 +51,9 @@ public: GrGLSLShaderVar(const GrGLSLShaderVar& var) : GrShaderVar(var.c_str(), var.getType(), var.getTypeModifier(), var.getArrayCount(), var.getPrecision()) - , fUseUniformFloatArrays(var.fUseUniformFloatArrays) { + , fUseUniformFloatArrays(var.fUseUniformFloatArrays) + , fLayoutQualifier(var.fLayoutQualifier) + , fExtraModifiers(var.fExtraModifiers) { SkASSERT(kVoid_GrSLType != var.getType()); } @@ -71,11 +73,15 @@ public: const SkString& name, GrSLPrecision precision = kDefault_GrSLPrecision, const char* layoutQualifier = nullptr, + const char* extraModifiers = nullptr, bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { SkASSERT(kVoid_GrSLType != type); SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsNumeric(type)); INHERITED::set(type, name, typeModifier, precision); fLayoutQualifier = layoutQualifier; + if (extraModifiers) { + fExtraModifiers.printf("%s ", extraModifiers); + } fUseUniformFloatArrays = useUniformFloatArrays; } @@ -87,11 +93,15 @@ public: const char* name, GrSLPrecision precision = kDefault_GrSLPrecision, const char* layoutQualifier = nullptr, + const char* extraModifiers = nullptr, bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { SkASSERT(kVoid_GrSLType != type); SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsNumeric(type)); INHERITED::set(type, name, typeModifier, precision); fLayoutQualifier = layoutQualifier; + if (extraModifiers) { + fExtraModifiers.printf("%s ", extraModifiers); + } fUseUniformFloatArrays = useUniformFloatArrays; } @@ -104,11 +114,15 @@ public: int count, GrSLPrecision precision = kDefault_GrSLPrecision, const char* layoutQualifier = nullptr, + const char* extraModifiers = nullptr, bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { SkASSERT(kVoid_GrSLType != type); SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsNumeric(type)); INHERITED::set(type, name, typeModifier, precision, count); fLayoutQualifier = layoutQualifier; + if (extraModifiers) { + fExtraModifiers.printf("%s ", extraModifiers); + } fUseUniformFloatArrays = useUniformFloatArrays; } @@ -121,11 +135,15 @@ public: int count, GrSLPrecision precision = kDefault_GrSLPrecision, const char* layoutQualifier = nullptr, + const char* extraModifiers = nullptr, bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { SkASSERT(kVoid_GrSLType != type); SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsNumeric(type)); INHERITED::set(type, name, typeModifier, precision, count); fLayoutQualifier = layoutQualifier; + if (extraModifiers) { + fExtraModifiers.printf("%s ", extraModifiers); + } fUseUniformFloatArrays = useUniformFloatArrays; } @@ -136,6 +154,12 @@ public: fLayoutQualifier = layoutQualifier; } + void addModifier(const char* modifier) { + if (modifier) { + fExtraModifiers.appendf("%s ", modifier); + } + } + /** * Write a declaration of this variable to out. */ @@ -144,11 +168,8 @@ public: if (!fLayoutQualifier.isEmpty()) { out->appendf("layout(%s) ", fLayoutQualifier.c_str()); } + out->append(fExtraModifiers); if (this->getTypeModifier() != kNone_TypeModifier) { - if (GrSLTypeIsIntType(fType) && (this->getTypeModifier() == kVaryingIn_TypeModifier || - this->getTypeModifier() == kVaryingOut_TypeModifier)) { - out->append("flat "); - } out->append(TypeModifierString(glslCaps, this->getTypeModifier())); out->append(" "); } @@ -234,9 +255,10 @@ private: /// Work around driver bugs on some hardware that don't correctly /// support uniform float [] - bool fUseUniformFloatArrays; + bool fUseUniformFloatArrays; - SkString fLayoutQualifier; + SkString fLayoutQualifier; + SkString fExtraModifiers; typedef GrShaderVar INHERITED; }; diff --git a/src/gpu/glsl/GrGLSLVarying.cpp b/src/gpu/glsl/GrGLSLVarying.cpp index ea52fbe7ab..99bfe7e18f 100644 --- a/src/gpu/glsl/GrGLSLVarying.cpp +++ b/src/gpu/glsl/GrGLSLVarying.cpp @@ -10,10 +10,24 @@ #include "glsl/GrGLSLProgramBuilder.h" void GrGLSLVaryingHandler::addPassThroughAttribute(const GrGeometryProcessor::Attribute* input, - const char* output) { + const char* output, GrSLPrecision precision) { GrSLType type = GrVertexAttribTypeToSLType(input->fType); GrGLSLVertToFrag v(type); - this->addVarying(input->fName, &v); + this->addVarying(input->fName, &v, precision); + this->writePassThroughAttribute(input, output, v); +} + +void GrGLSLVaryingHandler::addFlatPassThroughAttribute(const GrGeometryProcessor::Attribute* input, + const char* output, + GrSLPrecision precision) { + GrSLType type = GrVertexAttribTypeToSLType(input->fType); + GrGLSLVertToFrag v(type); + this->addFlatVarying(input->fName, &v, precision); + this->writePassThroughAttribute(input, output, v); +} + +void GrGLSLVaryingHandler::writePassThroughAttribute(const GrGeometryProcessor::Attribute* input, + const char* output, const GrGLSLVarying& v) { fProgramBuilder->fVS.codeAppendf("%s = %s;", v.vsOut(), input->fName); if (fProgramBuilder->primitiveProcessor().willUseGeoShader()) { @@ -23,62 +37,33 @@ void GrGLSLVaryingHandler::addPassThroughAttribute(const GrGeometryProcessor::At fProgramBuilder->fFS.codeAppendf("%s = %s;", output, v.fsIn()); } -void GrGLSLVaryingHandler::addVarying(const char* name, - GrGLSLVarying* varying, - GrSLPrecision precision) { +void GrGLSLVaryingHandler::internalAddVarying(const char* name, + GrGLSLVarying* varying, + GrSLPrecision precision, + bool flat) { + bool willUseGeoShader = fProgramBuilder->primitiveProcessor().willUseGeoShader(); + VaryingInfo& v = fVaryings.push_back(); + SkASSERT(varying); + v.fType = varying->fType; + v.fPrecision = precision; + v.fIsFlat = flat; + fProgramBuilder->nameVariable(&v.fVsOut, 'v', name); + v.fVisibility = kNone_GrShaderFlags; if (varying->vsVarying()) { - this->addVertexVarying(name, precision, varying); + varying->fVsOut = v.fVsOut.c_str(); + v.fVisibility |= kVertex_GrShaderFlag; } - if (fProgramBuilder->primitiveProcessor().willUseGeoShader()) { - this->addGeomVarying(name, precision, varying); + if (willUseGeoShader) { + fProgramBuilder->nameVariable(&v.fGsOut, 'g', name); + varying->fGsIn = v.fVsOut.c_str(); + varying->fGsOut = v.fGsOut.c_str(); + v.fVisibility |= kGeometry_GrShaderFlag; } if (varying->fsVarying()) { - this->addFragVarying(precision, varying); - } -} - -void GrGLSLVaryingHandler::addVertexVarying(const char* name, - GrSLPrecision precision, - GrGLSLVarying* v) { - fVertexOutputs.push_back(); - fVertexOutputs.back().setType(v->fType); - fVertexOutputs.back().setTypeModifier(GrGLSLShaderVar::kVaryingOut_TypeModifier); - fVertexOutputs.back().setPrecision(precision); - fProgramBuilder->nameVariable(fVertexOutputs.back().accessName(), 'v', name); - v->fVsOut = fVertexOutputs.back().getName().c_str(); -} -void GrGLSLVaryingHandler::addGeomVarying(const char* name, - GrSLPrecision precision, - GrGLSLVarying* v) { - // if we have a GS take each varying in as an array - // and output as non-array. - if (v->vsVarying()) { - fGeomInputs.push_back(); - fGeomInputs.back().setType(v->fType); - fGeomInputs.back().setTypeModifier(GrGLSLShaderVar::kVaryingIn_TypeModifier); - fGeomInputs.back().setPrecision(precision); - fGeomInputs.back().setUnsizedArray(); - *fGeomInputs.back().accessName() = v->fVsOut; - v->fGsIn = v->fVsOut; + varying->fFsIn = (willUseGeoShader ? v.fGsOut : v.fVsOut).c_str(); + v.fVisibility |= kFragment_GrShaderFlag; } - - if (v->fsVarying()) { - fGeomOutputs.push_back(); - fGeomOutputs.back().setType(v->fType); - fGeomOutputs.back().setTypeModifier(GrGLSLShaderVar::kVaryingOut_TypeModifier); - fGeomOutputs.back().setPrecision(precision); - fProgramBuilder->nameVariable(fGeomOutputs.back().accessName(), 'g', name); - v->fGsOut = fGeomOutputs.back().getName().c_str(); - } -} - -void GrGLSLVaryingHandler::addFragVarying(GrSLPrecision precision, GrGLSLVarying* v) { - v->fFsIn = v->fGsOut ? v->fGsOut : v->fVsOut; - fFragInputs.push_back().set(v->fType, - GrGLSLShaderVar::kVaryingIn_TypeModifier, - v->fFsIn, - precision); } void GrGLSLVaryingHandler::emitAttributes(const GrGeometryProcessor& gp) { @@ -105,7 +90,46 @@ void GrGLSLVaryingHandler::addAttribute(const GrShaderVar& var) { fVertexInputs.push_back(var); } +void GrGLSLVaryingHandler::setNoPerspective() { + const GrGLSLCaps& caps = *fProgramBuilder->glslCaps(); + if (!caps.noperspectiveInterpolationSupport()) { + return; + } + if (const char* extension = caps.noperspectiveInterpolationExtensionString()) { + int bit = 1 << GrGLSLFragmentShaderBuilder::kNoPerspectiveInterpolation_GLSLPrivateFeature; + fProgramBuilder->fVS.addFeature(bit, extension); + if (fProgramBuilder->primitiveProcessor().willUseGeoShader()) { + fProgramBuilder->fGS.addFeature(bit, extension); + } + fProgramBuilder->fFS.addFeature(bit, extension); + } + fDefaultInterpolationModifier = "noperspective"; +} + void GrGLSLVaryingHandler::finalize() { + for (int i = 0; i < fVaryings.count(); ++i) { + const VaryingInfo& v = this->fVaryings[i]; + const char* modifier = v.fIsFlat ? "flat" : fDefaultInterpolationModifier; + if (v.fVisibility & kVertex_GrShaderFlag) { + fVertexOutputs.push_back().set(v.fType, GrShaderVar::kVaryingOut_TypeModifier, v.fVsOut, + v.fPrecision, nullptr, modifier); + if (v.fVisibility & kGeometry_GrShaderFlag) { + fGeomInputs.push_back().set(v.fType, GrShaderVar::kVaryingIn_TypeModifier, v.fVsOut, + GrShaderVar::kUnsizedArray, v.fPrecision, nullptr, + modifier); + } + } + if (v.fVisibility & kFragment_GrShaderFlag) { + const char* fsIn = v.fVsOut.c_str(); + if (v.fVisibility & kGeometry_GrShaderFlag) { + fGeomOutputs.push_back().set(v.fType, GrGLSLShaderVar::kVaryingOut_TypeModifier, + v.fGsOut, v.fPrecision, nullptr, modifier); + fsIn = v.fGsOut.c_str(); + } + fFragInputs.push_back().set(v.fType, GrShaderVar::kVaryingIn_TypeModifier, fsIn, + v.fPrecision, nullptr, modifier); + } + } this->onFinalize(); } diff --git a/src/gpu/glsl/GrGLSLVarying.h b/src/gpu/glsl/GrGLSLVarying.h index 22431978c8..5867361ce4 100644 --- a/src/gpu/glsl/GrGLSLVarying.h +++ b/src/gpu/glsl/GrGLSLVarying.h @@ -71,18 +71,25 @@ static const int kVaryingsPerBlock = 8; class GrGLSLVaryingHandler { public: explicit GrGLSLVaryingHandler(GrGLSLProgramBuilder* program) - : fVertexInputs(kVaryingsPerBlock) + : fVaryings(kVaryingsPerBlock) + , fVertexInputs(kVaryingsPerBlock) , fVertexOutputs(kVaryingsPerBlock) , fGeomInputs(kVaryingsPerBlock) , fGeomOutputs(kVaryingsPerBlock) , fFragInputs(kVaryingsPerBlock) , fFragOutputs(kVaryingsPerBlock) - , fProgramBuilder(program) {} + , fProgramBuilder(program) + , fDefaultInterpolationModifier(nullptr) {} virtual ~GrGLSLVaryingHandler() {} - typedef GrTAllocator<GrGLSLShaderVar> VarArray; - typedef GrGLSLProgramDataManager::VaryingHandle VaryingHandle; + /* + * Notifies the varying handler that this shader will never emit geometry in perspective and + * therefore does not require perspective-correct interpolation. When supported, this allows + * varyings to use the "noperspective" keyword, which means the GPU can use cheaper math for + * interpolation. + */ + void setNoPerspective(); /* * addVarying allows fine grained control for setting up varyings between stages. Calling this @@ -93,18 +100,36 @@ public: * TODO convert most uses of addVarying to addPassThroughAttribute */ void addVarying(const char* name, - GrGLSLVarying*, - GrSLPrecision precision = kDefault_GrSLPrecision); + GrGLSLVarying* varying, + GrSLPrecision precision = kDefault_GrSLPrecision) { + SkASSERT(GrSLTypeIsFloatType(varying->type())); // Integers must use addFlatVarying. + this->internalAddVarying(name, varying, precision, false /*flat*/); + } + + /* + * addFlatVarying sets up a varying whose value is constant across every fragment. The graphics + * pipeline will pull its value from the final vertex of the draw primitive (provoking vertex). + * Flat interpolation is not always supported and the user must check the caps before using. + * TODO: Some platforms can change the provoking vertex. Should we be resetting this knob? + */ + void addFlatVarying(const char* name, + GrGLSLVarying* varying, + GrSLPrecision precision = kDefault_GrSLPrecision) { + this->internalAddVarying(name, varying, precision, true /*flat*/); + } /* - * This call can be used by GP to pass an attribute through all shaders directly to 'output' in - * the fragment shader. Though this call effects both the vertex shader and fragment shader, - * it expects 'output' to be defined in the fragment shader before this call is made. If there + * The GP can use these calls to pass an attribute through all shaders directly to 'output' in + * the fragment shader. Though these calls affect both the vertex shader and fragment shader, + * they expect 'output' to be defined in the fragment shader before the call is made. If there * is a geometry shader, we will simply take the value of the varying from the first vertex and * that will be set as the output varying for all emitted vertices. - * TODO it might be nicer behavior to have a flag to declare output inside this call + * TODO it might be nicer behavior to have a flag to declare output inside these calls */ - void addPassThroughAttribute(const GrGeometryProcessor::Attribute*, const char* output); + void addPassThroughAttribute(const GrGeometryProcessor::Attribute*, const char* output, + GrSLPrecision = kDefault_GrSLPrecision); + void addFlatPassThroughAttribute(const GrGeometryProcessor::Attribute*, const char* output, + GrSLPrecision = kDefault_GrSLPrecision); void emitAttributes(const GrGeometryProcessor& gp); @@ -115,21 +140,36 @@ public: void getVertexDecls(SkString* inputDecls, SkString* outputDecls) const; void getGeomDecls(SkString* inputDecls, SkString* outputDecls) const; void getFragDecls(SkString* inputDecls, SkString* outputDecls) const; + protected: - VarArray fVertexInputs; - VarArray fVertexOutputs; - VarArray fGeomInputs; - VarArray fGeomOutputs; - VarArray fFragInputs; - VarArray fFragOutputs; + struct VaryingInfo { + GrSLType fType; + GrSLPrecision fPrecision; + bool fIsFlat; + SkString fVsOut; + SkString fGsOut; + GrShaderFlags fVisibility; + }; + + typedef GrTAllocator<VaryingInfo> VaryingList; + typedef GrTAllocator<GrGLSLShaderVar> VarArray; + typedef GrGLSLProgramDataManager::VaryingHandle VaryingHandle; + + VaryingList fVaryings; + VarArray fVertexInputs; + VarArray fVertexOutputs; + VarArray fGeomInputs; + VarArray fGeomOutputs; + VarArray fFragInputs; + VarArray fFragOutputs; // This is not owned by the class GrGLSLProgramBuilder* fProgramBuilder; private: - void addVertexVarying(const char* name, GrSLPrecision precision, GrGLSLVarying* v); - void addGeomVarying(const char* name, GrSLPrecision precision, GrGLSLVarying* v); - void addFragVarying(GrSLPrecision precision, GrGLSLVarying* v); + void internalAddVarying(const char* name, GrGLSLVarying*, GrSLPrecision, bool flat); + void writePassThroughAttribute(const GrGeometryProcessor::Attribute*, const char* output, + const GrGLSLVarying&); void addAttribute(const GrShaderVar& var); @@ -138,6 +178,8 @@ private: // helper function for get*Decls void appendDecls(const VarArray& vars, SkString* out) const; + const char* fDefaultInterpolationModifier; + friend class GrGLSLProgramBuilder; }; |