Added tests for rasterizer discard
authorToni Merilehti <toni.merilehti@siru.fi>
Thu, 31 May 2018 11:05:10 +0000 (14:05 +0300)
committerAlexander Galazin <Alexander.Galazin@arm.com>
Sun, 8 Jul 2018 14:08:21 +0000 (10:08 -0400)
New tests were added to verify correct functionality when setting
rasterizerDiscardEnable to VK_TRUE in rasterizationStateCreateInfo.
Tests verify that primitives are discarded before rasterization by
comparing the rendered image to a blank reference image and ensuring
that no fragment shader invocations have occured.

New tests:

dEQP-VK.rasterization.discard.*

Components: Vulkan

VK-GL-CTS issue: 1149

VK-GL-CTS public issue: 100

Change-Id: Ided170a2831efaac7e393ce8cafb93269180b3d0

android/cts/master/vk-master.txt
external/vulkancts/modules/vulkan/rasterization/vktRasterizationTests.cpp
external/vulkancts/mustpass/1.1.2/vk-default-no-waivers.txt
external/vulkancts/mustpass/1.1.2/vk-default.txt

index 11213d9..7b9d2b0 100755 (executable)
@@ -301057,6 +301057,18 @@ dEQP-VK.rasterization.culling.both_triangle_strip
 dEQP-VK.rasterization.culling.both_triangle_strip_reverse
 dEQP-VK.rasterization.culling.both_triangle_fan
 dEQP-VK.rasterization.culling.both_triangle_fan_reverse
+dEQP-VK.rasterization.discard.triangle_list.query_pipeline_false
+dEQP-VK.rasterization.discard.triangle_list.query_pipeline_true
+dEQP-VK.rasterization.discard.triangle_strip.query_pipeline_false
+dEQP-VK.rasterization.discard.triangle_strip.query_pipeline_true
+dEQP-VK.rasterization.discard.triangle_fan.query_pipeline_false
+dEQP-VK.rasterization.discard.triangle_fan.query_pipeline_true
+dEQP-VK.rasterization.discard.line_list.query_pipeline_false
+dEQP-VK.rasterization.discard.line_list.query_pipeline_true
+dEQP-VK.rasterization.discard.line_strip.query_pipeline_false
+dEQP-VK.rasterization.discard.line_strip.query_pipeline_true
+dEQP-VK.rasterization.discard.point_list.query_pipeline_false
+dEQP-VK.rasterization.discard.point_list.query_pipeline_true
 dEQP-VK.rasterization.interpolation.basic.triangles
 dEQP-VK.rasterization.interpolation.basic.triangle_strip
 dEQP-VK.rasterization.interpolation.basic.triangle_fan
index 9926650..55737e4 100644 (file)
@@ -2202,6 +2202,519 @@ protected:
        const VkPolygonMode                     m_polygonMode;
 };
 
+class DiscardTestInstance : public BaseRenderingTestInstance
+{
+public:
+                                                                                                                       DiscardTestInstance                                     (Context& context, VkPrimitiveTopology primitiveTopology, deBool queryFragmentShaderInvocations)
+                                                                                                                               : BaseRenderingTestInstance                     (context, VK_SAMPLE_COUNT_1_BIT, DEFAULT_RENDER_SIZE)
+                                                                                                                               , m_primitiveTopology                           (primitiveTopology)
+                                                                                                                               , m_queryFragmentShaderInvocations      (queryFragmentShaderInvocations)
+                                                                                                                       {}
+
+       virtual const VkPipelineRasterizationStateCreateInfo*   getRasterizationStateCreateInfo         (void) const;
+       tcu::TestStatus                                                                                 iterate                                                         (void);
+
+private:
+       void                                                                                                    generateVertices                                        (std::vector<tcu::Vec4>& outData) const;
+       void                                                                                                    extractTriangles                                        (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const;
+       void                                                                                                    extractLines                                            (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices) const;
+       void                                                                                                    extractPoints                                           (std::vector<PointSceneSpec::ScenePoint>& outPoints, const std::vector<tcu::Vec4>& vertices) const;
+       void                                                                                                    drawPrimitives                                          (tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, VkPrimitiveTopology primitiveTopology, Move<VkQueryPool>& queryPool);
+
+       const VkPrimitiveTopology                                                               m_primitiveTopology;
+       const deBool                                                                                    m_queryFragmentShaderInvocations;
+};
+
+tcu::TestStatus DiscardTestInstance::iterate (void)
+{
+       const DeviceInterface&                                                  vkd                     = m_context.getDeviceInterface();
+       const VkDevice                                                                  vkDevice        = m_context.getDevice();
+       deUint64                                                                                queryResult     = 0u;
+       tcu::Surface                                                                    resultImage     (m_renderSize, m_renderSize);
+       std::vector<tcu::Vec4>                                                  drawBuffer;
+       std::vector<PointSceneSpec::ScenePoint>                 points;
+       std::vector<LineSceneSpec::SceneLine>                   lines;
+       std::vector<TriangleSceneSpec::SceneTriangle>   triangles;
+
+       generateVertices(drawBuffer);
+
+       switch (m_primitiveTopology)
+       {
+               case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
+                       extractPoints(points, drawBuffer);
+                       break;
+
+               case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
+               case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
+                       extractLines(lines, drawBuffer);
+                       break;
+
+               case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
+               case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
+               case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
+                       extractTriangles(triangles, drawBuffer);
+                       break;
+
+               default:
+                       DE_ASSERT(false);
+       }
+
+       const VkQueryPoolCreateInfo queryPoolCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,                                               // VkStructureType                                      sType
+               DE_NULL,                                                                                                                // const void*                                          pNext
+               (VkQueryPoolCreateFlags)0,                                                                              // VkQueryPoolCreateFlags                       flags
+               VK_QUERY_TYPE_PIPELINE_STATISTICS ,                                                             // VkQueryType                                          queryType
+               1u,                                                                                                                             // deUint32                                                     entryCount
+               VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT,    // VkQueryPipelineStatisticFlags        pipelineStatistics
+       };
+
+       if (m_queryFragmentShaderInvocations)
+       {
+               Move<VkQueryPool> queryPool     = createQueryPool(vkd, vkDevice, &queryPoolCreateInfo);
+
+               drawPrimitives(resultImage, drawBuffer, m_primitiveTopology, queryPool);
+               vkd.getQueryPoolResults(vkDevice, *queryPool, 0u, 1u, sizeof(deUint64), &queryResult, 0u, VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
+       }
+       else
+               BaseRenderingTestInstance::drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
+
+       // compare
+       {
+               tcu::IVec4                                              colorBits       = tcu::getTextureFormatBitDepth(getTextureFormat());
+
+               const RasterizationArguments    args            =
+               {
+                       0,                                                      // int  numSamples;
+                       (int)m_subpixelBits,            // int  subpixelBits;
+                       colorBits[0],                           // int  redBits;
+                       colorBits[1],                           // int  greenBits;
+                       colorBits[2]                            // int  blueBits;
+               };
+
+               // Empty scene to compare to, primitives should be discarded before rasterization
+               TriangleSceneSpec                               scene;
+
+               const bool                                              isCompareOk     = verifyTriangleGroupRasterization(resultImage,
+                                                                                                                                                                          scene,
+                                                                                                                                                                          args,
+                                                                                                                                                                          m_context.getTestContext().getLog(),
+                                                                                                                                                                          tcu::VERIFICATIONMODE_STRICT);
+
+               if (isCompareOk)
+               {
+                       if (m_queryFragmentShaderInvocations && queryResult > 0u)
+                               return tcu::TestStatus::fail("Fragment shader invocations occured");
+                       else
+                               return tcu::TestStatus::pass("Pass");
+               }
+               else
+                       return tcu::TestStatus::fail("Incorrect rendering");
+       }
+}
+
+void DiscardTestInstance::generateVertices (std::vector<tcu::Vec4>& outData) const
+{
+       de::Random rnd(12345);
+
+       outData.resize(6);
+
+       for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
+       {
+               outData[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
+               outData[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
+               outData[vtxNdx].z() = 0.0f;
+               outData[vtxNdx].w() = 1.0f;
+       }
+}
+
+void DiscardTestInstance::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const
+{
+       switch (m_primitiveTopology)
+       {
+               case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
+               {
+                       for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
+                       {
+                               TriangleSceneSpec::SceneTriangle        tri;
+                               const tcu::Vec4&                                        v0      = vertices[vtxNdx + 0];
+                               const tcu::Vec4&                                        v1      = vertices[vtxNdx + 1];
+                               const tcu::Vec4&                                        v2      = vertices[vtxNdx + 2];
+
+                               tri.positions[0] = v0;
+                               tri.positions[1] = v1;
+                               tri.positions[2] = v2;
+
+                               outTriangles.push_back(tri);
+                       }
+
+                       break;
+               }
+
+               case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
+               {
+                       for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
+                       {
+                               TriangleSceneSpec::SceneTriangle        tri;
+                               const tcu::Vec4&                                        v0      = vertices[vtxNdx + 0];
+                               const tcu::Vec4&                                        v1      = vertices[vtxNdx + 1];
+                               const tcu::Vec4&                                        v2      = vertices[vtxNdx + 2];
+
+                               tri.positions[0] = v0;
+                               tri.positions[1] = v1;
+                               tri.positions[2] = v2;
+
+                               outTriangles.push_back(tri);
+                       }
+
+                       break;
+               }
+
+               case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
+               {
+                       for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
+                       {
+                               TriangleSceneSpec::SceneTriangle        tri;
+                               const tcu::Vec4&                                        v0      = vertices[0];
+                               const tcu::Vec4&                                        v1      = vertices[vtxNdx + 0];
+                               const tcu::Vec4&                                        v2      = vertices[vtxNdx + 1];
+
+                               tri.positions[0] = v0;
+                               tri.positions[1] = v1;
+                               tri.positions[2] = v2;
+
+                               outTriangles.push_back(tri);
+                       }
+
+                       break;
+               }
+
+               default:
+                       DE_ASSERT(false);
+       }
+}
+
+void DiscardTestInstance::extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices) const
+{
+       switch (m_primitiveTopology)
+       {
+               case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
+               {
+                       for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; vtxNdx += 2)
+                       {
+                               LineSceneSpec::SceneLine line;
+
+                               line.positions[0] = vertices[vtxNdx + 0];
+                               line.positions[1] = vertices[vtxNdx + 1];
+
+                               outLines.push_back(line);
+                       }
+
+                       break;
+               }
+
+               case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
+               {
+                       for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
+                       {
+                               LineSceneSpec::SceneLine line;
+
+                               line.positions[0] = vertices[vtxNdx + 0];
+                               line.positions[1] = vertices[vtxNdx + 1];
+
+                               outLines.push_back(line);
+                       }
+
+                       break;
+               }
+
+               default:
+                       DE_ASSERT(false);
+               }
+}
+
+void DiscardTestInstance::extractPoints (std::vector<PointSceneSpec::ScenePoint>& outPoints, const std::vector<tcu::Vec4>& vertices) const
+{
+       for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
+       {
+               for (int vrtxNdx = 0; vrtxNdx < 3; ++vrtxNdx)
+               {
+                       PointSceneSpec::ScenePoint point;
+
+                       point.position  = vertices[vrtxNdx];
+                       point.pointSize = 1.0f;
+
+                       outPoints.push_back(point);
+               }
+       }
+}
+
+const VkPipelineRasterizationStateCreateInfo* DiscardTestInstance::getRasterizationStateCreateInfo (void) const
+{
+       static const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,     // VkStructureType                                                      sType;
+               NULL,                                                                                                           // const void*                                                          pNext;
+               0,                                                                                                                      // VkPipelineRasterizationStateCreateFlags      flags;
+               VK_FALSE,                                                                                                       // VkBool32                                                                     depthClipEnable;
+               VK_TRUE,                                                                                                        // VkBool32                                                                     rasterizerDiscardEnable;
+               VK_POLYGON_MODE_FILL,                                                                           // VkFillMode                                                           fillMode;
+               VK_CULL_MODE_NONE,                                                                                      // VkCullMode                                                           cullMode;
+               VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                        // VkFrontFace                                                          frontFace;
+               VK_FALSE,                                                                                                       // VkBool32                                                                     depthBiasEnable;
+               0.0f,                                                                                                           // float                                                                        depthBias;
+               0.0f,                                                                                                           // float                                                                        depthBiasClamp;
+               0.0f,                                                                                                           // float                                                                        slopeScaledDepthBias;
+               getLineWidth(),                                                                                         // float                                                                        lineWidth;
+       };
+
+       return &rasterizationStateCreateInfo;
+}
+
+void DiscardTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, VkPrimitiveTopology primitiveTopology, Move<VkQueryPool>& queryPool)
+{
+       const DeviceInterface&                          vkd                                     = m_context.getDeviceInterface();
+       const VkDevice                                          vkDevice                        = m_context.getDevice();
+       const VkPhysicalDeviceProperties        properties                      = m_context.getDeviceProperties();
+       const VkQueue                                           queue                           = m_context.getUniversalQueue();
+       const deUint32                                          queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
+       Allocator&                                                      allocator                       = m_context.getDefaultAllocator();
+
+       const size_t                                            attributeBatchSize      = positionData.size() * sizeof(tcu::Vec4);
+       const VkDeviceSize                                      vertexBufferOffset      = 0;
+       de::MovePtr<Allocation>                         vertexBufferMemory;
+       Move<VkBuffer>                                          vertexBuffer;
+       Move<VkCommandBuffer>                           commandBuffer;
+       Move<VkPipeline>                                        graphicsPipeline;
+
+       if (attributeBatchSize > properties.limits.maxVertexInputAttributeOffset)
+       {
+               std::stringstream message;
+               message << "Larger vertex input attribute offset is needed (" << attributeBatchSize << ") than the available maximum (" << properties.limits.maxVertexInputAttributeOffset << ").";
+               TCU_THROW(NotSupportedError, message.str().c_str());
+       }
+
+       // Create Graphics Pipeline
+       {
+               const VkVertexInputBindingDescription           vertexInputBindingDescription           =
+               {
+                       0u,                                                                             // deUint32                                     binding;
+                       sizeof(tcu::Vec4),                                              // deUint32                                     strideInBytes;
+                       VK_VERTEX_INPUT_RATE_VERTEX                             // VkVertexInputStepRate        stepRate;
+               };
+
+               const VkVertexInputAttributeDescription         vertexInputAttributeDescriptions[2]     =
+               {
+                       {
+                               0u,                                                                     // deUint32     location;
+                               0u,                                                                     // deUint32     binding;
+                               VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat     format;
+                               0u                                                                      // deUint32     offsetInBytes;
+                       },
+                       {
+                               1u,                                                                     // deUint32     location;
+                               0u,                                                                     // deUint32     binding;
+                               VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat     format;
+                               (deUint32)attributeBatchSize            // deUint32     offsetInBytes;
+                       }
+               };
+
+               const VkPipelineVertexInputStateCreateInfo      vertexInputStateParams                          =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,      // VkStructureType                                                      sType;
+                       DE_NULL,                                                                                                        // const void*                                                          pNext;
+                       0,                                                                                                                      // VkPipelineVertexInputStateCreateFlags        flags;
+                       1u,                                                                                                                     // deUint32                                                                     bindingCount;
+                       &vertexInputBindingDescription,                                                         // const VkVertexInputBindingDescription*       pVertexBindingDescriptions;
+                       2u,                                                                                                                     // deUint32                                                                     attributeCount;
+                       vertexInputAttributeDescriptions                                                        // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions;
+               };
+
+               const std::vector<VkViewport>                           viewports                                                       (1, makeViewport(tcu::UVec2(m_renderSize)));
+               const std::vector<VkRect2D>                                     scissors                                                        (1, makeRect2D(tcu::UVec2(m_renderSize)));
+
+               const VkPipelineMultisampleStateCreateInfo      multisampleStateParams                          =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                      sType;
+                       DE_NULL,                                                                                                        // const void*                                                          pNext;
+                       0u,                                                                                                                     // VkPipelineMultisampleStateCreateFlags        flags;
+                       m_sampleCount,                                                                                          // VkSampleCountFlagBits                                        rasterizationSamples;
+                       VK_FALSE,                                                                                                       // VkBool32                                                                     sampleShadingEnable;
+                       0.0f,                                                                                                           // float                                                                        minSampleShading;
+                       DE_NULL,                                                                                                        // const VkSampleMask*                                          pSampleMask;
+                       VK_FALSE,                                                                                                       // VkBool32                                                                     alphaToCoverageEnable;
+                       VK_FALSE                                                                                                        // VkBool32                                                                     alphaToOneEnable;
+               };
+
+               graphicsPipeline = makeGraphicsPipeline(vkd,                                                            // const DeviceInterface&                                                       vk
+                                                                                               vkDevice,                                                       // const VkDevice                                                                       device
+                                                                                               *m_pipelineLayout,                                      // const VkPipelineLayout                                                       pipelineLayout
+                                                                                               *m_vertexShaderModule,                          // const VkShaderModule                                                         vertexShaderModule
+                                                                                               DE_NULL,                                                        // const VkShaderModule                                                         tessellationControlShaderModule
+                                                                                               DE_NULL,                                                        // const VkShaderModule                                                         tessellationEvalShaderModule
+                                                                                               DE_NULL,                                                        // const VkShaderModule                                                         geometryShaderModule
+                                                                                               *m_fragmentShaderModule,                        // const VkShaderModule                                                         fragmentShaderModule
+                                                                                               *m_renderPass,                                          // const VkRenderPass                                                           renderPass
+                                                                                               viewports,                                                      // const std::vector<VkViewport>&                                       viewports
+                                                                                               scissors,                                                       // const std::vector<VkRect2D>&                                         scissors
+                                                                                               primitiveTopology,                                      // const VkPrimitiveTopology                                            topology
+                                                                                               0u,                                                                     // const deUint32                                                                       subpass
+                                                                                               0u,                                                                     // const deUint32                                                                       patchControlPoints
+                                                                                               &vertexInputStateParams,                        // const VkPipelineVertexInputStateCreateInfo*          vertexInputStateCreateInfo
+                                                                                               getRasterizationStateCreateInfo(),      // const VkPipelineRasterizationStateCreateInfo*        rasterizationStateCreateInfo
+                                                                                               &multisampleStateParams,                        // const VkPipelineMultisampleStateCreateInfo*          multisampleStateCreateInfo
+                                                                                               DE_NULL,                                                        // const VkPipelineDepthStencilStateCreateInfo*         depthStencilStateCreateInfo,
+                                                                                               getColorBlendStateCreateInfo());        // const VkPipelineColorBlendStateCreateInfo*           colorBlendStateCreateInfo
+       }
+
+       // Create Vertex Buffer
+       {
+               const VkBufferCreateInfo                                        vertexBufferParams              =
+               {
+                       VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,   // VkStructureType              sType;
+                       DE_NULL,                                                                // const void*                  pNext;
+                       0u,                                                                             // VkBufferCreateFlags  flags;
+                       attributeBatchSize * 2,                                 // VkDeviceSize                 size;
+                       VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,              // VkBufferUsageFlags   usage;
+                       VK_SHARING_MODE_EXCLUSIVE,                              // VkSharingMode                sharingMode;
+                       1u,                                                                             // deUint32                             queueFamilyCount;
+                       &queueFamilyIndex                                               // const deUint32*              pQueueFamilyIndices;
+               };
+
+               const std::vector<tcu::Vec4>                            colorData                               (positionData.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
+
+               vertexBuffer            = createBuffer(vkd, vkDevice, &vertexBufferParams);
+               vertexBufferMemory      = allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
+
+               VK_CHECK(vkd.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
+
+               // Load vertices into vertex buffer
+               deMemcpy(vertexBufferMemory->getHostPtr(), positionData.data(), attributeBatchSize);
+               deMemcpy(reinterpret_cast<deUint8*>(vertexBufferMemory->getHostPtr()) + attributeBatchSize, colorData.data(), attributeBatchSize);
+               flushMappedMemoryRange(vkd, vkDevice, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset(), vertexBufferParams.size);
+       }
+
+       // Create Command Buffer
+       commandBuffer = allocateCommandBuffer(vkd, vkDevice, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+
+       // Begin Command Buffer
+       beginCommandBuffer(vkd, *commandBuffer);
+
+       addImageTransitionBarrier(*commandBuffer,                                                                       // VkCommandBuffer                      commandBuffer
+                                                         *m_image,                                                                                     // VkImage                                      image
+                                                         VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                            // VkPipelineStageFlags         srcStageMask
+                                                         VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,                           // VkPipelineStageFlags         dstStageMask
+                                                         0,                                                                                            // VkAccessFlags                        srcAccessMask
+                                                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                         // VkAccessFlags                        dstAccessMask
+                                                         VK_IMAGE_LAYOUT_UNDEFINED,                                            // VkImageLayout                        oldLayout;
+                                                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);            // VkImageLayout                        newLayout;
+
+       if (m_multisampling)
+       {
+               addImageTransitionBarrier(*commandBuffer,                                                               // VkCommandBuffer                      commandBuffer
+                                                                 *m_resolvedImage,                                                             // VkImage                                      image
+                                                                 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                    // VkPipelineStageFlags         srcStageMask
+                                                                 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,                   // VkPipelineStageFlags         dstStageMask
+                                                                 0,                                                                                    // VkAccessFlags                        srcAccessMask
+                                                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                 // VkAccessFlags                        dstAccessMask
+                                                                 VK_IMAGE_LAYOUT_UNDEFINED,                                    // VkImageLayout                        oldLayout;
+                                                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);    // VkImageLayout                        newLayout;
+       }
+
+       // Reset query pool
+       vkd.cmdResetQueryPool(*commandBuffer, *queryPool, 0u, 1u);
+
+       // Begin render pass and start query
+       beginRenderPass(vkd, *commandBuffer, *m_renderPass, *m_frameBuffer, vk::makeRect2D(0, 0, m_renderSize, m_renderSize), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
+       vkd.cmdBeginQuery(*commandBuffer, *queryPool, 0u, (VkQueryControlFlags)0u);
+       vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
+       vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &m_descriptorSet.get(), 0u, DE_NULL);
+       vkd.cmdBindVertexBuffers(*commandBuffer, 0, 1, &vertexBuffer.get(), &vertexBufferOffset);
+       vkd.cmdDraw(*commandBuffer, (deUint32)positionData.size(), 1, 0, 0);
+       endRenderPass(vkd, *commandBuffer);
+       vkd.cmdEndQuery(*commandBuffer, *queryPool, 0u);
+
+       // Copy Image
+       {
+               const VkBufferMemoryBarrier     bufferBarrier   =
+               {
+                       VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        // VkStructureType              sType;
+                       DE_NULL,                                                                        // const void*                  pNext;
+                       VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkMemoryOutputFlags  outputMask;
+                       VK_ACCESS_HOST_READ_BIT,                                        // VkMemoryInputFlags   inputMask;
+                       VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                             srcQueueFamilyIndex;
+                       VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                             destQueueFamilyIndex;
+                       *m_resultBuffer,                                                        // VkBuffer                             buffer;
+                       0u,                                                                                     // VkDeviceSize                 offset;
+                       m_resultBufferSize                                                      // VkDeviceSize                 size;
+               };
+
+               const VkBufferImageCopy         copyRegion              =
+               {
+                       0u,                                                                                     // VkDeviceSize                         bufferOffset;
+                       m_renderSize,                                                           // deUint32                                     bufferRowLength;
+                       m_renderSize,                                                           // deUint32                                     bufferImageHeight;
+                       { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u },      // VkImageSubresourceCopy       imageSubresource;
+                       { 0, 0, 0 },                                                            // VkOffset3D                           imageOffset;
+                       { m_renderSize, m_renderSize, 1u }                      // VkExtent3D                           imageExtent;
+               };
+
+               addImageTransitionBarrier(*commandBuffer,                                                                       // VkCommandBuffer                      commandBuffer
+                                                                 m_multisampling ? *m_resolvedImage : *m_image,        // VkImage                                      image
+                                                                 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,        // VkPipelineStageFlags         srcStageMask
+                                                                 VK_PIPELINE_STAGE_TRANSFER_BIT,                                       // VkPipelineStageFlags         dstStageMask
+                                                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                         // VkAccessFlags                        srcAccessMask
+                                                                 VK_ACCESS_TRANSFER_READ_BIT,                                          // VkAccessFlags                        dstAccessMask
+                                                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                     // VkImageLayout                        oldLayout;
+                                                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);                        // VkImageLayout                        newLayout;)
+
+               if (m_multisampling)
+                       vkd.cmdCopyImageToBuffer(*commandBuffer, *m_resolvedImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_resultBuffer, 1, &copyRegion);
+               else
+                       vkd.cmdCopyImageToBuffer(*commandBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_resultBuffer, 1, &copyRegion);
+
+               vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
+       }
+
+       endCommandBuffer(vkd, *commandBuffer);
+
+       // Set Point Size
+       {
+               float pointSize = getPointSize();
+
+               deMemcpy(m_uniformBufferMemory->getHostPtr(), &pointSize, (size_t)m_uniformBufferSize);
+               flushMappedMemoryRange(vkd, vkDevice, m_uniformBufferMemory->getMemory(), m_uniformBufferMemory->getOffset(), m_uniformBufferSize);
+       }
+
+       // Submit
+       submitCommandsAndWait(vkd, vkDevice, queue, commandBuffer.get());
+
+       invalidateMappedMemoryRange(vkd, vkDevice, m_resultBufferMemory->getMemory(), m_resultBufferMemory->getOffset(), m_resultBufferSize);
+       tcu::copy(result.getAccess(), tcu::ConstPixelBufferAccess(m_textureFormat, tcu::IVec3(m_renderSize, m_renderSize, 1), m_resultBufferMemory->getHostPtr()));
+}
+
+class DiscardTestCase : public BaseRenderingTestCase
+{
+public:
+                                                               DiscardTestCase                                 (tcu::TestContext& context, const std::string& name, const std::string& description, VkPrimitiveTopology primitiveTopology, deBool queryFragmentShaderInvocations, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
+                                                                       : BaseRenderingTestCase                         (context, name, description, sampleCount)
+                                                                       , m_primitiveTopology                           (primitiveTopology)
+                                                                       , m_queryFragmentShaderInvocations      (queryFragmentShaderInvocations)
+                                                               {}
+
+       virtual TestInstance*           createInstance          (Context& context) const
+                                                               {
+                                                                       if (m_queryFragmentShaderInvocations && !context.getDeviceFeatures().pipelineStatisticsQuery)
+                                                                               throw tcu::NotSupportedError("Pipeline statistics queries are not supported");
+
+                                                                       return new DiscardTestInstance (context, m_primitiveTopology, m_queryFragmentShaderInvocations);
+                                                               }
+
+protected:
+       const VkPrimitiveTopology       m_primitiveTopology;
+       const deBool                            m_queryFragmentShaderInvocations;
+};
+
 class TriangleInterpolationTestInstance : public BaseRenderingTestInstance
 {
 public:
@@ -2783,6 +3296,51 @@ void createRasterizationTests (tcu::TestCaseGroup* rasterizationTests)
                }
        }
 
+       // .discard
+       {
+               static const struct PrimitiveType
+               {
+                       VkPrimitiveTopology     type;
+                       const char*                     name;
+               } primitiveTypes[] =
+               {
+                       { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,  "triangle_list"         },
+                       { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, "triangle_strip"        },
+                       { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,   "triangle_fan"          },
+                       { VK_PRIMITIVE_TOPOLOGY_LINE_LIST,              "line_list"                     },
+                       { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,             "line_strip"            },
+                       { VK_PRIMITIVE_TOPOLOGY_POINT_LIST,             "point_list"            }
+               };
+
+               static const struct queryPipeline
+               {
+                       deBool                  useQuery;
+                       const char*             name;
+               } queryPipeline[] =
+               {
+                       { DE_FALSE,     "query_pipeline_false"  },
+                       { DE_TRUE,      "query_pipeline_true"   },
+               };
+
+               tcu::TestCaseGroup* const discard = new tcu::TestCaseGroup(testCtx, "discard", "Rasterizer discard");
+
+               for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveNdx)
+               {
+                       tcu::TestCaseGroup* const primitive = new tcu::TestCaseGroup(testCtx, primitiveTypes[primitiveNdx].name, "Rasterizer discard");
+
+                       for (int useQueryNdx = 0; useQueryNdx < DE_LENGTH_OF_ARRAY(queryPipeline); useQueryNdx++)
+                       {
+                               const std::string name = std::string(queryPipeline[useQueryNdx].name);
+
+                               primitive->addChild(new DiscardTestCase(testCtx, name, "Test primitive discarding.", primitiveTypes[primitiveNdx].type, queryPipeline[useQueryNdx].useQuery));
+                       }
+
+                       discard->addChild(primitive);
+               }
+
+               rasterizationTests->addChild(discard);
+       }
+
        // .interpolation
        {
                tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(testCtx, "interpolation", "Test interpolation");
index 6efcc63..fd1077c 100644 (file)
@@ -301385,6 +301385,18 @@ dEQP-VK.rasterization.culling.both_triangle_strip
 dEQP-VK.rasterization.culling.both_triangle_strip_reverse
 dEQP-VK.rasterization.culling.both_triangle_fan
 dEQP-VK.rasterization.culling.both_triangle_fan_reverse
+dEQP-VK.rasterization.discard.triangle_list.query_pipeline_false
+dEQP-VK.rasterization.discard.triangle_list.query_pipeline_true
+dEQP-VK.rasterization.discard.triangle_strip.query_pipeline_false
+dEQP-VK.rasterization.discard.triangle_strip.query_pipeline_true
+dEQP-VK.rasterization.discard.triangle_fan.query_pipeline_false
+dEQP-VK.rasterization.discard.triangle_fan.query_pipeline_true
+dEQP-VK.rasterization.discard.line_list.query_pipeline_false
+dEQP-VK.rasterization.discard.line_list.query_pipeline_true
+dEQP-VK.rasterization.discard.line_strip.query_pipeline_false
+dEQP-VK.rasterization.discard.line_strip.query_pipeline_true
+dEQP-VK.rasterization.discard.point_list.query_pipeline_false
+dEQP-VK.rasterization.discard.point_list.query_pipeline_true
 dEQP-VK.rasterization.interpolation.basic.triangles
 dEQP-VK.rasterization.interpolation.basic.triangle_strip
 dEQP-VK.rasterization.interpolation.basic.triangle_fan
index 6fc17dc..de66e1b 100644 (file)
@@ -301346,6 +301346,18 @@ dEQP-VK.rasterization.culling.both_triangle_strip
 dEQP-VK.rasterization.culling.both_triangle_strip_reverse
 dEQP-VK.rasterization.culling.both_triangle_fan
 dEQP-VK.rasterization.culling.both_triangle_fan_reverse
+dEQP-VK.rasterization.discard.triangle_list.query_pipeline_false
+dEQP-VK.rasterization.discard.triangle_list.query_pipeline_true
+dEQP-VK.rasterization.discard.triangle_strip.query_pipeline_false
+dEQP-VK.rasterization.discard.triangle_strip.query_pipeline_true
+dEQP-VK.rasterization.discard.triangle_fan.query_pipeline_false
+dEQP-VK.rasterization.discard.triangle_fan.query_pipeline_true
+dEQP-VK.rasterization.discard.line_list.query_pipeline_false
+dEQP-VK.rasterization.discard.line_list.query_pipeline_true
+dEQP-VK.rasterization.discard.line_strip.query_pipeline_false
+dEQP-VK.rasterization.discard.line_strip.query_pipeline_true
+dEQP-VK.rasterization.discard.point_list.query_pipeline_false
+dEQP-VK.rasterization.discard.point_list.query_pipeline_true
 dEQP-VK.rasterization.interpolation.basic.triangles
 dEQP-VK.rasterization.interpolation.basic.triangle_strip
 dEQP-VK.rasterization.interpolation.basic.triangle_fan