/*------------------------------------------------------------------------ * Vulkan Conformance Tests * ------------------------ * * Copyright (c) 2022 The Khronos Group Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief Tests subpass merge feedback extension *//*--------------------------------------------------------------------*/ #include "vktRenderPassSubpassMergeFeedbackTests.hpp" #include "pipeline/vktPipelineImageUtil.hpp" #include "vktTestCase.hpp" #include "vkImageUtil.hpp" #include "vkMemUtil.hpp" #include "vkPlatform.hpp" #include "vkPrograms.hpp" #include "vkQueryUtil.hpp" #include "vkCmdUtil.hpp" #include "vkRef.hpp" #include "vkRefUtil.hpp" #include "vkTypeUtil.hpp" #include "vkCmdUtil.hpp" #include "vkObjUtil.hpp" #include "tcuImageCompare.hpp" #include "tcuPlatform.hpp" #include "tcuTextureUtil.hpp" #include "tcuTestLog.hpp" #include "deStringUtil.hpp" #include "deUniquePtr.hpp" #include "deRandom.hpp" #include #include #include #include namespace vkt { namespace renderpass { using namespace vk; namespace { struct TestParams { deUint32 subpassCount; bool disallowMergeRenderpass; bool disallowMergeSubPass1; }; struct Vertex4RGBA { tcu::Vec4 position; tcu::Vec4 color; }; class SubpassMergeFeedbackTest : public vkt::TestCase { public: SubpassMergeFeedbackTest (tcu::TestContext& testContext, const std::string& name, const std::string& description, const TestParams& testParams); virtual ~SubpassMergeFeedbackTest (void); virtual TestInstance* createInstance (Context& context) const; private: const TestParams m_testParams; }; class SubpassMergeFeedbackTestInstance : public vkt::TestInstance { public: SubpassMergeFeedbackTestInstance (Context& context, const TestParams& testParams); virtual ~SubpassMergeFeedbackTestInstance (void); virtual tcu::TestStatus iterate (void); private: tcu::TestStatus createRenderPassAndVerify (const DeviceInterface& vk, VkDevice vkDevice); const TestParams m_testParams; }; SubpassMergeFeedbackTest::SubpassMergeFeedbackTest (tcu::TestContext& testContext, const std::string& name, const std::string& description, const TestParams& testParams) : vkt::TestCase (testContext, name, description) , m_testParams (testParams) { } SubpassMergeFeedbackTest::~SubpassMergeFeedbackTest (void) { } TestInstance* SubpassMergeFeedbackTest::createInstance (Context& context) const { return new SubpassMergeFeedbackTestInstance(context, m_testParams); } SubpassMergeFeedbackTestInstance::SubpassMergeFeedbackTestInstance (Context& context, const TestParams& testParams) : vkt::TestInstance (context) , m_testParams (testParams) { // Check for renderpass2 extension context.requireDeviceFunctionality("VK_KHR_create_renderpass2"); // Check for subpass merge feedback extension context.requireDeviceFunctionality("VK_EXT_subpass_merge_feedback"); } SubpassMergeFeedbackTestInstance::~SubpassMergeFeedbackTestInstance (void) { } tcu::TestStatus SubpassMergeFeedbackTestInstance::createRenderPassAndVerify (const DeviceInterface& vk, VkDevice vkDevice) { const VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; std::vector attachmentDescriptions; std::vector resultAttachments; std::vector inputAttachments; std::vector subpassMergeControls; std::vector subpassFeedbackCreateInfos; std::vector subpassFeedbackInfos; std::vector subpassDescriptions; for (deUint32 i = 0; i < m_testParams.subpassCount; ++i) { attachmentDescriptions.emplace_back( nullptr, // const void* pNext (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout ); resultAttachments.emplace_back( nullptr, // const void* pNext i, // deUint32 attachment VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout aspectMask // VkImageAspectFlags aspectMask ); inputAttachments.emplace_back( nullptr, // const void* pNext i, // deUint32 attachment VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout layout aspectMask // VkImageAspectFlags aspectMask ); VkBool32 disallowSubpassMerge = VK_FALSE; if (i == 1 && m_testParams.disallowMergeSubPass1) { disallowSubpassMerge = VK_TRUE; } const VkRenderPassCreationControlEXT mergeControl = { VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_CONTROL_EXT, // VkStructureType sType; nullptr, // const void* pNext; disallowSubpassMerge, // VkBool32 disallowMerging; }; subpassMergeControls.push_back( mergeControl ); VkRenderPassSubpassFeedbackInfoEXT feedbackInfo = { VK_SUBPASS_MERGE_STATUS_MERGED_EXT, // VkSubpassMergeStatusEXT subpassMergeStatus; "", // description[VK_MAX_DESCRIPTION_SIZE]; 0 // uint32_t postMergeIndex; }; subpassFeedbackInfos.push_back( feedbackInfo ); } for (deUint32 i = 0; i < m_testParams.subpassCount; ++i) { const VkRenderPassSubpassFeedbackCreateInfoEXT feedbackCreateInfo = { VK_STRUCTURE_TYPE_RENDER_PASS_SUBPASS_FEEDBACK_CREATE_INFO_EXT, // VkStructureType sType; &subpassMergeControls[i], // const void* pNext; &subpassFeedbackInfos[i] }; subpassFeedbackCreateInfos.push_back( feedbackCreateInfo ); } for (deUint32 i = 0; i < m_testParams.subpassCount; ++i) { subpassDescriptions.emplace_back ( &subpassFeedbackCreateInfos[i], (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint 0u, // deUint32 viewMask (i>0) ? 1u : 0u, // deUint32 inputAttachmentCount (i>0) ? &inputAttachments[i-1] : nullptr, // const VkAttachmentReference* pInputAttachments 1u, // deUint32 colorAttachmentCount &resultAttachments[i], // const VkAttachmentReference* pColorAttachments nullptr, // const VkAttachmentReference* pResolveAttachments nullptr, // const VkAttachmentReference* pDepthStencilAttachment 0u, // deUint32 preserveAttachmentCount nullptr // const deUint32* pPreserveAttachments ); } std::vector subpassDependencies; for (deUint32 i = 1; i < m_testParams.subpassCount; ++i) { subpassDependencies.emplace_back( nullptr, // const void* pNext i-1, // uint32_t srcSubpass i, // uint32_t dstSubpass VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags dstStageMask VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask VK_DEPENDENCY_BY_REGION_BIT, // VkDependencyFlags dependencyFlags 0u // deInt32 viewOffset ); } VkBool32 disallowMerging = VK_FALSE; if (m_testParams.disallowMergeRenderpass) { disallowMerging = VK_TRUE; } const VkRenderPassCreationControlEXT renderpassControl = { VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_CONTROL_EXT, // VkStructureType sType; DE_NULL, // const void* pNext; disallowMerging // VkBool32 disallowMerging; }; VkRenderPassCreationFeedbackInfoEXT renderpassFeedbackInfo = { 0 // uint32_t postMergeSubpassCount; }; VkRenderPassCreationFeedbackCreateInfoEXT renderpassFeedbackCreateInfo = { VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_FEEDBACK_CREATE_INFO_EXT, // VkStructureType sType; &renderpassControl, // const void* pNext; &renderpassFeedbackInfo }; const RenderPassCreateInfo2 renderPassInfo ( &renderpassFeedbackCreateInfo, // const void* pNext (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags static_cast(attachmentDescriptions.size()), // deUint32 attachmentCount attachmentDescriptions.data(), // 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 0u, // deUint32 correlatedViewMaskCount nullptr // const deUint32* pCorrelatedViewMasks ); Move renderPass = renderPassInfo.createRenderPass(vk, vkDevice); // Verify merge status flags if (m_testParams.disallowMergeRenderpass) { if (renderpassFeedbackInfo.postMergeSubpassCount != m_testParams.subpassCount) { return tcu::TestStatus::fail("Fail"); } for (deUint32 i = 0; i < m_testParams.subpassCount; ++i) { if (subpassFeedbackCreateInfos[i].pSubpassFeedback->subpassMergeStatus != VK_SUBPASS_MERGE_STATUS_DISALLOWED_EXT) { return tcu::TestStatus::fail("Fail"); } if (i > 0 && subpassFeedbackCreateInfos[i].pSubpassFeedback->postMergeIndex == subpassFeedbackCreateInfos[i-1].pSubpassFeedback->postMergeIndex) { return tcu::TestStatus::fail("Fail"); } } } else { if (renderpassFeedbackInfo.postMergeSubpassCount > m_testParams.subpassCount) { return tcu::TestStatus::fail("Fail"); } if (m_testParams.subpassCount == 1 && subpassFeedbackCreateInfos[0].pSubpassFeedback->subpassMergeStatus != VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SINGLE_SUBPASS_EXT) { return tcu::TestStatus::fail("Fail"); } for (deUint32 i = 1; i < m_testParams.subpassCount; ++i) { if (i == 1 && m_testParams.disallowMergeSubPass1 && subpassFeedbackCreateInfos[i].pSubpassFeedback->subpassMergeStatus != VK_SUBPASS_MERGE_STATUS_DISALLOWED_EXT) { return tcu::TestStatus::fail("Fail"); } if (subpassFeedbackCreateInfos[i].pSubpassFeedback->subpassMergeStatus == VK_SUBPASS_MERGE_STATUS_MERGED_EXT && subpassFeedbackCreateInfos[i].pSubpassFeedback->postMergeIndex != subpassFeedbackCreateInfos[i-1].pSubpassFeedback->postMergeIndex) { return tcu::TestStatus::fail("Fail"); } if (subpassFeedbackCreateInfos[i].pSubpassFeedback->subpassMergeStatus != VK_SUBPASS_MERGE_STATUS_MERGED_EXT && subpassFeedbackCreateInfos[i].pSubpassFeedback->postMergeIndex == subpassFeedbackCreateInfos[i-1].pSubpassFeedback->postMergeIndex) { return tcu::TestStatus::fail("Fail"); } } } return tcu::TestStatus::pass("Pass"); } tcu::TestStatus SubpassMergeFeedbackTestInstance::iterate (void) { const DeviceInterface& vk = m_context.getDeviceInterface(); const VkDevice vkDevice = m_context.getDevice(); // Create render pass return createRenderPassAndVerify(vk, vkDevice); } } // anonymous tcu::TestCaseGroup* createRenderPassSubpassMergeFeedbackTests (tcu::TestContext& testCtx, const RenderingType renderingType) { if (renderingType != RENDERING_TYPE_RENDERPASS2) { return nullptr; } de::MovePtr subpassMergeFeedbackTests (new tcu::TestCaseGroup(testCtx, "subpass_merge_feedback", "Subpass merge feedback tests")); { TestParams params; const std::string testName = std::string("single_subpass"); params.subpassCount = 1; params.disallowMergeRenderpass = false; params.disallowMergeSubPass1 = false; subpassMergeFeedbackTests->addChild(new SubpassMergeFeedbackTest(testCtx, testName, "", params)); } { TestParams params; const std::string testName = std::string("single_subpass_disallow_renderpass_merge"); params.subpassCount = 1; params.disallowMergeRenderpass = true; params.disallowMergeSubPass1 = false; subpassMergeFeedbackTests->addChild(new SubpassMergeFeedbackTest(testCtx, testName, "", params)); } { TestParams params; const std::string testName = std::string("three_subpasses"); params.subpassCount = 3; params.disallowMergeRenderpass = false; params.disallowMergeSubPass1 = false; subpassMergeFeedbackTests->addChild(new SubpassMergeFeedbackTest(testCtx, testName, "", params)); } { TestParams params; const std::string testName = std::string("three_subpasses_disallow_renderpass_merge"); params.subpassCount = 3; params.disallowMergeRenderpass = true; params.disallowMergeSubPass1 = false; subpassMergeFeedbackTests->addChild(new SubpassMergeFeedbackTest(testCtx, testName, "", params)); } { TestParams params; const std::string testName = std::string("three_subpasses_disallow_subpass_merge"); params.subpassCount = 3; params.disallowMergeRenderpass = false; params.disallowMergeSubPass1 = true; subpassMergeFeedbackTests->addChild(new SubpassMergeFeedbackTest(testCtx, testName, "", params)); } { TestParams params; const std::string testName = std::string("many_subpasses"); params.subpassCount = 32; params.disallowMergeRenderpass = false; params.disallowMergeSubPass1 = false; subpassMergeFeedbackTests->addChild(new SubpassMergeFeedbackTest(testCtx, testName, "", params)); } return subpassMergeFeedbackTests.release(); } } // renderpass } // vkt