OpenGL rasterization tests are ported.
authorPeter Siket <ps.szeged@partner.samsung.com>
Wed, 18 May 2016 11:31:42 +0000 (13:31 +0200)
committerPeter Siket <ps.szeged@partner.samsung.com>
Wed, 18 May 2016 12:37:18 +0000 (14:37 +0200)
12 files changed:
external/vulkancts/modules/vulkan/CMakeLists.txt
external/vulkancts/modules/vulkan/rasterization/CMakeLists.txt [new file with mode: 0644]
external/vulkancts/modules/vulkan/rasterization/vktRasterizationTests.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/rasterization/vktRasterizationTests.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/vktTestPackage.cpp
framework/common/CMakeLists.txt
framework/common/tcuRasterizationVerifier.cpp [moved from modules/glshared/glsRasterizationTestUtil.cpp with 98% similarity]
framework/common/tcuRasterizationVerifier.hpp [moved from modules/glshared/glsRasterizationTestUtil.hpp with 78% similarity]
modules/gles2/functional/es2fRasterizationTests.cpp
modules/gles3/functional/es3fRasterizationTests.cpp
modules/gles31/functional/es31fTextureMultisampleTests.cpp
modules/glshared/CMakeLists.txt

index 4a5b5db..630828c 100644 (file)
@@ -17,6 +17,7 @@ add_subdirectory(image)
 add_subdirectory(wsi)
 add_subdirectory(sparse_resources)
 add_subdirectory(tessellation)
+add_subdirectory(rasterization)
 
 include_directories(
        api
@@ -36,6 +37,7 @@ include_directories(
        wsi
        sparse_resources
        tessellation
+       rasterization
        )
 
 set(DEQP_VK_COMMON_SRCS
@@ -78,6 +80,7 @@ set(DEQP_VK_COMMON_LIBS
        deqp-vk-wsi
        deqp-vk-sparse-resources
        deqp-vk-tessellation
+       deqp-vk-rasterization
        )
 
 add_library(deqp-vk-common STATIC ${DEQP_VK_COMMON_SRCS})
diff --git a/external/vulkancts/modules/vulkan/rasterization/CMakeLists.txt b/external/vulkancts/modules/vulkan/rasterization/CMakeLists.txt
new file mode 100644 (file)
index 0000000..f6a0302
--- /dev/null
@@ -0,0 +1,15 @@
+include_directories(..)
+
+set(DEQP_VK_RASTERIZATION_SRCS
+       vktRasterizationTests.cpp
+       vktRasterizationTests.hpp
+       )
+
+set(DEQP_VK_RASTERIZATION_LIBS
+       deqp-vk-common
+       tcutil
+       vkutil
+       )
+
+add_library(deqp-vk-rasterization STATIC ${DEQP_VK_RASTERIZATION_SRCS})
+target_link_libraries(deqp-vk-rasterization ${DEQP_VK_RASTERIZATION_LIBS})
diff --git a/external/vulkancts/modules/vulkan/rasterization/vktRasterizationTests.cpp b/external/vulkancts/modules/vulkan/rasterization/vktRasterizationTests.cpp
new file mode 100644 (file)
index 0000000..3792b36
--- /dev/null
@@ -0,0 +1,2931 @@
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2016 The Khronos Group Inc.
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Functional rasterization tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "vktRasterizationTests.hpp"
+#include "tcuRasterizationVerifier.hpp"
+#include "tcuSurface.hpp"
+#include "tcuRenderTarget.hpp"
+#include "tcuVectorUtil.hpp"
+#include "tcuStringTemplate.hpp"
+#include "tcuTextureUtil.hpp"
+#include "tcuResultCollector.hpp"
+#include "vkImageUtil.hpp"
+#include "deStringUtil.hpp"
+#include "deRandom.hpp"
+#include "vktTestCase.hpp"
+#include "vktTestCaseUtil.hpp"
+#include "vktTestGroupUtil.hpp"
+#include "vkPrograms.hpp"
+#include "vkMemUtil.hpp"
+#include "vkRefUtil.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkBuilderUtil.hpp"
+#include "vkTypeUtil.hpp"
+
+#include <vector>
+
+using namespace vk;
+
+namespace vkt
+{
+namespace rasterization
+{
+namespace
+{
+
+using tcu::RasterizationArguments;
+using tcu::TriangleSceneSpec;
+using tcu::PointSceneSpec;
+using tcu::LineSceneSpec;
+using tcu::LineInterpolationMethod;
+
+static const char* const s_shaderVertexTemplate =      "#version 310 es\n"
+                                                                                                       "layout(location = 0) in highp vec4 a_position;\n"
+                                                                                                       "layout(location = 1) in highp vec4 a_color;\n"
+                                                                                                       "layout(location = 0) ${INTERPOLATION}out highp vec4 v_color;\n"
+                                                                                                       "layout (set=0, binding=0) uniform PointSize {\n"
+                                                                                                       "       highp float u_pointSize;\n"
+                                                                                                       "};\n"
+                                                                                                       "void main ()\n"
+                                                                                                       "{\n"
+                                                                                                       "       gl_Position = a_position;\n"
+                                                                                                       "       gl_PointSize = u_pointSize;\n"
+                                                                                                       "       v_color = a_color;\n"
+                                                                                                       "}\n";
+
+static const char* const s_shaderFragmentTemplate =    "#version 310 es\n"
+                                                                                                       "layout(location = 0) out highp vec4 fragColor;\n"
+                                                                                                       "layout(location = 0) ${INTERPOLATION}in highp vec4 v_color;\n"
+                                                                                                       "void main ()\n"
+                                                                                                       "{\n"
+                                                                                                       "       fragColor = v_color;\n"
+                                                                                                       "}\n";
+enum InterpolationCaseFlags
+{
+       INTERPOLATIONFLAGS_NONE = 0,
+       INTERPOLATIONFLAGS_PROJECTED = (1 << 1),
+       INTERPOLATIONFLAGS_FLATSHADE = (1 << 2),
+};
+
+enum PrimitiveWideness
+{
+       PRIMITIVEWIDENESS_NARROW = 0,
+       PRIMITIVEWIDENESS_WIDE,
+
+       PRIMITIVEWIDENESS_LAST
+};
+
+class BaseRenderingTestCase : public TestCase
+{
+public:
+                                                               BaseRenderingTestCase   (tcu::TestContext& context, const std::string& name, const std::string& description, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT, deBool flatshade = DE_FALSE);
+       virtual                                         ~BaseRenderingTestCase  (void);
+
+       virtual void                            initPrograms                    (vk::SourceCollections& programCollection) const;
+
+protected:
+       const VkSampleCountFlagBits     m_sampleCount;
+       const deBool                            m_flatshade;
+};
+
+BaseRenderingTestCase::BaseRenderingTestCase (tcu::TestContext& context, const std::string& name, const std::string& description, VkSampleCountFlagBits sampleCount, deBool flatshade)
+       : TestCase(context, name, description)
+       , m_sampleCount (sampleCount)
+       , m_flatshade   (flatshade)
+{
+}
+
+void BaseRenderingTestCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+       tcu::StringTemplate                                     vertexSource    (s_shaderVertexTemplate);
+       tcu::StringTemplate                                     fragmentSource  (s_shaderFragmentTemplate);
+       std::map<std::string, std::string>      params;
+
+       params["INTERPOLATION"] = (m_flatshade) ? ("flat ") : ("");
+
+       programCollection.glslSources.add("vertext_shader") << glu::VertexSource(vertexSource.specialize(params));
+       programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fragmentSource.specialize(params));
+}
+
+BaseRenderingTestCase::~BaseRenderingTestCase (void)
+{
+}
+
+class BaseRenderingTestInstance : public TestInstance
+{
+public:
+       enum {
+               DEFAULT_RENDER_SIZE = 256
+       };
+
+                                                                                                       BaseRenderingTestInstance               (Context& context, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT, deUint32 renderSize = DEFAULT_RENDER_SIZE);
+                                                                                                       ~BaseRenderingTestInstance              (void);
+
+protected:
+       void                                                                                    addImageTransitionBarrier               (VkCommandBuffer commandBuffer, VkImage image, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout) const;
+       void                                                                                    drawPrimitives                                  (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, VkPrimitiveTopology primitiveTopology);
+       void                                                                                    drawPrimitives                                  (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, const std::vector<tcu::Vec4>& coloDrata, VkPrimitiveTopology primitiveTopology);
+       virtual float                                                                   getLineWidth                                    (void) const;
+       virtual float                                                                   getPointSize                                    (void) const;
+
+       virtual
+       const VkPipelineRasterizationStateCreateInfo*   getRasterizationStateCreateInfo (void) const;
+
+       virtual
+       const VkPipelineColorBlendStateCreateInfo*              getColorBlendStateCreateInfo    (void) const;
+
+       const tcu::TextureFormat&                                               getTextureFormat                                (void) const;
+
+       const deUint32                                                                  m_renderSize;
+       const VkSampleCountFlagBits                                             m_sampleCount;
+       const deUint32                                                                  m_subpixelBits;
+       const deBool                                                                    m_multisampling;
+
+       const VkFormat                                                                  m_imageFormat;
+       const tcu::TextureFormat                                                m_textureFormat;
+       Move<VkCommandPool>                                                             m_commandPool;
+
+       Move<VkImage>                                                                   m_image;
+       de::MovePtr<Allocation>                                                 m_imageMemory;
+       Move<VkImageView>                                                               m_imageView;
+
+       Move<VkImage>                                                                   m_resolvedImage;
+       de::MovePtr<Allocation>                                                 m_resolvedImageMemory;
+       Move<VkImageView>                                                               m_resolvedImageView;
+
+       Move<VkRenderPass>                                                              m_renderPass;
+       Move<VkFramebuffer>                                                             m_frameBuffer;
+
+       Move<VkDescriptorPool>                                                  m_descriptorPool;
+       Move<VkDescriptorSet>                                                   m_descriptorSet;
+       Move<VkDescriptorSetLayout>                                             m_descriptorSetLayout;
+
+       Move<VkBuffer>                                                                  m_uniformBuffer;
+       de::MovePtr<Allocation>                                                 m_uniformBufferMemory;
+       const VkDeviceSize                                                              m_uniformBufferSize;
+
+       Move<VkPipelineLayout>                                                  m_pipelineLayout;
+
+       Move<VkShaderModule>                                                    m_vertexShaderModule;
+       Move<VkShaderModule>                                                    m_fragmentShaderModule;
+
+       Move<VkFence>                                                                   m_fence;
+
+       Move<VkBuffer>                                                                  m_resultBuffer;
+       de::MovePtr<Allocation>                                                 m_resultBufferMemory;
+       const VkDeviceSize                                                              m_resultBufferSize;
+
+};
+
+BaseRenderingTestInstance::BaseRenderingTestInstance (Context& context, VkSampleCountFlagBits sampleCount, deUint32 renderSize)
+       : TestInstance                  (context)
+       , m_renderSize                  (renderSize)
+       , m_sampleCount                 (sampleCount)
+       , m_subpixelBits                (context.getDeviceProperties().limits.subPixelPrecisionBits)
+       , m_multisampling               (m_sampleCount != VK_SAMPLE_COUNT_1_BIT)
+       , m_imageFormat                 (VK_FORMAT_R8G8B8A8_UNORM)
+       , m_textureFormat               (vk::mapVkFormat(m_imageFormat))
+       , m_uniformBufferSize   (sizeof(float))
+       , m_resultBufferSize    (renderSize * renderSize * m_textureFormat.getPixelSize())
+{
+       const DeviceInterface&                                          vkd                                             = m_context.getDeviceInterface();
+       const VkDevice                                                          vkDevice                                = m_context.getDevice();
+       const deUint32                                                          queueFamilyIndex                = m_context.getUniversalQueueFamilyIndex();
+       Allocator&                                                                      allocator                               = m_context.getDefaultAllocator();
+       DescriptorPoolBuilder                                           descriptorPoolBuilder;
+       DescriptorSetLayoutBuilder                                      descriptorSetLayoutBuilder;
+
+       // Command Pool
+       {
+               const VkCommandPoolCreateInfo                   cmdPoolCreateInfo               =
+               {
+                       VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,                                     // VkStructureType             sType;
+                       DE_NULL,                                                                                                        // const void*                 pNext;
+                       VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,                        // VkCommandPoolCreateFlags    flags;
+                       queueFamilyIndex                                                                                        // deUint32                    queueFamilyIndex;
+               };
+
+               m_commandPool = createCommandPool(vkd, vkDevice, &cmdPoolCreateInfo, DE_NULL);
+       }
+
+       // Image
+       {
+               const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+               VkImageFormatProperties properties;
+
+               if ((m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(),
+                                                                                                                                                                        m_imageFormat,
+                                                                                                                                                                        VK_IMAGE_TYPE_2D,
+                                                                                                                                                                        VK_IMAGE_TILING_OPTIMAL,
+                                                                                                                                                                        imageUsage,
+                                                                                                                                                                        0,
+                                                                                                                                                                        &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
+               {
+                       TCU_THROW(NotSupportedError, "Format not supported");
+               }
+
+               if ((properties.sampleCounts & m_sampleCount) != m_sampleCount)
+               {
+                       TCU_THROW(NotSupportedError, "Format not supported");
+               }
+
+               const VkImageCreateInfo                                 imageCreateInfo                 =
+               {
+                       VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,            // VkStructureType                      sType;
+                       DE_NULL,                                                                        // const void*                          pNext;
+                       0u,                                                                                     // VkImageCreateFlags           flags;
+                       VK_IMAGE_TYPE_2D,                                                       // VkImageType                          imageType;
+                       m_imageFormat,                                                          // VkFormat                                     format;
+                       { m_renderSize, m_renderSize, 1u },                     // VkExtent3D                           extent;
+                       1u,                                                                                     // deUint32                                     mipLevels;
+                       1u,                                                                                     // deUint32                                     arrayLayers;
+                       m_sampleCount,                                                          // VkSampleCountFlagBits        samples;
+                       VK_IMAGE_TILING_OPTIMAL,                                        // VkImageTiling                        tiling;
+                       imageUsage,                                                                     // VkImageUsageFlags            usage;
+                       VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                        sharingMode;
+                       1u,                                                                                     // deUint32                                     queueFamilyIndexCount;
+                       &queueFamilyIndex,                                                      // const deUint32*                      pQueueFamilyIndices;
+                       VK_IMAGE_LAYOUT_UNDEFINED                                       // VkImageLayout                        initialLayout;
+               };
+
+               m_image = vk::createImage(vkd, vkDevice, &imageCreateInfo, DE_NULL);
+
+               m_imageMemory   = allocator.allocate(getImageMemoryRequirements(vkd, vkDevice, *m_image), MemoryRequirement::Any);
+               VK_CHECK(vkd.bindImageMemory(vkDevice, *m_image, m_imageMemory->getMemory(), m_imageMemory->getOffset()));
+       }
+
+       // Image View
+       {
+               const VkImageViewCreateInfo                             imageViewCreateInfo             =
+               {
+                       VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,       // VkStructureType                              sType;
+                       DE_NULL,                                                                        // const void*                                  pNext;
+                       0u,                                                                                     // VkImageViewCreateFlags               flags;
+                       *m_image,                                                                       // VkImage                                              image;
+                       VK_IMAGE_VIEW_TYPE_2D,                                          // VkImageViewType                              viewType;
+                       m_imageFormat,                                                          // VkFormat                                             format;
+                       getFormatComponentMapping(m_imageFormat),       // VkComponentMapping                   components;
+                       {
+                               VK_IMAGE_ASPECT_COLOR_BIT,                                      // VkImageAspectFlags                   aspectMask;
+                               0u,                                                                                     // deUint32                                             baseMipLevel;
+                               1u,                                                                                     // deUint32                                             mipLevels;
+                               0u,                                                                                     // deUint32                                             baseArrayLayer;
+                               1u,                                                                                     // deUint32                                             arraySize;
+                       },                                                                                      // VkImageSubresourceRange              subresourceRange;
+               };
+
+               m_imageView = vk::createImageView(vkd, vkDevice, &imageViewCreateInfo, DE_NULL);
+       }
+
+       if (m_multisampling)
+       {
+               {
+                       // Resolved Image
+                       const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+                       VkImageFormatProperties properties;
+
+                       if ((m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(),
+                                                                                                                                                                                m_imageFormat,
+                                                                                                                                                                                VK_IMAGE_TYPE_2D,
+                                                                                                                                                                                VK_IMAGE_TILING_OPTIMAL,
+                                                                                                                                                                                imageUsage,
+                                                                                                                                                                                0,
+                                                                                                                                                                                &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
+                       {
+                               TCU_THROW(NotSupportedError, "Format not supported");
+                       }
+
+                       const VkImageCreateInfo                                 imageCreateInfo                 =
+                       {
+                               VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,            // VkStructureType                      sType;
+                               DE_NULL,                                                                        // const void*                          pNext;
+                               0u,                                                                                     // VkImageCreateFlags           flags;
+                               VK_IMAGE_TYPE_2D,                                                       // VkImageType                          imageType;
+                               m_imageFormat,                                                          // VkFormat                                     format;
+                               { m_renderSize, m_renderSize, 1u },                     // VkExtent3D                           extent;
+                               1u,                                                                                     // deUint32                                     mipLevels;
+                               1u,                                                                                     // deUint32                                     arrayLayers;
+                               VK_SAMPLE_COUNT_1_BIT,                                          // VkSampleCountFlagBits        samples;
+                               VK_IMAGE_TILING_OPTIMAL,                                        // VkImageTiling                        tiling;
+                               imageUsage,                                                                     // VkImageUsageFlags            usage;
+                               VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                        sharingMode;
+                               1u,                                                                                     // deUint32                                     queueFamilyIndexCount;
+                               &queueFamilyIndex,                                                      // const deUint32*                      pQueueFamilyIndices;
+                               VK_IMAGE_LAYOUT_UNDEFINED                                       // VkImageLayout                        initialLayout;
+                       };
+
+                       m_resolvedImage                 = vk::createImage(vkd, vkDevice, &imageCreateInfo, DE_NULL);
+                       m_resolvedImageMemory   = allocator.allocate(getImageMemoryRequirements(vkd, vkDevice, *m_resolvedImage), MemoryRequirement::Any);
+                       VK_CHECK(vkd.bindImageMemory(vkDevice, *m_resolvedImage, m_resolvedImageMemory->getMemory(), m_resolvedImageMemory->getOffset()));
+               }
+
+               // Resolved Image View
+               {
+                       const VkImageViewCreateInfo                             imageViewCreateInfo             =
+                       {
+                               VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,       // VkStructureType                              sType;
+                               DE_NULL,                                                                        // const void*                                  pNext;
+                               0u,                                                                                     // VkImageViewCreateFlags               flags;
+                               *m_resolvedImage,                                                                       // VkImage                                              image;
+                               VK_IMAGE_VIEW_TYPE_2D,                                          // VkImageViewType                              viewType;
+                               m_imageFormat,                                                          // VkFormat                                             format;
+                               getFormatComponentMapping(m_imageFormat),       // VkComponentMapping                   components;
+                               {
+                                       VK_IMAGE_ASPECT_COLOR_BIT,                                      // VkImageAspectFlags                   aspectMask;
+                                       0u,                                                                                     // deUint32                                             baseMipLevel;
+                                       1u,                                                                                     // deUint32                                             mipLevels;
+                                       0u,                                                                                     // deUint32                                             baseArrayLayer;
+                                       1u,                                                                                     // deUint32                                             arraySize;
+                               },                                                                                      // VkImageSubresourceRange              subresourceRange;
+                       };
+
+                       m_resolvedImageView = vk::createImageView(vkd, vkDevice, &imageViewCreateInfo, DE_NULL);
+               }
+
+       }
+
+       // Render Pass
+       {
+               const VkImageLayout                                             imageLayout                             = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+               const VkAttachmentDescription                   attachmentDesc[]                =
+               {
+                       {
+                               0u,                                                                                                     // VkAttachmentDescriptionFlags         flags;
+                               m_imageFormat,                                                                          // VkFormat                                                     format;
+                               m_sampleCount,                                                                          // 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;
+                               imageLayout,                                                                            // VkImageLayout                                        initialLayout;
+                               imageLayout,                                                                            // VkImageLayout                                        finalLayout;
+                       },
+                       {
+                               0u,                                                                                                     // VkAttachmentDescriptionFlags         flags;
+                               m_imageFormat,                                                                          // 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;
+                               imageLayout,                                                                            // VkImageLayout                                        initialLayout;
+                               imageLayout,                                                                            // VkImageLayout                                        finalLayout;
+                       }
+               };
+
+               const VkAttachmentReference                             attachmentRef                   =
+               {
+                       0u,                                                                                                     // deUint32                                                     attachment;
+                       imageLayout,                                                                            // VkImageLayout                                        layout;
+               };
+
+               const VkAttachmentReference                             resolveAttachmentRef    =
+               {
+                       1u,                                                                                                     // deUint32                                                     attachment;
+                       imageLayout,                                                                            // VkImageLayout                                        layout;
+               };
+
+               const VkSubpassDescription                              subpassDesc                             =
+               {
+                       0u,                                                                                                     // VkSubpassDescriptionFlags            flags;
+                       VK_PIPELINE_BIND_POINT_GRAPHICS,                                        // VkPipelineBindPoint                          pipelineBindPoint;
+                       0u,                                                                                                     // deUint32                                                     inputAttachmentCount;
+                       DE_NULL,                                                                                        // const VkAttachmentReference*         pInputAttachments;
+                       1u,                                                                                                     // deUint32                                                     colorAttachmentCount;
+                       &attachmentRef,                                                                         // const VkAttachmentReference*         pColorAttachments;
+                       m_multisampling ? &resolveAttachmentRef : DE_NULL,      // const VkAttachmentReference*         pResolveAttachments;
+                       DE_NULL,                                                                                        // const VkAttachmentReference*         pDepthStencilAttachment;
+                       0u,                                                                                                     // deUint32                                                     preserveAttachmentCount;
+                       DE_NULL,                                                                                        // const VkAttachmentReference*         pPreserveAttachments;
+               };
+
+               const VkRenderPassCreateInfo                    renderPassCreateInfo    =
+               {
+                       VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                      // VkStructureType                                      sType;
+                       DE_NULL,                                                                                        // const void*                                          pNext;
+                       0u,                                                                                                     // VkRenderPassCreateFlags                      flags;
+                       m_multisampling ? 2u : 1u,                                                      // deUint32                                                     attachmentCount;
+                       attachmentDesc,                                                                         // const VkAttachmentDescription*       pAttachments;
+                       1u,                                                                                                     // deUint32                                                     subpassCount;
+                       &subpassDesc,                                                                           // const VkSubpassDescription*          pSubpasses;
+                       0u,                                                                                                     // deUint32                                                     dependencyCount;
+                       DE_NULL,                                                                                        // const VkSubpassDependency*           pDependencies;
+               };
+
+               m_renderPass =  createRenderPass(vkd, vkDevice, &renderPassCreateInfo, DE_NULL);
+       }
+
+       // FrameBuffer
+       {
+               const VkImageView                                               attachments[]                   =
+               {
+                       *m_imageView,
+                       *m_resolvedImageView
+               };
+
+               const VkFramebufferCreateInfo                   framebufferCreateInfo   =
+               {
+                       VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,      // VkStructureType                      sType;
+                       DE_NULL,                                                                        // const void*                          pNext;
+                       0u,                                                                                     // VkFramebufferCreateFlags     flags;
+                       *m_renderPass,                                                          // VkRenderPass                         renderPass;
+                       m_multisampling ? 2u : 1u,                                      // deUint32                                     attachmentCount;
+                       attachments,                                                            // const VkImageView*           pAttachments;
+                       m_renderSize,                                                           // deUint32                                     width;
+                       m_renderSize,                                                           // deUint32                                     height;
+                       1u,                                                                                     // deUint32                                     layers;
+               };
+
+               m_frameBuffer = createFramebuffer(vkd, vkDevice, &framebufferCreateInfo, DE_NULL);
+       }
+
+       // Uniform Buffer
+       {
+               const VkBufferCreateInfo                                bufferCreateInfo                =
+               {
+                       VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
+                       DE_NULL,                                                                        // const void*                  pNext;
+                       0u,                                                                                     // VkBufferCreateFlags  flags;
+                       m_uniformBufferSize,                                            // VkDeviceSize                 size;
+                       VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,                     // VkBufferUsageFlags   usage;
+                       VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
+                       1u,                                                                                     // deUint32                             queueFamilyIndexCount;
+                       &queueFamilyIndex                                                       // const deUint32*              pQueueFamilyIndices;
+               };
+
+               m_uniformBuffer                 = createBuffer(vkd, vkDevice, &bufferCreateInfo);
+               m_uniformBufferMemory   = allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *m_uniformBuffer), MemoryRequirement::HostVisible);
+
+               VK_CHECK(vkd.bindBufferMemory(vkDevice, *m_uniformBuffer, m_uniformBufferMemory->getMemory(), m_uniformBufferMemory->getOffset()));
+       }
+
+       // Descriptors
+       {
+               descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
+               m_descriptorPool = descriptorPoolBuilder.build(vkd, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
+
+               descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_ALL);
+               m_descriptorSetLayout = descriptorSetLayoutBuilder.build(vkd, vkDevice);
+
+               const VkDescriptorSetAllocateInfo               descriptorSetParams             =
+               {
+                       VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+                       DE_NULL,
+                       *m_descriptorPool,
+                       1u,
+                       &m_descriptorSetLayout.get(),
+               };
+
+               m_descriptorSet = allocateDescriptorSet(vkd, vkDevice, &descriptorSetParams);
+
+               const VkDescriptorBufferInfo                    descriptorBufferInfo    =
+               {
+                       *m_uniformBuffer,                                                       // VkBuffer             buffer;
+                       0u,                                                                                     // VkDeviceSize offset;
+                       VK_WHOLE_SIZE                                                           // VkDeviceSize range;
+               };
+
+               const VkWriteDescriptorSet                              writeDescritporSet              =
+               {
+                       VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,         // VkStructureType                                      sType;
+                       DE_NULL,                                                                        // const void*                                          pNext;
+                       *m_descriptorSet,                                                       // VkDescriptorSet                                      destSet;
+                       0,                                                                                      // deUint32                                                     destBinding;
+                       0,                                                                                      // deUint32                                                     destArrayElement;
+                       1u,                                                                                     // deUint32                                                     count;
+                       VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,                      // VkDescriptorType                                     descriptorType;
+                       DE_NULL,                                                                        // const VkDescriptorImageInfo*         pImageInfo;
+                       &descriptorBufferInfo,                                          // const VkDescriptorBufferInfo*        pBufferInfo;
+                       DE_NULL                                                                         // const VkBufferView*                          pTexelBufferView;
+               };
+
+               vkd.updateDescriptorSets(vkDevice, 1u, &writeDescritporSet, 0u, DE_NULL);
+       }
+
+       // Pipeline Layout
+       {
+               const VkPipelineLayoutCreateInfo                pipelineLayoutCreateInfo        =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                              sType;
+                       DE_NULL,                                                                                        // const void*                                  pNext;
+                       0u,                                                                                                     // VkPipelineLayoutCreateFlags  flags;
+                       1u,                                                                                                     // deUint32                                             descriptorSetCount;
+                       &m_descriptorSetLayout.get(),                                           // const VkDescriptorSetLayout* pSetLayouts;
+                       0u,                                                                                                     // deUint32                                             pushConstantRangeCount;
+                       DE_NULL                                                                                         // const VkPushConstantRange*   pPushConstantRanges;
+               };
+
+               m_pipelineLayout = createPipelineLayout(vkd, vkDevice, &pipelineLayoutCreateInfo);
+       }
+
+       // Shaders
+       {
+               m_vertexShaderModule    = createShaderModule(vkd, vkDevice, m_context.getBinaryCollection().get("vertext_shader"), 0);
+               m_fragmentShaderModule  = createShaderModule(vkd, vkDevice, m_context.getBinaryCollection().get("fragment_shader"), 0);
+       }
+
+       // Fence
+       {
+               const VkFenceCreateInfo                                 fenceParams                                     =
+               {
+                       VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,    // VkStructureType              sType;
+                       DE_NULL,                                                                // const void*                  pNext;
+                       VK_FENCE_CREATE_SIGNALED_BIT                    // VkFenceCreateFlags   flags;
+               };
+
+               m_fence = createFence(vkd, vkDevice, &fenceParams);
+       }
+
+       // Result Buffer
+       {
+               const VkBufferCreateInfo                                bufferCreateInfo                =
+               {
+                       VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
+                       DE_NULL,                                                                        // const void*                  pNext;
+                       0u,                                                                                     // VkBufferCreateFlags  flags;
+                       m_resultBufferSize,                                                     // VkDeviceSize                 size;
+                       VK_BUFFER_USAGE_TRANSFER_DST_BIT,                       // VkBufferUsageFlags   usage;
+                       VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
+                       1u,                                                                                     // deUint32                             queueFamilyIndexCount;
+                       &queueFamilyIndex                                                       // const deUint32*              pQueueFamilyIndices;
+               };
+
+               m_resultBuffer                  = createBuffer(vkd, vkDevice, &bufferCreateInfo);
+               m_resultBufferMemory    = allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *m_resultBuffer), MemoryRequirement::HostVisible);
+
+               VK_CHECK(vkd.bindBufferMemory(vkDevice, *m_resultBuffer, m_resultBufferMemory->getMemory(), m_resultBufferMemory->getOffset()));
+       }
+
+       m_context.getTestContext().getLog() << tcu::TestLog::Message << "Sample count = " << getSampleCountFlagsStr(m_sampleCount) << tcu::TestLog::EndMessage;
+       m_context.getTestContext().getLog() << tcu::TestLog::Message << "SUBPIXEL_BITS = " << m_subpixelBits << tcu::TestLog::EndMessage;
+}
+
+BaseRenderingTestInstance::~BaseRenderingTestInstance (void)
+{
+}
+
+
+void BaseRenderingTestInstance::addImageTransitionBarrier(VkCommandBuffer commandBuffer, VkImage image, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout) const
+{
+
+       const DeviceInterface&                  vkd                                     = m_context.getDeviceInterface();
+
+       const VkImageSubresourceRange   subResourcerange        =
+       {
+               VK_IMAGE_ASPECT_COLOR_BIT,              // VkImageAspectFlags   aspectMask;
+               0,                                                              // deUint32                             baseMipLevel;
+               1,                                                              // deUint32                             levelCount;
+               0,                                                              // deUint32                             baseArrayLayer;
+               1                                                               // deUint32                             layerCount;
+       };
+
+       const VkImageMemoryBarrier              imageBarrier            =
+       {
+               VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         // VkStructureType                      sType;
+               DE_NULL,                                                                        // const void*                          pNext;
+               srcAccessMask,                                                          // VkAccessFlags                        srcAccessMask;
+               dstAccessMask,                                                          // VkAccessFlags                        dstAccessMask;
+               oldLayout,                                                                      // VkImageLayout                        oldLayout;
+               newLayout,                                                                      // VkImageLayout                        newLayout;
+               VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     srcQueueFamilyIndex;
+               VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     destQueueFamilyIndex;
+               image,                                                                          // VkImage                                      image;
+               subResourcerange                                                        // VkImageSubresourceRange      subresourceRange;
+       };
+
+       vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &imageBarrier);
+}
+
+void BaseRenderingTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, VkPrimitiveTopology primitiveTopology)
+{
+       // default to color white
+       const std::vector<tcu::Vec4> colorData(vertexData.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
+
+       drawPrimitives(result, vertexData, colorData, primitiveTopology);
+}
+
+void BaseRenderingTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, const std::vector<tcu::Vec4>& colorData, VkPrimitiveTopology primitiveTopology)
+{
+       const DeviceInterface&                                          vkd                                             = m_context.getDeviceInterface();
+       const VkDevice                                                          vkDevice                                = m_context.getDevice();
+       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);
+
+       Move<VkCommandBuffer>                                           commandBuffer;
+       Move<VkPipeline>                                                        graphicsPipeline;
+       Move<VkBuffer>                                                          vertexBuffer;
+       de::MovePtr<Allocation>                                         vertexBufferMemory;
+
+       // Create Graphics Pipeline
+       {
+               const VkPipelineShaderStageCreateInfo   shaderStageParams[2]    =
+               {
+                       {
+                               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,            // VkStructureType                                      sType;
+                               DE_NULL,                                                                                                        // const void*                                          pNext;
+                               0,                                                                                                                      // VkPipelineShaderStageCreateFlags flags;
+                               VK_SHADER_STAGE_VERTEX_BIT,                                                                     // VkShaderStage                                        stage;
+                               *m_vertexShaderModule,                                                                          // VkShader                                                     shader;
+                               "main",                                                                                                         // const char*                                          pName;
+                               DE_NULL                                                                                                         // const VkSpecializationInfo*          pSpecializationInfo;
+                       },
+                       {
+                               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,            // VkStructureType                                      sType;
+                               DE_NULL,                                                                                                        // const void*                                          pNext;
+                               0,                                                                                                                      // VkPipelineShaderStageCreateFlags flags;
+                               VK_SHADER_STAGE_FRAGMENT_BIT,                                                           // VkShaderStage                                        stage;
+                               *m_fragmentShaderModule,                                                                        // VkShader                                                     shader;
+                               "main",                                                                                                         // const char*                                          pName;
+                               DE_NULL                                                                                                         // const VkSpecializationInfo*          pSpecializationInfo;
+                       }
+               };
+
+               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 VkPipelineInputAssemblyStateCreateInfo    inputAssemblyStateParams =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                                                      sType;
+                       DE_NULL,                                                                                                                // const void*                                                          pNext;
+                       0,                                                                                                                              // VkPipelineInputAssemblyStateCreateFlags      flags;
+                       primitiveTopology,                                                                                              // VkPrimitiveTopology                                          topology;
+                       false                                                                                                                   // VkBool32                                                                     primitiveRestartEnable;
+               };
+
+               const VkViewport                                                viewport =
+               {
+                       0.0f,                                           // float        originX;
+                       0.0f,                                           // float        originY;
+                       m_renderSize,                           // float        width;
+                       m_renderSize,                           // float        height;
+                       0.0f,                                           // float        minDepth;
+                       1.0f                                            // float        maxDepth;
+               };
+
+               const VkRect2D                                                  scissor =
+               {
+                       { 0, 0 },                                                                                                               // VkOffset2D  offset;
+                       { m_renderSize, m_renderSize }                                                                  // VkExtent2D  extent;
+               };
+
+               const VkPipelineViewportStateCreateInfo viewportStateParams =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,                  // VkStructureType                                              sType;
+                       DE_NULL,                                                                                                                // const void*                                                  pNext;
+                       0,                                                                                                                              // VkPipelineViewportStateCreateFlags   flags;
+                       1u,                                                                                                                             // deUint32                                                             viewportCount;
+                       &viewport,                                                                                                              // const VkViewport*                                    pViewports;
+                       1u,                                                                                                                             // deUint32                                                             scissorCount;
+                       &scissor                                                                                                                // const VkRect2D*                                              pScissors;
+               };
+
+               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;
+               };
+
+               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;
+                       getRasterizationStateCreateInfo(),                                      // const VkPipelineRasterStateCreateInfo*                       pRasterizationState;
+                       &multisampleStateParams,                                                        // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
+                       DE_NULL,                                                                                        // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
+                       getColorBlendStateCreateInfo(),                                         // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
+                       DE_NULL,                                                                                        // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
+                       *m_pipelineLayout,                                                                      // VkPipelineLayout                                                                     layout;
+                       *m_renderPass,                                                                          // VkRenderPass                                                                         renderPass;
+                       0u,                                                                                                     // deUint32                                                                                     subpass;
+                       0u,                                                                                                     // VkPipeline                                                                           basePipelineHandle;
+                       0u                                                                                                      // deInt32                                                                                      basePipelineIndex;
+               };
+
+               graphicsPipeline                = createGraphicsPipeline(vkd, vkDevice, DE_NULL, &graphicsPipelineParams);
+       }
+
+       // 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;
+               };
+
+               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
+       {
+               const VkCommandBufferAllocateInfo               cmdBufferAllocateInfo   =
+               {
+                       VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,                         // VkStructureType             sType;
+                       DE_NULL,                                                                                                        // const void*                 pNext;
+                       *m_commandPool,                                                                                         // VkCommandPool               commandPool;
+                       VK_COMMAND_BUFFER_LEVEL_PRIMARY,                                                        // VkCommandBufferLevel        level;
+                       1                                                                                                                       // deUint32                    commandBufferCount;
+               };
+
+               commandBuffer = allocateCommandBuffer(vkd, vkDevice, &cmdBufferAllocateInfo);
+       }
+
+       // Begin Command Buffer
+       {
+               const VkCommandBufferBeginInfo          cmdBufferBeginInfo              =
+               {
+                       VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,    // VkStructureType                                                      sType;
+                       DE_NULL,                                                                                // const void*                                                          pNext;
+                       0u,                                                                                             // VkCmdBufferOptimizeFlags                                     flags;
+                       DE_NULL                                                                                 // const VkCommandBufferInheritanceInfo*        pInheritanceInfo;
+               };
+
+               VK_CHECK(vkd.beginCommandBuffer(*commandBuffer, &cmdBufferBeginInfo));
+       }
+
+       addImageTransitionBarrier(*commandBuffer, *m_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, *m_resolvedImage,
+                                                                 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;
+       }
+
+       // Begin Render Pass
+       {
+               const VkClearValue                                      clearValue                              = makeClearValueColorF32(0.0, 0.0, 0.0, 1.0);
+
+               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, m_renderSize }
+                       },                                                                                                              // VkRect2D                             renderArea;
+                       1u,                                                                                                             // deUint32                             clearValueCount;
+                       &clearValue                                                                                             // const VkClearValue*  pClearValues;
+               };
+
+               vkd.cmdBeginRenderPass(*commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+       }
+
+       const VkDeviceSize                                              vertexBufferOffset              = 0;
+
+       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);
+       vkd.cmdEndRenderPass(*commandBuffer);
+
+       // 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,
+                                                                 m_multisampling ? *m_resolvedImage : *m_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);
+       }
+
+       VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
+
+       // Set Point Size
+       {
+               float   pointSize       = getPointSize();
+               deMemcpy(m_uniformBufferMemory->getHostPtr(), &pointSize, m_uniformBufferSize);
+               flushMappedMemoryRange(vkd, vkDevice, m_uniformBufferMemory->getMemory(), m_uniformBufferMemory->getOffset(), m_uniformBufferSize);
+       }
+
+       // Submit
+       {
+               const VkSubmitInfo                                      submitInfo                              =
+               {
+                       VK_STRUCTURE_TYPE_SUBMIT_INFO,                  // VkStructureType                              sType;
+                       DE_NULL,                                                                // const void*                                  pNext;
+                       0u,                                                                             // deUint32                                             waitSemaphoreCount;
+                       DE_NULL,                                                                // const VkSemaphore*                   pWaitSemaphores;
+                       DE_NULL,                                                                // const VkPipelineStageFlags*  pWaitDstStageMask;
+                       1u,                                                                             // deUint32                                             commandBufferCount;
+                       &commandBuffer.get(),                                   // const VkCommandBuffer*               pCommandBuffers;
+                       0u,                                                                             // deUint32                                             signalSemaphoreCount;
+                       DE_NULL,                                                                // const VkSemaphore*                   pSignalSemaphores;
+               };
+
+               VK_CHECK(vkd.resetFences(vkDevice, 1, &m_fence.get()));
+               VK_CHECK(vkd.queueSubmit(queue, 1, &submitInfo, *m_fence));
+               VK_CHECK(vkd.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
+       }
+
+       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()));
+}
+
+float BaseRenderingTestInstance::getLineWidth (void) const
+{
+       return 1.0f;
+}
+
+float BaseRenderingTestInstance::getPointSize (void) const
+{
+       return 1.0f;
+}
+
+const VkPipelineRasterizationStateCreateInfo* BaseRenderingTestInstance::getRasterizationStateCreateInfo (void) const
+{
+       static VkPipelineRasterizationStateCreateInfo   rasterizationStateCreateInfo    =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                                                      sType;
+               DE_NULL,                                                                                                                // const void*                                                          pNext;
+               0,                                                                                                                              // VkPipelineRasterizationStateCreateFlags      flags;
+               false,                                                                                                                  // VkBool32                                                                     depthClipEnable;
+               false,                                                                                                                  // 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;
+       };
+
+       rasterizationStateCreateInfo.lineWidth = getLineWidth();
+       return &rasterizationStateCreateInfo;
+}
+
+const VkPipelineColorBlendStateCreateInfo* BaseRenderingTestInstance::getColorBlendStateCreateInfo (void) const
+{
+       static const VkPipelineColorBlendAttachmentState        colorBlendAttachmentState       =
+       {
+               false,                                                                                                          // VkBool32                     blendEnable;
+               VK_BLEND_FACTOR_ONE,                                                                            // VkBlend                      srcBlendColor;
+               VK_BLEND_FACTOR_ZERO,                                                                           // VkBlend                      destBlendColor;
+               VK_BLEND_OP_ADD,                                                                                        // VkBlendOp            blendOpColor;
+               VK_BLEND_FACTOR_ONE,                                                                            // VkBlend                      srcBlendAlpha;
+               VK_BLEND_FACTOR_ZERO,                                                                           // VkBlend                      destBlendAlpha;
+               VK_BLEND_OP_ADD,                                                                                        // VkBlendOp            blendOpAlpha;
+               (VK_COLOR_COMPONENT_R_BIT |
+                VK_COLOR_COMPONENT_G_BIT |
+                VK_COLOR_COMPONENT_B_BIT |
+                VK_COLOR_COMPONENT_A_BIT)                                                                      // VkChannelFlags       channelWriteMask;
+       };
+
+       static const VkPipelineColorBlendStateCreateInfo        colorBlendStateParams           =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                                                              sType;
+               DE_NULL,                                                                                                        // const void*                                                                  pNext;
+               0,                                                                                                                      // 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                                                                                blendConst[4];
+       };
+
+       return &colorBlendStateParams;
+}
+
+const tcu::TextureFormat& BaseRenderingTestInstance::getTextureFormat (void) const
+{
+       return m_textureFormat;
+}
+
+class BaseTriangleTestInstance : public BaseRenderingTestInstance
+{
+public:
+                                                       BaseTriangleTestInstance        (Context& context, VkPrimitiveTopology primitiveTopology, VkSampleCountFlagBits sampleCount);
+       virtual tcu::TestStatus iterate                                         (void);
+
+private:
+       virtual void                    generateTriangles                       (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles) = DE_NULL;
+
+       int                                             m_iteration;
+       const int                               m_iterationCount;
+       VkPrimitiveTopology             m_primitiveTopology;
+       bool                                    m_allIterationsPassed;
+};
+
+BaseTriangleTestInstance::BaseTriangleTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, VkSampleCountFlagBits sampleCount)
+       : BaseRenderingTestInstance             (context, sampleCount)
+       , m_iteration                                   (0)
+       , m_iterationCount                              (3)
+       , m_primitiveTopology                   (primitiveTopology)
+       , m_allIterationsPassed                 (true)
+{
+}
+
+tcu::TestStatus BaseTriangleTestInstance::iterate (void)
+{
+       const std::string                                                               iterationDescription    = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
+       const tcu::ScopedLogSection                                             section                                 (m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
+       tcu::Surface                                                                    resultImage                             (m_renderSize, m_renderSize);
+       std::vector<tcu::Vec4>                                                  drawBuffer;
+       std::vector<TriangleSceneSpec::SceneTriangle>   triangles;
+
+       generateTriangles(m_iteration, drawBuffer, triangles);
+
+       // draw image
+       drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
+
+       // compare
+       {
+               bool                                    compareOk;
+               RasterizationArguments  args;
+               TriangleSceneSpec               scene;
+
+               tcu::IVec4                              colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
+
+               args.numSamples         = m_multisampling ? 1 : 0;
+               args.subpixelBits       = m_subpixelBits;
+               args.redBits            = colorBits[0];
+               args.greenBits          = colorBits[1];
+               args.blueBits           = colorBits[2];
+
+               scene.triangles.swap(triangles);
+
+               compareOk = verifyTriangleGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
+
+               if (!compareOk)
+                       m_allIterationsPassed = false;
+       }
+
+       // result
+       if (++m_iteration == m_iterationCount)
+       {
+               if (m_allIterationsPassed)
+                       return tcu::TestStatus::pass("Pass");
+               else
+                       return tcu::TestStatus::fail("Incorrect rasterization");
+       }
+       else
+               return tcu::TestStatus::incomplete();
+}
+
+class BaseLineTestInstance : public BaseRenderingTestInstance
+{
+public:
+                                                       BaseLineTestInstance    (Context& context, VkPrimitiveTopology primitiveTopology, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount);
+       virtual tcu::TestStatus iterate                                 (void);
+       virtual float                   getLineWidth                    (void) const;
+
+private:
+       virtual void                    generateLines                   (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines) = DE_NULL;
+
+       int                                             m_iteration;
+       const int                               m_iterationCount;
+       VkPrimitiveTopology             m_primitiveTopology;
+       const PrimitiveWideness m_primitiveWideness;
+       bool                                    m_allIterationsPassed;
+       float                                   m_maxLineWidth;
+       std::vector<float>              m_lineWidths;
+};
+
+BaseLineTestInstance::BaseLineTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
+       : BaseRenderingTestInstance                     (context, sampleCount)
+       , m_iteration                                           (0)
+       , m_iterationCount                                      (3)
+       , m_primitiveTopology                           (primitiveTopology)
+       , m_primitiveWideness                           (wideness)
+       , m_allIterationsPassed                         (true)
+       , m_maxLineWidth                                        (1.0f)
+{
+       DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
+
+       if (!context.getDeviceProperties().limits.strictLines)
+               TCU_THROW(NotSupportedError, "Strict rasterization is not supported");
+
+       // create line widths
+       if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
+       {
+               m_lineWidths.resize(m_iterationCount, 1.0f);
+       }
+       else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
+       {
+               if (!m_context.getDeviceFeatures().wideLines)
+                       TCU_THROW(NotSupportedError , "wide line support required");
+
+               const float*    range = context.getDeviceProperties().limits.lineWidthRange;
+
+               m_context.getTestContext().getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
+
+               // no wide line support
+               if (range[1] <= 1.0f)
+                       TCU_THROW(NotSupportedError, "wide line support required");
+
+               // set hand picked sizes
+               m_lineWidths.push_back(5.0f);
+               m_lineWidths.push_back(10.0f);
+               m_lineWidths.push_back(range[1]);
+               DE_ASSERT((int)m_lineWidths.size() == m_iterationCount);
+
+               m_maxLineWidth = range[1];
+       }
+       else
+               DE_ASSERT(false);
+}
+
+tcu::TestStatus BaseLineTestInstance::iterate (void)
+{
+       const std::string                                               iterationDescription    = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
+       const tcu::ScopedLogSection                             section                                 (m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
+       const float                                                             lineWidth                               = getLineWidth();
+       tcu::Surface                                                    resultImage                             (m_renderSize, m_renderSize);
+       std::vector<tcu::Vec4>                                  drawBuffer;
+       std::vector<LineSceneSpec::SceneLine>   lines;
+
+       // supported?
+       if (lineWidth <= m_maxLineWidth)
+       {
+               // gen data
+               generateLines(m_iteration, drawBuffer, lines);
+
+               // draw image
+               drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
+
+               // compare
+               {
+                       RasterizationArguments  args;
+                       LineSceneSpec                   scene;
+
+
+                       tcu::IVec4                              colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
+
+                       args.numSamples         = m_multisampling ? 1 : 0;
+                       args.subpixelBits       = m_subpixelBits;
+                       args.redBits            = colorBits[0];
+                       args.greenBits          = colorBits[1];
+                       args.blueBits           = colorBits[2];
+
+                       scene.lines.swap(lines);
+                       scene.lineWidth = lineWidth;
+
+                       if (!verifyClippedTriangulatedLineGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog()))
+                               m_allIterationsPassed = false;
+               }
+       }
+       else
+               m_context.getTestContext().getLog() << tcu::TestLog::Message << "Line width " << lineWidth << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
+
+       // result
+       if (++m_iteration == m_iterationCount)
+       {
+               if (m_allIterationsPassed)
+                       return tcu::TestStatus::pass("Pass");
+               else
+                       return tcu::TestStatus::fail("Incorrect rasterization");
+       }
+       else
+               return tcu::TestStatus::incomplete();
+}
+
+
+float BaseLineTestInstance::getLineWidth (void) const
+{
+       return m_lineWidths[m_iteration];
+}
+
+
+class PointTestInstance : public BaseRenderingTestInstance
+{
+public:
+                                                       PointTestInstance               (Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount);
+       virtual tcu::TestStatus iterate                                 (void);
+       virtual float                   getPointSize                    (void) const;
+
+private:
+       virtual void                    generatePoints                  (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints);
+
+       int                                             m_iteration;
+       const int                               m_iterationCount;
+       const PrimitiveWideness m_primitiveWideness;
+       bool                                    m_allIterationsPassed;
+       float                                   m_maxPointSize;
+       std::vector<float>              m_pointSizes;
+};
+
+PointTestInstance::PointTestInstance (Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
+       : BaseRenderingTestInstance     (context, sampleCount)
+       , m_iteration                           (0)
+       , m_iterationCount                      (3)
+       , m_primitiveWideness           (wideness)
+       , m_allIterationsPassed         (true)
+       , m_maxPointSize                        (1.0f)
+{
+       // create point sizes
+       if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
+       {
+               m_pointSizes.resize(m_iterationCount, 1.0f);
+       }
+       else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
+       {
+               if (!m_context.getDeviceFeatures().largePoints)
+                       TCU_THROW(NotSupportedError , "large point support required");
+
+               const float*    range = context.getDeviceProperties().limits.pointSizeRange;
+
+               m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_ALIASED_POINT_SIZE_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
+
+               // no wide line support
+               if (range[1] <= 1.0f)
+                       TCU_THROW(NotSupportedError , "wide point support required");
+
+               // set hand picked sizes
+               m_pointSizes.push_back(10.0f);
+               m_pointSizes.push_back(25.0f);
+               m_pointSizes.push_back(range[1]);
+               DE_ASSERT((int)m_pointSizes.size() == m_iterationCount);
+
+               m_maxPointSize = range[1];
+       }
+       else
+               DE_ASSERT(false);
+}
+
+tcu::TestStatus PointTestInstance::iterate (void)
+{
+       const std::string                                               iterationDescription    = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
+       const tcu::ScopedLogSection                             section                                 (m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
+       const float                                                             pointSize                               = getPointSize();
+       tcu::Surface                                                    resultImage                             (m_renderSize, m_renderSize);
+       std::vector<tcu::Vec4>                                  drawBuffer;
+       std::vector<PointSceneSpec::ScenePoint> points;
+
+       // supported?
+       if (pointSize <= m_maxPointSize)
+       {
+               // gen data
+               generatePoints(m_iteration, drawBuffer, points);
+
+               // draw image
+               drawPrimitives(resultImage, drawBuffer, VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
+
+               // compare
+               {
+                       bool                                    compareOk;
+                       RasterizationArguments  args;
+                       PointSceneSpec                  scene;
+
+                       tcu::IVec4                              colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
+
+                       args.numSamples         = m_multisampling ? 1 : 0;
+                       args.subpixelBits       = m_subpixelBits;
+                       args.redBits            = colorBits[0];
+                       args.greenBits          = colorBits[1];
+                       args.blueBits           = colorBits[2];
+
+                       scene.points.swap(points);
+
+                       compareOk = verifyPointGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
+
+                       if (!compareOk)
+                               m_allIterationsPassed = false;
+               }
+       }
+       else
+               m_context.getTestContext().getLog() << tcu::TestLog::Message << "Point size " << pointSize << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
+
+       // result
+       if (++m_iteration == m_iterationCount)
+       {
+               if (m_allIterationsPassed)
+                       return tcu::TestStatus::pass("Pass");
+               else
+                       return tcu::TestStatus::fail("Incorrect rasterization");
+       }
+       else
+               return tcu::TestStatus::incomplete();
+}
+
+float PointTestInstance::getPointSize (void) const
+{
+       return m_pointSizes[m_iteration];
+}
+
+void PointTestInstance::generatePoints (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints)
+{
+       outData.resize(6);
+
+       switch (iteration)
+       {
+               case 0:
+                       // \note: these values are chosen arbitrarily
+                       outData[0] = tcu::Vec4( 0.2f,  0.8f, 0.0f, 1.0f);
+                       outData[1] = tcu::Vec4( 0.5f,  0.2f, 0.0f, 1.0f);
+                       outData[2] = tcu::Vec4( 0.5f,  0.3f, 0.0f, 1.0f);
+                       outData[3] = tcu::Vec4(-0.5f,  0.2f, 0.0f, 1.0f);
+                       outData[4] = tcu::Vec4(-0.2f, -0.4f, 0.0f, 1.0f);
+                       outData[5] = tcu::Vec4(-0.4f,  0.2f, 0.0f, 1.0f);
+                       break;
+
+               case 1:
+                       outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
+                       outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
+                       outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
+                       outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
+                       outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
+                       outData[5] = tcu::Vec4(   0.4f,   1.2f, 0.0f, 1.0f);
+                       break;
+
+               case 2:
+                       outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
+                       outData[1] = tcu::Vec4(  0.3f, -0.9f, 0.0f, 1.0f);
+                       outData[2] = tcu::Vec4( -0.4f, -0.1f, 0.0f, 1.0f);
+                       outData[3] = tcu::Vec4(-0.11f,  0.2f, 0.0f, 1.0f);
+                       outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
+                       outData[5] = tcu::Vec4( -0.4f,  0.4f, 0.0f, 1.0f);
+                       break;
+       }
+
+       outPoints.resize(outData.size());
+       for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
+       {
+               outPoints[pointNdx].position = outData[pointNdx];
+               outPoints[pointNdx].pointSize = getPointSize();
+       }
+
+       // log
+       m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outPoints.size() << " point(s): (point size = " << getPointSize() << ")" << tcu::TestLog::EndMessage;
+       for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
+               m_context.getTestContext().getLog() << tcu::TestLog::Message << "Point " << (pointNdx+1) << ":\t" << outPoints[pointNdx].position << tcu::TestLog::EndMessage;
+}
+
+template <typename ConcreteTestInstance>
+class BaseTestCase : public BaseRenderingTestCase
+{
+public:
+                                                       BaseTestCase    (tcu::TestContext& context, const std::string& name, const std::string& description, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
+                                                               : BaseRenderingTestCase(context, name, description, sampleCount)
+                                                       {}
+
+       virtual TestInstance*   createInstance  (Context& context) const
+                                                       {
+                                                               return new ConcreteTestInstance(context, m_sampleCount);
+                                                       }
+};
+
+class TrianglesTestInstance : public BaseTriangleTestInstance
+{
+public:
+                                                       TrianglesTestInstance   (Context& context, VkSampleCountFlagBits sampleCount)
+                                                               : BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, sampleCount)
+                                                       {}
+
+       void                                    generateTriangles               (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
+};
+
+void TrianglesTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
+{
+       outData.resize(6);
+
+       switch (iteration)
+       {
+               case 0:
+                       // \note: these values are chosen arbitrarily
+                       outData[0] = tcu::Vec4( 0.2f,  0.8f, 0.0f, 1.0f);
+                       outData[1] = tcu::Vec4( 0.5f,  0.2f, 0.0f, 1.0f);
+                       outData[2] = tcu::Vec4( 0.5f,  0.3f, 0.0f, 1.0f);
+                       outData[3] = tcu::Vec4(-0.5f,  0.2f, 0.0f, 1.0f);
+                       outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f);
+                       outData[5] = tcu::Vec4(-0.4f,  0.2f, 0.0f, 1.0f);
+                       break;
+
+               case 1:
+                       outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
+                       outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
+                       outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
+                       outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
+                       outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
+                       outData[5] = tcu::Vec4(   0.4f,   1.2f, 0.0f, 1.0f);
+                       break;
+
+               case 2:
+                       outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
+                       outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
+                       outData[2] = tcu::Vec4( -1.1f, -0.1f, 0.0f, 1.0f);
+                       outData[3] = tcu::Vec4(-0.11f,  0.2f, 0.0f, 1.0f);
+                       outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
+                       outData[5] = tcu::Vec4( -0.4f,  0.4f, 0.0f, 1.0f);
+                       break;
+       }
+
+       outTriangles.resize(2);
+       outTriangles[0].positions[0] = outData[0];      outTriangles[0].sharedEdge[0] = false;
+       outTriangles[0].positions[1] = outData[1];      outTriangles[0].sharedEdge[1] = false;
+       outTriangles[0].positions[2] = outData[2];      outTriangles[0].sharedEdge[2] = false;
+
+       outTriangles[1].positions[0] = outData[3];      outTriangles[1].sharedEdge[0] = false;
+       outTriangles[1].positions[1] = outData[4];      outTriangles[1].sharedEdge[1] = false;
+       outTriangles[1].positions[2] = outData[5];      outTriangles[1].sharedEdge[2] = false;
+
+       // log
+       m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outTriangles.size() << " triangle(s):" << tcu::TestLog::EndMessage;
+       for (int triangleNdx = 0; triangleNdx < (int)outTriangles.size(); ++triangleNdx)
+       {
+               m_context.getTestContext().getLog()
+                       << tcu::TestLog::Message
+                       << "Triangle " << (triangleNdx+1) << ":"
+                       << "\n\t" << outTriangles[triangleNdx].positions[0]
+                       << "\n\t" << outTriangles[triangleNdx].positions[1]
+                       << "\n\t" << outTriangles[triangleNdx].positions[2]
+                       << tcu::TestLog::EndMessage;
+       }
+}
+
+class TriangleStripTestInstance : public BaseTriangleTestInstance
+{
+public:
+                               TriangleStripTestInstance               (Context& context, VkSampleCountFlagBits sampleCount)
+                                       : BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, sampleCount)
+                               {}
+
+       void            generateTriangles                               (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
+};
+
+void TriangleStripTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
+{
+       outData.resize(5);
+
+       switch (iteration)
+       {
+               case 0:
+                       // \note: these values are chosen arbitrarily
+                       outData[0] = tcu::Vec4(-0.504f,  0.8f,   0.0f, 1.0f);
+                       outData[1] = tcu::Vec4(-0.2f,   -0.2f,   0.0f, 1.0f);
+                       outData[2] = tcu::Vec4(-0.2f,    0.199f, 0.0f, 1.0f);
+                       outData[3] = tcu::Vec4( 0.5f,    0.201f, 0.0f, 1.0f);
+                       outData[4] = tcu::Vec4( 1.5f,    0.4f,   0.0f, 1.0f);
+                       break;
+
+               case 1:
+                       outData[0] = tcu::Vec4(-0.499f, 0.129f,  0.0f, 1.0f);
+                       outData[1] = tcu::Vec4(-0.501f,  -0.3f,  0.0f, 1.0f);
+                       outData[2] = tcu::Vec4(  0.11f,  -0.2f,  0.0f, 1.0f);
+                       outData[3] = tcu::Vec4(  0.11f,  -0.31f, 0.0f, 1.0f);
+                       outData[4] = tcu::Vec4(  0.88f,   0.9f,  0.0f, 1.0f);
+                       break;
+
+               case 2:
+                       outData[0] = tcu::Vec4( -0.9f, -0.3f,  0.0f, 1.0f);
+                       outData[1] = tcu::Vec4(  1.1f, -0.9f,  0.0f, 1.0f);
+                       outData[2] = tcu::Vec4(-0.87f, -0.1f,  0.0f, 1.0f);
+                       outData[3] = tcu::Vec4(-0.11f,  0.19f, 0.0f, 1.0f);
+                       outData[4] = tcu::Vec4( 0.88f,  0.7f,  0.0f, 1.0f);
+                       break;
+       }
+
+       outTriangles.resize(3);
+       outTriangles[0].positions[0] = outData[0];      outTriangles[0].sharedEdge[0] = false;
+       outTriangles[0].positions[1] = outData[1];      outTriangles[0].sharedEdge[1] = true;
+       outTriangles[0].positions[2] = outData[2];      outTriangles[0].sharedEdge[2] = false;
+
+       outTriangles[1].positions[0] = outData[2];      outTriangles[1].sharedEdge[0] = true;
+       outTriangles[1].positions[1] = outData[1];      outTriangles[1].sharedEdge[1] = false;
+       outTriangles[1].positions[2] = outData[3];      outTriangles[1].sharedEdge[2] = true;
+
+       outTriangles[2].positions[0] = outData[2];      outTriangles[2].sharedEdge[0] = true;
+       outTriangles[2].positions[1] = outData[3];      outTriangles[2].sharedEdge[1] = false;
+       outTriangles[2].positions[2] = outData[4];      outTriangles[2].sharedEdge[2] = false;
+
+       // log
+       m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering triangle strip, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
+       for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
+       {
+               m_context.getTestContext().getLog()
+                       << tcu::TestLog::Message
+                       << "\t" << outData[vtxNdx]
+                       << tcu::TestLog::EndMessage;
+       }
+}
+
+class TriangleFanTestInstance : public BaseTriangleTestInstance
+{
+public:
+                               TriangleFanTestInstance                 (Context& context, VkSampleCountFlagBits sampleCount)
+                                       : BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, sampleCount)
+                               {}
+
+       void            generateTriangles                               (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
+};
+
+void TriangleFanTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
+{
+       outData.resize(5);
+
+       switch (iteration)
+       {
+               case 0:
+                       // \note: these values are chosen arbitrarily
+                       outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
+                       outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
+                       outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
+                       outData[3] = tcu::Vec4(-0.5f,   0.2f, 0.0f, 1.0f);
+                       outData[4] = tcu::Vec4(-1.5f,  -0.4f, 0.0f, 1.0f);
+                       break;
+
+               case 1:
+                       outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
+                       outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
+                       outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
+                       outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
+                       outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
+                       break;
+
+               case 2:
+                       outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
+                       outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
+                       outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
+                       outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
+                       outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
+                       break;
+       }
+
+       outTriangles.resize(3);
+       outTriangles[0].positions[0] = outData[0];      outTriangles[0].sharedEdge[0] = false;
+       outTriangles[0].positions[1] = outData[1];      outTriangles[0].sharedEdge[1] = false;
+       outTriangles[0].positions[2] = outData[2];      outTriangles[0].sharedEdge[2] = true;
+
+       outTriangles[1].positions[0] = outData[0];      outTriangles[1].sharedEdge[0] = true;
+       outTriangles[1].positions[1] = outData[2];      outTriangles[1].sharedEdge[1] = false;
+       outTriangles[1].positions[2] = outData[3];      outTriangles[1].sharedEdge[2] = true;
+
+       outTriangles[2].positions[0] = outData[0];      outTriangles[2].sharedEdge[0] = true;
+       outTriangles[2].positions[1] = outData[3];      outTriangles[2].sharedEdge[1] = false;
+       outTriangles[2].positions[2] = outData[4];      outTriangles[2].sharedEdge[2] = false;
+
+       // log
+       m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering triangle fan, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
+       for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
+       {
+               m_context.getTestContext().getLog()
+                       << tcu::TestLog::Message
+                       << "\t" << outData[vtxNdx]
+                       << tcu::TestLog::EndMessage;
+       }
+}
+
+template <typename ConcreteTestInstance>
+class WidenessTestCase : public BaseRenderingTestCase
+{
+public:
+                                                               WidenessTestCase        (tcu::TestContext& context, const std::string& name, const std::string& description, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
+                                                                       : BaseRenderingTestCase(context, name, description, sampleCount)
+                                                                       , m_wideness(wideness)
+                                                               {}
+
+       virtual TestInstance*           createInstance          (Context& context) const
+                                                               {
+                                                                       return new ConcreteTestInstance(context, m_wideness, m_sampleCount);
+                                                               }
+protected:
+       const PrimitiveWideness         m_wideness;
+};
+
+class LinesTestInstance : public BaseLineTestInstance
+{
+public:
+                                                               LinesTestInstance       (Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
+                                                                       : BaseLineTestInstance(context, VK_PRIMITIVE_TOPOLOGY_LINE_LIST, wideness, sampleCount)
+                                                               {}
+
+       virtual void                            generateLines           (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
+};
+
+void LinesTestInstance::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
+{
+       outData.resize(6);
+
+       switch (iteration)
+       {
+               case 0:
+                       // \note: these values are chosen arbitrarily
+                       outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
+                       outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
+                       outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
+                       outData[3] = tcu::Vec4(-0.3f,   0.2f, 0.0f, 1.0f);
+                       outData[4] = tcu::Vec4(-1.5f,  -0.4f, 0.0f, 1.0f);
+                       outData[5] = tcu::Vec4( 0.1f,   0.5f, 0.0f, 1.0f);
+                       break;
+
+               case 1:
+                       outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
+                       outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
+                       outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
+                       outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
+                       outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
+                       outData[5] = tcu::Vec4(  0.18f,  -0.2f, 0.0f, 1.0f);
+                       break;
+
+               case 2:
+                       outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
+                       outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
+                       outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
+                       outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
+                       outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
+                       outData[5] = tcu::Vec4(  0.8f, -0.7f, 0.0f, 1.0f);
+                       break;
+       }
+
+       outLines.resize(3);
+       outLines[0].positions[0] = outData[0];
+       outLines[0].positions[1] = outData[1];
+       outLines[1].positions[0] = outData[2];
+       outLines[1].positions[1] = outData[3];
+       outLines[2].positions[0] = outData[4];
+       outLines[2].positions[1] = outData[5];
+
+       // log
+       m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outLines.size() << " lines(s): (width = " << getLineWidth() << ")" << tcu::TestLog::EndMessage;
+       for (int lineNdx = 0; lineNdx < (int)outLines.size(); ++lineNdx)
+       {
+               m_context.getTestContext().getLog()
+                       << tcu::TestLog::Message
+                       << "Line " << (lineNdx+1) << ":"
+                       << "\n\t" << outLines[lineNdx].positions[0]
+                       << "\n\t" << outLines[lineNdx].positions[1]
+                       << tcu::TestLog::EndMessage;
+       }
+}
+
+class LineStripTestInstance : public BaseLineTestInstance
+{
+public:
+                                       LineStripTestInstance   (Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
+                                               : BaseLineTestInstance(context, VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, wideness, sampleCount)
+                                       {}
+
+       virtual void    generateLines                   (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
+};
+
+void LineStripTestInstance::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
+{
+       outData.resize(4);
+
+       switch (iteration)
+       {
+               case 0:
+                       // \note: these values are chosen arbitrarily
+                       outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
+                       outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
+                       outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
+                       outData[3] = tcu::Vec4(-0.5f,   0.2f, 0.0f, 1.0f);
+                       break;
+
+               case 1:
+                       outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
+                       outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
+                       outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
+                       outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
+                       break;
+
+               case 2:
+                       outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
+                       outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
+                       outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
+                       outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
+                       break;
+       }
+
+       outLines.resize(3);
+       outLines[0].positions[0] = outData[0];
+       outLines[0].positions[1] = outData[1];
+       outLines[1].positions[0] = outData[1];
+       outLines[1].positions[1] = outData[2];
+       outLines[2].positions[0] = outData[2];
+       outLines[2].positions[1] = outData[3];
+
+       // log
+       m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering line strip, width = " << getLineWidth() << ", " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
+       for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
+       {
+               m_context.getTestContext().getLog()
+                       << tcu::TestLog::Message
+                       << "\t" << outData[vtxNdx]
+                       << tcu::TestLog::EndMessage;
+       }
+}
+
+class FillRuleTestInstance : public BaseRenderingTestInstance
+{
+public:
+       enum FillRuleCaseType
+       {
+               FILLRULECASE_BASIC = 0,
+               FILLRULECASE_REVERSED,
+               FILLRULECASE_CLIPPED_FULL,
+               FILLRULECASE_CLIPPED_PARTIAL,
+               FILLRULECASE_PROJECTED,
+
+               FILLRULECASE_LAST
+       };
+                                                                                                               FillRuleTestInstance                    (Context& context, FillRuleCaseType type, VkSampleCountFlagBits sampleCount);
+       virtual tcu::TestStatus                                                         iterate                                                 (void);
+
+private:
+
+       virtual const VkPipelineColorBlendStateCreateInfo*      getColorBlendStateCreateInfo    (void) const;
+       int                                                                                                     getRenderSize                                   (FillRuleCaseType type) const;
+       int                                                                                                     getNumIterations                                (FillRuleCaseType type) const;
+       void                                                                                            generateTriangles                               (int iteration, std::vector<tcu::Vec4>& outData) const;
+
+       const FillRuleCaseType                                                          m_caseType;
+       int                                                                                                     m_iteration;
+       const int                                                                                       m_iterationCount;
+       bool                                                                                            m_allIterationsPassed;
+
+};
+
+FillRuleTestInstance::FillRuleTestInstance (Context& context, FillRuleCaseType type, VkSampleCountFlagBits sampleCount)
+       : BaseRenderingTestInstance             (context, sampleCount, getRenderSize(type))
+       , m_caseType                                    (type)
+       , m_iteration                                   (0)
+       , m_iterationCount                              (getNumIterations(type))
+       , m_allIterationsPassed                 (true)
+{
+       DE_ASSERT(type < FILLRULECASE_LAST);
+}
+
+tcu::TestStatus FillRuleTestInstance::iterate (void)
+{
+       const std::string                                               iterationDescription    = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
+       const tcu::ScopedLogSection                             section                                 (m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
+       tcu::IVec4                                                              colorBits                               = tcu::getTextureFormatBitDepth(getTextureFormat());
+       const int                                                               thresholdRed                    = 1 << (8 - colorBits[0]);
+       const int                                                               thresholdGreen                  = 1 << (8 - colorBits[1]);
+       const int                                                               thresholdBlue                   = 1 << (8 - colorBits[2]);
+       tcu::Surface                                                    resultImage                             (m_renderSize, m_renderSize);
+       std::vector<tcu::Vec4>                                  drawBuffer;
+
+       generateTriangles(m_iteration, drawBuffer);
+
+       // draw image
+       {
+               const std::vector<tcu::Vec4>    colorBuffer             (drawBuffer.size(), tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f));
+
+               m_context.getTestContext().getLog() << tcu::TestLog::Message << "Drawing gray triangles with shared edges.\nEnabling additive blending to detect overlapping fragments." << tcu::TestLog::EndMessage;
+
+               drawPrimitives(resultImage, drawBuffer, colorBuffer, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
+       }
+
+       // verify no overdraw
+       {
+               const tcu::RGBA triangleColor   = tcu::RGBA(127, 127, 127, 255);
+               bool                    overdraw                = false;
+
+               m_context.getTestContext().getLog() << tcu::TestLog::Message << "Verifying result." << tcu::TestLog::EndMessage;
+
+               for (int y = 0; y < resultImage.getHeight(); ++y)
+               for (int x = 0; x < resultImage.getWidth();  ++x)
+               {
+                       const tcu::RGBA color = resultImage.getPixel(x, y);
+
+                       // color values are greater than triangle color? Allow lower values for multisampled edges and background.
+                       if ((color.getRed()   - triangleColor.getRed())   > thresholdRed   ||
+                               (color.getGreen() - triangleColor.getGreen()) > thresholdGreen ||
+                               (color.getBlue()  - triangleColor.getBlue())  > thresholdBlue)
+                               overdraw = true;
+               }
+
+               // results
+               if (!overdraw)
+                       m_context.getTestContext().getLog() << tcu::TestLog::Message << "No overlapping fragments detected." << tcu::TestLog::EndMessage;
+               else
+               {
+                       m_context.getTestContext().getLog()     << tcu::TestLog::Message << "Overlapping fragments detected, image is not valid." << tcu::TestLog::EndMessage;
+                       m_allIterationsPassed = false;
+               }
+       }
+
+       // verify no missing fragments in the full viewport case
+       if (m_caseType == FILLRULECASE_CLIPPED_FULL)
+       {
+               bool missingFragments = false;
+
+               m_context.getTestContext().getLog() << tcu::TestLog::Message << "Searching missing fragments." << tcu::TestLog::EndMessage;
+
+               for (int y = 0; y < resultImage.getHeight(); ++y)
+               for (int x = 0; x < resultImage.getWidth();  ++x)
+               {
+                       const tcu::RGBA color = resultImage.getPixel(x, y);
+
+                       // black? (background)
+                       if (color.getRed()   <= thresholdRed   ||
+                               color.getGreen() <= thresholdGreen ||
+                               color.getBlue()  <= thresholdBlue)
+                               missingFragments = true;
+               }
+
+               // results
+               if (!missingFragments)
+                       m_context.getTestContext().getLog() << tcu::TestLog::Message << "No missing fragments detected." << tcu::TestLog::EndMessage;
+               else
+               {
+                       m_context.getTestContext().getLog()     << tcu::TestLog::Message << "Missing fragments detected, image is not valid." << tcu::TestLog::EndMessage;
+
+                       m_allIterationsPassed = false;
+               }
+       }
+
+       m_context.getTestContext().getLog()     << tcu::TestLog::ImageSet("Result of rendering", "Result of rendering")
+                                                                               << tcu::TestLog::Image("Result", "Result", resultImage)
+                                                                               << tcu::TestLog::EndImageSet;
+
+       // result
+       if (++m_iteration == m_iterationCount)
+       {
+               if (m_allIterationsPassed)
+                       return tcu::TestStatus::pass("Pass");
+               else
+                       return tcu::TestStatus::fail("Found invalid pixels");
+       }
+       else
+               return tcu::TestStatus::incomplete();
+}
+
+int FillRuleTestInstance::getRenderSize (FillRuleCaseType type) const
+{
+       if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
+               return DEFAULT_RENDER_SIZE / 4;
+       else
+               return DEFAULT_RENDER_SIZE;
+}
+
+int FillRuleTestInstance::getNumIterations (FillRuleCaseType type) const
+{
+       if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
+               return 15;
+       else
+               return 2;
+}
+
+void FillRuleTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData) const
+{
+       switch (m_caseType)
+       {
+               case FILLRULECASE_BASIC:
+               case FILLRULECASE_REVERSED:
+               case FILLRULECASE_PROJECTED:
+               {
+                       const int       numRows         = 4;
+                       const int       numColumns      = 4;
+                       const float     quadSide        = 0.15f;
+                       de::Random      rnd                     (0xabcd);
+
+                       outData.resize(6 * numRows * numColumns);
+
+                       for (int col = 0; col < numColumns; ++col)
+                       for (int row = 0; row < numRows;    ++row)
+                       {
+                               const tcu::Vec2 center          = tcu::Vec2(((float)row + 0.5f) / (float)numRows * 2.0f - 1.0f, ((float)col + 0.5f) / (float)numColumns * 2.0f - 1.0f);
+                               const float             rotation        = (float)(iteration * numColumns * numRows + col * numRows + row) / (float)(m_iterationCount * numColumns * numRows) * DE_PI / 2.0f;
+                               const tcu::Vec2 sideH           = quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
+                               const tcu::Vec2 sideV           = tcu::Vec2(sideH.y(), -sideH.x());
+                               const tcu::Vec2 quad[4]         =
+                               {
+                                       center + sideH + sideV,
+                                       center + sideH - sideV,
+                                       center - sideH - sideV,
+                                       center - sideH + sideV,
+                               };
+
+                               if (m_caseType == FILLRULECASE_BASIC)
+                               {
+                                       outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
+                                       outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
+                                       outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
+                                       outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
+                                       outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
+                                       outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
+                               }
+                               else if (m_caseType == FILLRULECASE_REVERSED)
+                               {
+                                       outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
+                                       outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
+                                       outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
+                                       outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
+                                       outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
+                                       outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
+                               }
+                               else if (m_caseType == FILLRULECASE_PROJECTED)
+                               {
+                                       const float w0 = rnd.getFloat(0.1f, 4.0f);
+                                       const float w1 = rnd.getFloat(0.1f, 4.0f);
+                                       const float w2 = rnd.getFloat(0.1f, 4.0f);
+                                       const float w3 = rnd.getFloat(0.1f, 4.0f);
+
+                                       outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
+                                       outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x() * w1, quad[1].y() * w1, 0.0f, w1);
+                                       outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
+                                       outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
+                                       outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
+                                       outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x() * w3, quad[3].y() * w3, 0.0f, w3);
+                               }
+                               else
+                                       DE_ASSERT(DE_FALSE);
+                       }
+
+                       break;
+               }
+
+               case FILLRULECASE_CLIPPED_PARTIAL:
+               case FILLRULECASE_CLIPPED_FULL:
+               {
+                       const float             quadSide        = (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (1.0f) : (2.0f);
+                       const tcu::Vec2 center          = (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (tcu::Vec2(0.5f, 0.5f)) : (tcu::Vec2(0.0f, 0.0f));
+                       const float             rotation        = (float)(iteration) / (float)(m_iterationCount - 1) * DE_PI / 2.0f;
+                       const tcu::Vec2 sideH           = quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
+                       const tcu::Vec2 sideV           = tcu::Vec2(sideH.y(), -sideH.x());
+                       const tcu::Vec2 quad[4]         =
+                       {
+                               center + sideH + sideV,
+                               center + sideH - sideV,
+                               center - sideH - sideV,
+                               center - sideH + sideV,
+                       };
+
+                       outData.resize(6);
+                       outData[0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
+                       outData[1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
+                       outData[2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
+                       outData[3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
+                       outData[4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
+                       outData[5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
+                       break;
+               }
+
+               default:
+                       DE_ASSERT(DE_FALSE);
+       }
+}
+
+const VkPipelineColorBlendStateCreateInfo* FillRuleTestInstance::getColorBlendStateCreateInfo (void) const
+{
+       static const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
+       {
+               true,                                                                                                           // VkBool32                     blendEnable;
+               VK_BLEND_FACTOR_ONE,                                                                            // VkBlend                      srcBlendColor;
+               VK_BLEND_FACTOR_ONE,                                                                            // VkBlend                      destBlendColor;
+               VK_BLEND_OP_ADD,                                                                                        // VkBlendOp            blendOpColor;
+               VK_BLEND_FACTOR_ONE,                                                                            // VkBlend                      srcBlendAlpha;
+               VK_BLEND_FACTOR_ONE,                                                                            // VkBlend                      destBlendAlpha;
+               VK_BLEND_OP_ADD,                                                                                        // VkBlendOp            blendOpAlpha;
+               (VK_COLOR_COMPONENT_R_BIT |
+                VK_COLOR_COMPONENT_G_BIT |
+                VK_COLOR_COMPONENT_B_BIT |
+                VK_COLOR_COMPONENT_A_BIT)                                                                      // VkChannelFlags       channelWriteMask;
+       };
+
+       static const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                                                              sType;
+               DE_NULL,                                                                                                        // const void*                                                                  pNext;
+               0,                                                                                                                      // 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                                                                                blendConst[4];
+       };
+
+       return &colorBlendStateParams;
+}
+
+
+class FillRuleTestCase : public BaseRenderingTestCase
+{
+public:
+                                                               FillRuleTestCase        (tcu::TestContext& context, const std::string& name, const std::string& description, FillRuleTestInstance::FillRuleCaseType type, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
+                                                                       : BaseRenderingTestCase (context, name, description, sampleCount)
+                                                                       , m_type                                (type)
+                                                               {}
+
+       virtual TestInstance*           createInstance          (Context& context) const
+                                                               {
+                                                                       return new FillRuleTestInstance(context, m_type, m_sampleCount);
+                                                               }
+protected:
+       const FillRuleTestInstance::FillRuleCaseType m_type;
+};
+
+class CullingTestInstance : public BaseRenderingTestInstance
+{
+public:
+                                                                                                       CullingTestInstance                             (Context& context, VkCullModeFlags cullMode, VkPrimitiveTopology primitiveTopology, VkFrontFace frontFace)
+                                                                                                               : BaseRenderingTestInstance             (context, VK_SAMPLE_COUNT_1_BIT, DEFAULT_RENDER_SIZE)
+                                                                                                               , m_cullMode                                    (cullMode)
+                                                                                                               , m_primitiveTopology                   (primitiveTopology)
+                                                                                                               , m_frontFace                                   (frontFace)
+                                                                                                       {}
+       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;
+       bool                                                                                    triangleOrder                                   (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const;
+
+       const VkCullModeFlags                                                   m_cullMode;
+       const VkPrimitiveTopology                                               m_primitiveTopology;
+       const VkFrontFace                                                               m_frontFace;
+};
+
+tcu::TestStatus CullingTestInstance::iterate (void)
+{
+       tcu::Surface                                                                    resultImage                                             (m_renderSize, m_renderSize);
+       std::vector<tcu::Vec4>                                                  drawBuffer;
+       std::vector<TriangleSceneSpec::SceneTriangle>   triangles;
+
+       // generate scene
+       generateVertices(drawBuffer);
+       extractTriangles(triangles, drawBuffer);
+
+       // draw image
+       {
+               m_context.getTestContext().getLog() << tcu::TestLog::Message << "Setting front face to " << m_frontFace << tcu::TestLog::EndMessage;
+               m_context.getTestContext().getLog() << tcu::TestLog::Message << "Setting cull face to " << m_cullMode << tcu::TestLog::EndMessage;
+               m_context.getTestContext().getLog() << tcu::TestLog::Message << "Drawing test pattern (" << m_primitiveTopology << ")" << tcu::TestLog::EndMessage;
+
+               drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
+       }
+
+       // compare
+       {
+               RasterizationArguments  args;
+               TriangleSceneSpec               scene;
+               tcu::IVec4                              colorBits       = tcu::getTextureFormatBitDepth(getTextureFormat());
+
+               args.numSamples         = m_multisampling ? 1 : 0;
+               args.subpixelBits       = m_subpixelBits;
+               args.redBits            = colorBits[0];
+               args.greenBits          = colorBits[1];
+               args.blueBits           = colorBits[2];
+
+               scene.triangles.swap(triangles);
+
+               if (verifyTriangleGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog(), tcu::VERIFICATIONMODE_WEAK))
+                       return tcu::TestStatus::pass("Pass");
+               else
+                       return tcu::TestStatus::fail("Incorrect rendering");
+       }
+}
+
+void CullingTestInstance::generateVertices (std::vector<tcu::Vec4>& outData) const
+{
+       de::Random rnd(543210);
+
+       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 CullingTestInstance::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const
+{
+       const bool cullDirection = (m_cullMode == VK_CULL_MODE_FRONT_BIT) ^ (m_frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE);
+
+       // No triangles
+       if (m_cullMode == VK_CULL_MODE_FRONT_AND_BACK)
+               return;
+
+       switch (m_primitiveTopology)
+       {
+               case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
+               {
+                       for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
+                       {
+                               const tcu::Vec4& v0 = vertices[vtxNdx + 0];
+                               const tcu::Vec4& v1 = vertices[vtxNdx + 1];
+                               const tcu::Vec4& v2 = vertices[vtxNdx + 2];
+
+                               if (triangleOrder(v0, v1, v2) != cullDirection)
+                               {
+                                       TriangleSceneSpec::SceneTriangle tri;
+                                       tri.positions[0] = v0;  tri.sharedEdge[0] = false;
+                                       tri.positions[1] = v1;  tri.sharedEdge[1] = false;
+                                       tri.positions[2] = v2;  tri.sharedEdge[2] = false;
+
+                                       outTriangles.push_back(tri);
+                               }
+                       }
+                       break;
+               }
+
+               case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
+               {
+                       for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
+                       {
+                               const tcu::Vec4& v0 = vertices[vtxNdx + 0];
+                               const tcu::Vec4& v1 = vertices[vtxNdx + 1];
+                               const tcu::Vec4& v2 = vertices[vtxNdx + 2];
+
+                               if (triangleOrder(v0, v1, v2) != (cullDirection ^ (vtxNdx % 2 != 0)))
+                               {
+                                       TriangleSceneSpec::SceneTriangle tri;
+                                       tri.positions[0] = v0;  tri.sharedEdge[0] = false;
+                                       tri.positions[1] = v1;  tri.sharedEdge[1] = false;
+                                       tri.positions[2] = v2;  tri.sharedEdge[2] = false;
+
+                                       outTriangles.push_back(tri);
+                               }
+                       }
+                       break;
+               }
+
+               case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
+               {
+                       for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
+                       {
+                               const tcu::Vec4& v0 = vertices[0];
+                               const tcu::Vec4& v1 = vertices[vtxNdx + 0];
+                               const tcu::Vec4& v2 = vertices[vtxNdx + 1];
+
+                               if (triangleOrder(v0, v1, v2) != cullDirection)
+                               {
+                                       TriangleSceneSpec::SceneTriangle tri;
+                                       tri.positions[0] = v0;  tri.sharedEdge[0] = false;
+                                       tri.positions[1] = v1;  tri.sharedEdge[1] = false;
+                                       tri.positions[2] = v2;  tri.sharedEdge[2] = false;
+
+                                       outTriangles.push_back(tri);
+                               }
+                       }
+                       break;
+               }
+
+               default:
+                       DE_ASSERT(false);
+       }
+}
+
+bool CullingTestInstance::triangleOrder (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const
+{
+       const tcu::Vec2 s0 = v0.swizzle(0, 1) / v0.w();
+       const tcu::Vec2 s1 = v1.swizzle(0, 1) / v1.w();
+       const tcu::Vec2 s2 = v2.swizzle(0, 1) / v2.w();
+
+       // cross
+       return ((s1.x() - s0.x()) * (s2.y() - s0.y()) - (s2.x() - s0.x()) * (s1.y() - s0.y())) > 0;
+}
+
+
+const VkPipelineRasterizationStateCreateInfo* CullingTestInstance::getRasterizationStateCreateInfo (void) const
+{
+       static VkPipelineRasterizationStateCreateInfo   rasterizationStateCreateInfo    =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                                                      sType;
+               DE_NULL,                                                                                                                // const void*                                                          pNext;
+               0,                                                                                                                              // VkPipelineRasterizationStateCreateFlags      flags;
+               false,                                                                                                                  // VkBool32                                                                     depthClipEnable;
+               false,                                                                                                                  // 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;
+       };
+
+       rasterizationStateCreateInfo.lineWidth = getLineWidth();
+       rasterizationStateCreateInfo.cullMode  = m_cullMode;
+       rasterizationStateCreateInfo.frontFace = m_frontFace;
+
+       return &rasterizationStateCreateInfo;
+}
+
+class CullingTestCase : public BaseRenderingTestCase
+{
+public:
+                                                               CullingTestCase         (tcu::TestContext& context, const std::string& name, const std::string& description, VkCullModeFlags cullMode, VkPrimitiveTopology primitiveTopology, VkFrontFace frontFace, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
+                                                                       : BaseRenderingTestCase (context, name, description, sampleCount)
+                                                                       , m_cullMode                    (cullMode)
+                                                                       , m_primitiveTopology   (primitiveTopology)
+                                                                       , m_frontFace                   (frontFace)
+                                                               {}
+
+       virtual TestInstance*           createInstance          (Context& context) const
+                                                               {
+                                                                       return new CullingTestInstance(context, m_cullMode, m_primitiveTopology, m_frontFace);
+                                                               }
+protected:
+       const VkCullModeFlags           m_cullMode;
+       const VkPrimitiveTopology       m_primitiveTopology;
+       const VkFrontFace                       m_frontFace;
+};
+
+class TriangleInterpolationTestInstance : public BaseRenderingTestInstance
+{
+public:
+
+                                                               TriangleInterpolationTestInstance       (Context& context, VkPrimitiveTopology primitiveTopology, int flags, VkSampleCountFlagBits sampleCount)
+                                                                       : BaseRenderingTestInstance     (context, sampleCount, DEFAULT_RENDER_SIZE)
+                                                                       , m_primitiveTopology           (primitiveTopology)
+                                                                       , m_projective                          ((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
+                                                                       , m_iterationCount                      (3)
+                                                                       , m_iteration                           (0)
+                                                                       , m_allIterationsPassed         (true)
+                                                                       , m_flatshade                           ((flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
+                                                               {}
+
+       tcu::TestStatus                         iterate                                                         (void);
+
+
+private:
+       void                                            generateVertices                                        (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
+       void                                            extractTriangles                                        (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
+
+
+       VkPrimitiveTopology                     m_primitiveTopology;
+       const bool                                      m_projective;
+       const int                                       m_iterationCount;
+       int                                                     m_iteration;
+       bool                                            m_allIterationsPassed;
+       const deBool                            m_flatshade;
+};
+
+tcu::TestStatus TriangleInterpolationTestInstance::iterate (void)
+{
+       const std::string                                                               iterationDescription    = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
+       const tcu::ScopedLogSection                                             section                                 (m_context.getTestContext().getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
+       tcu::Surface                                                                    resultImage                             (m_renderSize, m_renderSize);
+       std::vector<tcu::Vec4>                                                  drawBuffer;
+       std::vector<tcu::Vec4>                                                  colorBuffer;
+       std::vector<TriangleSceneSpec::SceneTriangle>   triangles;
+
+       // generate scene
+       generateVertices(m_iteration, drawBuffer, colorBuffer);
+       extractTriangles(triangles, drawBuffer, colorBuffer);
+
+       // log
+       {
+               m_context.getTestContext().getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
+               for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
+                       m_context.getTestContext().getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
+       }
+
+       // draw image
+       drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitiveTopology);
+
+       // compare
+       {
+               RasterizationArguments  args;
+               TriangleSceneSpec               scene;
+               tcu::IVec4                              colorBits       = tcu::getTextureFormatBitDepth(getTextureFormat());
+
+               args.numSamples         = m_multisampling ? 1 : 0;
+               args.subpixelBits       = m_subpixelBits;
+               args.redBits            = colorBits[0];
+               args.greenBits          = colorBits[1];
+               args.blueBits           = colorBits[2];
+
+               scene.triangles.swap(triangles);
+
+               if (!verifyTriangleGroupInterpolation(resultImage, scene, args, m_context.getTestContext().getLog()))
+                       m_allIterationsPassed = false;
+       }
+
+       // result
+       if (++m_iteration == m_iterationCount)
+       {
+               if (m_allIterationsPassed)
+                       return tcu::TestStatus::pass("Pass");
+               else
+                       return tcu::TestStatus::fail("Found invalid pixel values");
+       }
+       else
+               return tcu::TestStatus::incomplete();
+}
+
+void TriangleInterpolationTestInstance::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
+{
+       // use only red, green and blue
+       const tcu::Vec4 colors[] =
+       {
+               tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
+               tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
+               tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
+       };
+
+       de::Random rnd(123 + iteration * 1000 + (int)m_primitiveTopology);
+
+       outVertices.resize(6);
+       outColors.resize(6);
+
+       for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
+       {
+               outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
+               outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
+               outVertices[vtxNdx].z() = 0.0f;
+
+               if (!m_projective)
+                       outVertices[vtxNdx].w() = 1.0f;
+               else
+               {
+                       const float w = rnd.getFloat(0.2f, 4.0f);
+
+                       outVertices[vtxNdx].x() *= w;
+                       outVertices[vtxNdx].y() *= w;
+                       outVertices[vtxNdx].z() *= w;
+                       outVertices[vtxNdx].w() = w;
+               }
+
+               outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
+       }
+}
+
+void TriangleInterpolationTestInstance::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
+{
+       switch (m_primitiveTopology)
+       {
+               case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
+               {
+                       for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
+                       {
+                               TriangleSceneSpec::SceneTriangle tri;
+                               tri.positions[0]        = vertices[vtxNdx + 0];
+                               tri.positions[1]        = vertices[vtxNdx + 1];
+                               tri.positions[2]        = vertices[vtxNdx + 2];
+                               tri.sharedEdge[0]       = false;
+                               tri.sharedEdge[1]       = false;
+                               tri.sharedEdge[2]       = false;
+
+                               if (m_flatshade)
+                               {
+                                       tri.colors[0] = colors[vtxNdx];
+                                       tri.colors[1] = colors[vtxNdx];
+                                       tri.colors[2] = colors[vtxNdx];
+                               }
+                               else
+                               {
+                                       tri.colors[0] = colors[vtxNdx + 0];
+                                       tri.colors[1] = colors[vtxNdx + 1];
+                                       tri.colors[2] = colors[vtxNdx + 2];
+                               }
+
+                               outTriangles.push_back(tri);
+                       }
+                       break;
+               }
+
+               case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
+               {
+                       for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
+                       {
+                               TriangleSceneSpec::SceneTriangle tri;
+                               tri.positions[0]        = vertices[vtxNdx + 0];
+                               tri.positions[1]        = vertices[vtxNdx + 1];
+                               tri.positions[2]        = vertices[vtxNdx + 2];
+                               tri.sharedEdge[0]       = false;
+                               tri.sharedEdge[1]       = false;
+                               tri.sharedEdge[2]       = false;
+
+                               if (m_flatshade)
+                               {
+                                       tri.colors[0] = colors[vtxNdx];
+                                       tri.colors[1] = colors[vtxNdx];
+                                       tri.colors[2] = colors[vtxNdx];
+                               }
+                               else
+                               {
+                                       tri.colors[0] = colors[vtxNdx + 0];
+                                       tri.colors[1] = colors[vtxNdx + 1];
+                                       tri.colors[2] = colors[vtxNdx + 2];
+                               }
+
+                               outTriangles.push_back(tri);
+                       }
+                       break;
+               }
+
+               case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
+               {
+                       for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
+                       {
+                               TriangleSceneSpec::SceneTriangle tri;
+                               tri.positions[0]        = vertices[0];
+                               tri.positions[1]        = vertices[vtxNdx + 0];
+                               tri.positions[2]        = vertices[vtxNdx + 1];
+                               tri.sharedEdge[0]       = false;
+                               tri.sharedEdge[1]       = false;
+                               tri.sharedEdge[2]       = false;
+
+                               if (m_flatshade)
+                               {
+                                       tri.colors[0] = colors[vtxNdx];
+                                       tri.colors[1] = colors[vtxNdx];
+                                       tri.colors[2] = colors[vtxNdx];
+                               }
+                               else
+                               {
+                                       tri.colors[0] = colors[0];
+                                       tri.colors[1] = colors[vtxNdx + 0];
+                                       tri.colors[2] = colors[vtxNdx + 1];
+                               }
+
+                               outTriangles.push_back(tri);
+                       }
+                       break;
+               }
+
+               default:
+                       DE_ASSERT(false);
+       }
+}
+
+class TriangleInterpolationTestCase : public BaseRenderingTestCase
+{
+public:
+                                                               TriangleInterpolationTestCase   (tcu::TestContext& context, const std::string& name, const std::string& description, VkPrimitiveTopology primitiveTopology, int flags, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
+                                                                       : BaseRenderingTestCase         (context, name, description, sampleCount, (flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
+                                                                       , m_primitiveTopology           (primitiveTopology)
+                                                                       , m_flags                                       (flags)
+                                                               {}
+
+       virtual TestInstance*           createInstance                                  (Context& context) const
+                                                               {
+                                                                       return new TriangleInterpolationTestInstance(context, m_primitiveTopology, m_flags, m_sampleCount);
+                                                               }
+protected:
+       const VkPrimitiveTopology       m_primitiveTopology;
+       const int                                       m_flags;
+};
+
+class LineInterpolationTestInstance : public BaseRenderingTestInstance
+{
+public:
+                                                       LineInterpolationTestInstance   (Context& context, VkPrimitiveTopology primitiveTopology, int flags, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount);
+
+       virtual tcu::TestStatus iterate                                                 (void);
+
+private:
+       void                                    generateVertices                                (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
+       void                                    extractLines                                    (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
+       virtual float                   getLineWidth                                    (void) const;
+
+       VkPrimitiveTopology             m_primitiveTopology;
+       const bool                              m_projective;
+       const int                               m_iterationCount;
+       const PrimitiveWideness m_primitiveWideness;
+
+       int                                             m_iteration;
+       bool                                    m_allIterationsPassed;
+       float                                   m_maxLineWidth;
+       std::vector<float>              m_lineWidths;
+       bool                                    m_flatshade;
+};
+
+LineInterpolationTestInstance::LineInterpolationTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, int flags, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
+       : BaseRenderingTestInstance                     (context, sampleCount)
+       , m_primitiveTopology                           (primitiveTopology)
+       , m_projective                                          ((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
+       , m_iterationCount                                      (3)
+       , m_primitiveWideness                           (wideness)
+       , m_iteration                                           (0)
+       , m_allIterationsPassed                         (true)
+       , m_maxLineWidth                                        (1.0f)
+       , m_flatshade                                           ((flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
+{
+       DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
+
+       if (!context.getDeviceProperties().limits.strictLines)
+               TCU_THROW(NotSupportedError, "Strict rasterization is not supported");
+
+       // create line widths
+       if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
+       {
+               m_lineWidths.resize(m_iterationCount, 1.0f);
+       }
+       else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
+       {
+               if (!m_context.getDeviceFeatures().wideLines)
+                       TCU_THROW(NotSupportedError , "wide line support required");
+
+               const float*    range = context.getDeviceProperties().limits.lineWidthRange;
+
+               m_context.getTestContext().getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
+
+               // no wide line support
+               if (range[1] <= 1.0f)
+                       throw tcu::NotSupportedError("wide line support required");
+
+               // set hand picked sizes
+               m_lineWidths.push_back(5.0f);
+               m_lineWidths.push_back(10.0f);
+               m_lineWidths.push_back(range[1]);
+               DE_ASSERT((int)m_lineWidths.size() == m_iterationCount);
+
+               m_maxLineWidth = range[1];
+       }
+       else
+               DE_ASSERT(false);
+}
+
+tcu::TestStatus LineInterpolationTestInstance::iterate (void)
+{
+       const std::string                                               iterationDescription    = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
+       const tcu::ScopedLogSection                             section                                 (m_context.getTestContext().getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
+       const float                                                             lineWidth                               = getLineWidth();
+       tcu::Surface                                                    resultImage                             (m_renderSize, m_renderSize);
+       std::vector<tcu::Vec4>                                  drawBuffer;
+       std::vector<tcu::Vec4>                                  colorBuffer;
+       std::vector<LineSceneSpec::SceneLine>   lines;
+
+       // supported?
+       if (lineWidth <= m_maxLineWidth)
+       {
+               // generate scene
+               generateVertices(m_iteration, drawBuffer, colorBuffer);
+               extractLines(lines, drawBuffer, colorBuffer);
+
+               // log
+               {
+                       m_context.getTestContext().getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
+                       for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
+                               m_context.getTestContext().getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
+               }
+
+               // draw image
+               drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitiveTopology);
+
+               // compare
+               {
+                       RasterizationArguments  args;
+                       LineSceneSpec                   scene;
+
+                       tcu::IVec4                              colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
+
+                       args.numSamples         = m_multisampling ? 1 : 0;
+                       args.subpixelBits       = m_subpixelBits;
+                       args.redBits            = colorBits[0];
+                       args.greenBits          = colorBits[1];
+                       args.blueBits           = colorBits[2];
+
+                       scene.lines.swap(lines);
+                       scene.lineWidth = getLineWidth();
+
+                       if (!verifyTriangulatedLineGroupInterpolation(resultImage, scene, args, m_context.getTestContext().getLog()))
+                               m_allIterationsPassed = false;
+               }
+       }
+       else
+               m_context.getTestContext().getLog() << tcu::TestLog::Message << "Line width " << lineWidth << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
+
+       // result
+       if (++m_iteration == m_iterationCount)
+       {
+               if (m_allIterationsPassed)
+                       return tcu::TestStatus::pass("Pass");
+               else
+                       return tcu::TestStatus::fail("Incorrect rasterization");
+       }
+       else
+               return tcu::TestStatus::incomplete();
+}
+
+void LineInterpolationTestInstance::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
+{
+       // use only red, green and blue
+       const tcu::Vec4 colors[] =
+       {
+               tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
+               tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
+               tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
+       };
+
+       de::Random rnd(123 + iteration * 1000 + (int)m_primitiveTopology);
+
+       outVertices.resize(6);
+       outColors.resize(6);
+
+       for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
+       {
+               outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
+               outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
+               outVertices[vtxNdx].z() = 0.0f;
+
+               if (!m_projective)
+                       outVertices[vtxNdx].w() = 1.0f;
+               else
+               {
+                       const float w = rnd.getFloat(0.2f, 4.0f);
+
+                       outVertices[vtxNdx].x() *= w;
+                       outVertices[vtxNdx].y() *= w;
+                       outVertices[vtxNdx].z() *= w;
+                       outVertices[vtxNdx].w() = w;
+               }
+
+               outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
+       }
+}
+
+void LineInterpolationTestInstance::extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) 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];
+
+                               if (m_flatshade)
+                               {
+                                       line.colors[0] = colors[vtxNdx];
+                                       line.colors[1] = colors[vtxNdx];
+                               }
+                               else
+                               {
+                                       line.colors[0] = colors[vtxNdx + 0];
+                                       line.colors[1] = colors[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];
+
+                               if (m_flatshade)
+                               {
+                                       line.colors[0] = colors[vtxNdx];
+                                       line.colors[1] = colors[vtxNdx];
+                               }
+                               else
+                               {
+                                       line.colors[0] = colors[vtxNdx + 0];
+                                       line.colors[1] = colors[vtxNdx + 1];
+                               }
+
+                               outLines.push_back(line);
+                       }
+                       break;
+               }
+
+               default:
+                       DE_ASSERT(false);
+       }
+}
+
+float LineInterpolationTestInstance::getLineWidth (void) const
+{
+       return m_lineWidths[m_iteration];
+}
+
+class LineInterpolationTestCase : public BaseRenderingTestCase
+{
+public:
+                                                               LineInterpolationTestCase               (tcu::TestContext& context, const std::string& name, const std::string& description, VkPrimitiveTopology primitiveTopology, int flags, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
+                                                                       : BaseRenderingTestCase         (context, name, description, sampleCount, (flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
+                                                                       , m_primitiveTopology           (primitiveTopology)
+                                                                       , m_flags                                       (flags)
+                                                                       , m_wideness                            (wideness)
+                                                               {}
+
+       virtual TestInstance*           createInstance                                  (Context& context) const
+                                                               {
+                                                                       return new LineInterpolationTestInstance(context, m_primitiveTopology, m_flags, m_wideness, m_sampleCount);
+                                                               }
+protected:
+       const VkPrimitiveTopology       m_primitiveTopology;
+       const int                                       m_flags;
+       const PrimitiveWideness         m_wideness;
+};
+
+void createRasterizationTests (tcu::TestCaseGroup* rasterizationTests)
+{
+       tcu::TestContext&       testCtx         =       rasterizationTests->getTestContext();
+
+       // .primitives
+       {
+               tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(testCtx, "primitives", "Primitive rasterization");
+
+               rasterizationTests->addChild(primitives);
+
+               primitives->addChild(new BaseTestCase<TrianglesTestInstance>            (testCtx, "triangles",                  "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, verify rasterization result"));
+               primitives->addChild(new BaseTestCase<TriangleStripTestInstance>        (testCtx, "triangle_strip",             "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, verify rasterization result"));
+               primitives->addChild(new BaseTestCase<TriangleFanTestInstance>          (testCtx, "triangle_fan",               "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, verify rasterization result"));
+               primitives->addChild(new WidenessTestCase<LinesTestInstance>            (testCtx, "lines",                              "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result",                                            PRIMITIVEWIDENESS_NARROW));
+               primitives->addChild(new WidenessTestCase<LineStripTestInstance>        (testCtx, "line_strip",                 "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result",                                           PRIMITIVEWIDENESS_NARROW));
+               primitives->addChild(new WidenessTestCase<LinesTestInstance>            (testCtx, "lines_wide",                 "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result",            PRIMITIVEWIDENESS_WIDE));
+               primitives->addChild(new WidenessTestCase<LineStripTestInstance>        (testCtx, "line_strip_wide",    "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP with wide lines, verify rasterization result",           PRIMITIVEWIDENESS_WIDE));
+               primitives->addChild(new WidenessTestCase<PointTestInstance>            (testCtx, "points",                             "Render primitives as VK_PRIMITIVE_TOPOLOGY_POINT_LIST, verify rasterization result",                                           PRIMITIVEWIDENESS_WIDE));
+       }
+
+       // .fill_rules
+       {
+               tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(testCtx, "fill_rules", "Primitive fill rules");
+
+               rasterizationTests->addChild(fillRules);
+
+               fillRules->addChild(new FillRuleTestCase(testCtx,       "basic_quad",                   "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_BASIC));
+               fillRules->addChild(new FillRuleTestCase(testCtx,       "basic_quad_reverse",   "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_REVERSED));
+               fillRules->addChild(new FillRuleTestCase(testCtx,       "clipped_full",                 "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_CLIPPED_FULL));
+               fillRules->addChild(new FillRuleTestCase(testCtx,       "clipped_partly",               "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_CLIPPED_PARTIAL));
+               fillRules->addChild(new FillRuleTestCase(testCtx,       "projected",                    "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_PROJECTED));
+       }
+
+       // .culling
+       {
+               static const struct CullMode
+               {
+                       VkCullModeFlags mode;
+                       const char*             prefix;
+               } cullModes[] =
+               {
+                       { VK_CULL_MODE_FRONT_BIT,                               "front_"        },
+                       { VK_CULL_MODE_BACK_BIT,                                "back_"         },
+                       { VK_CULL_MODE_FRONT_AND_BACK,                  "both_"         },
+               };
+               static const struct PrimitiveType
+               {
+                       VkPrimitiveTopology     type;
+                       const char*                     name;
+               } primitiveTypes[] =
+               {
+                       { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,                  "triangles"                     },
+                       { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,                 "triangle_strip"        },
+                       { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,                   "triangle_fan"          },
+               };
+               static const struct FrontFaceOrder
+               {
+                       VkFrontFace     mode;
+                       const char*     postfix;
+               } frontOrders[] =
+               {
+                       { VK_FRONT_FACE_COUNTER_CLOCKWISE,      ""                      },
+                       { VK_FRONT_FACE_CLOCKWISE,                      "_reverse"      },
+               };
+
+               tcu::TestCaseGroup* const culling = new tcu::TestCaseGroup(testCtx, "culling", "Culling");
+
+               rasterizationTests->addChild(culling);
+
+               for (int cullModeNdx   = 0; cullModeNdx   < DE_LENGTH_OF_ARRAY(cullModes);      ++cullModeNdx)
+               for (int primitiveNdx  = 0; primitiveNdx  < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveNdx)
+               for (int frontOrderNdx = 0; frontOrderNdx < DE_LENGTH_OF_ARRAY(frontOrders);    ++frontOrderNdx)
+               {
+                       const std::string name = std::string(cullModes[cullModeNdx].prefix) + primitiveTypes[primitiveNdx].name + frontOrders[frontOrderNdx].postfix;
+
+                       culling->addChild(new CullingTestCase(testCtx, name, "Test primitive culling.", cullModes[cullModeNdx].mode, primitiveTypes[primitiveNdx].type, frontOrders[frontOrderNdx].mode));
+               }
+       }
+
+       // .interpolation
+       {
+               tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(testCtx, "interpolation", "Test interpolation");
+
+               rasterizationTests->addChild(interpolation);
+
+               // .basic
+               {
+                       tcu::TestCaseGroup* const basic = new tcu::TestCaseGroup(testCtx, "basic", "Non-projective interpolation");
+
+                       interpolation->addChild(basic);
+
+                       basic->addChild(new TriangleInterpolationTestCase               (testCtx, "triangles",          "Verify triangle interpolation",                VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,    INTERPOLATIONFLAGS_NONE));
+                       basic->addChild(new TriangleInterpolationTestCase               (testCtx, "triangle_strip",     "Verify triangle strip interpolation",  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,   INTERPOLATIONFLAGS_NONE));
+                       basic->addChild(new TriangleInterpolationTestCase               (testCtx, "triangle_fan",       "Verify triangle fan interpolation",    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,             INTERPOLATIONFLAGS_NONE));
+                       basic->addChild(new LineInterpolationTestCase                   (testCtx, "lines",                      "Verify line interpolation",                    VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_NARROW));
+                       basic->addChild(new LineInterpolationTestCase                   (testCtx, "line_strip",         "Verify line strip interpolation",              VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_NARROW));
+                       basic->addChild(new LineInterpolationTestCase                   (testCtx, "lines_wide",         "Verify wide line interpolation",               VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_WIDE));
+                       basic->addChild(new LineInterpolationTestCase                   (testCtx, "line_strip_wide","Verify wide line strip interpolation",     VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_WIDE));
+               }
+
+               // .projected
+               {
+                       tcu::TestCaseGroup* const projected = new tcu::TestCaseGroup(testCtx, "projected", "Projective interpolation");
+
+                       interpolation->addChild(projected);
+
+                       projected->addChild(new TriangleInterpolationTestCase   (testCtx, "triangles",          "Verify triangle interpolation",                VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,    INTERPOLATIONFLAGS_PROJECTED));
+                       projected->addChild(new TriangleInterpolationTestCase   (testCtx, "triangle_strip",     "Verify triangle strip interpolation",  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,   INTERPOLATIONFLAGS_PROJECTED));
+                       projected->addChild(new TriangleInterpolationTestCase   (testCtx, "triangle_fan",       "Verify triangle fan interpolation",    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,             INTERPOLATIONFLAGS_PROJECTED));
+                       projected->addChild(new LineInterpolationTestCase               (testCtx, "lines",                      "Verify line interpolation",                    VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_NARROW));
+                       projected->addChild(new LineInterpolationTestCase               (testCtx, "line_strip",         "Verify line strip interpolation",              VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_NARROW));
+                       projected->addChild(new LineInterpolationTestCase               (testCtx, "lines_wide",         "Verify wide line interpolation",               VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_WIDE));
+                       projected->addChild(new LineInterpolationTestCase               (testCtx, "line_strip_wide","Verify wide line strip interpolation",     VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_WIDE));
+               }
+       }
+
+       // .flatshading
+       {
+               tcu::TestCaseGroup* const flatshading = new tcu::TestCaseGroup(testCtx, "flatshading", "Test flatshading");
+
+               rasterizationTests->addChild(flatshading);
+
+               flatshading->addChild(new TriangleInterpolationTestCase         (testCtx, "triangles",          "Verify triangle flatshading",                  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,    INTERPOLATIONFLAGS_FLATSHADE));
+               flatshading->addChild(new TriangleInterpolationTestCase         (testCtx, "triangle_strip",     "Verify triangle strip flatshading",    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,   INTERPOLATIONFLAGS_FLATSHADE));
+               flatshading->addChild(new TriangleInterpolationTestCase         (testCtx, "triangle_fan",       "Verify triangle fan flatshading",              VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,             INTERPOLATIONFLAGS_FLATSHADE));
+               flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "lines",                      "Verify line flatshading",                              VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_NARROW));
+               flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "line_strip",         "Verify line strip flatshading",                VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_NARROW));
+               flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "lines_wide",         "Verify wide line flatshading",                 VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_WIDE));
+               flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "line_strip_wide","Verify wide line strip flatshading",       VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_WIDE));
+       }
+
+       const VkSampleCountFlagBits samples[] =
+       {
+               VK_SAMPLE_COUNT_2_BIT,
+               VK_SAMPLE_COUNT_4_BIT,
+               VK_SAMPLE_COUNT_8_BIT,
+               VK_SAMPLE_COUNT_16_BIT,
+               VK_SAMPLE_COUNT_32_BIT,
+               VK_SAMPLE_COUNT_64_BIT
+       };
+
+       for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
+       {
+               std::ostringstream caseName;
+
+               caseName << "_multisample_" << (2 << samplesNdx) << "_bit";
+
+               // .primitives
+               {
+                       tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(testCtx, ("primitives" + caseName.str()).c_str(), "Primitive rasterization");
+
+                       rasterizationTests->addChild(primitives);
+
+                       primitives->addChild(new BaseTestCase<TrianglesTestInstance>            (testCtx, "triangles",                  "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, verify rasterization result",                                        samples[samplesNdx]));
+                       primitives->addChild(new WidenessTestCase<LinesTestInstance>            (testCtx, "lines",                              "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result",                                            PRIMITIVEWIDENESS_NARROW,       samples[samplesNdx]));
+                       primitives->addChild(new WidenessTestCase<LinesTestInstance>            (testCtx, "lines_wide",                 "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result",            PRIMITIVEWIDENESS_WIDE,         samples[samplesNdx]));
+                       primitives->addChild(new WidenessTestCase<PointTestInstance>            (testCtx, "points",                             "Render primitives as VK_PRIMITIVE_TOPOLOGY_POINT_LIST, verify rasterization result",                                           PRIMITIVEWIDENESS_WIDE,         samples[samplesNdx]));
+               }
+
+               // .fill_rules
+               {
+                       tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(testCtx, ("fill_rules" + caseName.str()).c_str(), "Primitive fill rules");
+
+                       rasterizationTests->addChild(fillRules);
+
+                       fillRules->addChild(new FillRuleTestCase(testCtx,       "basic_quad",                   "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_BASIC,                       samples[samplesNdx]));
+                       fillRules->addChild(new FillRuleTestCase(testCtx,       "basic_quad_reverse",   "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_REVERSED,            samples[samplesNdx]));
+                       fillRules->addChild(new FillRuleTestCase(testCtx,       "clipped_full",                 "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_CLIPPED_FULL,        samples[samplesNdx]));
+                       fillRules->addChild(new FillRuleTestCase(testCtx,       "clipped_partly",               "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_CLIPPED_PARTIAL,     samples[samplesNdx]));
+                       fillRules->addChild(new FillRuleTestCase(testCtx,       "projected",                    "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_PROJECTED,           samples[samplesNdx]));
+               }
+
+               // .interpolation
+               {
+                       tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(testCtx, ("interpolation" + caseName.str()).c_str(), "Test interpolation");
+
+                       rasterizationTests->addChild(interpolation);
+
+                       interpolation->addChild(new TriangleInterpolationTestCase               (testCtx, "triangles",          "Verify triangle interpolation",                VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,    INTERPOLATIONFLAGS_NONE,                                                                samples[samplesNdx]));
+                       interpolation->addChild(new LineInterpolationTestCase                   (testCtx, "lines",                      "Verify line interpolation",                    VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_NARROW,       samples[samplesNdx]));
+                       interpolation->addChild(new LineInterpolationTestCase                   (testCtx, "lines_wide",         "Verify wide line interpolation",               VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_WIDE,         samples[samplesNdx]));
+               }
+       }
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx)
+{
+       return createTestGroup(testCtx, "rasterization", "Rasterization Tests", createRasterizationTests);
+}
+
+} // rasterization
+} // vkt
diff --git a/external/vulkancts/modules/vulkan/rasterization/vktRasterizationTests.hpp b/external/vulkancts/modules/vulkan/rasterization/vktRasterizationTests.hpp
new file mode 100644 (file)
index 0000000..61138e1
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef _VKTRASTERIZATIONTESTS_HPP
+#define _VKTRASTERIZATIONTESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2016 The Khronos Group Inc.
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Functional rasterization tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace rasterization
+{
+
+tcu::TestCaseGroup*            createTests     (tcu::TestContext& testCtx);
+
+} // rasterization
+} // vkt
+
+#endif // _VKTRASTERIZATIONTESTS_HPP
index 8277e91..0bb1689 100644 (file)
@@ -67,6 +67,7 @@
 #include "vktSynchronization.hpp"
 #include "vktSparseResourcesTests.hpp"
 #include "vktTessellationTests.hpp"
+#include "vktRasterizationTests.hpp"
 
 #include <vector>
 #include <sstream>
@@ -380,6 +381,7 @@ void TestPackage::init (void)
        addChild(createSynchronizationTests     (m_testCtx));
        addChild(sparse::createTests            (m_testCtx));
        addChild(tessellation::createTests      (m_testCtx));
+       addChild(rasterization::createTests (m_testCtx));
 }
 
 } // vkt
index 61f0399..3266413 100644 (file)
@@ -89,6 +89,8 @@ set(TCUTIL_SRCS
        tcuTestHierarchyUtil.hpp
        tcuAstcUtil.cpp
        tcuAstcUtil.hpp
+       tcuRasterizationVerifier.cpp
+       tcuRasterizationVerifier.hpp
        )
 
 set(TCUTIL_LIBS
@@ -1,6 +1,6 @@
 /*-------------------------------------------------------------------------
- * drawElements Quality Program OpenGL (ES) Module
- * -----------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
  *
  * Copyright 2014 The Android Open Source Project
  *
  *
  *//*!
  * \file
- * \brief rasterization test utils.
+ * \brief Rasterization verifier utils.
  *//*--------------------------------------------------------------------*/
 
-#include "glsRasterizationTestUtil.hpp"
+#include "tcuRasterizationVerifier.hpp"
 #include "tcuVector.hpp"
 #include "tcuSurface.hpp"
 #include "tcuTestLog.hpp"
 
 #include <limits>
 
-namespace deqp
-{
-namespace gls
-{
-namespace RasterizationTestUtil
+namespace tcu
 {
 namespace
 {
@@ -612,7 +608,6 @@ struct MultisampleLineInterpolator
 
        InterpolationRange interpolate (int primitiveNdx, const tcu::IVec2 pixel, const tcu::IVec2 viewportSize, bool multisample, int subpixelBits) const
        {
-               DE_ASSERT(multisample);
                DE_UNREF(multisample);
                DE_UNREF(subpixelBits);
 
@@ -867,7 +862,52 @@ bool verifyTriangleGroupInterpolationWithInterpolator (const tcu::Surface& surfa
        }
 }
 
-bool verifyMultisampleLineGroupRasterization (const tcu::Surface& surface, const LineSceneSpec& scene, const RasterizationArguments& args, tcu::TestLog& log)
+
+float calculateIntersectionParameter (const tcu::Vec2 line[2], float w, int componentNdx)
+{
+       DE_ASSERT(componentNdx < 2);
+       if (line[1][componentNdx] == line[0][componentNdx])
+               return -1.0f;
+
+       return (w - line[0][componentNdx]) / (line[1][componentNdx] - line[0][componentNdx]);
+}
+
+// Clips the given line with a ((-w, -w), (-w, w), (w, w), (w, -w)) rectangle
+void applyClippingBox (tcu::Vec2 line[2], float w)
+{
+       for (int side = 0; side < 4; ++side)
+       {
+               const int       sign            = ((side / 2) * -2) + 1;
+               const int       component       = side % 2;
+               const float     t                       = calculateIntersectionParameter(line, w * sign, component);
+
+               if (t > 0 && t < 1)
+               {
+                       float newCoord          = t * line[1][1 - component] + (1 - t) * line[0][1 - component];
+
+                       if (line[1][component] > w * sign)
+                       {
+                               line[1 - side / 2][component] = w * sign;
+                               line[1 - side / 2][1 - component] = newCoord;
+                       }
+                       else
+                       {
+                               line[side / 2][component] = w * sign;
+                               line[side / 2][1 - component] = newCoord;
+                       }
+               }
+       }
+}
+
+enum ClipMode
+{
+       CLIPMODE_NO_CLIPPING = 0,
+       CLIPMODE_USE_CLIPPING_BOX,
+
+       CLIPMODE_LAST
+};
+
+bool verifyMultisampleLineGroupRasterization (const tcu::Surface& surface, const LineSceneSpec& scene, const RasterizationArguments& args, tcu::TestLog& log, ClipMode clipMode)
 {
        // Multisampled line == 2 triangles
 
@@ -879,11 +919,17 @@ bool verifyMultisampleLineGroupRasterization (const tcu::Surface& surface, const
        for (int lineNdx = 0; lineNdx < (int)scene.lines.size(); ++lineNdx)
        {
                // Transform to screen space, add pixel offsets, convert back to normalized device space, and test as triangles
-               const tcu::Vec2 lineNormalizedDeviceSpace[2] =
+               tcu::Vec2 lineNormalizedDeviceSpace[2] =
                {
                        tcu::Vec2(scene.lines[lineNdx].positions[0].x() / scene.lines[lineNdx].positions[0].w(), scene.lines[lineNdx].positions[0].y() / scene.lines[lineNdx].positions[0].w()),
                        tcu::Vec2(scene.lines[lineNdx].positions[1].x() / scene.lines[lineNdx].positions[1].w(), scene.lines[lineNdx].positions[1].y() / scene.lines[lineNdx].positions[1].w()),
                };
+
+               if (clipMode == CLIPMODE_USE_CLIPPING_BOX)
+               {
+                       applyClippingBox(lineNormalizedDeviceSpace, 1.0f);
+               }
+
                const tcu::Vec2 lineScreenSpace[2] =
                {
                        (lineNormalizedDeviceSpace[0] + tcu::Vec2(1.0f, 1.0f)) * 0.5f * viewportSize,
@@ -2356,11 +2402,16 @@ bool verifyLineGroupRasterization (const tcu::Surface& surface, const LineSceneS
        const bool multisampled = args.numSamples != 0;
 
        if (multisampled)
-               return verifyMultisampleLineGroupRasterization(surface, scene, args, log);
+               return verifyMultisampleLineGroupRasterization(surface, scene, args, log, CLIPMODE_NO_CLIPPING);
        else
                return verifySinglesampleLineGroupRasterization(surface, scene, args, log);
 }
 
+bool verifyClippedTriangulatedLineGroupRasterization (const tcu::Surface& surface, const LineSceneSpec& scene, const RasterizationArguments& args, tcu::TestLog& log)
+{
+       return verifyMultisampleLineGroupRasterization(surface, scene, args, log, CLIPMODE_USE_CLIPPING_BOX);
+}
+
 bool verifyPointGroupRasterization (const tcu::Surface& surface, const PointSceneSpec& scene, const RasterizationArguments& args, tcu::TestLog& log)
 {
        // Splitting to triangles is a valid solution in multisampled cases and even in non-multisample cases too.
@@ -2407,6 +2458,9 @@ LineInterpolationMethod verifyLineGroupInterpolation (const tcu::Surface& surfac
        }
 }
 
-} // StateQueryUtil
-} // gls
-} // deqp
+bool verifyTriangulatedLineGroupInterpolation (const tcu::Surface& surface, const LineSceneSpec& scene, const RasterizationArguments& args, tcu::TestLog& log)
+{
+       return verifyMultisampleLineGroupInterpolation(surface, scene, args, log);
+}
+
+} // tcu
@@ -1,8 +1,8 @@
-#ifndef _GLSRASTERIZATIONTESTUTIL_HPP
-#define _GLSRASTERIZATIONTESTUTIL_HPP
+#ifndef _TCURASTERIZATIONVERIFIER_HPP
+#define _TCURASTERIZATIONVERIFIER_HPP
 /*-------------------------------------------------------------------------
- * drawElements Quality Program OpenGL (ES) Module
- * -----------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
  *
  * Copyright 2014 The Android Open Source Project
  *
  *
  *//*!
  * \file
- * \brief rasterization test utils.
+ * \brief Rasterization verifier utils.
  *//*--------------------------------------------------------------------*/
 
-#include "deMath.h"
 #include "tcuDefs.hpp"
 #include "tcuTestLog.hpp"
+#include "deMath.h"
 
 #include <vector>
 
-namespace deqp
-{
-namespace gls
-{
-namespace RasterizationTestUtil
+namespace tcu
 {
 
 enum CoverageType
@@ -137,6 +133,19 @@ bool verifyTriangleGroupRasterization (const tcu::Surface& surface, const Triang
 bool verifyLineGroupRasterization (const tcu::Surface& surface, const LineSceneSpec& scene, const RasterizationArguments& args, tcu::TestLog& log);
 
 /*--------------------------------------------------------------------*//*!
+ * \brief Verify clipped line rasterization result
+ * Verifies pixels in the surface are rasterized within the bounds given
+ * by RasterizationArguments and by clipping the lines with a (-1, -1), (1, 1)
+ * square. Lines should not be z-clipped.
+ *
+ * Line colors are not used. The line is expected to be white. Lines are
+ * rasterized as two triangles.
+ *
+ * Returns false if invalid rasterization is found.
+ *//*--------------------------------------------------------------------*/
+bool verifyClippedTriangulatedLineGroupRasterization (const tcu::Surface& surface, const LineSceneSpec& scene, const RasterizationArguments& args, tcu::TestLog& log);
+
+/*--------------------------------------------------------------------*//*!
  * \brief Verify point rasterization result
  * Verifies points in the surface are rasterized within the bounds given
  * by RasterizationArguments. Points should not be z-clipped.
@@ -169,8 +178,18 @@ bool verifyTriangleGroupInterpolation (const tcu::Surface& surface, const Triang
  *//*--------------------------------------------------------------------*/
 LineInterpolationMethod verifyLineGroupInterpolation (const tcu::Surface& surface, const LineSceneSpec& scene, const RasterizationArguments& args, tcu::TestLog& log);
 
-} // StateQueryUtil
-} // gls
-} // deqp
+/*--------------------------------------------------------------------*//*!
+ * \brief Verify line color interpolation is valid
+ * Verifies the color of a fragments of a colored line is in the
+ * valid range. Lines should not be z-clipped.
+ *
+ * The background is expected to be black. The lines are rasterized
+ * as two triangles.
+ *
+ * Returns false if invalid rasterization interpolation is found.
+ *//*--------------------------------------------------------------------*/
+bool verifyTriangulatedLineGroupInterpolation (const tcu::Surface& surface, const LineSceneSpec& scene, const RasterizationArguments& args, tcu::TestLog& log);
+
+} // tcu
 
-#endif // _GLSRASTERIZATIONTESTUTIL_HPP
+#endif // _TCURASTERIZATIONVERIFIER_HPP
index e9529a9..5f8c1c5 100644 (file)
@@ -22,7 +22,7 @@
  *//*--------------------------------------------------------------------*/
 
 #include "es2fRasterizationTests.hpp"
-#include "glsRasterizationTestUtil.hpp"
+#include "tcuRasterizationVerifier.hpp"
 #include "tcuSurface.hpp"
 #include "tcuRenderTarget.hpp"
 #include "tcuVectorUtil.hpp"
@@ -48,7 +48,11 @@ namespace Functional
 namespace
 {
 
-using namespace gls::RasterizationTestUtil;
+using tcu::RasterizationArguments;
+using tcu::TriangleSceneSpec;
+using tcu::PointSceneSpec;
+using tcu::LineSceneSpec;
+using tcu::LineInterpolationMethod;
 
 static const char* const s_shaderVertexTemplate =      "attribute highp vec4 a_position;\n"
                                                                                                        "attribute highp vec4 a_color;\n"
@@ -1284,7 +1288,7 @@ CullingTest::IterateResult CullingTest::iterate (void)
 
                scene.triangles.swap(triangles);
 
-               if (verifyTriangleGroupRasterization(resultImage, scene, args, m_testCtx.getLog(), VERIFICATIONMODE_WEAK))
+               if (verifyTriangleGroupRasterization(resultImage, scene, args, m_testCtx.getLog(), tcu::VERIFICATIONMODE_WEAK))
                        m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
                else
                        m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rendering");
@@ -1667,12 +1671,12 @@ LineInterpolationTest::IterateResult LineInterpolationTest::iterate (void)
                iterationResult = verifyLineGroupInterpolation(resultImage, scene, args, m_testCtx.getLog());
                switch (iterationResult)
                {
-                       case LINEINTERPOLATION_STRICTLY_CORRECT:
+                       case tcu::LINEINTERPOLATION_STRICTLY_CORRECT:
                                // line interpolation matches the specification
                                m_result.addResult(QP_TEST_RESULT_PASS, "Pass");
                                break;
 
-                       case LINEINTERPOLATION_PROJECTED:
+                       case tcu::LINEINTERPOLATION_PROJECTED:
                                // line interpolation weights are otherwise correct, but they are projected onto major axis
                                m_testCtx.getLog()      << tcu::TestLog::Message
                                                                        << "Interpolation was calculated using coordinates projected onto major axis. "
@@ -1681,7 +1685,7 @@ LineInterpolationTest::IterateResult LineInterpolationTest::iterate (void)
                                m_result.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Interpolation was calculated using projected coordinateds");
                                break;
 
-                       case LINEINTERPOLATION_INCORRECT:
+                       case tcu::LINEINTERPOLATION_INCORRECT:
                                if (scene.lineWidth != 1.0f && m_numSamples > 1)
                                {
                                        // multisampled wide lines might not be supported
index 52286f9..b7705ea 100644 (file)
@@ -22,7 +22,7 @@
  *//*--------------------------------------------------------------------*/
 
 #include "es3fRasterizationTests.hpp"
-#include "glsRasterizationTestUtil.hpp"
+#include "tcuRasterizationVerifier.hpp"
 #include "tcuSurface.hpp"
 #include "tcuRenderTarget.hpp"
 #include "tcuVectorUtil.hpp"
@@ -50,7 +50,11 @@ namespace Functional
 namespace
 {
 
-using namespace gls::RasterizationTestUtil;
+using tcu::RasterizationArguments;
+using tcu::TriangleSceneSpec;
+using tcu::PointSceneSpec;
+using tcu::LineSceneSpec;
+using tcu::LineInterpolationMethod;
 
 static const char* const s_shaderVertexTemplate =      "#version 300 es\n"
                                                                                                        "in highp vec4 a_position;\n"
@@ -1561,7 +1565,7 @@ CullingTest::IterateResult CullingTest::iterate (void)
 
                scene.triangles.swap(triangles);
 
-               if (verifyTriangleGroupRasterization(resultImage, scene, args, m_testCtx.getLog(), VERIFICATIONMODE_WEAK))
+               if (verifyTriangleGroupRasterization(resultImage, scene, args, m_testCtx.getLog(), tcu::VERIFICATIONMODE_WEAK))
                        m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
                else
                        m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rendering");
@@ -2017,12 +2021,12 @@ LineInterpolationTest::IterateResult LineInterpolationTest::iterate (void)
                        iterationResult = verifyLineGroupInterpolation(resultImage, scene, args, m_testCtx.getLog());
                        switch (iterationResult)
                        {
-                               case LINEINTERPOLATION_STRICTLY_CORRECT:
+                               case tcu::LINEINTERPOLATION_STRICTLY_CORRECT:
                                        // line interpolation matches the specification
                                        m_result.addResult(QP_TEST_RESULT_PASS, "Pass");
                                        break;
 
-                               case LINEINTERPOLATION_PROJECTED:
+                               case tcu::LINEINTERPOLATION_PROJECTED:
                                        // line interpolation weights are otherwise correct, but they are projected onto major axis
                                        m_testCtx.getLog()      << tcu::TestLog::Message
                                                                                << "Interpolation was calculated using coordinates projected onto major axis. "
@@ -2031,7 +2035,7 @@ LineInterpolationTest::IterateResult LineInterpolationTest::iterate (void)
                                        m_result.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Interpolation was calculated using projected coordinateds");
                                        break;
 
-                               case LINEINTERPOLATION_INCORRECT:
+                               case tcu::LINEINTERPOLATION_INCORRECT:
                                        if (scene.lineWidth != 1.0f && m_numSamples > 1)
                                        {
                                                // multisampled wide lines might not be supported
index 88bede3..bf9a51d 100644 (file)
@@ -28,7 +28,7 @@
 #include "tcuStringTemplate.hpp"
 #include "tcuTextureUtil.hpp"
 #include "glsStateQueryUtil.hpp"
-#include "glsRasterizationTestUtil.hpp"
+#include "tcuRasterizationVerifier.hpp"
 #include "gluRenderContext.hpp"
 #include "gluCallLogWrapper.hpp"
 #include "gluObjectWrapper.hpp"
@@ -42,8 +42,6 @@
 #include "deRandom.hpp"
 
 using namespace glw;
-using deqp::gls::RasterizationTestUtil::RasterizationArguments;
-using deqp::gls::RasterizationTestUtil::TriangleSceneSpec;
 
 namespace deqp
 {
@@ -54,6 +52,9 @@ namespace Functional
 namespace
 {
 
+using tcu::RasterizationArguments;
+using tcu::TriangleSceneSpec;
+
 static std::string sampleMaskToString (const std::vector<deUint32>& bitfield, int numBits)
 {
        std::string result(numBits, '0');
@@ -456,7 +457,7 @@ bool SamplePosRasterizationTest::testMultisampleTexture (int sampleNdx)
                args.numSamples         = 0;
                args.subpixelBits       = m_subpixelBits;
 
-               return gls::RasterizationTestUtil::verifyTriangleGroupRasterization(glSurface, scene, args, m_testCtx.getLog(), deqp::gls::RasterizationTestUtil::VERIFICATIONMODE_STRICT);
+               return tcu::verifyTriangleGroupRasterization(glSurface, scene, args, m_testCtx.getLog(), tcu::VERIFICATIONMODE_STRICT);
        }
 }
 
index ebec662..2542646 100644 (file)
@@ -51,8 +51,6 @@ set(DEQP_GL_SHARED_SRCS
        glsSamplerObjectTest.cpp
        glsShaderPerformanceMeasurer.cpp
        glsShaderPerformanceMeasurer.hpp
-       glsRasterizationTestUtil.cpp
-       glsRasterizationTestUtil.hpp
        glsInteractionTestUtil.cpp
        glsInteractionTestUtil.hpp
        glsRandomShaderProgram.cpp