| /*------------------------------------------------------------------------ |
| * Vulkan Conformance Tests |
| * ------------------------ |
| * |
| * Copyright (c) 2015 The Khronos Group Inc. |
| * Copyright (c) 2015 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 Vulkan Get Render Area Granularity Tests |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vktApiGranularityTests.hpp" |
| |
| #include "deRandom.hpp" |
| #include "deSharedPtr.hpp" |
| #include "deStringUtil.hpp" |
| #include "deUniquePtr.hpp" |
| |
| #include "vkImageUtil.hpp" |
| #include "vkMemUtil.hpp" |
| #include "vkQueryUtil.hpp" |
| #include "vkRefUtil.hpp" |
| #include "vkCmdUtil.hpp" |
| #include "vkTypeUtil.hpp" |
| #include "vktTestCase.hpp" |
| |
| #include "tcuTestLog.hpp" |
| #include "tcuTextureUtil.hpp" |
| |
| #include <string> |
| |
| namespace vkt |
| { |
| |
| namespace api |
| { |
| |
| using namespace vk; |
| |
| namespace |
| { |
| |
| struct AttachmentInfo |
| { |
| AttachmentInfo (const VkFormat vkFormat, |
| const deUint32 width, |
| const deUint32 height, |
| const deUint32 depth) |
| : format (vkFormat) |
| { |
| extent.width = width; |
| extent.height = height; |
| extent.depth = depth; |
| } |
| |
| ~AttachmentInfo (void) |
| {} |
| |
| VkFormat format; |
| VkExtent3D extent; |
| }; |
| |
| typedef de::SharedPtr<Allocation> AllocationSp; |
| typedef de::SharedPtr<Unique<VkImage> > VkImageSp; |
| typedef de::SharedPtr<Unique<VkImageView> > VkImageViewSp; |
| |
| class GranularityInstance : public vkt::TestInstance |
| { |
| public: |
| GranularityInstance (Context& context, |
| const std::vector<AttachmentInfo>& attachments, |
| const bool useRenderPass); |
| virtual ~GranularityInstance (void); |
| void checkFormatSupport (const VkFormat format); |
| void initAttachmentDescriptions (void); |
| void initImages (void); |
| void initRenderPass (void); |
| void beginRenderPass (void); |
| void endRenderPass (void); |
| virtual tcu::TestStatus iterate (void); |
| private: |
| const std::vector<AttachmentInfo> m_attachments; |
| const bool m_useRenderPass; |
| |
| Move<VkRenderPass> m_renderPass; |
| Move<VkFramebuffer> m_frameBuffer; |
| Move<VkCommandPool> m_cmdPool; |
| Move<VkCommandBuffer> m_cmdBuffer; |
| std::vector<VkAttachmentDescription> m_attachmentDescriptions; |
| std::vector<VkImageSp> m_images; |
| std::vector<AllocationSp> m_imageAllocs; |
| std::vector<VkImageViewSp> m_imageViews; |
| }; |
| |
| GranularityInstance::GranularityInstance (Context& context, |
| const std::vector<AttachmentInfo>& attachments, |
| const bool useRenderPass) |
| : vkt::TestInstance (context) |
| , m_attachments (attachments) |
| , m_useRenderPass (useRenderPass) |
| { |
| initAttachmentDescriptions(); |
| } |
| |
| GranularityInstance::~GranularityInstance (void) |
| { |
| } |
| |
| void GranularityInstance::checkFormatSupport (const VkFormat format) |
| { |
| VkImageFormatProperties properties; |
| |
| VkResult result = m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(), |
| format, VK_IMAGE_TYPE_2D, |
| VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_SAMPLED_BIT, |
| 0, |
| &properties); |
| |
| if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) |
| TCU_THROW(NotSupportedError, "Format not supported"); |
| } |
| |
| void GranularityInstance::initAttachmentDescriptions (void) |
| { |
| VkAttachmentDescription attachmentDescription = |
| { |
| 0u, // VkAttachmentDescriptionFlags flags; |
| VK_FORMAT_UNDEFINED, // VkFormat format; |
| VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp; |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, // 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_GENERAL, // VkImageLayout finalLayout; |
| }; |
| |
| for (std::vector<AttachmentInfo>::const_iterator it = m_attachments.begin(); it != m_attachments.end(); ++it) |
| { |
| checkFormatSupport(it->format); |
| attachmentDescription.format = it->format; |
| m_attachmentDescriptions.push_back(attachmentDescription); |
| } |
| } |
| |
| void GranularityInstance::initImages (void) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice device = m_context.getDevice(); |
| const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); |
| SimpleAllocator memAlloc (vk, device, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice())); |
| |
| for (std::vector<AttachmentInfo>::const_iterator it = m_attachments.begin(); it != m_attachments.end(); ++it) |
| { |
| const VkImageCreateInfo imageInfo = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkImageCreateFlags flags; |
| VK_IMAGE_TYPE_2D, // VkImageType imageType; |
| it->format, // VkFormat format; |
| it->extent, // VkExtent3D extent; |
| 1u, // deUint32 mipLevels; |
| 1u, // deUint32 arrayLayers; |
| VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; |
| VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; |
| VK_IMAGE_USAGE_SAMPLED_BIT, // VkImageUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; |
| }; |
| |
| // Create the image |
| Move<VkImage> image = createImage(vk, device, &imageInfo); |
| de::MovePtr<Allocation> imageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, device, *image), MemoryRequirement::Any); |
| VK_CHECK(vk.bindImageMemory(device, *image, imageAlloc->getMemory(), imageAlloc->getOffset())); |
| |
| VkImageAspectFlags aspectFlags = 0; |
| const tcu::TextureFormat tcuFormat = mapVkFormat(it->format); |
| |
| if (tcu::hasDepthComponent(tcuFormat.order)) |
| aspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT; |
| |
| if (tcu::hasStencilComponent(tcuFormat.order)) |
| aspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT; |
| |
| if (!aspectFlags) |
| aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT; |
| |
| VkFormatProperties formatProperties; |
| m_context.getInstanceInterface().getPhysicalDeviceFormatProperties(m_context.getPhysicalDevice(), |
| it->format, &formatProperties); |
| |
| if ((formatProperties.optimalTilingFeatures & (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | |
| VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) == 0) |
| throw tcu::NotSupportedError("Format not supported as attachment"); |
| |
| const VkImageViewCreateInfo createInfo = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0, // VkImageViewCreateFlags flags; |
| *image, // VkImage image; |
| VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; |
| it->format, // VkFormat format; |
| { |
| VK_COMPONENT_SWIZZLE_R, |
| VK_COMPONENT_SWIZZLE_G, |
| VK_COMPONENT_SWIZZLE_B, |
| VK_COMPONENT_SWIZZLE_A |
| }, // VkComponentMapping components; |
| { aspectFlags, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange; |
| }; |
| |
| // Create the Image View |
| Move<VkImageView> imageView = createImageView(vk, device, &createInfo); |
| |
| // To prevent object free |
| m_images.push_back(VkImageSp(new Unique<VkImage>(image))); |
| m_imageAllocs.push_back(AllocationSp(imageAlloc.release())); |
| m_imageViews.push_back(VkImageViewSp(new Unique<VkImageView>(imageView))); |
| } |
| } |
| |
| void GranularityInstance::initRenderPass (void) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice device = m_context.getDevice(); |
| const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); |
| |
| { // Create RenderPass |
| const VkSubpassDescription subpassDesc = |
| { |
| (VkSubpassDescriptionFlags)0u, // VkSubpassDescriptionFlags flags; |
| VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; |
| 0u, // deUint32 inputCount; |
| DE_NULL, // const VkAttachmentReference* pInputAttachments; |
| 0u, // deUint32 colorCount; |
| DE_NULL, // const VkAttachmentReference* pColorAttachments; |
| DE_NULL, // const VkAttachmentReference* pResolveAttachments; |
| DE_NULL, // VkAttachmentReference depthStencilAttachment; |
| 0u, // deUint32 preserveCount; |
| DE_NULL // const VkAttachmentReference* pPreserveAttachments; |
| }; |
| |
| const VkRenderPassCreateInfo renderPassParams = |
| { |
| VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; |
| (deUint32)m_attachmentDescriptions.size(), // deUint32 attachmentCount; |
| &m_attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments; |
| 1u, // deUint32 subpassCount; |
| &subpassDesc, // const VkSubpassDescription* pSubpasses; |
| 0u, // deUint32 dependencyCount; |
| DE_NULL // const VkSubpassDependency* pDependencies; |
| }; |
| |
| m_renderPass = createRenderPass(vk, device, &renderPassParams); |
| } |
| |
| initImages(); |
| |
| { // Create Framebuffer |
| std::vector<VkImageView> imageViews; |
| |
| for (std::vector<VkImageViewSp>::const_iterator it = m_imageViews.begin(); it != m_imageViews.end(); ++it) |
| imageViews.push_back(it->get()->get()); |
| |
| const VkFramebufferCreateInfo framebufferParams = |
| { |
| VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags; |
| *m_renderPass, // VkRenderPass renderPass; |
| (deUint32)imageViews.size(), // deUint32 attachmentCount; |
| &imageViews[0], // const VkImageView* pAttachments; |
| 1, // deUint32 width; |
| 1, // deUint32 height; |
| 1 // deUint32 layers; |
| }; |
| |
| m_frameBuffer = createFramebuffer(vk, device, &framebufferParams); |
| } |
| |
| m_cmdPool = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex); |
| |
| // Create CommandBuffer |
| m_cmdBuffer = allocateCommandBuffer(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); |
| |
| // Begin CommandBuffer |
| beginCommandBuffer(vk, *m_cmdBuffer, 0u); |
| } |
| |
| void GranularityInstance::beginRenderPass (void) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| |
| const VkRect2D renderArea = makeRect2D(1u, 1u); |
| |
| vk::beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_frameBuffer, renderArea); |
| } |
| |
| void GranularityInstance::endRenderPass (void) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| |
| vk::endRenderPass(vk, *m_cmdBuffer); |
| endCommandBuffer(vk, *m_cmdBuffer); |
| } |
| |
| tcu::TestStatus GranularityInstance::iterate (void) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice device = m_context.getDevice(); |
| tcu::TestLog& log = m_context.getTestContext().getLog(); |
| |
| initRenderPass(); |
| |
| VkExtent2D prePassGranularity = { ~0u, ~0u }; |
| vk.getRenderAreaGranularity(device, *m_renderPass, &prePassGranularity); |
| |
| if(m_useRenderPass) |
| beginRenderPass(); |
| |
| VkExtent2D granularity = { 0u, 0u }; |
| vk.getRenderAreaGranularity(device, *m_renderPass, &granularity); |
| TCU_CHECK(granularity.width >= 1 && granularity.height >= 1); |
| TCU_CHECK(prePassGranularity.width == granularity.width && prePassGranularity.height == granularity.height); |
| TCU_CHECK(granularity.width <= m_context.getDeviceProperties().limits.maxFramebufferWidth && granularity.height <= m_context.getDeviceProperties().limits.maxFramebufferHeight); |
| |
| if(m_useRenderPass) |
| endRenderPass(); |
| |
| log << tcu::TestLog::Message << "Horizontal granularity: " << granularity.width << " Vertical granularity: " << granularity.height << tcu::TestLog::EndMessage; |
| return tcu::TestStatus::pass("Granularity test"); |
| } |
| |
| class GranularityCase : public vkt::TestCase |
| { |
| public: |
| GranularityCase (tcu::TestContext& testCtx, |
| const std::string& name, |
| const std::string& description, |
| const std::vector<AttachmentInfo>& attachments, |
| const bool useRenderPass); |
| virtual ~GranularityCase (void); |
| |
| virtual TestInstance* createInstance (Context& context) const; |
| private: |
| const std::vector<AttachmentInfo> m_attachments; |
| const bool m_useRenderPass; |
| }; |
| |
| GranularityCase::GranularityCase (tcu::TestContext& testCtx, |
| const std::string& name, |
| const std::string& description, |
| const std::vector<AttachmentInfo>& attachments, |
| const bool useRenderPass = false) |
| : vkt::TestCase (testCtx, name, description) |
| , m_attachments (attachments) |
| , m_useRenderPass (useRenderPass) |
| { |
| } |
| |
| GranularityCase::~GranularityCase (void) |
| { |
| } |
| |
| TestInstance* GranularityCase::createInstance (Context& context) const |
| { |
| return new GranularityInstance(context, m_attachments, m_useRenderPass); |
| } |
| |
| } // anonymous |
| |
| tcu::TestCaseGroup* createGranularityQueryTests (tcu::TestContext& testCtx) |
| { |
| de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "granularity", "Granularity query tests")); |
| // Subgroups |
| de::MovePtr<tcu::TestCaseGroup> single (new tcu::TestCaseGroup(testCtx, "single", "Single texture granularity tests.")); |
| de::MovePtr<tcu::TestCaseGroup> multi (new tcu::TestCaseGroup(testCtx, "multi", "Multiple textures with same format granularity tests.")); |
| de::MovePtr<tcu::TestCaseGroup> random (new tcu::TestCaseGroup(testCtx, "random", "Multiple textures with a guaranteed format occurence.")); |
| de::MovePtr<tcu::TestCaseGroup> inRenderPass (new tcu::TestCaseGroup(testCtx, "in_render_pass", "Single texture granularity tests, inside render pass")); |
| |
| de::Random rnd(215); |
| const char* description = "Granularity case."; |
| |
| const VkFormat mandatoryFormats[] = |
| { |
| VK_FORMAT_B4G4R4A4_UNORM_PACK16, |
| VK_FORMAT_R5G6B5_UNORM_PACK16, |
| VK_FORMAT_A1R5G5B5_UNORM_PACK16, |
| VK_FORMAT_R8_UNORM, |
| VK_FORMAT_R8_SNORM, |
| VK_FORMAT_R8_UINT, |
| VK_FORMAT_R8_SINT, |
| VK_FORMAT_R8G8_UNORM, |
| VK_FORMAT_R8G8_SNORM, |
| VK_FORMAT_R8G8_UINT, |
| VK_FORMAT_R8G8_SINT, |
| VK_FORMAT_R8G8B8A8_UNORM, |
| VK_FORMAT_R8G8B8A8_SNORM, |
| VK_FORMAT_R8G8B8A8_UINT, |
| VK_FORMAT_R8G8B8A8_SINT, |
| VK_FORMAT_R8G8B8A8_SRGB, |
| VK_FORMAT_B8G8R8A8_UNORM, |
| VK_FORMAT_B8G8R8A8_SRGB, |
| VK_FORMAT_A8B8G8R8_UNORM_PACK32, |
| VK_FORMAT_A8B8G8R8_SNORM_PACK32, |
| VK_FORMAT_A8B8G8R8_UINT_PACK32, |
| VK_FORMAT_A8B8G8R8_SINT_PACK32, |
| VK_FORMAT_A8B8G8R8_SRGB_PACK32, |
| VK_FORMAT_A2B10G10R10_UNORM_PACK32, |
| VK_FORMAT_A2B10G10R10_UINT_PACK32, |
| VK_FORMAT_R16_UINT, |
| VK_FORMAT_R16_SINT, |
| VK_FORMAT_R16_SFLOAT, |
| VK_FORMAT_R16G16_UINT, |
| VK_FORMAT_R16G16_SINT, |
| VK_FORMAT_R16G16_SFLOAT, |
| VK_FORMAT_R16G16B16A16_UINT, |
| VK_FORMAT_R16G16B16A16_SINT, |
| VK_FORMAT_R16G16B16A16_SFLOAT, |
| VK_FORMAT_R32_UINT, |
| VK_FORMAT_R32_SINT, |
| VK_FORMAT_R32_SFLOAT, |
| VK_FORMAT_R32G32_UINT, |
| VK_FORMAT_R32G32_SINT, |
| VK_FORMAT_R32G32_SFLOAT, |
| VK_FORMAT_R32G32B32A32_UINT, |
| VK_FORMAT_R32G32B32A32_SINT, |
| VK_FORMAT_R32G32B32A32_SFLOAT, |
| VK_FORMAT_B10G11R11_UFLOAT_PACK32, |
| VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, |
| VK_FORMAT_D16_UNORM, |
| VK_FORMAT_D32_SFLOAT, |
| }; |
| |
| const deUint32 maxDimension = 500; |
| const deUint32 minIteration = 2; |
| const deUint32 maxIteration = 10; |
| |
| for (deUint32 formatIdx = 1; formatIdx <= VK_FORMAT_D32_SFLOAT_S8_UINT; ++formatIdx) |
| { |
| VkFormat format = VkFormat(formatIdx); |
| std::string name = de::toLower(getFormatName(format)).substr(10); |
| |
| { |
| std::vector<AttachmentInfo> attachments; |
| const int i0 = rnd.getInt(1, maxDimension); |
| const int i1 = rnd.getInt(1, maxDimension); |
| attachments.push_back(AttachmentInfo(format, i0, i1, 1)); |
| single->addChild(new GranularityCase(testCtx, name.c_str(), description, attachments)); |
| } |
| |
| { |
| std::vector<AttachmentInfo> attachments; |
| const deUint32 iterations = rnd.getInt(minIteration, maxIteration); |
| const int i0 = rnd.getInt(1, maxDimension); |
| const int i1 = rnd.getInt(1, maxDimension); |
| for (deUint32 idx = 0; idx < iterations; ++idx) |
| attachments.push_back(AttachmentInfo(VkFormat(formatIdx), i0, i1, 1)); |
| multi->addChild(new GranularityCase(testCtx, name.c_str(), description, attachments)); |
| } |
| |
| { |
| std::vector<AttachmentInfo> attachments; |
| const deUint32 iterations = rnd.getInt(minIteration, maxIteration); |
| const int i0 = rnd.getInt(1, maxDimension); |
| const int i1 = rnd.getInt(1, maxDimension); |
| attachments.push_back(AttachmentInfo(VkFormat(formatIdx), i0, i1, 1)); |
| for (deUint32 idx = 0; idx < iterations; ++idx) |
| { |
| const int i2 = rnd.getInt(0, DE_LENGTH_OF_ARRAY(mandatoryFormats) - 1); |
| const int i3 = rnd.getInt(1, maxDimension); |
| const int i4 = rnd.getInt(1, maxDimension); |
| attachments.push_back(AttachmentInfo(mandatoryFormats[i2], i3, i4, 1)); |
| } |
| random->addChild(new GranularityCase(testCtx, name.c_str(), description, attachments)); |
| } |
| |
| { |
| std::vector<AttachmentInfo> attachments; |
| const int i0 = rnd.getInt(1, maxDimension); |
| const int i1 = rnd.getInt(1, maxDimension); |
| attachments.push_back(AttachmentInfo(format, i0, i1, 1)); |
| inRenderPass->addChild(new GranularityCase(testCtx, name.c_str(), description, attachments, true)); |
| } |
| } |
| |
| group->addChild(single.release()); |
| group->addChild(multi.release()); |
| group->addChild(random.release()); |
| group->addChild(inRenderPass.release()); |
| |
| return group.release(); |
| } |
| |
| } // api |
| } // vkt |