Added pipeline multisample state tests.
authorDae Kim <dae.kimpark@imgtec.com>
Tue, 15 Dec 2015 11:11:10 +0000 (11:11 +0000)
committerDae Kim <dae.kimpark@imgtec.com>
Tue, 15 Dec 2015 11:11:10 +0000 (11:11 +0000)
external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt
external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleTests.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleTests.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/pipeline/vktPipelineReferenceRenderer.cpp
external/vulkancts/modules/vulkan/pipeline/vktPipelineReferenceRenderer.hpp
external/vulkancts/modules/vulkan/pipeline/vktPipelineTests.cpp

index d256c4a..40a6d72 100644 (file)
@@ -18,6 +18,8 @@ set(DEQP_VK_PIPELINE_SRCS
        vktPipelineImageUtil.hpp
        vktPipelineImageViewTests.cpp
        vktPipelineImageViewTests.hpp
+       vktPipelineMultisampleTests.cpp
+       vktPipelineMultisampleTests.hpp
        vktPipelineReferenceRenderer.cpp
        vktPipelineReferenceRenderer.hpp
        vktPipelineSamplerTests.cpp
diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleTests.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleTests.cpp
new file mode 100644 (file)
index 0000000..2320fc3
--- /dev/null
@@ -0,0 +1,2022 @@
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Multisample Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktPipelineMultisampleTests.hpp"
+#include "vktPipelineClearUtil.hpp"
+#include "vktPipelineImageUtil.hpp"
+#include "vktPipelineVertexUtil.hpp"
+#include "vktPipelineReferenceRenderer.hpp"
+#include "vktTestCase.hpp"
+#include "vktTestCaseUtil.hpp"
+#include "vkImageUtil.hpp"
+#include "vkMemUtil.hpp"
+#include "vkPrograms.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkRef.hpp"
+#include "vkRefUtil.hpp"
+#include "tcuImageCompare.hpp"
+#include "deUniquePtr.hpp"
+#include "deStringUtil.hpp"
+#include "deMemory.h"
+
+#include <sstream>
+#include <vector>
+#include <map>
+
+namespace vkt
+{
+namespace pipeline
+{
+
+using namespace vk;
+
+namespace
+{
+enum GeometryType
+{
+       GEOMETRY_TYPE_OPAQUE_TRIANGLE,
+       GEOMETRY_TYPE_OPAQUE_LINE,
+       GEOMETRY_TYPE_OPAQUE_POINT,
+       GEOMETRY_TYPE_OPAQUE_QUAD,
+       GEOMETRY_TYPE_TRANSLUCENT_QUAD,
+       GEOMETRY_TYPE_INVISIBLE_QUAD,
+       GEOMETRY_TYPE_GRADIENT_QUAD
+};
+
+
+bool                                                                   isSupportedSampleCount                          (const InstanceInterface& instanceInterface, VkPhysicalDevice physicalDevice, VkSampleCountFlagBits rasterizationSamples);
+VkPipelineColorBlendAttachmentState            getDefaultColorBlendAttachmentState     (void);
+deUint32                                                               getUniqueColorsCount                            (const tcu::ConstPixelBufferAccess& image);
+void                                                                   initMultisamplePrograms                         (SourceCollections& sources, GeometryType geometryType);
+
+class MultisampleTest : public vkt::TestCase
+{
+public:
+
+                                                                                               MultisampleTest                                         (tcu::TestContext&                                                              testContext,
+                                                                                                                                                                        const std::string&                                                             name,
+                                                                                                                                                                        const std::string&                                                             description,
+                                                                                                                                                                        const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
+                                                                                                                                                                        const VkPipelineColorBlendAttachmentState&             blendState,
+                                                                                                                                                                        GeometryType                                                                   geometryType);
+       virtual                                                                         ~MultisampleTest                                        (void);
+
+       virtual void                                                            initPrograms                                            (SourceCollections& programCollection) const;
+       virtual TestInstance*                                           createInstance                                          (Context& context) const;
+
+protected:
+       virtual TestInstance*                                           createMultisampleTestInstance           (Context&                                                                               context,
+                                                                                                                                                                        VkPrimitiveTopology                                                    topology,
+                                                                                                                                                                        const std::vector<Vertex4RGBA>&                                vertices,
+                                                                                                                                                                        const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
+                                                                                                                                                                        const VkPipelineColorBlendAttachmentState&             colorBlendState) const = 0;
+       VkPipelineMultisampleStateCreateInfo            m_multisampleStateParams;
+       const VkPipelineColorBlendAttachmentState       m_colorBlendState;
+       const GeometryType                                                      m_geometryType;
+       std::vector<VkSampleMask>                                       m_sampleMask;
+};
+
+class RasterizationSamplesTest : public MultisampleTest
+{
+public:
+                                                                                               RasterizationSamplesTest                        (tcu::TestContext&              testContext,
+                                                                                                                                                                        const std::string&             name,
+                                                                                                                                                                        const std::string&             description,
+                                                                                                                                                                        VkSampleCountFlagBits  rasterizationSamples,
+                                                                                                                                                                        GeometryType                   geometryType);
+       virtual                                                                         ~RasterizationSamplesTest                       (void) {}
+
+protected:
+       virtual TestInstance*                                           createMultisampleTestInstance           (Context&                                                                               context,
+                                                                                                                                                                        VkPrimitiveTopology                                                    topology,
+                                                                                                                                                                        const std::vector<Vertex4RGBA>&                                vertices,
+                                                                                                                                                                        const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
+                                                                                                                                                                        const VkPipelineColorBlendAttachmentState&             colorBlendState) const;
+
+       static VkPipelineMultisampleStateCreateInfo     getRasterizationSamplesStateParams      (VkSampleCountFlagBits rasterizationSamples);
+};
+
+class MinSampleShadingTest : public MultisampleTest
+{
+public:
+                                                                                               MinSampleShadingTest                            (tcu::TestContext&              testContext,
+                                                                                                                                                                        const std::string&             name,
+                                                                                                                                                                        const std::string&             description,
+                                                                                                                                                                        VkSampleCountFlagBits  rasterizationSamples,
+                                                                                                                                                                        float                                  minSampleShading,
+                                                                                                                                                                        GeometryType                   geometryType);
+       virtual                                                                         ~MinSampleShadingTest                           (void) {}
+
+protected:
+       virtual TestInstance*                                           createMultisampleTestInstance           (Context&                                                                               context,
+                                                                                                                                                                        VkPrimitiveTopology                                                    topology,
+                                                                                                                                                                        const std::vector<Vertex4RGBA>&                                vertices,
+                                                                                                                                                                        const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
+                                                                                                                                                                        const VkPipelineColorBlendAttachmentState&             colorBlendState) const;
+
+       static VkPipelineMultisampleStateCreateInfo     getMinSampleShadingStateParams          (VkSampleCountFlagBits rasterizationSamples, float minSampleShading);
+};
+
+class SampleMaskTest : public MultisampleTest
+{
+public:
+                                                                                               SampleMaskTest                                          (tcu::TestContext&                                      testContext,
+                                                                                                                                                                        const std::string&                                     name,
+                                                                                                                                                                        const std::string&                                     description,
+                                                                                                                                                                        VkSampleCountFlagBits                          rasterizationSamples,
+                                                                                                                                                                        const std::vector<VkSampleMask>&       sampleMask,
+                                                                                                                                                                        GeometryType                                           geometryType);
+
+       virtual                                                                         ~SampleMaskTest                                         (void) {}
+
+protected:
+       virtual TestInstance*                                           createMultisampleTestInstance           (Context&                                                                               context,
+                                                                                                                                                                        VkPrimitiveTopology                                                    topology,
+                                                                                                                                                                        const std::vector<Vertex4RGBA>&                                vertices,
+                                                                                                                                                                        const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
+                                                                                                                                                                        const VkPipelineColorBlendAttachmentState&             colorBlendState) const;
+
+       static VkPipelineMultisampleStateCreateInfo     getSampleMaskStateParams                        (VkSampleCountFlagBits rasterizationSamples, const std::vector<VkSampleMask>& sampleMask);
+};
+
+class AlphaToOneTest : public MultisampleTest
+{
+public:
+                                                                                               AlphaToOneTest                                  (tcu::TestContext&                                      testContext,
+                                                                                                                                                                const std::string&                                     name,
+                                                                                                                                                                const std::string&                                     description,
+                                                                                                                                                                VkSampleCountFlagBits                          rasterizationSamples);
+
+       virtual                                                                         ~AlphaToOneTest                                 (void) {}
+
+protected:
+       virtual TestInstance*                                           createMultisampleTestInstance   (Context&                                                                               context,
+                                                                                                                                                                VkPrimitiveTopology                                                    topology,
+                                                                                                                                                                const std::vector<Vertex4RGBA>&                                vertices,
+                                                                                                                                                                const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
+                                                                                                                                                                const VkPipelineColorBlendAttachmentState&             colorBlendState) const;
+
+       static VkPipelineMultisampleStateCreateInfo     getAlphaToOneStateParams                (VkSampleCountFlagBits rasterizationSamples);
+       static VkPipelineColorBlendAttachmentState      getAlphaToOneBlendState                 (void);
+};
+
+class AlphaToCoverageTest : public MultisampleTest
+{
+public:
+                                                                                               AlphaToCoverageTest                             (tcu::TestContext&              testContext,
+                                                                                                                                                                const std::string&             name,
+                                                                                                                                                                const std::string&             description,
+                                                                                                                                                                VkSampleCountFlagBits  rasterizationSamples,
+                                                                                                                                                                GeometryType                   geometryType);
+
+       virtual                                                                         ~AlphaToCoverageTest                    (void) {}
+
+protected:
+       virtual TestInstance*                                           createMultisampleTestInstance   (Context&                                                                               context,
+                                                                                                                                                                VkPrimitiveTopology                                                    topology,
+                                                                                                                                                                const std::vector<Vertex4RGBA>&                                vertices,
+                                                                                                                                                                const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
+                                                                                                                                                                const VkPipelineColorBlendAttachmentState&             colorBlendState) const;
+
+       static VkPipelineMultisampleStateCreateInfo     getAlphaToCoverageStateParams   (VkSampleCountFlagBits rasterizationSamples);
+
+       GeometryType                                                            m_geometryType;
+};
+
+class MultisampleRenderer
+{
+public:
+                                                                                               MultisampleRenderer                     (Context&                                                                               context,
+                                                                                                                                                        VkFormat                                                                               colorFormat,
+                                                                                                                                                        const tcu::IVec2&                                                              renderSize,
+                                                                                                                                                        VkPrimitiveTopology                                                    topology,
+                                                                                                                                                        const std::vector<Vertex4RGBA>&                                vertices,
+                                                                                                                                                        const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
+                                                                                                                                                        const VkPipelineColorBlendAttachmentState&             blendState);
+
+       virtual                                                                         ~MultisampleRenderer            (void);
+
+       de::MovePtr<tcu::TextureLevel>                          render                                          (void);
+
+protected:
+       Context&                                                                        m_context;
+
+       const VkFormat                                                          m_colorFormat;
+       tcu::IVec2                                                                      m_renderSize;
+
+       const VkPipelineMultisampleStateCreateInfo      m_multisampleStateParams;
+       const VkPipelineColorBlendAttachmentState       m_colorBlendState;
+
+       Move<VkImage>                                                           m_colorImage;
+       de::MovePtr<Allocation>                                         m_colorImageAlloc;
+       Move<VkImageView>                                                       m_colorAttachmentView;
+
+       Move<VkImage>                                                           m_resolveImage;
+       de::MovePtr<Allocation>                                         m_resolveImageAlloc;
+       Move<VkImageView>                                                       m_resolveAttachmentView;
+
+       Move<VkRenderPass>                                                      m_renderPass;
+       Move<VkFramebuffer>                                                     m_framebuffer;
+
+       Move<VkShaderModule>                                            m_vertexShaderModule;
+       Move<VkShaderModule>                                            m_fragmentShaderModule;
+
+       Move<VkBuffer>                                                          m_vertexBuffer;
+       de::MovePtr<Allocation>                                         m_vertexBufferAlloc;
+
+       Move<VkPipelineLayout>                                          m_pipelineLayout;
+       Move<VkPipeline>                                                        m_graphicsPipeline;
+
+       Move<VkCommandPool>                                                     m_cmdPool;
+       Move<VkCommandBuffer>                                           m_cmdBuffer;
+
+       Move<VkFence>                                                           m_fence;
+};
+
+class RasterizationSamplesInstance : public vkt::TestInstance
+{
+public:
+                                                                       RasterizationSamplesInstance    (Context&                                                                               context,
+                                                                                                                                        VkPrimitiveTopology                                                    topology,
+                                                                                                                                        const std::vector<Vertex4RGBA>&                                vertices,
+                                                                                                                                        const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
+                                                                                                                                        const VkPipelineColorBlendAttachmentState&             blendState);
+       virtual                                                 ~RasterizationSamplesInstance   (void) {}
+
+       virtual tcu::TestStatus                 iterate                                                 (void);
+
+protected:
+       virtual tcu::TestStatus                 verifyImage                                             (const tcu::ConstPixelBufferAccess& result);
+
+       const VkFormat                                  m_colorFormat;
+       const tcu::IVec2                                m_renderSize;
+       const VkPrimitiveTopology               m_primitiveTopology;
+       const std::vector<Vertex4RGBA>  m_vertices;
+       MultisampleRenderer                             m_multisampleRenderer;
+};
+
+class MinSampleShadingInstance : public vkt::TestInstance
+{
+public:
+                                                                                               MinSampleShadingInstance        (Context&                                                                               context,
+                                                                                                                                                        VkPrimitiveTopology                                                    topology,
+                                                                                                                                                        const std::vector<Vertex4RGBA>&                                vertices,
+                                                                                                                                                        const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
+                                                                                                                                                        const VkPipelineColorBlendAttachmentState&             blendState);
+       virtual                                                                         ~MinSampleShadingInstance       (void) {}
+
+       virtual tcu::TestStatus                                         iterate                                         (void);
+
+protected:
+       virtual tcu::TestStatus                                         verifyImage                                     (const tcu::ConstPixelBufferAccess& testShadingImage,
+                                                                                                                                                        const tcu::ConstPixelBufferAccess& minShadingImage,
+                                                                                                                                                        const tcu::ConstPixelBufferAccess& maxShadingImage);
+       const VkFormat                                                          m_colorFormat;
+       const tcu::IVec2                                                        m_renderSize;
+       const VkPrimitiveTopology                                       m_primitiveTopology;
+       const std::vector<Vertex4RGBA>                          m_vertices;
+       const VkPipelineMultisampleStateCreateInfo      m_multisampleStateParams;
+       const VkPipelineColorBlendAttachmentState       m_colorBlendState;
+};
+
+class SampleMaskInstance : public vkt::TestInstance
+{
+public:
+                                                                                               SampleMaskInstance                      (Context&                                                                               context,
+                                                                                                                                                        VkPrimitiveTopology                                                    topology,
+                                                                                                                                                        const std::vector<Vertex4RGBA>&                                vertices,
+                                                                                                                                                        const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
+                                                                                                                                                        const VkPipelineColorBlendAttachmentState&             blendState);
+       virtual                                                                         ~SampleMaskInstance                     (void) {}
+
+       virtual tcu::TestStatus                                         iterate                                         (void);
+
+protected:
+       virtual tcu::TestStatus                                         verifyImage                                     (const tcu::ConstPixelBufferAccess& testShadingImage,
+                                                                                                                                                        const tcu::ConstPixelBufferAccess& minShadingImage,
+                                                                                                                                                        const tcu::ConstPixelBufferAccess& maxShadingImage);
+       const VkFormat                                                          m_colorFormat;
+       const tcu::IVec2                                                        m_renderSize;
+       const VkPrimitiveTopology                                       m_primitiveTopology;
+       const std::vector<Vertex4RGBA>                          m_vertices;
+       const VkPipelineMultisampleStateCreateInfo      m_multisampleStateParams;
+       const VkPipelineColorBlendAttachmentState       m_colorBlendState;
+};
+
+class AlphaToOneInstance : public vkt::TestInstance
+{
+public:
+                                                                                               AlphaToOneInstance                      (Context&                                                                               context,
+                                                                                                                                                        VkPrimitiveTopology                                                    topology,
+                                                                                                                                                        const std::vector<Vertex4RGBA>&                                vertices,
+                                                                                                                                                        const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
+                                                                                                                                                        const VkPipelineColorBlendAttachmentState&             blendState);
+       virtual                                                                         ~AlphaToOneInstance                     (void) {}
+
+       virtual tcu::TestStatus                                         iterate                                         (void);
+
+protected:
+       virtual tcu::TestStatus                                         verifyImage                                     (const tcu::ConstPixelBufferAccess& alphaOneImage,
+                                                                                                                                                        const tcu::ConstPixelBufferAccess& noAlphaOneImage);
+       const VkFormat                                                          m_colorFormat;
+       const tcu::IVec2                                                        m_renderSize;
+       const VkPrimitiveTopology                                       m_primitiveTopology;
+       const std::vector<Vertex4RGBA>                          m_vertices;
+       const VkPipelineMultisampleStateCreateInfo      m_multisampleStateParams;
+       const VkPipelineColorBlendAttachmentState       m_colorBlendState;
+};
+
+class AlphaToCoverageInstance : public vkt::TestInstance
+{
+public:
+                                                                                               AlphaToCoverageInstance         (Context&                                                                               context,
+                                                                                                                                                        VkPrimitiveTopology                                                    topology,
+                                                                                                                                                        const std::vector<Vertex4RGBA>&                                vertices,
+                                                                                                                                                        const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
+                                                                                                                                                        const VkPipelineColorBlendAttachmentState&             blendState,
+                                                                                                                                                        GeometryType                                                                   geometryType);
+       virtual                                                                         ~AlphaToCoverageInstance        (void) {}
+
+       virtual tcu::TestStatus                                         iterate                                         (void);
+
+protected:
+       virtual tcu::TestStatus                                         verifyImage                                     (const tcu::ConstPixelBufferAccess& result);
+       const VkFormat                                                          m_colorFormat;
+       const tcu::IVec2                                                        m_renderSize;
+       const VkPrimitiveTopology                                       m_primitiveTopology;
+       const std::vector<Vertex4RGBA>                          m_vertices;
+       const VkPipelineMultisampleStateCreateInfo      m_multisampleStateParams;
+       const VkPipelineColorBlendAttachmentState       m_colorBlendState;
+       const GeometryType                      m_geometryType;
+};
+
+
+// Helper functions
+
+void initMultisamplePrograms (SourceCollections& sources, GeometryType geometryType)
+{
+       std::ostringstream vertexSource;
+
+       vertexSource <<
+               "#version 310 es\n"
+               "layout(location = 0) in vec4 position;\n"
+               "layout(location = 1) in vec4 color;\n"
+               "layout(location = 0) out highp vec4 vtxColor;\n"
+               "void main (void)\n"
+               "{\n"
+               "       gl_Position = position;\n"
+               "       vtxColor = color;\n"
+               << (geometryType == GEOMETRY_TYPE_OPAQUE_POINT ? "      gl_PointSize = 3.0f;\n"
+                                                                                                                : "" )
+               << "}\n";
+
+       static const char* fragmentSource =
+               "#version 310 es\n"
+               "layout(location = 0) in highp vec4 vtxColor;\n"
+               "layout(location = 0) out highp vec4 fragColor;\n"
+               "void main (void)\n"
+               "{\n"
+               "       fragColor = vtxColor;\n"
+               "}\n";
+
+       sources.glslSources.add("color_vert") << glu::VertexSource(vertexSource.str());
+       sources.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource);
+}
+
+bool isSupportedSampleCount (const InstanceInterface& instanceInterface, VkPhysicalDevice physicalDevice, VkSampleCountFlagBits rasterizationSamples)
+{
+       VkPhysicalDeviceProperties deviceProperties;
+
+       instanceInterface.getPhysicalDeviceProperties(physicalDevice, &deviceProperties);
+
+       return !!(deviceProperties.limits.framebufferColorSampleCounts & rasterizationSamples);
+}
+
+VkPipelineColorBlendAttachmentState getDefaultColorBlendAttachmentState (void)
+{
+       const VkPipelineColorBlendAttachmentState colorBlendState =
+       {
+               false,                                                                                                          // VkBool32                                     blendEnable;
+               VK_BLEND_FACTOR_ONE,                                                                            // VkBlendFactor                        srcColorBlendFactor;
+               VK_BLEND_FACTOR_ZERO,                                                                           // VkBlendFactor                        dstColorBlendFactor;
+               VK_BLEND_OP_ADD,                                                                                        // VkBlendOp                            colorBlendOp;
+               VK_BLEND_FACTOR_ONE,                                                                            // VkBlendFactor                        srcAlphaBlendFactor;
+               VK_BLEND_FACTOR_ZERO,                                                                           // VkBlendFactor                        dstAlphaBlendFactor;
+               VK_BLEND_OP_ADD,                                                                                        // VkBlendOp                            alphaBlendOp;
+               VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |           // VkColorComponentFlags        colorWriteMask;
+                       VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
+       };
+
+       return colorBlendState;
+}
+
+deUint32 getUniqueColorsCount (const tcu::ConstPixelBufferAccess& image)
+{
+       DE_ASSERT(image.getFormat().getPixelSize() == 4);
+
+       std::map<deUint32, deUint32>    histogram; // map<pixel value, number of occurrences>
+       const deUint32                                  pixelCount      = image.getWidth() * image.getHeight() * image.getDepth();
+
+       for (deUint32 pixelNdx = 0; pixelNdx < pixelCount; pixelNdx++)
+       {
+               const deUint32 pixelValue = *((const deUint32*)image.getDataPtr() + pixelNdx);
+
+               if (histogram.find(pixelValue) != histogram.end())
+                       histogram[pixelValue]++;
+               else
+                       histogram[pixelValue] = 1;
+       }
+
+       return (deUint32)histogram.size();
+}
+
+
+// MultisampleTest
+
+MultisampleTest::MultisampleTest (tcu::TestContext&                                                            testContext,
+                                                                 const std::string&                                                    name,
+                                                                 const std::string&                                                    description,
+                                                                 const VkPipelineMultisampleStateCreateInfo&   multisampleStateParams,
+                                                                 const VkPipelineColorBlendAttachmentState&    blendState,
+                                                                 GeometryType                                                                  geometryType)
+       : vkt::TestCase                         (testContext, name, description)
+       , m_multisampleStateParams      (multisampleStateParams)
+       , m_colorBlendState                     (blendState)
+       , m_geometryType                        (geometryType)
+{
+       if (m_multisampleStateParams.pSampleMask)
+       {
+               // Copy pSampleMask to avoid dependencies with other classes
+
+               const deUint32 maskCount = m_multisampleStateParams.rasterizationSamples / 32;
+
+               for (deUint32 maskNdx = 0; maskNdx < maskCount; maskNdx++)
+                       m_sampleMask.push_back(m_multisampleStateParams.pSampleMask[maskNdx]);
+
+               m_multisampleStateParams.pSampleMask = m_sampleMask.data();
+       }
+}
+
+MultisampleTest::~MultisampleTest (void)
+{
+}
+
+void MultisampleTest::initPrograms (SourceCollections& programCollection) const
+{
+       initMultisamplePrograms(programCollection, m_geometryType);
+}
+
+TestInstance* MultisampleTest::createInstance (Context& context) const
+{
+       VkPrimitiveTopology                     topology;
+       std::vector<Vertex4RGBA>        vertices;
+
+       switch (m_geometryType)
+       {
+               case GEOMETRY_TYPE_OPAQUE_TRIANGLE:
+               {
+                       topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+                       const Vertex4RGBA vertexData[3] =
+                       {
+                               {
+                                       tcu::Vec4(-0.75f, 0.0f, 0.0f, 1.0f),
+                                       tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
+                               },
+                               {
+                                       tcu::Vec4(0.75f, 0.125f, 0.0f, 1.0f),
+                                       tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
+                               },
+                               {
+                                       tcu::Vec4(0.75f, -0.125f, 0.0f, 1.0f),
+                                       tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
+                               }
+                       };
+
+                       vertices = std::vector<Vertex4RGBA>(vertexData, vertexData + 3);
+                       break;
+               }
+
+               case GEOMETRY_TYPE_OPAQUE_LINE:
+               {
+                       topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
+
+                       const Vertex4RGBA vertexData[2] =
+                       {
+                               {
+                                       tcu::Vec4(-0.75f, 0.25f, 0.0f, 1.0f),
+                                       tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
+                               },
+                               {
+                                       tcu::Vec4(0.75f, -0.25f, 0.0f, 1.0f),
+                                       tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
+                               }
+                       };
+
+                       vertices = std::vector<Vertex4RGBA>(vertexData, vertexData + 2);
+                       break;
+               }
+
+               case GEOMETRY_TYPE_OPAQUE_POINT:
+               {
+                       topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
+
+                       const Vertex4RGBA vertex =
+                       {
+                               tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
+                               tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
+                       };
+
+                       vertices = std::vector<Vertex4RGBA>(1, vertex);
+                       break;
+               }
+
+               case GEOMETRY_TYPE_OPAQUE_QUAD:
+               case GEOMETRY_TYPE_TRANSLUCENT_QUAD:
+               case GEOMETRY_TYPE_INVISIBLE_QUAD:
+               case GEOMETRY_TYPE_GRADIENT_QUAD:
+               {
+                       topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+
+                       Vertex4RGBA vertexData[4] =
+                       {
+                               {
+                                       tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
+                                       tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
+                               },
+                               {
+                                       tcu::Vec4(1.0f, -1.0f, 0.0f, 1.0f),
+                                       tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
+                               },
+                               {
+                                       tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
+                                       tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
+                               },
+                               {
+                                       tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
+                                       tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
+                               }
+                       };
+
+                       if (m_geometryType == GEOMETRY_TYPE_TRANSLUCENT_QUAD)
+                       {
+                               for (int i = 0; i < 4; i++)
+                                       vertexData[i].color.w() = 0.25f;
+                       }
+                       else if (m_geometryType == GEOMETRY_TYPE_INVISIBLE_QUAD)
+                       {
+                               for (int i = 0; i < 4; i++)
+                                       vertexData[i].color.w() = 0.0f;
+                       }
+                       else if (m_geometryType == GEOMETRY_TYPE_GRADIENT_QUAD)
+                       {
+                               vertexData[0].color.w() = 0.0f;
+                               vertexData[2].color.w() = 0.0f;
+                       }
+
+                       vertices = std::vector<Vertex4RGBA>(vertexData, vertexData + 4);
+                       break;
+               }
+
+               default:
+                       DE_ASSERT(false);
+       }
+
+       return createMultisampleTestInstance(context, topology, vertices, m_multisampleStateParams, m_colorBlendState);
+}
+
+
+// RasterizationSamplesTest
+
+RasterizationSamplesTest::RasterizationSamplesTest (tcu::TestContext&          testContext,
+                                                                                                       const std::string&              name,
+                                                                                                       const std::string&              description,
+                                                                                                       VkSampleCountFlagBits   rasterizationSamples,
+                                                                                                       GeometryType                    geometryType)
+       : MultisampleTest       (testContext, name, description, getRasterizationSamplesStateParams(rasterizationSamples), getDefaultColorBlendAttachmentState(), geometryType)
+{
+}
+
+VkPipelineMultisampleStateCreateInfo RasterizationSamplesTest::getRasterizationSamplesStateParams (VkSampleCountFlagBits rasterizationSamples)
+{
+       const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                      sType;
+               DE_NULL,                                                                                                        // const void*                                                          pNext;
+               0u,                                                                                                                     // VkPipelineMultisampleStateCreateFlags        flags;
+               rasterizationSamples,                                                                           // VkSampleCountFlagBits                                        rasterizationSamples;
+               false,                                                                                                          // VkBool32                                                                     sampleShadingEnable;
+               0.0f,                                                                                                           // float                                                                        minSampleShading;
+               DE_NULL,                                                                                                        // const VkSampleMask*                                          pSampleMask;
+               false,                                                                                                          // VkBool32                                                                     alphaToCoverageEnable;
+               false                                                                                                           // VkBool32                                                                     alphaToOneEnable;
+       };
+
+       return multisampleStateParams;
+}
+
+TestInstance* RasterizationSamplesTest::createMultisampleTestInstance (Context&                                                                                context,
+                                                                                                                                          VkPrimitiveTopology                                                  topology,
+                                                                                                                                          const std::vector<Vertex4RGBA>&                              vertices,
+                                                                                                                                          const VkPipelineMultisampleStateCreateInfo&  multisampleStateParams,
+                                                                                                                                          const VkPipelineColorBlendAttachmentState&   colorBlendState) const
+{
+       return new RasterizationSamplesInstance(context, topology, vertices, multisampleStateParams, colorBlendState);
+}
+
+
+// MinSampleShadingTest
+
+MinSampleShadingTest::MinSampleShadingTest (tcu::TestContext&          testContext,
+                                                                                       const std::string&              name,
+                                                                                       const std::string&              description,
+                                                                                       VkSampleCountFlagBits   rasterizationSamples,
+                                                                                       float                                   minSampleShading,
+                                                                                       GeometryType                    geometryType)
+       : MultisampleTest       (testContext, name, description, getMinSampleShadingStateParams(rasterizationSamples, minSampleShading), getDefaultColorBlendAttachmentState(), geometryType)
+{
+}
+
+TestInstance* MinSampleShadingTest::createMultisampleTestInstance (Context&                                                                            context,
+                                                                                                                                  VkPrimitiveTopology                                                  topology,
+                                                                                                                                  const std::vector<Vertex4RGBA>&                              vertices,
+                                                                                                                                  const VkPipelineMultisampleStateCreateInfo&  multisampleStateParams,
+                                                                                                                                  const VkPipelineColorBlendAttachmentState&   colorBlendState) const
+{
+       return new MinSampleShadingInstance(context, topology, vertices, multisampleStateParams, colorBlendState);
+}
+
+VkPipelineMultisampleStateCreateInfo MinSampleShadingTest::getMinSampleShadingStateParams (VkSampleCountFlagBits rasterizationSamples, float minSampleShading)
+{
+       const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                      sType;
+               DE_NULL,                                                                                                        // const void*                                                          pNext;
+               0u,                                                                                                                     // VkPipelineMultisampleStateCreateFlags        flags;
+               rasterizationSamples,                                                                           // VkSampleCountFlagBits                                        rasterizationSamples;
+               true,                                                                                                           // VkBool32                                                                     sampleShadingEnable;
+               minSampleShading,                                                                                       // float                                                                        minSampleShading;
+               DE_NULL,                                                                                                        // const VkSampleMask*                                          pSampleMask;
+               false,                                                                                                          //  VkBool32                                                            alphaToCoverageEnable;
+               false                                                                                                           //  VkBool32                                                            alphaToOneEnable;
+       };
+
+       return multisampleStateParams;
+}
+
+
+// SampleMaskTest
+
+SampleMaskTest::SampleMaskTest (tcu::TestContext&                                      testContext,
+                                                               const std::string&                                      name,
+                                                               const std::string&                                      description,
+                                                               VkSampleCountFlagBits                           rasterizationSamples,
+                                                               const std::vector<VkSampleMask>&        sampleMask,
+                                                               GeometryType                                            geometryType)
+       : MultisampleTest       (testContext, name, description, getSampleMaskStateParams(rasterizationSamples, sampleMask), getDefaultColorBlendAttachmentState(), geometryType)
+{
+}
+
+TestInstance* SampleMaskTest::createMultisampleTestInstance (Context&                                                                          context,
+                                                                                                                        VkPrimitiveTopology                                                    topology,
+                                                                                                                        const std::vector<Vertex4RGBA>&                                vertices,
+                                                                                                                        const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
+                                                                                                                        const VkPipelineColorBlendAttachmentState&             colorBlendState) const
+{
+       return new SampleMaskInstance(context, topology,vertices, multisampleStateParams, colorBlendState);
+}
+
+VkPipelineMultisampleStateCreateInfo SampleMaskTest::getSampleMaskStateParams (VkSampleCountFlagBits rasterizationSamples, const std::vector<VkSampleMask>& sampleMask)
+{
+       const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                      sType;
+               DE_NULL,                                                                                                        // const void*                                                          pNext;
+               0u,                                                                                                                     // VkPipelineMultisampleStateCreateFlags        flags;
+               rasterizationSamples,                                                                           // VkSampleCountFlagBits                                        rasterizationSamples;
+               false,                                                                                                          // VkBool32                                                                     sampleShadingEnable;
+               0.0f,                                                                                                           // float                                                                        minSampleShading;
+               sampleMask.data(),                                                                                      // const VkSampleMask*                                          pSampleMask;
+               false,                                                                                                          // VkBool32                                                                     alphaToCoverageEnable;
+               false                                                                                                           // VkBool32                                                                     alphaToOneEnable;
+       };
+
+       return multisampleStateParams;
+}
+
+
+// AlphaToOneTest
+
+AlphaToOneTest::AlphaToOneTest (tcu::TestContext&              testContext,
+                                                               const std::string&              name,
+                                                               const std::string&              description,
+                                                               VkSampleCountFlagBits   rasterizationSamples)
+       : MultisampleTest       (testContext, name, description, getAlphaToOneStateParams(rasterizationSamples), getAlphaToOneBlendState(), GEOMETRY_TYPE_GRADIENT_QUAD)
+{
+}
+
+TestInstance* AlphaToOneTest::createMultisampleTestInstance (Context&                                                                          context,
+                                                                                                                        VkPrimitiveTopology                                                    topology,
+                                                                                                                        const std::vector<Vertex4RGBA>&                                vertices,
+                                                                                                                        const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
+                                                                                                                        const VkPipelineColorBlendAttachmentState&             colorBlendState) const
+{
+       return new AlphaToOneInstance(context, topology, vertices, multisampleStateParams, colorBlendState);
+}
+
+VkPipelineMultisampleStateCreateInfo AlphaToOneTest::getAlphaToOneStateParams (VkSampleCountFlagBits rasterizationSamples)
+{
+       const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                      sType;
+               DE_NULL,                                                                                                        // const void*                                                          pNext;
+               0u,                                                                                                                     // VkPipelineMultisampleStateCreateFlags        flags;
+               rasterizationSamples,                                                                           // VkSampleCountFlagBits                                        rasterizationSamples;
+               false,                                                                                                          // VkBool32                                                                     sampleShadingEnable;
+               0.0f,                                                                                                           // float                                                                        minSampleShading;
+               DE_NULL,                                                                                                        // const VkSampleMask*                                          pSampleMask;
+               false,                                                                                                          // VkBool32                                                                     alphaToCoverageEnable;
+               true                                                                                                            // VkBool32                                                                     alphaToOneEnable;
+       };
+
+       return multisampleStateParams;
+}
+
+VkPipelineColorBlendAttachmentState AlphaToOneTest::getAlphaToOneBlendState (void)
+{
+       const VkPipelineColorBlendAttachmentState colorBlendState =
+       {
+               true,                                                                                                           // VkBool32                                     blendEnable;
+               VK_BLEND_FACTOR_SRC_ALPHA,                                                                      // VkBlendFactor                        srcColorBlendFactor;
+               VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,                                            // VkBlendFactor                        dstColorBlendFactor;
+               VK_BLEND_OP_ADD,                                                                                        // VkBlendOp                            colorBlendOp;
+               VK_BLEND_FACTOR_SRC_ALPHA,                                                                      // VkBlendFactor                        srcAlphaBlendFactor;
+               VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,                                            // VkBlendFactor                        dstAlphaBlendFactor;
+               VK_BLEND_OP_ADD,                                                                                        // VkBlendOp                            alphaBlendOp;
+               VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |           // VkColorComponentFlags        colorWriteMask;
+                       VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
+       };
+
+       return colorBlendState;
+}
+
+
+// AlphaToCoverageTest
+
+AlphaToCoverageTest::AlphaToCoverageTest (tcu::TestContext&                    testContext,
+                                                                                 const std::string&            name,
+                                                                                 const std::string&            description,
+                                                                                 VkSampleCountFlagBits         rasterizationSamples,
+                                                                                 GeometryType                          geometryType)
+       : MultisampleTest       (testContext, name, description, getAlphaToCoverageStateParams(rasterizationSamples), getDefaultColorBlendAttachmentState(), geometryType)
+       , m_geometryType        (geometryType)
+{
+}
+
+TestInstance* AlphaToCoverageTest::createMultisampleTestInstance (Context&                                                                             context,
+                                                                                                                                 VkPrimitiveTopology                                                   topology,
+                                                                                                                                 const std::vector<Vertex4RGBA>&                               vertices,
+                                                                                                                                 const VkPipelineMultisampleStateCreateInfo&   multisampleStateParams,
+                                                                                                                                 const VkPipelineColorBlendAttachmentState&    colorBlendState) const
+{
+       return new AlphaToCoverageInstance(context, topology, vertices, multisampleStateParams, colorBlendState, m_geometryType);
+}
+
+VkPipelineMultisampleStateCreateInfo AlphaToCoverageTest::getAlphaToCoverageStateParams (VkSampleCountFlagBits rasterizationSamples)
+{
+       const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                      sType;
+               DE_NULL,                                                                                                        // const void*                                                          pNext;
+               0u,                                                                                                                     // VkPipelineMultisampleStateCreateFlags        flags;
+               rasterizationSamples,                                                                           // VkSampleCountFlagBits                                        rasterizationSamples;
+               false,                                                                                                          // VkBool32                                                                     sampleShadingEnable;
+               0.0f,                                                                                                           // float                                                                        minSampleShading;
+               DE_NULL,                                                                                                        // const VkSampleMask*                                          pSampleMask;
+               true,                                                                                                           // VkBool32                                                                     alphaToCoverageEnable;
+               false                                                                                                           // VkBool32                                                                     alphaToOneEnable;
+       };
+
+       return multisampleStateParams;
+}
+
+// RasterizationSamplesInstance
+
+RasterizationSamplesInstance::RasterizationSamplesInstance (Context&                                                                           context,
+                                                                                                                       VkPrimitiveTopology                                                             topology,
+                                                                                                                       const std::vector<Vertex4RGBA>&                                 vertices,
+                                                                                                                       const VkPipelineMultisampleStateCreateInfo&             multisampleStateParams,
+                                                                                                                       const VkPipelineColorBlendAttachmentState&              blendState)
+       : vkt::TestInstance             (context)
+       , m_colorFormat                 (VK_FORMAT_R8G8B8A8_UNORM)
+       , m_renderSize                  (32, 32)
+       , m_primitiveTopology   (topology)
+       , m_vertices                    (vertices)
+       , m_multisampleRenderer (context, m_colorFormat, m_renderSize, topology, vertices, multisampleStateParams, blendState)
+{
+}
+
+tcu::TestStatus RasterizationSamplesInstance::iterate (void)
+{
+       de::MovePtr<tcu::TextureLevel> level(m_multisampleRenderer.render());
+       return verifyImage(level->getAccess());
+}
+
+tcu::TestStatus RasterizationSamplesInstance::verifyImage (const tcu::ConstPixelBufferAccess& result)
+{
+       // Verify range of unique pixels
+       {
+               const deUint32  numUniqueColors = getUniqueColorsCount(result);
+               const deUint32  minUniqueColors = 3;
+
+               tcu::TestLog& log = m_context.getTestContext().getLog();
+
+               log << tcu::TestLog::Message
+                       << "\nMin. unique colors expected: " << minUniqueColors << "\n"
+                       << "Unique colors found: " << numUniqueColors << "\n"
+                       << tcu::TestLog::EndMessage;
+
+               if (numUniqueColors < minUniqueColors)
+                       return tcu::TestStatus::fail("Unique colors out of expected bounds");
+       }
+
+       // Verify shape of the rendered primitive (fuzzy-compare)
+       {
+               const tcu::TextureFormat        tcuColorFormat  = mapVkFormat(m_colorFormat);
+               const tcu::TextureFormat        tcuDepthFormat  = tcu::TextureFormat();
+               const ColorVertexShader         vertexShader;
+               const ColorFragmentShader       fragmentShader  (tcuColorFormat, tcuDepthFormat);
+               const rr::Program                       program                 (&vertexShader, &fragmentShader);
+               ReferenceRenderer                       refRenderer             (m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
+               rr::RenderState                         renderState             (refRenderer.getViewportState());
+
+               if (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
+               {
+                       VkPhysicalDeviceProperties deviceProperties;
+
+                       m_context.getInstanceInterface().getPhysicalDeviceProperties(m_context.getPhysicalDevice(), &deviceProperties);
+
+                       // gl_PointSize is clamped to pointSizeRange
+                       renderState.point.pointSize = deFloatMin(3.0f, deviceProperties.limits.pointSizeRange[1]);
+               }
+
+               refRenderer.colorClear(tcu::Vec4(0.0f));
+               refRenderer.draw(renderState, mapVkPrimitiveTopology(m_primitiveTopology), m_vertices);
+
+               if (!tcu::fuzzyCompare(m_context.getTestContext().getLog(), "FuzzyImageCompare", "Image comparison", refRenderer.getAccess(), result, 0.05f, tcu::COMPARE_LOG_RESULT))
+                       return tcu::TestStatus::fail("Primitive has unexpected shape");
+
+       }
+
+       return tcu::TestStatus::pass("Primitive rendered, unique colors within expected bounds");
+}
+
+
+// MinSampleShadingInstance
+
+MinSampleShadingInstance::MinSampleShadingInstance (Context&                                                                   context,
+                                                                                                       VkPrimitiveTopology                                                     topology,
+                                                                                                       const std::vector<Vertex4RGBA>&                         vertices,
+                                                                                                       const VkPipelineMultisampleStateCreateInfo&     multisampleStateParams,
+                                                                                                       const VkPipelineColorBlendAttachmentState&      colorBlendState)
+       : vkt::TestInstance                     (context)
+       , m_colorFormat                         (VK_FORMAT_R8G8B8A8_UNORM)
+       , m_renderSize                          (32, 32)
+       , m_primitiveTopology           (topology)
+       , m_vertices                            (vertices)
+       , m_multisampleStateParams      (multisampleStateParams)
+       , m_colorBlendState                     (colorBlendState)
+{
+       VkPhysicalDeviceFeatures deviceFeatures;
+
+       m_context.getInstanceInterface().getPhysicalDeviceFeatures(m_context.getPhysicalDevice(), &deviceFeatures);
+
+       if (!deviceFeatures.sampleRateShading)
+               throw tcu::NotSupportedError("Sample shading is not supported");
+}
+
+tcu::TestStatus MinSampleShadingInstance::iterate (void)
+{
+       de::MovePtr<tcu::TextureLevel>                          testShadingImage;
+       de::MovePtr<tcu::TextureLevel>                          minShadingImage;
+       de::MovePtr<tcu::TextureLevel>                          maxShadingImage;
+
+       // Render with test minSampleShading
+       {
+               MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState);
+               testShadingImage = renderer.render();
+       }
+
+       // Render with minSampleShading = 0.0f
+       {
+               VkPipelineMultisampleStateCreateInfo    multisampleParams       = m_multisampleStateParams;
+               multisampleParams.minSampleShading = 0.0f;
+
+               MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState);
+               minShadingImage = renderer.render();
+       }
+
+       // Render with minSampleShading = 1.0f
+       {
+               VkPipelineMultisampleStateCreateInfo    multisampleParams       = m_multisampleStateParams;
+               multisampleParams.minSampleShading = 1.0f;
+
+               MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState);
+               maxShadingImage = renderer.render();
+       }
+
+       return verifyImage(testShadingImage->getAccess(), minShadingImage->getAccess(), maxShadingImage->getAccess());
+}
+
+tcu::TestStatus MinSampleShadingInstance::verifyImage (const tcu::ConstPixelBufferAccess& testShadingImage, const tcu::ConstPixelBufferAccess& minShadingImage, const tcu::ConstPixelBufferAccess& maxShadingImage)
+{
+       const deUint32  testColorCount  = getUniqueColorsCount(testShadingImage);
+       const deUint32  minColorCount   = getUniqueColorsCount(minShadingImage);
+       const deUint32  maxColorCount   = getUniqueColorsCount(maxShadingImage);
+
+       tcu::TestLog& log = m_context.getTestContext().getLog();
+
+       log << tcu::TestLog::Message
+               << "\nColors found: " << testColorCount << "\n"
+               << "Min. colors expected: " << minColorCount << "\n"
+               << "Max. colors expected: " << maxColorCount << "\n"
+               << tcu::TestLog::EndMessage;
+
+       if (minColorCount > testColorCount || testColorCount > maxColorCount)
+               return tcu::TestStatus::fail("Unique colors out of expected bounds");
+       else
+               return tcu::TestStatus::pass("Unique colors within expected bounds");
+}
+
+SampleMaskInstance::SampleMaskInstance (Context&                                                                               context,
+                                                                               VkPrimitiveTopology                                                             topology,
+                                                                               const std::vector<Vertex4RGBA>&                                 vertices,
+                                                                               const VkPipelineMultisampleStateCreateInfo&             multisampleStateParams,
+                                                                               const VkPipelineColorBlendAttachmentState&              blendState)
+       : vkt::TestInstance                     (context)
+       , m_colorFormat                         (VK_FORMAT_R8G8B8A8_UNORM)
+       , m_renderSize                          (32, 32)
+       , m_primitiveTopology           (topology)
+       , m_vertices                            (vertices)
+       , m_multisampleStateParams      (multisampleStateParams)
+       , m_colorBlendState                     (blendState)
+{
+}
+
+tcu::TestStatus SampleMaskInstance::iterate (void)
+{
+       de::MovePtr<tcu::TextureLevel>                          testSampleMaskImage;
+       de::MovePtr<tcu::TextureLevel>                          minSampleMaskImage;
+       de::MovePtr<tcu::TextureLevel>                          maxSampleMaskImage;
+
+       // Render with test flags
+       {
+               MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState);
+               testSampleMaskImage = renderer.render();
+       }
+
+       // Render with all flags off
+       {
+               VkPipelineMultisampleStateCreateInfo    multisampleParams       = m_multisampleStateParams;
+               const std::vector<VkSampleMask>                 sampleMask                      (multisampleParams.rasterizationSamples / 32, (VkSampleMask)0);
+
+               multisampleParams.pSampleMask = sampleMask.data();
+
+               MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState);
+               minSampleMaskImage = renderer.render();
+       }
+
+       // Render with all flags on
+       {
+               VkPipelineMultisampleStateCreateInfo    multisampleParams       = m_multisampleStateParams;
+               const std::vector<VkSampleMask>                 sampleMask                      (multisampleParams.rasterizationSamples / 32, ~((VkSampleMask)0));
+
+               multisampleParams.pSampleMask = sampleMask.data();
+
+               MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState);
+               maxSampleMaskImage = renderer.render();
+       }
+
+       return verifyImage(testSampleMaskImage->getAccess(), minSampleMaskImage->getAccess(), maxSampleMaskImage->getAccess());
+}
+
+tcu::TestStatus SampleMaskInstance::verifyImage (const tcu::ConstPixelBufferAccess& testSampleMaskImage,
+                                                                                                const tcu::ConstPixelBufferAccess& minSampleMaskImage,
+                                                                                                const tcu::ConstPixelBufferAccess& maxSampleMaskImage)
+{
+       const deUint32  testColorCount  = getUniqueColorsCount(testSampleMaskImage);
+       const deUint32  minColorCount   = getUniqueColorsCount(minSampleMaskImage);
+       const deUint32  maxColorCount   = getUniqueColorsCount(maxSampleMaskImage);
+
+       tcu::TestLog& log = m_context.getTestContext().getLog();
+
+       log << tcu::TestLog::Message
+               << "\nColors found: " << testColorCount << "\n"
+               << "Min. colors expected: " << minColorCount << "\n"
+               << "Max. colors expected: " << maxColorCount << "\n"
+               << tcu::TestLog::EndMessage;
+
+       if (minColorCount > testColorCount || testColorCount > maxColorCount)
+               return tcu::TestStatus::fail("Unique colors out of expected bounds");
+       else
+               return tcu::TestStatus::pass("Unique colors within expected bounds");
+}
+
+tcu::TestStatus testRasterSamplesConsistency (Context& context, GeometryType geometryType)
+{
+       // Use triangle only.
+       DE_UNREF(geometryType);
+
+       const VkSampleCountFlagBits samples[] =
+       {
+               VK_SAMPLE_COUNT_1_BIT,
+               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
+       };
+
+       const Vertex4RGBA vertexData[3] =
+       {
+               {
+                       tcu::Vec4(-0.75f, 0.0f, 0.0f, 1.0f),
+                       tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
+               },
+               {
+                       tcu::Vec4(0.75f, 0.125f, 0.0f, 1.0f),
+                       tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
+               },
+               {
+                       tcu::Vec4(0.75f, -0.125f, 0.0f, 1.0f),
+                       tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
+               }
+       };
+
+       const std::vector<Vertex4RGBA>  vertices                        (vertexData, vertexData + 3);
+       deUint32                                                prevUniqueColors        = 2;
+       int                                                             renderCount                     = 0;
+
+       // Do not render with 1 sample (start with samplesNdx = 1).
+       for (int samplesNdx = 1; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
+       {
+               if (!isSupportedSampleCount(context.getInstanceInterface(), context.getPhysicalDevice(), samples[samplesNdx]))
+                       continue;
+
+               const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                      sType;
+                       DE_NULL,                                                                                                        // const void*                                                          pNext;
+                       0u,                                                                                                                     // VkPipelineMultisampleStateCreateFlags        flags;
+                       samples[samplesNdx],                                                                            // VkSampleCountFlagBits                                        rasterizationSamples;
+                       false,                                                                                                          // VkBool32                                                                     sampleShadingEnable;
+                       0.0f,                                                                                                           // float                                                                        minSampleShading;
+                       DE_NULL,                                                                                                        // const VkSampleMask*                                          pSampleMask;
+                       false,                                                                                                          // VkBool32                                                                     alphaToCoverageEnable;
+                       false                                                                                                           // VkBool32                                                                     alphaToOneEnable;
+               };
+
+               MultisampleRenderer                             renderer                (context, VK_FORMAT_R8G8B8A8_UNORM, tcu::IVec2(32, 32), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, vertices, multisampleStateParams, getDefaultColorBlendAttachmentState());
+               de::MovePtr<tcu::TextureLevel>  result                  = renderer.render();
+               const deUint32                                  uniqueColors    = getUniqueColorsCount(result->getAccess());
+
+               renderCount++;
+
+               if (prevUniqueColors > uniqueColors)
+               {
+                       std::ostringstream message;
+
+                       message << "More unique colors generated with " << samples[samplesNdx - 1] << " than with " << samples[samplesNdx];
+                       return tcu::TestStatus::fail(message.str());
+               }
+
+               prevUniqueColors = uniqueColors;
+       }
+
+       if (renderCount == 0)
+               throw tcu::NotSupportedError("Multisampling is unsupported");
+
+       return tcu::TestStatus::pass("Number of unique colors increases as the sample count increases");
+}
+
+
+// AlphaToOneInstance
+
+AlphaToOneInstance::AlphaToOneInstance (Context&                                                                       context,
+                                                                               VkPrimitiveTopology                                                     topology,
+                                                                               const std::vector<Vertex4RGBA>&                         vertices,
+                                                                               const VkPipelineMultisampleStateCreateInfo&     multisampleStateParams,
+                                                                               const VkPipelineColorBlendAttachmentState&      blendState)
+       : vkt::TestInstance                     (context)
+       , m_colorFormat                         (VK_FORMAT_R8G8B8A8_UNORM)
+       , m_renderSize                          (32, 32)
+       , m_primitiveTopology           (topology)
+       , m_vertices                            (vertices)
+       , m_multisampleStateParams      (multisampleStateParams)
+       , m_colorBlendState                     (blendState)
+{
+       VkPhysicalDeviceFeatures deviceFeatures;
+
+       context.getInstanceInterface().getPhysicalDeviceFeatures(context.getPhysicalDevice(), &deviceFeatures);
+
+       if (!deviceFeatures.alphaToOne)
+               throw tcu::NotSupportedError("Alpha-to-one is not supported");
+}
+
+tcu::TestStatus AlphaToOneInstance::iterate    (void)
+{
+       DE_ASSERT(m_multisampleStateParams.alphaToOneEnable);
+       DE_ASSERT(m_colorBlendState.blendEnable);
+
+       de::MovePtr<tcu::TextureLevel>  alphaOneImage;
+       de::MovePtr<tcu::TextureLevel>  noAlphaOneImage;
+
+       // Render with blend enabled and alpha to one on
+       {
+               MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState);
+               alphaOneImage = renderer.render();
+       }
+
+       // Render with blend enabled and alpha to one off
+       {
+               VkPipelineMultisampleStateCreateInfo    multisampleParams       = m_multisampleStateParams;
+               multisampleParams.alphaToOneEnable = false;
+
+               MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState);
+               noAlphaOneImage = renderer.render();
+       }
+
+       return verifyImage(alphaOneImage->getAccess(), noAlphaOneImage->getAccess());
+}
+
+tcu::TestStatus AlphaToOneInstance::verifyImage (const tcu::ConstPixelBufferAccess&    alphaOneImage,
+                                                                                                const tcu::ConstPixelBufferAccess&     noAlphaOneImage)
+{
+       for (int y = 0; y < m_renderSize.y(); y++)
+       {
+               for (int x = 0; x < m_renderSize.x(); x++)
+               {
+                       if (!tcu::boolAll(tcu::greaterThanEqual(alphaOneImage.getPixel(x, y), noAlphaOneImage.getPixel(x, y))))
+                       {
+                               std::ostringstream message;
+                               message << "Unsatisfied condition: " << alphaOneImage.getPixel(x, y) << " >= " << noAlphaOneImage.getPixel(x, y);
+                               return tcu::TestStatus::fail(message.str());
+                       }
+               }
+       }
+
+       return tcu::TestStatus::pass("Image rendered with alpha-to-one contains pixels of image rendered with no alpha-to-one");
+}
+
+
+// AlphaToCoverageInstance
+
+AlphaToCoverageInstance::AlphaToCoverageInstance (Context&                                                                             context,
+                                                                                                 VkPrimitiveTopology                                                   topology,
+                                                                                                 const std::vector<Vertex4RGBA>&                               vertices,
+                                                                                                 const VkPipelineMultisampleStateCreateInfo&   multisampleStateParams,
+                                                                                                 const VkPipelineColorBlendAttachmentState&    blendState,
+                                                                                                 GeometryType                                                                  geometryType)
+       : vkt::TestInstance                     (context)
+       , m_colorFormat                         (VK_FORMAT_R8G8B8A8_UNORM)
+       , m_renderSize                          (32, 32)
+       , m_primitiveTopology           (topology)
+       , m_vertices                            (vertices)
+       , m_multisampleStateParams      (multisampleStateParams)
+       , m_colorBlendState                     (blendState)
+       , m_geometryType                        (geometryType)
+{
+}
+
+tcu::TestStatus AlphaToCoverageInstance::iterate (void)
+{
+       DE_ASSERT(m_multisampleStateParams.alphaToCoverageEnable);
+
+       de::MovePtr<tcu::TextureLevel>  result;
+       MultisampleRenderer                             renderer        (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState);
+
+       result = renderer.render();
+
+       return verifyImage(result->getAccess());
+}
+
+tcu::TestStatus AlphaToCoverageInstance::verifyImage (const tcu::ConstPixelBufferAccess&       result)
+{
+       float maxColorValue;
+
+       switch (m_geometryType)
+       {
+               case GEOMETRY_TYPE_OPAQUE_QUAD:
+                       maxColorValue = 1.01f;
+                       break;
+
+               case GEOMETRY_TYPE_TRANSLUCENT_QUAD:
+                       maxColorValue = 0.5f;
+                       break;
+
+               case GEOMETRY_TYPE_INVISIBLE_QUAD:
+                       maxColorValue = 0.01f;
+                       break;
+
+               default:
+                       DE_ASSERT(false);
+       }
+
+       for (int y = 0; y < m_renderSize.y(); y++)
+       {
+               for (int x = 0; x < m_renderSize.x(); x++)
+               {
+                       if (result.getPixel(x, y).x() > maxColorValue)
+                       {
+                               std::ostringstream message;
+                               message << "Pixel is not below the threshold value (" << result.getPixel(x, y).x() << " > " << maxColorValue << ")";
+                               return tcu::TestStatus::fail(message.str());
+                       }
+               }
+       }
+
+       return tcu::TestStatus::pass("Image matches reference value");
+}
+
+
+// MultisampleRenderer
+
+MultisampleRenderer::MultisampleRenderer (Context&                                                                             context,
+                                                                                 VkFormat                                                                              colorFormat,
+                                                                                 const tcu::IVec2&                                                             renderSize,
+                                                                                 VkPrimitiveTopology                                                   topology,
+                                                                                 const std::vector<Vertex4RGBA>&                               vertices,
+                                                                                 const VkPipelineMultisampleStateCreateInfo&   multisampleStateParams,
+                                                                                 const VkPipelineColorBlendAttachmentState&    blendState)
+
+       : m_context                                     (context)
+       , m_colorFormat                         (colorFormat)
+       , m_renderSize                          (renderSize)
+       , m_multisampleStateParams      (multisampleStateParams)
+       , m_colorBlendState                     (blendState)
+{
+       if (!isSupportedSampleCount(context.getInstanceInterface(), context.getPhysicalDevice(), multisampleStateParams.rasterizationSamples))
+               throw tcu::NotSupportedError("Unsupported number of rasterization samples");
+
+       const DeviceInterface&          vk                                              = context.getDeviceInterface();
+       const VkDevice                          vkDevice                                = context.getDevice();
+       const deUint32                          queueFamilyIndex                = context.getUniversalQueueFamilyIndex();
+       SimpleAllocator                         memAlloc                                (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
+       const VkComponentMapping        componentMappingRGBA    = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
+
+       // Create color image
+       {
+               const VkImageCreateInfo colorImageParams =
+               {
+                       VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                                            // VkStructureType                      sType;
+                       DE_NULL,                                                                                                                                        // const void*                          pNext;
+                       0u,                                                                                                                                                     // VkImageCreateFlags           flags;
+                       VK_IMAGE_TYPE_2D,                                                                                                                       // VkImageType                          imageType;
+                       m_colorFormat,                                                                                                                          // VkFormat                                     format;
+                       { m_renderSize.x(), m_renderSize.y(), 1u },                                                                     // VkExtent3D                           extent;
+                       1u,                                                                                                                                                     // deUint32                                     mipLevels;
+                       1u,                                                                                                                                                     // deUint32                                     arrayLayers;
+                       m_multisampleStateParams.rasterizationSamples,                                                          // VkSampleCountFlagBits        samples;
+                       VK_IMAGE_TILING_OPTIMAL,                                                                                                        // VkImageTiling                        tiling;
+                       VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,          // VkImageUsageFlags            usage;
+                       VK_SHARING_MODE_EXCLUSIVE,                                                                                                      // VkSharingMode                        sharingMode;
+                       1u,                                                                                                                                                     // deUint32                                     queueFamilyIndexCount;
+                       &queueFamilyIndex,                                                                                                                      // const deUint32*                      pQueueFamilyIndices;
+                       VK_IMAGE_LAYOUT_UNDEFINED,                                                                                                      // VkImageLayout                        initialLayout;
+               };
+
+               m_colorImage                    = createImage(vk, vkDevice, &colorImageParams);
+
+               // Allocate and bind color image memory
+               m_colorImageAlloc               = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
+               VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
+       }
+
+       // Create resolve image
+       {
+               const VkImageCreateInfo resolveImageParams =
+               {
+                       VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                                                    // VkStructureType                      sType;
+                       DE_NULL,                                                                                                                                                // const void*                          pNext;
+                       0u,                                                                                                                                                             // VkImageCreateFlags           flags;
+                       VK_IMAGE_TYPE_2D,                                                                                                                               // VkImageType                          imageType;
+                       m_colorFormat,                                                                                                                                  // VkFormat                                     format;
+                       { m_renderSize.x(), m_renderSize.y(), 1u },                                                                             // VkExtent3D                           extent;
+                       1u,                                                                                                                                                             // deUint32                                     mipLevels;
+                       1u,                                                                                                                                                             // deUint32                                     arrayLayers;
+                       VK_SAMPLE_COUNT_1_BIT,                                                                                                                  // VkSampleCountFlagBits        samples;
+                       VK_IMAGE_TILING_OPTIMAL,                                                                                                                // VkImageTiling                        tiling;
+                       VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |                 // VkImageUsageFlags            usage;
+                               VK_IMAGE_USAGE_TRANSFER_DST_BIT,
+                       VK_SHARING_MODE_EXCLUSIVE,                                                                                                              // VkSharingMode                        sharingMode;
+                       1u,                                                                                                                                                             // deUint32                                     queueFamilyIndexCount;
+                       &queueFamilyIndex,                                                                                                                              // const deUint32*                      pQueueFamilyIndices;
+                       VK_IMAGE_LAYOUT_UNDEFINED                                                                                                               // VkImageLayout                        initialLayout;
+               };
+
+               m_resolveImage = createImage(vk, vkDevice, &resolveImageParams);
+
+               // Allocate and bind resolve image memory
+               m_resolveImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_resolveImage), MemoryRequirement::Any);
+               VK_CHECK(vk.bindImageMemory(vkDevice, *m_resolveImage, m_resolveImageAlloc->getMemory(), m_resolveImageAlloc->getOffset()));
+       }
+
+       // Create color attachment view
+       {
+               const VkImageViewCreateInfo colorAttachmentViewParams =
+               {
+                       VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,               // VkStructureType                      sType;
+                       DE_NULL,                                                                                // const void*                          pNext;
+                       0u,                                                                                             // VkImageViewCreateFlags       flags;
+                       *m_colorImage,                                                                  // VkImage                                      image;
+                       VK_IMAGE_VIEW_TYPE_2D,                                                  // VkImageViewType                      viewType;
+                       m_colorFormat,                                                                  // VkFormat                                     format;
+                       componentMappingRGBA,                                                   // VkComponentMapping           components;
+                       { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }   // VkImageSubresourceRange      subresourceRange;
+               };
+
+               m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
+       }
+
+       // Create resolve attachment view
+       {
+               const VkImageViewCreateInfo resolveAttachmentViewParams =
+               {
+                       VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,               // VkStructureType                      sType;
+                       DE_NULL,                                                                                // const void*                          pNext;
+                       0u,                                                                                             // VkImageViewCreateFlags       flags;
+                       *m_resolveImage,                                                                // VkImage                                      image;
+                       VK_IMAGE_VIEW_TYPE_2D,                                                  // VkImageViewType                      viewType;
+                       m_colorFormat,                                                                  // VkFormat                                     format;
+                       componentMappingRGBA,                                                   // VkComponentMapping           components;
+                       { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }   // VkImageSubresourceRange      subresourceRange;
+               };
+
+               m_resolveAttachmentView = createImageView(vk, vkDevice, &resolveAttachmentViewParams);
+       }
+
+       // Create render pass
+       {
+               const VkAttachmentDescription attachmentDescriptions[2] =
+               {
+                       {
+                               0u,                                                                                                     // VkAttachmentDescriptionFlags         flags;
+                               m_colorFormat,                                                                          // VkFormat                                                     format;
+                               m_multisampleStateParams.rasterizationSamples,          // VkSampleCountFlagBits                        samples;
+                               VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                           loadOp;
+                               VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
+                               VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                           stencilLoadOp;
+                               VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
+                               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                        initialLayout;
+                               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout                                        finalLayout;
+                       },
+                       {
+                               0u,                                                                                                     // VkAttachmentDescriptionFlags         flags;
+                               m_colorFormat,                                                                          // VkFormat                                                     format;
+                               VK_SAMPLE_COUNT_1_BIT,                                                          // VkSampleCountFlagBits                        samples;
+                               VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                           loadOp;
+                               VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
+                               VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                           stencilLoadOp;
+                               VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
+                               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                        initialLayout;
+                               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout                                        finalLayout;
+                       }
+               };
+
+               const VkAttachmentReference colorAttachmentReference =
+               {
+                       0u,                                                                                                     // deUint32                     attachment;
+                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout        layout;
+               };
+
+               const VkAttachmentReference resolveAttachmentReference =
+               {
+                       1u,                                                                                                     // deUint32                     attachment;
+                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout        layout;
+               };
+
+               const VkSubpassDescription subpassDescription =
+               {
+                       0u,                                                                                                             // VkSubpassDescriptionFlags    flags;
+                       VK_PIPELINE_BIND_POINT_GRAPHICS,                                                // VkPipelineBindPoint                  pipelineBindPoint;
+                       0u,                                                                                                             // deUint32                                             inputAttachmentCount;
+                       DE_NULL,                                                                                                // const VkAttachmentReference* pInputAttachments;
+                       1u,                                                                                                             // deUint32                                             colorAttachmentCount;
+                       &colorAttachmentReference,                                                              // const VkAttachmentReference* pColorAttachments;
+                       &resolveAttachmentReference,                                                    // const VkAttachmentReference* pResolveAttachments;
+                       DE_NULL,                                                                                                // const VkAttachmentReference* pDepthStencilAttachment;
+                       0u,                                                                                                             // deUint32                                             preserveAttachmentCount;
+                       DE_NULL                                                                                                 // const VkAttachmentReference* pPreserveAttachments;
+               };
+
+               const VkRenderPassCreateInfo renderPassParams =
+               {
+                       VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                      // VkStructureType                                      sType;
+                       DE_NULL,                                                                                        // const void*                                          pNext;
+                       0u,                                                                                                     // VkRenderPassCreateFlags                      flags;
+                       2u,                                                                                                     // deUint32                                                     attachmentCount;
+                       attachmentDescriptions,                                                         // const VkAttachmentDescription*       pAttachments;
+                       1u,                                                                                                     // deUint32                                                     subpassCount;
+                       &subpassDescription,                                                            // const VkSubpassDescription*          pSubpasses;
+                       0u,                                                                                                     // deUint32                                                     dependencyCount;
+                       DE_NULL                                                                                         // const VkSubpassDependency*           pDependencies;
+               };
+
+               m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
+       }
+
+       // Create framebuffer
+       {
+               const VkImageView attachments[2] =
+               {
+                       *m_colorAttachmentView,
+                       *m_resolveAttachmentView
+               };
+
+               const VkFramebufferCreateInfo framebufferParams =
+               {
+                       VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,                      // VkStructureType                              sType;
+                       DE_NULL,                                                                                        // const void*                                  pNext;
+                       0u,                                                                                                     // VkFramebufferCreateFlags             flags;
+                       *m_renderPass,                                                                          // VkRenderPass                                 renderPass;
+                       2u,                                                                                                     // deUint32                                             attachmentCount;
+                       attachments,                                                                            // const VkImageView*                   pAttachments;
+                       (deUint32)m_renderSize.x(),                                                     // deUint32                                             width;
+                       (deUint32)m_renderSize.y(),                                                     // deUint32                                             height;
+                       1u                                                                                                      // deUint32                                             layers;
+               };
+
+               m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
+       }
+
+       // Create pipeline layout
+       {
+               const VkPipelineLayoutCreateInfo pipelineLayoutParams =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                                      sType;
+                       DE_NULL,                                                                                        // const void*                                          pNext;
+                       0u,                                                                                                     // VkPipelineLayoutCreateFlags          flags;
+                       0u,                                                                                                     // deUint32                                                     setLayoutCount;
+                       DE_NULL,                                                                                        // const VkDescriptorSetLayout*         pSetLayouts;
+                       0u,                                                                                                     // deUint32                                                     pushConstantRangeCount;
+                       DE_NULL                                                                                         // const VkPushConstantRange*           pPushConstantRanges;
+               };
+
+               m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
+       }
+
+       m_vertexShaderModule    = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
+       m_fragmentShaderModule  = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
+
+       // Create pipeline
+       {
+               const VkPipelineShaderStageCreateInfo shaderStageParams[2] =
+               {
+                       {
+                               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,            // VkStructureType                                              sType;
+                               DE_NULL,                                                                                                        // const void*                                                  pNext;
+                               0u,                                                                                                                     // VkPipelineShaderStageCreateFlags             flags;
+                               VK_SHADER_STAGE_VERTEX_BIT,                                                                     // VkShaderStageFlagBits                                stage;
+                               *m_vertexShaderModule,                                                                          // VkShaderModule                                               module;
+                               "main",                                                                                                         // const char*                                                  pName;
+                               DE_NULL                                                                                                         // const VkSpecializationInfo*                  pSpecializationInfo;
+                       },
+                       {
+                               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,            // VkStructureType                                              sType;
+                               DE_NULL,                                                                                                        // const void*                                                  pNext;
+                               0u,                                                                                                                     // VkPipelineShaderStageCreateFlags             flags;
+                               VK_SHADER_STAGE_FRAGMENT_BIT,                                                           // VkShaderStageFlagBits                                stage;
+                               *m_fragmentShaderModule,                                                                        // VkShaderModule                                               module;
+                               "main",                                                                                                         // const char*                                                  pName;
+                               DE_NULL                                                                                                         // const VkSpecializationInfo*                  pSpecializationInfo;
+                       }
+               };
+
+               const VkVertexInputBindingDescription vertexInputBindingDescription =
+               {
+                       0u,                                                                     // deUint32                             binding;
+                       sizeof(Vertex4RGBA),                            // deUint32                             stride;
+                       VK_VERTEX_INPUT_RATE_VERTEX                     // VkVertexInputRate    inputRate;
+               };
+
+               const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
+               {
+                       {
+                               0u,                                                                     // deUint32     location;
+                               0u,                                                                     // deUint32     binding;
+                               VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat     format;
+                               0u                                                                      // deUint32     offset;
+                       },
+                       {
+                               1u,                                                                     // deUint32     location;
+                               0u,                                                                     // deUint32     binding;
+                               VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat     format;
+                               DE_OFFSET_OF(Vertex4RGBA, color),       // deUint32     offset;
+                       }
+               };
+
+               const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,              // VkStructureType                                                      sType;
+                       DE_NULL,                                                                                                                // const void*                                                          pNext;
+                       0u,                                                                                                                             // VkPipelineVertexInputStateCreateFlags        flags;
+                       1u,                                                                                                                             // deUint32                                                                     vertexBindingDescriptionCount;
+                       &vertexInputBindingDescription,                                                                 // const VkVertexInputBindingDescription*       pVertexBindingDescriptions;
+                       2u,                                                                                                                             // deUint32                                                                     vertexAttributeDescriptionCount;
+                       vertexInputAttributeDescriptions                                                                // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions;
+               };
+
+               const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                                                      sType;
+                       DE_NULL,                                                                                                                // const void*                                                          pNext;
+                       0u,                                                                                                                             // VkPipelineInputAssemblyStateCreateFlags      flags;
+                       topology,                                                                                                               // VkPrimitiveTopology                                          topology;
+                       false                                                                                                                   // VkBool32                                                                     primitiveRestartEnable;
+               };
+
+               const VkViewport viewport =
+               {
+                       0.0f,                                           // float        x;
+                       0.0f,                                           // float        y;
+                       (float)m_renderSize.x(),        // float        width;
+                       (float)m_renderSize.y(),        // float        height;
+                       0.0f,                                           // float        minDepth;
+                       1.0f                                            // float        maxDepth;
+               };
+
+               const VkRect2D scissor =
+               {
+                       { 0, 0 },                                                                                               // VkOffset2D  offset;
+                       { m_renderSize.x(), m_renderSize.y() }                                  // VkExtent2D  extent;
+               };
+
+               const VkPipelineViewportStateCreateInfo viewportStateParams =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,                  // VkStructureType                                              sType;
+                       DE_NULL,                                                                                                                // const void*                                                  pNext;
+                       0u,                                                                                                                             // VkPipelineViewportStateCreateFlags   flags;
+                       1u,                                                                                                                             // deUint32                                                             viewportCount;
+                       &viewport,                                                                                                              // const VkViewport*                                    pViewports;
+                       1u,                                                                                                                             // deUint32                                                             scissorCount;
+                       &scissor                                                                                                                // const VkRect2D*                                              pScissors;
+               };
+
+               const VkPipelineRasterizationStateCreateInfo rasterStateParams =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                                                      sType;
+                       DE_NULL,                                                                                                                // const void*                                                          pNext;
+                       0u,                                                                                                                             // VkPipelineRasterizationStateCreateFlags      flags;
+                       false,                                                                                                                  // VkBool32                                                                     depthClampEnable;
+                       false,                                                                                                                  // VkBool32                                                                     rasterizerDiscardEnable;
+                       VK_POLYGON_MODE_FILL,                                                                                   // VkPolygonMode                                                        polygonMode;
+                       VK_CULL_MODE_NONE,                                                                                              // VkCullModeFlags                                                      cullMode;
+                       VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                // VkFrontFace                                                          frontFace;
+                       VK_FALSE,                                                                                                               // VkBool32                                                                     depthBiasEnable;
+                       0.0f,                                                                                                                   // float                                                                        depthBiasConstantFactor;
+                       0.0f,                                                                                                                   // float                                                                        depthBiasClamp;
+                       0.0f,                                                                                                                   // float                                                                        depthBiasSlopeFactor;
+                       1.0f                                                                                                                    // float                                                                        lineWidth;
+               };
+
+               const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                                                              sType;
+                       DE_NULL,                                                                                                        // const void*                                                                  pNext;
+                       0u,                                                                                                                     // VkPipelineColorBlendStateCreateFlags                 flags;
+                       false,                                                                                                          // VkBool32                                                                             logicOpEnable;
+                       VK_LOGIC_OP_COPY,                                                                                       // VkLogicOp                                                                    logicOp;
+                       1u,                                                                                                                     // deUint32                                                                             attachmentCount;
+                       &m_colorBlendState,                                                                                     // const VkPipelineColorBlendAttachmentState*   pAttachments;
+                       { 0.0f, 0.0f, 0.0f, 0.0f }                                                                      // float                                                                                blendConstants[4];
+               };
+
+               const VkPipelineDynamicStateCreateInfo  dynamicStateParams              =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,           // VkStructureType                                              sType;
+                       DE_NULL,                                                                                                        // const void*                                                  pNext;
+                       0u,                                                                                                                     // VkPipelineDynamicStateCreateFlags    flags;
+                       0u,                                                                                                                     // deUint32                                                             dynamicStateCount;
+                       DE_NULL                                                                                                         // const VkDynamicState*                                pDynamicStates;
+               };
+
+               const VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,     // VkStructureType                                                      sType;
+                       DE_NULL,                                                                                                        // const void*                                                          pNext;
+                       0u,                                                                                                                     // VkPipelineDepthStencilStateCreateFlags       flags;
+                       false,                                                                                                          // VkBool32                                                                     depthTestEnable;
+                       false,                                                                                                          // VkBool32                                                                     depthWriteEnable;
+                       VK_COMPARE_OP_LESS,                                                                                     // VkCompareOp                                                          depthCompareOp;
+                       false,                                                                                                          // VkBool32                                                                     depthBoundsTestEnable;
+                       false,                                                                                                          // VkBool32                                                                     stencilTestEnable;
+                       // VkStencilOpState     front;
+                       {
+                               VK_STENCIL_OP_KEEP,             // VkStencilOp  failOp;
+                               VK_STENCIL_OP_KEEP,             // VkStencilOp  passOp;
+                               VK_STENCIL_OP_KEEP,             // VkStencilOp  depthFailOp;
+                               VK_COMPARE_OP_NEVER,    // VkCompareOp  compareOp;
+                               0u,                                             // deUint32             compareMask;
+                               0u,                                             // deUint32             writeMask;
+                               0u,                                             // deUint32             reference;
+                       },
+                       // VkStencilOpState     back;
+                       {
+                               VK_STENCIL_OP_KEEP,             // VkStencilOp  failOp;
+                               VK_STENCIL_OP_KEEP,             // VkStencilOp  passOp;
+                               VK_STENCIL_OP_KEEP,             // VkStencilOp  depthFailOp;
+                               VK_COMPARE_OP_NEVER,    // VkCompareOp  compareOp;
+                               0u,                                             // deUint32             compareMask;
+                               0u,                                             // deUint32             writeMask;
+                               0u,                                             // deUint32             reference;
+                       },
+                       -1.0f,                                                                                                          // float                        minDepthBounds;
+                       +1.0f,                                                                                                          // float                        maxDepthBounds;
+               };
+
+               const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
+               {
+                       VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,        // VkStructureType                                                                      sType;
+                       DE_NULL,                                                                                        // const void*                                                                          pNext;
+                       0u,                                                                                                     // VkPipelineCreateFlags                                                        flags;
+                       2u,                                                                                                     // deUint32                                                                                     stageCount;
+                       shaderStageParams,                                                                      // const VkPipelineShaderStageCreateInfo*                       pStages;
+                       &vertexInputStateParams,                                                        // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
+                       &inputAssemblyStateParams,                                                      // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
+                       DE_NULL,                                                                                        // const VkPipelineTessellationStateCreateInfo*         pTessellationState;
+                       &viewportStateParams,                                                           // const VkPipelineViewportStateCreateInfo*                     pViewportState;
+                       &rasterStateParams,                                                                     // const VkPipelineRasterizationStateCreateInfo*        pRasterizationState;
+                       &m_multisampleStateParams,                                                      // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
+                       &depthStencilStateParams,                                                       // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
+                       &colorBlendStateParams,                                                         // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
+                       &dynamicStateParams,                                                            // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
+                       *m_pipelineLayout,                                                                      // VkPipelineLayout                                                                     layout;
+                       *m_renderPass,                                                                          // VkRenderPass                                                                         renderPass;
+                       0u,                                                                                                     // deUint32                                                                                     subpass;
+                       0u,                                                                                                     // VkPipeline                                                                           basePipelineHandle;
+                       0u                                                                                                      // deInt32                                                                                      basePipelineIndex;
+               };
+
+               m_graphicsPipeline      = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
+       }
+
+       // Create vertex buffer
+       {
+               const VkBufferCreateInfo vertexBufferParams =
+               {
+                       VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
+                       DE_NULL,                                                                        // const void*                  pNext;
+                       0u,                                                                                     // VkBufferCreateFlags  flags;
+                       1024u,                                                                          // VkDeviceSize                 size;
+                       VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,                      // VkBufferUsageFlags   usage;
+                       VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
+                       1u,                                                                                     // deUint32                             queueFamilyIndexCount;
+                       &queueFamilyIndex                                                       // const deUint32*              pQueueFamilyIndices;
+               };
+
+               m_vertexBuffer          = createBuffer(vk, vkDevice, &vertexBufferParams);
+               m_vertexBufferAlloc     = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
+
+               VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
+
+               // Load vertices into vertex buffer
+               deMemcpy(m_vertexBufferAlloc->getHostPtr(), vertices.data(), vertices.size() * sizeof(Vertex4RGBA));
+               flushMappedMemoryRange(vk, vkDevice, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset(), vertexBufferParams.size);
+       }
+
+       // Create command pool
+       {
+               const VkCommandPoolCreateInfo cmdPoolParams =
+               {
+                       VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,             // VkStructureType                              sType;
+                       DE_NULL,                                                                                // const void*                                  pNext;
+                       VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,                   // VkCommandPoolCreateFlags             flags;
+                       queueFamilyIndex,                                                               // deUint32                                             queueFamilyIndex;
+               };
+
+               m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
+       }
+
+       // Create command buffer
+       {
+               const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
+               {
+                       VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType                      sType;
+                       DE_NULL,                                                                                // const void*                          pNext;
+                       *m_cmdPool,                                                                             // VkCommandPool                        commandPool;
+                       VK_COMMAND_BUFFER_LEVEL_PRIMARY,                                // VkCommandBufferLevel level;
+                       1u                                                                                              // deUint32                             bufferCount;
+               };
+
+               const VkCommandBufferBeginInfo cmdBufferBeginInfo =
+               {
+                       VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,    // VkStructureType                                      sType;
+                       DE_NULL,                                                                                // const void*                                          pNext;
+                       0u,                                                                                             // VkCommandBufferUsageFlags            flags;
+                       DE_NULL,                                                                                // VkRenderPass                                         renderPass;
+                       0u,                                                                                             // deUint32                                                     subpass;
+                       DE_NULL,                                                                                // VkFramebuffer                                        framebuffer;
+                       false,                                                                                  // VkBool32                                                     occlusionQueryEnable;
+                       0u,                                                                                             // VkQueryControlFlags                          queryFlags;
+                       0u                                                                                              // VkQueryPipelineStatisticFlags        pipelineStatistics;
+               };
+
+               VkClearValue colorClearValue;
+               colorClearValue.color.float32[0] = 0.0f;
+               colorClearValue.color.float32[1] = 0.0f;
+               colorClearValue.color.float32[2] = 0.0f;
+               colorClearValue.color.float32[3] = 0.0f;
+
+               const VkClearValue clearValues[2] =
+               {
+                       colorClearValue,
+                       colorClearValue
+               };
+
+               const VkRenderPassBeginInfo renderPassBeginInfo =
+               {
+                       VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,                               // VkStructureType              sType;
+                       DE_NULL,                                                                                                // const void*                  pNext;
+                       *m_renderPass,                                                                                  // VkRenderPass                 renderPass;
+                       *m_framebuffer,                                                                                 // VkFramebuffer                framebuffer;
+                       { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } },   // VkRect2D                             renderArea;
+                       2,                                                                                                              // deUint32                             clearValueCount;
+                       clearValues                                                                                             // const VkClearValue*  pClearValues;
+               };
+
+               m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo);
+
+               VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
+               vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+               VkDeviceSize vertexBufferOffset = 0u;
+
+               vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
+               vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
+               vk.cmdDraw(*m_cmdBuffer, (deUint32)vertices.size(), 1, 0, 0);
+
+               vk.cmdEndRenderPass(*m_cmdBuffer);
+
+               VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
+       }
+
+       // Create fence
+       {
+               const VkFenceCreateInfo fenceParams =
+               {
+                       VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,    // VkStructureType              sType;
+                       DE_NULL,                                                                // const void*                  pNext;
+                       0u                                                                              // VkFenceCreateFlags   flags;
+               };
+
+               m_fence = createFence(vk, vkDevice, &fenceParams);
+       }
+}
+
+MultisampleRenderer::~MultisampleRenderer (void)
+{
+}
+
+de::MovePtr<tcu::TextureLevel> MultisampleRenderer::render (void)
+{
+       const DeviceInterface&          vk                                      = m_context.getDeviceInterface();
+       const VkDevice                          vkDevice                        = m_context.getDevice();
+       const VkQueue                           queue                           = m_context.getUniversalQueue();
+       const deUint32                          queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
+       SimpleAllocator                         allocator                       (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
+       const VkSubmitInfo                      submitInfo      =
+       {
+               VK_STRUCTURE_TYPE_SUBMIT_INFO,  // VkStructureType                      sType;
+               DE_NULL,                                                // const void*                          pNext;
+               0u,                                                             // deUint32                                     waitSemaphoreCount;
+               DE_NULL,                                                // const VkSemaphore*           pWaitSemaphores;
+               1u,                                                             // deUint32                                     commandBufferCount;
+               &m_cmdBuffer.get(),                             // const VkCommandBuffer*       pCommandBuffers;
+               0u,                                                             // deUint32                                     signalSemaphoreCount;
+               DE_NULL                                                 // const VkSemaphore*           pSignalSemaphores;
+       };
+
+       VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
+       VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
+       VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
+
+       return readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_resolveImage, m_colorFormat, m_renderSize);
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createMultisampleTests (tcu::TestContext& testCtx)
+{
+       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
+       };
+
+       de::MovePtr<tcu::TestCaseGroup> multisampleTests (new tcu::TestCaseGroup(testCtx, "multisample", ""));
+
+       // Rasterization samples tests
+       {
+               de::MovePtr<tcu::TestCaseGroup> rasterizationSamplesTests(new tcu::TestCaseGroup(testCtx, "raster_samples", ""));
+
+               for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
+               {
+                       std::ostringstream caseName;
+                       caseName << "samples_" << samples[samplesNdx];
+
+                       de::MovePtr<tcu::TestCaseGroup> samplesTests    (new tcu::TestCaseGroup(testCtx, caseName.str().c_str(), ""));
+
+                       samplesTests->addChild(new RasterizationSamplesTest(testCtx, "primitive_triangle", "", samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_TRIANGLE));
+                       samplesTests->addChild(new RasterizationSamplesTest(testCtx, "primitive_line", "", samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_LINE));
+                       samplesTests->addChild(new RasterizationSamplesTest(testCtx, "primitive_point", "", samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_POINT));
+
+                       rasterizationSamplesTests->addChild(samplesTests.release());
+               }
+
+               multisampleTests->addChild(rasterizationSamplesTests.release());
+       }
+
+       // Raster samples consistency check
+       {
+               de::MovePtr<tcu::TestCaseGroup> rasterSamplesConsistencyTests(new tcu::TestCaseGroup(testCtx, "raster_samples_consistency", ""));
+
+               addFunctionCaseWithPrograms(rasterSamplesConsistencyTests.get(),
+                                                                       "unique_colors_check",
+                                                                       "",
+                                                                       initMultisamplePrograms,
+                                                                       testRasterSamplesConsistency,
+                                                                       GEOMETRY_TYPE_OPAQUE_TRIANGLE);
+
+               multisampleTests->addChild(rasterSamplesConsistencyTests.release());
+       }
+
+       // minSampleShading tests
+       {
+               struct TestConfig
+               {
+                       const char*     name;
+                       float           minSampleShading;
+               };
+
+               const TestConfig testConfigs[] =
+               {
+                       { "min_0_0",    0.0f },
+                       { "min_0_25",   0.25f },
+                       { "min_0_5",    0.5f },
+                       { "min_0_75",   0.75f },
+                       { "min_1_0",    1.0f }
+               };
+
+               de::MovePtr<tcu::TestCaseGroup> minSampleShadingTests(new tcu::TestCaseGroup(testCtx, "min_sample_shading", ""));
+
+               for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testConfigs); configNdx++)
+               {
+                       const TestConfig&                               testConfig                              = testConfigs[configNdx];
+                       de::MovePtr<tcu::TestCaseGroup> minShadingValueTests    (new tcu::TestCaseGroup(testCtx, testConfigs[configNdx].name, ""));
+
+                       for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
+                       {
+                               std::ostringstream caseName;
+                               caseName << "samples_" << samples[samplesNdx];
+
+                               de::MovePtr<tcu::TestCaseGroup> samplesTests    (new tcu::TestCaseGroup(testCtx, caseName.str().c_str(), ""));
+
+                               samplesTests->addChild(new MinSampleShadingTest(testCtx, "primitive_triangle", "", samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_TRIANGLE));
+                               samplesTests->addChild(new MinSampleShadingTest(testCtx, "primitive_line", "", samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_LINE));
+                               samplesTests->addChild(new MinSampleShadingTest(testCtx, "primitive_point", "", samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_POINT));
+
+                               minShadingValueTests->addChild(samplesTests.release());
+                       }
+
+                       minSampleShadingTests->addChild(minShadingValueTests.release());
+               }
+
+               multisampleTests->addChild(minSampleShadingTests.release());
+       }
+
+       // pSampleMask tests
+       {
+               struct TestConfig
+               {
+                       const char*             name;
+                       const char*             description;
+                       VkSampleMask    sampleMask;
+               };
+
+               const TestConfig testConfigs[] =
+               {
+                       { "mask_all_on",        "All mask bits are off",                        0x0 },
+                       { "mask_all_off",       "All mask bits are on",                         0xFFFFFFFF },
+                       { "mask_one",           "All mask elements are 0x1",            0x1},
+                       { "mask_random",        "All mask elements are 0xAAAAAAAA",     0xAAAAAAAA },
+               };
+
+               de::MovePtr<tcu::TestCaseGroup> sampleMaskTests(new tcu::TestCaseGroup(testCtx, "sample_mask", ""));
+
+               for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testConfigs); configNdx++)
+               {
+                       const TestConfig&                               testConfig                              = testConfigs[configNdx];
+                       de::MovePtr<tcu::TestCaseGroup> sampleMaskValueTests    (new tcu::TestCaseGroup(testCtx, testConfig.name, testConfig.description));
+
+                       for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
+                       {
+                               std::ostringstream caseName;
+                               caseName << "samples_" << samples[samplesNdx];
+
+                               const deUint32                                  sampleMaskCount = samples[samplesNdx] / 32;
+                               de::MovePtr<tcu::TestCaseGroup> samplesTests    (new tcu::TestCaseGroup(testCtx, caseName.str().c_str(), ""));
+
+                               std::vector<VkSampleMask> mask;
+                               for (deUint32 maskNdx = 0; maskNdx < sampleMaskCount; maskNdx++)
+                                       mask.push_back(testConfig.sampleMask);
+
+                               samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_triangle", "", samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_TRIANGLE));
+                               samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_line", "", samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_LINE));
+                               samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_point", "", samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_POINT));
+
+                               sampleMaskValueTests->addChild(samplesTests.release());
+                       }
+
+                       sampleMaskTests->addChild(sampleMaskValueTests.release());
+               }
+
+               multisampleTests->addChild(sampleMaskTests.release());
+
+       }
+
+       // AlphaToOne tests
+       {
+               de::MovePtr<tcu::TestCaseGroup> alphaToOneTests(new tcu::TestCaseGroup(testCtx, "alpha_to_one", ""));
+
+               for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
+               {
+                       std::ostringstream caseName;
+                       caseName << "samples_" << samples[samplesNdx];
+
+                       alphaToOneTests->addChild(new AlphaToOneTest(testCtx, caseName.str(), "", samples[samplesNdx]));
+               }
+
+               multisampleTests->addChild(alphaToOneTests.release());
+       }
+
+       // AlphaToCoverageEnable tests
+       {
+               de::MovePtr<tcu::TestCaseGroup> alphaToCoverageTests (new tcu::TestCaseGroup(testCtx, "alpha_to_coverage", ""));
+
+               for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
+               {
+                       std::ostringstream caseName;
+                       caseName << "samples_" << samples[samplesNdx];
+
+                       de::MovePtr<tcu::TestCaseGroup> samplesTests    (new tcu::TestCaseGroup(testCtx, caseName.str().c_str(), ""));
+
+                       samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_opaque", "", samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_QUAD));
+                       samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_translucent", "", samples[samplesNdx], GEOMETRY_TYPE_TRANSLUCENT_QUAD));
+                       samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_invisible", "", samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_QUAD));
+
+                       alphaToCoverageTests->addChild(samplesTests.release());
+               }
+               multisampleTests->addChild(alphaToCoverageTests.release());
+       }
+
+       return multisampleTests.release();
+}
+
+} // pipeline
+} // vkt
diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleTests.hpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleTests.hpp
new file mode 100644 (file)
index 0000000..db5ed3b
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef _VKTPIPELINEMULTISAMPLETESTS_HPP
+#define _VKTPIPELINEMULTISAMPLETESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by Khronos,
+ * at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Multisample Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktTestCase.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+
+tcu::TestCaseGroup* createMultisampleTests (tcu::TestContext& testCtx);
+
+} // pipeline
+} // vkt
+
+#endif // _VKTPIPELINEMULTISAMPLETESTS_HPP
index a32196b..68376f9 100644 (file)
@@ -256,6 +256,12 @@ ReferenceRenderer::~ReferenceRenderer (void)
        delete m_renderTarget;
 }
 
+void ReferenceRenderer::colorClear(const tcu::Vec4& color)
+{
+       tcu::clear(m_colorBuffer.getAccess(), color);
+       tcu::clear(m_resolveColorBuffer.getAccess(), color);
+}
+
 void ReferenceRenderer::draw (const rr::RenderState&                   renderState,
                                                          const rr::PrimitiveType                       primitive,
                                                          const std::vector<Vertex4RGBA>&       vertexBuffer)
index 519b8dc..c3bc1c5 100644 (file)
@@ -306,6 +306,8 @@ public:
 
        virtual                                         ~ReferenceRenderer              (void);
 
+       void                                            colorClear                              (const tcu::Vec4& color);
+
        void                                            draw                                    (const rr::RenderState&                         renderState,
                                                                                                                 const rr::PrimitiveType                        primitive,
                                                                                                                 const std::vector<Vertex4RGBA>&        vertexBuffer);
index 22935ce..66b0863 100644 (file)
@@ -40,6 +40,7 @@
 #include "vktPipelineImageTests.hpp"
 #include "vktPipelineSamplerTests.hpp"
 #include "vktPipelineImageViewTests.hpp"
+#include "vktPipelineMultisampleTests.hpp"
 #include "deUniquePtr.hpp"
 
 namespace vkt
@@ -57,6 +58,7 @@ tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx)
        pipelineTests->addChild(createImageTests(testCtx));
        pipelineTests->addChild(createSamplerTests(testCtx));
        pipelineTests->addChild(createImageViewTests(testCtx));
+       pipelineTests->addChild(createMultisampleTests(testCtx));
 
        return pipelineTests.release();
 }