From f9ad8867f2bcd8563862b0a5a90b473ad020d465 Mon Sep 17 00:00:00 2001 From: "tomhudson@google.com" Date: Fri, 11 May 2012 20:38:48 +0000 Subject: [PATCH] Extract ShaderCodeSegments from GrGLProgram into a new class, GrGLShaderBuilder. Begin populating its interface. Requires gyp changes. http://codereview.appspot.com/6197076/ git-svn-id: http://skia.googlecode.com/svn/trunk@3916 2bbb7eff-a529-9590-31e7-b0007b416f81 --- gyp/gpu.gyp | 2 + src/gpu/gl/GrGLProgram.cpp | 157 ++++++------------------------- src/gpu/gl/GrGLProgram.h | 11 +-- src/gpu/gl/GrGLShaderBuilder.cpp | 80 ++++++++++++++++ src/gpu/gl/GrGLShaderBuilder.h | 58 ++++++++++++ 5 files changed, 173 insertions(+), 135 deletions(-) create mode 100644 src/gpu/gl/GrGLShaderBuilder.cpp create mode 100644 src/gpu/gl/GrGLShaderBuilder.h diff --git a/gyp/gpu.gyp b/gyp/gpu.gyp index 9d9c6c26c5..9ca225eb9b 100644 --- a/gyp/gpu.gyp +++ b/gyp/gpu.gyp @@ -297,6 +297,8 @@ '../src/gpu/gl/GrGLProgramStage.h', '../src/gpu/gl/GrGLRenderTarget.cpp', '../src/gpu/gl/GrGLRenderTarget.h', + '../src/gpu/gl/GrGLShaderBuilder.cpp', + '../src/gpu/gl/GrGLShaderBuilder.h', '../src/gpu/gl/GrGLShaderVar.h', '../src/gpu/gl/GrGLSL.cpp', '../src/gpu/gl/GrGLSL.h', diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index 27a0b12d3b..7ffb4d4da4 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -10,6 +10,7 @@ #include "GrAllocator.h" #include "GrCustomStage.h" #include "GrGLProgramStage.h" +#include "gl/GrGLShaderBuilder.h" #include "GrGLShaderVar.h" #include "GrProgramStageFactory.h" #include "SkTrace.h" @@ -27,42 +28,6 @@ enum { #define PRINT_SHADERS 0 -typedef GrTAllocator VarArray; - -// number of each input/output type in a single allocation block -static const int gVarsPerBlock = 8; -// except FS outputs where we expect 2 at most. -static const int gMaxFSOutputs = 2; - -struct ShaderCodeSegments { - ShaderCodeSegments() - : fVSUnis(gVarsPerBlock) - , fVSAttrs(gVarsPerBlock) - , fVSOutputs(gVarsPerBlock) - , fGSInputs(gVarsPerBlock) - , fGSOutputs(gVarsPerBlock) - , fFSInputs(gVarsPerBlock) - , fFSUnis(gVarsPerBlock) - , fFSOutputs(gMaxFSOutputs) - , fUsesGS(false) {} - GrStringBuilder fHeader; // VS+FS, GLSL version, etc - VarArray fVSUnis; - VarArray fVSAttrs; - VarArray fVSOutputs; - VarArray fGSInputs; - VarArray fGSOutputs; - VarArray fFSInputs; - GrStringBuilder fGSHeader; // layout qualifiers specific to GS - VarArray fFSUnis; - VarArray fFSOutputs; - GrStringBuilder fFSFunctions; - GrStringBuilder fVSCode; - GrStringBuilder fGSCode; - GrStringBuilder fFSCode; - - bool fUsesGS; -}; - typedef GrGLProgram::ProgramDesc::StageDesc StageDesc; #if GR_GL_ATTRIBUTE_MATRICES @@ -346,77 +311,14 @@ static void addColorMatrix(GrStringBuilder* fsCode, const char * outputVar, fsCode->appendf("\t%s.rgb *= %s.a;\n", outputVar, outputVar); } -namespace { - -// Adds a var that is computed in the VS and read in FS. -// If there is a GS it will just pass it through. -void append_varying(GrSLType type, - const char* name, - ShaderCodeSegments* segments, - const char** vsOutName = NULL, - const char** fsInName = NULL) { - segments->fVSOutputs.push_back(); - segments->fVSOutputs.back().setType(type); - segments->fVSOutputs.back().setTypeModifier( - GrGLShaderVar::kOut_TypeModifier); - segments->fVSOutputs.back().accessName()->printf("v%s", name); - if (vsOutName) { - *vsOutName = segments->fVSOutputs.back().getName().c_str(); - } - // input to FS comes either from VS or GS - const GrStringBuilder* fsName; - if (segments->fUsesGS) { - // if we have a GS take each varying in as an array - // and output as non-array. - segments->fGSInputs.push_back(); - segments->fGSInputs.back().setType(type); - segments->fGSInputs.back().setTypeModifier( - GrGLShaderVar::kIn_TypeModifier); - segments->fGSInputs.back().setUnsizedArray(); - *segments->fGSInputs.back().accessName() = - segments->fVSOutputs.back().getName(); - segments->fGSOutputs.push_back(); - segments->fGSOutputs.back().setType(type); - segments->fGSOutputs.back().setTypeModifier( - GrGLShaderVar::kOut_TypeModifier); - segments->fGSOutputs.back().accessName()->printf("g%s", name); - fsName = segments->fGSOutputs.back().accessName(); - } else { - fsName = segments->fVSOutputs.back().accessName(); - } - segments->fFSInputs.push_back(); - segments->fFSInputs.back().setType(type); - segments->fFSInputs.back().setTypeModifier( - GrGLShaderVar::kIn_TypeModifier); - segments->fFSInputs.back().setName(*fsName); - if (fsInName) { - *fsInName = fsName->c_str(); - } -} - -// version of above that adds a stage number to the -// the var name (for uniqueness) -void append_varying(GrSLType type, - const char* name, - int stageNum, - ShaderCodeSegments* segments, - const char** vsOutName = NULL, - const char** fsInName = NULL) { - GrStringBuilder nameWithStage(name); - nameWithStage.appendS32(stageNum); - append_varying(type, nameWithStage.c_str(), segments, vsOutName, fsInName); -} -} - void GrGLProgram::genEdgeCoverage(const GrGLContextInfo& gl, GrVertexLayout layout, CachedData* programData, GrStringBuilder* coverageVar, - ShaderCodeSegments* segments) const { + GrGLShaderBuilder* segments) const { if (layout & GrDrawTarget::kEdge_VertexLayoutBit) { const char *vsName, *fsName; - append_varying(kVec4f_GrSLType, "Edge", segments, - &vsName, &fsName); + segments->appendVarying(kVec4f_GrSLType, "Edge", &vsName, &fsName); segments->fVSAttrs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, EDGE_ATTR_NAME); segments->fVSCode.appendf("\t%s = " EDGE_ATTR_NAME ";\n", vsName); @@ -478,7 +380,7 @@ namespace { void genInputColor(GrGLProgram::ProgramDesc::ColorInput colorInput, GrGLProgram::CachedData* programData, - ShaderCodeSegments* segments, + GrGLShaderBuilder* segments, GrStringBuilder* inColor) { switch (colorInput) { case GrGLProgram::ProgramDesc::kAttribute_ColorInput: { @@ -486,7 +388,7 @@ void genInputColor(GrGLProgram::ProgramDesc::ColorInput colorInput, GrGLShaderVar::kAttribute_TypeModifier, COL_ATTR_NAME); const char *vsName, *fsName; - append_varying(kVec4f_GrSLType, "Color", segments, &vsName, &fsName); + segments->appendVarying(kVec4f_GrSLType, "Color", &vsName, &fsName); segments->fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName); *inColor = fsName; } break; @@ -508,14 +410,13 @@ void genInputColor(GrGLProgram::ProgramDesc::ColorInput colorInput, } } -void genAttributeCoverage(ShaderCodeSegments* segments, +void genAttributeCoverage(GrGLShaderBuilder* segments, GrStringBuilder* inOutCoverage) { segments->fVSAttrs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, COV_ATTR_NAME); const char *vsName, *fsName; - append_varying(kVec4f_GrSLType, "Coverage", - segments, &vsName, &fsName); + segments->appendVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName); segments->fVSCode.appendf("\t%s = " COV_ATTR_NAME ";\n", vsName); if (inOutCoverage->size()) { segments->fFSCode.appendf("\tvec4 attrCoverage = %s * %s;\n", @@ -526,7 +427,7 @@ void genAttributeCoverage(ShaderCodeSegments* segments, } } -void genUniformCoverage(ShaderCodeSegments* segments, +void genUniformCoverage(GrGLShaderBuilder* segments, GrGLProgram::CachedData* programData, GrStringBuilder* inOutCoverage) { segments->fFSUnis.push_back().set(kVec4f_GrSLType, @@ -545,7 +446,7 @@ void genUniformCoverage(ShaderCodeSegments* segments, } void GrGLProgram::genGeometryShader(const GrGLContextInfo& gl, - ShaderCodeSegments* segments) const { + GrGLShaderBuilder* segments) const { #if GR_GL_EXPERIMENTAL_GS if (fProgramDesc.fExperimentalGS) { GrAssert(gl.glslGeneration() >= k150_GrGLSLGeneration); @@ -596,7 +497,7 @@ GrGLProgram::CachedData::~CachedData() { bool GrGLProgram::genProgram(const GrGLContextInfo& gl, GrCustomStage** customStages, GrGLProgram::CachedData* programData) const { - ShaderCodeSegments segments; + GrGLShaderBuilder segments; const uint32_t& layout = fProgramDesc.fVertexLayout; programData->fUniLocations.reset(); @@ -1035,7 +936,7 @@ inline void append_decls(const VarArray& vars, } bool GrGLProgram::CompileShaders(const GrGLContextInfo& gl, - const ShaderCodeSegments& segments, + const GrGLShaderBuilder& segments, CachedData* programData) { enum { kPreAllocStringCnt = 8 }; @@ -1383,7 +1284,7 @@ bool isRadialMapping(GrGLProgram::StageDesc::CoordMapping mapping) { } GrGLShaderVar* genRadialVS(int stageNum, - ShaderCodeSegments* segments, + GrGLShaderBuilder* segments, GrGLProgram::StageUniLocations* locations, const char** radial2VaryingVSName, const char** radial2VaryingFSName, @@ -1403,12 +1304,11 @@ GrGLShaderVar* genRadialVS(int stageNum, // part of the quadratic as a varying. if (varyingDims == coordDims) { GrAssert(2 == coordDims); - append_varying(kFloat_GrSLType, - "Radial2BCoeff", - stageNum, - segments, - radial2VaryingVSName, - radial2VaryingFSName); + segments->appendVarying(kFloat_GrSLType, + "Radial2BCoeff", + stageNum, + radial2VaryingVSName, + radial2VaryingFSName); GrStringBuilder radial2p2; GrStringBuilder radial2p3; @@ -1426,7 +1326,7 @@ GrGLShaderVar* genRadialVS(int stageNum, } bool genRadial2GradientCoordMapping(int stageNum, - ShaderCodeSegments* segments, + GrGLShaderBuilder* segments, const char* radial2VaryingFSName, GrGLShaderVar* radial2Params, GrStringBuilder& sampleCoords, @@ -1494,7 +1394,7 @@ bool genRadial2GradientCoordMapping(int stageNum, } bool genRadial2GradientDegenerateCoordMapping(int stageNum, - ShaderCodeSegments* segments, + GrGLShaderBuilder* segments, const char* radial2VaryingFSName, GrGLShaderVar* radial2Params, GrStringBuilder& sampleCoords, @@ -1540,7 +1440,7 @@ bool genRadial2GradientDegenerateCoordMapping(int stageNum, } void gen2x2FS(int stageNum, - ShaderCodeSegments* segments, + GrGLShaderBuilder* segments, GrGLProgram::StageUniLocations* locations, GrStringBuilder* sampleCoords, const char* samplerName, @@ -1574,7 +1474,7 @@ void gen2x2FS(int stageNum, void genMorphologyVS(int stageNum, const StageDesc& desc, - ShaderCodeSegments* segments, + GrGLShaderBuilder* segments, GrGLProgram::StageUniLocations* locations, const char** imageIncrementName, const char* varyingVSName) { @@ -1596,7 +1496,7 @@ void genMorphologyVS(int stageNum, void genMorphologyFS(int stageNum, const StageDesc& desc, - ShaderCodeSegments* segments, + GrGLShaderBuilder* segments, const char* samplerName, const char* swizzle, const char* imageIncrementName, @@ -1642,7 +1542,7 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl, const char* fsInColor, // NULL means no incoming color const char* fsOutColor, const char* vsInCoord, - ShaderCodeSegments* segments, + GrGLShaderBuilder* segments, StageUniLocations* locations, GrGLProgramStage* customStage) const { @@ -1704,12 +1604,11 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl, } const char *varyingVSName, *varyingFSName; - append_varying(GrSLFloatVectorType(varyingDims), - "Stage", - stageNum, - segments, - &varyingVSName, - &varyingFSName); + segments->appendVarying(GrSLFloatVectorType(varyingDims), + "Stage", + stageNum, + &varyingVSName, + &varyingFSName); if (!matName) { GrAssert(varyingDims == coordDims); diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h index eecdee7575..c4aebf66ac 100644 --- a/src/gpu/gl/GrGLProgram.h +++ b/src/gpu/gl/GrGLProgram.h @@ -19,8 +19,7 @@ class GrBinHashKeyBuilder; class GrGLProgramStage; - -struct ShaderCodeSegments; +class GrGLShaderBuilder; // optionally compile the experimental GS code. Set to GR_DEBUG // so that debug build bots will execute the code. @@ -376,22 +375,22 @@ private: const char* fsInColor, // NULL means no incoming color const char* fsOutColor, const char* vsInCoord, - ShaderCodeSegments* segments, + GrGLShaderBuilder* segments, StageUniLocations* locations, GrGLProgramStage* override) const; void genGeometryShader(const GrGLContextInfo& gl, - ShaderCodeSegments* segments) const; + GrGLShaderBuilder* segments) const; // generates code to compute coverage based on edge AA. void genEdgeCoverage(const GrGLContextInfo& gl, GrVertexLayout layout, CachedData* programData, GrStringBuilder* coverageVar, - ShaderCodeSegments* segments) const; + GrGLShaderBuilder* segments) const; static bool CompileShaders(const GrGLContextInfo& gl, - const ShaderCodeSegments& segments, + const GrGLShaderBuilder& segments, CachedData* programData); // Compiles a GL shader, returns shader ID or 0 if failed diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp new file mode 100644 index 0000000000..77ae42536c --- /dev/null +++ b/src/gpu/gl/GrGLShaderBuilder.cpp @@ -0,0 +1,80 @@ +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "gl/GrGLShaderBuilder.h" + +namespace { + +// number of each input/output type in a single allocation block +static const int sVarsPerBlock = 8; + +// except FS outputs where we expect 2 at most. +static const int sMaxFSOutputs = 2; + +} + +GrGLShaderBuilder::GrGLShaderBuilder() + : fVSUnis(sVarsPerBlock) + , fVSAttrs(sVarsPerBlock) + , fVSOutputs(sVarsPerBlock) + , fGSInputs(sVarsPerBlock) + , fGSOutputs(sVarsPerBlock) + , fFSInputs(sVarsPerBlock) + , fFSUnis(sVarsPerBlock) + , fFSOutputs(sMaxFSOutputs) + , fUsesGS(false) { + +} + +void GrGLShaderBuilder::appendVarying(GrSLType type, + const char* name, + const char** vsOutName, + const char** fsInName) { + fVSOutputs.push_back(); + fVSOutputs.back().setType(type); + fVSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier); + fVSOutputs.back().accessName()->printf("v%s", name); + if (vsOutName) { + *vsOutName = fVSOutputs.back().getName().c_str(); + } + // input to FS comes either from VS or GS + const GrStringBuilder* fsName; + if (fUsesGS) { + // if we have a GS take each varying in as an array + // and output as non-array. + fGSInputs.push_back(); + fGSInputs.back().setType(type); + fGSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier); + fGSInputs.back().setUnsizedArray(); + *fGSInputs.back().accessName() = fVSOutputs.back().getName(); + fGSOutputs.push_back(); + fGSOutputs.back().setType(type); + fGSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier); + fGSOutputs.back().accessName()->printf("g%s", name); + fsName = fGSOutputs.back().accessName(); + } else { + fsName = fVSOutputs.back().accessName(); + } + fFSInputs.push_back(); + fFSInputs.back().setType(type); + fFSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier); + fFSInputs.back().setName(*fsName); + if (fsInName) { + *fsInName = fsName->c_str(); + } +} + + +void GrGLShaderBuilder::appendVarying(GrSLType type, + const char* name, + int stageNum, + const char** vsOutName, + const char** fsInName) { + GrStringBuilder nameWithStage(name); + nameWithStage.appendS32(stageNum); + this->appendVarying(type, nameWithStage.c_str(), vsOutName, fsInName); +} diff --git a/src/gpu/gl/GrGLShaderBuilder.h b/src/gpu/gl/GrGLShaderBuilder.h new file mode 100644 index 0000000000..1f4c41fd65 --- /dev/null +++ b/src/gpu/gl/GrGLShaderBuilder.h @@ -0,0 +1,58 @@ +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrGLShaderBuilder_DEFINED +#define GrGLShaderBuilder_DEFINED + +#include "GrAllocator.h" +#include "gl/GrGLShaderVar.h" +#include "gl/GrGLSL.h" + +typedef GrTAllocator VarArray; + +/** + Containts all the incremental state of a shader as it is being built, + as well as helpers to manipulate that state. + TODO: migrate CompileShaders() here? +*/ + +class GrGLShaderBuilder { + +public: + + GrGLShaderBuilder(); + + void appendVarying(GrSLType type, + const char* name, + const char** vsOutName = NULL, + const char** fsInName = NULL); + + void appendVarying(GrSLType type, + const char* name, + int stageNum, + const char** vsOutName = NULL, + const char** fsInName = NULL); + + GrStringBuilder fHeader; // VS+FS, GLSL version, etc + VarArray fVSUnis; + VarArray fVSAttrs; + VarArray fVSOutputs; + VarArray fGSInputs; + VarArray fGSOutputs; + VarArray fFSInputs; + GrStringBuilder fGSHeader; // layout qualifiers specific to GS + VarArray fFSUnis; + VarArray fFSOutputs; + GrStringBuilder fFSFunctions; + GrStringBuilder fVSCode; + GrStringBuilder fGSCode; + GrStringBuilder fFSCode; + + bool fUsesGS; +}; + +#endif