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>
This commit is contained in:
Ethan Nicholas 2017-01-13 16:40:35 -05:00 committed by Skia Commit-Bot
parent 6d4d6cce5e
commit fd146aa1dd
2 changed files with 76 additions and 0 deletions

View File

@ -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),

View File

@ -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);