],
'all_dependent_settings': {
'include_dirs': [
- '<(skia_src_path)/sksl',
+ '../src/sksl',
],
},
},
#include "GrGLContext.h"
#include "GrGLGLSL.h"
-#include "SkSLCompiler.h"
////////////////////////////////////////////////////////////////////////////////
return new GrGLContext(args);
}
-GrGLContext::~GrGLContext() {
- delete fCompiler;
-}
-
-SkSL::Compiler* GrGLContext::compiler() {
- if (!fCompiler) {
- fCompiler = new SkSL::Compiler();
- }
- return fCompiler;
-}
-
GrGLContextInfo::GrGLContextInfo(const ConstructorArgs& args) {
fInterface.reset(SkRef(args.fInterface));
fGLVersion = args.fGLVersion;
#include "GrGLUtil.h"
struct GrContextOptions;
-namespace SkSL {
- class Compiler;
-}
/**
* Encapsulates information about an OpenGL context including the OpenGL
const GrGLExtensions& extensions() const { return fInterface->fExtensions; }
- virtual ~GrGLContextInfo() {}
-
protected:
struct ConstructorArgs {
const GrGLInterface* fInterface;
};
/**
- * Extension of GrGLContextInfo that also provides access to GrGLInterface and SkSL::Compiler.
+ * Extension of GrGLContextInfo that also provides access to GrGLInterface.
*/
class GrGLContext : public GrGLContextInfo {
public:
const GrGLInterface* interface() const { return fInterface; }
- SkSL::Compiler* compiler();
-
- ~GrGLContext() override;
-
private:
- GrGLContext(const ConstructorArgs& args)
- : INHERITED(args)
- , fCompiler(nullptr) {}
-
- SkSL::Compiler* fCompiler;
+ GrGLContext(const ConstructorArgs& args) : INHERITED(args) {}
typedef GrGLContextInfo INHERITED;
};
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() {"
- " sk_FragColor = %s(u_texture, v_texCoord);"
+ " %s = %s(u_texture, v_texCoord);"
"}",
+ fsOutName,
GrGLSLTexture2DFunctionName(kVec2f_GrSLType, kSamplerTypes[progIdx], this->glslGeneration())
);
}
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());
if (oddWidth && oddHeight) {
fshaderTxt.appendf(
- " 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
+ " %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
);
} else if (oddWidth || oddHeight) {
fshaderTxt.appendf(
- " sk_FragColor = (%s(u_texture, v_texCoord0) + %s(u_texture, v_texCoord1)) * 0.5;",
- sampleFunction, sampleFunction
+ " %s = (%s(u_texture, v_texCoord0) + %s(u_texture, v_texCoord1)) * 0.5;",
+ fsOutName, sampleFunction, sampleFunction
);
} else {
fshaderTxt.appendf(
- " sk_FragColor = %s(u_texture, v_texCoord0);",
- sampleFunction
+ " %s = %s(u_texture, v_texCoord0);",
+ fsOutName, sampleFunction
);
}
&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() {"
- " sk_FragColor = %s;"
+ " %s = %s;"
"}",
+ fsOutName,
uColor.c_str()
);
#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)
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;
-}
-
GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx,
GrGLuint programId,
GrGLenum type,
return 0;
}
- std::string sksl;
#ifdef SK_DEBUG
SkString prettySource = GrGLSLPrettyPrint::PrettyPrintGLSL(strings, lengths, count, false);
- sksl = std::string(prettySource.c_str());
+ const GrGLchar* sourceStr = prettySource.c_str();
+ GrGLint sourceLength = static_cast<GrGLint>(prettySource.size());
+ GR_GL_CALL(gli, ShaderSource(shaderId, 1, &sourceStr, &sourceLength));
#else
- for (int i = 0; i < count; i++) {
- sksl.append(strings[i], lengths[i]);
- }
+ GR_GL_CALL(gli, ShaderSource(shaderId, count, strings, lengths));
#endif
- std::string glsl;
- // creating Compiler is expensive, and we are single-threaded anyway, so just reuse a static one
- static SkSL::Compiler 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);
- SkASSERTF(result, "SkSL errors:\n%s", compiler.errorText().c_str());
- 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);
}
const char* GrGLSLFragmentShaderBuilder::getPrimaryColorOutputName() const {
- return fHasCustomColorOutput ? DeclaredColorOutputName() : "sk_FragColor";
+ return fHasCustomColorOutput ? DeclaredColorOutputName() : "gl_FragColor";
}
void GrGLSLFragmentBuilder::declAppendf(const char* fmt, ...) {
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
+++ /dev/null
-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 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)
-* 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.
* 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:
#include "ir/SkSLIndexExpression.h"
#include "ir/SkSLVariableReference.h"
-#define SK_FRAGCOLOR_BUILTIN 10001
-
namespace SkSL {
void GLSLCodeGenerator::write(const char* s) {
this->writeLine("struct " + type.name() + " {");
fIndentation++;
for (const auto& f : type.fields()) {
- this->writeModifiers(f.fModifiers, false);
+ this->writeModifiers(f.fModifiers);
// sizes (which must be static in structs) are part of the type name here
this->writeType(*f.fType);
this->writeLine(" " + f.fName + ";");
}
}
-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) {
}
void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) {
- 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);
- }
+ this->write(ref.fVariable.fName);
}
void GLSLCodeGenerator::writeIndexExpression(const IndexExpression& expr) {
for (const auto& param : f.fDeclaration.fParameters) {
this->write(separator);
separator = ", ";
- this->writeModifiers(param->fModifiers, false);
+ this->writeModifiers(param->fModifiers);
this->writeType(param->fType);
this->write(" " + param->fName);
}
- 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());
+ this->write(") ");
+ this->writeBlock(*f.fBody);
+ this->writeLine();
}
-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) {
- bool modifier = false;
- if (modifiers.fFlags & Modifiers::kLowp_Flag) {
- this->write("lowp ");
- modifier = true;
- }
- if (modifiers.fFlags & Modifiers::kHighp_Flag) {
- this->write("highp ");
- modifier = true;
- }
- if (!modifier) {
- this->write("mediump ");
- }
- }
+void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers) {
+ this->write(modifiers.description());
}
void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
if (intf.fVariable.fName == "gl_PerVertex") {
return;
}
- this->writeModifiers(intf.fVariable.fModifiers, true);
+ this->writeModifiers(intf.fVariable.fModifiers);
this->writeLine(intf.fVariable.fType.name() + " {");
fIndentation++;
for (const auto& f : intf.fVariable.fType.fields()) {
- this->writeModifiers(f.fModifiers, false);
+ this->writeModifiers(f.fModifiers);
this->writeType(*f.fType);
this->writeLine(" " + f.fName + ";");
}
this->writeLine("};");
}
-void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool global) {
+void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl) {
ASSERT(decl.fVars.size() > 0);
- this->writeModifiers(decl.fVars[0].fVar->fModifiers, global);
+ this->writeModifiers(decl.fVars[0].fVar->fModifiers);
this->writeType(decl.fBaseType);
std::string separator = " ";
for (const auto& var : decl.fVars) {
this->writeReturnStatement((ReturnStatement&) s);
break;
case Statement::kVarDeclarations_Kind:
- this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration, false);
+ this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
break;
case Statement::kIf_Kind:
this->writeIfStatement((IfStatement&) s);
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) {
this->write(" es");
- } else if (fCaps.fIsCoreProfile) {
- this->write(" core");
}
this->writeLine();
for (const auto& e : program.fElements) {
break;
case ProgramElement::kVar_Kind: {
VarDeclarations& decl = (VarDeclarations&) *e;
- 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->writeLine("out vec4 sk_FragColor;");
- }
+ if (decl.fVars.size() > 0 &&
+ decl.fVars[0].fVar->fModifiers.fLayout.fBuiltin == -1) {
+ this->writeVarDeclarations(decl);
+ this->writeLine();
}
break;
}
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;
};
/**
GLSLCodeGenerator(const Context* context, GLCaps caps)
: fContext(*context)
, fCaps(caps)
- , fVarCount(0)
, fIndentation(0)
, fAtLineStart(true) {}
void writeLayout(const Layout& layout);
- void writeModifiers(const Modifiers& modifiers, bool globalContext);
+ void writeModifiers(const Modifiers& modifiers);
void writeGlobalVars(const VarDeclaration& vs);
- void writeVarDeclarations(const VarDeclarations& decl, bool global);
+ void writeVarDeclarations(const VarDeclarations& decl);
void writeVariableReference(const VariableReference& ref);
void writeIntrinsicCall(const FunctionCall& c);
- void writeMinAbsHack(Expression& absExpr, Expression& otherExpr);
-
void writeFunctionCall(const FunctionCall& c);
void writeConstructor(const Constructor& c);
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
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((uint64_t) i + 1) +
- " differ between declaration and "
- "definition");
+ to_string(i + 1) + " differ between " +
+ "declaration and definition");
return nullptr;
}
}
ASSERT(ctor);
return this->call(Position(), std::move(ctor), std::move(args));
}
- 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)));
+ ABORT("cannot coerce %s to %s", expr->fType.description().c_str(),
+ type.description().c_str());
}
static bool is_matrix_multiply(const Type& left, const Type& right) {
std::vector<std::unique_ptr<Expression>> arguments) {
if (function.fParameters.size() != arguments.size()) {
std::string msg = "call to '" + function.fName + "' expected " +
- to_string((uint64_t) function.fParameters.size()) +
+ to_string(function.fParameters.size()) +
" argument";
if (function.fParameters.size() != 1) {
msg += "s";
}
- msg += ", but found " + to_string((uint64_t) arguments.size());
+ msg += ", but found " + to_string(arguments.size());
fErrors.error(position, msg);
return nullptr;
}
if (args.size() != 1) {
fErrors.error(position, "invalid arguments to '" + type.description() +
"' constructor, (expected exactly 1 argument, but found " +
- to_string((uint64_t) args.size()) + ")");
+ to_string(args.size()) + ")");
}
if (args[0]->fType == *fContext.fBool_Type) {
std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, position, 0));
this->expect(Token::SEMICOLON, "';'");
}
-/* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? |
- DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */
+/* DIRECTIVE(#version) INT_LITERAL | DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */
std::unique_ptr<ASTDeclaration> Parser::directive() {
Token start;
if (!this->expect(Token::DIRECTIVE, "a directive", &start)) {
}
if (start.fText == "#version") {
this->expect(Token::INT_LITERAL, "a version number");
- 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
+ // ignored for now
return nullptr;
} else if (start.fText == "#extension") {
Token name;
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) {
return atoi(s.c_str());
}
// our own definitions of certain std:: functions, because they are not always present on Android
-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);
+template <typename T> std::string to_string(T value) {
+ std::stringstream buffer;
+ buffer << std::setprecision(std::numeric_limits<T>::digits10) << value;
+ return buffer.str();
+}
#if _MSC_VER
#define NORETURN __declspec(noreturn)
layout(builtin=15) in vec4 gl_FragCoord;
-layout(builtin=10001) vec4 sk_FragColor;
-
)
\ No newline at end of file
}
}
-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,
- "void main() { sk_FragColor = vec4(0.75); }",
- default_caps(),
+ "out vec4 fragColor; void main() { fragColor = vec4(0.75); }",
+ caps,
"#version 400\n"
+ "out vec4 fragColor;\n"
"void main() {\n"
- " gl_FragColor = vec4(0.75);\n"
+ " 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) { sk_FragColor = vec4(0.75); } else { discard; }"
+ "if (1 + 2 + 3 > 5) { fragColor = vec4(0.75); } else { discard; }"
"int i = 0;"
- "while (i < 10) sk_FragColor *= 0.5;"
- "do { sk_FragColor += 0.01; } while (sk_FragColor.x < 0.7);"
+ "while (i < 10) fragColor *= 0.5;"
+ "do { fragColor += 0.01; } while (fragColor.x < 0.7);"
"for (int i = 0; i < 10; i++) {"
"if (i % 0 == 1) break; else continue;"
"}"
"return;"
"}",
- default_caps(),
+ caps,
"#version 400\n"
+ "out vec4 fragColor;\n"
"void main() {\n"
" if ((1 + 2) + 3 > 5) {\n"
- " gl_FragColor = vec4(0.75);\n"
+ " fragColor = vec4(0.75);\n"
" } else {\n"
" discard;\n"
" }\n"
" int i = 0;\n"
- " while (i < 10) gl_FragColor *= 0.5;\n"
+ " while (i < 10) fragColor *= 0.5;\n"
" do {\n"
- " gl_FragColor += 0.01;\n"
- " } while (gl_FragColor.x < 0.7);\n"
+ " fragColor += 0.01;\n"
+ " } while (fragColor.x < 0.7);\n"
" for (int i = 0;i < 10; i++) {\n"
" if (i % 0 == 1) break; else continue;\n"
" }\n"
}
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); sk_FragColor = vec4(x); }",
- default_caps(),
+ "void main() { float x = 10; bar(x); fragColor = vec4(x); }",
+ caps,
"#version 400\n"
+ "out vec4 fragColor;\n"
"float foo(in float[2] v) {\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.0;\n"
+ " y[1] = x * 2;\n"
" z = foo(y);\n"
" x = z;\n"
"}\n"
"void main() {\n"
- " float x = 10.0;\n"
+ " float x = 10;\n"
" bar(x);\n"
- " gl_FragColor = vec4(x);\n"
+ " 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;"
"z <<= 4;"
"z %= 5;"
"}",
- default_caps(),
+ caps,
"#version 400\n"
"void main() {\n"
- " float x = 1.0, y = 2.0;\n"
+ " float x = 1, y = 2;\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.0 == x < 2.0 || (2 >= 5 && y <= float(z)) && 12 != 11;\n"
- " x += 12.0;\n"
- " x -= 12.0;\n"
+ " bool b = x > 4 == x < 2 || (2 >= 5 && y <= float(z)) && 12 != 11;\n"
+ " x += 12;\n"
+ " x -= 12;\n"
" x *= (y /= float(z = 10));\n"
" b ||= false;\n"
" b &&= true;\n"
}
DEF_TEST(SkSLMatrices, r) {
+ SkSL::GLCaps caps = { 400, SkSL::GLCaps::kGL_Standard };
test(r,
"void main() {"
"mat2x4 x = mat2x4(1);"
"vec3 v1 = mat3(1) * vec3(1);"
"vec3 v2 = vec3(1) * mat3(1);"
"}",
- default_caps(),
+ caps,
"#version 400\n"
"void main() {\n"
- " mat2x4 x = mat2x4(1.0);\n"
- " mat3x2 y = mat3x2(1.0, 0.0, 0.0, 1.0, vec2(2.0, 2.0));\n"
+ " mat2x4 x = mat2x4(1);\n"
+ " mat3x2 y = mat3x2(1, 0, 0, 1, vec2(2, 2));\n"
" mat3x4 z = x * y;\n"
- " vec3 v1 = mat3(1.0) * vec3(1.0);\n"
- " vec3 v2 = vec3(1.0) * mat3(1.0);\n"
+ " vec3 v1 = mat3(1) * vec3(1);\n"
+ " vec3 v2 = vec3(1) * mat3(1);\n"
"}\n");
}
DEF_TEST(SkSLInterfaceBlock, r) {
+ SkSL::GLCaps caps = { 400, SkSL::GLCaps::kGL_Standard };
test(r,
"uniform testBlock {"
"float x;"
"};"
"void main() {"
"}",
- default_caps(),
+ 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"
}
DEF_TEST(SkSLStructs, r) {
+ SkSL::GLCaps caps = { 400, SkSL::GLCaps::kGL_Standard };
test(r,
"struct A {"
"int x;"
"B b1, b2, b3;"
"void main() {"
"}",
- default_caps(),
+ caps,
"#version 400\n"
"struct A {\n"
" int x;\n"
"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.fUsesPrecisionModifiers = true;
- test(r,
- "void main() { float x = 0.75; highp float y = 1; }",
- caps,
- "#version 400\n"
- "void main() {\n"
- " mediump 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");
}