Index: src/gpu/glsl/GrGLSLVarying.h |
diff --git a/src/gpu/glsl/GrGLSLVarying.h b/src/gpu/glsl/GrGLSLVarying.h |
index 116ba09b99bd9d2b797a328494bd49b903d5ca81..899d1e30e8bddb7d4e6d6b988fb08dc561b2781a 100644 |
--- a/src/gpu/glsl/GrGLSLVarying.h |
+++ b/src/gpu/glsl/GrGLSLVarying.h |
@@ -72,15 +72,17 @@ class GrGLSLVaryingHandler { |
public: |
explicit GrGLSLVaryingHandler(GrGLSLProgramBuilder* program) |
: fVertexInputs(kVaryingsPerBlock) |
- , fVertexOutputs(kVaryingsPerBlock) |
- , fGeomInputs(kVaryingsPerBlock) |
- , fGeomOutputs(kVaryingsPerBlock) |
- , fFragInputs(kVaryingsPerBlock) |
+ , fVaryingShaderVars(kVaryingsPerBlock) |
, fFragOutputs(kVaryingsPerBlock) |
- , fProgramBuilder(program) {} |
- |
- typedef GrTAllocator<GrGLSLShaderVar> VarArray; |
- typedef GrGLSLProgramDataManager::VaryingHandle VaryingHandle; |
+ , fProgramBuilder(program) |
+ , fNoPerspective(false) {} |
+ /* |
+ * 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 |
@@ -91,44 +93,81 @@ 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*/); |
+ } |
/* |
- * 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 |
+ * 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, |
egdaniel
2016/02/10 14:23:44
instead of adding a new call here, does it make mo
Chris Dalton
2016/02/10 15:29:30
I thought this over quite a bit myself and my pref
|
+ GrGLSLVarying* varying, |
+ GrSLPrecision precision = kDefault_GrSLPrecision) { |
+ this->internalAddVarying(name, varying, precision, true /*flat*/); |
+ } |
+ |
+ /* |
+ * 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); |
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 VaryingShaderVars { |
+ GrGLSLShaderVar fVertexOutput; |
+ GrGLSLShaderVar fGeomInput; |
+ GrGLSLShaderVar fGeomOutput; |
+ GrGLSLShaderVar fFragInput; |
+ bool fIsFlat; |
+ |
+ void addModifier(const char* modifier) { |
+ fVertexOutput.addModifier(modifier); |
+ fGeomInput.addModifier(modifier); |
+ fGeomOutput.addModifier(modifier); |
+ fFragInput.addModifier(modifier); |
+ } |
+ }; |
+ |
+ typedef GrTAllocator<GrGLSLShaderVar> ShaderVarList; |
+ typedef GrTAllocator<VaryingShaderVars> VaryingShaderVarsList; |
+ typedef GrGLSLProgramDataManager::VaryingHandle VaryingHandle; |
+ |
+ ShaderVarList fVertexInputs; |
+ VaryingShaderVarsList fVaryingShaderVars; |
+ ShaderVarList 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 addAttribute(const GrShaderVar& var); |
+ void internalAddVarying(const char* name, GrGLSLVarying*, GrSLPrecision, bool flat); |
+ void writePassThroughAttribute(const GrGeometryProcessor::Attribute*, const char* output, |
+ const GrGLSLVarying&); |
+ |
// helper function for get*Decls |
- void appendDecls(const VarArray& vars, SkString* out) const; |
+ void appendDecls(const ShaderVarList& vars, SkString* out) const; |
+ |
+ bool fNoPerspective; |
friend class GrGLSLProgramBuilder; |
}; |