Sfoglia il codice sorgente

[spirv] Intrinsic fwidth & faceforward (#711)

Ehsan 7 anni fa
parent
commit
0888e319e7

+ 3 - 0
docs/SPIR-V.rst

@@ -1092,6 +1092,8 @@ The following intrinsic HLSL functions are currently supported:
 - ``ddy_coarse``: Low precision partial derivative with respect to the screen-space y-coordinate. Uses SIR-V ``OpDPdyCoarse``.
 - ``ddx_fine``: High precision partial derivative with respect to the screen-space x-coordinate. Uses SIR-V ``OpDPdxFine``.
 - ``ddy_fine``: High precision partial derivative with respect to the screen-space y-coordinate. Uses SIR-V ``OpDPdyFine``.
+- ``fwidth``: Returns the absolute value of the partial derivatives of the specified value. Uses SIR-V ``OpFwidth``.
+
 
 Using GLSL extended instructions
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1118,6 +1120,7 @@ HLSL Intrinsic Function   GLSL Extended Instruction
 ``determinant``         ``Determinant``
 ``exp``                 ``Exp``
 ``exp2``                ``exp2``
+``faceforward``         ``FaceForward``
 ``firstbithigh``        ``FindSMsb`` / ``FindUMsb``
 ``firstbitlow``         ``FindILsb``
 ``floor``               ``Floor``

+ 2 - 0
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -3777,6 +3777,7 @@ uint32_t SPIRVEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
     INTRINSIC_SPIRV_OP_CASE(isinf, IsInf, true);
     INTRINSIC_SPIRV_OP_CASE(isnan, IsNan, true);
     INTRINSIC_SPIRV_OP_CASE(fmod, FMod, true);
+    INTRINSIC_SPIRV_OP_CASE(fwidth, Fwidth, true);
     INTRINSIC_SPIRV_OP_CASE(reversebits, BitReverse, false);
     INTRINSIC_OP_CASE(round, Round, true);
     INTRINSIC_OP_CASE_INT_FLOAT(abs, SAbs, FAbs, true);
@@ -3795,6 +3796,7 @@ uint32_t SPIRVEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
     INTRINSIC_OP_CASE(exp2, Exp2, true);
     INTRINSIC_OP_CASE_SINT_UINT(firstbithigh, FindSMsb, FindUMsb, false);
     INTRINSIC_OP_CASE_SINT_UINT(ufirstbithigh, FindSMsb, FindUMsb, false);
+    INTRINSIC_OP_CASE(faceforward, FaceForward, false);
     INTRINSIC_OP_CASE(firstbitlow, FindILsb, false);
     INTRINSIC_OP_CASE(floor, Floor, true);
     INTRINSIC_OP_CASE(fma, Fma, true);

+ 15 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.faceforward.hlsl

@@ -0,0 +1,15 @@
+// Run: %dxc -T ps_6_0 -E main
+
+// faceforward only takes vector of floats, and returns a vector of the same size.
+
+// CHECK: [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float3 n, i, ng, result;
+  
+// CHECK:       [[n:%\d+]] = OpLoad %v3float %n
+// CHECK-NEXT:  [[i:%\d+]] = OpLoad %v3float %i
+// CHECK-NEXT: [[ng:%\d+]] = OpLoad %v3float %ng
+// CHECK-NEXT: {{%\d+}} = OpExtInst %v3float [[glsl]] FaceForward [[n]] [[i]] [[ng]]
+  result = faceforward(n, i, ng);
+}

+ 24 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.fwidth.hlsl

@@ -0,0 +1,24 @@
+// Run: %dxc -T ps_6_0 -E main
+
+void main() {
+
+  float    a;
+  float2   b;
+  float2x3 c;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT:   {{%\d+}} = OpFwidth %float [[a]]
+  float    fwa = fwidth(a);
+
+// CHECK:      [[b:%\d+]] = OpLoad %v2float %b
+// CHECK-NEXT:   {{%\d+}} = OpFwidth %v2float [[b]]
+  float2   fwb = fwidth(b);
+
+// CHECK:        [[c:%\d+]] = OpLoad %mat2v3float %c
+// CHECK-NEXT:  [[c0:%\d+]] = OpCompositeExtract %v3float [[c]] 0
+// CHECK-NEXT: [[dc0:%\d+]] = OpFwidth %v3float [[c0]]
+// CHECK-NEXT:  [[c1:%\d+]] = OpCompositeExtract %v3float [[c]] 1
+// CHECK-NEXT: [[dc1:%\d+]] = OpFwidth %v3float [[c1]]
+// CHECK-NEXT:     {{%\d+}} = OpCompositeConstruct %mat2v3float [[dc0]] [[dc1]]
+  float2x3 fwc = fwidth(c);
+}

+ 4 - 0
tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp

@@ -534,6 +534,9 @@ TEST_F(FileTest, IntrinsicsDeterminant) {
 }
 TEST_F(FileTest, IntrinsicsExp) { runFileTest("intrinsics.exp.hlsl"); }
 TEST_F(FileTest, IntrinsicsExp2) { runFileTest("intrinsics.exp2.hlsl"); }
+TEST_F(FileTest, IntrinsicsFaceForward) {
+  runFileTest("intrinsics.faceforward.hlsl");
+}
 TEST_F(FileTest, IntrinsicsFirstBitHigh) {
   runFileTest("intrinsics.firstbithigh.hlsl");
 }
@@ -545,6 +548,7 @@ TEST_F(FileTest, IntrinsicsFma) { runFileTest("intrinsics.fma.hlsl"); }
 TEST_F(FileTest, IntrinsicsFmod) { runFileTest("intrinsics.fmod.hlsl"); }
 TEST_F(FileTest, IntrinsicsFrac) { runFileTest("intrinsics.frac.hlsl"); }
 TEST_F(FileTest, IntrinsicsFrexp) { runFileTest("intrinsics.frexp.hlsl"); }
+TEST_F(FileTest, IntrinsicsFwidth) { runFileTest("intrinsics.fwidth.hlsl"); }
 TEST_F(FileTest, IntrinsicsIsFinite) {
   runFileTest("intrinsics.isfinite.hlsl");
 }