Commit a8c9cecf by Shahbaz Youssefi Committed by Angle LUCI CQ

Vulkan: SPIR-V Gen: Support break and continue

This is simply done by issuing a branch to the merge or continue blocks respectively. Bug: angleproject:4889 Change-Id: I3e96a3b0f1a0533aa4eac519ab64a87600c0983b Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2957810 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent e45682b4
......@@ -1009,6 +1009,43 @@ bool SPIRVBuilder::isInLoop() const
return false;
}
spirv::IdRef SPIRVBuilder::getBreakTargetId() const
{
for (size_t index = mConditionalStack.size(); index > 0; --index)
{
const SpirvConditional &conditional = mConditionalStack[index - 1];
if (conditional.isBreakable)
{
// The target of break; is always the merge block, and the merge block is always the
// last block.
return conditional.blockIds.back();
}
}
UNREACHABLE();
return spirv::IdRef{};
}
spirv::IdRef SPIRVBuilder::getContinueTargetId() const
{
for (size_t index = mConditionalStack.size(); index > 0; --index)
{
const SpirvConditional &conditional = mConditionalStack[index - 1];
if (conditional.isContinuable)
{
// The target of continue; is always the block before merge, so it's the one before
// last.
ASSERT(conditional.blockIds.size() > 2);
return conditional.blockIds[conditional.blockIds.size() - 2];
}
}
UNREACHABLE();
return spirv::IdRef{};
}
uint32_t SPIRVBuilder::nextUnusedBinding()
{
return mNextUnusedBinding++;
......
......@@ -339,6 +339,8 @@ class SPIRVBuilder : angle::NonCopyable
void nextConditionalBlock();
void endConditional();
bool isInLoop() const;
spirv::IdRef getBreakTargetId() const;
spirv::IdRef getContinueTargetId() const;
// TODO: remove name hashing once translation through glslang is removed. That is necessary to
// avoid name collision between ANGLE's internal symbols and user-defined ones when compiling
......
......@@ -3797,12 +3797,14 @@ bool OutputSPIRVTraverser::visitBranch(Visit visit, TIntermBranch *node)
mBuilder.terminateCurrentFunctionBlock();
break;
case EOpBreak:
// TODO: http://anglebug.com/4889
UNIMPLEMENTED();
spirv::WriteBranch(mBuilder.getSpirvCurrentFunctionBlock(),
mBuilder.getBreakTargetId());
mBuilder.terminateCurrentFunctionBlock();
break;
case EOpContinue:
// TODO: http://anglebug.com/4889
UNIMPLEMENTED();
spirv::WriteBranch(mBuilder.getSpirvCurrentFunctionBlock(),
mBuilder.getContinueTargetId());
mBuilder.terminateCurrentFunctionBlock();
break;
case EOpReturn:
// Evaluate the expression if any, and return.
......
......@@ -14,17 +14,24 @@
6073 GLES : ProgramInterfaceTestES31.ReloadFromCacheShouldNotCrash/ES3_1_OpenGLES__cached = SKIP
// Windows
3786 WIN NVIDIA D3D11 : BufferDataOverflowTest.VertexBufferIntegerOverflow/ES3_D3D11 = SKIP
4092 WIN VULKAN : BufferDataOverflowTest.VertexBufferIntegerOverflow/ES3_Vulkan* = SKIP
4092 WIN OPENGL : BufferDataOverflowTest.VertexBufferIntegerOverflow/ES3_OpenGL = SKIP
4092 WIN GLES : BufferDataOverflowTest.VertexBufferIntegerOverflow/ES3_OpenGLES = SKIP
3786 WIN NVIDIA D3D11 : BufferDataOverflowTest.VertexBufferIntegerOverflow/* = SKIP
4092 WIN VULKAN : BufferDataOverflowTest.VertexBufferIntegerOverflow/* = SKIP
4092 WIN OPENGL : BufferDataOverflowTest.VertexBufferIntegerOverflow/* = SKIP
4092 WIN GLES : BufferDataOverflowTest.VertexBufferIntegerOverflow/* = SKIP
6064 WIN D3D11 : SimpleStateChangeTestES31.DrawThenChangeFBOThenDrawThenFlushInAnotherThreadThenDrawIndexed/* = SKIP
// Linux
6065 LINUX INTEL VULKAN : SimpleStateChangeTestES31.DrawThenUpdateUBOThenDrawThenDrawIndexed/* = SKIP
// Fails in older mesa
6109 LINUX INTEL : GLSLTestLoops.BasicDoWhile/ES3_* = SKIP
6109 LINUX INTEL : GLSLTestLoops.BasicWhile/ES3_* = SKIP
6109 LINUX INTEL : GLSLTestLoops.*While*/* = SKIP
// Nvidia
6115 NVIDIA OPENGL : GLSLTestLoops.DoWhileContinue/* = SKIP
6115 NVIDIA OPENGL : GLSLTestLoops.DoWhileUnconditionalContinue/* = SKIP
6115 NVIDIA OPENGL : GLSLTestLoops.WhileBreak/* = SKIP
6115 NVIDIA GLES : GLSLTestLoops.DoWhileContinue/* = SKIP
6115 NVIDIA GLES : GLSLTestLoops.DoWhileUnconditionalContinue/* = SKIP
6115 NVIDIA GLES : GLSLTestLoops.WhileBreak/* = SKIP
// Intel Vulkan
......@@ -53,6 +60,7 @@
// Android
6095 ANDROID GLES : GLSLTest_ES3.InitGlobalComplexConstant/ES3_OpenGLES = SKIP
6116 ANDROID GLES : GLSLTestLoops.ForNoCondition/ES3_OpenGLES = SKIP
// Pixel 4 expectations.
5981 PIXEL4ORXL GLES : BlitFramebufferTest.BlitSRGBToRGBOversizedDestArea/* = SKIP
......
......@@ -11112,6 +11112,166 @@ void main()
runTest(kFS);
}
// Test for loop without condition
TEST_P(GLSLTestLoops, ForNoCondition)
{
constexpr char kFS[] = R"(#version 300 es
precision mediump float;
out vec4 color;
void main()
{
int result = 0;
for (int i = 0; i < 10; ++i)
for (int j = 0; ; ++j)
{
for (int k = 0; k < 2; ++k, ++j) ++result;
for (int k = 0; k < 3; ++k) ++result;
for (int k = 0; k < 0; ++k) ++result;
if (j >= 8)
break;
}
color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
})";
runTest(kFS);
}
// Test for loop without init and expression
TEST_P(GLSLTestLoops, ForNoInitConditionOrExpression)
{
constexpr char kFS[] = R"(#version 300 es
precision mediump float;
out vec4 color;
void main()
{
int result = 0;
for (int i = 0; i < 10; ++i)
{
int j = 0;
for (;;)
{
for (int k = 0; k < 2; ++k, ++j) ++result;
for (int k = 0; k < 3; ++k) ++result;
for (int k = 0; k < 0; ++k) ++result;
if (j >= 8)
break;
++j;
}
}
color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
})";
runTest(kFS);
}
// Test for loop with continue
TEST_P(GLSLTestLoops, ForContinue)
{
constexpr char kFS[] = R"(#version 300 es
precision mediump float;
out vec4 color;
void main()
{
int result = 0;
for (int i = 0; i < 10; ++i)
for (int j = 0; j < 8; ++j)
{
for (int k = 0; k < 2; ++k, ++j) ++result;
for (int k = 0; k < 3; ++k) ++result;
if (i > 3)
continue;
for (int k = 0; k < 0; ++k) ++result;
}
color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
})";
runTest(kFS);
}
// Test for loop with continue at the end of block
TEST_P(GLSLTestLoops, ForUnconditionalContinue)
{
constexpr char kFS[] = R"(#version 300 es
precision mediump float;
out vec4 color;
void main()
{
int result = 0;
for (int i = 0; i < 10; ++i)
for (int j = 0; j < 8; ++j)
{
for (int k = 0; k < 2; ++k, ++j) ++result;
for (int k = 0; k < 3; ++k) ++result;
for (int k = 0; k < 0; ++k) ++result;
continue;
}
color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
})";
runTest(kFS);
}
// Test for loop with break at the end of block
TEST_P(GLSLTestLoops, ForUnconditionalBreak)
{
constexpr char kFS[] = R"(#version 300 es
precision mediump float;
out vec4 color;
void main()
{
int result = 0;
for (int i = 0; i < 10; ++i)
for (int j = 0; j < 8; ++j)
{
for (int k = 0; k < 2; ++k, ++j) ++result;
for (int k = 0; k < 3; ++k) ++result;
for (int k = 0; k < 0; ++k) ++result;
break;
}
color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
})";
runTest(kFS);
}
// Test for loop with break and continue
TEST_P(GLSLTestLoops, ForBreakContinue)
{
constexpr char kFS[] = R"(#version 300 es
precision mediump float;
out vec4 color;
void main()
{
int result = 0;
for (int i = 0; i < 10; ++i)
for (int j = 0; j < 8; ++j)
{
if (j < 2) continue;
if (j > 6) break;
if (i < 3) continue;
if (i > 8) break;
++result;
}
color = result == 30 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
})";
runTest(kFS);
}
// Test basic while loops
TEST_P(GLSLTestLoops, BasicWhile)
{
......@@ -11143,6 +11303,139 @@ void main()
runTest(kFS);
}
// Test while loops with continue
TEST_P(GLSLTestLoops, WhileContinue)
{
constexpr char kFS[] = R"(#version 300 es
precision mediump float;
out vec4 color;
void main()
{
int result = 0;
int i = 0;
while (i < 10)
{
int j = 0;
while (j < 8)
{
int k = 0;
while (k < 2) { ++result; ++k; ++j; }
while (k < 5) { ++result; ++k; }
if (i > 3)
{
++j;
continue;
}
while (k < 4) { ++result; }
++j;
}
++i;
}
color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
})";
runTest(kFS);
}
// Test while loops with continue at the end of block
TEST_P(GLSLTestLoops, WhileUnconditionalContinue)
{
constexpr char kFS[] = R"(#version 300 es
precision mediump float;
out vec4 color;
void main()
{
int result = 0;
int i = 0;
while (i < 10)
{
int j = 0;
while (j < 8)
{
int k = 0;
while (k < 2) { ++result; ++k; ++j; }
while (k < 5) { ++result; ++k; }
while (k < 4) { ++result; }
++j;
continue;
}
++i;
}
color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
})";
runTest(kFS);
}
// Test while loops with break
TEST_P(GLSLTestLoops, WhileBreak)
{
constexpr char kFS[] = R"(#version 300 es
precision mediump float;
out vec4 color;
void main()
{
int result = 0;
int i = 0;
while (i < 10)
{
int j = 0;
while (true)
{
int k = 0;
while (k < 2) { ++result; ++k; ++j; }
while (k < 5) { ++result; ++k; }
while (k < 4) { ++result; }
++j;
if (j >= 8)
break;
}
++i;
}
color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
})";
runTest(kFS);
}
// Test while loops with continue at the end of block
TEST_P(GLSLTestLoops, WhileUnconditionalBreak)
{
constexpr char kFS[] = R"(#version 300 es
precision mediump float;
out vec4 color;
void main()
{
int result = 0;
int i = 0;
while (i < 10)
{
int j = 0;
while (j < 8)
{
int k = 0;
while (k < 2) { ++result; ++k; ++j; }
while (k < 5) { ++result; ++k; }
while (k < 4) { ++result; }
++j;
break;
}
++i;
}
color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
})";
runTest(kFS);
}
// Test basic do-while loops
TEST_P(GLSLTestLoops, BasicDoWhile)
{
......@@ -11174,6 +11467,137 @@ void main()
runTest(kFS);
}
// Test do-while loops with continue
TEST_P(GLSLTestLoops, DoWhileContinue)
{
constexpr char kFS[] = R"(#version 300 es
precision mediump float;
out vec4 color;
void main()
{
int result = 0;
int i = 0;
do
{
int j = 0;
do
{
int k = 0;
do { ++result; ++k; ++j; } while (k < 2);
if (i > 3)
{
++j;
continue;
}
do { ++result; ++k; } while (k < 5);
do { ++result; } while (k < 3);
++j;
} while (j < 8);
++i;
} while (i < 10);
color = result == 108 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
})";
runTest(kFS);
}
// Test do-while loops with continue at the end of block
TEST_P(GLSLTestLoops, DoWhileUnconditionalContinue)
{
constexpr char kFS[] = R"(#version 300 es
precision mediump float;
out vec4 color;
void main()
{
int result = 0;
int i = 0;
do
{
int j = 0;
do
{
int k = 0;
do { ++result; ++k; ++j; continue; } while (k < 2);
do { ++result; ++k; continue; } while (k < 5);
do { ++result; continue; } while (k < 3);
++j;
} while (j < 8);
++i;
} while (i < 10);
color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
})";
runTest(kFS);
}
// Test do-while loops with break
TEST_P(GLSLTestLoops, DoWhileBreak)
{
constexpr char kFS[] = R"(#version 300 es
precision mediump float;
out vec4 color;
void main()
{
int result = 0;
int i = 0;
do
{
int j = 0;
do
{
int k = 0;
do { ++result; ++k; ++j; } while (k < 2);
do { ++result; ++k; } while (k < 5);
do { ++result; } while (k < 3);
++j;
if (j >= 8)
break;
} while (true);
++i;
} while (i < 10);
color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
})";
runTest(kFS);
}
// Test do-while loops with break at the end of block
TEST_P(GLSLTestLoops, DoWhileUnconditionalBreak)
{
constexpr char kFS[] = R"(#version 300 es
precision mediump float;
out vec4 color;
void main()
{
int result = 0;
int i = 0;
do
{
int j = 0;
do
{
int k = 0;
do { ++result; ++k; ++j; break; } while (k < 2);
do { ++result; ++k; break; } while (k < 5);
do { ++result; break; } while (k < 3);
++j;
} while (j < 8);
++i;
} while (i < 10);
color = result == 120 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
})";
runTest(kFS);
}
} // anonymous namespace
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(GLSLTest);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment