Add tests recording multisubpass renderpass instances
authorSamuel Iglesias Gonsálvez <siglesias@igalia.com>
Fri, 13 Dec 2019 07:10:18 +0000 (08:10 +0100)
committerAlexander Galazin <Alexander.Galazin@arm.com>
Thu, 23 Jan 2020 08:19:56 +0000 (03:19 -0500)
As an implementation could store the current subpass index in the wrong
place, there could be issues when recording multi-subpass renderpass
instances into multiple command buffers simultaneously.

Components: Vulkan
VK-GL-CTS issue: 1942

Added tests:

   dEQP-VK.renderpass*.multiple_subpasses_multiple_command_buffers.test

Change-Id: I475ab8993486d1c58a20aed036e568b6f602bc01

AndroidGen.mk
android/cts/master/vk-master.txt
external/vulkancts/modules/vulkan/renderpass/CMakeLists.txt
external/vulkancts/modules/vulkan/renderpass/vktRenderPassMultipleSubpassesMultipleCommandBuffersTests.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/renderpass/vktRenderPassMultipleSubpassesMultipleCommandBuffersTests.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/renderpass/vktRenderPassTests.cpp
external/vulkancts/mustpass/master/vk-default-no-waivers.txt
external/vulkancts/mustpass/master/vk-default.txt

index 1ab13bb..b73a40f 100644 (file)
@@ -258,6 +258,7 @@ LOCAL_SRC_FILES := \
        external/vulkancts/modules/vulkan/rasterization/vktRasterizationTests.cpp \
        external/vulkancts/modules/vulkan/renderpass/vktRenderPassDepthStencilResolveTests.cpp \
        external/vulkancts/modules/vulkan/renderpass/vktRenderPassFragmentDensityMapTests.cpp \
+       external/vulkancts/modules/vulkan/renderpass/vktRenderPassMultipleSubpassesMultipleCommandBuffersTests.cpp \
        external/vulkancts/modules/vulkan/renderpass/vktRenderPassMultisampleResolveTests.cpp \
        external/vulkancts/modules/vulkan/renderpass/vktRenderPassMultisampleTests.cpp \
        external/vulkancts/modules/vulkan/renderpass/vktRenderPassSampleReadTests.cpp \
index 713f699..38e415e 100644 (file)
@@ -358932,6 +358932,7 @@ dEQP-VK.renderpass.dedicated_allocation.attachment_write_mask.attachment_count_8
 dEQP-VK.renderpass.dedicated_allocation.attachment_write_mask.attachment_count_8.start_index_5
 dEQP-VK.renderpass.dedicated_allocation.attachment_write_mask.attachment_count_8.start_index_6
 dEQP-VK.renderpass.dedicated_allocation.attachment_write_mask.attachment_count_8.start_index_7
+dEQP-VK.renderpass.multiple_subpasses_multiple_command_buffers.test
 dEQP-VK.renderpass2.suballocation.simple.color
 dEQP-VK.renderpass2.suballocation.simple.depth
 dEQP-VK.renderpass2.suballocation.simple.stencil
@@ -368216,6 +368217,7 @@ dEQP-VK.renderpass2.dedicated_allocation.attachment_write_mask.attachment_count_
 dEQP-VK.renderpass2.dedicated_allocation.attachment_write_mask.attachment_count_8.start_index_5
 dEQP-VK.renderpass2.dedicated_allocation.attachment_write_mask.attachment_count_8.start_index_6
 dEQP-VK.renderpass2.dedicated_allocation.attachment_write_mask.attachment_count_8.start_index_7
+dEQP-VK.renderpass2.multiple_subpasses_multiple_command_buffers.test
 dEQP-VK.renderpass2.depth_stencil_resolve.misc.properties
 dEQP-VK.renderpass2.depth_stencil_resolve.image_2d_32_32.samples_2.d16_unorm.depth_zero_stencil_none_testing_depth
 dEQP-VK.renderpass2.depth_stencil_resolve.image_2d_32_32.samples_2.d16_unorm.depth_zero_stencil_none_unused_resolve_testing_depth
index 0a2464f..b4fcc66 100644 (file)
@@ -27,6 +27,8 @@ set(DEQP_VK_RENDER_PASS_SRCS
        vktRenderPassUnusedClearAttachmentTests.hpp
        vktRenderPassFragmentDensityMapTests.cpp
        vktRenderPassFragmentDensityMapTests.hpp
+       vktRenderPassMultipleSubpassesMultipleCommandBuffersTests.cpp
+       vktRenderPassMultipleSubpassesMultipleCommandBuffersTests.hpp
        )
 
 set(DEQP_VK_RENDER_PASS_LIBS
diff --git a/external/vulkancts/modules/vulkan/renderpass/vktRenderPassMultipleSubpassesMultipleCommandBuffersTests.cpp b/external/vulkancts/modules/vulkan/renderpass/vktRenderPassMultipleSubpassesMultipleCommandBuffersTests.cpp
new file mode 100644 (file)
index 0000000..91f64fd
--- /dev/null
@@ -0,0 +1,879 @@
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2019 The Khronos Group Inc.
+ * Copyright (c) 2019 Valve Corporation.
+ *
+ * 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 vkCmdClearAttachments with unused attachments.
+ *//*--------------------------------------------------------------------*/
+
+#include "vktRenderPassMultipleSubpassesMultipleCommandBuffersTests.hpp"
+#include "pipeline/vktPipelineImageUtil.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkRefUtil.hpp"
+#include "vkCmdUtil.hpp"
+#include "vkObjUtil.hpp"
+#include "vkImageUtil.hpp"
+#include "tcuTextureUtil.hpp"
+#include "tcuImageCompare.hpp"
+#include <sstream>
+#include <functional>
+#include <vector>
+#include <string>
+#include <memory>
+
+namespace vkt
+{
+namespace renderpass
+{
+
+namespace
+{
+
+struct Vertex
+{
+       tcu::Vec4       position;
+       tcu::Vec4       color;
+};
+
+template<typename T>
+inline VkDeviceSize sizeInBytes(const std::vector<T>& vec)
+{
+       return vec.size() * sizeof(vec[0]);
+}
+
+std::vector<Vertex> genVertices (void)
+{
+       std::vector<Vertex>             vectorData;
+       const tcu::Vec4                 red                     = {1.0f, 0.0f, 0.0f, 1.0f};
+       const tcu::Vec4                 green           = {0.0f, 1.0f, 0.0f, 1.0f};
+       const tcu::Vec4                 blue            = {0.0f, 0.0f, 1.0f, 1.0f};
+       const tcu::Vec4                 yellow          = {1.0f, 1.0f, 0.0f, 1.0f};
+
+       vectorData.push_back({tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f) , red});
+       vectorData.push_back({tcu::Vec4( 0.0f, -1.0f, 0.0f, 1.0f) , red});
+       vectorData.push_back({tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f) , red});
+       vectorData.push_back({tcu::Vec4( 0.0f,  1.0f, 0.0f, 1.0f) , red});
+
+       vectorData.push_back({tcu::Vec4( 0.0f, -1.0f, 0.0f, 1.0f) , green});
+       vectorData.push_back({tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f) , green});
+       vectorData.push_back({tcu::Vec4( 0.0f,  1.0f, 0.0f, 1.0f) , green});
+       vectorData.push_back({tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f) , green});
+
+       vectorData.push_back({tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f) , blue});
+       vectorData.push_back({tcu::Vec4( 0.0f, -1.0f, 0.0f, 1.0f) , blue});
+       vectorData.push_back({tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f) , blue});
+       vectorData.push_back({tcu::Vec4( 0.0f,  1.0f, 0.0f, 1.0f) , blue});
+
+       vectorData.push_back({tcu::Vec4( 0.0f, -1.0f, 0.0f, 1.0f) , yellow});
+       vectorData.push_back({tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f) , yellow});
+       vectorData.push_back({tcu::Vec4( 0.0f,  1.0f, 0.0f, 1.0f) , yellow});
+       vectorData.push_back({tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f) , yellow});
+
+       return vectorData;
+}
+
+class MultipleSubpassesMultipleCommandBuffersTestInstance : public TestInstance
+{
+public:
+                                                                                       MultipleSubpassesMultipleCommandBuffersTestInstance     (Context&                       context);
+       virtual                                                                 ~MultipleSubpassesMultipleCommandBuffersTestInstance    (void) {}
+       virtual tcu::TestStatus                                 iterate                                                         (void);
+       void                                                                    createCommandBuffer                                     (const DeviceInterface& vk,
+                                                                                                                                                                VkDevice                               vkDevice);
+private:
+       static constexpr deUint32                               kImageWidth                     = 32;
+       static constexpr deUint32                               kImageHeight            = 32;
+       const tcu::UVec2                                                m_renderSize            = { kImageWidth, kImageHeight };
+
+       // FIXME: check if I need all of this.
+       VkClearValue                                                    m_initialColor;
+       VkClearValue                                                    m_clearColor;
+
+       Move<VkImage>                                                   m_colorImageA;
+       de::MovePtr<Allocation>                                 m_colorImageAllocA;
+       Move<VkImageView>                                               m_colorAttachmentViewA;
+
+       Move<VkImage>                                                   m_colorImageB;
+       de::MovePtr<Allocation>                                 m_colorImageAllocB;
+       Move<VkImageView>                                               m_colorAttachmentViewB;
+
+       Move<VkRenderPass>                                              m_renderPass;
+       Move<VkFramebuffer>                                             m_framebufferA;
+       Move<VkFramebuffer>                                             m_framebufferB;
+       Move<VkShaderModule>                                    m_vertexShaderModule;
+       Move<VkShaderModule>                                    m_fragmentShaderModule;
+       Move<VkDescriptorSetLayout>                             m_descriptorSetLayout;
+       Move<VkPipelineLayout>                                  m_pipelineLayout;
+       Move<VkPipeline>                                                m_graphicsPipeline0;
+       Move<VkPipeline>                                                m_graphicsPipeline1;
+       Move<VkPipeline>                                                m_graphicsPipeline2;
+       Move<VkCommandPool>                                             m_cmdPool;
+       Move<VkCommandBuffer>                                   m_cmdBufferA;
+       Move<VkCommandBuffer>                                   m_cmdBufferB;
+
+       Move<VkBuffer>                                                  m_vertexBuffer;
+       de::MovePtr<Allocation>                                 m_vertexBufferAlloc;
+};
+
+class MultipleSubpassesMultipleCommandBuffersTest : public vkt::TestCase
+{
+public:
+                                                                               MultipleSubpassesMultipleCommandBuffersTest     (tcu::TestContext&      testContext,
+                                                                                                                                        const std::string&     name,
+                                                                                                                                        const std::string&     description)
+                                                                                       : vkt::TestCase(testContext, name, description)
+                                                                                       {}
+       virtual                                                         ~MultipleSubpassesMultipleCommandBuffersTest    (void) {}
+       virtual void                                            initPrograms                            (SourceCollections&     sourceCollections) const;
+       virtual TestInstance*                           createInstance                          (Context&                       context) const;
+};
+
+TestInstance* MultipleSubpassesMultipleCommandBuffersTest::createInstance (Context& context) const
+{
+       return new MultipleSubpassesMultipleCommandBuffersTestInstance(context);
+}
+
+void MultipleSubpassesMultipleCommandBuffersTest::initPrograms (SourceCollections& sourceCollections) const
+{
+       // Vertex shader.
+       sourceCollections.glslSources.add("vert_shader") << glu::VertexSource(
+               "#version 450\n"
+               "layout(location = 0) in vec4 position;\n"
+               "layout(location = 1) in vec4 color;\n"
+               "layout(location = 0) out vec4 vtxColor;\n"
+               "void main (void)\n"
+               "{\n"
+               "\tgl_Position = position;\n"
+               "\tvtxColor = color;\n"
+               "}\n");
+
+       // Fragment shader.
+       std::ostringstream fragmentSource;
+
+       fragmentSource  << "#version 450\n"
+                                       << "layout(location = 0) in vec4 vtxColor;\n"
+                                       << "layout(location = 0) out vec4 fragColor;\n"
+                                       << "void main (void)\n"
+                                       << "{\n"
+                                       << "\tfragColor = vtxColor;\n"
+                                       << "}\n";
+
+       sourceCollections.glslSources.add("frag_shader") << glu::FragmentSource(fragmentSource.str());
+}
+
+// Create a render pass for this use case.
+Move<VkRenderPass> createRenderPass (const DeviceInterface&    vk, VkDevice vkDevice)
+{
+       // XXX: Add more code to this
+       // Create attachment descriptions.
+       const VkAttachmentDescription           attachmentDescription   =
+       {
+               (VkAttachmentDescriptionFlags)0,                        // VkAttachmentDescriptionFlags         flags
+               VK_FORMAT_R32G32B32A32_SFLOAT,                          // VkFormat                                                     format
+               VK_SAMPLE_COUNT_1_BIT,                                          // VkSampleCountFlagBits                        samples
+               VK_ATTACHMENT_LOAD_OP_LOAD,                                     // VkAttachmentLoadOp                           loadOp
+               VK_ATTACHMENT_STORE_OP_STORE,                           // VkAttachmentStoreOp                          storeOp
+               VK_ATTACHMENT_LOAD_OP_DONT_CARE,                        // VkAttachmentLoadOp                           stencilLoadOp
+               VK_ATTACHMENT_STORE_OP_DONT_CARE,                       // VkAttachmentStoreOp                          stencilStoreOp
+               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,       // VkImageLayout                                        initialLayout
+               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout                                        finalLayout
+       };
+
+       // XXX: Review this parameters, I think I am doing it wrong.
+       // Mark attachments as used or not depending on the test parameters.
+       const VkAttachmentReference                     attachmentReference
+       {
+               0u,                                                                                                                                     // deUint32                             attachment
+               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                                                       // VkImageLayout                layout
+       };
+
+       // Create subpass description with the previous color attachment references.
+       std::vector<vk::VkSubpassDescription> subpassDescriptions;
+       {
+               const vk::VkSubpassDescription                  subpassDescription =
+               {
+                       (VkSubpassDescriptionFlags)0,                                                                                   // VkSubpassDescriptionFlags            flags
+                       VK_PIPELINE_BIND_POINT_GRAPHICS,                                                                                // VkPipelineBindPoint                          pipelineBindPoint
+                       0u,                                                                                                                                             // deUint32                                                     inputAttachmentCount
+                       DE_NULL,                                                                                                                                // const VkAttachmentReference*         pInputAttachments
+                       1u,                                                                                                                                             // deUint32                                                     colorAttachmentCount
+                       &attachmentReference,                                                                                                   // const VkAttachmentReference*         pColorAttachments
+                       DE_NULL,                                                                                                                                // const VkAttachmentReference*         pResolveAttachments
+                       DE_NULL,                                                                                                                                // const VkAttachmentReference*         pDepthStencilAttachment
+                       0u,                                                                                                                                             // deUint32                                                     preserveAttachmentCount
+                       DE_NULL                                                                                                                                 // const deUint32*                                      pPreserveAttachments
+               };
+               subpassDescriptions.emplace_back(subpassDescription);
+               subpassDescriptions.emplace_back(subpassDescription);
+               subpassDescriptions.emplace_back(subpassDescription);
+       }
+
+       std::vector<vk::VkSubpassDependency> subpassDependencies;
+       {
+               vk::VkSubpassDependency                 subpassDependency =
+               {
+                       0u,                                                                                             // deUint32                             srcSubpass
+                       1u,                                                                                             // deUint32                                     dstSubpass
+                       VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,  // VkPipelineStageFlags         srcStageMask
+                       VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,  // VkPipelineStageFlags         dstStageMask
+                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                   // VkAccessFlags                        srcAccessMask
+                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                   // VkAccessFlags                        dstAccessMask
+                       0u                                                                                              // VkDependencyFlags            dependencyFlags
+               };
+               subpassDependencies.emplace_back(subpassDependency);
+               subpassDependency.srcSubpass = 1u;
+               subpassDependency.dstSubpass = 2u;
+               subpassDependencies.emplace_back(subpassDependency);
+       }
+
+
+       const vk::VkRenderPassCreateInfo        renderPassInfo =
+       {
+               VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                                                              // VkStructureType                                      sType
+               DE_NULL,                                                                                                                                // const void*                                          pNext
+               (VkRenderPassCreateFlags)0,                                                                                             // VkRenderPassCreateFlags                      flags
+               1u,                                                                                                                                             // deUint32                                                     attachmentCount
+               &attachmentDescription,                                                                                                 // const VkAttachmentDescription*       pAttachments
+               static_cast<deUint32>(subpassDescriptions.size()),                                              // deUint32                                                     subpassCount
+               subpassDescriptions.data(),                                                                                             // const VkSubpassDescription*          pSubpasses
+               static_cast<deUint32>(subpassDependencies.size()),                                              // deUint32                                                     dependencyCount
+               subpassDependencies.data(),                                                                                             // const VkSubpassDependency*           pDependencies
+       };
+
+       return createRenderPass(vk, vkDevice, &renderPassInfo);
+}
+
+MultipleSubpassesMultipleCommandBuffersTestInstance::MultipleSubpassesMultipleCommandBuffersTestInstance(Context&      context)
+       : vkt::TestInstance(context)
+{
+       // Initial color for all images.
+       m_initialColor.color.float32[0] = 0.0f;
+       m_initialColor.color.float32[1] = 0.0f;
+       m_initialColor.color.float32[2] = 0.0f;
+       m_initialColor.color.float32[3] = 1.0f;
+
+       // Clear color for used attachments.
+       m_clearColor.color.float32[0] = 1.0f;
+       m_clearColor.color.float32[1] = 1.0f;
+       m_clearColor.color.float32[2] = 1.0f;
+       m_clearColor.color.float32[3] = 1.0f;
+
+       const DeviceInterface&          vk                                              = m_context.getDeviceInterface();
+       const VkDevice                          vkDevice                                = m_context.getDevice();
+       const deUint32                          queueFamilyIndex                = m_context.getUniversalQueueFamilyIndex();
+       SimpleAllocator                         memAlloc                                (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
+       const VkComponentMapping        componentMapping                = { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY };
+
+       // Create color images.
+       {
+               const VkImageCreateInfo colorImageParams =
+               {
+                       VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                                    // VkStructureType                      sType;
+                       DE_NULL,                                                                                                                                // const void*                          pNext;
+                       0u,                                                                                                                                             // VkImageCreateFlags           flags;
+                       VK_IMAGE_TYPE_2D,                                                                                                               // VkImageType                          imageType;
+                       VK_FORMAT_R32G32B32A32_SFLOAT,                                                                                  // VkFormat                                     format;
+                       { kImageWidth, kImageHeight, 1u },                                                                              // VkExtent3D                           extent;
+                       1u,                                                                                                                                             // deUint32                                     mipLevels;
+                       1u,                                                                                                                                             // deUint32                                     arrayLayers;
+                       VK_SAMPLE_COUNT_1_BIT,                                                                                                  // VkSampleCountFlagBits        samples;
+                       VK_IMAGE_TILING_OPTIMAL,                                                                                                // VkImageTiling                        tiling;
+                       VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT
+                               | VK_IMAGE_USAGE_TRANSFER_DST_BIT,                                                                      // VkImageUsageFlags            usage;
+                       VK_SHARING_MODE_EXCLUSIVE,                                                                                              // VkSharingMode                        sharingMode;
+                       1u,                                                                                                                                             // deUint32                                     queueFamilyIndexCount;
+                       &queueFamilyIndex,                                                                                                              // const deUint32*                      pQueueFamilyIndices;
+                       VK_IMAGE_LAYOUT_UNDEFINED                                                                                               // VkImageLayout                        initialLayout;
+               };
+               // Create, allocate and bind image memory.
+               m_colorImageA = createImage(vk, vkDevice, &colorImageParams);
+               m_colorImageAllocA = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImageA), MemoryRequirement::Any);
+               VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImageA, m_colorImageAllocA->getMemory(), m_colorImageAllocA->getOffset()));
+
+               m_colorImageB = createImage(vk, vkDevice, &colorImageParams);
+               m_colorImageAllocB = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImageB), MemoryRequirement::Any);
+               VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImageB, m_colorImageAllocB->getMemory(), m_colorImageAllocB->getOffset()));
+
+               // Create image view.
+               {
+                       const VkImageViewCreateInfo colorAttachmentViewParamsA =
+                       {
+                               VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,                       // VkStructureType                      sType;
+                               DE_NULL,                                                                                        // const void*                          pNext;
+                               0u,                                                                                                     // VkImageViewCreateFlags       flags;
+                               *m_colorImageA,                                                                         // VkImage                                      image;
+                               VK_IMAGE_VIEW_TYPE_2D,                                                          // VkImageViewType                      viewType;
+                               VK_FORMAT_R32G32B32A32_SFLOAT,                                          // VkFormat                                     format;
+                               componentMapping,                                                                       // VkChannelMapping                     channels;
+                               { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }           // VkImageSubresourceRange      subresourceRange;
+                       };
+                       m_colorAttachmentViewA = createImageView(vk, vkDevice, &colorAttachmentViewParamsA);
+
+                       const VkImageViewCreateInfo colorAttachmentViewParamsB =
+                       {
+                               VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,                       // VkStructureType                      sType;
+                               DE_NULL,                                                                                        // const void*                          pNext;
+                               0u,                                                                                                     // VkImageViewCreateFlags       flags;
+                               *m_colorImageB,                                                                         // VkImage                                      image;
+                               VK_IMAGE_VIEW_TYPE_2D,                                                          // VkImageViewType                      viewType;
+                               VK_FORMAT_R32G32B32A32_SFLOAT,                                          // VkFormat                                     format;
+                               componentMapping,                                                                       // VkChannelMapping                     channels;
+                               { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }           // VkImageSubresourceRange      subresourceRange;
+                       };
+                       m_colorAttachmentViewB = createImageView(vk, vkDevice, &colorAttachmentViewParamsB);
+               }
+
+               // Clear image and leave it prepared to be used as a color attachment.
+               {
+                       const VkImageAspectFlags                aspectMask      = VK_IMAGE_ASPECT_COLOR_BIT;
+                       Move<VkCommandPool>                             cmdPool;
+                       Move<VkCommandBuffer>                   cmdBuffer;
+                       std::vector<VkImageMemoryBarrier> preImageBarriers;
+                       std::vector<VkImageMemoryBarrier> postImageBarriers;
+
+                       // Create command pool and buffer
+                       cmdPool         = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
+                       cmdBuffer       = allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+
+                       // From undefined layout to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.
+                       const VkImageMemoryBarrier preImageBarrierA =
+                       {
+                                VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,        // VkStructureType                      sType;
+                                DE_NULL,                                                                       // const void*                          pNext;
+                                0u,                                                                            // VkAccessFlags                        srcAccessMask;
+                                VK_ACCESS_TRANSFER_WRITE_BIT,                          // VkAccessFlags                        dstAccessMask;
+                                VK_IMAGE_LAYOUT_UNDEFINED,                                     // VkImageLayout                        oldLayout;
+                                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,          // VkImageLayout                        newLayout;
+                                VK_QUEUE_FAMILY_IGNORED,                                       // deUint32                                     srcQueueFamilyIndex;
+                                VK_QUEUE_FAMILY_IGNORED,                                       // deUint32                                     dstQueueFamilyIndex;
+                                *m_colorImageA,                                                        // VkImage                                      image;
+                                {                                                                                      // VkImageSubresourceRange      subresourceRange;
+                                       aspectMask,                                                             // VkImageAspect                        aspect;
+                                       0u,                                                                             // deUint32                                     baseMipLevel;
+                                       1u,                                                                             // deUint32                                     mipLevels;
+                                       0u,                                                                             // deUint32                                     baseArraySlice;
+                                       1u                                                                              // deUint32                                     arraySize;
+                                }
+                       };
+
+                       preImageBarriers.emplace_back(preImageBarrierA);
+
+                       // From VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL.
+                       const VkImageMemoryBarrier postImageBarrierA =
+                       {
+                               VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         // VkStructureType                      sType;
+                               DE_NULL,                                                                        // const void*                          pNext;
+                               VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags                        srcAccessMask;
+                               VK_ACCESS_SHADER_READ_BIT,                                      // VkAccessFlags                        dstAccessMask;
+                               VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,           // VkImageLayout                        oldLayout;
+                               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,       // VkImageLayout                        newLayout;
+                               VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     srcQueueFamilyIndex;
+                               VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     dstQueueFamilyIndex;
+                               *m_colorImageA,                                                         // VkImage                                      image;
+                               {                                                                                       // VkImageSubresourceRange      subresourceRange;
+                                       aspectMask,                                                             // VkImageAspect                        aspect;
+                                       0u,                                                                             // deUint32                                     baseMipLevel;
+                                       1u,                                                                             // deUint32                                     mipLevels;
+                                       0u,                                                                             // deUint32                                     baseArraySlice;
+                                       1u                                                                              // deUint32                                     arraySize;
+                               }
+                       };
+
+                       postImageBarriers.emplace_back(postImageBarrierA);
+
+                       // From undefined layout to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.
+                       const VkImageMemoryBarrier preImageBarrierB =
+                       {
+                                VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,        // VkStructureType                      sType;
+                                DE_NULL,                                                                       // const void*                          pNext;
+                                0u,                                                                            // VkAccessFlags                        srcAccessMask;
+                                VK_ACCESS_TRANSFER_WRITE_BIT,                          // VkAccessFlags                        dstAccessMask;
+                                VK_IMAGE_LAYOUT_UNDEFINED,                                     // VkImageLayout                        oldLayout;
+                                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,          // VkImageLayout                        newLayout;
+                                VK_QUEUE_FAMILY_IGNORED,                                       // deUint32                                     srcQueueFamilyIndex;
+                                VK_QUEUE_FAMILY_IGNORED,                                       // deUint32                                     dstQueueFamilyIndex;
+                                *m_colorImageB,                                                        // VkImage                                      image;
+                                {                                                                                      // VkImageSubresourceRange      subresourceRange;
+                                       aspectMask,                                                             // VkImageAspect                        aspect;
+                                       0u,                                                                             // deUint32                                     baseMipLevel;
+                                       1u,                                                                             // deUint32                                     mipLevels;
+                                       0u,                                                                             // deUint32                                     baseArraySlice;
+                                       1u                                                                              // deUint32                                     arraySize;
+                                }
+                       };
+
+                       preImageBarriers.emplace_back(preImageBarrierB);
+
+                       // From VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL.
+                       const VkImageMemoryBarrier postImageBarrierB =
+                       {
+                               VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         // VkStructureType                      sType;
+                               DE_NULL,                                                                        // const void*                          pNext;
+                               VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags                        srcAccessMask;
+                               VK_ACCESS_SHADER_READ_BIT,                                      // VkAccessFlags                        dstAccessMask;
+                               VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,           // VkImageLayout                        oldLayout;
+                               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,       // VkImageLayout                        newLayout;
+                               VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     srcQueueFamilyIndex;
+                               VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     dstQueueFamilyIndex;
+                               *m_colorImageB,                                                         // VkImage                                      image;
+                               {                                                                                       // VkImageSubresourceRange      subresourceRange;
+                                       aspectMask,                                                             // VkImageAspect                        aspect;
+                                       0u,                                                                             // deUint32                                     baseMipLevel;
+                                       1u,                                                                             // deUint32                                     mipLevels;
+                                       0u,                                                                             // deUint32                                     baseArraySlice;
+                                       1u                                                                              // deUint32                                     arraySize;
+                               }
+                       };
+
+                       postImageBarriers.emplace_back(postImageBarrierB);
+
+                       const VkImageSubresourceRange clearRange        =
+                       {
+                               aspectMask,     // VkImageAspectFlags   aspectMask;
+                               0u,                     // deUint32                             baseMipLevel;
+                               1u,                     // deUint32                             levelCount;
+                               0u,                     // deUint32                             baseArrayLayer;
+                               1u                      // deUint32                             layerCount;
+                       };
+
+                       // Clear image and transfer layout.
+                       beginCommandBuffer(vk, *cmdBuffer);
+                       vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, static_cast<deUint32>(preImageBarriers.size()), preImageBarriers.data());
+                       vk.cmdClearColorImage(*cmdBuffer, *m_colorImageA, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_initialColor.color, 1, &clearRange);
+                       vk.cmdClearColorImage(*cmdBuffer, *m_colorImageB, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_initialColor.color, 1, &clearRange);
+                       vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, static_cast<deUint32>(postImageBarriers.size()), postImageBarriers.data());
+                       endCommandBuffer(vk, *cmdBuffer);
+
+                       submitCommandsAndWait(vk, vkDevice, m_context.getUniversalQueue(), cmdBuffer.get());
+               }
+       }
+
+       // Create render pass.
+       m_renderPass = createRenderPass(vk, vkDevice);
+
+       // Create framebuffer
+       {
+               const VkImageView                               attachmentBindInfosA[1]                 =
+               {
+                       *m_colorAttachmentViewA,
+               };
+               const VkFramebufferCreateInfo   framebufferParamsA      =
+               {
+                       VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,                      // VkStructureType                      sType;
+                       DE_NULL,                                                                                        // const void*                          pNext;
+                       0u,                                                                                                     // VkFramebufferCreateFlags     flags;
+                       *m_renderPass,                                                                          // VkRenderPass                         renderPass;
+                       1u,                                                                                                     // deUint32                                     attachmentCount;
+                       attachmentBindInfosA,                                                           // const VkImageView*           pAttachments;
+                       kImageWidth,                                                                            // deUint32                                     width;
+                       kImageHeight,                                                                           // deUint32                                     height;
+                       1u                                                                                                      // deUint32                                     layers;
+               };
+
+               m_framebufferA = createFramebuffer(vk, vkDevice, &framebufferParamsA);
+
+               const VkImageView                               attachmentBindInfosB[1]                 =
+               {
+                       *m_colorAttachmentViewB,
+               };
+               const VkFramebufferCreateInfo   framebufferParamsB      =
+               {
+                       VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,                      // VkStructureType                      sType;
+                       DE_NULL,                                                                                        // const void*                          pNext;
+                       0u,                                                                                                     // VkFramebufferCreateFlags     flags;
+                       *m_renderPass,                                                                          // VkRenderPass                         renderPass;
+                       1u,                                                                                                     // deUint32                                     attachmentCount;
+                       attachmentBindInfosB,                                                           // const VkImageView*           pAttachments;
+                       kImageWidth,                                                                            // deUint32                                     width;
+                       kImageHeight,                                                                           // deUint32                                     height;
+                       1u                                                                                                      // deUint32                                     layers;
+               };
+
+               m_framebufferB = createFramebuffer(vk, vkDevice, &framebufferParamsB);
+       }
+
+       // Create pipeline layout.
+       {
+               const VkDescriptorSetLayoutCreateInfo   descriptorSetLayoutParams       =
+               {
+                       VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,    // VkStructureType                                              sType
+                       DE_NULL,                                                                                                // const void*                                                  pNext
+                       0u,                                                                                                             // VkDescriptorSetLayoutCreateFlags             flags
+                       0u,                                                                                                             // deUint32                                                             bindingCount
+                       DE_NULL                                                                                                 // const VkDescriptorSetLayoutBinding*  pBindings
+               };
+               m_descriptorSetLayout = createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams);
+
+               const VkPipelineLayoutCreateInfo                pipelineLayoutParams            =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                                      sType;
+                       DE_NULL,                                                                                        // const void*                                          pNext;
+                       0u,                                                                                                     // VkPipelineLayoutCreateFlags          flags;
+                       1u,                                                                                                     // deUint32                                                     setLayoutCount;
+                       &m_descriptorSetLayout.get(),                                           // const VkDescriptorSetLayout*         pSetLayouts;
+                       0u,                                                                                                     // deUint32                                                     pushConstantRangeCount;
+                       DE_NULL                                                                                         // const VkPushConstantRange*           pPushConstantRanges;
+               };
+
+               m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
+       }
+
+       // Create Vertex buffer
+       {
+               const std::vector<Vertex>               vertexValues            = genVertices();
+               const VkDeviceSize                              vertexBufferSize        = sizeInBytes(vertexValues);
+
+               const vk::VkBufferCreateInfo    bufferCreateInfo        =
+               {
+                       VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,                           // VkStructureType              sType
+                       DE_NULL,                                                                                        // const void*                  pNext
+                       0u,                                                                                                     // VkBufferCreateFlags  flags
+                       vertexBufferSize,                                                                       // VkDeviceSize                 size
+                       VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
+                       VK_BUFFER_USAGE_TRANSFER_DST_BIT,                                       // VkBufferUsageFlags   usage
+                       VK_SHARING_MODE_EXCLUSIVE,                                                      // VkSharingMode                sharingMode
+                       1u,                                                                                                     // deUint32                             queueFamilyIndexCount
+                       &queueFamilyIndex                                                                       // const deUint32*              pQueueFamilyIndices
+               };
+
+               m_vertexBuffer          = createBuffer(vk, vkDevice, &bufferCreateInfo);
+               m_vertexBufferAlloc     = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
+               VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
+               // Load vertices into vertex buffer
+               deMemcpy(m_vertexBufferAlloc->getHostPtr(), vertexValues.data(), static_cast<size_t>(vertexBufferSize));
+               flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
+       }
+
+       // Vertex buffer description
+       const vk::VkVertexInputBindingDescription bindingDescription =
+       {
+               0u,                                                                                                     // deUint32                             binding
+               sizeof(Vertex),                                                                         // deUint32                             stride
+               VK_VERTEX_INPUT_RATE_VERTEX                                                     // VkVertexInputRate    inputRate
+       };
+
+       std::vector<vk::VkVertexInputAttributeDescription> attributeDescriptions;
+       {
+               vk::VkVertexInputAttributeDescription attributeDescriptionVertex =
+               {
+                       0u,                                                                     // deUint32             location
+                       0u,                                                                     // deUint32             binding
+                       VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat             format
+                       offsetof(Vertex, position)                      // deUint32             offset
+               };
+
+               vk::VkVertexInputAttributeDescription attributeDescriptionColor =
+               {
+                       1u,                                                                     // deUint32             location
+                       0u,                                                                     // deUint32             binding
+                       VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat             format
+                       offsetof(Vertex, color)                         // deUint32             offset
+               };
+               attributeDescriptions.emplace_back(attributeDescriptionVertex);
+               attributeDescriptions.emplace_back(attributeDescriptionColor);
+       }
+
+       const vk::VkPipelineVertexInputStateCreateInfo vertexInputState =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,              // VkStructureType                                                      sType
+               DE_NULL,                                                                                                                // const void*                                                          pNext
+               0u,                                                                                                                             // VkPipelineVertexInputStateCreateFlags        flags
+               1u,                                                                                                                             // deUint32                                                                     vertexBindingDescriptionCount
+               &bindingDescription,                                                                                    // const VkVertexInputBindingDescription*       pVertexBindingDescriptions
+               static_cast<deUint32>(attributeDescriptions.size()),                    // deUint32                                                                     vertexAttributeDescriptionCount
+               attributeDescriptions.data(),                                                                   // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions
+       };
+
+       m_vertexShaderModule    = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vert_shader"), 0);
+       m_fragmentShaderModule  = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("frag_shader"), 0);
+
+       // Create pipeline.
+       {
+               const std::vector<VkViewport>                                           viewports                                               (1, makeViewport(m_renderSize));
+               const std::vector<VkRect2D>                                                     scissors                                                (1, makeRect2D(m_renderSize));
+
+               const VkPipelineColorBlendAttachmentState                       colorBlendAttachmentState               =
+               {
+                       VK_FALSE,                                       // VkBool32                                     blendEnable
+                       VK_BLEND_FACTOR_ZERO,           // VkBlendFactor                        srcColorBlendFactor
+                       VK_BLEND_FACTOR_ZERO,           // VkBlendFactor                        dstColorBlendFactor
+                       VK_BLEND_OP_ADD,                        // VkBlendOp                            colorBlendOp
+                       VK_BLEND_FACTOR_ZERO,           // VkBlendFactor                        srcAlphaBlendFactor
+                       VK_BLEND_FACTOR_ZERO,           // VkBlendFactor                        dstAlphaBlendFactor
+                       VK_BLEND_OP_ADD,                        // VkBlendOp                            alphaBlendOp
+                       VK_COLOR_COMPONENT_R_BIT        // VkColorComponentFlags        colorWriteMask
+                       | VK_COLOR_COMPONENT_G_BIT
+                       | VK_COLOR_COMPONENT_B_BIT
+                       | VK_COLOR_COMPONENT_A_BIT
+               };
+
+               const VkPipelineColorBlendStateCreateInfo                       colorBlendStateCreateInfo               =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,                                                       // VkStructureType                                                              sType
+                       DE_NULL,                                                                                                                                                        // const void*                                                                  pNext
+                       0u,                                                                                                                                                                     // VkPipelineColorBlendStateCreateFlags                 flags
+                       VK_FALSE,                                                                                                                                                       // VkBool32                                                                             logicOpEnable
+                       VK_LOGIC_OP_CLEAR,                                                                                                                                      // VkLogicOp                                                                    logicOp
+                   1u,                                                                                                                                                                 // deUint32                                                                             attachmentCount
+                   &colorBlendAttachmentState,                                                                                                                 // const VkPipelineColorBlendAttachmentState*   pAttachments
+                       { 0.0f, 0.0f, 0.0f, 0.0f }                                                                                                                      // float                                                                                blendConstants[4]
+               };
+
+               m_graphicsPipeline0 = makeGraphicsPipeline(vk,                                                                  // const DeviceInterface&                                                       vk
+                                                                                                  vkDevice,                                                            // const VkDevice                                                                       device
+                                                                                                  *m_pipelineLayout,                                   // const VkPipelineLayout                                                       pipelineLayout
+                                                                                                  *m_vertexShaderModule,                               // const VkShaderModule                                                         vertexShaderModule
+                                                                                                  DE_NULL,                                                             // const VkShaderModule                                                         tessellationControlModule
+                                                                                                  DE_NULL,                                                             // const VkShaderModule                                                         tessellationEvalModule
+                                                                                                  DE_NULL,                                                             // const VkShaderModule                                                         geometryShaderModule
+                                                                                                  *m_fragmentShaderModule,                             // const VkShaderModule                                                         fragmentShaderModule
+                                                                                                  *m_renderPass,                                               // const VkRenderPass                                                           renderPass
+                                                                                                  viewports,                                                   // const std::vector<VkViewport>&                                       viewports
+                                                                                                  scissors,                                                            // const std::vector<VkRect2D>&                                         scissors
+                                                                                                  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,        // const VkPrimitiveTopology                                            topology
+                                                                                                  0u,                                                                  // const deUint32                                                                       subpass
+                                                                                                  0u,                                                                  // const deUint32                                                                       patchControlPoints
+                                                                                                  &vertexInputState,                                   // const VkPipelineVertexInputStateCreateInfo*          vertexInputStateCreateInfo
+                                                                                                  DE_NULL,                                                             // const VkPipelineRasterizationStateCreateInfo*        rasterizationStateCreateInfo
+                                                                                                  DE_NULL,                                                             // const VkPipelineMultisampleStateCreateInfo*          multisampleStateCreateInfo
+                                                                                                  DE_NULL,                                                             // const VkPipelineDepthStencilStateCreateInfo*         depthStencilStateCreateInfo
+                                                                                                  &colorBlendStateCreateInfo);                 // const VkPipelineColorBlendStateCreateInfo*           colorBlendStateCreateInfo
+
+               m_graphicsPipeline1 = makeGraphicsPipeline(vk,                                                                  // const DeviceInterface&                                                       vk
+                                                                                                  vkDevice,                                                            // const VkDevice                                                                       device
+                                                                                                  *m_pipelineLayout,                                   // const VkPipelineLayout                                                       pipelineLayout
+                                                                                                  *m_vertexShaderModule,                               // const VkShaderModule                                                         vertexShaderModule
+                                                                                                  DE_NULL,                                                             // const VkShaderModule                                                         tessellationControlModule
+                                                                                                  DE_NULL,                                                             // const VkShaderModule                                                         tessellationEvalModule
+                                                                                                  DE_NULL,                                                             // const VkShaderModule                                                         geometryShaderModule
+                                                                                                  *m_fragmentShaderModule,                             // const VkShaderModule                                                         fragmentShaderModule
+                                                                                                  *m_renderPass,                                               // const VkRenderPass                                                           renderPass
+                                                                                                  viewports,                                                   // const std::vector<VkViewport>&                                       viewports
+                                                                                                  scissors,                                                            // const std::vector<VkRect2D>&                                         scissors
+                                                                                                  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,        // const VkPrimitiveTopology                                            topology
+                                                                                                  1u,                                                                  // const deUint32                                                                       subpass
+                                                                                                  0u,                                                                  // const deUint32                                                                       patchControlPoints
+                                                                                                  &vertexInputState,                                   // const VkPipelineVertexInputStateCreateInfo*          vertexInputStateCreateInfo
+                                                                                                  DE_NULL,                                                             // const VkPipelineRasterizationStateCreateInfo*        rasterizationStateCreateInfo
+                                                                                                  DE_NULL,                                                             // const VkPipelineMultisampleStateCreateInfo*          multisampleStateCreateInfo
+                                                                                                  DE_NULL,                                                             // const VkPipelineDepthStencilStateCreateInfo*         depthStencilStateCreateInfo
+                                                                                                  &colorBlendStateCreateInfo);                 // const VkPipelineColorBlendStateCreateInfo*           colorBlendStateCreateInfo
+
+               m_graphicsPipeline2 = makeGraphicsPipeline(vk,                                                                  // const DeviceInterface&                                                       vk
+                                                                                                  vkDevice,                                                            // const VkDevice                                                                       device
+                                                                                                  *m_pipelineLayout,                                   // const VkPipelineLayout                                                       pipelineLayout
+                                                                                                  *m_vertexShaderModule,                               // const VkShaderModule                                                         vertexShaderModule
+                                                                                                  DE_NULL,                                                             // const VkShaderModule                                                         tessellationControlModule
+                                                                                                  DE_NULL,                                                             // const VkShaderModule                                                         tessellationEvalModule
+                                                                                                  DE_NULL,                                                             // const VkShaderModule                                                         geometryShaderModule
+                                                                                                  *m_fragmentShaderModule,                             // const VkShaderModule                                                         fragmentShaderModule
+                                                                                                  *m_renderPass,                                               // const VkRenderPass                                                           renderPass
+                                                                                                  viewports,                                                   // const std::vector<VkViewport>&                                       viewports
+                                                                                                  scissors,                                                            // const std::vector<VkRect2D>&                                         scissors
+                                                                                                  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,        // const VkPrimitiveTopology                                            topology
+                                                                                                  2u,                                                                  // const deUint32                                                                       subpass
+                                                                                                  0u,                                                                  // const deUint32                                                                       patchControlPoints
+                                                                                                  &vertexInputState,                                   // const VkPipelineVertexInputStateCreateInfo*          vertexInputStateCreateInfo
+                                                                                                  DE_NULL,                                                             // const VkPipelineRasterizationStateCreateInfo*        rasterizationStateCreateInfo
+                                                                                                  DE_NULL,                                                             // const VkPipelineMultisampleStateCreateInfo*          multisampleStateCreateInfo
+                                                                                                  DE_NULL,                                                             // const VkPipelineDepthStencilStateCreateInfo*         depthStencilStateCreateInfo
+                                                                                                  &colorBlendStateCreateInfo);                 // const VkPipelineColorBlendStateCreateInfo*           colorBlendStateCreateInfo
+
+       }
+
+       // Create command pool
+       m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
+
+       // Create command buffer
+       createCommandBuffer(vk, vkDevice);
+}
+
+void MultipleSubpassesMultipleCommandBuffersTestInstance::createCommandBuffer (const DeviceInterface&  vk,
+                                                                                                                                                 VkDevice                                      vkDevice)
+{
+       const VkRenderPassBeginInfo                                                     renderPassBeginInfoA    =
+       {
+               VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,       // VkStructureType              sType;
+               DE_NULL,                                                                        // const void*                  pNext;
+               *m_renderPass,                                                          // VkRenderPass                 renderPass;
+               *m_framebufferA,                                                        // VkFramebuffer                framebuffer;
+               makeRect2D(m_renderSize),                                       // VkRect2D                             renderArea;
+               0u,                                                                                     // uint32_t                             clearValueCount;
+               DE_NULL                                                                         // const VkClearValue*  pClearValues;
+       };
+       const VkRenderPassBeginInfo                                                     renderPassBeginInfoB    =
+       {
+               VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,       // VkStructureType              sType;
+               DE_NULL,                                                                        // const void*                  pNext;
+               *m_renderPass,                                                          // VkRenderPass                 renderPass;
+               *m_framebufferB,                                                        // VkFramebuffer                framebuffer;
+               makeRect2D(m_renderSize),                                       // VkRect2D                             renderArea;
+               0u,                                                                                     // uint32_t                             clearValueCount;
+               DE_NULL                                                                         // const VkClearValue*  pClearValues;
+       };
+
+       m_cmdBufferA = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+       m_cmdBufferB = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+
+       const VkClearRect                                                                       clearRect                       =
+       {
+               {                                                                                               // VkRect2D             rect;
+                       { 0, 0, },                                                                      //      VkOffset2D      offset;
+                       { kImageWidth, kImageHeight }                           //      VkExtent2D      extent;
+               },
+               0u,                                                                                             // uint32_t             baseArrayLayer;
+               1u                                                                                              // uint32_t             layerCount;
+       };
+
+       const VkClearAttachment clearAttachment =
+       {
+               VK_IMAGE_ASPECT_COLOR_BIT,      // VkImageAspectFlags   aspectMask;
+               0u,                                                     // uint32_t                             colorAttachment;
+               m_clearColor                            // VkClearValue                 clearValue;
+       };
+
+       VkDeviceSize    vertexBufferOffset      = 0u;
+
+       // Command Buffer A will set his own event but wait for the B's event before continuing to the next subpass.
+       beginCommandBuffer(vk, *m_cmdBufferA, 0u);
+       beginCommandBuffer(vk, *m_cmdBufferB, 0u);
+               vk.cmdBeginRenderPass(*m_cmdBufferA, &renderPassBeginInfoA, VK_SUBPASS_CONTENTS_INLINE);
+               vk.cmdBindPipeline(*m_cmdBufferA, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline0);
+               vk.cmdBindVertexBuffers(*m_cmdBufferA, 0u, 1u, &m_vertexBuffer.get(), &vertexBufferOffset);
+               vk.cmdClearAttachments(*m_cmdBufferA, 1u, &clearAttachment, 1u, &clearRect);
+
+               vk.cmdBeginRenderPass(*m_cmdBufferB, &renderPassBeginInfoB, VK_SUBPASS_CONTENTS_INLINE);
+               vk.cmdBindPipeline(*m_cmdBufferB, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline0);
+               vk.cmdClearAttachments(*m_cmdBufferB, 1u, &clearAttachment, 1u, &clearRect);
+               vk.cmdNextSubpass(*m_cmdBufferB, VK_SUBPASS_CONTENTS_INLINE);
+
+               vk.cmdNextSubpass(*m_cmdBufferA, VK_SUBPASS_CONTENTS_INLINE);
+               vk.cmdBindPipeline(*m_cmdBufferA, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline1);
+               vk.cmdBindVertexBuffers(*m_cmdBufferA, 0u, 1u, &m_vertexBuffer.get(), &vertexBufferOffset);
+               vk.cmdDraw(*m_cmdBufferA, 4u, 1u, 0u, 0u);
+
+               vertexBufferOffset = 8 * sizeof(Vertex);
+               vk.cmdBindPipeline(*m_cmdBufferB, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline1);
+               vk.cmdBindVertexBuffers(*m_cmdBufferB, 0u, 1u, &m_vertexBuffer.get(), &vertexBufferOffset);
+               vk.cmdDraw(*m_cmdBufferB, 4u, 1u, 0u, 0u);
+               vk.cmdNextSubpass(*m_cmdBufferB, VK_SUBPASS_CONTENTS_INLINE);
+
+               vertexBufferOffset = 0u;
+               vk.cmdNextSubpass(*m_cmdBufferA, VK_SUBPASS_CONTENTS_INLINE);
+               vk.cmdBindPipeline(*m_cmdBufferA, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline2);
+               vk.cmdBindVertexBuffers(*m_cmdBufferA, 0u, 1u, &m_vertexBuffer.get(), &vertexBufferOffset);
+               vk.cmdDraw(*m_cmdBufferA, 4u, 1u, 4u, 0u);
+
+               vertexBufferOffset = 8 * sizeof(Vertex);
+               vk.cmdBindPipeline(*m_cmdBufferB, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline2);
+               vk.cmdDraw(*m_cmdBufferB, 4u, 1u, 4u, 0u);
+               vk.cmdEndRenderPass(*m_cmdBufferB);
+               vk.cmdEndRenderPass(*m_cmdBufferA);
+       endCommandBuffer(vk, *m_cmdBufferA);
+       endCommandBuffer(vk, *m_cmdBufferB);
+}
+
+tcu::TestStatus        MultipleSubpassesMultipleCommandBuffersTestInstance::iterate (void)
+{
+       const DeviceInterface&  vk                                      = m_context.getDeviceInterface();
+       const VkDevice                  vkDevice                        = m_context.getDevice();
+       const VkQueue                   queue                           = m_context.getUniversalQueue();
+       const deUint32                  queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
+       SimpleAllocator                 allocator                       (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
+
+       {
+               const Unique<VkFence>                           fence                           (createFence(vk, vkDevice));
+               std::vector<VkCommandBuffer>    commandBuffers;
+               commandBuffers.emplace_back(m_cmdBufferA.get());
+               commandBuffers.emplace_back(m_cmdBufferB.get());
+
+               const VkSubmitInfo              submitInfo                              =
+               {
+                       VK_STRUCTURE_TYPE_SUBMIT_INFO,                                          // VkStructureType                              sType;
+                       DE_NULL,                                                                                        // const void*                                  pNext;
+                       0u,                                                                                                     // deUint32                                             waitSemaphoreCount;
+                       DE_NULL,                                                                                        // const VkSemaphore*                   pWaitSemaphores;
+                       (const VkPipelineStageFlags*)DE_NULL,                           // const VkPipelineStageFlags*  pWaitDstStageMask;
+                       static_cast<deUint32>(commandBuffers.size()),           // deUint32                                             commandBufferCount;
+                       commandBuffers.data(),                                                          // const VkCommandBuffer*               pCommandBuffers;
+                       0u,                                                                                                     // deUint32                                             signalSemaphoreCount;
+                       DE_NULL,                                                                                        // const VkSemaphore*                   pSignalSemaphores;
+               };
+
+               VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
+               VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), DE_TRUE, ~0ull));
+       }
+
+       // XXX: Add code for image verification for both color attachments
+       {
+               // Colors to compare to.
+               const tcu::Vec4                 red                     = {1.0f, 0.0f, 0.0f, 1.0f};
+               const tcu::Vec4                 green           = {0.0f, 1.0f, 0.0f, 1.0f};
+               const tcu::Vec4                 blue            = {0.0f, 0.0f, 1.0f, 1.0f};
+               const tcu::Vec4                 yellow          = {1.0f, 1.0f, 0.0f, 1.0f};
+
+               // Read result images.
+               de::MovePtr<tcu::TextureLevel> imagePixelsA = pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImageA, VK_FORMAT_R32G32B32A32_SFLOAT, m_renderSize);
+               de::MovePtr<tcu::TextureLevel> imagePixelsB = pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImageB, VK_FORMAT_R32G32B32A32_SFLOAT, m_renderSize);
+
+               // Verify pixel colors match.
+               const tcu::ConstPixelBufferAccess&      imageAccessA            = imagePixelsA->getAccess();
+               const tcu::ConstPixelBufferAccess&      imageAccessB            = imagePixelsB->getAccess();
+
+
+               tcu::TextureLevel       referenceImageA(mapVkFormat(VK_FORMAT_R32G32B32A32_SFLOAT), m_renderSize.x(), m_renderSize.y());
+               tcu::TextureLevel       referenceImageB(mapVkFormat(VK_FORMAT_R32G32B32A32_SFLOAT), m_renderSize.x(), m_renderSize.y());
+
+               tcu::clear(tcu::getSubregion(referenceImageA.getAccess(), 0u, 0u,
+                                                                        imageAccessA.getWidth() / 2, imageAccessA.getHeight()),
+                                          red);
+               tcu::clear(tcu::getSubregion(referenceImageA.getAccess(), imageAccessA.getWidth() / 2, 0u,
+                                                                        imageAccessA.getWidth() / 2, imageAccessA.getHeight()),
+                                  green);
+
+               if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", referenceImageA.getAccess(), imageAccessA, tcu::Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
+                       TCU_FAIL("[A] Rendered image is not correct");
+
+               tcu::clear(tcu::getSubregion(referenceImageB.getAccess(), 0u, 0u,
+                                                                        imageAccessB.getWidth() / 2, imageAccessB.getHeight()),
+                                          blue);
+               tcu::clear(tcu::getSubregion(referenceImageB.getAccess(), imageAccessB.getWidth() / 2, 0u,
+                                                                        imageAccessA.getWidth() / 2, imageAccessB.getHeight()),
+                                  yellow);
+
+               if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", referenceImageB.getAccess(), imageAccessB, tcu::Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
+                       TCU_FAIL("[B] Rendered image is not correct");
+
+       }
+
+       return tcu::TestStatus::pass("Pass");
+}
+} // anonymous
+
+tcu::TestCaseGroup* createRenderPassMultipleSubpassesMultipleCommandBuffersTests (tcu::TestContext& testCtx)
+{
+       de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "multiple_subpasses_multiple_command_buffers", "Multiple subpasses multiple command buffers"));
+
+       testGroup->addChild(new MultipleSubpassesMultipleCommandBuffersTest(testCtx, "test", ""));
+
+       return testGroup.release();
+}
+
+} // renderpass
+} // vkt
diff --git a/external/vulkancts/modules/vulkan/renderpass/vktRenderPassMultipleSubpassesMultipleCommandBuffersTests.hpp b/external/vulkancts/modules/vulkan/renderpass/vktRenderPassMultipleSubpassesMultipleCommandBuffersTests.hpp
new file mode 100644 (file)
index 0000000..3fd887a
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef _VKTRENDERPASSMULTIPLESUBPASSESMULTIPLECOMMANDBUFFERSTESTS_HPP
+#define _VKTRENDERPASSMULTIPLESUBPASSESMULTIPLECOMMANDBUFFERSTESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2019 The Khronos Group Inc.
+ * Copyright (c) 2019 Valve Corporation.
+ *
+ * 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 vkCmdClearAttachments with unused attachments.
+ *//*--------------------------------------------------------------------*/
+
+#include "vktTestCase.hpp"
+#include "vktRenderPassTestsUtil.hpp"
+
+namespace vkt
+{
+namespace renderpass
+{
+
+tcu::TestCaseGroup* createRenderPassMultipleSubpassesMultipleCommandBuffersTests (tcu::TestContext& testCtx);
+
+} // renderpass
+} // vkt
+
+#endif // _VKTRENDERPASSMULTIPLESUBPASSESMULTIPLECOMMANDBUFFERSTESTS_HPP
index a23b6f7..44cf7b2 100644 (file)
@@ -34,6 +34,7 @@
 #include "vktRenderPassDepthStencilResolveTests.hpp"
 #include "vktRenderPassUnusedAttachmentSparseFillingTests.hpp"
 #include "vktRenderPassFragmentDensityMapTests.hpp"
+#include "vktRenderPassMultipleSubpassesMultipleCommandBuffersTests.hpp"
 
 #include "vktTestCaseUtil.hpp"
 #include "vktTestGroupUtil.hpp"
@@ -6995,6 +6996,7 @@ tcu::TestCaseGroup* createRenderPassTestsInternal (tcu::TestContext& testCtx, Re
 
        renderpassTests->addChild(suballocationTestGroup.release());
        renderpassTests->addChild(dedicatedAllocationTestGroup.release());
+       renderpassTests->addChild(createRenderPassMultipleSubpassesMultipleCommandBuffersTests(testCtx));
 
        if (renderPassType != RENDERPASS_TYPE_LEGACY)
        {
index 2185937..dfc2724 100644 (file)
@@ -358829,6 +358829,7 @@ dEQP-VK.renderpass.dedicated_allocation.attachment_write_mask.attachment_count_8
 dEQP-VK.renderpass.dedicated_allocation.attachment_write_mask.attachment_count_8.start_index_5
 dEQP-VK.renderpass.dedicated_allocation.attachment_write_mask.attachment_count_8.start_index_6
 dEQP-VK.renderpass.dedicated_allocation.attachment_write_mask.attachment_count_8.start_index_7
+dEQP-VK.renderpass.multiple_subpasses_multiple_command_buffers.test
 dEQP-VK.renderpass2.suballocation.simple.color
 dEQP-VK.renderpass2.suballocation.simple.depth
 dEQP-VK.renderpass2.suballocation.simple.stencil
@@ -368113,6 +368114,7 @@ dEQP-VK.renderpass2.dedicated_allocation.attachment_write_mask.attachment_count_
 dEQP-VK.renderpass2.dedicated_allocation.attachment_write_mask.attachment_count_8.start_index_5
 dEQP-VK.renderpass2.dedicated_allocation.attachment_write_mask.attachment_count_8.start_index_6
 dEQP-VK.renderpass2.dedicated_allocation.attachment_write_mask.attachment_count_8.start_index_7
+dEQP-VK.renderpass2.multiple_subpasses_multiple_command_buffers.test
 dEQP-VK.renderpass2.depth_stencil_resolve.misc.properties
 dEQP-VK.renderpass2.depth_stencil_resolve.image_2d_32_32.samples_2.d16_unorm.depth_zero_stencil_none_testing_depth
 dEQP-VK.renderpass2.depth_stencil_resolve.image_2d_32_32.samples_2.d16_unorm.depth_zero_stencil_none_unused_resolve_testing_depth
index 43aee8c..8cd94cb 100644 (file)
@@ -358791,6 +358791,7 @@ dEQP-VK.renderpass.dedicated_allocation.attachment_write_mask.attachment_count_8
 dEQP-VK.renderpass.dedicated_allocation.attachment_write_mask.attachment_count_8.start_index_5
 dEQP-VK.renderpass.dedicated_allocation.attachment_write_mask.attachment_count_8.start_index_6
 dEQP-VK.renderpass.dedicated_allocation.attachment_write_mask.attachment_count_8.start_index_7
+dEQP-VK.renderpass.multiple_subpasses_multiple_command_buffers.test
 dEQP-VK.renderpass2.suballocation.simple.color
 dEQP-VK.renderpass2.suballocation.simple.depth
 dEQP-VK.renderpass2.suballocation.simple.stencil
@@ -368075,6 +368076,7 @@ dEQP-VK.renderpass2.dedicated_allocation.attachment_write_mask.attachment_count_
 dEQP-VK.renderpass2.dedicated_allocation.attachment_write_mask.attachment_count_8.start_index_5
 dEQP-VK.renderpass2.dedicated_allocation.attachment_write_mask.attachment_count_8.start_index_6
 dEQP-VK.renderpass2.dedicated_allocation.attachment_write_mask.attachment_count_8.start_index_7
+dEQP-VK.renderpass2.multiple_subpasses_multiple_command_buffers.test
 dEQP-VK.renderpass2.depth_stencil_resolve.misc.properties
 dEQP-VK.renderpass2.depth_stencil_resolve.image_2d_32_32.samples_2.d16_unorm.depth_zero_stencil_none_testing_depth
 dEQP-VK.renderpass2.depth_stencil_resolve.image_2d_32_32.samples_2.d16_unorm.depth_zero_stencil_none_unused_resolve_testing_depth