diff options
author | Ethan Nicholas <ethannicholas@google.com> | 2017-12-12 09:48:48 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-12-12 15:24:09 +0000 |
commit | e7e81c15c144b8133f696d0744ed9f7e8d06e936 (patch) | |
tree | a8b97c5e3ee2dea146a9cedbff3a33356a181180 /src/sksl | |
parent | 344e9037e1befdee76691a1239a47829e6af4ea5 (diff) |
converted vertex shaders to device coords
Bug: skia:6239
Change-Id: I1a3b67fe84d208d426d71deb7aea6b0cd433af37
Reviewed-on: https://skia-review.googlesource.com/75501
Reviewed-by: Chris Dalton <csmartdalton@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Diffstat (limited to 'src/sksl')
-rw-r--r-- | src/sksl/README | 3 | ||||
-rw-r--r-- | src/sksl/SkSLCompiler.cpp | 19 | ||||
-rw-r--r-- | src/sksl/SkSLCompiler.h | 3 | ||||
-rw-r--r-- | src/sksl/SkSLIRGenerator.cpp | 89 | ||||
-rw-r--r-- | src/sksl/SkSLIRGenerator.h | 10 |
5 files changed, 109 insertions, 15 deletions
diff --git a/src/sksl/README b/src/sksl/README index 7c2cf04551..e9e46566a8 100644 --- a/src/sksl/README +++ b/src/sksl/README @@ -38,7 +38,8 @@ Differences from GLSL 'do_something_else();', depending on whether that cap is enabled or not. * no #version statement is required, and it will be ignored if present * the output color is sk_FragColor (do not declare it) -* use sk_Position instead of gl_Position +* use sk_Position instead of gl_Position. sk_Position is in device coordinates + rather than normalized coordinates. * use sk_PointSize instead of gl_PointSize * use sk_VertexID instead of gl_VertexID * use sk_InstanceID instead of gl_InstanceID diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp index c7a51aeb97..4a4facb5f4 100644 --- a/src/sksl/SkSLCompiler.cpp +++ b/src/sksl/SkSLCompiler.cpp @@ -200,7 +200,8 @@ Compiler::Compiler(Flags flags) fIRGenerator->fSymbolTable->add(skArgsName, std::unique_ptr<Symbol>(skArgs)); std::vector<std::unique_ptr<ProgramElement>> ignored; - fIRGenerator->convertProgram(SKSL_INCLUDE, strlen(SKSL_INCLUDE), *fTypes, &ignored); + fIRGenerator->convertProgram(Program::kFragment_Kind, SKSL_INCLUDE, strlen(SKSL_INCLUDE), + *fTypes, &ignored); fIRGenerator->fSymbolTable->markAllFunctionsBuiltin(); if (fErrorCount) { printf("Unexpected errors: %s\n", fErrorText.c_str()); @@ -1146,19 +1147,19 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String tex std::vector<std::unique_ptr<ProgramElement>> elements; switch (kind) { case Program::kVertex_Kind: - fIRGenerator->convertProgram(SKSL_VERT_INCLUDE, strlen(SKSL_VERT_INCLUDE), *fTypes, - &elements); + fIRGenerator->convertProgram(kind, SKSL_VERT_INCLUDE, strlen(SKSL_VERT_INCLUDE), + *fTypes, &elements); break; case Program::kFragment_Kind: - fIRGenerator->convertProgram(SKSL_FRAG_INCLUDE, strlen(SKSL_FRAG_INCLUDE), *fTypes, - &elements); + fIRGenerator->convertProgram(kind, SKSL_FRAG_INCLUDE, strlen(SKSL_FRAG_INCLUDE), + *fTypes, &elements); break; case Program::kGeometry_Kind: - fIRGenerator->convertProgram(SKSL_GEOM_INCLUDE, strlen(SKSL_GEOM_INCLUDE), *fTypes, - &elements); + fIRGenerator->convertProgram(kind, SKSL_GEOM_INCLUDE, strlen(SKSL_GEOM_INCLUDE), + *fTypes, &elements); break; case Program::kFragmentProcessor_Kind: - fIRGenerator->convertProgram(SKSL_FP_INCLUDE, strlen(SKSL_FP_INCLUDE), *fTypes, + fIRGenerator->convertProgram(kind, SKSL_FP_INCLUDE, strlen(SKSL_FP_INCLUDE), *fTypes, &elements); break; } @@ -1170,7 +1171,7 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String tex } std::unique_ptr<String> textPtr(new String(std::move(text))); fSource = textPtr.get(); - fIRGenerator->convertProgram(textPtr->c_str(), textPtr->size(), *fTypes, &elements); + fIRGenerator->convertProgram(kind, textPtr->c_str(), textPtr->size(), *fTypes, &elements); if (!fErrorCount) { for (auto& element : elements) { if (element->fKind == ProgramElement::kFunction_Kind) { diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h index ca39c8c659..eb2fc45b51 100644 --- a/src/sksl/SkSLCompiler.h +++ b/src/sksl/SkSLCompiler.h @@ -45,6 +45,9 @@ class IRGenerator; */ class Compiler : public ErrorReporter { public: + static constexpr const char* RTADJUST_NAME = "sk_RTAdjust"; + static constexpr const char* PERVERTEX_NAME = "sk_PerVertex"; + enum Flags { kNone_Flags = 0, // permits static if/switch statements to be used with non-constant tests. This is used when diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp index cfa3049a2c..3d7e84329d 100644 --- a/src/sksl/SkSLIRGenerator.cpp +++ b/src/sksl/SkSLIRGenerator.cpp @@ -154,6 +154,9 @@ void IRGenerator::start(const Program::Settings* settings) { this->pushSymbolTable(); fInvocations = -1; fInputs.reset(); + fSkPerVertex = nullptr; + fRTAdjust = nullptr; + fRTAdjustInterfaceBlock = nullptr; } void IRGenerator::finish() { @@ -171,8 +174,26 @@ std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTStatement& sta return this->convertBlock((ASTBlock&) statement); case ASTStatement::kVarDeclaration_Kind: return this->convertVarDeclarationStatement((ASTVarDeclarationStatement&) statement); - case ASTStatement::kExpression_Kind: - return this->convertExpressionStatement((ASTExpressionStatement&) statement); + case ASTStatement::kExpression_Kind: { + std::unique_ptr<Statement> result = + this->convertExpressionStatement((ASTExpressionStatement&) statement); + if (fRTAdjust && Program::kGeometry_Kind == fKind) { + ASSERT(result->fKind == Statement::kExpression_Kind); + Expression& expr = *((ExpressionStatement&) *result).fExpression; + if (expr.fKind == Expression::kFunctionCall_Kind) { + FunctionCall& fc = (FunctionCall&) expr; + if (fc.fFunction.fBuiltin && fc.fFunction.fName == "EmitVertex") { + std::vector<std::unique_ptr<Statement>> statements; + statements.push_back(getNormalizeSkPositionCode()); + statements.push_back(std::move(result)); + return std::unique_ptr<Block>(new Block(statement.fOffset, + std::move(statements), + fSymbolTable)); + } + } + } + return result; + } case ASTStatement::kIf_Kind: return this->convertIf((ASTIfStatement&) statement); case ASTStatement::kFor_Kind: @@ -257,6 +278,11 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVa } auto var = std::unique_ptr<Variable>(new Variable(decl.fOffset, decl.fModifiers, varDecl.fName, *type, storage)); + if (var->fName == Compiler::RTADJUST_NAME) { + ASSERT(!fRTAdjust); + ASSERT(var->fType == *fContext.fFloat4_Type); + fRTAdjust = var.get(); + } std::unique_ptr<Expression> value; if (varDecl.fValue) { value = this->convertExpression(*varDecl.fValue); @@ -471,6 +497,10 @@ std::unique_ptr<Statement> IRGenerator::convertExpressionStatement( std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTReturnStatement& r) { ASSERT(fCurrentFunction); + // early returns from a vertex main function will bypass the sk_Position normalization, so + // assert that we aren't doing that. It is of course possible to fix this by adding a + // normalization before each return, but it will probably never actually be necessary. + ASSERT(Program::kVertex_Kind != fKind || !fRTAdjust || "main" != fCurrentFunction->fName); if (r.fExpression) { std::unique_ptr<Expression> result = this->convertExpression(*r.fExpression); if (!result) { @@ -574,6 +604,40 @@ std::unique_ptr<Block> IRGenerator::applyInvocationIDWorkaround(std::unique_ptr< return std::unique_ptr<Block>(new Block(-1, std::move(children))); } +std::unique_ptr<Statement> IRGenerator::getNormalizeSkPositionCode() { + // sk_Position = float4(sk_Position.x * rtAdjust.x + sk_Position.w * rtAdjust.y, + // sk_Position.y * rtAdjust.z + sk_Position.w * rtAdjust.w, + // 0, + // sk_Position.w); + ASSERT(fSkPerVertex && fRTAdjust); + #define REF(var) std::unique_ptr<Expression>(\ + new VariableReference(-1, *var, VariableReference::kRead_RefKind)) + #define FIELD(var, idx) std::unique_ptr<Expression>(\ + new FieldAccess(REF(var), idx, FieldAccess::kAnonymousInterfaceBlock_OwnerKind)) + #define POS std::unique_ptr<Expression>(new FieldAccess(REF(fSkPerVertex), 0, \ + FieldAccess::kAnonymousInterfaceBlock_OwnerKind)) + #define ADJUST (fRTAdjustInterfaceBlock ? \ + FIELD(fRTAdjustInterfaceBlock, fRTAdjustFieldIndex) : \ + REF(fRTAdjust)) + #define SWIZZLE(expr, field) std::unique_ptr<Expression>(new Swizzle(fContext, expr, { field })) + #define OP(left, op, right) std::unique_ptr<Expression>(\ + new BinaryExpression(-1, left, op, right, *fContext.fFloat_Type)) + std::vector<std::unique_ptr<Expression>> children; + children.push_back(OP(OP(SWIZZLE(POS, 0), Token::STAR, SWIZZLE(ADJUST, 0)), + Token::PLUS, + OP(SWIZZLE(POS, 3), Token::STAR, SWIZZLE(ADJUST, 1)))); + children.push_back(OP(OP(SWIZZLE(POS, 1), Token::STAR, SWIZZLE(ADJUST, 2)), + Token::PLUS, + OP(SWIZZLE(POS, 3), Token::STAR, SWIZZLE(ADJUST, 3)))); + children.push_back(std::unique_ptr<Expression>(new IntLiteral(fContext, -1, 0))); + children.push_back(SWIZZLE(POS, 3)); + std::unique_ptr<Expression> result = OP(POS, Token::EQ, + std::unique_ptr<Expression>(new Constructor(-1, + *fContext.fFloat4_Type, + std::move(children)))); + return std::unique_ptr<Statement>(new ExpressionStatement(std::move(result))); +} + void IRGenerator::convertFunction(const ASTFunction& f) { const Type* returnType = this->convertType(*f.fReturnType); if (!returnType) { @@ -690,7 +754,9 @@ void IRGenerator::convertFunction(const ASTFunction& f) { } // conservatively assume all user-defined functions have side effects ((Modifiers&) decl->fModifiers).fFlags |= Modifiers::kHasSideEffects_Flag; - + if (Program::kVertex_Kind == fKind && f.fName == "main" && fRTAdjust) { + body->fStatements.insert(body->fStatements.end(), this->getNormalizeSkPositionCode()); + } fProgramElements->push_back(std::unique_ptr<FunctionDefinition>( new FunctionDefinition(f.fOffset, *decl, std::move(body)))); } @@ -701,6 +767,7 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInte AutoSymbolTable table(this); std::vector<Type::Field> fields; bool haveRuntimeArray = false; + bool foundRTAdjust = false; for (size_t i = 0; i < intf.fDeclarations.size(); i++) { std::unique_ptr<VarDeclarations> decl = this->convertVarDeclarations( *intf.fDeclarations[i], @@ -715,6 +782,11 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInte "only the last entry in an interface block may be a runtime-sized " "array"); } + if (vd.fVar == fRTAdjust) { + foundRTAdjust = true; + ASSERT(vd.fVar->fType == *fContext.fFloat4_Type); + fRTAdjustFieldIndex = fields.size(); + } fields.push_back(Type::Field(vd.fVar->fModifiers, vd.fVar->fName, &vd.fVar->fType)); if (vd.fValue) { @@ -768,6 +840,9 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInte Variable* var = new Variable(intf.fOffset, intf.fModifiers, intf.fInstanceName.fLength ? intf.fInstanceName : intf.fTypeName, *type, Variable::kGlobal_Storage); + if (foundRTAdjust) { + fRTAdjustInterfaceBlock = var; + } old->takeOwnership(var); if (intf.fInstanceName.fLength) { old->addWithoutOwnership(intf.fInstanceName, var); @@ -777,6 +852,10 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInte (int) i))); } } + if (var->fName == Compiler::PERVERTEX_NAME) { + ASSERT(!fSkPerVertex); + fSkPerVertex = var; + } return std::unique_ptr<InterfaceBlock>(new InterfaceBlock(intf.fOffset, var, intf.fTypeName, @@ -2020,10 +2099,12 @@ void IRGenerator::markWrittenTo(const Expression& expr, bool readWrite) { } } -void IRGenerator::convertProgram(const char* text, +void IRGenerator::convertProgram(Program::Kind kind, + const char* text, size_t length, SymbolTable& types, std::vector<std::unique_ptr<ProgramElement>>* out) { + fKind = kind; fProgramElements = out; Parser parser(text, length, types, fErrors); std::vector<std::unique_ptr<ASTDeclaration>> parsed = parser.file(); diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h index 1df9b65bd0..327fe6fc7a 100644 --- a/src/sksl/SkSLIRGenerator.h +++ b/src/sksl/SkSLIRGenerator.h @@ -62,7 +62,8 @@ public: IRGenerator(const Context* context, std::shared_ptr<SymbolTable> root, ErrorReporter& errorReporter); - void convertProgram(const char* text, + void convertProgram(Program::Kind kind, + const char* text, size_t length, SymbolTable& types, std::vector<std::unique_ptr<ProgramElement>>* result); @@ -156,12 +157,15 @@ private: std::unique_ptr<Statement> convertWhile(const ASTWhileStatement& w); void convertEnum(const ASTEnum& e); std::unique_ptr<Block> applyInvocationIDWorkaround(std::unique_ptr<Block> main); + // returns a statement which converts sk_Position from device to normalized coordinates + std::unique_ptr<Statement> getNormalizeSkPositionCode(); void fixRectSampling(std::vector<std::unique_ptr<Expression>>& arguments); void checkValid(const Expression& expr); void markWrittenTo(const Expression& expr, bool readWrite); void getConstantInt(const Expression& value, int64_t* out); + Program::Kind fKind; const FunctionDeclaration* fCurrentFunction; std::unordered_map<String, Program::Settings::Value> fCapsMap; std::shared_ptr<SymbolTable> fRootSymbolTable; @@ -175,6 +179,10 @@ private: ErrorReporter& fErrors; int fInvocations; std::vector<std::unique_ptr<ProgramElement>>* fProgramElements; + Variable* fSkPerVertex; + Variable* fRTAdjust; + Variable* fRTAdjustInterfaceBlock; + int fRTAdjustFieldIndex; friend class AutoSymbolTable; friend class AutoLoopLevel; |