Fix validation errors in pipeline tests
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / pipeline / vktPipelineMultisampleTests.cpp
index 7a0e980..8c1e9b0 100644 (file)
@@ -4,6 +4,7 @@
  *
  * Copyright (c) 2015 The Khronos Group Inc.
  * Copyright (c) 2015 Imagination Technologies Ltd.
+ * Copyright (c) 2017 Google Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -24,6 +25,7 @@
 
 #include "vktPipelineMultisampleTests.hpp"
 #include "vktPipelineMultisampleImageTests.hpp"
+#include "vktPipelineMultisampleSampleLocationsExtTests.hpp"
 #include "vktPipelineClearUtil.hpp"
 #include "vktPipelineImageUtil.hpp"
 #include "vktPipelineVertexUtil.hpp"
@@ -34,6 +36,7 @@
 #include "vkMemUtil.hpp"
 #include "vkPrograms.hpp"
 #include "vkQueryUtil.hpp"
+#include "vkCmdUtil.hpp"
 #include "vkRef.hpp"
 #include "vkRefUtil.hpp"
 #include "tcuImageCompare.hpp"
@@ -76,7 +79,28 @@ enum TestModeBits
 };
 typedef deUint32 TestModeFlags;
 
-void                                                                   initMultisamplePrograms                         (SourceCollections& sources, GeometryType geometryType);
+enum RenderType
+{
+       // resolve multisample rendering to single sampled image
+       RENDER_TYPE_RESOLVE             = 0u,
+
+       // copy samples to an array of single sampled images
+       RENDER_TYPE_COPY_SAMPLES
+};
+
+enum ImageBackingMode
+{
+       IMAGE_BACKING_MODE_REGULAR      = 0u,
+       IMAGE_BACKING_MODE_SPARSE
+};
+
+struct MultisampleTestParams
+{
+       GeometryType            geometryType;
+       ImageBackingMode        backingMode;
+};
+
+void                                                                   initMultisamplePrograms                         (SourceCollections& sources, MultisampleTestParams params);
 bool                                                                   isSupportedSampleCount                          (const InstanceInterface& instanceInterface, VkPhysicalDevice physicalDevice, VkSampleCountFlagBits rasterizationSamples);
 bool                                                                   isSupportedDepthStencilFormat           (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkFormat format);
 VkPipelineColorBlendAttachmentState            getDefaultColorBlendAttachmentState     (void);
@@ -95,7 +119,8 @@ public:
                                                                                                                                                                         const std::string&                                                             description,
                                                                                                                                                                         const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
                                                                                                                                                                         const VkPipelineColorBlendAttachmentState&             blendState,
-                                                                                                                                                                        GeometryType                                                                   geometryType);
+                                                                                                                                                                        GeometryType                                                                   geometryType,
+                                                                                                                                                                        ImageBackingMode                                                               backingMode);
        virtual                                                                         ~MultisampleTest                                        (void) {}
 
        virtual void                                                            initPrograms                                            (SourceCollections& programCollection) const;
@@ -110,6 +135,7 @@ protected:
        VkPipelineMultisampleStateCreateInfo            m_multisampleStateParams;
        const VkPipelineColorBlendAttachmentState       m_colorBlendState;
        const GeometryType                                                      m_geometryType;
+       const ImageBackingMode                                          m_backingMode;
        std::vector<VkSampleMask>                                       m_sampleMask;
 };
 
@@ -121,6 +147,7 @@ public:
                                                                                                                                                                         const std::string&             description,
                                                                                                                                                                         VkSampleCountFlagBits  rasterizationSamples,
                                                                                                                                                                         GeometryType                   geometryType,
+                                                                                                                                                                        ImageBackingMode               backingMode,
                                                                                                                                                                         TestModeFlags                  modeFlags                               = 0u);
        virtual                                                                         ~RasterizationSamplesTest                       (void) {}
 
@@ -133,6 +160,7 @@ protected:
 
        static VkPipelineMultisampleStateCreateInfo     getRasterizationSamplesStateParams      (VkSampleCountFlagBits rasterizationSamples);
 
+       const ImageBackingMode                                          m_backingMode;
        const TestModeFlags                                                     m_modeFlags;
 };
 
@@ -144,10 +172,12 @@ public:
                                                                                                                                                                         const std::string&             description,
                                                                                                                                                                         VkSampleCountFlagBits  rasterizationSamples,
                                                                                                                                                                         float                                  minSampleShading,
-                                                                                                                                                                        GeometryType                   geometryType);
+                                                                                                                                                                        GeometryType                   geometryType,
+                                                                                                                                                                        ImageBackingMode               backingMode);
        virtual                                                                         ~MinSampleShadingTest                           (void) {}
 
 protected:
+       virtual void                                                            initPrograms                                            (SourceCollections& programCollection) const;
        virtual TestInstance*                                           createMultisampleTestInstance           (Context&                                                                               context,
                                                                                                                                                                         VkPrimitiveTopology                                                    topology,
                                                                                                                                                                         const std::vector<Vertex4RGBA>&                                vertices,
@@ -155,6 +185,8 @@ protected:
                                                                                                                                                                         const VkPipelineColorBlendAttachmentState&             colorBlendState) const;
 
        static VkPipelineMultisampleStateCreateInfo     getMinSampleShadingStateParams          (VkSampleCountFlagBits rasterizationSamples, float minSampleShading);
+
+       const ImageBackingMode                                          m_backingMode;
 };
 
 class SampleMaskTest : public MultisampleTest
@@ -165,7 +197,8 @@ public:
                                                                                                                                                                         const std::string&                                     description,
                                                                                                                                                                         VkSampleCountFlagBits                          rasterizationSamples,
                                                                                                                                                                         const std::vector<VkSampleMask>&       sampleMask,
-                                                                                                                                                                        GeometryType                                           geometryType);
+                                                                                                                                                                        GeometryType                                           geometryType,
+                                                                                                                                                                        ImageBackingMode                                       backingMode);
 
        virtual                                                                         ~SampleMaskTest                                         (void) {}
 
@@ -177,6 +210,8 @@ protected:
                                                                                                                                                                         const VkPipelineColorBlendAttachmentState&             colorBlendState) const;
 
        static VkPipelineMultisampleStateCreateInfo     getSampleMaskStateParams                        (VkSampleCountFlagBits rasterizationSamples, const std::vector<VkSampleMask>& sampleMask);
+
+       const ImageBackingMode                                          m_backingMode;
 };
 
 class AlphaToOneTest : public MultisampleTest
@@ -185,7 +220,8 @@ public:
                                                                                                AlphaToOneTest                                  (tcu::TestContext&                                      testContext,
                                                                                                                                                                 const std::string&                                     name,
                                                                                                                                                                 const std::string&                                     description,
-                                                                                                                                                                VkSampleCountFlagBits                          rasterizationSamples);
+                                                                                                                                                                VkSampleCountFlagBits                          rasterizationSamples,
+                                                                                                                                                                ImageBackingMode                                       backingMode);
 
        virtual                                                                         ~AlphaToOneTest                                 (void) {}
 
@@ -198,6 +234,8 @@ protected:
 
        static VkPipelineMultisampleStateCreateInfo     getAlphaToOneStateParams                (VkSampleCountFlagBits rasterizationSamples);
        static VkPipelineColorBlendAttachmentState      getAlphaToOneBlendState                 (void);
+
+       const ImageBackingMode                                          m_backingMode;
 };
 
 class AlphaToCoverageTest : public MultisampleTest
@@ -207,7 +245,8 @@ public:
                                                                                                                                                                 const std::string&             name,
                                                                                                                                                                 const std::string&             description,
                                                                                                                                                                 VkSampleCountFlagBits  rasterizationSamples,
-                                                                                                                                                                GeometryType                   geometryType);
+                                                                                                                                                                GeometryType                   geometryType,
+                                                                                                                                                                ImageBackingMode               backingMode);
 
        virtual                                                                         ~AlphaToCoverageTest                    (void) {}
 
@@ -221,6 +260,7 @@ protected:
        static VkPipelineMultisampleStateCreateInfo     getAlphaToCoverageStateParams   (VkSampleCountFlagBits rasterizationSamples);
 
        GeometryType                                                            m_geometryType;
+       const ImageBackingMode                                          m_backingMode;
 };
 
 typedef de::SharedPtr<Unique<VkPipeline> > VkPipelineSp;
@@ -234,7 +274,9 @@ public:
                                                                                                                                                         const VkPrimitiveTopology                                              topology,
                                                                                                                                                         const std::vector<Vertex4RGBA>&                                vertices,
                                                                                                                                                         const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
-                                                                                                                                                        const VkPipelineColorBlendAttachmentState&             blendState);
+                                                                                                                                                        const VkPipelineColorBlendAttachmentState&             blendState,
+                                                                                                                                                        const RenderType                                                               renderType,
+                                                                                                                                                        const ImageBackingMode                                                 backingMode);
 
                                                                                                MultisampleRenderer                     (Context&                                                                               context,
                                                                                                                                                         const VkFormat                                                                 colorFormat,
@@ -246,11 +288,14 @@ public:
                                                                                                                                                         const VkPrimitiveTopology*                                             pTopology,
                                                                                                                                                         const std::vector<Vertex4RGBA>*                                pVertices,
                                                                                                                                                         const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
-                                                                                                                                                        const VkPipelineColorBlendAttachmentState&             blendState);
+                                                                                                                                                        const VkPipelineColorBlendAttachmentState&             blendState,
+                                                                                                                                                    const RenderType                                                           renderType,
+                                                                                                                                                        const ImageBackingMode                                                 backingMode);
 
        virtual                                                                         ~MultisampleRenderer            (void);
 
        de::MovePtr<tcu::TextureLevel>                          render                                          (void);
+       de::MovePtr<tcu::TextureLevel>                          getSingleSampledImage           (deUint32 sampleId);
 
 protected:
        void                                                                            initialize                                      (Context&                                                                               context,
@@ -260,6 +305,8 @@ protected:
 
        Context&                                                                        m_context;
 
+       const Unique<VkSemaphore>                                       m_bindSemaphore;
+
        const VkFormat                                                          m_colorFormat;
        const VkFormat                                                          m_depthStencilFormat;
        tcu::IVec2                                                                      m_renderSize;
@@ -269,6 +316,8 @@ protected:
        const VkPipelineMultisampleStateCreateInfo      m_multisampleStateParams;
        const VkPipelineColorBlendAttachmentState       m_colorBlendState;
 
+       const RenderType                                                        m_renderType;
+
        Move<VkImage>                                                           m_colorImage;
        de::MovePtr<Allocation>                                         m_colorImageAlloc;
        Move<VkImageView>                                                       m_colorAttachmentView;
@@ -277,6 +326,14 @@ protected:
        de::MovePtr<Allocation>                                         m_resolveImageAlloc;
        Move<VkImageView>                                                       m_resolveAttachmentView;
 
+       struct PerSampleImage
+       {
+               Move<VkImage>                                                           m_image;
+               de::MovePtr<Allocation>                                         m_imageAlloc;
+               Move<VkImageView>                                                       m_attachmentView;
+       };
+       std::vector<de::SharedPtr<PerSampleImage> >     m_perSampleImages;
+
        Move<VkImage>                                                           m_depthStencilImage;
        de::MovePtr<Allocation>                                         m_depthStencilImageAlloc;
        Move<VkImageView>                                                       m_depthStencilAttachmentView;
@@ -287,16 +344,28 @@ protected:
        Move<VkShaderModule>                                            m_vertexShaderModule;
        Move<VkShaderModule>                                            m_fragmentShaderModule;
 
+       Move<VkShaderModule>                                            m_copySampleVertexShaderModule;
+       Move<VkShaderModule>                                            m_copySampleFragmentShaderModule;
+
        Move<VkBuffer>                                                          m_vertexBuffer;
        de::MovePtr<Allocation>                                         m_vertexBufferAlloc;
 
        Move<VkPipelineLayout>                                          m_pipelineLayout;
        std::vector<VkPipelineSp>                                       m_graphicsPipelines;
 
+       Move<VkDescriptorSetLayout>                                     m_copySampleDesciptorLayout;
+       Move<VkDescriptorPool>                                          m_copySampleDesciptorPool;
+       Move<VkDescriptorSet>                                           m_copySampleDesciptorSet;
+
+       Move<VkPipelineLayout>                                          m_copySamplePipelineLayout;
+       std::vector<VkPipelineSp>                                       m_copySamplePipelines;
+
        Move<VkCommandPool>                                                     m_cmdPool;
        Move<VkCommandBuffer>                                           m_cmdBuffer;
 
-       Move<VkFence>                                                           m_fence;
+       std::vector<de::SharedPtr<Allocation> >         m_allocations;
+
+       ImageBackingMode                                                        m_backingMode;
 };
 
 class RasterizationSamplesInstance : public vkt::TestInstance
@@ -307,7 +376,8 @@ public:
                                                                                                                                                 const std::vector<Vertex4RGBA>&                                vertices,
                                                                                                                                                 const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
                                                                                                                                                 const VkPipelineColorBlendAttachmentState&             blendState,
-                                                                                                                                                const TestModeFlags                                                    modeFlags);
+                                                                                                                                                const TestModeFlags                                                    modeFlags,
+                                                                                                                                                ImageBackingMode                                                               backingMode);
        virtual                                                         ~RasterizationSamplesInstance   (void) {}
 
        virtual tcu::TestStatus                         iterate                                                 (void);
@@ -331,21 +401,23 @@ public:
                                                                                                                                                         VkPrimitiveTopology                                                    topology,
                                                                                                                                                         const std::vector<Vertex4RGBA>&                                vertices,
                                                                                                                                                         const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
-                                                                                                                                                        const VkPipelineColorBlendAttachmentState&             blendState);
+                                                                                                                                                        const VkPipelineColorBlendAttachmentState&             blendState,
+                                                                                                                                                        ImageBackingMode                                                               backingMode);
        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);
+       virtual tcu::TestStatus                                         verifySampleShadedImage         (const std::vector<tcu::TextureLevel>& testShadingImages,
+                                                                                                                                                        const tcu::ConstPixelBufferAccess& noSampleshadingImage);
+
        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 ImageBackingMode                                          m_backingMode;
 };
 
 class SampleMaskInstance : public vkt::TestInstance
@@ -355,7 +427,8 @@ public:
                                                                                                                                                         VkPrimitiveTopology                                                    topology,
                                                                                                                                                         const std::vector<Vertex4RGBA>&                                vertices,
                                                                                                                                                         const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
-                                                                                                                                                        const VkPipelineColorBlendAttachmentState&             blendState);
+                                                                                                                                                        const VkPipelineColorBlendAttachmentState&             blendState,
+                                                                                                                                                        ImageBackingMode                                                               backingMode);
        virtual                                                                         ~SampleMaskInstance                     (void) {}
 
        virtual tcu::TestStatus                                         iterate                                         (void);
@@ -370,6 +443,7 @@ protected:
        const std::vector<Vertex4RGBA>                          m_vertices;
        const VkPipelineMultisampleStateCreateInfo      m_multisampleStateParams;
        const VkPipelineColorBlendAttachmentState       m_colorBlendState;
+       const ImageBackingMode                                          m_backingMode;
 };
 
 class AlphaToOneInstance : public vkt::TestInstance
@@ -379,7 +453,8 @@ public:
                                                                                                                                                         VkPrimitiveTopology                                                    topology,
                                                                                                                                                         const std::vector<Vertex4RGBA>&                                vertices,
                                                                                                                                                         const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
-                                                                                                                                                        const VkPipelineColorBlendAttachmentState&             blendState);
+                                                                                                                                                        const VkPipelineColorBlendAttachmentState&             blendState,
+                                                                                                                                                        ImageBackingMode                                                               backingMode);
        virtual                                                                         ~AlphaToOneInstance                     (void) {}
 
        virtual tcu::TestStatus                                         iterate                                         (void);
@@ -393,6 +468,7 @@ protected:
        const std::vector<Vertex4RGBA>                          m_vertices;
        const VkPipelineMultisampleStateCreateInfo      m_multisampleStateParams;
        const VkPipelineColorBlendAttachmentState       m_colorBlendState;
+       const ImageBackingMode                                          m_backingMode;
 };
 
 class AlphaToCoverageInstance : public vkt::TestInstance
@@ -403,7 +479,8 @@ public:
                                                                                                                                                         const std::vector<Vertex4RGBA>&                                vertices,
                                                                                                                                                         const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
                                                                                                                                                         const VkPipelineColorBlendAttachmentState&             blendState,
-                                                                                                                                                        GeometryType                                                                   geometryType);
+                                                                                                                                                        GeometryType                                                                   geometryType,
+                                                                                                                                                        ImageBackingMode                                                               backingMode);
        virtual                                                                         ~AlphaToCoverageInstance        (void) {}
 
        virtual tcu::TestStatus                                         iterate                                         (void);
@@ -417,12 +494,13 @@ protected:
        const VkPipelineMultisampleStateCreateInfo      m_multisampleStateParams;
        const VkPipelineColorBlendAttachmentState       m_colorBlendState;
        const GeometryType                                                      m_geometryType;
+       const ImageBackingMode                                          m_backingMode;
 };
 
 
 // Helper functions
 
-void initMultisamplePrograms (SourceCollections& sources, GeometryType geometryType)
+void initMultisamplePrograms (SourceCollections& sources, MultisampleTestParams params)
 {
        std::ostringstream vertexSource;
 
@@ -435,8 +513,8 @@ void initMultisamplePrograms (SourceCollections& sources, GeometryType geometryT
                "{\n"
                "       gl_Position = position;\n"
                "       vtxColor = color;\n"
-               << (geometryType == GEOMETRY_TYPE_OPAQUE_POINT ? "      gl_PointSize = 3.0f;\n"
-                                                                                                                : "" )
+                       << (params.geometryType == GEOMETRY_TYPE_OPAQUE_POINT ? "       gl_PointSize = 3.0f;\n"
+                       : "")
                << "}\n";
 
        static const char* fragmentSource =
@@ -452,6 +530,67 @@ void initMultisamplePrograms (SourceCollections& sources, GeometryType geometryT
        sources.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource);
 }
 
+void initSampleShadingPrograms (SourceCollections& sources, GeometryType geometryType)
+{
+       {
+               std::ostringstream vertexSource;
+
+               vertexSource <<
+                       "#version 440\n"
+                       "layout(location = 0) in vec4 position;\n"
+                       "layout(location = 1) in vec4 color;\n"
+                       "void main (void)\n"
+                       "{\n"
+                       "       gl_Position = position;\n"
+                       << (geometryType == GEOMETRY_TYPE_OPAQUE_POINT ? "      gl_PointSize = 3.0f;\n"
+                               : "")
+                       << "}\n";
+
+               static const char* fragmentSource =
+                       "#version 440\n"
+                       "layout(location = 0) out highp vec4 fragColor;\n"
+                       "void main (void)\n"
+                       "{\n"
+                       "       fragColor = vec4(fract(gl_FragCoord.xy), 0.0, 1.0);\n"
+                       "}\n";
+
+               sources.glslSources.add("color_vert") << glu::VertexSource(vertexSource.str());
+               sources.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource);
+       }
+
+       {
+               static const char*  vertexSource =
+                       "#version 440\n"
+                       "void main (void)\n"
+                       "{\n"
+                       "       const vec4 positions[4] = vec4[4](\n"
+                       "               vec4(-1.0, -1.0, 0.0, 1.0),\n"
+                       "               vec4(-1.0,  1.0, 0.0, 1.0),\n"
+                       "               vec4( 1.0, -1.0, 0.0, 1.0),\n"
+                       "               vec4( 1.0,  1.0, 0.0, 1.0)\n"
+                       "       );\n"
+                       "       gl_Position = positions[gl_VertexIndex];\n"
+                       "}\n";
+
+               static const char* fragmentSource =
+                       "#version 440\n"
+                       "precision highp float;\n"
+                       "layout(location = 0) out highp vec4 fragColor;\n"
+                       "layout(set = 0, binding = 0, input_attachment_index = 0) uniform subpassInputMS imageMS;\n"
+                       "layout(push_constant) uniform PushConstantsBlock\n"
+                       "{\n"
+                       "       int sampleId;\n"
+                       "} pushConstants;\n"
+                       "void main (void)\n"
+                       "{\n"
+                       "       fragColor = subpassLoad(imageMS, pushConstants.sampleId);\n"
+                       "}\n";
+
+               sources.glslSources.add("quad_vert") << glu::VertexSource(vertexSource);
+               sources.glslSources.add("copy_sample_frag") << glu::FragmentSource(fragmentSource);
+       }
+}
+
 bool isSupportedSampleCount (const InstanceInterface& instanceInterface, VkPhysicalDevice physicalDevice, VkSampleCountFlagBits rasterizationSamples)
 {
        VkPhysicalDeviceProperties deviceProperties;
@@ -689,11 +828,13 @@ MultisampleTest::MultisampleTest (tcu::TestContext&                                                               testContext,
                                                                  const std::string&                                                    description,
                                                                  const VkPipelineMultisampleStateCreateInfo&   multisampleStateParams,
                                                                  const VkPipelineColorBlendAttachmentState&    blendState,
-                                                                 GeometryType                                                                  geometryType)
+                                                                 GeometryType                                                                  geometryType,
+                                                                 ImageBackingMode                                                              backingMode)
        : vkt::TestCase                         (testContext, name, description)
        , m_multisampleStateParams      (multisampleStateParams)
        , m_colorBlendState                     (blendState)
        , m_geometryType                        (geometryType)
+       , m_backingMode                         (backingMode)
 {
        if (m_multisampleStateParams.pSampleMask)
        {
@@ -710,7 +851,8 @@ MultisampleTest::MultisampleTest (tcu::TestContext&                                                         testContext,
 
 void MultisampleTest::initPrograms (SourceCollections& programCollection) const
 {
-       initMultisamplePrograms(programCollection, m_geometryType);
+       MultisampleTestParams params = {m_geometryType, m_backingMode};
+       initMultisamplePrograms(programCollection, params);
 }
 
 TestInstance* MultisampleTest::createInstance (Context& context) const
@@ -726,8 +868,10 @@ RasterizationSamplesTest::RasterizationSamplesTest (tcu::TestContext&              testConte
                                                                                                        const std::string&              description,
                                                                                                        VkSampleCountFlagBits   rasterizationSamples,
                                                                                                        GeometryType                    geometryType,
+                                                                                                       ImageBackingMode                backingMode,
                                                                                                        TestModeFlags                   modeFlags)
-       : MultisampleTest       (testContext, name, description, getRasterizationSamplesStateParams(rasterizationSamples), getDefaultColorBlendAttachmentState(), geometryType)
+       : MultisampleTest       (testContext, name, description, getRasterizationSamplesStateParams(rasterizationSamples), getDefaultColorBlendAttachmentState(), geometryType, backingMode)
+       , m_backingMode         (backingMode)
        , m_modeFlags           (modeFlags)
 {
 }
@@ -756,7 +900,7 @@ TestInstance* RasterizationSamplesTest::createMultisampleTestInstance (Context&
                                                                                                                                           const VkPipelineMultisampleStateCreateInfo&  multisampleStateParams,
                                                                                                                                           const VkPipelineColorBlendAttachmentState&   colorBlendState) const
 {
-       return new RasterizationSamplesInstance(context, topology, vertices, multisampleStateParams, colorBlendState, m_modeFlags);
+       return new RasterizationSamplesInstance(context, topology, vertices, multisampleStateParams, colorBlendState, m_modeFlags, m_backingMode);
 }
 
 
@@ -767,18 +911,25 @@ MinSampleShadingTest::MinSampleShadingTest (tcu::TestContext&             testContext,
                                                                                        const std::string&              description,
                                                                                        VkSampleCountFlagBits   rasterizationSamples,
                                                                                        float                                   minSampleShading,
-                                                                                       GeometryType                    geometryType)
-       : MultisampleTest       (testContext, name, description, getMinSampleShadingStateParams(rasterizationSamples, minSampleShading), getDefaultColorBlendAttachmentState(), geometryType)
+                                                                                       GeometryType                    geometryType,
+                                                                                       ImageBackingMode                backingMode)
+       : MultisampleTest       (testContext, name, description, getMinSampleShadingStateParams(rasterizationSamples, minSampleShading), getDefaultColorBlendAttachmentState(), geometryType, backingMode)
+       , m_backingMode         (backingMode)
 {
 }
 
+void MinSampleShadingTest::initPrograms (SourceCollections& programCollection) const
+{
+       initSampleShadingPrograms(programCollection, m_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);
+       return new MinSampleShadingInstance(context, topology, vertices, multisampleStateParams, colorBlendState, m_backingMode);
 }
 
 VkPipelineMultisampleStateCreateInfo MinSampleShadingTest::getMinSampleShadingStateParams (VkSampleCountFlagBits rasterizationSamples, float minSampleShading)
@@ -807,8 +958,10 @@ SampleMaskTest::SampleMaskTest (tcu::TestContext&                                  testContext,
                                                                const std::string&                                      description,
                                                                VkSampleCountFlagBits                           rasterizationSamples,
                                                                const std::vector<VkSampleMask>&        sampleMask,
-                                                               GeometryType                                            geometryType)
-       : MultisampleTest       (testContext, name, description, getSampleMaskStateParams(rasterizationSamples, sampleMask), getDefaultColorBlendAttachmentState(), geometryType)
+                                                               GeometryType                                            geometryType,
+                                                               ImageBackingMode                                        backingMode)
+       : MultisampleTest       (testContext, name, description, getSampleMaskStateParams(rasterizationSamples, sampleMask), getDefaultColorBlendAttachmentState(), geometryType, backingMode)
+       , m_backingMode         (backingMode)
 {
 }
 
@@ -818,7 +971,7 @@ TestInstance* SampleMaskTest::createMultisampleTestInstance (Context&                                                                               c
                                                                                                                         const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
                                                                                                                         const VkPipelineColorBlendAttachmentState&             colorBlendState) const
 {
-       return new SampleMaskInstance(context, topology,vertices, multisampleStateParams, colorBlendState);
+       return new SampleMaskInstance(context, topology,vertices, multisampleStateParams, colorBlendState, m_backingMode);
 }
 
 VkPipelineMultisampleStateCreateInfo SampleMaskTest::getSampleMaskStateParams (VkSampleCountFlagBits rasterizationSamples, const std::vector<VkSampleMask>& sampleMask)
@@ -845,8 +998,10 @@ VkPipelineMultisampleStateCreateInfo SampleMaskTest::getSampleMaskStateParams (V
 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)
+                                                               VkSampleCountFlagBits   rasterizationSamples,
+                                                               ImageBackingMode                backingMode)
+       : MultisampleTest       (testContext, name, description, getAlphaToOneStateParams(rasterizationSamples), getAlphaToOneBlendState(), GEOMETRY_TYPE_GRADIENT_QUAD, backingMode)
+       , m_backingMode(backingMode)
 {
 }
 
@@ -856,7 +1011,7 @@ TestInstance* AlphaToOneTest::createMultisampleTestInstance (Context&                                                                              c
                                                                                                                         const VkPipelineMultisampleStateCreateInfo&    multisampleStateParams,
                                                                                                                         const VkPipelineColorBlendAttachmentState&             colorBlendState) const
 {
-       return new AlphaToOneInstance(context, topology, vertices, multisampleStateParams, colorBlendState);
+       return new AlphaToOneInstance(context, topology, vertices, multisampleStateParams, colorBlendState, m_backingMode);
 }
 
 VkPipelineMultisampleStateCreateInfo AlphaToOneTest::getAlphaToOneStateParams (VkSampleCountFlagBits rasterizationSamples)
@@ -902,9 +1057,11 @@ 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)
+                                                                                 GeometryType                          geometryType,
+                                                                                 ImageBackingMode                      backingMode)
+       : MultisampleTest       (testContext, name, description, getAlphaToCoverageStateParams(rasterizationSamples), getDefaultColorBlendAttachmentState(), geometryType, backingMode)
        , m_geometryType        (geometryType)
+       , m_backingMode         (backingMode)
 {
 }
 
@@ -914,7 +1071,7 @@ TestInstance* AlphaToCoverageTest::createMultisampleTestInstance (Context&
                                                                                                                                  const VkPipelineMultisampleStateCreateInfo&   multisampleStateParams,
                                                                                                                                  const VkPipelineColorBlendAttachmentState&    colorBlendState) const
 {
-       return new AlphaToCoverageInstance(context, topology, vertices, multisampleStateParams, colorBlendState, m_geometryType);
+       return new AlphaToCoverageInstance(context, topology, vertices, multisampleStateParams, colorBlendState, m_geometryType, m_backingMode);
 }
 
 VkPipelineMultisampleStateCreateInfo AlphaToCoverageTest::getAlphaToCoverageStateParams (VkSampleCountFlagBits rasterizationSamples)
@@ -942,7 +1099,8 @@ RasterizationSamplesInstance::RasterizationSamplesInstance (Context&                                                                               co
                                                                                                                        const std::vector<Vertex4RGBA>&                                 vertices,
                                                                                                                        const VkPipelineMultisampleStateCreateInfo&             multisampleStateParams,
                                                                                                                        const VkPipelineColorBlendAttachmentState&              blendState,
-                                                                                                                       const TestModeFlags                                                             modeFlags)
+                                                                                                                       const TestModeFlags                                                             modeFlags,
+                                                                                                                       ImageBackingMode                                                                backingMode)
        : vkt::TestInstance             (context)
        , m_colorFormat                 (VK_FORMAT_R8G8B8A8_UNORM)
        , m_renderSize                  (32, 32)
@@ -965,12 +1123,12 @@ RasterizationSamplesInstance::RasterizationSamplesInstance (Context&                                                                             co
 
                m_multisampleRenderer = de::MovePtr<MultisampleRenderer>(
                        new MultisampleRenderer(
-                               context, m_colorFormat, depthStencilFormat, m_renderSize, useDepth, useStencil, 2u, pTopology, pVertices, multisampleStateParams, blendState));
+                               context, m_colorFormat, depthStencilFormat, m_renderSize, useDepth, useStencil, 2u, pTopology, pVertices, multisampleStateParams, blendState, RENDER_TYPE_RESOLVE, backingMode));
        }
        else
        {
                m_multisampleRenderer = de::MovePtr<MultisampleRenderer>(
-                       new MultisampleRenderer(context, m_colorFormat, m_renderSize, topology, vertices, multisampleStateParams, blendState));
+                       new MultisampleRenderer(context, m_colorFormat, m_renderSize, topology, vertices, multisampleStateParams, blendState, RENDER_TYPE_RESOLVE, backingMode));
        }
 }
 
@@ -1044,7 +1202,8 @@ MinSampleShadingInstance::MinSampleShadingInstance (Context&                                                                      context,
                                                                                                        VkPrimitiveTopology                                                     topology,
                                                                                                        const std::vector<Vertex4RGBA>&                         vertices,
                                                                                                        const VkPipelineMultisampleStateCreateInfo&     multisampleStateParams,
-                                                                                                       const VkPipelineColorBlendAttachmentState&      colorBlendState)
+                                                                                                       const VkPipelineColorBlendAttachmentState&      colorBlendState,
+                                                                                                       ImageBackingMode                                                        backingMode)
        : vkt::TestInstance                     (context)
        , m_colorFormat                         (VK_FORMAT_R8G8B8A8_UNORM)
        , m_renderSize                          (32, 32)
@@ -1052,6 +1211,7 @@ MinSampleShadingInstance::MinSampleShadingInstance (Context&                                                                      context,
        , m_vertices                            (vertices)
        , m_multisampleStateParams      (multisampleStateParams)
        , m_colorBlendState                     (colorBlendState)
+       , m_backingMode                         (backingMode)
 {
        VkPhysicalDeviceFeatures deviceFeatures;
 
@@ -1063,62 +1223,117 @@ MinSampleShadingInstance::MinSampleShadingInstance (Context&                                                                   context,
 
 tcu::TestStatus MinSampleShadingInstance::iterate (void)
 {
-       de::MovePtr<tcu::TextureLevel>                          testShadingImage;
-       de::MovePtr<tcu::TextureLevel>                          minShadingImage;
-       de::MovePtr<tcu::TextureLevel>                          maxShadingImage;
+       de::MovePtr<tcu::TextureLevel>  noSampleshadingImage;
+       std::vector<tcu::TextureLevel>  sampleShadedImages;
 
-       // Render with test minSampleShading
+       // Render and resolve without sample shading
        {
-               MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState);
-               testShadingImage = renderer.render();
+               VkPipelineMultisampleStateCreateInfo multisampleStateParms = m_multisampleStateParams;
+               multisampleStateParms.sampleShadingEnable       = VK_FALSE;
+               multisampleStateParms.minSampleShading          = 0.0;
+
+               MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleStateParms, m_colorBlendState, RENDER_TYPE_RESOLVE, m_backingMode);
+               noSampleshadingImage  = renderer.render();
        }
 
-       // Render with minSampleShading = 0.0f
+       // Render with test minSampleShading and collect per-sample images
        {
-               VkPipelineMultisampleStateCreateInfo    multisampleParams       = m_multisampleStateParams;
-               multisampleParams.minSampleShading = 0.0f;
+               MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState, RENDER_TYPE_COPY_SAMPLES, m_backingMode);
+               renderer.render();
 
-               MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState);
-               minShadingImage = renderer.render();
+               sampleShadedImages.resize(m_multisampleStateParams.rasterizationSamples);
+               for (deUint32 sampleId = 0; sampleId < sampleShadedImages.size(); sampleId++)
+               {
+                       sampleShadedImages[sampleId] = *renderer.getSingleSampledImage(sampleId);
+               }
        }
 
-       // Render with minSampleShading = 1.0f
+       // Log images
        {
-               VkPipelineMultisampleStateCreateInfo    multisampleParams       = m_multisampleStateParams;
-               multisampleParams.minSampleShading = 1.0f;
+               tcu::TestLog& testLog   = m_context.getTestContext().getLog();
+
+               testLog << tcu::TestLog::ImageSet("Images", "Images")
+                               << tcu::TestLog::Image("noSampleshadingImage", "Image rendered without sample shading", noSampleshadingImage->getAccess());
 
-               MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState);
-               maxShadingImage = renderer.render();
+               for (deUint32 sampleId = 0; sampleId < sampleShadedImages.size(); sampleId++)
+               {
+                       testLog << tcu::TestLog::Image("sampleShadedImage", "One sample of sample shaded image", sampleShadedImages[sampleId].getAccess());
+               }
+               testLog << tcu::TestLog::EndImageSet;
        }
 
-       return verifyImage(testShadingImage->getAccess(), minShadingImage->getAccess(), maxShadingImage->getAccess());
+       return verifySampleShadedImage(sampleShadedImages, noSampleshadingImage->getAccess());
 }
 
-tcu::TestStatus MinSampleShadingInstance::verifyImage (const tcu::ConstPixelBufferAccess& testShadingImage, const tcu::ConstPixelBufferAccess& minShadingImage, const tcu::ConstPixelBufferAccess& maxShadingImage)
+tcu::TestStatus MinSampleShadingInstance::verifySampleShadedImage (const std::vector<tcu::TextureLevel>& sampleShadedImages, const tcu::ConstPixelBufferAccess& noSampleshadingImage)
 {
-       const deUint32  testColorCount  = getUniqueColorsCount(testShadingImage);
-       const deUint32  minColorCount   = getUniqueColorsCount(minShadingImage);
-       const deUint32  maxColorCount   = getUniqueColorsCount(maxShadingImage);
+       const deUint32  pixelCount      = noSampleshadingImage.getWidth() * noSampleshadingImage.getHeight() * noSampleshadingImage.getDepth();
 
-       tcu::TestLog& log = m_context.getTestContext().getLog();
+       bool anyPixelCovered            = false;
 
-       log << tcu::TestLog::Message
-               << "\nColors found: " << testColorCount << "\n"
-               << "Min. colors expected: " << minColorCount << "\n"
-               << "Max. colors expected: " << maxColorCount << "\n"
-               << tcu::TestLog::EndMessage;
+       for (deUint32 pixelNdx = 0; pixelNdx < pixelCount; pixelNdx++)
+       {
+               const deUint32 noSampleShadingValue = *((const deUint32*)noSampleshadingImage.getDataPtr() + pixelNdx);
 
-       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");
+               if (noSampleShadingValue == 0)
+               {
+                       // non-covered pixel, continue
+                       continue;
+               }
+               else
+               {
+                       anyPixelCovered = true;
+               }
+
+               int numNotCoveredSamples = 0;
+
+               std::map<deUint32, deUint32>    histogram; // map<pixel value, number of occurrences>
+
+               // Collect histogram of occurrences or each pixel across all samples
+               for (size_t i = 0; i < sampleShadedImages.size(); ++i)
+               {
+                       const deUint32 sampleShadedValue = *((const deUint32*)sampleShadedImages[i].getAccess().getDataPtr() + pixelNdx);
+
+                       if (sampleShadedValue == 0)
+                       {
+                               numNotCoveredSamples++;
+                               continue;
+                       }
+
+                       if (histogram.find(sampleShadedValue) != histogram.end())
+                               histogram[sampleShadedValue]++;
+                       else
+                               histogram[sampleShadedValue] = 1;
+               }
+
+               if (numNotCoveredSamples == static_cast<int>(sampleShadedImages.size()))
+               {
+                       return tcu::TestStatus::fail("Got uncovered pixel, where covered samples were expected");
+               }
+
+               const int uniqueColorsCount                             = (int)histogram.size();
+               const int expectedUniqueSamplesCount    = static_cast<int>(m_multisampleStateParams.minSampleShading * static_cast<float>(sampleShadedImages.size()) + 0.5f);
+
+               if (uniqueColorsCount + numNotCoveredSamples < expectedUniqueSamplesCount)
+               {
+                       return tcu::TestStatus::fail("Got less unique colors than requested through minSampleShading");
+               }
+       }
+
+       if (!anyPixelCovered)
+       {
+               return tcu::TestStatus::fail("Did not get any covered pixel, cannot test minSampleShading");
+       }
+
+       return tcu::TestStatus::pass("Got proper count of unique colors");
 }
 
 SampleMaskInstance::SampleMaskInstance (Context&                                                                               context,
                                                                                VkPrimitiveTopology                                                             topology,
                                                                                const std::vector<Vertex4RGBA>&                                 vertices,
                                                                                const VkPipelineMultisampleStateCreateInfo&             multisampleStateParams,
-                                                                               const VkPipelineColorBlendAttachmentState&              blendState)
+                                                                               const VkPipelineColorBlendAttachmentState&              blendState,
+                                                                               ImageBackingMode                                                                backingMode)
        : vkt::TestInstance                     (context)
        , m_colorFormat                         (VK_FORMAT_R8G8B8A8_UNORM)
        , m_renderSize                          (32, 32)
@@ -1126,6 +1341,7 @@ SampleMaskInstance::SampleMaskInstance (Context&                                                                          context,
        , m_vertices                            (vertices)
        , m_multisampleStateParams      (multisampleStateParams)
        , m_colorBlendState                     (blendState)
+       , m_backingMode                         (backingMode)
 {
 }
 
@@ -1137,7 +1353,7 @@ tcu::TestStatus SampleMaskInstance::iterate (void)
 
        // Render with test flags
        {
-               MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState);
+               MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState, RENDER_TYPE_RESOLVE, m_backingMode);
                testSampleMaskImage = renderer.render();
        }
 
@@ -1148,7 +1364,7 @@ tcu::TestStatus SampleMaskInstance::iterate (void)
 
                multisampleParams.pSampleMask = sampleMask.data();
 
-               MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState);
+               MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState, RENDER_TYPE_RESOLVE, m_backingMode);
                minSampleMaskImage = renderer.render();
        }
 
@@ -1159,7 +1375,7 @@ tcu::TestStatus SampleMaskInstance::iterate (void)
 
                multisampleParams.pSampleMask = sampleMask.data();
 
-               MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState);
+               MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState, RENDER_TYPE_RESOLVE, m_backingMode);
                maxSampleMaskImage = renderer.render();
        }
 
@@ -1188,11 +1404,8 @@ tcu::TestStatus SampleMaskInstance::verifyImage (const tcu::ConstPixelBufferAcce
                return tcu::TestStatus::pass("Unique colors within expected bounds");
 }
 
-tcu::TestStatus testRasterSamplesConsistency (Context& context, GeometryType geometryType)
+tcu::TestStatus testRasterSamplesConsistency (Context& context, MultisampleTestParams params)
 {
-       // Use triangle only.
-       DE_UNREF(geometryType);
-
        const VkSampleCountFlagBits samples[] =
        {
                VK_SAMPLE_COUNT_1_BIT,
@@ -1243,7 +1456,7 @@ tcu::TestStatus testRasterSamplesConsistency (Context& context, GeometryType geo
                        false                                                                                                           // VkBool32                                                                     alphaToOneEnable;
                };
 
-               MultisampleRenderer                             renderer                (context, VK_FORMAT_R8G8B8A8_UNORM, tcu::IVec2(32, 32), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, vertices, multisampleStateParams, getDefaultColorBlendAttachmentState());
+               MultisampleRenderer                             renderer                (context, VK_FORMAT_R8G8B8A8_UNORM, tcu::IVec2(32, 32), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, vertices, multisampleStateParams, getDefaultColorBlendAttachmentState(), RENDER_TYPE_RESOLVE, params.backingMode);
                de::MovePtr<tcu::TextureLevel>  result                  = renderer.render();
                const deUint32                                  uniqueColors    = getUniqueColorsCount(result->getAccess());
 
@@ -1273,7 +1486,8 @@ AlphaToOneInstance::AlphaToOneInstance (Context&                                                                  context,
                                                                                VkPrimitiveTopology                                                     topology,
                                                                                const std::vector<Vertex4RGBA>&                         vertices,
                                                                                const VkPipelineMultisampleStateCreateInfo&     multisampleStateParams,
-                                                                               const VkPipelineColorBlendAttachmentState&      blendState)
+                                                                               const VkPipelineColorBlendAttachmentState&      blendState,
+                                                                               ImageBackingMode                                                        backingMode)
        : vkt::TestInstance                     (context)
        , m_colorFormat                         (VK_FORMAT_R8G8B8A8_UNORM)
        , m_renderSize                          (32, 32)
@@ -1281,6 +1495,7 @@ AlphaToOneInstance::AlphaToOneInstance (Context&                                                                  context,
        , m_vertices                            (vertices)
        , m_multisampleStateParams      (multisampleStateParams)
        , m_colorBlendState                     (blendState)
+       , m_backingMode                         (backingMode)
 {
        VkPhysicalDeviceFeatures deviceFeatures;
 
@@ -1300,7 +1515,7 @@ tcu::TestStatus AlphaToOneInstance::iterate       (void)
 
        // 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);
+               MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState, RENDER_TYPE_RESOLVE, m_backingMode);
                alphaOneImage = renderer.render();
        }
 
@@ -1309,7 +1524,7 @@ tcu::TestStatus AlphaToOneInstance::iterate       (void)
                VkPipelineMultisampleStateCreateInfo    multisampleParams       = m_multisampleStateParams;
                multisampleParams.alphaToOneEnable = false;
 
-               MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState);
+               MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState, RENDER_TYPE_RESOLVE, m_backingMode);
                noAlphaOneImage = renderer.render();
        }
 
@@ -1343,7 +1558,8 @@ AlphaToCoverageInstance::AlphaToCoverageInstance (Context&                                                                                context,
                                                                                                  const std::vector<Vertex4RGBA>&                               vertices,
                                                                                                  const VkPipelineMultisampleStateCreateInfo&   multisampleStateParams,
                                                                                                  const VkPipelineColorBlendAttachmentState&    blendState,
-                                                                                                 GeometryType                                                                  geometryType)
+                                                                                                 GeometryType                                                                  geometryType,
+                                                                                                 ImageBackingMode                                                              backingMode)
        : vkt::TestInstance                     (context)
        , m_colorFormat                         (VK_FORMAT_R8G8B8A8_UNORM)
        , m_renderSize                          (32, 32)
@@ -1352,6 +1568,7 @@ AlphaToCoverageInstance::AlphaToCoverageInstance (Context&                                                                                context,
        , m_multisampleStateParams      (multisampleStateParams)
        , m_colorBlendState                     (blendState)
        , m_geometryType                        (geometryType)
+       , m_backingMode                         (backingMode)
 {
 }
 
@@ -1360,7 +1577,7 @@ 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);
+       MultisampleRenderer                             renderer        (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState, RENDER_TYPE_RESOLVE, m_backingMode);
 
        result = renderer.render();
 
@@ -1415,8 +1632,11 @@ MultisampleRenderer::MultisampleRenderer (Context&                                                                               context,
                                                                                  const VkPrimitiveTopology                                             topology,
                                                                                  const std::vector<Vertex4RGBA>&                               vertices,
                                                                                  const VkPipelineMultisampleStateCreateInfo&   multisampleStateParams,
-                                                                                 const VkPipelineColorBlendAttachmentState&    blendState)
+                                                                                 const VkPipelineColorBlendAttachmentState&    blendState,
+                                                                                 const RenderType                                                              renderType,
+                                                                                 const ImageBackingMode                                                backingMode)
        : m_context                                     (context)
+       , m_bindSemaphore                       (createSemaphore(context.getDeviceInterface(), context.getDevice()))
        , m_colorFormat                         (colorFormat)
        , m_depthStencilFormat          (VK_FORMAT_UNDEFINED)
        , m_renderSize                          (renderSize)
@@ -1424,6 +1644,8 @@ MultisampleRenderer::MultisampleRenderer (Context&                                                                                context,
        , m_useStencil                          (false)
        , m_multisampleStateParams      (multisampleStateParams)
        , m_colorBlendState                     (blendState)
+       , m_renderType                          (renderType)
+       , m_backingMode                         (backingMode)
 {
        initialize(context, 1u, &topology, &vertices);
 }
@@ -1438,8 +1660,11 @@ MultisampleRenderer::MultisampleRenderer (Context&                                                                               context,
                                                                                  const VkPrimitiveTopology*                                    pTopology,
                                                                                  const std::vector<Vertex4RGBA>*                               pVertices,
                                                                                  const VkPipelineMultisampleStateCreateInfo&   multisampleStateParams,
-                                                                                 const VkPipelineColorBlendAttachmentState&    blendState)
+                                                                                 const VkPipelineColorBlendAttachmentState&    blendState,
+                                                                                 const RenderType                                                              renderType,
+                                                                                 const ImageBackingMode                                                backingMode)
        : m_context                                     (context)
+       , m_bindSemaphore                       (createSemaphore(context.getDeviceInterface(), context.getDevice()))
        , m_colorFormat                         (colorFormat)
        , m_depthStencilFormat          (depthStencilFormat)
        , m_renderSize                          (renderSize)
@@ -1447,6 +1672,8 @@ MultisampleRenderer::MultisampleRenderer (Context&                                                                                context,
        , m_useStencil                          (useStencil)
        , m_multisampleStateParams      (multisampleStateParams)
        , m_colorBlendState                     (blendState)
+       , m_renderType                          (renderType)
+       , m_backingMode                         (backingMode)
 {
        initialize(context, numTopologies, pTopology, pVertices);
 }
@@ -1461,17 +1688,23 @@ void MultisampleRenderer::initialize (Context&                                                                  context,
 
        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 deUint32                          queueFamilyIndices[]    = { context.getUniversalQueueFamilyIndex(), context.getSparseQueueFamilyIndex() };
+       const bool                                      sparse                                  = m_backingMode == IMAGE_BACKING_MODE_SPARSE;
        const VkComponentMapping        componentMappingRGBA    = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
+       const VkImageCreateFlags        imageCreateFlags                = sparse ? (VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) : 0u;
+       const VkSharingMode                     sharingMode                             = (sparse && context.getUniversalQueueFamilyIndex() != context.getSparseQueueFamilyIndex()) ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE;
+       Allocator&                                      memAlloc                                = m_context.getDefaultAllocator();
 
        // Create color image
        {
-               const VkImageCreateInfo colorImageParams =
+               const VkImageUsageFlags imageUsageFlags         = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+                       (m_renderType == RENDER_TYPE_COPY_SAMPLES ? VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT : (VkImageUsageFlagBits)0u);
+
+               const VkImageCreateInfo colorImageParams        =
                {
                        VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                                            // VkStructureType                      sType;
                        DE_NULL,                                                                                                                                        // const void*                          pNext;
-                       0u,                                                                                                                                                     // VkImageCreateFlags           flags;
+                       imageCreateFlags,                                                                                                                       // VkImageCreateFlags           flags;
                        VK_IMAGE_TYPE_2D,                                                                                                                       // VkImageType                          imageType;
                        m_colorFormat,                                                                                                                          // VkFormat                                     format;
                        { (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y(), 1u },                         // VkExtent3D                           extent;
@@ -1479,21 +1712,32 @@ void MultisampleRenderer::initialize (Context&                                                                  context,
                        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;
+                       imageUsageFlags,                                                                                                                        // VkImageUsageFlags            usage;
+                       sharingMode,                                                                                                                            // VkSharingMode                        sharingMode;
+                       sharingMode == VK_SHARING_MODE_CONCURRENT ? 2u : 1u,                                            // deUint32                                     queueFamilyIndexCount;
+                       queueFamilyIndices,                                                                                                                     // const deUint32*                      pQueueFamilyIndices;
                        VK_IMAGE_LAYOUT_UNDEFINED,                                                                                                      // VkImageLayout                        initialLayout;
                };
 
-               m_colorImage                    = createImage(vk, vkDevice, &colorImageParams);
+               if (sparse && !checkSparseImageFormatSupport(context.getPhysicalDevice(), context.getInstanceInterface(), colorImageParams))
+                       TCU_THROW(NotSupportedError, "The image format does not support sparse operations.");
+
+               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()));
+               if (sparse)
+               {
+                       allocateAndBindSparseImage(vk, vkDevice, context.getPhysicalDevice(), context.getInstanceInterface(), colorImageParams, *m_bindSemaphore, context.getSparseQueue(), memAlloc, m_allocations, mapVkFormat(m_colorFormat), *m_colorImage);
+               }
+               else
+               {
+                       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
+       if (m_renderType == RENDER_TYPE_RESOLVE)
        {
                const VkImageCreateInfo resolveImageParams =
                {
@@ -1511,7 +1755,7 @@ void MultisampleRenderer::initialize (Context&                                                                    context,
                                VK_IMAGE_USAGE_TRANSFER_DST_BIT,
                        VK_SHARING_MODE_EXCLUSIVE,                                                                                                              // VkSharingMode                        sharingMode;
                        1u,                                                                                                                                                             // deUint32                                     queueFamilyIndexCount;
-                       &queueFamilyIndex,                                                                                                                              // const deUint32*                      pQueueFamilyIndices;
+                       queueFamilyIndices,                                                                                                                             // const deUint32*                      pQueueFamilyIndices;
                        VK_IMAGE_LAYOUT_UNDEFINED                                                                                                               // VkImageLayout                        initialLayout;
                };
 
@@ -1520,6 +1764,78 @@ void MultisampleRenderer::initialize (Context&                                                                   context,
                // 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 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 per-sample output images
+       if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
+       {
+               const VkImageCreateInfo perSampleImageParams =
+               {
+                       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;
+                       { (deUint32)m_renderSize.x(), (deUint32)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;
+                       queueFamilyIndices,                                                                                                                             // const deUint32*                      pQueueFamilyIndices;
+                       VK_IMAGE_LAYOUT_UNDEFINED                                                                                                               // VkImageLayout                        initialLayout;
+               };
+
+               m_perSampleImages.resize(static_cast<size_t>(m_multisampleStateParams.rasterizationSamples));
+
+               for (size_t i = 0; i < m_perSampleImages.size(); ++i)
+               {
+                       m_perSampleImages[i]    = de::SharedPtr<PerSampleImage>(new PerSampleImage);
+                       PerSampleImage& image   = *m_perSampleImages[i];
+
+                       image.m_image                   = createImage(vk, vkDevice, &perSampleImageParams);
+
+                       // Allocate and bind image memory
+                       image.m_imageAlloc              = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *image.m_image), MemoryRequirement::Any);
+                       VK_CHECK(vk.bindImageMemory(vkDevice, *image.m_image, image.m_imageAlloc->getMemory(), image.m_imageAlloc->getOffset()));
+
+                       // Create per-sample attachment view
+                       {
+                               const VkImageViewCreateInfo perSampleAttachmentViewParams =
+                               {
+                                       VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,               // VkStructureType                      sType;
+                                       DE_NULL,                                                                                // const void*                          pNext;
+                                       0u,                                                                                             // VkImageViewCreateFlags       flags;
+                                       *image.m_image,                                                                 // 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;
+                               };
+
+                               image.m_attachmentView = createImageView(vk, vkDevice, &perSampleAttachmentViewParams);
+                       }
+               }
        }
 
        // Create a depth/stencil image
@@ -1540,7 +1856,7 @@ void MultisampleRenderer::initialize (Context&                                                                    context,
                        VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,                                                                    // VkImageUsageFlags            usage;
                        VK_SHARING_MODE_EXCLUSIVE,                                                                                                              // VkSharingMode                        sharingMode;
                        1u,                                                                                                                                                             // deUint32                                     queueFamilyIndexCount;
-                       &queueFamilyIndex,                                                                                                                              // const deUint32*                      pQueueFamilyIndices;
+                       queueFamilyIndices,                                                                                                                             // const deUint32*                      pQueueFamilyIndices;
                        VK_IMAGE_LAYOUT_UNDEFINED                                                                                                               // VkImageLayout                        initialLayout;
                };
 
@@ -1568,25 +1884,7 @@ void MultisampleRenderer::initialize (Context&                                                                   context,
                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);
-       }
-
        VkImageAspectFlags      depthStencilAttachmentAspect    = (VkImageAspectFlagBits)0;
-       const deUint32          numUsedAttachments                              = (m_useDepth || m_useStencil ? 3u : 2u);
 
        // Create depth/stencil attachment view
        if (m_useDepth || m_useStencil)
@@ -1610,8 +1908,9 @@ void MultisampleRenderer::initialize (Context&                                                                    context,
 
        // Create render pass
        {
-               const VkAttachmentDescription attachmentDescriptions[3] =
+               std::vector<VkAttachmentDescription> attachmentDescriptions;
                {
+                       const VkAttachmentDescription colorAttachmentDescription =
                        {
                                0u,                                                                                                     // VkAttachmentDescriptionFlags         flags;
                                m_colorFormat,                                                                          // VkFormat                                                     format;
@@ -1622,7 +1921,17 @@ void MultisampleRenderer::initialize (Context&                                                                   context,
                                VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
                                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                        initialLayout;
                                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout                                        finalLayout;
-                       },
+                       };
+                       attachmentDescriptions.push_back(colorAttachmentDescription);
+               }
+
+               deUint32 resolveAttachmentIndex = VK_ATTACHMENT_UNUSED;
+
+               if (m_renderType == RENDER_TYPE_RESOLVE)
+               {
+                       resolveAttachmentIndex = static_cast<deUint32>(attachmentDescriptions.size());
+
+                       const VkAttachmentDescription resolveAttachmentDescription =
                        {
                                0u,                                                                                                     // VkAttachmentDescriptionFlags         flags;
                                m_colorFormat,                                                                          // VkFormat                                                     format;
@@ -1633,7 +1942,42 @@ void MultisampleRenderer::initialize (Context&                                                                   context,
                                VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
                                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                        initialLayout;
                                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout                                        finalLayout;
-                       },
+                       };
+                       attachmentDescriptions.push_back(resolveAttachmentDescription);
+               }
+
+               deUint32 perSampleAttachmentIndex = VK_ATTACHMENT_UNUSED;
+
+               if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
+               {
+                       perSampleAttachmentIndex = static_cast<deUint32>(attachmentDescriptions.size());
+
+                       const VkAttachmentDescription perSampleAttachmentDescription =
+                       {
+                               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;
+                       };
+
+                       for (size_t i = 0; i < m_perSampleImages.size(); ++i)
+                       {
+                               attachmentDescriptions.push_back(perSampleAttachmentDescription);
+                       }
+               }
+
+               deUint32 depthStencilAttachmentIndex = VK_ATTACHMENT_UNUSED;
+
+               if (m_useDepth || m_useStencil)
+               {
+                       depthStencilAttachmentIndex = static_cast<deUint32>(attachmentDescriptions.size());
+
+                       const VkAttachmentDescription depthStencilAttachmentDescription =
                        {
                                0u,                                                                                                                                                                     // VkAttachmentDescriptionFlags         flags;
                                m_depthStencilFormat,                                                                                                                           // VkFormat                                                     format;
@@ -1644,7 +1988,8 @@ void MultisampleRenderer::initialize (Context&                                                                    context,
                                (m_useStencil ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE),       // VkAttachmentStoreOp                          stencilStoreOp;
                                VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,                                                                       // VkImageLayout                                        initialLayout;
                                VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL                                                                        // VkImageLayout                                        finalLayout;
-                       },
+                       };
+                       attachmentDescriptions.push_back(depthStencilAttachmentDescription);
                };
 
                const VkAttachmentReference colorAttachmentReference =
@@ -1653,43 +1998,103 @@ void MultisampleRenderer::initialize (Context&                                                                 context,
                        VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout        layout;
                };
 
+               const VkAttachmentReference inputAttachmentReference =
+               {
+                       0u,                                                                                                     // deUint32                     attachment;
+                       VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL                        // VkImageLayout        layout;
+               };
+
                const VkAttachmentReference resolveAttachmentReference =
                {
-                       1u,                                                                                                     // deUint32                     attachment;
+                       resolveAttachmentIndex,                                                         // deUint32                     attachment;
                        VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout        layout;
                };
 
+               std::vector<VkAttachmentReference> perSampleAttachmentReferences(m_perSampleImages.size());
+               if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
+               {
+                       for (size_t i = 0; i < m_perSampleImages.size(); ++i)
+                       {
+                               const VkAttachmentReference perSampleAttachmentReference =
+                               {
+                                       perSampleAttachmentIndex + static_cast<deUint32>(i),    // deUint32                     attachment;
+                                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                                // VkImageLayout        layout;
+                               };
+                               perSampleAttachmentReferences[i] = perSampleAttachmentReference;
+                       }
+               }
+
                const VkAttachmentReference depthStencilAttachmentReference =
                {
-                       2u,                                                                                                     // deUint32                     attachment;
+                       depthStencilAttachmentIndex,                                            // deUint32                     attachment;
                        VK_IMAGE_LAYOUT_DEPTH_STENCIL_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;
-                       (m_useDepth || m_useStencil ? &depthStencilAttachmentReference : DE_NULL),      // const VkAttachmentReference* pDepthStencilAttachment;
-                       0u,                                                                                                                                                     // deUint32                                             preserveAttachmentCount;
-                       DE_NULL                                                                                                                                         // const VkAttachmentReference* pPreserveAttachments;
-               };
+               std::vector<VkSubpassDescription>       subpassDescriptions;
+               std::vector<VkSubpassDependency>        subpassDependencies;
+
+               {
+                       const VkSubpassDescription renderSubpassDescription =
+                       {
+                               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;
+                               (m_renderType == RENDER_TYPE_RESOLVE) ? &resolveAttachmentReference : DE_NULL,  // const VkAttachmentReference* pResolveAttachments;
+                               (m_useDepth || m_useStencil ? &depthStencilAttachmentReference : DE_NULL),              // const VkAttachmentReference* pDepthStencilAttachment;
+                               0u,                                                                                                                                                             // deUint32                                             preserveAttachmentCount;
+                               DE_NULL                                                                                                                                                 // const VkAttachmentReference* pPreserveAttachments;
+                       };
+                       subpassDescriptions.push_back(renderSubpassDescription);
+               }
+
+               if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
+               {
+
+                       for (size_t i = 0; i < m_perSampleImages.size(); ++i)
+                       {
+                               const VkSubpassDescription copySampleSubpassDescription =
+                               {
+                                       0u,                                                                                                     // VkSubpassDescriptionFlags            flags;
+                                       VK_PIPELINE_BIND_POINT_GRAPHICS,                                        // VkPipelineBindPoint                          pipelineBindPoint;
+                                       1u,                                                                                                     // deUint32                                                     inputAttachmentCount;
+                                       &inputAttachmentReference,                                                      // const VkAttachmentReference*         pInputAttachments;
+                                       1u,                                                                                                     // deUint32                                                     colorAttachmentCount;
+                                       &perSampleAttachmentReferences[i],                                      // const VkAttachmentReference*         pColorAttachments;
+                                       DE_NULL,                                                                                        // const VkAttachmentReference*         pResolveAttachments;
+                                       DE_NULL,                                                                                        // const VkAttachmentReference*         pDepthStencilAttachment;
+                                       0u,                                                                                                     // deUint32                                                     preserveAttachmentCount;
+                                       DE_NULL                                                                                         // const VkAttachmentReference*         pPreserveAttachments;
+                               };
+                               subpassDescriptions.push_back(copySampleSubpassDescription);
+
+                               const VkSubpassDependency copySampleSubpassDependency =
+                               {
+                                       0u,                                                                                                     // deUint32                                                     srcSubpass
+                                       1u + static_cast<deUint32>(i),                                          // deUint32                                                     dstSubpass
+                                       VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                                      // VkPipelineStageFlags                         srcStageMask
+                                       VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,                          // VkPipelineStageFlags                         dstStageMask
+                                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                           // VkAccessFlags                                        srcAccessMask
+                                       VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,                            // VkAccessFlags                                        dstAccessMask
+                                       0u,                                                                                                     // VkDependencyFlags                            dependencyFlags
+                               };
+                               subpassDependencies.push_back(copySampleSubpassDependency);
+                       }
+               }
 
                const VkRenderPassCreateInfo renderPassParams =
                {
-                       VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                      // VkStructureType                                      sType;
-                       DE_NULL,                                                                                        // const void*                                          pNext;
-                       0u,                                                                                                     // VkRenderPassCreateFlags                      flags;
-                       numUsedAttachments,                                                                     // deUint32                                                     attachmentCount;
-                       attachmentDescriptions,                                                         // const VkAttachmentDescription*       pAttachments;
-                       1u,                                                                                                     // deUint32                                                     subpassCount;
-                       &subpassDescription,                                                            // const VkSubpassDescription*          pSubpasses;
-                       0u,                                                                                                     // deUint32                                                     dependencyCount;
-                       DE_NULL                                                                                         // const VkSubpassDependency*           pDependencies;
+                       VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                                      // VkStructureType                                      sType;
+                       DE_NULL,                                                                                                        // const void*                                          pNext;
+                       0u,                                                                                                                     // VkRenderPassCreateFlags                      flags;
+                       (deUint32)attachmentDescriptions.size(),                                        // deUint32                                                     attachmentCount;
+                       &attachmentDescriptions[0],                                                                     // const VkAttachmentDescription*       pAttachments;
+                       (deUint32)subpassDescriptions.size(),                                           // deUint32                                                     subpassCount;
+                       &subpassDescriptions[0],                                                                        // const VkSubpassDescription*          pSubpasses;
+                       (deUint32)subpassDependencies.size(),                                           // deUint32                                                     dependencyCount;
+                       subpassDependencies.size() != 0 ? &subpassDependencies[0] : DE_NULL
                };
 
                m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
@@ -1697,24 +2102,36 @@ void MultisampleRenderer::initialize (Context&                                                                  context,
 
        // Create framebuffer
        {
-               const VkImageView attachments[3] =
+               std::vector<VkImageView> attachments;
+               attachments.push_back(*m_colorAttachmentView);
+               if (m_renderType == RENDER_TYPE_RESOLVE)
                {
-                       *m_colorAttachmentView,
-                       *m_resolveAttachmentView,
-                       *m_depthStencilAttachmentView
-               };
+                       attachments.push_back(*m_resolveAttachmentView);
+               }
+               if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
+               {
+                       for (size_t i = 0; i < m_perSampleImages.size(); ++i)
+                       {
+                               attachments.push_back(*m_perSampleImages[i]->m_attachmentView);
+                       }
+               }
+
+               if (m_useDepth || m_useStencil)
+               {
+                       attachments.push_back(*m_depthStencilAttachmentView);
+               }
 
                const VkFramebufferCreateInfo framebufferParams =
                {
-                       VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,                      // VkStructureType                              sType;
-                       DE_NULL,                                                                                        // const void*                                  pNext;
-                       0u,                                                                                                     // VkFramebufferCreateFlags             flags;
-                       *m_renderPass,                                                                          // VkRenderPass                                 renderPass;
-                       numUsedAttachments,                                                                     // deUint32                                             attachmentCount;
-                       attachments,                                                                            // const VkImageView*                   pAttachments;
-                       (deUint32)m_renderSize.x(),                                                     // deUint32                                             width;
-                       (deUint32)m_renderSize.y(),                                                     // deUint32                                             height;
-                       1u                                                                                                      // deUint32                                             layers;
+                       VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,                      // VkStructureType                                      sType;
+                       DE_NULL,                                                                                        // const void*                                          pNext;
+                       0u,                                                                                                     // VkFramebufferCreateFlags                     flags;
+                       *m_renderPass,                                                                          // VkRenderPass                                         renderPass;
+                       (deUint32)attachments.size(),                                           // deUint32                                                     attachmentCount;
+                       &attachments[0],                                                                        // const VkImageView*                           pAttachments;
+                       (deUint32)m_renderSize.x(),                                                     // deUint32                                                     width;
+                       (deUint32)m_renderSize.y(),                                                     // deUint32                                                     height;
+                       1u                                                                                                      // deUint32                                                     layers;
                };
 
                m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
@@ -1734,14 +2151,64 @@ void MultisampleRenderer::initialize (Context&                                                                  context,
                };
 
                m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
+
+               if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
+               {
+
+                       // Create descriptor set layout
+                       const VkDescriptorSetLayoutBinding              layoutBinding                                   =
+                       {
+                               0u,                                                                                                                     // deUint32                                                             binding;
+                               VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,                                            // VkDescriptorType                                             descriptorType;
+                               1u,                                                                                                                     // deUint32                                                             descriptorCount;
+                               VK_SHADER_STAGE_FRAGMENT_BIT,                                                           // VkShaderStageFlags                                   stageFlags;
+                               DE_NULL,                                                                                                        // const VkSampler*                                             pImmutableSamplers;
+                       };
+
+                       const VkDescriptorSetLayoutCreateInfo   descriptorSetLayoutParams               =
+                       {
+                               VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,            // VkStructureType                                              sType
+                               DE_NULL,                                                                                                        // const void*                                                  pNext
+                               0u,                                                                                                                     // VkDescriptorSetLayoutCreateFlags             flags
+                               1u,                                                                                                                     // deUint32                                                             bindingCount
+                               &layoutBinding                                                                                          // const VkDescriptorSetLayoutBinding*  pBindings
+                       };
+                       m_copySampleDesciptorLayout     = createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams);
+
+                       // Create pipeline layout
+
+                       const VkPushConstantRange                               pushConstantRange                               =
+                       {
+                               VK_SHADER_STAGE_FRAGMENT_BIT,                                                           // VkShaderStageFlags                                   stageFlags;
+                               0u,                                                                                                                     // deUint32                                                             offset;
+                               sizeof(deInt32)                                                                                         // deUint32                                                             size;
+                       };
+                       const VkPipelineLayoutCreateInfo                copySamplePipelineLayoutParams  =
+                       {
+                               VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,                          // VkStructureType                                              sType;
+                               DE_NULL,                                                                                                        // const void*                                                  pNext;
+                               0u,                                                                                                                     // VkPipelineLayoutCreateFlags                  flags;
+                               1u,                                                                                                                     // deUint32                                                             setLayoutCount;
+                               &m_copySampleDesciptorLayout.get(),                                                     // const VkDescriptorSetLayout*                 pSetLayouts;
+                               1u,                                                                                                                     // deUint32                                                             pushConstantRangeCount;
+                               &pushConstantRange                                                                                      // const VkPushConstantRange*                   pPushConstantRanges;
+                       };
+                       m_copySamplePipelineLayout              = createPipelineLayout(vk, vkDevice, &copySamplePipelineLayoutParams);
+               }
        }
 
        m_vertexShaderModule    = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
        m_fragmentShaderModule  = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
 
+       if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
+       {
+               m_copySampleVertexShaderModule          = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("quad_vert"), 0);
+               m_copySampleFragmentShaderModule        = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("copy_sample_frag"), 0);
+       }
+
        // Create pipeline
        {
-               const VkPipelineShaderStageCreateInfo shaderStageParams[2] =
+               const VkPipelineShaderStageCreateInfo   shaderStageParams[2] =
                {
                        {
                                VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,            // VkStructureType                                              sType;
@@ -1763,7 +2230,7 @@ void MultisampleRenderer::initialize (Context&                                                                    context,
                        }
                };
 
-               const VkVertexInputBindingDescription vertexInputBindingDescription =
+               const VkVertexInputBindingDescription   vertexInputBindingDescription =
                {
                        0u,                                                                     // deUint32                             binding;
                        sizeof(Vertex4RGBA),                            // deUint32                             stride;
@@ -1920,6 +2387,208 @@ void MultisampleRenderer::initialize (Context&                                                                  context,
                }
        }
 
+       if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
+       {
+               // Create pipelines for copying samples to single sampled images
+               {
+                       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_copySampleVertexShaderModule,                                                        // 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_copySampleFragmentShaderModule,                                                      // VkShaderModule                                                       module;
+                                       "main",                                                                                                         // const char*                                                          pName;
+                                       DE_NULL                                                                                                         // const VkSpecializationInfo*                          pSpecializationInfo;
+                               }
+                       };
+
+                       const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
+                       {
+                               VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,              // VkStructureType                                                      sType;
+                               DE_NULL,                                                                                                                // const void*                                                          pNext;
+                               0u,                                                                                                                             // VkPipelineVertexInputStateCreateFlags        flags;
+                               0u,                                                                                                                             // deUint32                                                                     vertexBindingDescriptionCount;
+                               DE_NULL,                                                                                                                // const VkVertexInputBindingDescription*       pVertexBindingDescriptions;
+                               0u,                                                                                                                             // deUint32                                                                     vertexAttributeDescriptionCount;
+                               DE_NULL                                                                                                                 // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions;
+                       };
+
+                       // Topology is set before the pipeline creation.
+                       VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
+                       {
+                               VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                                                      sType;
+                               DE_NULL,                                                                                                                // const void*                                                          pNext;
+                               0u,                                                                                                                             // VkPipelineInputAssemblyStateCreateFlags      flags;
+                               VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,                                                   // 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;
+                               { (deUint32)m_renderSize.x(), (deUint32)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  VkPipelineMultisampleStateCreateInfo multisampleStateParams =
+                       {
+                               VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                      sType
+                               DE_NULL,                                                                                                        // const void*                                                          pNext
+                               0u,                                                                                                                     // VkPipelineMultisampleStateCreateFlags        flags
+                               VK_SAMPLE_COUNT_1_BIT,                                                                          // VkSampleCountFlagBits                                        rasterizationSamples
+                               VK_FALSE,                                                                                                       // VkBool32                                                                     sampleShadingEnable
+                               0.0f,                                                                                                           // float                                                                        minSampleShading
+                               DE_NULL,                                                                                                        // const VkSampleMask*                                          pSampleMask
+                               VK_FALSE,                                                                                                       // VkBool32                                                                     alphaToCoverageEnable
+                               VK_FALSE,                                                                                                       // VkBool32                                                                     alphaToOneEnable
+                       };
+
+                       const VkGraphicsPipelineCreateInfo graphicsPipelineTemplate =
+                       {
+                               VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,        // VkStructureType                                                                      sType;
+                               DE_NULL,                                                                                        // const void*                                                                          pNext;
+                               0u,                                                                                                     // VkPipelineCreateFlags                                                        flags;
+                               2u,                                                                                                     // deUint32                                                                                     stageCount;
+                               shaderStageParams,                                                                      // const VkPipelineShaderStageCreateInfo*                       pStages;
+                               &vertexInputStateParams,                                                        // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
+                               &inputAssemblyStateParams,                                                      // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
+                               DE_NULL,                                                                                        // const VkPipelineTessellationStateCreateInfo*         pTessellationState;
+                               &viewportStateParams,                                                           // const VkPipelineViewportStateCreateInfo*                     pViewportState;
+                               &rasterStateParams,                                                                     // const VkPipelineRasterizationStateCreateInfo*        pRasterizationState;
+                               &multisampleStateParams,                                                        // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
+                               DE_NULL,                                                                                        // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
+                               &colorBlendStateParams,                                                         // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
+                               (const VkPipelineDynamicStateCreateInfo*)DE_NULL,       // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
+                               *m_copySamplePipelineLayout,                                            // VkPipelineLayout                                                                     layout;
+                               *m_renderPass,                                                                          // VkRenderPass                                                                         renderPass;
+                               0u,                                                                                                     // deUint32                                                                                     subpass;
+                               0u,                                                                                                     // VkPipeline                                                                           basePipelineHandle;
+                               0u                                                                                                      // deInt32                                                                                      basePipelineIndex;
+                       };
+
+                       for (size_t i = 0; i < m_perSampleImages.size(); ++i)
+                       {
+                               VkGraphicsPipelineCreateInfo graphicsPipelineParams = graphicsPipelineTemplate;
+
+                               // Pipeline is to be used in subpasses subsequent to sample-shading subpass
+                               graphicsPipelineParams.subpass = 1u + (deUint32)i;
+
+                               m_copySamplePipelines.push_back(VkPipelineSp(new Unique<VkPipeline>(createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams))));
+                       }
+               }
+
+
+               const VkDescriptorPoolSize                      descriptorPoolSize                      =
+               {
+                       VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,                                    // VkDescriptorType                                     type;
+                       1u                                                                                                              // deUint32                                                     descriptorCount;
+               };
+
+               const VkDescriptorPoolCreateInfo        descriptorPoolCreateInfo        =
+               {
+                       VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,                  // VkStructureType                                      sType
+                       DE_NULL,                                                                                                // const void*                                          pNext
+                       VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,              // VkDescriptorPoolCreateFlags          flags
+                       1u,                                                                                                     // deUint32                                                     maxSets
+                       1u,                                                                                                             // deUint32                                                     poolSizeCount
+                       &descriptorPoolSize                                                                             // const VkDescriptorPoolSize*          pPoolSizes
+               };
+
+               m_copySampleDesciptorPool = createDescriptorPool(vk, vkDevice, &descriptorPoolCreateInfo);
+
+               const VkDescriptorSetAllocateInfo       descriptorSetAllocateInfo       =
+               {
+                       VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,                 // VkStructureType                                      sType
+                       DE_NULL,                                                                                                // const void*                                          pNext
+                       *m_copySampleDesciptorPool,                                                             // VkDescriptorPool                                     descriptorPool
+                       1u,                                                                                                             // deUint32                                                     descriptorSetCount
+                       &m_copySampleDesciptorLayout.get(),                                             // const VkDescriptorSetLayout*         pSetLayouts
+               };
+
+               m_copySampleDesciptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
+
+               const VkDescriptorImageInfo                     imageInfo                                       =
+               {
+                       DE_NULL,
+                       *m_colorAttachmentView,
+                       VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
+               };
+               const VkWriteDescriptorSet                      descriptorWrite                         =
+               {
+                       VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,                 // VkStructureType                                      sType;
+                       DE_NULL,                                                                                // const void*                                          pNext;
+                       *m_copySampleDesciptorSet,                                              // VkDescriptorSet                                      dstSet;
+                       0u,                                                                                             // deUint32                                                     dstBinding;
+                       0u,                                                                                             // deUint32                                                     dstArrayElement;
+                       1u,                                                                                             // deUint32                                                     descriptorCount;
+                       VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,                    // VkDescriptorType                                     descriptorType;
+                       &imageInfo,                                                                             // const VkDescriptorImageInfo*         pImageInfo;
+                       DE_NULL,                                                                                // const VkDescriptorBufferInfo*        pBufferInfo;
+                       DE_NULL,                                                                                // const VkBufferView*                          pTexelBufferView;
+               };
+               vk.updateDescriptorSets(vkDevice, 1u, &descriptorWrite, 0u, DE_NULL);
+       }
+
        // Create vertex buffer
        {
                const VkBufferCreateInfo vertexBufferParams =
@@ -1931,7 +2600,7 @@ void MultisampleRenderer::initialize (Context&                                                                    context,
                        VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,                      // VkBufferUsageFlags   usage;
                        VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
                        1u,                                                                                     // deUint32                             queueFamilyIndexCount;
-                       &queueFamilyIndex                                                       // const deUint32*              pQueueFamilyIndices;
+                       &queueFamilyIndices[0]                                          // const deUint32*              pQueueFamilyIndices;
                };
 
                m_vertexBuffer          = createBuffer(vk, vkDevice, &vertexBufferParams);
@@ -1952,7 +2621,7 @@ void MultisampleRenderer::initialize (Context&                                                                    context,
        }
 
        // Create command pool
-       m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
+       m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndices[0]);
 
        // Create command buffer
        {
@@ -1974,12 +2643,23 @@ void MultisampleRenderer::initialize (Context&                                                                  context,
                depthStencilClearValue.depthStencil.depth = 1.0f;
                depthStencilClearValue.depthStencil.stencil = 0u;
 
-               const VkClearValue clearValues[3] =
+               std::vector<VkClearValue> clearValues;
+               clearValues.push_back(colorClearValue);
+               if (m_renderType == RENDER_TYPE_RESOLVE)
                {
-                       colorClearValue,
-                       colorClearValue,
-                       depthStencilClearValue
-               };
+                       clearValues.push_back(colorClearValue);
+               }
+               if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
+               {
+                       for (size_t i = 0; i < m_perSampleImages.size(); ++i)
+                       {
+                               clearValues.push_back(colorClearValue);
+                       }
+               }
+               if (m_useDepth || m_useStencil)
+               {
+                       clearValues.push_back(depthStencilClearValue);
+               }
 
                const VkRenderPassBeginInfo renderPassBeginInfo =
                {
@@ -1991,13 +2671,16 @@ void MultisampleRenderer::initialize (Context&                                                                  context,
                                { 0, 0 },
                                { (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y() }
                        },                                                                                                              // VkRect2D                             renderArea;
-                       numUsedAttachments,                                                                             // deUint32                             clearValueCount;
-                       clearValues                                                                                             // const VkClearValue*  pClearValues;
+                       (deUint32)clearValues.size(),                                                   // deUint32                             clearValueCount;
+                       &clearValues[0]                                                                                 // const VkClearValue*  pClearValues;
                };
 
-               const VkImageMemoryBarrier imageLayoutBarriers[] =
+               vk::VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+               std::vector<VkImageMemoryBarrier> imageLayoutBarriers;
+
                {
-                       // color attachment image
+                       const VkImageMemoryBarrier colorImageBarrier =
+                               // color attachment image
                        {
                                VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                 // VkStructureType                      sType;
                                DE_NULL,                                                                                // const void*                          pNext;
@@ -2009,7 +2692,12 @@ void MultisampleRenderer::initialize (Context&                                                                   context,
                                VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     dstQueueFamilyIndex;
                                *m_colorImage,                                                                  // VkImage                                      image;
                                { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },  // VkImageSubresourceRange      subresourceRange;
-                       },
+                       };
+                       imageLayoutBarriers.push_back(colorImageBarrier);
+               }
+               if (m_renderType == RENDER_TYPE_RESOLVE)
+               {
+                       const VkImageMemoryBarrier resolveImageBarrier =
                        // resolve attachment image
                        {
                                VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                 // VkStructureType                      sType;
@@ -2022,7 +2710,33 @@ void MultisampleRenderer::initialize (Context&                                                                   context,
                                VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     dstQueueFamilyIndex;
                                *m_resolveImage,                                                                // VkImage                                      image;
                                { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },  // VkImageSubresourceRange      subresourceRange;
-                       },
+                       };
+                       imageLayoutBarriers.push_back(resolveImageBarrier);
+               }
+               if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
+               {
+                       for (size_t i = 0; i < m_perSampleImages.size(); ++i)
+                       {
+                               const VkImageMemoryBarrier perSampleImageBarrier =
+                               // resolve attachment image
+                               {
+                                       VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                 // VkStructureType                      sType;
+                                       DE_NULL,                                                                                // const void*                          pNext;
+                                       0u,                                                                                             // VkAccessFlags                        srcAccessMask;
+                                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                   // VkAccessFlags                        dstAccessMask;
+                                       VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout                        oldLayout;
+                                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,               // VkImageLayout                        newLayout;
+                                       VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     srcQueueFamilyIndex;
+                                       VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     dstQueueFamilyIndex;
+                                       *m_perSampleImages[i]->m_image,                                 // VkImage                                      image;
+                                       { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },  // VkImageSubresourceRange      subresourceRange;
+                               };
+                               imageLayoutBarriers.push_back(perSampleImageBarrier);
+                       }
+               }
+               if (m_useDepth || m_useStencil)
+               {
+                       const VkImageMemoryBarrier depthStencilImageBarrier =
                        // depth/stencil attachment image
                        {
                                VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // VkStructureType                      sType;
@@ -2035,15 +2749,17 @@ void MultisampleRenderer::initialize (Context&                                                                  context,
                                VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     dstQueueFamilyIndex;
                                *m_depthStencilImage,                                                           // VkImage                                      image;
                                { depthStencilAttachmentAspect, 0u, 1u, 0u, 1u },       // VkImageSubresourceRange      subresourceRange;
-                       },
+                       };
+                       imageLayoutBarriers.push_back(depthStencilImageBarrier);
+                       dstStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
                };
 
                m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
 
                VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
 
-               vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0,
-                       0u, DE_NULL, 0u, DE_NULL, numUsedAttachments, imageLayoutBarriers);
+               vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, dstStageMask, (VkDependencyFlags)0,
+                       0u, DE_NULL, 0u, DE_NULL, (deUint32)imageLayoutBarriers.size(), &imageLayoutBarriers[0]);
 
                vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
 
@@ -2058,13 +2774,23 @@ void MultisampleRenderer::initialize (Context&                                                                  context,
                        vertexBufferOffset += static_cast<VkDeviceSize>(pVertices[i].size() * sizeof(Vertex4RGBA));
                }
 
+               if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
+               {
+                       // Copy each sample id to single sampled image
+                       for (deInt32 sampleId = 0; sampleId < (deInt32)m_perSampleImages.size(); ++sampleId)
+                       {
+                               vk.cmdNextSubpass(*m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
+                               vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **m_copySamplePipelines[sampleId]);
+                               vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_copySamplePipelineLayout, 0u, 1u, &m_copySampleDesciptorSet.get(), 0u, DE_NULL);
+                               vk.cmdPushConstants(*m_cmdBuffer, *m_copySamplePipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(deInt32), &sampleId);
+                               vk.cmdDraw(*m_cmdBuffer, 4, 1, 0, 0);
+                       }
+               }
+
                vk.cmdEndRenderPass(*m_cmdBuffer);
 
                VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
        }
-
-       // Create fence
-       m_fence = createFence(vk, vkDevice);
 }
 
 MultisampleRenderer::~MultisampleRenderer (void)
@@ -2077,25 +2803,22 @@ de::MovePtr<tcu::TextureLevel> MultisampleRenderer::render (void)
        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;
-               (const VkPipelineStageFlags*)DE_NULL,
-               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*/));
+       submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
 
-       return readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_resolveImage, m_colorFormat, m_renderSize.cast<deUint32>());
+       if (m_renderType == RENDER_TYPE_RESOLVE)
+       {
+               return readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, m_context.getDefaultAllocator(), *m_resolveImage, m_colorFormat, m_renderSize.cast<deUint32>());
+       }
+       else
+       {
+               return de::MovePtr<tcu::TextureLevel>();
+       }
+}
+
+de::MovePtr<tcu::TextureLevel> MultisampleRenderer::getSingleSampledImage (deUint32 sampleId)
+{
+       return readColorAttachment(m_context.getDeviceInterface(), m_context.getDevice(), m_context.getUniversalQueue(), m_context.getUniversalQueueFamilyIndex(), m_context.getDefaultAllocator(), *m_perSampleImages[sampleId]->m_image, m_colorFormat, m_renderSize.cast<deUint32>());
 }
 
 } // anonymous
@@ -2125,13 +2848,21 @@ tcu::TestCaseGroup* createMultisampleTests (tcu::TestContext& testCtx)
 
                        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));
+                       samplesTests->addChild(new RasterizationSamplesTest(testCtx, "primitive_triangle", "",  samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_TRIANGLE, IMAGE_BACKING_MODE_REGULAR));
+                       samplesTests->addChild(new RasterizationSamplesTest(testCtx, "primitive_line", "",              samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_LINE, IMAGE_BACKING_MODE_REGULAR));
+                       samplesTests->addChild(new RasterizationSamplesTest(testCtx, "primitive_point", "",             samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_POINT, IMAGE_BACKING_MODE_REGULAR));
+
+                       samplesTests->addChild(new RasterizationSamplesTest(testCtx, "depth", "",                       samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_TRIANGLE, IMAGE_BACKING_MODE_REGULAR, TEST_MODE_DEPTH_BIT));
+                       samplesTests->addChild(new RasterizationSamplesTest(testCtx, "stencil", "",                     samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_TRIANGLE, IMAGE_BACKING_MODE_REGULAR, TEST_MODE_STENCIL_BIT));
+                       samplesTests->addChild(new RasterizationSamplesTest(testCtx, "depth_stencil", "",       samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_TRIANGLE, IMAGE_BACKING_MODE_REGULAR, TEST_MODE_DEPTH_BIT | TEST_MODE_STENCIL_BIT));
 
-                       samplesTests->addChild(new RasterizationSamplesTest(testCtx, "depth", "",                       samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_TRIANGLE, TEST_MODE_DEPTH_BIT));
-                       samplesTests->addChild(new RasterizationSamplesTest(testCtx, "stencil", "",                     samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_TRIANGLE, TEST_MODE_STENCIL_BIT));
-                       samplesTests->addChild(new RasterizationSamplesTest(testCtx, "depth_stencil", "",       samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_TRIANGLE, TEST_MODE_DEPTH_BIT | TEST_MODE_STENCIL_BIT));
+                       samplesTests->addChild(new RasterizationSamplesTest(testCtx, "primitive_triangle_sparse", "",   samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_TRIANGLE, IMAGE_BACKING_MODE_SPARSE));
+                       samplesTests->addChild(new RasterizationSamplesTest(testCtx, "primitive_line_sparse", "",               samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_LINE, IMAGE_BACKING_MODE_SPARSE));
+                       samplesTests->addChild(new RasterizationSamplesTest(testCtx, "primitive_point_sparse", "",              samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_POINT, IMAGE_BACKING_MODE_SPARSE));
+
+                       samplesTests->addChild(new RasterizationSamplesTest(testCtx, "depth_sparse", "",                        samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_TRIANGLE, IMAGE_BACKING_MODE_SPARSE, TEST_MODE_DEPTH_BIT));
+                       samplesTests->addChild(new RasterizationSamplesTest(testCtx, "stencil_sparse", "",                      samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_TRIANGLE, IMAGE_BACKING_MODE_SPARSE, TEST_MODE_STENCIL_BIT));
+                       samplesTests->addChild(new RasterizationSamplesTest(testCtx, "depth_stencil_sparse", "",        samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_TRIANGLE, IMAGE_BACKING_MODE_SPARSE, TEST_MODE_DEPTH_BIT | TEST_MODE_STENCIL_BIT));
 
                        rasterizationSamplesTests->addChild(samplesTests.release());
                }
@@ -2141,14 +2872,23 @@ tcu::TestCaseGroup* createMultisampleTests (tcu::TestContext& testCtx)
 
        // Raster samples consistency check
        {
-               de::MovePtr<tcu::TestCaseGroup> rasterSamplesConsistencyTests(new tcu::TestCaseGroup(testCtx, "raster_samples_consistency", ""));
+               de::MovePtr<tcu::TestCaseGroup> rasterSamplesConsistencyTests   (new tcu::TestCaseGroup(testCtx, "raster_samples_consistency", ""));
+               MultisampleTestParams                   paramsRegular                                   = {GEOMETRY_TYPE_OPAQUE_TRIANGLE, IMAGE_BACKING_MODE_REGULAR};
+               MultisampleTestParams                   paramsSparse                                    = {GEOMETRY_TYPE_OPAQUE_TRIANGLE, IMAGE_BACKING_MODE_SPARSE};
 
                addFunctionCaseWithPrograms(rasterSamplesConsistencyTests.get(),
                                                                        "unique_colors_check",
                                                                        "",
                                                                        initMultisamplePrograms,
                                                                        testRasterSamplesConsistency,
-                                                                       GEOMETRY_TYPE_OPAQUE_TRIANGLE);
+                                                                       paramsRegular);
+
+               addFunctionCaseWithPrograms(rasterSamplesConsistencyTests.get(),
+                                                                       "unique_colors_check_sparse",
+                                                                       "",
+                                                                       initMultisamplePrograms,
+                                                                       testRasterSamplesConsistency,
+                                                                       paramsSparse);
 
                multisampleTests->addChild(rasterSamplesConsistencyTests.release());
        }
@@ -2184,9 +2924,13 @@ tcu::TestCaseGroup* createMultisampleTests (tcu::TestContext& testCtx)
 
                                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));
+                               samplesTests->addChild(new MinSampleShadingTest(testCtx, "primitive_triangle", "", samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_TRIANGLE, IMAGE_BACKING_MODE_REGULAR));
+                               samplesTests->addChild(new MinSampleShadingTest(testCtx, "primitive_line", "", samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_LINE, IMAGE_BACKING_MODE_REGULAR));
+                               samplesTests->addChild(new MinSampleShadingTest(testCtx, "primitive_point", "", samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_POINT, IMAGE_BACKING_MODE_REGULAR));
+
+                               samplesTests->addChild(new MinSampleShadingTest(testCtx, "primitive_triangle_sparse", "", samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_TRIANGLE, IMAGE_BACKING_MODE_SPARSE));
+                               samplesTests->addChild(new MinSampleShadingTest(testCtx, "primitive_line_sparse", "", samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_LINE, IMAGE_BACKING_MODE_SPARSE));
+                               samplesTests->addChild(new MinSampleShadingTest(testCtx, "primitive_point_sparse", "", samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_POINT, IMAGE_BACKING_MODE_SPARSE));
 
                                minShadingValueTests->addChild(samplesTests.release());
                        }
@@ -2233,9 +2977,13 @@ tcu::TestCaseGroup* createMultisampleTests (tcu::TestContext& testCtx)
                                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));
+                               samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_triangle", "", samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_TRIANGLE, IMAGE_BACKING_MODE_REGULAR));
+                               samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_line", "", samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_LINE, IMAGE_BACKING_MODE_REGULAR));
+                               samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_point", "", samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_POINT, IMAGE_BACKING_MODE_REGULAR));
+
+                               samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_triangle_sparse", "", samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_TRIANGLE, IMAGE_BACKING_MODE_SPARSE));
+                               samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_line_sparse", "", samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_LINE, IMAGE_BACKING_MODE_SPARSE));
+                               samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_point_sparse", "", samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_POINT, IMAGE_BACKING_MODE_SPARSE));
 
                                sampleMaskValueTests->addChild(samplesTests.release());
                        }
@@ -2256,7 +3004,10 @@ tcu::TestCaseGroup* createMultisampleTests (tcu::TestContext& testCtx)
                        std::ostringstream caseName;
                        caseName << "samples_" << samples[samplesNdx];
 
-                       alphaToOneTests->addChild(new AlphaToOneTest(testCtx, caseName.str(), "", samples[samplesNdx]));
+                       alphaToOneTests->addChild(new AlphaToOneTest(testCtx, caseName.str(), "", samples[samplesNdx], IMAGE_BACKING_MODE_REGULAR));
+
+                       caseName << "_sparse";
+                       alphaToOneTests->addChild(new AlphaToOneTest(testCtx, caseName.str(), "", samples[samplesNdx], IMAGE_BACKING_MODE_SPARSE));
                }
 
                multisampleTests->addChild(alphaToOneTests.release());
@@ -2273,9 +3024,13 @@ tcu::TestCaseGroup* createMultisampleTests (tcu::TestContext& testCtx)
 
                        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));
+                       samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_opaque", "", samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_QUAD, IMAGE_BACKING_MODE_REGULAR));
+                       samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_translucent", "", samples[samplesNdx], GEOMETRY_TYPE_TRANSLUCENT_QUAD, IMAGE_BACKING_MODE_REGULAR));
+                       samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_invisible", "", samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_QUAD, IMAGE_BACKING_MODE_REGULAR));
+
+                       samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_opaque_sparse", "", samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_QUAD, IMAGE_BACKING_MODE_SPARSE));
+                       samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_translucent_sparse", "", samples[samplesNdx], GEOMETRY_TYPE_TRANSLUCENT_QUAD, IMAGE_BACKING_MODE_SPARSE));
+                       samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_invisible_sparse", "", samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_QUAD, IMAGE_BACKING_MODE_SPARSE));
 
                        alphaToCoverageTests->addChild(samplesTests.release());
                }
@@ -2292,6 +3047,11 @@ tcu::TestCaseGroup* createMultisampleTests (tcu::TestContext& testCtx)
                multisampleTests->addChild(createMultisampleStorageImageTests(testCtx));
        }
 
+       // VK_EXT_sample_locations
+       {
+               multisampleTests->addChild(createMultisampleSampleLocationsExtTests(testCtx));
+       }
+
        return multisampleTests.release();
 }