- Adding half tests for unary,binary,tertiary math operations
- Add 'exec-future' option for hcttest
This commit is contained in:
Young Kim 2017-12-12 15:12:19 -08:00 коммит произвёл GitHub
Родитель 1d4509f35d
Коммит ecf0307963
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
7 изменённых файлов: 2351 добавлений и 617 удалений

Просмотреть файл

@ -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);

Просмотреть файл

@ -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) {

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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) {

Просмотреть файл

@ -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__

Просмотреть файл

@ -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,6 +261,34 @@ g_shader_texts = {
g_buf[GI] = l;
};''',
"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;
@ -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={
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(

Просмотреть файл

@ -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" (
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.