diff options
author | joshualitt <joshualitt@chromium.org> | 2015-02-13 16:23:48 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-02-13 16:23:49 -0800 |
commit | 1c3c2d83364ee228e0751df0e1b9c161c0ba8c1e (patch) | |
tree | f5913f990f042a0b97992f3c33567bf959902084 | |
parent | 3a6672ae0c95f24f873dca21424e060df9f9c3e5 (diff) |
Multi-string shaders
BUG=skia:
Review URL: https://codereview.chromium.org/929503002
-rw-r--r-- | include/gpu/gl/GrGLSLPrettyPrint.h | 5 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp | 31 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLFragmentShaderBuilder.h | 2 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp | 35 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLGeometryShaderBuilder.h | 2 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLProgramBuilder.h | 7 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLSLPrettyPrint.cpp | 147 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLShaderBuilder.cpp | 69 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLShaderBuilder.h | 45 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLShaderStringBuilder.cpp | 30 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLShaderStringBuilder.h | 4 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp | 27 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLVertexShaderBuilder.h | 2 | ||||
-rw-r--r-- | tests/GrGLSLPrettyPrintTest.cpp | 51 |
14 files changed, 279 insertions, 178 deletions
diff --git a/include/gpu/gl/GrGLSLPrettyPrint.h b/include/gpu/gl/GrGLSLPrettyPrint.h index 7273aaa3fc..52fb74557d 100644 --- a/include/gpu/gl/GrGLSLPrettyPrint.h +++ b/include/gpu/gl/GrGLSLPrettyPrint.h @@ -10,7 +10,10 @@ #include "SkString.h" namespace GrGLSLPrettyPrint { - SkString PrettyPrintGLSL(const SkString& input, bool countlines); + SkString PrettyPrintGLSL(const char** strings, + int* lengths, + int count, + bool countlines); }; #endif /* GRGLPRETTYPRINTSL_H_ */ diff --git a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp index 86c622d456..c739f1162a 100644 --- a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp +++ b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp @@ -6,7 +6,6 @@ */ #include "GrGLFragmentShaderBuilder.h" -#include "GrGLShaderStringBuilder.h" #include "GrGLProgramBuilder.h" #include "../GrGLGpu.h" @@ -210,33 +209,19 @@ const char* GrGLFragmentShaderBuilder::getSecondaryColorOutputName() const { } bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId, - SkTDArray<GrGLuint>* shaderIds) const { + SkTDArray<GrGLuint>* shaderIds) { GrGLGpu* gpu = fProgramBuilder->gpu(); - SkString fragShaderSrc(GrGetGLSLVersionDecl(gpu->ctxInfo())); - fragShaderSrc.append(fExtensions); + this->versionDecl() = GrGetGLSLVersionDecl(gpu->ctxInfo()); append_default_precision_qualifier(kDefault_GrSLPrecision, gpu->glStandard(), - &fragShaderSrc); - fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kFragment_Visibility, &fragShaderSrc); - this->appendDecls(fInputs, &fragShaderSrc); + &this->precisionQualifier()); + fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kFragment_Visibility, + &this->uniforms()); + this->appendDecls(fInputs, &this->inputs()); // We shouldn't have declared outputs on 1.10 SkASSERT(k110_GrGLSLGeneration != gpu->glslGeneration() || fOutputs.empty()); - this->appendDecls(fOutputs, &fragShaderSrc); - fragShaderSrc.append(fFunctions); - fragShaderSrc.append("void main() {\n"); - fragShaderSrc.append(fCode); - fragShaderSrc.append("}\n"); - - GrGLuint fragShaderId = GrGLCompileAndAttachShader(gpu->glContext(), programId, - GR_GL_FRAGMENT_SHADER, fragShaderSrc, - gpu->stats()); - if (!fragShaderId) { - return false; - } - - *shaderIds->append() = fragShaderId; - - return true; + this->appendDecls(fOutputs, &this->outputs()); + return this->finalize(programId, GR_GL_FRAGMENT_SHADER, shaderIds); } void GrGLFragmentShaderBuilder::bindFragmentShaderLocations(GrGLuint programID) { diff --git a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h index 903c5e1d7b..f294257a1b 100644 --- a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h +++ b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h @@ -101,7 +101,7 @@ private: void enableSecondaryOutput(); const char* getPrimaryColorOutputName() const; const char* getSecondaryColorOutputName() const; - bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const; + bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds); void bindFragmentShaderLocations(GrGLuint programID); // As GLProcessors emit code, there are some conditions we need to verify. We use the below diff --git a/src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp b/src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp index 8be2531c96..b20575259b 100644 --- a/src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp +++ b/src/gpu/gl/builders/GrGLGeometryShaderBuilder.cpp @@ -6,7 +6,6 @@ */ #include "GrGLGeometryShaderBuilder.h" -#include "GrGLShaderStringBuilder.h" #include "GrGLProgramBuilder.h" #include "../GrGLGpu.h" @@ -37,35 +36,7 @@ void GrGLGeometryBuilder::addVarying(const char* name, GrGLVarying* v) { } bool GrGLGeometryBuilder::compileAndAttachShaders(GrGLuint programId, - SkTDArray<GrGLuint>* shaderIds) const { - const GrGLContext& glCtx = fProgramBuilder->gpu()->glContext(); - SkASSERT(fProgramBuilder->ctxInfo().glslGeneration() >= k150_GrGLSLGeneration); - SkString geomShaderSrc(GrGetGLSLVersionDecl(fProgramBuilder->ctxInfo())); - geomShaderSrc.append("layout(triangles) in;\n" - "layout(triangle_strip, max_vertices = 6) out;\n"); - this->appendDecls(fInputs, &geomShaderSrc); - this->appendDecls(fOutputs, &geomShaderSrc); - geomShaderSrc.append("void main() {\n"); - geomShaderSrc.append("\tfor (int i = 0; i < 3; ++i) {\n" - "\t\tgl_Position = gl_in[i].gl_Position;\n"); - geomShaderSrc.append("\t\tgl_PointSize = 1.0;\n"); - SkASSERT(fInputs.count() == fOutputs.count()); - for (int i = 0; i < fInputs.count(); ++i) { - geomShaderSrc.appendf("\t\t%s = %s[i];\n", - fOutputs[i].getName().c_str(), - fInputs[i].getName().c_str()); - } - geomShaderSrc.append("\t\tEmitVertex();\n" - "\t}\n" - "\tEndPrimitive();\n"); - geomShaderSrc.append("}\n"); - GrGLuint geomShaderId = - GrGLCompileAndAttachShader(glCtx, programId, - GR_GL_GEOMETRY_SHADER, geomShaderSrc, - fProgramBuilder->gpu()->stats()); - if (!geomShaderId) { - return false; - } - *shaderIds->append() = geomShaderId; - return true; + SkTDArray<GrGLuint>* shaderIds) { + SkFAIL("Geometry shaders are not currently supported"); + return false; } diff --git a/src/gpu/gl/builders/GrGLGeometryShaderBuilder.h b/src/gpu/gl/builders/GrGLGeometryShaderBuilder.h index 88fa298823..c4c019be18 100644 --- a/src/gpu/gl/builders/GrGLGeometryShaderBuilder.h +++ b/src/gpu/gl/builders/GrGLGeometryShaderBuilder.h @@ -22,7 +22,7 @@ private: */ void addVarying(const char* name, GrGLVarying*); - bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const; + bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds); friend class GrGLProgramBuilder; diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h index 37908f9971..46d2816c52 100644 --- a/src/gpu/gl/builders/GrGLProgramBuilder.h +++ b/src/gpu/gl/builders/GrGLProgramBuilder.h @@ -356,7 +356,12 @@ protected: }; class AutoStageAdvance { public: - AutoStageAdvance(GrGLProgramBuilder* pb) : fPB(pb) { fPB->reset(); } + AutoStageAdvance(GrGLProgramBuilder* pb) + : fPB(pb) { + fPB->reset(); + // Each output to the fragment processor gets its own code section + fPB->fFS.nextStage(); + } ~AutoStageAdvance() { fPB->exitStage(); } private: GrGLProgramBuilder* fPB; diff --git a/src/gpu/gl/builders/GrGLSLPrettyPrint.cpp b/src/gpu/gl/builders/GrGLSLPrettyPrint.cpp index 27f4b44e66..02802987c6 100644 --- a/src/gpu/gl/builders/GrGLSLPrettyPrint.cpp +++ b/src/gpu/gl/builders/GrGLSLPrettyPrint.cpp @@ -12,69 +12,86 @@ class GLSLPrettyPrint { public: GLSLPrettyPrint() {} - SkString prettify(const SkString& input, bool countlines) { - // setup pretty state - fIndex = 0; - fLength = input.size(); - fInput = input; + SkString prettify(const char** strings, + int* lengths, + int count, + bool countlines) { fCountlines = countlines; fTabs = 0; fLinecount = 1; fFreshline = true; + // If a string breaks while in the middle 'parse until' we need to continue parsing on the + // next string + fInParseUntilNewline = false; + fInParseUntil = false; + int parensDepth = 0; + // number 1st line this->lineNumbering(); - while (fLength > fIndex) { - /* the heart and soul of our prettification algorithm. The rules should hopefully be - * self explanatory. For '#' and '//' tokens we parse until we reach a newline. - * - * For long style comments like this one, we search for the ending token. We also - * preserve whitespace in these comments WITH THE CAVEAT that we do the newlines - * ourselves. This allows us to remain in control of line numbers, and matching tabs - * Existing tabs in the input string are copied over too, but this will look funny - * - * '{' and '}' are handled in basically the same way. We add a newline if we aren't - * on a fresh line, dirty the line, then add a second newline, ie braces are always - * on their own lines indented properly. The one funkiness here is structs print with - * the semicolon on its own line. Its not a problem for a glsl compiler though - * - * '(' and ')' are basically ignored, except as a sign we need to ignore ';' ala - * in for loops. - * - * ';' means add a new line - * - * '\t' and '\n' are ignored in general parsing for backwards compatability with - * existing shader code and we also have a special case for handling whitespace - * at the beginning of fresh lines. - * - * Otherwise just add the new character to the pretty string, indenting if necessary. - */ - if (this->hasToken("#") || this->hasToken("//")) { - this->parseUntilNewline(); - } else if (this->hasToken("/*")) { - this->parseUntil("*/"); - } else if ('{' == fInput[fIndex]) { - this->newline(); - this->appendChar('{'); - fTabs++; - this->newline(); - } else if ('}' == fInput[fIndex]) { - fTabs--; - this->newline(); - this->appendChar('}'); - this->newline(); - } else if (this->hasToken(")")) { - parensDepth--; - } else if (this->hasToken("(")) { - parensDepth++; - } else if (!parensDepth && this->hasToken(";")) { - this->newline(); - } else if ('\t' == fInput[fIndex] || '\n' == fInput[fIndex] || - (fFreshline && ' ' == fInput[fIndex])) { - fIndex++; - } else { - this->appendChar(input[fIndex]); + for (int i = 0; i < count; i++) { + // setup pretty state + fIndex = 0; + fLength = lengths[i]; + fInput = strings[i]; + + while (fLength > fIndex) { + /* the heart and soul of our prettification algorithm. The rules should hopefully + * be self explanatory. For '#' and '//' tokens we parse until we reach a newline. + * + * For long style comments like this one, we search for the ending token. We also + * preserve whitespace in these comments WITH THE CAVEAT that we do the newlines + * ourselves. This allows us to remain in control of line numbers, and matching + * tabs Existing tabs in the input string are copied over too, but this will look + * funny + * + * '{' and '}' are handled in basically the same way. We add a newline if we aren't + * on a fresh line, dirty the line, then add a second newline, ie braces are always + * on their own lines indented properly. The one funkiness here is structs print + * with the semicolon on its own line. Its not a problem for a glsl compiler though + * + * '(' and ')' are basically ignored, except as a sign we need to ignore ';' ala + * in for loops. + * + * ';' means add a new line + * + * '\t' and '\n' are ignored in general parsing for backwards compatability with + * existing shader code and we also have a special case for handling whitespace + * at the beginning of fresh lines. + * + * Otherwise just add the new character to the pretty string, indenting if necessary. + */ + if (fInParseUntilNewline) { + this->parseUntilNewline(); + } else if (fInParseUntil) { + this->parseUntil(fInParseUntilToken); + } else if (this->hasToken("#") || this->hasToken("//")) { + this->parseUntilNewline(); + } else if (this->hasToken("/*")) { + this->parseUntil("*/"); + } else if ('{' == fInput[fIndex]) { + this->newline(); + this->appendChar('{'); + fTabs++; + this->newline(); + } else if ('}' == fInput[fIndex]) { + fTabs--; + this->newline(); + this->appendChar('}'); + this->newline(); + } else if (this->hasToken(")")) { + parensDepth--; + } else if (this->hasToken("(")) { + parensDepth++; + } else if (!parensDepth && this->hasToken(";")) { + this->newline(); + } else if ('\t' == fInput[fIndex] || '\n' == fInput[fIndex] || + (fFreshline && ' ' == fInput[fIndex])) { + fIndex++; + } else { + this->appendChar(fInput[fIndex]); + } } } return fPretty; @@ -107,9 +124,11 @@ private: if ('\n' == fInput[fIndex]) { fIndex++; this->newline(); + fInParseUntilNewline = false; break; } fPretty.appendf("%c", fInput[fIndex++]); + fInParseUntilNewline = true; } } @@ -127,10 +146,13 @@ private: fIndex++; } if (this->hasToken(token)) { + fInParseUntil = false; break; } fFreshline = false; fPretty.appendf("%c", fInput[fIndex++]); + fInParseUntil = true; + fInParseUntilToken = token; } } @@ -162,12 +184,21 @@ private: bool fCountlines, fFreshline; int fTabs, fLinecount; size_t fIndex, fLength; - SkString fInput, fPretty; + const char* fInput; + SkString fPretty; + + // Some helpers for parseUntil when we go over a string length + bool fInParseUntilNewline; + bool fInParseUntil; + const char* fInParseUntilToken; }; -SkString PrettyPrintGLSL(const SkString& input, bool countlines) { +SkString PrettyPrintGLSL(const char** strings, + int* lengths, + int count, + bool countlines) { GLSLPrettyPrint pp; - return pp.prettify(input, countlines); + return pp.prettify(strings, lengths, count, countlines); } } // end namespace diff --git a/src/gpu/gl/builders/GrGLShaderBuilder.cpp b/src/gpu/gl/builders/GrGLShaderBuilder.cpp index 48872256da..0711c91fb2 100644 --- a/src/gpu/gl/builders/GrGLShaderBuilder.cpp +++ b/src/gpu/gl/builders/GrGLShaderBuilder.cpp @@ -7,7 +7,7 @@ #include "GrGLShaderBuilder.h" #include "GrGLProgramBuilder.h" -#include "GrGLProgramBuilder.h" +#include "GrGLShaderStringBuilder.h" #include "../GrGLGpu.h" #include "../GrGLShaderVar.h" @@ -59,7 +59,17 @@ GrGLShaderBuilder::GrGLShaderBuilder(GrGLProgramBuilder* program) : fProgramBuilder(program) , fInputs(GrGLProgramBuilder::kVarsPerBlock) , fOutputs(GrGLProgramBuilder::kVarsPerBlock) - , fFeaturesAddedMask(0) { + , fFeaturesAddedMask(0) + , fCodeIndex(kCode) + , fFinalized(false) { + // We push back some dummy pointers which will later become our header + for (int i = 0; i <= kCode; i++) { + fShaderStrings.push_back(); + fCompilerStrings.push_back(NULL); + fCompilerStringLengths.push_back(0); + } + + this->main() = "void main() {"; } void GrGLShaderBuilder::declAppend(const GrGLShaderVar& var) { @@ -74,20 +84,20 @@ void GrGLShaderBuilder::emitFunction(GrSLType returnType, const GrGLShaderVar* args, const char* body, SkString* outName) { - fFunctions.append(GrGLSLTypeString(returnType)); + this->functions().append(GrGLSLTypeString(returnType)); fProgramBuilder->nameVariable(outName, '\0', name); - fFunctions.appendf(" %s", outName->c_str()); - fFunctions.append("("); + this->functions().appendf(" %s", outName->c_str()); + this->functions().append("("); const GrGLContextInfo& ctxInfo = fProgramBuilder->gpu()->ctxInfo(); for (int i = 0; i < argCnt; ++i) { - args[i].appendDecl(ctxInfo, &fFunctions); + args[i].appendDecl(ctxInfo, &this->functions()); if (i < argCnt - 1) { - fFunctions.append(", "); + this->functions().append(", "); } } - fFunctions.append(") {\n"); - fFunctions.append(body); - fFunctions.append("}\n\n"); + this->functions().append(") {\n"); + this->functions().append(body); + this->functions().append("}\n\n"); } void GrGLShaderBuilder::appendTextureLookup(SkString* out, @@ -106,7 +116,7 @@ void GrGLShaderBuilder::appendTextureLookup(SkString* out, void GrGLShaderBuilder::appendTextureLookup(const TextureSampler& sampler, const char* coordName, GrSLType varyingType) { - this->appendTextureLookup(&fCode, sampler, coordName, varyingType); + this->appendTextureLookup(&this->code(), sampler, coordName, varyingType); } void GrGLShaderBuilder::appendTextureLookupAndModulate(const char* modulation, @@ -137,8 +147,8 @@ const GrGLenum* GrGLShaderBuilder::GetTexParamSwizzle(GrPixelConfig config, cons void GrGLShaderBuilder::addFeature(uint32_t featureBit, const char* extensionName) { if (!(featureBit & fFeaturesAddedMask)) { - fExtensions.appendf("#extension %s: require\n", extensionName); - fFeaturesAddedMask |= featureBit; + this->extensions().appendf("#extension %s: require\n", extensionName); + fFeaturesAddedMask |= featureBit; } } @@ -153,7 +163,7 @@ void GrGLShaderBuilder::appendTextureLookup(const char* samplerName, const char* coordName, uint32_t configComponentMask, const char* swizzle) { - append_texture_lookup(&fCode, + append_texture_lookup(&this->code(), fProgramBuilder->gpu(), samplerName, coordName, @@ -161,3 +171,34 @@ void GrGLShaderBuilder::appendTextureLookup(const char* samplerName, swizzle, kVec2f_GrSLType); } + +bool +GrGLShaderBuilder::finalize(GrGLuint programId, GrGLenum type, SkTDArray<GrGLuint>* shaderIds) { + SkASSERT(!fFinalized); + // append the 'footer' to code + this->code().append("}"); + + for (int i = 0; i <= fCodeIndex; i++) { + fCompilerStrings[i] = fShaderStrings[i].c_str(); + fCompilerStringLengths[i] = fShaderStrings[i].size(); + } + + GrGLGpu* gpu = fProgramBuilder->gpu(); + GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(), + programId, + type, + fCompilerStrings.begin(), + fCompilerStringLengths.begin(), + fCompilerStrings.count(), + gpu->stats()); + + fFinalized = true; + + if (!shaderId) { + return false; + } + + *shaderIds->append() = shaderId; + + return true; +} diff --git a/src/gpu/gl/builders/GrGLShaderBuilder.h b/src/gpu/gl/builders/GrGLShaderBuilder.h index 8b7b9f9974..86db597bff 100644 --- a/src/gpu/gl/builders/GrGLShaderBuilder.h +++ b/src/gpu/gl/builders/GrGLShaderBuilder.h @@ -8,6 +8,7 @@ #ifndef GrGLShaderBuilder_DEFINED #define GrGLShaderBuilder_DEFINED +#include "SkTArray.h" #include "gl/GrGLProcessor.h" #include "gl/GrGLProgramDesc.h" #include "gl/GrGLProgramDataManager.h" @@ -73,16 +74,16 @@ public: void codeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) { va_list args; va_start(args, format); - fCode.appendVAList(format, args); + this->code().appendVAList(format, args); va_end(args); } - void codeAppend(const char* str) { fCode.append(str); } + void codeAppend(const char* str) { this->code().append(str); } void codePrependf(const char format[], ...) SK_PRINTF_LIKE(2, 3) { va_list args; va_start(args, format); - fCode.prependVAList(format, args); + this->code().prependVAList(format, args); va_end(args); } @@ -138,8 +139,40 @@ protected: */ void addFeature(uint32_t featureBit, const char* extensionName); - GrGLProgramBuilder* fProgramBuilder; + void nextStage() { + fShaderStrings.push_back(); + fCompilerStrings.push_back(this->code().c_str()); + fCompilerStringLengths.push_back(this->code().size()); + fCodeIndex++; + } + + SkString& versionDecl() { return fShaderStrings[kVersionDecl]; } + SkString& extensions() { return fShaderStrings[kExtensions]; } + SkString& precisionQualifier() { return fShaderStrings[kPrecisionQualifier]; } + SkString& uniforms() { return fShaderStrings[kUniforms]; } + SkString& inputs() { return fShaderStrings[kInputs]; } + SkString& outputs() { return fShaderStrings[kOutputs]; } + SkString& functions() { return fShaderStrings[kFunctions]; } + SkString& main() { return fShaderStrings[kMain]; } + SkString& code() { return fShaderStrings[fCodeIndex]; } + bool finalize(GrGLuint programId, GrGLenum type, SkTDArray<GrGLuint>* shaderIds); + + enum { + kVersionDecl, + kExtensions, + kPrecisionQualifier, + kUniforms, + kInputs, + kOutputs, + kFunctions, + kMain, + kCode, + }; + GrGLProgramBuilder* fProgramBuilder; + SkSTArray<kCode, const char*, true> fCompilerStrings; + SkSTArray<kCode, int, true> fCompilerStringLengths; + SkSTArray<kCode, SkString> fShaderStrings; SkString fCode; SkString fFunctions; SkString fExtensions; @@ -147,5 +180,9 @@ protected: VarArray fInputs; VarArray fOutputs; uint32_t fFeaturesAddedMask; + int fCodeIndex; + bool fFinalized; + + friend class GrGLProgramBuilder; }; #endif diff --git a/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp b/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp index 1e750489ff..59e0cd8978 100644 --- a/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp +++ b/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp @@ -20,7 +20,9 @@ SK_CONF_DECLARE(bool, c_PrintShaders, "gpu.printShaders", false, GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx, GrGLuint programId, GrGLenum type, - const SkString& shaderSrc, + const char** strings, + int* lengths, + int count, GrGpu::Stats* stats) { const GrGLInterface* gli = glCtx.interface(); @@ -31,14 +33,23 @@ GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx, } #ifdef SK_DEBUG - SkString prettySource = GrGLSLPrettyPrint::PrettyPrintGLSL(shaderSrc, false); + SkString prettySource = GrGLSLPrettyPrint::PrettyPrintGLSL(strings, lengths, count, false); const GrGLchar* sourceStr = prettySource.c_str(); GrGLint sourceLength = static_cast<GrGLint>(prettySource.size()); + GR_GL_CALL(gli, ShaderSource(shaderId, 1, &sourceStr, &sourceLength)); #else - GrGLint sourceLength = static_cast<GrGLint>(shaderSrc.size()); - const GrGLchar* sourceStr = shaderSrc.c_str(); + GR_GL_CALL(gli, ShaderSource(shaderId, count, strings, lengths)); #endif - GR_GL_CALL(gli, ShaderSource(shaderId, 1, &sourceStr, &sourceLength)); + + // If tracing is enabled in chrome then we pretty print + bool traceShader; + TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), &traceShader); + if (traceShader) { + SkString shader = GrGLSLPrettyPrint::PrettyPrintGLSL(strings, lengths, count, false); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), "skia_gpu::GLShader", + TRACE_EVENT_SCOPE_THREAD, "shader", TRACE_STR_COPY(shader.c_str())); + } + stats->incShaderCompilations(); GR_GL_CALL(gli, CompileShader(shaderId)); @@ -59,9 +70,8 @@ GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx, // retrieve length even though we don't need it to workaround bug in Chromium cmd // buffer param validation. GrGLsizei length = GR_GL_INIT_ZERO; - GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, - &length, (char*)log.get())); - SkDebugf(GrGLSLPrettyPrint::PrettyPrintGLSL(shaderSrc, true).c_str()); + GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, &length, (char*)log.get())); + SkDebugf(GrGLSLPrettyPrint::PrettyPrintGLSL(strings, lengths, count, true).c_str()); SkDebugf("\n%s", log.get()); } SkDEBUGFAIL("Shader compilation failed!"); @@ -70,10 +80,8 @@ GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx, } } - TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), "skia_gpu::GLShader", - TRACE_EVENT_SCOPE_THREAD, "shader", TRACE_STR_COPY(shaderSrc.c_str())); if (c_PrintShaders) { - SkDebugf(GrGLSLPrettyPrint::PrettyPrintGLSL(shaderSrc, true).c_str()); + SkDebugf(GrGLSLPrettyPrint::PrettyPrintGLSL(strings, lengths, count, true).c_str()); SkDebugf("\n"); } diff --git a/src/gpu/gl/builders/GrGLShaderStringBuilder.h b/src/gpu/gl/builders/GrGLShaderStringBuilder.h index cf54253e80..062e229cdf 100644 --- a/src/gpu/gl/builders/GrGLShaderStringBuilder.h +++ b/src/gpu/gl/builders/GrGLShaderStringBuilder.h @@ -16,7 +16,9 @@ GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx, GrGLuint programId, GrGLenum type, - const SkString& shaderSrc, + const char** strings, + int* lengths, + int count, GrGpu::Stats*); #endif diff --git a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp index f1671af54c..00e96a5618 100644 --- a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp +++ b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp @@ -7,7 +7,6 @@ #include "GrGLVertexShaderBuilder.h" #include "GrGLProgramBuilder.h" -#include "GrGLShaderStringBuilder.h" #include "../GrGLGpu.h" #define GL_CALL(X) GR_GL_CALL(fProgramBuilder->gpu()->glInterface(), X) @@ -73,25 +72,13 @@ void GrGLVertexBuilder::bindVertexAttributes(GrGLuint programID) { return; } -bool GrGLVertexBuilder::compileAndAttachShaders(GrGLuint programId, - SkTDArray<GrGLuint>* shaderIds) const { - GrGLGpu* gpu = fProgramBuilder->gpu(); - const GrGLContext& glCtx = gpu->glContext(); - const GrGLContextInfo& ctxInfo = gpu->ctxInfo(); - SkString vertShaderSrc(GrGetGLSLVersionDecl(ctxInfo)); - fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kVertex_Visibility, &vertShaderSrc); - this->appendDecls(fInputs, &vertShaderSrc); - this->appendDecls(fOutputs, &vertShaderSrc); - vertShaderSrc.append("void main() {"); - vertShaderSrc.append(fCode); - vertShaderSrc.append("}\n"); - GrGLuint vertShaderId = GrGLCompileAndAttachShader(glCtx, programId, GR_GL_VERTEX_SHADER, - vertShaderSrc, gpu->stats()); - if (!vertShaderId) { - return false; - } - *shaderIds->append() = vertShaderId; - return true; +bool +GrGLVertexBuilder::compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) { + this->versionDecl() = GrGetGLSLVersionDecl(fProgramBuilder->ctxInfo()); + fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kVertex_Visibility, &this->uniforms()); + this->appendDecls(fInputs, &this->inputs()); + this->appendDecls(fOutputs, &this->outputs()); + return this->finalize(programId, GR_GL_VERTEX_SHADER, shaderIds); } bool GrGLVertexBuilder::addAttribute(const GrShaderVar& var) { diff --git a/src/gpu/gl/builders/GrGLVertexShaderBuilder.h b/src/gpu/gl/builders/GrGLVertexShaderBuilder.h index 4c99a7b728..71a60a0804 100644 --- a/src/gpu/gl/builders/GrGLVertexShaderBuilder.h +++ b/src/gpu/gl/builders/GrGLVertexShaderBuilder.h @@ -35,7 +35,7 @@ private: * private helpers for compilation by GrGLProgramBuilder */ void bindVertexAttributes(GrGLuint programID); - bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const; + bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds); // an internal call which checks for uniquness of a var before adding it to the list of inputs bool addAttribute(const GrShaderVar& var); diff --git a/tests/GrGLSLPrettyPrintTest.cpp b/tests/GrGLSLPrettyPrintTest.cpp index 9977488d58..37aa5a88e1 100644 --- a/tests/GrGLSLPrettyPrintTest.cpp +++ b/tests/GrGLSLPrettyPrintTest.cpp @@ -13,12 +13,16 @@ const SkString input1("#this is not a realshader\nvec4 some stuff;outside of a function;" "int i(int b, int c) { { some stuff;} fake block; //comments\n return i;}" - "void main()" - "{nowin a function;{indenting;{abit more;dreadedfor((;;)(;)((;;);)){doingstuff" + "void main()"); +const SkString input2("{nowin a function;{indenting;{abit more;dreadedfor((;;)(;)((;;);)){" + "doingstuff" ";for(;;;){and more stufff;mixed garbage\n\n\t\t\t\t\n/*using this" - " comment\n is" - " dangerous\ndo so at your own\n risk*/;\n\n\t\t\t\n" - "//a comment\n}}a; little ; love; for ; leading; spaces;} " + " comment\n is"); +const SkString input3(" dangerous\ndo so at your own\n risk*/;\n\n\t\t\t\n" + "//a comment"); +const SkString input4("breaking in comment"); +const SkString input5("continuing the comment"); +const SkString input6("\n}}a; little ; love; for ; leading; spaces;} " "an struct = { int a; int b; };" "int[5] arr = int[5](1,2,3,4,5);} some code at the bottom; for(;;) {} }"); @@ -52,7 +56,7 @@ const SkString output1( " 27\t\t\t\t\t\t is dangerous\n" " 28\t\t\t\t\t\tdo so at your own\n" " 29\t\t\t\t\t\t risk*/;\n" - " 30\t\t\t\t\t\t//a comment\n" + " 30\t\t\t\t\t\t//a commentbreaking in commentcontinuing the comment\n" " 31\t\t\t\t\t}\n" " 32\t\t\t\t}\n" " 33\t\t\t\ta;\n" @@ -77,16 +81,43 @@ const SkString output1( " 52\t}\n" " 53\t"); -const SkString input2("{;;{{{{;;;{{{{{{{{{{{###\n##\n#####(((((((((((((unbalanced verything;;;" - "}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}" +const SkString neg1("{;;{{{{;;;{{{{{{{{{{{"); +const SkString neg2("###\n##\n#####(((((((((((((unbalanced verything;;;"); +const SkString neg3("}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}" ";;;;;;/////"); DEF_TEST(GrGLSLPrettyPrint, r) { - SkString test = GrGLSLPrettyPrint::PrettyPrintGLSL(input1, true); + SkTArray<const char*> testStr; + SkTArray<int> lengths; + testStr.push_back(input1.c_str()); + lengths.push_back(input1.size()); + testStr.push_back(input2.c_str()); + lengths.push_back(input2.size()); + testStr.push_back(input3.c_str()); + lengths.push_back(input3.size()); + testStr.push_back(input4.c_str()); + lengths.push_back(input4.size()); + testStr.push_back(input5.c_str()); + lengths.push_back(input5.size()); + testStr.push_back(input6.c_str()); + lengths.push_back(input6.size()); + + SkString test = GrGLSLPrettyPrint::PrettyPrintGLSL(testStr.begin(), lengths.begin(), + testStr.count(), true); ASSERT(output1 == test); + testStr.reset(); + lengths.reset(); + testStr.push_back(neg1.c_str()); + lengths.push_back(neg1.size()); + testStr.push_back(neg2.c_str()); + lengths.push_back(neg2.size()); + testStr.push_back(neg3.c_str()); + lengths.push_back(neg3.size()); + // Just test we don't crash with garbage input - ASSERT(GrGLSLPrettyPrint::PrettyPrintGLSL(input2, true).c_str() != NULL); + ASSERT(GrGLSLPrettyPrint::PrettyPrintGLSL(testStr.begin(), lengths.begin(), 1, + true).c_str() != NULL); } #endif |