فهرست منبع

Half tests (#911)

- Adding half tests for unary,binary,tertiary math operations
- Add 'exec-future' option for hcttest
Young Kim 7 سال پیش
والد
کامیت
ecf0307963

+ 362 - 67
tools/clang/unittests/HLSL/ExecutionTest.cpp

@@ -563,6 +563,18 @@ public:
     TEST_METHOD_PROPERTY(L"DataSource", L"Table:ShaderOpArithTable.xml#TertiaryFloatOpTable")
   END_TEST_METHOD()
 
+  BEGIN_TEST_METHOD(UnaryHalfOpTest)
+    TEST_METHOD_PROPERTY(L"DataSource", L"Table:ShaderOpArithTable.xml#UnaryHalfOpTable")
+    TEST_METHOD_PROPERTY(L"Priority", L"2") // Remove this line once warp supports this feature in Shader Model 6.2
+  END_TEST_METHOD()
+  BEGIN_TEST_METHOD(BinaryHalfOpTest)
+    TEST_METHOD_PROPERTY(L"DataSource", L"Table:ShaderOpArithTable.xml#BinaryHalfOpTable")
+    TEST_METHOD_PROPERTY(L"Priority", L"2") // Remove this line once warp supports this feature in Shader Model 6.2
+  END_TEST_METHOD()
+  BEGIN_TEST_METHOD(TertiaryHalfOpTest)
+    TEST_METHOD_PROPERTY(L"DataSource", L"Table:ShaderOpArithTable.xml#TertiaryHalfOpTable")
+    TEST_METHOD_PROPERTY(L"Priority", L"2") // Remove this line once warp supports this feature in Shader Model 6.2
+  END_TEST_METHOD()
   BEGIN_TEST_METHOD(UnaryIntOpTest)
     TEST_METHOD_PROPERTY(L"DataSource", L"Table:ShaderOpArithTable.xml#UnaryIntOpTable")
   END_TEST_METHOD()
@@ -2495,6 +2507,25 @@ struct STertiaryFPOp {
     float output;
 };
 
+struct SUnaryHalfOp {
+  uint16_t input;
+  uint16_t output;
+};
+
+struct SBinaryHalfOp {
+  uint16_t input1;
+  uint16_t input2;
+  uint16_t output1;
+  uint16_t output2;
+};
+
+struct STertiaryHalfOp {
+  uint16_t input1;
+  uint16_t input2;
+  uint16_t input3;
+  uint16_t output;
+};
+
 struct SUnaryIntOp {
     int input;
     int output;
@@ -2548,7 +2579,6 @@ struct SMsad4 {
     XMUINT4 accum;
     XMUINT4 result;
 };
-
 // Parameter representation for taef data-driven tests
 struct TableParameter {
     LPCWSTR m_name;
@@ -2719,8 +2749,8 @@ public:
 static TableParameter UnaryFPOpParameters[] = {
     { L"ShaderOp.Target", TableParameter::STRING, true },
     { L"ShaderOp.Text", TableParameter::STRING, true },
-    { L"Validation.Input1", TableParameter::STRING_TABLE, true },
-    { L"Validation.Expected1", TableParameter::STRING_TABLE, true },
+    { L"Validation.Input1", TableParameter::FLOAT_TABLE, true },
+    { L"Validation.Expected1", TableParameter::FLOAT_TABLE, true },
     { L"Validation.Type", TableParameter::STRING, true },
     { L"Validation.Tolerance", TableParameter::DOUBLE, true },
     { L"Warp.Version", TableParameter::UINT, false }
@@ -2729,10 +2759,10 @@ static TableParameter UnaryFPOpParameters[] = {
 static TableParameter BinaryFPOpParameters[] = {
     { L"ShaderOp.Target", TableParameter::STRING, true },
     { L"ShaderOp.Text", TableParameter::STRING, true },
-    { L"Validation.Input1", TableParameter::STRING_TABLE, true },
-    { L"Validation.Input2", TableParameter::STRING_TABLE, true },
-    { L"Validation.Expected1", TableParameter::STRING_TABLE, true },
-    { L"Validation.Expected2", TableParameter::STRING_TABLE, false },
+    { L"Validation.Input1", TableParameter::FLOAT_TABLE, true },
+    { L"Validation.Input2", TableParameter::FLOAT_TABLE, true },
+    { L"Validation.Expected1", TableParameter::FLOAT_TABLE, true },
+    { L"Validation.Expected2", TableParameter::FLOAT_TABLE, false },
     { L"Validation.Type", TableParameter::STRING, true },
     { L"Validation.Tolerance", TableParameter::DOUBLE, true },
 };
@@ -2740,10 +2770,42 @@ static TableParameter BinaryFPOpParameters[] = {
 static TableParameter TertiaryFPOpParameters[] = {
     { L"ShaderOp.Target", TableParameter::STRING, true },
     { L"ShaderOp.Text", TableParameter::STRING, true },
-    { L"Validation.Input1", TableParameter::STRING_TABLE, true },
-    { L"Validation.Input2", TableParameter::STRING_TABLE, true },
-    { L"Validation.Input3", TableParameter::STRING_TABLE, true },
-    { L"Validation.Expected1", TableParameter::STRING_TABLE, true },
+    { L"Validation.Input1", TableParameter::FLOAT_TABLE, true },
+    { L"Validation.Input2", TableParameter::FLOAT_TABLE, true },
+    { L"Validation.Input3", TableParameter::FLOAT_TABLE, true },
+    { L"Validation.Expected1", TableParameter::FLOAT_TABLE, true },
+    { L"Validation.Type", TableParameter::STRING, true },
+    { L"Validation.Tolerance", TableParameter::DOUBLE, true },
+};
+
+static TableParameter UnaryHalfOpParameters[] = {
+    { L"ShaderOp.Target", TableParameter::STRING, true },
+    { L"ShaderOp.Text", TableParameter::STRING, true },
+    { L"Validation.Input1", TableParameter::HALF_TABLE, true },
+    { L"Validation.Expected1", TableParameter::HALF_TABLE, true },
+    { L"Validation.Type", TableParameter::STRING, true },
+    { L"Validation.Tolerance", TableParameter::DOUBLE, true },
+    { L"Warp.Version", TableParameter::UINT, false }
+};
+
+static TableParameter BinaryHalfOpParameters[] = {
+    { L"ShaderOp.Target", TableParameter::STRING, true },
+    { L"ShaderOp.Text", TableParameter::STRING, true },
+    { L"Validation.Input1", TableParameter::HALF_TABLE, true },
+    { L"Validation.Input2", TableParameter::HALF_TABLE, true },
+    { L"Validation.Expected1", TableParameter::HALF_TABLE, true },
+    { L"Validation.Expected2", TableParameter::HALF_TABLE, false },
+    { L"Validation.Type", TableParameter::STRING, true },
+    { L"Validation.Tolerance", TableParameter::DOUBLE, true },
+};
+
+static TableParameter TertiaryHalfOpParameters[] = {
+    { L"ShaderOp.Target", TableParameter::STRING, true },
+    { L"ShaderOp.Text", TableParameter::STRING, true },
+    { L"Validation.Input1", TableParameter::HALF_TABLE, true },
+    { L"Validation.Input2", TableParameter::HALF_TABLE, true },
+    { L"Validation.Input3", TableParameter::HALF_TABLE, true },
+    { L"Validation.Expected1", TableParameter::HALF_TABLE, true },
     { L"Validation.Type", TableParameter::STRING, true },
     { L"Validation.Tolerance", TableParameter::DOUBLE, true },
 };
@@ -3146,7 +3208,10 @@ static HRESULT ParseTableRow(TableParameter *table, unsigned int size) {
       for (size_t j = 0, end = tempTable.GetSize(); j != end; ++j) {
         float val;
         ParseDataToFloat(tempTable[j], val);
-        table[i].m_halfTable[j] = st::ConvertFloat32ToFloat16(val);
+        if (isdenorm(val))
+          table[i].m_halfTable[j] = signbit(val) ? Float16NegDenorm : Float16PosDenorm;
+        else
+          table[i].m_halfTable[j] = ConvertFloat32ToFloat16(val);
       }
       break;
     }
@@ -3221,6 +3286,22 @@ static void VerifyOutputWithExpectedValueFloat(
   }
 }
 
+static void VerifyOutputWithExpectedValueHalf(
+  uint16_t output, uint16_t ref, LPCWSTR type, double tolerance) {
+  if (_wcsicmp(type, L"Relative") == 0) {
+    VERIFY_IS_TRUE(CompareHalfRelativeEpsilon(output, ref, tolerance));
+  }
+  else if (_wcsicmp(type, L"Epsilon") == 0) {
+    VERIFY_IS_TRUE(CompareHalfEpsilon(output, ref, tolerance));
+  }
+  else if (_wcsicmp(type, L"ULP") == 0) {
+    VERIFY_IS_TRUE(CompareHalfULP(output, ref, (int)tolerance));
+  }
+  else {
+    LogErrorFmt(L"Failed to read comparison type %S", type);
+  }
+}
+
 TEST_F(ExecutionTest, UnaryFloatOpTest) {
     WEX::TestExecution::SetVerifyOutput verifySettings(
         WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
@@ -3245,10 +3326,10 @@ TEST_F(ExecutionTest, UnaryFloatOpTest) {
         return;
     }
 
-    std::vector<WEX::Common::String> *Validation_Input =
-        &(handler.GetTableParamByName(L"Validation.Input1")->m_StringTable);
-    std::vector<WEX::Common::String> *Validation_Expected =
-        &(handler.GetTableParamByName(L"Validation.Expected1")->m_StringTable);
+    std::vector<float> *Validation_Input =
+        &(handler.GetTableParamByName(L"Validation.Input1")->m_floatTable);
+    std::vector<float> *Validation_Expected =
+        &(handler.GetTableParamByName(L"Validation.Expected1")->m_floatTable);
 
     LPCWSTR Validation_Type = handler.GetTableParamByName(L"Validation.Type")->m_str;
     double Validation_Tolerance = handler.GetTableParamByName(L"Validation.Tolerance")->m_double;
@@ -3266,10 +3347,7 @@ TEST_F(ExecutionTest, UnaryFloatOpTest) {
           SUnaryFPOp *pPrimitives = (SUnaryFPOp *)Data.data();
           for (size_t i = 0; i < count; ++i) {
             SUnaryFPOp *p = &pPrimitives[i];
-            PCWSTR str = (*Validation_Input)[i % Validation_Input->size()];
-            float val;
-            VERIFY_SUCCEEDED(ParseDataToFloat(str, val));
-            p->input = val;
+            p->input = (*Validation_Input)[i % Validation_Input->size()];
           }
           // use shader from data table
           pShaderOp->Shaders.at(0).Target = Target.m_psz;
@@ -3283,9 +3361,7 @@ TEST_F(ExecutionTest, UnaryFloatOpTest) {
     WEX::TestExecution::DisableVerifyExceptions dve;
     for (unsigned i = 0; i < count; ++i) {
         SUnaryFPOp *p = &pPrimitives[i];
-        LPCWSTR str = (*Validation_Expected)[i % Validation_Expected->size()];
-        float val;
-        VERIFY_SUCCEEDED(ParseDataToFloat(str, val));
+        float val = (*Validation_Expected)[i % Validation_Expected->size()];
         LogCommentFmt(
             L"element #%u, input = %6.8f, output = %6.8f, expected = %6.8f", i,
             p->input, p->output, val);
@@ -3312,16 +3388,16 @@ TEST_F(ExecutionTest, BinaryFloatOpTest) {
     CW2A Target(handler.GetTableParamByName(L"ShaderOp.Target")->m_str);
     CW2A Text(handler.GetTableParamByName(L"ShaderOp.Text")->m_str);
 
-    std::vector<WEX::Common::String> *Validation_Input1 =
-        &(handler.GetTableParamByName(L"Validation.Input1")->m_StringTable);
-    std::vector<WEX::Common::String> *Validation_Input2 =
-        &(handler.GetTableParamByName(L"Validation.Input2")->m_StringTable);
+    std::vector<float> *Validation_Input1 =
+        &(handler.GetTableParamByName(L"Validation.Input1")->m_floatTable);
+    std::vector<float> *Validation_Input2 =
+        &(handler.GetTableParamByName(L"Validation.Input2")->m_floatTable);
 
-    std::vector<WEX::Common::String> *Validation_Expected1 =
-        &(handler.GetTableParamByName(L"Validation.Expected1")->m_StringTable);
+    std::vector<float> *Validation_Expected1 =
+        &(handler.GetTableParamByName(L"Validation.Expected1")->m_floatTable);
 
-    std::vector<WEX::Common::String> *Validation_Expected2 =
-        &(handler.GetTableParamByName(L"Validation.Expected2")->m_StringTable);
+    std::vector<float> *Validation_Expected2 =
+        &(handler.GetTableParamByName(L"Validation.Expected2")->m_floatTable);
 
     LPCWSTR Validation_Type = handler.GetTableParamByName(L"Validation.Type")->m_str;
     double Validation_Tolerance = handler.GetTableParamByName(L"Validation.Tolerance")->m_double;
@@ -3338,13 +3414,8 @@ TEST_F(ExecutionTest, BinaryFloatOpTest) {
         SBinaryFPOp *pPrimitives = (SBinaryFPOp *)Data.data();
         for (size_t i = 0; i < count; ++i) {
             SBinaryFPOp *p = &pPrimitives[i];
-            PCWSTR str1 = (*Validation_Input1)[i % Validation_Input1->size()];
-            PCWSTR str2 = (*Validation_Input2)[i % Validation_Input2->size()];
-            float val1, val2;
-            VERIFY_SUCCEEDED(ParseDataToFloat(str1, val1));
-            VERIFY_SUCCEEDED(ParseDataToFloat(str2, val2));
-            p->input1 = val1;
-            p->input2 = val2;
+            p->input1 = (*Validation_Input1)[i % Validation_Input1->size()];
+            p->input2 = (*Validation_Input2)[i % Validation_Input2->size()];
         }
 
         // use shader from data table
@@ -3361,11 +3432,8 @@ TEST_F(ExecutionTest, BinaryFloatOpTest) {
     if (numExpected == 2) {
       for (unsigned i = 0; i < count; ++i) {
         SBinaryFPOp *p = &pPrimitives[i];
-        LPCWSTR str1 = (*Validation_Expected1)[i % Validation_Expected1->size()];
-        LPCWSTR str2 = (*Validation_Expected2)[i % Validation_Expected2->size()];
-        float val1, val2;
-        VERIFY_SUCCEEDED(ParseDataToFloat(str1, val1));
-        VERIFY_SUCCEEDED(ParseDataToFloat(str2, val2));
+        float val1 = (*Validation_Expected1)[i % Validation_Expected1->size()];
+        float val2 = (*Validation_Expected2)[i % Validation_Expected2->size()];
         LogCommentFmt(L"element #%u, input1 = %6.8f, input2 = %6.8f, output1 = "
             L"%6.8f, expected1 = %6.8f, output2 = %6.8f, expected2 = %6.8f",
             i, p->input1, p->input2, p->output1, val1, p->output2,
@@ -3379,9 +3447,7 @@ TEST_F(ExecutionTest, BinaryFloatOpTest) {
     else if (numExpected == 1) {
       for (unsigned i = 0; i < count; ++i) {
         SBinaryFPOp *p = &pPrimitives[i];
-        LPCWSTR str1 = (*Validation_Expected1)[i % Validation_Expected1->size()];
-        float val1;
-        VERIFY_SUCCEEDED(ParseDataToFloat(str1, val1));
+        float val1 = (*Validation_Expected1)[i % Validation_Expected1->size()];
         LogCommentFmt(L"element #%u, input1 = %6.8f, input2 = %6.8f, output1 = "
           L"%6.8f, expected1 = %6.8f",
           i, p->input1, p->input2, p->output1, val1);
@@ -3414,15 +3480,15 @@ TEST_F(ExecutionTest, TertiaryFloatOpTest) {
     CW2A Target(handler.GetTableParamByName(L"ShaderOp.Target")->m_str);
     CW2A Text(handler.GetTableParamByName(L"ShaderOp.Text")->m_str);
 
-    std::vector<WEX::Common::String> *Validation_Input1 =
-        &(handler.GetTableParamByName(L"Validation.Input1")->m_StringTable);
-    std::vector<WEX::Common::String> *Validation_Input2 =
-        &(handler.GetTableParamByName(L"Validation.Input2")->m_StringTable);
-    std::vector<WEX::Common::String> *Validation_Input3 =
-        &(handler.GetTableParamByName(L"Validation.Input3")->m_StringTable);
+    std::vector<float> *Validation_Input1 =
+        &(handler.GetTableParamByName(L"Validation.Input1")->m_floatTable);
+    std::vector<float> *Validation_Input2 =
+        &(handler.GetTableParamByName(L"Validation.Input2")->m_floatTable);
+    std::vector<float> *Validation_Input3 =
+        &(handler.GetTableParamByName(L"Validation.Input3")->m_floatTable);
 
-    std::vector<WEX::Common::String> *Validation_Expected =
-        &(handler.GetTableParamByName(L"Validation.Expected1")->m_StringTable);
+    std::vector<float> *Validation_Expected =
+        &(handler.GetTableParamByName(L"Validation.Expected1")->m_floatTable);
 
     LPCWSTR Validation_Type = handler.GetTableParamByName(L"Validation.Type")->m_str;
     double Validation_Tolerance = handler.GetTableParamByName(L"Validation.Tolerance")->m_double;
@@ -3439,16 +3505,9 @@ TEST_F(ExecutionTest, TertiaryFloatOpTest) {
         STertiaryFPOp *pPrimitives = (STertiaryFPOp *)Data.data();
         for (size_t i = 0; i < count; ++i) {
             STertiaryFPOp *p = &pPrimitives[i];
-            PCWSTR str1 = (*Validation_Input1)[i % Validation_Input1->size()];
-            PCWSTR str2 = (*Validation_Input2)[i % Validation_Input2->size()];
-            PCWSTR str3 = (*Validation_Input3)[i % Validation_Input3->size()];
-            float val1, val2, val3;
-            VERIFY_SUCCEEDED(ParseDataToFloat(str1, val1));
-            VERIFY_SUCCEEDED(ParseDataToFloat(str2, val2));
-            VERIFY_SUCCEEDED(ParseDataToFloat(str3, val3));
-            p->input1 = val1;
-            p->input2 = val2;
-            p->input3 = val3;
+            p->input1 = (*Validation_Input1)[i % Validation_Input1->size()];
+            p->input2 = (*Validation_Input2)[i % Validation_Input2->size()];
+            p->input3 = (*Validation_Input3)[i % Validation_Input3->size()];
         }
 
         // use shader from data table
@@ -3464,9 +3523,7 @@ TEST_F(ExecutionTest, TertiaryFloatOpTest) {
 
     for (unsigned i = 0; i < count; ++i) {
       STertiaryFPOp *p = &pPrimitives[i];
-      LPCWSTR str = (*Validation_Expected)[i % Validation_Expected->size()];
-      float val;
-      VERIFY_SUCCEEDED(ParseDataToFloat(str, val));
+      float val = (*Validation_Expected)[i % Validation_Expected->size()];
       LogCommentFmt(L"element #%u, input1 = %6.8f, input2 = %6.8f, input3 = %6.8f, output1 = "
                     L"%6.8f, expected = %6.8f",
                     i, p->input1, p->input2, p->input3, p->output, val);
@@ -3475,6 +3532,244 @@ TEST_F(ExecutionTest, TertiaryFloatOpTest) {
     }
 }
 
+TEST_F(ExecutionTest, UnaryHalfOpTest) {
+    WEX::TestExecution::SetVerifyOutput verifySettings(
+        WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
+    CComPtr<IStream> pStream;
+    ReadHlslDataIntoNewStream(L"ShaderOpArith.xml", &pStream);
+
+    CComPtr<ID3D12Device> pDevice;
+    if (!CreateDevice(&pDevice)) {
+      return;
+    }
+    // Read data from the table
+    int tableSize = sizeof(UnaryHalfOpParameters) / sizeof(TableParameter);
+    TableParameterHandler handler(UnaryHalfOpParameters, tableSize);
+    handler.clearTableParameter();
+    VERIFY_SUCCEEDED(ParseTableRow(UnaryHalfOpParameters, tableSize));
+
+    CW2A Target(handler.GetTableParamByName(L"ShaderOp.Target")->m_str);
+    CW2A Text(handler.GetTableParamByName(L"ShaderOp.Text")->m_str);
+
+    unsigned int WarpVersion = handler.GetTableParamByName(L"Warp.Version")->m_uint;
+    if (GetTestParamUseWARP(true) && !IsValidWarpDllVersion(WarpVersion)) {
+        return;
+    }
+
+    std::vector<uint16_t> *Validation_Input =
+        &(handler.GetTableParamByName(L"Validation.Input1")->m_halfTable);
+    std::vector<uint16_t> *Validation_Expected =
+        &(handler.GetTableParamByName(L"Validation.Expected1")->m_halfTable);
+
+    LPCWSTR Validation_Type = handler.GetTableParamByName(L"Validation.Type")->m_str;
+    double Validation_Tolerance = handler.GetTableParamByName(L"Validation.Tolerance")->m_double;
+
+    size_t count = Validation_Input->size();
+
+    std::shared_ptr<ShaderOpTestResult> test = RunShaderOpTest(
+        pDevice, m_support, pStream, "UnaryFPOp",
+        // this callbacked is called when the test
+        // is creating the resource to run the test
+        [&](LPCSTR Name, std::vector<BYTE> &Data, st::ShaderOp *pShaderOp) {
+          VERIFY_IS_TRUE(0 == _stricmp(Name, "SUnaryFPOp"));
+          size_t size = sizeof(SUnaryHalfOp) * count;
+          Data.resize(size);
+          SUnaryHalfOp *pPrimitives = (SUnaryHalfOp *)Data.data();
+          for (size_t i = 0; i < count; ++i) {
+            SUnaryHalfOp *p = &pPrimitives[i];
+            p->input = (*Validation_Input)[i % Validation_Input->size()];
+          }
+          // use shader from data table
+          pShaderOp->Shaders.at(0).Target = Target.m_psz;
+          pShaderOp->Shaders.at(0).Text = Text.m_psz;
+        });
+
+    MappedData data;
+    test->Test->GetReadBackData("SUnaryFPOp", &data);
+
+    SUnaryHalfOp *pPrimitives = (SUnaryHalfOp*)data.data();
+    WEX::TestExecution::DisableVerifyExceptions dve;
+    for (unsigned i = 0; i < count; ++i) {
+        SUnaryHalfOp *p = &pPrimitives[i];
+        uint16_t expected = (*Validation_Expected)[i % Validation_Input->size()];
+        LogCommentFmt(L"element #%u, input = %6.8f(0x%04x), output = "
+                      L"%6.8f(0x%04x), expected = %6.8f(0x%04x)",
+                      i, ConvertFloat16ToFloat32(p->input), p->input,
+                      ConvertFloat16ToFloat32(p->output), p->output,
+                      ConvertFloat16ToFloat32(expected), expected);
+        VerifyOutputWithExpectedValueHalf(p->output, expected, Validation_Type, Validation_Tolerance);
+    }
+}
+
+TEST_F(ExecutionTest, BinaryHalfOpTest) {
+    WEX::TestExecution::SetVerifyOutput verifySettings(
+        WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
+    CComPtr<IStream> pStream;
+    ReadHlslDataIntoNewStream(L"ShaderOpArith.xml", &pStream);
+
+    CComPtr<ID3D12Device> pDevice;
+    if (!CreateDevice(&pDevice)) {
+        return;
+    }
+    // Read data from the table
+    int tableSize = sizeof(BinaryHalfOpParameters) / sizeof(TableParameter);
+    TableParameterHandler handler(BinaryHalfOpParameters, tableSize);
+    handler.clearTableParameter();
+    VERIFY_SUCCEEDED(ParseTableRow(BinaryHalfOpParameters, tableSize));
+
+    CW2A Target(handler.GetTableParamByName(L"ShaderOp.Target")->m_str);
+    CW2A Text(handler.GetTableParamByName(L"ShaderOp.Text")->m_str);
+
+    std::vector<uint16_t> *Validation_Input1 =
+        &(handler.GetTableParamByName(L"Validation.Input1")->m_halfTable);
+    std::vector<uint16_t> *Validation_Input2 =
+        &(handler.GetTableParamByName(L"Validation.Input2")->m_halfTable);
+
+    std::vector<uint16_t> *Validation_Expected1 =
+        &(handler.GetTableParamByName(L"Validation.Expected1")->m_halfTable);
+
+    std::vector<uint16_t> *Validation_Expected2 =
+        &(handler.GetTableParamByName(L"Validation.Expected2")->m_halfTable);
+
+    LPCWSTR Validation_Type = handler.GetTableParamByName(L"Validation.Type")->m_str;
+    double Validation_Tolerance = handler.GetTableParamByName(L"Validation.Tolerance")->m_double;
+    size_t count = Validation_Input1->size();
+
+    std::shared_ptr<ShaderOpTestResult> test = RunShaderOpTest(
+        pDevice, m_support, pStream, "BinaryFPOp", 
+        // this callbacked is called when the test
+        // is creating the resource to run the test
+        [&](LPCSTR Name, std::vector<BYTE> &Data, st::ShaderOp *pShaderOp) {
+        VERIFY_IS_TRUE(0 == _stricmp(Name, "SBinaryFPOp"));
+        size_t size = sizeof(SBinaryHalfOp) * count;
+        Data.resize(size);
+        SBinaryHalfOp *pPrimitives = (SBinaryHalfOp *)Data.data();
+        for (size_t i = 0; i < count; ++i) {
+            SBinaryHalfOp *p = &pPrimitives[i];
+            p->input1 = (*Validation_Input1)[i % Validation_Input1->size()];
+            p->input2 = (*Validation_Input1)[i % Validation_Input1->size()];
+        }
+
+        // use shader from data table
+        pShaderOp->Shaders.at(0).Target = Target.m_psz;
+        pShaderOp->Shaders.at(0).Text = Text.m_psz;
+    });
+
+    MappedData data;
+    test->Test->GetReadBackData("SBinaryFPOp", &data);
+
+    SBinaryHalfOp *pPrimitives = (SBinaryHalfOp *)data.data();
+    WEX::TestExecution::DisableVerifyExceptions dve;
+    unsigned numExpected = Validation_Expected2->size() == 0 ? 1 : 2;
+    if (numExpected == 2) {
+      for (unsigned i = 0; i < count; ++i) {
+        SBinaryHalfOp *p = &pPrimitives[i];
+        uint16_t expected1 = (*Validation_Expected1)[i % Validation_Input1->size()];
+        uint16_t expected2 = (*Validation_Expected2)[i % Validation_Input2->size()];
+        LogCommentFmt(L"element #%u, input1 = %6.8f(0x%04x), input2 = %6.8f(0x%04x), output1 = "
+          L"%6.8f(0x%04x), expected1 = %6.8f(0x%04x), output2 = %6.8f(0x%04x), expected2 = %6.8f(0x%04x)",
+          i, ConvertFloat16ToFloat32(p->input1), p->input1,
+          ConvertFloat16ToFloat32(p->input2), p->input2,
+          ConvertFloat16ToFloat32(p->output1), p->output1,
+          ConvertFloat16ToFloat32(p->output2), p->output2,
+          ConvertFloat16ToFloat32(expected1), expected1,
+          ConvertFloat16ToFloat32(expected2), expected2);
+        VerifyOutputWithExpectedValueHalf(p->output1, expected1, Validation_Type, Validation_Tolerance);
+        VerifyOutputWithExpectedValueHalf(p->output2, expected2, Validation_Type, Validation_Tolerance);
+      }
+    }
+    else if (numExpected == 1) {
+      for (unsigned i = 0; i < count; ++i) {
+        uint16_t expected = (*Validation_Expected1)[i % Validation_Input1->size()];
+        SBinaryHalfOp *p = &pPrimitives[i];
+        LogCommentFmt(L"element #%u, input = %6.8f(0x%04x), output = "
+          L"%6.8f(0x%04x), expected = %6.8f(0x%04x)",
+          i, ConvertFloat16ToFloat32(p->input1), p->input1,
+          ConvertFloat16ToFloat32(p->output1), p->output1,
+          ConvertFloat16ToFloat32(expected), expected);
+        VerifyOutputWithExpectedValueHalf(p->output1, expected, Validation_Type, Validation_Tolerance);
+      }
+    }
+    else {
+      LogErrorFmt(L"Unexpected number of expected values for operation %i", numExpected);
+    }
+}
+
+TEST_F(ExecutionTest, TertiaryHalfOpTest) {
+    WEX::TestExecution::SetVerifyOutput verifySettings(
+        WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
+    CComPtr<IStream> pStream;
+    ReadHlslDataIntoNewStream(L"ShaderOpArith.xml", &pStream);
+
+    CComPtr<ID3D12Device> pDevice;
+    if (!CreateDevice(&pDevice)) {
+        return;
+    }
+    // Read data from the table
+    
+    int tableSize = sizeof(TertiaryHalfOpParameters) / sizeof(TableParameter);
+    TableParameterHandler handler(TertiaryHalfOpParameters, tableSize);
+    handler.clearTableParameter();
+    VERIFY_SUCCEEDED(ParseTableRow(TertiaryHalfOpParameters, tableSize));
+
+    CW2A Target(handler.GetTableParamByName(L"ShaderOp.Target")->m_str);
+    CW2A Text(handler.GetTableParamByName(L"ShaderOp.Text")->m_str);
+
+    std::vector<uint16_t> *Validation_Input1 =
+        &(handler.GetTableParamByName(L"Validation.Input1")->m_halfTable);
+    std::vector<uint16_t> *Validation_Input2 =
+        &(handler.GetTableParamByName(L"Validation.Input2")->m_halfTable);
+    std::vector<uint16_t> *Validation_Input3 =
+        &(handler.GetTableParamByName(L"Validation.Input3")->m_halfTable);
+
+    std::vector<uint16_t> *Validation_Expected =
+        &(handler.GetTableParamByName(L"Validation.Expected1")->m_halfTable);
+
+    LPCWSTR Validation_Type = handler.GetTableParamByName(L"Validation.Type")->m_str;
+    double Validation_Tolerance = handler.GetTableParamByName(L"Validation.Tolerance")->m_double;
+    size_t count = Validation_Input1->size();
+
+    std::shared_ptr<ShaderOpTestResult> test = RunShaderOpTest(
+        pDevice, m_support, pStream, "TertiaryFPOp",
+        // this callbacked is called when the test
+        // is creating the resource to run the test
+        [&](LPCSTR Name, std::vector<BYTE> &Data, st::ShaderOp *pShaderOp) {
+        VERIFY_IS_TRUE(0 == _stricmp(Name, "STertiaryFPOp"));
+        size_t size = sizeof(STertiaryHalfOp) * count;
+        Data.resize(size);
+        STertiaryHalfOp *pPrimitives = (STertiaryHalfOp *)Data.data();
+        for (size_t i = 0; i < count; ++i) {
+            STertiaryHalfOp *p = &pPrimitives[i];
+            p->input1 = (*Validation_Input1)[i % Validation_Input1->size()];
+            p->input2 = (*Validation_Input2)[i % Validation_Input2->size()];
+            p->input3 = (*Validation_Input3)[i % Validation_Input3->size()];
+        }
+
+        // use shader from data table
+        pShaderOp->Shaders.at(0).Target = Target.m_psz;
+        pShaderOp->Shaders.at(0).Text = Text.m_psz;
+    });
+
+    MappedData data;
+    test->Test->GetReadBackData("STertiaryFPOp", &data);
+
+    STertiaryHalfOp *pPrimitives = (STertiaryHalfOp *)data.data();
+    WEX::TestExecution::DisableVerifyExceptions dve;
+
+    for (unsigned i = 0; i < count; ++i) {
+      STertiaryHalfOp *p = &pPrimitives[i];
+      uint16_t expected = (*Validation_Expected)[i % Validation_Expected->size()];
+      LogCommentFmt(L"element #%u,  input1 = %6.8f(0x%04x), input2 = %6.8f(0x%04x), input3 = %6.8f(0x%04x), output = "
+        L"%6.8f(0x%04x), expected = %6.8f(0x%04x)",
+        i, ConvertFloat16ToFloat32(p->input1), p->input1,
+        ConvertFloat16ToFloat32(p->input2), p->input2,
+        ConvertFloat16ToFloat32(p->input3), p->input3,
+        ConvertFloat16ToFloat32(p->output), p->output,
+        ConvertFloat16ToFloat32(expected), expected);
+      VerifyOutputWithExpectedValueHalf(p->output, expected, Validation_Type, Validation_Tolerance);
+    }
+}
+
 TEST_F(ExecutionTest, UnaryIntOpTest) {
     WEX::TestExecution::SetVerifyOutput verifySettings(
         WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);

+ 152 - 7
tools/clang/unittests/HLSL/HlslTestUtils.h

@@ -8,7 +8,6 @@
 // Provides utility functions for HLSL tests.                                //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
-
 #include <string>
 #include <sstream>
 #include <fstream>
@@ -204,18 +203,137 @@ inline bool ifdenorm_flushf_eq_or_nans(float a, float b) {
   return ifdenorm_flushf(a) == ifdenorm_flushf(b);
 }
 
-using namespace hlsl::DXIL;
+static const uint16_t Float16NaN = 0xff80;
+static const uint16_t Float16PosInf = 0x7c00;
+static const uint16_t Float16NegInf = 0xfc00;
+static const uint16_t Float16PosDenorm = 0x0008;
+static const uint16_t Float16NegDenorm = 0x8008;
+static const uint16_t Float16PosZero = 0x0000;
+static const uint16_t Float16NegZero = 0x8000;
+
+inline bool GetSign(float x) {
+  return std::signbit(x);
+}
+
+inline int GetMantissa(float x) {
+  int bits = reinterpret_cast<int &>(x);
+  return bits & 0x7fffff;
+}
+
+inline int GetExponent(float x) {
+  int bits = reinterpret_cast<int &>(x);
+  return (bits >> 23) & 0xff;
+}
+
+#define FLOAT16_BIT_SIGN 0x8000
+#define FLOAT16_BIT_EXP 0x7c00
+#define FLOAT16_BIT_MANTISSA 0x03ff
+#define FLOAT16_BIGGEST_DENORM FLOAT16_BIT_MANTISSA
+#define FLOAT16_BIGGEST_NORMAL 0x7bff
+
+inline bool isnanFloat16(uint16_t val) {
+  return (val & FLOAT16_BIT_EXP) == FLOAT16_BIT_EXP &&
+         (val & FLOAT16_BIT_MANTISSA) != 0;
+}
+
+inline uint16_t ConvertFloat32ToFloat16(float val) {
+  union Bits {
+    uint32_t u_bits;
+    float f_bits;
+  };
+
+  static const uint32_t SignMask = 0x8000;
+
+  // Maximum f32 value representable in f16 format
+  static const uint32_t Max16in32 = 0x477fe000;
+
+  // Minimum f32 value representable in f16 format without denormalizing
+  static const uint32_t Min16in32 = 0x38800000;
+
+  // Maximum f32 value (next to infinity)
+  static const uint32_t Max32 = 0x7f7FFFFF;
+
+  // Mask for f32 mantissa
+  static const uint32_t Fraction32Mask = 0x007FFFFF;
+
+  // pow(2,24)
+  static const uint32_t DenormalRatio = 0x4B800000;
+
+  static const uint32_t NormalDelta = 0x38000000;
+
+  Bits bits;
+  bits.f_bits = val;
+  uint32_t sign = bits.u_bits & (SignMask << 16);
+  Bits Abs;
+  Abs.u_bits = bits.u_bits ^ sign;
 
+  bool isLessThanNormal = Abs.f_bits < *(float*)&Min16in32;
+  bool isInfOrNaN = Abs.u_bits > Max32;
+
+  if (isLessThanNormal) {
+    // Compute Denormal result
+    return (uint16_t)(Abs.f_bits * *(float*)(&DenormalRatio)) | sign;
+  }
+  else if (isInfOrNaN) {
+    // Compute Inf or Nan result
+    uint32_t Fraction = Abs.u_bits & Fraction32Mask;
+    uint16_t IsNaN = Fraction == 0 ? 0 : 0xffff;
+    return (IsNaN & FLOAT16_BIT_MANTISSA) | FLOAT16_BIT_EXP | (sign >> 16);
+  }
+  else {
+    // Compute Normal result
+    return (uint16_t)((Abs.u_bits - NormalDelta) >> 13) | (sign >> 16);
+  }
+}
+
+inline float ConvertFloat16ToFloat32(uint16_t x) {
+ union Bits {
+    float f_bits;
+    uint32_t u_bits;
+  };
+
+  uint32_t Sign = (x & FLOAT16_BIT_SIGN) << 16;
+
+  // nan -> exponent all set and mantisa is non zero
+  // +/-inf -> exponent all set and mantissa is zero
+  // denorm -> exponent zero and significand nonzero
+  uint32_t Abs = (x & 0x7fff);
+  uint32_t IsNormal = Abs > FLOAT16_BIGGEST_DENORM;
+  uint32_t IsInfOrNaN = Abs > FLOAT16_BIGGEST_NORMAL;
+
+  // Signless Result for normals
+  uint32_t DenormRatio = 0x33800000;
+  float DenormResult = Abs * (*(float*)&DenormRatio);
+
+  uint32_t AbsShifted = Abs << 13;
+  // Signless Result for normals
+  uint32_t NormalResult = AbsShifted + 0x38000000;
+  // Signless Result for int & nans
+  uint32_t InfResult = AbsShifted + 0x70000000;
+
+  Bits bits;
+  bits.u_bits = 0;
+  if (IsInfOrNaN)
+    bits.u_bits |= InfResult;
+  else if (IsNormal)
+    bits.u_bits |= NormalResult;
+  else
+    bits.f_bits = DenormResult;
+  bits.u_bits |= Sign;
+  return bits.f_bits;
+}
+uint16_t ConvertFloat32ToFloat16(float val);
+float ConvertFloat16ToFloat32(uint16_t val);
 inline bool CompareFloatULP(const float &fsrc, const float &fref,
                             int ULPTolerance,
-                            Float32DenormMode mode = Float32DenormMode::Any) {
+                            hlsl::DXIL::Float32DenormMode mode = hlsl::DXIL::Float32DenormMode::Any) {
   if (fsrc == fref) {
     return true;
   }
   if (isnan(fsrc)) {
     return isnan(fref);
   }
-  if (mode == Float32DenormMode::Any) {
+  if (mode == hlsl::DXIL::Float32DenormMode::Any) {
     // If denorm expected, output can be sign preserved zero. Otherwise output
     // should pass the regular ulp testing.
     if (isdenorm(fref) && fsrc == 0 && signbit(fsrc) == signbit(fref))
@@ -230,14 +348,14 @@ inline bool CompareFloatULP(const float &fsrc, const float &fref,
 
 inline bool
 CompareFloatEpsilon(const float &fsrc, const float &fref, float epsilon,
-                    Float32DenormMode mode = Float32DenormMode::Any) {
+                    hlsl::DXIL::Float32DenormMode mode = hlsl::DXIL::Float32DenormMode::Any) {
   if (fsrc == fref) {
     return true;
   }
   if (isnan(fsrc)) {
     return isnan(fref);
   }
-  if (mode == Float32DenormMode::Any) {
+  if (mode == hlsl::DXIL::Float32DenormMode::Any) {
     // If denorm expected, output can be sign preserved zero. Otherwise output
     // should pass the regular epsilon testing.
     if (isdenorm(fref) && fsrc == 0 && signbit(fsrc) == signbit(fref))
@@ -252,10 +370,37 @@ CompareFloatEpsilon(const float &fsrc, const float &fref, float epsilon,
 inline bool
 CompareFloatRelativeEpsilon(const float &fsrc, const float &fref,
                             int nRelativeExp,
-                            Float32DenormMode mode = Float32DenormMode::Any) {
+                            hlsl::DXIL::Float32DenormMode mode = hlsl::DXIL::Float32DenormMode::Any) {
   return CompareFloatULP(fsrc, fref, 23 - nRelativeExp, mode);
 }
 
+inline bool CompareHalfULP(const uint16_t &fsrc, const uint16_t &fref, float ULPTolerance) {
+  if (fsrc == fref)
+    return true;
+  if (isnanFloat16(fsrc))
+    return isnanFloat16(fref);
+  // 16-bit floating point numbers must preserve denorms
+  int diff = *((DWORD *)&fsrc) - *((DWORD *)&fref);
+  unsigned int uDiff = diff < 0 ? -diff : diff;
+  return uDiff <= (unsigned int)ULPTolerance;
+}
+
+inline bool CompareHalfEpsilon(const uint16_t &fsrc, const uint16_t &fref, float epsilon) {
+  if (fsrc == fref)
+    return true;
+  if (isnanFloat16(fsrc))
+    return isnanFloat16(fref);
+  float src_f32 = ConvertFloat16ToFloat32(fsrc);
+  float ref_f32 = ConvertFloat16ToFloat32(fref);
+  return abs(src_f32-ref_f32) < epsilon;
+}
+
+inline bool
+CompareHalfRelativeEpsilon(const uint16_t &fsrc, const uint16_t &fref,
+  int nRelativeExp) {
+  return CompareHalfULP(fsrc, fref, 10 - nRelativeExp);
+}
+
 // returns the number of bytes per pixel for a given dxgi format
 // add more cases if different format needed to copy back resources
 inline UINT GetByteSizeForFormat(DXGI_FORMAT value) {

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1314 - 127
tools/clang/unittests/HLSL/ShaderOpArithTable.xml


+ 0 - 39
tools/clang/unittests/HLSL/ShaderOpTest.cpp

@@ -1880,45 +1880,6 @@ DXIL::ComponentType GetCompType(LPCWSTR pText, LPCWSTR pEnd) {
   }
 }
 
-bool GetSign(float x) {
-  return std::signbit(x);
-}
-
-int GetMantissa(float x) {
-  int bits = reinterpret_cast<int &>(x);
-  return bits & 0x7fffff;
-}
-
-int GetExponent(float x) {
-  int bits = reinterpret_cast<int &>(x);
-  return (bits >> 23) & 0xff;
-}
-
-
-// Note: This is not a precise float32 to float16 conversion.
-// This function should be used to convert float values read from ShaderOp data that were intended to be used for halves.
-// So special values (nan, denorm, inf) for float32 will map to their corresponding bits in float16,
-// and it will not handle true conversions that spans float16 denorms and float32 non-denorms.
-uint16_t ConvertFloat32ToFloat16(float x) {
-  bool isNeg = GetSign(x);
-  int exp = GetExponent(x);
-  int mantissa = GetMantissa(x);
-  if (isnan(x)) return Float16NaN;
-  if (isinf(x) || exp - 127 > 15) {
-    return isNeg ? Float16NegInf : Float16PosInf;
-  }
-  if (isdenorm(x)) return isNeg ? Float16NegDenorm : Float16PosDenorm;
-  if (exp == 0 && mantissa == 0) return isNeg ? Float16NegZero : Float16PosZero;
-  else {
-    DXASSERT(exp - 127 <= 15, "else invalid float conversion");
-    uint16_t val = 0;
-    val |= isNeg ? 0x8000 : 0;
-    val |= (exp - 127 + 15) << 10; // subtract from float32 exponent bias and add float16 exponent bias
-    val |= mantissa >> 13; // only first 10 significands taken
-    return val;
-  }
-}
-
 void ParseDataFromText(LPCWSTR pText, LPCWSTR pEnd, DXIL::ComponentType compType, std::vector<BYTE> &V) {
   BYTE *pB;
   if (compType == DXIL::ComponentType::F16 || compType == DXIL::ComponentType::F32) {

+ 0 - 16
tools/clang/unittests/HLSL/ShaderOpTest.h

@@ -298,22 +298,6 @@ void ParseShaderOpSetFromStream(IStream *pStream, ShaderOpSet *pShaderOpSet);
 // Deserialize a ShaderOpSet from an IXmlReader instance.
 void ParseShaderOpSetFromXml(IXmlReader *pReader, ShaderOpSet *pShaderOpSet);
 
-static const uint16_t Float16NaN = 0xff80;
-static const uint16_t Float16PosInf = 0x7c00;
-static const uint16_t Float16NegInf = 0xfc00;
-static const uint16_t Float16PosDenorm = 0x0001;
-static const uint16_t Float16NegDenorm = 0x8001;
-static const uint16_t Float16PosZero = 0x0000;
-static const uint16_t Float16NegZero = 0x8000;
-
-bool GetSign(float x);
-
-int GetMantissa(float x);
-
-int GetExponent(float x);
-
-uint16_t ConvertFloat32ToFloat16(float x);
-
 } // namespace st
 
 #endif __SHADEROPTEST_H__

+ 226 - 83
utils/hct/hctdb_test.py

@@ -73,6 +73,21 @@ def add_test_case(test_name, inst_names, validation_type, validation_tolerance,
     for inst_name in inst_names:
         g_instruction_nodes[inst_name].test_cases += [case]
 
+def add_test_case_float_half(test_name, inst_names, validation_type, validation_tolerance,
+                  float_input_lists, float_output_lists, shader_key, shader_op_name, **kwargs):
+    add_test_case(test_name, inst_names, validation_type, validation_tolerance,
+                  float_input_lists, float_output_lists, "cs_6_0", get_shader_text(shader_key, shader_op_name), **kwargs)
+    # if half test cases are different from float input lists, use those lists instead for half testings
+    half_input_lists, half_output_lists = float_input_lists, float_output_lists
+    if "half_inputs" in kwargs:
+        half_input_lists = kwargs["half_inputs"]
+    if "half_outputs" in kwargs:
+        half_output_lists = kwargs["half_outputs"]
+    # skip relative error test check for half for now
+    if validation_type != "Relative":
+        add_test_case(test_name + "Half", inst_names, validation_type, validation_tolerance,
+                    half_input_lists, half_output_lists, "cs_6_2", get_shader_text(shader_key.replace("float","half"), shader_op_name), **kwargs)
+
 def add_test_case_denorm(test_name, inst_names, validation_type, validation_tolerance, input_lists, output_lists_ftz, output_lists_preserve, shader_target, shader_text, **kwargs):
     add_test_case(test_name + "FTZ", inst_names, validation_type, validation_tolerance, input_lists,
                   output_lists_ftz, shader_target, shader_text, shader_arguments="-denorm ftz")
@@ -134,6 +149,34 @@ g_shader_texts = {
                     l.output = 0;
                 g_buf[GI] = l;
             };''',
+
+    "unary half": ''' struct SUnaryFPOp {
+                half input;
+                half output;
+            };
+            RWStructuredBuffer<SUnaryFPOp> g_buf : register(u0);
+            [numthreads(8,8,1)]
+            void main(uint GI : SV_GroupIndex) {
+                SUnaryFPOp l = g_buf[GI];
+                l.output = %s(l.input);
+                g_buf[GI] = l;
+            };''',
+
+    "unary half bool": ''' struct SUnaryFPOp {
+                half input;
+                half output;
+            };
+            RWStructuredBuffer<SUnaryFPOp> g_buf : register(u0);
+            [numthreads(8,8,1)]
+            void main(uint GI : SV_GroupIndex) {
+                SUnaryFPOp l = g_buf[GI];
+                if (%s(l.input))
+                    l.output = 1;
+                else
+                    l.output = 0;
+                g_buf[GI] = l;
+            };''',
+
      "binary int": ''' struct SBinaryIntOp {
                 int input1;
                 int input2;
@@ -176,7 +219,6 @@ g_shader_texts = {
                 g_buf[GI] = l;
             };''',
 
-
     "binary uint call": ''' struct SBinaryUintOp {
                 uint input1;
                 uint input2;
@@ -219,7 +261,35 @@ g_shader_texts = {
                 g_buf[GI] = l;
             };''',
 
-    "tertiary int": ''' struct STertiaryIntOp {
+    "binary half": ''' struct SBinaryFPOp {
+                half input1;
+                half input2;
+                half output1;
+                half output2;
+            };
+            RWStructuredBuffer<SBinaryFPOp> g_buf : register(u0);
+            [numthreads(8,8,1)]
+            void main(uint GI : SV_GroupIndex) {
+                SBinaryFPOp l = g_buf[GI];
+                l.output1 = l.input1 %s l.input2;
+                g_buf[GI] = l;
+            };''',
+
+    "binary half call": ''' struct SBinaryFPOp {
+                half input1;
+                half input2;
+                half output1;
+                half output2;
+            };
+            RWStructuredBuffer<SBinaryFPOp> g_buf : register(u0);
+            [numthreads(8,8,1)]
+            void main(uint GI : SV_GroupIndex) {
+                SBinaryFPOp l = g_buf[GI];
+                l.output1 = %s(l.input1,l.input2);
+                g_buf[GI] = l;
+            };''',
+
+     "tertiary int": ''' struct STertiaryIntOp {
                 int input1;
                 int input2;
                 int input3;
@@ -260,6 +330,19 @@ g_shader_texts = {
                 l.output = %s(l.input1, l.input2, l.input3);
                 g_buf[GI] = l;
             };''',
+    'tertiary half': ''' struct STertiaryHalfOp {
+                half input1;
+                half input2;
+                half input3;
+                half output;
+            };
+            RWStructuredBuffer<STertiaryHalfOp> g_buf : register(u0);
+            [numthreads(8,8,1)]
+            void main(uint GI : SV_GroupIndex) {
+                STertiaryHalfOp l = g_buf[GI];
+                l.output = %s(l.input1, l.input2, l.input3);
+                g_buf[GI] = l;
+            };''',
     "wave op int" :''' struct PerThreadData {
                         uint firstLaneId;
                         uint laneIndex;
@@ -350,142 +433,164 @@ def add_test_cases():
     p_denorm = float('1e-38')
     n_denorm = float('-1e-38')
     # Unary Float
-    add_test_case('Sin', ['Sin'], 'Epsilon', 0.0008, [[
+    add_test_case_float_half('Sin', ['Sin'], 'Epsilon', 0.0008, [[
         'NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '-314.16',
         '314.16'
     ]], [[
         'NaN', 'NaN', '-0', '-0', '0', '0', 'NaN', '-0.0007346401',
         '0.0007346401'
-    ]], 'cs_6_0', get_shader_text("unary float", "sin"))
-    add_test_case('Cos', ['Cos'], 'Epsilon', 0.0008, [[
+    ]], "unary float", "sin", half_inputs=[[
+        'NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '-314',
+        '314'
+    ]], half_outputs=[[
+        'NaN', 'NaN', '-0', '-0', '0', '0', 'NaN', '-0.1585929',
+        '0.1585929'
+    ]])
+    add_test_case_float_half('Cos', ['Cos'], 'Epsilon', 0.0008, [[
         'NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '-314.16',
         '314.16'
     ]], [[
         'NaN', 'NaN', '1.0', '1.0', '1.0', '1.0', 'NaN', '0.99999973015',
         '0.99999973015'
-    ]], 'cs_6_0', get_shader_text("unary float", "cos"))
-    add_test_case('Tan', ['Tan'], 'Epsilon', 0.0008, [[
+    ]], "unary float", "cos", half_inputs=[[
+        'NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '-314',
+        '314'
+    ]], half_outputs=[[
+        'NaN', 'NaN', '-0', '-0', '0', '0', 'NaN', '0.987344',
+        '0.987344'
+    ]])
+    add_test_case_float_half('Tan', ['Tan'], 'Epsilon', 0.0008, [[
         'NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '-314.16',
         '314.16'
     ]], [[
         'NaN', 'NaN', '-0.0', '-0.0', '0.0', '0.0', 'NaN', '-0.000735',
         '0.000735'
-    ]], 'cs_6_0', get_shader_text("unary float", "tan"))
-    add_test_case('Hcos', ['Hcos'], 'Epsilon', 0.0008,
+    ]], "unary float", "tan", half_inputs=[[
+        'NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '-314',
+        '314'
+    ]], half_outputs=[[
+        'NaN', 'NaN', '-0', '-0', '0', '0', 'NaN', '0.1606257',
+        '-0.1606257'
+    ]])
+    add_test_case_float_half('Hcos', ['Hcos'], 'Epsilon', 0.0008,
         [['NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '1', '-1']], [[
             'NaN', 'Inf', '1.0', '1.0', '1.0', '1.0', 'Inf', '1.543081',
             '1.543081'
-        ]], 'cs_6_0', get_shader_text("unary float", "cosh"))
-    add_test_case('Hsin', ['Hsin'], 'Epsilon', 0.0008,
+        ]], "unary float", "cosh")
+    add_test_case_float_half('Hsin', ['Hsin'], 'Epsilon', 0.0008,
         [['NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '1', '-1']], [[
             'NaN', '-Inf', '0.0', '0.0', '0.0', '0.0', 'Inf', '1.175201',
             '-1.175201'
-        ]], 'cs_6_0', get_shader_text("unary float", "sinh"))
-    add_test_case('Htan', ['Htan'], 'Epsilon', 0.0008,
+        ]], "unary float", "sinh")
+    add_test_case_float_half('Htan', ['Htan'], 'Epsilon', 0.0008,
         [['NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '1', '-1']], [[
             'NaN', '-1', '-0.0', '-0.0', '0.0', '0.0', '1', '0.761594',
             '-0.761594'
-        ]], 'cs_6_0', get_shader_text("unary float", "tanh"), warp_version=16202)
-    add_test_case('Acos', ['Acos'], 'Epsilon', 0.0008, [[
+        ]], "unary float", "tanh", warp_version=16202)
+    add_test_case_float_half('Acos', ['Acos'], 'Epsilon', 0.0008, [[
         'NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '1', '-1', '1.5',
         '-1.5'
     ]], [[
         'NaN', 'NaN', '1.570796', '1.570796', '1.570796', '1.570796', 'NaN',
         '0', '3.1415926', 'NaN', 'NaN'
-    ]], 'cs_6_0', get_shader_text("unary float", "acos"))
-    add_test_case('Asin', ['Asin'], 'Epsilon', 0.0008, [[
+    ]], "unary float", "acos")
+    add_test_case_float_half('Asin', ['Asin'], 'Epsilon', 0.0008, [[
         'NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '1', '-1', '1.5',
         '-1.5'
     ]], [[
         'NaN', 'NaN', '0.0', '0.0', '0.0', '0.0', 'NaN', '1.570796',
         '-1.570796', 'NaN', 'NaN'
-    ]], 'cs_6_0', get_shader_text("unary float", "asin"))
-    add_test_case('Atan', ['Atan'], 'Epsilon', 0.0008,
+    ]], "unary float", "asin")
+    add_test_case_float_half('Atan', ['Atan'], 'Epsilon', 0.0008,
         [['NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '1', '-1']], [[
             'NaN', '-1.570796', '0.0', '0.0', '0.0', '0.0', '1.570796',
             '0.785398163', '-0.785398163'
-        ]], 'cs_6_0', get_shader_text("unary float", "atan"), warp_version=16202)
-    add_test_case('Exp', ['Exp'], 'Relative', 21,
+        ]], "unary float", "atan", warp_version=16202)
+    add_test_case_float_half('Exp', ['Exp'], 'Relative', 21,
         [['NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '-1', '10']],
         [['NaN', '0', '1', '1', '1', '1', 'Inf', '0.367879441', '22026.46579']
-         ], 'cs_6_0', get_shader_text("unary float", "exp"))
-    add_test_case('Frc', ['Frc'], 'Epsilon', 0.0008, [[
+         ], "unary float", "exp")
+    add_test_case_float_half('Frc', ['Frc'], 'Epsilon', 0.0008, [[
         'NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '-1', '2.718280',
         '1000.599976', '-7.389'
     ]], [[
         'NaN', 'NaN', '0', '0', '0', '0', 'NaN', '0', '0.718280', '0.599976',
         '0.611'
-    ]], 'cs_6_0', get_shader_text("unary float", "frac"))
-    add_test_case('Log', ['Log'], 'Relative', 21, [[
+    ]], "unary float", "frac", 
+        half_inputs=[['NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '-1', '2.719',
+        '1000.5', '-7.39']], 
+        half_outputs=[[
+         'NaN', 'NaN', '0', '0', '0', '0', 'NaN', '0', '0.719', '0.5',
+        '0.61']])
+    add_test_case_float_half('Log', ['Log'], 'Relative', 21, [[
         'NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '-1',
         '2.718281828', '7.389056', '100'
     ]], [[
         'NaN', 'NaN', '-Inf', '-Inf', '-Inf', '-Inf', 'Inf', 'NaN', '1.0',
         '1.99999998', '4.6051701'
-    ]], 'cs_6_0', get_shader_text("unary float", "log"))
-    add_test_case('Sqrt', ['Sqrt'], 'ulp', 1, [[
+    ]],"unary float", "log", half_inputs=[[
+        'NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '-1',
+        '2.719', '7.39', '100'
+    ]], half_outputs=[[
+        'NaN', 'NaN', '-Inf', '-Inf', '-Inf', '-Inf', 'Inf', 'NaN', '1.0',
+        '2', '4.605'
+    ]])
+    add_test_case_float_half('Sqrt', ['Sqrt'], 'ulp', 1, [[
         'NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '-1', '2',
         '16.0', '256.0'
     ]], [[
         'NaN', 'NaN', '-0', '-0', '0', '0', 'Inf', 'NaN', '1.41421356237',
         '4.0', '16.0'
-    ]], 'cs_6_0', get_shader_text("unary float", "sqrt"))
-    add_test_case('Rsqrt', ['Rsqrt'], 'ulp', 1, [[
+    ]], "unary float", "sqrt")
+    add_test_case_float_half('Rsqrt', ['Rsqrt'], 'ulp', 1, [[
         'NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '-1', '16.0',
         '256.0', '65536.0'
     ]], [[
         'NaN', 'NaN', '-Inf', '-Inf', 'Inf', 'Inf', '0', 'NaN', '0.25',
         '0.0625', '0.00390625'
-    ]], 'cs_6_0', get_shader_text("unary float", "rsqrt"))
-    add_test_case('Rsqrt', ['Rsqrt'], 'ulp', 1, [[
+    ]], "unary float", "rsqrt", half_inputs=[[
         'NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '-1', '16.0',
-        '256.0', '65536.0'
-    ]], [[
+        '256.0', '65500'
+    ]], half_outputs=[[
         'NaN', 'NaN', '-Inf', '-Inf', 'Inf', 'Inf', '0', 'NaN', '0.25',
-        '0.0625', '0.00390625'
-    ]], 'cs_6_0', get_shader_text("unary float", "rsqrt"))
-    add_test_case('Round_ne', ['Round_ne'], 'Epsilon', 0, [[
+        '0.0625', '0.00001526'
+    ]])
+    add_test_case_float_half('Round_ne', ['Round_ne'], 'Epsilon', 0, [[
         'NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '10.0', '10.4',
         '10.5', '10.6', '11.5', '-10.0', '-10.4', '-10.5', '-10.6'
     ]], [[
         'NaN', '-Inf', '-0', '-0', '0', '0', 'Inf', '10.0', '10.0', '10.0',
         '11.0', '12.0', '-10.0', '-10.0', '-10.0', '-11.0'
-    ]], 'cs_6_0', get_shader_text("unary float", "round"))
-    add_test_case('Round_ni', ['Round_ni'], 'Epsilon', 0, [[
+    ]], "unary float", "round")
+    add_test_case_float_half('Round_ni', ['Round_ni'], 'Epsilon', 0, [[
         'NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '10.0', '10.4',
         '10.5', '10.6', '-10.0', '-10.4', '-10.5', '-10.6'
     ]], [[
         'NaN', '-Inf', '-0', '-0', '0', '0', 'Inf', '10.0', '10.0', '10.0',
         '10.0', '-10.0', '-11.0', '-11.0', '-11.0'
-    ]], 'cs_6_0', get_shader_text("unary float", "floor"))
-    add_test_case('Round_pi', ['Round_pi'], 'Epsilon', 0,
+    ]], "unary float", "floor")
+    add_test_case_float_half('Round_pi', ['Round_pi'], 'Epsilon', 0,
         [['NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '10.0', '10.4',
         '10.5', '10.6', '-10.0', '-10.4', '-10.5', '-10.6']],
         [['NaN', '-Inf', '-0', '-0', '0', '0', 'Inf', '10.0', '11.0', '11.0',
-        '11.0', '-10.0', '-10.0', '-10.0', '-10.0']], 'cs_6_0',
-        get_shader_text("unary float", "ceil"))
-    add_test_case('Round_z', ['Round_z'], 'Epsilon', 0,
+        '11.0', '-10.0', '-10.0', '-10.0', '-10.0']], "unary float", "ceil")
+    add_test_case_float_half('Round_z', ['Round_z'], 'Epsilon', 0,
         [['NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '10.0', '10.4',
         '10.5', '10.6', '-10.0', '-10.4', '-10.5', '-10.6']],
         [['NaN', '-Inf', '-0', '-0', '0', '0', 'Inf', '10.0', '10.0', '10.0',
-        '10.0', '-10.0', '-10.0', '-10.0', '-10.0']],'cs_6_0',
-        get_shader_text("unary float", "trunc"))
-    add_test_case('IsNaN', ['IsNaN'], 'Epsilon', 0,
+        '10.0', '-10.0', '-10.0', '-10.0', '-10.0']], "unary float", "trunc")
+    add_test_case_float_half('IsNaN', ['IsNaN'], 'Epsilon', 0,
         [['NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '1.0', '-1.0']
-         ], [['1', '0', '0', '0', '0', '0', '0', '0', '0']], 'cs_6_0',
-        get_shader_text("unary float bool", "isnan"))
-    add_test_case('IsInf', ['IsInf'], 'Epsilon', 0,
+         ], [['1', '0', '0', '0', '0', '0', '0', '0', '0']], "unary float bool", "isnan")
+    add_test_case_float_half('IsInf', ['IsInf'], 'Epsilon', 0,
         [['NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '1.0', '-1.0']
-         ], [['0', '1', '0', '0', '0', '0', '1', '0', '0']], 'cs_6_0',
-        get_shader_text("unary float bool", "isinf"))
-    add_test_case('IsFinite', ['IsFinite'], 'Epsilon', 0,
+         ], [['0', '1', '0', '0', '0', '0', '1', '0', '0']], "unary float bool", "isinf")
+    add_test_case_float_half('IsFinite', ['IsFinite'], 'Epsilon', 0,
         [['NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '1.0', '-1.0']
-         ], [['0', '0', '1', '1', '1', '1', '0', '1', '1']], 'cs_6_0',
-        get_shader_text("unary float bool", "isfinite"), warp_version=16202)
-    add_test_case('FAbs', ['FAbs'], 'Epsilon', 0,
+         ], [['0', '0', '1', '1', '1', '1', '0', '1', '1']], "unary float bool", "isfinite", warp_version=16202)
+    add_test_case_float_half('FAbs', ['FAbs'], 'Epsilon', 0,
         [['NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '1.0', '-1.0']
-         ], [['NaN', 'Inf', 'denorm', '0', '0', 'denorm', 'Inf', '1', '1']],
-        'cs_6_0', get_shader_text("unary float", "abs"))
+         ], [['NaN', 'Inf', 'denorm', '0', '0', 'denorm', 'Inf', '1', '1']], "unary float", "abs")
     # Binary Float
     add_test_case('FMin', ['FMin','FMax'], 'epsilon', 0, [[
         '-inf', '-inf', '-inf', '-inf', 'inf', 'inf', 'inf', 'inf', 'NaN',
@@ -513,14 +618,40 @@ def add_test_cases():
                 l.output2 = max(l.input1, l.input2);
                 g_buf[GI] = l;
             };''')
-    add_test_case('FAdd', ['FAdd'], 'ulp', 1, [['-1.0', '1.0', '32.5', '1.0000001000'],['4', '5.5', '334.7', '0.5000001000']], [['3.0', '6.5', '367.2', '1.5000002000']],
-    'cs_6_0', get_shader_text("binary float", "+"))
-    add_test_case('FSub', ['FSub'], 'ulp', 1, [['-1.0', '5.5', '32.5', '1.0000001000'],['4', '1.25', '334.7', '0.5000001000']], [['-5', '4.25', '-302.2', '0.5000']],
-    'cs_6_0', get_shader_text("binary float", "-"))
-    add_test_case('FMul', ['FMul'], 'ulp', 1, [['-1.0', '5.5', '1.0000001'],['4', '1.25', '2.0']], [['-4.0', '6.875', '2.0000002']],
-    'cs_6_0', get_shader_text("binary float", "*"))
-    add_test_case('FDiv', ['FDiv'], 'ulp', 1, [['-1.0', '5.5', '1.0000001'],['4', '1.25', '2.0']], [['-0.25', '4.4', '0.50000006']],
-    'cs_6_0', get_shader_text("binary float", "/"))
+    add_test_case('FMinHalf', ['FMin','FMax'], 'epsilon', 0, [[
+        '-inf', '-inf', '-inf', '-inf', 'inf', 'inf', 'inf', 'inf', 'NaN',
+        'NaN', 'NaN', 'NaN', '1.0', '1.0', '-1.0', '-1.0', '1.0'
+    ], [
+        '-inf', 'inf', '1.0', 'NaN', '-inf', 'inf', '1.0', 'NaN', '-inf',
+        'inf', '1.0', 'NaN', '-inf', 'inf', '1.0', 'NaN', '-1.0'
+    ]], [[
+        '-inf', '-inf', '-inf', '-inf', '-inf', 'inf', '1.0', 'inf', '-inf',
+        'inf', '1.0', 'NaN', '-inf', '1.0', '-1.0', '-1.0', '-1.0'
+    ], [
+        '-inf', 'inf', '1.0', '-inf', 'inf', 'inf', 'inf', 'inf', '-inf',
+        'inf', '1.0', 'NaN', '1.0', 'inf', '1.0', '-1.0', '1.0'
+    ]], 'cs_6_0', ''' struct SBinaryHalfOp {
+                half input1;
+                half input2;
+                half output1;
+                half output2;
+            };
+            RWStructuredBuffer<SBinaryHalfOp> g_buf : register(u0);
+            [numthreads(8,8,1)]
+            void main(uint GI : SV_GroupIndex) {
+                SBinaryHalfOp l = g_buf[GI];
+                l.output1 = min(l.input1, l.input2);
+                l.output2 = max(l.input1, l.input2);
+                g_buf[GI] = l;
+            };''')
+    add_test_case_float_half('FAdd', ['FAdd'], 'ulp', 1, [['-1.0', '1.0', '32.5', '1.0000001000'],['4', '5.5', '334.7', '0.5000001000']], [['3.0', '6.5', '367.2', '1.5000002000']],
+    "binary float", "+")
+    add_test_case_float_half('FSub', ['FSub'], 'ulp', 1, [['-1.0', '5.5', '32.5', '1.0000001000'],['4', '1.25', '334.7', '0.5000001000']], [['-5', '4.25', '-302.2', '0.5000']],
+    "binary float", "-")
+    add_test_case_float_half('FMul', ['FMul'], 'ulp', 1, [['-1.0', '5.5', '1.0000001'],['4', '1.25', '2.0']], [['-4.0', '6.875', '2.0000002']],
+    "binary float", "*")
+    add_test_case_float_half('FDiv', ['FDiv'], 'ulp', 1, [['-1.0', '5.5', '1.0000001'],['4', '1.25', '2.0']], [['-0.25', '4.4', '0.50000006']],
+    "binary float", "/")
 
     # Denorm Binary Float
     add_test_case_denorm('FAddDenorm', ['FAdd'], 'ulp', 1,
@@ -544,7 +675,7 @@ def add_test_cases():
     [['0x00018000','0x007F0000', '0', '0x01960000', '0x32400000']],
     'cs_6_2', get_shader_text("binary float", "*"))
     # Tertiary Float
-    add_test_case('FMad', ['FMad'], 'ulp', 1, [[
+    add_test_case_float_half('FMad', ['FMad'], 'ulp', 1, [[
         'NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '1.0', '-1.0',
         '0', '1', '1.5'
     ], [
@@ -554,7 +685,7 @@ def add_test_cases():
         'NaN', '-Inf', '-denorm', '-0', '0', 'denorm', 'Inf', '1.0', '-1.0',
         '1', '0', '-5.5'
     ]], [['NaN', 'NaN', '0', '0', '0', '0', 'Inf', '2', '0', '1', '1', '9.5']],
-                  'cs_6_0', get_shader_text("tertiary float", "mad"))
+                  "tertiary float", "mad")
 
     # Denorm Tertiary Float
     add_test_case_denorm('FMadDenorm', ['FMad'], 'ulp', 1,
@@ -1085,10 +1216,21 @@ def generate_table_for_taef():
                 "Id": "BinaryFloatOpTable"
             }), 2, 2)
         generate_parameter_types(
-            ET.SubElement(
-                root, "Table", attrib={
-                    "Id": "TertiaryFloatOpTable"
-                }), 3, 1)
+            ET.SubElement(root, "Table", attrib={
+                "Id": "TertiaryFloatOpTable"
+            }), 3, 1)
+        generate_parameter_types(
+            ET.SubElement(root, "Table", attrib={
+                "Id": "UnaryHalfOpTable"
+            }), 1, 1, True)
+        generate_parameter_types(
+            ET.SubElement(root, "Table", attrib={
+                "Id": "BinaryHalfOpTable"
+            }), 2, 2)
+        generate_parameter_types(
+            ET.SubElement(root, "Table", attrib={
+                "Id": "TertiaryHalfOpTable"
+            }), 3, 1)
         generate_parameter_types(
             ET.SubElement(root, "Table", attrib={
                 "Id": "UnaryIntOpTable"
@@ -1155,10 +1297,12 @@ def generate_table_for_taef():
         for case in g_test_cases.values():
             cur_inst = case.insts[0]
             if cur_inst.is_cast or cur_inst.category.startswith("Unary"):
-                if "f" in cur_inst.oload_types:
+                if "f" in cur_inst.oload_types and not "Half" in case.test_name:
                     generate_row(
                         root.find("./Table[@Id='UnaryFloatOpTable']"),
                         case)
+                if "h" in cur_inst.oload_types and "Half" in case.test_name:
+                    generate_row(root.find("./Table[@Id='UnaryHalfOpTable']"),case)
                 if "i" in cur_inst.oload_types:
                     if cur_inst.category.startswith("Unary int"):
                         generate_row(
@@ -1173,7 +1317,7 @@ def generate_table_for_taef():
                         print(cur_inst.dxil_class)
             elif cur_inst.is_binary or cur_inst.category.startswith(
                     "Binary"):
-                if "f" in cur_inst.oload_types:
+                if "f" in cur_inst.oload_types and not "Half" in case.test_name:
                     if case.test_name in g_denorm_tests: # for denorm tests
                         generate_row(
                             root.find("./Table[@Id='DenormBinaryFloatOpTable']"),
@@ -1182,7 +1326,9 @@ def generate_table_for_taef():
                         generate_row(
                             root.find("./Table[@Id='BinaryFloatOpTable']"),
                             case)
-                elif "i" in cur_inst.oload_types:
+                if "h" in cur_inst.oload_types and "Half" in case.test_name:
+                    generate_row(root.find("./Table[@Id='BinaryHalfOpTable']"),case)
+                if "i" in cur_inst.oload_types:
                     if cur_inst.category.startswith("Binary int"):
                         if case.test_name in ['UAdd', 'USub', 'UMul']: # Add, Sub, Mul use same operations for int and uint.
                             generate_row(
@@ -1201,16 +1347,16 @@ def generate_table_for_taef():
                         print(cur_inst.dxil_class)
 
             elif cur_inst.category.startswith("Tertiary"):
-                if "f" in cur_inst.oload_types:
+                if "f" in cur_inst.oload_types and not "Half" in case.test_name:
                     if case.test_name in g_denorm_tests: # for denorm tests
                         generate_row(
-                            root.find("./Table[@Id='DenormTertiaryFloatOpTable']"),
-                            case)
+                            root.find("./Table[@Id='DenormTertiaryFloatOpTable']"),case)
                     else:
                         generate_row(
-                            root.find("./Table[@Id='TertiaryFloatOpTable']"),
-                            case)
-                elif "i" in cur_inst.oload_types:
+                            root.find("./Table[@Id='TertiaryFloatOpTable']"),case)
+                if "h" in cur_inst.oload_types and "Half" in case.test_name:
+                    generate_row(root.find("./Table[@Id='TertiaryHalfOpTable']"),case)
+                if "i" in cur_inst.oload_types:
                     if cur_inst.category.startswith("Tertiary int"):
                         generate_row(
                             root.find("./Table[@Id='TertiaryIntOpTable']"),
@@ -1223,9 +1369,6 @@ def generate_table_for_taef():
                     else:
                         print("unknown op: " + cur_inst.name)
                         print(cur_inst.dxil_class)
-                else:
-                    print("unknown op: " + cur_inst.name)
-                    print(cur_inst.dxil_class)
             elif cur_inst.category.startswith("Quaternary"):
                 if cur_inst.name == "Bfi":
                     generate_row(

+ 20 - 1
utils/hct/hcttest.cmd

@@ -12,6 +12,7 @@ set TEST_ALL=1
 set TEST_CLANG=0
 set TEST_CMD=0
 set TEST_EXEC=0
+set TEST_EXEC_FUTURE=0
 set TEST_EXTRAS=0
 set TEST_EXEC_REQUIRED=0
 set TEST_CLANG_FILTER= /select: "@Priority<1"
@@ -110,6 +111,18 @@ if "%1"=="-clean" (
   set TEST_EXEC_FILTER=ExecutionTest::%2
   set TEST_EXEC_REQUIRED=1
   shift /1
+) else if "%1"=="exec-future" (
+  set TEST_ALL=0
+  set TEST_EXEC=1
+  set TEST_EXEC_FUTURE=1
+  set TEST_EXEC_REQUIRED=1
+) else if "%1"=="exec-future-filter" (
+  set TEST_ALL=0
+  set TEST_EXEC=1
+  set TEST_EXEC_FUTURE=1
+  set TEST_EXEC_FILTER=ExecutionTest::%2
+  set TEST_EXEC_REQUIRED=1
+  shift /1
 ) else if "%1"=="extras" (
   set TEST_ALL=0
   set TEST_EXTRAS=1
@@ -247,7 +260,11 @@ if "%TEST_EXEC%"=="1" (
 )
 
 if "%TEST_EXEC%"=="1" (
-  call :runte clang-hlsl-tests.dll /p:"HlslDataDir=%HLSL_SRC_DIR%\tools\clang\test\HLSL" /select:"@Name='%TEST_EXEC_FILTER%' AND @Priority<2" /runIgnoredTests /p:"ExperimentalShaders=*" %TEST_ADAPTER% %ADDITIONAL_OPTS%
+  if "%TEST_EXEC_FUTURE%"=="1" (
+    call :runte clang-hlsl-tests.dll /p:"HlslDataDir=%HLSL_SRC_DIR%\tools\clang\test\HLSL" /select:"@Name='%TEST_EXEC_FILTER%' AND @Priority=2" /runIgnoredTests /p:"ExperimentalShaders=*" %TEST_ADAPTER% %ADDITIONAL_OPTS%
+  ) else (
+    call :runte clang-hlsl-tests.dll /p:"HlslDataDir=%HLSL_SRC_DIR%\tools\clang\test\HLSL" /select:"@Name='%TEST_EXEC_FILTER%' AND @Priority<2" /runIgnoredTests /p:"ExperimentalShaders=*" %TEST_ADAPTER% %ADDITIONAL_OPTS%
+  )
   set RES_EXEC=!ERRORLEVEL!
 )
 
@@ -331,12 +348,14 @@ echo                - hcttest compat-suite "..\CodeGenHLSL\shader-compat-suite\l
 echo  cmd           - run command line tool tests.
 echo  v             - run the subset of clang tests that are verified-based.
 echo  exec          - run execution tests.
+echo  exec-future   - run execution tests for future releases.
 echo  extras        - run hcttest-extras tests.
 echo  noexec        - all except exec and extras tests.
 echo.
 echo Select clang or exec targets with filter by test name:
 echo  clang-filter Name
 echo  exec-filter Name
+echo  exec-exp-filter Name
 echo.
 echo Use the HCT_EXTRAS environment variable to add hcttest-before and hcttest-after hooks.
 echo.

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است