/*------------------------------------------------------------------------ * 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 #include #include #include #include namespace vkt { namespace renderpass { namespace { struct Vertex { tcu::Vec4 position; tcu::Vec4 color; }; template inline VkDeviceSize sizeInBytes(const std::vector& vec) { return vec.size() * sizeof(vec[0]); } std::vector genVertices (void) { std::vector 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 }; VkClearValue m_initialColor; VkClearValue m_clearColor; Move m_colorImageA; de::MovePtr m_colorImageAllocA; Move m_colorAttachmentViewA; Move m_colorImageB; de::MovePtr m_colorImageAllocB; Move m_colorAttachmentViewB; Move m_renderPass; Move m_framebufferA; Move m_framebufferB; Move m_vertexShaderModule; Move m_fragmentShaderModule; Move m_descriptorSetLayout; Move m_pipelineLayout; Move m_graphicsPipeline0; Move m_graphicsPipeline1; Move m_graphicsPipeline2; Move m_cmdPool; Move m_cmdBufferA; Move m_cmdBufferB; Move m_vertexBuffer; de::MovePtr 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 createRenderPass (const DeviceInterface& vk, VkDevice vkDevice) { // 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 }; // 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 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 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(subpassDescriptions.size()), // deUint32 subpassCount subpassDescriptions.data(), // const VkSubpassDescription* pSubpasses static_cast(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 cmdPool; Move cmdBuffer; std::vector preImageBarriers; std::vector 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(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(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 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(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 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(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 viewports (1, makeViewport(m_renderSize)); const std::vector 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& viewports scissors, // const std::vector& 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& viewports scissors, // const std::vector& 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& viewports scissors, // const std::vector& 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 its 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 fence (createFence(vk, vkDevice)); std::vector 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(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)); } { // 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 imagePixelsA = pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImageA, VK_FORMAT_R32G32B32A32_SFLOAT, m_renderSize); de::MovePtr 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 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