From da668988e92a63cc504d6bfc79d94df393cb350c Mon Sep 17 00:00:00 2001 From: "tomhudson@google.com" Date: Wed, 7 Dec 2011 15:06:29 +0000 Subject: [PATCH] Add method to GrGLShadeVar to create GLSL string accessing an element of an array. codereview.appspot.com/5437149/ git-svn-id: http://skia.googlecode.com/svn/trunk@2818 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/gpu/GrGLProgram.cpp | 118 ++++++++++++++++++++++++++++++------------------ src/gpu/GrGLShaderVar.h | 46 +++++++++++++++---- 2 files changed, 111 insertions(+), 53 deletions(-) diff --git a/src/gpu/GrGLProgram.cpp b/src/gpu/GrGLProgram.cpp index f2a21b2..9395c0e 100644 --- a/src/gpu/GrGLProgram.cpp +++ b/src/gpu/GrGLProgram.cpp @@ -1324,7 +1324,7 @@ bool isRadialMapping(GrGLProgram::StageDesc::CoordMapping mapping) { GrGLProgram::StageDesc::kRadial2GradientDegenerate_CoordMapping == mapping); } -const char* genRadialVS(int stageNum, +GrGLShaderVar* genRadialVS(int stageNum, ShaderCodeSegments* segments, GrGLProgram::StageUniLocations* locations, const char** radial2VaryingVSName, @@ -1351,20 +1351,25 @@ const char* genRadialVS(int stageNum, radial2VaryingVSName, radial2VaryingFSName); + GrStringBuilder radial2p2; + GrStringBuilder radial2p3; + radial2FSParams->appendArrayAccess(2, &radial2p2); + radial2FSParams->appendArrayAccess(3, &radial2p3); + // r2Var = 2 * (r2Parm[2] * varCoord.x - r2Param[3]) const char* r2ParamName = radial2FSParams->getName().c_str(); - segments->fVSCode.appendf("\t%s = 2.0 *(%s[2] * %s.x - %s[3]);\n", - *radial2VaryingVSName, r2ParamName, - varyingVSName, r2ParamName); + segments->fVSCode.appendf("\t%s = 2.0 *(%s * %s.x - %s);\n", + *radial2VaryingVSName, radial2p2.c_str(), + varyingVSName, radial2p3.c_str()); } - return radial2FSParams->getName().c_str(); + return radial2FSParams; } bool genRadial2GradientCoordMapping(int stageNum, ShaderCodeSegments* segments, const char* radial2VaryingFSName, - const char* radial2ParamsName, + GrGLShaderVar* radial2Params, GrStringBuilder& sampleCoords, GrStringBuilder& fsCoordName, int varyingDims, @@ -1377,6 +1382,19 @@ bool genRadial2GradientCoordMapping(int stageNum, ac4Name.appendS32(stageNum); rootName.appendS32(stageNum); + GrStringBuilder radial2p0; + GrStringBuilder radial2p1; + GrStringBuilder radial2p2; + GrStringBuilder radial2p3; + GrStringBuilder radial2p4; + GrStringBuilder radial2p5; + radial2Params->appendArrayAccess(0, &radial2p0); + radial2Params->appendArrayAccess(1, &radial2p1); + radial2Params->appendArrayAccess(2, &radial2p2); + radial2Params->appendArrayAccess(3, &radial2p3); + radial2Params->appendArrayAccess(4, &radial2p4); + radial2Params->appendArrayAccess(5, &radial2p5); + // if we were able to interpolate the linear component bVar is the varying // otherwise compute it GrStringBuilder bVar; @@ -1387,19 +1405,19 @@ bool genRadial2GradientCoordMapping(int stageNum, GrAssert(3 == varyingDims); bVar = "b"; bVar.appendS32(stageNum); - segments->fFSCode.appendf("\tfloat %s = 2.0 * (%s[2] * %s.x - %s[3]);\n", - bVar.c_str(), radial2ParamsName, - fsCoordName.c_str(), radial2ParamsName); + segments->fFSCode.appendf("\tfloat %s = 2.0 * (%s * %s.x - %s);\n", + bVar.c_str(), radial2p2.c_str(), + fsCoordName.c_str(), radial2p3.c_str()); } // c = (x^2)+(y^2) - params[4] - segments->fFSCode.appendf("\tfloat %s = dot(%s, %s) - %s[4];\n", + segments->fFSCode.appendf("\tfloat %s = dot(%s, %s) - %s;\n", cName.c_str(), fsCoordName.c_str(), fsCoordName.c_str(), - radial2ParamsName); + radial2p4.c_str()); // ac4 = 4.0 * params[0] * c - segments->fFSCode.appendf("\tfloat %s = %s[0] * 4.0 * %s;\n", - ac4Name.c_str(), radial2ParamsName, + segments->fFSCode.appendf("\tfloat %s = %s * 4.0 * %s;\n", + ac4Name.c_str(), radial2p0.c_str(), cName.c_str()); // root = sqrt(b^2-4ac) @@ -1410,16 +1428,16 @@ bool genRadial2GradientCoordMapping(int stageNum, // x coord is: (-b + params[5] * sqrt(b^2-4ac)) * params[1] // y coord is 0.5 (texture is effectively 1D) - sampleCoords.printf("vec2((-%s + %s[5] * %s) * %s[1], 0.5)", - bVar.c_str(), radial2ParamsName, - rootName.c_str(), radial2ParamsName); + sampleCoords.printf("vec2((-%s + %s * %s) * %s, 0.5)", + bVar.c_str(), radial2p5.c_str(), + rootName.c_str(), radial2p1.c_str()); return true; } bool genRadial2GradientDegenerateCoordMapping(int stageNum, ShaderCodeSegments* segments, const char* radial2VaryingFSName, - const char* radial2ParamsName, + GrGLShaderVar* radial2Params, GrStringBuilder& sampleCoords, GrStringBuilder& fsCoordName, int varyingDims, @@ -1428,6 +1446,13 @@ bool genRadial2GradientDegenerateCoordMapping(int stageNum, cName.appendS32(stageNum); + GrStringBuilder radial2p2; + GrStringBuilder radial2p3; + GrStringBuilder radial2p4; + radial2Params->appendArrayAccess(2, &radial2p2); + radial2Params->appendArrayAccess(3, &radial2p3); + radial2Params->appendArrayAccess(4, &radial2p4); + // if we were able to interpolate the linear component bVar is the varying // otherwise compute it GrStringBuilder bVar; @@ -1438,16 +1463,16 @@ bool genRadial2GradientDegenerateCoordMapping(int stageNum, GrAssert(3 == varyingDims); bVar = "b"; bVar.appendS32(stageNum); - segments->fFSCode.appendf("\tfloat %s = 2.0 * (%s[2] * %s.x - %s[3]);\n", - bVar.c_str(), radial2ParamsName, - fsCoordName.c_str(), radial2ParamsName); + segments->fFSCode.appendf("\tfloat %s = 2.0 * (%s * %s.x - %s);\n", + bVar.c_str(), radial2p2.c_str(), + fsCoordName.c_str(), radial2p3.c_str()); } // c = (x^2)+(y^2) - params[4] - segments->fFSCode.appendf("\tfloat %s = dot(%s, %s) - %s[4];\n", + segments->fFSCode.appendf("\tfloat %s = dot(%s, %s) - %s;\n", cName.c_str(), fsCoordName.c_str(), fsCoordName.c_str(), - radial2ParamsName); + radial2p4.c_str()); // x coord is: -c/b // y coord is 0.5 (texture is effectively 1D) @@ -1492,19 +1517,19 @@ void genConvolutionVS(int stageNum, const StageDesc& desc, ShaderCodeSegments* segments, GrGLProgram::StageUniLocations* locations, - const char** kernelName, + GrGLShaderVar** kernel, const char** imageIncrementName, const char* varyingVSName) { - GrGLShaderVar* kernel = &segments->fFSUnis.push_back(); - kernel->setType(GrGLShaderVar::kFloat_Type); - kernel->setArrayCount(desc.fKernelWidth); + //GrGLShaderVar* kernel = &segments->fFSUnis.push_back(); + *kernel = &segments->fFSUnis.push_back(); + (*kernel)->setType(GrGLShaderVar::kFloat_Type); + (*kernel)->setArrayCount(desc.fKernelWidth); GrGLShaderVar* imgInc = &segments->fFSUnis.push_back(); imgInc->setType(GrGLShaderVar::kVec2f_Type); convolve_param_names(stageNum, - kernel->accessName(), + (*kernel)->accessName(), imgInc->accessName()); - *kernelName = kernel->getName().c_str(); *imageIncrementName = imgInc->getName().c_str(); // need image increment in both VS and FS @@ -1522,7 +1547,7 @@ void genConvolutionFS(int stageNum, const StageDesc& desc, ShaderCodeSegments* segments, const char* samplerName, - const char* kernelName, + GrGLShaderVar* kernel, const char* swizzle, const char* imageIncrementName, const char* fsOutColor, @@ -1534,6 +1559,9 @@ void genConvolutionFS(int stageNum, GrStringBuilder coordVar("coord"); coordVar.appendS32(stageNum); + GrStringBuilder kernelIndex; + kernel->appendArrayAccess("i", &kernelIndex); + segments->fFSCode.appendf("\tvec4 %s = vec4(0, 0, 0, 0);\n", sumVar.c_str()); segments->fFSCode.appendf("\tvec2 %s = %s;\n", @@ -1541,10 +1569,10 @@ void genConvolutionFS(int stageNum, sampleCoords.c_str()); segments->fFSCode.appendf("\tfor (int i = 0; i < %d; i++) {\n", desc.fKernelWidth); - segments->fFSCode.appendf("\t\t%s += %s(%s, %s)%s * %s[i];\n", + segments->fFSCode.appendf("\t\t%s += %s(%s, %s)%s * %s;\n", sumVar.c_str(), texFunc.c_str(), samplerName, coordVar.c_str(), swizzle, - kernelName); + kernelIndex.c_str()); segments->fFSCode.appendf("\t\t%s += %s;\n", coordVar.c_str(), imageIncrementName); @@ -1630,24 +1658,24 @@ void GrGLProgram::genStageCode(const GrGLInterface* gl, vector_all_coords(varyingDims)); } - const char* radial2ParamsName = NULL; - const char *radial2VaryingVSName = NULL; - const char *radial2VaryingFSName = NULL; + GrGLShaderVar* radial2Params = NULL; + const char* radial2VaryingVSName = NULL; + const char* radial2VaryingFSName = NULL; if (isRadialMapping((StageDesc::CoordMapping) desc.fCoordMapping)) { - radial2ParamsName = genRadialVS(stageNum, segments, - locations, - &radial2VaryingVSName, - &radial2VaryingFSName, - varyingVSName, - varyingDims, coordDims); + radial2Params = genRadialVS(stageNum, segments, + locations, + &radial2VaryingVSName, + &radial2VaryingFSName, + varyingVSName, + varyingDims, coordDims); } - const char* kernelName = NULL; + GrGLShaderVar* kernel = NULL; const char* imageIncrementName = NULL; if (StageDesc::kConvolution_FetchMode == desc.fFetchMode) { genConvolutionVS(stageNum, desc, segments, locations, - &kernelName, &imageIncrementName, varyingVSName); + &kernel, &imageIncrementName, varyingVSName); } /// Fragment Shader Stuff @@ -1696,7 +1724,7 @@ void GrGLProgram::genStageCode(const GrGLInterface* gl, case StageDesc::kRadial2Gradient_CoordMapping: complexCoord = genRadial2GradientCoordMapping( stageNum, segments, - radial2VaryingFSName, radial2ParamsName, + radial2VaryingFSName, radial2Params, sampleCoords, fsCoordName, varyingDims, coordDims); @@ -1704,7 +1732,7 @@ void GrGLProgram::genStageCode(const GrGLInterface* gl, case StageDesc::kRadial2GradientDegenerate_CoordMapping: complexCoord = genRadial2GradientDegenerateCoordMapping( stageNum, segments, - radial2VaryingFSName, radial2ParamsName, + radial2VaryingFSName, radial2Params, sampleCoords, fsCoordName, varyingDims, coordDims); break; @@ -1754,7 +1782,7 @@ void GrGLProgram::genStageCode(const GrGLInterface* gl, GrAssert(!(desc.fInConfigFlags & StageDesc::kMulRGBByAlpha_InConfigFlag)); genConvolutionFS(stageNum, desc, segments, - samplerName, kernelName, swizzle, imageIncrementName, fsOutColor, + samplerName, kernel, swizzle, imageIncrementName, fsOutColor, sampleCoords, texFunc, modulate); break; default: diff --git a/src/gpu/GrGLShaderVar.h b/src/gpu/GrGLShaderVar.h index 8eba714..1e278c2 100644 --- a/src/gpu/GrGLShaderVar.h +++ b/src/gpu/GrGLShaderVar.h @@ -12,6 +12,8 @@ #include "GrGLInterface.h" #include "GrStringBuilder.h" +#define USE_UNIFORM_FLOAT_ARRAYS true + /** * Represents a variable in a shader */ @@ -34,13 +36,15 @@ public: fType = kFloat_Type; fCount = kNonArray; fEmitPrecision = false; + fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS; } GrGLShaderVar(const GrGLShaderVar& var) : fType(var.fType) , fName(var.fName) , fCount(var.fCount) - , fEmitPrecision(var.fEmitPrecision) {} + , fEmitPrecision(var.fEmitPrecision) + , fUseUniformFloatArrays(var.fUseUniformFloatArrays) {} /** * Values for array count that have special meaning. We allow 1-sized arrays. @@ -55,11 +59,13 @@ public: */ void set(Type type, const GrStringBuilder& name, - bool emitPrecision = false) { + bool emitPrecision = false, + bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { fType = type; fName = name; fCount = kNonArray; fEmitPrecision = emitPrecision; + fUseUniformFloatArrays = useUniformFloatArrays; } /** @@ -67,11 +73,13 @@ public: */ void set(Type type, const char* name, - bool specifyPrecision = false) { + bool specifyPrecision = false, + bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { fType = type; fName = name; fCount = kNonArray; fEmitPrecision = specifyPrecision; + fUseUniformFloatArrays = useUniformFloatArrays; } /** @@ -80,11 +88,13 @@ public: void set(Type type, const GrStringBuilder& name, int count, - bool specifyPrecision = false) { + bool specifyPrecision = false, + bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { fType = type; fName = name; fCount = count; fEmitPrecision = specifyPrecision; + fUseUniformFloatArrays = useUniformFloatArrays; } /** @@ -93,11 +103,13 @@ public: void set(Type type, const char* name, int count, - bool specifyPrecision = false) { + bool specifyPrecision = false, + bool useUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS) { fType = type; fName = name; fCount = count; fEmitPrecision = specifyPrecision; + fUseUniformFloatArrays = useUniformFloatArrays; } /** @@ -165,21 +177,22 @@ public: out->append(PrecisionString(gl)); out->append(" "); } + Type effectiveType = this->getType(); if (this->isArray()) { if (this->isUnsizedArray()) { out->appendf("%s %s[]", - TypeString(this->getType()), + TypeString(effectiveType), this->getName().c_str()); } else { GrAssert(this->getArrayCount() > 0); out->appendf("%s %s[%d]", - TypeString(this->getType()), + TypeString(effectiveType), this->getName().c_str(), this->getArrayCount()); } } else { out->appendf("%s %s", - TypeString(this->getType()), + TypeString(effectiveType), this->getName().c_str()); } } @@ -204,6 +217,20 @@ public: } } + void appendArrayAccess(int index, GrStringBuilder* out) { + out->appendf("%s[%d]%s", + this->getName().c_str(), + index, + fUseUniformFloatArrays ? "" : ".x"); + } + + void appendArrayAccess(const char* indexName, GrStringBuilder* out) { + out->appendf("%s[%s]%s", + this->getName().c_str(), + indexName, + fUseUniformFloatArrays ? "" : ".x"); + } + private: static const char* PrecisionString(const GrGLInterface* gl) { return gl->supportsDesktop() ? "" : "mediump"; @@ -213,6 +240,9 @@ private: GrStringBuilder fName; int fCount; bool fEmitPrecision; + /// Work around driver bugs on some hardware that don't correctly + /// support uniform float [] + bool fUseUniformFloatArrays; }; #endif -- 2.7.4