Commit 0e976bca by Ben Clayton

SpirvShader: Fixes for complex loops.

Combine all the active lane masks for the merge block. Previously this was only using the lane mask of the last loop iteration. Loop phis were being overridden even for disabled lanes. Now fixed. Made EmitBranch() use addActiveLaneMaskEdge(). This is effectively a noop change, but keeps the code more consistent. dEQP-VK.glsl.switch.switch_in_do_while_loop_dynamic_vertex still seems broken, which I'm investigating. Tests: dEQP-VK.glsl.switch.* Bug: b/128527271 Change-Id: I49bafe5cdb49d6878dde98134f9cbb9a3ad4d384 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/31268 Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Presubmit-Ready: Ben Clayton <bclayton@google.com> Tested-by: 's avatarBen Clayton <bclayton@google.com> Reviewed-by: 's avatarChris Forbes <chrisforbes@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent 40a6ed8d
...@@ -2076,6 +2076,14 @@ namespace sw ...@@ -2076,6 +2076,14 @@ namespace sw
} }
} }
// mergeActiveLaneMasks contains edge lane masks for the merge block.
// This is the union of all edge masks across all iterations of the loop.
std::unordered_map<Block::ID, SIMD::Int> mergeActiveLaneMasks;
for (auto in : getBlock(block.mergeBlock).ins)
{
mergeActiveLaneMasks.emplace(in, SIMD::Int(0));
}
// Generate an alloca for each of the loop's phis. // Generate an alloca for each of the loop's phis.
// These will be primed with the incoming, non back edge Phi values // These will be primed with the incoming, non back edge Phi values
// before the loop, and then updated just before the loop jumps back to // before the loop, and then updated just before the loop jumps back to
...@@ -2192,6 +2200,17 @@ namespace sw ...@@ -2192,6 +2200,17 @@ namespace sw
} }
} }
// Add active lanes to the merge lane mask.
for (auto in : getBlock(block.mergeBlock).ins)
{
auto edge = Block::Edge{in, block.mergeBlock};
auto it = state->edgeActiveLaneMasks.find(edge);
if (it != state->edgeActiveLaneMasks.end())
{
mergeActiveLaneMasks[in] |= it->second;
}
}
// Update loop phi values // Update loop phi values
for (auto &phi : phis) for (auto &phi : phis)
{ {
...@@ -2201,7 +2220,7 @@ namespace sw ...@@ -2201,7 +2220,7 @@ namespace sw
auto &type = getType(getObject(phi.phiId).type); auto &type = getType(getObject(phi.phiId).type);
for (unsigned int i = 0u; i < type.sizeInComponents; i++) for (unsigned int i = 0u; i < type.sizeInComponents; i++)
{ {
phi.storage[i] = val.Int(i); phi.storage[i] = (val.Int(i) & loopActiveLaneMask) | (phi.storage[i] & ~loopActiveLaneMask);
} }
} }
} }
...@@ -2214,6 +2233,10 @@ namespace sw ...@@ -2214,6 +2233,10 @@ namespace sw
// Continue emitting from the merge block. // Continue emitting from the merge block.
Nucleus::setInsertBlock(mergeBasicBlock); Nucleus::setInsertBlock(mergeBasicBlock);
state->pending->emplace(block.mergeBlock); state->pending->emplace(block.mergeBlock);
for (auto it : mergeActiveLaneMasks)
{
state->addActiveLaneMaskEdge(it.first, block.mergeBlock, it.second);
}
} }
SpirvShader::EmitResult SpirvShader::EmitInstruction(InsnIterator insn, EmitState *state) const SpirvShader::EmitResult SpirvShader::EmitInstruction(InsnIterator insn, EmitState *state) const
...@@ -4501,8 +4524,7 @@ namespace sw ...@@ -4501,8 +4524,7 @@ namespace sw
SpirvShader::EmitResult SpirvShader::EmitBranch(InsnIterator insn, EmitState *state) const SpirvShader::EmitResult SpirvShader::EmitBranch(InsnIterator insn, EmitState *state) const
{ {
auto target = Block::ID(insn.word(1)); auto target = Block::ID(insn.word(1));
auto edge = Block::Edge{state->currentBlock, target}; state->addActiveLaneMaskEdge(state->currentBlock, target, state->activeLaneMask());
state->edgeActiveLaneMasks.emplace(edge, state->activeLaneMask());
return EmitResult::Terminator; return EmitResult::Terminator;
} }
......
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