aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/glsl
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu/glsl')
-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
9 files changed, 205 insertions, 94 deletions
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;
};