diff options
author | 2017-01-13 16:40:35 -0500 | |
---|---|---|
committer | 2017-01-17 15:22:06 +0000 | |
commit | fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0 (patch) | |
tree | ee58419e34142c9ab6d5292a90d7450be401891b /src | |
parent | 6d4d6cce5e6e73d14c5d39c20321b189d737dfd5 (diff) |
do/while loops in SPIR-V no longer cause an assertion failure
BUG=skia:
Change-Id: Ic5f590879d8ada5d4580b5c6e9091ccc9532be4b
Reviewed-on: https://skia-review.googlesource.com/6605
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/sksl/SkSLSPIRVCodeGenerator.cpp | 70 | ||||
-rw-r--r-- | src/sksl/SkSLSPIRVCodeGenerator.h | 6 |
2 files changed, 76 insertions, 0 deletions
diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp index 1e85f115fd..8afd13688c 100644 --- a/src/sksl/SkSLSPIRVCodeGenerator.cpp +++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp @@ -2626,6 +2626,12 @@ void SPIRVCodeGenerator::writeStatement(const Statement& s, SkWStream& out) { case Statement::kFor_Kind: this->writeForStatement((ForStatement&) s, out); break; + case Statement::kWhile_Kind: + this->writeWhileStatement((WhileStatement&) s, out); + break; + case Statement::kDo_Kind: + this->writeDoStatement((DoStatement&) s, out); + break; case Statement::kBreak_Kind: this->writeInstruction(SpvOpBranch, fBreakTarget.top(), out); break; @@ -2712,6 +2718,70 @@ void SPIRVCodeGenerator::writeForStatement(const ForStatement& f, SkWStream& out fContinueTarget.pop(); } +void SPIRVCodeGenerator::writeWhileStatement(const WhileStatement& w, SkWStream& out) { + // We believe the while loop code below will work, but Skia doesn't actually use them and + // adequately testing this code in the absence of Skia exercising it isn't straightforward. For + // the time being, we just fail with an error due to the lack of testing. If you encounter this + // message, simply remove the error call below to see whether our while loop support actually + // works. + fErrors.error(w.fPosition, "internal error: while loop support has been disabled in SPIR-V, " + "see SkSLSPIRVCodeGenerator.cpp for details"); + + SpvId header = this->nextId(); + SpvId start = this->nextId(); + SpvId body = this->nextId(); + fContinueTarget.push(start); + SpvId end = this->nextId(); + fBreakTarget.push(end); + this->writeInstruction(SpvOpBranch, header, out); + this->writeLabel(header, out); + this->writeInstruction(SpvOpLoopMerge, end, start, SpvLoopControlMaskNone, out); + this->writeInstruction(SpvOpBranch, start, out); + this->writeLabel(start, out); + SpvId test = this->writeExpression(*w.fTest, out); + this->writeInstruction(SpvOpBranchConditional, test, body, end, out); + this->writeLabel(body, out); + this->writeStatement(*w.fStatement, out); + if (fCurrentBlock) { + this->writeInstruction(SpvOpBranch, start, out); + } + this->writeLabel(end, out); + fBreakTarget.pop(); + fContinueTarget.pop(); +} + +void SPIRVCodeGenerator::writeDoStatement(const DoStatement& d, SkWStream& out) { + // We believe the do loop code below will work, but Skia doesn't actually use them and + // adequately testing this code in the absence of Skia exercising it isn't straightforward. For + // the time being, we just fail with an error due to the lack of testing. If you encounter this + // message, simply remove the error call below to see whether our do loop support actually + // works. + fErrors.error(d.fPosition, "internal error: do loop support has been disabled in SPIR-V, see " + "SkSLSPIRVCodeGenerator.cpp for details"); + + SpvId header = this->nextId(); + SpvId start = this->nextId(); + SpvId next = this->nextId(); + fContinueTarget.push(next); + SpvId end = this->nextId(); + fBreakTarget.push(end); + this->writeInstruction(SpvOpBranch, header, out); + this->writeLabel(header, out); + this->writeInstruction(SpvOpLoopMerge, end, start, SpvLoopControlMaskNone, out); + this->writeInstruction(SpvOpBranch, start, out); + this->writeLabel(start, out); + this->writeStatement(*d.fStatement, out); + if (fCurrentBlock) { + this->writeInstruction(SpvOpBranch, next, out); + } + this->writeLabel(next, out); + SpvId test = this->writeExpression(*d.fTest, out); + this->writeInstruction(SpvOpBranchConditional, test, start, end, out); + this->writeLabel(end, out); + fBreakTarget.pop(); + fContinueTarget.pop(); +} + void SPIRVCodeGenerator::writeReturnStatement(const ReturnStatement& r, SkWStream& out) { if (r.fExpression) { this->writeInstruction(SpvOpReturnValue, this->writeExpression(*r.fExpression, out), diff --git a/src/sksl/SkSLSPIRVCodeGenerator.h b/src/sksl/SkSLSPIRVCodeGenerator.h index 96ff187983..562bf279e9 100644 --- a/src/sksl/SkSLSPIRVCodeGenerator.h +++ b/src/sksl/SkSLSPIRVCodeGenerator.h @@ -18,6 +18,7 @@ #include "ir/SkSLBinaryExpression.h" #include "ir/SkSLBoolLiteral.h" #include "ir/SkSLConstructor.h" +#include "ir/SkSLDoStatement.h" #include "ir/SkSLFloatLiteral.h" #include "ir/SkSLIfStatement.h" #include "ir/SkSLIndexExpression.h" @@ -38,6 +39,7 @@ #include "ir/SkSLVarDeclarations.h" #include "ir/SkSLVarDeclarationsStatement.h" #include "ir/SkSLVariableReference.h" +#include "ir/SkSLWhileStatement.h" #include "spirv.h" namespace SkSL { @@ -191,6 +193,10 @@ private: void writeForStatement(const ForStatement& f, SkWStream& out); + void writeWhileStatement(const WhileStatement& w, SkWStream& out); + + void writeDoStatement(const DoStatement& d, SkWStream& out); + void writeReturnStatement(const ReturnStatement& r, SkWStream& out); void writeCapabilities(SkWStream& out); |