diff options
Diffstat (limited to 'src/sksl')
-rw-r--r-- | src/sksl/SkSLCodeGenerator.h | 13 | ||||
-rw-r--r-- | src/sksl/SkSLCompiler.cpp | 108 | ||||
-rw-r--r-- | src/sksl/SkSLCompiler.h | 30 | ||||
-rw-r--r-- | src/sksl/SkSLErrorReporter.h | 2 | ||||
-rw-r--r-- | src/sksl/SkSLGLSLCodeGenerator.cpp | 118 | ||||
-rw-r--r-- | src/sksl/SkSLGLSLCodeGenerator.h | 27 | ||||
-rw-r--r-- | src/sksl/SkSLIRGenerator.cpp | 44 | ||||
-rw-r--r-- | src/sksl/SkSLIRGenerator.h | 12 | ||||
-rw-r--r-- | src/sksl/SkSLMain.cpp | 9 | ||||
-rw-r--r-- | src/sksl/SkSLSPIRVCodeGenerator.cpp | 105 | ||||
-rw-r--r-- | src/sksl/SkSLSPIRVCodeGenerator.h | 28 | ||||
-rw-r--r-- | src/sksl/SkSLUtil.h | 15 | ||||
-rw-r--r-- | src/sksl/ir/SkSLProgram.h | 43 | ||||
-rw-r--r-- | src/sksl/sksl_frag.include | 2 |
14 files changed, 181 insertions, 375 deletions
diff --git a/src/sksl/SkSLCodeGenerator.h b/src/sksl/SkSLCodeGenerator.h index 111e73a139..ed93778e13 100644 --- a/src/sksl/SkSLCodeGenerator.h +++ b/src/sksl/SkSLCodeGenerator.h @@ -18,20 +18,9 @@ namespace SkSL { */ class CodeGenerator { public: - CodeGenerator(const Program* program, ErrorReporter* errors, SkWStream* out) - : fProgram(*program) - , fErrors(*errors) - , fOut(out) {} - virtual ~CodeGenerator() {} - virtual bool generateCode() = 0; - -protected: - - const Program& fProgram; - ErrorReporter& fErrors; - SkWStream* fOut; + virtual void generateCode(const Program& program, ErrorReporter& errors, SkWStream& out) = 0; }; } // namespace diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp index 9faf836156..1be0ba988a 100644 --- a/src/sksl/SkSLCompiler.cpp +++ b/src/sksl/SkSLCompiler.cpp @@ -9,7 +9,6 @@ #include "ast/SkSLASTPrecision.h" #include "SkSLCFGGenerator.h" -#include "SkSLGLSLCodeGenerator.h" #include "SkSLIRGenerator.h" #include "SkSLParser.h" #include "SkSLSPIRVCodeGenerator.h" @@ -393,10 +392,10 @@ void Compiler::internalConvertProgram(SkString text, } std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, SkString text, - const Program::Settings& settings) { + std::unordered_map<SkString, CapValue> caps) { fErrorText = ""; fErrorCount = 0; - fIRGenerator->start(&settings); + fIRGenerator->start(&caps); std::vector<std::unique_ptr<ProgramElement>> elements; Modifiers::Flag ignored; switch (kind) { @@ -410,46 +409,47 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, SkString t fIRGenerator->fSymbolTable->markAllFunctionsBuiltin(); Modifiers::Flag defaultPrecision; this->internalConvertProgram(text, &defaultPrecision, &elements); - auto result = std::unique_ptr<Program>(new Program(kind, settings, defaultPrecision, &fContext, - std::move(elements), - fIRGenerator->fSymbolTable, - fIRGenerator->fInputs)); + auto result = std::unique_ptr<Program>(new Program(kind, defaultPrecision, std::move(elements), + fIRGenerator->fSymbolTable)); fIRGenerator->finish(); this->writeErrorCount(); - if (fErrorCount) { - return nullptr; - } return result; } +void Compiler::error(Position position, SkString msg) { + fErrorCount++; + fErrorText += "error: " + position.description() + ": " + msg.c_str() + "\n"; +} -bool Compiler::toSPIRV(const Program& program, SkWStream& out) { - SPIRVCodeGenerator cg(&fContext, &program, this, &out); - bool result = cg.generateCode(); - this->writeErrorCount(); +SkString Compiler::errorText() { + SkString result = fErrorText; return result; } -bool Compiler::toSPIRV(const Program& program, SkString* out) { - SkDynamicMemoryWStream buffer; - bool result = this->toSPIRV(program, buffer); - if (result) { - sk_sp<SkData> data(buffer.detachAsData()); - *out = SkString((const char*) data->data(), data->size()); +void Compiler::writeErrorCount() { + if (fErrorCount) { + fErrorText += to_string(fErrorCount) + " error"; + if (fErrorCount > 1) { + fErrorText += "s"; + } + fErrorText += "\n"; } - return result; } -bool Compiler::toGLSL(const Program& program, SkWStream& out) { - GLSLCodeGenerator cg(&fContext, &program, this, &out); - bool result = cg.generateCode(); - this->writeErrorCount(); - return result; +bool Compiler::toSPIRV(Program::Kind kind, const SkString& text, SkWStream& out) { + std::unordered_map<SkString, CapValue> capsMap; + auto program = this->convertProgram(kind, text, capsMap); + if (fErrorCount == 0) { + SkSL::SPIRVCodeGenerator cg(&fContext); + cg.generateCode(*program.get(), *this, out); + this->writeErrorCount(); + } + return fErrorCount == 0; } -bool Compiler::toGLSL(const Program& program, SkString* out) { +bool Compiler::toSPIRV(Program::Kind kind, const SkString& text, SkString* out) { SkDynamicMemoryWStream buffer; - bool result = this->toGLSL(program, buffer); + bool result = this->toSPIRV(kind, text, buffer); if (result) { sk_sp<SkData> data(buffer.detachAsData()); *out = SkString((const char*) data->data(), data->size()); @@ -457,25 +457,49 @@ bool Compiler::toGLSL(const Program& program, SkString* out) { return result; } - -void Compiler::error(Position position, SkString msg) { - fErrorCount++; - fErrorText += "error: " + position.description() + ": " + msg.c_str() + "\n"; +static void fill_caps(const GrShaderCaps& caps, std::unordered_map<SkString, CapValue>* capsMap) { +#define CAP(name) capsMap->insert(std::make_pair(SkString(#name), CapValue(caps.name()))); + CAP(fbFetchSupport); + CAP(fbFetchNeedsCustomOutput); + CAP(bindlessTextureSupport); + CAP(dropsTileOnZeroDivide); + CAP(flatInterpolationSupport); + CAP(noperspectiveInterpolationSupport); + CAP(multisampleInterpolationSupport); + CAP(sampleVariablesSupport); + CAP(sampleMaskOverrideCoverageSupport); + CAP(externalTextureSupport); + CAP(texelFetchSupport); + CAP(imageLoadStoreSupport); + CAP(mustEnableAdvBlendEqs); + CAP(mustEnableSpecificAdvBlendEqs); + CAP(mustDeclareFragmentShaderOutput); + CAP(canUseAnyFunctionInShader); +#undef CAP } -SkString Compiler::errorText() { - SkString result = fErrorText; - return result; +bool Compiler::toGLSL(Program::Kind kind, const SkString& text, const GrShaderCaps& caps, + SkWStream& out) { + std::unordered_map<SkString, CapValue> capsMap; + fill_caps(caps, &capsMap); + auto program = this->convertProgram(kind, text, capsMap); + if (fErrorCount == 0) { + SkSL::GLSLCodeGenerator cg(&fContext, &caps); + cg.generateCode(*program.get(), *this, out); + this->writeErrorCount(); + } + return fErrorCount == 0; } -void Compiler::writeErrorCount() { - if (fErrorCount) { - fErrorText += to_string(fErrorCount) + " error"; - if (fErrorCount > 1) { - fErrorText += "s"; - } - fErrorText += "\n"; +bool Compiler::toGLSL(Program::Kind kind, const SkString& text, const GrShaderCaps& caps, + SkString* out) { + SkDynamicMemoryWStream buffer; + bool result = this->toGLSL(kind, text, caps, buffer); + if (result) { + sk_sp<SkData> data(buffer.detachAsData()); + *out = SkString((const char*) data->data(), data->size()); } + return result; } } // namespace diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h index 0f893f7e64..114f8efeba 100644 --- a/src/sksl/SkSLCompiler.h +++ b/src/sksl/SkSLCompiler.h @@ -16,9 +16,9 @@ #include "SkSLContext.h" #include "SkSLErrorReporter.h" #include "SkSLIRGenerator.h" +#include "SkSLGLSLCodeGenerator.h" #define SK_FRAGCOLOR_BUILTIN 10001 -#define SK_FRAGCOORD_BUILTIN 15 namespace SkSL { @@ -26,7 +26,7 @@ class IRGenerator; /** * Main compiler entry point. This is a traditional compiler design which first parses the .sksl - * file into an abstract syntax tree (a tree of ASTNodes), then performs semantic analysis to + * 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. * @@ -38,16 +38,18 @@ public: ~Compiler(); - std::unique_ptr<Program> convertProgram(Program::Kind kind, SkString text, - const Program::Settings& settings); + std::unique_ptr<Program> convertProgram(Program::Kind kind, SkString text, + std::unordered_map<SkString, CapValue> caps); - bool toSPIRV(const Program& program, SkWStream& out); + bool toSPIRV(Program::Kind kind, const SkString& text, SkWStream& out); + + bool toSPIRV(Program::Kind kind, const SkString& text, SkString* out); - bool toSPIRV(const Program& program, SkString* out); - - bool toGLSL(const Program& program, SkWStream& out); - - bool toGLSL(const Program& program, SkString* out); + bool toGLSL(Program::Kind kind, const SkString& text, const GrShaderCaps& caps, + SkWStream& out); + + bool toGLSL(Program::Kind kind, const SkString& text, const GrShaderCaps& caps, + SkString* out); void error(Position position, SkString msg) override; @@ -55,15 +57,11 @@ public: void writeErrorCount(); - int errorCount() override { - return fErrorCount; - } - private: void addDefinition(const Expression* lvalue, const Expression* expr, std::unordered_map<const Variable*, const Expression*>* definitions); - - void addDefinitions(const BasicBlock::Node& node, + + void addDefinitions(const BasicBlock::Node& node, std::unordered_map<const Variable*, const Expression*>* definitions); void scanCFG(CFG* cfg, BlockId block, std::set<BlockId>* workList); diff --git a/src/sksl/SkSLErrorReporter.h b/src/sksl/SkSLErrorReporter.h index 85d386d49c..585a97cc51 100644 --- a/src/sksl/SkSLErrorReporter.h +++ b/src/sksl/SkSLErrorReporter.h @@ -24,8 +24,6 @@ public: } virtual void error(Position position, SkString msg) = 0; - - virtual int errorCount() = 0; }; } // namespace diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp index caf6ec841d..5b747240e9 100644 --- a/src/sksl/SkSLGLSLCodeGenerator.cpp +++ b/src/sksl/SkSLGLSLCodeGenerator.cpp @@ -11,13 +11,14 @@ #include "GLSL.std.450.h" -#include "SkSLCompiler.h" #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) { @@ -133,10 +134,10 @@ static bool is_abs(Expression& expr) { return ((FunctionCall&) expr).fFunction.fName == "abs"; } -// turns min(abs(x), y) into ((tmpVar1 = abs(x)) < (tmpVar2 = y) ? tmpVar1 : tmpVar2) to avoid a +// turns min(abs(x), y) into ((tmpVar1 = abs(x)) < (tmpVar2 = y) ? tmpVar1 : tmpVar2) to avoid a // Tegra3 compiler bug. void GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherExpr) { - ASSERT(!fProgram.fSettings.fCaps->canUseMinAndAbsTogether()); + ASSERT(!fCaps.canUseMinAndAbsTogether()); SkString tmpVar1 = "minAbsHackVar" + to_string(fVarCount++); SkString tmpVar2 = "minAbsHackVar" + to_string(fVarCount++); this->fFunctionHeader += " " + absExpr.fType.name() + " " + tmpVar1 + ";\n"; @@ -149,8 +150,7 @@ void GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherEx } void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) { - if (!fProgram.fSettings.fCaps->canUseMinAndAbsTogether() && c.fFunction.fName == "min" && - c.fFunction.fBuiltin) { + if (!fCaps.canUseMinAndAbsTogether() && c.fFunction.fName == "min" && c.fFunction.fBuiltin) { ASSERT(c.fArguments.size() == 2); if (is_abs(*c.fArguments[0])) { this->writeMinAbsHack(*c.fArguments[0], *c.fArguments[1]); @@ -163,9 +163,8 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) { return; } } - if (fProgram.fSettings.fCaps->mustForceNegatedAtanParamToFloat() && - c.fFunction.fName == "atan" && - c.fFunction.fBuiltin && c.fArguments.size() == 2 && + if (fCaps.mustForceNegatedAtanParamToFloat() && c.fFunction.fName == "atan" && + c.fFunction.fBuiltin && c.fArguments.size() == 2 && c.fArguments[1]->fKind == Expression::kPrefix_Kind) { const PrefixExpression& p = (PrefixExpression&) *c.fArguments[1]; if (p.fOperator == Token::MINUS) { @@ -177,11 +176,11 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) { return; } } - if (!fFoundDerivatives && (c.fFunction.fName == "dFdx" || c.fFunction.fName == "dFdy") && - c.fFunction.fBuiltin && fProgram.fSettings.fCaps->shaderDerivativeExtensionString()) { - ASSERT(fProgram.fSettings.fCaps->shaderDerivativeSupport()); + if (!fFoundDerivatives && (c.fFunction.fName == "dFdx" || c.fFunction.fName == "dFdy") && + c.fFunction.fBuiltin && fCaps.shaderDerivativeExtensionString()) { + ASSERT(fCaps.shaderDerivativeSupport()); fHeader.writeText("#extension "); - fHeader.writeText(fProgram.fSettings.fCaps->shaderDerivativeExtensionString()); + fHeader.writeText(fCaps.shaderDerivativeExtensionString()); fHeader.writeText(" : require\n"); fFoundDerivatives = true; } @@ -236,7 +235,7 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) { break; } this->write("texture"); - if (fProgram.fSettings.fCaps->generation() < k130_GrGLSLGeneration) { + if (fCaps.generation() < k130_GrGLSLGeneration) { this->write(dim); } if (proj) { @@ -267,56 +266,15 @@ void GLSLCodeGenerator::writeConstructor(const Constructor& c) { this->write(")"); } -void GLSLCodeGenerator::writeFragCoord() { - // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers - // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the - // declaration varies in earlier GLSL specs. So it is simpler to omit it. - if (!fProgram.fSettings.fFlipY) { - fSetupFragPosition = true; - this->write("gl_FragCoord"); - } else if (const char* extension = - fProgram.fSettings.fCaps->fragCoordConventionsExtensionString()) { - if (!fSetupFragPosition) { - if (fProgram.fSettings.fCaps->generation() < k150_GrGLSLGeneration) { - fHeader.writeText("#extension "); - fHeader.writeText(extension); - fHeader.writeText(" : require\n"); - } - fHeader.writeText("layout(origin_upper_left) in vec4 gl_FragCoord;\n"); - fSetupFragPosition = true; +void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) { + if (ref.fVariable.fModifiers.fLayout.fBuiltin == SK_FRAGCOLOR_BUILTIN) { + if (fCaps.mustDeclareFragmentShaderOutput()) { + this->write("sk_FragColor"); + } else { + this->write("gl_FragColor"); } - this->write("gl_FragCoord"); } else { - if (!fSetupFragPosition) { - // The Adreno compiler seems to be very touchy about access to "gl_FragCoord". - // Accessing glFragCoord.zw can cause a program to fail to link. Additionally, - // depending on the surrounding code, accessing .xy with a uniform involved can - // do the same thing. Copying gl_FragCoord.xy into a temp vec2 beforehand - // (and only accessing .xy) seems to "fix" things. - fHeader.writeText("uniform float " SKSL_RTHEIGHT_NAME ";\n" - "highp vec2 _sktmpCoord = gl_FragCoord.xy;\n" - "highp vec4 sk_FragCoord = vec4(_sktmpCoord.x, " SKSL_RTHEIGHT_NAME - " - _sktmpCoord.y, 1.0, 1.0);\n"); - fSetupFragPosition = true; - } - this->write("sk_FragCoord"); - } -} - -void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) { - switch (ref.fVariable.fModifiers.fLayout.fBuiltin) { - case SK_FRAGCOLOR_BUILTIN: - if (fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) { - this->write("sk_FragColor"); - } else { - this->write("gl_FragColor"); - } - break; - case SK_FRAGCOORD_BUILTIN: - this->writeFragCoord(); - break; - default: - this->write(ref.fVariable.fName); + this->write(ref.fVariable.fName); } } @@ -526,16 +484,14 @@ void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers, (modifiers.fFlags & Modifiers::kOut_Flag)) { this->write("inout "); } else if (modifiers.fFlags & Modifiers::kIn_Flag) { - if (globalContext && - fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) { + if (globalContext && fCaps.generation() < GrGLSLGeneration::k130_GrGLSLGeneration) { this->write(fProgramKind == Program::kVertex_Kind ? "attribute " : "varying "); } else { this->write("in "); } } else if (modifiers.fFlags & Modifiers::kOut_Flag) { - if (globalContext && - fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) { + if (globalContext && fCaps.generation() < GrGLSLGeneration::k130_GrGLSLGeneration) { this->write("varying "); } else { this->write("out "); @@ -547,7 +503,7 @@ void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers, if (modifiers.fFlags & Modifiers::kConst_Flag) { this->write("const "); } - if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) { + if (fCaps.usesPrecisionModifiers()) { if (modifiers.fFlags & Modifiers::kLowp_Flag) { this->write("lowp "); } @@ -598,9 +554,9 @@ void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool g this->writeExpression(*var.fValue, kTopLevel_Precedence); } if (!fFoundImageDecl && var.fVar->fType == *fContext.fImage2D_Type) { - if (fProgram.fSettings.fCaps->imageLoadStoreExtensionString()) { + if (fCaps.imageLoadStoreExtensionString()) { fHeader.writeText("#extension "); - fHeader.writeText(fProgram.fSettings.fCaps->imageLoadStoreExtensionString()); + fHeader.writeText(fCaps.imageLoadStoreExtensionString()); fHeader.writeText(" : require\n"); } fFoundImageDecl = true; @@ -714,22 +670,23 @@ void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) { this->write(";"); } -bool GLSLCodeGenerator::generateCode() { - SkWStream* rawOut = fOut; +void GLSLCodeGenerator::generateCode(const Program& program, ErrorReporter& errors, + SkWStream& out) { + ASSERT(fOut == nullptr); fOut = &fHeader; - fProgramKind = fProgram.fKind; - this->write(fProgram.fSettings.fCaps->versionDeclString()); + fProgramKind = program.fKind; + this->write(fCaps.versionDeclString()); this->writeLine(); - for (const auto& e : fProgram.fElements) { + for (const auto& e : program.fElements) { if (e->fKind == ProgramElement::kExtension_Kind) { this->writeExtension((Extension&) *e); } } SkDynamicMemoryWStream body; fOut = &body; - if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) { + if (fCaps.usesPrecisionModifiers()) { this->write("precision "); - switch (fProgram.fDefaultPrecision) { + switch (program.fDefaultPrecision) { case Modifiers::kLowp_Flag: this->write("lowp"); break; @@ -745,7 +702,7 @@ bool GLSLCodeGenerator::generateCode() { } this->writeLine(" float;"); } - for (const auto& e : fProgram.fElements) { + for (const auto& e : program.fElements) { switch (e->fKind) { case ProgramElement::kExtension_Kind: break; @@ -758,9 +715,9 @@ bool GLSLCodeGenerator::generateCode() { this->writeVarDeclarations(decl, true); this->writeLine(); } else if (builtin == SK_FRAGCOLOR_BUILTIN && - fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) { + fCaps.mustDeclareFragmentShaderOutput()) { this->write("out "); - if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) { + if (fCaps.usesPrecisionModifiers()) { this->write("mediump "); } this->writeLine("vec4 sk_FragColor;"); @@ -785,9 +742,8 @@ bool GLSLCodeGenerator::generateCode() { } fOut = nullptr; - write_data(*fHeader.detachAsData(), *rawOut); - write_data(*body.detachAsData(), *rawOut); - return true; + write_data(*fHeader.detachAsData(), out); + write_data(*body.detachAsData(), out); } } diff --git a/src/sksl/SkSLGLSLCodeGenerator.h b/src/sksl/SkSLGLSLCodeGenerator.h index bb7d8b1080..ffc5a4d473 100644 --- a/src/sksl/SkSLGLSLCodeGenerator.h +++ b/src/sksl/SkSLGLSLCodeGenerator.h @@ -4,7 +4,7 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ - + #ifndef SKSL_GLSLCODEGENERATOR #define SKSL_GLSLCODEGENERATOR @@ -12,6 +12,7 @@ #include <tuple> #include <unordered_map> +#include "GrShaderCaps.h" #include "SkStream.h" #include "SkSLCodeGenerator.h" #include "ir/SkSLBinaryExpression.h" @@ -71,12 +72,11 @@ public: kTopLevel_Precedence = 18 }; - GLSLCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors, - SkWStream* out) - : INHERITED(program, errors, out) - , fContext(*context) {} + GLSLCodeGenerator(const Context* context, const GrShaderCaps* caps) + : fContext(*context) + , fCaps(*caps) {} - virtual bool generateCode() override; + void generateCode(const Program& program, ErrorReporter& errors, SkWStream& out) override; private: void write(const char* s); @@ -104,17 +104,15 @@ private: void writeLayout(const Layout& layout); void writeModifiers(const Modifiers& modifiers, bool globalContext); - + void writeGlobalVars(const VarDeclaration& vs); void writeVarDeclarations(const VarDeclarations& decl, bool global); - void writeFragCoord(); - void writeVariableReference(const VariableReference& ref); void writeExpression(const Expression& expr, Precedence parentPrecedence); - + void writeIntrinsicCall(const FunctionCall& c); void writeMinAbsHack(Expression& absExpr, Expression& otherExpr); @@ -158,22 +156,21 @@ private: void writeReturnStatement(const ReturnStatement& r); const Context& fContext; + const GrShaderCaps& fCaps; + SkWStream* fOut = nullptr; SkDynamicMemoryWStream fHeader; SkString fFunctionHeader; Program::Kind fProgramKind; int fVarCount = 0; int fIndentation = 0; bool fAtLineStart = false; - // Keeps track of which struct types we have written. Given that we are unlikely to ever write - // more than one or two structs per shader, a simple linear search will be faster than anything + // Keeps track of which struct types we have written. Given that we are unlikely to ever write + // more than one or two structs per shader, a simple linear search will be faster than anything // fancier. std::vector<const Type*> fWrittenStructs; // true if we have run into usages of dFdx / dFdy bool fFoundDerivatives = false; bool fFoundImageDecl = false; - bool fSetupFragPosition = false; - - typedef CodeGenerator INHERITED; }; } diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp index 06988173aa..023f1916c8 100644 --- a/src/sksl/SkSLIRGenerator.cpp +++ b/src/sksl/SkSLIRGenerator.cpp @@ -9,7 +9,6 @@ #include "limits.h" -#include "SkSLCompiler.h" #include "ast/SkSLASTBoolLiteral.h" #include "ast/SkSLASTFieldSuffix.h" #include "ast/SkSLASTFloatLiteral.h" @@ -85,6 +84,7 @@ IRGenerator::IRGenerator(const Context* context, std::shared_ptr<SymbolTable> sy ErrorReporter& errorReporter) : fContext(*context) , fCurrentFunction(nullptr) +, fCapsMap(nullptr) , fSymbolTable(std::move(symbolTable)) , fLoopLevel(0) , fErrors(errorReporter) {} @@ -97,40 +97,14 @@ void IRGenerator::popSymbolTable() { fSymbolTable = fSymbolTable->fParent; } -static void fill_caps(const GrShaderCaps& caps, std::unordered_map<SkString, CapValue>* capsMap) { -#define CAP(name) capsMap->insert(std::make_pair(SkString(#name), CapValue(caps.name()))); - CAP(fbFetchSupport); - CAP(fbFetchNeedsCustomOutput); - CAP(bindlessTextureSupport); - CAP(dropsTileOnZeroDivide); - CAP(flatInterpolationSupport); - CAP(noperspectiveInterpolationSupport); - CAP(multisampleInterpolationSupport); - CAP(sampleVariablesSupport); - CAP(sampleMaskOverrideCoverageSupport); - CAP(externalTextureSupport); - CAP(texelFetchSupport); - CAP(imageLoadStoreSupport); - CAP(mustEnableAdvBlendEqs); - CAP(mustEnableSpecificAdvBlendEqs); - CAP(mustDeclareFragmentShaderOutput); - CAP(canUseAnyFunctionInShader); -#undef CAP -} - -void IRGenerator::start(const Program::Settings* settings) { - fSettings = settings; - fCapsMap.clear(); - if (settings->fCaps) { - fill_caps(*settings->fCaps, &fCapsMap); - } +void IRGenerator::start(std::unordered_map<SkString, CapValue>* caps) { + this->fCapsMap = caps; this->pushSymbolTable(); - fInputs.reset(); } void IRGenerator::finish() { this->popSymbolTable(); - fSettings = nullptr; + this->fCapsMap = nullptr; } std::unique_ptr<Extension> IRGenerator::convertExtension(const ASTExtension& extension) { @@ -626,11 +600,6 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier& case Symbol::kVariable_Kind: { const Variable* var = (const Variable*) result; this->markReadFrom(*var); - if (var->fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN && - fSettings->fFlipY && - (!fSettings->fCaps || !fSettings->fCaps->fragCoordConventionsExtensionString())) { - fInputs.fRTHeight = true; - } return std::unique_ptr<VariableReference>(new VariableReference(identifier.fPosition, *var)); } @@ -1367,8 +1336,9 @@ std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expressi } std::unique_ptr<Expression> IRGenerator::getCap(Position position, SkString name) { - auto found = fCapsMap.find(name); - if (found == fCapsMap.end()) { + ASSERT(fCapsMap); + auto found = fCapsMap->find(name); + if (found == fCapsMap->end()) { fErrors.error(position, "unknown capability flag '" + name + "'"); return nullptr; } diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h index 13b20fbbcc..ade6150089 100644 --- a/src/sksl/SkSLIRGenerator.h +++ b/src/sksl/SkSLIRGenerator.h @@ -40,7 +40,6 @@ #include "ir/SkSLInterfaceBlock.h" #include "ir/SkSLModifiers.h" #include "ir/SkSLModifiersDeclaration.h" -#include "ir/SkSLProgram.h" #include "ir/SkSLSymbolTable.h" #include "ir/SkSLStatement.h" #include "ir/SkSLType.h" @@ -88,14 +87,12 @@ public: std::unique_ptr<ModifiersDeclaration> convertModifiersDeclaration( const ASTModifiersDeclaration& m); - Program::Inputs fInputs; - private: /** - * Prepare to compile a program. Resets state, pushes a new symbol table, and installs the - * settings. + * Prepare to compile a program. Pushes a new symbol table and installs the caps so that + * references to sk_Caps.<cap> can be resolved. */ - void start(const Program::Settings* settings); + void start(std::unordered_map<SkString, CapValue>* caps); /** * Performs cleanup after compilation is complete. @@ -156,8 +153,7 @@ private: const Context& fContext; const FunctionDeclaration* fCurrentFunction; - const Program::Settings* fSettings; - std::unordered_map<SkString, CapValue> fCapsMap; + const std::unordered_map<SkString, CapValue>* fCapsMap; std::shared_ptr<SymbolTable> fSymbolTable; int fLoopLevel; ErrorReporter& fErrors; diff --git a/src/sksl/SkSLMain.cpp b/src/sksl/SkSLMain.cpp index f493b0577d..381fcf08d4 100644 --- a/src/sksl/SkSLMain.cpp +++ b/src/sksl/SkSLMain.cpp @@ -37,9 +37,6 @@ int main(int argc, const char** argv) { printf("error reading '%s'\n", argv[1]); exit(2); } - SkSL::Program::Settings settings; - sk_sp<GrShaderCaps> caps = SkSL::ShaderCapsFactory::Default(); - settings.fCaps = caps.get(); SkString name(argv[2]); if (name.endsWith(".spirv")) { SkFILEWStream out(argv[2]); @@ -48,8 +45,7 @@ int main(int argc, const char** argv) { printf("error writing '%s'\n", argv[2]); exit(4); } - std::unique_ptr<SkSL::Program> program = compiler.convertProgram(kind, text, settings); - if (!program || !compiler.toSPIRV(*program, out)) { + if (!compiler.toSPIRV(kind, text, out)) { printf("%s", compiler.errorText().c_str()); exit(3); } @@ -60,8 +56,7 @@ int main(int argc, const char** argv) { printf("error writing '%s'\n", argv[2]); exit(4); } - std::unique_ptr<SkSL::Program> program = compiler.convertProgram(kind, text, settings); - if (!program || !compiler.toGLSL(*program, out)) { + if (!compiler.toGLSL(kind, text, *SkSL::ShaderCapsFactory::Default(), out)) { printf("%s", compiler.errorText().c_str()); exit(3); } diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp index 63fe020993..b2857f44ef 100644 --- a/src/sksl/SkSLSPIRVCodeGenerator.cpp +++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp @@ -994,14 +994,14 @@ void SPIRVCodeGenerator::writeStruct(const Type& type, const MemoryLayout& memor const Layout& fieldLayout = type.fields()[i].fModifiers.fLayout; if (fieldLayout.fOffset >= 0) { if (fieldLayout.fOffset <= (int) offset) { - fErrors.error(type.fPosition, - "offset of field '" + type.fields()[i].fName + "' must be at " - "least " + to_string((int) offset)); + fErrors->error(type.fPosition, + "offset of field '" + type.fields()[i].fName + "' must be at " + "least " + to_string((int) offset)); } if (fieldLayout.fOffset % alignment) { - fErrors.error(type.fPosition, - "offset of field '" + type.fields()[i].fName + "' must be a multiple" - " of " + to_string((int) alignment)); + fErrors->error(type.fPosition, + "offset of field '" + type.fields()[i].fName + "' must be a multiple" + " of " + to_string((int) alignment)); } offset = fieldLayout.fOffset; } else { @@ -1847,64 +1847,11 @@ std::unique_ptr<SPIRVCodeGenerator::LValue> SPIRVCodeGenerator::getLValue(const } SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, SkWStream& out) { - SpvId result = this->nextId(); auto entry = fVariableMap.find(&ref.fVariable); ASSERT(entry != fVariableMap.end()); SpvId var = entry->second; + SpvId result = this->nextId(); this->writeInstruction(SpvOpLoad, this->getType(ref.fVariable.fType), result, var, out); - if (ref.fVariable.fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN && - fProgram.fSettings.fFlipY) { - // need to remap to a top-left coordinate system - if (fRTHeightStructId == (SpvId) -1) { - // height variable hasn't been written yet - std::shared_ptr<SymbolTable> st(new SymbolTable(fErrors)); - ASSERT(fRTHeightFieldIndex == (SpvId) -1); - std::vector<Type::Field> fields; - fields.emplace_back(Modifiers(), SkString(SKSL_RTHEIGHT_NAME), - fContext.fFloat_Type.get()); - SkString name("sksl_synthetic_uniforms"); - Type intfStruct(Position(), name, fields); - Layout layout(-1, -1, 1, -1, -1, -1, -1, false, false, false, Layout::Format::kUnspecified, - false); - Variable intfVar(Position(), Modifiers(layout, Modifiers::kUniform_Flag), name, - intfStruct, Variable::kGlobal_Storage); - InterfaceBlock intf(Position(), intfVar, st); - fRTHeightStructId = this->writeInterfaceBlock(intf); - fRTHeightFieldIndex = 0; - } - ASSERT(fRTHeightFieldIndex != (SpvId) -1); - // write vec4(gl_FragCoord.x, u_skRTHeight - gl_FragCoord.y, 0.0, 1.0) - SpvId xId = this->nextId(); - this->writeInstruction(SpvOpCompositeExtract, this->getType(*fContext.fFloat_Type), xId, - result, 0, out); - IntLiteral fieldIndex(fContext, Position(), fRTHeightFieldIndex); - SpvId fieldIndexId = this->writeIntLiteral(fieldIndex); - SpvId heightRead = this->nextId(); - this->writeOpCode(SpvOpAccessChain, 5, out); - this->writeWord(this->getPointerType(*fContext.fFloat_Type, SpvStorageClassUniform), out); - this->writeWord(heightRead, out); - this->writeWord(fRTHeightStructId, out); - this->writeWord(fieldIndexId, out); - SpvId rawYId = this->nextId(); - this->writeInstruction(SpvOpCompositeExtract, this->getType(*fContext.fFloat_Type), rawYId, - result, 1, out); - SpvId flippedYId = this->nextId(); - this->writeInstruction(SpvOpFSub, this->getType(*fContext.fFloat_Type), flippedYId, - heightRead, rawYId, out); - FloatLiteral zero(fContext, Position(), 0.0); - SpvId zeroId = writeFloatLiteral(zero); - FloatLiteral one(fContext, Position(), 1.0); - SpvId oneId = writeFloatLiteral(one); - SpvId flipped = this->nextId(); - this->writeOpCode(SpvOpCompositeConstruct, 7, out); - this->writeWord(this->getType(*fContext.fVec4_Type), out); - this->writeWord(flipped, out); - this->writeWord(xId, out); - this->writeWord(flippedYId, out); - this->writeWord(zeroId, out); - this->writeWord(oneId, out); - return flipped; - } return result; } @@ -2495,22 +2442,12 @@ SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { MemoryLayout layout = intf.fVariable.fModifiers.fLayout.fPushConstant ? MemoryLayout(MemoryLayout::k430_Standard) : fDefaultLayout; + SpvId type = this->getType(intf.fVariable.fType, layout); SpvId result = this->nextId(); - const Type* type = &intf.fVariable.fType; - if (fProgram.fInputs.fRTHeight) { - ASSERT(fRTHeightStructId == (SpvId) -1); - ASSERT(fRTHeightFieldIndex == (SpvId) -1); - std::vector<Type::Field> fields = type->fields(); - fRTHeightStructId = result; - fRTHeightFieldIndex = fields.size(); - fields.emplace_back(Modifiers(), SkString(SKSL_RTHEIGHT_NAME), fContext.fFloat_Type.get()); - type = new Type(type->fPosition, type->name(), fields); - } - SpvId typeId = this->getType(*type, layout); - this->writeInstruction(SpvOpDecorate, typeId, SpvDecorationBlock, fDecorationBuffer); + this->writeInstruction(SpvOpDecorate, type, SpvDecorationBlock, fDecorationBuffer); SpvStorageClass_ storageClass = get_storage_class(intf.fVariable.fModifiers); SpvId ptrType = this->nextId(); - this->writeInstruction(SpvOpTypePointer, ptrType, storageClass, typeId, fConstantBuffer); + this->writeInstruction(SpvOpTypePointer, ptrType, storageClass, type, fConstantBuffer); this->writeInstruction(SpvOpVariable, ptrType, result, storageClass, fConstantBuffer); this->writeLayout(intf.fVariable.fModifiers.fLayout, result); fVariableMap[&intf.fVariable] = result; @@ -2797,7 +2734,6 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, SkWStream& ou } } - write_data(*fExtraGlobalsBuffer.detachAsData(), out); write_data(*fNameBuffer.detachAsData(), out); write_data(*fDecorationBuffer.detachAsData(), out); write_data(*fConstantBuffer.detachAsData(), out); @@ -2805,17 +2741,18 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, SkWStream& ou write_data(*body.detachAsData(), out); } -bool SPIRVCodeGenerator::generateCode() { - ASSERT(!fErrors.errorCount()); - this->writeWord(SpvMagicNumber, *fOut); - this->writeWord(SpvVersion, *fOut); - this->writeWord(SKSL_MAGIC, *fOut); +void SPIRVCodeGenerator::generateCode(const Program& program, ErrorReporter& errors, + SkWStream& out) { + fErrors = &errors; + this->writeWord(SpvMagicNumber, out); + this->writeWord(SpvVersion, out); + this->writeWord(SKSL_MAGIC, out); SkDynamicMemoryWStream buffer; - this->writeInstructions(fProgram, buffer); - this->writeWord(fIdCount, *fOut); - this->writeWord(0, *fOut); // reserved, always zero - write_data(*buffer.detachAsData(), *fOut); - return 0 == fErrors.errorCount(); + this->writeInstructions(program, buffer); + this->writeWord(fIdCount, out); + this->writeWord(0, out); // reserved, always zero + write_data(*buffer.detachAsData(), out); + fErrors = nullptr; } } diff --git a/src/sksl/SkSLSPIRVCodeGenerator.h b/src/sksl/SkSLSPIRVCodeGenerator.h index 96ff187983..5567ec5404 100644 --- a/src/sksl/SkSLSPIRVCodeGenerator.h +++ b/src/sksl/SkSLSPIRVCodeGenerator.h @@ -62,21 +62,18 @@ public: virtual void store(SpvId value, SkWStream& out) = 0; }; - SPIRVCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors, - SkWStream* out) - : INHERITED(program, errors, out) - , fContext(*context) + SPIRVCodeGenerator(const Context* context) + : fContext(*context) , fDefaultLayout(MemoryLayout::k140_Standard) , fCapabilities(1 << SpvCapabilityShader) , fIdCount(1) , fBoolTrue(0) , fBoolFalse(0) - , fSetupFragPosition(false) , fCurrentBlock(0) { this->setupIntrinsics(); } - bool generateCode() override; + void generateCode(const Program& program, ErrorReporter& errors, SkWStream& out) override; private: enum IntrinsicKind { @@ -103,7 +100,7 @@ private: SpvId getPointerType(const Type& type, SpvStorageClass_ storageClass); - SpvId getPointerType(const Type& type, const MemoryLayout& layout, + SpvId getPointerType(const Type& type, const MemoryLayout& layout, SpvStorageClass_ storageClass); std::vector<SpvId> getAccessChain(const Expression& expr, SkWStream& out); @@ -156,11 +153,11 @@ private: SpvId writeSwizzle(const Swizzle& swizzle, SkWStream& out); - SpvId writeBinaryOperation(const Type& resultType, const Type& operandType, SpvId lhs, - SpvId rhs, SpvOp_ ifFloat, SpvOp_ ifInt, SpvOp_ ifUInt, + SpvId writeBinaryOperation(const Type& resultType, const Type& operandType, SpvId lhs, + SpvId rhs, SpvOp_ ifFloat, SpvOp_ ifInt, SpvOp_ ifUInt, SpvOp_ ifBool, SkWStream& out); - SpvId writeBinaryOperation(const BinaryExpression& expr, SpvOp_ ifFloat, SpvOp_ ifInt, + SpvId writeBinaryOperation(const BinaryExpression& expr, SpvOp_ ifFloat, SpvOp_ ifInt, SpvOp_ ifUInt, SkWStream& out); SpvId writeBinaryExpression(const BinaryExpression& b, SkWStream& out); @@ -218,7 +215,7 @@ private: void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, SkWStream& out); - void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, + void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, SkWStream& out); void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4, @@ -234,11 +231,12 @@ private: int32_t word5, int32_t word6, int32_t word7, SkWStream& out); void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4, - int32_t word5, int32_t word6, int32_t word7, int32_t word8, + int32_t word5, int32_t word6, int32_t word7, int32_t word8, SkWStream& out); const Context& fContext; const MemoryLayout fDefaultLayout; + ErrorReporter* fErrors; uint64_t fCapabilities; SpvId fIdCount; @@ -252,7 +250,6 @@ private: SkDynamicMemoryWStream fCapabilitiesBuffer; SkDynamicMemoryWStream fGlobalInitializersBuffer; SkDynamicMemoryWStream fConstantBuffer; - SkDynamicMemoryWStream fExtraGlobalsBuffer; SkDynamicMemoryWStream fExternalFunctionsBuffer; SkDynamicMemoryWStream fVariableBuffer; SkDynamicMemoryWStream fNameBuffer; @@ -264,18 +261,13 @@ private: std::unordered_map<uint64_t, SpvId> fUIntConstants; std::unordered_map<float, SpvId> fFloatConstants; std::unordered_map<double, SpvId> fDoubleConstants; - bool fSetupFragPosition; // label of the current block, or 0 if we are not in a block SpvId fCurrentBlock; std::stack<SpvId> fBreakTarget; std::stack<SpvId> fContinueTarget; - SpvId fRTHeightStructId = (SpvId) -1; - SpvId fRTHeightFieldIndex = (SpvId) -1; friend class PointerLValue; friend class SwizzleLValue; - - typedef CodeGenerator INHERITED; }; } diff --git a/src/sksl/SkSLUtil.h b/src/sksl/SkSLUtil.h index 678241d205..95b25298ae 100644 --- a/src/sksl/SkSLUtil.h +++ b/src/sksl/SkSLUtil.h @@ -72,21 +72,6 @@ public: return result; } - static sk_sp<GrShaderCaps> FragCoordsOld() { - sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); - result->fVersionDeclString = "#version 110"; - result->fGLSLGeneration = GrGLSLGeneration::k110_GrGLSLGeneration; - result->fFragCoordConventionsExtensionString = "GL_ARB_fragment_coord_conventions"; - return result; - } - - static sk_sp<GrShaderCaps> FragCoordsNew() { - sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); - result->fVersionDeclString = "#version 400"; - result->fFragCoordConventionsExtensionString = "GL_ARB_fragment_coord_conventions"; - return result; - } - static sk_sp<GrShaderCaps> VariousCaps() { sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); result->fVersionDeclString = "#version 400"; diff --git a/src/sksl/ir/SkSLProgram.h b/src/sksl/ir/SkSLProgram.h index ac49d6dcc7..8393341269 100644 --- a/src/sksl/ir/SkSLProgram.h +++ b/src/sksl/ir/SkSLProgram.h @@ -4,73 +4,42 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ - + #ifndef SKSL_PROGRAM #define SKSL_PROGRAM #include <vector> #include <memory> -#include "SkSLContext.h" #include "SkSLModifiers.h" #include "SkSLProgramElement.h" #include "SkSLSymbolTable.h" -// name of the render target height uniform -#define SKSL_RTHEIGHT_NAME "u_skRTHeight" - namespace SkSL { /** * Represents a fully-digested program, ready for code generation. */ struct Program { - struct Settings { - const GrShaderCaps* fCaps = nullptr; - bool fFlipY = false; - }; - - struct Inputs { - // if true, this program requires the render target height uniform to be defined - bool fRTHeight; - - void reset() { - fRTHeight = false; - } - - bool isEmpty() { - return !fRTHeight; - } - }; - enum Kind { kFragment_Kind, kVertex_Kind }; - Program(Kind kind, - Settings settings, + Program(Kind kind, Modifiers::Flag defaultPrecision, - Context* context, - std::vector<std::unique_ptr<ProgramElement>> elements, - std::shared_ptr<SymbolTable> symbols, - Inputs inputs) - : fKind(kind) - , fSettings(settings) + std::vector<std::unique_ptr<ProgramElement>> elements, + std::shared_ptr<SymbolTable> symbols) + : fKind(kind) , fDefaultPrecision(defaultPrecision) - , fContext(context) , fElements(std::move(elements)) - , fSymbols(symbols) - , fInputs(inputs) {} + , fSymbols(symbols) {} Kind fKind; - Settings fSettings; // FIXME handle different types; currently it assumes this is for floats Modifiers::Flag fDefaultPrecision; - Context* fContext; std::vector<std::unique_ptr<ProgramElement>> fElements; std::shared_ptr<SymbolTable> fSymbols; - Inputs fInputs; }; } // namespace diff --git a/src/sksl/sksl_frag.include b/src/sksl/sksl_frag.include index 21849866df..62f06e81bf 100644 --- a/src/sksl/sksl_frag.include +++ b/src/sksl/sksl_frag.include @@ -2,7 +2,7 @@ STRINGIFY( // defines built-in interfaces supported by SkiaSL fragment shaders -layout(builtin=15) in vec4 sk_FragCoord; +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 |