| /*------------------------------------------------------------------------ |
| * Vulkan Conformance Tests |
| * ------------------------ |
| * |
| * Copyright (c) 2017 Google 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 YCbCr format copy tests |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vktYCbCrCopyTests.hpp" |
| |
| #include "vktTestCaseUtil.hpp" |
| #include "vktTestGroupUtil.hpp" |
| #include "vktYCbCrUtil.hpp" |
| |
| #include "vkQueryUtil.hpp" |
| #include "vkRefUtil.hpp" |
| #include "vkTypeUtil.hpp" |
| #include "vkCmdUtil.hpp" |
| |
| #include "tcuSeedBuilder.hpp" |
| #include "tcuTestLog.hpp" |
| #include "tcuVector.hpp" |
| #include "tcuVectorUtil.hpp" |
| |
| #include "deRandom.hpp" |
| #include "deSTLUtil.hpp" |
| #include "deStringUtil.hpp" |
| |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| using tcu::UVec2; |
| using tcu::Vec4; |
| using tcu::TestLog; |
| |
| using std::string; |
| using std::vector; |
| using std::pair; |
| |
| namespace vkt |
| { |
| namespace ycbcr |
| { |
| namespace |
| { |
| |
| struct ImageConfig |
| { |
| ImageConfig (vk::VkFormat format_, |
| vk::VkImageTiling tiling_, |
| bool disjoint_, |
| const UVec2& size_) |
| : format (format_) |
| , tiling (tiling_) |
| , disjoint (disjoint_) |
| , size (size_) |
| { |
| } |
| |
| vk::VkFormat format; |
| vk::VkImageTiling tiling; |
| bool disjoint; |
| UVec2 size; |
| }; |
| |
| struct TestConfig |
| { |
| TestConfig (const ImageConfig& src_, |
| const ImageConfig& dst_) |
| : src (src_) |
| , dst (dst_) |
| { |
| } |
| |
| ImageConfig src; |
| ImageConfig dst; |
| }; |
| |
| void checkFormatSupport(Context& context, const ImageConfig& config) |
| { |
| try |
| { |
| const vk::VkFormatProperties properties (vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), config.format)); |
| const vk::VkFormatFeatureFlags features (config.tiling == vk::VK_IMAGE_TILING_OPTIMAL |
| ? properties.optimalTilingFeatures |
| : properties.linearTilingFeatures); |
| |
| if ((features & vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0 |
| && (features & vk::VK_FORMAT_FEATURE_TRANSFER_DST_BIT) == 0) |
| { |
| TCU_THROW(NotSupportedError, "Format doesn't support copies"); |
| } |
| |
| if (config.disjoint && ((features & vk::VK_FORMAT_FEATURE_DISJOINT_BIT) == 0)) |
| TCU_THROW(NotSupportedError, "Format doesn't support disjoint planes"); |
| } |
| catch (const vk::Error& err) |
| { |
| if (err.getError() == vk::VK_ERROR_FORMAT_NOT_SUPPORTED) |
| TCU_THROW(NotSupportedError, "Format not supported"); |
| |
| throw; |
| } |
| } |
| |
| void checkSupport (Context& context, const TestConfig config) |
| { |
| const vk::VkPhysicalDeviceLimits limits = context.getDeviceProperties().limits; |
| |
| if (config.src.size.x() > limits.maxImageDimension2D || config.src.size.y() > limits.maxImageDimension2D |
| || config.dst.size.x() > limits.maxImageDimension2D || config.dst.size.y() > limits.maxImageDimension2D) |
| { |
| TCU_THROW(NotSupportedError, "Requested image dimensions not supported"); |
| } |
| |
| if (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), string("VK_KHR_sampler_ycbcr_conversion"))) |
| TCU_THROW(NotSupportedError, "Extension VK_KHR_sampler_ycbcr_conversion not supported"); |
| |
| checkFormatSupport(context, config.src); |
| checkFormatSupport(context, config.dst); |
| } |
| |
| vk::Move<vk::VkImage> createImage (const vk::DeviceInterface& vkd, |
| vk::VkDevice device, |
| vk::VkFormat format, |
| const UVec2& size, |
| bool disjoint, |
| vk::VkImageTiling tiling) |
| { |
| const vk::VkImageCreateInfo createInfo = |
| { |
| vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, |
| DE_NULL, |
| disjoint ? (vk::VkImageCreateFlags)vk::VK_IMAGE_CREATE_DISJOINT_BIT : (vk::VkImageCreateFlags)0u, |
| |
| vk::VK_IMAGE_TYPE_2D, |
| format, |
| vk::makeExtent3D(size.x(), size.y(), 1u), |
| 1u, |
| 1u, |
| vk::VK_SAMPLE_COUNT_1_BIT, |
| tiling, |
| vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT, |
| vk::VK_SHARING_MODE_EXCLUSIVE, |
| 0u, |
| (const deUint32*)DE_NULL, |
| tiling == vk::VK_IMAGE_TILING_LINEAR ? vk::VK_IMAGE_LAYOUT_PREINITIALIZED : vk::VK_IMAGE_LAYOUT_UNDEFINED, |
| }; |
| |
| return vk::createImage(vkd, device, &createInfo); |
| } |
| |
| bool isCompatible (vk::VkFormat srcFormat, |
| vk::VkFormat dstFormat) |
| { |
| if (srcFormat == dstFormat) |
| return true; |
| else |
| { |
| const vk::VkFormat class8Bit[] = |
| { |
| vk::VK_FORMAT_R4G4_UNORM_PACK8, |
| vk::VK_FORMAT_R8_UNORM, |
| vk::VK_FORMAT_R8_SNORM, |
| vk::VK_FORMAT_R8_USCALED, |
| vk::VK_FORMAT_R8_SSCALED, |
| vk::VK_FORMAT_R8_UINT, |
| vk::VK_FORMAT_R8_SINT, |
| vk::VK_FORMAT_R8_SRGB |
| }; |
| const vk::VkFormat class16Bit[] = |
| { |
| vk::VK_FORMAT_R4G4B4A4_UNORM_PACK16, |
| vk::VK_FORMAT_B4G4R4A4_UNORM_PACK16, |
| vk::VK_FORMAT_R5G6B5_UNORM_PACK16, |
| vk::VK_FORMAT_B5G6R5_UNORM_PACK16, |
| vk::VK_FORMAT_R5G5B5A1_UNORM_PACK16, |
| vk::VK_FORMAT_B5G5R5A1_UNORM_PACK16, |
| vk::VK_FORMAT_A1R5G5B5_UNORM_PACK16, |
| vk::VK_FORMAT_R8G8_UNORM, |
| vk::VK_FORMAT_R8G8_SNORM, |
| vk::VK_FORMAT_R8G8_USCALED, |
| vk::VK_FORMAT_R8G8_SSCALED, |
| vk::VK_FORMAT_R8G8_UINT, |
| vk::VK_FORMAT_R8G8_SINT, |
| vk::VK_FORMAT_R8G8_SRGB, |
| vk::VK_FORMAT_R16_UNORM, |
| vk::VK_FORMAT_R16_SNORM, |
| vk::VK_FORMAT_R16_USCALED, |
| vk::VK_FORMAT_R16_SSCALED, |
| vk::VK_FORMAT_R16_UINT, |
| vk::VK_FORMAT_R16_SINT, |
| vk::VK_FORMAT_R16_SFLOAT, |
| vk::VK_FORMAT_R10X6_UNORM_PACK16, |
| vk::VK_FORMAT_R12X4_UNORM_PACK16 |
| }; |
| const vk::VkFormat class24Bit[] = |
| { |
| vk::VK_FORMAT_R8G8B8_UNORM, |
| vk::VK_FORMAT_R8G8B8_SNORM, |
| vk::VK_FORMAT_R8G8B8_USCALED, |
| vk::VK_FORMAT_R8G8B8_SSCALED, |
| vk::VK_FORMAT_R8G8B8_UINT, |
| vk::VK_FORMAT_R8G8B8_SINT, |
| vk::VK_FORMAT_R8G8B8_SRGB, |
| vk::VK_FORMAT_B8G8R8_UNORM, |
| vk::VK_FORMAT_B8G8R8_SNORM, |
| vk::VK_FORMAT_B8G8R8_USCALED, |
| vk::VK_FORMAT_B8G8R8_SSCALED, |
| vk::VK_FORMAT_B8G8R8_UINT, |
| vk::VK_FORMAT_B8G8R8_SINT, |
| vk::VK_FORMAT_B8G8R8_SRGB |
| }; |
| const vk::VkFormat class32Bit[] = |
| { |
| vk::VK_FORMAT_R8G8B8A8_UNORM, |
| vk::VK_FORMAT_R8G8B8A8_SNORM, |
| vk::VK_FORMAT_R8G8B8A8_USCALED, |
| vk::VK_FORMAT_R8G8B8A8_SSCALED, |
| vk::VK_FORMAT_R8G8B8A8_UINT, |
| vk::VK_FORMAT_R8G8B8A8_SINT, |
| vk::VK_FORMAT_R8G8B8A8_SRGB, |
| vk::VK_FORMAT_B8G8R8A8_UNORM, |
| vk::VK_FORMAT_B8G8R8A8_SNORM, |
| vk::VK_FORMAT_B8G8R8A8_USCALED, |
| vk::VK_FORMAT_B8G8R8A8_SSCALED, |
| vk::VK_FORMAT_B8G8R8A8_UINT, |
| vk::VK_FORMAT_B8G8R8A8_SINT, |
| vk::VK_FORMAT_B8G8R8A8_SRGB, |
| vk::VK_FORMAT_A8B8G8R8_UNORM_PACK32, |
| vk::VK_FORMAT_A8B8G8R8_SNORM_PACK32, |
| vk::VK_FORMAT_A8B8G8R8_USCALED_PACK32, |
| vk::VK_FORMAT_A8B8G8R8_SSCALED_PACK32, |
| vk::VK_FORMAT_A8B8G8R8_UINT_PACK32, |
| vk::VK_FORMAT_A8B8G8R8_SINT_PACK32, |
| vk::VK_FORMAT_A8B8G8R8_SRGB_PACK32, |
| vk::VK_FORMAT_A2R10G10B10_UNORM_PACK32, |
| vk::VK_FORMAT_A2R10G10B10_SNORM_PACK32, |
| vk::VK_FORMAT_A2R10G10B10_USCALED_PACK32, |
| vk::VK_FORMAT_A2R10G10B10_SSCALED_PACK32, |
| vk::VK_FORMAT_A2R10G10B10_UINT_PACK32, |
| vk::VK_FORMAT_A2R10G10B10_SINT_PACK32, |
| vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32, |
| vk::VK_FORMAT_A2B10G10R10_SNORM_PACK32, |
| vk::VK_FORMAT_A2B10G10R10_USCALED_PACK32, |
| vk::VK_FORMAT_A2B10G10R10_SSCALED_PACK32, |
| vk::VK_FORMAT_A2B10G10R10_UINT_PACK32, |
| vk::VK_FORMAT_A2B10G10R10_SINT_PACK32, |
| vk::VK_FORMAT_R16G16_UNORM, |
| vk::VK_FORMAT_R16G16_SNORM, |
| vk::VK_FORMAT_R16G16_USCALED, |
| vk::VK_FORMAT_R16G16_SSCALED, |
| vk::VK_FORMAT_R16G16_UINT, |
| vk::VK_FORMAT_R16G16_SINT, |
| vk::VK_FORMAT_R16G16_SFLOAT, |
| vk::VK_FORMAT_R32_UINT, |
| vk::VK_FORMAT_R32_SINT, |
| vk::VK_FORMAT_R32_SFLOAT, |
| vk::VK_FORMAT_B10G11R11_UFLOAT_PACK32, |
| vk::VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, |
| vk::VK_FORMAT_R10X6G10X6_UNORM_2PACK16, |
| vk::VK_FORMAT_R12X4G12X4_UNORM_2PACK16 |
| }; |
| const vk::VkFormat class48Bit[] = |
| { |
| vk::VK_FORMAT_R16G16B16_UNORM, |
| vk::VK_FORMAT_R16G16B16_SNORM, |
| vk::VK_FORMAT_R16G16B16_USCALED, |
| vk::VK_FORMAT_R16G16B16_SSCALED, |
| vk::VK_FORMAT_R16G16B16_UINT, |
| vk::VK_FORMAT_R16G16B16_SINT, |
| vk::VK_FORMAT_R16G16B16_SFLOAT |
| }; |
| const vk::VkFormat class64Bit[] = |
| { |
| vk::VK_FORMAT_R16G16B16A16_UNORM, |
| vk::VK_FORMAT_R16G16B16A16_SNORM, |
| vk::VK_FORMAT_R16G16B16A16_USCALED, |
| vk::VK_FORMAT_R16G16B16A16_SSCALED, |
| vk::VK_FORMAT_R16G16B16A16_UINT, |
| vk::VK_FORMAT_R16G16B16A16_SINT, |
| vk::VK_FORMAT_R16G16B16A16_SFLOAT, |
| vk::VK_FORMAT_R32G32_UINT, |
| vk::VK_FORMAT_R32G32_SINT, |
| vk::VK_FORMAT_R32G32_SFLOAT, |
| vk::VK_FORMAT_R64_UINT, |
| vk::VK_FORMAT_R64_SINT, |
| vk::VK_FORMAT_R64_SFLOAT |
| }; |
| const vk::VkFormat class96Bit[] = |
| { |
| vk::VK_FORMAT_R32G32B32_UINT, |
| vk::VK_FORMAT_R32G32B32_SINT, |
| vk::VK_FORMAT_R32G32B32_SFLOAT |
| }; |
| const vk::VkFormat class128Bit[] = |
| { |
| vk::VK_FORMAT_R32G32B32A32_UINT, |
| vk::VK_FORMAT_R32G32B32A32_SINT, |
| vk::VK_FORMAT_R32G32B32A32_SFLOAT, |
| vk::VK_FORMAT_R64G64_UINT, |
| vk::VK_FORMAT_R64G64_SINT, |
| vk::VK_FORMAT_R64G64_SFLOAT |
| }; |
| const vk::VkFormat class192Bit[] = |
| { |
| vk::VK_FORMAT_R64G64B64_UINT, |
| vk::VK_FORMAT_R64G64B64_SINT, |
| vk::VK_FORMAT_R64G64B64_SFLOAT |
| }; |
| const vk::VkFormat class256Bit[] = |
| { |
| vk::VK_FORMAT_R64G64B64A64_UINT, |
| vk::VK_FORMAT_R64G64B64A64_SINT, |
| vk::VK_FORMAT_R64G64B64A64_SFLOAT |
| }; |
| |
| if (de::contains(DE_ARRAY_BEGIN(class8Bit), DE_ARRAY_END(class8Bit), srcFormat) |
| && de::contains(DE_ARRAY_BEGIN(class8Bit), DE_ARRAY_END(class8Bit), dstFormat)) |
| return true; |
| |
| if (de::contains(DE_ARRAY_BEGIN(class16Bit), DE_ARRAY_END(class16Bit), srcFormat) |
| && de::contains(DE_ARRAY_BEGIN(class16Bit), DE_ARRAY_END(class16Bit), dstFormat)) |
| return true; |
| |
| if (de::contains(DE_ARRAY_BEGIN(class24Bit), DE_ARRAY_END(class24Bit), srcFormat) |
| && de::contains(DE_ARRAY_BEGIN(class24Bit), DE_ARRAY_END(class24Bit), dstFormat)) |
| return true; |
| |
| if (de::contains(DE_ARRAY_BEGIN(class32Bit), DE_ARRAY_END(class32Bit), srcFormat) |
| && de::contains(DE_ARRAY_BEGIN(class32Bit), DE_ARRAY_END(class32Bit), dstFormat)) |
| return true; |
| |
| if (de::contains(DE_ARRAY_BEGIN(class48Bit), DE_ARRAY_END(class48Bit), srcFormat) |
| && de::contains(DE_ARRAY_BEGIN(class48Bit), DE_ARRAY_END(class48Bit), dstFormat)) |
| return true; |
| |
| if (de::contains(DE_ARRAY_BEGIN(class64Bit), DE_ARRAY_END(class64Bit), srcFormat) |
| && de::contains(DE_ARRAY_BEGIN(class64Bit), DE_ARRAY_END(class64Bit), dstFormat)) |
| return true; |
| |
| if (de::contains(DE_ARRAY_BEGIN(class96Bit), DE_ARRAY_END(class96Bit), srcFormat) |
| && de::contains(DE_ARRAY_BEGIN(class96Bit), DE_ARRAY_END(class96Bit), dstFormat)) |
| return true; |
| |
| if (de::contains(DE_ARRAY_BEGIN(class128Bit), DE_ARRAY_END(class128Bit), srcFormat) |
| && de::contains(DE_ARRAY_BEGIN(class128Bit), DE_ARRAY_END(class128Bit), dstFormat)) |
| return true; |
| |
| if (de::contains(DE_ARRAY_BEGIN(class192Bit), DE_ARRAY_END(class192Bit), srcFormat) |
| && de::contains(DE_ARRAY_BEGIN(class192Bit), DE_ARRAY_END(class192Bit), dstFormat)) |
| return true; |
| |
| if (de::contains(DE_ARRAY_BEGIN(class256Bit), DE_ARRAY_END(class256Bit), srcFormat) |
| && de::contains(DE_ARRAY_BEGIN(class256Bit), DE_ARRAY_END(class256Bit), dstFormat)) |
| return true; |
| |
| return false; |
| } |
| } |
| |
| deUint32 getBlockByteSize (vk::VkFormat format) |
| { |
| switch (format) |
| { |
| case vk::VK_FORMAT_B8G8R8G8_422_UNORM: |
| case vk::VK_FORMAT_G8B8G8R8_422_UNORM: |
| return 4u; |
| |
| case vk::VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16: |
| case vk::VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16: |
| case vk::VK_FORMAT_B16G16R16G16_422_UNORM: |
| case vk::VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16: |
| case vk::VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16: |
| case vk::VK_FORMAT_G16B16G16R16_422_UNORM: |
| case vk::VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16: |
| case vk::VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16: |
| case vk::VK_FORMAT_R16G16B16A16_UNORM: |
| return 4u * 2u; |
| |
| case vk::VK_FORMAT_R10X6_UNORM_PACK16: |
| case vk::VK_FORMAT_R12X4_UNORM_PACK16: |
| return 2u; |
| |
| case vk::VK_FORMAT_R10X6G10X6_UNORM_2PACK16: |
| case vk::VK_FORMAT_R12X4G12X4_UNORM_2PACK16: |
| return 2u * 2u; |
| |
| case vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16: |
| case vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16: |
| return 3u * 2u; |
| |
| case vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16: |
| case vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16: |
| case vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16: |
| case vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16: |
| case vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16: |
| case vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16: |
| case vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16: |
| case vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16: |
| case vk::VK_FORMAT_G16_B16R16_2PLANE_420_UNORM: |
| case vk::VK_FORMAT_G16_B16R16_2PLANE_422_UNORM: |
| case vk::VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM: |
| case vk::VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM: |
| case vk::VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM: |
| case vk::VK_FORMAT_G8_B8R8_2PLANE_420_UNORM: |
| case vk::VK_FORMAT_G8_B8R8_2PLANE_422_UNORM: |
| case vk::VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM: |
| case vk::VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM: |
| case vk::VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM: |
| DE_FATAL("Plane formats not supported"); |
| return ~0u; |
| |
| default: |
| return (deUint32)vk::mapVkFormat(format).getPixelSize(); |
| } |
| } |
| |
| UVec2 randomUVec2 (de::Random& rng, |
| const UVec2& min, |
| const UVec2& max) |
| { |
| UVec2 result; |
| |
| result[0] = min[0] + (rng.getUint32() % (1 + max[0] - min[0])); |
| result[1] = min[1] + (rng.getUint32() % (1 + max[1] - min[1])); |
| |
| return result; |
| } |
| |
| void genCopies (de::Random& rng, |
| size_t copyCount, |
| vk::VkFormat srcFormat, |
| const UVec2& srcSize, |
| vk::VkFormat dstFormat, |
| const UVec2& dstSize, |
| vector<vk::VkImageCopy>* copies) |
| { |
| vector<pair<deUint32, deUint32> > pairs; |
| const vk::PlanarFormatDescription srcPlaneInfo (vk::getPlanarFormatDescription(srcFormat)); |
| const vk::PlanarFormatDescription dstPlaneInfo (vk::getPlanarFormatDescription(dstFormat)); |
| |
| for (deUint32 srcPlaneNdx = 0; srcPlaneNdx < srcPlaneInfo.numPlanes; srcPlaneNdx++) |
| { |
| for (deUint32 dstPlaneNdx = 0; dstPlaneNdx < dstPlaneInfo.numPlanes; dstPlaneNdx++) |
| { |
| const vk::VkFormat srcPlaneFormat (getPlaneCompatibleFormat(srcPlaneInfo, srcPlaneNdx)); |
| const vk::VkFormat dstPlaneFormat (getPlaneCompatibleFormat(dstPlaneInfo, dstPlaneNdx)); |
| |
| if (isCompatible(srcPlaneFormat, dstPlaneFormat)) |
| pairs.push_back(std::make_pair(srcPlaneNdx, dstPlaneNdx)); |
| } |
| } |
| |
| DE_ASSERT(!pairs.empty()); |
| |
| copies->reserve(copyCount); |
| |
| for (size_t copyNdx = 0; copyNdx < copyCount; copyNdx++) |
| { |
| const pair<deUint32, deUint32> planes (rng.choose<pair<deUint32, deUint32> >(pairs.begin(), pairs.end())); |
| |
| const deUint32 srcPlaneNdx (planes.first); |
| const vk::VkFormat srcPlaneFormat (getPlaneCompatibleFormat(srcPlaneInfo, srcPlaneNdx)); |
| const UVec2 srcBlockExtent (getBlockExtent(srcPlaneFormat)); |
| const UVec2 srcPlaneExtent (getPlaneExtent(srcPlaneInfo, srcSize, srcPlaneNdx, 0)); |
| const UVec2 srcPlaneBlockExtent (srcPlaneExtent / srcBlockExtent); |
| |
| const deUint32 dstPlaneNdx (planes.second); |
| const vk::VkFormat dstPlaneFormat (getPlaneCompatibleFormat(dstPlaneInfo, dstPlaneNdx)); |
| const UVec2 dstBlockExtent (getBlockExtent(dstPlaneFormat)); |
| const UVec2 dstPlaneExtent (getPlaneExtent(dstPlaneInfo, dstSize, dstPlaneNdx, 0)); |
| const UVec2 dstPlaneBlockExtent (dstPlaneExtent / dstBlockExtent); |
| |
| const UVec2 copyBlockExtent (randomUVec2(rng, UVec2(1u, 1u), tcu::min(srcPlaneBlockExtent, dstPlaneBlockExtent))); |
| const UVec2 srcOffset (srcBlockExtent * randomUVec2(rng, UVec2(0u, 0u), srcPlaneBlockExtent - copyBlockExtent)); |
| const UVec2 dstOffset (dstBlockExtent * randomUVec2(rng, UVec2(0u, 0u), dstPlaneBlockExtent - copyBlockExtent)); |
| const UVec2 copyExtent (copyBlockExtent * srcBlockExtent); |
| const vk::VkImageCopy copy = |
| { |
| // src |
| { |
| static_cast<vk::VkImageAspectFlags>(srcPlaneInfo.numPlanes > 1 ? vk::getPlaneAspect(srcPlaneNdx) : vk::VK_IMAGE_ASPECT_COLOR_BIT), |
| 0u, |
| 0u, |
| 1u |
| }, |
| { |
| (deInt32)srcOffset.x(), |
| (deInt32)srcOffset.y(), |
| 0, |
| }, |
| // dst |
| { |
| static_cast<vk::VkImageAspectFlags>(dstPlaneInfo.numPlanes > 1 ? vk::getPlaneAspect(dstPlaneNdx) : vk::VK_IMAGE_ASPECT_COLOR_BIT), |
| 0u, |
| 0u, |
| 1u |
| }, |
| { |
| (deInt32)dstOffset.x(), |
| (deInt32)dstOffset.y(), |
| 0, |
| }, |
| // size |
| { |
| copyExtent.x(), |
| copyExtent.y(), |
| 1u |
| } |
| }; |
| |
| copies->push_back(copy); |
| } |
| } |
| |
| tcu::SeedBuilder& operator<< (tcu::SeedBuilder& builder, const ImageConfig& config) |
| { |
| |
| builder << (deUint32)config.format << (deUint32)config.tiling << config.disjoint << config.size[0] << config.size[1]; |
| return builder; |
| } |
| |
| deUint32 buildSeed (const TestConfig& config) |
| { |
| tcu::SeedBuilder builder; |
| |
| builder << 6792903u << config.src << config.dst; |
| |
| return builder.get(); |
| } |
| |
| void logImageInfo (TestLog& log, |
| const ImageConfig& config) |
| { |
| log << TestLog::Message << "Format: " << config.format << TestLog::EndMessage; |
| log << TestLog::Message << "Tiling: " << config.tiling << TestLog::EndMessage; |
| log << TestLog::Message << "Size: " << config.size << TestLog::EndMessage; |
| log << TestLog::Message << "Disjoint: " << (config.disjoint ? "true" : "false") << TestLog::EndMessage; |
| } |
| void logTestCaseInfo (TestLog& log, |
| const TestConfig& config, |
| const vector<vk::VkImageCopy>& copies) |
| { |
| { |
| const tcu::ScopedLogSection section (log, "SourceImage", "SourceImage"); |
| logImageInfo(log, config.src); |
| } |
| |
| { |
| const tcu::ScopedLogSection section (log, "DestinationImage", "DestinationImage"); |
| logImageInfo(log, config.dst); |
| } |
| { |
| const tcu::ScopedLogSection section (log, "Copies", "Copies"); |
| |
| for (size_t copyNdx = 0; copyNdx < copies.size(); copyNdx++) |
| log << TestLog::Message << copies[copyNdx] << TestLog::EndMessage; |
| } |
| } |
| |
| tcu::TestStatus imageCopyTest (Context& context, const TestConfig config) |
| { |
| { |
| const size_t copyCount = 10; |
| TestLog& log (context.getTestContext().getLog()); |
| |
| MultiPlaneImageData srcData (config.src.format, config.src.size); |
| MultiPlaneImageData dstData (config.dst.format, config.dst.size); |
| MultiPlaneImageData result (config.dst.format, config.dst.size); |
| vector<vk::VkImageCopy> copies; |
| |
| de::Random rng (buildSeed(config)); |
| |
| genCopies(rng, copyCount, config.src.format, config.src.size, config.dst.format, config.dst.size, &copies); |
| |
| logTestCaseInfo(log, config, copies); |
| |
| fillRandom(&rng, &srcData); |
| fillRandom(&rng, &dstData); |
| |
| { |
| const vk::DeviceInterface& vkd (context.getDeviceInterface()); |
| const vk::VkDevice device (context.getDevice()); |
| |
| const vk::Unique<vk::VkImage> srcImage (createImage(vkd, device, config.src.format, config.src.size, config.src.disjoint, config.src.tiling)); |
| const vk::MemoryRequirement srcMemoryRequirement (config.src.tiling == vk::VK_IMAGE_TILING_OPTIMAL |
| ? vk::MemoryRequirement::Any |
| : vk::MemoryRequirement::HostVisible); |
| const vk::VkImageCreateFlags srcCreateFlags (config.src.disjoint ? vk::VK_IMAGE_CREATE_DISJOINT_BIT : (vk::VkImageCreateFlagBits)0u); |
| const vector<AllocationSp> srcImageMemory (allocateAndBindImageMemory(vkd, device, context.getDefaultAllocator(), *srcImage, config.src.format, srcCreateFlags, srcMemoryRequirement)); |
| |
| const vk::Unique<vk::VkImage> dstImage (createImage(vkd, device, config.dst.format, config.dst.size, config.dst.disjoint, config.dst.tiling)); |
| const vk::MemoryRequirement dstMemoryRequirement (config.dst.tiling == vk::VK_IMAGE_TILING_OPTIMAL |
| ? vk::MemoryRequirement::Any |
| : vk::MemoryRequirement::HostVisible); |
| const vk::VkImageCreateFlags dstCreateFlags (config.dst.disjoint ? vk::VK_IMAGE_CREATE_DISJOINT_BIT : (vk::VkImageCreateFlagBits)0u); |
| const vector<AllocationSp> dstImageMemory (allocateAndBindImageMemory(vkd, device, context.getDefaultAllocator(), *dstImage, config.dst.format, dstCreateFlags, dstMemoryRequirement)); |
| |
| if (config.src.tiling == vk::VK_IMAGE_TILING_OPTIMAL) |
| uploadImage(vkd, device, context.getUniversalQueueFamilyIndex(), context.getDefaultAllocator(), *srcImage, srcData, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); |
| else |
| fillImageMemory(vkd, device, context.getUniversalQueueFamilyIndex(), *srcImage, srcImageMemory, srcData, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); |
| |
| if (config.dst.tiling == vk::VK_IMAGE_TILING_OPTIMAL) |
| uploadImage(vkd, device, context.getUniversalQueueFamilyIndex(), context.getDefaultAllocator(), *dstImage, dstData, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); |
| else |
| fillImageMemory(vkd, device, context.getUniversalQueueFamilyIndex(), *dstImage, dstImageMemory, dstData, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); |
| |
| { |
| const deUint32 queueFamilyNdx (context.getUniversalQueueFamilyIndex()); |
| const vk::VkQueue queue (context.getUniversalQueue()); |
| const vk::Unique<vk::VkCommandPool> cmdPool (createCommandPool(vkd, device, (vk::VkCommandPoolCreateFlags)0, queueFamilyNdx)); |
| const vk::Unique<vk::VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vkd, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY)); |
| |
| beginCommandBuffer(vkd, *cmdBuffer); |
| |
| for (size_t i = 0; i < copies.size(); i++) |
| { |
| vkd.cmdCopyImage(*cmdBuffer, *srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copies[i]); |
| |
| const vk::VkImageMemoryBarrier preCopyBarrier = |
| { |
| vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, |
| DE_NULL, |
| vk::VK_ACCESS_TRANSFER_WRITE_BIT, |
| vk::VK_ACCESS_TRANSFER_WRITE_BIT, |
| vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, |
| vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, |
| VK_QUEUE_FAMILY_IGNORED, |
| VK_QUEUE_FAMILY_IGNORED, |
| *dstImage, |
| { vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } |
| }; |
| |
| vkd.cmdPipelineBarrier(*cmdBuffer, |
| (vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_TRANSFER_BIT, |
| (vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_TRANSFER_BIT, |
| (vk::VkDependencyFlags)0u, |
| 0u, |
| (const vk::VkMemoryBarrier*)DE_NULL, |
| 0u, |
| (const vk::VkBufferMemoryBarrier*)DE_NULL, |
| 1u, |
| &preCopyBarrier); |
| } |
| |
| endCommandBuffer(vkd, *cmdBuffer); |
| |
| submitCommandsAndWait(vkd, device, queue, *cmdBuffer); |
| } |
| |
| if (config.dst.tiling == vk::VK_IMAGE_TILING_OPTIMAL) |
| downloadImage(vkd, device, context.getUniversalQueueFamilyIndex(), context.getDefaultAllocator(), *dstImage, &result, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); |
| else |
| readImageMemory(vkd, device, context.getUniversalQueueFamilyIndex(), *dstImage, dstImageMemory, &result, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); |
| } |
| |
| { |
| MultiPlaneImageData reference (dstData); |
| const size_t maxErrorCount = 30; |
| size_t errorCount = 0; |
| |
| for (size_t copyNdx = 0; copyNdx < copies.size(); copyNdx++) |
| { |
| const vk::VkImageCopy& copy (copies[copyNdx]); |
| |
| const deUint32 srcPlaneNdx (copy.srcSubresource.aspectMask != vk::VK_IMAGE_ASPECT_COLOR_BIT |
| ? vk::getAspectPlaneNdx((vk::VkImageAspectFlagBits)copy.srcSubresource.aspectMask) |
| : 0u); |
| const UVec2 srcPlaneExtent (getPlaneExtent(srcData.getDescription(), config.src.size, srcPlaneNdx, 0)); |
| |
| const vk::VkFormat srcPlaneFormat (getPlaneCompatibleFormat(config.src.format, srcPlaneNdx)); |
| const UVec2 srcBlockExtent (getBlockExtent(srcPlaneFormat)); |
| |
| const deUint32 blockSizeBytes (getBlockByteSize(srcPlaneFormat)); |
| |
| const UVec2 srcPlaneBlockExtent (srcPlaneExtent / srcBlockExtent); |
| const UVec2 srcBlockOffset (copy.srcOffset.x / srcBlockExtent.x(), copy.srcOffset.y / srcBlockExtent.y()); |
| const UVec2 srcBlockPitch (blockSizeBytes, blockSizeBytes * srcPlaneBlockExtent.x()); |
| |
| const deUint32 dstPlaneNdx (copy.dstSubresource.aspectMask != vk::VK_IMAGE_ASPECT_COLOR_BIT |
| ? vk::getAspectPlaneNdx((vk::VkImageAspectFlagBits)copy.dstSubresource.aspectMask) |
| : 0u); |
| const UVec2 dstPlaneExtent (getPlaneExtent(dstData.getDescription(), config.dst.size, dstPlaneNdx, 0)); |
| |
| const vk::VkFormat dstPlaneFormat (getPlaneCompatibleFormat(config.dst.format, dstPlaneNdx)); |
| const UVec2 dstBlockExtent (getBlockExtent(dstPlaneFormat)); |
| |
| const UVec2 dstPlaneBlockExtent (dstPlaneExtent / dstBlockExtent); |
| const UVec2 dstBlockOffset (copy.dstOffset.x / dstBlockExtent.x(), copy.dstOffset.y / dstBlockExtent.y()); |
| const UVec2 dstBlockPitch (blockSizeBytes, blockSizeBytes * dstPlaneBlockExtent.x()); |
| |
| const UVec2 blockExtent (copy.extent.width / srcBlockExtent.x(), copy.extent.height / srcBlockExtent.y()); |
| |
| DE_ASSERT(blockSizeBytes == getBlockByteSize(dstPlaneFormat)); |
| |
| for (deUint32 y = 0; y < blockExtent.y(); y++) |
| { |
| const deUint32 size = blockExtent.x() * blockSizeBytes; |
| const deUint32 srcPos = tcu::dot(srcBlockPitch, UVec2(srcBlockOffset.x(), srcBlockOffset.y() + y)); |
| const deUint32 dstPos = tcu::dot(dstBlockPitch, UVec2(dstBlockOffset.x(), dstBlockOffset.y() + y)); |
| |
| deMemcpy(((deUint8*)reference.getPlanePtr(dstPlaneNdx)) + dstPos, |
| ((const deUint8*)srcData.getPlanePtr(srcPlaneNdx)) + srcPos, size); |
| } |
| } |
| |
| bool ignoreLsb6Bits = areLsb6BitsDontCare(srcData.getFormat(), dstData.getFormat()); |
| bool ignoreLsb4Bits = areLsb4BitsDontCare(srcData.getFormat(), dstData.getFormat()); |
| |
| for (deUint32 planeNdx = 0; planeNdx < result.getDescription().numPlanes; ++planeNdx) |
| { |
| deUint32 planeSize = vk::getPlaneSizeInBytes(result.getDescription(), result.getSize(), planeNdx, 0u, 1u); |
| for (size_t byteNdx = 0; byteNdx < planeSize; byteNdx++) |
| { |
| const deUint8 res = ((const deUint8*)result.getPlanePtr(planeNdx))[byteNdx]; |
| const deUint8 ref = ((const deUint8*)reference.getPlanePtr(planeNdx))[byteNdx]; |
| |
| deUint8 mask = 0xFF; |
| if (!(byteNdx & 0x01) && (ignoreLsb6Bits)) |
| mask = 0xC0; |
| else if (!(byteNdx & 0x01) && (ignoreLsb4Bits)) |
| mask = 0xF0; |
| |
| if ((res & mask) != (ref & mask)) |
| { |
| log << TestLog::Message << "Plane: " << planeNdx << ", Offset: " << byteNdx << ", Expected: " << (deUint32)(ref & mask) << ", Got: " << (deUint32)(res & mask) << TestLog::EndMessage; |
| errorCount++; |
| |
| if (errorCount > maxErrorCount) |
| break; |
| } |
| } |
| |
| if (errorCount > maxErrorCount) |
| break; |
| } |
| |
| if (errorCount > 0) |
| return tcu::TestStatus::fail("Failed, found " + (errorCount > maxErrorCount ? de::toString(maxErrorCount) + "+" : de::toString(errorCount)) + " incorrect bytes"); |
| else |
| return tcu::TestStatus::pass("Pass"); |
| } |
| } |
| } |
| |
| bool isCopyCompatible (vk::VkFormat srcFormat, vk::VkFormat dstFormat) |
| { |
| if (isYCbCrFormat(srcFormat) && isYCbCrFormat(dstFormat)) |
| { |
| const vk::PlanarFormatDescription srcPlaneInfo (vk::getPlanarFormatDescription(srcFormat)); |
| const vk::PlanarFormatDescription dstPlaneInfo (vk::getPlanarFormatDescription(dstFormat)); |
| |
| for (deUint32 srcPlaneNdx = 0; srcPlaneNdx < srcPlaneInfo.numPlanes; srcPlaneNdx++) |
| { |
| for (deUint32 dstPlaneNdx = 0; dstPlaneNdx < dstPlaneInfo.numPlanes; dstPlaneNdx++) |
| { |
| const vk::VkFormat srcPlaneFormat (getPlaneCompatibleFormat(srcFormat, srcPlaneNdx)); |
| const vk::VkFormat dstPlaneFormat (getPlaneCompatibleFormat(dstFormat, dstPlaneNdx)); |
| |
| if (isCompatible(srcPlaneFormat, dstPlaneFormat)) |
| return true; |
| } |
| } |
| } |
| else if (isYCbCrFormat(srcFormat)) |
| { |
| const vk::PlanarFormatDescription srcPlaneInfo (vk::getPlanarFormatDescription(srcFormat)); |
| |
| for (deUint32 srcPlaneNdx = 0; srcPlaneNdx < srcPlaneInfo.numPlanes; srcPlaneNdx++) |
| { |
| const vk::VkFormat srcPlaneFormat (getPlaneCompatibleFormat(srcFormat, srcPlaneNdx)); |
| |
| if (isCompatible(srcPlaneFormat, dstFormat)) |
| return true; |
| } |
| } |
| else if (isYCbCrFormat(dstFormat)) |
| { |
| const vk::PlanarFormatDescription dstPlaneInfo (vk::getPlanarFormatDescription(dstFormat)); |
| |
| for (deUint32 dstPlaneNdx = 0; dstPlaneNdx < dstPlaneInfo.numPlanes; dstPlaneNdx++) |
| { |
| const vk::VkFormat dstPlaneFormat (getPlaneCompatibleFormat(dstFormat, dstPlaneNdx)); |
| |
| if (isCompatible(dstPlaneFormat, srcFormat)) |
| return true; |
| } |
| } |
| else |
| return isCompatible(srcFormat, dstFormat); |
| |
| return false; |
| } |
| |
| void initYcbcrDefaultCopyTests (tcu::TestCaseGroup* testGroup) |
| { |
| const vk::VkFormat ycbcrFormats[] = |
| { |
| vk::VK_FORMAT_R4G4_UNORM_PACK8, |
| vk::VK_FORMAT_R4G4B4A4_UNORM_PACK16, |
| vk::VK_FORMAT_B4G4R4A4_UNORM_PACK16, |
| vk::VK_FORMAT_R5G6B5_UNORM_PACK16, |
| vk::VK_FORMAT_B5G6R5_UNORM_PACK16, |
| vk::VK_FORMAT_R5G5B5A1_UNORM_PACK16, |
| vk::VK_FORMAT_B5G5R5A1_UNORM_PACK16, |
| vk::VK_FORMAT_A1R5G5B5_UNORM_PACK16, |
| vk::VK_FORMAT_R8_UNORM, |
| vk::VK_FORMAT_R8G8_UNORM, |
| vk::VK_FORMAT_R8G8B8_UNORM, |
| vk::VK_FORMAT_B8G8R8_UNORM, |
| vk::VK_FORMAT_R8G8B8A8_UNORM, |
| vk::VK_FORMAT_B8G8R8A8_UNORM, |
| vk::VK_FORMAT_A8B8G8R8_UNORM_PACK32, |
| vk::VK_FORMAT_A2R10G10B10_UNORM_PACK32, |
| vk::VK_FORMAT_R16_UNORM, |
| vk::VK_FORMAT_R16G16_UNORM, |
| vk::VK_FORMAT_R16G16B16_UNORM, |
| vk::VK_FORMAT_R16G16B16A16_UNORM, |
| vk::VK_FORMAT_B10G11R11_UFLOAT_PACK32, |
| vk::VK_FORMAT_G8B8G8R8_422_UNORM, |
| vk::VK_FORMAT_B8G8R8G8_422_UNORM, |
| vk::VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, |
| vk::VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, |
| vk::VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM, |
| vk::VK_FORMAT_G8_B8R8_2PLANE_422_UNORM, |
| vk::VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM, |
| vk::VK_FORMAT_R10X6_UNORM_PACK16, |
| vk::VK_FORMAT_R10X6G10X6_UNORM_2PACK16, |
| vk::VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16, |
| vk::VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16, |
| vk::VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16, |
| vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, |
| vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, |
| vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16, |
| vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, |
| vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16, |
| vk::VK_FORMAT_R12X4_UNORM_PACK16, |
| vk::VK_FORMAT_R12X4G12X4_UNORM_2PACK16, |
| vk::VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16, |
| vk::VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16, |
| vk::VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16, |
| vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16, |
| vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, |
| vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16, |
| vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16, |
| vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16, |
| vk::VK_FORMAT_G16B16G16R16_422_UNORM, |
| vk::VK_FORMAT_B16G16R16G16_422_UNORM, |
| vk::VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, |
| vk::VK_FORMAT_G16_B16R16_2PLANE_420_UNORM, |
| vk::VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, |
| vk::VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, |
| vk::VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM |
| }; |
| const struct |
| { |
| const char* name; |
| vk::VkImageTiling value; |
| } imageTilings[] = |
| { |
| { "linear", vk::VK_IMAGE_TILING_LINEAR }, |
| { "optimal", vk::VK_IMAGE_TILING_OPTIMAL } |
| }; |
| tcu::TestContext& testCtx = testGroup->getTestContext(); |
| |
| for (size_t srcFormatNdx = 0; srcFormatNdx < DE_LENGTH_OF_ARRAY(ycbcrFormats); srcFormatNdx++) |
| { |
| const vk::VkFormat srcFormat (ycbcrFormats[srcFormatNdx]); |
| const UVec2 srcSize (isYCbCrFormat(srcFormat) ? UVec2(24u, 16u) : UVec2(23u, 17u)); |
| const string srcFormatName (de::toLower(std::string(getFormatName(srcFormat)).substr(10))); |
| de::MovePtr<tcu::TestCaseGroup> srcFormatGroup (new tcu::TestCaseGroup(testCtx, srcFormatName.c_str(), ("Tests for copies using format " + srcFormatName).c_str())); |
| |
| for (size_t dstFormatNdx = 0; dstFormatNdx < DE_LENGTH_OF_ARRAY(ycbcrFormats); dstFormatNdx++) |
| { |
| const vk::VkFormat dstFormat (ycbcrFormats[dstFormatNdx]); |
| const UVec2 dstSize (isYCbCrFormat(dstFormat) ? UVec2(24u, 16u) : UVec2(23u, 17u)); |
| const string dstFormatName (de::toLower(std::string(getFormatName(dstFormat)).substr(10))); |
| |
| if ((!vk::isYCbCrFormat(srcFormat) && !vk::isYCbCrFormat(dstFormat)) |
| || !isCopyCompatible(srcFormat, dstFormat)) |
| continue; |
| |
| de::MovePtr<tcu::TestCaseGroup> dstFormatGroup (new tcu::TestCaseGroup(testCtx, dstFormatName.c_str(), ("Tests for copies using format " + dstFormatName).c_str())); |
| |
| for (size_t srcTilingNdx = 0; srcTilingNdx < DE_LENGTH_OF_ARRAY(imageTilings); srcTilingNdx++) |
| { |
| const vk::VkImageTiling srcTiling = imageTilings[srcTilingNdx].value; |
| const char* const srcTilingName = imageTilings[srcTilingNdx].name; |
| |
| for (size_t dstTilingNdx = 0; dstTilingNdx < DE_LENGTH_OF_ARRAY(imageTilings); dstTilingNdx++) |
| { |
| const vk::VkImageTiling dstTiling = imageTilings[dstTilingNdx].value; |
| const char* const dstTilingName = imageTilings[dstTilingNdx].name; |
| |
| for (size_t srcDisjointNdx = 0; srcDisjointNdx < 2; srcDisjointNdx++) |
| for (size_t dstDisjointNdx = 0; dstDisjointNdx < 2; dstDisjointNdx++) |
| { |
| const bool srcDisjoint = srcDisjointNdx == 1; |
| const bool dstDisjoint = dstDisjointNdx == 1; |
| const TestConfig config (ImageConfig(srcFormat, srcTiling, srcDisjoint, srcSize), ImageConfig(dstFormat, dstTiling, dstDisjoint, dstSize)); |
| |
| addFunctionCase(dstFormatGroup.get(), string(srcTilingName) + (srcDisjoint ? "_disjoint_" : "_") + string(dstTilingName) + (dstDisjoint ? "_disjoint" : ""), "", checkSupport, imageCopyTest, config); |
| } |
| } |
| } |
| |
| srcFormatGroup->addChild(dstFormatGroup.release()); |
| } |
| |
| testGroup->addChild(srcFormatGroup.release()); |
| } |
| } |
| |
| void initYcbcrDimensionsCopyTests (tcu::TestCaseGroup* testGroup) |
| { |
| tcu::TestContext& testCtx = testGroup->getTestContext(); |
| |
| const vk::VkFormat testFormats[] = |
| { |
| // 8-bit |
| vk::VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, |
| // 10-bit |
| vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, |
| // 12-bit |
| vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16, |
| // 16-bit |
| vk::VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, |
| // Non-ycbcr |
| vk::VK_FORMAT_R8G8B8A8_UNORM, |
| }; |
| |
| const tcu::UVec2 imageDimensions[] = |
| { |
| // Wide: large pot x small pot |
| tcu::UVec2(4096, 4u), |
| tcu::UVec2(8192, 4u), |
| tcu::UVec2(16384, 4u), |
| tcu::UVec2(32768, 4u), |
| |
| // Wide: large pot x small npot |
| tcu::UVec2(4096, 6u), |
| tcu::UVec2(8192, 6u), |
| tcu::UVec2(16384, 6u), |
| tcu::UVec2(32768, 6u), |
| |
| // Tall: small pot x large pot |
| tcu::UVec2(4u, 4096), |
| tcu::UVec2(4u, 8192), |
| tcu::UVec2(4u, 16384), |
| tcu::UVec2(4u, 32768), |
| |
| // Tall: small npot x large pot |
| tcu::UVec2(6u, 4096), |
| tcu::UVec2(6u, 8192), |
| tcu::UVec2(6u, 16384), |
| tcu::UVec2(6u, 32768) |
| }; |
| |
| const struct |
| { |
| const char* name; |
| vk::VkImageTiling value; |
| } imageTilings[] = |
| { |
| { "linear", vk::VK_IMAGE_TILING_LINEAR }, |
| { "optimal", vk::VK_IMAGE_TILING_OPTIMAL } |
| }; |
| |
| for (size_t imageDimensionNdx = 0; imageDimensionNdx < DE_LENGTH_OF_ARRAY(imageDimensions); imageDimensionNdx++) |
| { |
| const UVec2 srcSize (imageDimensions[imageDimensionNdx]); |
| const UVec2 dstSize (imageDimensions[imageDimensionNdx]); |
| const string dimensionsName ("src" + de::toString(srcSize.x()) + "x" + de::toString(srcSize.y()) + "_dst" + de::toString(dstSize.x()) + "x" + de::toString(dstSize.y())); |
| |
| de::MovePtr<tcu::TestCaseGroup> dimensionGroup (new tcu::TestCaseGroup(testCtx, dimensionsName.c_str(), ("Image dimensions " + dimensionsName).c_str())); |
| |
| for (size_t srcFormatNdx = 0; srcFormatNdx < DE_LENGTH_OF_ARRAY(testFormats); srcFormatNdx++) |
| { |
| const vk::VkFormat srcFormat (testFormats[srcFormatNdx]); |
| const string srcFormatName (de::toLower(std::string(getFormatName(srcFormat)).substr(10))); |
| de::MovePtr<tcu::TestCaseGroup> srcFormatGroup (new tcu::TestCaseGroup(testCtx, srcFormatName.c_str(), ("Tests for copies using format " + srcFormatName).c_str())); |
| |
| for (size_t dstFormatNdx = 0; dstFormatNdx < DE_LENGTH_OF_ARRAY(testFormats); dstFormatNdx++) |
| { |
| const vk::VkFormat dstFormat (testFormats[dstFormatNdx]); |
| const string dstFormatName (de::toLower(std::string(getFormatName(dstFormat)).substr(10))); |
| |
| if ((!vk::isYCbCrFormat(srcFormat) && !vk::isYCbCrFormat(dstFormat)) |
| || !isCopyCompatible(srcFormat, dstFormat)) |
| continue; |
| |
| de::MovePtr<tcu::TestCaseGroup> dstFormatGroup (new tcu::TestCaseGroup(testCtx, dstFormatName.c_str(), ("Tests for copies using format " + dstFormatName).c_str())); |
| |
| for (size_t srcTilingNdx = 0; srcTilingNdx < DE_LENGTH_OF_ARRAY(imageTilings); srcTilingNdx++) |
| { |
| const vk::VkImageTiling srcTiling = imageTilings[srcTilingNdx].value; |
| const char* const srcTilingName = imageTilings[srcTilingNdx].name; |
| |
| for (size_t dstTilingNdx = 0; dstTilingNdx < DE_LENGTH_OF_ARRAY(imageTilings); dstTilingNdx++) |
| { |
| const vk::VkImageTiling dstTiling = imageTilings[dstTilingNdx].value; |
| const char* const dstTilingName = imageTilings[dstTilingNdx].name; |
| |
| for (size_t srcDisjointNdx = 0; srcDisjointNdx < 2; srcDisjointNdx++) |
| for (size_t dstDisjointNdx = 0; dstDisjointNdx < 2; dstDisjointNdx++) |
| { |
| const bool srcDisjoint = srcDisjointNdx == 1; |
| const bool dstDisjoint = dstDisjointNdx == 1; |
| const TestConfig config (ImageConfig(srcFormat, srcTiling, srcDisjoint, srcSize), ImageConfig(dstFormat, dstTiling, dstDisjoint, dstSize)); |
| |
| addFunctionCase(dstFormatGroup.get(), string(srcTilingName) + (srcDisjoint ? "_disjoint_" : "_") + string(dstTilingName) + (dstDisjoint ? "_disjoint" : ""), "", checkSupport, imageCopyTest, config); |
| } |
| } |
| } |
| |
| srcFormatGroup->addChild(dstFormatGroup.release()); |
| } |
| |
| dimensionGroup->addChild(srcFormatGroup.release()); |
| } |
| |
| testGroup->addChild(dimensionGroup.release()); |
| } |
| } |
| |
| } // anonymous |
| |
| tcu::TestCaseGroup* createCopyTests (tcu::TestContext& testCtx) |
| { |
| return createTestGroup(testCtx, "copy", "YCbCr Format Copy Tests", initYcbcrDefaultCopyTests); |
| } |
| |
| tcu::TestCaseGroup* createDimensionsCopyTests (tcu::TestContext& testCtx) |
| { |
| return createTestGroup(testCtx, "copy_dimensions", "YCbCr format copy tests between different image dimensions", initYcbcrDimensionsCopyTests); |
| } |
| |
| } // ycbcr |
| } // vkt |