aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrPathProcessor.cpp7
-rw-r--r--src/gpu/batches/GrPLSPathRenderer.cpp4
-rw-r--r--src/gpu/gl/GrGLCaps.cpp18
-rw-r--r--src/gpu/gl/GrGLGpu.cpp68
-rw-r--r--src/gpu/gl/GrGLVaryingHandler.cpp10
-rw-r--r--src/gpu/gl/GrGLVaryingHandler.h7
-rwxr-xr-xsrc/gpu/glsl/GrGLSLCaps.cpp6
-rwxr-xr-xsrc/gpu/glsl/GrGLSLCaps.h12
-rw-r--r--src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp2
-rw-r--r--src/gpu/glsl/GrGLSLFragmentShaderBuilder.h16
-rw-r--r--src/gpu/glsl/GrGLSLGeometryProcessor.cpp3
-rw-r--r--src/gpu/glsl/GrGLSLShaderBuilder.h14
-rw-r--r--src/gpu/glsl/GrGLSLShaderVar.h36
-rw-r--r--src/gpu/glsl/GrGLSLVarying.cpp128
-rw-r--r--src/gpu/glsl/GrGLSLVarying.h82
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;
};