Add render pass multisample resolve tests
authorMika Isojärvi <misojarvi@google.com>
Tue, 28 Mar 2017 20:45:01 +0000 (13:45 -0700)
committerAlexander Galazin <alexander.galazin@arm.com>
Fri, 23 Jun 2017 22:06:57 +0000 (00:06 +0200)
- Check that attachment components are resolved consistently
- Check that attachments are resolved consistently
- Check that integer formats always resolve to one of the samples
- Check that empty sample mask doesn't change values
- Check that all possible sample combinations of 1.0 and 0.0 values
  resolve to 0.5 on average.

VK-GL-CTS issues: 96
Components: Vulkan

Change-Id: I18b92ed713175cd935651575f4e48d9fd207ef00
(cherry picked from commit c8c44388f472dcbb6145b520c4a89e5ef02221b3)

Android.mk
android/cts/master/vk-master.txt
external/vulkancts/framework/vulkan/vkTypeUtil.hpp
external/vulkancts/modules/vulkan/renderpass/CMakeLists.txt
external/vulkancts/modules/vulkan/renderpass/vktRenderPassMultisampleResolveTests.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/renderpass/vktRenderPassMultisampleResolveTests.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/renderpass/vktRenderPassTests.cpp
external/vulkancts/mustpass/1.0.2/vk-default.txt

index e8f4c59..666c3ef 100644 (file)
@@ -819,6 +819,7 @@ LOCAL_SRC_FILES := \
        external/vulkancts/modules/vulkan/query_pool/vktQueryPoolOcclusionTests.cpp \
        external/vulkancts/modules/vulkan/query_pool/vktQueryPoolTests.cpp \
        external/vulkancts/modules/vulkan/rasterization/vktRasterizationTests.cpp \
+       external/vulkancts/modules/vulkan/renderpass/vktRenderPassMultisampleResolveTests.cpp \
        external/vulkancts/modules/vulkan/renderpass/vktRenderPassMultisampleTests.cpp \
        external/vulkancts/modules/vulkan/renderpass/vktRenderPassTests.cpp \
        external/vulkancts/modules/vulkan/shaderexecutor/vktOpaqueTypeIndexingTests.cpp \
index 3a35535..0518efe 100644 (file)
@@ -133361,6 +133361,150 @@ dEQP-VK.renderpass.multisample.d32_sfloat_s8_uint.samples_4
 dEQP-VK.renderpass.multisample.d32_sfloat_s8_uint.samples_8
 dEQP-VK.renderpass.multisample.d32_sfloat_s8_uint.samples_16
 dEQP-VK.renderpass.multisample.d32_sfloat_s8_uint.samples_32
+dEQP-VK.renderpass.multisample_resolve.r5g6b5_unorm_pack16.samples_2
+dEQP-VK.renderpass.multisample_resolve.r5g6b5_unorm_pack16.samples_4
+dEQP-VK.renderpass.multisample_resolve.r5g6b5_unorm_pack16.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8_unorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8_unorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8_unorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8_snorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8_snorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8_snorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8_uint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8_uint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8_uint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8_sint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8_sint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8_sint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8g8_unorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8g8_unorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8g8_unorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8g8_snorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8g8_snorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8g8_snorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8g8_uint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8g8_uint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8g8_uint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8g8_sint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8g8_sint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8g8_sint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_unorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_unorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_unorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_snorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_snorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_snorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_uint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_uint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_uint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_sint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_sint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_sint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_srgb.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_srgb.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_srgb.samples_8
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_unorm_pack32.samples_2
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_unorm_pack32.samples_4
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_unorm_pack32.samples_8
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_snorm_pack32.samples_2
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_snorm_pack32.samples_4
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_snorm_pack32.samples_8
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_uint_pack32.samples_2
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_uint_pack32.samples_4
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_uint_pack32.samples_8
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_sint_pack32.samples_2
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_sint_pack32.samples_4
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_sint_pack32.samples_8
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_srgb_pack32.samples_2
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_srgb_pack32.samples_4
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_srgb_pack32.samples_8
+dEQP-VK.renderpass.multisample_resolve.b8g8r8a8_unorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.b8g8r8a8_unorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.b8g8r8a8_unorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.b8g8r8a8_srgb.samples_2
+dEQP-VK.renderpass.multisample_resolve.b8g8r8a8_srgb.samples_4
+dEQP-VK.renderpass.multisample_resolve.b8g8r8a8_srgb.samples_8
+dEQP-VK.renderpass.multisample_resolve.a2r10g10b10_unorm_pack32.samples_2
+dEQP-VK.renderpass.multisample_resolve.a2r10g10b10_unorm_pack32.samples_4
+dEQP-VK.renderpass.multisample_resolve.a2r10g10b10_unorm_pack32.samples_8
+dEQP-VK.renderpass.multisample_resolve.a2b10g10r10_unorm_pack32.samples_2
+dEQP-VK.renderpass.multisample_resolve.a2b10g10r10_unorm_pack32.samples_4
+dEQP-VK.renderpass.multisample_resolve.a2b10g10r10_unorm_pack32.samples_8
+dEQP-VK.renderpass.multisample_resolve.a2b10g10r10_uint_pack32.samples_2
+dEQP-VK.renderpass.multisample_resolve.a2b10g10r10_uint_pack32.samples_4
+dEQP-VK.renderpass.multisample_resolve.a2b10g10r10_uint_pack32.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16_unorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16_unorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16_unorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16_snorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16_snorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16_snorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16_uint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16_uint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16_uint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16_sint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16_sint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16_sint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16_sfloat.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16_sfloat.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16_sfloat.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16g16_unorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16g16_unorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16g16_unorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16g16_snorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16g16_snorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16g16_snorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16g16_uint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16g16_uint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16g16_uint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16g16_sint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16g16_sint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16g16_sint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16g16_sfloat.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16g16_sfloat.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16g16_sfloat.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_unorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_unorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_unorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_snorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_snorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_snorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_uint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_uint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_uint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_sint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_sint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_sint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_sfloat.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_sfloat.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_sfloat.samples_8
+dEQP-VK.renderpass.multisample_resolve.r32_uint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r32_uint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r32_uint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r32_sint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r32_sint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r32_sint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r32_sfloat.samples_2
+dEQP-VK.renderpass.multisample_resolve.r32_sfloat.samples_4
+dEQP-VK.renderpass.multisample_resolve.r32_sfloat.samples_8
+dEQP-VK.renderpass.multisample_resolve.r32g32_uint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r32g32_uint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r32g32_uint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r32g32_sint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r32g32_sint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r32g32_sint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r32g32_sfloat.samples_2
+dEQP-VK.renderpass.multisample_resolve.r32g32_sfloat.samples_4
+dEQP-VK.renderpass.multisample_resolve.r32g32_sfloat.samples_8
+dEQP-VK.renderpass.multisample_resolve.r32g32b32a32_uint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r32g32b32a32_uint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r32g32b32a32_uint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r32g32b32a32_sint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r32g32b32a32_sint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r32g32b32a32_sint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r32g32b32a32_sfloat.samples_2
+dEQP-VK.renderpass.multisample_resolve.r32g32b32a32_sfloat.samples_4
+dEQP-VK.renderpass.multisample_resolve.r32g32b32a32_sfloat.samples_8
 dEQP-VK.ubo.2_level_array.std140.float_vertex
 dEQP-VK.ubo.2_level_array.std140.float_fragment
 dEQP-VK.ubo.2_level_array.std140.float_both
index ef4a8e9..667a2c5 100644 (file)
@@ -51,6 +51,16 @@ inline VkClearValue makeClearValueColorU32 (deUint32 r, deUint32 g, deUint32 b,
        return v;
 }
 
+inline VkClearValue makeClearValueColorI32 (deInt32 r, deInt32 g, deInt32 b, deInt32 a)
+{
+       VkClearValue v;
+       v.color.int32[0] = r;
+       v.color.int32[1] = g;
+       v.color.int32[2] = b;
+       v.color.int32[3] = a;
+       return v;
+}
+
 inline VkClearValue makeClearValueColor (const tcu::Vec4& color)
 {
        VkClearValue v;
index 7248a96..213c3e7 100644 (file)
@@ -7,6 +7,8 @@ set(DEQP_VK_RENDER_PASS_SRCS
        vktRenderPassTests.hpp
        vktRenderPassMultisampleTests.cpp
        vktRenderPassMultisampleTests.hpp
+       vktRenderPassMultisampleResolveTests.cpp
+       vktRenderPassMultisampleResolveTests.hpp
        )
 
 set(DEQP_VK_RENDER_PASS_LIBS
diff --git a/external/vulkancts/modules/vulkan/renderpass/vktRenderPassMultisampleResolveTests.cpp b/external/vulkancts/modules/vulkan/renderpass/vktRenderPassMultisampleResolveTests.cpp
new file mode 100644 (file)
index 0000000..c261e2a
--- /dev/null
@@ -0,0 +1,1727 @@
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2017 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Tests for render pass multisample resolve
+ *//*--------------------------------------------------------------------*/
+
+#include "vktRenderPassMultisampleResolveTests.hpp"
+
+#include "vktTestCaseUtil.hpp"
+#include "vktTestGroupUtil.hpp"
+
+#include "vkDefs.hpp"
+#include "vkDeviceUtil.hpp"
+#include "vkImageUtil.hpp"
+#include "vkMemUtil.hpp"
+#include "vkPlatform.hpp"
+#include "vkPrograms.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkRef.hpp"
+#include "vkRefUtil.hpp"
+#include "vkTypeUtil.hpp"
+
+#include "tcuFloat.hpp"
+#include "tcuImageCompare.hpp"
+#include "tcuFormatUtil.hpp"
+#include "tcuMaybe.hpp"
+#include "tcuResultCollector.hpp"
+#include "tcuTestLog.hpp"
+#include "tcuTextureUtil.hpp"
+#include "tcuVectorUtil.hpp"
+
+#include "deUniquePtr.hpp"
+#include "deSharedPtr.hpp"
+
+using namespace vk;
+
+using tcu::BVec4;
+using tcu::IVec2;
+using tcu::IVec4;
+using tcu::UVec2;
+using tcu::UVec4;
+using tcu::Vec2;
+using tcu::Vec4;
+
+using tcu::Maybe;
+using tcu::just;
+using tcu::nothing;
+
+using tcu::ConstPixelBufferAccess;
+using tcu::PixelBufferAccess;
+
+using tcu::TestLog;
+
+using std::pair;
+using std::string;
+using std::vector;
+
+typedef de::SharedPtr<vk::Unique<VkImage> >            VkImageSp;
+typedef de::SharedPtr<vk::Unique<VkImageView> >        VkImageViewSp;
+typedef de::SharedPtr<vk::Unique<VkBuffer> >   VkBufferSp;
+typedef de::SharedPtr<vk::Unique<VkPipeline> > VkPipelineSp;
+
+namespace vkt
+{
+namespace
+{
+enum
+{
+       MAX_COLOR_ATTACHMENT_COUNT = 4u
+};
+
+template<typename T>
+de::SharedPtr<T> safeSharedPtr (T* ptr)
+{
+       try
+       {
+               return de::SharedPtr<T>(ptr);
+       }
+       catch (...)
+       {
+               delete ptr;
+               throw;
+       }
+}
+
+void bindBufferMemory (const DeviceInterface& vk, VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memOffset)
+{
+       VK_CHECK(vk.bindBufferMemory(device, buffer, mem, memOffset));
+}
+
+void bindImageMemory (const DeviceInterface& vk, VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memOffset)
+{
+       VK_CHECK(vk.bindImageMemory(device, image, mem, memOffset));
+}
+
+de::MovePtr<Allocation> createBufferMemory (const DeviceInterface&     vk,
+                                                                                       VkDevice                                device,
+                                                                                       Allocator&                              allocator,
+                                                                                       VkBuffer                                buffer)
+{
+       de::MovePtr<Allocation> allocation (allocator.allocate(getBufferMemoryRequirements(vk, device, buffer), MemoryRequirement::HostVisible));
+       bindBufferMemory(vk, device, buffer, allocation->getMemory(), allocation->getOffset());
+       return allocation;
+}
+
+de::MovePtr<Allocation> createImageMemory (const DeviceInterface&      vk,
+                                                                                  VkDevice                                     device,
+                                                                                  Allocator&                           allocator,
+                                                                                  VkImage                                      image)
+{
+       de::MovePtr<Allocation> allocation (allocator.allocate(getImageMemoryRequirements(vk, device, image), MemoryRequirement::Any));
+       bindImageMemory(vk, device, image, allocation->getMemory(), allocation->getOffset());
+       return allocation;
+}
+
+Move<VkImage> createImage (const DeviceInterface&      vk,
+                                                  VkDevice                                     device,
+                                                  VkImageCreateFlags           flags,
+                                                  VkImageType                          imageType,
+                                                  VkFormat                                     format,
+                                                  VkExtent3D                           extent,
+                                                  deUint32                                     mipLevels,
+                                                  deUint32                                     arrayLayers,
+                                                  VkSampleCountFlagBits        samples,
+                                                  VkImageTiling                        tiling,
+                                                  VkImageUsageFlags            usage,
+                                                  VkSharingMode                        sharingMode,
+                                                  deUint32                                     queueFamilyCount,
+                                                  const deUint32*                      pQueueFamilyIndices,
+                                                  VkImageLayout                        initialLayout)
+{
+       const VkImageCreateInfo pCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+               DE_NULL,
+               flags,
+               imageType,
+               format,
+               extent,
+               mipLevels,
+               arrayLayers,
+               samples,
+               tiling,
+               usage,
+               sharingMode,
+               queueFamilyCount,
+               pQueueFamilyIndices,
+               initialLayout
+       };
+       return createImage(vk, device, &pCreateInfo);
+}
+
+Move<VkImageView> createImageView (const DeviceInterface&      vk,
+                                                                  VkDevice                                     device,
+                                                                  VkImageViewCreateFlags       flags,
+                                                                  VkImage                                      image,
+                                                                  VkImageViewType                      viewType,
+                                                                  VkFormat                                     format,
+                                                                  VkComponentMapping           components,
+                                                                  VkImageSubresourceRange      subresourceRange)
+{
+       const VkImageViewCreateInfo pCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+               DE_NULL,
+               flags,
+               image,
+               viewType,
+               format,
+               components,
+               subresourceRange,
+       };
+       return createImageView(vk, device, &pCreateInfo);
+}
+
+Move<VkImage> createImage (const InstanceInterface&    vki,
+                                                  VkPhysicalDevice                     physicalDevice,
+                                                  const DeviceInterface&       vkd,
+                                                  VkDevice                                     device,
+                                                  VkFormat                                     vkFormat,
+                                                  VkSampleCountFlagBits        sampleCountBit,
+                                                  VkImageUsageFlags            usage,
+                                                  deUint32                                     width,
+                                                  deUint32                                     height)
+{
+       try
+       {
+               const tcu::TextureFormat                format                                  (mapVkFormat(vkFormat));
+               const VkImageType                               imageType                               (VK_IMAGE_TYPE_2D);
+               const VkImageTiling                             imageTiling                             (VK_IMAGE_TILING_OPTIMAL);
+               const VkFormatProperties                formatProperties                (getPhysicalDeviceFormatProperties(vki, physicalDevice, vkFormat));
+               const VkImageFormatProperties   imageFormatProperties   (getPhysicalDeviceImageFormatProperties(vki, physicalDevice, vkFormat, imageType, imageTiling, usage, 0u));
+               const VkExtent3D                                imageExtent                             =
+               {
+                       width,
+                       height,
+                       1u
+               };
+
+               if ((tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
+                       && (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)
+                       TCU_THROW(NotSupportedError, "Format can't be used as depth stencil attachment");
+
+               if (!(tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
+                       && (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)
+                       TCU_THROW(NotSupportedError, "Format can't be used as color attachment");
+
+               if (imageFormatProperties.maxExtent.width < imageExtent.width
+                       || imageFormatProperties.maxExtent.height < imageExtent.height
+                       || ((imageFormatProperties.sampleCounts & sampleCountBit) == 0))
+               {
+                       TCU_THROW(NotSupportedError, "Image type not supported");
+               }
+
+               return createImage(vkd, device, 0u, imageType, vkFormat, imageExtent, 1u, 1u, sampleCountBit, imageTiling, usage, VK_SHARING_MODE_EXCLUSIVE, 0u, DE_NULL, VK_IMAGE_LAYOUT_UNDEFINED);
+       }
+       catch (const vk::Error& error)
+       {
+               if (error.getError() == VK_ERROR_FORMAT_NOT_SUPPORTED)
+                       TCU_THROW(NotSupportedError, "Image format not supported");
+
+               throw;
+       }
+}
+
+Move<VkImageView> createImageView (const DeviceInterface&      vkd,
+                                                                  VkDevice                                     device,
+                                                                  VkImage                                      image,
+                                                                  VkFormat                                     format,
+                                                                  VkImageAspectFlags           aspect)
+{
+       const VkImageSubresourceRange   range =
+       {
+               aspect,
+               0u,
+               1u,
+               0u,
+               1u
+       };
+
+       return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
+}
+
+VkDeviceSize getPixelSize (VkFormat vkFormat)
+{
+       const tcu::TextureFormat        format  (mapVkFormat(vkFormat));
+
+       return format.getPixelSize();
+}
+
+Move<VkBuffer> createBuffer (const DeviceInterface&            vkd,
+                                                        VkDevice                                       device,
+                                                        VkFormat                                       format,
+                                                        deUint32                                       width,
+                                                        deUint32                                       height)
+{
+       const VkBufferUsageFlags        bufferUsage                     (VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+       const VkDeviceSize                      pixelSize                       (getPixelSize(format));
+       const VkBufferCreateInfo        createInfo                      =
+       {
+               VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+               DE_NULL,
+               0u,
+
+               width * height * pixelSize,
+               bufferUsage,
+
+               VK_SHARING_MODE_EXCLUSIVE,
+               0u,
+               DE_NULL
+       };
+       return createBuffer(vkd, device, &createInfo);
+}
+
+VkSampleCountFlagBits sampleCountBitFromSampleCount (deUint32 count)
+{
+       switch (count)
+       {
+               case 1:  return VK_SAMPLE_COUNT_1_BIT;
+               case 2:  return VK_SAMPLE_COUNT_2_BIT;
+               case 4:  return VK_SAMPLE_COUNT_4_BIT;
+               case 8:  return VK_SAMPLE_COUNT_8_BIT;
+               case 16: return VK_SAMPLE_COUNT_16_BIT;
+               case 32: return VK_SAMPLE_COUNT_32_BIT;
+               case 64: return VK_SAMPLE_COUNT_64_BIT;
+
+               default:
+                       DE_FATAL("Invalid sample count");
+                       return (VkSampleCountFlagBits)0x0;
+       }
+}
+
+std::vector<VkImageSp> createMultisampleImages (const InstanceInterface&       vki,
+                                                                                               VkPhysicalDevice                        physicalDevice,
+                                                                                               const DeviceInterface&          vkd,
+                                                                                               VkDevice                                        device,
+                                                                                               VkFormat                                        format,
+                                                                                               deUint32                                        sampleCount,
+                                                                                               deUint32                                        width,
+                                                                                               deUint32                                        height)
+{
+       std::vector<VkImageSp> images (MAX_COLOR_ATTACHMENT_COUNT);
+
+       for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
+               images[imageNdx] = safeSharedPtr(new Unique<VkImage>(createImage(vki, physicalDevice, vkd, device, format, sampleCountBitFromSampleCount(sampleCount), VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, width, height)));
+
+       return images;
+}
+
+std::vector<VkImageSp> createSingleSampleImages (const InstanceInterface&      vki,
+                                                                                                VkPhysicalDevice                       physicalDevice,
+                                                                                                const DeviceInterface&         vkd,
+                                                                                                VkDevice                                       device,
+                                                                                                VkFormat                                       format,
+                                                                                                deUint32                                       width,
+                                                                                                deUint32                                       height)
+{
+       std::vector<VkImageSp> images (MAX_COLOR_ATTACHMENT_COUNT);
+
+       for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
+               images[imageNdx] = safeSharedPtr(new Unique<VkImage>(createImage(vki, physicalDevice, vkd, device, format, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, width, height)));
+
+       return images;
+}
+
+std::vector<de::SharedPtr<Allocation> > createImageMemory (const DeviceInterface&              vkd,
+                                                                                                                  VkDevice                                             device,
+                                                                                                                  Allocator&                                   allocator,
+                                                                                                                  const std::vector<VkImageSp> images)
+{
+       std::vector<de::SharedPtr<Allocation> > memory (images.size());
+
+       for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
+               memory[memoryNdx] = safeSharedPtr(createImageMemory(vkd, device, allocator, **images[memoryNdx]).release());
+
+       return memory;
+}
+
+std::vector<VkImageViewSp> createImageViews (const DeviceInterface&                    vkd,
+                                                                                        VkDevice                                               device,
+                                                                                        const std::vector<VkImageSp>&  images,
+                                                                                        VkFormat                                               format,
+                                                                                        VkImageAspectFlagBits                  aspect)
+{
+       std::vector<VkImageViewSp> views (images.size());
+
+       for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
+               views[imageNdx] = safeSharedPtr(new Unique<VkImageView>(createImageView(vkd, device, **images[imageNdx], format, aspect)));
+
+       return views;
+}
+
+std::vector<VkBufferSp> createBuffers (const DeviceInterface&  vkd,
+                                                                          VkDevice                                     device,
+                                                                          VkFormat                                     format,
+                                                                          deUint32                                     width,
+                                                                          deUint32                                     height)
+{
+       std::vector<VkBufferSp> buffers (MAX_COLOR_ATTACHMENT_COUNT);
+
+       for (size_t bufferNdx = 0; bufferNdx < buffers.size(); bufferNdx++)
+               buffers[bufferNdx] = safeSharedPtr(new Unique<VkBuffer>(createBuffer(vkd, device, format, width, height)));
+
+       return buffers;
+}
+
+std::vector<de::SharedPtr<Allocation> > createBufferMemory (const DeviceInterface&                     vkd,
+                                                                                                                       VkDevice                                                device,
+                                                                                                                       Allocator&                                              allocator,
+                                                                                                                       const std::vector<VkBufferSp>   buffers)
+{
+       std::vector<de::SharedPtr<Allocation> > memory (buffers.size());
+
+       for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
+               memory[memoryNdx] = safeSharedPtr(createBufferMemory(vkd, device, allocator, **buffers[memoryNdx]).release());
+
+       return memory;
+}
+
+Move<VkRenderPass> createRenderPass (const DeviceInterface&    vkd,
+                                                                        VkDevice                               device,
+                                                                        VkFormat                               format,
+                                                                        deUint32                               sampleCount)
+{
+       const VkSampleCountFlagBits                             samples                                         (sampleCountBitFromSampleCount(sampleCount));
+       std::vector<VkAttachmentDescription>    attachments;
+       std::vector<VkAttachmentReference>              colorAttachmentRefs;
+       std::vector<VkAttachmentReference>              resolveAttachmentRefs;
+
+       for (size_t attachmentNdx = 0; attachmentNdx < 4; attachmentNdx++)
+       {
+               {
+                       const VkAttachmentDescription multisampleAttachment =
+                       {
+                               0u,
+
+                               format,
+                               samples,
+
+                               VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+                               VK_ATTACHMENT_STORE_OP_DONT_CARE,
+
+                               VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+                               VK_ATTACHMENT_STORE_OP_DONT_CARE,
+
+                               VK_IMAGE_LAYOUT_UNDEFINED,
+                               VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
+                       };
+                       const VkAttachmentReference attachmentRef =
+                       {
+                               (deUint32)attachments.size(),
+                               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
+                       };
+                       colorAttachmentRefs.push_back(attachmentRef);
+                       attachments.push_back(multisampleAttachment);
+               }
+               {
+                       const VkAttachmentDescription singlesampleAttachment =
+                       {
+                               0u,
+
+                               format,
+                               VK_SAMPLE_COUNT_1_BIT,
+
+                               VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+                               VK_ATTACHMENT_STORE_OP_STORE,
+
+                               VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+                               VK_ATTACHMENT_STORE_OP_DONT_CARE,
+
+                               VK_IMAGE_LAYOUT_UNDEFINED,
+                               VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
+                       };
+                       const VkAttachmentReference attachmentRef =
+                       {
+                               (deUint32)attachments.size(),
+                               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
+                       };
+                       resolveAttachmentRefs.push_back(attachmentRef);
+                       attachments.push_back(singlesampleAttachment);
+               }
+       }
+
+       DE_ASSERT(colorAttachmentRefs.size() == resolveAttachmentRefs.size());
+       DE_ASSERT(attachments.size() == colorAttachmentRefs.size() + resolveAttachmentRefs.size());
+
+       {
+               const VkSubpassDescription      subpass =
+               {
+                       (VkSubpassDescriptionFlags)0,
+                       VK_PIPELINE_BIND_POINT_GRAPHICS,
+
+                       0u,
+                       DE_NULL,
+
+                       (deUint32)colorAttachmentRefs.size(),
+                       &colorAttachmentRefs[0],
+                       &resolveAttachmentRefs[0],
+
+                       DE_NULL,
+                       0u,
+                       DE_NULL
+               };
+               const VkRenderPassCreateInfo    createInfo      =
+               {
+                       VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
+                       DE_NULL,
+                       (VkRenderPassCreateFlags)0u,
+
+                       (deUint32)attachments.size(),
+                       &attachments[0],
+
+                       1u,
+                       &subpass,
+
+                       0u,
+                       DE_NULL
+               };
+
+               return createRenderPass(vkd, device, &createInfo);
+       }
+}
+
+Move<VkFramebuffer> createFramebuffer (const DeviceInterface&                  vkd,
+                                                                          VkDevice                                                     device,
+                                                                          VkRenderPass                                         renderPass,
+                                                                          const std::vector<VkImageViewSp>&    multisampleImageViews,
+                                                                          const std::vector<VkImageViewSp>&    singlesampleImageViews,
+                                                                          deUint32                                                     width,
+                                                                          deUint32                                                     height)
+{
+       std::vector<VkImageView> attachments;
+
+       attachments.reserve(multisampleImageViews.size() + singlesampleImageViews.size());
+
+       DE_ASSERT(multisampleImageViews.size() == singlesampleImageViews.size());
+
+       for (size_t ndx = 0; ndx < multisampleImageViews.size(); ndx++)
+       {
+               attachments.push_back(**multisampleImageViews[ndx]);
+               attachments.push_back(**singlesampleImageViews[ndx]);
+       }
+
+       const VkFramebufferCreateInfo createInfo =
+       {
+               VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
+               DE_NULL,
+               0u,
+
+               renderPass,
+               (deUint32)attachments.size(),
+               &attachments[0],
+
+               width,
+               height,
+               1u
+       };
+
+       return createFramebuffer(vkd, device, &createInfo);
+}
+
+Move<VkPipelineLayout> createRenderPipelineLayout (const DeviceInterface&      vkd,
+                                                                                                  VkDevice                                     device)
+{
+       const VkPushConstantRange                       pushConstant                    =
+       {
+               VK_SHADER_STAGE_FRAGMENT_BIT,
+               0u,
+               4u
+       };
+       const VkPipelineLayoutCreateInfo        createInfo      =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+               DE_NULL,
+               (vk::VkPipelineLayoutCreateFlags)0,
+
+               0u,
+               DE_NULL,
+
+               1u,
+               &pushConstant
+       };
+
+       return createPipelineLayout(vkd, device, &createInfo);
+}
+
+Move<VkPipeline> createRenderPipeline (const DeviceInterface&                                                  vkd,
+                                                                          VkDevice                                                                                     device,
+                                                                          VkRenderPass                                                                         renderPass,
+                                                                          VkPipelineLayout                                                                     pipelineLayout,
+                                                                          const vk::ProgramCollection<vk::ProgramBinary>&      binaryCollection,
+                                                                          deUint32                                                                                     width,
+                                                                          deUint32                                                                                     height,
+                                                                          deUint32                                                                                     sampleCount)
+{
+       const Unique<VkShaderModule>    vertexShaderModule                      (createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
+       const Unique<VkShaderModule>    fragmentShaderModule            (createShaderModule(vkd, device, binaryCollection.get("quad-frag"), 0u));
+       const VkSpecializationInfo              emptyShaderSpecializations      =
+       {
+               0u,
+               DE_NULL,
+
+               0u,
+               DE_NULL
+       };
+       // Disable blending
+       const VkPipelineColorBlendAttachmentState attachmentBlendState =
+       {
+               VK_FALSE,
+               VK_BLEND_FACTOR_SRC_ALPHA,
+               VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
+               VK_BLEND_OP_ADD,
+               VK_BLEND_FACTOR_ONE,
+               VK_BLEND_FACTOR_ONE,
+               VK_BLEND_OP_ADD,
+               VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT
+       };
+       const VkPipelineColorBlendAttachmentState attachmentBlendStates[] =
+       {
+               attachmentBlendState,
+               attachmentBlendState,
+               attachmentBlendState,
+               attachmentBlendState,
+       };
+       const VkPipelineShaderStageCreateInfo shaderStages[2] =
+       {
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+                       DE_NULL,
+                       (VkPipelineShaderStageCreateFlags)0u,
+                       VK_SHADER_STAGE_VERTEX_BIT,
+                       *vertexShaderModule,
+                       "main",
+                       &emptyShaderSpecializations
+               },
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+                       DE_NULL,
+                       (VkPipelineShaderStageCreateFlags)0u,
+                       VK_SHADER_STAGE_FRAGMENT_BIT,
+                       *fragmentShaderModule,
+                       "main",
+                       &emptyShaderSpecializations
+               }
+       };
+       const VkPipelineVertexInputStateCreateInfo vertexInputState =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
+               DE_NULL,
+               (VkPipelineVertexInputStateCreateFlags)0u,
+
+               0u,
+               DE_NULL,
+
+               0u,
+               DE_NULL
+       };
+       const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
+               DE_NULL,
+
+               (VkPipelineInputAssemblyStateCreateFlags)0u,
+               VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
+               VK_FALSE
+       };
+       const VkViewport viewport =
+       {
+               0.0f,  0.0f,
+               (float)width, (float)height,
+
+               0.0f, 1.0f
+       };
+       const VkRect2D scissor =
+       {
+               { 0u, 0u },
+               { width, height }
+       };
+       const VkPipelineViewportStateCreateInfo viewportState =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
+               DE_NULL,
+               (VkPipelineViewportStateCreateFlags)0u,
+
+               1u,
+               &viewport,
+
+               1u,
+               &scissor
+       };
+       const VkPipelineRasterizationStateCreateInfo rasterState =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
+               DE_NULL,
+               (VkPipelineRasterizationStateCreateFlags)0u,
+               VK_TRUE,
+               VK_FALSE,
+               VK_POLYGON_MODE_FILL,
+               VK_CULL_MODE_NONE,
+               VK_FRONT_FACE_COUNTER_CLOCKWISE,
+               VK_FALSE,
+               0.0f,
+               0.0f,
+               0.0f,
+               1.0f
+       };
+       const VkPipelineMultisampleStateCreateInfo multisampleState =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
+               DE_NULL,
+               (VkPipelineMultisampleStateCreateFlags)0u,
+
+               sampleCountBitFromSampleCount(sampleCount),
+               VK_FALSE,
+               0.0f,
+               DE_NULL,
+               VK_FALSE,
+               VK_FALSE,
+       };
+       const VkPipelineDepthStencilStateCreateInfo depthStencilState =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
+               DE_NULL,
+               (VkPipelineDepthStencilStateCreateFlags)0u,
+
+               VK_FALSE,
+               VK_TRUE,
+               VK_COMPARE_OP_ALWAYS,
+               VK_FALSE,
+               VK_TRUE,
+               {
+                       VK_STENCIL_OP_KEEP,
+                       VK_STENCIL_OP_INCREMENT_AND_WRAP,
+                       VK_STENCIL_OP_KEEP,
+                       VK_COMPARE_OP_ALWAYS,
+                       ~0u,
+                       ~0u,
+                       0xFFu / (sampleCount + 1)
+               },
+               {
+                       VK_STENCIL_OP_KEEP,
+                       VK_STENCIL_OP_INCREMENT_AND_WRAP,
+                       VK_STENCIL_OP_KEEP,
+                       VK_COMPARE_OP_ALWAYS,
+                       ~0u,
+                       ~0u,
+                       0xFFu / (sampleCount + 1)
+               },
+
+               0.0f,
+               1.0f
+       };
+       const VkPipelineColorBlendStateCreateInfo blendState =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
+               DE_NULL,
+               (VkPipelineColorBlendStateCreateFlags)0u,
+
+               VK_FALSE,
+               VK_LOGIC_OP_COPY,
+               DE_LENGTH_OF_ARRAY(attachmentBlendStates),
+               attachmentBlendStates,
+               { 0.0f, 0.0f, 0.0f, 0.0f }
+       };
+       const VkGraphicsPipelineCreateInfo createInfo =
+       {
+               VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
+               DE_NULL,
+               (VkPipelineCreateFlags)0u,
+
+               2,
+               shaderStages,
+
+               &vertexInputState,
+               &inputAssemblyState,
+               DE_NULL,
+               &viewportState,
+               &rasterState,
+               &multisampleState,
+               &depthStencilState,
+               &blendState,
+               (const VkPipelineDynamicStateCreateInfo*)DE_NULL,
+               pipelineLayout,
+
+               renderPass,
+               0u,
+               DE_NULL,
+               0u
+       };
+
+       return createGraphicsPipeline(vkd, device, DE_NULL, &createInfo);
+}
+
+struct TestConfig
+{
+                               TestConfig              (VkFormat       format_,
+                                                                deUint32       sampleCount_)
+               : format                (format_)
+               , sampleCount   (sampleCount_)
+       {
+       }
+
+       VkFormat        format;
+       deUint32        sampleCount;
+};
+
+class MultisampleRenderPassTestInstance : public TestInstance
+{
+public:
+                                                                                                       MultisampleRenderPassTestInstance       (Context& context, TestConfig config);
+                                                                                                       ~MultisampleRenderPassTestInstance      (void);
+
+       tcu::TestStatus                                                                 iterate                                                         (void);
+
+private:
+       void                                                                                    submit                                                          (void);
+       void                                                                                    verify                                                          (void);
+
+       const VkFormat                                                                  m_format;
+       const deUint32                                                                  m_sampleCount;
+       const deUint32                                                                  m_width;
+       const deUint32                                                                  m_height;
+
+       const std::vector<VkImageSp>                                    m_multisampleImages;
+       const std::vector<de::SharedPtr<Allocation> >   m_multisampleImageMemory;
+       const std::vector<VkImageViewSp>                                m_multisampleImageViews;
+
+       const std::vector<VkImageSp>                                    m_singlesampleImages;
+       const std::vector<de::SharedPtr<Allocation> >   m_singlesampleImageMemory;
+       const std::vector<VkImageViewSp>                                m_singlesampleImageViews;
+
+       const Unique<VkRenderPass>                                              m_renderPass;
+       const Unique<VkFramebuffer>                                             m_framebuffer;
+
+       const Unique<VkPipelineLayout>                                  m_renderPipelineLayout;
+       const Unique<VkPipeline>                                                m_renderPipeline;
+
+       const std::vector<VkBufferSp>                                   m_buffers;
+       const std::vector<de::SharedPtr<Allocation> >   m_bufferMemory;
+
+       const Unique<VkCommandPool>                                             m_commandPool;
+       tcu::TextureLevel                                                               m_sum;
+       deUint32                                                                                m_sampleMask;
+       tcu::ResultCollector                                                    m_resultCollector;
+};
+
+MultisampleRenderPassTestInstance::MultisampleRenderPassTestInstance (Context& context, TestConfig config)
+       : TestInstance                          (context)
+       , m_format                                      (config.format)
+       , m_sampleCount                         (config.sampleCount)
+       , m_width                                       (32u)
+       , m_height                                      (32u)
+
+       , m_multisampleImages           (createMultisampleImages(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_format, m_sampleCount, m_width, m_height))
+       , m_multisampleImageMemory      (createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_multisampleImages))
+       , m_multisampleImageViews       (createImageViews(context.getDeviceInterface(), context.getDevice(), m_multisampleImages, m_format, VK_IMAGE_ASPECT_COLOR_BIT))
+
+       , m_singlesampleImages          (createSingleSampleImages(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_format, m_width, m_height))
+       , m_singlesampleImageMemory     (createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_singlesampleImages))
+       , m_singlesampleImageViews      (createImageViews(context.getDeviceInterface(), context.getDevice(), m_singlesampleImages, m_format, VK_IMAGE_ASPECT_COLOR_BIT))
+
+       , m_renderPass                          (createRenderPass(context.getDeviceInterface(), context.getDevice(), m_format, m_sampleCount))
+       , m_framebuffer                         (createFramebuffer(context.getDeviceInterface(), context.getDevice(), *m_renderPass, m_multisampleImageViews, m_singlesampleImageViews, m_width, m_height))
+
+       , m_renderPipelineLayout        (createRenderPipelineLayout(context.getDeviceInterface(), context.getDevice()))
+       , m_renderPipeline                      (createRenderPipeline(context.getDeviceInterface(), context.getDevice(), *m_renderPass, *m_renderPipelineLayout, context.getBinaryCollection(), m_width, m_height, m_sampleCount))
+
+       , m_buffers                                     (createBuffers(context.getDeviceInterface(), context.getDevice(), m_format, m_width, m_height))
+       , m_bufferMemory                        (createBufferMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_buffers))
+
+       , m_commandPool                         (createCommandPool(context.getDeviceInterface(), context.getDevice(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex()))
+       , m_sum                                         (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), m_width, m_height)
+       , m_sampleMask                          (0x0u)
+{
+       tcu::clear(m_sum.getAccess(), Vec4(0.0f, 0.0f, 0.0f, 0.0f));
+}
+
+MultisampleRenderPassTestInstance::~MultisampleRenderPassTestInstance (void)
+{
+}
+
+void MultisampleRenderPassTestInstance::submit (void)
+{
+       const DeviceInterface&                  vkd                             (m_context.getDeviceInterface());
+       const VkDevice                                  device                  (m_context.getDevice());
+       const Unique<VkCommandBuffer>   commandBuffer   (allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
+
+       {
+               const VkCommandBufferBeginInfo beginInfo =
+               {
+                       VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+                       DE_NULL,
+
+                       VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
+                       DE_NULL
+               };
+
+               VK_CHECK(vkd.beginCommandBuffer(*commandBuffer, &beginInfo));
+       }
+
+       {
+               const VkRenderPassBeginInfo beginInfo =
+               {
+                       VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
+                       DE_NULL,
+
+                       *m_renderPass,
+                       *m_framebuffer,
+
+                       {
+                               { 0u, 0u },
+                               { m_width, m_height }
+                       },
+
+                       0u,
+                       DE_NULL
+               };
+               vkd.cmdBeginRenderPass(*commandBuffer, &beginInfo, VK_SUBPASS_CONTENTS_INLINE);
+       }
+
+       // Memory barriers between previous copies and rendering
+       {
+               std::vector<VkImageMemoryBarrier> barriers;
+
+               for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
+               {
+                       const VkImageMemoryBarrier barrier =
+                       {
+                               VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+                               DE_NULL,
+
+                               VK_ACCESS_TRANSFER_READ_BIT,
+                               VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+
+                               VK_IMAGE_LAYOUT_UNDEFINED,
+                               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+
+                               VK_QUEUE_FAMILY_IGNORED,
+                               VK_QUEUE_FAMILY_IGNORED,
+
+                               **m_singlesampleImages[dstNdx],
+                               {
+                                       VK_IMAGE_ASPECT_COLOR_BIT,
+                                       0u,
+                                       1u,
+                                       0u,
+                                       1u
+                               }
+                       };
+
+                       barriers.push_back(barrier);
+               }
+
+               vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0]);
+       }
+
+       // Clear everything to black
+       {
+               const tcu::TextureFormat                        format                  (mapVkFormat(m_format));
+               const tcu::TextureChannelClass          channelClass    (tcu::getTextureChannelClass(format.type));
+               VkClearValue                                            value;
+
+               switch (channelClass)
+               {
+                       case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
+                               value = makeClearValueColorF32(-1.0f, -1.0f, -1.0f, -1.0f);
+                               break;
+
+                       case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
+                               value = makeClearValueColorF32(0.0f, 0.0f, 0.0f, 0.0f);
+                               break;
+
+                       case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
+                               value = makeClearValueColorF32(-1.0f, -1.0f, -1.0f, -1.0f);
+                               break;
+
+                       case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
+                               value = makeClearValueColorI32(-128, -128, -128, -128);
+                               break;
+
+                       case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
+                               value = makeClearValueColorU32(0u, 0u, 0u, 0u);
+                               break;
+
+                       default:
+                               DE_FATAL("Unknown channel class");
+               }
+               const VkClearAttachment                         colors[]                =
+               {
+                       {
+                               VK_IMAGE_ASPECT_COLOR_BIT,
+                               0u,
+                               value
+                       },
+                       {
+                               VK_IMAGE_ASPECT_COLOR_BIT,
+                               1u,
+                               value
+                       },
+                       {
+                               VK_IMAGE_ASPECT_COLOR_BIT,
+                               2u,
+                               value
+                       },
+                       {
+                               VK_IMAGE_ASPECT_COLOR_BIT,
+                               3u,
+                               value
+                       }
+               };
+               const VkClearRect rect =
+               {
+                       {
+                               { 0u, 0u },
+                               { m_width, m_height }
+                       },
+                       0u,
+                       1u,
+               };
+               vkd.cmdClearAttachments(*commandBuffer, DE_LENGTH_OF_ARRAY(colors), colors, 1u, &rect);
+       }
+
+       // Render black samples
+       {
+               vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline);
+               vkd.cmdPushConstants(*commandBuffer, *m_renderPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(m_sampleMask), &m_sampleMask);
+               vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
+       }
+
+       vkd.cmdEndRenderPass(*commandBuffer);
+
+       // Memory barriers between rendering and copies
+       {
+               std::vector<VkImageMemoryBarrier> barriers;
+
+               for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
+               {
+                       const VkImageMemoryBarrier barrier =
+                       {
+                               VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+                               DE_NULL,
+
+                               VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+                               VK_ACCESS_TRANSFER_READ_BIT,
+
+                               VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+                               VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+
+                               VK_QUEUE_FAMILY_IGNORED,
+                               VK_QUEUE_FAMILY_IGNORED,
+
+                               **m_singlesampleImages[dstNdx],
+                               {
+                                       VK_IMAGE_ASPECT_COLOR_BIT,
+                                       0u,
+                                       1u,
+                                       0u,
+                                       1u
+                               }
+                       };
+
+                       barriers.push_back(barrier);
+               }
+
+               vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0]);
+       }
+
+       // Copy image memory to buffers
+       for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
+       {
+               const VkBufferImageCopy region =
+               {
+                       0u,
+                       0u,
+                       0u,
+                       {
+                               VK_IMAGE_ASPECT_COLOR_BIT,
+                               0u,
+                               0u,
+                               1u,
+                       },
+                       { 0u, 0u, 0u },
+                       { m_width, m_height, 1u }
+               };
+
+               vkd.cmdCopyImageToBuffer(*commandBuffer, **m_singlesampleImages[dstNdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_buffers[dstNdx], 1u, &region);
+       }
+
+       // Memory barriers between copies and host access
+       {
+               std::vector<VkBufferMemoryBarrier> barriers;
+
+               for (size_t dstNdx = 0; dstNdx < m_buffers.size(); dstNdx++)
+               {
+                       const VkBufferMemoryBarrier barrier =
+                       {
+                               VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
+                               DE_NULL,
+
+                               VK_ACCESS_TRANSFER_WRITE_BIT,
+                               VK_ACCESS_HOST_READ_BIT,
+
+                               VK_QUEUE_FAMILY_IGNORED,
+                               VK_QUEUE_FAMILY_IGNORED,
+
+                               **m_buffers[dstNdx],
+                               0u,
+                               VK_WHOLE_SIZE
+                       };
+
+                       barriers.push_back(barrier);
+               }
+
+               vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0], 0u, DE_NULL);
+       }
+
+       VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
+
+       {
+               const VkSubmitInfo submitInfo =
+               {
+                       VK_STRUCTURE_TYPE_SUBMIT_INFO,
+                       DE_NULL,
+
+                       0u,
+                       DE_NULL,
+                       DE_NULL,
+
+                       1u,
+                       &*commandBuffer,
+
+                       0u,
+                       DE_NULL
+               };
+
+               VK_CHECK(vkd.queueSubmit(m_context.getUniversalQueue(), 1u, &submitInfo, (VkFence)0u));
+
+               VK_CHECK(vkd.queueWaitIdle(m_context.getUniversalQueue()));
+       }
+}
+
+void MultisampleRenderPassTestInstance::verify (void)
+{
+       const Vec4                                                      errorColor              (1.0f, 0.0f, 0.0f, 1.0f);
+       const Vec4                                                      okColor                 (0.0f, 0.0f, 0.0f, 1.0f);
+       const tcu::TextureFormat                        format                  (mapVkFormat(m_format));
+       const tcu::TextureChannelClass          channelClass    (tcu::getTextureChannelClass(format.type));
+       const void* const                                       ptrs[]                  =
+       {
+               m_bufferMemory[0]->getHostPtr(),
+               m_bufferMemory[1]->getHostPtr(),
+               m_bufferMemory[2]->getHostPtr(),
+               m_bufferMemory[3]->getHostPtr()
+       };
+       const tcu::ConstPixelBufferAccess       accesses[]              =
+       {
+               tcu::ConstPixelBufferAccess(format, m_width, m_height, 1, ptrs[0]),
+               tcu::ConstPixelBufferAccess(format, m_width, m_height, 1, ptrs[1]),
+               tcu::ConstPixelBufferAccess(format, m_width, m_height, 1, ptrs[2]),
+               tcu::ConstPixelBufferAccess(format, m_width, m_height, 1, ptrs[3])
+       };
+       tcu::TextureLevel                                       errorMask               (tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width, m_height);
+       tcu::TestLog&                                           log                             (m_context.getTestContext().getLog());
+
+       switch (channelClass)
+       {
+               case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
+               case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
+               case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
+               {
+                       const int       componentCount  (tcu::getNumUsedChannels(format.order));
+                       bool            isOk                    = true;
+                       float           clearValue;
+                       float           renderValue;
+
+                       switch (channelClass)
+                       {
+                               case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
+                               case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
+                                       clearValue  = -1.0f;
+                                       renderValue = 1.0f;
+                                       break;
+
+                               case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
+                                       clearValue  = 0.0f;
+                                       renderValue = 1.0f;
+                                       break;
+
+                               default:
+                                       clearValue  = 0.0f;
+                                       renderValue = 0.0f;
+                                       DE_FATAL("Unknown channel class");
+                       }
+
+                       for (deUint32 y = 0; y < m_height; y++)
+                       for (deUint32 x = 0; x < m_width; x++)
+                       {
+                               // Color has to be black if no samples were covered, white if all samples were covered or same in every attachment
+                               const Vec4      firstColor      (accesses[0].getPixel(x, y));
+                               const Vec4      refColor        (m_sampleMask == 0x0u
+                                                                               ? Vec4(clearValue,
+                                                                                               componentCount > 1 ? clearValue : 0.0f,
+                                                                                               componentCount > 2 ? clearValue : 0.0f,
+                                                                                               componentCount > 3 ? clearValue : 1.0f)
+                                                                               : m_sampleMask == ((0x1u << m_sampleCount) - 1u)
+                                                                               ? Vec4(renderValue,
+                                                                                               componentCount > 1 ? renderValue : 0.0f,
+                                                                                               componentCount > 2 ? renderValue : 0.0f,
+                                                                                               componentCount > 3 ? renderValue : 1.0f)
+                                                                               : firstColor);
+
+                               errorMask.getAccess().setPixel(okColor, x, y);
+
+                               for (size_t attachmentNdx = 0; attachmentNdx < MAX_COLOR_ATTACHMENT_COUNT; attachmentNdx++)
+                               {
+                                       const Vec4 color (accesses[attachmentNdx].getPixel(x, y));
+
+                                       if (refColor != color)
+                                       {
+                                               isOk = false;
+                                               errorMask.getAccess().setPixel(errorColor, x, y);
+                                               break;
+                                       }
+                               }
+
+                               {
+                                       const Vec4 old = m_sum.getAccess().getPixel(x, y);
+
+                                       m_sum.getAccess().setPixel(old + firstColor, x, y);
+                               }
+                       }
+
+                       if (!isOk)
+                       {
+                               const std::string                       sectionName     ("ResolveVerifyWithMask" + de::toString(m_sampleMask));
+                               const tcu::ScopedLogSection     section         (log, sectionName, sectionName);
+
+                               for (size_t attachmentNdx = 0; attachmentNdx < MAX_COLOR_ATTACHMENT_COUNT; attachmentNdx++)
+                               {
+                                       const std::string       name    ("Attachment" + de::toString(attachmentNdx));
+                                       m_context.getTestContext().getLog() << tcu::LogImage(name.c_str(), name.c_str(), accesses[attachmentNdx]);
+                               }
+
+                               m_context.getTestContext().getLog() << tcu::LogImage("ErrorMask", "ErrorMask", errorMask.getAccess());
+
+                               if (m_sampleMask == 0x0u)
+                               {
+                                       m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
+                                       m_resultCollector.fail("Empty sample mask didn't produce correct pixel values");
+                               }
+                               else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
+                               {
+                                       m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
+                                       m_resultCollector.fail("Full sample mask didn't produce correct pixel values");
+                               }
+                               else
+                               {
+                                       m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve is inconsistent between attachments" << tcu::TestLog::EndMessage;
+                                       m_resultCollector.fail("Resolve is inconsistent between attachments");
+                               }
+                       }
+                       break;
+               }
+
+               case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
+               {
+                       const int               componentCount                  (tcu::getNumUsedChannels(format.order));
+                       const UVec4             bitDepth                                (tcu::getTextureFormatBitDepth(format).cast<deUint32>());
+                       const UVec4             renderValue                             (tcu::select((UVec4(1u) << tcu::min(UVec4(8u), bitDepth)) - UVec4(1u),
+                                                                                                                                 UVec4(0u, 0u, 0u, 1u),
+                                                                                                                                 tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
+                       const UVec4             clearValue                              (tcu::select(UVec4(0u),
+                                                                                                                                UVec4(0u, 0u, 0u, 1u),
+                                                                                                                                tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
+                       bool                    unexpectedValues                = false;
+                       bool                    inconsistentComponents  = false;
+                       bool                    inconsistentAttachments = false;
+
+                       for (deUint32 y = 0; y < m_height; y++)
+                       for (deUint32 x = 0; x < m_width; x++)
+                       {
+                               // Color has to be all zeros if no samples were covered, all 255 if all samples were covered or consistent across all attachments
+                               const UVec4 refColor    (m_sampleMask == 0x0u
+                                                                               ? clearValue
+                                                                               : m_sampleMask == ((0x1u << m_sampleCount) - 1u)
+                                                                               ? renderValue
+                                                                               : accesses[0].getPixelUint(x, y));
+
+                               errorMask.getAccess().setPixel(okColor, x, y);
+
+                               // If reference value was taken from first attachment, check that it is valid value i.e. clear or render value
+                               if (m_sampleMask != 0x0u && m_sampleMask != ((0x1u << m_sampleCount) - 1u))
+                               {
+                                       // Each component must be resolved same way
+                                       const BVec4             isRenderValue   (refColor == renderValue);
+                                       const BVec4             isClearValue    (refColor == clearValue);
+
+                                       unexpectedValues                = tcu::anyNotEqual(tcu::logicalOr(isRenderValue, isClearValue), BVec4(true));
+                                       inconsistentComponents  = !(tcu::allEqual(isRenderValue, BVec4(true)) || tcu::allEqual(isClearValue, BVec4(true)));
+
+                                       if (unexpectedValues || inconsistentComponents)
+                                               errorMask.getAccess().setPixel(errorColor, x, y);
+                               }
+
+                               for (size_t attachmentNdx = 0; attachmentNdx < MAX_COLOR_ATTACHMENT_COUNT; attachmentNdx++)
+                               {
+                                       const UVec4 color (accesses[attachmentNdx].getPixelUint(x, y));
+
+                                       if (refColor != color)
+                                       {
+                                               inconsistentAttachments = true;
+                                               errorMask.getAccess().setPixel(errorColor, x, y);
+                                               break;
+                                       }
+                               }
+                       }
+
+                       if (unexpectedValues || inconsistentComponents || inconsistentAttachments)
+                       {
+                               const std::string                       sectionName     ("ResolveVerifyWithMask" + de::toString(m_sampleMask));
+                               const tcu::ScopedLogSection     section         (log, sectionName, sectionName);
+
+                               for (size_t attachmentNdx = 0; attachmentNdx < MAX_COLOR_ATTACHMENT_COUNT; attachmentNdx++)
+                               {
+                                       const std::string       name    ("Attachment" + de::toString(attachmentNdx));
+                                       m_context.getTestContext().getLog() << tcu::LogImage(name.c_str(), name.c_str(), accesses[attachmentNdx]);
+                               }
+
+                               m_context.getTestContext().getLog() << tcu::LogImage("ErrorMask", "ErrorMask", errorMask.getAccess());
+
+                               if (m_sampleMask == 0x0u)
+                               {
+                                       m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
+                                       m_resultCollector.fail("Empty sample mask didn't produce correct pixels");
+                               }
+                               else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
+                               {
+                                       m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
+                                       m_resultCollector.fail("Full sample mask didn't produce correct pixels");
+                               }
+                               else
+                               {
+                                       if (unexpectedValues)
+                                       {
+                                               m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve produced unexpected values i.e. not " << clearValue << " or " << renderValue << tcu::TestLog::EndMessage;
+                                               m_resultCollector.fail("Resolve produced unexpected values");
+                                       }
+
+                                       if (inconsistentComponents)
+                                       {
+                                               m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different components of attachment were resolved to different values." << tcu::TestLog::EndMessage;
+                                               m_resultCollector.fail("Different components of attachment were resolved to different values.");
+                                       }
+
+                                       if (inconsistentAttachments)
+                                       {
+                                               m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different attachments were resolved to different values." << tcu::TestLog::EndMessage;
+                                               m_resultCollector.fail("Different attachments were resolved to different values.");
+                                       }
+                               }
+                       }
+                       break;
+               }
+
+               case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
+               {
+                       const int               componentCount                  (tcu::getNumUsedChannels(format.order));
+                       const IVec4             bitDepth                                (tcu::getTextureFormatBitDepth(format));
+                       const IVec4             renderValue                             (tcu::select((IVec4(1) << (tcu::min(IVec4(8), bitDepth) - IVec4(1))) - IVec4(1),
+                                                                                                                                 IVec4(0, 0, 0, 1),
+                                                                                                                                 tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
+                       const IVec4             clearValue                              (tcu::select(-(IVec4(1) << (tcu::min(IVec4(8), bitDepth) - IVec4(1))),
+                                                                                                                                IVec4(0, 0, 0, 1),
+                                                                                                                                tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
+                       bool                    unexpectedValues                = false;
+                       bool                    inconsistentComponents  = false;
+                       bool                    inconsistentAttachments = false;
+
+                       for (deUint32 y = 0; y < m_height; y++)
+                       for (deUint32 x = 0; x < m_width; x++)
+                       {
+                               // Color has to be all zeros if no samples were covered, all 255 if all samples were covered or consistent across all attachments
+                               const IVec4 refColor    (m_sampleMask == 0x0u
+                                                                               ? clearValue
+                                                                               : m_sampleMask == ((0x1u << m_sampleCount) - 1u)
+                                                                               ? renderValue
+                                                                               : accesses[0].getPixelInt(x, y));
+
+                               errorMask.getAccess().setPixel(okColor, x, y);
+
+                               // If reference value was taken from first attachment, check that it is valid value i.e. clear or render value
+                               if (m_sampleMask != 0x0u && m_sampleMask != ((0x1u << m_sampleCount) - 1u))
+                               {
+                                       // Each component must be resolved same way
+                                       const BVec4             isRenderValue   (refColor == renderValue);
+                                       const BVec4             isClearValue    (refColor == clearValue);
+
+                                       unexpectedValues                = tcu::anyNotEqual(tcu::logicalOr(isRenderValue, isClearValue), BVec4(true));
+                                       inconsistentComponents  = !(tcu::allEqual(isRenderValue, BVec4(true)) || tcu::allEqual(isClearValue, BVec4(true)));
+
+                                       if (unexpectedValues || inconsistentComponents)
+                                               errorMask.getAccess().setPixel(errorColor, x, y);
+                               }
+                       }
+
+                       if (unexpectedValues || inconsistentComponents || inconsistentAttachments)
+                       {
+                               const std::string                       sectionName     ("ResolveVerifyWithMask" + de::toString(m_sampleMask));
+                               const tcu::ScopedLogSection     section         (log, sectionName, sectionName);
+
+                               for (size_t attachmentNdx = 0; attachmentNdx < MAX_COLOR_ATTACHMENT_COUNT; attachmentNdx++)
+                               {
+                                       const std::string       name    ("Attachment" + de::toString(attachmentNdx));
+                                       m_context.getTestContext().getLog() << tcu::LogImage(name.c_str(), name.c_str(), accesses[attachmentNdx]);
+                               }
+
+                               m_context.getTestContext().getLog() << tcu::LogImage("ErrorMask", "ErrorMask", errorMask.getAccess());
+
+                               if (m_sampleMask == 0x0u)
+                               {
+                                       m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
+                                       m_resultCollector.fail("Empty sample mask didn't produce correct pixels");
+                               }
+                               else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
+                               {
+                                       m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
+                                       m_resultCollector.fail("Full sample mask didn't produce correct pixels");
+                               }
+                               else
+                               {
+                                       if (unexpectedValues)
+                                       {
+                                               m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve produced unexpected values i.e. not " << clearValue << " or " << renderValue << tcu::TestLog::EndMessage;
+                                               m_resultCollector.fail("Resolve produced unexpected values");
+                                       }
+
+                                       if (inconsistentComponents)
+                                       {
+                                               m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different components of attachment were resolved to different values." << tcu::TestLog::EndMessage;
+                                               m_resultCollector.fail("Different components of attachment were resolved to different values.");
+                                       }
+
+                                       if (inconsistentAttachments)
+                                       {
+                                               m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different attachments were resolved to different values." << tcu::TestLog::EndMessage;
+                                               m_resultCollector.fail("Different attachments were resolved to different values.");
+                                       }
+                               }
+                       }
+                       break;
+               }
+
+               default:
+                       DE_FATAL("Unknown channel class");
+       }
+}
+
+tcu::TestStatus MultisampleRenderPassTestInstance::iterate (void)
+{
+       if (m_sampleMask == 0u)
+       {
+               const tcu::TextureFormat                format                  (mapVkFormat(m_format));
+               const tcu::TextureChannelClass  channelClass    (tcu::getTextureChannelClass(format.type));
+               tcu::TestLog&                                   log                             (m_context.getTestContext().getLog());
+
+               switch (channelClass)
+               {
+                       case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
+                               log << TestLog::Message << "Clearing target to zero and rendering 255 pixels with every possible sample mask" << TestLog::EndMessage;
+                               break;
+
+                       case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
+                               log << TestLog::Message << "Clearing target to -128 and rendering 127 pixels with every possible sample mask" << TestLog::EndMessage;
+                               break;
+
+                       case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
+                       case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
+                       case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
+                               log << TestLog::Message << "Clearing target to black and rendering white pixels with every possible sample mask" << TestLog::EndMessage;
+                               break;
+
+                       default:
+                               DE_FATAL("Unknown channel class");
+               }
+       }
+
+       submit();
+       verify();
+
+       if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
+       {
+               const tcu::TextureFormat                format                  (mapVkFormat(m_format));
+               const tcu::TextureChannelClass  channelClass    (tcu::getTextureChannelClass(format.type));
+               tcu::TestLog&                                   log                             (m_context.getTestContext().getLog());
+
+               if (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT
+                               || channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT
+                               || channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
+               {
+                       const float                     threshold               = 0.05f;
+                       const int                       componentCount  (tcu::getNumUsedChannels(format.order));
+                       const Vec4                      errorColor              (1.0f, 0.0f, 0.0f, 1.0f);
+                       const Vec4                      okColor                 (0.0f, 0.0f, 0.0f, 1.0f);
+                       tcu::TextureLevel       errorMask               (tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width, m_height);
+                       bool                            isOk                    = true;
+                       Vec4                            maxDiff                 (0.0f);
+                       Vec4                            expectedAverage;
+
+                       switch (channelClass)
+                       {
+                               case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
+                               {
+                                       expectedAverage = Vec4(0.5f, componentCount > 1 ? 0.5f : 0.0f, componentCount > 2 ? 0.5f : 0.0f, componentCount > 3 ? 0.5f : 1.0f);
+                                       break;
+                               }
+
+                               case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
+                               case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
+                               {
+                                       expectedAverage = Vec4(0.0f, 0.0f, 0.0f, componentCount > 3 ? 0.0f : 1.0f);
+                                       break;
+                               }
+
+                               default:
+                                       DE_FATAL("Unknown channel class");
+                       }
+
+                       for (deUint32 y = 0; y < m_height; y++)
+                       for (deUint32 x = 0; x < m_width; x++)
+                       {
+                               const Vec4      sum             (m_sum.getAccess().getPixel(x, y));
+                               const Vec4      average (sum / Vec4((float)(0x1u << m_sampleCount)));
+                               const Vec4      diff    (tcu::abs(average - expectedAverage));
+
+                               m_sum.getAccess().setPixel(average, x, y);
+                               errorMask.getAccess().setPixel(okColor, x, y);
+
+                               if (diff[0] > threshold
+                                               || diff[1] > threshold
+                                               || diff[2] > threshold
+                                               || diff[3] > threshold)
+                               {
+                                       isOk    = false;
+                                       maxDiff = tcu::max(maxDiff, diff);
+                                       errorMask.getAccess().setPixel(errorColor, x, y);
+                               }
+                       }
+
+                       log << TestLog::Image("Average resolved values in attachment 0", "Average resolved values in attachment 0", m_sum);
+
+                       if (!isOk)
+                       {
+                               m_context.getTestContext().getLog() << tcu::LogImage("ErrorMask", "ErrorMask", errorMask.getAccess());
+
+                               log << TestLog::Message << "Average resolved values differ from expected average values by more than " << threshold << " max per component diff " << maxDiff << TestLog::EndMessage;
+                       }
+               }
+
+               return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
+       }
+       else
+       {
+               m_sampleMask++;
+               return tcu::TestStatus::incomplete();
+       }
+}
+
+struct Programs
+{
+       void init (vk::SourceCollections& dst, TestConfig config) const
+       {
+               const tcu::TextureFormat                format                  (mapVkFormat(config.format));
+               const tcu::TextureChannelClass  channelClass    (tcu::getTextureChannelClass(format.type));
+
+               dst.glslSources.add("quad-vert") << glu::VertexSource(
+                       "#version 450\n"
+                       "out gl_PerVertex {\n"
+                       "\tvec4 gl_Position;\n"
+                       "};\n"
+                       "highp float;\n"
+                       "void main (void) {\n"
+                       "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
+                       "\t                   ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
+                       "}\n");
+
+               switch (channelClass)
+               {
+                       case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
+                               dst.glslSources.add("quad-frag") << glu::FragmentSource(
+                                       "#version 450\n"
+                                       "layout(push_constant) uniform PushConstant {\n"
+                                       "\thighp uint sampleMask;\n"
+                                       "} pushConstants;\n"
+                                       "layout(location = 0) out highp uvec4 o_color0;\n"
+                                       "layout(location = 1) out highp uvec4 o_color1;\n"
+                                       "layout(location = 2) out highp uvec4 o_color2;\n"
+                                       "layout(location = 3) out highp uvec4 o_color3;\n"
+                                       "void main (void)\n"
+                                       "{\n"
+                                       "\tgl_SampleMask[0] = int(pushConstants.sampleMask);\n"
+                                       "\to_color0 = uvec4(255);\n"
+                                       "\to_color1 = uvec4(255);\n"
+                                       "\to_color2 = uvec4(255);\n"
+                                       "\to_color3 = uvec4(255);\n"
+                                       "}\n");
+                               break;
+
+                       case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
+                               dst.glslSources.add("quad-frag") << glu::FragmentSource(
+                                       "#version 450\n"
+                                       "layout(push_constant) uniform PushConstant {\n"
+                                       "\thighp uint sampleMask;\n"
+                                       "} pushConstants;\n"
+                                       "layout(location = 0) out highp ivec4 o_color0;\n"
+                                       "layout(location = 1) out highp ivec4 o_color1;\n"
+                                       "layout(location = 2) out highp ivec4 o_color2;\n"
+                                       "layout(location = 3) out highp ivec4 o_color3;\n"
+                                       "void main (void)\n"
+                                       "{\n"
+                                       "\tgl_SampleMask[0] = int(pushConstants.sampleMask);\n"
+                                       "\to_color0 = ivec4(127);\n"
+                                       "\to_color1 = ivec4(127);\n"
+                                       "\to_color2 = ivec4(127);\n"
+                                       "\to_color3 = ivec4(127);\n"
+                                       "}\n");
+                               break;
+
+                       case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
+                       case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
+                       case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
+                               dst.glslSources.add("quad-frag") << glu::FragmentSource(
+                                       "#version 450\n"
+                                       "layout(push_constant) uniform PushConstant {\n"
+                                       "\thighp uint sampleMask;\n"
+                                       "} pushConstants;\n"
+                                       "layout(location = 0) out highp vec4 o_color0;\n"
+                                       "layout(location = 1) out highp vec4 o_color1;\n"
+                                       "layout(location = 2) out highp vec4 o_color2;\n"
+                                       "layout(location = 3) out highp vec4 o_color3;\n"
+                                       "void main (void)\n"
+                                       "{\n"
+                                       "\tgl_SampleMask[0] = int(pushConstants.sampleMask);\n"
+                                       "\to_color0 = vec4(1.0);\n"
+                                       "\to_color1 = vec4(1.0);\n"
+                                       "\to_color2 = vec4(1.0);\n"
+                                       "\to_color3 = vec4(1.0);\n"
+                                       "}\n");
+                               break;
+
+                       default:
+                               DE_FATAL("Unknown channel class");
+               }
+       }
+};
+
+std::string formatToName (VkFormat format)
+{
+       const std::string       formatStr       = de::toString(format);
+       const std::string       prefix          = "VK_FORMAT_";
+
+       DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
+
+       return de::toLower(formatStr.substr(prefix.length()));
+}
+
+void initTests (tcu::TestCaseGroup* group)
+{
+       static const VkFormat   formats[]       =
+       {
+               VK_FORMAT_R5G6B5_UNORM_PACK16,
+               VK_FORMAT_R8_UNORM,
+               VK_FORMAT_R8_SNORM,
+               VK_FORMAT_R8_UINT,
+               VK_FORMAT_R8_SINT,
+               VK_FORMAT_R8G8_UNORM,
+               VK_FORMAT_R8G8_SNORM,
+               VK_FORMAT_R8G8_UINT,
+               VK_FORMAT_R8G8_SINT,
+               VK_FORMAT_R8G8B8A8_UNORM,
+               VK_FORMAT_R8G8B8A8_SNORM,
+               VK_FORMAT_R8G8B8A8_UINT,
+               VK_FORMAT_R8G8B8A8_SINT,
+               VK_FORMAT_R8G8B8A8_SRGB,
+               VK_FORMAT_A8B8G8R8_UNORM_PACK32,
+               VK_FORMAT_A8B8G8R8_SNORM_PACK32,
+               VK_FORMAT_A8B8G8R8_UINT_PACK32,
+               VK_FORMAT_A8B8G8R8_SINT_PACK32,
+               VK_FORMAT_A8B8G8R8_SRGB_PACK32,
+               VK_FORMAT_B8G8R8A8_UNORM,
+               VK_FORMAT_B8G8R8A8_SRGB,
+               VK_FORMAT_A2R10G10B10_UNORM_PACK32,
+               VK_FORMAT_A2B10G10R10_UNORM_PACK32,
+               VK_FORMAT_A2B10G10R10_UINT_PACK32,
+               VK_FORMAT_R16_UNORM,
+               VK_FORMAT_R16_SNORM,
+               VK_FORMAT_R16_UINT,
+               VK_FORMAT_R16_SINT,
+               VK_FORMAT_R16_SFLOAT,
+               VK_FORMAT_R16G16_UNORM,
+               VK_FORMAT_R16G16_SNORM,
+               VK_FORMAT_R16G16_UINT,
+               VK_FORMAT_R16G16_SINT,
+               VK_FORMAT_R16G16_SFLOAT,
+               VK_FORMAT_R16G16B16A16_UNORM,
+               VK_FORMAT_R16G16B16A16_SNORM,
+               VK_FORMAT_R16G16B16A16_UINT,
+               VK_FORMAT_R16G16B16A16_SINT,
+               VK_FORMAT_R16G16B16A16_SFLOAT,
+               VK_FORMAT_R32_UINT,
+               VK_FORMAT_R32_SINT,
+               VK_FORMAT_R32_SFLOAT,
+               VK_FORMAT_R32G32_UINT,
+               VK_FORMAT_R32G32_SINT,
+               VK_FORMAT_R32G32_SFLOAT,
+               VK_FORMAT_R32G32B32A32_UINT,
+               VK_FORMAT_R32G32B32A32_SINT,
+               VK_FORMAT_R32G32B32A32_SFLOAT,
+       };
+       const deUint32                  sampleCounts[] =
+       {
+               2u, 4u, 8u
+       };
+       tcu::TestContext&               testCtx         (group->getTestContext());
+
+       for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
+       {
+               const VkFormat                                  format          (formats[formatNdx]);
+               const std::string                               formatName      (formatToName(format));
+               de::MovePtr<tcu::TestCaseGroup> formatGroup     (new tcu::TestCaseGroup(testCtx, formatName.c_str(), formatName.c_str()));
+
+               for (size_t sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountNdx++)
+               {
+                       const deUint32          sampleCount     (sampleCounts[sampleCountNdx]);
+                       const std::string       testName        ("samples_" + de::toString(sampleCount));
+
+                       formatGroup->addChild(new InstanceFactory1<MultisampleRenderPassTestInstance, TestConfig, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, testName.c_str(), testName.c_str(), TestConfig(format, sampleCount)));
+               }
+
+               group->addChild(formatGroup.release());
+       }
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createRenderPassMultisampleResolveTests (tcu::TestContext& testCtx)
+{
+       return createTestGroup(testCtx, "multisample_resolve", "Multisample render pass resolve tests", initTests);
+}
+
+} // vkt
diff --git a/external/vulkancts/modules/vulkan/renderpass/vktRenderPassMultisampleResolveTests.hpp b/external/vulkancts/modules/vulkan/renderpass/vktRenderPassMultisampleResolveTests.hpp
new file mode 100644 (file)
index 0000000..463a7db
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef _VKTRENDERPASSMULTISAMPLERESOLVETESTS_HPP
+#define _VKTRENDERPASSMULTISAMPLERESOLVETESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2017 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Tests for render pass multisample resolve
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+
+tcu::TestCaseGroup*    createRenderPassMultisampleResolveTests (tcu::TestContext& testCtx);
+
+} // vkt
+
+#endif // _VKTRENDERPASSMULTISAMPLERESOLVETESTS_HPP
index eb3016a..650639a 100644 (file)
@@ -24,6 +24,7 @@
 #include "vktRenderPassTests.hpp"
 
 #include "vktRenderPassMultisampleTests.hpp"
+#include "vktRenderPassMultisampleResolveTests.hpp"
 
 #include "vktTestCaseUtil.hpp"
 #include "vktTestGroupUtil.hpp"
@@ -5685,6 +5686,7 @@ tcu::TestCaseGroup* createRenderPassTests (tcu::TestContext& testCtx)
        addTestGroup(renderpassTests.get(), "attachment_allocation", "Attachment allocation tests", addAttachmentAllocationTests);
 
        renderpassTests->addChild(createRenderPassMultisampleTests(testCtx));
+       renderpassTests->addChild(createRenderPassMultisampleResolveTests(testCtx));
 
        return renderpassTests.release();
 }
index e2b37a3..016a46e 100644 (file)
@@ -133229,6 +133229,150 @@ dEQP-VK.renderpass.multisample.d32_sfloat_s8_uint.samples_4
 dEQP-VK.renderpass.multisample.d32_sfloat_s8_uint.samples_8
 dEQP-VK.renderpass.multisample.d32_sfloat_s8_uint.samples_16
 dEQP-VK.renderpass.multisample.d32_sfloat_s8_uint.samples_32
+dEQP-VK.renderpass.multisample_resolve.r5g6b5_unorm_pack16.samples_2
+dEQP-VK.renderpass.multisample_resolve.r5g6b5_unorm_pack16.samples_4
+dEQP-VK.renderpass.multisample_resolve.r5g6b5_unorm_pack16.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8_unorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8_unorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8_unorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8_snorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8_snorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8_snorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8_uint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8_uint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8_uint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8_sint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8_sint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8_sint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8g8_unorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8g8_unorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8g8_unorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8g8_snorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8g8_snorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8g8_snorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8g8_uint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8g8_uint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8g8_uint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8g8_sint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8g8_sint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8g8_sint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_unorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_unorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_unorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_snorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_snorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_snorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_uint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_uint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_uint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_sint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_sint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_sint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_srgb.samples_2
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_srgb.samples_4
+dEQP-VK.renderpass.multisample_resolve.r8g8b8a8_srgb.samples_8
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_unorm_pack32.samples_2
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_unorm_pack32.samples_4
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_unorm_pack32.samples_8
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_snorm_pack32.samples_2
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_snorm_pack32.samples_4
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_snorm_pack32.samples_8
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_uint_pack32.samples_2
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_uint_pack32.samples_4
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_uint_pack32.samples_8
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_sint_pack32.samples_2
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_sint_pack32.samples_4
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_sint_pack32.samples_8
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_srgb_pack32.samples_2
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_srgb_pack32.samples_4
+dEQP-VK.renderpass.multisample_resolve.a8b8g8r8_srgb_pack32.samples_8
+dEQP-VK.renderpass.multisample_resolve.b8g8r8a8_unorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.b8g8r8a8_unorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.b8g8r8a8_unorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.b8g8r8a8_srgb.samples_2
+dEQP-VK.renderpass.multisample_resolve.b8g8r8a8_srgb.samples_4
+dEQP-VK.renderpass.multisample_resolve.b8g8r8a8_srgb.samples_8
+dEQP-VK.renderpass.multisample_resolve.a2r10g10b10_unorm_pack32.samples_2
+dEQP-VK.renderpass.multisample_resolve.a2r10g10b10_unorm_pack32.samples_4
+dEQP-VK.renderpass.multisample_resolve.a2r10g10b10_unorm_pack32.samples_8
+dEQP-VK.renderpass.multisample_resolve.a2b10g10r10_unorm_pack32.samples_2
+dEQP-VK.renderpass.multisample_resolve.a2b10g10r10_unorm_pack32.samples_4
+dEQP-VK.renderpass.multisample_resolve.a2b10g10r10_unorm_pack32.samples_8
+dEQP-VK.renderpass.multisample_resolve.a2b10g10r10_uint_pack32.samples_2
+dEQP-VK.renderpass.multisample_resolve.a2b10g10r10_uint_pack32.samples_4
+dEQP-VK.renderpass.multisample_resolve.a2b10g10r10_uint_pack32.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16_unorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16_unorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16_unorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16_snorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16_snorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16_snorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16_uint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16_uint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16_uint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16_sint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16_sint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16_sint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16_sfloat.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16_sfloat.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16_sfloat.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16g16_unorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16g16_unorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16g16_unorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16g16_snorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16g16_snorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16g16_snorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16g16_uint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16g16_uint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16g16_uint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16g16_sint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16g16_sint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16g16_sint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16g16_sfloat.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16g16_sfloat.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16g16_sfloat.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_unorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_unorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_unorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_snorm.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_snorm.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_snorm.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_uint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_uint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_uint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_sint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_sint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_sint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_sfloat.samples_2
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_sfloat.samples_4
+dEQP-VK.renderpass.multisample_resolve.r16g16b16a16_sfloat.samples_8
+dEQP-VK.renderpass.multisample_resolve.r32_uint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r32_uint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r32_uint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r32_sint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r32_sint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r32_sint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r32_sfloat.samples_2
+dEQP-VK.renderpass.multisample_resolve.r32_sfloat.samples_4
+dEQP-VK.renderpass.multisample_resolve.r32_sfloat.samples_8
+dEQP-VK.renderpass.multisample_resolve.r32g32_uint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r32g32_uint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r32g32_uint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r32g32_sint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r32g32_sint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r32g32_sint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r32g32_sfloat.samples_2
+dEQP-VK.renderpass.multisample_resolve.r32g32_sfloat.samples_4
+dEQP-VK.renderpass.multisample_resolve.r32g32_sfloat.samples_8
+dEQP-VK.renderpass.multisample_resolve.r32g32b32a32_uint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r32g32b32a32_uint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r32g32b32a32_uint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r32g32b32a32_sint.samples_2
+dEQP-VK.renderpass.multisample_resolve.r32g32b32a32_sint.samples_4
+dEQP-VK.renderpass.multisample_resolve.r32g32b32a32_sint.samples_8
+dEQP-VK.renderpass.multisample_resolve.r32g32b32a32_sfloat.samples_2
+dEQP-VK.renderpass.multisample_resolve.r32g32b32a32_sfloat.samples_4
+dEQP-VK.renderpass.multisample_resolve.r32g32b32a32_sfloat.samples_8
 dEQP-VK.ubo.2_level_array.std140.float_vertex
 dEQP-VK.ubo.2_level_array.std140.float_fragment
 dEQP-VK.ubo.2_level_array.std140.float_both