| /*------------------------------------------------------------------------- |
| * Vulkan Conformance Tests |
| * ------------------------ |
| * |
| * Copyright (c) 2018 Google Inc. |
| * Copyright (c) 2018 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. |
| * |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vktApiMemoryRequirementInvarianceTests.hpp" |
| #include "vktApiBufferAndImageAllocationUtil.hpp" |
| #include "deRandom.h" |
| #include "tcuTestLog.hpp" |
| #include "vkQueryUtil.hpp" |
| #include "vkMemUtil.hpp" |
| #include "vkRefUtil.hpp" |
| #include "vkImageUtil.hpp" |
| |
| namespace vkt |
| { |
| namespace api |
| { |
| |
| using namespace vk; |
| |
| // Number of items to allocate |
| const unsigned int testCycles = 1000u; |
| |
| // All legal memory combinations (spec chapter 10.2: Device Memory) |
| const unsigned int legalMemoryTypeCount = 11u; |
| const MemoryRequirement legalMemoryTypes[legalMemoryTypeCount] = { |
| MemoryRequirement::Any, |
| MemoryRequirement::HostVisible | MemoryRequirement::Coherent, |
| MemoryRequirement::HostVisible | MemoryRequirement::Cached, |
| MemoryRequirement::HostVisible | MemoryRequirement::Cached | MemoryRequirement::Coherent, |
| MemoryRequirement::Local, |
| MemoryRequirement::Local | MemoryRequirement::HostVisible | MemoryRequirement::Coherent, |
| MemoryRequirement::Local | MemoryRequirement::HostVisible | MemoryRequirement::Cached, |
| MemoryRequirement::Local | MemoryRequirement::HostVisible | MemoryRequirement::Cached | MemoryRequirement::Coherent, |
| MemoryRequirement::Local | MemoryRequirement::LazilyAllocated, |
| MemoryRequirement::Protected, |
| MemoryRequirement::Protected | MemoryRequirement::Local}; |
| |
| class IObjectAllocator |
| { |
| public: |
| IObjectAllocator() |
| { |
| } |
| virtual ~IObjectAllocator() |
| { |
| } |
| virtual void allocate(Context &context) = 0; |
| virtual void deallocate(Context &context) = 0; |
| virtual size_t getSize(Context &context) = 0; |
| }; |
| |
| class BufferAllocator : public IObjectAllocator |
| { |
| public: |
| BufferAllocator(deRandom &random, bool dedicated, std::vector<int> &memoryTypes); |
| virtual ~BufferAllocator(); |
| virtual void allocate(Context &context); |
| virtual void deallocate(Context &context); |
| virtual size_t getSize(Context &context); |
| |
| private: |
| bool m_dedicated; |
| Move<VkBuffer> m_buffer; |
| VkDeviceSize m_size; |
| VkBufferUsageFlags m_usage; |
| int m_memoryType; |
| de::MovePtr<Allocation> m_bufferAlloc; |
| }; |
| |
| BufferAllocator::BufferAllocator(deRandom &random, bool dedicated, std::vector<int> &memoryTypes) |
| { |
| // If dedicated allocation is supported, randomly pick it |
| m_dedicated = dedicated && deRandom_getBool(&random); |
| // Random buffer sizes to find potential issues caused by strange alignment |
| m_size = (deRandom_getUint32(&random) % 1024) + 7; |
| // Pick a random usage from the 9 VkBufferUsageFlags. |
| m_usage = 1 << (deRandom_getUint32(&random) % 9); |
| // Pick random memory type from the supported ones |
| m_memoryType = memoryTypes[deRandom_getUint32(&random) % memoryTypes.size()]; |
| } |
| |
| BufferAllocator::~BufferAllocator() |
| { |
| } |
| |
| void BufferAllocator::allocate(Context &context) |
| { |
| Allocator &memAlloc = context.getDefaultAllocator(); |
| de::MovePtr<IBufferAllocator> allocator; |
| MemoryRequirement requirement = legalMemoryTypes[m_memoryType]; |
| |
| if (m_dedicated) |
| allocator = de::MovePtr<IBufferAllocator>(new BufferDedicatedAllocation); |
| else |
| allocator = de::MovePtr<IBufferAllocator>(new BufferSuballocation); |
| |
| allocator->createTestBuffer(m_size, m_usage, context, memAlloc, m_buffer, requirement, m_bufferAlloc); |
| } |
| |
| void BufferAllocator::deallocate(Context &context) |
| { |
| const DeviceInterface &vk = context.getDeviceInterface(); |
| const vk::VkDevice &device = context.getDevice(); |
| |
| vk.destroyBuffer(device, m_buffer.disown(), DE_NULL); |
| m_bufferAlloc.clear(); |
| } |
| |
| size_t BufferAllocator::getSize(Context &context) |
| { |
| const DeviceInterface &vk = context.getDeviceInterface(); |
| const vk::VkDevice &device = context.getDevice(); |
| VkMemoryRequirements memReq; |
| |
| vk.getBufferMemoryRequirements(device, *m_buffer, &memReq); |
| |
| return (size_t)memReq.size; |
| } |
| |
| class ImageAllocator : public IObjectAllocator |
| { |
| public: |
| ImageAllocator(deRandom &random, bool dedicated, std::vector<int> &linearformats, std::vector<int> &optimalformats, |
| std::vector<int> &memoryTypes); |
| virtual ~ImageAllocator(); |
| virtual void allocate(Context &context); |
| virtual void deallocate(Context &context); |
| virtual size_t getSize(Context &context); |
| |
| private: |
| bool m_dedicated; |
| bool m_linear; |
| Move<vk::VkImage> m_image; |
| tcu::IVec2 m_size; |
| vk::VkFormat m_colorFormat; |
| de::MovePtr<Allocation> m_imageAlloc; |
| int m_memoryType; |
| }; |
| |
| ImageAllocator::ImageAllocator(deRandom &random, bool dedicated, std::vector<int> &linearformats, |
| std::vector<int> &optimalformats, std::vector<int> &memoryTypes) |
| { |
| // If dedicated allocation is supported, pick it randomly |
| m_dedicated = dedicated && deRandom_getBool(&random); |
| // If linear formats are supported, pick it randomly |
| m_linear = (linearformats.size() > 0) && deRandom_getBool(&random); |
| |
| if (m_linear) |
| m_colorFormat = (VkFormat)linearformats[deRandom_getUint32(&random) % linearformats.size()]; |
| else |
| m_colorFormat = (VkFormat)optimalformats[deRandom_getUint32(&random) % optimalformats.size()]; |
| |
| int widthAlignment = (isYCbCr420Format(m_colorFormat) || isYCbCr422Format(m_colorFormat)) ? 2 : 1; |
| int heightAlignment = isYCbCr420Format(m_colorFormat) ? 2 : 1; |
| |
| // Random small size for causing potential alignment issues |
| m_size = tcu::IVec2((deRandom_getUint32(&random) % 16 + 3) & ~(widthAlignment - 1), |
| (deRandom_getUint32(&random) % 16 + 3) & ~(heightAlignment - 1)); |
| // Pick random memory type from the supported set |
| m_memoryType = memoryTypes[deRandom_getUint32(&random) % memoryTypes.size()]; |
| } |
| |
| ImageAllocator::~ImageAllocator() |
| { |
| } |
| |
| void ImageAllocator::allocate(Context &context) |
| { |
| Allocator &memAlloc = context.getDefaultAllocator(); |
| de::MovePtr<IImageAllocator> allocator; |
| MemoryRequirement requirement = legalMemoryTypes[m_memoryType]; |
| |
| if (m_dedicated) |
| allocator = de::MovePtr<IImageAllocator>(new ImageDedicatedAllocation); |
| else |
| allocator = de::MovePtr<IImageAllocator>(new ImageSuballocation); |
| |
| allocator->createTestImage(m_size, m_colorFormat, context, memAlloc, m_image, requirement, m_imageAlloc, |
| m_linear ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL); |
| } |
| |
| void ImageAllocator::deallocate(Context &context) |
| { |
| const DeviceInterface &vk = context.getDeviceInterface(); |
| const VkDevice &device = context.getDevice(); |
| |
| vk.destroyImage(device, m_image.disown(), DE_NULL); |
| m_imageAlloc.clear(); |
| } |
| |
| size_t ImageAllocator::getSize(Context &context) |
| { |
| const DeviceInterface &vk = context.getDeviceInterface(); |
| const VkDevice &device = context.getDevice(); |
| VkMemoryRequirements memReq; |
| |
| vk.getImageMemoryRequirements(device, *m_image, &memReq); |
| |
| return (size_t)memReq.size; |
| } |
| |
| class InvarianceInstance : public vkt::TestInstance |
| { |
| public: |
| InvarianceInstance(Context &context, const uint32_t seed); |
| virtual ~InvarianceInstance(void); |
| virtual tcu::TestStatus iterate(void); |
| |
| private: |
| deRandom m_random; |
| }; |
| |
| InvarianceInstance::InvarianceInstance(Context &context, const uint32_t seed) : vkt::TestInstance(context) |
| { |
| deRandom_init(&m_random, seed); |
| } |
| |
| InvarianceInstance::~InvarianceInstance(void) |
| { |
| } |
| |
| tcu::TestStatus InvarianceInstance::iterate(void) |
| { |
| de::MovePtr<IObjectAllocator> objs[testCycles]; |
| size_t refSizes[testCycles]; |
| unsigned int order[testCycles]; |
| bool supported[testCycles]; |
| bool allUnsupported = true; |
| bool success = true; |
| const bool isDedicatedAllocationSupported = m_context.isDeviceFunctionalitySupported("VK_KHR_dedicated_allocation"); |
| const bool isYcbcrSupported = m_context.isDeviceFunctionalitySupported("VK_KHR_sampler_ycbcr_conversion"); |
| const bool isYcbcrExtensionSupported = m_context.isDeviceFunctionalitySupported("VK_EXT_ycbcr_2plane_444_formats"); |
| std::vector<int> optimalFormats; |
| std::vector<int> linearFormats; |
| std::vector<int> memoryTypes; |
| vk::VkPhysicalDeviceMemoryProperties memProperties; |
| |
| // List of all VkFormat enums |
| const unsigned int formatlist[] = { |
| VK_FORMAT_UNDEFINED, |
| VK_FORMAT_R4G4_UNORM_PACK8, |
| VK_FORMAT_R4G4B4A4_UNORM_PACK16, |
| VK_FORMAT_B4G4R4A4_UNORM_PACK16, |
| VK_FORMAT_R5G6B5_UNORM_PACK16, |
| VK_FORMAT_B5G6R5_UNORM_PACK16, |
| VK_FORMAT_R5G5B5A1_UNORM_PACK16, |
| VK_FORMAT_B5G5R5A1_UNORM_PACK16, |
| VK_FORMAT_A1R5G5B5_UNORM_PACK16, |
| VK_FORMAT_R8_UNORM, |
| VK_FORMAT_R8_SNORM, |
| VK_FORMAT_R8_USCALED, |
| VK_FORMAT_R8_SSCALED, |
| VK_FORMAT_R8_UINT, |
| VK_FORMAT_R8_SINT, |
| VK_FORMAT_R8_SRGB, |
| VK_FORMAT_R8G8_UNORM, |
| VK_FORMAT_R8G8_SNORM, |
| VK_FORMAT_R8G8_USCALED, |
| VK_FORMAT_R8G8_SSCALED, |
| VK_FORMAT_R8G8_UINT, |
| VK_FORMAT_R8G8_SINT, |
| VK_FORMAT_R8G8_SRGB, |
| VK_FORMAT_R8G8B8_UNORM, |
| VK_FORMAT_R8G8B8_SNORM, |
| VK_FORMAT_R8G8B8_USCALED, |
| VK_FORMAT_R8G8B8_SSCALED, |
| VK_FORMAT_R8G8B8_UINT, |
| VK_FORMAT_R8G8B8_SINT, |
| VK_FORMAT_R8G8B8_SRGB, |
| VK_FORMAT_B8G8R8_UNORM, |
| VK_FORMAT_B8G8R8_SNORM, |
| VK_FORMAT_B8G8R8_USCALED, |
| VK_FORMAT_B8G8R8_SSCALED, |
| VK_FORMAT_B8G8R8_UINT, |
| VK_FORMAT_B8G8R8_SINT, |
| VK_FORMAT_B8G8R8_SRGB, |
| VK_FORMAT_R8G8B8A8_UNORM, |
| VK_FORMAT_R8G8B8A8_SNORM, |
| VK_FORMAT_R8G8B8A8_USCALED, |
| VK_FORMAT_R8G8B8A8_SSCALED, |
| VK_FORMAT_R8G8B8A8_UINT, |
| VK_FORMAT_R8G8B8A8_SINT, |
| VK_FORMAT_R8G8B8A8_SRGB, |
| VK_FORMAT_B8G8R8A8_UNORM, |
| VK_FORMAT_B8G8R8A8_SNORM, |
| VK_FORMAT_B8G8R8A8_USCALED, |
| VK_FORMAT_B8G8R8A8_SSCALED, |
| VK_FORMAT_B8G8R8A8_UINT, |
| VK_FORMAT_B8G8R8A8_SINT, |
| VK_FORMAT_B8G8R8A8_SRGB, |
| VK_FORMAT_A8B8G8R8_UNORM_PACK32, |
| VK_FORMAT_A8B8G8R8_SNORM_PACK32, |
| VK_FORMAT_A8B8G8R8_USCALED_PACK32, |
| VK_FORMAT_A8B8G8R8_SSCALED_PACK32, |
| VK_FORMAT_A8B8G8R8_UINT_PACK32, |
| VK_FORMAT_A8B8G8R8_SINT_PACK32, |
| VK_FORMAT_A8B8G8R8_SRGB_PACK32, |
| VK_FORMAT_A2R10G10B10_UNORM_PACK32, |
| VK_FORMAT_A2R10G10B10_SNORM_PACK32, |
| VK_FORMAT_A2R10G10B10_USCALED_PACK32, |
| VK_FORMAT_A2R10G10B10_SSCALED_PACK32, |
| VK_FORMAT_A2R10G10B10_UINT_PACK32, |
| VK_FORMAT_A2R10G10B10_SINT_PACK32, |
| VK_FORMAT_A2B10G10R10_UNORM_PACK32, |
| VK_FORMAT_A2B10G10R10_SNORM_PACK32, |
| VK_FORMAT_A2B10G10R10_USCALED_PACK32, |
| VK_FORMAT_A2B10G10R10_SSCALED_PACK32, |
| VK_FORMAT_A2B10G10R10_UINT_PACK32, |
| VK_FORMAT_A2B10G10R10_SINT_PACK32, |
| VK_FORMAT_R16_UNORM, |
| VK_FORMAT_R16_SNORM, |
| VK_FORMAT_R16_USCALED, |
| VK_FORMAT_R16_SSCALED, |
| VK_FORMAT_R16_UINT, |
| VK_FORMAT_R16_SINT, |
| VK_FORMAT_R16_SFLOAT, |
| VK_FORMAT_R16G16_UNORM, |
| VK_FORMAT_R16G16_SNORM, |
| VK_FORMAT_R16G16_USCALED, |
| VK_FORMAT_R16G16_SSCALED, |
| VK_FORMAT_R16G16_UINT, |
| VK_FORMAT_R16G16_SINT, |
| VK_FORMAT_R16G16_SFLOAT, |
| VK_FORMAT_R16G16B16_UNORM, |
| VK_FORMAT_R16G16B16_SNORM, |
| VK_FORMAT_R16G16B16_USCALED, |
| VK_FORMAT_R16G16B16_SSCALED, |
| VK_FORMAT_R16G16B16_UINT, |
| VK_FORMAT_R16G16B16_SINT, |
| VK_FORMAT_R16G16B16_SFLOAT, |
| VK_FORMAT_R16G16B16A16_UNORM, |
| VK_FORMAT_R16G16B16A16_SNORM, |
| VK_FORMAT_R16G16B16A16_USCALED, |
| VK_FORMAT_R16G16B16A16_SSCALED, |
| 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_R32G32B32_UINT, |
| VK_FORMAT_R32G32B32_SINT, |
| VK_FORMAT_R32G32B32_SFLOAT, |
| VK_FORMAT_R32G32B32A32_UINT, |
| VK_FORMAT_R32G32B32A32_SINT, |
| VK_FORMAT_R32G32B32A32_SFLOAT, |
| VK_FORMAT_R64_UINT, |
| VK_FORMAT_R64_SINT, |
| VK_FORMAT_R64_SFLOAT, |
| VK_FORMAT_R64G64_UINT, |
| VK_FORMAT_R64G64_SINT, |
| VK_FORMAT_R64G64_SFLOAT, |
| VK_FORMAT_R64G64B64_UINT, |
| VK_FORMAT_R64G64B64_SINT, |
| VK_FORMAT_R64G64B64_SFLOAT, |
| VK_FORMAT_R64G64B64A64_UINT, |
| VK_FORMAT_R64G64B64A64_SINT, |
| VK_FORMAT_R64G64B64A64_SFLOAT, |
| VK_FORMAT_B10G11R11_UFLOAT_PACK32, |
| VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, |
| VK_FORMAT_D16_UNORM, |
| VK_FORMAT_X8_D24_UNORM_PACK32, |
| VK_FORMAT_D32_SFLOAT, |
| VK_FORMAT_S8_UINT, |
| VK_FORMAT_D16_UNORM_S8_UINT, |
| VK_FORMAT_D24_UNORM_S8_UINT, |
| VK_FORMAT_D32_SFLOAT_S8_UINT, |
| VK_FORMAT_BC1_RGB_UNORM_BLOCK, |
| VK_FORMAT_BC1_RGB_SRGB_BLOCK, |
| VK_FORMAT_BC1_RGBA_UNORM_BLOCK, |
| VK_FORMAT_BC1_RGBA_SRGB_BLOCK, |
| VK_FORMAT_BC2_UNORM_BLOCK, |
| VK_FORMAT_BC2_SRGB_BLOCK, |
| VK_FORMAT_BC3_UNORM_BLOCK, |
| VK_FORMAT_BC3_SRGB_BLOCK, |
| VK_FORMAT_BC4_UNORM_BLOCK, |
| VK_FORMAT_BC4_SNORM_BLOCK, |
| VK_FORMAT_BC5_UNORM_BLOCK, |
| VK_FORMAT_BC5_SNORM_BLOCK, |
| VK_FORMAT_BC6H_UFLOAT_BLOCK, |
| VK_FORMAT_BC6H_SFLOAT_BLOCK, |
| VK_FORMAT_BC7_UNORM_BLOCK, |
| VK_FORMAT_BC7_SRGB_BLOCK, |
| VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, |
| VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK, |
| VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, |
| VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK, |
| VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, |
| VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK, |
| VK_FORMAT_EAC_R11_UNORM_BLOCK, |
| VK_FORMAT_EAC_R11_SNORM_BLOCK, |
| VK_FORMAT_EAC_R11G11_UNORM_BLOCK, |
| VK_FORMAT_EAC_R11G11_SNORM_BLOCK, |
| VK_FORMAT_ASTC_4x4_UNORM_BLOCK, |
| VK_FORMAT_ASTC_4x4_SRGB_BLOCK, |
| VK_FORMAT_ASTC_5x4_UNORM_BLOCK, |
| VK_FORMAT_ASTC_5x4_SRGB_BLOCK, |
| VK_FORMAT_ASTC_5x5_UNORM_BLOCK, |
| VK_FORMAT_ASTC_5x5_SRGB_BLOCK, |
| VK_FORMAT_ASTC_6x5_UNORM_BLOCK, |
| VK_FORMAT_ASTC_6x5_SRGB_BLOCK, |
| VK_FORMAT_ASTC_6x6_UNORM_BLOCK, |
| VK_FORMAT_ASTC_6x6_SRGB_BLOCK, |
| VK_FORMAT_ASTC_8x5_UNORM_BLOCK, |
| VK_FORMAT_ASTC_8x5_SRGB_BLOCK, |
| VK_FORMAT_ASTC_8x6_UNORM_BLOCK, |
| VK_FORMAT_ASTC_8x6_SRGB_BLOCK, |
| VK_FORMAT_ASTC_8x8_UNORM_BLOCK, |
| VK_FORMAT_ASTC_8x8_SRGB_BLOCK, |
| VK_FORMAT_ASTC_10x5_UNORM_BLOCK, |
| VK_FORMAT_ASTC_10x5_SRGB_BLOCK, |
| VK_FORMAT_ASTC_10x6_UNORM_BLOCK, |
| VK_FORMAT_ASTC_10x6_SRGB_BLOCK, |
| VK_FORMAT_ASTC_10x8_UNORM_BLOCK, |
| VK_FORMAT_ASTC_10x8_SRGB_BLOCK, |
| VK_FORMAT_ASTC_10x10_UNORM_BLOCK, |
| VK_FORMAT_ASTC_10x10_SRGB_BLOCK, |
| VK_FORMAT_ASTC_12x10_UNORM_BLOCK, |
| VK_FORMAT_ASTC_12x10_SRGB_BLOCK, |
| VK_FORMAT_ASTC_12x12_UNORM_BLOCK, |
| VK_FORMAT_ASTC_12x12_SRGB_BLOCK, |
| VK_FORMAT_G8B8G8R8_422_UNORM, |
| VK_FORMAT_B8G8R8G8_422_UNORM, |
| VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, |
| VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, |
| VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM, |
| VK_FORMAT_G8_B8R8_2PLANE_422_UNORM, |
| VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM, |
| VK_FORMAT_R10X6_UNORM_PACK16, |
| VK_FORMAT_R10X6G10X6_UNORM_2PACK16, |
| VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16, |
| VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16, |
| VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16, |
| VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, |
| VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, |
| VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16, |
| VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, |
| VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16, |
| VK_FORMAT_R12X4_UNORM_PACK16, |
| VK_FORMAT_R12X4G12X4_UNORM_2PACK16, |
| VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16, |
| VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16, |
| VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16, |
| VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16, |
| VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, |
| VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16, |
| VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16, |
| VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16, |
| VK_FORMAT_G16B16G16R16_422_UNORM, |
| VK_FORMAT_B16G16R16G16_422_UNORM, |
| VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, |
| VK_FORMAT_G16_B16R16_2PLANE_420_UNORM, |
| VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, |
| VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, |
| VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, |
| VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, |
| VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG, |
| VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG, |
| VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG, |
| VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG, |
| VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG, |
| VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG, |
| VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG, |
| VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT, |
| VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT, |
| VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT, |
| VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT, |
| VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT, |
| VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT, |
| }; |
| int formatCount = (int)(sizeof(formatlist) / sizeof(unsigned int)); |
| |
| // Find supported image formats |
| for (int i = 0; i < formatCount; i++) |
| { |
| if (isYCbCrFormat((VkFormat)formatlist[i]) && !isYcbcrSupported) |
| continue; |
| |
| if (isYCbCrExtensionFormat((VkFormat)formatlist[i]) && !isYcbcrExtensionSupported) |
| continue; |
| |
| vk::VkImageFormatProperties imageformatprops; |
| |
| // Check for support in linear tiling mode |
| if (m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties( |
| m_context.getPhysicalDevice(), (VkFormat)formatlist[i], VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_LINEAR, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 0, &imageformatprops) == VK_SUCCESS) |
| linearFormats.push_back(formatlist[i]); |
| |
| // Check for support in optimal tiling mode |
| if (m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties( |
| m_context.getPhysicalDevice(), (VkFormat)formatlist[i], VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, |
| VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0, |
| &imageformatprops) == VK_SUCCESS) |
| optimalFormats.push_back(formatlist[i]); |
| } |
| |
| // Check for supported heap types |
| m_context.getInstanceInterface().getPhysicalDeviceMemoryProperties(m_context.getPhysicalDevice(), &memProperties); |
| |
| for (unsigned int j = 0; j < legalMemoryTypeCount; j++) |
| { |
| bool found = false; |
| for (unsigned int i = 0; !found && i < memProperties.memoryTypeCount; i++) |
| { |
| if (legalMemoryTypes[j].matchesHeap(memProperties.memoryTypes[i].propertyFlags)) |
| { |
| memoryTypes.push_back(j); |
| found = true; |
| } |
| } |
| } |
| |
| // Log the used image types and heap types |
| tcu::TestLog &log = m_context.getTestContext().getLog(); |
| |
| { |
| std::ostringstream values; |
| for (unsigned int i = 0; i < linearFormats.size(); i++) |
| values << " " << linearFormats[i]; |
| log << tcu::TestLog::Message << "Using linear formats:" << values.str() << tcu::TestLog::EndMessage; |
| } |
| |
| { |
| std::ostringstream values; |
| for (unsigned int i = 0; i < optimalFormats.size(); i++) |
| values << " " << optimalFormats[i]; |
| log << tcu::TestLog::Message << "Using optimal formats:" << values.str() << tcu::TestLog::EndMessage; |
| } |
| |
| { |
| std::ostringstream values; |
| for (unsigned int i = 0; i < memoryTypes.size(); i++) |
| values << " " << memoryTypes[i]; |
| log << tcu::TestLog::Message << "Using memory types:" << values.str() << tcu::TestLog::EndMessage; |
| } |
| |
| for (unsigned int i = 0; i < testCycles; i++) |
| { |
| if (deRandom_getBool(&m_random)) |
| objs[i] = de::MovePtr<IObjectAllocator>( |
| new BufferAllocator(m_random, isDedicatedAllocationSupported, memoryTypes)); |
| else |
| objs[i] = de::MovePtr<IObjectAllocator>(new ImageAllocator(m_random, isDedicatedAllocationSupported, |
| linearFormats, optimalFormats, memoryTypes)); |
| order[i] = i; |
| } |
| |
| // First get reference values for the object sizes |
| for (unsigned int i = 0; i < testCycles; i++) |
| { |
| try |
| { |
| objs[i]->allocate(m_context); |
| refSizes[i] = objs[i]->getSize(m_context); |
| objs[i]->deallocate(m_context); |
| supported[i] = true; |
| allUnsupported = false; |
| } |
| catch (const tcu::NotSupportedError &) |
| { |
| supported[i] = false; |
| } |
| } |
| |
| if (allUnsupported) |
| TCU_THROW(NotSupportedError, "All allocations unsupported"); |
| |
| // Shuffle order by swapping random pairs |
| for (unsigned int i = 0; i < testCycles; i++) |
| { |
| int a = deRandom_getUint32(&m_random) % testCycles; |
| int b = deRandom_getUint32(&m_random) % testCycles; |
| std::swap(order[a], order[b]); |
| } |
| |
| // Allocate objects in shuffled order |
| for (unsigned int i = 0; i < testCycles; i++) |
| { |
| if (supported[order[i]]) |
| objs[order[i]]->allocate(m_context); |
| } |
| |
| // Check for size mismatches |
| for (unsigned int i = 0; i < testCycles; i++) |
| { |
| if (!supported[order[i]]) |
| continue; |
| |
| size_t val = objs[order[i]]->getSize(m_context); |
| |
| if (val != refSizes[order[i]]) |
| { |
| success = false; |
| log << tcu::TestLog::Message << "Object " << order[i] << " size mismatch (" << val |
| << " != " << refSizes[order[i]] << ")" << tcu::TestLog::EndMessage; |
| } |
| } |
| |
| // Clean up |
| for (unsigned int i = 0; i < testCycles; i++) |
| { |
| if (supported[order[i]]) |
| objs[order[i]]->deallocate(m_context); |
| } |
| |
| if (success) |
| return tcu::TestStatus::pass("Pass"); |
| |
| return tcu::TestStatus::fail("One or more allocation is not invariant"); |
| } |
| |
| class AlignmentMatchingInstance : public vkt::TestInstance |
| { |
| public: |
| AlignmentMatchingInstance(Context &context); |
| virtual ~AlignmentMatchingInstance(void) = default; |
| virtual tcu::TestStatus iterate(void); |
| }; |
| |
| AlignmentMatchingInstance::AlignmentMatchingInstance(Context &context) : vkt::TestInstance(context) |
| { |
| } |
| |
| tcu::TestStatus AlignmentMatchingInstance::iterate(void) |
| { |
| const VkDevice device = m_context.getDevice(); |
| const DeviceInterface &vk = m_context.getDeviceInterface(); |
| const uint32_t objectsCount = 5; |
| tcu::TestLog &log = m_context.getTestContext().getLog(); |
| bool success = true; |
| VkExtent3D baseExtent = {32, 31, 1}; |
| VkDeviceSize baseSize = 1023; |
| |
| VkImageCreateInfo imageCreateInfo{ |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkImageCreateFlags flags; |
| VK_IMAGE_TYPE_2D, // VkImageType imageType; |
| VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format; |
| baseExtent, // VkExtent3D extent; |
| 1u, // uint32_t mipLevels; |
| 1u, // uint32_t arraySize; |
| VK_SAMPLE_COUNT_1_BIT, // uint32_t samples; |
| VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 0u, // uint32_t queueFamilyCount; |
| DE_NULL, // const uint32_t* pQueueFamilyIndices; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; |
| }; |
| |
| VkBufferCreateInfo bufferCreateInfo{ |
| VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| 0u, // VkBufferCreateFlags flags |
| baseSize, // VkDeviceSize size |
| VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode |
| 0u, // uint32_t queueFamilyIndexCount |
| DE_NULL // const uint32_t* pQueueFamilyIndices |
| }; |
| |
| Move<VkImage> baseImage = createImage(vk, device, &imageCreateInfo); |
| Move<VkBuffer> baseBuffer = createBuffer(vk, device, &bufferCreateInfo); |
| |
| VkMemoryRequirements baseImageRequirements = getImageMemoryRequirements(vk, device, *baseImage); |
| VkMemoryRequirements baseBufferRequirements = getBufferMemoryRequirements(vk, device, *baseBuffer); |
| |
| // Create a bunch of VkBuffer and VkImage objects with the same |
| // create infos and make sure their alignments all match. |
| { |
| std::vector<Move<VkImage>> images(objectsCount); |
| std::vector<Move<VkBuffer>> buffers(objectsCount); |
| |
| for (uint32_t idx = 0; idx < objectsCount; ++idx) |
| { |
| images[idx] = createImage(vk, device, &imageCreateInfo); |
| buffers[idx] = createBuffer(vk, device, &bufferCreateInfo); |
| |
| VkMemoryRequirements imageRequirements = getImageMemoryRequirements(vk, device, *images[idx]); |
| VkMemoryRequirements buffersRequirements = getBufferMemoryRequirements(vk, device, *buffers[idx]); |
| |
| if (baseImageRequirements.alignment != imageRequirements.alignment) |
| { |
| success = false; |
| log << tcu::TestLog::Message |
| << "Alignments for all VkImage objects created with the same create infos should match\n" |
| << tcu::TestLog::EndMessage; |
| } |
| if (baseBufferRequirements.alignment != buffersRequirements.alignment) |
| { |
| success = false; |
| log << tcu::TestLog::Message |
| << "Alignments for all VkBuffer objects created with the same create infos should match\n" |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| } |
| |
| if (m_context.isDeviceFunctionalitySupported("VK_KHR_get_memory_requirements2")) |
| { |
| VkBufferMemoryRequirementsInfo2 bufferMemoryRequirementsInfo{ |
| VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| *baseBuffer // VkBuffer buffer |
| }; |
| VkImageMemoryRequirementsInfo2 imageMemoryRequirementsInfo{ |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| *baseImage // VkImage image |
| }; |
| std::vector<VkMemoryRequirements2> requirements2( |
| 2, |
| { |
| VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR, // VkStructureType sType |
| DE_NULL, // void* pNext |
| {0, 0, 0} // VkMemoryRequirements memoryRequirements |
| }); |
| |
| auto areRequirementsTheSame = [](VkMemoryRequirements2 &a, VkMemoryRequirements2 &b) |
| { |
| return ((a.memoryRequirements.size == b.memoryRequirements.size) && |
| (a.memoryRequirements.alignment == b.memoryRequirements.alignment) && |
| (a.memoryRequirements.memoryTypeBits == b.memoryRequirements.memoryTypeBits)); |
| }; |
| |
| // The memory requirements returned by vkGetBufferCreateInfoMemoryRequirementsKHR are identical to those that |
| // would be returned by vkGetBufferMemoryRequirements2 if it were called with a VkBuffer created with the same |
| // VkBufferCreateInfo values. |
| vk.getBufferMemoryRequirements2(device, &bufferMemoryRequirementsInfo, &requirements2[0]); |
| const VkDeviceBufferMemoryRequirementsKHR bufferMemInfo = { |
| VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS_KHR, DE_NULL, &bufferCreateInfo}; |
| vk.getDeviceBufferMemoryRequirementsKHR(device, &bufferMemInfo, &requirements2[1]); |
| |
| if (!areRequirementsTheSame(requirements2[0], requirements2[1])) |
| { |
| success = false; |
| log << tcu::TestLog::Message |
| << "vkGetDeviceBufferMemoryRequirementsKHR and vkGetBufferMemoryRequirements2\n" |
| "report diferent memory requirements\n" |
| << tcu::TestLog::EndMessage; |
| } |
| |
| // Similarly, vkGetImageCreateInfoMemoryRequirementsKHR will report the same memory requirements as |
| // vkGetImageMemoryRequirements2 would if called with a VkImage created with the supplied VkImageCreateInfo |
| vk.getImageMemoryRequirements2(device, &imageMemoryRequirementsInfo, &requirements2[0]); |
| const VkDeviceImageMemoryRequirementsKHR imageMemInfo = {VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS_KHR, |
| DE_NULL, &imageCreateInfo, |
| vk::VkImageAspectFlagBits(0)}; |
| vk.getDeviceImageMemoryRequirementsKHR(device, &imageMemInfo, &requirements2[1]); |
| |
| if (!areRequirementsTheSame(requirements2[0], requirements2[1])) |
| { |
| success = false; |
| log << tcu::TestLog::Message |
| << "vkGetDeviceImageMemoryRequirementsKHR and vkGetImageMemoryRequirements2\n" |
| "report diferent memory requirements\n" |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| |
| // For a VkImage, the size memory requirement is never greater than that of another VkImage created with |
| // a greater or equal extent dimension specified in VkImageCreateInfo, all other creation parameters being identical. |
| // For a VkBuffer, the size memory requirement is never greater than that of another VkBuffer created with |
| // a greater or equal size specified in VkBufferCreateInfo, all other creation parameters being identical. |
| { |
| std::vector<Move<VkImage>> images(objectsCount); |
| std::vector<Move<VkBuffer>> buffers(objectsCount); |
| |
| for (uint32_t idx = 0; idx < objectsCount; ++idx) |
| { |
| imageCreateInfo.extent = {baseExtent.width + (idx % 2) * idx, baseExtent.height + idx, 1u}; |
| bufferCreateInfo.size = baseSize + idx; |
| |
| images[idx] = createImage(vk, device, &imageCreateInfo); |
| buffers[idx] = createBuffer(vk, device, &bufferCreateInfo); |
| |
| VkMemoryRequirements imageRequirements = getImageMemoryRequirements(vk, device, *images[idx]); |
| VkMemoryRequirements buffersRequirements = getBufferMemoryRequirements(vk, device, *buffers[idx]); |
| |
| if (baseImageRequirements.size > imageRequirements.size) |
| { |
| success = false; |
| log << tcu::TestLog::Message |
| << "Size memory requiremen for VkImage should never be greater than that of another VkImage\n" |
| "created with a greater or equal extent dimension specified in VkImageCreateInfo when all\n" |
| "other creation parameters are identical\n" |
| << tcu::TestLog::EndMessage; |
| } |
| if (baseBufferRequirements.size > buffersRequirements.size) |
| { |
| success = false; |
| log << tcu::TestLog::Message |
| << "Size memory requiremen for VkBuffer should never be greater than that of another VkBuffer\n" |
| "created with a greater or size specified in VkImageCreateInfo when all\n" |
| "other creation parameters are identical\n" |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| } |
| |
| if (success) |
| return tcu::TestStatus::pass("Pass"); |
| |
| return tcu::TestStatus::fail("Fail"); |
| } |
| |
| enum TestType |
| { |
| TT_BASIC_INVARIANCE = 0, |
| TT_REQUIREMENTS_MATCHING |
| }; |
| |
| class InvarianceCase : public vkt::TestCase |
| { |
| public: |
| InvarianceCase(tcu::TestContext &testCtx, const std::string &name, const std::string &description, |
| TestType testType); |
| virtual ~InvarianceCase(void) = default; |
| |
| virtual TestInstance *createInstance(Context &context) const; |
| virtual void checkSupport(Context &context) const; |
| |
| protected: |
| TestType m_testType; |
| }; |
| |
| InvarianceCase::InvarianceCase(tcu::TestContext &testCtx, const std::string &name, const std::string &description, |
| TestType testType) |
| : vkt::TestCase(testCtx, name, description) |
| , m_testType(testType) |
| { |
| } |
| |
| TestInstance *InvarianceCase::createInstance(Context &context) const |
| { |
| if (TT_REQUIREMENTS_MATCHING == m_testType) |
| return new AlignmentMatchingInstance(context); |
| |
| return new InvarianceInstance(context, 0x600613); |
| } |
| |
| void InvarianceCase::checkSupport(Context &context) const |
| { |
| if (TT_REQUIREMENTS_MATCHING == m_testType) |
| context.requireDeviceFunctionality("VK_KHR_maintenance4"); |
| } |
| |
| tcu::TestCaseGroup *createMemoryRequirementInvarianceTests(tcu::TestContext &testCtx) |
| { |
| de::MovePtr<tcu::TestCaseGroup> invarianceTests( |
| new tcu::TestCaseGroup(testCtx, "invariance", "Memory requirement invariance tests")); |
| |
| invarianceTests->addChild(new InvarianceCase(testCtx, "random", "Random case", TT_BASIC_INVARIANCE)); |
| invarianceTests->addChild(new InvarianceCase(testCtx, "memory_requirements_matching", "VK_KHR_maintenance4 case", |
| TT_REQUIREMENTS_MATCHING)); |
| |
| return invarianceTests.release(); |
| } |
| |
| } // namespace api |
| } // namespace vkt |