From d7727ceb82e271f8b5580c51571c57b09c5e3ced Mon Sep 17 00:00:00 2001 From: "bsalomon@google.com" Date: Thu, 12 Jul 2012 16:40:03 +0000 Subject: [PATCH] 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 --- src/gpu/gl/GrGLSL.cpp | 16 ------- src/gpu/gl/GrGLSL.h | 12 ------ src/gpu/gl/GrGLShaderBuilder.cpp | 39 +++++++++++++++--- src/gpu/gl/GrGLShaderVar.h | 71 ++++++++++++++++++++++---------- 4 files changed, 82 insertions(+), 56 deletions(-) diff --git a/src/gpu/gl/GrGLSL.cpp b/src/gpu/gl/GrGLSL.cpp index 21dd940c66..759a17c39a 100644 --- a/src/gpu/gl/GrGLSL.cpp +++ b/src/gpu/gl/GrGLSL.cpp @@ -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, const char* nameIfDeclared, GrGLShaderVar* var) { diff --git a/src/gpu/gl/GrGLSL.h b/src/gpu/gl/GrGLSL.h index 587d6f27b4..7b92c23434 100644 --- a/src/gpu/gl/GrGLSL.h +++ b/src/gpu/gl/GrGLSL.h @@ -57,18 +57,6 @@ GrGLSLGeneration GrGetGLSLGeneration(GrGLBinding binding, const char* GrGetGLSLVersionDecl(GrGLBinding binding, 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 * variable from the fragment shader for the color. Otherwise, the shader must diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp index d24f2f89f6..3303bf2729 100644 --- a/src/gpu/gl/GrGLShaderBuilder.cpp +++ b/src/gpu/gl/GrGLShaderBuilder.cpp @@ -14,6 +14,9 @@ static const int kVarsPerBlock = 8; // except FS outputs where we expect 2 at most. 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. // Likely to become non-constant and non-static, perhaps even // varying by stage, if we use 1D textures for gradients! @@ -139,10 +142,9 @@ const GrGLShaderVar& GrGLShaderBuilder::addUniform(uint32_t visibility, var->setArrayCount(count); if ((kVertex_ShaderType | kFragment_ShaderType) == visibility) { + // the fragment and vertex precisions must match + var->setPrecision(kDefaultFragmentPrecision); 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; @@ -186,7 +188,6 @@ void GrGLShaderBuilder::addVarying(GrSLType type, } } - void GrGLShaderBuilder::addVarying(GrSLType type, const char* name, int stageNum, @@ -198,6 +199,30 @@ void GrGLShaderBuilder::addVarying(GrSLType type, } 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, const GrGLContextInfo& ctx, SkString* string) { @@ -229,7 +254,9 @@ void GrGLShaderBuilder::getShader(ShaderType type, SkString* shaderStr) const { break; case kFragment_ShaderType: *shaderStr = fHeader; - shaderStr->append(GrGetGLSLShaderPrecisionDecl(fContext.binding())); + append_default_precision_qualifier(kDefaultFragmentPrecision, + fContext.binding(), + shaderStr); append_decls(fFSUnis, fContext, shaderStr); append_decls(fFSInputs, fContext, shaderStr); // We shouldn't have declared outputs on 1.10 @@ -239,5 +266,5 @@ void GrGLShaderBuilder::getShader(ShaderType type, SkString* shaderStr) const { shaderStr->append(fFSCode); break; } - } + diff --git a/src/gpu/gl/GrGLShaderVar.h b/src/gpu/gl/GrGLShaderVar.h index 7be417dec3..2eccd3b1e8 100644 --- a/src/gpu/gl/GrGLShaderVar.h +++ b/src/gpu/gl/GrGLShaderVar.h @@ -33,6 +33,17 @@ public: 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 */ @@ -40,7 +51,7 @@ public: fType = kFloat_GrSLType; fTypeModifier = kNone_TypeModifier; fCount = kNonArray; - fEmitPrecision = false; + fPrecision = kDefault_Precision; fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS; } @@ -49,7 +60,7 @@ public: , fTypeModifier(var.fTypeModifier) , fName(var.fName) , fCount(var.fCount) - , fEmitPrecision(var.fEmitPrecision) + , fPrecision(var.fPrecision) , fUseUniformFloatArrays(var.fUseUniformFloatArrays) {} /** @@ -66,13 +77,13 @@ public: void set(GrSLType type, TypeModifier typeModifier, const SkString& name, - bool emitPrecision = false, + Precision precision = kDefault_Precision, bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { fType = type; fTypeModifier = typeModifier; fName = name; fCount = kNonArray; - fEmitPrecision = emitPrecision; + fPrecision = precision; fUseUniformFloatArrays = useUniformFloatArrays; } @@ -82,13 +93,13 @@ public: void set(GrSLType type, TypeModifier typeModifier, const char* name, - bool specifyPrecision = false, + Precision precision = kDefault_Precision, bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { fType = type; fTypeModifier = typeModifier; fName = name; fCount = kNonArray; - fEmitPrecision = specifyPrecision; + fPrecision = precision; fUseUniformFloatArrays = useUniformFloatArrays; } @@ -99,13 +110,13 @@ public: TypeModifier typeModifier, const SkString& name, int count, - bool specifyPrecision = false, + Precision precision = kDefault_Precision, bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { fType = type; fTypeModifier = typeModifier; fName = name; fCount = count; - fEmitPrecision = specifyPrecision; + fPrecision = precision; fUseUniformFloatArrays = useUniformFloatArrays; } @@ -116,13 +127,13 @@ public: TypeModifier typeModifier, const char* name, int count, - bool specifyPrecision = false, + Precision precision = kDefault_Precision, bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { fType = type; fTypeModifier = typeModifier; fName = name; fCount = count; - fEmitPrecision = specifyPrecision; + fPrecision = precision; fUseUniformFloatArrays = useUniformFloatArrays; } @@ -178,13 +189,14 @@ public: 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. @@ -195,10 +207,7 @@ public: gl.glslGeneration())); out->append(" "); } - if (this->emitsPrecision()) { - out->append(GrGetGLSLVarPrecisionDeclType(gl.binding())); - out->append(" "); - } + out->append(PrecisionString(fPrecision, gl.binding())); GrSLType effectiveType = this->getType(); if (this->isArray()) { if (this->isUnsizedArray()) { @@ -257,8 +266,7 @@ public: } private: - static const char* TypeModifierString(TypeModifier t, - GrGLSLGeneration gen) { + static const char* TypeModifierString(TypeModifier t, GrGLSLGeneration gen) { switch (t) { case kNone_TypeModifier: 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; SkString fName; int fCount; - bool fEmitPrecision; + Precision fPrecision; /// Work around driver bugs on some hardware that don't correctly /// support uniform float [] bool fUseUniformFloatArrays;