Commit 44f462b0 by Alexis Hetu Committed by Alexis Hétu

Fix support for OpKill as non-terminator

Fixing this issue required using the WrapOpKill SPIRV-Tools pass. This pass wraps OpKill instructions inside a function. See the following for the explanation: https://github.com/KhronosGroup/SPIRV-Tools/issues/2726 dEQP-GLES2.functional.shaders.discard.function_always fails on ANGLE on top of SwiftShader Vulkan without this fix. Bug b/141246700 Change-Id: I48ce3c19a1b02160fd8f23b60a75e5f8f35a4d37 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/36450 Presubmit-Ready: Alexis Hétu <sugoi@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent b6fa949c
...@@ -917,12 +917,15 @@ namespace sw ...@@ -917,12 +917,15 @@ namespace sw
break; break;
case spv::OpFunctionParameter: case spv::OpFunctionParameter:
case spv::OpFunctionCall:
// These should have all been removed by preprocessing passes. If we see them here, // These should have all been removed by preprocessing passes. If we see them here,
// our assumptions are wrong and we will probably generate wrong code. // our assumptions are wrong and we will probably generate wrong code.
UNREACHABLE("%s should have already been lowered.", OpcodeName(opcode).c_str()); UNREACHABLE("%s should have already been lowered.", OpcodeName(opcode).c_str());
break; break;
case spv::OpFunctionCall:
// TODO(b/141246700): Add full support for spv::OpFunctionCall
break;
case spv::OpFConvert: case spv::OpFConvert:
UNSUPPORTED("SPIR-V Float16 or Float64 Capability (OpFConvert)"); UNSUPPORTED("SPIR-V Float16 or Float64 Capability (OpFConvert)");
break; break;
...@@ -2693,6 +2696,9 @@ namespace sw ...@@ -2693,6 +2696,9 @@ namespace sw
case spv::OpReturn: case spv::OpReturn:
return EmitReturn(insn, state); return EmitReturn(insn, state);
case spv::OpFunctionCall:
return EmitFunctionCall(insn, state);
case spv::OpKill: case spv::OpKill:
return EmitKill(insn, state); return EmitKill(insn, state);
...@@ -4833,6 +4839,44 @@ namespace sw ...@@ -4833,6 +4839,44 @@ namespace sw
return EmitResult::Terminator; return EmitResult::Terminator;
} }
SpirvShader::EmitResult SpirvShader::EmitFunctionCall(InsnIterator insn, EmitState *state) const
{
auto functionId = Function::ID(insn.word(3));
const auto& functionIt = functions.find(functionId);
ASSERT(functionIt != functions.end());
auto& function = functionIt->second;
// TODO(b/141246700): Add full support for spv::OpFunctionCall
// The only supported function is a single OpKill wrapped in a
// function, as a result of the "wrap OpKill" SPIRV-Tools pass
ASSERT(function.blocks.size() == 1);
spv::Op wrapOpKill[] = { spv::OpLabel, spv::OpKill };
for (auto block : function.blocks)
{
int insnNumber = 0;
for (auto blockInsn : block.second)
{
if (insnNumber > 1)
{
UNIMPLEMENTED("Function block number of instructions: %d", insnNumber);
return EmitResult::Continue;
}
if (blockInsn.opcode() != wrapOpKill[insnNumber++])
{
UNIMPLEMENTED("Function block instruction %d : %s", insnNumber - 1, OpcodeName(blockInsn.opcode()).c_str());
return EmitResult::Continue;
}
if (blockInsn.opcode() == spv::OpKill)
{
EmitInstruction(blockInsn, state);
}
}
}
return EmitResult::Continue;
}
SpirvShader::EmitResult SpirvShader::EmitPhi(InsnIterator insn, EmitState *state) const SpirvShader::EmitResult SpirvShader::EmitPhi(InsnIterator insn, EmitState *state) const
{ {
auto &function = getFunction(state->function); auto &function = getFunction(state->function);
......
...@@ -1224,6 +1224,7 @@ namespace sw ...@@ -1224,6 +1224,7 @@ namespace sw
EmitResult EmitUnreachable(InsnIterator insn, EmitState *state) const; EmitResult EmitUnreachable(InsnIterator insn, EmitState *state) const;
EmitResult EmitReturn(InsnIterator insn, EmitState *state) const; EmitResult EmitReturn(InsnIterator insn, EmitState *state) const;
EmitResult EmitKill(InsnIterator insn, EmitState *state) const; EmitResult EmitKill(InsnIterator insn, EmitState *state) const;
EmitResult EmitFunctionCall(InsnIterator insn, EmitState *state) const;
EmitResult EmitPhi(InsnIterator insn, EmitState *state) const; EmitResult EmitPhi(InsnIterator insn, EmitState *state) const;
EmitResult EmitImageSampleImplicitLod(Variant variant, InsnIterator insn, EmitState *state) const; EmitResult EmitImageSampleImplicitLod(Variant variant, InsnIterator insn, EmitState *state) const;
EmitResult EmitImageSampleExplicitLod(Variant variant, InsnIterator insn, EmitState *state) const; EmitResult EmitImageSampleExplicitLod(Variant variant, InsnIterator insn, EmitState *state) const;
......
...@@ -193,7 +193,8 @@ std::vector<uint32_t> preprocessSpirv( ...@@ -193,7 +193,8 @@ std::vector<uint32_t> preprocessSpirv(
} }
// Full optimization list taken from spirv-opt. // Full optimization list taken from spirv-opt.
opt.RegisterPass(spvtools::CreateDeadBranchElimPass()) opt.RegisterPass(spvtools::CreateWrapOpKillPass())
.RegisterPass(spvtools::CreateDeadBranchElimPass())
.RegisterPass(spvtools::CreateMergeReturnPass()) .RegisterPass(spvtools::CreateMergeReturnPass())
.RegisterPass(spvtools::CreateInlineExhaustivePass()) .RegisterPass(spvtools::CreateInlineExhaustivePass())
.RegisterPass(spvtools::CreateAggressiveDCEPass()) .RegisterPass(spvtools::CreateAggressiveDCEPass())
......
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