OSDN Git Service

SpirvShader: Begin unary and binary ops.
authorBen Clayton <bclayton@google.com>
Thu, 28 Feb 2019 19:59:15 +0000 (19:59 +0000)
committerChris Forbes <chrisforbes@google.com>
Fri, 1 Mar 2019 16:04:15 +0000 (16:04 +0000)
Far from a complete set, but both Chris and I are looking at tests that require these opcodes.

Bug: b/126870789
Bug: b/126873455
Change-Id: Idb2109cfc3352da83aa38d42eed5d15537dfb6b7
Reviewed-on: https://swiftshader-review.googlesource.com/c/25868
Tested-by: Chris Forbes <chrisforbes@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>

src/Pipeline/SpirvShader.cpp
src/Pipeline/SpirvShader.hpp

index 70440b2..1c02bd7 100644 (file)
@@ -212,6 +212,27 @@ namespace sw
                        case spv::OpCompositeInsert:
                        case spv::OpCompositeExtract:
                        case spv::OpVectorShuffle:
+                       case spv::OpNot: // Unary ops
+                       case spv::OpSNegate:
+                       case spv::OpFNegate:
+                       case spv::OpLogicalNot:
+                       case spv::OpIAdd: // Binary ops
+                       case spv::OpISub:
+                       case spv::OpIMul:
+                       case spv::OpSDiv:
+                       case spv::OpUDiv:
+                       case spv::OpFAdd:
+                       case spv::OpFSub:
+                       case spv::OpFDiv:
+                       case spv::OpUMod:
+                       case spv::OpShiftRightLogical:
+                       case spv::OpShiftRightArithmetic:
+                       case spv::OpShiftLeftLogical:
+                       case spv::OpBitwiseOr:
+                       case spv::OpBitwiseXor:
+                       case spv::OpBitwiseAnd:
+                       case spv::OpLogicalOr:
+                       case spv::OpLogicalAnd:
                                // Instructions that yield an ssavalue.
                        {
                                TypeID typeId = insn.word(1);
@@ -862,6 +883,33 @@ namespace sw
                                EmitVectorShuffle(insn, routine);
                                break;
 
+                       case spv::OpNot:
+                       case spv::OpSNegate:
+                       case spv::OpFNegate:
+                       case spv::OpLogicalNot:
+                               EmitUnaryOp(insn, routine);
+                               break;
+
+                       case spv::OpIAdd:
+                       case spv::OpISub:
+                       case spv::OpIMul:
+                       case spv::OpSDiv:
+                       case spv::OpUDiv:
+                       case spv::OpFAdd:
+                       case spv::OpFSub:
+                       case spv::OpFDiv:
+                       case spv::OpUMod:
+                       case spv::OpShiftRightLogical:
+                       case spv::OpShiftRightArithmetic:
+                       case spv::OpShiftLeftLogical:
+                       case spv::OpBitwiseOr:
+                       case spv::OpBitwiseXor:
+                       case spv::OpBitwiseAnd:
+                       case spv::OpLogicalOr:
+                       case spv::OpLogicalAnd:
+                               EmitBinaryOp(insn, routine);
+                               break;
+
                        default:
                                printf("emit: ignoring opcode %s\n", OpcodeName(insn.opcode()).c_str());
                                break;
@@ -1120,6 +1168,101 @@ namespace sw
                }
        }
 
+       void SpirvShader::EmitUnaryOp(InsnIterator insn, SpirvRoutine *routine) const
+       {
+               auto &type = getType(insn.word(1));
+               auto &dst = routine->createIntermediate(insn.word(2), type.sizeInComponents);
+               auto src = GenericValue(this, routine, insn.word(3));
+
+               for (auto i = 0u; i < type.sizeInComponents; i++)
+               {
+                       auto val = src[i];
+
+                       switch (insn.opcode())
+                       {
+                       case spv::OpNot:
+                       case spv::OpLogicalNot:         // logical not == bitwise not due to all-bits boolean representation
+                               dst.emplace(i, As<SIMD::Float>(~As<SIMD::UInt>(val)));
+                               break;
+                       case spv::OpSNegate:
+                               dst.emplace(i, As<SIMD::Float>(-As<SIMD::Int>(val)));
+                               break;
+                       case spv::OpFNegate:
+                               dst.emplace(i, -val);
+                               break;
+                       default:
+                               UNIMPLEMENTED("Unhandled unary operator %s", OpcodeName(insn.opcode()).c_str());
+                       }
+               }
+       }
+
+       void SpirvShader::EmitBinaryOp(InsnIterator insn, SpirvRoutine *routine) const
+       {
+               auto &type = getType(insn.word(1));
+               auto &dst = routine->createIntermediate(insn.word(2), type.sizeInComponents);
+               auto srcLHS = GenericValue(this, routine, insn.word(3));
+               auto srcRHS = GenericValue(this, routine, insn.word(4));
+
+               for (auto i = 0u; i < type.sizeInComponents; i++)
+               {
+                       auto lhs = srcLHS[i];
+                       auto rhs = srcRHS[i];
+
+                       switch (insn.opcode())
+                       {
+                       case spv::OpIAdd:
+                               dst.emplace(i, As<SIMD::Float>(As<SIMD::Int>(lhs) + As<SIMD::Int>(rhs)));
+                               break;
+                       case spv::OpISub:
+                               dst.emplace(i, As<SIMD::Float>(As<SIMD::Int>(lhs) - As<SIMD::Int>(rhs)));
+                               break;
+                       case spv::OpIMul:
+                               dst.emplace(i, As<SIMD::Float>(As<SIMD::Int>(lhs) * As<SIMD::Int>(rhs)));
+                               break;
+                       case spv::OpSDiv:
+                               dst.emplace(i, As<SIMD::Float>(As<SIMD::Int>(lhs) / As<SIMD::Int>(rhs)));
+                               break;
+                       case spv::OpUDiv:
+                               dst.emplace(i, As<SIMD::Float>(As<SIMD::UInt>(lhs) / As<SIMD::UInt>(rhs)));
+                               break;
+                       case spv::OpUMod:
+                               dst.emplace(i, As<SIMD::Float>(As<SIMD::UInt>(lhs) % As<SIMD::UInt>(rhs)));
+                               break;
+                       case spv::OpFAdd:
+                               dst.emplace(i, lhs + rhs);
+                               break;
+                       case spv::OpFSub:
+                               dst.emplace(i, lhs - rhs);
+                               break;
+                       case spv::OpFDiv:
+                               dst.emplace(i, lhs / rhs);
+                               break;
+                       case spv::OpShiftRightLogical:
+                               dst.emplace(i, As<SIMD::Float>(As<SIMD::UInt>(lhs) >> As<SIMD::UInt>(rhs)));
+                               break;
+                       case spv::OpShiftRightArithmetic:
+                               dst.emplace(i, As<SIMD::Float>(As<SIMD::Int>(lhs) >> As<SIMD::Int>(rhs)));
+                               break;
+                       case spv::OpShiftLeftLogical:
+                               dst.emplace(i, As<SIMD::Float>(As<SIMD::UInt>(lhs) << As<SIMD::UInt>(rhs)));
+                               break;
+                       case spv::OpBitwiseOr:
+                       case spv::OpLogicalOr:
+                               dst.emplace(i, As<SIMD::Float>(As<SIMD::UInt>(lhs) | As<SIMD::UInt>(rhs)));
+                               break;
+                       case spv::OpBitwiseXor:
+                               dst.emplace(i, As<SIMD::Float>(As<SIMD::UInt>(lhs) ^ As<SIMD::UInt>(rhs)));
+                               break;
+                       case spv::OpBitwiseAnd:
+                       case spv::OpLogicalAnd:
+                               dst.emplace(i, As<SIMD::Float>(As<SIMD::UInt>(lhs) & As<SIMD::UInt>(rhs)));
+                               break;
+                       default:
+                               UNIMPLEMENTED("Unhandled binary operator %s", OpcodeName(insn.opcode()).c_str());
+                       }
+               }
+       }
+
        void SpirvShader::emitEpilog(SpirvRoutine *routine) const
        {
                for (auto insn : *this)
index c877ad7..a90f5fb 100644 (file)
@@ -45,6 +45,7 @@ namespace sw
 
                using Float = rr::Float4;
                using Int = rr::Int4;
+               using UInt = rr::UInt4;
        }
 
        // Incrementally constructed complex bundle of rvalues
@@ -390,6 +391,8 @@ namespace sw
                void EmitCompositeInsert(InsnIterator insn, SpirvRoutine *routine) const;
                void EmitCompositeExtract(InsnIterator insn, SpirvRoutine *routine) const;
                void EmitVectorShuffle(InsnIterator insn, SpirvRoutine *routine) const;
+               void EmitUnaryOp(InsnIterator insn, SpirvRoutine *routine) const;
+               void EmitBinaryOp(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.