Add support for OpAny, OpAll A step toward being able to run many of dEQP-VK.glsl.* Bug: b/126870789 Change-Id: Id53d5a511d7f0fa10994c46254529027ad773542 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/26569 Tested-by: Chris Forbes <chrisforbes@google.com> Presubmit-Ready: Chris Forbes <chrisforbes@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp index 9790712..1926823 100644 --- a/src/Pipeline/SpirvShader.cpp +++ b/src/Pipeline/SpirvShader.cpp
@@ -332,6 +332,8 @@ case spv::OpExtInst: case spv::OpIsInf: case spv::OpIsNan: + case spv::OpAny: + case spv::OpAll: // Instructions that yield an intermediate value { TypeID typeId = insn.word(1); @@ -1104,6 +1106,14 @@ EmitExtendedInstruction(insn, routine); break; + case spv::OpAny: + EmitAny(insn, routine); + break; + + case spv::OpAll: + EmitAll(insn, routine); + break; + default: UNIMPLEMENTED(OpcodeName(insn.opcode()).c_str()); break; @@ -1685,6 +1695,42 @@ } } + void SpirvShader::EmitAny(InsnIterator insn, SpirvRoutine *routine) const + { + auto &type = getType(insn.word(1)); + assert(type.sizeInComponents == 1); + auto &dst = routine->createIntermediate(insn.word(2), type.sizeInComponents); + auto &srcType = getType(getObject(insn.word(3)).type); + auto src = GenericValue(this, routine, insn.word(3)); + + SIMD::UInt result = As<SIMD::UInt>(src[0]); + + for (auto i = 1u; i < srcType.sizeInComponents; i++) + { + result |= As<SIMD::UInt>(src[i]); + } + + dst.emplace(0, As<SIMD::Float>(result)); + } + + void SpirvShader::EmitAll(InsnIterator insn, SpirvRoutine *routine) const + { + auto &type = getType(insn.word(1)); + assert(type.sizeInComponents == 1); + auto &dst = routine->createIntermediate(insn.word(2), type.sizeInComponents); + auto &srcType = getType(getObject(insn.word(3)).type); + auto src = GenericValue(this, routine, insn.word(3)); + + SIMD::UInt result = As<SIMD::UInt>(src[0]); + + for (auto i = 1u; i < srcType.sizeInComponents; i++) + { + result &= As<SIMD::UInt>(src[i]); + } + + dst.emplace(0, As<SIMD::Float>(result)); + } + void SpirvShader::emitEpilog(SpirvRoutine *routine) const { for (auto insn : *this)
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp index 1c507c6..8c02997 100644 --- a/src/Pipeline/SpirvShader.hpp +++ b/src/Pipeline/SpirvShader.hpp
@@ -449,6 +449,8 @@ void EmitDot(InsnIterator insn, SpirvRoutine *routine) const; void EmitSelect(InsnIterator insn, SpirvRoutine *routine) const; void EmitExtendedInstruction(InsnIterator insn, SpirvRoutine *routine) const; + void EmitAny(InsnIterator insn, SpirvRoutine *routine) const; + void EmitAll(InsnIterator insn, SpirvRoutine *routine) const; // OpcodeName returns the name of the opcode op. // If NDEBUG is defined, then OpcodeName will only return the numerical code.