aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Ethan Nicholas <ethannicholas@google.com>2017-01-13 16:40:35 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-01-17 15:22:06 +0000
commitfd146aa1dd8ea2d83396bb3a19c7556d9297a5e0 (patch)
treeee58419e34142c9ab6d5292a90d7450be401891b /src
parent6d4d6cce5e6e73d14c5d39c20321b189d737dfd5 (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.cpp70
-rw-r--r--src/sksl/SkSLSPIRVCodeGenerator.h6
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);