Multi-string shaders
BUG=skia: Committed: https://skia.googlesource.com/skia/+/1c3c2d83364ee228e0751df0e1b9c161c0ba8c1e Review URL: https://codereview.chromium.org/929503002
This commit is contained in:
parent
b8a82f2bce
commit
43466a1ade
@ -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_ */
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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] = (int)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;
|
||||
}
|
||||
|
@ -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((int)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
|
||||
|
@ -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());
|
||||
#else
|
||||
GrGLint sourceLength = static_cast<GrGLint>(shaderSrc.size());
|
||||
const GrGLchar* sourceStr = shaderSrc.c_str();
|
||||
#endif
|
||||
GR_GL_CALL(gli, ShaderSource(shaderId, 1, &sourceStr, &sourceLength));
|
||||
#else
|
||||
GR_GL_CALL(gli, ShaderSource(shaderId, count, strings, lengths));
|
||||
#endif
|
||||
|
||||
// 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");
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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((int)input1.size());
|
||||
testStr.push_back(input2.c_str());
|
||||
lengths.push_back((int)input2.size());
|
||||
testStr.push_back(input3.c_str());
|
||||
lengths.push_back((int)input3.size());
|
||||
testStr.push_back(input4.c_str());
|
||||
lengths.push_back((int)input4.size());
|
||||
testStr.push_back(input5.c_str());
|
||||
lengths.push_back((int)input5.size());
|
||||
testStr.push_back(input6.c_str());
|
||||
lengths.push_back((int)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((int)neg1.size());
|
||||
testStr.push_back(neg2.c_str());
|
||||
lengths.push_back((int)neg2.size());
|
||||
testStr.push_back(neg3.c_str());
|
||||
lengths.push_back((int)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
|
||||
|
Loading…
Reference in New Issue
Block a user