Refactor how precision is handled with GrGLShaderVar

Review URL: http://codereview.appspot.com/6392049/


git-svn-id: http://skia.googlecode.com/svn/trunk@4575 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bsalomon@google.com 2012-07-12 16:40:03 +00:00
parent ba68cdb415
commit d7727ceb82
4 changed files with 82 additions and 56 deletions

View File

@ -55,22 +55,6 @@ const char* GrGetGLSLVersionDecl(GrGLBinding binding,
} }
} }
const char* GrGetGLSLVarPrecisionDeclType(GrGLBinding binding) {
if (kES2_GrGLBinding == binding) {
return "mediump";
} else {
return " ";
}
}
const char* GrGetGLSLShaderPrecisionDecl(GrGLBinding binding) {
if (kES2_GrGLBinding == binding) {
return "precision mediump float;\n";
} else {
return "";
}
}
bool GrGLSLSetupFSColorOuput(GrGLSLGeneration gen, bool GrGLSLSetupFSColorOuput(GrGLSLGeneration gen,
const char* nameIfDeclared, const char* nameIfDeclared,
GrGLShaderVar* var) { GrGLShaderVar* var) {

View File

@ -57,18 +57,6 @@ GrGLSLGeneration GrGetGLSLGeneration(GrGLBinding binding,
const char* GrGetGLSLVersionDecl(GrGLBinding binding, const char* GrGetGLSLVersionDecl(GrGLBinding binding,
GrGLSLGeneration v); GrGLSLGeneration v);
/**
* Returns a string to include in a variable decleration to set the fp precision
* or an emptry string if precision is not required.
*/
const char* GrGetGLSLVarPrecisionDeclType(GrGLBinding binding);
/**
* Returns a string to set the default fp precision for an entire shader, or
* an emptry string if precision is not required.
*/
const char* GrGetGLSLShaderPrecisionDecl(GrGLBinding binding);
/** /**
* Depending on the GLSL version being emitted there may be an assumed output * Depending on the GLSL version being emitted there may be an assumed output
* variable from the fragment shader for the color. Otherwise, the shader must * variable from the fragment shader for the color. Otherwise, the shader must

View File

@ -14,6 +14,9 @@ static const int kVarsPerBlock = 8;
// except FS outputs where we expect 2 at most. // except FS outputs where we expect 2 at most.
static const int kMaxFSOutputs = 2; static const int kMaxFSOutputs = 2;
// ES2 FS only guarantees mediump and lowp support
static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
// Architectural assumption: always 2-d input coords. // Architectural assumption: always 2-d input coords.
// Likely to become non-constant and non-static, perhaps even // Likely to become non-constant and non-static, perhaps even
// varying by stage, if we use 1D textures for gradients! // varying by stage, if we use 1D textures for gradients!
@ -139,10 +142,9 @@ const GrGLShaderVar& GrGLShaderBuilder::addUniform(uint32_t visibility,
var->setArrayCount(count); var->setArrayCount(count);
if ((kVertex_ShaderType | kFragment_ShaderType) == visibility) { if ((kVertex_ShaderType | kFragment_ShaderType) == visibility) {
// the fragment and vertex precisions must match
var->setPrecision(kDefaultFragmentPrecision);
fFSUnis.push_back(*var); fFSUnis.push_back(*var);
// If it's shared between VS and FS, VS must override
// default highp and specify mediump.
var->setEmitPrecision(true);
} }
return *var; return *var;
@ -186,7 +188,6 @@ void GrGLShaderBuilder::addVarying(GrSLType type,
} }
} }
void GrGLShaderBuilder::addVarying(GrSLType type, void GrGLShaderBuilder::addVarying(GrSLType type,
const char* name, const char* name,
int stageNum, int stageNum,
@ -198,6 +199,30 @@ void GrGLShaderBuilder::addVarying(GrSLType type,
} }
namespace { namespace {
inline void append_default_precision_qualifier(GrGLShaderVar::Precision p,
GrGLBinding binding,
SkString* str) {
// Desktop GLSL has added precision qualifiers but they don't do anything.
if (kES2_GrGLBinding == binding) {
switch (p) {
case GrGLShaderVar::kHigh_Precision:
str->append("precision highp float;\n");
break;
case GrGLShaderVar::kMedium_Precision:
str->append("precision mediump float;\n");
break;
case GrGLShaderVar::kLow_Precision:
str->append("precision lowp float;\n");
break;
case GrGLShaderVar::kDefault_Precision:
GrCrash("Default precision now allowed.");
default:
GrCrash("Unknown precision value.");
}
}
}
void append_decls(const GrGLShaderBuilder::VarArray& vars, void append_decls(const GrGLShaderBuilder::VarArray& vars,
const GrGLContextInfo& ctx, const GrGLContextInfo& ctx,
SkString* string) { SkString* string) {
@ -229,7 +254,9 @@ void GrGLShaderBuilder::getShader(ShaderType type, SkString* shaderStr) const {
break; break;
case kFragment_ShaderType: case kFragment_ShaderType:
*shaderStr = fHeader; *shaderStr = fHeader;
shaderStr->append(GrGetGLSLShaderPrecisionDecl(fContext.binding())); append_default_precision_qualifier(kDefaultFragmentPrecision,
fContext.binding(),
shaderStr);
append_decls(fFSUnis, fContext, shaderStr); append_decls(fFSUnis, fContext, shaderStr);
append_decls(fFSInputs, fContext, shaderStr); append_decls(fFSInputs, fContext, shaderStr);
// We shouldn't have declared outputs on 1.10 // We shouldn't have declared outputs on 1.10
@ -239,5 +266,5 @@ void GrGLShaderBuilder::getShader(ShaderType type, SkString* shaderStr) const {
shaderStr->append(fFSCode); shaderStr->append(fFSCode);
break; break;
} }
} }

View File

@ -33,6 +33,17 @@ public:
kAttribute_TypeModifier kAttribute_TypeModifier
}; };
enum Precision {
kLow_Precision, // lowp
kMedium_Precision, // mediump
kHigh_Precision, // highp
kDefault_Precision, // Default for the current context. We make
// fragment shaders default to mediump on ES2
// because highp support is not guaranteed (and
// we haven't been motivated to test for it).
// Otherwise, highp.
};
/** /**
* Defaults to a float with no precision specifier * Defaults to a float with no precision specifier
*/ */
@ -40,7 +51,7 @@ public:
fType = kFloat_GrSLType; fType = kFloat_GrSLType;
fTypeModifier = kNone_TypeModifier; fTypeModifier = kNone_TypeModifier;
fCount = kNonArray; fCount = kNonArray;
fEmitPrecision = false; fPrecision = kDefault_Precision;
fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS; fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS;
} }
@ -49,7 +60,7 @@ public:
, fTypeModifier(var.fTypeModifier) , fTypeModifier(var.fTypeModifier)
, fName(var.fName) , fName(var.fName)
, fCount(var.fCount) , fCount(var.fCount)
, fEmitPrecision(var.fEmitPrecision) , fPrecision(var.fPrecision)
, fUseUniformFloatArrays(var.fUseUniformFloatArrays) {} , fUseUniformFloatArrays(var.fUseUniformFloatArrays) {}
/** /**
@ -66,13 +77,13 @@ public:
void set(GrSLType type, void set(GrSLType type,
TypeModifier typeModifier, TypeModifier typeModifier,
const SkString& name, const SkString& name,
bool emitPrecision = false, Precision precision = kDefault_Precision,
bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
fType = type; fType = type;
fTypeModifier = typeModifier; fTypeModifier = typeModifier;
fName = name; fName = name;
fCount = kNonArray; fCount = kNonArray;
fEmitPrecision = emitPrecision; fPrecision = precision;
fUseUniformFloatArrays = useUniformFloatArrays; fUseUniformFloatArrays = useUniformFloatArrays;
} }
@ -82,13 +93,13 @@ public:
void set(GrSLType type, void set(GrSLType type,
TypeModifier typeModifier, TypeModifier typeModifier,
const char* name, const char* name,
bool specifyPrecision = false, Precision precision = kDefault_Precision,
bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
fType = type; fType = type;
fTypeModifier = typeModifier; fTypeModifier = typeModifier;
fName = name; fName = name;
fCount = kNonArray; fCount = kNonArray;
fEmitPrecision = specifyPrecision; fPrecision = precision;
fUseUniformFloatArrays = useUniformFloatArrays; fUseUniformFloatArrays = useUniformFloatArrays;
} }
@ -99,13 +110,13 @@ public:
TypeModifier typeModifier, TypeModifier typeModifier,
const SkString& name, const SkString& name,
int count, int count,
bool specifyPrecision = false, Precision precision = kDefault_Precision,
bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
fType = type; fType = type;
fTypeModifier = typeModifier; fTypeModifier = typeModifier;
fName = name; fName = name;
fCount = count; fCount = count;
fEmitPrecision = specifyPrecision; fPrecision = precision;
fUseUniformFloatArrays = useUniformFloatArrays; fUseUniformFloatArrays = useUniformFloatArrays;
} }
@ -116,13 +127,13 @@ public:
TypeModifier typeModifier, TypeModifier typeModifier,
const char* name, const char* name,
int count, int count,
bool specifyPrecision = false, Precision precision = kDefault_Precision,
bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) {
fType = type; fType = type;
fTypeModifier = typeModifier; fTypeModifier = typeModifier;
fName = name; fName = name;
fCount = count; fCount = count;
fEmitPrecision = specifyPrecision; fPrecision = precision;
fUseUniformFloatArrays = useUniformFloatArrays; fUseUniformFloatArrays = useUniformFloatArrays;
} }
@ -178,13 +189,14 @@ public:
void setTypeModifier(TypeModifier type) { fTypeModifier = type; } void setTypeModifier(TypeModifier type) { fTypeModifier = type; }
/** /**
* Must the variable declaration emit a precision specifier * Get the precision of the var
*/ */
bool emitsPrecision() const { return fEmitPrecision; } Precision getPrecision() const { return fPrecision; }
/** /**
* Specify whether the declaration should specify precision * Set the precision of the var
*/ */
void setEmitPrecision(bool p) { fEmitPrecision = p; } void setPrecision(Precision p) { fPrecision = p; }
/** /**
* Write a declaration of this variable to out. * Write a declaration of this variable to out.
@ -195,10 +207,7 @@ public:
gl.glslGeneration())); gl.glslGeneration()));
out->append(" "); out->append(" ");
} }
if (this->emitsPrecision()) { out->append(PrecisionString(fPrecision, gl.binding()));
out->append(GrGetGLSLVarPrecisionDeclType(gl.binding()));
out->append(" ");
}
GrSLType effectiveType = this->getType(); GrSLType effectiveType = this->getType();
if (this->isArray()) { if (this->isArray()) {
if (this->isUnsizedArray()) { if (this->isUnsizedArray()) {
@ -257,8 +266,7 @@ public:
} }
private: private:
static const char* TypeModifierString(TypeModifier t, static const char* TypeModifierString(TypeModifier t, GrGLSLGeneration gen) {
GrGLSLGeneration gen) {
switch (t) { switch (t) {
case kNone_TypeModifier: case kNone_TypeModifier:
return ""; return "";
@ -276,11 +284,30 @@ private:
} }
} }
GrSLType fType; static const char* PrecisionString(Precision p, GrGLBinding binding) {
// Desktop GLSL has added precision qualifiers but they don't do anything.
if (kES2_GrGLBinding == binding) {
switch (p) {
case kLow_Precision:
return "lowp ";
case kMedium_Precision:
return "mediump ";
case kHigh_Precision:
return "highp ";
case kDefault_Precision:
return "";
default:
GrCrash("Unexpected precision type.");
}
}
return "";
}
GrSLType fType;
TypeModifier fTypeModifier; TypeModifier fTypeModifier;
SkString fName; SkString fName;
int fCount; int fCount;
bool fEmitPrecision; Precision fPrecision;
/// Work around driver bugs on some hardware that don't correctly /// Work around driver bugs on some hardware that don't correctly
/// support uniform float [] /// support uniform float []
bool fUseUniformFloatArrays; bool fUseUniformFloatArrays;