SpirvShader: Support scalar conditions for OpSelect
We were assuming the condition was the same width as the lhs and rhs types - it can also be a scalar even if the result is not.
Bug: b/133440380
Change-Id: Ib0e971af426b71030a097838295b07bb6e4261e0
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/31841
Reviewed-by: Chris Forbes <chrisforbes@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Ben Clayton <bclayton@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index 70f1f99..269564f 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -3479,12 +3479,14 @@
auto &type = getType(insn.word(1));
auto &dst = routine->createIntermediate(insn.word(2), type.sizeInComponents);
auto cond = GenericValue(this, routine, insn.word(3));
+ auto condIsScalar = (getType(cond.type).sizeInComponents == 1);
auto lhs = GenericValue(this, routine, insn.word(4));
auto rhs = GenericValue(this, routine, insn.word(5));
for (auto i = 0u; i < type.sizeInComponents; i++)
{
- dst.move(i, (cond.Int(i) & lhs.Int(i)) | (~cond.Int(i) & rhs.Int(i))); // FIXME: IfThenElse()
+ auto sel = cond.Int(condIsScalar ? 0 : i);
+ dst.move(i, (sel & lhs.Int(i)) | (~sel & rhs.Int(i))); // FIXME: IfThenElse()
}
return EmitResult::Continue;
@@ -5852,12 +5854,14 @@
{
auto &result = CreateConstant(insn);
auto const &cond = getObject(insn.word(4));
+ auto condIsScalar = (getType(cond.type).sizeInComponents == 1);
auto const &left = getObject(insn.word(5));
auto const &right = getObject(insn.word(6));
for (auto i = 0u; i < getType(result.type).sizeInComponents; i++)
{
- result.constantValue[i] = cond.constantValue[i] ? left.constantValue[i] : right.constantValue[i];
+ auto sel = cond.constantValue[condIsScalar ? 0 : i];
+ result.constantValue[i] = sel ? left.constantValue[i] : right.constantValue[i];
}
break;
}