Skip to content

Commit ee0994e

Browse files
authored
add barycentrics ordering check onto existing barycentrics test (microsoft#4635)
* add barycentrics ordering check onto existing barycentrics test, with extra shader
1 parent ffe931e commit ee0994e

File tree

2 files changed

+128
-35
lines changed

2 files changed

+128
-35
lines changed

tools/clang/test/HLSL/ShaderOpArith.xml

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,12 +1493,9 @@
14931493

14941494
<ShaderOp Name="Barycentrics" PS="PS" VS="VS">
14951495
<RootSignature>RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT)</RootSignature>
1496-
<Resource Name="VBuffer" Dimension="BUFFER" Width="1024" Flags="ALLOW_UNORDERED_ACCESS" InitialResourceState="COPY_DEST" Init="FromBytes" ReadBack="true">
1497-
{ { 0.0f, 1.0f , 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } },
1498-
{ { 1.0f, -1.0f , 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
1499-
{ { -1.0f, -1.0f , 0.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }
1500-
</Resource>
1501-
<Resource Name="RTarget" Dimension="TEXTURE2D" Width="1280" Height="2400" Format="R32G32B32A32_FLOAT" Flags="ALLOW_RENDER_TARGET" InitialResourceState="COPY_DEST" ReadBack="true" />
1496+
<Resource Name="VBuffer" Dimension="BUFFER" Width="1024" Flags="ALLOW_UNORDERED_ACCESS" InitialResourceState="COPY_DEST" Init="ByName" ReadBack="true">
1497+
</Resource>
1498+
<Resource Name="RTarget" Dimension="TEXTURE2D" Width="64" Height="64" Format="R32G32B32A32_FLOAT" Flags="ALLOW_RENDER_TARGET" InitialResourceState="COPY_DEST" ReadBack="true" />
15021499
<DescriptorHeap Name="RtvHeap" NumDescriptors="1" Type="RTV">
15031500
<Descriptor Name="RTarget" Kind="RTV"/>
15041501
</DescriptorHeap>
@@ -1535,7 +1532,40 @@
15351532
float4 vColor2 = GetAttributeAtVertex(input.color, 2);
15361533
return bary.x * vColor0 + bary.y * vColor1 + bary.z * vColor2;
15371534
}
1538-
]]>
1535+
]]>
1536+
</Shader>
1537+
1538+
<!-- This part of the shader op is for the barycentrics ordering part of the barycentrics test -->
1539+
<Shader Name="PSordering" Target="ps_6_1" EntryPoint="PSMain" Text="@MAIN"/>
1540+
<Shader Name="VSordering" Target="vs_6_1" EntryPoint="VSMain" Text="@MAIN"/>
1541+
1542+
<Shader Name="MAIN" Target="vs_6_1" EntryPoint="VSMain">
1543+
<![CDATA[
1544+
struct PSInput {
1545+
float4 position : SV_POSITION;
1546+
nointerpolation float4 color : COLOR;
1547+
uint svid : SVertexID;
1548+
};
1549+
1550+
PSInput VSMain(float4 position : POSITION, float4 color : COLOR, uint svid : SV_VertexID) {
1551+
PSInput result;
1552+
result.position = position;
1553+
result.color = color;
1554+
result.svid = svid;
1555+
1556+
return result;
1557+
}
1558+
1559+
float4 PSMain(PSInput input) : SV_Target {
1560+
// check to make sure that the pixel shader will see the barycentric weight associated
1561+
// with the first vertex in the x component of the SV_Barycentric vector, and likewise for subsequent vertices
1562+
1563+
return float4(float3(GetAttributeAtVertex(input.svid, 0),
1564+
GetAttributeAtVertex(input.svid, 1),
1565+
GetAttributeAtVertex(input.svid, 2)) * 0.5, 1.0);
1566+
}
1567+
1568+
]]>
15391569
</Shader>
15401570
</ShaderOp>
15411571

tools/clang/unittests/HLSL/ExecutionTest.cpp

Lines changed: 91 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8988,30 +8988,15 @@ TEST_F(ExecutionTest, CBufferTestHalf) {
89888988
}
89898989
}
89908990

8991-
TEST_F(ExecutionTest, BarycentricsTest) {
8992-
WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
8993-
CComPtr<IStream> pStream;
8994-
ReadHlslDataIntoNewStream(L"ShaderOpArith.xml", &pStream);
8995-
8996-
CComPtr<ID3D12Device> pDevice;
8997-
if (!CreateDevice(&pDevice, D3D_SHADER_MODEL_6_1))
8998-
return;
8999-
9000-
if (!DoesDeviceSupportBarycentrics(pDevice)) {
9001-
WEX::Logging::Log::Comment(L"Device does not support barycentrics.");
9002-
WEX::Logging::Log::Result(WEX::Logging::TestResults::Skipped);
9003-
return;
9004-
}
9005-
9006-
std::shared_ptr<ShaderOpTestResult> test = RunShaderOpTest(pDevice, m_support, pStream, "Barycentrics", nullptr);
8991+
void TestBarycentricVariant(bool checkOrdering, std::shared_ptr<ShaderOpTestResult> test){
90078992
MappedData data;
90088993
D3D12_RESOURCE_DESC &D = test->ShaderOp->GetResourceByName("RTarget")->Desc;
90098994
UINT width = (UINT)D.Width;
90108995
UINT height = D.Height;
90118996
UINT pixelSize = GetByteSizeForFormat(D.Format);
90128997

90138998
test->Test->GetReadBackData("RTarget", &data);
9014-
//const uint8_t *pPixels = (uint8_t *)data.data();
8999+
90159000
const float *pPixels = (float *)data.data();
90169001
// Get the vertex of barycentric coordinate using VBuffer
90179002
MappedData triangleData;
@@ -9025,33 +9010,106 @@ TEST_F(ExecutionTest, BarycentricsTest) {
90259010
XMFLOAT2 p0(pTriangleData[0], pTriangleData[1]);
90269011
XMFLOAT2 p1(pTriangleData[triangleVertexSizeInFloat], pTriangleData[triangleVertexSizeInFloat + 1]);
90279012
XMFLOAT2 p2(pTriangleData[triangleVertexSizeInFloat * 2], pTriangleData[triangleVertexSizeInFloat * 2 + 1]);
9028-
9013+
9014+
// Seems like the 3 floats must add up to 1 to get accurate results.
90299015
XMFLOAT3 barycentricWeights[4] = {
9030-
XMFLOAT3(0.3333f, 0.3333f, 0.3333f),
9016+
XMFLOAT3(0.4f, 0.2f, 0.4f),
90319017
XMFLOAT3(0.5f, 0.25f, 0.25f),
90329018
XMFLOAT3(0.25f, 0.5f, 0.25f),
90339019
XMFLOAT3(0.25f, 0.25f, 0.50f)
9034-
};
9020+
};
90359021

9036-
float tolerance = 0.001f;
9022+
float tolerance = 0.02f;
90379023
for (unsigned i = 0; i < sizeof(barycentricWeights) / sizeof(XMFLOAT3); ++i) {
90389024
float w0 = barycentricWeights[i].x;
90399025
float w1 = barycentricWeights[i].y;
90409026
float w2 = barycentricWeights[i].z;
90419027
float x1 = w0 * p0.x + w1 * p1.x + w2 * p2.x;
90429028
float y1 = w0 * p0.y + w1 * p1.y + w2 * p2.y;
90439029
// map from x1 y1 to rtv pixels
9044-
int pixelX = (int)((x1 + 1) * (width - 1) / 2);
9045-
int pixelY = (int)((1 - y1) * (height - 1) / 2);
9030+
int pixelX = (int)round((x1 + 1) * (width - 1) / 2.0);
9031+
int pixelY = (int)round((1 - y1) * (height - 1) / 2.0);
90469032
int offset = pixelSize * (pixelX + pixelY * width) / sizeof(pPixels[0]);
90479033
LogCommentFmt(L"location %u %u, value %f, %f, %f", pixelX, pixelY, pPixels[offset], pPixels[offset + 1], pPixels[offset + 2]);
9048-
VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset], w0, tolerance));
9049-
VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 1], w1, tolerance));
9050-
VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 2], w2, tolerance));
9034+
if (!checkOrdering){
9035+
VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset], w0, tolerance));
9036+
VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 1], w1, tolerance));
9037+
VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 2], w2, tolerance));
9038+
}
9039+
else{
9040+
// If the ordering constraint is met, then this pixel's RGBA should be all 1.0's
9041+
// since the shader only returns float4<1.0,1.0,1.0,1.0> when this condition is met.
9042+
VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset] , 0.0, tolerance));
9043+
VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 1], 0.5, tolerance));
9044+
VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 2], 1.0, tolerance));
9045+
VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 3], 1.0, tolerance));
9046+
}
9047+
}
9048+
}
9049+
9050+
st::ShaderOpTest::TInitCallbackFn MakeBarycentricsResourceInitCallbackFn(int &vertexShift){
9051+
return [&](LPCSTR Name, std::vector<BYTE>& Data, st::ShaderOp* pShaderOp) {
9052+
std::vector<float> bary = { 0.0f, 1.0f , 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
9053+
1.0f, -1.0f , 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
9054+
-1.0f, -1.0f , 0.0f, 0.0f, 0.0f, 1.0f, 1.0f };
9055+
const int barysize = 21;
9056+
9057+
UNREFERENCED_PARAMETER(pShaderOp);
9058+
VERIFY_IS_TRUE(0 == _stricmp(Name, "VBuffer"));
9059+
size_t size = sizeof(float) * barysize;
9060+
Data.resize(size);
9061+
float* vb = (float*)Data.data();
9062+
for (size_t i = 0; i < barysize; ++i) {
9063+
float* p = &vb[i];
9064+
float tempfloat = bary[(i + (7 * vertexShift)) % barysize];
9065+
*p = tempfloat;
9066+
}
9067+
};
9068+
9069+
}
9070+
9071+
TEST_F(ExecutionTest, BarycentricsTest) {
9072+
WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
9073+
CComPtr<IStream> pStream;
9074+
ReadHlslDataIntoNewStream(L"ShaderOpArith.xml", &pStream);
9075+
9076+
CComPtr<ID3D12Device> pDevice;
9077+
if (!CreateDevice(&pDevice, D3D_SHADER_MODEL_6_1))
9078+
return;
9079+
9080+
if (!DoesDeviceSupportBarycentrics(pDevice)) {
9081+
WEX::Logging::Log::Comment(L"Device does not support barycentrics.");
9082+
WEX::Logging::Log::Result(WEX::Logging::TestResults::Skipped);
9083+
return;
90519084
}
9052-
//SavePixelsToFile(pPixels, DXGI_FORMAT_R32G32B32A32_FLOAT, width, height, L"barycentric.bmp");
9085+
9086+
DXASSERT_NOMSG(pStream != nullptr);
9087+
std::shared_ptr<st::ShaderOpSet> ShaderOpSet =
9088+
std::make_shared<st::ShaderOpSet>();
9089+
st::ParseShaderOpSetFromStream(pStream, ShaderOpSet.get());
9090+
st::ShaderOp* pShaderOp =
9091+
ShaderOpSet->GetShaderOp("Barycentrics");
9092+
9093+
int test_iteration = 0;
9094+
auto ResourceCallbackFnNoShift = MakeBarycentricsResourceInitCallbackFn(test_iteration);
9095+
9096+
std::shared_ptr<ShaderOpTestResult> test = RunShaderOpTestAfterParse(pDevice, m_support, "Barycentrics", ResourceCallbackFnNoShift, ShaderOpSet);
9097+
TestBarycentricVariant(false, test);
9098+
9099+
// Now test that barycentric ordering is consistent
9100+
LogCommentFmt(L"Now testing that the barycentric ordering constraint is upheld for each pixel...");
9101+
pShaderOp->VS = pShaderOp->GetString("VSordering");
9102+
pShaderOp->PS = pShaderOp->GetString("PSordering");
9103+
for(; test_iteration < 3; test_iteration++)
9104+
{
9105+
auto ResourceCallbackFn = MakeBarycentricsResourceInitCallbackFn(test_iteration);
9106+
9107+
std::shared_ptr<ShaderOpTestResult> test2 = RunShaderOpTestAfterParse(pDevice, m_support, "Barycentrics", ResourceCallbackFn, ShaderOpSet);
9108+
TestBarycentricVariant(true, test2);
9109+
}
90539110
}
90549111

9112+
90559113
static const char RawBufferTestShaderDeclarations[] =
90569114
"// Note: COMPONENT_TYPE and COMPONENT_SIZE will be defined via compiler option -D\r\n"
90579115
"typedef COMPONENT_TYPE scalar; \r\n"
@@ -11488,7 +11546,12 @@ TEST_F(ExecutionTest, IsNormalTest) {
1148811546
st::ParseShaderOpSetFromStream(pStream, ShaderOpSet.get());
1148911547
st::ShaderOp *pShaderOp = ShaderOpSet->GetShaderOp("IsNormal");
1149011548
vector<st::ShaderOpRootValue> fallbackRootValues = pShaderOp->RootValues;
11491-
11549+
11550+
D3D_SHADER_MODEL sm = D3D_SHADER_MODEL_6_0;
11551+
LogCommentFmt(L"\r\nVerifying isNormal in shader "
11552+
L"model 6.%1u",
11553+
((UINT)sm & 0x0f));
11554+
1149211555
size_t count = Validation_Input->size();
1149311556

1149411557
auto ShaderInitFn = MakeShaderReplacementCallback(

0 commit comments

Comments
 (0)