From 15dfc73372e2b02289bc9274420375508bf3ba02 Mon Sep 17 00:00:00 2001 From: Joshua Batista Date: Fri, 2 Sep 2022 18:06:11 -0700 Subject: [PATCH 1/7] add barycentrics ordering check onto existing barycentrics test, with extra shader --- tools/clang/test/HLSL/ShaderOpArith.xml | 60 +++++++ tools/clang/unittests/HLSL/ExecutionTest.cpp | 168 ++++++++++++++----- 2 files changed, 185 insertions(+), 43 deletions(-) diff --git a/tools/clang/test/HLSL/ShaderOpArith.xml b/tools/clang/test/HLSL/ShaderOpArith.xml index 5d9c1c9d68..3dda24c304 100644 --- a/tools/clang/test/HLSL/ShaderOpArith.xml +++ b/tools/clang/test/HLSL/ShaderOpArith.xml @@ -1539,6 +1539,66 @@ + + + RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT) + + + + + + + + + + + + + + + + + + + + + + + + + RootFlags(0), SRV(t0), SRV(t1), UAV(u0), UAV(u1), DescriptorTable(SRV(t2,numDescriptors=2), UAV(u2,numDescriptors=2)) diff --git a/tools/clang/unittests/HLSL/ExecutionTest.cpp b/tools/clang/unittests/HLSL/ExecutionTest.cpp index a1437c2d2c..d18ae73905 100644 --- a/tools/clang/unittests/HLSL/ExecutionTest.cpp +++ b/tools/clang/unittests/HLSL/ExecutionTest.cpp @@ -9001,53 +9001,135 @@ TEST_F(ExecutionTest, BarycentricsTest) { return; } - std::shared_ptr test = RunShaderOpTest(pDevice, m_support, pStream, "Barycentrics", nullptr); - MappedData data; - D3D12_RESOURCE_DESC &D = test->ShaderOp->GetResourceByName("RTarget")->Desc; - UINT width = (UINT)D.Width; - UINT height = D.Height; - UINT pixelSize = GetByteSizeForFormat(D.Format); + DXASSERT_NOMSG(pStream != nullptr); + std::shared_ptr ShaderOpSet = + std::make_shared(); + st::ParseShaderOpSetFromStream(pStream, ShaderOpSet.get()); - test->Test->GetReadBackData("RTarget", &data); - //const uint8_t *pPixels = (uint8_t *)data.data(); - const float *pPixels = (float *)data.data(); - // Get the vertex of barycentric coordinate using VBuffer - MappedData triangleData; - test->Test->GetReadBackData("VBuffer", &triangleData); - const float *pTriangleData = (float*)triangleData.data(); - // get the size of the input data - unsigned triangleVertexSizeInFloat = 0; - for (auto element : test->ShaderOp->InputElements) - triangleVertexSizeInFloat += GetByteSizeForFormat(element.Format) / 4; - - XMFLOAT2 p0(pTriangleData[0], pTriangleData[1]); - XMFLOAT2 p1(pTriangleData[triangleVertexSizeInFloat], pTriangleData[triangleVertexSizeInFloat + 1]); - XMFLOAT2 p2(pTriangleData[triangleVertexSizeInFloat * 2], pTriangleData[triangleVertexSizeInFloat * 2 + 1]); - - XMFLOAT3 barycentricWeights[4] = { - XMFLOAT3(0.3333f, 0.3333f, 0.3333f), - XMFLOAT3(0.5f, 0.25f, 0.25f), - XMFLOAT3(0.25f, 0.5f, 0.25f), - XMFLOAT3(0.25f, 0.25f, 0.50f) - }; + { + std::shared_ptr test = RunShaderOpTestAfterParse(pDevice, m_support, "Barycentrics", nullptr, ShaderOpSet); + MappedData data; + D3D12_RESOURCE_DESC &D = test->ShaderOp->GetResourceByName("RTarget")->Desc; + UINT width = (UINT)D.Width; + UINT height = D.Height; + UINT pixelSize = GetByteSizeForFormat(D.Format); + + test->Test->GetReadBackData("RTarget", &data); + //const uint8_t *pPixels = (uint8_t *)data.data(); + const float *pPixels = (float *)data.data(); + // Get the vertex of barycentric coordinate using VBuffer + MappedData triangleData; + test->Test->GetReadBackData("VBuffer", &triangleData); + const float *pTriangleData = (float*)triangleData.data(); + // get the size of the input data + unsigned triangleVertexSizeInFloat = 0; + for (auto element : test->ShaderOp->InputElements) + triangleVertexSizeInFloat += GetByteSizeForFormat(element.Format) / 4; + + XMFLOAT2 p0(pTriangleData[0], pTriangleData[1]); + XMFLOAT2 p1(pTriangleData[triangleVertexSizeInFloat], pTriangleData[triangleVertexSizeInFloat + 1]); + XMFLOAT2 p2(pTriangleData[triangleVertexSizeInFloat * 2], pTriangleData[triangleVertexSizeInFloat * 2 + 1]); + + XMFLOAT3 barycentricWeights[4] = { + XMFLOAT3(0.3333f, 0.3333f, 0.3333f), + XMFLOAT3(0.5f, 0.25f, 0.25f), + XMFLOAT3(0.25f, 0.5f, 0.25f), + XMFLOAT3(0.25f, 0.25f, 0.50f) + }; - float tolerance = 0.001f; - for (unsigned i = 0; i < sizeof(barycentricWeights) / sizeof(XMFLOAT3); ++i) { - float w0 = barycentricWeights[i].x; - float w1 = barycentricWeights[i].y; - float w2 = barycentricWeights[i].z; - float x1 = w0 * p0.x + w1 * p1.x + w2 * p2.x; - float y1 = w0 * p0.y + w1 * p1.y + w2 * p2.y; - // map from x1 y1 to rtv pixels - int pixelX = (int)((x1 + 1) * (width - 1) / 2); - int pixelY = (int)((1 - y1) * (height - 1) / 2); - int offset = pixelSize * (pixelX + pixelY * width) / sizeof(pPixels[0]); - LogCommentFmt(L"location %u %u, value %f, %f, %f", pixelX, pixelY, pPixels[offset], pPixels[offset + 1], pPixels[offset + 2]); - VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset], w0, tolerance)); - VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 1], w1, tolerance)); - VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 2], w2, tolerance)); + float tolerance = 0.001f; + for (unsigned i = 0; i < sizeof(barycentricWeights) / sizeof(XMFLOAT3); ++i) { + float w0 = barycentricWeights[i].x; + float w1 = barycentricWeights[i].y; + float w2 = barycentricWeights[i].z; + float x1 = w0 * p0.x + w1 * p1.x + w2 * p2.x; + float y1 = w0 * p0.y + w1 * p1.y + w2 * p2.y; + // map from x1 y1 to rtv pixels + int pixelX = (int)((x1 + 1) * (width - 1) / 2); + int pixelY = (int)((1 - y1) * (height - 1) / 2); + int offset = pixelSize * (pixelX + pixelY * width) / sizeof(pPixels[0]); + LogCommentFmt(L"location %u %u, value %f, %f, %f", pixelX, pixelY, pPixels[offset], pPixels[offset + 1], pPixels[offset + 2]); + VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset], w0, tolerance)); + VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 1], w1, tolerance)); + VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 2], w2, tolerance)); + } } + + // Now test that barycentric ordering is consistent + LogCommentFmt(L"Now testing that the barycentric ordering constraint is upheld for each pixel..."); + for(int test_iteration = 0; test_iteration < 3; test_iteration++) + { + auto ResourceCallbackFn = + [&](LPCSTR Name, std::vector &Data, st::ShaderOp *pShaderOp) { + std::vector bary = {0.0f, 1.0f , 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, -1.0f , 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, + -1.0f, -1.0f , 0.0f, 0.0f, 0.0f, 1.0f, 1.0f}; + const int barysize = 21; + + UNREFERENCED_PARAMETER(pShaderOp); + VERIFY_IS_TRUE(0 == _stricmp(Name, "VBuffer")); + size_t size = sizeof(float)*barysize; + Data.resize(size); + float *vb = (float *)Data.data(); + for (size_t i = 0; i < barysize; ++i) { + float *p = &vb[i]; + float tempfloat = bary[(i+(7*test_iteration))%barysize]; + *p = tempfloat; + } + }; + + std::shared_ptr test2 = RunShaderOpTestAfterParse(pDevice, m_support, "BarycentricsCheckOrder", ResourceCallbackFn, ShaderOpSet); + MappedData data; + D3D12_RESOURCE_DESC &D = test2->ShaderOp->GetResourceByName("RTarget")->Desc; + UINT width = (UINT)D.Width; + UINT height = D.Height; + UINT pixelSize = GetByteSizeForFormat(D.Format); + test2->Test->GetReadBackData("RTarget", &data); + //const uint8_t *pPixels = (uint8_t *)data.data(); + const float *pPixels = (float *)data.data(); + // Get the vertex of barycentric coordinate using VBuffer + MappedData triangleData; + test2->Test->GetReadBackData("VBuffer", &triangleData); + const float *pTriangleData = (float*)triangleData.data(); + + // get the size of the input data + unsigned triangleVertexSizeInFloat = 0; + for (auto element : test2->ShaderOp->InputElements) + triangleVertexSizeInFloat += GetByteSizeForFormat(element.Format) / 4; + XMFLOAT2 p0(pTriangleData[0], pTriangleData[1]); + XMFLOAT2 p1(pTriangleData[triangleVertexSizeInFloat], pTriangleData[triangleVertexSizeInFloat + 1]); + XMFLOAT2 p2(pTriangleData[triangleVertexSizeInFloat * 2], pTriangleData[triangleVertexSizeInFloat * 2 + 1]); + XMFLOAT3 barycentricWeights[4] = { + XMFLOAT3(0.3333f, 0.3333f, 0.3333f), + XMFLOAT3(0.5f, 0.25f, 0.25f), + XMFLOAT3(0.25f, 0.5f, 0.25f), + XMFLOAT3(0.25f, 0.25f, 0.50f) + }; + float tolerance = 0.001f; + for (unsigned i = 0; i < sizeof(barycentricWeights) / sizeof(XMFLOAT3); ++i) { + float w0 = barycentricWeights[i].x; + float w1 = barycentricWeights[i].y; + float w2 = barycentricWeights[i].z; + float x1 = w0 * p0.x + w1 * p1.x + w2 * p2.x; + float y1 = w0 * p0.y + w1 * p1.y + w2 * p2.y; + // map from x1 y1 to rtv pixels + int pixelX = (int)((x1 + 1) * (width - 1) / 2); + int pixelY = (int)((1 - y1) * (height - 1) / 2); + int offset = pixelSize * (pixelX + pixelY * width) / sizeof(pPixels[0]); + LogCommentFmt(L"location %u %u, value %f, %f, %f, %f", pixelX, pixelY, pPixels[offset], pPixels[offset + 1], pPixels[offset + 2], pPixels[offset + 3]); + + // If the ordering constraint is met, then this pixel's RGBA should be all 1.0's + // since the shader only returns float4<1.0,1.0,1.0,1.0> when this condition is met. + VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset] , 1.0, tolerance)); + VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 1], 1.0, tolerance)); + VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 2], 1.0, tolerance)); + VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 3], 1.0, tolerance)); + } + + } + //SavePixelsToFile(pPixels, DXGI_FORMAT_R32G32B32A32_FLOAT, width, height, L"barycentric.bmp"); + } static const char RawBufferTestShaderDeclarations[] = From 73ffc283ff49148d8f42006911c06365759189d4 Mon Sep 17 00:00:00 2001 From: Joshua Batista Date: Tue, 6 Sep 2022 12:45:02 -0700 Subject: [PATCH 2/7] shrink RT dimensions for both barycentrics tests, remove unused var in shader --- tools/clang/test/HLSL/ShaderOpArith.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/clang/test/HLSL/ShaderOpArith.xml b/tools/clang/test/HLSL/ShaderOpArith.xml index 3dda24c304..7442f16fb6 100644 --- a/tools/clang/test/HLSL/ShaderOpArith.xml +++ b/tools/clang/test/HLSL/ShaderOpArith.xml @@ -1498,7 +1498,7 @@ { { 1.0f, -1.0f , 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, { { -1.0f, -1.0f , 0.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } } - + @@ -1544,7 +1544,7 @@ RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT) - + @@ -1579,7 +1579,7 @@ return result; } - float4 PSMain(PSInput input, float3 bary : SV_Barycentrics) : SV_Target { + float4 PSMain(PSInput input) : SV_Target { // check to make sure that the pixel shader will see the barycentric weight associated // with the first vertex in the x component of the SV_Barycentric vector, and likewise for subsequent vertices From b3ba4cc20a756f4759028f8e1b40388789b67a5c Mon Sep 17 00:00:00 2001 From: Joshua Batista Date: Tue, 20 Sep 2022 12:04:49 -0700 Subject: [PATCH 3/7] factor out test code, remove commented code. --- tools/clang/test/HLSL/ShaderOpArith.xml | 2 +- tools/clang/unittests/HLSL/ExecutionTest.cpp | 163 ++++++++----------- 2 files changed, 66 insertions(+), 99 deletions(-) diff --git a/tools/clang/test/HLSL/ShaderOpArith.xml b/tools/clang/test/HLSL/ShaderOpArith.xml index 7442f16fb6..47ac7d2bac 100644 --- a/tools/clang/test/HLSL/ShaderOpArith.xml +++ b/tools/clang/test/HLSL/ShaderOpArith.xml @@ -1498,7 +1498,7 @@ { { 1.0f, -1.0f , 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, { { -1.0f, -1.0f , 0.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } } - + diff --git a/tools/clang/unittests/HLSL/ExecutionTest.cpp b/tools/clang/unittests/HLSL/ExecutionTest.cpp index d18ae73905..e7877469e7 100644 --- a/tools/clang/unittests/HLSL/ExecutionTest.cpp +++ b/tools/clang/unittests/HLSL/ExecutionTest.cpp @@ -8986,6 +8986,64 @@ TEST_F(ExecutionTest, CBufferTestHalf) { } } +void TestBarycentricVariant(bool checkOrdering, std::shared_ptr test){ + MappedData data; + D3D12_RESOURCE_DESC &D = test->ShaderOp->GetResourceByName("RTarget")->Desc; + UINT width = (UINT)D.Width; + UINT height = D.Height; + UINT pixelSize = GetByteSizeForFormat(D.Format); + + test->Test->GetReadBackData("RTarget", &data); + + const float *pPixels = (float *)data.data(); + // Get the vertex of barycentric coordinate using VBuffer + MappedData triangleData; + test->Test->GetReadBackData("VBuffer", &triangleData); + const float *pTriangleData = (float*)triangleData.data(); + // get the size of the input data + unsigned triangleVertexSizeInFloat = 0; + for (auto element : test->ShaderOp->InputElements) + triangleVertexSizeInFloat += GetByteSizeForFormat(element.Format) / 4; + + XMFLOAT2 p0(pTriangleData[0], pTriangleData[1]); + XMFLOAT2 p1(pTriangleData[triangleVertexSizeInFloat], pTriangleData[triangleVertexSizeInFloat + 1]); + XMFLOAT2 p2(pTriangleData[triangleVertexSizeInFloat * 2], pTriangleData[triangleVertexSizeInFloat * 2 + 1]); + + XMFLOAT3 barycentricWeights[4] = { + XMFLOAT3(0.3333f, 0.3333f, 0.3333f), + XMFLOAT3(0.5f, 0.25f, 0.25f), + XMFLOAT3(0.25f, 0.5f, 0.25f), + XMFLOAT3(0.25f, 0.25f, 0.50f) + }; + + float tolerance = 0.019f; + for (unsigned i = 0; i < sizeof(barycentricWeights) / sizeof(XMFLOAT3); ++i) { + float w0 = barycentricWeights[i].x; + float w1 = barycentricWeights[i].y; + float w2 = barycentricWeights[i].z; + float x1 = w0 * p0.x + w1 * p1.x + w2 * p2.x; + float y1 = w0 * p0.y + w1 * p1.y + w2 * p2.y; + // map from x1 y1 to rtv pixels + int pixelX = (int)((x1 + 1) * (width - 1) / 2); + int pixelY = (int)((1 - y1) * (height - 1) / 2); + int offset = pixelSize * (pixelX + pixelY * width) / sizeof(pPixels[0]); + LogCommentFmt(L"location %u %u, value %f, %f, %f", pixelX, pixelY, pPixels[offset], pPixels[offset + 1], pPixels[offset + 2]); + if (!checkOrdering){ + VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset], w0, tolerance)); + VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 1], w1, tolerance)); + VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 2], w2, tolerance)); + } + else{ + // If the ordering constraint is met, then this pixel's RGBA should be all 1.0's + // since the shader only returns float4<1.0,1.0,1.0,1.0> when this condition is met. + VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset] , 1.0, tolerance)); + VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 1], 1.0, tolerance)); + VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 2], 1.0, tolerance)); + VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 3], 1.0, tolerance)); + } + } +} + TEST_F(ExecutionTest, BarycentricsTest) { WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures); CComPtr pStream; @@ -9006,55 +9064,10 @@ TEST_F(ExecutionTest, BarycentricsTest) { std::make_shared(); st::ParseShaderOpSetFromStream(pStream, ShaderOpSet.get()); - { - std::shared_ptr test = RunShaderOpTestAfterParse(pDevice, m_support, "Barycentrics", nullptr, ShaderOpSet); - MappedData data; - D3D12_RESOURCE_DESC &D = test->ShaderOp->GetResourceByName("RTarget")->Desc; - UINT width = (UINT)D.Width; - UINT height = D.Height; - UINT pixelSize = GetByteSizeForFormat(D.Format); - - test->Test->GetReadBackData("RTarget", &data); - //const uint8_t *pPixels = (uint8_t *)data.data(); - const float *pPixels = (float *)data.data(); - // Get the vertex of barycentric coordinate using VBuffer - MappedData triangleData; - test->Test->GetReadBackData("VBuffer", &triangleData); - const float *pTriangleData = (float*)triangleData.data(); - // get the size of the input data - unsigned triangleVertexSizeInFloat = 0; - for (auto element : test->ShaderOp->InputElements) - triangleVertexSizeInFloat += GetByteSizeForFormat(element.Format) / 4; - - XMFLOAT2 p0(pTriangleData[0], pTriangleData[1]); - XMFLOAT2 p1(pTriangleData[triangleVertexSizeInFloat], pTriangleData[triangleVertexSizeInFloat + 1]); - XMFLOAT2 p2(pTriangleData[triangleVertexSizeInFloat * 2], pTriangleData[triangleVertexSizeInFloat * 2 + 1]); - - XMFLOAT3 barycentricWeights[4] = { - XMFLOAT3(0.3333f, 0.3333f, 0.3333f), - XMFLOAT3(0.5f, 0.25f, 0.25f), - XMFLOAT3(0.25f, 0.5f, 0.25f), - XMFLOAT3(0.25f, 0.25f, 0.50f) - }; - - float tolerance = 0.001f; - for (unsigned i = 0; i < sizeof(barycentricWeights) / sizeof(XMFLOAT3); ++i) { - float w0 = barycentricWeights[i].x; - float w1 = barycentricWeights[i].y; - float w2 = barycentricWeights[i].z; - float x1 = w0 * p0.x + w1 * p1.x + w2 * p2.x; - float y1 = w0 * p0.y + w1 * p1.y + w2 * p2.y; - // map from x1 y1 to rtv pixels - int pixelX = (int)((x1 + 1) * (width - 1) / 2); - int pixelY = (int)((1 - y1) * (height - 1) / 2); - int offset = pixelSize * (pixelX + pixelY * width) / sizeof(pPixels[0]); - LogCommentFmt(L"location %u %u, value %f, %f, %f", pixelX, pixelY, pPixels[offset], pPixels[offset + 1], pPixels[offset + 2]); - VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset], w0, tolerance)); - VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 1], w1, tolerance)); - VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 2], w2, tolerance)); - } - } - + + std::shared_ptr test = RunShaderOpTestAfterParse(pDevice, m_support, "Barycentrics", nullptr, ShaderOpSet); + TestBarycentricVariant(false, test); + // Now test that barycentric ordering is consistent LogCommentFmt(L"Now testing that the barycentric ordering constraint is upheld for each pixel..."); for(int test_iteration = 0; test_iteration < 3; test_iteration++) @@ -9079,59 +9092,13 @@ TEST_F(ExecutionTest, BarycentricsTest) { }; std::shared_ptr test2 = RunShaderOpTestAfterParse(pDevice, m_support, "BarycentricsCheckOrder", ResourceCallbackFn, ShaderOpSet); - MappedData data; - D3D12_RESOURCE_DESC &D = test2->ShaderOp->GetResourceByName("RTarget")->Desc; - UINT width = (UINT)D.Width; - UINT height = D.Height; - UINT pixelSize = GetByteSizeForFormat(D.Format); - test2->Test->GetReadBackData("RTarget", &data); - //const uint8_t *pPixels = (uint8_t *)data.data(); - const float *pPixels = (float *)data.data(); - // Get the vertex of barycentric coordinate using VBuffer - MappedData triangleData; - test2->Test->GetReadBackData("VBuffer", &triangleData); - const float *pTriangleData = (float*)triangleData.data(); - - // get the size of the input data - unsigned triangleVertexSizeInFloat = 0; - for (auto element : test2->ShaderOp->InputElements) - triangleVertexSizeInFloat += GetByteSizeForFormat(element.Format) / 4; - XMFLOAT2 p0(pTriangleData[0], pTriangleData[1]); - XMFLOAT2 p1(pTriangleData[triangleVertexSizeInFloat], pTriangleData[triangleVertexSizeInFloat + 1]); - XMFLOAT2 p2(pTriangleData[triangleVertexSizeInFloat * 2], pTriangleData[triangleVertexSizeInFloat * 2 + 1]); - XMFLOAT3 barycentricWeights[4] = { - XMFLOAT3(0.3333f, 0.3333f, 0.3333f), - XMFLOAT3(0.5f, 0.25f, 0.25f), - XMFLOAT3(0.25f, 0.5f, 0.25f), - XMFLOAT3(0.25f, 0.25f, 0.50f) - }; - float tolerance = 0.001f; - for (unsigned i = 0; i < sizeof(barycentricWeights) / sizeof(XMFLOAT3); ++i) { - float w0 = barycentricWeights[i].x; - float w1 = barycentricWeights[i].y; - float w2 = barycentricWeights[i].z; - float x1 = w0 * p0.x + w1 * p1.x + w2 * p2.x; - float y1 = w0 * p0.y + w1 * p1.y + w2 * p2.y; - // map from x1 y1 to rtv pixels - int pixelX = (int)((x1 + 1) * (width - 1) / 2); - int pixelY = (int)((1 - y1) * (height - 1) / 2); - int offset = pixelSize * (pixelX + pixelY * width) / sizeof(pPixels[0]); - LogCommentFmt(L"location %u %u, value %f, %f, %f, %f", pixelX, pixelY, pPixels[offset], pPixels[offset + 1], pPixels[offset + 2], pPixels[offset + 3]); - - // If the ordering constraint is met, then this pixel's RGBA should be all 1.0's - // since the shader only returns float4<1.0,1.0,1.0,1.0> when this condition is met. - VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset] , 1.0, tolerance)); - VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 1], 1.0, tolerance)); - VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 2], 1.0, tolerance)); - VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 3], 1.0, tolerance)); - } - + TestBarycentricVariant(true, test2); } + - //SavePixelsToFile(pPixels, DXGI_FORMAT_R32G32B32A32_FLOAT, width, height, L"barycentric.bmp"); - } + static const char RawBufferTestShaderDeclarations[] = "// Note: COMPONENT_TYPE and COMPONENT_SIZE will be defined via compiler option -D\r\n" "typedef COMPONENT_TYPE scalar; \r\n" From ed349d17333adfcc80048c7ab2aaa13ed8b678c5 Mon Sep 17 00:00:00 2001 From: Joshua Batista Date: Tue, 13 Dec 2022 15:39:18 -0800 Subject: [PATCH 4/7] merge ordering and old bary shaders into one, increase tolerance --- tools/clang/test/HLSL/ShaderOpArith.xml | 37 ++-------- tools/clang/unittests/HLSL/ExecutionTest.cpp | 75 +++++++++++--------- 2 files changed, 48 insertions(+), 64 deletions(-) diff --git a/tools/clang/test/HLSL/ShaderOpArith.xml b/tools/clang/test/HLSL/ShaderOpArith.xml index 47ac7d2bac..5861394f2e 100644 --- a/tools/clang/test/HLSL/ShaderOpArith.xml +++ b/tools/clang/test/HLSL/ShaderOpArith.xml @@ -1493,11 +1493,8 @@ RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT) - - { { 0.0f, 1.0f , 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, - { { 1.0f, -1.0f , 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, - { { -1.0f, -1.0f , 0.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } } - + + @@ -1535,32 +1532,12 @@ float4 vColor2 = GetAttributeAtVertex(input.color, 2); return bary.x * vColor0 + bary.y * vColor1 + bary.z * vColor2; } - ]]> + ]]> - - - - - RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT) - - - - - - - - - - - - - - - - - - - + + + + & Data, st::ShaderOp* pShaderOp) { + std::vector bary = { 0.0f, 1.0f , 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, -1.0f , 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, + -1.0f, -1.0f , 0.0f, 0.0f, 0.0f, 1.0f, 1.0f }; + const int barysize = 21; + + UNREFERENCED_PARAMETER(pShaderOp); + VERIFY_IS_TRUE(0 == _stricmp(Name, "VBuffer")); + size_t size = sizeof(float) * barysize; + Data.resize(size); + float* vb = (float*)Data.data(); + for (size_t i = 0; i < barysize; ++i) { + float* p = &vb[i]; + float tempfloat = bary[(i + (7 * vertexShift)) % barysize]; + *p = tempfloat; + } + }; + +} + TEST_F(ExecutionTest, BarycentricsTest) { WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures); CComPtr pStream; @@ -9061,41 +9083,28 @@ TEST_F(ExecutionTest, BarycentricsTest) { DXASSERT_NOMSG(pStream != nullptr); std::shared_ptr ShaderOpSet = - std::make_shared(); + std::make_shared(); st::ParseShaderOpSetFromStream(pStream, ShaderOpSet.get()); + st::ShaderOp* pShaderOp = + ShaderOpSet->GetShaderOp("Barycentrics"); - - std::shared_ptr test = RunShaderOpTestAfterParse(pDevice, m_support, "Barycentrics", nullptr, ShaderOpSet); + int test_iteration = 0; + auto ResourceCallbackFnNoShift = MakeBarycentricsResourceInitCallbackFn(test_iteration); + + std::shared_ptr test = RunShaderOpTestAfterParse(pDevice, m_support, "Barycentrics", ResourceCallbackFnNoShift, ShaderOpSet); TestBarycentricVariant(false, test); // Now test that barycentric ordering is consistent LogCommentFmt(L"Now testing that the barycentric ordering constraint is upheld for each pixel..."); - for(int test_iteration = 0; test_iteration < 3; test_iteration++) + pShaderOp->VS = pShaderOp->GetString("VSordering"); + pShaderOp->PS = pShaderOp->GetString("PSordering"); + for(; test_iteration < 3; test_iteration++) { - auto ResourceCallbackFn = - [&](LPCSTR Name, std::vector &Data, st::ShaderOp *pShaderOp) { - std::vector bary = {0.0f, 1.0f , 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, - 1.0f, -1.0f , 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, - -1.0f, -1.0f , 0.0f, 0.0f, 0.0f, 1.0f, 1.0f}; - const int barysize = 21; - - UNREFERENCED_PARAMETER(pShaderOp); - VERIFY_IS_TRUE(0 == _stricmp(Name, "VBuffer")); - size_t size = sizeof(float)*barysize; - Data.resize(size); - float *vb = (float *)Data.data(); - for (size_t i = 0; i < barysize; ++i) { - float *p = &vb[i]; - float tempfloat = bary[(i+(7*test_iteration))%barysize]; - *p = tempfloat; - } - }; + auto ResourceCallbackFn = MakeBarycentricsResourceInitCallbackFn(test_iteration); - std::shared_ptr test2 = RunShaderOpTestAfterParse(pDevice, m_support, "BarycentricsCheckOrder", ResourceCallbackFn, ShaderOpSet); + std::shared_ptr test2 = RunShaderOpTestAfterParse(pDevice, m_support, "Barycentrics", ResourceCallbackFn, ShaderOpSet); TestBarycentricVariant(true, test2); - } - - + } } @@ -11515,8 +11524,6 @@ TEST_F(ExecutionTest, IsNormalTest) { st::ShaderOp *pShaderOp = ShaderOpSet->GetShaderOp("IsNormal"); vector fallbackRootValues = pShaderOp->RootValues; - - const int expectedResultsSize = 12; D3D_SHADER_MODEL sm = D3D_SHADER_MODEL_6_0; LogCommentFmt(L"\r\nVerifying isNormal in shader " From ed53264906d4a3821b62f67073abbee69789a559 Mon Sep 17 00:00:00 2001 From: Joshua Batista Date: Tue, 13 Dec 2022 16:34:57 -0800 Subject: [PATCH 5/7] remove redefinition in other test to make build pass --- tools/clang/unittests/HLSL/ExecutionTest.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/clang/unittests/HLSL/ExecutionTest.cpp b/tools/clang/unittests/HLSL/ExecutionTest.cpp index 44bb4a77d4..7d523c00a8 100644 --- a/tools/clang/unittests/HLSL/ExecutionTest.cpp +++ b/tools/clang/unittests/HLSL/ExecutionTest.cpp @@ -11552,9 +11552,6 @@ TEST_F(ExecutionTest, IsNormalTest) { L"model 6.%1u", ((UINT)sm & 0x0f)); - CComPtr pDevice; - VERIFY_IS_TRUE(CreateDevice(&pDevice, sm, false /* skipUnsupported */)); - size_t count = Validation_Input->size(); auto ShaderInitFn = MakeShaderReplacementCallback( From 872b3c35bd3e9927511cb9d2e31de063fee3755f Mon Sep 17 00:00:00 2001 From: Joshua Batista Date: Thu, 15 Dec 2022 12:06:31 -0800 Subject: [PATCH 6/7] prevent early truncation in division op --- tools/clang/unittests/HLSL/ExecutionTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/clang/unittests/HLSL/ExecutionTest.cpp b/tools/clang/unittests/HLSL/ExecutionTest.cpp index 7d523c00a8..b163ee1a37 100644 --- a/tools/clang/unittests/HLSL/ExecutionTest.cpp +++ b/tools/clang/unittests/HLSL/ExecutionTest.cpp @@ -9027,8 +9027,8 @@ void TestBarycentricVariant(bool checkOrdering, std::shared_ptr Date: Thu, 15 Dec 2022 14:00:26 -0800 Subject: [PATCH 7/7] remove comment, simplify shader --- tools/clang/test/HLSL/ShaderOpArith.xml | 13 +++---------- tools/clang/unittests/HLSL/ExecutionTest.cpp | 6 +++--- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/tools/clang/test/HLSL/ShaderOpArith.xml b/tools/clang/test/HLSL/ShaderOpArith.xml index 15e3155509..277e8cf8fa 100644 --- a/tools/clang/test/HLSL/ShaderOpArith.xml +++ b/tools/clang/test/HLSL/ShaderOpArith.xml @@ -1560,16 +1560,9 @@ // check to make sure that the pixel shader will see the barycentric weight associated // with the first vertex in the x component of the SV_Barycentric vector, and likewise for subsequent vertices - if (0 == GetAttributeAtVertex(input.svid, 0) && - 1 == GetAttributeAtVertex(input.svid, 1) && - 2 == GetAttributeAtVertex(input.svid, 2)) - { - // special value of all 1's in a float4 will be returned if the ordering is maintained for this pixel. - return float4(1.0, 1.0, 1.0, 1.0); - } - - // special value of all 0's in a float 4 will be returned otherwise - return float4(0.0, 0.0, 0.0, 0.0); + return float4(float3(GetAttributeAtVertex(input.svid, 0), + GetAttributeAtVertex(input.svid, 1), + GetAttributeAtVertex(input.svid, 2)) * 0.5, 1.0); } ]]> diff --git a/tools/clang/unittests/HLSL/ExecutionTest.cpp b/tools/clang/unittests/HLSL/ExecutionTest.cpp index b163ee1a37..0390db0304 100644 --- a/tools/clang/unittests/HLSL/ExecutionTest.cpp +++ b/tools/clang/unittests/HLSL/ExecutionTest.cpp @@ -9028,7 +9028,7 @@ void TestBarycentricVariant(bool checkOrdering, std::shared_ptr when this condition is met. - VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset] , 1.0, tolerance)); - VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 1], 1.0, tolerance)); + VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset] , 0.0, tolerance)); + VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 1], 0.5, tolerance)); VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 2], 1.0, tolerance)); VERIFY_IS_TRUE(CompareFloatEpsilon(pPixels[offset + 3], 1.0, tolerance)); }