Skip to content

Commit 50764ba

Browse files
authored
Implement Split/MakeDouble tests (#7675)
Adds two additional 'AsType' exec tests. One for AsUint and one for AsDouble. Which map to the Split and MakeDouble. Also added some new code comments to help clarify a few things. Also cleans up some dead code left over from remove clamp in a previous PR. Resolves #7667
1 parent 9618a81 commit 50764ba

File tree

6 files changed

+208
-88
lines changed

6 files changed

+208
-88
lines changed

tools/clang/unittests/HLSLExec/LongVectorOpTable.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,10 @@
314314
<Parameter Name="OpTypeEnum">BinaryOpType_Max</Parameter>
315315
<Parameter Name="DataType">uint32</Parameter>
316316
</Row>
317+
<Row Name="AsDouble_uint32">
318+
<Parameter Name="OpTypeEnum">BinaryOpType_AsDouble</Parameter>
319+
<Parameter Name="DataType">uint32</Parameter>
320+
</Row>
317321
<!-- LongVectorBinaryOpTypeTable DataType: uint64 -->
318322
<Row Name="ScalarAdd_uint64">
319323
<Parameter Name="OpTypeEnum">BinaryOpType_ScalarAdd</Parameter>
@@ -655,6 +659,13 @@
655659
<Parameter Name="OpTypeEnum">UnaryOpType_Initialize</Parameter>
656660
<Parameter Name="DataType">float64</Parameter>
657661
</Row>
662+
<Row Name="AsUint_SplitDouble_float64">
663+
<Parameter Name="OpTypeEnum">UnaryOpType_AsUint_SplitDouble</Parameter>
664+
<Parameter Name="DataType">float64</Parameter>
665+
<!-- Use a special InputValueSetName1 so we verify with values that
666+
produce non-zero outputs for HighBits and LowBits -->
667+
<Parameter Name="InputValueSetName1">SplitDoubleInputValueSet</Parameter>
668+
</Row>
658669
</Table>
659670
<Table Id="TrigonometricOpTable">
660671
<ParameterTypes>

tools/clang/unittests/HLSLExec/LongVectorTestData.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,10 @@ template <> struct LongVectorTestData<double> {
292292
-0.883}},
293293
{L"TrigonometricInputValueSet_RangeOne",
294294
{0.331, 0.277, -0.957, 0.677, -0.025, 0.495, 0.855, -0.673, -0.678,
295-
-0.905}}};
295+
-0.905}},
296+
{L"SplitDoubleInputValueSet",
297+
{0.0, -1.0, 1.0, -1.0, 12345678.87654321, -1.0, 1.0, -1.0, 1.0, -1.0}},
298+
};
296299
};
297300

298301
#endif // LONGVECTORTESTDATA_H

tools/clang/unittests/HLSLExec/LongVectors.cpp

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -337,14 +337,7 @@ void LongVector::OpTest::testBaseMethod(
337337
L"RunShaderOpTest CallBack. Unexpected Resource Name: %S", Name);
338338
});
339339

340-
// Map the data from GPU to CPU memory so we can verify our expectations.
341-
MappedData ShaderOutData;
342-
TestResult->Test->GetReadBackData("OutputVector", &ShaderOutData);
343-
344-
// The TestConfig object help handles more complicated verification cases. We
345-
// pass in the MappedData instead of the typed data because the TestConfig may
346-
// need to resolve the output type for test cases where the return type of the
347-
// intrinsic being tested does not match the input type, such as the AsType*
348-
// intrinsics (AsInt, AsInt16, AsFloat, ... etc).
349-
VERIFY_SUCCEEDED(TestConfig.verifyOutput(ShaderOutData));
340+
// The TestConfig object handles the logic for extracting the shader output
341+
// based on the op type.
342+
VERIFY_SUCCEEDED(TestConfig.verifyOutput(TestResult));
350343
}

tools/clang/unittests/HLSLExec/LongVectors.h

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ enum BinaryOpType {
146146
BinaryOpType_Max,
147147
BinaryOpType_ScalarMin,
148148
BinaryOpType_ScalarMax,
149+
BinaryOpType_AsDouble,
149150
BinaryOpType_EnumValueCount
150151
};
151152

@@ -164,6 +165,7 @@ static const LongVectorOpTypeStringToEnumValue binaryOpTypeStringToEnumMap[] = {
164165
{L"BinaryOpType_Max", BinaryOpType_Max},
165166
{L"BinaryOpType_ScalarMin", BinaryOpType_ScalarMin},
166167
{L"BinaryOpType_ScalarMax", BinaryOpType_ScalarMax},
168+
{L"BinaryOpType_AsDouble", BinaryOpType_AsDouble},
167169
};
168170

169171
static_assert(_countof(binaryOpTypeStringToEnumMap) ==
@@ -180,6 +182,7 @@ enum UnaryOpType {
180182
UnaryOpType_AsInt,
181183
UnaryOpType_AsInt16,
182184
UnaryOpType_AsUint,
185+
UnaryOpType_AsUint_SplitDouble,
183186
UnaryOpType_AsUint16,
184187
UnaryOpType_EnumValueCount
185188
};
@@ -191,6 +194,7 @@ static const LongVectorOpTypeStringToEnumValue unaryOpTypeStringToEnumMap[] = {
191194
{L"UnaryOpType_AsInt", UnaryOpType_AsInt},
192195
{L"UnaryOpType_AsInt16", UnaryOpType_AsInt16},
193196
{L"UnaryOpType_AsUint", UnaryOpType_AsUint},
197+
{L"UnaryOpType_AsUint_SplitDouble", UnaryOpType_AsUint_SplitDouble},
194198
{L"UnaryOpType_AsUint16", UnaryOpType_AsUint16},
195199
};
196200

@@ -327,6 +331,38 @@ unsigned int asUint(const int &A) {
327331
return LongVector::bit_cast<unsigned int>(A);
328332
}
329333

334+
template <typename DataTypeInT>
335+
void splitDouble([[maybe_unused]] const DataTypeInT &A,
336+
[[maybe_unused]] uint32_t &LowBits,
337+
[[maybe_unused]] uint32_t &HighBits) {
338+
LOG_ERROR_FMT_THROW(L"Programmer Error: splitDouble only accepts a double as "
339+
L"input. Have DataTypeInT: %S",
340+
typeid(DataTypeInT).name());
341+
}
342+
343+
void splitDouble(const double &A, uint32_t &LowBits, uint32_t &HighBits) {
344+
uint64_t Bits = 0;
345+
std::memcpy(&Bits, &A, sizeof(Bits));
346+
LowBits = static_cast<uint32_t>(Bits & 0xFFFFFFFF);
347+
HighBits = static_cast<uint32_t>(Bits >> 32);
348+
}
349+
350+
template <typename DataTypeInT>
351+
double asDouble([[maybe_unused]] const DataTypeInT &LowBits,
352+
[[maybe_unused]] const DataTypeInT &HighBits) {
353+
LOG_ERROR_FMT_THROW(L"Programmer Error: asDouble only accepts two uint32_t "
354+
L"inputs. Have DataTypeInT : %S",
355+
typeid(DataTypeInT).name());
356+
return 0.0;
357+
}
358+
359+
double asDouble(const uint32_t &LowBits, const uint32_t &HighBits) {
360+
uint64_t Bits = (static_cast<uint64_t>(HighBits) << 32) | LowBits;
361+
double Result;
362+
std::memcpy(&Result, &Bits, sizeof(Result));
363+
return Result;
364+
}
365+
330366
template <typename LongVectorOpTypeT> struct TestConfigTraits {
331367
TestConfigTraits(LongVectorOpTypeT OpType) : OpType(OpType) {}
332368
// LongVectorOpTypeT* Enum values. We don't use a UINT because
@@ -393,9 +429,6 @@ template <typename DataTypeT, typename LongVectorOpTypeT> class TestConfig {
393429

394430
bool isAsTypeOp() const { return isAsTypeOp(OpTypeTraits.OpType); }
395431

396-
bool hasFunctionDefinition() const;
397-
std::string getOPERAND2String() const;
398-
399432
// Helpers to get the hlsl type as a string for a given C++ type.
400433
std::string getHLSLInputTypeString() const;
401434
std::string getHLSLOutputTypeString() const;
@@ -409,6 +442,9 @@ template <typename DataTypeT, typename LongVectorOpTypeT> class TestConfig {
409442
DataTypeT computeExpectedValue(const DataTypeT &A) const;
410443
void
411444
computeExpectedValuesForAsTypeOp(const std::vector<DataTypeT> &InputVector1);
445+
void
446+
computeExpectedValuesForAsTypeOp(const std::vector<DataTypeT> &InputVector1,
447+
const std::vector<DataTypeT> &InputVector2);
412448

413449
void setInputArgsArrayName(const std::wstring &InputArgsArrayName) {
414450
this->InputArgsArrayName = InputArgsArrayName;
@@ -451,28 +487,29 @@ template <typename DataTypeT, typename LongVectorOpTypeT> class TestConfig {
451487

452488
LongVector::VariantVector &getExpectedVector() { return ExpectedVector; }
453489

454-
bool verifyOutput(MappedData &ShaderOutData);
490+
bool verifyOutput(const std::shared_ptr<st::ShaderOpTestResult> &TestResult);
455491

456492
private:
457493
bool isAsTypeOp(LongVector::UnaryOpType OpType) const;
458-
bool isAsTypeOp(LongVector::BinaryOpType) const { return false; }
494+
bool isAsTypeOp(LongVector::BinaryOpType) const;
459495
bool isAsTypeOp(LongVector::TrigonometricOpType) const { return false; }
460496

461-
std::string HLSLOutputTypeString(LongVector::UnaryOpType OpType) const;
462-
463-
bool resolveOutputTypeAndVerifyOutput(MappedData &ShaderOutData);
497+
bool resolveOutputTypeAndVerifyOutput(
498+
const std::shared_ptr<st::ShaderOpTestResult> &TestResult);
464499

465500
// Templated version to be used when the output data type does not match the
466501
// input data type.
467502
template <typename OutputDataTypeT>
468-
bool verifyOutput(MappedData &ShaderOutData);
503+
bool verifyOutput(const std::shared_ptr<st::ShaderOpTestResult> &TestResult);
469504

470505
std::vector<DataTypeT> getInputValueSet(size_t ValueSetIndex) const;
471506

472507
// To be used for the value of -DOPERATOR
473508
std::string OperatorString;
474509
// To be used for the value of -DFUNC
475510
std::string IntrinsicString;
511+
// Used to add special -D defines to the compiler options.
512+
std::string SpecialDefines = "";
476513
LongVector::BasicOpType BasicOpType = LongVector::BasicOpType_EnumValueCount;
477514
float Tolerance = 0.0;
478515
LongVector::ValidationType ValidationType =

0 commit comments

Comments
 (0)