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);
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;
}
}
+ 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)
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.