Turned on SkSL->GLSL compiler
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2288033003
Committed: https://skia.googlesource.com/skia/+/9b0fe3d125f237d9884732a48414fa85fc71b4e3
Review-Url: https://codereview.chromium.org/2288033003
diff --git a/gyp/sksl.gyp b/gyp/sksl.gyp
index 609ace9..f45b702 100644
--- a/gyp/sksl.gyp
+++ b/gyp/sksl.gyp
@@ -18,7 +18,7 @@
],
'all_dependent_settings': {
'include_dirs': [
- '../src/sksl',
+ '<(skia_src_path)/sksl',
],
},
},
diff --git a/src/gpu/gl/GrGLContext.cpp b/src/gpu/gl/GrGLContext.cpp
index 9e70b47..2126314 100644
--- a/src/gpu/gl/GrGLContext.cpp
+++ b/src/gpu/gl/GrGLContext.cpp
@@ -7,6 +7,7 @@
#include "GrGLContext.h"
#include "GrGLGLSL.h"
+#include "SkSLCompiler.h"
////////////////////////////////////////////////////////////////////////////////
@@ -63,6 +64,17 @@
return new GrGLContext(args);
}
+GrGLContext::~GrGLContext() {
+ delete fCompiler;
+}
+
+SkSL::Compiler* GrGLContext::compiler() const {
+ if (!fCompiler) {
+ fCompiler = new SkSL::Compiler();
+ }
+ return fCompiler;
+}
+
GrGLContextInfo::GrGLContextInfo(const ConstructorArgs& args) {
fInterface.reset(SkRef(args.fInterface));
fGLVersion = args.fGLVersion;
diff --git a/src/gpu/gl/GrGLContext.h b/src/gpu/gl/GrGLContext.h
index 6016f68..8207ac8 100644
--- a/src/gpu/gl/GrGLContext.h
+++ b/src/gpu/gl/GrGLContext.h
@@ -15,6 +15,9 @@
#include "GrGLUtil.h"
struct GrContextOptions;
+namespace SkSL {
+ class Compiler;
+}
/**
* Encapsulates information about an OpenGL context including the OpenGL
@@ -39,6 +42,8 @@
const GrGLExtensions& extensions() const { return fInterface->fExtensions; }
+ virtual ~GrGLContextInfo() {}
+
protected:
struct ConstructorArgs {
const GrGLInterface* fInterface;
@@ -64,7 +69,7 @@
};
/**
- * Extension of GrGLContextInfo that also provides access to GrGLInterface.
+ * Extension of GrGLContextInfo that also provides access to GrGLInterface and SkSL::Compiler.
*/
class GrGLContext : public GrGLContextInfo {
public:
@@ -76,8 +81,16 @@
const GrGLInterface* interface() const { return fInterface; }
+ SkSL::Compiler* compiler() const;
+
+ ~GrGLContext() override;
+
private:
- GrGLContext(const ConstructorArgs& args) : INHERITED(args) {}
+ GrGLContext(const ConstructorArgs& args)
+ : INHERITED(args)
+ , fCompiler(nullptr) {}
+
+ mutable SkSL::Compiler* fCompiler;
typedef GrGLContextInfo INHERITED;
};
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index fcd3270..341216a 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -3790,20 +3790,11 @@
fshaderTxt.append(";");
uTexture.appendDecl(glslCaps, &fshaderTxt);
fshaderTxt.append(";");
- const char* fsOutName;
- if (glslCaps->mustDeclareFragmentShaderOutput()) {
- oFragColor.appendDecl(glslCaps, &fshaderTxt);
- fshaderTxt.append(";");
- fsOutName = oFragColor.c_str();
- } else {
- fsOutName = "gl_FragColor";
- }
fshaderTxt.appendf(
"// Copy Program FS\n"
"void main() {"
- " %s = %s(u_texture, v_texCoord);"
+ " sk_FragColor = %s(u_texture, v_texCoord);"
"}",
- fsOutName,
GrGLSLTexture2DFunctionName(kVec2f_GrSLType, kSamplerTypes[progIdx], this->glslGeneration())
);
@@ -3936,14 +3927,6 @@
}
uTexture.appendDecl(glslCaps, &fshaderTxt);
fshaderTxt.append(";");
- const char* fsOutName;
- if (glslCaps->mustDeclareFragmentShaderOutput()) {
- oFragColor.appendDecl(glslCaps, &fshaderTxt);
- fshaderTxt.append(";");
- fsOutName = oFragColor.c_str();
- } else {
- fsOutName = "gl_FragColor";
- }
const char* sampleFunction = GrGLSLTexture2DFunctionName(kVec2f_GrSLType,
kTexture2DSampler_GrSLType,
this->glslGeneration());
@@ -3954,19 +3937,19 @@
if (oddWidth && oddHeight) {
fshaderTxt.appendf(
- " %s = (%s(u_texture, v_texCoord0) + %s(u_texture, v_texCoord1) + "
- " %s(u_texture, v_texCoord2) + %s(u_texture, v_texCoord3)) * 0.25;",
- fsOutName, sampleFunction, sampleFunction, sampleFunction, sampleFunction
+ " sk_FragColor = (%s(u_texture, v_texCoord0) + %s(u_texture, v_texCoord1) + "
+ " %s(u_texture, v_texCoord2) + %s(u_texture, v_texCoord3)) * 0.25;",
+ sampleFunction, sampleFunction, sampleFunction, sampleFunction
);
} else if (oddWidth || oddHeight) {
fshaderTxt.appendf(
- " %s = (%s(u_texture, v_texCoord0) + %s(u_texture, v_texCoord1)) * 0.5;",
- fsOutName, sampleFunction, sampleFunction
+ " sk_FragColor = (%s(u_texture, v_texCoord0) + %s(u_texture, v_texCoord1)) * 0.5;",
+ sampleFunction, sampleFunction
);
} else {
fshaderTxt.appendf(
- " %s = %s(u_texture, v_texCoord0);",
- fsOutName, sampleFunction
+ " sk_FragColor = %s(u_texture, v_texCoord0);",
+ sampleFunction
);
}
@@ -4053,20 +4036,11 @@
&fshaderTxt);
uColor.appendDecl(this->glCaps().glslCaps(), &fshaderTxt);
fshaderTxt.append(";");
- const char* fsOutName;
- if (this->glCaps().glslCaps()->mustDeclareFragmentShaderOutput()) {
- oFragColor.appendDecl(this->glCaps().glslCaps(), &fshaderTxt);
- fshaderTxt.append(";");
- fsOutName = oFragColor.c_str();
- } else {
- fsOutName = "gl_FragColor";
- }
fshaderTxt.appendf(
"// Write Rect Program FS\n"
"void main() {"
- " %s = %s;"
+ " sk_FragColor = %s;"
"}",
- fsOutName,
uColor.c_str()
);
diff --git a/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp b/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
index d2e49a5..04d90ee 100644
--- a/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
@@ -9,6 +9,8 @@
#include "gl/GrGLGpu.h"
#include "gl/GrGLSLPrettyPrint.h"
#include "SkTraceEvent.h"
+#include "SkSLCompiler.h"
+#include "ir/SkSLProgram.h"
#define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X)
@@ -18,6 +20,90 @@
static void print_shader_source(const char** strings, int* lengths, int count);
+static SkSL::GLCaps skslcaps_for_context(const GrGLContext& context) {
+ GrGLStandard standard = context.standard();
+ const GrGLCaps* caps = context.caps();
+ const GrGLSLCaps* glslCaps = caps->glslCaps();
+ SkSL::GLCaps result;
+ switch (standard) {
+ case kGL_GrGLStandard:
+ result.fStandard = SkSL::GLCaps::kGL_Standard;
+ break;
+ case kGLES_GrGLStandard:
+ result.fStandard = SkSL::GLCaps::kGLES_Standard;
+ break;
+ default:
+ SkASSERT(false);
+ result.fStandard = SkSL::GLCaps::kGL_Standard;
+ }
+
+ switch (glslCaps->generation()) {
+ case k110_GrGLSLGeneration:
+ if (kGLES_GrGLStandard == standard) {
+ // ES2's shader language is based on GLSL 1.20 but is version 1.00 of the ES
+ // language
+ result.fVersion = 100;
+ } else {
+ SkASSERT(kGL_GrGLStandard == standard);
+ result.fVersion = 110;
+ }
+ break;
+ case k130_GrGLSLGeneration:
+ SkASSERT(kGL_GrGLStandard == standard);
+ result.fVersion = 130;
+ break;
+ case k140_GrGLSLGeneration:
+ SkASSERT(kGL_GrGLStandard == standard);
+ result.fVersion = 140;
+ break;
+ case k150_GrGLSLGeneration:
+ SkASSERT(kGL_GrGLStandard == standard);
+ result.fVersion = 150;
+ break;
+ case k330_GrGLSLGeneration:
+ if (kGLES_GrGLStandard == standard) {
+ result.fVersion = 300;
+ } else {
+ SkASSERT(kGL_GrGLStandard == standard);
+ result.fVersion = 330;
+ }
+ break;
+ case k400_GrGLSLGeneration:
+ SkASSERT(kGL_GrGLStandard == standard);
+ result.fVersion = 400;
+ break;
+ case k310es_GrGLSLGeneration:
+ SkASSERT(kGLES_GrGLStandard == standard);
+ result.fVersion = 310;
+ break;
+ case k320es_GrGLSLGeneration:
+ SkASSERT(kGLES_GrGLStandard == standard);
+ result.fVersion = 320;
+ break;
+ }
+ result.fIsCoreProfile = caps->isCoreProfile();
+ result.fUsesPrecisionModifiers = glslCaps->usesPrecisionModifiers();
+ result.fMustDeclareFragmentShaderOutput = glslCaps->mustDeclareFragmentShaderOutput();
+ result.fCanUseMinAndAbsTogether = glslCaps->canUseMinAndAbsTogether();
+ return result;
+}
+
+static void dump_string(std::string s) {
+ // on Android, SkDebugf only displays the first 1K characters of output, which results in
+ // incomplete shader source code. Print each line individually to avoid this problem.
+ size_t index = 0;
+ for (;;) {
+ size_t next = s.find("\n", index);
+ if (next == std::string::npos) {
+ SkDebugf("%s", s.substr(index).c_str());
+ break;
+ } else {
+ SkDebugf("%s", s.substr(index, next - index + 1).c_str());
+ index = next + 1;
+ }
+ }
+}
+
GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx,
GrGLuint programId,
GrGLenum type,
@@ -33,15 +119,39 @@
return 0;
}
+ std::string sksl;
#ifdef SK_DEBUG
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));
+ sksl = std::string(prettySource.c_str());
#else
- GR_GL_CALL(gli, ShaderSource(shaderId, count, strings, lengths));
+ for (int i = 0; i < count; i++) {
+ sksl.append(strings[i], lengths[i]);
+ }
#endif
+ std::string glsl;
+ SkSL::Compiler& compiler = *glCtx.compiler();
+ SkSL::GLCaps caps = skslcaps_for_context(glCtx);
+ SkASSERT(type == GR_GL_VERTEX_SHADER || type == GR_GL_FRAGMENT_SHADER);
+ SkDEBUGCODE(bool result = )compiler.toGLSL(type == GR_GL_VERTEX_SHADER
+ ? SkSL::Program::kVertex_Kind
+ : SkSL::Program::kFragment_Kind,
+ std::string(sksl.c_str()),
+ caps,
+ &glsl);
+#ifdef SK_DEBUG
+ if (!result) {
+ SkDebugf("SKSL compilation error\n----------------------\n");
+ SkDebugf("SKSL:\n");
+ dump_string(sksl);
+ SkDebugf("\nErrors:\n%s\n", compiler.errorText().c_str());
+ SkDEBUGFAIL("SKSL compilation failed!\n");
+ }
+#endif
+ const char* glslChars = glsl.c_str();
+ GrGLint glslLength = (GrGLint) glsl.length();
+ GR_GL_CALL(gli, ShaderSource(shaderId, 1, &glslChars, &glslLength));
+
// If tracing is enabled in chrome then we pretty print
bool traceShader;
TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), &traceShader);
@@ -72,10 +182,14 @@
// buffer param validation.
GrGLsizei length = GR_GL_INIT_ZERO;
GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, &length, (char*)log.get()));
- print_shader_source(strings, lengths, count);
- SkDebugf("\n%s", (const char*)log.get());
+ SkDebugf("GLSL compilation error\n----------------------\n");
+ SkDebugf("SKSL:\n");
+ dump_string(sksl);
+ SkDebugf("GLSL:\n");
+ dump_string(glsl);
+ SkDebugf("Errors:\n%s\n", (const char*) log.get());
}
- SkDEBUGFAIL("Shader compilation failed!");
+ SkDEBUGFAIL("GLSL compilation failed!");
GR_GL_CALL(gli, DeleteShader(shaderId));
return 0;
}
diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
index d35730f..eb744a9 100644
--- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
@@ -291,10 +291,10 @@
if (!fHasCustomColorOutput) {
fHasCustomColorOutput = true;
fCustomColorOutputIndex = fOutputs.count();
- fOutputs.push_back().set(kVec4f_GrSLType,
- GrGLSLShaderVar::kOut_TypeModifier,
- DeclaredColorOutputName());
- fProgramBuilder->finalizeFragmentOutputColor(fOutputs.back());
+ fOutputs.push_back().set(kVec4f_GrSLType,
+ GrGLSLShaderVar::kOut_TypeModifier,
+ DeclaredColorOutputName());
+ fProgramBuilder->finalizeFragmentOutputColor(fOutputs.back());
}
}
@@ -318,7 +318,7 @@
}
const char* GrGLSLFragmentShaderBuilder::getPrimaryColorOutputName() const {
- return fHasCustomColorOutput ? DeclaredColorOutputName() : "gl_FragColor";
+ return fHasCustomColorOutput ? DeclaredColorOutputName() : "sk_FragColor";
}
void GrGLSLFragmentBuilder::declAppendf(const char* fmt, ...) {
diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
index ecb6d45..6a4a184 100644
--- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
+++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
@@ -203,7 +203,7 @@
}
#endif
- static const char* DeclaredColorOutputName() { return "fsColorOut"; }
+ static const char* DeclaredColorOutputName() { return "sk_FragColor"; }
static const char* DeclaredSecondaryColorOutputName() { return "fsSecondaryColorOut"; }
GrSurfaceOrigin getSurfaceOrigin() const;
diff --git a/src/gpu/glsl/GrGLSLShaderBuilder.h b/src/gpu/glsl/GrGLSLShaderBuilder.h
index a6ff96d..f59edb4 100644
--- a/src/gpu/glsl/GrGLSLShaderBuilder.h
+++ b/src/gpu/glsl/GrGLSLShaderBuilder.h
@@ -72,23 +72,27 @@
void appendTexelFetch(SamplerHandle, const char* coordExpr);
/**
- * Adds a #define directive to the top of the shader.
+ * Adds a constant declaration to the top of the shader.
*/
- void define(const char* macro, const char* replacement) {
- this->definitions().appendf("#define %s %s\n", macro, replacement);
+ void defineConstant(const char* type, const char* name, const char* value) {
+ this->definitions().appendf("const %s %s = %s;\n", type, name, value);
}
- void define(const char* macro, int replacement) {
- this->definitions().appendf("#define %s %i\n", macro, replacement);
+ void defineConstant(const char* name, int value) {
+ this->definitions().appendf("const int %s = %i;\n", name, value);
}
- void definef(const char* macro, const char* replacement, ...) {
- this->definitions().appendf("#define %s ", macro);
+ void defineConstant(const char* name, float value) {
+ this->definitions().appendf("const float %s = %f;\n", name, value);
+ }
+
+ void defineConstantf(const char* type, const char* name, const char* fmt, ...) {
+ this->definitions().appendf("const %s %s = ", type, name);
va_list args;
- va_start(args, replacement);
- this->definitions().appendVAList(replacement, args);
+ va_start(args, fmt);
+ this->definitions().appendVAList(fmt, args);
va_end(args);
- this->definitions().append("\n");
+ this->definitions().append(";\n");
}
/**
diff --git a/src/gpu/glsl/GrGLSLShaderVar.h b/src/gpu/glsl/GrGLSLShaderVar.h
index 9d162ec..35ac4bc 100644
--- a/src/gpu/glsl/GrGLSLShaderVar.h
+++ b/src/gpu/glsl/GrGLSLShaderVar.h
@@ -213,24 +213,20 @@
private:
static const char* TypeModifierString(const GrGLSLCaps* glslCaps, TypeModifier t) {
- GrGLSLGeneration gen = glslCaps->generation();
switch (t) {
case kNone_TypeModifier:
return "";
+ case kAttribute_TypeModifier: // fall through
+ case kVaryingIn_TypeModifier: // fall through
case kIn_TypeModifier:
return "in";
case kInOut_TypeModifier:
return "inout";
+ case kVaryingOut_TypeModifier: // fall through
case kOut_TypeModifier:
return "out";
case kUniform_TypeModifier:
return "uniform";
- case kAttribute_TypeModifier:
- return k110_GrGLSLGeneration == gen ? "attribute" : "in";
- case kVaryingIn_TypeModifier:
- return k110_GrGLSLGeneration == gen ? "varying" : "in";
- case kVaryingOut_TypeModifier:
- return k110_GrGLSLGeneration == gen ? "varying" : "out";
default:
SkFAIL("Unknown shader variable type modifier.");
return ""; // suppress warning
diff --git a/src/gpu/instanced/InstanceProcessor.cpp b/src/gpu/instanced/InstanceProcessor.cpp
index 480155b..82116c4 100644
--- a/src/gpu/instanced/InstanceProcessor.cpp
+++ b/src/gpu/instanced/InstanceProcessor.cpp
@@ -107,10 +107,10 @@
void initParams(const SamplerHandle paramsBuffer) {
fParamsBuffer = paramsBuffer;
- fVertexBuilder->definef("PARAMS_IDX_MASK", "0x%xu", kParamsIdx_InfoMask);
fVertexBuilder->appendPrecisionModifier(kHigh_GrSLPrecision);
- fVertexBuilder->codeAppendf("int paramsIdx = int(%s & PARAMS_IDX_MASK);",
- this->attr(Attrib::kInstanceInfo));
+ fVertexBuilder->codeAppendf("int paramsIdx = int(%s & 0x%x);",
+ this->attr(Attrib::kInstanceInfo),
+ kParamsIdx_InfoMask);
}
const char* attr(Attrib attr) const { return fInstProc.getAttrib((int)attr).fName; }
@@ -224,10 +224,10 @@
v->codeAppendf("mat2x3 shapeMatrix = mat2x3(%s, %s);",
inputs.attr(Attrib::kShapeMatrixX), inputs.attr(Attrib::kShapeMatrixY));
} else {
- v->definef("PERSPECTIVE_FLAG", "0x%xu", kPerspective_InfoFlag);
+ v->defineConstantf("int", "PERSPECTIVE_FLAG", "0x%x", kPerspective_InfoFlag);
v->codeAppendf("mat3 shapeMatrix = mat3(%s, %s, vec3(0, 0, 1));",
inputs.attr(Attrib::kShapeMatrixX), inputs.attr(Attrib::kShapeMatrixY));
- v->codeAppendf("if (0u != (%s & PERSPECTIVE_FLAG)) {",
+ v->codeAppendf("if (0 != (%s & PERSPECTIVE_FLAG)) {",
inputs.attr(Attrib::kInstanceInfo));
v->codeAppend ( "shapeMatrix[2] = ");
inputs.fetchNextParam(kVec3f_GrSLType);
@@ -237,7 +237,7 @@
bool hasSingleShapeType = SkIsPow2(ip.batchInfo().fShapeTypes);
if (!hasSingleShapeType) {
- v->define("SHAPE_TYPE_BIT", kShapeType_InfoBit);
+ v->defineConstant("SHAPE_TYPE_BIT", kShapeType_InfoBit);
v->codeAppendf("uint shapeType = %s >> SHAPE_TYPE_BIT;",
inputs.attr(Attrib::kInstanceInfo));
}
@@ -285,8 +285,8 @@
if (ip.batchInfo().fInnerShapeTypes) {
bool hasSingleInnerShapeType = SkIsPow2(ip.batchInfo().fInnerShapeTypes);
if (!hasSingleInnerShapeType) {
- v->definef("INNER_SHAPE_TYPE_MASK", "0x%xu", kInnerShapeType_InfoMask);
- v->define("INNER_SHAPE_TYPE_BIT", kInnerShapeType_InfoBit);
+ v->defineConstantf("int", "INNER_SHAPE_TYPE_MASK", "0x%x", kInnerShapeType_InfoMask);
+ v->defineConstant("INNER_SHAPE_TYPE_BIT", kInnerShapeType_InfoBit);
v->codeAppendf("uint innerShapeType = ((%s & INNER_SHAPE_TYPE_MASK) >> "
"INNER_SHAPE_TYPE_BIT);",
inputs.attr(Attrib::kInstanceInfo));
@@ -346,13 +346,13 @@
}
if (usedShapeDefinitions & kOval_ShapeFlag) {
- v->definef("OVAL_SHAPE_TYPE", "%du", (int)ShapeType::kOval);
+ v->defineConstant("OVAL_SHAPE_TYPE", (int)ShapeType::kOval);
}
if (usedShapeDefinitions & kSimpleRRect_ShapeFlag) {
- v->definef("SIMPLE_R_RECT_SHAPE_TYPE", "%du", (int)ShapeType::kSimpleRRect);
+ v->defineConstant("SIMPLE_R_RECT_SHAPE_TYPE", (int)ShapeType::kSimpleRRect);
}
if (usedShapeDefinitions & kNinePatch_ShapeFlag) {
- v->definef("NINE_PATCH_SHAPE_TYPE", "%du", (int)ShapeType::kNinePatch);
+ v->defineConstant("NINE_PATCH_SHAPE_TYPE", (int)ShapeType::kNinePatch);
}
SkASSERT(!(usedShapeDefinitions & (kRect_ShapeFlag | kComplexRRect_ShapeFlag)));
@@ -367,8 +367,8 @@
inputs.attr(Attrib::kLocalRect), inputs.attr(Attrib::kLocalRect));
}
if (ip.batchInfo().fHasLocalMatrix && ip.batchInfo().fHasParams) {
- v->definef("LOCAL_MATRIX_FLAG", "0x%xu", kLocalMatrix_InfoFlag);
- v->codeAppendf("if (0u != (%s & LOCAL_MATRIX_FLAG)) {",
+ v->defineConstantf("int", "LOCAL_MATRIX_FLAG", "0x%x", kLocalMatrix_InfoFlag);
+ v->codeAppendf("if (0 != (%s & LOCAL_MATRIX_FLAG)) {",
inputs.attr(Attrib::kInstanceInfo));
if (!ip.batchInfo().fUsesLocalCoords) {
inputs.skipParams(2);
@@ -1179,7 +1179,7 @@
}
}
if (kRect_ShapeFlag != fBatchInfo.fShapeTypes) {
- v->definef("SAMPLE_MASK_ALL", "0x%x", (1 << fEffectiveSampleCnt) - 1);
+ v->defineConstantf("int", "SAMPLE_MASK_ALL", "0x%x", (1 << fEffectiveSampleCnt) - 1);
varyingHandler->addFlatVarying("earlyAccept", &fEarlyAccept, kHigh_GrSLPrecision);
}
}
@@ -1360,10 +1360,10 @@
void GLSLInstanceProcessor::BackendMultisample::onEmitCode(GrGLSLVertexBuilder*,
GrGLSLPPFragmentBuilder* f,
const char*, const char*) {
- f->define("SAMPLE_COUNT", fEffectiveSampleCnt);
+ f->defineConstant("SAMPLE_COUNT", fEffectiveSampleCnt);
if (this->isMixedSampled()) {
- f->definef("SAMPLE_MASK_ALL", "0x%x", (1 << fEffectiveSampleCnt) - 1);
- f->definef("SAMPLE_MASK_MSB", "0x%x", 1 << (fEffectiveSampleCnt - 1));
+ f->defineConstantf("int", "SAMPLE_MASK_ALL", "0x%x", (1 << fEffectiveSampleCnt) - 1);
+ f->defineConstantf("int", "SAMPLE_MASK_MSB", "0x%x", 1 << (fEffectiveSampleCnt - 1));
}
if (kRect_ShapeFlag != (fBatchInfo.fShapeTypes | fBatchInfo.fInnerShapeTypes)) {
diff --git a/src/sksl/README b/src/sksl/README
new file mode 100644
index 0000000..1427c21
--- /dev/null
+++ b/src/sksl/README
@@ -0,0 +1,35 @@
+Overview
+========
+
+SkSL ("Skia Shading Language") is a variant of GLSL which is used as Skia's
+internal shading language. SkSL is, at its heart, a single standardized version
+of GLSL which avoids all of the various version and dialect differences found
+in GLSL "in the wild", but it does bring a few of its own changes to the table.
+
+Skia uses the SkSL compiler to convert SkSL code to GLSL, GLSL ES, or SPIR-V
+before handing it over to the graphics driver.
+
+Differences from GLSL
+=====================
+
+SkSL is based on GLSL 4.5. For the most part, write SkSL exactly as you would
+desktop GLSL, and the SkSL compiler will take care of version and dialect
+differences (for instance, you always use "in" and "out", and skslc will handle
+translating them to "varying" and "attribute" as appropriate). Be aware of the
+following differences between SkSL and GLSL:
+
+* no #version or "precision" statement is required, and they will be ignored if
+ present
+* the output color is sk_FragColor (do not declare it)
+* lowp, mediump, and highp are always permitted (but will only be respected if
+ you run on a GLES device)
+* you do not need to include ".0" to make a number a float (meaning that
+ "vec2(x, y) * 4" is perfectly legal in SkSL, unlike GLSL where it would often
+ have to be expressed "vec2(x, y) * 4.0". There is no performance penalty for
+ this, as the number is converted to a float at compile time)
+* type suffixes on numbers (1.0f, 0xFFu) are both unnecessary and unsupported
+* some built-in functions and one or two rarely-used language features are not
+ yet supported (sorry!)
+
+SkSL is still under development, and is expected to diverge further from GLSL
+over time.
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index d2ad812..b57e673 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -15,6 +15,7 @@
#include "SkSLSPIRVCodeGenerator.h"
#include "ir/SkSLExpression.h"
#include "ir/SkSLIntLiteral.h"
+#include "ir/SkSLModifiersDeclaration.h"
#include "ir/SkSLSymbolTable.h"
#include "ir/SkSLVarDeclaration.h"
#include "SkMutex.h"
@@ -97,6 +98,7 @@
ADD_TYPE(Sampler1D);
ADD_TYPE(Sampler2D);
ADD_TYPE(Sampler3D);
+ ADD_TYPE(SamplerExternalOES);
ADD_TYPE(SamplerCube);
ADD_TYPE(Sampler2DRect);
ADD_TYPE(Sampler1DArray);
@@ -130,6 +132,7 @@
std::vector<std::unique_ptr<ProgramElement>> ignored;
this->internalConvertProgram(SKSL_INCLUDE, &ignored);
+ printf("%s", errorText().c_str());
ASSERT(!fErrorCount);
}
@@ -164,6 +167,14 @@
}
break;
}
+ case ASTDeclaration::kModifiers_Kind: {
+ std::unique_ptr<ModifiersDeclaration> f = fIRGenerator->convertModifiersDeclaration(
+ (ASTModifiersDeclaration&) decl);
+ if (f) {
+ result->push_back(std::move(f));
+ }
+ break;
+ }
case ASTDeclaration::kInterfaceBlock_Kind: {
std::unique_ptr<InterfaceBlock> i = fIRGenerator->convertInterfaceBlock(
(ASTInterfaceBlock&) decl);
diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h
index 9cd1eac..7c8cf81 100644
--- a/src/sksl/SkSLCompiler.h
+++ b/src/sksl/SkSLCompiler.h
@@ -15,6 +15,8 @@
#include "SkSLErrorReporter.h"
#include "SkSLGLSLCodeGenerator.h"
+#define SK_FRAGCOLOR_BUILTIN 10001
+
namespace SkSL {
class IRGenerator;
@@ -24,6 +26,8 @@
* file into an abstract syntax tree (a tree of ASTNodes), then performs semantic analysis to
* produce a Program (a tree of IRNodes), then feeds the Program into a CodeGenerator to produce
* compiled output.
+ *
+ * See the README for information about SkSL.
*/
class Compiler : public ErrorReporter {
public:
diff --git a/src/sksl/SkSLContext.h b/src/sksl/SkSLContext.h
index 1f124d0..82c265b 100644
--- a/src/sksl/SkSLContext.h
+++ b/src/sksl/SkSLContext.h
@@ -60,6 +60,7 @@
, fSampler1D_Type(new Type("sampler1D", SpvDim1D, false, false, false, true))
, fSampler2D_Type(new Type("sampler2D", SpvDim2D, false, false, false, true))
, fSampler3D_Type(new Type("sampler3D", SpvDim3D, false, false, false, true))
+ , fSamplerExternalOES_Type(new Type("samplerExternalOES", SpvDim2D, false, false, false, true))
, fSamplerCube_Type(new Type("samplerCube"))
, fSampler2DRect_Type(new Type("sampler2DRect"))
, fSampler1DArray_Type(new Type("sampler1DArray"))
@@ -169,6 +170,7 @@
const std::unique_ptr<Type> fSampler1D_Type;
const std::unique_ptr<Type> fSampler2D_Type;
const std::unique_ptr<Type> fSampler3D_Type;
+ const std::unique_ptr<Type> fSamplerExternalOES_Type;
const std::unique_ptr<Type> fSamplerCube_Type;
const std::unique_ptr<Type> fSampler2DRect_Type;
const std::unique_ptr<Type> fSampler1DArray_Type;
diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp
index da0bcb9..6a82cf2 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.cpp
+++ b/src/sksl/SkSLGLSLCodeGenerator.cpp
@@ -14,8 +14,11 @@
#include "ir/SkSLExpressionStatement.h"
#include "ir/SkSLExtension.h"
#include "ir/SkSLIndexExpression.h"
+#include "ir/SkSLModifiersDeclaration.h"
#include "ir/SkSLVariableReference.h"
+#define SK_FRAGCOLOR_BUILTIN 10001
+
namespace SkSL {
void GLSLCodeGenerator::write(const char* s) {
@@ -66,7 +69,7 @@
this->writeLine("struct " + type.name() + " {");
fIndentation++;
for (const auto& f : type.fields()) {
- this->writeModifiers(f.fModifiers);
+ this->writeModifiers(f.fModifiers, false);
// sizes (which must be static in structs) are part of the type name here
this->writeType(*f.fType);
this->writeLine(" " + f.fName + ";");
@@ -124,7 +127,40 @@
}
}
+static bool is_abs(Expression& expr) {
+ if (expr.fKind != Expression::kFunctionCall_Kind) {
+ return false;
+ }
+ return ((FunctionCall&) expr).fFunction.fName == "abs";
+}
+
+// turns min(abs(x), y) into (abs(x) > (tmpVar = y) ? tmpVar : abs(x)) to avoid a Tegra3 compiler
+// bug.
+void GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherExpr) {
+ ASSERT(!fCaps.fCanUseMinAndAbsTogether);
+ std::string varName = "minAbsHackVar" + to_string(fVarCount++);
+ this->fFunctionHeader += " " + otherExpr.fType.name() + " " + varName + ";\n";
+ this->write("(");
+ this->writeExpression(absExpr, kTopLevel_Precedence);
+ this->write(" > (" + varName + " = ");
+ this->writeExpression(otherExpr, kRelational_Precedence);
+ this->write(") ? " + varName + " : ");
+ this->writeExpression(absExpr, kTernary_Precedence);
+ this->write(")");
+}
+
void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
+ if (!fCaps.fCanUseMinAndAbsTogether && c.fFunction.fName == "min") {
+ ASSERT(c.fArguments.size() == 2);
+ if (is_abs(*c.fArguments[0])) {
+ this->writeMinAbsHack(*c.fArguments[0], *c.fArguments[1]);
+ return;
+ }
+ if (is_abs(*c.fArguments[1])) {
+ this->writeMinAbsHack(*c.fArguments[1], *c.fArguments[0]);
+ return;
+ }
+ }
this->write(c.fFunction.fName + "(");
const char* separator = "";
for (const auto& arg : c.fArguments) {
@@ -147,7 +183,15 @@
}
void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) {
- this->write(ref.fVariable.fName);
+ if (ref.fVariable.fModifiers.fLayout.fBuiltin == SK_FRAGCOLOR_BUILTIN) {
+ if (fCaps.fMustDeclareFragmentShaderOutput) {
+ this->write("sk_FragColor");
+ } else {
+ this->write("gl_FragColor");
+ }
+ } else {
+ this->write(ref.fVariable.fName);
+ }
}
void GLSLCodeGenerator::writeIndexExpression(const IndexExpression& expr) {
@@ -270,7 +314,11 @@
}
void GLSLCodeGenerator::writeIntLiteral(const IntLiteral& i) {
- this->write(to_string(i.fValue));
+ if (i.fType == *fContext.fUInt_Type) {
+ this->write(to_string(i.fValue & 0xffffffff) + "u");
+ } else {
+ this->write(to_string(i.fValue));
+ }
}
void GLSLCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
@@ -284,28 +332,96 @@
for (const auto& param : f.fDeclaration.fParameters) {
this->write(separator);
separator = ", ";
- this->writeModifiers(param->fModifiers);
- this->writeType(param->fType);
+ this->writeModifiers(param->fModifiers, false);
+ std::vector<int> sizes;
+ const Type* type = ¶m->fType;
+ while (type->kind() == Type::kArray_Kind) {
+ sizes.push_back(type->columns());
+ type = &type->componentType();
+ }
+ this->writeType(*type);
this->write(" " + param->fName);
+ for (int s : sizes) {
+ if (s <= 0) {
+ this->write("[]");
+ } else {
+ this->write("[" + to_string(s) + "]");
+ }
+ }
}
- this->write(") ");
- this->writeBlock(*f.fBody);
- this->writeLine();
+ this->writeLine(") {");
+
+ fFunctionHeader = "";
+ std::ostream* oldOut = fOut;
+ std::stringstream buffer;
+ fOut = &buffer;
+ fIndentation++;
+ for (const auto& s : f.fBody->fStatements) {
+ this->writeStatement(*s);
+ this->writeLine();
+ }
+ fIndentation--;
+ this->writeLine("}");
+
+ fOut = oldOut;
+ this->write(fFunctionHeader);
+ this->write(buffer.str());
}
-void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers) {
- this->write(modifiers.description());
+void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers,
+ bool globalContext) {
+ if (modifiers.fFlags & Modifiers::kNoPerspective_Flag) {
+ this->write("noperspective ");
+ }
+ if (modifiers.fFlags & Modifiers::kFlat_Flag) {
+ this->write("flat ");
+ }
+ std::string layout = modifiers.fLayout.description();
+ if (layout.length()) {
+ this->write(layout + " ");
+ }
+ if ((modifiers.fFlags & Modifiers::kIn_Flag) &&
+ (modifiers.fFlags & Modifiers::kOut_Flag)) {
+ this->write("inout ");
+ } else if (modifiers.fFlags & Modifiers::kIn_Flag) {
+ if (globalContext && fCaps.fVersion < 130) {
+ this->write(fProgramKind == Program::kVertex_Kind ? "attribute "
+ : "varying ");
+ } else {
+ this->write("in ");
+ }
+ } else if (modifiers.fFlags & Modifiers::kOut_Flag) {
+ if (globalContext && fCaps.fVersion < 130) {
+ this->write("varying ");
+ } else {
+ this->write("out ");
+ }
+ }
+ if (modifiers.fFlags & Modifiers::kUniform_Flag) {
+ this->write("uniform ");
+ }
+ if (modifiers.fFlags & Modifiers::kConst_Flag) {
+ this->write("const ");
+ }
+ if (fCaps.fUsesPrecisionModifiers) {
+ if (modifiers.fFlags & Modifiers::kLowp_Flag) {
+ this->write("lowp ");
+ }
+ if (modifiers.fFlags & Modifiers::kHighp_Flag) {
+ this->write("highp ");
+ }
+ }
}
void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
if (intf.fVariable.fName == "gl_PerVertex") {
return;
}
- this->writeModifiers(intf.fVariable.fModifiers);
+ this->writeModifiers(intf.fVariable.fModifiers, true);
this->writeLine(intf.fVariable.fType.name() + " {");
fIndentation++;
for (const auto& f : intf.fVariable.fType.fields()) {
- this->writeModifiers(f.fModifiers);
+ this->writeModifiers(f.fModifiers, false);
this->writeType(*f.fType);
this->writeLine(" " + f.fName + ";");
}
@@ -313,9 +429,9 @@
this->writeLine("};");
}
-void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl) {
+void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool global) {
ASSERT(decl.fVars.size() > 0);
- this->writeModifiers(decl.fVars[0].fVar->fModifiers);
+ this->writeModifiers(decl.fVars[0].fVar->fModifiers, global);
this->writeType(decl.fBaseType);
std::string separator = " ";
for (const auto& var : decl.fVars) {
@@ -325,7 +441,9 @@
this->write(var.fVar->fName);
for (const auto& size : var.fSizes) {
this->write("[");
- this->writeExpression(*size, kTopLevel_Precedence);
+ if (size) {
+ this->writeExpression(*size, kTopLevel_Precedence);
+ }
this->write("]");
}
if (var.fValue) {
@@ -349,7 +467,7 @@
this->writeReturnStatement((ReturnStatement&) s);
break;
case Statement::kVarDeclarations_Kind:
- this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
+ this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration, false);
break;
case Statement::kIf_Kind:
this->writeIfStatement((IfStatement&) s);
@@ -444,22 +562,42 @@
void GLSLCodeGenerator::generateCode(const Program& program, std::ostream& out) {
ASSERT(fOut == nullptr);
fOut = &out;
+ fProgramKind = program.fKind;
this->write("#version " + to_string(fCaps.fVersion));
- if (fCaps.fStandard == GLCaps::kGLES_Standard) {
+ if (fCaps.fStandard == GLCaps::kGLES_Standard && fCaps.fVersion >= 300) {
this->write(" es");
+ } else if (fCaps.fIsCoreProfile) {
+ this->write(" core");
}
this->writeLine();
for (const auto& e : program.fElements) {
+ if (e->fKind == ProgramElement::kExtension_Kind) {
+ this->writeExtension((Extension&) *e);
+ }
+ }
+ if (fCaps.fStandard == GLCaps::kGLES_Standard) {
+ this->writeLine("precision mediump float;");
+ }
+ for (const auto& e : program.fElements) {
switch (e->fKind) {
case ProgramElement::kExtension_Kind:
- this->writeExtension((Extension&) *e);
break;
case ProgramElement::kVar_Kind: {
VarDeclarations& decl = (VarDeclarations&) *e;
- if (decl.fVars.size() > 0 &&
- decl.fVars[0].fVar->fModifiers.fLayout.fBuiltin == -1) {
- this->writeVarDeclarations(decl);
- this->writeLine();
+ if (decl.fVars.size() > 0) {
+ int builtin = decl.fVars[0].fVar->fModifiers.fLayout.fBuiltin;
+ if (builtin == -1) {
+ // normal var
+ this->writeVarDeclarations(decl, true);
+ this->writeLine();
+ } else if (builtin == SK_FRAGCOLOR_BUILTIN &&
+ fCaps.fMustDeclareFragmentShaderOutput) {
+ this->write("out ");
+ if (fCaps.fUsesPrecisionModifiers) {
+ this->write("mediump ");
+ }
+ this->writeLine("vec4 sk_FragColor;");
+ }
}
break;
}
@@ -469,6 +607,10 @@
case ProgramElement::kFunction_Kind:
this->writeFunction((FunctionDefinition&) *e);
break;
+ case ProgramElement::kModifiers_Kind:
+ this->writeModifiers(((ModifiersDeclaration&) *e).fModifiers, true);
+ this->writeLine(";");
+ break;
default:
printf("%s\n", e->description().c_str());
ABORT("unsupported program element");
diff --git a/src/sksl/SkSLGLSLCodeGenerator.h b/src/sksl/SkSLGLSLCodeGenerator.h
index 3534aff..9851123 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.h
+++ b/src/sksl/SkSLGLSLCodeGenerator.h
@@ -50,6 +50,11 @@
kGL_Standard,
kGLES_Standard
} fStandard;
+ bool fIsCoreProfile;
+ bool fUsesPrecisionModifiers;
+ bool fMustDeclareFragmentShaderOutput;
+ // The Tegra3 compiler will sometimes never return if we have min(abs(x), y)
+ bool fCanUseMinAndAbsTogether;
};
/**
@@ -81,6 +86,8 @@
GLSLCodeGenerator(const Context* context, GLCaps caps)
: fContext(*context)
, fCaps(caps)
+ , fOut(nullptr)
+ , fVarCount(0)
, fIndentation(0)
, fAtLineStart(true) {}
@@ -111,11 +118,11 @@
void writeLayout(const Layout& layout);
- void writeModifiers(const Modifiers& modifiers);
+ void writeModifiers(const Modifiers& modifiers, bool globalContext);
void writeGlobalVars(const VarDeclaration& vs);
- void writeVarDeclarations(const VarDeclarations& decl);
+ void writeVarDeclarations(const VarDeclarations& decl, bool global);
void writeVariableReference(const VariableReference& ref);
@@ -123,6 +130,8 @@
void writeIntrinsicCall(const FunctionCall& c);
+ void writeMinAbsHack(Expression& absExpr, Expression& otherExpr);
+
void writeFunctionCall(const FunctionCall& c);
void writeConstructor(const Constructor& c);
@@ -164,6 +173,9 @@
const Context& fContext;
const GLCaps fCaps;
std::ostream* fOut;
+ std::string fFunctionHeader;
+ Program::Kind fProgramKind;
+ int fVarCount;
int fIndentation;
bool fAtLineStart;
// Keeps track of which struct types we have written. Given that we are unlikely to ever write
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index c30cac1..64cc2df 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -189,10 +189,16 @@
}
value = this->coerce(std::move(value), *type);
}
- if ("gl_FragCoord" == varDecl.fName && (*fSymbolTable)[varDecl.fName]) {
+ if ("sk_FragColor" == varDecl.fName && (*fSymbolTable)[varDecl.fName]) {
+ // already defined, ignore
+ } else if ((*fSymbolTable)[varDecl.fName] &&
+ (*fSymbolTable)[varDecl.fName]->fKind == Symbol::kVariable_Kind &&
+ ((Variable*) (*fSymbolTable)[varDecl.fName])->fModifiers.fLayout.fBuiltin >= 0) {
// already defined, just update the modifiers
Variable* old = (Variable*) (*fSymbolTable)[varDecl.fName];
+ int builtin = old->fModifiers.fLayout.fBuiltin;
old->fModifiers = var->fModifiers;
+ old->fModifiers.fLayout.fBuiltin = builtin;
} else {
variables.emplace_back(var.get(), std::move(sizes), std::move(value));
fSymbolTable->add(varDecl.fName, std::move(var));
@@ -203,6 +209,12 @@
std::move(variables)));
}
+std::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration(
+ const ASTModifiersDeclaration& m) {
+ Modifiers modifiers = this->convertModifiers(m.fModifiers);
+ return std::unique_ptr<ModifiersDeclaration>(new ModifiersDeclaration(modifiers));
+}
+
std::unique_ptr<Statement> IRGenerator::convertIf(const ASTIfStatement& s) {
std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*s.fTest),
*fContext.fBool_Type);
@@ -419,8 +431,9 @@
for (size_t i = 0; i < parameters.size(); i++) {
if (parameters[i]->fModifiers != other->fParameters[i]->fModifiers) {
fErrors.error(f.fPosition, "modifiers on parameter " +
- to_string(i + 1) + " differ between " +
- "declaration and definition");
+ to_string((uint64_t) i + 1) +
+ " differ between declaration and "
+ "definition");
return nullptr;
}
}
@@ -616,8 +629,9 @@
ASSERT(ctor);
return this->call(Position(), std::move(ctor), std::move(args));
}
- ABORT("cannot coerce %s to %s", expr->fType.description().c_str(),
- type.description().c_str());
+ std::vector<std::unique_ptr<Expression>> args;
+ args.push_back(std::move(expr));
+ return std::unique_ptr<Expression>(new Constructor(Position(), type, std::move(args)));
}
static bool is_matrix_multiply(const Type& left, const Type& right) {
@@ -832,12 +846,12 @@
std::vector<std::unique_ptr<Expression>> arguments) {
if (function.fParameters.size() != arguments.size()) {
std::string msg = "call to '" + function.fName + "' expected " +
- to_string(function.fParameters.size()) +
+ to_string((uint64_t) function.fParameters.size()) +
" argument";
if (function.fParameters.size() != 1) {
msg += "s";
}
- msg += ", but found " + to_string(arguments.size());
+ msg += ", but found " + to_string((uint64_t) arguments.size());
fErrors.error(position, msg);
return nullptr;
}
@@ -921,7 +935,8 @@
std::vector<std::unique_ptr<Expression>> args) {
// FIXME: add support for structs and arrays
Type::Kind kind = type.kind();
- if (!type.isNumber() && kind != Type::kVector_Kind && kind != Type::kMatrix_Kind) {
+ if (!type.isNumber() && kind != Type::kVector_Kind && kind != Type::kMatrix_Kind &&
+ kind != Type::kArray_Kind) {
fErrors.error(position, "cannot construct '" + type.description() + "'");
return nullptr;
}
@@ -938,7 +953,7 @@
if (args.size() != 1) {
fErrors.error(position, "invalid arguments to '" + type.description() +
"' constructor, (expected exactly 1 argument, but found " +
- to_string(args.size()) + ")");
+ to_string((uint64_t) args.size()) + ")");
}
if (args[0]->fType == *fContext.fBool_Type) {
std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, position, 0));
@@ -953,6 +968,18 @@
"' constructor (expected a number or bool, but found '" +
args[0]->fType.description() + "')");
}
+ if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext.fInt_Type ||
+ type == *fContext.fUInt_Type)) {
+ return std::unique_ptr<Expression>(new IntLiteral(fContext,
+ position,
+ ((IntLiteral&) *args[0]).fValue,
+ &type));
+ }
+ } else if (kind == Type::kArray_Kind) {
+ const Type& base = type.componentType();
+ for (size_t i = 0; i < args.size(); i++) {
+ args[i] = this->coerce(std::move(args[i]), base);
+ }
} else {
ASSERT(kind == Type::kVector_Kind || kind == Type::kMatrix_Kind);
int actual = 0;
@@ -1054,7 +1081,8 @@
std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression> base,
const ASTExpression& index) {
- if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind) {
+ if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind &&
+ base->fType.kind() != Type::kVector_Kind) {
fErrors.error(base->fPosition, "expected array, but found '" + base->fType.description() +
"'");
return nullptr;
@@ -1063,9 +1091,11 @@
if (!converted) {
return nullptr;
}
- converted = this->coerce(std::move(converted), *fContext.fInt_Type);
- if (!converted) {
- return nullptr;
+ if (converted->fType != *fContext.fUInt_Type) {
+ converted = this->coerce(std::move(converted), *fContext.fInt_Type);
+ if (!converted) {
+ return nullptr;
+ }
}
return std::unique_ptr<Expression>(new IndexExpression(fContext, std::move(base),
std::move(converted)));
@@ -1143,9 +1173,21 @@
return nullptr;
}
switch (expression.fSuffix->fKind) {
- case ASTSuffix::kIndex_Kind:
- return this->convertIndex(std::move(base),
- *((ASTIndexSuffix&) *expression.fSuffix).fExpression);
+ case ASTSuffix::kIndex_Kind: {
+ const ASTExpression* expr = ((ASTIndexSuffix&) *expression.fSuffix).fExpression.get();
+ if (expr) {
+ return this->convertIndex(std::move(base), *expr);
+ } else if (base->fKind == Expression::kTypeReference_Kind) {
+ const Type& oldType = ((TypeReference&) *base).fValue;
+ Type* newType = new Type(oldType.name() + "[]", Type::kArray_Kind, oldType,
+ -1);
+ fSymbolTable->takeOwnership(newType);
+ return std::unique_ptr<Expression>(new TypeReference(fContext, base->fPosition,
+ *newType));
+ } else {
+ fErrors.error(expression.fPosition, "'[]' must follow a type name");
+ }
+ }
case ASTSuffix::kCall_Kind: {
auto rawArguments = &((ASTCallSuffix&) *expression.fSuffix).fArguments;
std::vector<std::unique_ptr<Expression>> arguments;
diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h
index a3ff210..834ed8d 100644
--- a/src/sksl/SkSLIRGenerator.h
+++ b/src/sksl/SkSLIRGenerator.h
@@ -25,6 +25,7 @@
#include "ast/SkSLASTIfStatement.h"
#include "ast/SkSLASTInterfaceBlock.h"
#include "ast/SkSLASTModifiers.h"
+#include "ast/SkSLASTModifiersDeclaration.h"
#include "ast/SkSLASTPrefixExpression.h"
#include "ast/SkSLASTReturnStatement.h"
#include "ast/SkSLASTStatement.h"
@@ -39,6 +40,7 @@
#include "ir/SkSLFunctionDefinition.h"
#include "ir/SkSLInterfaceBlock.h"
#include "ir/SkSLModifiers.h"
+#include "ir/SkSLModifiersDeclaration.h"
#include "ir/SkSLSymbolTable.h"
#include "ir/SkSLStatement.h"
#include "ir/SkSLType.h"
@@ -61,6 +63,8 @@
std::unique_ptr<FunctionDefinition> convertFunction(const ASTFunction& f);
std::unique_ptr<Statement> convertStatement(const ASTStatement& statement);
std::unique_ptr<Expression> convertExpression(const ASTExpression& expression);
+ std::unique_ptr<ModifiersDeclaration> convertModifiersDeclaration(
+ const ASTModifiersDeclaration& m);
private:
void pushSymbolTable();
diff --git a/src/sksl/SkSLMain.cpp b/src/sksl/SkSLMain.cpp
index 24fbb6c..de1b981 100644
--- a/src/sksl/SkSLMain.cpp
+++ b/src/sksl/SkSLMain.cpp
@@ -9,6 +9,24 @@
#include <fstream>
#include "SkSLCompiler.h"
+bool endsWith(const std::string& s, const std::string& ending) {
+ if (s.length() >= ending.length()) {
+ return (0 == s.compare(s.length() - ending.length(), ending.length(), ending));
+ }
+ return false;
+}
+
+static SkSL::GLCaps default_caps() {
+ return {
+ 400,
+ SkSL::GLCaps::kGL_Standard,
+ false, // isCoreProfile
+ false, // usesPrecisionModifiers;
+ false, // mustDeclareFragmentShaderOutput
+ true // canUseMinAndAbsTogether
+ };
+}
+
/**
* Very simple standalone executable to facilitate testing.
*/
@@ -35,14 +53,30 @@
printf("error reading '%s'\n", argv[1]);
exit(2);
}
- std::ofstream out(argv[2], std::ofstream::binary);
- SkSL::Compiler compiler;
- if (!compiler.toSPIRV(kind, text, out)) {
- printf("%s", compiler.errorText().c_str());
- exit(3);
- }
- if (out.rdstate()) {
- printf("error writing '%s'\n", argv[2]);
- exit(4);
+ std::string name(argv[2]);
+ if (endsWith(name, ".spirv")) {
+ std::ofstream out(argv[2], std::ofstream::binary);
+ SkSL::Compiler compiler;
+ if (!compiler.toSPIRV(kind, text, out)) {
+ printf("%s", compiler.errorText().c_str());
+ exit(3);
+ }
+ if (out.rdstate()) {
+ printf("error writing '%s'\n", argv[2]);
+ exit(4);
+ }
+ } else if (endsWith(name, ".glsl")) {
+ std::ofstream out(argv[2], std::ofstream::binary);
+ SkSL::Compiler compiler;
+ if (!compiler.toGLSL(kind, text, default_caps(), out)) {
+ printf("%s", compiler.errorText().c_str());
+ exit(3);
+ }
+ if (out.rdstate()) {
+ printf("error writing '%s'\n", argv[2]);
+ exit(4);
+ }
+ } else {
+ printf("expected output filename to end with '.spirv' or '.glsl'");
}
}
diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp
index b240e45..cc133a8 100644
--- a/src/sksl/SkSLParser.cpp
+++ b/src/sksl/SkSLParser.cpp
@@ -56,6 +56,7 @@
#include "ast/SkSLASTIndexSuffix.h"
#include "ast/SkSLASTInterfaceBlock.h"
#include "ast/SkSLASTIntLiteral.h"
+#include "ast/SkSLASTModifiersDeclaration.h"
#include "ast/SkSLASTParameter.h"
#include "ast/SkSLASTPrefixExpression.h"
#include "ast/SkSLASTReturnStatement.h"
@@ -185,7 +186,8 @@
this->expect(Token::SEMICOLON, "';'");
}
-/* DIRECTIVE(#version) INT_LITERAL | DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */
+/* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? |
+ DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */
std::unique_ptr<ASTDeclaration> Parser::directive() {
Token start;
if (!this->expect(Token::DIRECTIVE, "a directive", &start)) {
@@ -193,7 +195,12 @@
}
if (start.fText == "#version") {
this->expect(Token::INT_LITERAL, "a version number");
- // ignored for now
+ Token next = this->peek();
+ if (next.fText == "es" || next.fText == "compatibility") {
+ this->nextToken();
+ }
+ // version is ignored for now; it will eventually become an error when we stop pretending
+ // to be GLSL
return nullptr;
} else if (start.fText == "#extension") {
Token name;
@@ -227,6 +234,10 @@
if (lookahead.fKind == Token::STRUCT) {
return this->structVarDeclaration(modifiers);
}
+ if (lookahead.fKind == Token::SEMICOLON) {
+ this->nextToken();
+ return std::unique_ptr<ASTDeclaration>(new ASTModifiersDeclaration(modifiers));
+ }
std::unique_ptr<ASTType> type(this->type());
if (!type) {
return nullptr;
@@ -477,10 +488,13 @@
int set = -1;
int builtin = -1;
bool originUpperLeft = false;
+ bool overrideCoverage = false;
+ bool blendSupportAllEquations = false;
if (this->peek().fKind == Token::LAYOUT) {
this->nextToken();
if (!this->expect(Token::LPAREN, "'('")) {
- return ASTLayout(location, binding, index, set, builtin, originUpperLeft);
+ return ASTLayout(location, binding, index, set, builtin, originUpperLeft,
+ overrideCoverage, blendSupportAllEquations);
}
for (;;) {
Token t = this->nextToken();
@@ -496,6 +510,10 @@
builtin = this->layoutInt();
} else if (t.fText == "origin_upper_left") {
originUpperLeft = true;
+ } else if (t.fText == "override_coverage") {
+ overrideCoverage = true;
+ } else if (t.fText == "blend_support_all_equations") {
+ blendSupportAllEquations = true;
} else {
this->error(t.fPosition, ("'" + t.fText +
"' is not a valid layout qualifier").c_str());
@@ -509,7 +527,8 @@
}
}
}
- return ASTLayout(location, binding, index, set, builtin, originUpperLeft);
+ return ASTLayout(location, binding, index, set, builtin, originUpperLeft, overrideCoverage,
+ blendSupportAllEquations);
}
/* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE)* */
@@ -1254,12 +1273,16 @@
}
}
-/* LBRACKET expression RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN |
+/* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN |
PLUSPLUS | MINUSMINUS */
std::unique_ptr<ASTSuffix> Parser::suffix() {
Token next = this->nextToken();
switch (next.fKind) {
case Token::LBRACKET: {
+ if (this->peek().fKind == Token::RBRACKET) {
+ this->nextToken();
+ return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(next.fPosition));
+ }
std::unique_ptr<ASTExpression> e = this->expression();
if (!e) {
return nullptr;
diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp
index d17e3c4..f13fc7e 100644
--- a/src/sksl/SkSLSPIRVCodeGenerator.cpp
+++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp
@@ -15,6 +15,7 @@
#include "ir/SkSLExtension.h"
#include "ir/SkSLIndexExpression.h"
#include "ir/SkSLVariableReference.h"
+#include "SkSLCompiler.h"
namespace SkSL {
@@ -2321,7 +2322,7 @@
this->writeInstruction(SpvOpDecorate, target, SpvDecorationDescriptorSet, layout.fSet,
fDecorationBuffer);
}
- if (layout.fBuiltin >= 0) {
+ if (layout.fBuiltin >= 0 && layout.fBuiltin != SK_FRAGCOLOR_BUILTIN) {
this->writeInstruction(SpvOpDecorate, target, SpvDecorationBuiltIn, layout.fBuiltin,
fDecorationBuffer);
}
@@ -2363,10 +2364,19 @@
return result;
}
-void SPIRVCodeGenerator::writeGlobalVars(const VarDeclarations& decl, std::ostream& out) {
+#define BUILTIN_IGNORE 9999
+void SPIRVCodeGenerator::writeGlobalVars(Program::Kind kind, const VarDeclarations& decl,
+ std::ostream& out) {
for (size_t i = 0; i < decl.fVars.size(); i++) {
const VarDeclaration& varDecl = decl.fVars[i];
const Variable* var = varDecl.fVar;
+ if (var->fModifiers.fLayout.fBuiltin == BUILTIN_IGNORE) {
+ continue;
+ }
+ if (var->fModifiers.fLayout.fBuiltin == SK_FRAGCOLOR_BUILTIN &&
+ kind != Program::kFragment_Kind) {
+ continue;
+ }
if (!var->fIsReadFrom && !var->fIsWrittenTo &&
!(var->fModifiers.fFlags & (Modifiers::kIn_Flag |
Modifiers::kOut_Flag |
@@ -2562,7 +2572,8 @@
}
for (size_t i = 0; i < program.fElements.size(); i++) {
if (program.fElements[i]->fKind == ProgramElement::kVar_Kind) {
- this->writeGlobalVars(((VarDeclarations&) *program.fElements[i]), body);
+ this->writeGlobalVars(program.fKind, ((VarDeclarations&) *program.fElements[i]),
+ body);
}
}
for (size_t i = 0; i < program.fElements.size(); i++) {
diff --git a/src/sksl/SkSLSPIRVCodeGenerator.h b/src/sksl/SkSLSPIRVCodeGenerator.h
index e7b2b30..2800a86 100644
--- a/src/sksl/SkSLSPIRVCodeGenerator.h
+++ b/src/sksl/SkSLSPIRVCodeGenerator.h
@@ -115,7 +115,7 @@
SpvId writeFunction(const FunctionDefinition& f, std::ostream& out);
- void writeGlobalVars(const VarDeclarations& v, std::ostream& out);
+ void writeGlobalVars(Program::Kind kind, const VarDeclarations& v, std::ostream& out);
void writeVarDeclarations(const VarDeclarations& decl, std::ostream& out);
diff --git a/src/sksl/SkSLUtil.cpp b/src/sksl/SkSLUtil.cpp
index 327bffe..2b51cff 100644
--- a/src/sksl/SkSLUtil.cpp
+++ b/src/sksl/SkSLUtil.cpp
@@ -9,7 +9,48 @@
namespace SkSL {
+std::string to_string(double value) {
+ std::stringstream buffer;
+ buffer << std::setprecision(std::numeric_limits<double>::digits10) << value;
+ std::string result = buffer.str();
+ if (result.find_last_of(".") == std::string::npos &&
+ result.find_last_of("e") == std::string::npos) {
+ result += ".0";
+ }
+ return result;
+}
+
+std::string to_string(int32_t value) {
+ std::stringstream buffer;
+ buffer << value;
+ return buffer.str();
+}
+
+std::string to_string(uint32_t value) {
+ std::stringstream buffer;
+ buffer << value;
+ return buffer.str();
+}
+
+std::string to_string(int64_t value) {
+ std::stringstream buffer;
+ buffer << value;
+ return buffer.str();
+}
+
+std::string to_string(uint64_t value) {
+ std::stringstream buffer;
+ buffer << value;
+ return buffer.str();
+}
+
int stoi(std::string s) {
+ if (s.size() > 2 && s[0] == '0' && s[1] == 'x') {
+ char* p;
+ int result = strtoul(s.substr(2).c_str(), &p, 16);
+ ASSERT(*p == 0);
+ return result;
+ }
return atoi(s.c_str());
}
@@ -18,6 +59,12 @@
}
long stol(std::string s) {
+ if (s.size() > 2 && s[0] == '0' && s[1] == 'x') {
+ char* p;
+ int result = strtoul(s.substr(2).c_str(), &p, 16);
+ ASSERT(*p == 0);
+ return result;
+ }
return atol(s.c_str());
}
diff --git a/src/sksl/SkSLUtil.h b/src/sksl/SkSLUtil.h
index 33611cd..efffaae 100644
--- a/src/sksl/SkSLUtil.h
+++ b/src/sksl/SkSLUtil.h
@@ -19,11 +19,15 @@
// our own definitions of certain std:: functions, because they are not always present on Android
-template <typename T> std::string to_string(T value) {
- std::stringstream buffer;
- buffer << std::setprecision(std::numeric_limits<T>::digits10) << value;
- return buffer.str();
-}
+std::string to_string(double value);
+
+std::string to_string(int32_t value);
+
+std::string to_string(uint32_t value);
+
+std::string to_string(int64_t value);
+
+std::string to_string(uint64_t value);
#if _MSC_VER
#define NORETURN __declspec(noreturn)
diff --git a/src/sksl/ast/SkSLASTDeclaration.h b/src/sksl/ast/SkSLASTDeclaration.h
index 8b55ecf..cd8aae1 100644
--- a/src/sksl/ast/SkSLASTDeclaration.h
+++ b/src/sksl/ast/SkSLASTDeclaration.h
@@ -20,7 +20,8 @@
kVar_Kind,
kFunction_Kind,
kInterfaceBlock_Kind,
- kExtension_Kind
+ kExtension_Kind,
+ kModifiers_Kind
};
ASTDeclaration(Position position, Kind kind)
diff --git a/src/sksl/ast/SkSLASTIndexSuffix.h b/src/sksl/ast/SkSLASTIndexSuffix.h
index 44d91fa..755029b 100644
--- a/src/sksl/ast/SkSLASTIndexSuffix.h
+++ b/src/sksl/ast/SkSLASTIndexSuffix.h
@@ -14,17 +14,27 @@
namespace SkSL {
/**
- * A bracketed expression, as in '[0]', indicating an array access.
+ * A bracketed expression, as in '[0]', indicating an array access. Empty brackets (as occur in
+ * 'float[](5, 6)' are represented with a null fExpression.
*/
struct ASTIndexSuffix : public ASTSuffix {
+ ASTIndexSuffix(Position position)
+ : INHERITED(position, ASTSuffix::kIndex_Kind)
+ , fExpression(nullptr) {}
+
ASTIndexSuffix(std::unique_ptr<ASTExpression> expression)
- : INHERITED(expression->fPosition, ASTSuffix::kIndex_Kind)
+ : INHERITED(expression ? expression->fPosition : Position(), ASTSuffix::kIndex_Kind)
, fExpression(std::move(expression)) {}
std::string description() const override {
- return "[" + fExpression->description() + "]";
+ if (fExpression) {
+ return "[" + fExpression->description() + "]";
+ } else {
+ return "[]";
+ }
}
+ // may be null
std::unique_ptr<ASTExpression> fExpression;
typedef ASTSuffix INHERITED;
diff --git a/src/sksl/ast/SkSLASTLayout.h b/src/sksl/ast/SkSLASTLayout.h
index 08d6753..515eb2b 100644
--- a/src/sksl/ast/SkSLASTLayout.h
+++ b/src/sksl/ast/SkSLASTLayout.h
@@ -20,13 +20,16 @@
*/
struct ASTLayout : public ASTNode {
// For all parameters, a -1 means no value
- ASTLayout(int location, int binding, int index, int set, int builtin, bool originUpperLeft)
+ ASTLayout(int location, int binding, int index, int set, int builtin, bool originUpperLeft,
+ bool overrideCoverage, bool blendSupportAllEquations)
: fLocation(location)
, fBinding(binding)
, fIndex(index)
, fSet(set)
, fBuiltin(builtin)
- , fOriginUpperLeft(originUpperLeft) {}
+ , fOriginUpperLeft(originUpperLeft)
+ , fOverrideCoverage(overrideCoverage)
+ , fBlendSupportAllEquations(blendSupportAllEquations) {}
std::string description() const {
std::string result;
@@ -55,6 +58,14 @@
result += separator + "origin_upper_left";
separator = ", ";
}
+ if (fOverrideCoverage) {
+ result += separator + "override_coverage";
+ separator = ", ";
+ }
+ if (fBlendSupportAllEquations) {
+ result += separator + "blend_support_all_equations";
+ separator = ", ";
+ }
if (result.length() > 0) {
result = "layout (" + result + ")";
}
@@ -67,6 +78,8 @@
const int fSet;
const int fBuiltin;
const bool fOriginUpperLeft;
+ const bool fOverrideCoverage;
+ const bool fBlendSupportAllEquations;
};
} // namespace
diff --git a/src/sksl/ast/SkSLASTModifiersDeclaration.h b/src/sksl/ast/SkSLASTModifiersDeclaration.h
new file mode 100644
index 0000000..f5cc620
--- /dev/null
+++ b/src/sksl/ast/SkSLASTModifiersDeclaration.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SKSL_ASTMODIFIERDECLARATION
+#define SKSL_ASTMODIFIERDECLARATION
+
+#include "SkSLASTDeclaration.h"
+#include "SkSLASTModifiers.h"
+
+namespace SkSL {
+
+/**
+ * A declaration that consists only of modifiers, e.g.:
+ *
+ * layout(blend_support_all_equations) out;
+ */
+struct ASTModifiersDeclaration : public ASTDeclaration {
+ ASTModifiersDeclaration(ASTModifiers modifiers)
+ : INHERITED(Position(), kModifiers_Kind)
+ , fModifiers(modifiers) {}
+
+ std::string description() const {
+ return fModifiers.description() + ";";
+ }
+
+ ASTModifiers fModifiers;
+
+ typedef ASTDeclaration INHERITED;
+};
+
+} // namespace
+
+#endif
diff --git a/src/sksl/ir/SkSLIndexExpression.h b/src/sksl/ir/SkSLIndexExpression.h
index f5b0d09..319e06f 100644
--- a/src/sksl/ir/SkSLIndexExpression.h
+++ b/src/sksl/ir/SkSLIndexExpression.h
@@ -19,7 +19,7 @@
static const Type& index_type(const Context& context, const Type& type) {
if (type.kind() == Type::kMatrix_Kind) {
if (type.componentType() == *context.fFloat_Type) {
- switch (type.columns()) {
+ switch (type.rows()) {
case 2: return *context.fVec2_Type;
case 3: return *context.fVec3_Type;
case 4: return *context.fVec4_Type;
@@ -47,7 +47,7 @@
: INHERITED(base->fPosition, kIndex_Kind, index_type(context, base->fType))
, fBase(std::move(base))
, fIndex(std::move(index)) {
- ASSERT(fIndex->fType == *context.fInt_Type);
+ ASSERT(fIndex->fType == *context.fInt_Type || fIndex->fType == *context.fUInt_Type);
}
std::string description() const override {
diff --git a/src/sksl/ir/SkSLIntLiteral.h b/src/sksl/ir/SkSLIntLiteral.h
index 2bc5657..8921c28 100644
--- a/src/sksl/ir/SkSLIntLiteral.h
+++ b/src/sksl/ir/SkSLIntLiteral.h
@@ -18,8 +18,8 @@
struct IntLiteral : public Expression {
// FIXME: we will need to revisit this if/when we add full support for both signed and unsigned
// 64-bit integers, but for right now an int64_t will hold every value we care about
- IntLiteral(const Context& context, Position position, int64_t value)
- : INHERITED(position, kIntLiteral_Kind, *context.fInt_Type)
+ IntLiteral(const Context& context, Position position, int64_t value, const Type* type = nullptr)
+ : INHERITED(position, kIntLiteral_Kind, type ? *type : *context.fInt_Type)
, fValue(value) {}
virtual std::string description() const override {
diff --git a/src/sksl/ir/SkSLLayout.h b/src/sksl/ir/SkSLLayout.h
index d8dc980..24087d0 100644
--- a/src/sksl/ir/SkSLLayout.h
+++ b/src/sksl/ir/SkSLLayout.h
@@ -22,15 +22,20 @@
, fIndex(layout.fIndex)
, fSet(layout.fSet)
, fBuiltin(layout.fBuiltin)
- , fOriginUpperLeft(layout.fOriginUpperLeft) {}
+ , fOriginUpperLeft(layout.fOriginUpperLeft)
+ , fOverrideCoverage(layout.fOverrideCoverage)
+ , fBlendSupportAllEquations(layout.fBlendSupportAllEquations) {}
- Layout(int location, int binding, int index, int set, int builtin, bool originUpperLeft)
+ Layout(int location, int binding, int index, int set, int builtin, bool originUpperLeft,
+ bool overrideCoverage, bool blendSupportAllEquations)
: fLocation(location)
, fBinding(binding)
, fIndex(index)
, fSet(set)
, fBuiltin(builtin)
- , fOriginUpperLeft(originUpperLeft) {}
+ , fOriginUpperLeft(originUpperLeft)
+ , fOverrideCoverage(overrideCoverage)
+ , fBlendSupportAllEquations(blendSupportAllEquations) {}
std::string description() const {
std::string result;
@@ -59,6 +64,14 @@
result += separator + "origin_upper_left";
separator = ", ";
}
+ if (fOverrideCoverage) {
+ result += separator + "override_coverage";
+ separator = ", ";
+ }
+ if (fBlendSupportAllEquations) {
+ result += separator + "blend_support_all_equations";
+ separator = ", ";
+ }
if (result.length() > 0) {
result = "layout (" + result + ")";
}
@@ -66,11 +79,14 @@
}
bool operator==(const Layout& other) const {
- return fLocation == other.fLocation &&
- fBinding == other.fBinding &&
- fIndex == other.fIndex &&
- fSet == other.fSet &&
- fBuiltin == other.fBuiltin;
+ return fLocation == other.fLocation &&
+ fBinding == other.fBinding &&
+ fIndex == other.fIndex &&
+ fSet == other.fSet &&
+ fBuiltin == other.fBuiltin &&
+ fOriginUpperLeft == other.fOriginUpperLeft &&
+ fOverrideCoverage == other.fOverrideCoverage &&
+ fBlendSupportAllEquations == other.fBlendSupportAllEquations;
}
bool operator!=(const Layout& other) const {
@@ -85,6 +101,8 @@
int fSet;
int fBuiltin;
bool fOriginUpperLeft;
+ bool fOverrideCoverage;
+ bool fBlendSupportAllEquations;
};
} // namespace
diff --git a/src/sksl/ir/SkSLModifiersDeclaration.h b/src/sksl/ir/SkSLModifiersDeclaration.h
new file mode 100644
index 0000000..0066fab
--- /dev/null
+++ b/src/sksl/ir/SkSLModifiersDeclaration.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SKSL_MODIFIERDECLARATION
+#define SKSL_MODIFIERDECLARATION
+
+#include "SkSLProgramElement.h"
+#include "SkSLModifiers.h"
+
+namespace SkSL {
+
+/**
+ * A declaration that consists only of modifiers, e.g.:
+ *
+ * layout(blend_support_all_equations) out;
+ */
+struct ModifiersDeclaration : public ProgramElement {
+ ModifiersDeclaration(Modifiers modifiers)
+ : INHERITED(Position(), kModifiers_Kind)
+ , fModifiers(modifiers) {}
+
+ std::string description() const {
+ return fModifiers.description() + ";";
+ }
+
+ Modifiers fModifiers;
+
+ typedef ProgramElement INHERITED;
+};
+
+} // namespace
+
+#endif
diff --git a/src/sksl/ir/SkSLProgramElement.h b/src/sksl/ir/SkSLProgramElement.h
index 44fc340..2f1ce77 100644
--- a/src/sksl/ir/SkSLProgramElement.h
+++ b/src/sksl/ir/SkSLProgramElement.h
@@ -20,7 +20,8 @@
kVar_Kind,
kFunction_Kind,
kInterfaceBlock_Kind,
- kExtension_Kind
+ kExtension_Kind,
+ kModifiers_Kind
};
ProgramElement(Position position, Kind kind)
diff --git a/src/sksl/lex.sksl.c b/src/sksl/lex.sksl.c
index 4993fac..ed6bd6b 100644
--- a/src/sksl/lex.sksl.c
+++ b/src/sksl/lex.sksl.c
@@ -4,7 +4,7 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
-
+
#line 3 "lex.sksl.c"
#define YY_INT_ALIGNED short int
@@ -14,7 +14,7 @@
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 37
+#define YY_FLEX_SUBMINOR_VERSION 35
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
@@ -52,6 +52,7 @@
typedef uint16_t flex_uint16_t;
typedef int32_t flex_int32_t;
typedef uint32_t flex_uint32_t;
+typedef uint64_t flex_uint64_t;
#else
typedef signed char flex_int8_t;
typedef short int flex_int16_t;
@@ -59,6 +60,7 @@
typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
/* Limits of integral types. */
#ifndef INT8_MIN
@@ -89,8 +91,6 @@
#define UINT32_MAX (4294967295U)
#endif
-#endif /* ! C99 */
-
#endif /* ! FLEXINT_H */
#ifdef __cplusplus
@@ -194,7 +194,7 @@
*/
#define YY_LESS_LINENO(n) \
do { \
- int yyl;\
+ yy_size_t yyl;\
for ( yyl = n; yyl < yyleng; ++yyl )\
if ( yytext[yyl] == '\n' )\
--yylineno;\
@@ -360,13 +360,13 @@
*/
#define YY_DO_BEFORE_ACTION \
yyg->yytext_ptr = yy_bp; \
- yyleng = (size_t) (yy_cp - yy_bp); \
+ yyleng = (yy_size_t) (yy_cp - yy_bp); \
yyg->yy_hold_char = *yy_cp; \
*yy_cp = '\0'; \
yyg->yy_c_buf_p = yy_cp;
-#define YY_NUM_RULES 82
-#define YY_END_OF_BUFFER 83
+#define YY_NUM_RULES 83
+#define YY_END_OF_BUFFER 84
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@@ -374,30 +374,31 @@
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static yyconst flex_int16_t yy_accept[201] =
+static yyconst flex_int16_t yy_accept[204] =
{ 0,
- 0, 0, 83, 81, 80, 80, 54, 81, 29, 45,
- 50, 31, 32, 43, 41, 38, 42, 37, 44, 4,
- 56, 77, 61, 57, 60, 55, 35, 36, 49, 29,
- 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
- 29, 29, 29, 29, 29, 29, 33, 48, 34, 80,
- 59, 30, 29, 68, 53, 73, 66, 39, 64, 40,
- 65, 1, 0, 78, 67, 2, 4, 0, 46, 63,
- 58, 62, 47, 72, 52, 29, 29, 29, 11, 29,
- 29, 29, 29, 29, 7, 16, 29, 29, 29, 29,
- 29, 29, 29, 29, 29, 29, 29, 71, 51, 30,
+ 0, 0, 84, 82, 81, 81, 55, 82, 30, 46,
+ 51, 32, 33, 44, 42, 39, 43, 38, 45, 4,
+ 4, 57, 78, 62, 58, 61, 56, 36, 37, 50,
+ 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 34, 49, 35,
+ 81, 60, 31, 30, 69, 54, 74, 67, 40, 65,
+ 41, 66, 1, 0, 79, 68, 2, 4, 0, 0,
+ 47, 64, 59, 63, 48, 73, 53, 30, 30, 30,
+ 12, 30, 30, 30, 30, 30, 8, 17, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30, 30, 72,
- 76, 0, 0, 0, 78, 1, 0, 0, 3, 69,
- 70, 75, 29, 29, 29, 29, 29, 29, 9, 29,
- 29, 29, 29, 29, 29, 17, 29, 29, 29, 29,
- 29, 29, 74, 0, 1, 79, 0, 0, 2, 29,
- 29, 29, 29, 8, 29, 24, 29, 29, 29, 21,
- 29, 29, 29, 29, 29, 5, 29, 29, 0, 1,
- 12, 20, 29, 29, 6, 23, 18, 29, 29, 29,
- 29, 29, 29, 29, 10, 29, 29, 27, 29, 29,
- 29, 15, 26, 29, 29, 14, 22, 29, 29, 19,
- 13, 29, 29, 29, 28, 29, 29, 29, 25, 0
+ 52, 31, 77, 0, 0, 0, 79, 1, 0, 0,
+ 3, 5, 70, 71, 76, 30, 30, 30, 30, 30,
+ 30, 10, 30, 30, 30, 30, 30, 30, 18, 30,
+ 30, 30, 30, 30, 30, 75, 0, 1, 80, 0,
+ 0, 2, 30, 30, 30, 30, 9, 30, 25, 30,
+ 30, 30, 22, 30, 30, 30, 30, 30, 6, 30,
+ 30, 0, 1, 13, 21, 30, 30, 7, 24, 19,
+ 30, 30, 30, 30, 30, 30, 30, 11, 30, 30,
+ 28, 30, 30, 30, 16, 27, 30, 30, 15, 23,
+ 30, 30, 20, 14, 30, 30, 30, 29, 30, 30,
+ 30, 26, 0
} ;
static yyconst flex_int32_t yy_ec[256] =
@@ -406,16 +407,16 @@
1, 1, 2, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 2, 4, 1, 5, 6, 7, 8, 1, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 18, 19, 20,
- 21, 22, 23, 1, 6, 6, 6, 6, 24, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 25, 1, 26, 27, 6, 1, 28, 29, 30, 31,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 19, 20, 21,
+ 22, 23, 24, 1, 25, 25, 25, 25, 26, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 27, 1, 28, 29, 6, 1, 30, 31, 32, 33,
- 32, 33, 34, 35, 36, 6, 37, 38, 39, 40,
- 41, 42, 6, 43, 44, 45, 46, 47, 48, 6,
- 49, 6, 50, 51, 52, 1, 1, 1, 1, 1,
+ 34, 35, 36, 37, 38, 25, 39, 40, 41, 42,
+ 43, 44, 25, 45, 46, 47, 48, 49, 50, 51,
+ 52, 25, 53, 54, 55, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -432,152 +433,158 @@
1, 1, 1, 1, 1
} ;
-static yyconst flex_int32_t yy_meta[53] =
+static yyconst flex_int32_t yy_meta[56] =
{ 0,
1, 1, 2, 1, 1, 3, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 4, 1, 1, 1,
- 1, 1, 1, 3, 1, 1, 1, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 1,
- 1, 1
+ 1, 1, 1, 1, 1, 1, 4, 4, 1, 1,
+ 1, 1, 1, 1, 5, 5, 1, 1, 1, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 1, 1, 1
} ;
-static yyconst flex_int16_t yy_base[206] =
+static yyconst flex_int16_t yy_base[210] =
{ 0,
- 0, 0, 238, 239, 51, 53, 216, 0, 0, 215,
- 49, 239, 239, 214, 46, 239, 45, 217, 52, 45,
- 239, 239, 44, 212, 50, 239, 239, 239, 53, 189,
- 190, 40, 192, 47, 193, 46, 50, 196, 186, 180,
- 182, 192, 178, 179, 181, 185, 239, 61, 239, 81,
- 239, 0, 0, 239, 198, 239, 239, 239, 239, 239,
- 239, 70, 207, 0, 239, 72, 75, 81, 196, 239,
- 239, 239, 195, 239, 194, 182, 173, 168, 0, 167,
- 172, 181, 165, 173, 0, 165, 156, 156, 172, 160,
- 156, 168, 154, 155, 151, 160, 159, 239, 173, 0,
+ 0, 0, 272, 273, 54, 56, 249, 0, 0, 248,
+ 52, 273, 273, 247, 49, 273, 48, 46, 56, 51,
+ 58, 273, 273, 58, 246, 59, 273, 273, 273, 61,
+ 222, 223, 48, 225, 57, 226, 53, 63, 229, 219,
+ 213, 215, 225, 211, 212, 214, 218, 273, 67, 273,
+ 96, 273, 0, 0, 273, 232, 273, 273, 273, 273,
+ 273, 273, 86, 242, 0, 273, 90, 96, 111, 0,
+ 230, 273, 273, 273, 229, 273, 228, 215, 206, 201,
+ 0, 200, 205, 214, 198, 206, 0, 198, 188, 189,
+ 205, 193, 189, 201, 187, 188, 184, 193, 192, 273,
- 239, 89, 182, 176, 0, 91, 97, 174, 173, 239,
- 239, 239, 161, 72, 158, 155, 142, 140, 0, 149,
- 137, 141, 139, 144, 147, 0, 148, 131, 130, 143,
- 141, 135, 239, 155, 154, 239, 107, 153, 152, 131,
- 122, 130, 137, 0, 132, 0, 121, 117, 115, 0,
- 114, 116, 122, 114, 126, 0, 114, 122, 136, 135,
- 0, 0, 111, 107, 0, 0, 0, 104, 109, 103,
- 102, 105, 99, 100, 0, 96, 110, 0, 98, 97,
- 102, 0, 0, 98, 102, 0, 0, 90, 79, 0,
- 0, 88, 73, 65, 0, 69, 53, 65, 0, 239,
+ 207, 0, 273, 119, 217, 211, 0, 92, 126, 117,
+ 124, 0, 273, 273, 273, 196, 99, 193, 190, 177,
+ 175, 0, 184, 172, 176, 174, 179, 182, 0, 183,
+ 166, 165, 178, 176, 170, 273, 130, 132, 273, 139,
+ 137, 141, 170, 161, 169, 176, 0, 171, 0, 160,
+ 156, 154, 0, 153, 155, 161, 153, 165, 0, 153,
+ 161, 143, 145, 0, 0, 152, 148, 0, 0, 0,
+ 145, 150, 144, 143, 146, 140, 141, 0, 137, 146,
+ 0, 121, 108, 101, 0, 0, 91, 93, 0, 0,
+ 85, 74, 0, 0, 83, 63, 54, 0, 58, 45,
- 58, 122, 124, 128, 132
+ 31, 0, 273, 161, 164, 167, 172, 177, 179
} ;
-static yyconst flex_int16_t yy_def[206] =
+static yyconst flex_int16_t yy_def[210] =
{ 0,
- 200, 1, 200, 200, 200, 200, 200, 201, 202, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 202,
- 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 200, 200, 200, 200,
- 200, 203, 202, 200, 200, 200, 200, 200, 200, 200,
- 200, 200, 204, 205, 200, 200, 200, 200, 200, 200,
- 200, 200, 200, 200, 200, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 200, 200, 203,
+ 203, 1, 203, 203, 203, 203, 203, 204, 205, 203,
+ 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
+ 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
+ 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
+ 205, 205, 205, 205, 205, 205, 205, 203, 203, 203,
+ 203, 203, 206, 205, 203, 203, 203, 203, 203, 203,
+ 203, 203, 203, 207, 208, 203, 203, 203, 203, 209,
+ 203, 203, 203, 203, 203, 203, 203, 205, 205, 205,
+ 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
+ 205, 205, 205, 205, 205, 205, 205, 205, 205, 203,
- 200, 200, 204, 204, 205, 200, 200, 200, 200, 200,
- 200, 200, 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 200, 200, 200, 200, 200, 200, 200, 202,
- 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202, 200, 200,
- 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202, 202, 0,
+ 203, 206, 203, 203, 207, 207, 208, 203, 203, 203,
+ 203, 209, 203, 203, 203, 205, 205, 205, 205, 205,
+ 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
+ 205, 205, 205, 205, 205, 203, 203, 203, 203, 203,
+ 203, 203, 205, 205, 205, 205, 205, 205, 205, 205,
+ 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
+ 205, 203, 203, 205, 205, 205, 205, 205, 205, 205,
+ 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
+ 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
+ 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
- 200, 200, 200, 200, 200
+ 205, 205, 0, 203, 203, 203, 203, 203, 203
} ;
-static yyconst flex_int16_t yy_nxt[292] =
+static yyconst flex_int16_t yy_nxt[329] =
{ 0,
4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 9, 27, 28, 29, 9, 30, 31,
- 32, 33, 34, 9, 35, 36, 9, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 9, 46, 9, 47,
- 48, 49, 50, 50, 50, 50, 55, 58, 60, 66,
- 52, 67, 63, 69, 70, 61, 59, 64, 68, 56,
- 72, 73, 65, 74, 81, 78, 68, 87, 85, 75,
- 79, 98, 50, 50, 82, 86, 62, 83, 106, 66,
- 88, 67, 108, 102, 108, 107, 199, 109, 68, 198,
+ 24, 25, 26, 27, 9, 9, 28, 29, 30, 9,
+ 31, 32, 33, 34, 35, 9, 36, 37, 9, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 9, 47,
+ 9, 9, 48, 49, 50, 51, 51, 51, 51, 56,
+ 59, 61, 63, 63, 202, 67, 64, 68, 68, 62,
+ 60, 65, 67, 57, 68, 68, 69, 66, 71, 72,
+ 74, 75, 76, 69, 69, 80, 83, 87, 100, 77,
+ 81, 69, 89, 201, 88, 200, 84, 51, 51, 85,
- 134, 102, 134, 107, 197, 135, 68, 106, 138, 196,
- 138, 99, 195, 139, 137, 141, 142, 194, 159, 193,
- 159, 192, 137, 160, 53, 53, 100, 100, 103, 103,
- 103, 103, 105, 191, 105, 105, 190, 189, 188, 187,
- 186, 185, 184, 183, 182, 181, 180, 179, 178, 177,
- 176, 160, 160, 175, 174, 173, 172, 171, 170, 169,
- 168, 167, 166, 165, 164, 163, 162, 161, 139, 139,
- 135, 135, 158, 157, 156, 155, 154, 153, 152, 151,
- 150, 149, 148, 147, 146, 145, 144, 143, 140, 109,
- 109, 136, 104, 133, 132, 131, 130, 129, 128, 127,
+ 199, 70, 63, 63, 198, 90, 108, 108, 108, 108,
+ 67, 104, 68, 68, 197, 109, 196, 140, 195, 104,
+ 101, 69, 110, 109, 110, 140, 194, 111, 111, 69,
+ 137, 193, 137, 111, 111, 138, 138, 141, 192, 141,
+ 111, 111, 142, 142, 144, 145, 138, 138, 138, 138,
+ 162, 191, 162, 142, 142, 163, 163, 142, 142, 163,
+ 163, 163, 163, 53, 190, 53, 54, 54, 54, 102,
+ 102, 102, 105, 105, 105, 105, 105, 107, 189, 107,
+ 107, 107, 112, 112, 188, 187, 186, 185, 184, 183,
+ 182, 181, 180, 179, 178, 177, 176, 175, 174, 173,
- 126, 125, 124, 123, 122, 121, 120, 119, 118, 117,
- 116, 115, 114, 113, 112, 111, 110, 104, 101, 97,
- 96, 95, 94, 93, 92, 91, 90, 89, 84, 80,
- 77, 76, 71, 62, 57, 54, 51, 200, 3, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
- 200
+ 172, 171, 170, 169, 168, 167, 166, 165, 164, 161,
+ 160, 159, 158, 157, 156, 155, 154, 153, 152, 151,
+ 150, 149, 148, 147, 146, 143, 139, 106, 136, 135,
+ 134, 133, 132, 131, 130, 129, 128, 127, 126, 125,
+ 124, 123, 122, 121, 120, 119, 118, 117, 116, 115,
+ 114, 113, 106, 103, 99, 98, 97, 96, 95, 94,
+ 93, 92, 91, 86, 82, 79, 78, 73, 58, 55,
+ 52, 203, 3, 203, 203, 203, 203, 203, 203, 203,
+ 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
+ 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
+ 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
+ 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
+ 203, 203, 203, 203, 203, 203, 203, 203
} ;
-static yyconst flex_int16_t yy_chk[292] =
+static yyconst flex_int16_t yy_chk[329] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 5, 5, 6, 6, 11, 15, 17, 20,
- 201, 20, 19, 23, 23, 17, 15, 19, 20, 11,
- 25, 25, 19, 29, 34, 32, 20, 37, 36, 29,
- 32, 48, 50, 50, 34, 36, 62, 34, 66, 67,
- 37, 67, 68, 62, 68, 66, 198, 68, 67, 197,
+ 1, 1, 1, 1, 1, 5, 5, 6, 6, 11,
+ 15, 17, 18, 18, 201, 20, 19, 20, 20, 17,
+ 15, 19, 21, 11, 21, 21, 20, 19, 24, 24,
+ 26, 26, 30, 21, 20, 33, 35, 37, 49, 30,
+ 33, 21, 38, 200, 37, 199, 35, 51, 51, 35,
- 102, 62, 102, 66, 196, 102, 67, 106, 107, 194,
- 107, 48, 193, 107, 106, 114, 114, 192, 137, 189,
- 137, 188, 106, 137, 202, 202, 203, 203, 204, 204,
- 204, 204, 205, 185, 205, 205, 184, 181, 180, 179,
- 177, 176, 174, 173, 172, 171, 170, 169, 168, 164,
- 163, 160, 159, 158, 157, 155, 154, 153, 152, 151,
- 149, 148, 147, 145, 143, 142, 141, 140, 139, 138,
- 135, 134, 132, 131, 130, 129, 128, 127, 125, 124,
- 123, 122, 121, 120, 118, 117, 116, 115, 113, 109,
- 108, 104, 103, 99, 97, 96, 95, 94, 93, 92,
+ 197, 20, 63, 63, 196, 38, 67, 67, 108, 108,
+ 68, 63, 68, 68, 195, 67, 192, 108, 191, 63,
+ 49, 68, 69, 67, 69, 108, 188, 69, 69, 68,
+ 104, 187, 104, 110, 110, 104, 104, 109, 184, 109,
+ 111, 111, 109, 109, 117, 117, 137, 137, 138, 138,
+ 140, 183, 140, 141, 141, 140, 140, 142, 142, 162,
+ 162, 163, 163, 204, 182, 204, 205, 205, 205, 206,
+ 206, 206, 207, 207, 207, 207, 207, 208, 180, 208,
+ 208, 208, 209, 209, 179, 177, 176, 175, 174, 173,
+ 172, 171, 167, 166, 161, 160, 158, 157, 156, 155,
- 91, 90, 89, 88, 87, 86, 84, 83, 82, 81,
- 80, 78, 77, 76, 75, 73, 69, 63, 55, 46,
- 45, 44, 43, 42, 41, 40, 39, 38, 35, 33,
- 31, 30, 24, 18, 14, 10, 7, 3, 200, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
- 200
+ 154, 152, 151, 150, 148, 146, 145, 144, 143, 135,
+ 134, 133, 132, 131, 130, 128, 127, 126, 125, 124,
+ 123, 121, 120, 119, 118, 116, 106, 105, 101, 99,
+ 98, 97, 96, 95, 94, 93, 92, 91, 90, 89,
+ 88, 86, 85, 84, 83, 82, 80, 79, 78, 77,
+ 75, 71, 64, 56, 47, 46, 45, 44, 43, 42,
+ 41, 40, 39, 36, 34, 32, 31, 25, 14, 10,
+ 7, 3, 203, 203, 203, 203, 203, 203, 203, 203,
+ 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
+ 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
+ 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
+ 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
+ 203, 203, 203, 203, 203, 203, 203, 203
} ;
/* Table of booleans, true if rule could match eol. */
-static yyconst flex_int32_t yy_rule_can_match_eol[83] =
+static yyconst flex_int32_t yy_rule_can_match_eol[84] =
{ 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
- 1, 0, 0, };
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 0, 0, };
/* The intent behind this definition is that it'll catch
* any uses of REJECT which flex missed.
@@ -600,7 +607,7 @@
*/
#define YY_NO_UNISTD_H 1
-#line 598 "lex.sksl.c"
+#line 605 "lex.sksl.c"
#define INITIAL 0
@@ -685,10 +692,6 @@
void skslset_lineno (int line_number ,yyscan_t yyscanner );
-int skslget_column (yyscan_t yyscanner );
-
-void skslset_column (int column_no ,yyscan_t yyscanner );
-
/* Macros after this point can all be overridden by user definitions in
* section 1.
*/
@@ -731,7 +734,7 @@
/* This used to be an fputs(), but since the string might contain NUL's,
* we now use fwrite().
*/
-#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+#define ECHO fwrite( yytext, yyleng, 1, yyout )
#endif
/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
@@ -742,7 +745,7 @@
if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
{ \
int c = '*'; \
- size_t n; \
+ yy_size_t n; \
for ( n = 0; n < max_size && \
(c = getc( yyin )) != EOF && c != '\n'; ++n ) \
buf[n] = (char) c; \
@@ -828,7 +831,7 @@
#line 23 "sksl.flex"
-#line 826 "lex.sksl.c"
+#line 829 "lex.sksl.c"
if ( !yyg->yy_init )
{
@@ -881,13 +884,13 @@
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 201 )
+ if ( yy_current_state >= 204 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
++yy_cp;
}
- while ( yy_current_state != 200 );
+ while ( yy_current_state != 203 );
yy_cp = yyg->yy_last_accepting_cpos;
yy_current_state = yyg->yy_last_accepting_state;
@@ -898,7 +901,7 @@
if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
{
- int yyl;
+ yy_size_t yyl;
for ( yyl = 0; yyl < yyleng; ++yyl )
if ( yytext[yyl] == '\n' )
@@ -942,396 +945,401 @@
case 5:
YY_RULE_SETUP
#line 33 "sksl.flex"
-{ return SkSL::Token::TRUE_LITERAL; }
+{ return SkSL::Token::INT_LITERAL; }
YY_BREAK
case 6:
YY_RULE_SETUP
#line 35 "sksl.flex"
-{ return SkSL::Token::FALSE_LITERAL; }
+{ return SkSL::Token::TRUE_LITERAL; }
YY_BREAK
case 7:
YY_RULE_SETUP
#line 37 "sksl.flex"
-{ return SkSL::Token::IF; }
+{ return SkSL::Token::FALSE_LITERAL; }
YY_BREAK
case 8:
YY_RULE_SETUP
#line 39 "sksl.flex"
-{ return SkSL::Token::ELSE; }
+{ return SkSL::Token::IF; }
YY_BREAK
case 9:
YY_RULE_SETUP
#line 41 "sksl.flex"
-{ return SkSL::Token::FOR; }
+{ return SkSL::Token::ELSE; }
YY_BREAK
case 10:
YY_RULE_SETUP
#line 43 "sksl.flex"
-{ return SkSL::Token::WHILE; }
+{ return SkSL::Token::FOR; }
YY_BREAK
case 11:
YY_RULE_SETUP
#line 45 "sksl.flex"
-{ return SkSL::Token::DO; }
+{ return SkSL::Token::WHILE; }
YY_BREAK
case 12:
YY_RULE_SETUP
#line 47 "sksl.flex"
-{ return SkSL::Token::BREAK; }
+{ return SkSL::Token::DO; }
YY_BREAK
case 13:
YY_RULE_SETUP
#line 49 "sksl.flex"
-{ return SkSL::Token::CONTINUE; }
+{ return SkSL::Token::BREAK; }
YY_BREAK
case 14:
YY_RULE_SETUP
#line 51 "sksl.flex"
-{ return SkSL::Token::DISCARD; }
+{ return SkSL::Token::CONTINUE; }
YY_BREAK
case 15:
YY_RULE_SETUP
#line 53 "sksl.flex"
-{ return SkSL::Token::RETURN; }
+{ return SkSL::Token::DISCARD; }
YY_BREAK
case 16:
YY_RULE_SETUP
#line 55 "sksl.flex"
-{ return SkSL::Token::IN; }
+{ return SkSL::Token::RETURN; }
YY_BREAK
case 17:
YY_RULE_SETUP
#line 57 "sksl.flex"
-{ return SkSL::Token::OUT; }
+{ return SkSL::Token::IN; }
YY_BREAK
case 18:
YY_RULE_SETUP
#line 59 "sksl.flex"
-{ return SkSL::Token::INOUT; }
+{ return SkSL::Token::OUT; }
YY_BREAK
case 19:
YY_RULE_SETUP
#line 61 "sksl.flex"
-{ return SkSL::Token::UNIFORM; }
+{ return SkSL::Token::INOUT; }
YY_BREAK
case 20:
YY_RULE_SETUP
#line 63 "sksl.flex"
-{ return SkSL::Token::CONST; }
+{ return SkSL::Token::UNIFORM; }
YY_BREAK
case 21:
YY_RULE_SETUP
#line 65 "sksl.flex"
-{ return SkSL::Token::LOWP; }
+{ return SkSL::Token::CONST; }
YY_BREAK
case 22:
YY_RULE_SETUP
#line 67 "sksl.flex"
-{ return SkSL::Token::MEDIUMP; }
+{ return SkSL::Token::LOWP; }
YY_BREAK
case 23:
YY_RULE_SETUP
#line 69 "sksl.flex"
-{ return SkSL::Token::HIGHP; }
+{ return SkSL::Token::MEDIUMP; }
YY_BREAK
case 24:
YY_RULE_SETUP
#line 71 "sksl.flex"
-{ return SkSL::Token::FLAT; }
+{ return SkSL::Token::HIGHP; }
YY_BREAK
case 25:
YY_RULE_SETUP
#line 73 "sksl.flex"
-{ return SkSL::Token::NOPERSPECTIVE; }
+{ return SkSL::Token::FLAT; }
YY_BREAK
case 26:
YY_RULE_SETUP
#line 75 "sksl.flex"
-{ return SkSL::Token::STRUCT; }
+{ return SkSL::Token::NOPERSPECTIVE; }
YY_BREAK
case 27:
YY_RULE_SETUP
#line 77 "sksl.flex"
-{ return SkSL::Token::LAYOUT; }
+{ return SkSL::Token::STRUCT; }
YY_BREAK
case 28:
YY_RULE_SETUP
#line 79 "sksl.flex"
-{ return SkSL::Token::PRECISION; }
+{ return SkSL::Token::LAYOUT; }
YY_BREAK
case 29:
YY_RULE_SETUP
#line 81 "sksl.flex"
-{ return SkSL::Token::IDENTIFIER; }
+{ return SkSL::Token::PRECISION; }
YY_BREAK
case 30:
YY_RULE_SETUP
#line 83 "sksl.flex"
-{ return SkSL::Token::DIRECTIVE; }
+{ return SkSL::Token::IDENTIFIER; }
YY_BREAK
case 31:
YY_RULE_SETUP
#line 85 "sksl.flex"
-{ return SkSL::Token::LPAREN; }
+{ return SkSL::Token::DIRECTIVE; }
YY_BREAK
case 32:
YY_RULE_SETUP
#line 87 "sksl.flex"
-{ return SkSL::Token::RPAREN; }
+{ return SkSL::Token::LPAREN; }
YY_BREAK
case 33:
YY_RULE_SETUP
#line 89 "sksl.flex"
-{ return SkSL::Token::LBRACE; }
+{ return SkSL::Token::RPAREN; }
YY_BREAK
case 34:
YY_RULE_SETUP
#line 91 "sksl.flex"
-{ return SkSL::Token::RBRACE; }
+{ return SkSL::Token::LBRACE; }
YY_BREAK
case 35:
YY_RULE_SETUP
#line 93 "sksl.flex"
-{ return SkSL::Token::LBRACKET; }
+{ return SkSL::Token::RBRACE; }
YY_BREAK
case 36:
YY_RULE_SETUP
#line 95 "sksl.flex"
-{ return SkSL::Token::RBRACKET; }
+{ return SkSL::Token::LBRACKET; }
YY_BREAK
case 37:
YY_RULE_SETUP
#line 97 "sksl.flex"
-{ return SkSL::Token::DOT; }
+{ return SkSL::Token::RBRACKET; }
YY_BREAK
case 38:
YY_RULE_SETUP
#line 99 "sksl.flex"
-{ return SkSL::Token::COMMA; }
+{ return SkSL::Token::DOT; }
YY_BREAK
case 39:
YY_RULE_SETUP
#line 101 "sksl.flex"
-{ return SkSL::Token::PLUSPLUS; }
+{ return SkSL::Token::COMMA; }
YY_BREAK
case 40:
YY_RULE_SETUP
#line 103 "sksl.flex"
-{ return SkSL::Token::MINUSMINUS; }
+{ return SkSL::Token::PLUSPLUS; }
YY_BREAK
case 41:
YY_RULE_SETUP
#line 105 "sksl.flex"
-{ return SkSL::Token::PLUS; }
+{ return SkSL::Token::MINUSMINUS; }
YY_BREAK
case 42:
YY_RULE_SETUP
#line 107 "sksl.flex"
-{ return SkSL::Token::MINUS; }
+{ return SkSL::Token::PLUS; }
YY_BREAK
case 43:
YY_RULE_SETUP
#line 109 "sksl.flex"
-{ return SkSL::Token::STAR; }
+{ return SkSL::Token::MINUS; }
YY_BREAK
case 44:
YY_RULE_SETUP
#line 111 "sksl.flex"
-{ return SkSL::Token::SLASH; }
+{ return SkSL::Token::STAR; }
YY_BREAK
case 45:
YY_RULE_SETUP
#line 113 "sksl.flex"
-{ return SkSL::Token::PERCENT; }
+{ return SkSL::Token::SLASH; }
YY_BREAK
case 46:
YY_RULE_SETUP
#line 115 "sksl.flex"
-{ return SkSL::Token::SHL; }
+{ return SkSL::Token::PERCENT; }
YY_BREAK
case 47:
YY_RULE_SETUP
#line 117 "sksl.flex"
-{ return SkSL::Token::SHR; }
+{ return SkSL::Token::SHL; }
YY_BREAK
case 48:
YY_RULE_SETUP
#line 119 "sksl.flex"
-{ return SkSL::Token::BITWISEOR; }
+{ return SkSL::Token::SHR; }
YY_BREAK
case 49:
YY_RULE_SETUP
#line 121 "sksl.flex"
-{ return SkSL::Token::BITWISEXOR; }
+{ return SkSL::Token::BITWISEOR; }
YY_BREAK
case 50:
YY_RULE_SETUP
#line 123 "sksl.flex"
-{ return SkSL::Token::BITWISEAND; }
+{ return SkSL::Token::BITWISEXOR; }
YY_BREAK
case 51:
YY_RULE_SETUP
#line 125 "sksl.flex"
-{ return SkSL::Token::LOGICALOR; }
+{ return SkSL::Token::BITWISEAND; }
YY_BREAK
case 52:
YY_RULE_SETUP
#line 127 "sksl.flex"
-{ return SkSL::Token::LOGICALXOR; }
+{ return SkSL::Token::LOGICALOR; }
YY_BREAK
case 53:
YY_RULE_SETUP
#line 129 "sksl.flex"
-{ return SkSL::Token::LOGICALAND; }
+{ return SkSL::Token::LOGICALXOR; }
YY_BREAK
case 54:
YY_RULE_SETUP
#line 131 "sksl.flex"
-{ return SkSL::Token::NOT; }
+{ return SkSL::Token::LOGICALAND; }
YY_BREAK
case 55:
YY_RULE_SETUP
#line 133 "sksl.flex"
-{ return SkSL::Token::QUESTION; }
+{ return SkSL::Token::NOT; }
YY_BREAK
case 56:
YY_RULE_SETUP
#line 135 "sksl.flex"
-{ return SkSL::Token::COLON; }
+{ return SkSL::Token::QUESTION; }
YY_BREAK
case 57:
YY_RULE_SETUP
#line 137 "sksl.flex"
-{ return SkSL::Token::EQ; }
+{ return SkSL::Token::COLON; }
YY_BREAK
case 58:
YY_RULE_SETUP
#line 139 "sksl.flex"
-{ return SkSL::Token::EQEQ; }
+{ return SkSL::Token::EQ; }
YY_BREAK
case 59:
YY_RULE_SETUP
#line 141 "sksl.flex"
-{ return SkSL::Token::NEQ; }
+{ return SkSL::Token::EQEQ; }
YY_BREAK
case 60:
YY_RULE_SETUP
#line 143 "sksl.flex"
-{ return SkSL::Token::GT; }
+{ return SkSL::Token::NEQ; }
YY_BREAK
case 61:
YY_RULE_SETUP
#line 145 "sksl.flex"
-{ return SkSL::Token::LT; }
+{ return SkSL::Token::GT; }
YY_BREAK
case 62:
YY_RULE_SETUP
#line 147 "sksl.flex"
-{ return SkSL::Token::GTEQ; }
+{ return SkSL::Token::LT; }
YY_BREAK
case 63:
YY_RULE_SETUP
#line 149 "sksl.flex"
-{ return SkSL::Token::LTEQ; }
+{ return SkSL::Token::GTEQ; }
YY_BREAK
case 64:
YY_RULE_SETUP
#line 151 "sksl.flex"
-{ return SkSL::Token::PLUSEQ; }
+{ return SkSL::Token::LTEQ; }
YY_BREAK
case 65:
YY_RULE_SETUP
#line 153 "sksl.flex"
-{ return SkSL::Token::MINUSEQ; }
+{ return SkSL::Token::PLUSEQ; }
YY_BREAK
case 66:
YY_RULE_SETUP
#line 155 "sksl.flex"
-{ return SkSL::Token::STAREQ; }
+{ return SkSL::Token::MINUSEQ; }
YY_BREAK
case 67:
YY_RULE_SETUP
#line 157 "sksl.flex"
-{ return SkSL::Token::SLASHEQ; }
+{ return SkSL::Token::STAREQ; }
YY_BREAK
case 68:
YY_RULE_SETUP
#line 159 "sksl.flex"
-{ return SkSL::Token::PERCENTEQ; }
+{ return SkSL::Token::SLASHEQ; }
YY_BREAK
case 69:
YY_RULE_SETUP
#line 161 "sksl.flex"
-{ return SkSL::Token::SHLEQ; }
+{ return SkSL::Token::PERCENTEQ; }
YY_BREAK
case 70:
YY_RULE_SETUP
#line 163 "sksl.flex"
-{ return SkSL::Token::SHREQ; }
+{ return SkSL::Token::SHLEQ; }
YY_BREAK
case 71:
YY_RULE_SETUP
#line 165 "sksl.flex"
-{ return SkSL::Token::BITWISEOREQ; }
+{ return SkSL::Token::SHREQ; }
YY_BREAK
case 72:
YY_RULE_SETUP
#line 167 "sksl.flex"
-{ return SkSL::Token::BITWISEXOREQ; }
+{ return SkSL::Token::BITWISEOREQ; }
YY_BREAK
case 73:
YY_RULE_SETUP
#line 169 "sksl.flex"
-{ return SkSL::Token::BITWISEANDEQ; }
+{ return SkSL::Token::BITWISEXOREQ; }
YY_BREAK
case 74:
YY_RULE_SETUP
#line 171 "sksl.flex"
-{ return SkSL::Token::LOGICALOREQ; }
+{ return SkSL::Token::BITWISEANDEQ; }
YY_BREAK
case 75:
YY_RULE_SETUP
#line 173 "sksl.flex"
-{ return SkSL::Token::LOGICALXOREQ; }
+{ return SkSL::Token::LOGICALOREQ; }
YY_BREAK
case 76:
YY_RULE_SETUP
#line 175 "sksl.flex"
-{ return SkSL::Token::LOGICALANDEQ; }
+{ return SkSL::Token::LOGICALXOREQ; }
YY_BREAK
case 77:
YY_RULE_SETUP
#line 177 "sksl.flex"
-{ return SkSL::Token::SEMICOLON; }
+{ return SkSL::Token::LOGICALANDEQ; }
YY_BREAK
case 78:
YY_RULE_SETUP
#line 179 "sksl.flex"
-/* line comment */
+{ return SkSL::Token::SEMICOLON; }
YY_BREAK
case 79:
-/* rule 79 can match eol */
YY_RULE_SETUP
#line 181 "sksl.flex"
-/* block comment */
+/* line comment */
YY_BREAK
case 80:
/* rule 80 can match eol */
YY_RULE_SETUP
#line 183 "sksl.flex"
-/* whitespace */
+/* block comment */
YY_BREAK
case 81:
+/* rule 81 can match eol */
YY_RULE_SETUP
#line 185 "sksl.flex"
-{ return SkSL::Token::INVALID_TOKEN; }
+/* whitespace */
YY_BREAK
case 82:
YY_RULE_SETUP
#line 187 "sksl.flex"
+{ return SkSL::Token::INVALID_TOKEN; }
+ YY_BREAK
+case 83:
+YY_RULE_SETUP
+#line 189 "sksl.flex"
ECHO;
YY_BREAK
-#line 1329 "lex.sksl.c"
+#line 1337 "lex.sksl.c"
case YY_STATE_EOF(INITIAL):
yyterminate();
@@ -1526,7 +1534,7 @@
{ /* Not enough room in the buffer - grow it. */
/* just a shorter name for the current buffer */
- YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
int yy_c_buf_p_offset =
(int) (yyg->yy_c_buf_p - b->yy_ch_buf);
@@ -1626,7 +1634,7 @@
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 201 )
+ if ( yy_current_state >= 204 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1655,13 +1663,12 @@
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 201 )
+ if ( yy_current_state >= 204 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 200);
+ yy_is_jam = (yy_current_state == 203);
- (void)yyg;
return yy_is_jam ? 0 : yy_current_state;
}
@@ -1756,7 +1763,7 @@
case EOB_ACT_END_OF_FILE:
{
if ( skslwrap(yyscanner ) )
- return EOF;
+ return 0;
if ( ! yyg->yy_did_buffer_switch_on_eof )
YY_NEW_FILE;
@@ -2112,8 +2119,8 @@
/** Setup the input buffer state to scan the given bytes. The next call to sksllex() will
* scan from a @e copy of @a bytes.
- * @param yybytes the byte buffer to scan
- * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
*/
@@ -2121,8 +2128,7 @@
{
YY_BUFFER_STATE b;
char *buf;
- yy_size_t n;
- int i;
+ yy_size_t n, i;
/* Get memory for full buffer, including space for trailing EOB's. */
n = _yybytes_len + 2;
@@ -2268,7 +2274,7 @@
/* lineno is only valid if an input buffer exists. */
if (! YY_CURRENT_BUFFER )
- YY_FATAL_ERROR( "skslset_lineno called with no buffer" );
+ yy_fatal_error( "skslset_lineno called with no buffer" , yyscanner);
yylineno = line_number;
}
@@ -2283,7 +2289,7 @@
/* column is only valid if an input buffer exists. */
if (! YY_CURRENT_BUFFER )
- YY_FATAL_ERROR( "skslset_column called with no buffer" );
+ yy_fatal_error( "skslset_column called with no buffer" , yyscanner);
yycolumn = column_no;
}
@@ -2495,7 +2501,7 @@
#define YYTABLES_NAME "yytables"
-#line 187 "sksl.flex"
+#line 189 "sksl.flex"
diff --git a/src/sksl/sksl.flex b/src/sksl/sksl.flex
index 67b48e9..70a7718 100644
--- a/src/sksl/sksl.flex
+++ b/src/sksl/sksl.flex
@@ -30,6 +30,8 @@
{DIGIT}+ { return SkSL::Token::INT_LITERAL; }
+"0x"[0-9a-zA-Z]+ { return SkSL::Token::INT_LITERAL; }
+
true { return SkSL::Token::TRUE_LITERAL; }
false { return SkSL::Token::FALSE_LITERAL; }
diff --git a/src/sksl/sksl.include b/src/sksl/sksl.include
index bf35f22..2cb0116 100644
--- a/src/sksl/sksl.include
+++ b/src/sksl/sksl.include
@@ -244,6 +244,8 @@
$gvec4 texture($gsampler1D sampler, float P);
$gvec4 texture($gsampler1D sampler, float P, float bias);
$gvec4 texture($gsampler2D sampler, vec2 P);
+vec4 texture(samplerExternalOES sampler, vec2 P, float bias);
+vec4 texture(samplerExternalOES sampler, vec2 P);
$gvec4 texture($gsampler2D sampler, vec2 P, float bias);
$gvec4 texture($gsampler3D sampler, vec3 P);
$gvec4 texture($gsampler3D sampler, vec3 P, float bias);
@@ -464,6 +466,7 @@
vec4 texture1DProjLod(sampler1D sampler, vec2 coord, float lod);
vec4 texture1DProjLod(sampler1D sampler, vec4 coord, float lod);
vec4 texture2D(sampler2D sampler, vec2 coord);
+vec4 texture2D(samplerExternalOES sampler, vec2 coord);
vec4 texture2D(sampler2D sampler, vec2 coord, float bias);
vec4 texture2DProj(sampler2D sampler, vec3 coord);
vec4 texture2DProj(sampler2D sampler, vec3 coord, float bias);
diff --git a/src/sksl/sksl_frag.include b/src/sksl/sksl_frag.include
index b4047fe..98ea65f 100644
--- a/src/sksl/sksl_frag.include
+++ b/src/sksl/sksl_frag.include
@@ -4,4 +4,16 @@
layout(builtin=15) in vec4 gl_FragCoord;
+// 9999 is a temporary value that causes us to ignore these declarations beyond
+// adding them to the symbol table. This works fine in GLSL (where they do not
+// require any further handling) but will fail in SPIR-V. We'll have a better
+// solution for this soon.
+layout(builtin=9999) vec4 gl_LastFragData[1];
+layout(builtin=9999) vec4 gl_LastFragColor;
+layout(builtin=9999) vec4 gl_LastFragColorARM;
+layout(builtin=9999) int gl_SampleMaskIn[];
+layout(builtin=9999) out int gl_SampleMask[];
+
+layout(location=0,index=0,builtin=10001) out vec4 sk_FragColor;
+
)
\ No newline at end of file
diff --git a/tests/SkSLErrorTest.cpp b/tests/SkSLErrorTest.cpp
index 75fa20d..400ab6d 100644
--- a/tests/SkSLErrorTest.cpp
+++ b/tests/SkSLErrorTest.cpp
@@ -263,8 +263,8 @@
"void main() { int x = 2[0]; }",
"error: 1: expected array, but found 'int'\n1 error\n");
test_failure(r,
- "void main() { vec2 x = vec2(0); int y = x[0]; }",
- "error: 1: expected array, but found 'vec2'\n1 error\n");
+ "void main() { vec2 x = vec2(0); int y = x[0][0]; }",
+ "error: 1: expected array, but found 'float'\n1 error\n");
}
DEF_TEST(SkSLTernaryMismatch, r) {
diff --git a/tests/SkSLGLSLTest.cpp b/tests/SkSLGLSLTest.cpp
index 3906f67..af9fd83 100644
--- a/tests/SkSLGLSLTest.cpp
+++ b/tests/SkSLGLSLTest.cpp
@@ -26,46 +26,52 @@
}
}
+static SkSL::GLCaps default_caps() {
+ return {
+ 400,
+ SkSL::GLCaps::kGL_Standard,
+ false, // isCoreProfile
+ false, // usesPrecisionModifiers;
+ false, // mustDeclareFragmentShaderOutput
+ true // canUseMinAndAbsTogether
+ };
+}
+
DEF_TEST(SkSLHelloWorld, r) {
- SkSL::GLCaps caps = { 400, SkSL::GLCaps::kGL_Standard };
test(r,
- "out vec4 fragColor; void main() { fragColor = vec4(0.75); }",
- caps,
+ "void main() { sk_FragColor = vec4(0.75); }",
+ default_caps(),
"#version 400\n"
- "out vec4 fragColor;\n"
"void main() {\n"
- " fragColor = vec4(0.75);\n"
+ " gl_FragColor = vec4(0.75);\n"
"}\n");
}
DEF_TEST(SkSLControl, r) {
- SkSL::GLCaps caps = { 400, SkSL::GLCaps::kGL_Standard };
test(r,
- "out vec4 fragColor;"
"void main() {"
- "if (1 + 2 + 3 > 5) { fragColor = vec4(0.75); } else { discard; }"
+ "if (1 + 2 + 3 > 5) { sk_FragColor = vec4(0.75); } else { discard; }"
"int i = 0;"
- "while (i < 10) fragColor *= 0.5;"
- "do { fragColor += 0.01; } while (fragColor.x < 0.7);"
+ "while (i < 10) sk_FragColor *= 0.5;"
+ "do { sk_FragColor += 0.01; } while (sk_FragColor.x < 0.7);"
"for (int i = 0; i < 10; i++) {"
"if (i % 0 == 1) break; else continue;"
"}"
"return;"
"}",
- caps,
+ default_caps(),
"#version 400\n"
- "out vec4 fragColor;\n"
"void main() {\n"
" if ((1 + 2) + 3 > 5) {\n"
- " fragColor = vec4(0.75);\n"
+ " gl_FragColor = vec4(0.75);\n"
" } else {\n"
" discard;\n"
" }\n"
" int i = 0;\n"
- " while (i < 10) fragColor *= 0.5;\n"
+ " while (i < 10) gl_FragColor *= 0.5;\n"
" do {\n"
- " fragColor += 0.01;\n"
- " } while (fragColor.x < 0.7);\n"
+ " gl_FragColor += 0.01;\n"
+ " } while (gl_FragColor.x < 0.7);\n"
" for (int i = 0;i < 10; i++) {\n"
" if (i % 0 == 1) break; else continue;\n"
" }\n"
@@ -74,34 +80,30 @@
}
DEF_TEST(SkSLFunctions, r) {
- SkSL::GLCaps caps = { 400, SkSL::GLCaps::kGL_Standard };
test(r,
- "out vec4 fragColor;"
"float foo(float v[2]) { return v[0] * v[1]; }"
"void bar(inout float x) { float y[2], z; y[0] = x; y[1] = x * 2; z = foo(y); x = z; }"
- "void main() { float x = 10; bar(x); fragColor = vec4(x); }",
- caps,
+ "void main() { float x = 10; bar(x); sk_FragColor = vec4(x); }",
+ default_caps(),
"#version 400\n"
- "out vec4 fragColor;\n"
- "float foo(in float[2] v) {\n"
+ "float foo(in float v[2]) {\n"
" return v[0] * v[1];\n"
"}\n"
"void bar(inout float x) {\n"
" float y[2], z;\n"
" y[0] = x;\n"
- " y[1] = x * 2;\n"
+ " y[1] = x * 2.0;\n"
" z = foo(y);\n"
" x = z;\n"
"}\n"
"void main() {\n"
- " float x = 10;\n"
+ " float x = 10.0;\n"
" bar(x);\n"
- " fragColor = vec4(x);\n"
+ " gl_FragColor = vec4(x);\n"
"}\n");
}
DEF_TEST(SkSLOperators, r) {
- SkSL::GLCaps caps = { 400, SkSL::GLCaps::kGL_Standard };
test(r,
"void main() {"
"float x = 1, y = 2;"
@@ -123,17 +125,17 @@
"z <<= 4;"
"z %= 5;"
"}",
- caps,
+ default_caps(),
"#version 400\n"
"void main() {\n"
- " float x = 1, y = 2;\n"
+ " float x = 1.0, y = 2.0;\n"
" int z = 3;\n"
" x = x + ((y * float(z)) * x) * (y - float(z));\n"
" y = (x / y) / float(z);\n"
" z = (((z / 2) % 3 << 4) >> 2) << 1;\n"
- " bool b = x > 4 == x < 2 || (2 >= 5 && y <= float(z)) && 12 != 11;\n"
- " x += 12;\n"
- " x -= 12;\n"
+ " bool b = x > 4.0 == x < 2.0 || (2 >= 5 && y <= float(z)) && 12 != 11;\n"
+ " x += 12.0;\n"
+ " x -= 12.0;\n"
" x *= (y /= float(z = 10));\n"
" b ||= false;\n"
" b &&= true;\n"
@@ -148,7 +150,6 @@
}
DEF_TEST(SkSLMatrices, r) {
- SkSL::GLCaps caps = { 400, SkSL::GLCaps::kGL_Standard };
test(r,
"void main() {"
"mat2x4 x = mat2x4(1);"
@@ -157,19 +158,18 @@
"vec3 v1 = mat3(1) * vec3(1);"
"vec3 v2 = vec3(1) * mat3(1);"
"}",
- caps,
+ default_caps(),
"#version 400\n"
"void main() {\n"
- " mat2x4 x = mat2x4(1);\n"
- " mat3x2 y = mat3x2(1, 0, 0, 1, vec2(2, 2));\n"
+ " mat2x4 x = mat2x4(1.0);\n"
+ " mat3x2 y = mat3x2(1.0, 0.0, 0.0, 1.0, vec2(2.0, 2.0));\n"
" mat3x4 z = x * y;\n"
- " vec3 v1 = mat3(1) * vec3(1);\n"
- " vec3 v2 = vec3(1) * mat3(1);\n"
+ " vec3 v1 = mat3(1.0) * vec3(1.0);\n"
+ " vec3 v2 = vec3(1.0) * mat3(1.0);\n"
"}\n");
}
DEF_TEST(SkSLInterfaceBlock, r) {
- SkSL::GLCaps caps = { 400, SkSL::GLCaps::kGL_Standard };
test(r,
"uniform testBlock {"
"float x;"
@@ -179,12 +179,12 @@
"};"
"void main() {"
"}",
- caps,
+ default_caps(),
"#version 400\n"
"uniform testBlock {\n"
" float x;\n"
" float[2] y;\n"
- " layout (binding = 12)mat3x2 z;\n"
+ " layout (binding = 12) mat3x2 z;\n"
" bool w;\n"
"};\n"
"void main() {\n"
@@ -192,7 +192,6 @@
}
DEF_TEST(SkSLStructs, r) {
- SkSL::GLCaps caps = { 400, SkSL::GLCaps::kGL_Standard };
test(r,
"struct A {"
"int x;"
@@ -207,7 +206,7 @@
"B b1, b2, b3;"
"void main() {"
"}",
- caps,
+ default_caps(),
"#version 400\n"
"struct A {\n"
" int x;\n"
@@ -218,10 +217,149 @@
"struct B {\n"
" float x;\n"
" float[2] y;\n"
- " layout (binding = 1)A z;\n"
+ " layout (binding = 1) A z;\n"
"}\n"
" b1, b2, b3;\n"
"void main() {\n"
"}\n");
+}
+DEF_TEST(SkSLVersion, r) {
+ SkSL::GLCaps caps = default_caps();
+ caps.fVersion = 450;
+ caps.fIsCoreProfile = true;
+ test(r,
+ "in float test; void main() { sk_FragColor = vec4(0.75); }",
+ caps,
+ "#version 450 core\n"
+ "in float test;\n"
+ "void main() {\n"
+ " gl_FragColor = vec4(0.75);\n"
+ "}\n");
+ caps.fVersion = 110;
+ caps.fIsCoreProfile = false;
+ test(r,
+ "in float test; void main() { sk_FragColor = vec4(0.75); }",
+ caps,
+ "#version 110\n"
+ "varying float test;\n"
+ "void main() {\n"
+ " gl_FragColor = vec4(0.75);\n"
+ "}\n");
+}
+
+DEF_TEST(SkSLDeclareOutput, r) {
+ SkSL::GLCaps caps = default_caps();
+ caps.fMustDeclareFragmentShaderOutput = true;
+ test(r,
+ "void main() { sk_FragColor = vec4(0.75); }",
+ caps,
+ "#version 400\n"
+ "out vec4 sk_FragColor;\n"
+ "void main() {\n"
+ " sk_FragColor = vec4(0.75);\n"
+ "}\n");
+}
+
+DEF_TEST(SkSLUsesPrecisionModifiers, r) {
+ SkSL::GLCaps caps = default_caps();
+ test(r,
+ "void main() { float x = 0.75; highp float y = 1; }",
+ caps,
+ "#version 400\n"
+ "void main() {\n"
+ " float x = 0.75;\n"
+ " float y = 1.0;\n"
+ "}\n");
+ caps.fStandard = SkSL::GLCaps::kGLES_Standard;
+ caps.fUsesPrecisionModifiers = true;
+ test(r,
+ "void main() { float x = 0.75; highp float y = 1; }",
+ caps,
+ "#version 400 es\n"
+ "precision mediump float;\n"
+ "void main() {\n"
+ " float x = 0.75;\n"
+ " highp float y = 1.0;\n"
+ "}\n");
+}
+
+DEF_TEST(SkSLMinAbs, r) {
+ test(r,
+ "void main() {"
+ "float x = -5;"
+ "x = min(abs(x), 6);"
+ "}",
+ default_caps(),
+ "#version 400\n"
+ "void main() {\n"
+ " float x = -5.0;\n"
+ " x = min(abs(x), 6.0);\n"
+ "}\n");
+
+ SkSL::GLCaps caps = default_caps();
+ caps.fCanUseMinAndAbsTogether = false;
+ test(r,
+ "void main() {"
+ "float x = -5.0;"
+ "x = min(abs(x), 6.0);"
+ "}",
+ caps,
+ "#version 400\n"
+ "void main() {\n"
+ " float minAbsHackVar0;\n"
+ " float x = -5.0;\n"
+ " x = (abs(x) > (minAbsHackVar0 = 6.0) ? minAbsHackVar0 : abs(x));\n"
+ "}\n");
+}
+
+DEF_TEST(SkSLModifiersDeclaration, r) {
+ test(r,
+ "layout(blend_support_all_equations) out;"
+ "void main() { }",
+ default_caps(),
+ "#version 400\n"
+ "layout (blend_support_all_equations) out ;\n"
+ "void main() {\n"
+ "}\n");
+}
+
+DEF_TEST(SkSLHex, r) {
+ test(r,
+ "void main() {"
+ "int i1 = 0x0;"
+ "int i2 = 0x1234abcd;"
+ "int i3 = 0x7fffffff;"
+ "int i4 = 0xffffffff;"
+ "int i5 = -0xbeef;"
+ "uint u1 = 0x0;"
+ "uint u2 = 0x1234abcd;"
+ "uint u3 = 0x7fffffff;"
+ "uint u4 = 0xffffffff;"
+ "}",
+ default_caps(),
+ "#version 400\n"
+ "void main() {\n"
+ " int i1 = 0;\n"
+ " int i2 = 305441741;\n"
+ " int i3 = 2147483647;\n"
+ " int i4 = -1;\n"
+ " int i5 = -48879;\n"
+ " uint u1 = 0u;\n"
+ " uint u2 = 305441741u;\n"
+ " uint u3 = 2147483647u;\n"
+ " uint u4 = 4294967295u;\n"
+ "}\n");
+}
+
+DEF_TEST(SkSLArrayConstructors, r) {
+ test(r,
+ "float test1[] = float[](1, 2, 3, 4);"
+ "vec2 test2[] = vec2[](vec2(1, 2), vec2(3, 4));"
+ "mat4 test3[] = mat4[]();",
+ default_caps(),
+ "#version 400\n"
+ "float test1[] = float[](1.0, 2.0, 3.0, 4.0);\n"
+ "vec2 test2[] = vec2[](vec2(1.0, 2.0), vec2(3.0, 4.0));\n"
+ "mat4 test3[] = mat4[]();\n");
}