From 80cd47a1938c6f094a4aab249ba6d09eed3ebf3f Mon Sep 17 00:00:00 2001 From: Dae Kim Date: Tue, 15 Dec 2015 15:15:29 +0000 Subject: [PATCH] Added pipeline input assembly tests. --- .../modules/vulkan/pipeline/CMakeLists.txt | 3 + .../pipeline/vktPipelineInputAssemblyTests.cpp | 1640 ++++++++++++++++++++ .../pipeline/vktPipelineInputAssemblyTests.hpp | 50 + .../modules/vulkan/pipeline/vktPipelineTests.cpp | 2 + 4 files changed, 1695 insertions(+) create mode 100644 external/vulkancts/modules/vulkan/pipeline/vktPipelineInputAssemblyTests.cpp create mode 100644 external/vulkancts/modules/vulkan/pipeline/vktPipelineInputAssemblyTests.hpp diff --git a/external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt b/external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt index d256c4a..f87377e 100644 --- a/external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt +++ b/external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt @@ -18,6 +18,8 @@ set(DEQP_VK_PIPELINE_SRCS vktPipelineImageUtil.hpp vktPipelineImageViewTests.cpp vktPipelineImageViewTests.hpp + vktPipelineInputAssemblyTests.cpp + vktPipelineInputAssemblyTests.hpp vktPipelineReferenceRenderer.cpp vktPipelineReferenceRenderer.hpp vktPipelineSamplerTests.cpp @@ -26,6 +28,7 @@ set(DEQP_VK_PIPELINE_SRCS vktPipelineStencilTests.hpp vktPipelineTests.cpp vktPipelineTests.hpp + vktPipelineUniqueRandomIterator.hpp vktPipelineVertexUtil.cpp vktPipelineVertexUtil.hpp ) diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineInputAssemblyTests.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineInputAssemblyTests.cpp new file mode 100644 index 0000000..a27a2f3 --- /dev/null +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineInputAssemblyTests.cpp @@ -0,0 +1,1640 @@ +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2015 The Khronos Group Inc. + * Copyright (c) 2015 Imagination Technologies Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are furnished to do so, subject to + * the following conditions: + * + * The above copyright notice(s) and this permission notice shall be included + * in all copies or substantial portions of the Materials. + * + * The Materials are Confidential Information as defined by the + * Khronos Membership Agreement until designated non-confidential by Khronos, + * at which point this condition clause shall be removed. + * + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + * + *//*! + * \file + * \brief Input Assembly Tests + *//*--------------------------------------------------------------------*/ + +#include "vktPipelineInputAssemblyTests.hpp" +#include "vktPipelineClearUtil.hpp" +#include "vktPipelineImageUtil.hpp" +#include "vktPipelineVertexUtil.hpp" +#include "vktPipelineReferenceRenderer.hpp" +#include "vktTestCase.hpp" +#include "vkImageUtil.hpp" +#include "vkMemUtil.hpp" +#include "vkPrograms.hpp" +#include "vkQueryUtil.hpp" +#include "vkRef.hpp" +#include "vkRefUtil.hpp" +#include "tcuImageCompare.hpp" +#include "deMath.h" +#include "deMemory.h" +#include "deRandom.hpp" +#include "deStringUtil.hpp" +#include "deUniquePtr.hpp" + +#include +#include +#include + +namespace vkt +{ +namespace pipeline +{ + +using namespace vk; + +namespace +{ + +class InputAssemblyTest : public vkt::TestCase +{ +public: + const static VkPrimitiveTopology s_primitiveTopologies[]; + const static deUint32 s_restartIndex32; + const static deUint16 s_restartIndex16; + + InputAssemblyTest (tcu::TestContext& testContext, + const std::string& name, + const std::string& description, + VkPrimitiveTopology primitiveTopology, + int primitiveCount, + bool testPrimitiveRestart, + VkIndexType indexType); + virtual ~InputAssemblyTest (void) {} + virtual void initPrograms (SourceCollections& sourceCollections) const; + virtual TestInstance* createInstance (Context& context) const; + static bool isRestartIndex (VkIndexType indexType, deUint32 indexValue); + static deUint32 getRestartIndex (VkIndexType indexType); + +protected: + virtual void createBufferData (VkPrimitiveTopology topology, + int primitiveCount, + VkIndexType indexType, + std::vector& indexData, + std::vector& vertexData) const = 0; + +private: + VkPrimitiveTopology m_primitiveTopology; + const int m_primitiveCount; + bool m_testPrimitiveRestart; + VkIndexType m_indexType; +}; + +class PrimitiveTopologyTest : public InputAssemblyTest +{ +public: + PrimitiveTopologyTest (tcu::TestContext& testContext, + const std::string& name, + const std::string& description, + VkPrimitiveTopology primitiveTopology); + virtual ~PrimitiveTopologyTest (void) {} + +protected: + virtual void createBufferData (VkPrimitiveTopology topology, + int primitiveCount, + VkIndexType indexType, + std::vector& indexData, + std::vector& vertexData) const; + +private: +}; + +class PrimitiveRestartTest : public InputAssemblyTest +{ +public: + const static VkPrimitiveTopology s_primitiveTopologies[]; + + PrimitiveRestartTest (tcu::TestContext& testContext, + const std::string& name, + const std::string& description, + VkPrimitiveTopology primitiveTopology, + VkIndexType indexType); + virtual ~PrimitiveRestartTest (void) {} + +protected: + virtual void createBufferData (VkPrimitiveTopology topology, + int primitiveCount, + VkIndexType indexType, + std::vector& indexData, + std::vector& vertexData) const; + +private: + bool isRestartPrimitive (int primitiveIndex) const; + + std::vector m_restartPrimitives; +}; + +class InputAssemblyInstance : public vkt::TestInstance +{ +public: + InputAssemblyInstance (Context& context, + VkPrimitiveTopology primitiveTopology, + bool testPrimitiveRestart, + VkIndexType indexType, + const std::vector& indexBufferData, + const std::vector& vertexBufferData); + virtual ~InputAssemblyInstance (void); + virtual tcu::TestStatus iterate (void); + +private: + tcu::TestStatus verifyImage (void); + void uploadIndexBufferData16 (deUint16* destPtr, const std::vector& indexBufferData); + + VkPrimitiveTopology m_primitiveTopology; + bool m_primitiveRestartEnable; + VkIndexType m_indexType; + + Move m_vertexBuffer; + std::vector m_vertices; + de::MovePtr m_vertexBufferAlloc; + + Move m_indexBuffer; + std::vector m_indices; + de::MovePtr m_indexBufferAlloc; + + const tcu::IVec2 m_renderSize; + + const VkFormat m_colorFormat; + VkImageCreateInfo m_colorImageCreateInfo; + Move m_colorImage; + de::MovePtr m_colorImageAlloc; + Move m_colorAttachmentView; + Move m_renderPass; + Move m_framebuffer; + + Move m_vertexShaderModule; + Move m_fragmentShaderModule; + + Move m_pipelineLayout; + Move m_graphicsPipeline; + + Move m_cmdPool; + Move m_cmdBuffer; + + Move m_fence; +}; + + +// InputAssemblyTest + +const VkPrimitiveTopology InputAssemblyTest::s_primitiveTopologies[] = +{ + VK_PRIMITIVE_TOPOLOGY_POINT_LIST, + VK_PRIMITIVE_TOPOLOGY_LINE_LIST, + VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, + VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, + VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY +}; + +const deUint32 InputAssemblyTest::s_restartIndex32 = ~((deUint32)0u); +const deUint16 InputAssemblyTest::s_restartIndex16 = ~((deUint16)0u); + +InputAssemblyTest::InputAssemblyTest (tcu::TestContext& testContext, + const std::string& name, + const std::string& description, + VkPrimitiveTopology primitiveTopology, + int primitiveCount, + bool testPrimitiveRestart, + VkIndexType indexType) + + : vkt::TestCase (testContext, name, description) + , m_primitiveTopology (primitiveTopology) + , m_primitiveCount (primitiveCount) + , m_testPrimitiveRestart (testPrimitiveRestart) + , m_indexType (indexType) +{ +} + +TestInstance* InputAssemblyTest::createInstance (Context& context) const +{ + std::vector indexBufferData; + std::vector vertexBufferData; + + createBufferData(m_primitiveTopology, m_primitiveCount, m_indexType, indexBufferData, vertexBufferData); + + return new InputAssemblyInstance(context, m_primitiveTopology, m_testPrimitiveRestart, m_indexType, indexBufferData, vertexBufferData); +} + +void InputAssemblyTest::initPrograms (SourceCollections& sourceCollections) const +{ + std::ostringstream vertexSource; + + vertexSource << + "#version 310 es\n" + "layout(location = 0) in vec4 position;\n" + "layout(location = 1) in vec4 color;\n" + "layout(location = 0) out highp vec4 vtxColor;\n" + "void main (void)\n" + "{\n" + " gl_Position = position;\n" + << (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST ? " gl_PointSize = 3.0;\n" + : "" ) + << " vtxColor = color;\n" + "}\n"; + + sourceCollections.glslSources.add("color_vert") << glu::VertexSource(vertexSource.str()); + + sourceCollections.glslSources.add("color_frag") << glu::FragmentSource( + "#version 310 es\n" + "layout(location = 0) in highp vec4 vtxColor;\n" + "layout(location = 0) out highp vec4 fragColor;\n" + "void main (void)\n" + "{\n" + " fragColor = vtxColor;\n" + "}\n"); +} + +bool InputAssemblyTest::isRestartIndex (VkIndexType indexType, deUint32 indexValue) +{ + if (indexType == VK_INDEX_TYPE_UINT32) + return indexValue == s_restartIndex32; + else + return indexValue == s_restartIndex16; +} + +deUint32 InputAssemblyTest::getRestartIndex (VkIndexType indexType) +{ + if (indexType == VK_INDEX_TYPE_UINT16) + return InputAssemblyTest::s_restartIndex16; + else + return InputAssemblyTest::s_restartIndex32; +} + + +// PrimitiveTopologyTest + +PrimitiveTopologyTest::PrimitiveTopologyTest (tcu::TestContext& testContext, + const std::string& name, + const std::string& description, + VkPrimitiveTopology primitiveTopology) + : InputAssemblyTest (testContext, name, description, primitiveTopology, 10, false, VK_INDEX_TYPE_UINT32) +{ +} + +void PrimitiveTopologyTest::createBufferData (VkPrimitiveTopology topology, int primitiveCount, VkIndexType indexType, std::vector& indexData, std::vector& vertexData) const +{ + DE_ASSERT(primitiveCount > 0); + DE_UNREF(indexType); + + const tcu::Vec4 red (1.0f, 0.0f, 0.0f, 1.0f); + const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f); + const float border = 0.2f; + const float originX = -1.0f + border; + const float originY = -1.0f + border; + const Vertex4RGBA defaultVertex = { tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), green }; + float primitiveSizeY = (2.0f - 2.0f * border); + float primitiveSizeX; + std::vector indices; + std::vector vertices; + + + // Calculate primitive size + switch (topology) + { + case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: + primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2 + primitiveCount % 2 - 1); + break; + + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: + primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount - 1); + break; + + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: + primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2); + break; + + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: + primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount + primitiveCount / 2 + primitiveCount % 2 - 1); + break; + + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: + primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2 + primitiveCount % 2); + break; + + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: + primitiveSizeX = 1.0f - border; + primitiveSizeY = 1.0f - border; + break; + + default: + DE_ASSERT(false); + } + + switch (topology) + { + case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: + for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) + { + const Vertex4RGBA vertex = + { + tcu::Vec4(originX + float(primitiveNdx / 2) * primitiveSizeX, originY + float(primitiveNdx % 2) * primitiveSizeY, 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back(primitiveNdx); + } + break; + + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: + for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) + { + for (int vertexNdx = 0; vertexNdx < 2; vertexNdx++) + { + const Vertex4RGBA vertex = + { + tcu::Vec4(originX + float((primitiveNdx * 2 + vertexNdx) / 2) * primitiveSizeX, originY + float(vertexNdx % 2) * primitiveSizeY, 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back((primitiveNdx * 2 + vertexNdx)); + } + } + break; + + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: + for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) + { + if (primitiveNdx == 0) + { + Vertex4RGBA vertex = + { + tcu::Vec4(originX, originY, 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back(0); + + vertex.position = tcu::Vec4(originX, originY + primitiveSizeY, 0.0f, 1.0f); + vertices.push_back(vertex); + indices.push_back(1); + } + else + { + const Vertex4RGBA vertex = + { + tcu::Vec4(originX + float((primitiveNdx + 1) / 2) * primitiveSizeX, originY + float((primitiveNdx + 1) % 2) * primitiveSizeY, 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back(primitiveNdx + 1); + } + } + break; + + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: + for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) + { + for (int vertexNdx = 0; vertexNdx < 3; vertexNdx++) + { + const Vertex4RGBA vertex = + { + tcu::Vec4(originX + float((primitiveNdx * 3 + vertexNdx) / 2) * primitiveSizeX, originY + float((primitiveNdx * 3 + vertexNdx)% 2) * primitiveSizeY, 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back(primitiveNdx * 3 + vertexNdx); + } + } + break; + + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: + for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) + { + if (primitiveNdx == 0) + { + for (int vertexNdx = 0; vertexNdx < 3; vertexNdx++) + { + const Vertex4RGBA vertex = + { + tcu::Vec4(originX + float(vertexNdx / 2) * primitiveSizeX, originY + float(vertexNdx % 2) * primitiveSizeY, 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back(vertexNdx); + } + } + else + { + const Vertex4RGBA vertex = + { + tcu::Vec4(originX + float((primitiveNdx + 2) / 2) * primitiveSizeX, originY + float((primitiveNdx + 2) % 2) * primitiveSizeY, 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back(primitiveNdx + 2); + } + } + break; + + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: + { + const float stepAngle = de::min(DE_PI * 0.5f, (2 * DE_PI) / float(primitiveCount)); + + for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) + { + if (primitiveNdx == 0) + { + Vertex4RGBA vertex = + { + tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back(0); + + vertex.position = tcu::Vec4(primitiveSizeX, 0.0f, 0.0f, 1.0f); + vertices.push_back(vertex); + indices.push_back(1); + + vertex.position = tcu::Vec4(primitiveSizeX * deFloatCos(stepAngle), primitiveSizeY * deFloatSin(stepAngle), 0.0f, 1.0f); + vertices.push_back(vertex); + indices.push_back(2); + } + else + { + const Vertex4RGBA vertex = + { + tcu::Vec4(primitiveSizeX * deFloatCos(stepAngle * float(primitiveNdx + 1)), primitiveSizeY * deFloatSin(stepAngle * float(primitiveNdx + 1)), 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back(primitiveNdx + 2); + } + } + break; + } + + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: + vertices.push_back(defaultVertex); + + for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) + { + indices.push_back(0); + + for (int vertexNdx = 0; vertexNdx < 2; vertexNdx++) + { + const Vertex4RGBA vertex = + { + tcu::Vec4(originX + float((primitiveNdx * 2 + vertexNdx) / 2) * primitiveSizeX, originY + float(vertexNdx % 2) * primitiveSizeY, 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back(primitiveNdx * 2 + vertexNdx + 1); + } + + indices.push_back(0); + } + break; + + + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: + vertices.push_back(defaultVertex); + indices.push_back(0); + + for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) + { + if (primitiveNdx == 0) + { + Vertex4RGBA vertex = + { + tcu::Vec4(originX, originY, 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back(1); + + vertex.position = tcu::Vec4(originX, originY + primitiveSizeY, 0.0f, 1.0f); + vertices.push_back(vertex); + indices.push_back(2); + } + else + { + const Vertex4RGBA vertex = + { + tcu::Vec4(originX + float((primitiveNdx + 1) / 2) * primitiveSizeX, originY + float((primitiveNdx + 1) % 2) * primitiveSizeY, 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back(primitiveNdx + 2); + } + } + + indices.push_back(0); + break; + + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: + vertices.push_back(defaultVertex); + + for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) + { + for (int vertexNdx = 0; vertexNdx < 3; vertexNdx++) + { + const Vertex4RGBA vertex = + { + tcu::Vec4(originX + float((primitiveNdx * 3 + vertexNdx) / 2) * primitiveSizeX, originY + float((primitiveNdx * 3 + vertexNdx)% 2) * primitiveSizeY, 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back(primitiveNdx * 3 + vertexNdx + 1); + indices.push_back(0); + } + } + break; + + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: + vertices.push_back(defaultVertex); + + for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) + { + if (primitiveNdx == 0) + { + for (int vertexNdx = 0; vertexNdx < 3; vertexNdx++) + { + const Vertex4RGBA vertex = + { + tcu::Vec4(originX + float(vertexNdx / 2) * primitiveSizeX, originY + float(vertexNdx % 2) * primitiveSizeY, 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back(vertexNdx + 1); + indices.push_back(0); + } + } + else + { + const Vertex4RGBA vertex = + { + tcu::Vec4(originX + float((primitiveNdx + 2) / 2) * primitiveSizeX, originY + float((primitiveNdx + 2) % 2) * primitiveSizeY, 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back(primitiveNdx + 2 + 1); + indices.push_back(0); + } + } + break; + + default: + DE_ASSERT(false); + break; + } + + vertexData = vertices; + indexData = indices; +} + + +// PrimitiveRestartTest + +PrimitiveRestartTest::PrimitiveRestartTest (tcu::TestContext& testContext, + const std::string& name, + const std::string& description, + VkPrimitiveTopology primitiveTopology, + VkIndexType indexType) + + : InputAssemblyTest (testContext, name, description, primitiveTopology, 10, true, indexType) +{ + DE_ASSERT(primitiveTopology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP || + primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP || + primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN || + primitiveTopology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY || + primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY); + + deUint32 restartPrimitives[] = { 1, 5 }; + + m_restartPrimitives = std::vector(restartPrimitives, restartPrimitives + sizeof(restartPrimitives) / sizeof(deUint32)); +} + +void PrimitiveRestartTest::createBufferData (VkPrimitiveTopology topology, int primitiveCount, VkIndexType indexType, std::vector& indexData, std::vector& vertexData) const +{ + DE_ASSERT(primitiveCount > 0); + DE_UNREF(indexType); + + const tcu::Vec4 red (1.0f, 0.0f, 0.0f, 1.0f); + const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f); + const float border = 0.2f; + const float originX = -1.0f + border; + const float originY = -1.0f + border; + const Vertex4RGBA defaultVertex = { tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), green }; + float primitiveSizeY = (2.0f - 2.0f * border); + float primitiveSizeX; + bool primitiveStart = true; + std::vector indices; + std::vector vertices; + + + // Calculate primitive size + switch (topology) + { + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: + primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2); + break; + + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: + primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2 + primitiveCount % 2); + break; + + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: + primitiveSizeX = 1.0f - border; + primitiveSizeY = 1.0f - border; + break; + + default: + DE_ASSERT(false); + } + + switch (topology) + { + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: + for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) + { + if (isRestartPrimitive(primitiveNdx)) + { + indices.push_back(InputAssemblyTest::getRestartIndex(indexType)); + primitiveStart = true; + } + else + { + if (primitiveStart) + { + const Vertex4RGBA vertex = + { + tcu::Vec4(originX + float(primitiveNdx / 2) * primitiveSizeX, originY + float(primitiveNdx % 2) * primitiveSizeY, 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back((deUint32)vertices.size() - 1); + + primitiveStart = false; + } + + const Vertex4RGBA vertex = + { + tcu::Vec4(originX + float((primitiveNdx + 1) / 2) * primitiveSizeX, originY + float((primitiveNdx + 1) % 2) * primitiveSizeY, 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back((deUint32)vertices.size() - 1); + } + } + break; + + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: + { + for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) + { + if (isRestartPrimitive(primitiveNdx)) + { + indices.push_back(InputAssemblyTest::getRestartIndex(indexType)); + primitiveStart = true; + } + else + { + if (primitiveStart) + { + for (int vertexNdx = 0; vertexNdx < 2; vertexNdx++) + { + const Vertex4RGBA vertex = + { + tcu::Vec4(originX + float((primitiveNdx + vertexNdx) / 2) * primitiveSizeX, originY + float((primitiveNdx + vertexNdx) % 2) * primitiveSizeY, 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back((deUint32)vertices.size() - 1); + } + + primitiveStart = false; + } + const Vertex4RGBA vertex = + { + tcu::Vec4(originX + float((primitiveNdx + 2) / 2) * primitiveSizeX, originY + float((primitiveNdx + 2) % 2) * primitiveSizeY, 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back((deUint32)vertices.size() - 1); + } + } + break; + } + + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: + { + const float stepAngle = de::min(DE_PI * 0.5f, (2 * DE_PI) / float(primitiveCount)); + + for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) + { + if (isRestartPrimitive(primitiveNdx)) + { + indices.push_back(InputAssemblyTest::getRestartIndex(indexType)); + primitiveStart = true; + } + else + { + if (primitiveStart) + { + Vertex4RGBA vertex = + { + tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back((deUint32)vertices.size() - 1); + + vertex.position = tcu::Vec4(primitiveSizeX * deFloatCos(stepAngle * float(primitiveNdx)), primitiveSizeY * deFloatSin(stepAngle * float(primitiveNdx)), 0.0f, 1.0f), + vertices.push_back(vertex); + indices.push_back((deUint32)vertices.size() - 1); + + primitiveStart = false; + } + + const Vertex4RGBA vertex = + { + tcu::Vec4(primitiveSizeX * deFloatCos(stepAngle * float(primitiveNdx + 1)), primitiveSizeY * deFloatSin(stepAngle * float(primitiveNdx + 1)), 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back((deUint32)vertices.size() - 1); + } + } + break; + } + + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: + vertices.push_back(defaultVertex); + + for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) + { + if (isRestartPrimitive(primitiveNdx)) + { + indices.push_back(0); + indices.push_back(InputAssemblyTest::getRestartIndex(indexType)); + primitiveStart = true; + } + else + { + if (primitiveStart) + { + indices.push_back(0); + + const Vertex4RGBA vertex = + { + tcu::Vec4(originX + float(primitiveNdx / 2) * primitiveSizeX, originY + float(primitiveNdx % 2) * primitiveSizeY, 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back((deUint32)vertices.size() - 1); + + primitiveStart = false; + } + + const Vertex4RGBA vertex = + { + tcu::Vec4(originX + float((primitiveNdx + 1) / 2) * primitiveSizeX, originY + float((primitiveNdx + 1) % 2) * primitiveSizeY, 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back((deUint32)vertices.size() - 1); + } + } + + indices.push_back(0); + break; + + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: + vertices.push_back(defaultVertex); + + for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) + { + if (isRestartPrimitive(primitiveNdx)) + { + indices.push_back(InputAssemblyTest::getRestartIndex(indexType)); + primitiveStart = true; + } + else + { + if (primitiveStart) + { + for (int vertexNdx = 0; vertexNdx < 2; vertexNdx++) + { + const Vertex4RGBA vertex = + { + tcu::Vec4(originX + float((primitiveNdx + vertexNdx) / 2) * primitiveSizeX, originY + float((primitiveNdx + vertexNdx) % 2) * primitiveSizeY, 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back((deUint32)vertices.size() - 1); + indices.push_back(0); + } + + primitiveStart = false; + } + + const Vertex4RGBA vertex = + { + tcu::Vec4(originX + float((primitiveNdx + 2) / 2) * primitiveSizeX, originY + float((primitiveNdx + 2) % 2) * primitiveSizeY, 0.0f, 1.0f), + red + }; + + vertices.push_back(vertex); + indices.push_back((deUint32)vertices.size() - 1); + indices.push_back(0); + } + } + break; + + default: + DE_ASSERT(false); + break; + } + + vertexData = vertices; + indexData = indices; +} + +bool PrimitiveRestartTest::isRestartPrimitive (int primitiveIndex) const +{ + return std::find(m_restartPrimitives.begin(), m_restartPrimitives.end(), primitiveIndex) != m_restartPrimitives.end(); +} + + +// InputAssemblyInstance + +InputAssemblyInstance::InputAssemblyInstance (Context& context, + VkPrimitiveTopology primitiveTopology, + bool testPrimitiveRestart, + VkIndexType indexType, + const std::vector& indexBufferData, + const std::vector& vertexBufferData) + + : vkt::TestInstance (context) + , m_primitiveTopology (primitiveTopology) + , m_primitiveRestartEnable (testPrimitiveRestart) + , m_indexType (indexType) + , m_vertices (vertexBufferData) + , m_indices (indexBufferData) + , m_renderSize ((primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN) ? tcu::IVec2(32, 32) : tcu::IVec2(64, 16)) + , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM) +{ + const DeviceInterface& vk = context.getDeviceInterface(); + const VkDevice vkDevice = context.getDevice(); + const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); + SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())); + const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; + + // Create color image + { + const VkImageCreateInfo colorImageParams = + { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkImageCreateFlags flags; + VK_IMAGE_TYPE_2D, // VkImageType imageType; + m_colorFormat, // VkFormat format; + { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent; + 1u, // deUint32 mipLevels; + 1u, // deUint32 arrayLayers; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 1u, // deUint32 queueFamilyIndexCount; + &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; + VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout; + }; + + m_colorImageCreateInfo = colorImageParams; + m_colorImage = createImage(vk, vkDevice, &m_colorImageCreateInfo); + + // Allocate and bind color image memory + m_colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any); + VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset())); + } + + // Create color attachment view + { + const VkImageViewCreateInfo colorAttachmentViewParams = + { + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkImageViewCreateFlags flags; + *m_colorImage, // VkImage image; + VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; + m_colorFormat, // VkFormat format; + componentMappingRGBA, // VkComponentMapping components; + { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange; + }; + + m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams); + } + + // Create render pass + { + const VkAttachmentDescription colorAttachmentDescription = + { + 0u, // VkAttachmentDescriptionFlags flags; + m_colorFormat, // VkFormat format; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; + VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; + VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; + VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; + }; + + const VkAttachmentReference colorAttachmentReference = + { + 0u, // deUint32 attachment; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; + }; + + const VkSubpassDescription subpassDescription = + { + 0u, // VkSubpassDescriptionFlags flags; + VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; + 0u, // deUint32 inputAttachmentCount; + DE_NULL, // const VkAttachmentReference* pInputAttachments; + 1u, // deUint32 colorAttachmentCount; + &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments; + DE_NULL, // const VkAttachmentReference* pResolveAttachments; + DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; + 0u, // deUint32 preserveAttachmentCount; + DE_NULL // const VkAttachmentReference* pPreserveAttachments; + }; + + const VkRenderPassCreateInfo renderPassParams = + { + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkRenderPassCreateFlags flags; + 1u, // deUint32 attachmentCount; + &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments; + 1u, // deUint32 subpassCount; + &subpassDescription, // const VkSubpassDescription* pSubpasses; + 0u, // deUint32 dependencyCount; + DE_NULL // const VkSubpassDependency* pDependencies; + }; + + m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams); + } + + // Create framebuffer + { + const VkFramebufferCreateInfo framebufferParams = + { + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkFramebufferCreateFlags flags; + *m_renderPass, // VkRenderPass renderPass; + 1u, // deUint32 attachmentCount; + &m_colorAttachmentView.get(), // const VkImageView* pAttachments; + (deUint32)m_renderSize.x(), // deUint32 width; + (deUint32)m_renderSize.y(), // deUint32 height; + 1u // deUint32 layers; + }; + + m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams); + } + + // Create pipeline layout + { + const VkPipelineLayoutCreateInfo pipelineLayoutParams = + { + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineLayoutCreateFlags flags; + 0u, // deUint32 setLayoutCount; + DE_NULL, // const VkDescriptorSetLayout* pSetLayouts; + 0u, // deUint32 pushConstantRangeCount; + DE_NULL // const VkPushConstantRange* pPushConstantRanges; + }; + + m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams); + } + + m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0); + m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0); + + // Create pipeline + { + const VkPipelineShaderStageCreateInfo shaderStageParams[2] = + { + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineShaderStageCreateFlags flags; + VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; + *m_vertexShaderModule, // VkShaderModule module; + "main", // const char* pName; + DE_NULL // const VkSpecializationInfo* pSpecializationInfo; + }, + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineShaderStageCreateFlags flags; + VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; + *m_fragmentShaderModule, // VkShaderModule module; + "main", // const char* pName; + DE_NULL // const VkSpecializationInfo* pSpecializationInfo; + } + }; + + const VkVertexInputBindingDescription vertexInputBindingDescription = + { + 0u, // deUint32 binding; + sizeof(Vertex4RGBA), // deUint32 stride; + VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate; + }; + + const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = + { + { + 0u, // deUint32 location; + 0u, // deUint32 binding; + VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; + 0u // deUint32 offset; + }, + { + 1u, // deUint32 location; + 0u, // deUint32 binding; + VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; + DE_OFFSET_OF(Vertex4RGBA, color), // deUint32 offset; + } + }; + + const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = + { + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineVertexInputStateCreateFlags flags; + 1u, // deUint32 vertexBindingDescriptionCount; + &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; + 2u, // deUint32 vertexAttributeDescriptionCount; + vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; + }; + + const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams = + { + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineInputAssemblyStateCreateFlags flags; + m_primitiveTopology, // VkPrimitiveTopology topology; + m_primitiveRestartEnable // VkBool32 primitiveRestartEnable; + }; + + const VkViewport viewport = + { + 0.0f, // float x; + 0.0f, // float y; + (float)m_renderSize.x(), // float width; + (float)m_renderSize.y(), // float height; + 0.0f, // float minDepth; + 1.0f // float maxDepth; + }; + + const VkRect2D scissor = { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } }; + + const VkPipelineViewportStateCreateInfo viewportStateParams = + { + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineViewportStateCreateFlags flags; + 1u, // deUint32 viewportCount; + &viewport, // const VkViewport* pViewports; + 1u, // deUint32 scissorCount; + &scissor, // const VkRect2D* pScissors; + }; + + const VkPipelineRasterizationStateCreateInfo rasterStateParams = + { + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineRasterizationStateCreateFlags flags; + false, // VkBool32 depthClampEnable; + false, // VkBool32 rasterizerDiscardEnable; + VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; + VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; + VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; + VK_FALSE, // VkBool32 depthBiasEnable; + 0.0f, // float depthBiasConstantFactor; + 0.0f, // float depthBiasClamp; + 0.0f, // float depthBiasSlopeFactor; + 1.0f // float lineWidth; + }; + + const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = + { + false, // VkBool32 blendEnable; + VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; + VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; + VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; + VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; + VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; + VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask; + VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT + }; + + const VkPipelineColorBlendStateCreateInfo colorBlendStateParams = + { + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineColorBlendStateCreateFlags flags; + false, // VkBool32 logicOpEnable; + VK_LOGIC_OP_COPY, // VkLogicOp logicOp; + 1u, // deUint32 attachmentCount; + &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; + { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4]; + }; + + const VkPipelineMultisampleStateCreateInfo multisampleStateParams = + { + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineMultisampleStateCreateFlags flags; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; + false, // VkBool32 sampleShadingEnable; + 0.0f, // float minSampleShading; + DE_NULL, // const VkSampleMask* pSampleMask; + false, // VkBool32 alphaToCoverageEnable; + false // VkBool32 alphaToOneEnable; + }; + + VkPipelineDepthStencilStateCreateInfo depthStencilStateParams = + { + VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineDepthStencilStateCreateFlags flags; + false, // VkBool32 depthTestEnable; + false, // VkBool32 depthWriteEnable; + VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp; + false, // VkBool32 depthBoundsTestEnable; + false, // VkBool32 stencilTestEnable; + // VkStencilOpState front; + { + VK_STENCIL_OP_KEEP, // VkStencilOp failOp; + VK_STENCIL_OP_KEEP, // VkStencilOp passOp; + VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp; + VK_COMPARE_OP_NEVER, // VkCompareOp compareOp; + 0u, // deUint32 compareMask; + 0u, // deUint32 writeMask; + 0u, // deUint32 reference; + }, + // VkStencilOpState back; + { + VK_STENCIL_OP_KEEP, // VkStencilOp failOp; + VK_STENCIL_OP_KEEP, // VkStencilOp passOp; + VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp; + VK_COMPARE_OP_NEVER, // VkCompareOp compareOp; + 0u, // deUint32 compareMask; + 0u, // deUint32 writeMask; + 0u, // deUint32 reference; + }, + -1.0f, // float minDepthBounds; + +1.0f // float maxDepthBounds; + }; + + const VkPipelineDynamicStateCreateInfo dynamicStateParams = + { + VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineDynamicStateCreateFlags flags; + 0u, // deUint32 dynamicStateCount; + DE_NULL // const VkDynamicState* pDynamicStates; + }; + + const VkGraphicsPipelineCreateInfo graphicsPipelineParams = + { + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineCreateFlags flags; + 2u, // deUint32 stageCount; + shaderStageParams, // const VkPipelineShaderStageCreateInfo* pStages; + &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; + &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; + DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; + &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState; + &rasterStateParams, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; + &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; + &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; + &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; + &dynamicStateParams, // const VkPipelineDynamicStateCreateInfo* pDynamicState; + *m_pipelineLayout, // VkPipelineLayout layout; + *m_renderPass, // VkRenderPass renderPass; + 0u, // deUint32 subpass; + 0u, // VkPipeline basePipelineHandle; + 0u // deInt32 basePipelineIndex; + }; + + m_graphicsPipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams); + } + + // Create vertex and index buffer + { + const VkBufferCreateInfo indexBufferParams = + { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkBufferCreateFlags flags; + m_indices.size() * sizeof(deUint32), // VkDeviceSize size; + VK_BUFFER_USAGE_INDEX_BUFFER_BIT, // VkBufferUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 1u, // deUint32 queueFamilyIndexCount; + &queueFamilyIndex // const deUint32* pQueueFamilyIndices; + }; + + const VkBufferCreateInfo vertexBufferParams = + { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkBufferCreateFlags flags; + m_vertices.size() * sizeof(Vertex4RGBA), // VkDeviceSize size; + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 1u, // deUint32 queueFamilyIndexCount; + &queueFamilyIndex // const deUint32* pQueueFamilyIndices; + }; + + m_indexBuffer = createBuffer(vk, vkDevice, &indexBufferParams); + m_indexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_indexBuffer), MemoryRequirement::HostVisible); + + VK_CHECK(vk.bindBufferMemory(vkDevice, *m_indexBuffer, m_indexBufferAlloc->getMemory(), m_indexBufferAlloc->getOffset())); + + m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams); + m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible); + + VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset())); + + // Load vertices into index buffer + if (m_indexType == VK_INDEX_TYPE_UINT32) + { + deMemcpy(m_indexBufferAlloc->getHostPtr(), m_indices.data(), m_indices.size() * sizeof(deUint32)); + } + else // m_indexType == VK_INDEX_TYPE_UINT16 + { + uploadIndexBufferData16((deUint16*)m_indexBufferAlloc->getHostPtr(), m_indices); + } + + // Load vertices into vertex buffer + deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA)); + + // Flush memory + const VkMappedMemoryRange flushMemoryRanges[] = + { + { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; + DE_NULL, // const void* pNext; + m_indexBufferAlloc->getMemory(), // VkDeviceMemory memory; + m_indexBufferAlloc->getOffset(), // VkDeviceSize offset; + indexBufferParams.size // VkDeviceSize size; + }, + { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; + DE_NULL, // const void* pNext; + m_vertexBufferAlloc->getMemory(), // VkDeviceMemory memory; + m_vertexBufferAlloc->getOffset(), // VkDeviceSize offset; + vertexBufferParams.size // VkDeviceSize size; + }, + }; + + vk.flushMappedMemoryRanges(vkDevice, 2, flushMemoryRanges); + } + + // Create command pool + { + const VkCommandPoolCreateInfo cmdPoolParams = + { + VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCommandPoolCreateFlags flags; + queueFamilyIndex // deUint32 queueFamilyIndex; + }; + + m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams); + } + + // Create command buffer + { + const VkCommandBufferAllocateInfo cmdBufferAllocateInfo = + { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + *m_cmdPool, // VkCommandPool commandPool; + VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level; + 1u // deUint32 bufferCount; + }; + + const VkCommandBufferBeginInfo cmdBufferBeginInfo = + { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkCommandBufferUsageFlags flags; + DE_NULL, // VkRenderPass renderPass; + 0u, // deUint32 subpass; + DE_NULL, // VkFramebuffer framebuffer; + false, // VkBool32 occlusionQueryEnable; + 0u, // VkQueryControlFlags queryFlags; + 0u // VkQueryPipelineStatisticFlags pipelineStatistics; + }; + + const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat); + + const VkRenderPassBeginInfo renderPassBeginInfo = + { + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + *m_renderPass, // VkRenderPass renderPass; + *m_framebuffer, // VkFramebuffer framebuffer; + { { 0, 0 } , { m_renderSize.x(), m_renderSize.y() } }, // VkRect2D renderArea; + 1u, // deUint32 clearValueCount; + &attachmentClearValue // const VkClearValue* pClearValues; + }; + + m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo); + + VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo)); + vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + + const VkDeviceSize vertexBufferOffset = 0; + + vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline); + vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset); + vk.cmdBindIndexBuffer(*m_cmdBuffer, *m_indexBuffer, 0, m_indexType); + vk.cmdDrawIndexed(*m_cmdBuffer, (deUint32)m_indices.size(), 1, 0, 0, 0); + + vk.cmdEndRenderPass(*m_cmdBuffer); + VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer)); + } + + // Create fence + { + const VkFenceCreateInfo fenceParams = + { + VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u // VkFenceCreateFlags flags; + }; + + m_fence = createFence(vk, vkDevice, &fenceParams); + } +} + +InputAssemblyInstance::~InputAssemblyInstance (void) +{ +} + +tcu::TestStatus InputAssemblyInstance::iterate (void) +{ + const DeviceInterface& vk = m_context.getDeviceInterface(); + const VkDevice vkDevice = m_context.getDevice(); + const VkQueue queue = m_context.getUniversalQueue(); + const VkSubmitInfo submitInfo = + { + VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // deUint32 waitSemaphoreCount; + DE_NULL, // const VkSemaphore* pWaitSemaphores; + 1u, // deUint32 commandBufferCount; + &m_cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers; + 0u, // deUint32 signalSemaphoreCount; + DE_NULL // const VkSemaphore* pSignalSemaphores; + }; + + VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get())); + VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence)); + VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/)); + + return verifyImage(); +} + +tcu::TestStatus InputAssemblyInstance::verifyImage (void) +{ + const tcu::TextureFormat tcuColorFormat = mapVkFormat(m_colorFormat); + const tcu::TextureFormat tcuStencilFormat = tcu::TextureFormat(); + const ColorVertexShader vertexShader; + const ColorFragmentShader fragmentShader (tcuColorFormat, tcuStencilFormat); + const rr::Program program (&vertexShader, &fragmentShader); + ReferenceRenderer refRenderer (m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuStencilFormat, &program); + bool compareOk = false; + + // Render reference image + { + const rr::PrimitiveType topology = mapVkPrimitiveTopology(m_primitiveTopology); + rr::RenderState renderState (refRenderer.getViewportState()); + + + if (m_primitiveRestartEnable) + { + std::vector indicesRange; + + for (size_t indexNdx = 0; indexNdx < m_indices.size(); indexNdx++) + { + const bool isRestart = InputAssemblyTest::isRestartIndex(m_indexType, m_indices[indexNdx]); + + if (!isRestart) + indicesRange.push_back(m_indices[indexNdx]); + + if (isRestart || indexNdx == (m_indices.size() - 1)) + { + // Draw the range of indices found so far + + std::vector nonIndexedVertices; + for (size_t i = 0; i < indicesRange.size(); i++) + nonIndexedVertices.push_back(m_vertices[indicesRange[i]]); + + refRenderer.draw(renderState, topology, nonIndexedVertices); + indicesRange.clear(); + } + } + } + else + { + std::vector nonIndexedVertices; + for (size_t i = 0; i < m_indices.size(); i++) + nonIndexedVertices.push_back(m_vertices[m_indices[i]]); + + refRenderer.draw(renderState, topology, nonIndexedVertices); + } + } + + // Compare result with reference image + { + const DeviceInterface& vk = m_context.getDeviceInterface(); + const VkDevice vkDevice = m_context.getDevice(); + const VkQueue queue = m_context.getUniversalQueue(); + const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); + SimpleAllocator allocator (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice())); + de::UniquePtr result (readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize).release()); + + compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(), + "IntImageCompare", + "Image comparison", + refRenderer.getAccess(), + result->getAccess(), + tcu::UVec4(2, 2, 2, 2), + tcu::IVec3(1, 1, 0), + true, + tcu::COMPARE_LOG_RESULT); + } + + if (compareOk) + return tcu::TestStatus::pass("Result image matches reference"); + else + return tcu::TestStatus::fail("Image mismatch"); +} + +void InputAssemblyInstance::uploadIndexBufferData16 (deUint16* destPtr, const std::vector& indexBufferData) +{ + for (size_t i = 0; i < indexBufferData.size(); i++) + { + DE_ASSERT(indexBufferData[i] <= 0xFFFF); + destPtr[i] = (deUint16)indexBufferData[i]; + } +} + + +// Utilities for test names + +std::string getPrimitiveTopologyCaseName (VkPrimitiveTopology topology) +{ + const std::string fullName = getPrimitiveTopologyName(topology); + + DE_ASSERT(de::beginsWith(fullName, "VK_PRIMITIVE_TOPOLOGY_")); + + return de::toLower(fullName.substr(22)); +} + +std::string getFormatCaseName (VkFormat format) +{ + const std::string fullName = getFormatName(format); + + DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_")); + + return de::toLower(fullName.substr(10)); +} + +de::MovePtr createPrimitiveTopologyTests (tcu::TestContext& testCtx) +{ + de::MovePtr primitiveTopologyTests (new tcu::TestCaseGroup(testCtx, "primitive_topology", "")); + + for (int topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(InputAssemblyTest::s_primitiveTopologies); topologyNdx++) + { + const VkPrimitiveTopology topology = InputAssemblyTest::s_primitiveTopologies[topologyNdx]; + + primitiveTopologyTests->addChild(new PrimitiveTopologyTest(testCtx, + getPrimitiveTopologyCaseName(topology), + "", + topology)); + } + + return primitiveTopologyTests; +} + +de::MovePtr createPrimitiveRestartTests (tcu::TestContext& testCtx) +{ + const VkPrimitiveTopology primitiveRestartTopologies[] = + { + VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, + VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY + }; + + de::MovePtr primitiveRestartTests (new tcu::TestCaseGroup(testCtx, "primitive_restart", "Restarts indices of ")); + + de::MovePtr indexUint16Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint16", "")); + de::MovePtr indexUint32Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint32", "")); + + for (int topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(primitiveRestartTopologies); topologyNdx++) + { + const VkPrimitiveTopology topology = primitiveRestartTopologies[topologyNdx]; + + indexUint16Tests->addChild(new PrimitiveRestartTest(testCtx, + getPrimitiveTopologyCaseName(topology), + "", + topology, + VK_INDEX_TYPE_UINT16)); + + indexUint32Tests->addChild(new PrimitiveRestartTest(testCtx, + getPrimitiveTopologyCaseName(topology), + "", + topology, + VK_INDEX_TYPE_UINT32)); + } + + primitiveRestartTests->addChild(indexUint16Tests.release()); + primitiveRestartTests->addChild(indexUint32Tests.release()); + + return primitiveRestartTests; +} + +} // anonymous + +tcu::TestCaseGroup* createInputAssemblyTests (tcu::TestContext& testCtx) +{ + de::MovePtr inputAssemblyTests (new tcu::TestCaseGroup(testCtx, "input_assembly", "Input assembly tests")); + + inputAssemblyTests->addChild(createPrimitiveTopologyTests(testCtx).release()); + inputAssemblyTests->addChild(createPrimitiveRestartTests(testCtx).release()); + + return inputAssemblyTests.release(); +} + +} // pipeline +} // vkt diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineInputAssemblyTests.hpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineInputAssemblyTests.hpp new file mode 100644 index 0000000..894a31b --- /dev/null +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineInputAssemblyTests.hpp @@ -0,0 +1,50 @@ +#ifndef _VKTPIPELINEINPUTASSEMBLYTESTS_HPP +#define _VKTPIPELINEINPUTASSEMBLYTESTS_HPP +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2015 The Khronos Group Inc. + * Copyright (c) 2015 Imagination Technologies Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are furnished to do so, subject to + * the following conditions: + * + * The above copyright notice(s) and this permission notice shall be included + * in all copies or substantial portions of the Materials. + * + * The Materials are Confidential Information as defined by the + * Khronos Membership Agreement until designated non-confidential by Khronos, + * at which point this condition clause shall be removed. + * + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + * + *//*! + * \file + * \brief Input Assembly Tests + *//*--------------------------------------------------------------------*/ + +#include "vktTestCase.hpp" + +namespace vkt +{ +namespace pipeline +{ + +tcu::TestCaseGroup* createInputAssemblyTests (tcu::TestContext& testCtx); + +} // pipeline +} // vkt + +#endif // _VKTPIPELINEINPUTASSEMBLYTESTS_HPP diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineTests.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineTests.cpp index 22935ce..b5fa006 100644 --- a/external/vulkancts/modules/vulkan/pipeline/vktPipelineTests.cpp +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineTests.cpp @@ -38,6 +38,7 @@ #include "vktPipelineBlendTests.hpp" #include "vktPipelineDepthTests.hpp" #include "vktPipelineImageTests.hpp" +#include "vktPipelineInputAssemblyTests.hpp" #include "vktPipelineSamplerTests.hpp" #include "vktPipelineImageViewTests.hpp" #include "deUniquePtr.hpp" @@ -55,6 +56,7 @@ tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx) pipelineTests->addChild(createBlendTests(testCtx)); pipelineTests->addChild(createDepthTests(testCtx)); pipelineTests->addChild(createImageTests(testCtx)); + pipelineTests->addChild(createInputAssemblyTests(testCtx)); pipelineTests->addChild(createSamplerTests(testCtx)); pipelineTests->addChild(createImageViewTests(testCtx)); -- 2.7.4