From f66d28dfb25127ff073e2e9549c6985785a65afa Mon Sep 17 00:00:00 2001 From: Ethan Nicholas Date: Tue, 20 Jun 2017 15:27:46 -0400 Subject: [PATCH] Revert "Revert "implemented mustImplementGSInvocationsWithLoop workaround in sksl"" This reverts commit 8ea60736aaa92cf3cf24705fb356e9e09e85b1fd. Bug: skia: Change-Id: If77035e03430b469c2682788610b33ae0aefbe1f Reviewed-on: https://skia-review.googlesource.com/20053 Reviewed-by: Chris Dalton Commit-Queue: Ethan Nicholas --- src/gpu/glsl/GrGLSLGeometryShaderBuilder.cpp | 17 -- src/sksl/SkSLCompiler.cpp | 82 ++------- src/sksl/SkSLCompiler.h | 4 - src/sksl/SkSLIRGenerator.cpp | 165 +++++++++++++++++-- src/sksl/SkSLIRGenerator.h | 24 ++- src/sksl/SkSLUtil.h | 11 ++ src/sksl/ir/SkSLVarDeclarationsStatement.h | 2 +- tests/SkSLGLSLTest.cpp | 35 ++++ 8 files changed, 230 insertions(+), 110 deletions(-) diff --git a/src/gpu/glsl/GrGLSLGeometryShaderBuilder.cpp b/src/gpu/glsl/GrGLSLGeometryShaderBuilder.cpp index 01f223f4b3..ea8e73f7b8 100644 --- a/src/gpu/glsl/GrGLSLGeometryShaderBuilder.cpp +++ b/src/gpu/glsl/GrGLSLGeometryShaderBuilder.cpp @@ -42,10 +42,6 @@ void GrGLSLGeometryBuilder::configure(InputType inputType, OutputType outputType int numInvocations) { SkASSERT(!this->isConfigured()); fNumInvocations = numInvocations; - if (this->getProgramBuilder()->shaderCaps()->mustImplementGSInvocationsWithLoop()) { - maxVertices *= numInvocations; - numInvocations = 1; - } this->addLayoutQualifier(input_type_name(inputType), kIn_InterfaceQualifier); this->addLayoutQualifier(SkStringPrintf("invocations = %i", numInvocations).c_str(), kIn_InterfaceQualifier); @@ -57,17 +53,4 @@ void GrGLSLGeometryBuilder::configure(InputType inputType, OutputType outputType void GrGLSLGeometryBuilder::onFinalize() { SkASSERT(this->isConfigured()); fProgramBuilder->varyingHandler()->getGeomDecls(&this->inputs(), &this->outputs()); - GrShaderVar sk_InvocationID("sk_InvocationID", kInt_GrSLType); - this->declareGlobal(sk_InvocationID); - SkASSERT(sk_InvocationID.getName() == SkString("sk_InvocationID")); - if (this->getProgramBuilder()->shaderCaps()->mustImplementGSInvocationsWithLoop()) { - SkString invokeFn; - this->emitFunction(kVoid_GrSLType, "invoke", 0, nullptr, this->code().c_str(), &invokeFn); - this->code().printf("for (sk_InvocationID = 0; sk_InvocationID < %i; ++sk_InvocationID) {" - "%s();" - "EndPrimitive();" - "}", fNumInvocations, invokeFn.c_str()); - } else { - this->codePrependf("sk_InvocationID = gl_InvocationID;"); - } } diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp index dd20b5c257..2d541a3b53 100644 --- a/src/sksl/SkSLCompiler.cpp +++ b/src/sksl/SkSLCompiler.cpp @@ -7,11 +7,9 @@ #include "SkSLCompiler.h" -#include "ast/SkSLASTPrecision.h" #include "SkSLCFGGenerator.h" #include "SkSLGLSLCodeGenerator.h" #include "SkSLIRGenerator.h" -#include "SkSLParser.h" #include "SkSLSPIRVCodeGenerator.h" #include "ir/SkSLExpression.h" #include "ir/SkSLExpressionStatement.h" @@ -156,7 +154,7 @@ Compiler::Compiler() Modifiers::Flag ignored1; std::vector> ignored2; - this->internalConvertProgram(String(SKSL_INCLUDE), &ignored1, &ignored2); + fIRGenerator->convertProgram(String(SKSL_INCLUDE), *fTypes, &ignored1, &ignored2); fIRGenerator->fSymbolTable->markAllFunctionsBuiltin(); ASSERT(!fErrorCount); } @@ -1059,69 +1057,6 @@ void Compiler::scanCFG(FunctionDefinition& f) { } } -void Compiler::internalConvertProgram(String text, - Modifiers::Flag* defaultPrecision, - std::vector>* result) { - Parser parser(text, *fTypes, *this); - std::vector> parsed = parser.file(); - if (fErrorCount) { - return; - } - *defaultPrecision = Modifiers::kHighp_Flag; - for (size_t i = 0; i < parsed.size(); i++) { - ASTDeclaration& decl = *parsed[i]; - switch (decl.fKind) { - case ASTDeclaration::kVar_Kind: { - std::unique_ptr s = fIRGenerator->convertVarDeclarations( - (ASTVarDeclarations&) decl, - Variable::kGlobal_Storage); - if (s) { - result->push_back(std::move(s)); - } - break; - } - case ASTDeclaration::kFunction_Kind: { - std::unique_ptr f = fIRGenerator->convertFunction( - (ASTFunction&) decl); - if (!fErrorCount && f) { - this->scanCFG(*f); - result->push_back(std::move(f)); - } - break; - } - case ASTDeclaration::kModifiers_Kind: { - std::unique_ptr f = fIRGenerator->convertModifiersDeclaration( - (ASTModifiersDeclaration&) decl); - if (f) { - result->push_back(std::move(f)); - } - break; - } - case ASTDeclaration::kInterfaceBlock_Kind: { - std::unique_ptr i = fIRGenerator->convertInterfaceBlock( - (ASTInterfaceBlock&) decl); - if (i) { - result->push_back(std::move(i)); - } - break; - } - case ASTDeclaration::kExtension_Kind: { - std::unique_ptr e = fIRGenerator->convertExtension((ASTExtension&) decl); - if (e) { - result->push_back(std::move(e)); - } - break; - } - case ASTDeclaration::kPrecision_Kind: { - *defaultPrecision = ((ASTPrecision&) decl).fPrecision; - break; - } - default: - ABORT("unsupported declaration: %s\n", decl.description().c_str()); - } - } -} - std::unique_ptr Compiler::convertProgram(Program::Kind kind, String text, const Program::Settings& settings) { fErrorText = ""; @@ -1131,18 +1066,25 @@ std::unique_ptr Compiler::convertProgram(Program::Kind kind, String tex Modifiers::Flag ignored; switch (kind) { case Program::kVertex_Kind: - this->internalConvertProgram(String(SKSL_VERT_INCLUDE), &ignored, &elements); + fIRGenerator->convertProgram(String(SKSL_VERT_INCLUDE), *fTypes, &ignored, &elements); break; case Program::kFragment_Kind: - this->internalConvertProgram(String(SKSL_FRAG_INCLUDE), &ignored, &elements); + fIRGenerator->convertProgram(String(SKSL_FRAG_INCLUDE), *fTypes, &ignored, &elements); break; case Program::kGeometry_Kind: - this->internalConvertProgram(String(SKSL_GEOM_INCLUDE), &ignored, &elements); + fIRGenerator->convertProgram(String(SKSL_GEOM_INCLUDE), *fTypes, &ignored, &elements); break; } fIRGenerator->fSymbolTable->markAllFunctionsBuiltin(); Modifiers::Flag defaultPrecision; - this->internalConvertProgram(text, &defaultPrecision, &elements); + fIRGenerator->convertProgram(text, *fTypes, &defaultPrecision, &elements); + if (!fErrorCount) { + for (auto& element : elements) { + if (element->fKind == ProgramElement::kFunction_Kind) { + this->scanCFG((FunctionDefinition&) *element); + } + } + } auto result = std::unique_ptr(new Program(kind, settings, defaultPrecision, &fContext, std::move(elements), fIRGenerator->fSymbolTable, diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h index 5e7bc9e71b..bc9a1964ac 100644 --- a/src/sksl/SkSLCompiler.h +++ b/src/sksl/SkSLCompiler.h @@ -98,10 +98,6 @@ private: void scanCFG(FunctionDefinition& f); - void internalConvertProgram(String text, - Modifiers::Flag* defaultPrecision, - std::vector>* result); - std::shared_ptr fTypes; IRGenerator* fIRGenerator; String fSkiaVertText; // FIXME store parsed version instead diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp index f85ea1054d..11e7a568c2 100644 --- a/src/sksl/SkSLIRGenerator.cpp +++ b/src/sksl/SkSLIRGenerator.cpp @@ -11,11 +11,13 @@ #include #include "SkSLCompiler.h" +#include "SkSLParser.h" #include "ast/SkSLASTBoolLiteral.h" #include "ast/SkSLASTFieldSuffix.h" #include "ast/SkSLASTFloatLiteral.h" #include "ast/SkSLASTIndexSuffix.h" #include "ast/SkSLASTIntLiteral.h" +#include "ast/SkSLASTPrecision.h" #include "ir/SkSLBinaryExpression.h" #include "ir/SkSLBoolLiteral.h" #include "ir/SkSLBreakStatement.h" @@ -143,6 +145,7 @@ void IRGenerator::start(const Program::Settings* settings) { fill_caps(*settings->fCaps, &fCapsMap); } this->pushSymbolTable(); + fInvocations = -1; fInputs.reset(); } @@ -278,7 +281,24 @@ std::unique_ptr IRGenerator::convertVarDeclarations(const ASTVa std::unique_ptr IRGenerator::convertModifiersDeclaration( const ASTModifiersDeclaration& m) { - return std::unique_ptr(new ModifiersDeclaration(m.fModifiers)); + Modifiers modifiers = m.fModifiers; + if (modifiers.fLayout.fInvocations != -1) { + fInvocations = modifiers.fLayout.fInvocations; + if (fSettings->fCaps && fSettings->fCaps->mustImplementGSInvocationsWithLoop()) { + modifiers.fLayout.fInvocations = -1; + Variable* invocationId = (Variable*) (*fSymbolTable)["sk_InvocationID"]; + ASSERT(invocationId); + invocationId->fModifiers.fLayout.fBuiltin = -1; + if (modifiers.fLayout.description() == "") { + return nullptr; + } + } + } + if (modifiers.fLayout.fMaxVertices != -1 && fInvocations > 0 && fSettings->fCaps && + fSettings->fCaps->mustImplementGSInvocationsWithLoop()) { + modifiers.fLayout.fMaxVertices *= fInvocations; + } + return std::unique_ptr(new ModifiersDeclaration(modifiers)); } std::unique_ptr IRGenerator::convertIf(const ASTIfStatement& s) { @@ -490,16 +510,73 @@ std::unique_ptr IRGenerator::convertDiscard(const ASTDiscardStatement return std::unique_ptr(new DiscardStatement(d.fPosition)); } -std::unique_ptr IRGenerator::convertFunction(const ASTFunction& f) { +std::unique_ptr IRGenerator::applyInvocationIDWorkaround(std::unique_ptr main, + std::vector>* out) { + Layout invokeLayout; + Modifiers invokeModifiers(invokeLayout, Modifiers::kHasSideEffects_Flag); + FunctionDeclaration* invokeDecl = new FunctionDeclaration(Position(), + invokeModifiers, + "_invoke", + std::vector(), + *fContext.fVoid_Type); + out->push_back(std::unique_ptr(new FunctionDefinition(Position(), + *invokeDecl, + std::move(main)))); + fSymbolTable->add(invokeDecl->fName, std::unique_ptr(invokeDecl)); + + std::vector> variables; + Variable* loopIdx = (Variable*) (*fSymbolTable)["sk_InvocationID"]; + ASSERT(loopIdx); + std::unique_ptr test(new BinaryExpression(Position(), + std::unique_ptr(new VariableReference(Position(), *loopIdx)), + Token::LT, + std::unique_ptr(new IntLiteral(fContext, Position(), fInvocations)), + *fContext.fBool_Type)); + std::unique_ptr next(new PostfixExpression( + std::unique_ptr( + new VariableReference(Position(), + *loopIdx, + VariableReference::kReadWrite_RefKind)), + Token::PLUSPLUS)); + ASTIdentifier endPrimitiveID = ASTIdentifier(Position(), "EndPrimitive"); + std::unique_ptr endPrimitive = this->convertExpression(endPrimitiveID); + ASSERT(endPrimitive); + + std::vector> loopBody; + std::vector> invokeArgs; + loopBody.push_back(std::unique_ptr(new ExpressionStatement( + this->call(Position(), *invokeDecl, { })))); + loopBody.push_back(std::unique_ptr(new ExpressionStatement( + this->call(Position(), std::move(endPrimitive), { })))); + std::unique_ptr assignment(new BinaryExpression(Position(), + std::unique_ptr(new VariableReference(Position(), *loopIdx)), + Token::EQ, + std::unique_ptr(new IntLiteral(fContext, Position(), 0)), + *fContext.fInt_Type)); + std::unique_ptr initializer(new ExpressionStatement(std::move(assignment))); + std::unique_ptr loop = std::unique_ptr( + new ForStatement(Position(), + std::move(initializer), + std::move(test), + std::move(next), + std::unique_ptr(new Block(Position(), std::move(loopBody))), + fSymbolTable)); + std::vector> children; + children.push_back(std::move(loop)); + return std::unique_ptr(new Block(Position(), std::move(children))); +} + +void IRGenerator::convertFunction(const ASTFunction& f, + std::vector>* out) { const Type* returnType = this->convertType(*f.fReturnType); if (!returnType) { - return nullptr; + return; } std::vector parameters; for (const auto& param : f.fParameters) { const Type* type = this->convertType(*param->fType); if (!type) { - return nullptr; + return; } for (int j = (int) param->fSizes.size() - 1; j >= 0; j--) { int size = param->fSizes[j]; @@ -530,7 +607,7 @@ std::unique_ptr IRGenerator::convertFunction(const ASTFuncti break; default: fErrors.error(f.fPosition, "symbol '" + f.fName + "' was already defined"); - return nullptr; + return; } for (const auto& other : functions) { ASSERT(other->fName == f.fName); @@ -549,7 +626,7 @@ std::unique_ptr IRGenerator::convertFunction(const ASTFuncti fErrors.error(f.fPosition, "functions '" + newDecl.description() + "' and '" + other->description() + "' differ only in return type"); - return nullptr; + return; } decl = other; for (size_t i = 0; i < parameters.size(); i++) { @@ -558,7 +635,7 @@ std::unique_ptr IRGenerator::convertFunction(const ASTFuncti to_string((uint64_t) i + 1) + " differ between declaration and " "definition"); - return nullptr; + return; } } if (other->fDefined) { @@ -589,17 +666,23 @@ std::unique_ptr IRGenerator::convertFunction(const ASTFuncti for (size_t i = 0; i < parameters.size(); i++) { fSymbolTable->addWithoutOwnership(parameters[i]->fName, decl->fParameters[i]); } + bool needInvocationIDWorkaround = fSettings->fCaps && + fSettings->fCaps->mustImplementGSInvocationsWithLoop() && + fInvocations != -1 && f.fName == "main"; std::unique_ptr body = this->convertBlock(*f.fBody); fCurrentFunction = nullptr; if (!body) { - return nullptr; + return; + } + if (needInvocationIDWorkaround) { + body = this->applyInvocationIDWorkaround(std::move(body), out); } // conservatively assume all user-defined functions have side effects ((Modifiers&) decl->fModifiers).fFlags |= Modifiers::kHasSideEffects_Flag; - return std::unique_ptr(new FunctionDefinition(f.fPosition, *decl, - std::move(body))); + + out->push_back(std::unique_ptr( + new FunctionDefinition(f.fPosition, *decl, std::move(body)))); } - return nullptr; } std::unique_ptr IRGenerator::convertInterfaceBlock(const ASTInterfaceBlock& intf) { @@ -1788,4 +1871,64 @@ void IRGenerator::markWrittenTo(const Expression& expr, bool readWrite) { } } +void IRGenerator::convertProgram(String text, + SymbolTable& types, + Modifiers::Flag* defaultPrecision, + std::vector>* out) { + Parser parser(text, types, fErrors); + std::vector> parsed = parser.file(); + if (fErrors.errorCount()) { + return; + } + *defaultPrecision = Modifiers::kHighp_Flag; + for (size_t i = 0; i < parsed.size(); i++) { + ASTDeclaration& decl = *parsed[i]; + switch (decl.fKind) { + case ASTDeclaration::kVar_Kind: { + std::unique_ptr s = this->convertVarDeclarations( + (ASTVarDeclarations&) decl, + Variable::kGlobal_Storage); + if (s) { + out->push_back(std::move(s)); + } + break; + } + case ASTDeclaration::kFunction_Kind: { + this->convertFunction((ASTFunction&) decl, out); + break; + } + case ASTDeclaration::kModifiers_Kind: { + std::unique_ptr f = this->convertModifiersDeclaration( + (ASTModifiersDeclaration&) decl); + if (f) { + out->push_back(std::move(f)); + } + break; + } + case ASTDeclaration::kInterfaceBlock_Kind: { + std::unique_ptr i = this->convertInterfaceBlock( + (ASTInterfaceBlock&) decl); + if (i) { + out->push_back(std::move(i)); + } + break; + } + case ASTDeclaration::kExtension_Kind: { + std::unique_ptr e = this->convertExtension((ASTExtension&) decl); + if (e) { + out->push_back(std::move(e)); + } + break; + } + case ASTDeclaration::kPrecision_Kind: { + *defaultPrecision = ((ASTPrecision&) decl).fPrecision; + break; + } + default: + ABORT("unsupported declaration: %s\n", decl.description().c_str()); + } + } +} + + } diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h index d4a684638c..29513d8d34 100644 --- a/src/sksl/SkSLIRGenerator.h +++ b/src/sksl/SkSLIRGenerator.h @@ -81,13 +81,10 @@ public: IRGenerator(const Context* context, std::shared_ptr root, ErrorReporter& errorReporter); - std::unique_ptr convertVarDeclarations(const ASTVarDeclarations& decl, - Variable::Storage storage); - std::unique_ptr convertFunction(const ASTFunction& f); - std::unique_ptr convertStatement(const ASTStatement& statement); - std::unique_ptr convertExpression(const ASTExpression& expression); - std::unique_ptr convertModifiersDeclaration( - const ASTModifiersDeclaration& m); + void convertProgram(String text, + SymbolTable& types, + Modifiers::Flag* defaultPrecision, + std::vector>* result); /** * If both operands are compile-time constants and can be folded, returns an expression @@ -115,6 +112,15 @@ private: void pushSymbolTable(); void popSymbolTable(); + std::unique_ptr convertVarDeclarations(const ASTVarDeclarations& decl, + Variable::Storage storage); + void convertFunction(const ASTFunction& f, + std::vector>* out); + std::unique_ptr convertStatement(const ASTStatement& statement); + std::unique_ptr convertExpression(const ASTExpression& expression); + std::unique_ptr convertModifiersDeclaration( + const ASTModifiersDeclaration& m); + const Type* convertType(const ASTType& type); std::unique_ptr call(Position position, const FunctionDeclaration& function, @@ -163,6 +169,9 @@ private: std::unique_ptr convertTernaryExpression(const ASTTernaryExpression& expression); std::unique_ptr convertVarDeclarationStatement(const ASTVarDeclarationStatement& s); std::unique_ptr convertWhile(const ASTWhileStatement& w); + std::unique_ptr applyInvocationIDWorkaround( + std::unique_ptr main, + std::vector>* out); void fixRectSampling(std::vector>& arguments); void checkValid(const Expression& expr); @@ -175,6 +184,7 @@ private: int fLoopLevel; int fSwitchLevel; ErrorReporter& fErrors; + int fInvocations; friend class AutoSymbolTable; friend class AutoLoopLevel; diff --git a/src/sksl/SkSLUtil.h b/src/sksl/SkSLUtil.h index d1af9bb3c7..b56ae16d2c 100644 --- a/src/sksl/SkSLUtil.h +++ b/src/sksl/SkSLUtil.h @@ -150,6 +150,10 @@ public: const char* versionDeclString() const { return ""; } + + bool mustImplementGSInvocationsWithLoop() const { + return false; + } }; extern StandaloneShaderCaps standaloneCaps; @@ -224,6 +228,13 @@ public: return result; } + static sk_sp MustImplementGSInvocationsWithLoop() { + sk_sp result = sk_make_sp(GrContextOptions()); + result->fVersionDeclString = "#version 400"; + result->fMustImplementGSInvocationsWithLoop = true; + return result; + } + static sk_sp VariousCaps() { sk_sp result = sk_make_sp(GrContextOptions()); result->fVersionDeclString = "#version 400"; diff --git a/src/sksl/ir/SkSLVarDeclarationsStatement.h b/src/sksl/ir/SkSLVarDeclarationsStatement.h index ab6753610f..a6a95a9c08 100644 --- a/src/sksl/ir/SkSLVarDeclarationsStatement.h +++ b/src/sksl/ir/SkSLVarDeclarationsStatement.h @@ -31,7 +31,7 @@ struct VarDeclarationsStatement : public Statement { } String description() const override { - return fDeclaration->description(); + return fDeclaration->description() + ";"; } std::shared_ptr fDeclaration; diff --git a/tests/SkSLGLSLTest.cpp b/tests/SkSLGLSLTest.cpp index 2ea6c7ec71..a4a3c0e04f 100644 --- a/tests/SkSLGLSLTest.cpp +++ b/tests/SkSLGLSLTest.cpp @@ -1393,4 +1393,39 @@ DEF_TEST(SkSLDeadLoopVar, r) { ); } +DEF_TEST(SkSLInvocations, r) { + test(r, + "layout(points) in;" + "layout(invocations = 2) in;" + "layout(line_strip, max_vertices = 2) out;" + "void test() {" + "gl_Position = sk_in[0].gl_Position + vec4(0.5, 0, 0, sk_InvocationID);" + "EmitVertex();" + "}" + "void main() {" + "gl_Position = sk_in[0].gl_Position + vec4(-0.5, 0, 0, sk_InvocationID);" + "EmitVertex();" + "}", + *SkSL::ShaderCapsFactory::MustImplementGSInvocationsWithLoop(), + "#version 400\n" + "int sk_InvocationID;\n" + "layout (points) in ;\n" + "layout (line_strip, max_vertices = 4) out ;\n" + "void test() {\n" + " gl_Position = gl_in[0].gl_Position + vec4(0.5, 0.0, 0.0, float(sk_InvocationID));\n" + " EmitVertex();\n" + "}\n" + "void _invoke() {\n" + " gl_Position = gl_in[0].gl_Position + vec4(-0.5, 0.0, 0.0, float(sk_InvocationID));\n" + " EmitVertex();\n" + "}\n" + "void main() {\n" + " for (sk_InvocationID = 0;sk_InvocationID < 2; sk_InvocationID++) {\n" + " _invoke();\n" + " EndPrimitive();\n" + " }\n" + "}\n", + SkSL::Program::kGeometry_Kind); +} + #endif