浏览代码

[spirv] Support UnaryOperator for negating a matrix. (#3099)

Ehsan 5 年之前
父节点
当前提交
8ffccecea1
共有 2 个文件被更改,包括 47 次插入5 次删除
  1. 19 5
      tools/clang/lib/SPIRV/SpirvEmitter.cpp
  2. 28 0
      tools/clang/test/CodeGenSPIRV/unary-op.minus.hlsl

+ 19 - 5
tools/clang/lib/SPIRV/SpirvEmitter.cpp

@@ -4922,12 +4922,26 @@ SpirvInstruction *SpirvEmitter::doUnaryOperator(const UnaryOperator *expr) {
     return subValue;
   case UO_Minus: {
     // SPIR-V have two opcodes for negating values: OpSNegate and OpFNegate.
-    const spv::Op spvOp = isFloatOrVecOfFloatType(subType) ? spv::Op::OpFNegate
-                                                           : spv::Op::OpSNegate;
-    subValue = spvBuilder.createUnaryOp(spvOp, subType, subValue,
+    const spv::Op spvOp = isFloatOrVecMatOfFloatType(subType)
+                              ? spv::Op::OpFNegate
+                              : spv::Op::OpSNegate;
+
+    if (isMxNMatrix(subType)) {
+      // For matrices, we can only negate each vector of it.
+      const auto actOnEachVec = [this, spvOp, expr](uint32_t /*index*/,
+                                                    QualType vecType,
+                                                    SpirvInstruction *lhsVec) {
+        return spvBuilder.createUnaryOp(spvOp, vecType, lhsVec,
                                         expr->getOperatorLoc());
-    subValue->setRValue();
-    return subValue;
+      };
+      return processEachVectorInMatrix(subExpr, subValue, actOnEachVec,
+                                       expr->getLocStart());
+    } else {
+      subValue = spvBuilder.createUnaryOp(spvOp, subType, subValue,
+                                          expr->getOperatorLoc());
+      subValue->setRValue();
+      return subValue;
+    }
   }
   default:
     break;

+ 28 - 0
tools/clang/test/CodeGenSPIRV/unary-op.minus.hlsl

@@ -31,4 +31,32 @@ void main() {
 // CHECK-NEXT: [[y0:%\d+]] = OpSNegate %v3int [[x0]]
 // CHECK-NEXT: OpStore %y [[y0]]
     y = -x;
+
+// CHECK-NEXT:       [[s:%\d+]] = OpLoad %_arr_v4int_uint_4 %s
+// CHECK-NEXT:    [[row0:%\d+]] = OpCompositeExtract %v4int [[s]] 0
+// CHECK-NEXT: [[result0:%\d+]] = OpSNegate %v4int [[row0]]
+// CHECK-NEXT:    [[row1:%\d+]] = OpCompositeExtract %v4int [[s]] 1
+// CHECK-NEXT: [[result1:%\d+]] = OpSNegate %v4int [[row1]]
+// CHECK-NEXT:    [[row2:%\d+]] = OpCompositeExtract %v4int [[s]] 2
+// CHECK-NEXT: [[result2:%\d+]] = OpSNegate %v4int [[row2]]
+// CHECK-NEXT:    [[row3:%\d+]] = OpCompositeExtract %v4int [[s]] 3
+// CHECK-NEXT: [[result3:%\d+]] = OpSNegate %v4int [[row3]]
+// CHECK-NEXT:  [[result:%\d+]] = OpCompositeConstruct %_arr_v4int_uint_4 [[result0]] [[result1]] [[result2]] [[result3]]
+// CHECK-NEXT:                    OpStore %r [[result]]
+    int4x4 r, s;
+    r = -s;
+
+// CHECK-NEXT:       [[u:%\d+]] = OpLoad %mat4v4float %u
+// CHECK-NEXT:    [[row0:%\d+]] = OpCompositeExtract %v4float [[u]] 0
+// CHECK-NEXT: [[result0:%\d+]] = OpFNegate %v4float [[row0]]
+// CHECK-NEXT:    [[row1:%\d+]] = OpCompositeExtract %v4float [[u]] 1
+// CHECK-NEXT: [[result1:%\d+]] = OpFNegate %v4float [[row1]]
+// CHECK-NEXT:    [[row2:%\d+]] = OpCompositeExtract %v4float [[u]] 2
+// CHECK-NEXT: [[result2:%\d+]] = OpFNegate %v4float [[row2]]
+// CHECK-NEXT:    [[row3:%\d+]] = OpCompositeExtract %v4float [[u]] 3
+// CHECK-NEXT: [[result3:%\d+]] = OpFNegate %v4float [[row3]]
+// CHECK-NEXT:  [[result:%\d+]] = OpCompositeConstruct %mat4v4float [[result0]] [[result1]] [[result2]] [[result3]]
+// CHECK-NEXT:                    OpStore %t [[result]]
+    float4x4 t, u;
+    t = -u;
 }