/*------------------------------------------------------------------------ * Vulkan Conformance Tests * ------------------------ * * Copyright (c) 2017 The Khronos Group Inc. * Copyright (c) 2017 Samsung Electronics Co., Ltd. * * 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 Protected memory attachment clear tests *//*--------------------------------------------------------------------*/ #include "vktProtectedMemAttachmentClearTests.hpp" #include "deRandom.hpp" #include "tcuTestLog.hpp" #include "tcuVector.hpp" #include "vkPrograms.hpp" #include "vktTestCase.hpp" #include "vktTestGroupUtil.hpp" #include "vkTypeUtil.hpp" #include "vkBuilderUtil.hpp" #include "vkCmdUtil.hpp" #include "vktProtectedMemContext.hpp" #include "vktProtectedMemUtils.hpp" #include "vktProtectedMemImageValidator.hpp" namespace vkt { namespace ProtectedMem { namespace { enum { RENDER_WIDTH = 128, RENDER_HEIGHT = 128, }; class AttachmentClearTestInstance : public ProtectedTestInstance { public: AttachmentClearTestInstance (Context& ctx, const vk::VkClearValue& clearValue, const ValidationData& refData, const ImageValidator& validator, const CmdBufferType cmdBufferType); virtual tcu::TestStatus iterate (void); private: const vk::VkFormat m_imageFormat; const vk::VkClearValue& m_clearValue; const ValidationData& m_refData; const ImageValidator& m_validator; const CmdBufferType m_cmdBufferType; }; class AttachmentClearTestCase : public TestCase { public: AttachmentClearTestCase (tcu::TestContext& testCtx, const std::string& name, vk::VkClearValue clearValue, ValidationData data, CmdBufferType cmdBufferType) : TestCase (testCtx, name, "Clear attachment.") , m_clearValue (clearValue) , m_refData (data) , m_cmdBufferType (cmdBufferType) { } virtual ~AttachmentClearTestCase (void) {} virtual TestInstance* createInstance (Context& ctx) const { return new AttachmentClearTestInstance(ctx, m_clearValue, m_refData, m_validator, m_cmdBufferType); } virtual void initPrograms (vk::SourceCollections& programCollection) const { m_validator.initPrograms(programCollection); } private: vk::VkClearValue m_clearValue; ValidationData m_refData; ImageValidator m_validator; CmdBufferType m_cmdBufferType; }; AttachmentClearTestInstance::AttachmentClearTestInstance (Context& ctx, const vk::VkClearValue& clearValue, const ValidationData& refData, const ImageValidator& validator, const CmdBufferType cmdBufferType) : ProtectedTestInstance (ctx) , m_imageFormat (vk::VK_FORMAT_R8G8B8A8_UNORM) , m_clearValue (clearValue) , m_refData (refData) , m_validator (validator) , m_cmdBufferType (cmdBufferType) { } tcu::TestStatus AttachmentClearTestInstance::iterate() { ProtectedContext& ctx (m_protectedContext); const vk::DeviceInterface& vk = ctx.getDeviceInterface(); const vk::VkDevice device = ctx.getDevice(); const vk::VkQueue queue = ctx.getQueue(); const deUint32 queueFamilyIndex = ctx.getQueueFamilyIndex(); // Create output image de::MovePtr colorImage (createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex, RENDER_WIDTH, RENDER_HEIGHT, m_imageFormat, vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|vk::VK_IMAGE_USAGE_SAMPLED_BIT)); vk::Unique colorImageView (createImageView(ctx, **colorImage, m_imageFormat)); vk::Unique renderPass (createRenderPass(ctx, m_imageFormat)); vk::Unique framebuffer (createFramebuffer(ctx, RENDER_WIDTH, RENDER_HEIGHT, *renderPass, *colorImageView)); vk::Unique pipelineLayout (createPipelineLayout(ctx, 0u, DE_NULL)); vk::Unique cmdPool (makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex)); vk::Unique cmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY)); vk::Unique secondaryCmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY)); vk::VkCommandBuffer targetCmdBuffer = (m_cmdBufferType == CMD_BUFFER_SECONDARY) ? *secondaryCmdBuffer : *cmdBuffer; // Begin cmd buffer beginCommandBuffer(vk, *cmdBuffer); // Start image barrier { const vk::VkImageMemoryBarrier startImgBarrier = { vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType DE_NULL, // pNext 0, // srcAccessMask vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // dstAccessMask vk::VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout queueFamilyIndex, // srcQueueFamilyIndex queueFamilyIndex, // dstQueueFamilyIndex **colorImage, // image { vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask 0u, // baseMipLevel 1u, // mipLevels 0u, // baseArraySlice 1u, // subresourceRange } }; vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &startImgBarrier); } // Image clear to different from input color const tcu::Vec4 clearValue (m_clearValue.color.float32[0] < 0.5f ? 1.0f : 0.0f, m_clearValue.color.float32[1] < 0.5f ? 1.0f : 0.0f, m_clearValue.color.float32[2] < 0.5f ? 1.0f : 0.0f, m_clearValue.color.float32[3] < 0.5f ? 1.0f : 0.0f); const vk::VkSubpassContents subpassContents = m_cmdBufferType == CMD_BUFFER_SECONDARY ? vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS : vk::VK_SUBPASS_CONTENTS_INLINE; beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, vk::makeRect2D(RENDER_WIDTH, RENDER_HEIGHT), clearValue, subpassContents); if (m_cmdBufferType == CMD_BUFFER_SECONDARY) { // Begin secondary command buffer const vk::VkCommandBufferInheritanceInfo bufferInheritanceInfo = { vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // sType DE_NULL, // pNext *renderPass, // renderPass 0u, // subpass *framebuffer, // framebuffer VK_FALSE, // occlusionQueryEnable (vk::VkQueryControlFlags)0u, // queryFlags (vk::VkQueryPipelineStatisticFlags)0u, // pipelineStatistics }; beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer, bufferInheritanceInfo); } { const vk::VkClearAttachment pAttachments = { vk::VK_IMAGE_ASPECT_COLOR_BIT, //VkImageAspectFlags aspectMask 0u, //uint32_t colorAttachment m_clearValue // VkClearValue clearValue; }; const vk::VkRect2D rect2D = vk::makeRect2D(RENDER_WIDTH, RENDER_HEIGHT); const vk::VkClearRect clearRect = { rect2D, // VkRect2D rect; 0u, // deUint32 baseArrayLayer; 1u // deUint32 layerCount; }; vk.cmdClearAttachments(targetCmdBuffer, 1u, &pAttachments, 1u, &clearRect); } if (m_cmdBufferType == CMD_BUFFER_SECONDARY) { endCommandBuffer(vk, *secondaryCmdBuffer); vk.cmdExecuteCommands(*cmdBuffer, 1u, &secondaryCmdBuffer.get()); } endRenderPass(vk, *cmdBuffer); { // Image validator reads image in compute shader const vk::VkImageMemoryBarrier endImgBarrier = { vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType DE_NULL, // pNext vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // srcAccessMask vk::VK_ACCESS_SHADER_READ_BIT, // dstAccessMask vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // oldLayout vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // newLayout queueFamilyIndex, // srcQueueFamilyIndex queueFamilyIndex, // dstQueueFamilyIndex **colorImage, // image { vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask 0u, // baseMipLevel 1u, // mipLevels 0u, // baseArraySlice 1u, // subresourceRange } }; vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &endImgBarrier); } endCommandBuffer(vk, *cmdBuffer); // Submit command buffer const vk::Unique fence (vk::createFence(vk, device)); VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull)); // Log out test data ctx.getTestContext().getLog() << tcu::TestLog::Message << "Color clear value: " << tcu::Vec4(m_clearValue.color.float32) << tcu::TestLog::EndMessage << tcu::TestLog::Message << "Depth clear value: " << m_clearValue.depthStencil.depth << tcu::TestLog::EndMessage << tcu::TestLog::Message << "Stencil clear value: " << m_clearValue.depthStencil.stencil << tcu::TestLog::EndMessage; // Validate resulting image if (m_validator.validateImage(ctx, m_refData, **colorImage, m_imageFormat, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)) return tcu::TestStatus::pass("Everything went OK"); else return tcu::TestStatus::fail("Something went really wrong"); } tcu::TestCaseGroup* createAttachmentClearTests (tcu::TestContext& testCtx, CmdBufferType cmdBufferType) { struct { const vk::VkClearValue clearValue; const ValidationData data; } testData[] = { { vk::makeClearValueColorF32(1.0f, 0.0f, 0.0f, 1.0f), { { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f), tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), }, { tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), } } }, { vk::makeClearValueColorF32(0.0f, 1.0f, 0.0f, 1.0f), { { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f), tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), }, { tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), } } }, { vk::makeClearValueColorF32(0.0f, 0.0f, 1.0f, 1.0f), { { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f), tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), }, { tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), } } }, { vk::makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f), { { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f), tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), }, { tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), } } }, { vk::makeClearValueColorF32(1.0f, 0.0f, 0.0f, 1.0f), { { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f), tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), }, { tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), } } }, { vk::makeClearValueColorF32(1.0f, 0.0f, 0.0f, 0.0f), { { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f), tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), }, { tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), } } }, { vk::makeClearValueColorF32(0.1f, 0.2f, 0.3f, 0.0f), { { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f), tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), }, { tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f), tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f), tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f), tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f), } } }, }; de::MovePtr clearStaticTests (new tcu::TestCaseGroup(testCtx, "static", "Attachment Clear Op Tests with static input")); for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(testData); ++ndx) { const std::string name = "clear_" + de::toString(ndx + 1); clearStaticTests->addChild(new AttachmentClearTestCase(testCtx, name.c_str(), testData[ndx].clearValue, testData[ndx].data, cmdBufferType)); } /* Add a few randomized tests */ de::MovePtr clearRandomTests (new tcu::TestCaseGroup(testCtx, "random", "Attachment Clear Op Tests with random input")); const int testCount = 10; de::Random rnd (testCtx.getCommandLine().getBaseSeed()); for (int ndx = 0; ndx < testCount; ++ndx) { const std::string name = "clear_" + de::toString(ndx + 1); vk::VkClearValue clearValue = vk::makeClearValueColorF32( rnd.getFloat(0.0, 1.0f), rnd.getFloat(0.0, 1.0f), rnd.getFloat(0.0, 1.0f), rnd.getFloat(0.0, 1.0f)); tcu::Vec4 refValue (clearValue.color.float32[0], clearValue.color.float32[1], clearValue.color.float32[2], clearValue.color.float32[3]); ValidationData data = { { tcu::Vec4(rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f)), tcu::Vec4(rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f)), tcu::Vec4(rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f)), tcu::Vec4(rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f)) }, { refValue, refValue, refValue, refValue } }; clearRandomTests->addChild(new AttachmentClearTestCase(testCtx, name.c_str(), clearValue, data, cmdBufferType)); } std::string groupName = getCmdBufferTypeStr(cmdBufferType); std::string groupDesc = "Attachment Clear Op Tests with " + groupName + " command buffer"; de::MovePtr clearTests (new tcu::TestCaseGroup(testCtx, groupName.c_str(), groupDesc.c_str())); clearTests->addChild(clearStaticTests.release()); clearTests->addChild(clearRandomTests.release()); return clearTests.release(); } } // anonymous tcu::TestCaseGroup* createAttachmentClearTests (tcu::TestContext& testCtx) { de::MovePtr clearTests (new tcu::TestCaseGroup(testCtx, "clear_op", "Attachment Clear Op Tests")); clearTests->addChild(createAttachmentClearTests(testCtx, CMD_BUFFER_PRIMARY)); clearTests->addChild(createAttachmentClearTests(testCtx, CMD_BUFFER_SECONDARY)); return clearTests.release(); } } // ProtectedMem } // vkt