--- /dev/null
+/*------------------------------------------------------------------------
+ * 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