Просмотр исходного кода

[SPIRV] Support 16-bit Type Cast Intrinsics (#4679)

* [SPIRV] Support 16-bit Type Cast Intrinsics

This change adds support for 16-bit type cast intrinsics by routing
them into the same logic used by the 32-bit type casts. With this
change in place, asfloat16, asint16, and asuint16 are now translated
into OpBitcast in SPIR-V.

This change also includes new partial disassembly tests for each
function similar to the ones used for 32-bit casts.

* Update Comments in processIntrinsicsAsType

This commit updates the comments at the top of processIntrinsicsAsType
in order to indicate that this function also supports the 16-bit
variants of the type casting intrinsics.
gmitrano-unity 3 лет назад
Родитель
Сommit
aaa30e2c9c

+ 15 - 1
tools/clang/lib/SPIRV/SpirvEmitter.cpp

@@ -7969,8 +7969,11 @@ SpirvEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
     break;
   case hlsl::IntrinsicOp::IOP_asdouble:
   case hlsl::IntrinsicOp::IOP_asfloat:
+  case hlsl::IntrinsicOp::IOP_asfloat16:
   case hlsl::IntrinsicOp::IOP_asint:
+  case hlsl::IntrinsicOp::IOP_asint16:
   case hlsl::IntrinsicOp::IOP_asuint:
+  case hlsl::IntrinsicOp::IOP_asuint16:
     retVal = processIntrinsicAsType(callExpr);
     break;
   case hlsl::IntrinsicOp::IOP_clip:
@@ -10106,7 +10109,18 @@ SpirvEmitter::processIntrinsicAllOrAny(const CallExpr *callExpr,
 
 SpirvInstruction *
 SpirvEmitter::processIntrinsicAsType(const CallExpr *callExpr) {
-  // This function handles 'asint', 'asuint', 'asfloat', and 'asdouble'.
+  // This function handles the following intrinsics:
+  //    'asint'
+  //    'asint16'
+  //    'asuint'
+  //    'asuint16'
+  //    'asfloat'
+  //    'asfloat16'
+  //    'asdouble'
+
+  // Note: The logic for the 32-bit and 16-bit variants of these functions is
+  //       identical so we don't bother distinguishing between related types
+  //       like float and float16 in the comments.
 
   // Method 1: ret asint(arg)
   //    arg component type = {float, uint}

+ 64 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.asfloat16.hlsl

@@ -0,0 +1,64 @@
+// RUN: %dxc -T vs_6_2 -E main -enable-16bit-types
+
+// CHECK: OpCapability Float16
+// CHECK: OpCapability Int16
+
+void main() {
+    float16_t result;
+    float16_t4 result4;
+
+    // CHECK:      [[a:%\d+]] = OpLoad %short %a
+    // CHECK-NEXT: [[a_as_half:%\d+]] = OpBitcast %half [[a]]
+    // CHECK-NEXT: OpStore %result [[a_as_half]]
+    int16_t a;
+    result = asfloat16(a);
+
+    // CHECK-NEXT: [[b:%\d+]] = OpLoad %ushort %b
+    // CHECK-NEXT: [[b_as_half:%\d+]] = OpBitcast %half [[b]]
+    // CHECK-NEXT: OpStore %result [[b_as_half]]
+    uint16_t b;
+    result = asfloat16(b);
+
+    // CHECK-NEXT: [[c:%\d+]] = OpLoad %half %c
+    // CHECK-NEXT: OpStore %result [[c]]
+    float16_t c;
+    result = asfloat16(c);
+
+    // CHECK-NEXT: [[d:%\d+]] = OpLoad %v4short %d
+    // CHECK-NEXT: [[d_as_half:%\d+]] = OpBitcast %v4half [[d]]
+    // CHECK-NEXT: OpStore %result4 [[d_as_half]]
+    int16_t4 d;
+    result4 = asfloat16(d);
+
+    // CHECK-NEXT: [[e:%\d+]] = OpLoad %v4ushort %e
+    // CHECK-NEXT: [[e_as_half:%\d+]] = OpBitcast %v4half [[e]]
+    // CHECK-NEXT: OpStore %result4 [[e_as_half]]
+    uint16_t4 e;
+    result4 = asfloat16(e);
+
+    // CHECK-NEXT: [[f:%\d+]] = OpLoad %v4half %f
+    // CHECK-NEXT: OpStore %result4 [[f]]
+    float16_t4 f;
+    result4 = asfloat16(f);
+
+    int16_t2x3 intMat;
+    uint16_t2x3 uintMat;
+
+    // CHECK:       [[intMat:%\d+]] = OpLoad %_arr_v3short_uint_2 %intMat
+    // CHECK-NEXT: [[intMat0:%\d+]] = OpCompositeExtract %v3short [[intMat]] 0
+    // CHECK-NEXT:      [[row0:%\d+]] = OpBitcast %v3half [[intMat0]]
+    // CHECK-NEXT: [[intMat1:%\d+]] = OpCompositeExtract %v3short [[intMat]] 1
+    // CHECK-NEXT:      [[row1:%\d+]] = OpBitcast %v3half [[intMat1]]
+    // CHECK-NEXT:         [[g:%\d+]] = OpCompositeConstruct %mat2v3half [[row0]] [[row1]]
+    // CHECK-NEXT:                      OpStore %g [[g]]
+    float16_t2x3 g = asfloat16(intMat);
+
+    // CHECK:       [[uintMat:%\d+]] = OpLoad %_arr_v3ushort_uint_2 %uintMat
+    // CHECK-NEXT: [[uintMat0:%\d+]] = OpCompositeExtract %v3ushort [[uintMat]] 0
+    // CHECK-NEXT:      [[row0:%\d+]] = OpBitcast %v3half [[uintMat0]]
+    // CHECK-NEXT: [[uintMat1:%\d+]] = OpCompositeExtract %v3ushort [[uintMat]] 1
+    // CHECK-NEXT:      [[row1:%\d+]] = OpBitcast %v3half [[uintMat1]]
+    // CHECK-NEXT:         [[h:%\d+]] = OpCompositeConstruct %mat2v3half [[row0]] [[row1]]
+    // CHECK-NEXT:                      OpStore %h [[h]]
+    float16_t2x3 h = asfloat16(uintMat);
+}

+ 64 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.asint16.hlsl

@@ -0,0 +1,64 @@
+// RUN: %dxc -T vs_6_2 -E main -enable-16bit-types
+
+// CHECK: OpCapability Int16
+// CHECK: OpCapability Float16
+
+void main() {
+    int16_t result;
+    int16_t4 result4;
+
+    // CHECK: [[a:%\d+]] = OpLoad %short %a
+    // CHECK-NEXT: OpStore %result [[a]]
+    int16_t a;
+    result = asint16(a);
+
+    // CHECK: [[b:%\d+]] = OpLoad %ushort %b
+    // CHECK-NEXT: [[b_as_short:%\d+]] = OpBitcast %short [[b]]
+    // CHECK-NEXT: OpStore %result [[b_as_short]]
+    uint16_t b;
+    result = asint16(b);
+
+    // CHECK: [[c:%\d+]] = OpLoad %half %c
+    // CHECK-NEXT: [[c_as_short:%\d+]] = OpBitcast %short [[c]]
+    // CHECK-NEXT: OpStore %result [[c_as_short]]
+    float16_t c;
+    result = asint16(c);
+
+    // CHECK: [[d:%\d+]] = OpLoad %v4short %d
+    // CHECK-NEXT: OpStore %result4 [[d]]
+    int16_t4 d;
+    result4 = asint16(d);
+
+    // CHECK: [[e:%\d+]] = OpLoad %v4ushort %e
+    // CHECK-NEXT: [[e_as_short:%\d+]] = OpBitcast %v4short [[e]]
+    // CHECK-NEXT: OpStore %result4 [[e_as_short]]
+    uint16_t4 e;
+    result4 = asint16(e);
+
+    // CHECK: [[f:%\d+]] = OpLoad %v4half %f
+    // CHECK-NEXT: [[f_as_short:%\d+]] = OpBitcast %v4short [[f]]
+    // CHECK-NEXT: OpStore %result4 [[f_as_short]]
+    float16_t4 f;
+    result4 = asint16(f);
+
+    float16_t2x3 floatMat;
+    uint16_t2x3 uintMat;
+
+    // CHECK:       [[floatMat:%\d+]] = OpLoad %mat2v3half %floatMat
+    // CHECK-NEXT: [[floatMat0:%\d+]] = OpCompositeExtract %v3half [[floatMat]] 0
+    // CHECK-NEXT:      [[row0:%\d+]] = OpBitcast %v3short [[floatMat0]]
+    // CHECK-NEXT: [[floatMat1:%\d+]] = OpCompositeExtract %v3half [[floatMat]] 1
+    // CHECK-NEXT:      [[row1:%\d+]] = OpBitcast %v3short [[floatMat1]]
+    // CHECK-NEXT:         [[g:%\d+]] = OpCompositeConstruct %_arr_v3short_uint_2 [[row0]] [[row1]]
+    // CHECK-NEXT:                      OpStore %g [[g]]
+    int16_t2x3 g = asint16(floatMat);
+
+    // CHECK:       [[uintMat:%\d+]] = OpLoad %_arr_v3ushort_uint_2 %uintMat
+    // CHECK-NEXT: [[uintMat0:%\d+]] = OpCompositeExtract %v3ushort [[uintMat]] 0
+    // CHECK-NEXT:      [[row0:%\d+]] = OpBitcast %v3short [[uintMat0]]
+    // CHECK-NEXT: [[uintMat1:%\d+]] = OpCompositeExtract %v3ushort [[uintMat]] 1
+    // CHECK-NEXT:      [[row1:%\d+]] = OpBitcast %v3short [[uintMat1]]
+    // CHECK-NEXT:         [[h:%\d+]] = OpCompositeConstruct %_arr_v3short_uint_2 [[row0]] [[row1]]
+    // CHECK-NEXT:                      OpStore %h [[h]]
+    int16_t2x3 h = asint16(uintMat);
+}

+ 64 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.asuint16.hlsl

@@ -0,0 +1,64 @@
+// RUN: %dxc -T vs_6_2 -E main -enable-16bit-types
+
+// CHECK: OpCapability Int16
+// CHECK: OpCapability Float16
+
+void main() {
+    uint16_t result;
+    uint16_t4 result4;
+
+    // CHECK: [[a:%\d+]] = OpLoad %short %a
+    // CHECK-NEXT: [[a_as_ushort:%\d+]] = OpBitcast %ushort [[a]]
+    // CHECK-NEXT: OpStore %result [[a_as_ushort]]
+    int16_t a;
+    result = asuint16(a);
+
+    // CHECK: [[b:%\d+]] = OpLoad %ushort %b
+    // CHECK-NEXT: OpStore %result [[b]]
+    uint16_t b;
+    result = asuint16(b);
+
+    // CHECK: [[c:%\d+]] = OpLoad %half %c
+    // CHECK-NEXT: [[c_as_ushort:%\d+]] = OpBitcast %ushort [[c]]
+    // CHECK-NEXT: OpStore %result [[c_as_ushort]]
+    float16_t c;
+    result = asuint16(c);
+
+    // CHECK: [[d:%\d+]] = OpLoad %v4short %d
+    // CHECK-NEXT: [[d_as_ushort:%\d+]] = OpBitcast %v4ushort [[d]]
+    // CHECK-NEXT: OpStore %result4 [[d_as_ushort]]
+    int16_t4 d;
+    result4 = asuint16(d);
+
+    // CHECK: [[e:%\d+]] = OpLoad %v4ushort %e
+    // CHECK-NEXT: OpStore %result4 [[e]]
+    uint16_t4 e;
+    result4 = asuint16(e);
+
+    // CHECK: [[f:%\d+]] = OpLoad %v4half %f
+    // CHECK-NEXT: [[f_as_ushort:%\d+]] = OpBitcast %v4ushort [[f]]
+    // CHECK-NEXT: OpStore %result4 [[f_as_ushort]]
+    float16_t4 f;
+    result4 = asuint16(f);
+
+    float16_t2x3 floatMat;
+    int16_t2x3 intMat;
+
+    // CHECK:       [[floatMat:%\d+]] = OpLoad %mat2v3half %floatMat
+    // CHECK-NEXT: [[floatMat0:%\d+]] = OpCompositeExtract %v3half [[floatMat]] 0
+    // CHECK-NEXT:      [[row0:%\d+]] = OpBitcast %v3ushort [[floatMat0]]
+    // CHECK-NEXT: [[floatMat1:%\d+]] = OpCompositeExtract %v3half [[floatMat]] 1
+    // CHECK-NEXT:      [[row1:%\d+]] = OpBitcast %v3ushort [[floatMat1]]
+    // CHECK-NEXT:         [[g:%\d+]] = OpCompositeConstruct %_arr_v3ushort_uint_2 [[row0]] [[row1]]
+    // CHECK-NEXT:                      OpStore %g [[g]]
+    uint16_t2x3 g = asuint16(floatMat);
+
+    // CHECK:       [[intMat:%\d+]] = OpLoad %_arr_v3short_uint_2 %intMat
+    // CHECK-NEXT: [[intMat0:%\d+]] = OpCompositeExtract %v3short [[intMat]] 0
+    // CHECK-NEXT:      [[row0:%\d+]] = OpBitcast %v3ushort [[intMat0]]
+    // CHECK-NEXT: [[intMat1:%\d+]] = OpCompositeExtract %v3short [[intMat]] 1
+    // CHECK-NEXT:      [[row1:%\d+]] = OpBitcast %v3ushort [[intMat1]]
+    // CHECK-NEXT:         [[h:%\d+]] = OpCompositeConstruct %_arr_v3ushort_uint_2 [[row0]] [[row1]]
+    // CHECK-NEXT:                      OpStore %h [[h]]
+    uint16_t2x3 h = asuint16(intMat);
+}

+ 3 - 0
tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp

@@ -1165,8 +1165,11 @@ TEST_F(FileTest, IntrinsicsAsDouble) {
   runFileTest("intrinsics.asdouble.hlsl");
 }
 TEST_F(FileTest, IntrinsicsAsfloat) { runFileTest("intrinsics.asfloat.hlsl"); }
+TEST_F(FileTest, IntrinsicsAsfloat16) { runFileTest("intrinsics.asfloat16.hlsl"); }
 TEST_F(FileTest, IntrinsicsAsint) { runFileTest("intrinsics.asint.hlsl"); }
+TEST_F(FileTest, IntrinsicsAsint16) { runFileTest("intrinsics.asint16.hlsl"); }
 TEST_F(FileTest, IntrinsicsAsuint) { runFileTest("intrinsics.asuint.hlsl"); }
+TEST_F(FileTest, IntrinsicsAsuint16) { runFileTest("intrinsics.asuint16.hlsl"); }
 TEST_F(FileTest, IntrinsicsAsuintArgumentMustBeRValue) {
   runFileTest("intrinsics.asuint.rvalue.hlsl");
 }