Skip to content

Commit d64d34c

Browse files
authored
Merge Long Vector Trigonometric Op Exec Tests (#7665)
Resolves #7629 Merge the long vector trig op exec tests from staging-sm6.9. Verified locally against WARP: `F:\hlsl.bin\TAEF\x64\te.exe "F:\hlsl.bin\Debug\bin\ExecHLSLTests.dll" /name:LongVector::OpTest::trig* /p:D3D12SDKVersion=1 /p:"ExperimentalShaders=*"`
1 parent c78ed99 commit d64d34c

File tree

4 files changed

+285
-0
lines changed

4 files changed

+285
-0
lines changed

tools/clang/unittests/HLSLExec/LongVectorOpTable.xml

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,4 +596,98 @@
596596
<Parameter Name="DataType">float64</Parameter>
597597
</Row>
598598
</Table>
599+
<Table Id="TrigonometricOpTable">
600+
<ParameterTypes>
601+
<!-- InputValueSetName1 is optional. If no value is provided use the
602+
default value set for the data type. This string is meant to be a key
603+
value for the the array of std::pairs defined in LongVectorTestData.h
604+
for the applicable DataType-->
605+
<ParameterType Name="InputValueSetName1">String</ParameterType>
606+
<!-- InputArgsName is optional and is also a key to the array of
607+
std::pairs defined in LongVectorTestData.h for the applicable DataType.
608+
Used for args like min and max in clamp-->
609+
<ParameterType Name="DataType">String</ParameterType>
610+
<ParameterType Name="OpTypeEnum">String</ParameterType>
611+
</ParameterTypes>
612+
<!-- LongVectorUnaryOpTable_Trigonometric DataType: float16 -->
613+
<Row Name="Acos_float16">
614+
<Parameter Name="OpTypeEnum">TrigonometricOpType_Acos</Parameter>
615+
<Parameter Name="DataType">float16</Parameter>
616+
<Parameter Name="InputValueSetName1">TrigonometricInputValueSet_RangeOne</Parameter>
617+
</Row>
618+
<Row Name="Asin_float16">
619+
<Parameter Name="OpTypeEnum">TrigonometricOpType_Asin</Parameter>
620+
<Parameter Name="DataType">float16</Parameter>
621+
<Parameter Name="InputValueSetName1">TrigonometricInputValueSet_RangeHalfPi</Parameter>
622+
</Row>
623+
<Row Name="Atan_float16">
624+
<Parameter Name="OpTypeEnum">TrigonometricOpType_Atan</Parameter>
625+
<Parameter Name="DataType">float16</Parameter>
626+
<Parameter Name="InputValueSetName1">TrigonometricInputValueSet_RangeHalfPi</Parameter>
627+
</Row>
628+
<Row Name="Cos_float16">
629+
<Parameter Name="OpTypeEnum">TrigonometricOpType_Cos</Parameter>
630+
<Parameter Name="DataType">float16</Parameter>
631+
</Row>
632+
<Row Name="Cosh_float16">
633+
<Parameter Name="OpTypeEnum">TrigonometricOpType_Cosh</Parameter>
634+
<Parameter Name="DataType">float16</Parameter>
635+
</Row>
636+
<Row Name="Sin_float16">
637+
<Parameter Name="OpTypeEnum">TrigonometricOpType_Sin</Parameter>
638+
<Parameter Name="DataType">float16</Parameter>
639+
</Row>
640+
<Row Name="Sinh_float16">
641+
<Parameter Name="OpTypeEnum">TrigonometricOpType_Sinh</Parameter>
642+
<Parameter Name="DataType">float16</Parameter>
643+
</Row>
644+
<Row Name="Tan_float16">
645+
<Parameter Name="OpTypeEnum">TrigonometricOpType_Tan</Parameter>
646+
<Parameter Name="DataType">float16</Parameter>
647+
</Row>
648+
<Row Name="Tanh_float16">
649+
<Parameter Name="OpTypeEnum">TrigonometricOpType_Tanh</Parameter>
650+
<Parameter Name="DataType">float16</Parameter>
651+
</Row>
652+
<!-- LongVectorUnaryOpTable_Trigonometric DataType: float32 -->
653+
<Row Name="Acos_float32">
654+
<Parameter Name="OpTypeEnum">TrigonometricOpType_Acos</Parameter>
655+
<Parameter Name="DataType">float32</Parameter>
656+
<Parameter Name="InputValueSetName1">TrigonometricInputValueSet_RangeOne</Parameter>
657+
</Row>
658+
<Row Name="Asin_float32">
659+
<Parameter Name="OpTypeEnum">TrigonometricOpType_Asin</Parameter>
660+
<Parameter Name="DataType">float32</Parameter>
661+
<Parameter Name="InputValueSetName1">TrigonometricInputValueSet_RangeHalfPi</Parameter>
662+
</Row>
663+
<Row Name="Atan_float32">
664+
<Parameter Name="OpTypeEnum">TrigonometricOpType_Atan</Parameter>
665+
<Parameter Name="DataType">float32</Parameter>
666+
<Parameter Name="InputValueSetName1">TrigonometricInputValueSet_RangeHalfPi</Parameter>
667+
</Row>
668+
<Row Name="Cos_float32">
669+
<Parameter Name="OpTypeEnum">TrigonometricOpType_Cos</Parameter>
670+
<Parameter Name="DataType">float32</Parameter>
671+
</Row>
672+
<Row Name="Cosh_float32">
673+
<Parameter Name="OpTypeEnum">TrigonometricOpType_Cosh</Parameter>
674+
<Parameter Name="DataType">float32</Parameter>
675+
</Row>
676+
<Row Name="Sin_float32">
677+
<Parameter Name="OpTypeEnum">TrigonometricOpType_Sin</Parameter>
678+
<Parameter Name="DataType">float32</Parameter>
679+
</Row>
680+
<Row Name="Sinh_float32">
681+
<Parameter Name="OpTypeEnum">TrigonometricOpType_Sinh</Parameter>
682+
<Parameter Name="DataType">float32</Parameter>
683+
</Row>
684+
<Row Name="Tan_float32">
685+
<Parameter Name="OpTypeEnum">TrigonometricOpType_Tan</Parameter>
686+
<Parameter Name="DataType">float32</Parameter>
687+
</Row>
688+
<Row Name="Tanh_float32">
689+
<Parameter Name="OpTypeEnum">TrigonometricOpType_Tanh</Parameter>
690+
<Parameter Name="DataType">float32</Parameter>
691+
</Row>
692+
</Table>
599693
</Data>

tools/clang/unittests/HLSLExec/LongVectors.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ LongVector::getUnaryOpType(const std::wstring &OpTypeString) {
1616
std::size(unaryOpTypeStringToEnumMap));
1717
}
1818

19+
LongVector::TrigonometricOpType
20+
LongVector::getTrigonometricOpType(const std::wstring &OpTypeString) {
21+
return getLongVectorOpType<LongVector::TrigonometricOpType>(
22+
trigonometricOpTypeStringToEnumMap, OpTypeString,
23+
std::size(trigonometricOpTypeStringToEnumMap));
24+
}
25+
1926
// These are helper arrays to be used with the TableParameterHandler that parses
2027
// the LongVectorOpTable.xml file for us.
2128
static TableParameter BinaryOpParameters[] = {
@@ -90,6 +97,20 @@ TEST_F(LongVector::OpTest, binaryOpTest) {
9097
dispatchTestByDataType(OpType, DataType, Handler);
9198
}
9299

100+
TEST_F(LongVector::OpTest, trigonometricOpTest) {
101+
WEX::TestExecution::SetVerifyOutput verifySettings(
102+
WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
103+
104+
const int TableSize = sizeof(UnaryOpParameters) / sizeof(TableParameter);
105+
TableParameterHandler Handler(UnaryOpParameters, TableSize);
106+
107+
std::wstring DataType(Handler.GetTableParamByName(L"DataType")->m_str);
108+
std::wstring OpTypeString(Handler.GetTableParamByName(L"OpTypeEnum")->m_str);
109+
110+
auto OpType = LongVector::getTrigonometricOpType(OpTypeString);
111+
dispatchTestByDataType(OpType, DataType, Handler);
112+
}
113+
93114
TEST_F(LongVector::OpTest, unaryOpTest) {
94115
WEX::TestExecution::SetVerifyOutput verifySettings(
95116
WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);

tools/clang/unittests/HLSLExec/LongVectors.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ class OpTest {
3535
L"Table:LongVectorOpTable.xml#BinaryOpTable")
3636
END_TEST_METHOD()
3737

38+
BEGIN_TEST_METHOD(trigonometricOpTest)
39+
TEST_METHOD_PROPERTY(L"DataSource",
40+
L"Table:LongVectorOpTable.xml#TrigonometricOpTable")
41+
END_TEST_METHOD()
42+
3843
BEGIN_TEST_METHOD(unaryOpTest)
3944
TEST_METHOD_PROPERTY(L"DataSource",
4045
L"Table:LongVectorOpTable.xml#UnaryOpTable")
@@ -150,6 +155,39 @@ static_assert(_countof(unaryOpTypeStringToEnumMap) ==
150155

151156
UnaryOpType getUnaryOpType(const std::wstring &OpTypeString);
152157

158+
enum TrigonometricOpType {
159+
TrigonometricOpType_Acos,
160+
TrigonometricOpType_Asin,
161+
TrigonometricOpType_Atan,
162+
TrigonometricOpType_Cos,
163+
TrigonometricOpType_Cosh,
164+
TrigonometricOpType_Sin,
165+
TrigonometricOpType_Sinh,
166+
TrigonometricOpType_Tan,
167+
TrigonometricOpType_Tanh,
168+
TrigonometricOpType_EnumValueCount
169+
};
170+
171+
static const LongVectorOpTypeStringToEnumValue
172+
trigonometricOpTypeStringToEnumMap[] = {
173+
{L"TrigonometricOpType_Acos", TrigonometricOpType_Acos},
174+
{L"TrigonometricOpType_Asin", TrigonometricOpType_Asin},
175+
{L"TrigonometricOpType_Atan", TrigonometricOpType_Atan},
176+
{L"TrigonometricOpType_Cos", TrigonometricOpType_Cos},
177+
{L"TrigonometricOpType_Cosh", TrigonometricOpType_Cosh},
178+
{L"TrigonometricOpType_Sin", TrigonometricOpType_Sin},
179+
{L"TrigonometricOpType_Sinh", TrigonometricOpType_Sinh},
180+
{L"TrigonometricOpType_Tan", TrigonometricOpType_Tan},
181+
{L"TrigonometricOpType_Tanh", TrigonometricOpType_Tanh},
182+
};
183+
184+
static_assert(_countof(trigonometricOpTypeStringToEnumMap) ==
185+
TrigonometricOpType_EnumValueCount,
186+
"trigonometricOpTypeStringToEnumMap size mismatch. Did you add "
187+
"a new enum value?");
188+
189+
TrigonometricOpType getTrigonometricOpType(const std::wstring &OpTypeString);
190+
153191
template <typename DataTypeT>
154192
std::vector<DataTypeT> getInputValueSetByKey(const std::wstring &Key,
155193
bool LogKey = true) {
@@ -214,6 +252,7 @@ template <typename DataTypeT, typename LongVectorOpTypeT> class TestConfig {
214252

215253
TestConfig(UnaryOpType OpType);
216254
TestConfig(BinaryOpType OpType);
255+
TestConfig(TrigonometricOpType OpType);
217256

218257
bool isBinaryOp() const {
219258
return BasicOpType == LongVector::BasicOpType_Binary ||
@@ -238,9 +277,15 @@ template <typename DataTypeT, typename LongVectorOpTypeT> class TestConfig {
238277
DataTypeT computeExpectedValue(const DataTypeT &A, const DataTypeT &B,
239278
BinaryOpType OpType) const;
240279
DataTypeT computeExpectedValue(const DataTypeT &A, const DataTypeT &B) const;
280+
DataTypeT computeExpectedValue(const DataTypeT &A,
281+
TrigonometricOpType OpType) const;
241282
DataTypeT computeExpectedValue(const DataTypeT &A, UnaryOpType OpType) const;
242283
DataTypeT computeExpectedValue(const DataTypeT &A) const;
243284

285+
void setInputArgsArrayName(const std::wstring &InputArgsArrayName) {
286+
this->InputArgsArrayName = InputArgsArrayName;
287+
}
288+
244289
void setInputValueSet1(const std::wstring &InputValueSetName) {
245290
this->InputValueSetName1 = InputValueSetName;
246291
}
@@ -257,6 +302,8 @@ template <typename DataTypeT, typename LongVectorOpTypeT> class TestConfig {
257302
return getInputValueSet(2);
258303
}
259304

305+
std::vector<DataTypeT> getInputArgsArray() const;
306+
260307
float getTolerance() const { return Tolerance; }
261308
LongVector::ValidationType getValidationType() const {
262309
return ValidationType;
@@ -278,6 +325,8 @@ template <typename DataTypeT, typename LongVectorOpTypeT> class TestConfig {
278325
LongVector::TestConfigTraits<LongVectorOpTypeT> OpTypeTraits;
279326
std::wstring InputValueSetName1 = L"DefaultInputValueSet1";
280327
std::wstring InputValueSetName2 = L"DefaultInputValueSet2";
328+
// No default args array
329+
std::wstring InputArgsArrayName = L"";
281330
}; // class LongVector::TestConfig
282331

283332
}; // namespace LongVector

tools/clang/unittests/HLSLExec/LongVectors.tpp

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,59 @@ LongVector::TestConfig<DataTypeT, LongVectorOpTypeT>::TestConfig(LongVector::Bin
342342
}
343343
}
344344

345+
template <typename DataTypeT, typename LongVectorOpTypeT>
346+
LongVector::TestConfig<DataTypeT, LongVectorOpTypeT>::TestConfig(LongVector::TrigonometricOpType OpType)
347+
: OpTypeTraits(OpType) {
348+
IntrinsicString = "";
349+
BasicOpType = LongVector::BasicOpType_Unary;
350+
351+
// All trigonometric ops are floating point types.
352+
// These trig functions are defined to have a max absolute error of 0.0008
353+
// as per the D3D functional specs. An example with this spec for sin and
354+
// cos is available here:
355+
// https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#22.10.20
356+
ValidationType = LongVector::ValidationType_Epsilon;
357+
if (std::is_same_v<DataTypeT, HLSLHalf_t>)
358+
Tolerance = 0.0010f;
359+
else if (std::is_same_v<DataTypeT, float>)
360+
Tolerance = 0.0008f;
361+
else
362+
VERIFY_FAIL(
363+
"Invalid type for trigonometric op. Expecting half or float.");
364+
365+
switch (OpType) {
366+
case LongVector::TrigonometricOpType_Acos:
367+
IntrinsicString = "acos";
368+
break;
369+
case LongVector::TrigonometricOpType_Asin:
370+
IntrinsicString = "asin";
371+
break;
372+
case LongVector::TrigonometricOpType_Atan:
373+
IntrinsicString = "atan";
374+
break;
375+
case LongVector::TrigonometricOpType_Cos:
376+
IntrinsicString = "cos";
377+
break;
378+
case LongVector::TrigonometricOpType_Cosh:
379+
IntrinsicString = "cosh";
380+
break;
381+
case LongVector::TrigonometricOpType_Sin:
382+
IntrinsicString = "sin";
383+
break;
384+
case LongVector::TrigonometricOpType_Sinh:
385+
IntrinsicString = "sinh";
386+
break;
387+
case LongVector::TrigonometricOpType_Tan:
388+
IntrinsicString = "tan";
389+
break;
390+
case LongVector::TrigonometricOpType_Tanh:
391+
IntrinsicString = "tanh";
392+
break;
393+
default:
394+
VERIFY_FAIL("Invalid TrigonometricOpType");
395+
}
396+
}
397+
345398
template <typename DataTypeT, typename LongVectorOpTypeT>
346399
bool LongVector::TestConfig<DataTypeT, LongVectorOpTypeT>::hasFunctionDefinition() const {
347400
if constexpr (std::is_same_v<LongVectorOpTypeT, LongVector::UnaryOpType>) {
@@ -463,6 +516,13 @@ DataTypeT LongVector::TestConfig<DataTypeT, LongVectorOpTypeT>::computeExpectedV
463516
template <typename DataTypeT, typename LongVectorOpTypeT>
464517
DataTypeT LongVector::TestConfig<DataTypeT, LongVectorOpTypeT>::computeExpectedValue(const DataTypeT &A) const {
465518

519+
if constexpr (std::is_same_v<LongVectorOpTypeT, LongVector::TrigonometricOpType>) {
520+
const auto OpType = static_cast<LongVector::TrigonometricOpType>(OpTypeTraits.OpType);
521+
// HLSLHalf_t is a struct. We need to call the constructor to get the
522+
// expected value.
523+
return computeExpectedValue(A, OpType);
524+
}
525+
466526
if constexpr (std::is_same_v<LongVectorOpTypeT, LongVector::UnaryOpType>) {
467527
const auto OpType = static_cast<LongVector::UnaryOpType>(OpTypeTraits.OpType);
468528
// HLSLHalf_t is a struct. We need to call the constructor to get the
@@ -477,6 +537,67 @@ DataTypeT LongVector::TestConfig<DataTypeT, LongVectorOpTypeT>::computeExpectedV
477537
return DataTypeT();
478538
}
479539

540+
template <typename DataTypeT, typename LongVectorOpTypeT>
541+
DataTypeT LongVector::TestConfig<DataTypeT, LongVectorOpTypeT>::computeExpectedValue(const DataTypeT &A,
542+
LongVector::TrigonometricOpType OpType) const {
543+
// The trig functions are only valid on floating point types. The constexpr in
544+
// this case is a relatively easy and clean way to prevent the compiler from
545+
// erroring out trying to resolve these for the non floating point types. We
546+
// won't use them in the first place.
547+
if constexpr (isFloatingPointType<DataTypeT>()) {
548+
switch (OpType) {
549+
case LongVector::TrigonometricOpType_Acos:
550+
return std::acos(A);
551+
case LongVector::TrigonometricOpType_Asin:
552+
return std::asin(A);
553+
case LongVector::TrigonometricOpType_Atan:
554+
return std::atan(A);
555+
case LongVector::TrigonometricOpType_Cos:
556+
return std::cos(A);
557+
case LongVector::TrigonometricOpType_Cosh:
558+
return std::cosh(A);
559+
case LongVector::TrigonometricOpType_Sin:
560+
return std::sin(A);
561+
case LongVector::TrigonometricOpType_Sinh:
562+
return std::sinh(A);
563+
case LongVector::TrigonometricOpType_Tan:
564+
return std::tan(A);
565+
case LongVector::TrigonometricOpType_Tanh:
566+
return std::tanh(A);
567+
default:
568+
LOG_ERROR_FMT_THROW(L"Unknown TrigonometricOpType: %d",
569+
OpTypeTraits.OpType);
570+
return DataTypeT();
571+
}
572+
}
573+
574+
LOG_ERROR_FMT_THROW(L"ComputeExpectedValue(const DataTypeT &A, "
575+
L"LongVectorOpTypeT OpType) called on a "
576+
L"non-float type: %d",
577+
OpType);
578+
579+
return DataTypeT();
580+
}
581+
582+
template <typename DataTypeT, typename LongVectorOpTypeT>
583+
std::vector<DataTypeT> LongVector::TestConfig<DataTypeT, LongVectorOpTypeT>::getInputArgsArray() const {
584+
585+
std::vector<DataTypeT> InputArgs;
586+
587+
std::wstring InputArgsArrayName = this->InputArgsArrayName;
588+
589+
if (InputArgsArrayName.empty())
590+
VERIFY_FAIL("No args array name set.");
591+
592+
if (std::is_same_v<DataTypeT, HLSLBool_t> && isClampOp())
593+
VERIFY_FAIL("Clamp is not supported for bools.");
594+
else
595+
return getInputValueSetByKey<DataTypeT>(InputArgsArrayName, false);
596+
597+
VERIFY_FAIL("Invalid type for args array.");
598+
return std::vector<DataTypeT>();
599+
}
600+
480601
template <typename DataTypeT, typename LongVectorOpTypeT>
481602
std::string LongVector::TestConfig<DataTypeT, LongVectorOpTypeT>::getCompilerOptionsString(size_t VectorSize) const {
482603
std::stringstream CompilerOptions("");

0 commit comments

Comments
 (0)