Multisample Shader BuiltIn Tests
authorKantoch <marcin.kantoch@mobica.com>
Thu, 13 Oct 2016 12:29:53 +0000 (14:29 +0200)
committerPyry Haulos <phaulos@google.com>
Wed, 18 Jan 2017 18:49:14 +0000 (10:49 -0800)
Tests for gl_SampleID, gl_SamplePosition, gl_SampleMaskIn[], gl_SampleMask[]

New tests:
- dEQP-VK.pipeline.multisample_shader_builtin.*

Issue #450

Change-Id: I82875fc20d01232127f01186644a04d67ddb8833

16 files changed:
android/cts/master/vk-master.txt
external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt
external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBase.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBase.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolve.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolve.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolveAndPerSampleFetch.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolveAndPerSampleFetch.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleInterpolationTests.cpp
external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleInterpolationTests.hpp
external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleShaderBuiltInTests.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleShaderBuiltInTests.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleTestsUtil.cpp
external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleTestsUtil.hpp
external/vulkancts/modules/vulkan/pipeline/vktPipelineTests.cpp
external/vulkancts/mustpass/1.0.2/vk-default.txt

index d2bfa17..3076317 100644 (file)
@@ -87177,6 +87177,82 @@ dEQP-VK.pipeline.multisample_interpolation.offset_interpolate_at_sample_position
 dEQP-VK.pipeline.multisample_interpolation.offset_interpolate_at_sample_position.137_191_1.samples_16
 dEQP-VK.pipeline.multisample_interpolation.offset_interpolate_at_sample_position.137_191_1.samples_32
 dEQP-VK.pipeline.multisample_interpolation.offset_interpolate_at_sample_position.137_191_1.samples_64
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_64
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_64
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_64
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_64
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_64
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_64
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.128_128_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.128_128_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.128_128_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.128_128_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.128_128_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.137_191_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.137_191_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.137_191_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.137_191_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.137_191_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.128_128_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.128_128_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.128_128_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.128_128_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.128_128_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.137_191_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.137_191_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.137_191_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.137_191_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.137_191_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.128_128_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.128_128_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.128_128_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.128_128_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.128_128_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.137_191_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.137_191_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.137_191_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.137_191_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.137_191_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.128_128_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.128_128_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.128_128_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.128_128_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.128_128_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.137_191_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.137_191_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.137_191_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.137_191_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.137_191_1.samples_32
 dEQP-VK.pipeline.vertex_input.single_attribute.float_as_r8_unorm_rate_vertex
 dEQP-VK.pipeline.vertex_input.single_attribute.float_as_r8_unorm_rate_instance
 dEQP-VK.pipeline.vertex_input.single_attribute.float_as_r8_snorm_rate_vertex
index d3c7850..6b36ec2 100644 (file)
@@ -29,8 +29,16 @@ set(DEQP_VK_PIPELINE_SRCS
        vktPipelineMultisampleTestsUtil.hpp
        vktPipelineMultisampleTests.cpp
        vktPipelineMultisampleTests.hpp
+       vktPipelineMultisampleBase.cpp
+       vktPipelineMultisampleBase.hpp
+       vktPipelineMultisampleBaseResolve.cpp
+       vktPipelineMultisampleBaseResolve.hpp
+       vktPipelineMultisampleBaseResolveAndPerSampleFetch.cpp
+       vktPipelineMultisampleBaseResolveAndPerSampleFetch.hpp
        vktPipelineMultisampleInterpolationTests.cpp
        vktPipelineMultisampleInterpolationTests.hpp
+       vktPipelineMultisampleShaderBuiltInTests.cpp
+       vktPipelineMultisampleShaderBuiltInTests.hpp
        vktPipelineMultisampleImageTests.cpp
        vktPipelineMultisampleImageTests.hpp
        vktPipelineInputAssemblyTests.cpp
diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBase.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBase.cpp
new file mode 100644 (file)
index 0000000..07c3729
--- /dev/null
@@ -0,0 +1,166 @@
+/*------------------------------------------------------------------------
+* Vulkan Conformance Tests
+* ------------------------
+*
+* Copyright (c) 2016 The Khronos Group Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+*//*
+* \file vktPipelineMultisampleBase.cpp
+* \brief Multisample Tests Base Classes
+*//*--------------------------------------------------------------------*/
+
+#include "vktPipelineMultisampleBase.hpp"
+#include "vkQueryUtil.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+namespace multisample
+{
+
+using namespace vk;
+
+void MultisampleInstanceBase::validateImageSize        (const InstanceInterface&       instance,
+                                                                                                const VkPhysicalDevice         physicalDevice,
+                                                                                                const ImageType                        imageType,
+                                                                                                const tcu::UVec3&                      imageSize) const
+{
+       const VkPhysicalDeviceProperties deviceProperties = getPhysicalDeviceProperties(instance, physicalDevice);
+
+       bool isImageSizeValid = true;
+
+       switch (imageType)
+       {
+               case IMAGE_TYPE_1D:
+                       isImageSizeValid =      imageSize.x() <= deviceProperties.limits.maxImageDimension1D;
+                       break;
+               case IMAGE_TYPE_1D_ARRAY:
+                       isImageSizeValid =      imageSize.x() <= deviceProperties.limits.maxImageDimension1D &&
+                                                               imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
+                       break;
+               case IMAGE_TYPE_2D:
+                       isImageSizeValid =      imageSize.x() <= deviceProperties.limits.maxImageDimension2D &&
+                                                               imageSize.y() <= deviceProperties.limits.maxImageDimension2D;
+                       break;
+               case IMAGE_TYPE_2D_ARRAY:
+                       isImageSizeValid =      imageSize.x() <= deviceProperties.limits.maxImageDimension2D &&
+                                                               imageSize.y() <= deviceProperties.limits.maxImageDimension2D &&
+                                                               imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
+                       break;
+               case IMAGE_TYPE_CUBE:
+                       isImageSizeValid =      imageSize.x() <= deviceProperties.limits.maxImageDimensionCube &&
+                                                               imageSize.y() <= deviceProperties.limits.maxImageDimensionCube;
+                       break;
+               case IMAGE_TYPE_CUBE_ARRAY:
+                       isImageSizeValid =      imageSize.x() <= deviceProperties.limits.maxImageDimensionCube &&
+                                                               imageSize.y() <= deviceProperties.limits.maxImageDimensionCube &&
+                                                               imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
+                       break;
+               case IMAGE_TYPE_3D:
+                       isImageSizeValid =      imageSize.x() <= deviceProperties.limits.maxImageDimension3D &&
+                                                               imageSize.y() <= deviceProperties.limits.maxImageDimension3D &&
+                                                               imageSize.z() <= deviceProperties.limits.maxImageDimension3D;
+                       break;
+               default:
+                       DE_FATAL("Unknown image type");
+       }
+
+       if (!isImageSizeValid)
+       {
+               std::ostringstream      notSupportedStream;
+
+               notSupportedStream << "Image type (" << getImageTypeName(imageType) << ") with size (" << imageSize.x() << ", " << imageSize.y() << ", " << imageSize.z() << ") not supported by device" << std::endl;
+
+               const std::string notSupportedString = notSupportedStream.str();
+
+               TCU_THROW(NotSupportedError, notSupportedString.c_str());
+       }
+}
+
+void MultisampleInstanceBase::validateImageFeatureFlags        (const InstanceInterface&       instance,
+                                                                                                                const VkPhysicalDevice         physicalDevice,
+                                                                                                                const VkFormat                         format,
+                                                                                                                const VkFormatFeatureFlags     featureFlags) const
+{
+       const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(instance, physicalDevice, format);
+
+       if ((formatProperties.optimalTilingFeatures & featureFlags) != featureFlags)
+       {
+               std::ostringstream      notSupportedStream;
+
+               notSupportedStream << "Device does not support image format " << format << " for feature flags " << featureFlags << std::endl;
+
+               const std::string notSupportedString = notSupportedStream.str();
+
+               TCU_THROW(NotSupportedError, notSupportedString.c_str());
+       }
+}
+
+void MultisampleInstanceBase::validateImageInfo        (const InstanceInterface&       instance,
+                                                                                                const VkPhysicalDevice         physicalDevice,
+                                                                                                const VkImageCreateInfo&       imageInfo) const
+{
+       VkImageFormatProperties imageFormatProps;
+       instance.getPhysicalDeviceImageFormatProperties(physicalDevice, imageInfo.format, imageInfo.imageType, imageInfo.tiling, imageInfo.usage, imageInfo.flags, &imageFormatProps);
+
+       if (imageFormatProps.maxExtent.width  < imageInfo.extent.width  ||
+               imageFormatProps.maxExtent.height < imageInfo.extent.height ||
+               imageFormatProps.maxExtent.depth  < imageInfo.extent.depth)
+       {
+               std::ostringstream      notSupportedStream;
+
+               notSupportedStream      << "Image extent ("
+                                                       << imageInfo.extent.width  << ", "
+                                                       << imageInfo.extent.height << ", "
+                                                       << imageInfo.extent.depth
+                                                       << ") exceeds allowed maximum ("
+                                                       << imageFormatProps.maxExtent.width <<  ", "
+                                                       << imageFormatProps.maxExtent.height << ", "
+                                                       << imageFormatProps.maxExtent.depth
+                                                       << ")"
+                                                       << std::endl;
+
+               const std::string notSupportedString = notSupportedStream.str();
+
+               TCU_THROW(NotSupportedError, notSupportedString.c_str());
+       }
+
+       if (imageFormatProps.maxArrayLayers < imageInfo.arrayLayers)
+       {
+               std::ostringstream      notSupportedStream;
+
+               notSupportedStream << "Image layers count of " << imageInfo.arrayLayers << " exceeds allowed maximum which is " << imageFormatProps.maxArrayLayers << std::endl;
+
+               const std::string notSupportedString = notSupportedStream.str();
+
+               TCU_THROW(NotSupportedError, notSupportedString.c_str());
+       }
+
+       if (!(imageFormatProps.sampleCounts & imageInfo.samples))
+       {
+               std::ostringstream      notSupportedStream;
+
+               notSupportedStream << "Samples count of " << imageInfo.samples << " not supported for image" << std::endl;
+
+               const std::string notSupportedString = notSupportedStream.str();
+
+               TCU_THROW(NotSupportedError, notSupportedString.c_str());
+       }
+}
+
+} // multisample
+} // pipeline
+} // vkt
diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBase.hpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBase.hpp
new file mode 100644 (file)
index 0000000..ed20661
--- /dev/null
@@ -0,0 +1,146 @@
+#ifndef _VKTPIPELINEMULTISAMPLEBASE_HPP
+#define _VKTPIPELINEMULTISAMPLEBASE_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2016 The Khronos Group Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file vktPipelineMultisampleBase.hpp
+ * \brief Multisample Tests Base Classes
+ *//*--------------------------------------------------------------------*/
+
+#include "vktPipelineMultisampleTestsUtil.hpp"
+#include "vktTestCase.hpp"
+#include "tcuVector.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+namespace multisample
+{
+
+struct ImageMSParams
+{
+       ImageMSParams(const vk::VkSampleCountFlagBits samples, const tcu::UVec3& size) : numSamples(samples), imageSize(size) {}
+
+       vk::VkSampleCountFlagBits       numSamples;
+       tcu::UVec3                                      imageSize;
+};
+
+class MultisampleCaseBase : public TestCase
+{
+public:
+       MultisampleCaseBase     (tcu::TestContext&              testCtx,
+                                                const std::string&             name,
+                                                const ImageMSParams&   imageMSParams)
+               : TestCase(testCtx, name, "")
+               , m_imageMSParams(imageMSParams)
+       {}
+
+protected:
+       const ImageMSParams m_imageMSParams;
+};
+
+typedef MultisampleCaseBase* (*MultisampleCaseFuncPtr)(tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams);
+
+class MultisampleInstanceBase : public TestInstance
+{
+public:
+                                                               MultisampleInstanceBase         (Context&                                                       context,
+                                                                                                                        const ImageMSParams&                           imageMSParams)
+               : TestInstance          (context)
+               , m_imageMSParams       (imageMSParams)
+               , m_imageType           (IMAGE_TYPE_2D)
+               , m_imageFormat         (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8))
+       {}
+
+       typedef std::vector<vk::VkVertexInputAttributeDescription> VertexAttribDescVec;
+
+       struct VertexDataDesc
+       {
+               vk::VkPrimitiveTopology primitiveTopology;
+               deUint32                                verticesCount;
+               deUint32                                dataStride;
+               vk::VkDeviceSize                dataSize;
+               VertexAttribDescVec             vertexAttribDescVec;
+       };
+
+protected:
+
+       void                                    validateImageSize                       (const vk::InstanceInterface&   instance,
+                                                                                                                const vk::VkPhysicalDevice             physicalDevice,
+                                                                                                                const ImageType                                imageType,
+                                                                                                                const tcu::UVec3&                              imageSize) const;
+
+       void                                    validateImageFeatureFlags       (const vk::InstanceInterface&   instance,
+                                                                                                                const vk::VkPhysicalDevice             physicalDevice,
+                                                                                                                const vk::VkFormat                             format,
+                                                                                                                const vk::VkFormatFeatureFlags featureFlags) const;
+
+       void                                    validateImageInfo                       (const vk::InstanceInterface&   instance,
+                                                                                                                const vk::VkPhysicalDevice             physicalDevice,
+                                                                                                                const vk::VkImageCreateInfo&   imageInfo) const;
+
+       virtual VertexDataDesc  getVertexDataDescripton         (void) const = 0;
+
+       virtual void                    uploadVertexData                        (const vk::Allocation&                  vertexBufferAllocation,
+                                                                                                                const VertexDataDesc&                  vertexDataDescripton) const = 0;
+protected:
+       const ImageMSParams                     m_imageMSParams;
+       const ImageType                         m_imageType;
+       const tcu::TextureFormat        m_imageFormat;
+};
+
+} // multisample
+
+template <class CaseClass>
+tcu::TestCaseGroup* makeMSGroup        (tcu::TestContext&                                                      testCtx,
+                                                                const std::string                                                      groupName,
+                                                                const tcu::UVec3                                                       imageSizes[],
+                                                                const deUint32                                                         imageSizesElemCount,
+                                                                const vk::VkSampleCountFlagBits                        imageSamples[],
+                                                                const deUint32                                                         imageSamplesElemCount)
+{
+       de::MovePtr<tcu::TestCaseGroup> caseGroup(new tcu::TestCaseGroup(testCtx, groupName.c_str(), ""));
+
+       for (deUint32 imageSizeNdx = 0u; imageSizeNdx < imageSizesElemCount; ++imageSizeNdx)
+       {
+               const tcu::UVec3        imageSize = imageSizes[imageSizeNdx];
+               std::ostringstream      imageSizeStream;
+
+               imageSizeStream << imageSize.x() << "_" << imageSize.y() << "_" << imageSize.z();
+
+               de::MovePtr<tcu::TestCaseGroup> sizeGroup(new tcu::TestCaseGroup(testCtx, imageSizeStream.str().c_str(), ""));
+
+               for (deUint32 imageSamplesNdx = 0u; imageSamplesNdx < imageSamplesElemCount; ++imageSamplesNdx)
+               {
+                       const vk::VkSampleCountFlagBits         samples = imageSamples[imageSamplesNdx];
+                       const multisample::ImageMSParams        imageMSParams = multisample::ImageMSParams(samples, imageSize);
+
+                       sizeGroup->addChild(CaseClass::createCase(testCtx, "samples_" + de::toString(samples), imageMSParams));
+               }
+
+               caseGroup->addChild(sizeGroup.release());
+       }
+       return caseGroup.release();
+}
+
+} // pipeline
+} // vkt
+
+#endif // _VKTPIPELINEMULTISAMPLEBASE_HPP
diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolve.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolve.cpp
new file mode 100644 (file)
index 0000000..4ad1644
--- /dev/null
@@ -0,0 +1,550 @@
+/*------------------------------------------------------------------------
+* Vulkan Conformance Tests
+* ------------------------
+*
+* Copyright (c) 2016 The Khronos Group Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+*//*
+* \file vktPipelineMultisampleBaseResolve.cpp
+* \brief Base class for tests that check results of multisample resolve
+*//*--------------------------------------------------------------------*/
+
+#include "vktPipelineMultisampleBaseResolve.hpp"
+#include "vktPipelineMakeUtil.hpp"
+#include "vkBuilderUtil.hpp"
+#include "vkQueryUtil.hpp"
+#include <vector>
+
+namespace vkt
+{
+namespace pipeline
+{
+namespace multisample
+{
+
+using namespace vk;
+
+tcu::TestStatus MSInstanceBaseResolve::iterate (void)
+{
+       const InstanceInterface&        instance                        = m_context.getInstanceInterface();
+       const DeviceInterface&          deviceInterface         = m_context.getDeviceInterface();
+       const VkDevice                          device                          = m_context.getDevice();
+       const VkPhysicalDevice          physicalDevice          = m_context.getPhysicalDevice();
+       Allocator&                                      allocator                       = m_context.getDefaultAllocator();
+       const VkQueue                           queue                           = m_context.getUniversalQueue();
+       const deUint32                          queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
+
+       VkImageCreateInfo                       imageMSInfo;
+       VkImageCreateInfo                       imageRSInfo;
+
+       // Check if image size does not exceed device limits
+       validateImageSize(instance, physicalDevice, m_imageType, m_imageMSParams.imageSize);
+
+       // Check if device supports image format as color attachment
+       validateImageFeatureFlags(instance, physicalDevice, mapTextureFormat(m_imageFormat), VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);
+
+       imageMSInfo.sType                                       = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+       imageMSInfo.pNext                                       = DE_NULL;
+       imageMSInfo.flags                                       = 0u;
+       imageMSInfo.imageType                           = mapImageType(m_imageType);
+       imageMSInfo.format                                      = mapTextureFormat(m_imageFormat);
+       imageMSInfo.extent                                      = makeExtent3D(getLayerSize(m_imageType, m_imageMSParams.imageSize));
+       imageMSInfo.arrayLayers                         = getNumLayers(m_imageType, m_imageMSParams.imageSize);
+       imageMSInfo.mipLevels                           = 1u;
+       imageMSInfo.samples                                     = m_imageMSParams.numSamples;
+       imageMSInfo.tiling                                      = VK_IMAGE_TILING_OPTIMAL;
+       imageMSInfo.initialLayout                       = VK_IMAGE_LAYOUT_UNDEFINED;
+       imageMSInfo.usage                                       = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+       imageMSInfo.sharingMode                         = VK_SHARING_MODE_EXCLUSIVE;
+       imageMSInfo.queueFamilyIndexCount       = 0u;
+       imageMSInfo.pQueueFamilyIndices         = DE_NULL;
+
+       if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY)
+       {
+               imageMSInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
+       }
+
+       validateImageInfo(instance, physicalDevice, imageMSInfo);
+
+       const de::UniquePtr<Image> imageMS(new Image(deviceInterface, device, allocator, imageMSInfo, MemoryRequirement::Any));
+
+       imageRSInfo                     = imageMSInfo;
+       imageRSInfo.samples     = VK_SAMPLE_COUNT_1_BIT;
+
+       validateImageInfo(instance, physicalDevice, imageRSInfo);
+
+       const de::UniquePtr<Image> imageRS(new Image(deviceInterface, device, allocator, imageRSInfo, MemoryRequirement::Any));
+
+       // Create render pass
+       const VkAttachmentDescription attachmentMSDesc =
+       {
+               (VkAttachmentDescriptionFlags)0u,                       // VkAttachmentDescriptionFlags         flags;
+               imageMSInfo.format,                                                     // VkFormat                                                     format;
+               imageMSInfo.samples,                                            // VkSampleCountFlagBits                        samples;
+               VK_ATTACHMENT_LOAD_OP_CLEAR,                            // VkAttachmentLoadOp                           loadOp;
+               VK_ATTACHMENT_STORE_OP_STORE,                           // VkAttachmentStoreOp                          storeOp;
+               VK_ATTACHMENT_LOAD_OP_DONT_CARE,                        // VkAttachmentLoadOp                           stencilLoadOp;
+               VK_ATTACHMENT_STORE_OP_DONT_CARE,                       // VkAttachmentStoreOp                          stencilStoreOp;
+               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,       // VkImageLayout                                        initialLayout;
+               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout                                        finalLayout;
+       };
+
+       const VkAttachmentDescription attachmentRSDesc =
+       {
+               (VkAttachmentDescriptionFlags)0u,                       // VkAttachmentDescriptionFlags         flags;
+               imageRSInfo.format,                                                     // VkFormat                                                     format;
+               imageRSInfo.samples,                                            // VkSampleCountFlagBits                        samples;
+               VK_ATTACHMENT_LOAD_OP_CLEAR,                    // VkAttachmentLoadOp                           loadOp;
+               VK_ATTACHMENT_STORE_OP_STORE,                           // VkAttachmentStoreOp                          storeOp;
+               VK_ATTACHMENT_LOAD_OP_DONT_CARE,                        // VkAttachmentLoadOp                           stencilLoadOp;
+               VK_ATTACHMENT_STORE_OP_DONT_CARE,                       // VkAttachmentStoreOp                          stencilStoreOp;
+               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,       // VkImageLayout                                        initialLayout;
+               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout                                        finalLayout;
+       };
+
+       const VkAttachmentDescription attachments[] = { attachmentMSDesc, attachmentRSDesc };
+
+       const VkAttachmentReference attachmentMSRef =
+       {
+               0u,                                                                                     // deUint32                     attachment;
+               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout        layout;
+       };
+
+       const VkAttachmentReference attachmentRSRef =
+       {
+               1u,                                                                                     // deUint32                     attachment;
+               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout        layout;
+       };
+
+       const VkAttachmentReference* resolveAttachment = m_imageMSParams.numSamples == VK_SAMPLE_COUNT_1_BIT ? DE_NULL : &attachmentRSRef;
+
+       const VkSubpassDescription subpassDescription =
+       {
+               (VkSubpassDescriptionFlags)0u,                                          // VkSubpassDescriptionFlags            flags;
+               VK_PIPELINE_BIND_POINT_GRAPHICS,                                        // VkPipelineBindPoint                          pipelineBindPoint;
+               0u,                                                                                                     // deUint32                                                     inputAttachmentCount;
+               DE_NULL,                                                                                        // const VkAttachmentReference*         pInputAttachments;
+               1u,                                                                                                     // deUint32                                                     colorAttachmentCount;
+               &attachmentMSRef,                                                                       // const VkAttachmentReference*         pColorAttachments;
+               resolveAttachment,                                                              // const VkAttachmentReference*         pResolveAttachments;
+               DE_NULL,                                                                                        // const VkAttachmentReference*         pDepthStencilAttachment;
+               0u,                                                                                                     // deUint32                                                     preserveAttachmentCount;
+               DE_NULL                                                                                         // const deUint32*                                      pPreserveAttachments;
+       };
+
+       const VkRenderPassCreateInfo renderPassInfo =
+       {
+               VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                      // VkStructureType                                      sType;
+               DE_NULL,                                                                                        // const void*                                          pNext;
+               (VkRenderPassCreateFlags)0u,                                            // VkRenderPassCreateFlags                      flags;
+               2u,                                                                                                     // deUint32                                                     attachmentCount;
+               attachments,                                                                            // const VkAttachmentDescription*       pAttachments;
+               1u,                                                                                                     // deUint32                                                     subpassCount;
+               &subpassDescription,                                                            // const VkSubpassDescription*          pSubpasses;
+               0u,                                                                                                     // deUint32                                                     dependencyCount;
+               DE_NULL                                                                                         // const VkSubpassDependency*           pDependencies;
+       };
+
+       const Unique<VkRenderPass> renderPass(createRenderPass(deviceInterface, device, &renderPassInfo));
+
+       const VkImageSubresourceRange fullImageRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageMSInfo.mipLevels, 0u, imageMSInfo.arrayLayers);
+
+       // Create color attachments image views
+       const Unique<VkImageView> imageMSView(makeImageView(deviceInterface, device, **imageMS, mapImageViewType(m_imageType), imageMSInfo.format, fullImageRange));
+       const Unique<VkImageView> imageRSView(makeImageView(deviceInterface, device, **imageRS, mapImageViewType(m_imageType), imageMSInfo.format, fullImageRange));
+
+       const VkImageView attachmentsViews[] = { *imageMSView, *imageRSView };
+
+       // Create framebuffer
+       const VkFramebufferCreateInfo framebufferInfo =
+       {
+               VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,      // VkStructureType                             sType;
+               DE_NULL,                                                                        // const void*                                 pNext;
+               (VkFramebufferCreateFlags)0u,                           // VkFramebufferCreateFlags                    flags;
+               *renderPass,                                                            // VkRenderPass                                renderPass;
+               2u,                                                                                     // uint32_t                                    attachmentCount;
+               attachmentsViews,                                                       // const VkImageView*                          pAttachments;
+               imageMSInfo.extent.width,                                       // uint32_t                                    width;
+               imageMSInfo.extent.height,                                      // uint32_t                                    height;
+               imageMSInfo.arrayLayers,                                        // uint32_t                                    layers;
+       };
+
+       const Unique<VkFramebuffer> framebuffer(createFramebuffer(deviceInterface, device, &framebufferInfo));
+
+       // Create pipeline layout
+       const VkPipelineLayoutCreateInfo pipelineLayoutParams =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                                      sType;
+               DE_NULL,                                                                                        // const void*                                          pNext;
+               (VkPipelineLayoutCreateFlags)0u,                                        // VkPipelineLayoutCreateFlags          flags;
+               0u,                                                                                                     // deUint32                                                     setLayoutCount;
+               DE_NULL,                                                                                        // const VkDescriptorSetLayout*         pSetLayouts;
+               0u,                                                                                                     // deUint32                                                     pushConstantRangeCount;
+               DE_NULL,                                                                                        // const VkPushConstantRange*           pPushConstantRanges;
+       };
+
+       const Unique<VkPipelineLayout> pipelineLayout(createPipelineLayout(deviceInterface, device, &pipelineLayoutParams));
+
+       // Create vertex attributes data
+       const VertexDataDesc vertexDataDesc = getVertexDataDescripton();
+
+       de::SharedPtr<Buffer> vertexBuffer = de::SharedPtr<Buffer>(new Buffer(deviceInterface, device, allocator, makeBufferCreateInfo(vertexDataDesc.dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
+       const Allocation& vertexBufferAllocation = vertexBuffer->getAllocation();
+
+       uploadVertexData(vertexBufferAllocation, vertexDataDesc);
+
+       flushMappedMemoryRange(deviceInterface, device, vertexBufferAllocation.getMemory(), vertexBufferAllocation.getOffset(), VK_WHOLE_SIZE);
+
+       const VkVertexInputBindingDescription vertexBinding =
+       {
+               0u,                                                     // deUint32                             binding;
+               vertexDataDesc.dataStride,      // deUint32                             stride;
+               VK_VERTEX_INPUT_RATE_VERTEX     // VkVertexInputRate    inputRate;
+       };
+
+       const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,                      // VkStructureType                             sType;
+               DE_NULL,                                                                                                                        // const void*                                 pNext;
+               (VkPipelineVertexInputStateCreateFlags)0u,                                                      // VkPipelineVertexInputStateCreateFlags       flags;
+               1u,                                                                                                                                     // uint32_t                                    vertexBindingDescriptionCount;
+               &vertexBinding,                                                                                                         // const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
+               static_cast<deUint32>(vertexDataDesc.vertexAttribDescVec.size()),       // uint32_t                                    vertexAttributeDescriptionCount;
+               dataPointer(vertexDataDesc.vertexAttribDescVec),                                        // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
+       };
+
+       const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                             sType;
+               DE_NULL,                                                                                                                // const void*                                 pNext;
+               (VkPipelineInputAssemblyStateCreateFlags)0u,                                    // VkPipelineInputAssemblyStateCreateFlags     flags;
+               vertexDataDesc.primitiveTopology,                                                               // VkPrimitiveTopology                         topology;
+               VK_FALSE,                                                                                                               // VkBool32                                    primitiveRestartEnable;
+       };
+
+       const VkViewport viewport =
+       {
+               0.0f, 0.0f,
+               static_cast<float>(imageMSInfo.extent.width), static_cast<float>(imageMSInfo.extent.height),
+               0.0f, 1.0f
+       };
+
+       const VkRect2D scissor =
+       {
+               makeOffset2D(0, 0),
+               makeExtent2D(imageMSInfo.extent.width, imageMSInfo.extent.height),
+       };
+
+       const VkPipelineViewportStateCreateInfo viewportStateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,                  // VkStructureType                             sType;
+               DE_NULL,                                                                                                                // const void*                                 pNext;
+               (VkPipelineViewportStateCreateFlags)0u,                                                 // VkPipelineViewportStateCreateFlags          flags;
+               1u,                                                                                                                             // uint32_t                                    viewportCount;
+               &viewport,                                                                                                              // const VkViewport*                           pViewports;
+               1u,                                                                                                                             // uint32_t                                    scissorCount;
+               &scissor,                                                                                                               // const VkRect2D*                             pScissors;
+       };
+
+       const VkPipelineRasterizationStateCreateInfo rasterizationStateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                          sType;
+               DE_NULL,                                                                                                                // const void*                              pNext;
+               (VkPipelineRasterizationStateCreateFlags)0u,                                    // VkPipelineRasterizationStateCreateFlags  flags;
+               VK_FALSE,                                                                                                               // VkBool32                                 depthClampEnable;
+               VK_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 VkPipelineMultisampleStateCreateInfo multisampleStateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,               // VkStructureType                                                      sType;
+               DE_NULL,                                                                                                                // const void*                                                          pNext;
+               (VkPipelineMultisampleStateCreateFlags)0u,                                              // VkPipelineMultisampleStateCreateFlags        flags;
+               imageMSInfo.samples,                                                                                    // VkSampleCountFlagBits                                        rasterizationSamples;
+               VK_TRUE,                                                                                                                // VkBool32                                                                     sampleShadingEnable;
+               1.0f,                                                                                                                   // float                                                                        minSampleShading;
+               DE_NULL,                                                                                                                // const VkSampleMask*                                          pSampleMask;
+               VK_FALSE,                                                                                                               // VkBool32                                                                     alphaToCoverageEnable;
+               VK_FALSE,                                                                                                               // VkBool32                                                                     alphaToOneEnable;
+       };
+
+       const VkStencilOpState stencilOpState = makeStencilOpState
+       (
+               VK_STENCIL_OP_KEEP,             // stencil fail
+               VK_STENCIL_OP_KEEP,             // depth & stencil pass
+               VK_STENCIL_OP_KEEP,             // depth only fail
+               VK_COMPARE_OP_ALWAYS,   // compare op
+               0u,                                             // compare mask
+               0u,                                             // write mask
+               0u                                              // reference
+       );
+
+       const VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,             // VkStructureType                                                      sType;
+               DE_NULL,                                                                                                                // const void*                                                          pNext;
+               (VkPipelineDepthStencilStateCreateFlags)0u,                                             // VkPipelineDepthStencilStateCreateFlags       flags;
+               VK_FALSE,                                                                                                               // VkBool32                                                                     depthTestEnable;
+               VK_FALSE,                                                                                                               // VkBool32                                                                     depthWriteEnable;
+               VK_COMPARE_OP_LESS,                                                                                             // VkCompareOp                                                          depthCompareOp;
+               VK_FALSE,                                                                                                               // VkBool32                                                                     depthBoundsTestEnable;
+               VK_FALSE,                                                                                                               // VkBool32                                                                     stencilTestEnable;
+               stencilOpState,                                                                                                 // VkStencilOpState                                                     front;
+               stencilOpState,                                                                                                 // VkStencilOpState                                                     back;
+               0.0f,                                                                                                                   // float                                                                        minDepthBounds;
+               1.0f,                                                                                                                   // float                                                                        maxDepthBounds;
+       };
+
+       const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
+
+       const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
+       {
+               VK_FALSE,                                                                                                               // VkBool32                                     blendEnable;
+               VK_BLEND_FACTOR_ONE,                                                                                    // VkBlendFactor                        srcColorBlendFactor;
+               VK_BLEND_FACTOR_ZERO,                                                                                   // VkBlendFactor                        dstColorBlendFactor;
+               VK_BLEND_OP_ADD,                                                                                                // VkBlendOp                            colorBlendOp;
+               VK_BLEND_FACTOR_ONE,                                                                                    // VkBlendFactor                        srcAlphaBlendFactor;
+               VK_BLEND_FACTOR_ZERO,                                                                                   // VkBlendFactor                        dstAlphaBlendFactor;
+               VK_BLEND_OP_ADD,                                                                                                // VkBlendOp                            alphaBlendOp;
+               colorComponentsAll,                                                                                             // VkColorComponentFlags        colorWriteMask;
+       };
+
+       const VkPipelineColorBlendStateCreateInfo colorBlendStateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,               // VkStructureType                                                              sType;
+               DE_NULL,                                                                                                                // const void*                                                                  pNext;
+               (VkPipelineColorBlendStateCreateFlags)0u,                                               // VkPipelineColorBlendStateCreateFlags                 flags;
+               VK_FALSE,                                                                                                               // VkBool32                                                                             logicOpEnable;
+               VK_LOGIC_OP_COPY,                                                                                               // VkLogicOp                                                                    logicOp;
+               1u,                                                                                                                             // deUint32                                                                             attachmentCount;
+               &colorBlendAttachmentState,                                                                             // const VkPipelineColorBlendAttachmentState*   pAttachments;
+               { 0.0f, 0.0f, 0.0f, 0.0f },                                                                             // float                                                                                blendConstants[4];
+       };
+
+       const Unique<VkShaderModule> vsModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("vertex_shader"), (VkShaderModuleCreateFlags)0));
+
+       const VkPipelineShaderStageCreateInfo vsShaderStageInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,                    // VkStructureType                                              sType;
+               DE_NULL,                                                                                                                // const void*                                                  pNext;
+               (VkPipelineShaderStageCreateFlags)0u,                                                   // VkPipelineShaderStageCreateFlags             flags;
+               VK_SHADER_STAGE_VERTEX_BIT,                                                                             // VkShaderStageFlagBits                                stage;
+               *vsModule,                                                                                                              // VkShaderModule                                               module;
+               "main",                                                                                                                 // const char*                                                  pName;
+               DE_NULL,                                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
+       };
+
+       const Unique<VkShaderModule> fsModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("fragment_shader"), (VkShaderModuleCreateFlags)0));
+
+       const VkPipelineShaderStageCreateInfo fsShaderStageInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,                    // VkStructureType                                              sType;
+               DE_NULL,                                                                                                                // const void*                                                  pNext;
+               (VkPipelineShaderStageCreateFlags)0u,                                                   // VkPipelineShaderStageCreateFlags             flags;
+               VK_SHADER_STAGE_FRAGMENT_BIT,                                                                   // VkShaderStageFlagBits                                stage;
+               *fsModule,                                                                                                              // VkShaderModule                                               module;
+               "main",                                                                                                                 // const char*                                                  pName;
+               DE_NULL,                                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
+       };
+
+       const VkPipelineShaderStageCreateInfo shaderStageInfos[] = { vsShaderStageInfo, fsShaderStageInfo };
+
+       const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
+       {
+               VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,                                // VkStructureType                                                                      sType;
+               DE_NULL,                                                                                                                // const void*                                                                          pNext;
+               (VkPipelineCreateFlags)0,                                                                               // VkPipelineCreateFlags                                                        flags;
+               2u,                                                                                                                             // deUint32                                                                                     stageCount;
+               shaderStageInfos,                                                                                               // const VkPipelineShaderStageCreateInfo*                       pStages;
+               &vertexInputStateInfo,                                                                                  // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
+               &inputAssemblyStateInfo,                                                                                // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
+               DE_NULL,                                                                                                                // const VkPipelineTessellationStateCreateInfo*         pTessellationState;
+               &viewportStateInfo,                                                                                             // const VkPipelineViewportStateCreateInfo*                     pViewportState;
+               &rasterizationStateInfo,                                                                                // const VkPipelineRasterizationStateCreateInfo*        pRasterizationState;
+               &multisampleStateInfo,                                                                                  // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
+               &depthStencilStateInfo,                                                                                 // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
+               &colorBlendStateInfo,                                                                                   // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
+               DE_NULL,                                                                                                                // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
+               *pipelineLayout,                                                                                                // VkPipelineLayout                                                                     layout;
+               *renderPass,                                                                                                    // VkRenderPass                                                                         renderPass;
+               0u,                                                                                                                             // deUint32                                                                                     subpass;
+               DE_NULL,                                                                                                                // VkPipeline                                                                           basePipelineHandle;
+               0u,                                                                                                                             // deInt32                                                                                      basePipelineIndex;
+       };
+
+       // Create graphics pipeline
+       const Unique<VkPipeline> graphicsPipeline(createGraphicsPipeline(deviceInterface, device, DE_NULL, &graphicsPipelineInfo));
+
+       // Create command buffer for compute and transfer oparations
+       const Unique<VkCommandPool>       commandPool(makeCommandPool(deviceInterface, device, queueFamilyIndex));
+       const Unique<VkCommandBuffer> commandBuffer(makeCommandBuffer(deviceInterface, device, *commandPool));
+
+       // Start recording commands
+       beginCommandBuffer(deviceInterface, *commandBuffer);
+
+       {
+               VkImageMemoryBarrier imageOutputAttachmentBarriers[2];
+
+               imageOutputAttachmentBarriers[0] = makeImageMemoryBarrier
+               (
+                       0u,
+                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+                       VK_IMAGE_LAYOUT_UNDEFINED,
+                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+                       **imageMS,
+                       fullImageRange
+               );
+
+               imageOutputAttachmentBarriers[1] = makeImageMemoryBarrier
+               (
+                       0u,
+                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+                       VK_IMAGE_LAYOUT_UNDEFINED,
+                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+                       **imageRS,
+                       fullImageRange
+               );
+
+               deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 2u, imageOutputAttachmentBarriers);
+       }
+
+       {
+               const VkDeviceSize vertexStartOffset = 0u;
+
+               std::vector<VkClearValue> clearValues;
+               clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
+               clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
+
+               const vk::VkRect2D renderArea =
+               {
+                       makeOffset2D(0u, 0u),
+                       makeExtent2D(imageMSInfo.extent.width, imageMSInfo.extent.height),
+               };
+
+               // Begin render pass
+               const VkRenderPassBeginInfo renderPassBeginInfo =
+               {
+                       VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,               // VkStructureType         sType;
+                       DE_NULL,                                                                                // const void*             pNext;
+                       *renderPass,                                                                            // VkRenderPass            renderPass;
+                       *framebuffer,                                                                   // VkFramebuffer           framebuffer;
+                       renderArea,                                                                             // VkRect2D                renderArea;
+                       static_cast<deUint32>(clearValues.size()),              // deUint32                clearValueCount;
+                       &clearValues[0],                                                                // const VkClearValue*     pClearValues;
+               };
+
+               deviceInterface.cmdBeginRenderPass(*commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+               // Bind graphics pipeline
+               deviceInterface.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
+
+               // Bind vertex buffer
+               deviceInterface.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBuffer->get(), &vertexStartOffset);
+
+               // Draw full screen quad
+               deviceInterface.cmdDraw(*commandBuffer, vertexDataDesc.verticesCount, 1u, 0u, 0u);
+
+               // End render pass
+               deviceInterface.cmdEndRenderPass(*commandBuffer);
+       }
+
+       const VkImage sourceImage = m_imageMSParams.numSamples == VK_SAMPLE_COUNT_1_BIT ? **imageMS : **imageRS;
+
+       {
+               const VkImageMemoryBarrier imageTransferSrcBarrier = makeImageMemoryBarrier
+               (
+                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+                       VK_ACCESS_TRANSFER_READ_BIT,
+                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+                       VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+                       sourceImage,
+                       fullImageRange
+               );
+
+               deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageTransferSrcBarrier);
+       }
+
+       // Copy data from resolve image to buffer
+       const deUint32                          imageRSSizeInBytes = getImageSizeInBytes(imageRSInfo.extent, imageRSInfo.arrayLayers, m_imageFormat, imageRSInfo.mipLevels);
+
+       const VkBufferCreateInfo        bufferRSInfo = makeBufferCreateInfo(imageRSSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+       const de::UniquePtr<Buffer>     bufferRS(new Buffer(deviceInterface, device, allocator, bufferRSInfo, MemoryRequirement::HostVisible));
+
+       {
+               const VkBufferImageCopy bufferImageCopy =
+               {
+                       0u,                                                                                                                                                                             //      VkDeviceSize                            bufferOffset;
+                       0u,                                                                                                                                                                             //      deUint32                                        bufferRowLength;
+                       0u,                                                                                                                                                                             //      deUint32                                        bufferImageHeight;
+                       makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageRSInfo.arrayLayers), //      VkImageSubresourceLayers        imageSubresource;
+                       makeOffset3D(0, 0, 0),                                                                                                                                  //      VkOffset3D                                      imageOffset;
+                       imageRSInfo.extent,                                                                                                                                             //      VkExtent3D                                      imageExtent;
+               };
+
+               deviceInterface.cmdCopyImageToBuffer(*commandBuffer, sourceImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, bufferRS->get(), 1u, &bufferImageCopy);
+       }
+
+       {
+               const VkBufferMemoryBarrier bufferRSHostReadBarrier = makeBufferMemoryBarrier
+               (
+                       VK_ACCESS_TRANSFER_WRITE_BIT,
+                       VK_ACCESS_HOST_READ_BIT,
+                       bufferRS->get(),
+                       0u,
+                       imageRSSizeInBytes
+               );
+
+               deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferRSHostReadBarrier, 0u, DE_NULL);
+       }
+
+       // End recording commands
+       VK_CHECK(deviceInterface.endCommandBuffer(*commandBuffer));
+
+       // Submit commands for execution and wait for completion
+       submitCommandsAndWait(deviceInterface, device, queue, *commandBuffer);
+
+       // Retrieve data from buffer to host memory
+       const Allocation& bufferRSAllocation = bufferRS->getAllocation();
+
+       invalidateMappedMemoryRange(deviceInterface, device, bufferRSAllocation.getMemory(), bufferRSAllocation.getOffset(), VK_WHOLE_SIZE);
+
+       const tcu::ConstPixelBufferAccess bufferRSData (m_imageFormat,
+                                                                                                       imageRSInfo.extent.width,
+                                                                                                       imageRSInfo.extent.height,
+                                                                                                       imageRSInfo.extent.depth * imageRSInfo.arrayLayers,
+                                                                                                       bufferRSAllocation.getHostPtr());
+
+       std::stringstream imageName;
+       imageName << getImageTypeName(m_imageType) << "_" << bufferRSData.getWidth() << "_" << bufferRSData.getHeight() << "_" << bufferRSData.getDepth() << std::endl;
+
+       m_context.getTestContext().getLog()
+               << tcu::TestLog::Section(imageName.str(), imageName.str())
+               << tcu::LogImage("image", "", bufferRSData)
+               << tcu::TestLog::EndSection;
+
+       return verifyImageData(imageRSInfo, bufferRSData);
+}
+
+} // multisample
+} // pipeline
+} // vkt
diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolve.hpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolve.hpp
new file mode 100644 (file)
index 0000000..c123a15
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef _VKTPIPELINEMULTISAMPLEBASERESOLVE_HPP
+#define _VKTPIPELINEMULTISAMPLEBASERESOLVE_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2016 The Khronos Group Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file vktPipelineMultisampleBaseResolve.hpp
+ * \brief Base class for tests that check results of multisample resolve
+ *//*--------------------------------------------------------------------*/
+
+#include "vktPipelineMultisampleBase.hpp"
+#include "vktTestCase.hpp"
+#include "tcuVector.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+namespace multisample
+{
+
+class MSCaseBaseResolve : public MultisampleCaseBase
+{
+public:
+       MSCaseBaseResolve       (tcu::TestContext&              testCtx,
+                                                const std::string&             name,
+                                                const ImageMSParams&   imageMSParams)
+               : MultisampleCaseBase(testCtx, name, imageMSParams)
+       {}
+};
+
+class MSInstanceBaseResolve : public MultisampleInstanceBase
+{
+public:
+                                                       MSInstanceBaseResolve   (Context&                                                       context,
+                                                                                                        const ImageMSParams&                           imageMSParams)
+                                                               : MultisampleInstanceBase(context, imageMSParams)
+                                                       {}
+
+protected:
+
+       tcu::TestStatus                 iterate                                 (void);
+
+       virtual tcu::TestStatus verifyImageData                 (const vk::VkImageCreateInfo&           imageRSInfo,
+                                                                                                        const tcu::ConstPixelBufferAccess&     dataRS) const = 0;
+};
+
+} // multisample
+} // pipeline
+} // vkt
+
+#endif // _VKTPIPELINEMULTISAMPLEBASERESOLVE_HPP
diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolveAndPerSampleFetch.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolveAndPerSampleFetch.cpp
new file mode 100644 (file)
index 0000000..6b670ca
--- /dev/null
@@ -0,0 +1,1026 @@
+/*------------------------------------------------------------------------
+* Vulkan Conformance Tests
+* ------------------------
+*
+* Copyright (c) 2016 The Khronos Group Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+*//*
+* \file vktPipelineMultisampleBaseResolveAndPerSampleFetch.cpp
+* \brief Base class for tests that check results of multisample resolve
+*                and/or values of individual samples
+*//*--------------------------------------------------------------------*/
+
+#include "vktPipelineMultisampleBaseResolveAndPerSampleFetch.hpp"
+#include "vktPipelineMakeUtil.hpp"
+#include "vkBuilderUtil.hpp"
+#include "vkQueryUtil.hpp"
+#include <vector>
+
+namespace vkt
+{
+namespace pipeline
+{
+namespace multisample
+{
+
+using namespace vk;
+
+void MSCaseBaseResolveAndPerSampleFetch::initPrograms (vk::SourceCollections& programCollection) const
+{
+       // Create vertex shader
+       std::ostringstream vs;
+
+       vs << "#version 440\n"
+               << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
+               << "\n"
+               << "out gl_PerVertex {\n"
+               << "    vec4  gl_Position;\n"
+               << "};\n"
+               << "void main (void)\n"
+               << "{\n"
+               << "    gl_Position     = vs_in_position_ndc;\n"
+               << "}\n";
+
+       programCollection.glslSources.add("per_sample_fetch_vs") << glu::VertexSource(vs.str());
+
+       // Create fragment shader
+       std::ostringstream fs;
+
+       fs << "#version 440\n"
+               << "\n"
+               << "layout(location = 0) out vec4 fs_out_color;\n"
+               << "\n"
+               << "layout(set = 0, binding = 0, input_attachment_index = 0) uniform subpassInputMS imageMS;\n"
+               << "\n"
+               << "layout(set = 0, binding = 1, std140) uniform SampleBlock {\n"
+               << "    int sampleNdx;\n"
+               << "};\n"
+               << "void main (void)\n"
+               << "{\n"
+               << "    fs_out_color = subpassLoad(imageMS, sampleNdx);\n"
+               << "}\n";
+
+       programCollection.glslSources.add("per_sample_fetch_fs") << glu::FragmentSource(fs.str());
+}
+
+VkPipelineMultisampleStateCreateInfo MSInstanceBaseResolveAndPerSampleFetch::getMSStateCreateInfo (const ImageMSParams& imageMSParams) const
+{
+       const VkPipelineMultisampleStateCreateInfo multisampleStateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,               // VkStructureType                                                      sType;
+               DE_NULL,                                                                                                                // const void*                                                          pNext;
+               (VkPipelineMultisampleStateCreateFlags)0u,                                              // VkPipelineMultisampleStateCreateFlags        flags;
+               imageMSParams.numSamples,                                                                               // VkSampleCountFlagBits                                        rasterizationSamples;
+               VK_TRUE,                                                                                                                // VkBool32                                                                     sampleShadingEnable;
+               1.0f,                                                                                                                   // float                                                                        minSampleShading;
+               DE_NULL,                                                                                                                // const VkSampleMask*                                          pSampleMask;
+               VK_FALSE,                                                                                                               // VkBool32                                                                     alphaToCoverageEnable;
+               VK_FALSE,                                                                                                               // VkBool32                                                                     alphaToOneEnable;
+       };
+
+       return multisampleStateInfo;
+}
+
+const VkDescriptorSetLayout* MSInstanceBaseResolveAndPerSampleFetch::createMSPassDescSetLayout(const ImageMSParams& imageMSParams)
+{
+       DE_UNREF(imageMSParams);
+
+       return DE_NULL;
+}
+
+const VkDescriptorSet* MSInstanceBaseResolveAndPerSampleFetch::createMSPassDescSet(const ImageMSParams& imageMSParams, const VkDescriptorSetLayout* descSetLayout)
+{
+       DE_UNREF(imageMSParams);
+       DE_UNREF(descSetLayout);
+
+       return DE_NULL;
+}
+
+tcu::TestStatus MSInstanceBaseResolveAndPerSampleFetch::iterate (void)
+{
+       const InstanceInterface&        instance                        = m_context.getInstanceInterface();
+       const DeviceInterface&          deviceInterface         = m_context.getDeviceInterface();
+       const VkDevice                          device                          = m_context.getDevice();
+       const VkPhysicalDevice          physicalDevice          = m_context.getPhysicalDevice();
+       Allocator&                                      allocator                       = m_context.getDefaultAllocator();
+       const VkQueue                           queue                           = m_context.getUniversalQueue();
+       const deUint32                          queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
+
+       VkImageCreateInfo                       imageMSInfo;
+       VkImageCreateInfo                       imageRSInfo;
+       const deUint32                          firstSubpassAttachmentsCount = 2u;
+
+       // Check if image size does not exceed device limits
+       validateImageSize(instance, physicalDevice, m_imageType, m_imageMSParams.imageSize);
+
+       // Check if device supports image format as color attachment
+       validateImageFeatureFlags(instance, physicalDevice, mapTextureFormat(m_imageFormat), VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);
+
+       imageMSInfo.sType                                       = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+       imageMSInfo.pNext                                       = DE_NULL;
+       imageMSInfo.flags                                       = 0u;
+       imageMSInfo.imageType                           = mapImageType(m_imageType);
+       imageMSInfo.format                                      = mapTextureFormat(m_imageFormat);
+       imageMSInfo.extent                                      = makeExtent3D(getLayerSize(m_imageType, m_imageMSParams.imageSize));
+       imageMSInfo.arrayLayers                         = getNumLayers(m_imageType, m_imageMSParams.imageSize);
+       imageMSInfo.mipLevels                           = 1u;
+       imageMSInfo.samples                                     = m_imageMSParams.numSamples;
+       imageMSInfo.tiling                                      = VK_IMAGE_TILING_OPTIMAL;
+       imageMSInfo.initialLayout                       = VK_IMAGE_LAYOUT_UNDEFINED;
+       imageMSInfo.usage                                       = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
+       imageMSInfo.sharingMode                         = VK_SHARING_MODE_EXCLUSIVE;
+       imageMSInfo.queueFamilyIndexCount       = 0u;
+       imageMSInfo.pQueueFamilyIndices         = DE_NULL;
+
+       if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY)
+       {
+               imageMSInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
+       }
+
+       validateImageInfo(instance, physicalDevice, imageMSInfo);
+
+       const de::UniquePtr<Image> imageMS(new Image(deviceInterface, device, allocator, imageMSInfo, MemoryRequirement::Any));
+
+       imageRSInfo                     = imageMSInfo;
+       imageRSInfo.samples     = VK_SAMPLE_COUNT_1_BIT;
+       imageRSInfo.usage       = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+
+       validateImageInfo(instance, physicalDevice, imageRSInfo);
+
+       const de::UniquePtr<Image> imageRS(new Image(deviceInterface, device, allocator, imageRSInfo, MemoryRequirement::Any));
+
+       const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
+
+       std::vector<de::SharedPtr<Image> > imagesPerSampleVec(numSamples);
+
+       for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
+       {
+               imagesPerSampleVec[sampleNdx] = de::SharedPtr<Image>(new Image(deviceInterface, device, allocator, imageRSInfo, MemoryRequirement::Any));
+       }
+
+       // Create render pass
+       std::vector<VkAttachmentDescription> attachments(firstSubpassAttachmentsCount + numSamples);
+
+       {
+               const VkAttachmentDescription attachmentMSDesc =
+               {
+                       (VkAttachmentDescriptionFlags)0u,                       // VkAttachmentDescriptionFlags         flags;
+                       imageMSInfo.format,                                                     // VkFormat                                                     format;
+                       imageMSInfo.samples,                                            // 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_SHADER_READ_ONLY_OPTIMAL        // VkImageLayout                                        finalLayout;
+               };
+
+               attachments[0] = attachmentMSDesc;
+
+               const VkAttachmentDescription attachmentRSDesc =
+               {
+                       (VkAttachmentDescriptionFlags)0u,                       // VkAttachmentDescriptionFlags         flags;
+                       imageRSInfo.format,                                                     // VkFormat                                                     format;
+                       imageRSInfo.samples,                                            // 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;
+               };
+
+               attachments[1] = attachmentRSDesc;
+
+               for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
+               {
+                       attachments[firstSubpassAttachmentsCount + sampleNdx] = attachmentRSDesc;
+               }
+       }
+
+       const VkAttachmentReference attachmentMSColorRef =
+       {
+               0u,                                                                                     // deUint32                     attachment;
+               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout        layout;
+       };
+
+       const VkAttachmentReference attachmentMSInputRef =
+       {
+               0u,                                                                                     // deUint32                     attachment;
+               VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL        // VkImageLayout        layout;
+       };
+
+       const VkAttachmentReference attachmentRSColorRef =
+       {
+               1u,                                                                                     // deUint32                     attachment;
+               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout        layout;
+       };
+
+       std::vector<VkAttachmentReference> perSampleAttachmentRef(numSamples);
+
+       for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
+       {
+               const VkAttachmentReference attachmentRef =
+               {
+                       firstSubpassAttachmentsCount + sampleNdx,       // deUint32                     attachment;
+                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout        layout;
+               };
+
+               perSampleAttachmentRef[sampleNdx] = attachmentRef;
+       }
+
+       std::vector<deUint32> preserveAttachments(1u + numSamples);
+
+       for (deUint32 attachNdx = 0u; attachNdx < 1u + numSamples; ++attachNdx)
+       {
+               preserveAttachments[attachNdx] = 1u + attachNdx;
+       }
+
+       std::vector<VkSubpassDescription> subpasses(1u + numSamples);
+       std::vector<VkSubpassDependency>  subpassDependencies(numSamples);
+
+       const VkSubpassDescription firstSubpassDesc =
+       {
+               (VkSubpassDescriptionFlags)0u,          // VkSubpassDescriptionFlags            flags;
+               VK_PIPELINE_BIND_POINT_GRAPHICS,        // VkPipelineBindPoint                          pipelineBindPoint;
+               0u,                                                                     // deUint32                                                     inputAttachmentCount;
+               DE_NULL,                                                        // const VkAttachmentReference*         pInputAttachments;
+               1u,                                                                     // deUint32                                                     colorAttachmentCount;
+               &attachmentMSColorRef,                          // const VkAttachmentReference*         pColorAttachments;
+               &attachmentRSColorRef,                          // const VkAttachmentReference*         pResolveAttachments;
+               DE_NULL,                                                        // const VkAttachmentReference*         pDepthStencilAttachment;
+               0u,                                                                     // deUint32                                                     preserveAttachmentCount;
+               DE_NULL                                                         // const deUint32*                                      pPreserveAttachments;
+       };
+
+       subpasses[0] = firstSubpassDesc;
+
+       for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
+       {
+               const VkSubpassDescription subpassDesc =
+               {
+                       (VkSubpassDescriptionFlags)0u,                  // VkSubpassDescriptionFlags            flags;
+                       VK_PIPELINE_BIND_POINT_GRAPHICS,                // VkPipelineBindPoint                          pipelineBindPoint;
+                       1u,                                                                             // deUint32                                                     inputAttachmentCount;
+                       &attachmentMSInputRef,                                  // const VkAttachmentReference*         pInputAttachments;
+                       1u,                                                                             // deUint32                                                     colorAttachmentCount;
+                       &perSampleAttachmentRef[sampleNdx],             // const VkAttachmentReference*         pColorAttachments;
+                       DE_NULL,                                                                // const VkAttachmentReference*         pResolveAttachments;
+                       DE_NULL,                                                                // const VkAttachmentReference*         pDepthStencilAttachment;
+                       1u + sampleNdx,                                                 // deUint32                                                     preserveAttachmentCount;
+                       dataPointer(preserveAttachments)                // const deUint32*                                      pPreserveAttachments;
+               };
+
+               subpasses[1u + sampleNdx] = subpassDesc;
+
+               const VkSubpassDependency subpassDependency =
+               {
+                       0u,                                                                                             // uint32_t                srcSubpass;
+                       1u + sampleNdx,                                                                 // uint32_t                dstSubpass;
+                       VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_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[sampleNdx] = subpassDependency;
+       }
+
+       const VkRenderPassCreateInfo renderPassInfo =
+       {
+               VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                      // VkStructureType                                      sType;
+               DE_NULL,                                                                                        // const void*                                          pNext;
+               (VkRenderPassCreateFlags)0u,                                            // VkRenderPassCreateFlags                      flags;
+               static_cast<deUint32>(attachments.size()),                      // deUint32                                                     attachmentCount;
+               dataPointer(attachments),                                                       // const VkAttachmentDescription*       pAttachments;
+               static_cast<deUint32>(subpasses.size()),                        // deUint32                                                     subpassCount;
+               dataPointer(subpasses),                                                         // const VkSubpassDescription*          pSubpasses;
+               static_cast<deUint32>(subpassDependencies.size()),      // deUint32                                                     dependencyCount;
+               dataPointer(subpassDependencies)                                        // const VkSubpassDependency*           pDependencies;
+       };
+
+       const Unique<VkRenderPass> renderPass(createRenderPass(deviceInterface, device, &renderPassInfo));
+
+       const VkImageSubresourceRange fullImageRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageMSInfo.mipLevels, 0u, imageMSInfo.arrayLayers);
+
+       // Create color attachments image views
+       typedef de::SharedPtr<Unique<VkImageView> > VkImageViewSp;
+       std::vector<VkImageViewSp>      imageViewsShPtrs(firstSubpassAttachmentsCount + numSamples);
+       std::vector<VkImageView>        imageViews(firstSubpassAttachmentsCount + numSamples);
+
+       imageViewsShPtrs[0] = makeVkSharedPtr(makeImageView(deviceInterface, device, **imageMS, mapImageViewType(m_imageType), imageMSInfo.format, fullImageRange));
+       imageViewsShPtrs[1] = makeVkSharedPtr(makeImageView(deviceInterface, device, **imageRS, mapImageViewType(m_imageType), imageRSInfo.format, fullImageRange));
+
+       imageViews[0] = **imageViewsShPtrs[0];
+       imageViews[1] = **imageViewsShPtrs[1];
+
+       for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
+       {
+               imageViewsShPtrs[firstSubpassAttachmentsCount + sampleNdx] = makeVkSharedPtr(makeImageView(deviceInterface, device, **imagesPerSampleVec[sampleNdx], mapImageViewType(m_imageType), imageRSInfo.format, fullImageRange));
+               imageViews[firstSubpassAttachmentsCount + sampleNdx] = **imageViewsShPtrs[firstSubpassAttachmentsCount + sampleNdx];
+       }
+
+       // Create framebuffer
+       const VkFramebufferCreateInfo framebufferInfo =
+       {
+               VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,      // VkStructureType                                                         sType;
+               DE_NULL,                                                                        // const void*                                 pNext;
+               (VkFramebufferCreateFlags)0u,                           // VkFramebufferCreateFlags                    flags;
+               *renderPass,                                                            // VkRenderPass                                renderPass;
+               static_cast<deUint32>(imageViews.size()),       // uint32_t                                    attachmentCount;
+               dataPointer(imageViews),                                        // const VkImageView*                          pAttachments;
+               imageMSInfo.extent.width,                                       // uint32_t                                    width;
+               imageMSInfo.extent.height,                                      // uint32_t                                    height;
+               imageMSInfo.arrayLayers,                                        // uint32_t                                    layers;
+       };
+
+       const Unique<VkFramebuffer> framebuffer(createFramebuffer(deviceInterface, device, &framebufferInfo));
+
+       const VkDescriptorSetLayout* descriptorSetLayoutMSPass = createMSPassDescSetLayout(m_imageMSParams);
+
+       // Create pipeline layout
+       const VkPipelineLayoutCreateInfo pipelineLayoutMSPassParams =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,  // VkStructureType                                      sType;
+               DE_NULL,                                                                                // const void*                                          pNext;
+               (VkPipelineLayoutCreateFlags)0u,                                // VkPipelineLayoutCreateFlags          flags;
+               descriptorSetLayoutMSPass ? 1u : 0u,                    // deUint32                                                     setLayoutCount;
+               descriptorSetLayoutMSPass,                                              // const VkDescriptorSetLayout*         pSetLayouts;
+               0u,                                                                                             // deUint32                                                     pushConstantRangeCount;
+               DE_NULL,                                                                                // const VkPushConstantRange*           pPushConstantRanges;
+       };
+
+       const Unique<VkPipelineLayout> pipelineLayoutMSPass(createPipelineLayout(deviceInterface, device, &pipelineLayoutMSPassParams));
+
+       // Create vertex attributes data
+       const VertexDataDesc vertexDataDesc = getVertexDataDescripton();
+
+       de::SharedPtr<Buffer> vertexBuffer = de::SharedPtr<Buffer>(new Buffer(deviceInterface, device, allocator, makeBufferCreateInfo(vertexDataDesc.dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
+       const Allocation& vertexBufferAllocation = vertexBuffer->getAllocation();
+
+       uploadVertexData(vertexBufferAllocation, vertexDataDesc);
+
+       flushMappedMemoryRange(deviceInterface, device, vertexBufferAllocation.getMemory(), vertexBufferAllocation.getOffset(), VK_WHOLE_SIZE);
+
+       const VkVertexInputBindingDescription vertexBinding =
+       {
+               0u,                                                     // deUint32                             binding;
+               vertexDataDesc.dataStride,      // deUint32                             stride;
+               VK_VERTEX_INPUT_RATE_VERTEX     // VkVertexInputRate    inputRate;
+       };
+
+       const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,                      // VkStructureType                             sType;
+               DE_NULL,                                                                                                                        // const void*                                 pNext;
+               (VkPipelineVertexInputStateCreateFlags)0u,                                                      // VkPipelineVertexInputStateCreateFlags       flags;
+               1u,                                                                                                                                     // uint32_t                                    vertexBindingDescriptionCount;
+               &vertexBinding,                                                                                                         // const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
+               static_cast<deUint32>(vertexDataDesc.vertexAttribDescVec.size()),       // uint32_t                                    vertexAttributeDescriptionCount;
+               dataPointer(vertexDataDesc.vertexAttribDescVec),                                        // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
+       };
+
+       const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                             sType;
+               DE_NULL,                                                                                                                // const void*                                 pNext;
+               (VkPipelineInputAssemblyStateCreateFlags)0u,                                    // VkPipelineInputAssemblyStateCreateFlags     flags;
+               vertexDataDesc.primitiveTopology,                                                               // VkPrimitiveTopology                         topology;
+               VK_FALSE,                                                                                                               // VkBool32                                    primitiveRestartEnable;
+       };
+
+       const VkViewport viewport =
+       {
+               0.0f, 0.0f,
+               static_cast<float>(imageMSInfo.extent.width), static_cast<float>(imageMSInfo.extent.height),
+               0.0f, 1.0f
+       };
+
+       const VkRect2D scissor =
+       {
+               makeOffset2D(0, 0),
+               makeExtent2D(imageMSInfo.extent.width, imageMSInfo.extent.height),
+       };
+
+       const VkPipelineViewportStateCreateInfo viewportStateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,                  // VkStructureType                             sType;
+               DE_NULL,                                                                                                                // const void*                                 pNext;
+               (VkPipelineViewportStateCreateFlags)0u,                                                 // VkPipelineViewportStateCreateFlags          flags;
+               1u,                                                                                                                             // uint32_t                                    viewportCount;
+               &viewport,                                                                                                              // const VkViewport*                           pViewports;
+               1u,                                                                                                                             // uint32_t                                    scissorCount;
+               &scissor,                                                                                                               // const VkRect2D*                             pScissors;
+       };
+
+       const VkPipelineRasterizationStateCreateInfo rasterizationStateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                          sType;
+               DE_NULL,                                                                                                                // const void*                              pNext;
+               (VkPipelineRasterizationStateCreateFlags)0u,                                    // VkPipelineRasterizationStateCreateFlags  flags;
+               VK_FALSE,                                                                                                               // VkBool32                                 depthClampEnable;
+               VK_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 VkPipelineMultisampleStateCreateInfo multisampleStateInfo = getMSStateCreateInfo(m_imageMSParams);
+
+       const VkStencilOpState stencilOpState = makeStencilOpState
+       (
+               VK_STENCIL_OP_KEEP,             // stencil fail
+               VK_STENCIL_OP_KEEP,             // depth & stencil pass
+               VK_STENCIL_OP_KEEP,             // depth only fail
+               VK_COMPARE_OP_ALWAYS,   // compare op
+               0u,                                             // compare mask
+               0u,                                             // write mask
+               0u                                              // reference
+       );
+
+       const VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,             // VkStructureType                                                      sType;
+               DE_NULL,                                                                                                                // const void*                                                          pNext;
+               (VkPipelineDepthStencilStateCreateFlags)0u,                                             // VkPipelineDepthStencilStateCreateFlags       flags;
+               VK_FALSE,                                                                                                               // VkBool32                                                                     depthTestEnable;
+               VK_FALSE,                                                                                                               // VkBool32                                                                     depthWriteEnable;
+               VK_COMPARE_OP_LESS,                                                                                             // VkCompareOp                                                          depthCompareOp;
+               VK_FALSE,                                                                                                               // VkBool32                                                                     depthBoundsTestEnable;
+               VK_FALSE,                                                                                                               // VkBool32                                                                     stencilTestEnable;
+               stencilOpState,                                                                                                 // VkStencilOpState                                                     front;
+               stencilOpState,                                                                                                 // VkStencilOpState                                                     back;
+               0.0f,                                                                                                                   // float                                                                        minDepthBounds;
+               1.0f,                                                                                                                   // float                                                                        maxDepthBounds;
+       };
+
+       const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
+
+       const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
+       {
+               VK_FALSE,                                                                                                               // VkBool32                                     blendEnable;
+               VK_BLEND_FACTOR_ONE,                                                                                    // VkBlendFactor                        srcColorBlendFactor;
+               VK_BLEND_FACTOR_ZERO,                                                                                   // VkBlendFactor                        dstColorBlendFactor;
+               VK_BLEND_OP_ADD,                                                                                                // VkBlendOp                            colorBlendOp;
+               VK_BLEND_FACTOR_ONE,                                                                                    // VkBlendFactor                        srcAlphaBlendFactor;
+               VK_BLEND_FACTOR_ZERO,                                                                                   // VkBlendFactor                        dstAlphaBlendFactor;
+               VK_BLEND_OP_ADD,                                                                                                // VkBlendOp                            alphaBlendOp;
+               colorComponentsAll,                                                                                             // VkColorComponentFlags        colorWriteMask;
+       };
+
+       const VkPipelineColorBlendStateCreateInfo colorBlendStateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,               // VkStructureType                                                              sType;
+               DE_NULL,                                                                                                                // const void*                                                                  pNext;
+               (VkPipelineColorBlendStateCreateFlags)0u,                                               // VkPipelineColorBlendStateCreateFlags                 flags;
+               VK_FALSE,                                                                                                               // VkBool32                                                                             logicOpEnable;
+               VK_LOGIC_OP_COPY,                                                                                               // VkLogicOp                                                                    logicOp;
+               1u,                                                                                                                             // deUint32                                                                             attachmentCount;
+               &colorBlendAttachmentState,                                                                             // const VkPipelineColorBlendAttachmentState*   pAttachments;
+               { 0.0f, 0.0f, 0.0f, 0.0f },                                                                             // float                                                                                blendConstants[4];
+       };
+
+       // Create graphics pipeline for multisample pass
+       const Unique<VkShaderModule> vsMSPassModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("vertex_shader"), (VkShaderModuleCreateFlags)0u));
+
+       const VkPipelineShaderStageCreateInfo vsMSPassShaderStageInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,                    // VkStructureType                                              sType;
+               DE_NULL,                                                                                                                // const void*                                                  pNext;
+               (VkPipelineShaderStageCreateFlags)0u,                                                   // VkPipelineShaderStageCreateFlags             flags;
+               VK_SHADER_STAGE_VERTEX_BIT,                                                                             // VkShaderStageFlagBits                                stage;
+               *vsMSPassModule,                                                                                                // VkShaderModule                                               module;
+               "main",                                                                                                                 // const char*                                                  pName;
+               DE_NULL,                                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
+       };
+
+       const Unique<VkShaderModule> fsMSPassModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("fragment_shader"), (VkShaderModuleCreateFlags)0u));
+
+       const VkPipelineShaderStageCreateInfo fsMSPassShaderStageInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,                    // VkStructureType                                              sType;
+               DE_NULL,                                                                                                                // const void*                                                  pNext;
+               (VkPipelineShaderStageCreateFlags)0u,                                                   // VkPipelineShaderStageCreateFlags             flags;
+               VK_SHADER_STAGE_FRAGMENT_BIT,                                                                   // VkShaderStageFlagBits                                stage;
+               *fsMSPassModule,                                                                                                // VkShaderModule                                               module;
+               "main",                                                                                                                 // const char*                                                  pName;
+               DE_NULL,                                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
+       };
+
+       const VkPipelineShaderStageCreateInfo shaderStageInfosMSPass[] = { vsMSPassShaderStageInfo, fsMSPassShaderStageInfo };
+
+       const VkGraphicsPipelineCreateInfo graphicsPipelineInfoMSPass =
+       {
+               VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,                                // VkStructureType                                                                      sType;
+               DE_NULL,                                                                                                                // const void*                                                                          pNext;
+               (VkPipelineCreateFlags)0u,                                                                              // VkPipelineCreateFlags                                                        flags;
+               2u,                                                                                                                             // deUint32                                                                                     stageCount;
+               shaderStageInfosMSPass,                                                                                 // const VkPipelineShaderStageCreateInfo*                       pStages;
+               &vertexInputStateInfo,                                                                                  // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
+               &inputAssemblyStateInfo,                                                                                // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
+               DE_NULL,                                                                                                                // const VkPipelineTessellationStateCreateInfo*         pTessellationState;
+               &viewportStateInfo,                                                                                             // const VkPipelineViewportStateCreateInfo*                     pViewportState;
+               &rasterizationStateInfo,                                                                                // const VkPipelineRasterizationStateCreateInfo*        pRasterizationState;
+               &multisampleStateInfo,                                                                                  // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
+               &depthStencilStateInfo,                                                                                 // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
+               &colorBlendStateInfo,                                                                                   // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
+               DE_NULL,                                                                                                                // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
+               *pipelineLayoutMSPass,                                                                                  // VkPipelineLayout                                                                     layout;
+               *renderPass,                                                                                                    // VkRenderPass                                                                         renderPass;
+               0u,                                                                                                                             // deUint32                                                                                     subpass;
+               DE_NULL,                                                                                                                // VkPipeline                                                                           basePipelineHandle;
+               0u,                                                                                                                             // deInt32                                                                                      basePipelineIndex;
+       };
+
+       const Unique<VkPipeline> graphicsPipelineMSPass(createGraphicsPipeline(deviceInterface, device, DE_NULL, &graphicsPipelineInfoMSPass));
+
+       typedef de::SharedPtr<Unique<VkPipeline> > VkPipelineSp;
+       std::vector<VkPipelineSp> graphicsPipelinesPerSampleFetch(numSamples);
+
+       // Create descriptor set layout
+       const Unique<VkDescriptorSetLayout> descriptorSetLayout(
+               DescriptorSetLayoutBuilder()
+               .addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT)
+               .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, VK_SHADER_STAGE_FRAGMENT_BIT)
+               .build(deviceInterface, device));
+
+       const Unique<VkPipelineLayout> pipelineLayoutPerSampleFetchPass(makePipelineLayout(deviceInterface, device, *descriptorSetLayout));
+
+       const deUint32 bufferPerSampleFetchPassSize = 4u * (deUint32)sizeof(tcu::Vec4);
+
+       de::SharedPtr<Buffer> vertexBufferPerSampleFetchPass = de::SharedPtr<Buffer>(new Buffer(deviceInterface, device, allocator, makeBufferCreateInfo(bufferPerSampleFetchPassSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
+
+       // Create graphics pipelines for per sample texel fetch passes
+       {
+               const Unique<VkShaderModule> vsPerSampleFetchPassModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("per_sample_fetch_vs"), (VkShaderModuleCreateFlags)0u));
+
+               const VkPipelineShaderStageCreateInfo vsPerSampleFetchPassShaderStageInfo =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,                    // VkStructureType                                              sType;
+                       DE_NULL,                                                                                                                // const void*                                                  pNext;
+                       (VkPipelineShaderStageCreateFlags)0u,                                                   // VkPipelineShaderStageCreateFlags             flags;
+                       VK_SHADER_STAGE_VERTEX_BIT,                                                                             // VkShaderStageFlagBits                                stage;
+                       *vsPerSampleFetchPassModule,                                                                    // VkShaderModule                                               module;
+                       "main",                                                                                                                 // const char*                                                  pName;
+                       DE_NULL,                                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
+               };
+
+               const Unique<VkShaderModule> fsPerSampleFetchPassModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("per_sample_fetch_fs"), (VkShaderModuleCreateFlags)0u));
+
+               const VkPipelineShaderStageCreateInfo fsPerSampleFetchPassShaderStageInfo =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,                    // VkStructureType                                              sType;
+                       DE_NULL,                                                                                                                // const void*                                                  pNext;
+                       (VkPipelineShaderStageCreateFlags)0u,                                                   // VkPipelineShaderStageCreateFlags             flags;
+                       VK_SHADER_STAGE_FRAGMENT_BIT,                                                                   // VkShaderStageFlagBits                                stage;
+                       *fsPerSampleFetchPassModule,                                                                    // VkShaderModule                                               module;
+                       "main",                                                                                                                 // const char*                                                  pName;
+                       DE_NULL,                                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
+               };
+
+               const VkPipelineShaderStageCreateInfo shaderStageInfosPerSampleFetchPass[] = { vsPerSampleFetchPassShaderStageInfo, fsPerSampleFetchPassShaderStageInfo };
+
+               std::vector<tcu::Vec4> vertices;
+
+               vertices.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
+               vertices.push_back(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f));
+               vertices.push_back(tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f));
+               vertices.push_back(tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f));
+
+               const Allocation& vertexAllocPerSampleFetchPass = vertexBufferPerSampleFetchPass->getAllocation();
+
+               deMemcpy(vertexAllocPerSampleFetchPass.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(bufferPerSampleFetchPassSize));
+
+               flushMappedMemoryRange(deviceInterface, device, vertexAllocPerSampleFetchPass.getMemory(), vertexAllocPerSampleFetchPass.getOffset(), VK_WHOLE_SIZE);
+
+               const VkVertexInputBindingDescription vertexBindingPerSampleFetchPass =
+               {
+                       0u,                                                     // deUint32                             binding;
+                       sizeof(tcu::Vec4),                      // deUint32                             stride;
+                       VK_VERTEX_INPUT_RATE_VERTEX     // VkVertexInputRate    inputRate;
+               };
+
+               const VkVertexInputAttributeDescription vertexAttribPositionNdc =
+               {
+                       0u,                                                                                     // deUint32     location;
+                       0u,                                                                                     // deUint32     binding;
+                       VK_FORMAT_R32G32B32A32_SFLOAT,                          // VkFormat     format;
+                       0u,                                                                                     // deUint32     offset;
+               };
+
+               const VkPipelineVertexInputStateCreateInfo vertexInputStatePerSampleFetchPass =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,                      // VkStructureType                             sType;
+                       DE_NULL,                                                                                                                        // const void*                                 pNext;
+                       (VkPipelineVertexInputStateCreateFlags)0u,                                                      // VkPipelineVertexInputStateCreateFlags       flags;
+                       1u,                                                                                                                                     // uint32_t                                    vertexBindingDescriptionCount;
+                       &vertexBindingPerSampleFetchPass,                                                                       // const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
+                       1u,                                                                                                                                     // uint32_t                                    vertexAttributeDescriptionCount;
+                       &vertexAttribPositionNdc,                                                                                       // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
+               };
+
+               const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStatePerSampleFetchPass =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                             sType;
+                       DE_NULL,                                                                                                                // const void*                                 pNext;
+                       (VkPipelineInputAssemblyStateCreateFlags)0u,                                    // VkPipelineInputAssemblyStateCreateFlags     flags;
+                       VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,                                                           // VkPrimitiveTopology                         topology;
+                       VK_FALSE,                                                                                                               // VkBool32                                    primitiveRestartEnable;
+               };
+
+               const VkPipelineMultisampleStateCreateInfo multisampleStatePerSampleFetchPass =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,               // VkStructureType                                                      sType;
+                       DE_NULL,                                                                                                                // const void*                                                          pNext;
+                       (VkPipelineMultisampleStateCreateFlags)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;
+               };
+
+               for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
+               {
+                       const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
+                       {
+                               VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,                                // VkStructureType                                                                      sType;
+                               DE_NULL,                                                                                                                // const void*                                                                          pNext;
+                               (VkPipelineCreateFlags)0u,                                                                              // VkPipelineCreateFlags                                                        flags;
+                               2u,                                                                                                                             // deUint32                                                                                     stageCount;
+                               shaderStageInfosPerSampleFetchPass,                                                             // const VkPipelineShaderStageCreateInfo*                       pStages;
+                               &vertexInputStatePerSampleFetchPass,                                                    // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
+                               &inputAssemblyStatePerSampleFetchPass,                                                  // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
+                               DE_NULL,                                                                                                                // const VkPipelineTessellationStateCreateInfo*         pTessellationState;
+                               &viewportStateInfo,                                                                                             // const VkPipelineViewportStateCreateInfo*                     pViewportState;
+                               &rasterizationStateInfo,                                                                                // const VkPipelineRasterizationStateCreateInfo*        pRasterizationState;
+                               &multisampleStatePerSampleFetchPass,                                                    // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
+                               &depthStencilStateInfo,                                                                                 // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
+                               &colorBlendStateInfo,                                                                                   // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
+                               DE_NULL,                                                                                                                // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
+                               *pipelineLayoutPerSampleFetchPass,                                                              // VkPipelineLayout                                                                     layout;
+                               *renderPass,                                                                                                    // VkRenderPass                                                                         renderPass;
+                               1u + sampleNdx,                                                                                                 // deUint32                                                                                     subpass;
+                               DE_NULL,                                                                                                                // VkPipeline                                                                           basePipelineHandle;
+                               0u,                                                                                                                             // deInt32                                                                                      basePipelineIndex;
+                       };
+
+                       graphicsPipelinesPerSampleFetch[sampleNdx] = makeVkSharedPtr(createGraphicsPipeline(deviceInterface, device, DE_NULL, &graphicsPipelineInfo));
+               }
+       }
+
+       // Create descriptor pool
+       const Unique<VkDescriptorPool> descriptorPool(
+               DescriptorPoolBuilder()
+               .addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u)
+               .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1u)
+               .build(deviceInterface, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
+
+       // Create descriptor set
+       const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(deviceInterface, device, *descriptorPool, *descriptorSetLayout));
+
+       const VkPhysicalDeviceLimits deviceLimits = getPhysicalDeviceProperties(instance, physicalDevice).limits;
+
+       VkDeviceSize uboOffsetAlignment = sizeof(deInt32) < deviceLimits.minUniformBufferOffsetAlignment ? deviceLimits.minUniformBufferOffsetAlignment : sizeof(deInt32);
+
+       uboOffsetAlignment += (deviceLimits.minUniformBufferOffsetAlignment - uboOffsetAlignment % deviceLimits.minUniformBufferOffsetAlignment) % deviceLimits.minUniformBufferOffsetAlignment;
+
+       const VkBufferCreateInfo        bufferSampleIDInfo = makeBufferCreateInfo(uboOffsetAlignment * numSamples, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
+       const de::UniquePtr<Buffer>     bufferSampleID(new Buffer(deviceInterface, device, allocator, bufferSampleIDInfo, MemoryRequirement::HostVisible));
+
+       std::vector<deUint32> sampleIDsOffsets(numSamples);
+
+       {
+               deInt8* sampleIDs = new deInt8[uboOffsetAlignment * numSamples];
+
+               for (deInt32 sampleNdx = 0u; sampleNdx < static_cast<deInt32>(numSamples); ++sampleNdx)
+               {
+                       sampleIDsOffsets[sampleNdx] = static_cast<deUint32>(sampleNdx * uboOffsetAlignment);
+                       deInt8* samplePtr = sampleIDs + sampleIDsOffsets[sampleNdx];
+
+                       deMemcpy(samplePtr, &sampleNdx, sizeof(deInt32));
+               }
+
+               deMemcpy(bufferSampleID->getAllocation().getHostPtr(), sampleIDs, static_cast<deUint32>(uboOffsetAlignment * numSamples));
+
+               flushMappedMemoryRange(deviceInterface, device, bufferSampleID->getAllocation().getMemory(), bufferSampleID->getAllocation().getOffset(), VK_WHOLE_SIZE);
+
+               delete[] sampleIDs;
+       }
+
+       {
+               const VkDescriptorImageInfo      descImageInfo  = makeDescriptorImageInfo(DE_NULL, imageViews[0], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+               const VkDescriptorBufferInfo descBufferInfo     = makeDescriptorBufferInfo(**bufferSampleID, 0u, sizeof(deInt32));
+
+               DescriptorSetUpdateBuilder()
+                       .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &descImageInfo)
+                       .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, &descBufferInfo)
+                       .update(deviceInterface, device);
+       }
+
+       // Create command buffer for compute and transfer oparations
+       const Unique<VkCommandPool>       commandPool(makeCommandPool(deviceInterface, device, queueFamilyIndex));
+       const Unique<VkCommandBuffer> commandBuffer(makeCommandBuffer(deviceInterface, device, *commandPool));
+
+       // Start recording commands
+       beginCommandBuffer(deviceInterface, *commandBuffer);
+
+       {
+               std::vector<VkImageMemoryBarrier> imageOutputAttachmentBarriers(firstSubpassAttachmentsCount + numSamples);
+
+               imageOutputAttachmentBarriers[0] = makeImageMemoryBarrier
+               (
+                       0u,
+                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+                       VK_IMAGE_LAYOUT_UNDEFINED,
+                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+                       **imageMS,
+                       fullImageRange
+               );
+
+               imageOutputAttachmentBarriers[1] = makeImageMemoryBarrier
+               (
+                       0u,
+                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+                       VK_IMAGE_LAYOUT_UNDEFINED,
+                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+                       **imageRS,
+                       fullImageRange
+               );
+
+               for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
+               {
+                       imageOutputAttachmentBarriers[firstSubpassAttachmentsCount + sampleNdx] = makeImageMemoryBarrier
+                       (
+                               0u,
+                               VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+                               VK_IMAGE_LAYOUT_UNDEFINED,
+                               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+                               **imagesPerSampleVec[sampleNdx],
+                               fullImageRange
+                       );
+               }
+
+               deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL,
+                       static_cast<deUint32>(imageOutputAttachmentBarriers.size()), dataPointer(imageOutputAttachmentBarriers));
+       }
+
+       {
+               const VkDeviceSize vertexStartOffset = 0u;
+
+               std::vector<VkClearValue> clearValues(firstSubpassAttachmentsCount + numSamples);
+               for (deUint32 attachmentNdx = 0u; attachmentNdx < firstSubpassAttachmentsCount + numSamples; ++attachmentNdx)
+               {
+                       clearValues[attachmentNdx] = makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
+               }
+
+               const vk::VkRect2D renderArea =
+               {
+                       makeOffset2D(0u, 0u),
+                       makeExtent2D(imageMSInfo.extent.width, imageMSInfo.extent.height),
+               };
+
+               // Begin render pass
+               const VkRenderPassBeginInfo renderPassBeginInfo =
+               {
+                       VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,               // VkStructureType         sType;
+                       DE_NULL,                                                                                // const void*             pNext;
+                       *renderPass,                                                                    // VkRenderPass            renderPass;
+                       *framebuffer,                                                                   // VkFramebuffer           framebuffer;
+                       renderArea,                                                                             // VkRect2D                renderArea;
+                       static_cast<deUint32>(clearValues.size()),              // deUint32                clearValueCount;
+                       dataPointer(clearValues),                                               // const VkClearValue*     pClearValues;
+               };
+
+               deviceInterface.cmdBeginRenderPass(*commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+               // Bind graphics pipeline
+               deviceInterface.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelineMSPass);
+
+               const VkDescriptorSet* descriptorSetMSPass = createMSPassDescSet(m_imageMSParams, descriptorSetLayoutMSPass);
+
+               if (descriptorSetMSPass)
+               {
+                       // Bind descriptor set
+                       deviceInterface.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayoutMSPass, 0u, 1u, descriptorSetMSPass, 0u, DE_NULL);
+               }
+
+               // Bind vertex buffer
+               deviceInterface.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBuffer->get(), &vertexStartOffset);
+
+               // Perform a draw
+               deviceInterface.cmdDraw(*commandBuffer, vertexDataDesc.verticesCount, 1u, 0u, 0u);
+
+               // Change imageMS layout for input attachment compatibility
+               const VkImageMemoryBarrier imageMSInputAttachmentBarrier = makeImageMemoryBarrier
+               (
+                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+                       VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
+                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+                       VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+                       **imageMS,
+                       fullImageRange
+               );
+
+               deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageMSInputAttachmentBarrier);
+
+               for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
+               {
+                       deviceInterface.cmdNextSubpass(*commandBuffer, VK_SUBPASS_CONTENTS_INLINE);
+
+                       // Bind graphics pipeline
+                       deviceInterface.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **graphicsPipelinesPerSampleFetch[sampleNdx]);
+
+                       // Bind descriptor set
+                       deviceInterface.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayoutPerSampleFetchPass, 0u, 1u, &descriptorSet.get(), 1u, &sampleIDsOffsets[sampleNdx]);
+
+                       // Bind vertex buffer
+                       deviceInterface.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBufferPerSampleFetchPass->get(), &vertexStartOffset);
+
+                       // Perform a draw
+                       deviceInterface.cmdDraw(*commandBuffer, 4u, 1u, 0u, 0u);
+               }
+
+               // End render pass
+               deviceInterface.cmdEndRenderPass(*commandBuffer);
+       }
+
+       {
+               const VkImageMemoryBarrier imageRSTransferBarrier = makeImageMemoryBarrier
+               (
+                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+                       VK_ACCESS_TRANSFER_READ_BIT,
+                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+                       VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+                       **imageRS,
+                       fullImageRange
+               );
+
+               deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageRSTransferBarrier);
+       }
+
+       // Copy data from imageRS to buffer
+       const deUint32                          imageRSSizeInBytes = getImageSizeInBytes(imageRSInfo.extent, imageRSInfo.arrayLayers, m_imageFormat, imageRSInfo.mipLevels, 1u);
+
+       const VkBufferCreateInfo        bufferRSInfo = makeBufferCreateInfo(imageRSSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+       const de::UniquePtr<Buffer>     bufferRS(new Buffer(deviceInterface, device, allocator, bufferRSInfo, MemoryRequirement::HostVisible));
+
+       {
+               const VkBufferImageCopy bufferImageCopy =
+               {
+                       0u,                                                                                                                                                                             //      VkDeviceSize                            bufferOffset;
+                       0u,                                                                                                                                                                             //      deUint32                                        bufferRowLength;
+                       0u,                                                                                                                                                                             //      deUint32                                        bufferImageHeight;
+                       makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageRSInfo.arrayLayers), //      VkImageSubresourceLayers        imageSubresource;
+                       makeOffset3D(0, 0, 0),                                                                                                                                  //      VkOffset3D                                      imageOffset;
+                       imageRSInfo.extent,                                                                                                                                             //      VkExtent3D                                      imageExtent;
+               };
+
+               deviceInterface.cmdCopyImageToBuffer(*commandBuffer, **imageRS, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, bufferRS->get(), 1u, &bufferImageCopy);
+       }
+
+       {
+               const VkBufferMemoryBarrier bufferRSHostReadBarrier = makeBufferMemoryBarrier
+               (
+                       VK_ACCESS_TRANSFER_WRITE_BIT,
+                       VK_ACCESS_HOST_READ_BIT,
+                       bufferRS->get(),
+                       0u,
+                       imageRSSizeInBytes
+               );
+
+               deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferRSHostReadBarrier, 0u, DE_NULL);
+       }
+
+       // Copy data from per sample images to buffers
+       std::vector<VkImageMemoryBarrier> imagesPerSampleTransferBarriers(numSamples);
+
+       for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
+       {
+               imagesPerSampleTransferBarriers[sampleNdx] = makeImageMemoryBarrier
+               (
+                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+                       VK_ACCESS_TRANSFER_READ_BIT,
+                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+                       VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+                       **imagesPerSampleVec[sampleNdx],
+                       fullImageRange
+               );
+       }
+
+       deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL,
+               static_cast<deUint32>(imagesPerSampleTransferBarriers.size()), dataPointer(imagesPerSampleTransferBarriers));
+
+       std::vector<de::SharedPtr<Buffer> > buffersPerSample(numSamples);
+
+       for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
+       {
+               buffersPerSample[sampleNdx] = de::SharedPtr<Buffer>(new Buffer(deviceInterface, device, allocator, bufferRSInfo, MemoryRequirement::HostVisible));
+
+               const VkBufferImageCopy bufferImageCopy =
+               {
+                       0u,                                                                                                                                                                             //      VkDeviceSize                            bufferOffset;
+                       0u,                                                                                                                                                                             //      deUint32                                        bufferRowLength;
+                       0u,                                                                                                                                                                             //      deUint32                                        bufferImageHeight;
+                       makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageRSInfo.arrayLayers), //      VkImageSubresourceLayers        imageSubresource;
+                       makeOffset3D(0, 0, 0),                                                                                                                                  //      VkOffset3D                                      imageOffset;
+                       imageRSInfo.extent,                                                                                                                                             //      VkExtent3D                                      imageExtent;
+               };
+
+               deviceInterface.cmdCopyImageToBuffer(*commandBuffer, **imagesPerSampleVec[sampleNdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **buffersPerSample[sampleNdx], 1u, &bufferImageCopy);
+       }
+
+       std::vector<VkBufferMemoryBarrier> buffersPerSampleHostReadBarriers(numSamples);
+
+       for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
+       {
+               buffersPerSampleHostReadBarriers[sampleNdx] = makeBufferMemoryBarrier
+               (
+                       VK_ACCESS_TRANSFER_WRITE_BIT,
+                       VK_ACCESS_HOST_READ_BIT,
+                       **buffersPerSample[sampleNdx],
+                       0u,
+                       imageRSSizeInBytes
+               );
+       }
+
+       deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL,
+               static_cast<deUint32>(buffersPerSampleHostReadBarriers.size()), dataPointer(buffersPerSampleHostReadBarriers), 0u, DE_NULL);
+
+       // End recording commands
+       VK_CHECK(deviceInterface.endCommandBuffer(*commandBuffer));
+
+       // Submit commands for execution and wait for completion
+       submitCommandsAndWait(deviceInterface, device, queue, *commandBuffer);
+
+       // Retrieve data from bufferRS to host memory
+       const Allocation& bufferRSAlloc = bufferRS->getAllocation();
+
+       invalidateMappedMemoryRange(deviceInterface, device, bufferRSAlloc.getMemory(), bufferRSAlloc.getOffset(), VK_WHOLE_SIZE);
+
+       const tcu::ConstPixelBufferAccess bufferRSData (m_imageFormat,
+                                                                                                       imageRSInfo.extent.width,
+                                                                                                       imageRSInfo.extent.height,
+                                                                                                       imageRSInfo.extent.depth * imageRSInfo.arrayLayers,
+                                                                                                       bufferRSAlloc.getHostPtr());
+
+       std::stringstream resolveName;
+       resolveName << "Resolve image " << getImageTypeName(m_imageType) << "_" << bufferRSData.getWidth() << "_" << bufferRSData.getHeight() << "_" << bufferRSData.getDepth() << std::endl;
+
+       m_context.getTestContext().getLog()
+               << tcu::TestLog::Section(resolveName.str(), resolveName.str())
+               << tcu::LogImage("resolve", "", bufferRSData)
+               << tcu::TestLog::EndSection;
+
+       std::vector<tcu::ConstPixelBufferAccess> buffersPerSampleData(numSamples);
+
+       // Retrieve data from per sample buffers to host memory
+       for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
+       {
+               const Allocation& bufferAlloc = buffersPerSample[sampleNdx]->getAllocation();
+
+               invalidateMappedMemoryRange(deviceInterface, device, bufferAlloc.getMemory(), bufferAlloc.getOffset(), VK_WHOLE_SIZE);
+
+               buffersPerSampleData[sampleNdx] = tcu::ConstPixelBufferAccess
+               (
+                       m_imageFormat,
+                       imageRSInfo.extent.width,
+                       imageRSInfo.extent.height,
+                       imageRSInfo.extent.depth * imageRSInfo.arrayLayers,
+                       bufferAlloc.getHostPtr()
+               );
+
+               std::stringstream sampleName;
+               sampleName << "Sample " << sampleNdx << " image" << std::endl;
+
+               m_context.getTestContext().getLog()
+                       << tcu::TestLog::Section(sampleName.str(), sampleName.str())
+                       << tcu::LogImage("sample", "", buffersPerSampleData[sampleNdx])
+                       << tcu::TestLog::EndSection;
+       }
+
+       return verifyImageData(imageMSInfo, imageRSInfo, buffersPerSampleData, bufferRSData);
+}
+
+} // multisample
+} // pipeline
+} // vkt
diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolveAndPerSampleFetch.hpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolveAndPerSampleFetch.hpp
new file mode 100644 (file)
index 0000000..158b80b
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef _VKTPIPELINEMULTISAMPLEBASERESOLVEANDPERSAMPLEFETCH_HPP
+#define _VKTPIPELINEMULTISAMPLEBASERESOLVEANDPERSAMPLEFETCH_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2016 The Khronos Group Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file vktPipelineMultisampleBaseResolveAndPerSampleFetch.hpp
+ * \brief Base class for tests that check results of multisample resolve
+ *               and/or values of individual samples
+ *//*--------------------------------------------------------------------*/
+
+#include "vktPipelineMultisampleBase.hpp"
+#include "vktTestCase.hpp"
+#include "tcuVector.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+namespace multisample
+{
+
+class MSCaseBaseResolveAndPerSampleFetch : public MultisampleCaseBase
+{
+public:
+               MSCaseBaseResolveAndPerSampleFetch      (tcu::TestContext&              testCtx,
+                                                                                        const std::string&             name,
+                                                                                        const ImageMSParams&   imageMSParams)
+               : MultisampleCaseBase(testCtx, name, imageMSParams) {}
+
+       void initPrograms                                               (vk::SourceCollections& programCollection) const;
+};
+
+class MSInstanceBaseResolveAndPerSampleFetch : public MultisampleInstanceBase
+{
+public:
+                                                       MSInstanceBaseResolveAndPerSampleFetch                                  (Context&                                                                                       context,
+                                                                                                                                                                        const ImageMSParams&                                                           imageMSParams)
+                                                       : MultisampleInstanceBase(context, imageMSParams) {}
+
+protected:
+
+       tcu::TestStatus                                                                         iterate                                         (void);
+
+       virtual vk::VkPipelineMultisampleStateCreateInfo        getMSStateCreateInfo            (const ImageMSParams&                                                           imageMSParams) const;
+
+       virtual const vk::VkDescriptorSetLayout*                        createMSPassDescSetLayout       (const ImageMSParams&                                                           imageMSParams);
+
+       virtual const vk::VkDescriptorSet*                                      createMSPassDescSet                     (const ImageMSParams&                                                           imageMSParams,
+                                                                                                                                                                        const vk::VkDescriptorSetLayout*                                       descSetLayout);
+
+       virtual tcu::TestStatus                                                         verifyImageData                         (const vk::VkImageCreateInfo&                                           imageMSInfo,
+                                                                                                                                                                        const vk::VkImageCreateInfo&                                           imageRSInfo,
+                                                                                                                                                                        const std::vector<tcu::ConstPixelBufferAccess>&        dataPerSample,
+                                                                                                                                                                        const tcu::ConstPixelBufferAccess&                                     dataRS) const = 0;
+};
+
+} // multisample
+} // pipeline
+} // vkt
+
+#endif // _VKTPIPELINEMULTISAMPLEBASERESOLVEANDPERSAMPLEFETCH_HPP
index 63a1bb1..7a6174b 100644 (file)
 *//*--------------------------------------------------------------------*/
 
 #include "vktPipelineMultisampleInterpolationTests.hpp"
+#include "vktPipelineMultisampleBaseResolve.hpp"
 #include "vktPipelineMultisampleTestsUtil.hpp"
 #include "vktPipelineMakeUtil.hpp"
 #include "vkQueryUtil.hpp"
-
-#include <set>
+#include <vector>
 
 namespace vkt
 {
@@ -37,745 +37,90 @@ namespace multisample
 
 using namespace vk;
 
-struct ImageMSParams
+struct VertexDataNdc
 {
-       ImageMSParams(const VkSampleCountFlagBits samples, const tcu::UVec3& size) : numSamples(samples), imageSize(size) {}
+       VertexDataNdc (const tcu::Vec4& posNdc) : positionNdc(posNdc) {}
 
-       VkSampleCountFlagBits   numSamples;
-       tcu::UVec3                              imageSize;
+       tcu::Vec4 positionNdc;
 };
 
-class MSInterpolationCaseBase : public TestCase
+struct VertexDataNdcScreen
 {
-public:
-       MSInterpolationCaseBase (tcu::TestContext&              testCtx,
-                                                        const std::string&             name,
-                                                        const ImageMSParams&   imageMSParams)
-               : TestCase(testCtx, name, "")
-               , m_imageMSParams(imageMSParams)
-       {}
-
-protected:
-       const ImageMSParams m_imageMSParams;
-};
+       VertexDataNdcScreen (const tcu::Vec4& posNdc, const tcu::Vec2& posScreen) : positionNdc(posNdc), positionScreen(posScreen) {}
 
-typedef MSInterpolationCaseBase* (*MSInterpolationCaseFuncPtr)(tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams);
+       tcu::Vec4 positionNdc;
+       tcu::Vec2 positionScreen;
+};
 
-class MSInterpolationInstanceBase : public TestInstance
+struct VertexDataNdcBarycentric
 {
-public:
-                                                               MSInterpolationInstanceBase     (Context&                                                       context,
-                                                                                                                        const ImageMSParams&                           imageMSParams)
-               : TestInstance          (context)
-               , m_imageMSParams       (imageMSParams)
-               , m_imageType           (IMAGE_TYPE_2D)
-               , m_imageFormat         (tcu::TextureFormat(tcu::TextureFormat::RG, tcu::TextureFormat::UNORM_INT8))
-       {}
+       VertexDataNdcBarycentric (const tcu::Vec4& posNdc, const tcu::Vec3& barCoord) : positionNdc(posNdc), barycentricCoord(barCoord) {}
 
-       tcu::TestStatus                         iterate                                         (void);
-
-protected:
-
-       typedef std::vector<VkVertexInputAttributeDescription> VertexAttribDescVec;
-
-       struct VertexDataDesc
-       {
-               VkPrimitiveTopology     primitiveTopology;
-               deUint32                        verticesCount;
-               deUint32                        dataStride;
-               VkDeviceSize            dataSize;
-               VertexAttribDescVec     vertexAttribDescVec;
-       };
-
-       void                                            validateImageSize                       (const InstanceInterface&                       instance,
-                                                                                                                        const VkPhysicalDevice                         physicalDevice,
-                                                                                                                        const ImageType                                        imageType,
-                                                                                                                        const tcu::UVec3&                                      imageSize) const;
-
-       void                                            validateImageFeatureFlags       (const InstanceInterface&                       instance,
-                                                                                                                        const VkPhysicalDevice                         physicalDevice,
-                                                                                                                        const VkFormat                                         format,
-                                                                                                                        const VkFormatFeatureFlags                     featureFlags) const;
-
-       void                                            validateImageInfo                       (const InstanceInterface&                       instance,
-                                                                                                                        const VkPhysicalDevice                         physicalDevice,
-                                                                                                                        const VkImageCreateInfo&                       imageInfo) const;
-
-       virtual VertexDataDesc          getVertexDataDescripton         (void) const = 0;
-
-       virtual void                            uploadVertexData                        (const Allocation&                                      vertexBufferAllocation,
-                                                                                                                        const VertexDataDesc&                          vertexDataDescripton) const = 0;
-
-       virtual tcu::TestStatus         verifyResolvedImage                     (const tcu::ConstPixelBufferAccess&     imageData) const = 0;
-protected:
-       const ImageMSParams                     m_imageMSParams;
-       const ImageType                         m_imageType;
-       const tcu::TextureFormat        m_imageFormat;
+       tcu::Vec4 positionNdc;
+       tcu::Vec3 barycentricCoord;
 };
 
-void MSInterpolationInstanceBase::validateImageSize (const InstanceInterface&  instance,
-                                                                                                        const VkPhysicalDevice         physicalDevice,
-                                                                                                        const ImageType                        imageType,
-                                                                                                        const tcu::UVec3&                      imageSize) const
+bool checkForError (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS, const deUint32 errorCompNdx)
 {
-       const VkPhysicalDeviceProperties deviceProperties = getPhysicalDeviceProperties(instance, physicalDevice);
-
-       bool isImageSizeValid = true;
-
-       switch (imageType)
+       for (deUint32 z = 0u; z < imageRSInfo.extent.depth;  ++z)
+       for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
+       for (deUint32 x = 0u; x < imageRSInfo.extent.width;  ++x)
        {
-               case IMAGE_TYPE_1D:
-                       isImageSizeValid =      imageSize.x() <= deviceProperties.limits.maxImageDimension1D;
-                       break;
-               case IMAGE_TYPE_1D_ARRAY:
-                       isImageSizeValid =      imageSize.x() <= deviceProperties.limits.maxImageDimension1D &&
-                                                               imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
-                       break;
-               case IMAGE_TYPE_2D:
-                       isImageSizeValid =      imageSize.x() <= deviceProperties.limits.maxImageDimension2D &&
-                                                               imageSize.y() <= deviceProperties.limits.maxImageDimension2D;
-                       break;
-               case IMAGE_TYPE_2D_ARRAY:
-                       isImageSizeValid =      imageSize.x() <= deviceProperties.limits.maxImageDimension2D &&
-                                                               imageSize.y() <= deviceProperties.limits.maxImageDimension2D &&
-                                                               imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
-                       break;
-               case IMAGE_TYPE_CUBE:
-                       isImageSizeValid =      imageSize.x() <= deviceProperties.limits.maxImageDimensionCube &&
-                                                               imageSize.y() <= deviceProperties.limits.maxImageDimensionCube;
-                       break;
-               case IMAGE_TYPE_CUBE_ARRAY:
-                       isImageSizeValid =      imageSize.x() <= deviceProperties.limits.maxImageDimensionCube &&
-                                                               imageSize.y() <= deviceProperties.limits.maxImageDimensionCube &&
-                                                               imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
-                       break;
-               case IMAGE_TYPE_3D:
-                       isImageSizeValid =      imageSize.x() <= deviceProperties.limits.maxImageDimension3D &&
-                                                               imageSize.y() <= deviceProperties.limits.maxImageDimension3D &&
-                                                               imageSize.z() <= deviceProperties.limits.maxImageDimension3D;
-                       break;
-               default:
-                       DE_FATAL("Unknown image type");
-       }
-
-       if (!isImageSizeValid)
-       {
-               std::ostringstream      notSupportedStream;
-
-               notSupportedStream << "Image type (" << getImageTypeName(imageType) << ") with size (" << imageSize.x() << ", " << imageSize.y() << ", " << imageSize.z() << ") not supported by device" << std::endl;
+               const deUint32 errorComponent = dataRS.getPixelUint(x, y, z)[errorCompNdx];
 
-               const std::string notSupportedString = notSupportedStream.str();
-
-               TCU_THROW(NotSupportedError, notSupportedString.c_str());
+               if (errorComponent > 0)
+                       return true;
        }
-}
-
-void MSInterpolationInstanceBase::validateImageFeatureFlags    (const InstanceInterface&       instance,
-                                                                                                                        const VkPhysicalDevice         physicalDevice,
-                                                                                                                        const VkFormat                         format,
-                                                                                                                        const VkFormatFeatureFlags     featureFlags) const
-{
-       const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(instance, physicalDevice, format);
 
-       if ((formatProperties.optimalTilingFeatures & featureFlags) != featureFlags)
-       {
-               std::ostringstream      notSupportedStream;
-
-               notSupportedStream << "Device does not support image format " << format << " for feature flags " << featureFlags << std::endl;
-
-               const std::string notSupportedString = notSupportedStream.str();
-
-               TCU_THROW(NotSupportedError, notSupportedString.c_str());
-       }
+       return false;
 }
 
-void MSInterpolationInstanceBase::validateImageInfo    (const InstanceInterface&       instance,
-                                                                                                        const VkPhysicalDevice         physicalDevice,
-                                                                                                        const VkImageCreateInfo&       imageInfo) const
+template <typename CaseClassName>
+class MSCase : public MultisampleCaseBase
 {
-       VkImageFormatProperties imageFormatProps;
-       instance.getPhysicalDeviceImageFormatProperties(physicalDevice, imageInfo.format, imageInfo.imageType, imageInfo.tiling, imageInfo.usage, imageInfo.flags, &imageFormatProps);
-
-       if (imageFormatProps.maxExtent.width  < imageInfo.extent.width  ||
-               imageFormatProps.maxExtent.height < imageInfo.extent.height ||
-               imageFormatProps.maxExtent.depth  < imageInfo.extent.depth)
-       {
-               std::ostringstream      notSupportedStream;
-
-               notSupportedStream      << "Image extent ("
-                                                       << imageInfo.extent.width  << ", "
-                                                       << imageInfo.extent.height << ", "
-                                                       << imageInfo.extent.depth
-                                                       << ") exceeds allowed maximum ("
-                                                       << imageFormatProps.maxExtent.width <<  ", "
-                                                       << imageFormatProps.maxExtent.height << ", "
-                                                       << imageFormatProps.maxExtent.depth
-                                                       << ")"
-                                                       << std::endl;
-
-               const std::string notSupportedString = notSupportedStream.str();
-
-               TCU_THROW(NotSupportedError, notSupportedString.c_str());
-       }
-
-       if (imageFormatProps.maxArrayLayers < imageInfo.arrayLayers)
-       {
-               std::ostringstream      notSupportedStream;
-
-               notSupportedStream << "Image layers count of " << imageInfo.arrayLayers << " exceeds allowed maximum which is " << imageFormatProps.maxArrayLayers << std::endl;
-
-               const std::string notSupportedString = notSupportedStream.str();
-
-               TCU_THROW(NotSupportedError, notSupportedString.c_str());
-       }
-
-       if (!(imageFormatProps.sampleCounts & imageInfo.samples))
-       {
-               std::ostringstream      notSupportedStream;
-
-               notSupportedStream << "Samples count of " << imageInfo.samples << " not supported for image" << std::endl;
-
-               const std::string notSupportedString = notSupportedStream.str();
-
-               TCU_THROW(NotSupportedError, notSupportedString.c_str());
-       }
-}
+public:
+                                                               MSCase                  (tcu::TestContext&              testCtx,
+                                                                                                const std::string&             name,
+                                                                                                const ImageMSParams&   imageMSParams)
+                                                               : MultisampleCaseBase(testCtx, name, imageMSParams) {}
+
+       void                                            init                    (void);
+       void                                            initPrograms    (vk::SourceCollections& programCollection) const;
+       TestInstance*                           createInstance  (Context&                               context) const;
+       static MultisampleCaseBase*     createCase              (tcu::TestContext&              testCtx,
+                                                                                                const std::string&             name,
+                                                                                                const ImageMSParams&   imageMSParams);
+};
 
-tcu::TestStatus MSInterpolationInstanceBase::iterate (void)
+template <typename CaseClassName>
+MultisampleCaseBase* MSCase<CaseClassName>::createCase (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
 {
-       const InstanceInterface&        instance                        = m_context.getInstanceInterface();
-       const DeviceInterface&          deviceInterface         = m_context.getDeviceInterface();
-       const VkDevice                          device                          = m_context.getDevice();
-       const VkPhysicalDevice          physicalDevice          = m_context.getPhysicalDevice();
-       Allocator&                                      allocator                       = m_context.getDefaultAllocator();
-       const VkQueue                           queue                           = m_context.getUniversalQueue();
-       const deUint32                          queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
-
-       VkImageCreateInfo                       imageMSInfo;
-       VkImageCreateInfo                       imageRSInfo;
-
-       // Check if image size does not exceed device limits
-       validateImageSize(instance, physicalDevice, m_imageType, m_imageMSParams.imageSize);
-
-       // Check if device supports image format as color attachment
-       validateImageFeatureFlags(instance, physicalDevice, mapTextureFormat(m_imageFormat), VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);
-
-       imageMSInfo.sType                                       = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
-       imageMSInfo.pNext                                       = DE_NULL;
-       imageMSInfo.flags                                       = 0u;
-       imageMSInfo.imageType                           = mapImageType(m_imageType);
-       imageMSInfo.format                                      = mapTextureFormat(m_imageFormat);
-       imageMSInfo.extent                                      = makeExtent3D(getLayerSize(m_imageType, m_imageMSParams.imageSize));
-       imageMSInfo.arrayLayers                         = getNumLayers(m_imageType, m_imageMSParams.imageSize);
-       imageMSInfo.mipLevels                           = 1u;
-       imageMSInfo.samples                                     = m_imageMSParams.numSamples;
-       imageMSInfo.tiling                                      = VK_IMAGE_TILING_OPTIMAL;
-       imageMSInfo.initialLayout                       = VK_IMAGE_LAYOUT_UNDEFINED;
-       imageMSInfo.usage                                       = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
-       imageMSInfo.sharingMode                         = VK_SHARING_MODE_EXCLUSIVE;
-       imageMSInfo.queueFamilyIndexCount       = 0u;
-       imageMSInfo.pQueueFamilyIndices         = DE_NULL;
-
-       if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY)
-       {
-               imageMSInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
-       }
-
-       validateImageInfo(instance, physicalDevice, imageMSInfo);
-
-       const de::UniquePtr<Image> imageMS(new Image(deviceInterface, device, allocator, imageMSInfo, MemoryRequirement::Any));
-
-       imageRSInfo                     = imageMSInfo;
-       imageRSInfo.samples     = VK_SAMPLE_COUNT_1_BIT;
-
-       validateImageInfo(instance, physicalDevice, imageRSInfo);
-
-       const de::UniquePtr<Image> imageRS(new Image(deviceInterface, device, allocator, imageRSInfo, MemoryRequirement::Any));
-
-       // Create render pass
-       const VkAttachmentDescription attachmentMSDesc =
-       {
-               (VkAttachmentDescriptionFlags)0u,                       // VkAttachmentDescriptionFlags         flags;
-               imageMSInfo.format,                                                     // VkFormat                                                     format;
-               imageMSInfo.samples,                                            // VkSampleCountFlagBits                        samples;
-               VK_ATTACHMENT_LOAD_OP_CLEAR,                            // VkAttachmentLoadOp                           loadOp;
-               VK_ATTACHMENT_STORE_OP_STORE,                           // VkAttachmentStoreOp                          storeOp;
-               VK_ATTACHMENT_LOAD_OP_DONT_CARE,                        // VkAttachmentLoadOp                           stencilLoadOp;
-               VK_ATTACHMENT_STORE_OP_DONT_CARE,                       // VkAttachmentStoreOp                          stencilStoreOp;
-               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,       // VkImageLayout                                        initialLayout;
-               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout                                        finalLayout;
-       };
-
-       const VkAttachmentDescription attachmentRSDesc =
-       {
-               (VkAttachmentDescriptionFlags)0u,                       // VkAttachmentDescriptionFlags         flags;
-               imageRSInfo.format,                                                     // VkFormat                                                     format;
-               imageRSInfo.samples,                                            // VkSampleCountFlagBits                        samples;
-               VK_ATTACHMENT_LOAD_OP_CLEAR,                    // VkAttachmentLoadOp                           loadOp;
-               VK_ATTACHMENT_STORE_OP_STORE,                           // VkAttachmentStoreOp                          storeOp;
-               VK_ATTACHMENT_LOAD_OP_DONT_CARE,                        // VkAttachmentLoadOp                           stencilLoadOp;
-               VK_ATTACHMENT_STORE_OP_DONT_CARE,                       // VkAttachmentStoreOp                          stencilStoreOp;
-               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,       // VkImageLayout                                        initialLayout;
-               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout                                        finalLayout;
-       };
-
-       const VkAttachmentDescription attachments[] = { attachmentMSDesc, attachmentRSDesc };
-
-       const VkAttachmentReference attachmentMSRef =
-       {
-               0u,                                                                                     // deUint32                     attachment;
-               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout        layout;
-       };
-
-       const VkAttachmentReference attachmentRSRef =
-       {
-               1u,                                                                                     // deUint32                     attachment;
-               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout        layout;
-       };
-
-       const VkAttachmentReference* resolveAttachment = m_imageMSParams.numSamples == VK_SAMPLE_COUNT_1_BIT ? DE_NULL : &attachmentRSRef;
-
-       const VkSubpassDescription subpassDescription =
-       {
-               (VkSubpassDescriptionFlags)0u,                                          // VkSubpassDescriptionFlags            flags;
-               VK_PIPELINE_BIND_POINT_GRAPHICS,                                        // VkPipelineBindPoint                          pipelineBindPoint;
-               0u,                                                                                                     // deUint32                                                     inputAttachmentCount;
-               DE_NULL,                                                                                        // const VkAttachmentReference*         pInputAttachments;
-               1u,                                                                                                     // deUint32                                                     colorAttachmentCount;
-               &attachmentMSRef,                                                                       // const VkAttachmentReference*         pColorAttachments;
-               resolveAttachment,                                                              // const VkAttachmentReference*         pResolveAttachments;
-               DE_NULL,                                                                                        // const VkAttachmentReference*         pDepthStencilAttachment;
-               0u,                                                                                                     // deUint32                                                     preserveAttachmentCount;
-               DE_NULL                                                                                         // const deUint32*                                      pPreserveAttachments;
-       };
-
-       const VkRenderPassCreateInfo renderPassInfo =
-       {
-               VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                      // VkStructureType                                      sType;
-               DE_NULL,                                                                                        // const void*                                          pNext;
-               (VkRenderPassCreateFlags)0u,                                            // VkRenderPassCreateFlags                      flags;
-               2u,                                                                                                     // deUint32                                                     attachmentCount;
-               attachments,                                                                            // const VkAttachmentDescription*       pAttachments;
-               1u,                                                                                                     // deUint32                                                     subpassCount;
-               &subpassDescription,                                                            // const VkSubpassDescription*          pSubpasses;
-               0u,                                                                                                     // deUint32                                                     dependencyCount;
-               DE_NULL                                                                                         // const VkSubpassDependency*           pDependencies;
-       };
-
-       const Unique<VkRenderPass> renderPass(createRenderPass(deviceInterface, device, &renderPassInfo));
-
-       const VkImageSubresourceRange fullImageRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageMSInfo.mipLevels, 0u, imageMSInfo.arrayLayers);
-
-       // Create color attachments image views
-       const Unique<VkImageView> imageMSView(makeImageView(deviceInterface, device, **imageMS, mapImageViewType(m_imageType), imageMSInfo.format, fullImageRange));
-       const Unique<VkImageView> imageRSView(makeImageView(deviceInterface, device, **imageRS, mapImageViewType(m_imageType), imageMSInfo.format, fullImageRange));
-
-       const VkImageView attachmentsViews[] = { *imageMSView, *imageRSView };
-
-       // Create framebuffer
-       const VkFramebufferCreateInfo framebufferInfo =
-       {
-               VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,      // VkStructureType                             sType;
-               DE_NULL,                                                                        // const void*                                 pNext;
-               (VkFramebufferCreateFlags)0u,                           // VkFramebufferCreateFlags                    flags;
-               *renderPass,                                                            // VkRenderPass                                renderPass;
-               2u,                                                                                     // uint32_t                                    attachmentCount;
-               attachmentsViews,                                                       // const VkImageView*                          pAttachments;
-               imageMSInfo.extent.width,                                       // uint32_t                                    width;
-               imageMSInfo.extent.height,                                      // uint32_t                                    height;
-               imageMSInfo.arrayLayers,                                        // uint32_t                                    layers;
-       };
-
-       const Unique<VkFramebuffer> framebuffer(createFramebuffer(deviceInterface, device, &framebufferInfo));
-
-       // Create pipeline layout
-       const VkPipelineLayoutCreateInfo pipelineLayoutParams =
-       {
-               VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                                      sType;
-               DE_NULL,                                                                                        // const void*                                          pNext;
-               (VkPipelineLayoutCreateFlags)0u,                                        // VkPipelineLayoutCreateFlags          flags;
-               0u,                                                                                                     // deUint32                                                     setLayoutCount;
-               DE_NULL,                                                                                        // const VkDescriptorSetLayout*         pSetLayouts;
-               0u,                                                                                                     // deUint32                                                     pushConstantRangeCount;
-               DE_NULL,                                                                                        // const VkPushConstantRange*           pPushConstantRanges;
-       };
-
-       const Unique<VkPipelineLayout> pipelineLayout(createPipelineLayout(deviceInterface, device, &pipelineLayoutParams));
-
-       // Create vertex attributes data
-       const VertexDataDesc vertexDataDesc = getVertexDataDescripton();
-
-       de::SharedPtr<Buffer> vertexBuffer = de::SharedPtr<Buffer>(new Buffer(deviceInterface, device, allocator, makeBufferCreateInfo(vertexDataDesc.dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
-       const Allocation& vertexBufferAllocation = vertexBuffer->getAllocation();
-
-       uploadVertexData(vertexBufferAllocation, vertexDataDesc);
-
-       flushMappedMemoryRange(deviceInterface, device, vertexBufferAllocation.getMemory(), vertexBufferAllocation.getOffset(), vertexDataDesc.dataSize);
-
-       const VkVertexInputBindingDescription vertexBinding =
-       {
-               0u,                                                     // deUint32                             binding;
-               vertexDataDesc.dataStride,      // deUint32                             stride;
-               VK_VERTEX_INPUT_RATE_VERTEX     // VkVertexInputRate    inputRate;
-       };
-
-       const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
-       {
-               VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,                      // VkStructureType                             sType;
-               DE_NULL,                                                                                                                        // const void*                                 pNext;
-               (VkPipelineVertexInputStateCreateFlags)0u,                                                      // VkPipelineVertexInputStateCreateFlags       flags;
-               1u,                                                                                                                                     // uint32_t                                    vertexBindingDescriptionCount;
-               &vertexBinding,                                                                                                         // const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
-               static_cast<deUint32>(vertexDataDesc.vertexAttribDescVec.size()),       // uint32_t                                    vertexAttributeDescriptionCount;
-               dataPointer(vertexDataDesc.vertexAttribDescVec),                                        // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
-       };
-
-       const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateInfo =
-       {
-               VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                             sType;
-               DE_NULL,                                                                                                                // const void*                                 pNext;
-               (VkPipelineInputAssemblyStateCreateFlags)0u,                                    // VkPipelineInputAssemblyStateCreateFlags     flags;
-               vertexDataDesc.primitiveTopology,                                                               // VkPrimitiveTopology                         topology;
-               VK_FALSE,                                                                                                               // VkBool32                                    primitiveRestartEnable;
-       };
-
-       const VkViewport viewport =
-       {
-               0.0f, 0.0f,
-               static_cast<float>(imageMSInfo.extent.width), static_cast<float>(imageMSInfo.extent.height),
-               0.0f, 1.0f
-       };
-
-       const VkRect2D scissor =
-       {
-               makeOffset2D(0, 0),
-               makeExtent2D(imageMSInfo.extent.width, imageMSInfo.extent.height),
-       };
-
-       const VkPipelineViewportStateCreateInfo viewportStateInfo =
-       {
-               VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,                  // VkStructureType                             sType;
-               DE_NULL,                                                                                                                // const void*                                 pNext;
-               (VkPipelineViewportStateCreateFlags)0u,                                                 // VkPipelineViewportStateCreateFlags          flags;
-               1u,                                                                                                                             // uint32_t                                    viewportCount;
-               &viewport,                                                                                                              // const VkViewport*                           pViewports;
-               1u,                                                                                                                             // uint32_t                                    scissorCount;
-               &scissor,                                                                                                               // const VkRect2D*                             pScissors;
-       };
-
-       const VkPipelineRasterizationStateCreateInfo rasterizationStateInfo =
-       {
-               VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                          sType;
-               DE_NULL,                                                                                                                // const void*                              pNext;
-               (VkPipelineRasterizationStateCreateFlags)0u,                                    // VkPipelineRasterizationStateCreateFlags  flags;
-               VK_FALSE,                                                                                                               // VkBool32                                 depthClampEnable;
-               VK_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 VkPipelineMultisampleStateCreateInfo multisampleStateInfo =
-       {
-               VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,               // VkStructureType                                                      sType;
-               DE_NULL,                                                                                                                // const void*                                                          pNext;
-               (VkPipelineMultisampleStateCreateFlags)0u,                                              // VkPipelineMultisampleStateCreateFlags        flags;
-               imageMSInfo.samples,                                                                                    // VkSampleCountFlagBits                                        rasterizationSamples;
-               VK_TRUE,                                                                                                                // VkBool32                                                                     sampleShadingEnable;
-               1.0f,                                                                                                                   // float                                                                        minSampleShading;
-               DE_NULL,                                                                                                                // const VkSampleMask*                                          pSampleMask;
-               VK_FALSE,                                                                                                               // VkBool32                                                                     alphaToCoverageEnable;
-               VK_FALSE,                                                                                                               // VkBool32                                                                     alphaToOneEnable;
-       };
-
-       const VkStencilOpState stencilOpState = makeStencilOpState
-       (
-               VK_STENCIL_OP_KEEP,             // stencil fail
-               VK_STENCIL_OP_KEEP,             // depth & stencil pass
-               VK_STENCIL_OP_KEEP,             // depth only fail
-               VK_COMPARE_OP_ALWAYS,   // compare op
-               0u,                                             // compare mask
-               0u,                                             // write mask
-               0u                                              // reference
-       );
-
-       const VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo =
-       {
-               VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,             // VkStructureType                                                      sType;
-               DE_NULL,                                                                                                                // const void*                                                          pNext;
-               (VkPipelineDepthStencilStateCreateFlags)0u,                                             // VkPipelineDepthStencilStateCreateFlags       flags;
-               VK_FALSE,                                                                                                               // VkBool32                                                                     depthTestEnable;
-               VK_FALSE,                                                                                                               // VkBool32                                                                     depthWriteEnable;
-               VK_COMPARE_OP_LESS,                                                                                             // VkCompareOp                                                          depthCompareOp;
-               VK_FALSE,                                                                                                               // VkBool32                                                                     depthBoundsTestEnable;
-               VK_FALSE,                                                                                                               // VkBool32                                                                     stencilTestEnable;
-               stencilOpState,                                                                                                 // VkStencilOpState                                                     front;
-               stencilOpState,                                                                                                 // VkStencilOpState                                                     back;
-               0.0f,                                                                                                                   // float                                                                        minDepthBounds;
-               1.0f,                                                                                                                   // float                                                                        maxDepthBounds;
-       };
-
-       const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
-
-       const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
-       {
-               VK_FALSE,                                                                                                               // VkBool32                                     blendEnable;
-               VK_BLEND_FACTOR_SRC_ALPHA,                                                                              // VkBlendFactor                        srcColorBlendFactor;
-               VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,                                                    // VkBlendFactor                        dstColorBlendFactor;
-               VK_BLEND_OP_ADD,                                                                                                // VkBlendOp                            colorBlendOp;
-               VK_BLEND_FACTOR_SRC_ALPHA,                                                                              // VkBlendFactor                        srcAlphaBlendFactor;
-               VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,                                                    // VkBlendFactor                        dstAlphaBlendFactor;
-               VK_BLEND_OP_ADD,                                                                                                // VkBlendOp                            alphaBlendOp;
-               colorComponentsAll,                                                                                             // VkColorComponentFlags        colorWriteMask;
-       };
-
-       const VkPipelineColorBlendStateCreateInfo colorBlendStateInfo =
-       {
-               VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,               // VkStructureType                                                              sType;
-               DE_NULL,                                                                                                                // const void*                                                                  pNext;
-               (VkPipelineColorBlendStateCreateFlags)0u,                                               // VkPipelineColorBlendStateCreateFlags                 flags;
-               VK_FALSE,                                                                                                               // VkBool32                                                                             logicOpEnable;
-               VK_LOGIC_OP_COPY,                                                                                               // VkLogicOp                                                                    logicOp;
-               1u,                                                                                                                             // deUint32                                                                             attachmentCount;
-               &colorBlendAttachmentState,                                                                             // const VkPipelineColorBlendAttachmentState*   pAttachments;
-               { 0.0f, 0.0f, 0.0f, 0.0f },                                                                             // float                                                                                blendConstants[4];
-       };
-
-       const Unique<VkShaderModule> vsModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("vertex_shader"), (VkShaderModuleCreateFlags)0));
-
-       const VkPipelineShaderStageCreateInfo vsShaderStageInfo =
-       {
-               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,                    // VkStructureType                                              sType;
-               DE_NULL,                                                                                                                // const void*                                                  pNext;
-               (VkPipelineShaderStageCreateFlags)0u,                                                   // VkPipelineShaderStageCreateFlags             flags;
-               VK_SHADER_STAGE_VERTEX_BIT,                                                                             // VkShaderStageFlagBits                                stage;
-               *vsModule,                                                                                                              // VkShaderModule                                               module;
-               "main",                                                                                                                 // const char*                                                  pName;
-               DE_NULL,                                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
-       };
-
-       const Unique<VkShaderModule> fsModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("fragment_shader"), (VkShaderModuleCreateFlags)0));
-
-       const VkPipelineShaderStageCreateInfo fsShaderStageInfo =
-       {
-               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,                    // VkStructureType                                              sType;
-               DE_NULL,                                                                                                                // const void*                                                  pNext;
-               (VkPipelineShaderStageCreateFlags)0u,                                                   // VkPipelineShaderStageCreateFlags             flags;
-               VK_SHADER_STAGE_FRAGMENT_BIT,                                                                   // VkShaderStageFlagBits                                stage;
-               *fsModule,                                                                                                              // VkShaderModule                                               module;
-               "main",                                                                                                                 // const char*                                                  pName;
-               DE_NULL,                                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
-       };
-
-       const VkPipelineShaderStageCreateInfo shaderStageInfos[] = { vsShaderStageInfo, fsShaderStageInfo };
-
-       const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
-       {
-               VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,                                // VkStructureType                                                                      sType;
-               DE_NULL,                                                                                                                // const void*                                                                          pNext;
-               (VkPipelineCreateFlags)0,                                                                               // VkPipelineCreateFlags                                                        flags;
-               2u,                                                                                                                             // deUint32                                                                                     stageCount;
-               shaderStageInfos,                                                                                               // const VkPipelineShaderStageCreateInfo*                       pStages;
-               &vertexInputStateInfo,                                                                                  // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
-               &inputAssemblyStateInfo,                                                                                // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
-               DE_NULL,                                                                                                                // const VkPipelineTessellationStateCreateInfo*         pTessellationState;
-               &viewportStateInfo,                                                                                             // const VkPipelineViewportStateCreateInfo*                     pViewportState;
-               &rasterizationStateInfo,                                                                                // const VkPipelineRasterizationStateCreateInfo*        pRasterizationState;
-               &multisampleStateInfo,                                                                                  // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
-               &depthStencilStateInfo,                                                                                 // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
-               &colorBlendStateInfo,                                                                                   // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
-               DE_NULL,                                                                                                                // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
-               *pipelineLayout,                                                                                                // VkPipelineLayout                                                                     layout;
-               *renderPass,                                                                                                    // VkRenderPass                                                                         renderPass;
-               0u,                                                                                                                             // deUint32                                                                                     subpass;
-               DE_NULL,                                                                                                                // VkPipeline                                                                           basePipelineHandle;
-               0u,                                                                                                                             // deInt32                                                                                      basePipelineIndex;
-       };
-
-       // Create graphics pipeline
-       const Unique<VkPipeline> graphicsPipeline(createGraphicsPipeline(deviceInterface, device, DE_NULL, &graphicsPipelineInfo));
-
-       // Create command buffer for compute and transfer oparations
-       const Unique<VkCommandPool>       commandPool(makeCommandPool(deviceInterface, device, queueFamilyIndex));
-       const Unique<VkCommandBuffer> commandBuffer(makeCommandBuffer(deviceInterface, device, *commandPool));
-
-       // Start recording commands
-       beginCommandBuffer(deviceInterface, *commandBuffer);
-
-       {
-               VkImageMemoryBarrier imageOutputAttachmentBarriers[2];
-
-               imageOutputAttachmentBarriers[0] = makeImageMemoryBarrier
-               (
-                       0u,
-                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
-                       VK_IMAGE_LAYOUT_UNDEFINED,
-                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
-                       **imageMS,
-                       fullImageRange
-               );
-
-               imageOutputAttachmentBarriers[1] = makeImageMemoryBarrier
-               (
-                       0u,
-                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
-                       VK_IMAGE_LAYOUT_UNDEFINED,
-                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
-                       **imageRS,
-                       fullImageRange
-               );
-
-               deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 2u, imageOutputAttachmentBarriers);
-       }
-
-       {
-               const VkDeviceSize vertexStartOffset = 0u;
-
-               std::vector<VkClearValue> clearValues;
-               clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
-               clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
-
-               const vk::VkRect2D renderArea =
-               {
-                       makeOffset2D(0u, 0u),
-                       makeExtent2D(imageMSInfo.extent.width, imageMSInfo.extent.height),
-               };
-
-               // Begin render pass
-               const VkRenderPassBeginInfo renderPassBeginInfo =
-               {
-                       VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,               // VkStructureType         sType;
-                       DE_NULL,                                                                                // const void*             pNext;
-                       *renderPass,                                                                            // VkRenderPass            renderPass;
-                       *framebuffer,                                                                   // VkFramebuffer           framebuffer;
-                       renderArea,                                                                             // VkRect2D                renderArea;
-                       static_cast<deUint32>(clearValues.size()),              // deUint32                clearValueCount;
-                       &clearValues[0],                                                                // const VkClearValue*     pClearValues;
-               };
-
-               deviceInterface.cmdBeginRenderPass(*commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
-
-               // Bind graphics pipeline
-               deviceInterface.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
-
-               // Bind vertex buffer
-               deviceInterface.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBuffer->get(), &vertexStartOffset);
-
-               // Draw full screen quad
-               deviceInterface.cmdDraw(*commandBuffer, vertexDataDesc.verticesCount, 1u, 0u, 0u);
-
-               // End render pass
-               deviceInterface.cmdEndRenderPass(*commandBuffer);
-       }
-
-       const VkImage sourceImage = m_imageMSParams.numSamples == VK_SAMPLE_COUNT_1_BIT ? **imageMS : **imageRS;
-
-       {
-               const VkImageMemoryBarrier imageTransferSrcBarrier = makeImageMemoryBarrier
-               (
-                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
-                       VK_ACCESS_TRANSFER_READ_BIT,
-                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
-                       VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
-                       sourceImage,
-                       fullImageRange
-               );
-
-               deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageTransferSrcBarrier);
-       }
-
-       // Copy data from resolve image to buffer
-       const deUint32                          imageRSSizeInBytes = getImageSizeInBytes(imageRSInfo.extent, imageRSInfo.arrayLayers, m_imageFormat, imageRSInfo.mipLevels);
-
-       const VkBufferCreateInfo        bufferRSInfo = makeBufferCreateInfo(imageRSSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
-       const de::UniquePtr<Buffer>     bufferRS(new Buffer(deviceInterface, device, allocator, bufferRSInfo, MemoryRequirement::HostVisible));
-
-       {
-               const VkBufferImageCopy bufferImageCopy =
-               {
-                       0u,                                                                                                                                                                             //      VkDeviceSize                            bufferOffset;
-                       0u,                                                                                                                                                                             //      deUint32                                        bufferRowLength;
-                       0u,                                                                                                                                                                             //      deUint32                                        bufferImageHeight;
-                       makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageRSInfo.arrayLayers), //      VkImageSubresourceLayers        imageSubresource;
-                       makeOffset3D(0, 0, 0),                                                                                                                                  //      VkOffset3D                                      imageOffset;
-                       imageRSInfo.extent,                                                                                                                                             //      VkExtent3D                                      imageExtent;
-               };
-
-               deviceInterface.cmdCopyImageToBuffer(*commandBuffer, sourceImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, bufferRS->get(), 1u, &bufferImageCopy);
-       }
-
-       {
-               const VkBufferMemoryBarrier bufferRSHostReadBarrier = makeBufferMemoryBarrier
-               (
-                       VK_ACCESS_TRANSFER_WRITE_BIT,
-                       VK_ACCESS_HOST_READ_BIT,
-                       bufferRS->get(),
-                       0u,
-                       imageRSSizeInBytes
-               );
-
-               deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferRSHostReadBarrier, 0u, DE_NULL);
-       }
-
-       // End recording commands
-       VK_CHECK(deviceInterface.endCommandBuffer(*commandBuffer));
-
-       // Submit commands for execution and wait for completion
-       submitCommandsAndWait(deviceInterface, device, queue, *commandBuffer);
-
-       // Retrieve data from buffer to host memory
-       const Allocation& bufferRSAllocation = bufferRS->getAllocation();
-
-       invalidateMappedMemoryRange(deviceInterface, device, bufferRSAllocation.getMemory(), bufferRSAllocation.getOffset(), imageRSSizeInBytes);
-
-       const tcu::ConstPixelBufferAccess bufferRSData (m_imageFormat,
-                                                                                                       imageRSInfo.extent.width,
-                                                                                                       imageRSInfo.extent.height,
-                                                                                                       imageRSInfo.extent.depth * imageRSInfo.arrayLayers,
-                                                                                                       bufferRSAllocation.getHostPtr());
-
-       std::stringstream imageName;
-       imageName << getImageTypeName(m_imageType) << "_" << bufferRSData.getWidth() << "_" << bufferRSData.getHeight() << "_" << bufferRSData.getDepth() << std::endl;
-
-       m_context.getTestContext().getLog()
-               << tcu::TestLog::Section(imageName.str(), imageName.str())
-               << tcu::LogImage("image", "", bufferRSData)
-               << tcu::TestLog::EndSection;
-
-       return verifyResolvedImage(bufferRSData);
+       return new MSCase<CaseClassName>(testCtx, name, imageMSParams);
 }
 
-class MSInstanceDistinctValues : public MSInterpolationInstanceBase
+template <typename InstanceClassName>
+class MSInstance : public MSInstanceBaseResolve
 {
 public:
-                                       MSInstanceDistinctValues(Context&                               context,
-                                                                                        const ImageMSParams&   imageMSParams)
-       : MSInterpolationInstanceBase(context, imageMSParams) {}
+                                       MSInstance                              (Context&                                                       context,
+                                                                                        const ImageMSParams&                           imageMSParams)
+                                       : MSInstanceBaseResolve(context, imageMSParams) {}
 
        VertexDataDesc  getVertexDataDescripton (void) const;
-       void                    uploadVertexData                (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const;
-       tcu::TestStatus verifyResolvedImage             (const tcu::ConstPixelBufferAccess&     imageData) const;
-
-protected:
-       struct VertexData
-       {
-               VertexData(const tcu::Vec4& posNdc) : positionNdc(posNdc) {}
-
-               tcu::Vec4 positionNdc;
-       };
+       void                    uploadVertexData                (const Allocation&                                      vertexBufferAllocation,
+                                                                                        const VertexDataDesc&                          vertexDataDescripton) const;
+       tcu::TestStatus verifyImageData                 (const vk::VkImageCreateInfo&           imageRSInfo,
+                                                                                        const tcu::ConstPixelBufferAccess& dataRS) const;
 };
 
-MSInterpolationInstanceBase::VertexDataDesc MSInstanceDistinctValues::getVertexDataDescripton (void) const
+class MSInstanceDistinctValues;
+
+template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceDistinctValues>::getVertexDataDescripton (void) const
 {
        VertexDataDesc vertexDataDesc;
 
        vertexDataDesc.verticesCount            = 3u;
-       vertexDataDesc.dataStride                       = sizeof(VertexData);
+       vertexDataDesc.dataStride                       = sizeof(VertexDataNdc);
        vertexDataDesc.dataSize                         = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
        vertexDataDesc.primitiveTopology        = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
 
@@ -784,7 +129,7 @@ MSInterpolationInstanceBase::VertexDataDesc MSInstanceDistinctValues::getVertexD
                0u,                                                                             // deUint32     location;
                0u,                                                                             // deUint32     binding;
                VK_FORMAT_R32G32B32A32_SFLOAT,                  // VkFormat     format;
-               DE_OFFSET_OF(VertexData, positionNdc),  // deUint32     offset;
+               DE_OFFSET_OF(VertexDataNdc, positionNdc),       // deUint32     offset;
        };
 
        vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
@@ -792,28 +137,28 @@ MSInterpolationInstanceBase::VertexDataDesc MSInstanceDistinctValues::getVertexD
        return vertexDataDesc;
 }
 
-void MSInstanceDistinctValues::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
+template<> void MSInstance<MSInstanceDistinctValues>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
 {
-       std::vector<VertexData> vertices;
+       std::vector<VertexDataNdc> vertices;
 
-       vertices.push_back(VertexData(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f)));
-       vertices.push_back(VertexData(tcu::Vec4(-1.0f, 4.0f, 0.0f, 1.0f)));
-       vertices.push_back(VertexData(tcu::Vec4( 4.0f,-1.0f, 0.0f, 1.0f)));
+       vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f)));
+       vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f,  4.0f, 0.0f, 1.0f)));
+       vertices.push_back(VertexDataNdc(tcu::Vec4( 4.0f, -1.0f, 0.0f, 1.0f)));
 
        deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
 }
 
-tcu::TestStatus        MSInstanceDistinctValues::verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const
+template<> tcu::TestStatus MSInstance<MSInstanceDistinctValues>::verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS) const
 {
        const deUint32 distinctValuesExpected = static_cast<deUint32>(m_imageMSParams.numSamples) + 1u;
 
        std::vector<tcu::IVec4> distinctValues;
 
-       for (deInt32 z = 0u; z < imageData.getDepth();  ++z)
-       for (deInt32 y = 0u; y < imageData.getHeight(); ++y)
-       for (deInt32 x = 0u; x < imageData.getWidth();  ++x)
+       for (deUint32 z = 0u; z < imageRSInfo.extent.depth;      ++z)
+       for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
+       for (deUint32 x = 0u; x < imageRSInfo.extent.width;      ++x)
        {
-               const tcu::IVec4 pixel = imageData.getPixelInt(x, y, z);
+               const tcu::IVec4 pixel = dataRS.getPixelInt(x, y, z);
 
                if (std::find(distinctValues.begin(), distinctValues.end(), pixel) == distinctValues.end())
                        distinctValues.push_back(pixel);
@@ -822,28 +167,12 @@ tcu::TestStatus   MSInstanceDistinctValues::verifyResolvedImage (const tcu::ConstP
        if (distinctValues.size() >= distinctValuesExpected)
                return tcu::TestStatus::pass("Passed");
        else
-               return tcu::TestStatus::fail("Failed");
+               return tcu::TestStatus::fail("Expected numSamples+1 different colors in the output image");
 }
 
-class MSCaseSampleQualifierDistinctValues : public MSInterpolationCaseBase
-{
-public:
-                                       MSCaseSampleQualifierDistinctValues     (tcu::TestContext&              testCtx,
-                                                                                                                const std::string&             name,
-                                                                                                                const ImageMSParams&   imageMSParams)
-       : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
-
-       void                    init                                                            (void);
-       void                    initPrograms                                            (vk::SourceCollections& programCollection) const;
-       TestInstance*   createInstance                                          (Context&                               context) const;
-};
+class MSCaseSampleQualifierDistinctValues;
 
-MSInterpolationCaseBase* createMSCaseSampleQualifierDistinctValues (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
-{
-       return new MSCaseSampleQualifierDistinctValues(testCtx, name, imageMSParams);
-}
-
-void MSCaseSampleQualifierDistinctValues::init (void)
+template<> void MSCase<MSCaseSampleQualifierDistinctValues>::init (void)
 {
        m_testCtx.getLog()
                << tcu::TestLog::Message
@@ -852,10 +181,10 @@ void MSCaseSampleQualifierDistinctValues::init (void)
                << "    => Resulting image should contain n+1 different colors, where n = sample count.\n"
                << tcu::TestLog::EndMessage;
 
-       MSInterpolationCaseBase::init();
+       MultisampleCaseBase::init();
 }
 
-void MSCaseSampleQualifierDistinctValues::initPrograms (vk::SourceCollections& programCollection) const
+template<> void MSCase<MSCaseSampleQualifierDistinctValues>::initPrograms (vk::SourceCollections& programCollection) const
 {
        // Create vertex shader
        std::ostringstream vs;
@@ -882,43 +211,27 @@ void MSCaseSampleQualifierDistinctValues::initPrograms (vk::SourceCollections& p
        fs << "#version 440\n"
                << "layout(location = 0) sample in vec4 fs_in_position_ndc;\n"
                << "\n"
-               << "layout(location = 0) out vec2 fs_out_color;\n"
+               << "layout(location = 0) out vec4 fs_out_color;\n"
                << "\n"
                << "void main (void)\n"
                << "{\n"
                << "    if(fs_in_position_ndc.y < -2.0*pow(0.5*(fs_in_position_ndc.x + 1.0), 2.0) + 1.0)\n"
-               << "            fs_out_color = vec2(1.0, 0.0);\n"
+               << "            fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
                << "    else\n"
-               << "            fs_out_color = vec2(0.0, 1.0);\n"
+               << "            fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
                << "}\n";
 
        programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
 }
 
-TestInstance* MSCaseSampleQualifierDistinctValues::createInstance (Context& context) const
+template<> TestInstance* MSCase<MSCaseSampleQualifierDistinctValues>::createInstance (Context& context) const
 {
-       return new MSInstanceDistinctValues(context, m_imageMSParams);
+       return new MSInstance<MSInstanceDistinctValues>(context, m_imageMSParams);
 }
 
-class MSCaseInterpolateAtSampleDistinctValues : public MSInterpolationCaseBase
-{
-public:
-                                       MSCaseInterpolateAtSampleDistinctValues (tcu::TestContext&              testCtx,
-                                                                                                                        const std::string&             name,
-                                                                                                                        const ImageMSParams&   imageMSParams)
-       : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
-
-       void                    init                                                                    (void);
-       void                    initPrograms                                                    (vk::SourceCollections& programCollection) const;
-       TestInstance*   createInstance                                                  (Context&                               context) const;
-};
-
-MSInterpolationCaseBase* createMSCaseInterpolateAtSampleDistinctValues (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
-{
-       return new MSCaseInterpolateAtSampleDistinctValues(testCtx, name, imageMSParams);
-}
+class MSCaseInterpolateAtSampleDistinctValues;
 
-void MSCaseInterpolateAtSampleDistinctValues::init (void)
+template<> void MSCase<MSCaseInterpolateAtSampleDistinctValues>::init (void)
 {
        m_testCtx.getLog()
                << tcu::TestLog::Message
@@ -927,10 +240,10 @@ void MSCaseInterpolateAtSampleDistinctValues::init (void)
                << "    => Resulting image should contain n+1 different colors, where n = sample count.\n"
                << tcu::TestLog::EndMessage;
 
-       MSInterpolationCaseBase::init();
+       MultisampleCaseBase::init();
 }
 
-void MSCaseInterpolateAtSampleDistinctValues::initPrograms (vk::SourceCollections& programCollection) const
+template<> void MSCase<MSCaseInterpolateAtSampleDistinctValues>::initPrograms (vk::SourceCollections& programCollection) const
 {
        // Create vertex shader
        std::ostringstream vs;
@@ -957,61 +270,42 @@ void MSCaseInterpolateAtSampleDistinctValues::initPrograms (vk::SourceCollection
        fs << "#version 440\n"
                << "layout(location = 0) in vec4 fs_in_position_ndc;\n"
                << "\n"
-               << "layout(location = 0) out vec2 fs_out_color;\n"
+               << "layout(location = 0) out vec4 fs_out_color;\n"
                << "\n"
                << "void main (void)\n"
                << "{\n"
                << "    const vec4 position_ndc_at_sample = interpolateAtSample(fs_in_position_ndc, gl_SampleID);\n"
                << "    if(position_ndc_at_sample.y < -2.0*pow(0.5*(position_ndc_at_sample.x + 1.0), 2.0) + 1.0)\n"
-               << "            fs_out_color = vec2(0.0, 1.0);\n"
+               << "            fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
                << "    else\n"
-               << "            fs_out_color = vec2(1.0, 0.0);\n"
+               << "            fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
                << "}\n";
 
        programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
 }
 
-TestInstance* MSCaseInterpolateAtSampleDistinctValues::createInstance (Context& context) const
+template<> TestInstance* MSCase<MSCaseInterpolateAtSampleDistinctValues>::createInstance (Context& context) const
 {
-       return new MSInstanceDistinctValues(context, m_imageMSParams);
+       return new MSInstance<MSInstanceDistinctValues>(context, m_imageMSParams);
 }
 
-class MSInstanceInterpolateScreenPosition : public MSInterpolationInstanceBase
-{
-public:
-                                       MSInstanceInterpolateScreenPosition     (Context&                               context,
-                                                                                                                const ImageMSParams&   imageMSParams)
-       : MSInterpolationInstanceBase(context, imageMSParams) {}
-
-       VertexDataDesc  getVertexDataDescripton                         (void) const;
-       void                    uploadVertexData                                        (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const;
-       tcu::TestStatus verifyResolvedImage                                     (const tcu::ConstPixelBufferAccess&     imageData) const;
-
-protected:
-       struct VertexData
-       {
-               VertexData(const tcu::Vec4& posNdc, const tcu::Vec2& posScreen) : positionNdc(posNdc), positionScreen(posScreen) {}
-
-               tcu::Vec4 positionNdc;
-               tcu::Vec2 positionScreen;
-       };
-};
+class MSInstanceInterpolateScreenPosition;
 
-MSInterpolationInstanceBase::VertexDataDesc MSInstanceInterpolateScreenPosition::getVertexDataDescripton (void) const
+template<> MSInstanceBaseResolve::VertexDataDesc MSInstance<MSInstanceInterpolateScreenPosition>::getVertexDataDescripton (void) const
 {
        VertexDataDesc vertexDataDesc;
 
        vertexDataDesc.verticesCount            = 4u;
-       vertexDataDesc.dataStride                       = sizeof(VertexData);
+       vertexDataDesc.dataStride                       = sizeof(VertexDataNdcScreen);
        vertexDataDesc.dataSize                         = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
        vertexDataDesc.primitiveTopology        = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
 
        const VkVertexInputAttributeDescription vertexAttribPositionNdc =
        {
-               0u,                                                                                     // deUint32     location;
-               0u,                                                                                     // deUint32     binding;
-               VK_FORMAT_R32G32B32A32_SFLOAT,                          // VkFormat     format;
-               DE_OFFSET_OF(VertexData, positionNdc),          // deUint32     offset;
+               0u,                                                                                             // deUint32     location;
+               0u,                                                                                             // deUint32     binding;
+               VK_FORMAT_R32G32B32A32_SFLOAT,                                  // VkFormat     format;
+               DE_OFFSET_OF(VertexDataNdcScreen, positionNdc), // deUint32     offset;
        };
 
        vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
@@ -1021,7 +315,7 @@ MSInterpolationInstanceBase::VertexDataDesc MSInstanceInterpolateScreenPosition:
                1u,                                                                                     // deUint32     location;
                0u,                                                                                     // deUint32     binding;
                VK_FORMAT_R32G32_SFLOAT,                                        // VkFormat     format;
-               DE_OFFSET_OF(VertexData, positionScreen),       // deUint32     offset;
+               DE_OFFSET_OF(VertexDataNdcScreen, positionScreen),      // deUint32     offset;
        };
 
        vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionScreen);
@@ -1029,50 +323,33 @@ MSInterpolationInstanceBase::VertexDataDesc MSInstanceInterpolateScreenPosition:
        return vertexDataDesc;
 }
 
-void MSInstanceInterpolateScreenPosition::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
+template<> void MSInstance<MSInstanceInterpolateScreenPosition>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
 {
        const tcu::UVec3 layerSize              = getLayerSize(IMAGE_TYPE_2D, m_imageMSParams.imageSize);
        const float              screenSizeX    = static_cast<float>(layerSize.x());
        const float              screenSizeY    = static_cast<float>(layerSize.y());
 
-       std::vector<VertexData> vertices;
+       std::vector<VertexDataNdcScreen> vertices;
 
-       vertices.push_back(VertexData(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f,                0.0f)));
-       vertices.push_back(VertexData(tcu::Vec4( 1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, 0.0f)));
-       vertices.push_back(VertexData(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f,                screenSizeY)));
-       vertices.push_back(VertexData(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, screenSizeY)));
+       vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, 0.0f)));
+       vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, 0.0f)));
+       vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, screenSizeY)));
+       vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, screenSizeY)));
 
        deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
 }
 
-tcu::TestStatus        MSInstanceInterpolateScreenPosition::verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const
+template<> tcu::TestStatus MSInstance<MSInstanceInterpolateScreenPosition>::verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS) const
 {
-       for (deInt32 z = 0u; z < imageData.getDepth();  ++z)
-       for (deInt32 y = 0u; y < imageData.getHeight(); ++y)
-       for (deInt32 x = 0u; x < imageData.getWidth();  ++x)
-       {
-               const deInt32 firstComponent = imageData.getPixelInt(x, y, z).x();
+       if (checkForError(imageRSInfo, dataRS, 0))
+               return tcu::TestStatus::fail("Failed");
 
-               if (firstComponent > 0)
-                       return tcu::TestStatus::fail("Failed");
-       }
        return tcu::TestStatus::pass("Passed");
 }
 
-class MSCaseInterpolateAtSampleSingleSample : public MSInterpolationCaseBase
-{
-public:
-                                       MSCaseInterpolateAtSampleSingleSample   (tcu::TestContext&              testCtx,
-                                                                                                                        const std::string&             name,
-                                                                                                                        tcu::UVec3                             imageSize)
-       : MSInterpolationCaseBase(testCtx, name, ImageMSParams(VK_SAMPLE_COUNT_1_BIT, imageSize)) {}
-
-       void                    init                                                                    (void);
-       void                    initPrograms                                                    (vk::SourceCollections& programCollection) const;
-       TestInstance*   createInstance                                                  (Context&                               context) const;
-};
+class MSCaseInterpolateAtSampleSingleSample;
 
-void MSCaseInterpolateAtSampleSingleSample::init (void)
+template<> void MSCase<MSCaseInterpolateAtSampleSingleSample>::init (void)
 {
        m_testCtx.getLog()
                << tcu::TestLog::Message
@@ -1081,10 +358,10 @@ void MSCaseInterpolateAtSampleSingleSample::init (void)
                << "    => fract(screen space location) should be (about) (0.5, 0.5)\n"
                << tcu::TestLog::EndMessage;
 
-       MSInterpolationCaseBase::init();
+       MultisampleCaseBase::init();
 }
 
-void MSCaseInterpolateAtSampleSingleSample::initPrograms (vk::SourceCollections& programCollection) const
+template<> void MSCase<MSCaseInterpolateAtSampleSingleSample>::initPrograms (vk::SourceCollections& programCollection) const
 {
        // Create vertex shader
        std::ostringstream vs;
@@ -1112,7 +389,7 @@ void MSCaseInterpolateAtSampleSingleSample::initPrograms (vk::SourceCollections&
        fs << "#version 440\n"
                << "layout(location = 0) in vec2 fs_in_position_screen;\n"
                << "\n"
-               << "layout(location = 0) out vec2 fs_out_color;\n"
+               << "layout(location = 0) out vec4 fs_out_color;\n"
                << "\n"
                << "void main (void)\n"
                << "{\n"
@@ -1121,38 +398,22 @@ void MSCaseInterpolateAtSampleSingleSample::initPrograms (vk::SourceCollections&
                << "    const vec2  position_inside_pixel               = fract(position_screen_at_sample);\n"
                << "\n"
                << "    if (abs(position_inside_pixel.x - 0.5) <= threshold && abs(position_inside_pixel.y - 0.5) <= threshold)\n"
-               << "            fs_out_color = vec2(0.0, 1.0);\n"
+               << "            fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
                << "    else\n"
-               << "            fs_out_color = vec2(1.0, 0.0);\n"
+               << "            fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
                << "}\n";
 
        programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
 }
 
-TestInstance* MSCaseInterpolateAtSampleSingleSample::createInstance (Context& context) const
+template<> TestInstance* MSCase<MSCaseInterpolateAtSampleSingleSample>::createInstance (Context& context) const
 {
-       return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
+       return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
 }
 
-class MSCaseInterpolateAtSampleIgnoresCentroid : public MSInterpolationCaseBase
-{
-public:
-                                       MSCaseInterpolateAtSampleIgnoresCentroid(tcu::TestContext&              testCtx,
-                                                                                                                        const std::string&             name,
-                                                                                                                        const ImageMSParams&   imageMSParams)
-       : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
-
-       void                    init                                                                    (void);
-       void                    initPrograms                                                    (vk::SourceCollections& programCollection) const;
-       TestInstance*   createInstance                                                  (Context&                               context) const;
-};
-
-MSInterpolationCaseBase* createMSCaseInterpolateAtSampleIgnoresCentroid (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
-{
-       return new MSCaseInterpolateAtSampleIgnoresCentroid(testCtx, name, imageMSParams);
-}
+class MSCaseInterpolateAtSampleIgnoresCentroid;
 
-void MSCaseInterpolateAtSampleIgnoresCentroid::init (void)
+template<> void MSCase<MSCaseInterpolateAtSampleIgnoresCentroid>::init (void)
 {
        m_testCtx.getLog()
                << tcu::TestLog::Message
@@ -1161,10 +422,10 @@ void MSCaseInterpolateAtSampleIgnoresCentroid::init (void)
                << "    => interpolateAtSample(screenSample, n) ~= interpolateAtSample(screenCentroid, n)\n"
                << tcu::TestLog::EndMessage;
 
-       MSInterpolationCaseBase::init();
+       MultisampleCaseBase::init();
 }
 
-void MSCaseInterpolateAtSampleIgnoresCentroid::initPrograms (vk::SourceCollections& programCollection) const
+template<> void MSCase<MSCaseInterpolateAtSampleIgnoresCentroid>::initPrograms (vk::SourceCollections& programCollection) const
 {
        // Create vertex shader
        std::ostringstream vs;
@@ -1195,7 +456,7 @@ void MSCaseInterpolateAtSampleIgnoresCentroid::initPrograms (vk::SourceCollectio
                << "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n"
                << "layout(location = 1)                  in vec2 fs_in_pos_screen_fragment;\n"
                << "\n"
-               << "layout(location = 0) out vec2 fs_out_color;\n"
+               << "layout(location = 0) out vec4 fs_out_color;\n"
                << "\n"
                << "void main (void)\n"
                << "{\n"
@@ -1206,38 +467,22 @@ void MSCaseInterpolateAtSampleIgnoresCentroid::initPrograms (vk::SourceCollectio
                << "    const bool valuesEqual = all(lessThan(abs(position_a - position_b), vec2(threshold)));\n"
                << "\n"
                << "    if (valuesEqual)\n"
-               << "            fs_out_color = vec2(0.0, 1.0);\n"
+               << "            fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
                << "    else\n"
-               << "            fs_out_color = vec2(1.0, 0.0);\n"
+               << "            fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
                << "}\n";
 
        programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
 }
 
-TestInstance* MSCaseInterpolateAtSampleIgnoresCentroid::createInstance (Context& context) const
+template<> TestInstance* MSCase<MSCaseInterpolateAtSampleIgnoresCentroid>::createInstance (Context& context) const
 {
-       return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
+       return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
 }
 
-class MSCaseInterpolateAtSampleConsistency : public MSInterpolationCaseBase
-{
-public:
-                                       MSCaseInterpolateAtSampleConsistency    (tcu::TestContext&              testCtx,
-                                                                                                                        const std::string&             name,
-                                                                                                                        const ImageMSParams&   imageMSParams)
-       : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
-
-       void                    init                                                                    (void);
-       void                    initPrograms                                                    (vk::SourceCollections& programCollection) const;
-       TestInstance*   createInstance                                                  (Context&                               context) const;
-};
+class MSCaseInterpolateAtSampleConsistency;
 
-MSInterpolationCaseBase* createMSCaseInterpolateAtSampleConsistency (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
-{
-       return new MSCaseInterpolateAtSampleConsistency(testCtx, name, imageMSParams);
-}
-
-void MSCaseInterpolateAtSampleConsistency::init (void)
+template<> void MSCase<MSCaseInterpolateAtSampleConsistency>::init (void)
 {
        m_testCtx.getLog()
                << tcu::TestLog::Message
@@ -1246,10 +491,10 @@ void MSCaseInterpolateAtSampleConsistency::init (void)
                << "    => interpolateAtSample(screenCentroid, sampleID) = screenSample\n"
                << tcu::TestLog::EndMessage;
 
-       MSInterpolationCaseBase::init();
+       MultisampleCaseBase::init();
 }
 
-void MSCaseInterpolateAtSampleConsistency::initPrograms (vk::SourceCollections& programCollection) const
+template<> void MSCase<MSCaseInterpolateAtSampleConsistency>::initPrograms (vk::SourceCollections& programCollection) const
 {
        // Create vertex shader
        std::ostringstream vs;
@@ -1280,7 +525,7 @@ void MSCaseInterpolateAtSampleConsistency::initPrograms (vk::SourceCollections&
                << "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n"
                << "layout(location = 1) sample   in vec2 fs_in_pos_screen_sample;\n"
                << "\n"
-               << "layout(location = 0) out vec2 fs_out_color;\n"
+               << "layout(location = 0) out vec4 fs_out_color;\n"
                << "\n"
                << "void main (void)\n"
                << "{\n"
@@ -1290,38 +535,22 @@ void MSCaseInterpolateAtSampleConsistency::initPrograms (vk::SourceCollections&
                << "    const bool  valuesEqual                            = all(lessThan(abs(pos_interpolated_at_sample - fs_in_pos_screen_sample), vec2(threshold)));\n"
                << "\n"
                << "    if (valuesEqual)\n"
-               << "            fs_out_color = vec2(0.0, 1.0);\n"
+               << "            fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
                << "    else\n"
-               << "            fs_out_color = vec2(1.0, 0.0);\n"
+               << "            fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
                << "}\n";
 
        programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
 }
 
-TestInstance* MSCaseInterpolateAtSampleConsistency::createInstance (Context& context) const
+template<> TestInstance* MSCase<MSCaseInterpolateAtSampleConsistency>::createInstance (Context& context) const
 {
-       return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
+       return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
 }
 
-class MSCaseInterpolateAtCentroidConsistency : public MSInterpolationCaseBase
-{
-public:
-                                       MSCaseInterpolateAtCentroidConsistency  (tcu::TestContext&              testCtx,
-                                                                                                                        const std::string&             name,
-                                                                                                                        const ImageMSParams&   imageMSParams)
-       : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
-
-       void                    init                                                                    (void);
-       void                    initPrograms                                                    (vk::SourceCollections& programCollection) const;
-       TestInstance*   createInstance                                                  (Context&                               context) const;
-};
-
-MSInterpolationCaseBase* createMSCaseInterpolateAtCentroidConsistency (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
-{
-       return new MSCaseInterpolateAtCentroidConsistency(testCtx, name, imageMSParams);
-}
+class MSCaseInterpolateAtCentroidConsistency;
 
-void MSCaseInterpolateAtCentroidConsistency::init (void)
+template<> void MSCase<MSCaseInterpolateAtCentroidConsistency>::init (void)
 {
        m_testCtx.getLog()
                << tcu::TestLog::Message
@@ -1330,10 +559,10 @@ void MSCaseInterpolateAtCentroidConsistency::init (void)
                << "    => interpolateAtCentroid(screenSample) = screenCentroid\n"
                << tcu::TestLog::EndMessage;
 
-       MSInterpolationCaseBase::init();
+       MultisampleCaseBase::init();
 }
 
-void MSCaseInterpolateAtCentroidConsistency::initPrograms (vk::SourceCollections& programCollection) const
+template<> void MSCase<MSCaseInterpolateAtCentroidConsistency>::initPrograms (vk::SourceCollections& programCollection) const
 {
        // Create vertex shader
        std::ostringstream vs;
@@ -1364,7 +593,7 @@ void MSCaseInterpolateAtCentroidConsistency::initPrograms (vk::SourceCollections
                << "layout(location = 0) sample   in vec2 fs_in_pos_screen_sample;\n"
                << "layout(location = 1) centroid in vec2 fs_in_pos_screen_centroid;\n"
                << "\n"
-               << "layout(location = 0) out vec2 fs_out_color;\n"
+               << "layout(location = 0) out vec4 fs_out_color;\n"
                << "\n"
                << "void main (void)\n"
                << "{\n"
@@ -1374,38 +603,22 @@ void MSCaseInterpolateAtCentroidConsistency::initPrograms (vk::SourceCollections
                << "    const bool valuesEqual                                  = all(lessThan(abs(pos_interpolated_at_centroid - fs_in_pos_screen_centroid), vec2(threshold)));\n"
                << "\n"
                << "    if (valuesEqual)\n"
-               << "            fs_out_color = vec2(0.0, 1.0);\n"
+               << "            fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
                << "    else\n"
-               << "            fs_out_color = vec2(1.0, 0.0);\n"
+               << "            fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
                << "}\n";
 
        programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
 }
 
-TestInstance* MSCaseInterpolateAtCentroidConsistency::createInstance (Context& context) const
+template<> TestInstance* MSCase<MSCaseInterpolateAtCentroidConsistency>::createInstance (Context& context) const
 {
-       return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
+       return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
 }
 
-class MSCaseInterpolateAtOffsetPixelCenter : public MSInterpolationCaseBase
-{
-public:
-                                       MSCaseInterpolateAtOffsetPixelCenter(tcu::TestContext&          testCtx,
-                                                                                                                const std::string&             name,
-                                                                                                                const ImageMSParams&   imageMSParams)
-       : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
-
-       void                    init                                                            (void);
-       void                    initPrograms                                            (vk::SourceCollections& programCollection) const;
-       TestInstance*   createInstance                                          (Context&                               context) const;
-};
-
-MSInterpolationCaseBase* createMSCaseInterpolateAtOffsetPixelCenter (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
-{
-       return new MSCaseInterpolateAtOffsetPixelCenter(testCtx, name, imageMSParams);
-}
+class MSCaseInterpolateAtOffsetPixelCenter;
 
-void MSCaseInterpolateAtOffsetPixelCenter::init (void)
+template<> void MSCase<MSCaseInterpolateAtOffsetPixelCenter>::init (void)
 {
        m_testCtx.getLog()
                << tcu::TestLog::Message
@@ -1414,10 +627,10 @@ void MSCaseInterpolateAtOffsetPixelCenter::init (void)
                << "    => interpolateAtOffset(screen, offset) should be \"varying value at the pixel center\" + offset"
                << tcu::TestLog::EndMessage;
 
-       MSInterpolationCaseBase::init();
+       MultisampleCaseBase::init();
 }
 
-void MSCaseInterpolateAtOffsetPixelCenter::initPrograms (vk::SourceCollections& programCollection) const
+template<> void MSCase<MSCaseInterpolateAtOffsetPixelCenter>::initPrograms (vk::SourceCollections& programCollection) const
 {
        // Create vertex shader
        std::ostringstream vs;
@@ -1448,7 +661,7 @@ void MSCaseInterpolateAtOffsetPixelCenter::initPrograms (vk::SourceCollections&
                << "layout(location = 0) in  vec2 fs_in_pos_screen;\n"
                << "layout(location = 1) in  vec2 fs_in_offset;\n"
                << "\n"
-               << "layout(location = 0) out vec2 fs_out_color;\n"
+               << "layout(location = 0) out vec4 fs_out_color;\n"
                << "\n"
                << "void main (void)\n"
                << "{\n"
@@ -1465,38 +678,22 @@ void MSCaseInterpolateAtOffsetPixelCenter::initPrograms (vk::SourceCollections&
                << "    }\n"
                << "\n"
                << "    if (valuesEqual)\n"
-               << "        fs_out_color = vec2(0.0, 1.0);\n"
+               << "        fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
                << "    else\n"
-               << "        fs_out_color = vec2(1.0, 0.0);\n"
+               << "        fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
                << "}\n";
 
        programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
 }
 
-TestInstance* MSCaseInterpolateAtOffsetPixelCenter::createInstance (Context& context) const
+template<> TestInstance* MSCase<MSCaseInterpolateAtOffsetPixelCenter>::createInstance (Context& context) const
 {
-       return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
+       return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
 }
 
-class MSCaseInterpolateAtOffsetSamplePosition : public MSInterpolationCaseBase
-{
-public:
-                                       MSCaseInterpolateAtOffsetSamplePosition (tcu::TestContext&              testCtx,
-                                                                                                                        const std::string&             name,
-                                                                                                                        const ImageMSParams&   imageMSParams)
-       : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
-
-       void                    init                                                                    (void);
-       void                    initPrograms                                                    (vk::SourceCollections& programCollection) const;
-       TestInstance*   createInstance                                                  (Context&                               context) const;
-};
-
-MSInterpolationCaseBase* createMSCaseInterpolateAtOffsetSamplePosition (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
-{
-       return new MSCaseInterpolateAtOffsetSamplePosition(testCtx, name, imageMSParams);
-}
+class MSCaseInterpolateAtOffsetSamplePosition;
 
-void MSCaseInterpolateAtOffsetSamplePosition::init (void)
+template<> void MSCase<MSCaseInterpolateAtOffsetSamplePosition>::init (void)
 {
        m_testCtx.getLog()
                << tcu::TestLog::Message
@@ -1506,10 +703,10 @@ void MSCaseInterpolateAtOffsetSamplePosition::init (void)
                << "    => interpolateAtOffset(screenFragment, samplePosition - (0.5,0.5)) = screenSample"
                << tcu::TestLog::EndMessage;
 
-       MSInterpolationCaseBase::init();
+       MultisampleCaseBase::init();
 }
 
-void MSCaseInterpolateAtOffsetSamplePosition::initPrograms (vk::SourceCollections& programCollection) const
+template<> void MSCase<MSCaseInterpolateAtOffsetSamplePosition>::initPrograms (vk::SourceCollections& programCollection) const
 {
        // Create vertex shader
        std::ostringstream vs;
@@ -1540,7 +737,7 @@ void MSCaseInterpolateAtOffsetSamplePosition::initPrograms (vk::SourceCollection
                << "layout(location = 0)                in vec2 fs_in_pos_screen_fragment;\n"
                << "layout(location = 1) sample in vec2 fs_in_pos_screen_sample;\n"
                << "\n"
-               << "layout(location = 0) out vec2 fs_out_color;\n"
+               << "layout(location = 0) out vec4 fs_out_color;\n"
                << "\n"
                << "void main (void)\n"
                << "{\n"
@@ -1551,65 +748,46 @@ void MSCaseInterpolateAtOffsetSamplePosition::initPrograms (vk::SourceCollection
                << "    const bool valuesEqual                            = all(lessThan(abs(pos_interpolated_at_offset - fs_in_pos_screen_sample), vec2(threshold)));\n"
                << "\n"
                << "    if (valuesEqual)\n"
-               << "            fs_out_color = vec2(0.0, 1.0);\n"
+               << "            fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
                << "    else\n"
-               << "            fs_out_color = vec2(1.0, 0.0);\n"
+               << "            fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
                << "}\n";
 
        programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
 }
 
-TestInstance* MSCaseInterpolateAtOffsetSamplePosition::createInstance (Context& context) const
+template<> TestInstance* MSCase<MSCaseInterpolateAtOffsetSamplePosition>::createInstance (Context& context) const
 {
-       return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
+       return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
 }
 
-class MSInstanceInterpolateBarycentricCoordinates : public MSInterpolationInstanceBase
-{
-public:
-                                       MSInstanceInterpolateBarycentricCoordinates     (Context&                               context,
-                                                                                                                                const ImageMSParams&   imageMSParams)
-       : MSInterpolationInstanceBase(context, imageMSParams) {}
-
-       VertexDataDesc  getVertexDataDescripton                                         (void) const;
-       void                    uploadVertexData                                                        (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const;
-       tcu::TestStatus verifyResolvedImage                                                     (const tcu::ConstPixelBufferAccess&     imageData) const;
-
-protected:
-       struct VertexData
-       {
-               VertexData(const tcu::Vec4& posNdc, const tcu::Vec3& barCoord) : positionNdc(posNdc), barycentricCoord(barCoord) {}
+class MSInstanceInterpolateBarycentricCoordinates;
 
-               tcu::Vec4 positionNdc;
-               tcu::Vec3 barycentricCoord;
-       };
-};
-
-MSInterpolationInstanceBase::VertexDataDesc MSInstanceInterpolateBarycentricCoordinates::getVertexDataDescripton (void) const
+template<> MSInstanceBaseResolve::VertexDataDesc MSInstance<MSInstanceInterpolateBarycentricCoordinates>::getVertexDataDescripton (void) const
 {
        VertexDataDesc vertexDataDesc;
 
        vertexDataDesc.verticesCount            = 3u;
-       vertexDataDesc.dataStride                       = sizeof(VertexData);
+       vertexDataDesc.dataStride                       = sizeof(VertexDataNdcBarycentric);
        vertexDataDesc.dataSize                         = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
        vertexDataDesc.primitiveTopology        = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
 
        const VkVertexInputAttributeDescription vertexAttribPositionNdc =
        {
-               0u,                                                                                     // deUint32     location;
-               0u,                                                                                     // deUint32     binding;
-               VK_FORMAT_R32G32B32A32_SFLOAT,                          // VkFormat     format;
-               DE_OFFSET_OF(VertexData, positionNdc),          // deUint32     offset;
+               0u,                                                                                                                     // deUint32     location;
+               0u,                                                                                                                     // deUint32     binding;
+               VK_FORMAT_R32G32B32A32_SFLOAT,                                                          // VkFormat     format;
+               DE_OFFSET_OF(VertexDataNdcBarycentric, positionNdc),            // deUint32     offset;
        };
 
        vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
 
        const VkVertexInputAttributeDescription vertexAttrBarCoord =
        {
-               1u,                                                                                     // deUint32     location;
-               0u,                                                                                     // deUint32     binding;
-               VK_FORMAT_R32G32B32_SFLOAT,                                     // VkFormat     format;
-               DE_OFFSET_OF(VertexData, barycentricCoord),     // deUint32     offset;
+               1u,                                                                                                                     // deUint32     location;
+               0u,                                                                                                                     // deUint32     binding;
+               VK_FORMAT_R32G32B32_SFLOAT,                                                                     // VkFormat     format;
+               DE_OFFSET_OF(VertexDataNdcBarycentric, barycentricCoord),       // deUint32     offset;
        };
 
        vertexDataDesc.vertexAttribDescVec.push_back(vertexAttrBarCoord);
@@ -1617,52 +795,29 @@ MSInterpolationInstanceBase::VertexDataDesc MSInstanceInterpolateBarycentricCoor
        return vertexDataDesc;
 }
 
-void MSInstanceInterpolateBarycentricCoordinates::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
+template<> void MSInstance<MSInstanceInterpolateBarycentricCoordinates>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
 {
        // Create buffer storing vertex data
-       std::vector<VertexData> vertices;
+       std::vector<VertexDataNdcBarycentric> vertices;
 
-       vertices.push_back(VertexData(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 0.0f, 1.0f)));
-       vertices.push_back(VertexData(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec3(1.0f, 0.0f, 0.0f)));
-       vertices.push_back(VertexData(tcu::Vec4( 1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 1.0f, 0.0f)));
+       vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 0.0f, 1.0f)));
+       vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f), tcu::Vec3(1.0f, 0.0f, 0.0f)));
+       vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 1.0f, 0.0f)));
 
        deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
 }
 
-tcu::TestStatus MSInstanceInterpolateBarycentricCoordinates::verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const
+template<> tcu::TestStatus MSInstance<MSInstanceInterpolateBarycentricCoordinates>::verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS) const
 {
-       for (deInt32 z = 0u; z < imageData.getDepth();  ++z)
-       for (deInt32 y = 0u; y < imageData.getHeight(); ++y)
-       for (deInt32 x = 0u; x < imageData.getWidth();  ++x)
-       {
-               const deInt32 firstComponent = imageData.getPixelInt(x, y, z).x();
-
-               if (firstComponent > 0)
-                       return tcu::TestStatus::fail("Failed");
-       }
+       if (checkForError(imageRSInfo, dataRS, 0))
+               return tcu::TestStatus::fail("Failed");
 
        return tcu::TestStatus::pass("Passed");
 }
 
-class MSCaseCentroidQualifierInsidePrimitive : public MSInterpolationCaseBase
-{
-public:
-                                       MSCaseCentroidQualifierInsidePrimitive  (tcu::TestContext&              testCtx,
-                                                                                                                        const std::string&             name,
-                                                                                                                        const ImageMSParams&   imageMSParams)
-       : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
-
-       void                    init                                                                    (void);
-       void                    initPrograms                                                    (vk::SourceCollections& programCollection) const;
-       TestInstance*   createInstance                                                  (Context&                               context) const;
-};
-
-MSInterpolationCaseBase* createMSCaseCentroidQualifierInsidePrimitive (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
-{
-       return new MSCaseCentroidQualifierInsidePrimitive(testCtx, name, imageMSParams);
-}
+class MSCaseCentroidQualifierInsidePrimitive;
 
-void MSCaseCentroidQualifierInsidePrimitive::init (void)
+template<> void MSCase<MSCaseCentroidQualifierInsidePrimitive>::init (void)
 {
        m_testCtx.getLog()
                << tcu::TestLog::Message
@@ -1671,10 +826,10 @@ void MSCaseCentroidQualifierInsidePrimitive::init (void)
                << "    => After interpolation we expect barycentric.xyz >= 0.0 && barycentric.xyz <= 1.0\n"
                << tcu::TestLog::EndMessage;
 
-       MSInterpolationCaseBase::init();
+       MultisampleCaseBase::init();
 }
 
-void MSCaseCentroidQualifierInsidePrimitive::initPrograms (vk::SourceCollections& programCollection) const
+template<> void MSCase<MSCaseCentroidQualifierInsidePrimitive>::initPrograms (vk::SourceCollections& programCollection) const
 {
        // Create vertex shader
        std::ostringstream vs;
@@ -1702,58 +857,26 @@ void MSCaseCentroidQualifierInsidePrimitive::initPrograms (vk::SourceCollections
        fs << "#version 440\n"
                << "layout(location = 0) centroid in vec3 fs_in_barCoord;\n"
                << "\n"
-               << "layout(location = 0) out vec2 fs_out_color;\n"
+               << "layout(location = 0) out vec4 fs_out_color;\n"
                << "\n"
                << "void main (void)\n"
                << "{\n"
                << "    if( all(greaterThanEqual(fs_in_barCoord, vec3(0.0))) && all(lessThanEqual(fs_in_barCoord, vec3(1.0))) )\n"
-               << "                    fs_out_color = vec2(0.0, 1.0);\n"
+               << "                    fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
                << "    else\n"
-               << "                    fs_out_color = vec2(1.0, 0.0);\n"
+               << "                    fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
                << "}\n";
 
        programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
 }
 
-TestInstance* MSCaseCentroidQualifierInsidePrimitive::createInstance (Context& context) const
+template<> TestInstance* MSCase<MSCaseCentroidQualifierInsidePrimitive>::createInstance (Context& context) const
 {
-       return new MSInstanceInterpolateBarycentricCoordinates(context, m_imageMSParams);
+       return new MSInstance<MSInstanceInterpolateBarycentricCoordinates>(context, m_imageMSParams);
 }
 
 } // multisample
 
-tcu::TestCaseGroup* makeGroup( multisample::MSInterpolationCaseFuncPtr createCaseFuncPtr,
-                                                               tcu::TestContext&                                               testCtx,
-                                                               const std::string                                               groupName,
-                                                               const tcu::UVec3                                                imageSizes[],
-                                                               const deUint32                                                  imageSizesElemCount,
-                                                               const vk::VkSampleCountFlagBits                 imageSamples[],
-                                                               const deUint32                                                  imageSamplesElemCount)
-{
-       de::MovePtr<tcu::TestCaseGroup> caseGroup(new tcu::TestCaseGroup(testCtx, groupName.c_str(), ""));
-
-       for (deUint32 imageSizeNdx = 0u; imageSizeNdx < imageSizesElemCount; ++imageSizeNdx)
-       {
-               const tcu::UVec3        imageSize = imageSizes[imageSizeNdx];
-               std::ostringstream      imageSizeStream;
-
-               imageSizeStream << imageSize.x() << "_" << imageSize.y() << "_" << imageSize.z();
-
-               de::MovePtr<tcu::TestCaseGroup> sizeGroup(new tcu::TestCaseGroup(testCtx, imageSizeStream.str().c_str(), ""));
-
-               for (deUint32 imageSamplesNdx = 0u; imageSamplesNdx < imageSamplesElemCount; ++imageSamplesNdx)
-               {
-                       const vk::VkSampleCountFlagBits         samples                 = imageSamples[imageSamplesNdx];
-                       const multisample::ImageMSParams        imageMSParams   = multisample::ImageMSParams(samples, imageSize);
-
-                       sizeGroup->addChild(createCaseFuncPtr(testCtx, "samples_" + de::toString(samples), imageMSParams));
-               }
-
-               caseGroup->addChild(sizeGroup.release());
-       }
-       return caseGroup.release();
-}
-
 tcu::TestCaseGroup* createMultisampleInterpolationTests (tcu::TestContext& testCtx)
 {
        de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "multisample_interpolation", "Multisample Interpolation"));
@@ -1789,21 +912,21 @@ tcu::TestCaseGroup* createMultisampleInterpolationTests (tcu::TestContext& testC
 
                de::MovePtr<tcu::TestCaseGroup> sizeGroup(new tcu::TestCaseGroup(testCtx, imageSizeStream.str().c_str(), ""));
 
-               sizeGroup->addChild(new multisample::MSCaseInterpolateAtSampleSingleSample(testCtx, "samples_" + de::toString(1), imageSize));
+               sizeGroup->addChild(multisample::MSCase<multisample::MSCaseInterpolateAtSampleSingleSample>::createCase(testCtx, "samples_" + de::toString(1), multisample::ImageMSParams(vk::VK_SAMPLE_COUNT_1_BIT, imageSize)));
 
                caseGroup->addChild(sizeGroup.release());
        }
 
        testGroup->addChild(caseGroup.release());
 
-       testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtSampleDistinctValues,       testCtx, "sample_interpolate_at_distinct_values",       imageSizes, sizesElemCount, imageSamples, samplesElemCount));
-       testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtSampleIgnoresCentroid,      testCtx, "sample_interpolate_at_ignores_centroid",      imageSizes, sizesElemCount, imageSamples, samplesElemCount));
-       testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtSampleConsistency,          testCtx, "sample_interpolate_at_consistency",           imageSizes, sizesElemCount, imageSamples, samplesElemCount));
-       testGroup->addChild(makeGroup(multisample::createMSCaseSampleQualifierDistinctValues,           testCtx, "sample_qualifier_distinct_values",            imageSizes, sizesElemCount, imageSamples, samplesElemCount));
-       testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtCentroidConsistency,        testCtx, "centroid_interpolate_at_consistency",         imageSizes, sizesElemCount, imageSamples, samplesElemCount));
-       testGroup->addChild(makeGroup(multisample::createMSCaseCentroidQualifierInsidePrimitive,        testCtx, "centroid_qualifier_inside_primitive",         imageSizes, sizesElemCount, imageSamples, samplesElemCount));
-       testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtOffsetPixelCenter,          testCtx, "offset_interpolate_at_pixel_center",          imageSizes, sizesElemCount, imageSamples, samplesElemCount));
-       testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtOffsetSamplePosition,       testCtx, "offset_interpolate_at_sample_position",       imageSizes, sizesElemCount, imageSamples, samplesElemCount));
+       testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleDistinctValues> >     (testCtx, "sample_interpolate_at_distinct_values",      imageSizes, sizesElemCount, imageSamples, samplesElemCount));
+       testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleIgnoresCentroid> >(testCtx, "sample_interpolate_at_ignores_centroid", imageSizes, sizesElemCount, imageSamples, samplesElemCount));
+       testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleConsistency> >        (testCtx, "sample_interpolate_at_consistency",          imageSizes, sizesElemCount, imageSamples, samplesElemCount));
+       testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleQualifierDistinctValues> >         (testCtx, "sample_qualifier_distinct_values",           imageSizes, sizesElemCount, imageSamples, samplesElemCount));
+       testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtCentroidConsistency> >      (testCtx, "centroid_interpolate_at_consistency",        imageSizes, sizesElemCount, imageSamples, samplesElemCount));
+       testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseCentroidQualifierInsidePrimitive> >      (testCtx, "centroid_qualifier_inside_primitive",        imageSizes, sizesElemCount, imageSamples, samplesElemCount));
+       testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetPixelCenter> >        (testCtx, "offset_interpolate_at_pixel_center",         imageSizes, sizesElemCount, imageSamples, samplesElemCount));
+       testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetSamplePosition> >     (testCtx, "offset_interpolate_at_sample_position",      imageSizes, sizesElemCount, imageSamples, samplesElemCount));
 
        return testGroup.release();
 }
index c4052ca..74ae7ca 100644 (file)
@@ -4,8 +4,7 @@
  * Vulkan Conformance Tests
  * ------------------------
  *
- * Copyright (c) 2015 The Khronos Group Inc.
- * Copyright (c) 2015 Imagination Technologies Ltd.
+ * Copyright (c) 2016 The Khronos Group Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleShaderBuiltInTests.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleShaderBuiltInTests.cpp
new file mode 100644 (file)
index 0000000..344cf9e
--- /dev/null
@@ -0,0 +1,1077 @@
+/*------------------------------------------------------------------------
+* Vulkan Conformance Tests
+* ------------------------
+*
+* Copyright (c) 2016 The Khronos Group Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+*//*
+* \file vktPipelineMultisampleShaderBuiltInTests.cpp
+* \brief Multisample Shader BuiltIn Tests
+*//*--------------------------------------------------------------------*/
+
+#include "vktPipelineMultisampleShaderBuiltInTests.hpp"
+#include "vktPipelineMultisampleBaseResolveAndPerSampleFetch.hpp"
+#include "vktPipelineMakeUtil.hpp"
+#include "vkBuilderUtil.hpp"
+#include "vkQueryUtil.hpp"
+#include "tcuVectorUtil.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+namespace multisample
+{
+
+using namespace vk;
+
+struct VertexDataNdc
+{
+       VertexDataNdc (const tcu::Vec4& posNdc) : positionNdc(posNdc) {}
+
+       tcu::Vec4 positionNdc;
+};
+
+MultisampleInstanceBase::VertexDataDesc getVertexDataDescriptonNdc (void)
+{
+       MultisampleInstanceBase::VertexDataDesc vertexDataDesc;
+
+       vertexDataDesc.verticesCount     = 4u;
+       vertexDataDesc.dataStride                = sizeof(VertexDataNdc);
+       vertexDataDesc.dataSize                  = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
+       vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+
+       const VkVertexInputAttributeDescription vertexAttribPositionNdc =
+       {
+               0u,                                                                                     // deUint32     location;
+               0u,                                                                                     // deUint32     binding;
+               VK_FORMAT_R32G32B32A32_SFLOAT,                          // VkFormat     format;
+               DE_OFFSET_OF(VertexDataNdc, positionNdc),       // deUint32     offset;
+       };
+
+       vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
+
+       return vertexDataDesc;
+}
+
+void uploadVertexDataNdc (const Allocation& vertexBufferAllocation, const MultisampleInstanceBase::VertexDataDesc& vertexDataDescripton)
+{
+       std::vector<VertexDataNdc> vertices;
+
+       vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f)));
+       vertices.push_back(VertexDataNdc(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f)));
+       vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f)));
+       vertices.push_back(VertexDataNdc(tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f)));
+
+       deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
+}
+
+struct VertexDataNdcScreen
+{
+       VertexDataNdcScreen (const tcu::Vec4& posNdc, const tcu::Vec2& posScreen) : positionNdc(posNdc), positionScreen(posScreen) {}
+
+       tcu::Vec4 positionNdc;
+       tcu::Vec2 positionScreen;
+};
+
+MultisampleInstanceBase::VertexDataDesc getVertexDataDescriptonNdcScreen (void)
+{
+       MultisampleInstanceBase::VertexDataDesc vertexDataDesc;
+
+       vertexDataDesc.verticesCount     = 4u;
+       vertexDataDesc.dataStride                = sizeof(VertexDataNdcScreen);
+       vertexDataDesc.dataSize                  = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
+       vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+
+       const VkVertexInputAttributeDescription vertexAttribPositionNdc =
+       {
+               0u,                                                                                                     // deUint32     location;
+               0u,                                                                                                     // deUint32     binding;
+               VK_FORMAT_R32G32B32A32_SFLOAT,                                          // VkFormat     format;
+               DE_OFFSET_OF(VertexDataNdcScreen, positionNdc),         // deUint32     offset;
+       };
+
+       vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
+
+       const VkVertexInputAttributeDescription vertexAttribPositionScreen =
+       {
+               1u,                                                                                                     // deUint32     location;
+               0u,                                                                                                     // deUint32     binding;
+               VK_FORMAT_R32G32_SFLOAT,                                                        // VkFormat     format;
+               DE_OFFSET_OF(VertexDataNdcScreen, positionScreen),      // deUint32     offset;
+       };
+
+       vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionScreen);
+
+       return vertexDataDesc;
+}
+
+void uploadVertexDataNdcScreen (const Allocation& vertexBufferAllocation, const MultisampleInstanceBase::VertexDataDesc& vertexDataDescripton, const tcu::Vec2& screenSize)
+{
+       std::vector<VertexDataNdcScreen> vertices;
+
+       vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, 0.0f)));
+       vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(screenSize.x(), 0.0f)));
+       vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, screenSize.y())));
+       vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f), tcu::Vec2(screenSize.x(), screenSize.y())));
+
+       deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
+}
+
+bool checkForErrorMS (const vk::VkImageCreateInfo& imageMSInfo, const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, const deUint32 errorCompNdx)
+{
+       const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
+
+       for (deUint32 z = 0u; z < imageMSInfo.extent.depth;  ++z)
+       for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
+       for (deUint32 x = 0u; x < imageMSInfo.extent.width;  ++x)
+       {
+               for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
+               {
+                       const deUint32 errorComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z)[errorCompNdx];
+
+                       if (errorComponent > 0)
+                               return true;
+               }
+       }
+
+       return false;
+}
+
+bool checkForErrorRS (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS, const deUint32 errorCompNdx)
+{
+       for (deUint32 z = 0u; z < imageRSInfo.extent.depth;  ++z)
+       for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
+       for (deUint32 x = 0u; x < imageRSInfo.extent.width;  ++x)
+       {
+               const deUint32 errorComponent = dataRS.getPixelUint(x, y, z)[errorCompNdx];
+
+               if (errorComponent > 0)
+                       return true;
+       }
+
+       return false;
+}
+
+template <typename CaseClassName>
+class MSCase : public MSCaseBaseResolveAndPerSampleFetch
+{
+public:
+                                                               MSCase                  (tcu::TestContext&              testCtx,
+                                                                                                const std::string&             name,
+                                                                                                const ImageMSParams&   imageMSParams)
+                                                               : MSCaseBaseResolveAndPerSampleFetch(testCtx, name, imageMSParams) {}
+
+       void                                            init                    (void);
+       void                                            initPrograms    (vk::SourceCollections& programCollection) const;
+       TestInstance*                           createInstance  (Context&                               context) const;
+       static MultisampleCaseBase*     createCase              (tcu::TestContext&              testCtx,
+                                                                                                const std::string&             name,
+                                                                                                const ImageMSParams&   imageMSParams);
+};
+
+template <typename CaseClassName>
+MultisampleCaseBase* MSCase<CaseClassName>::createCase (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
+{
+       return new MSCase<CaseClassName>(testCtx, name, imageMSParams);
+}
+
+template <typename InstanceClassName>
+class MSInstance : public MSInstanceBaseResolveAndPerSampleFetch
+{
+public:
+                                       MSInstance                              (Context&                                                                                       context,
+                                                                                        const ImageMSParams&                                                           imageMSParams)
+                                       : MSInstanceBaseResolveAndPerSampleFetch(context, imageMSParams) {}
+
+       VertexDataDesc  getVertexDataDescripton (void) const;
+       void                    uploadVertexData                (const Allocation&                                                                      vertexBufferAllocation,
+                                                                                        const VertexDataDesc&                                                          vertexDataDescripton) const;
+
+       tcu::TestStatus verifyImageData                 (const vk::VkImageCreateInfo&                                           imageMSInfo,
+                                                                                        const vk::VkImageCreateInfo&                                           imageRSInfo,
+                                                                                        const std::vector<tcu::ConstPixelBufferAccess>&        dataPerSample,
+                                                                                        const tcu::ConstPixelBufferAccess&                                     dataRS) const;
+};
+
+class MSInstanceSampleID;
+
+template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleID>::getVertexDataDescripton (void) const
+{
+       return getVertexDataDescriptonNdc();
+}
+
+template<> void MSInstance<MSInstanceSampleID>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
+{
+       uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
+}
+
+template<> tcu::TestStatus MSInstance<MSInstanceSampleID>::verifyImageData     (const vk::VkImageCreateInfo&                                           imageMSInfo,
+                                                                                                                                                        const vk::VkImageCreateInfo&                                           imageRSInfo,
+                                                                                                                                                        const std::vector<tcu::ConstPixelBufferAccess>&        dataPerSample,
+                                                                                                                                                        const tcu::ConstPixelBufferAccess&                                     dataRS) const
+{
+       DE_UNREF(imageRSInfo);
+       DE_UNREF(dataRS);
+
+       const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
+
+       for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
+       {
+               for (deUint32 z = 0u; z < imageMSInfo.extent.depth;  ++z)
+               for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
+               for (deUint32 x = 0u; x < imageMSInfo.extent.width;  ++x)
+               {
+                       const deUint32 sampleID = dataPerSample[sampleNdx].getPixelUint(x, y, z).x();
+
+                       if (sampleID != sampleNdx)
+                               return tcu::TestStatus::fail("gl_SampleID does not have correct value");
+               }
+       }
+
+       return tcu::TestStatus::pass("Passed");
+}
+
+class MSCaseSampleID;
+
+template<> void MSCase<MSCaseSampleID>::init (void)
+{
+       m_testCtx.getLog()
+               << tcu::TestLog::Message
+               << "Writing gl_SampleID to the red channel of the texture and verifying texture values.\n"
+               << "Expecting value N at sample index N of a multisample texture.\n"
+               << tcu::TestLog::EndMessage;
+
+       MultisampleCaseBase::init();
+}
+
+template<> void MSCase<MSCaseSampleID>::initPrograms (vk::SourceCollections& programCollection) const
+{
+       MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
+
+       // Create vertex shader
+       std::ostringstream vs;
+
+       vs << "#version 440\n"
+               << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
+               << "\n"
+               << "out gl_PerVertex {\n"
+               << "    vec4  gl_Position;\n"
+               << "};\n"
+               << "void main (void)\n"
+               << "{\n"
+               << "    gl_Position     = vs_in_position_ndc;\n"
+               << "}\n";
+
+       programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
+
+       // Create fragment shader
+       std::ostringstream fs;
+
+       fs << "#version 440\n"
+               << "\n"
+               << "layout(location = 0) out vec4 fs_out_color;\n"
+               << "\n"
+               << "void main (void)\n"
+               << "{\n"
+               << "    fs_out_color = vec4(float(gl_SampleID) / float(255), 0.0, 0.0, 1.0);\n"
+               << "}\n";
+
+       programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
+}
+
+template<> TestInstance* MSCase<MSCaseSampleID>::createInstance (Context& context) const
+{
+       return new MSInstance<MSInstanceSampleID>(context, m_imageMSParams);
+}
+
+class MSInstanceSamplePosDistribution;
+
+template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSamplePosDistribution>::getVertexDataDescripton (void) const
+{
+       return getVertexDataDescriptonNdc();
+}
+
+template<> void MSInstance<MSInstanceSamplePosDistribution>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
+{
+       uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
+}
+
+template<> tcu::TestStatus MSInstance<MSInstanceSamplePosDistribution>::verifyImageData        (const vk::VkImageCreateInfo&                                           imageMSInfo,
+                                                                                                                                                                                const vk::VkImageCreateInfo&                                           imageRSInfo,
+                                                                                                                                                                                const std::vector<tcu::ConstPixelBufferAccess>&        dataPerSample,
+                                                                                                                                                                                const tcu::ConstPixelBufferAccess&                                     dataRS) const
+{
+       const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
+
+       // approximate Bates distribution as normal
+       const float variance = (1.0f / (12.0f * (float)numSamples));
+       const float standardDeviation = deFloatSqrt(variance);
+
+       // 95% of means of sample positions are within 2 standard deviations if
+       // they were randomly assigned. Sample patterns are expected to be more
+       // uniform than a random pattern.
+       const float distanceThreshold = 2.0f * standardDeviation;
+
+       for (deUint32 z = 0u; z < imageRSInfo.extent.depth;  ++z)
+       for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
+       for (deUint32 x = 0u; x < imageRSInfo.extent.width;  ++x)
+       {
+               const deUint32 errorComponent = dataRS.getPixelUint(x, y, z).z();
+
+               if (errorComponent > 0)
+                       return tcu::TestStatus::fail("gl_SamplePosition is not within interval [0,1]");
+
+               if (numSamples >= VK_SAMPLE_COUNT_4_BIT)
+               {
+                       const tcu::Vec2 averageSamplePos        = tcu::Vec2((float)dataRS.getPixelUint(x, y, z).x() / 255.0f, (float)dataRS.getPixelUint(x, y, z).y() / 255.0f);
+                       const tcu::Vec2 distanceFromCenter      = tcu::abs(averageSamplePos - tcu::Vec2(0.5f, 0.5f));
+
+                       if (distanceFromCenter.x() > distanceThreshold || distanceFromCenter.y() > distanceThreshold)
+                               return tcu::TestStatus::fail("Sample positions are not uniformly distributed within the pixel");
+               }
+       }
+
+       for (deUint32 z = 0u; z < imageMSInfo.extent.depth;  ++z)
+       for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
+       for (deUint32 x = 0u; x < imageMSInfo.extent.width;  ++x)
+       {
+               std::vector<tcu::Vec2> samplePositions(numSamples);
+
+               for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
+               {
+                       const deUint32 errorComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z).z();
+
+                       if (errorComponent > 0)
+                               return tcu::TestStatus::fail("gl_SamplePosition is not within interval [0,1]");
+
+                       samplePositions[sampleNdx] = tcu::Vec2( (float)dataPerSample[sampleNdx].getPixelUint(x, y, z).x() / 255.0f,
+                                                                                                       (float)dataPerSample[sampleNdx].getPixelUint(x, y, z).y() / 255.0f);
+               }
+
+               for (deUint32 sampleNdxA = 0u;                          sampleNdxA < numSamples; ++sampleNdxA)
+               for (deUint32 sampleNdxB = sampleNdxA + 1u; sampleNdxB < numSamples; ++sampleNdxB)
+               {
+                       if (samplePositions[sampleNdxA] == samplePositions[sampleNdxB])
+                               return tcu::TestStatus::fail("Two samples have the same position");
+               }
+
+               if (numSamples >= VK_SAMPLE_COUNT_4_BIT)
+               {
+                       tcu::Vec2 averageSamplePos(0.0f, 0.0f);
+
+                       for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
+                       {
+                               averageSamplePos.x() += samplePositions[sampleNdx].x();
+                               averageSamplePos.y() += samplePositions[sampleNdx].y();
+                       }
+
+                       averageSamplePos.x() /= (float)numSamples;
+                       averageSamplePos.y() /= (float)numSamples;
+
+                       const tcu::Vec2 distanceFromCenter = tcu::abs(averageSamplePos - tcu::Vec2(0.5f, 0.5f));
+
+                       if (distanceFromCenter.x() > distanceThreshold || distanceFromCenter.y() > distanceThreshold)
+                               return tcu::TestStatus::fail("Sample positions are not uniformly distributed within the pixel");
+               }
+       }
+
+       return tcu::TestStatus::pass("Passed");
+}
+
+class MSCaseSamplePosDistribution;
+
+template<> void MSCase<MSCaseSamplePosDistribution>::init (void)
+{
+       m_testCtx.getLog()
+               << tcu::TestLog::Message
+               << "Verifying gl_SamplePosition value with multisample targets:\n"
+               << "    a) Expect legal sample position.\n"
+               << "    b) Sample position is unique within the set of all sample positions of a pixel.\n"
+               << "    c) Sample position distribution is uniform or almost uniform.\n"
+               << tcu::TestLog::EndMessage;
+
+       MultisampleCaseBase::init();
+}
+
+template<> void MSCase<MSCaseSamplePosDistribution>::initPrograms (vk::SourceCollections& programCollection) const
+{
+       MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
+
+       // Create vertex shader
+       std::ostringstream vs;
+
+       vs << "#version 440\n"
+               << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
+               << "\n"
+               << "out gl_PerVertex {\n"
+               << "    vec4  gl_Position;\n"
+               << "};\n"
+               << "void main (void)\n"
+               << "{\n"
+               << "    gl_Position     = vs_in_position_ndc;\n"
+               << "}\n";
+
+       programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
+
+       // Create fragment shader
+       std::ostringstream fs;
+
+       fs << "#version 440\n"
+               << "\n"
+               << "layout(location = 0) out vec4 fs_out_color;\n"
+               << "\n"
+               << "void main (void)\n"
+               << "{\n"
+               << "    if (gl_SamplePosition.x < 0.0 || gl_SamplePosition.x > 1.0 || gl_SamplePosition.y < 0.0 || gl_SamplePosition.y > 1.0)\n"
+               "               fs_out_color = vec4(0.0, 0.0, 1.0, 1.0);\n"
+               "       else\n"
+               "               fs_out_color = vec4(gl_SamplePosition.x, gl_SamplePosition.y, 0.0, 1.0);\n"
+               "}\n";
+
+       programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
+}
+
+template<> TestInstance* MSCase<MSCaseSamplePosDistribution>::createInstance (Context& context) const
+{
+       return new MSInstance<MSInstanceSamplePosDistribution>(context, m_imageMSParams);
+}
+
+class MSInstanceSamplePosCorrectness;
+
+template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSamplePosCorrectness>::getVertexDataDescripton (void) const
+{
+       return getVertexDataDescriptonNdcScreen();
+}
+
+template<> void MSInstance<MSInstanceSamplePosCorrectness>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
+{
+       const tcu::UVec3 layerSize = getLayerSize(IMAGE_TYPE_2D, m_imageMSParams.imageSize);
+
+       uploadVertexDataNdcScreen(vertexBufferAllocation, vertexDataDescripton, tcu::Vec2(static_cast<float>(layerSize.x()), static_cast<float>(layerSize.y())));
+}
+
+template<> tcu::TestStatus MSInstance<MSInstanceSamplePosCorrectness>::verifyImageData (const vk::VkImageCreateInfo&                                           imageMSInfo,
+                                                                                                                                                                                const vk::VkImageCreateInfo&                                           imageRSInfo,
+                                                                                                                                                                                const std::vector<tcu::ConstPixelBufferAccess>&        dataPerSample,
+                                                                                                                                                                                const tcu::ConstPixelBufferAccess&                                     dataRS) const
+{
+       if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
+               return tcu::TestStatus::fail("Varying values are not sampled at gl_SamplePosition");
+
+       if (checkForErrorRS(imageRSInfo, dataRS, 0))
+               return tcu::TestStatus::fail("Varying values are not sampled at gl_SamplePosition");
+
+       return tcu::TestStatus::pass("Passed");
+}
+
+class MSCaseSamplePosCorrectness;
+
+template<> void MSCase<MSCaseSamplePosCorrectness>::init (void)
+{
+       m_testCtx.getLog()
+               << tcu::TestLog::Message
+               << "Verifying gl_SamplePosition correctness:\n"
+               << "    1) Varying values should be sampled at the sample position.\n"
+               << "            => fract(position_screen) == gl_SamplePosition\n"
+               << tcu::TestLog::EndMessage;
+
+       MultisampleCaseBase::init();
+}
+
+template<> void MSCase<MSCaseSamplePosCorrectness>::initPrograms (vk::SourceCollections& programCollection) const
+{
+       MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
+
+       // Create vertex shaders
+       std::ostringstream vs;
+
+       vs      << "#version 440\n"
+               << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
+               << "layout(location = 1) in vec2 vs_in_position_screen;\n"
+               << "\n"
+               << "layout(location = 0) sample out vec2 vs_out_position_screen;\n"
+               << "\n"
+               << "out gl_PerVertex {\n"
+               << "    vec4  gl_Position;\n"
+               << "};\n"
+               << "void main (void)\n"
+               << "{\n"
+               << "    gl_Position                             = vs_in_position_ndc;\n"
+               << "    vs_out_position_screen  = vs_in_position_screen;\n"
+               << "}\n";
+
+       programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
+
+       // Create fragment shader
+       std::ostringstream fs;
+
+       fs      << "#version 440\n"
+               << "layout(location = 0) sample in vec2 fs_in_position_screen;\n"
+               << "\n"
+               << "layout(location = 0) out vec4 fs_out_color;\n"
+               << "\n"
+               << "void main (void)\n"
+               << "{\n"
+               << "    const float threshold = 0.15625; // 4 subpixel bits. Assume 3 accurate bits + 0.03125 for other errors\n"
+               << "    const ivec2 nearby_pixel = ivec2(floor(fs_in_position_screen));\n"
+               << "    bool ok = false;\n"
+               << "\n"
+               << "    // sample at edge + inaccuaries may cause us to round to any neighboring pixel\n"
+               << "    // check all neighbors for any match\n"
+               << "    for (int dy = -1; dy <= 1; ++dy)\n"
+               << "    for (int dx = -1; dx <= 1; ++dx)\n"
+               << "    {\n"
+               << "            ivec2 current_pixel                     = nearby_pixel + ivec2(dx, dy);\n"
+               << "            vec2 position_inside_pixel      = vec2(current_pixel) + gl_SamplePosition;\n"
+               << "            vec2 position_diff                      = abs(position_inside_pixel - fs_in_position_screen);\n"
+               << "\n"
+               << "            if (all(lessThan(position_diff, vec2(threshold))))\n"
+               << "                    ok = true;\n"
+               << "    }\n"
+               << "\n"
+               << "    if (ok)\n"
+               << "            fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
+               << "    else\n"
+               << "            fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
+               << "}\n";
+
+       programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
+}
+
+template<> TestInstance* MSCase<MSCaseSamplePosCorrectness>::createInstance (Context& context) const
+{
+       return new MSInstance<MSInstanceSamplePosCorrectness>(context, m_imageMSParams);
+}
+
+class MSInstanceSampleMaskPattern : public MSInstanceBaseResolveAndPerSampleFetch
+{
+public:
+                                                                                       MSInstanceSampleMaskPattern     (Context&                                                                                       context,
+                                                                                                                                                const ImageMSParams&                                                           imageMSParams);
+
+       VkPipelineMultisampleStateCreateInfo    getMSStateCreateInfo            (const ImageMSParams&                                                           imageMSParams) const;
+
+       const VkDescriptorSetLayout*                    createMSPassDescSetLayout       (const ImageMSParams&                                                           imageMSParams);
+
+       const VkDescriptorSet*                                  createMSPassDescSet                     (const ImageMSParams&                                                           imageMSParams,
+                                                                                                                                                const VkDescriptorSetLayout*                                           descSetLayout);
+
+       VertexDataDesc                                                  getVertexDataDescripton         (void) const;
+
+       void                                                                    uploadVertexData                        (const Allocation&                                                                      vertexBufferAllocation,
+                                                                                                                                                const VertexDataDesc&                                                          vertexDataDescripton) const;
+
+       tcu::TestStatus                                                 verifyImageData                         (const vk::VkImageCreateInfo&                                           imageMSInfo,
+                                                                                                                                                const vk::VkImageCreateInfo&                                           imageRSInfo,
+                                                                                                                                                const std::vector<tcu::ConstPixelBufferAccess>&        dataPerSample,
+                                                                                                                                                const tcu::ConstPixelBufferAccess&                                     dataRS) const;
+protected:
+
+       VkSampleMask                            m_sampleMask;
+       Move<VkDescriptorSetLayout>     m_descriptorSetLayout;
+       Move<VkDescriptorPool>          m_descriptorPool;
+       Move<VkDescriptorSet>           m_descriptorSet;
+       de::MovePtr<Buffer>                     m_buffer;
+};
+
+MSInstanceSampleMaskPattern::MSInstanceSampleMaskPattern (Context& context, const ImageMSParams& imageMSParams) : MSInstanceBaseResolveAndPerSampleFetch(context, imageMSParams)
+{
+       m_sampleMask = 0xAAAAAAAAu & ((1u << imageMSParams.numSamples) - 1u);
+}
+
+VkPipelineMultisampleStateCreateInfo MSInstanceSampleMaskPattern::getMSStateCreateInfo (const ImageMSParams& imageMSParams) const
+{
+       const VkPipelineMultisampleStateCreateInfo multisampleStateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,               // VkStructureType                                                      sType;
+               DE_NULL,                                                                                                                // const void*                                                          pNext;
+               (VkPipelineMultisampleStateCreateFlags)0u,                                              // VkPipelineMultisampleStateCreateFlags        flags;
+               imageMSParams.numSamples,                                                                               // VkSampleCountFlagBits                                        rasterizationSamples;
+               VK_TRUE,                                                                                                                // VkBool32                                                                     sampleShadingEnable;
+               1.0f,                                                                                                                   // float                                                                        minSampleShading;
+               &m_sampleMask,                                                                                                  // const VkSampleMask*                                          pSampleMask;
+               VK_FALSE,                                                                                                               // VkBool32                                                                     alphaToCoverageEnable;
+               VK_FALSE,                                                                                                               // VkBool32                                                                     alphaToOneEnable;
+       };
+
+       return multisampleStateInfo;
+}
+
+const VkDescriptorSetLayout* MSInstanceSampleMaskPattern::createMSPassDescSetLayout (const ImageMSParams& imageMSParams)
+{
+       DE_UNREF(imageMSParams);
+
+       const DeviceInterface&          deviceInterface = m_context.getDeviceInterface();
+       const VkDevice                          device                  = m_context.getDevice();
+
+       // Create descriptor set layout
+       m_descriptorSetLayout = DescriptorSetLayoutBuilder()
+               .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
+               .build(deviceInterface, device);
+
+       return &m_descriptorSetLayout.get();
+}
+
+const VkDescriptorSet* MSInstanceSampleMaskPattern::createMSPassDescSet (const ImageMSParams& imageMSParams, const VkDescriptorSetLayout* descSetLayout)
+{
+       DE_UNREF(imageMSParams);
+
+       const DeviceInterface&          deviceInterface = m_context.getDeviceInterface();
+       const VkDevice                          device                  = m_context.getDevice();
+       Allocator&                                      allocator               = m_context.getDefaultAllocator();
+
+       // Create descriptor pool
+       m_descriptorPool = DescriptorPoolBuilder()
+               .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u)
+               .build(deviceInterface, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
+
+       // Create descriptor set
+       m_descriptorSet = makeDescriptorSet(deviceInterface, device, *m_descriptorPool, *descSetLayout);
+
+       const VkBufferCreateInfo bufferSampleMaskInfo = makeBufferCreateInfo(sizeof(VkSampleMask), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
+
+       m_buffer = de::MovePtr<Buffer>(new Buffer(deviceInterface, device, allocator, bufferSampleMaskInfo, MemoryRequirement::HostVisible));
+
+       deMemcpy(m_buffer->getAllocation().getHostPtr(), &m_sampleMask, sizeof(VkSampleMask));
+
+       flushMappedMemoryRange(deviceInterface, device, m_buffer->getAllocation().getMemory(), m_buffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
+
+       const VkDescriptorBufferInfo descBufferInfo = makeDescriptorBufferInfo(**m_buffer, 0u, sizeof(VkSampleMask));
+
+       DescriptorSetUpdateBuilder()
+               .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descBufferInfo)
+               .update(deviceInterface, device);
+
+       return &m_descriptorSet.get();
+}
+
+MultisampleInstanceBase::VertexDataDesc MSInstanceSampleMaskPattern::getVertexDataDescripton (void) const
+{
+       return getVertexDataDescriptonNdc();
+}
+
+void MSInstanceSampleMaskPattern::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
+{
+       uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
+}
+
+tcu::TestStatus        MSInstanceSampleMaskPattern::verifyImageData    (const vk::VkImageCreateInfo&                                           imageMSInfo,
+                                                                                                                                const vk::VkImageCreateInfo&                                           imageRSInfo,
+                                                                                                                                const std::vector<tcu::ConstPixelBufferAccess>&        dataPerSample,
+                                                                                                                                const tcu::ConstPixelBufferAccess&                                     dataRS) const
+{
+       DE_UNREF(imageRSInfo);
+       DE_UNREF(dataRS);
+
+       if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
+               return tcu::TestStatus::fail("gl_SampleMaskIn bits have not been killed by pSampleMask state");
+
+       return tcu::TestStatus::pass("Passed");
+}
+
+class MSCaseSampleMaskPattern;
+
+template<> void MSCase<MSCaseSampleMaskPattern>::init (void)
+{
+       m_testCtx.getLog()
+               << tcu::TestLog::Message
+               << "Verifying gl_SampleMaskIn value with pSampleMask state. gl_SampleMaskIn does not contain any bits set that are have been killed by pSampleMask state. Expecting:\n"
+               << "Expected result: gl_SampleMaskIn AND ~(pSampleMask) should be zero.\n"
+               << tcu::TestLog::EndMessage;
+
+       MultisampleCaseBase::init();
+}
+
+template<> void MSCase<MSCaseSampleMaskPattern>::initPrograms (vk::SourceCollections& programCollection) const
+{
+       MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
+
+       // Create vertex shader
+       std::ostringstream vs;
+
+       vs << "#version 440\n"
+               << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
+               << "\n"
+               << "out gl_PerVertex {\n"
+               << "    vec4  gl_Position;\n"
+               << "};\n"
+               << "void main (void)\n"
+               << "{\n"
+               << "    gl_Position     = vs_in_position_ndc;\n"
+               << "}\n";
+
+       programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
+
+       // Create fragment shader
+       std::ostringstream fs;
+
+       fs << "#version 440\n"
+               << "\n"
+               << "layout(location = 0) out vec4 fs_out_color;\n"
+               << "\n"
+               << "layout(set = 0, binding = 0, std140) uniform SampleMaskBlock\n"
+               << "{\n"
+               << "    int sampleMaskPattern;\n"
+               << "};"
+               << "\n"
+               << "void main (void)\n"
+               << "{\n"
+               << "    if ((gl_SampleMaskIn[0] & ~sampleMaskPattern) != 0)\n"
+               << "            fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
+               << "    else\n"
+               << "            fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
+               << "}\n";
+
+       programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
+}
+
+template<> TestInstance* MSCase<MSCaseSampleMaskPattern>::createInstance (Context& context) const
+{
+       return new MSInstanceSampleMaskPattern(context, m_imageMSParams);
+}
+
+class MSInstanceSampleMaskBitCount;
+
+template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskBitCount>::getVertexDataDescripton (void) const
+{
+       return getVertexDataDescriptonNdc();
+}
+
+template<> void MSInstance<MSInstanceSampleMaskBitCount>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
+{
+       uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
+}
+
+template<> tcu::TestStatus MSInstance<MSInstanceSampleMaskBitCount>::verifyImageData   (const vk::VkImageCreateInfo&                                           imageMSInfo,
+                                                                                                                                                                                const vk::VkImageCreateInfo&                                           imageRSInfo,
+                                                                                                                                                                                const std::vector<tcu::ConstPixelBufferAccess>&        dataPerSample,
+                                                                                                                                                                                const tcu::ConstPixelBufferAccess&                                     dataRS) const
+{
+       DE_UNREF(imageRSInfo);
+       DE_UNREF(dataRS);
+
+       if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
+               return tcu::TestStatus::fail("gl_SampleMaskIn has more than one bit set for some shader invocations");
+
+       return tcu::TestStatus::pass("Passed");
+}
+
+class MSCaseSampleMaskBitCount;
+
+template<> void MSCase<MSCaseSampleMaskBitCount>::init (void)
+{
+       m_testCtx.getLog()
+               << tcu::TestLog::Message
+               << "Verifying gl_SampleMaskIn.\n"
+               << "    Fragment shader will be invoked numSamples times.\n"
+               << "    => gl_SampleMaskIn should have only one bit set for each shader invocation.\n"
+               << tcu::TestLog::EndMessage;
+
+       MultisampleCaseBase::init();
+}
+
+template<> void MSCase<MSCaseSampleMaskBitCount>::initPrograms (vk::SourceCollections& programCollection) const
+{
+       MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
+
+       // Create vertex shader
+       std::ostringstream vs;
+
+       vs << "#version 440\n"
+               << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
+               << "\n"
+               << "out gl_PerVertex {\n"
+               << "    vec4  gl_Position;\n"
+               << "};\n"
+               << "void main (void)\n"
+               << "{\n"
+               << "    gl_Position     = vs_in_position_ndc;\n"
+               << "}\n";
+
+       programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
+
+       // Create fragment shader
+       std::ostringstream fs;
+
+       fs << "#version 440\n"
+               << "\n"
+               << "layout(location = 0) out vec4 fs_out_color;\n"
+               << "\n"
+               << "void main (void)\n"
+               << "{\n"
+               << "    uint maskBitCount = 0u;\n"
+               << "\n"
+               << "    for (int i = 0; i < 32; ++i)\n"
+               << "            if (((gl_SampleMaskIn[0] >> i) & 0x01) == 0x01)\n"
+               << "                    ++maskBitCount;\n"
+               << "\n"
+               << "    if (maskBitCount != 1u)\n"
+               << "            fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
+               << "    else\n"
+               << "            fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
+               << "}\n";
+
+       programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
+}
+
+template<> TestInstance* MSCase<MSCaseSampleMaskBitCount>::createInstance (Context& context) const
+{
+       return new MSInstance<MSInstanceSampleMaskBitCount>(context, m_imageMSParams);
+}
+
+class MSInstanceSampleMaskCorrectBit;
+
+template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskCorrectBit>::getVertexDataDescripton (void) const
+{
+       return getVertexDataDescriptonNdc();
+}
+
+template<> void MSInstance<MSInstanceSampleMaskCorrectBit>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
+{
+       uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
+}
+
+template<> tcu::TestStatus MSInstance<MSInstanceSampleMaskCorrectBit>::verifyImageData (const vk::VkImageCreateInfo&                                           imageMSInfo,
+                                                                                                                                                                                const vk::VkImageCreateInfo&                                           imageRSInfo,
+                                                                                                                                                                                const std::vector<tcu::ConstPixelBufferAccess>&        dataPerSample,
+                                                                                                                                                                                const tcu::ConstPixelBufferAccess&                                     dataRS) const
+{
+       DE_UNREF(imageRSInfo);
+       DE_UNREF(dataRS);
+
+       if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
+               return tcu::TestStatus::fail("The bit corresponsing to current gl_SampleID is not set in gl_SampleMaskIn");
+
+       return tcu::TestStatus::pass("Passed");
+}
+
+class MSCaseSampleMaskCorrectBit;
+
+template<> void MSCase<MSCaseSampleMaskCorrectBit>::init (void)
+{
+       m_testCtx.getLog()
+               << tcu::TestLog::Message
+               << "Verifying gl_SampleMaskIn.\n"
+               << "    Fragment shader will be invoked numSamples times.\n"
+               << "    => In each invocation gl_SampleMaskIn should have the bit set that corresponds to gl_SampleID.\n"
+               << tcu::TestLog::EndMessage;
+
+       MultisampleCaseBase::init();
+}
+
+template<> void MSCase<MSCaseSampleMaskCorrectBit>::initPrograms (vk::SourceCollections& programCollection) const
+{
+       MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
+
+       // Create vertex shader
+       std::ostringstream vs;
+
+       vs << "#version 440\n"
+               << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
+               << "\n"
+               << "out gl_PerVertex {\n"
+               << "    vec4  gl_Position;\n"
+               << "};\n"
+               << "void main (void)\n"
+               << "{\n"
+               << "    gl_Position     = vs_in_position_ndc;\n"
+               << "}\n";
+
+       programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
+
+       // Create fragment shader
+       std::ostringstream fs;
+
+       fs << "#version 440\n"
+               << "\n"
+               << "layout(location = 0) out vec4 fs_out_color;\n"
+               << "\n"
+               << "void main (void)\n"
+               << "{\n"
+               << "    if (((gl_SampleMaskIn[0] >> gl_SampleID) & 0x01) == 0x01)\n"
+               << "            fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
+               << "    else\n"
+               << "            fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
+               << "}\n";
+
+       programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
+}
+
+template<> TestInstance* MSCase<MSCaseSampleMaskCorrectBit>::createInstance (Context& context) const
+{
+       return new MSInstance<MSInstanceSampleMaskCorrectBit>(context, m_imageMSParams);
+}
+
+class MSInstanceSampleMaskWrite;
+
+template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskWrite>::getVertexDataDescripton (void) const
+{
+       return getVertexDataDescriptonNdc();
+}
+
+template<> void MSInstance<MSInstanceSampleMaskWrite>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
+{
+       uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
+}
+
+template<> tcu::TestStatus MSInstance<MSInstanceSampleMaskWrite>::verifyImageData      (const vk::VkImageCreateInfo&                                           imageMSInfo,
+                                                                                                                                                                        const vk::VkImageCreateInfo&                                           imageRSInfo,
+                                                                                                                                                                        const std::vector<tcu::ConstPixelBufferAccess>&        dataPerSample,
+                                                                                                                                                                        const tcu::ConstPixelBufferAccess&                                     dataRS) const
+{
+       const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
+
+       for (deUint32 z = 0u; z < imageMSInfo.extent.depth;  ++z)
+       for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
+       for (deUint32 x = 0u; x < imageMSInfo.extent.width;  ++x)
+       {
+               for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
+               {
+                       const deUint32 firstComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z)[0];
+
+                       if (firstComponent != 0u && firstComponent != 255u)
+                               return tcu::TestStatus::fail("Expected color to be zero or saturated on the first channel");
+               }
+       }
+
+       for (deUint32 z = 0u; z < imageRSInfo.extent.depth;  ++z)
+       for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
+       for (deUint32 x = 0u; x < imageRSInfo.extent.width;  ++x)
+       {
+               const float firstComponent = dataRS.getPixel(x, y, z)[0];
+
+               if (deFloatAbs(firstComponent - 0.5f) > 0.02f)
+                       return tcu::TestStatus::fail("Expected resolve color to be half intensity on the first channel");
+       }
+
+       return tcu::TestStatus::pass("Passed");
+}
+
+class MSCaseSampleMaskWrite;
+
+template<> void MSCase<MSCaseSampleMaskWrite>::init (void)
+{
+       m_testCtx.getLog()
+               << tcu::TestLog::Message
+               << "Discarding half of the samples using gl_SampleMask."
+               << "Expecting half intensity on multisample targets (numSamples > 1)\n"
+               << tcu::TestLog::EndMessage;
+
+       MultisampleCaseBase::init();
+}
+
+template<> void MSCase<MSCaseSampleMaskWrite>::initPrograms (vk::SourceCollections& programCollection) const
+{
+       MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
+
+       // Create vertex shader
+       std::ostringstream vs;
+
+       vs << "#version 440\n"
+               << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
+               << "\n"
+               << "out gl_PerVertex {\n"
+               << "    vec4  gl_Position;\n"
+               << "};\n"
+               << "void main (void)\n"
+               << "{\n"
+               << "    gl_Position     = vs_in_position_ndc;\n"
+               << "}\n";
+
+       programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
+
+       // Create fragment shader
+       std::ostringstream fs;
+
+       fs << "#version 440\n"
+               << "\n"
+               << "layout(location = 0) out vec4 fs_out_color;\n"
+               << "\n"
+               << "void main (void)\n"
+               << "{\n"
+               << "    gl_SampleMask[0] = 0xAAAAAAAA;\n"
+               << "\n"
+               << "    fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
+               << "}\n";
+
+       programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
+}
+
+template<> TestInstance* MSCase<MSCaseSampleMaskWrite>::createInstance (Context& context) const
+{
+       return new MSInstance<MSInstanceSampleMaskWrite>(context, m_imageMSParams);
+}
+
+} // multisample
+
+tcu::TestCaseGroup* createMultisampleShaderBuiltInTests (tcu::TestContext& testCtx)
+{
+       de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "multisample_shader_builtin", "Multisample Shader BuiltIn Tests"));
+
+       const tcu::UVec3 imageSizes[] =
+       {
+               tcu::UVec3(128u, 128u, 1u),
+               tcu::UVec3(137u, 191u, 1u),
+       };
+
+       const deUint32 sizesElemCount = static_cast<deUint32>(sizeof(imageSizes) / sizeof(tcu::UVec3));
+
+       const vk::VkSampleCountFlagBits samplesSetFull[] =
+       {
+               vk::VK_SAMPLE_COUNT_2_BIT,
+               vk::VK_SAMPLE_COUNT_4_BIT,
+               vk::VK_SAMPLE_COUNT_8_BIT,
+               vk::VK_SAMPLE_COUNT_16_BIT,
+               vk::VK_SAMPLE_COUNT_32_BIT,
+               vk::VK_SAMPLE_COUNT_64_BIT,
+       };
+
+       const deUint32 samplesSetFullCount = static_cast<deUint32>(sizeof(samplesSetFull) / sizeof(vk::VkSampleCountFlagBits));
+
+       testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleID> >(testCtx, "sample_id", imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount));
+
+       de::MovePtr<tcu::TestCaseGroup> samplePositionGroup(new tcu::TestCaseGroup(testCtx, "sample_position", "Sample Position Tests"));
+
+       samplePositionGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSamplePosDistribution> >(testCtx, "distribution", imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount));
+       samplePositionGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSamplePosCorrectness> > (testCtx, "correctness",  imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount));
+
+       testGroup->addChild(samplePositionGroup.release());
+
+       const vk::VkSampleCountFlagBits samplesSetReduced[] =
+       {
+               vk::VK_SAMPLE_COUNT_2_BIT,
+               vk::VK_SAMPLE_COUNT_4_BIT,
+               vk::VK_SAMPLE_COUNT_8_BIT,
+               vk::VK_SAMPLE_COUNT_16_BIT,
+               vk::VK_SAMPLE_COUNT_32_BIT,
+       };
+
+       const deUint32 samplesSetReducedCount = static_cast<deUint32>(sizeof(samplesSetReduced) / sizeof(vk::VkSampleCountFlagBits));
+
+       de::MovePtr<tcu::TestCaseGroup> sampleMaskGroup(new tcu::TestCaseGroup(testCtx, "sample_mask", "Sample Mask Tests"));
+
+       sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskPattern> >       (testCtx, "pattern",    imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
+       sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskBitCount> >      (testCtx, "bit_count",  imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
+       sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskCorrectBit> >(testCtx, "correct_bit",imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
+       sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskWrite> >         (testCtx, "write",              imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
+
+       testGroup->addChild(sampleMaskGroup.release());
+
+       return testGroup.release();
+}
+
+} // pipeline
+} // vkt
diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleShaderBuiltInTests.hpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleShaderBuiltInTests.hpp
new file mode 100644 (file)
index 0000000..607c7d9
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef _VKTPIPELINEMULTISAMPLESHADERBUILTINTESTS_HPP
+#define _VKTPIPELINEMULTISAMPLESHADERBUILTINTESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2016 The Khronos Group Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file vktPipelineMultisampleShaderBuiltInTests.hpp
+ * \brief Multisample Shader BuiltIn Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktTestCase.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+
+tcu::TestCaseGroup* createMultisampleShaderBuiltInTests (tcu::TestContext& testCtx);
+
+} // pipeline
+} // vkt
+
+#endif // _VKTPIPELINEMULTISAMPLESHADERBUILTINTESTS_HPP
index f1493e2..792873d 100644 (file)
@@ -371,19 +371,19 @@ deUint32 getImageMaxMipLevels (const VkImageFormatProperties& imageFormatPropert
        return std::min(static_cast<deUint32>(deFloatLog2(static_cast<float>(widestEdge))) + 1u, imageFormatProperties.maxMipLevels);
 }
 
-deUint32 getImageMipLevelSizeInBytes (const VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevel)
+deUint32 getImageMipLevelSizeInBytes (const VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevel, const deUint32 numSamples)
 {
        const VkExtent3D extents = mipLevelExtents(baseExtents, mipmapLevel);
 
-       return extents.width * extents.height * extents.depth * layersCount * tcu::getPixelSize(format);
+       return extents.width * extents.height * extents.depth * layersCount * numSamples * tcu::getPixelSize(format);
 }
 
-deUint32 getImageSizeInBytes (const VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevelsCount)
+deUint32 getImageSizeInBytes (const VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevelsCount, const deUint32 numSamples)
 {
        deUint32 imageSizeInBytes = 0;
        for (deUint32 mipmapLevel = 0; mipmapLevel < mipmapLevelsCount; ++mipmapLevel)
        {
-               imageSizeInBytes += getImageMipLevelSizeInBytes(baseExtents, layersCount, format, mipmapLevel);
+               imageSizeInBytes += getImageMipLevelSizeInBytes(baseExtents, layersCount, format, mipmapLevel, numSamples);
        }
 
        return imageSizeInBytes;
index 03e721e..97a5248 100644 (file)
@@ -75,8 +75,8 @@ deUint32                      getDimensions                                   (const ImageType imageType);
 deUint32                       getLayerDimensions                              (const ImageType imageType);
 vk::VkExtent3D         mipLevelExtents                                 (const vk::VkExtent3D& baseExtents, const deUint32 mipLevel);
 tcu::UVec3                     mipLevelExtents                                 (const tcu::UVec3&         baseExtents, const deUint32 mipLevel);
-deUint32                       getImageMipLevelSizeInBytes             (const vk::VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevel);
-deUint32                       getImageSizeInBytes                             (const vk::VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevelsCount = 1u);
+deUint32                       getImageMipLevelSizeInBytes             (const vk::VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevel, const deUint32 numSamples = 1u);
+deUint32                       getImageSizeInBytes                             (const vk::VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevelsCount = 1u, const deUint32 numSamples = 1u);
 deUint32                       getImageMaxMipLevels                    (const vk::VkImageFormatProperties& imageFormatProperties, const vk::VkExtent3D& extent);
 
 enum FeatureFlagBits
index 1cb900a..148f197 100644 (file)
@@ -34,6 +34,7 @@
 #include "vktPipelineSpecConstantTests.hpp"
 #include "vktPipelineMultisampleTests.hpp"
 #include "vktPipelineMultisampleInterpolationTests.hpp"
+#include "vktPipelineMultisampleShaderBuiltInTests.hpp"
 #include "vktPipelineVertexInputTests.hpp"
 #include "vktPipelineTimestampTests.hpp"
 #include "vktPipelineCacheTests.hpp"
@@ -62,6 +63,7 @@ void createChildren (tcu::TestCaseGroup* pipelineTests)
        pipelineTests->addChild(createSpecConstantTests                         (testCtx));
        pipelineTests->addChild(createMultisampleTests                          (testCtx));
        pipelineTests->addChild(createMultisampleInterpolationTests     (testCtx));
+       pipelineTests->addChild(createMultisampleShaderBuiltInTests     (testCtx));
        pipelineTests->addChild(createVertexInputTests                          (testCtx));
        pipelineTests->addChild(createInputAssemblyTests                        (testCtx));
        pipelineTests->addChild(createTimestampTests                            (testCtx));
index 08642d9..ae00cda 100644 (file)
@@ -87189,6 +87189,82 @@ dEQP-VK.pipeline.multisample_interpolation.offset_interpolate_at_sample_position
 dEQP-VK.pipeline.multisample_interpolation.offset_interpolate_at_sample_position.137_191_1.samples_16
 dEQP-VK.pipeline.multisample_interpolation.offset_interpolate_at_sample_position.137_191_1.samples_32
 dEQP-VK.pipeline.multisample_interpolation.offset_interpolate_at_sample_position.137_191_1.samples_64
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_64
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_64
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_64
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_64
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_64
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_64
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.128_128_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.128_128_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.128_128_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.128_128_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.128_128_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.137_191_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.137_191_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.137_191_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.137_191_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.137_191_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.128_128_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.128_128_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.128_128_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.128_128_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.128_128_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.137_191_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.137_191_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.137_191_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.137_191_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.137_191_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.128_128_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.128_128_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.128_128_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.128_128_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.128_128_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.137_191_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.137_191_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.137_191_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.137_191_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.137_191_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.128_128_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.128_128_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.128_128_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.128_128_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.128_128_1.samples_32
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.137_191_1.samples_2
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.137_191_1.samples_4
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.137_191_1.samples_8
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.137_191_1.samples_16
+dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.137_191_1.samples_32
 dEQP-VK.pipeline.vertex_input.single_attribute.float_as_r8_unorm_rate_vertex
 dEQP-VK.pipeline.vertex_input.single_attribute.float_as_r8_unorm_rate_instance
 dEQP-VK.pipeline.vertex_input.single_attribute.float_as_r8_snorm_rate_vertex