X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=external%2Fvulkancts%2Fmodules%2Fvulkan%2Ftessellation%2FvktTessellationWindingTests.cpp;h=555832ce17ed24c41001037785c7f27257257671;hb=07ca20740c08c56131a568bc803c208084d9dd5e;hp=d61bc073dddc71ae4a8fa9acd02dc2d8f8c78040;hpb=bfe2a6433e76101bc421748438c841873212e9ab;p=platform%2Fupstream%2FVK-GL-CTS.git diff --git a/external/vulkancts/modules/vulkan/tessellation/vktTessellationWindingTests.cpp b/external/vulkancts/modules/vulkan/tessellation/vktTessellationWindingTests.cpp index d61bc07..555832c 100644 --- a/external/vulkancts/modules/vulkan/tessellation/vktTessellationWindingTests.cpp +++ b/external/vulkancts/modules/vulkan/tessellation/vktTessellationWindingTests.cpp @@ -25,9 +25,11 @@ #include "vktTessellationWindingTests.hpp" #include "vktTestCaseUtil.hpp" #include "vktTessellationUtil.hpp" +#include "vktTestGroupUtil.hpp" #include "tcuTestLog.hpp" #include "tcuRGBA.hpp" +#include "tcuMaybe.hpp" #include "vkDefs.hpp" #include "vkQueryUtil.hpp" @@ -48,10 +50,12 @@ using namespace vk; namespace { -std::string getCaseName (const TessPrimitiveType primitiveType, const Winding winding) +std::string getCaseName (const TessPrimitiveType primitiveType, const Winding winding, bool yFlip) { std::ostringstream str; str << getTessPrimitiveTypeShaderName(primitiveType) << "_" << getWindingShaderName(winding); + if (yFlip) + str << "_yflip"; return str.str(); } @@ -71,17 +75,22 @@ inline VkFrontFace mapFrontFace (const Winding winding) bool verifyResultImage (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image, const TessPrimitiveType primitiveType, + const VkTessellationDomainOriginKHR domainOrigin, const Winding winding, + bool yFlip, const Winding frontFaceWinding) { - const int totalNumPixels = image.getWidth()*image.getHeight(); - const int badPixelTolerance = (primitiveType == TESSPRIMITIVETYPE_TRIANGLES ? 5*de::max(image.getWidth(), image.getHeight()) : 0); + const bool expectVisiblePrimitive = ((frontFaceWinding == winding) == (domainOrigin == VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR)) != yFlip; - const tcu::Vec4 white = tcu::RGBA::white().toVec(); - const tcu::Vec4 red = tcu::RGBA::red().toVec(); + const int totalNumPixels = image.getWidth()*image.getHeight(); - int numWhitePixels = 0; - int numRedPixels = 0; + const tcu::Vec4 white = tcu::RGBA::white().toVec(); + const tcu::Vec4 red = tcu::RGBA::red().toVec(); + + int numWhitePixels = 0; + int numRedPixels = 0; + + // Count red and white pixels for (int y = 0; y < image.getHeight(); y++) for (int x = 0; x < image.getWidth(); x++) { @@ -93,24 +102,63 @@ bool verifyResultImage (tcu::TestLog& log, log << tcu::TestLog::Message << "Note: got " << numWhitePixels << " white and " << numRedPixels << " red pixels" << tcu::TestLog::EndMessage; - const int otherPixels = totalNumPixels - numWhitePixels - numRedPixels; - if (otherPixels > badPixelTolerance) { - log << tcu::TestLog::Message - << "Failure: Got " << otherPixels << " other than white or red pixels (maximum tolerance " << badPixelTolerance << ")" - << tcu::TestLog::EndMessage; - return false; + const int otherPixels = totalNumPixels - numWhitePixels - numRedPixels; + if (otherPixels > 0) + { + log << tcu::TestLog::Message + << "Failure: Got " << otherPixels << " other than white or red pixels" + << tcu::TestLog::EndMessage; + return false; + } } - if (frontFaceWinding == winding) + if (expectVisiblePrimitive) { if (primitiveType == TESSPRIMITIVETYPE_TRIANGLES) { + const int badPixelTolerance = (primitiveType == TESSPRIMITIVETYPE_TRIANGLES ? 5*de::max(image.getWidth(), image.getHeight()) : 0); + if (de::abs(numWhitePixels - totalNumPixels/2) > badPixelTolerance) { log << tcu::TestLog::Message << "Failure: wrong number of white pixels; expected approximately " << totalNumPixels/2 << tcu::TestLog::EndMessage; return false; } + + // Check number of filled pixels (from left) in top and bottom rows to + // determine if triangle is in right orientation. + { + const tcu::IVec2 expectedStart (0, 1); + const tcu::IVec2 expectedEnd (image.getWidth()-1, image.getWidth()); + const tcu::IVec2 expectedTop = yFlip ? expectedStart : expectedEnd; + const tcu::IVec2 expectedBottom = yFlip ? expectedEnd : expectedStart; + int numTopFilled = 0; + int numBottomFilled = 0; + + for (int x = 0; x < image.getWidth(); ++x) + { + if (image.getPixel(x, 0) == white) + numTopFilled += 1; + else + break; + } + + for (int x = 0; x < image.getWidth(); ++x) + { + if (image.getPixel(x, image.getHeight()-1) == white) + numBottomFilled += 1; + else + break; + } + + if (!de::inBounds(numTopFilled, expectedTop[0], expectedTop[1]) || + !de::inBounds(numBottomFilled, expectedBottom[0], expectedBottom[1])) + { + log << tcu::TestLog::Message << "Failure: triangle orientation is incorrect" << tcu::TestLog::EndMessage; + return false; + } + } + } else if (primitiveType == TESSPRIMITIVETYPE_QUADS) { @@ -135,27 +183,37 @@ bool verifyResultImage (tcu::TestLog& log, return true; } +typedef tcu::Maybe MaybeDomainOrigin; + class WindingTest : public TestCase { public: WindingTest (tcu::TestContext& testCtx, const TessPrimitiveType primitiveType, - const Winding winding); + const MaybeDomainOrigin& domainOrigin, + const Winding winding, + bool yFlip); void initPrograms (SourceCollections& programCollection) const; TestInstance* createInstance (Context& context) const; private: const TessPrimitiveType m_primitiveType; + const MaybeDomainOrigin m_domainOrigin; const Winding m_winding; + const bool m_yFlip; }; WindingTest::WindingTest (tcu::TestContext& testCtx, const TessPrimitiveType primitiveType, - const Winding winding) - : TestCase (testCtx, getCaseName(primitiveType, winding), "") + const MaybeDomainOrigin& domainOrigin, + const Winding winding, + bool yFlip) + : TestCase (testCtx, getCaseName(primitiveType, winding, yFlip), "") , m_primitiveType (primitiveType) + , m_domainOrigin (domainOrigin) , m_winding (winding) + , m_yFlip (yFlip) { } @@ -233,22 +291,43 @@ class WindingTestInstance : public TestInstance public: WindingTestInstance (Context& context, const TessPrimitiveType primitiveType, - const Winding winding); + const MaybeDomainOrigin& domainOrigin, + const Winding winding, + bool yFlip); tcu::TestStatus iterate (void); private: + void requireExtension (const char* name) const; + const TessPrimitiveType m_primitiveType; + const MaybeDomainOrigin m_domainOrigin; const Winding m_winding; + const bool m_yFlip; }; WindingTestInstance::WindingTestInstance (Context& context, const TessPrimitiveType primitiveType, - const Winding winding) + const MaybeDomainOrigin& domainOrigin, + const Winding winding, + bool yFlip) : TestInstance (context) , m_primitiveType (primitiveType) + , m_domainOrigin (domainOrigin) , m_winding (winding) + , m_yFlip (yFlip) { + if (m_yFlip) + requireExtension("VK_KHR_maintenance1"); + + if ((bool)m_domainOrigin) + requireExtension("VK_KHR_maintenance2"); +} + +void WindingTestInstance::requireExtension (const char* name) const +{ + if (!de::contains(m_context.getDeviceExtensions().begin(), m_context.getDeviceExtensions().end(), name)) + TCU_THROW(NotSupportedError, (std::string(name) + " is not supported").c_str()); } tcu::TestStatus WindingTestInstance::iterate (void) @@ -285,24 +364,24 @@ tcu::TestStatus WindingTestInstance::iterate (void) // Front face is static state, so we have to create two pipelines. const Unique pipelineCounterClockwise(GraphicsPipelineBuilder() - .setRenderSize (renderSize) - .setCullModeFlags(cullMode) - .setFrontFace (VK_FRONT_FACE_COUNTER_CLOCKWISE) - .setShader (vk, device, VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("vert"), DE_NULL) - .setShader (vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, m_context.getBinaryCollection().get("tesc"), DE_NULL) - .setShader (vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, m_context.getBinaryCollection().get("tese"), DE_NULL) - .setShader (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("frag"), DE_NULL) - .build (vk, device, *pipelineLayout, *renderPass)); + .setCullModeFlags (cullMode) + .setFrontFace (VK_FRONT_FACE_COUNTER_CLOCKWISE) + .setShader (vk, device, VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("vert"), DE_NULL) + .setShader (vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, m_context.getBinaryCollection().get("tesc"), DE_NULL) + .setShader (vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, m_context.getBinaryCollection().get("tese"), DE_NULL) + .setShader (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("frag"), DE_NULL) + .setTessellationDomainOrigin (m_domainOrigin) + .build (vk, device, *pipelineLayout, *renderPass)); const Unique pipelineClockwise(GraphicsPipelineBuilder() - .setRenderSize (renderSize) - .setCullModeFlags(cullMode) - .setFrontFace (VK_FRONT_FACE_CLOCKWISE) - .setShader (vk, device, VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("vert"), DE_NULL) - .setShader (vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, m_context.getBinaryCollection().get("tesc"), DE_NULL) - .setShader (vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, m_context.getBinaryCollection().get("tese"), DE_NULL) - .setShader (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("frag"), DE_NULL) - .build (vk, device, *pipelineLayout, *renderPass)); + .setCullModeFlags (cullMode) + .setFrontFace (VK_FRONT_FACE_CLOCKWISE) + .setShader (vk, device, VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("vert"), DE_NULL) + .setShader (vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, m_context.getBinaryCollection().get("tesc"), DE_NULL) + .setShader (vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, m_context.getBinaryCollection().get("tese"), DE_NULL) + .setShader (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("frag"), DE_NULL) + .setTessellationDomainOrigin (m_domainOrigin) + .build (vk, device, *pipelineLayout, *renderPass)); const struct // not static { @@ -322,7 +401,7 @@ tcu::TestStatus WindingTestInstance::iterate (void) // Draw commands const Unique cmdPool (makeCommandPool (vk, device, queueFamilyIndex)); - const Unique cmdBuffer(makeCommandBuffer(vk, device, *cmdPool)); + const Unique cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(testCases); ++caseNdx) { @@ -359,6 +438,24 @@ tcu::TestStatus WindingTestInstance::iterate (void) beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor); } + const VkViewport viewport = + { + 0.0f, // float x; + m_yFlip ? static_cast(renderSize.y()) : 0.0f, // float y; + static_cast(renderSize.x()), // float width; + static_cast(m_yFlip ? -renderSize.y() : renderSize.y()), // float height; + 0.0f, // float minDepth; + 1.0f, // float maxDepth; + }; + vk.cmdSetViewport(*cmdBuffer, 0, 1, &viewport); + + const VkRect2D scissor = + { + makeOffset2D(0, 0), + makeExtent2D(renderSize.x(), renderSize.y()), + }; + vk.cmdSetScissor(*cmdBuffer, 0, 1, &scissor); + vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, testCases[caseNdx].pipeline); // Process a single abstract vertex. @@ -376,7 +473,7 @@ tcu::TestStatus WindingTestInstance::iterate (void) 0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentPreCopyBarrier); } { - const VkBufferImageCopy copyRegion = makeBufferImageCopy(makeExtent3D(renderSize.x(), renderSize.y(), 0), makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u)); + const VkBufferImageCopy copyRegion = makeBufferImageCopy(makeExtent3D(renderSize.x(), renderSize.y(), 1), makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u)); vk.cmdCopyImageToBuffer(*cmdBuffer, *colorAttachmentImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ©Region); } { @@ -399,7 +496,13 @@ tcu::TestStatus WindingTestInstance::iterate (void) log << tcu::TestLog::Image("color0", "Rendered image", imagePixelAccess); // Verify case result - success = success && verifyResultImage(log, imagePixelAccess, m_primitiveType, m_winding, frontFaceWinding); + success = verifyResultImage(log, + imagePixelAccess, + m_primitiveType, + !m_domainOrigin ? VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR : *m_domainOrigin, + m_winding, + m_yFlip, + frontFaceWinding) && success; } } // for windingNdx @@ -410,16 +513,11 @@ TestInstance* WindingTest::createInstance (Context& context) const { requireFeatures(context.getInstanceInterface(), context.getPhysicalDevice(), FEATURE_TESSELLATION_SHADER); - return new WindingTestInstance(context, m_primitiveType, m_winding); + return new WindingTestInstance(context, m_primitiveType, m_domainOrigin, m_winding, m_yFlip); } -} // anonymous - -//! These tests correspond to dEQP-GLES31.functional.tessellation.winding.* -tcu::TestCaseGroup* createWindingTests (tcu::TestContext& testCtx) +void populateWindingGroup (tcu::TestCaseGroup* group, tcu::Maybe domainOrigin) { - de::MovePtr group (new tcu::TestCaseGroup(testCtx, "winding", "Test the cw and ccw input layout qualifiers")); - static const TessPrimitiveType primitivesNoIsolines[] = { TESSPRIMITIVETYPE_TRIANGLES, @@ -428,7 +526,22 @@ tcu::TestCaseGroup* createWindingTests (tcu::TestContext& testCtx) for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitivesNoIsolines); ++primitiveTypeNdx) for (int windingNdx = 0; windingNdx < WINDING_LAST; ++windingNdx) - group->addChild(new WindingTest(testCtx, primitivesNoIsolines[primitiveTypeNdx], (Winding)windingNdx)); + { + group->addChild(new WindingTest(group->getTestContext(), primitivesNoIsolines[primitiveTypeNdx], domainOrigin, (Winding)windingNdx, false)); + group->addChild(new WindingTest(group->getTestContext(), primitivesNoIsolines[primitiveTypeNdx], domainOrigin, (Winding)windingNdx, true)); + } +} + +} // anonymous + +//! These tests correspond to dEQP-GLES31.functional.tessellation.winding.* +tcu::TestCaseGroup* createWindingTests (tcu::TestContext& testCtx) +{ + de::MovePtr group (new tcu::TestCaseGroup(testCtx, "winding", "Test the cw and ccw input layout qualifiers")); + + addTestGroup(group.get(), "default_domain", "No tessellation domain specified", populateWindingGroup, tcu::nothing()); + addTestGroup(group.get(), "lower_left_domain", "Lower left tessellation domain", populateWindingGroup, tcu::just(VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT_KHR)); + addTestGroup(group.get(), "upper_left_domain", "Upper left tessellation domain", populateWindingGroup, tcu::just(VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR)); return group.release(); }