Home | History | Annotate | Download | only in ycbcr
      1 /*------------------------------------------------------------------------
      2  * Vulkan Conformance Tests
      3  * ------------------------
      4  *
      5  * Copyright (c) 2017 Google Inc.
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief YCbCr format copy tests
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "vktYCbCrCopyTests.hpp"
     25 
     26 #include "vktTestCaseUtil.hpp"
     27 #include "vktTestGroupUtil.hpp"
     28 #include "vktYCbCrUtil.hpp"
     29 
     30 #include "vkQueryUtil.hpp"
     31 #include "vkRefUtil.hpp"
     32 #include "vkTypeUtil.hpp"
     33 
     34 #include "tcuSeedBuilder.hpp"
     35 #include "tcuTestLog.hpp"
     36 #include "tcuVector.hpp"
     37 #include "tcuVectorUtil.hpp"
     38 
     39 #include "deRandom.hpp"
     40 #include "deSTLUtil.hpp"
     41 #include "deStringUtil.hpp"
     42 
     43 #include <string>
     44 #include <utility>
     45 #include <vector>
     46 
     47 using tcu::UVec2;
     48 using tcu::Vec4;
     49 using tcu::TestLog;
     50 
     51 using std::string;
     52 using std::vector;
     53 using std::pair;
     54 
     55 namespace vkt
     56 {
     57 namespace ycbcr
     58 {
     59 namespace
     60 {
     61 typedef de::SharedPtr<vk::Allocation> AllocationSp;
     62 
     63 struct ImageConfig
     64 {
     65 						ImageConfig	(vk::VkFormat		format_,
     66 									 vk::VkImageTiling	tiling_,
     67 									 bool				disjoint_,
     68 									 const UVec2&		size_)
     69 		: format	(format_)
     70 		, tiling	(tiling_)
     71 		, disjoint	(disjoint_)
     72 		, size		(size_)
     73 	{
     74 	}
     75 
     76 	vk::VkFormat		format;
     77 	vk::VkImageTiling	tiling;
     78 	bool				disjoint;
     79 	UVec2				size;
     80 };
     81 
     82 struct TestConfig
     83 {
     84 				TestConfig		(const ImageConfig&	src_,
     85 								 const ImageConfig&	dst_)
     86 		: src	(src_)
     87 		, dst	(dst_)
     88 	{
     89 	}
     90 
     91 	ImageConfig	src;
     92 	ImageConfig	dst;
     93 };
     94 
     95 void checkSupport (Context& context, const TestConfig& config)
     96 {
     97 	if (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), string("VK_KHR_sampler_ycbcr_conversion")))
     98 		TCU_THROW(NotSupportedError, "Extension VK_KHR_sampler_ycbcr_conversion not supported");
     99 
    100 	try
    101 	{
    102 		const vk::VkFormatProperties	properties	(vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), config.src.format));
    103 		const vk::VkFormatFeatureFlags	features	(config.src.tiling == vk::VK_IMAGE_TILING_OPTIMAL
    104 													? properties.optimalTilingFeatures
    105 													: properties.linearTilingFeatures);
    106 
    107 		if ((features & vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0
    108 			&& (features & vk::VK_FORMAT_FEATURE_TRANSFER_DST_BIT) == 0)
    109 		{
    110 			TCU_THROW(NotSupportedError, "Source format doesn't support copies");
    111 		}
    112 
    113 		if (config.src.disjoint && ((features & vk::VK_FORMAT_FEATURE_DISJOINT_BIT) == 0))
    114 			TCU_THROW(NotSupportedError, "Format doesn'tsupport  disjoint planes");
    115 	}
    116 	catch (const vk::Error& err)
    117 	{
    118 		if (err.getError() == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
    119 			TCU_THROW(NotSupportedError, "Format not supported");
    120 
    121 		throw;
    122 	}
    123 
    124 	try
    125 	{
    126 		const vk::VkFormatProperties	properties	(vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), config.dst.format));
    127 		const vk::VkFormatFeatureFlags	features	(config.dst.tiling == vk::VK_IMAGE_TILING_OPTIMAL
    128 													? properties.optimalTilingFeatures
    129 													: properties.linearTilingFeatures);
    130 
    131 		if ((features & vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0
    132 			&& (features & vk::VK_FORMAT_FEATURE_TRANSFER_DST_BIT) == 0)
    133 		{
    134 			TCU_THROW(NotSupportedError, "Source format doesn't support copies");
    135 		}
    136 
    137 		if (config.dst.disjoint && ((features & vk::VK_FORMAT_FEATURE_DISJOINT_BIT) == 0))
    138 			TCU_THROW(NotSupportedError, "Format doesn't disjoint planes");
    139 	}
    140 	catch (const vk::Error& err)
    141 	{
    142 		if (err.getError() == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
    143 			TCU_THROW(NotSupportedError, "Format not supported");
    144 
    145 		throw;
    146 	}
    147 }
    148 
    149 vk::Move<vk::VkImage> createImage (const vk::DeviceInterface&	vkd,
    150 								   vk::VkDevice					device,
    151 								   vk::VkFormat					format,
    152 								   const UVec2&					size,
    153 								   bool							disjoint,
    154 								   vk::VkImageTiling			tiling)
    155 {
    156 	const vk::VkImageCreateInfo createInfo =
    157 	{
    158 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
    159 		DE_NULL,
    160 		disjoint ? (vk::VkImageCreateFlags)vk::VK_IMAGE_CREATE_DISJOINT_BIT : (vk::VkImageCreateFlags)0u,
    161 
    162 		vk::VK_IMAGE_TYPE_2D,
    163 		format,
    164 		vk::makeExtent3D(size.x(), size.y(), 1u),
    165 		1u,
    166 		1u,
    167 		vk::VK_SAMPLE_COUNT_1_BIT,
    168 		tiling,
    169 		vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
    170 		vk::VK_SHARING_MODE_EXCLUSIVE,
    171 		0u,
    172 		(const deUint32*)DE_NULL,
    173 		vk::VK_IMAGE_LAYOUT_UNDEFINED,
    174 	};
    175 
    176 	return vk::createImage(vkd, device, &createInfo);
    177 }
    178 
    179 vk::VkFormat getPlaneCompatibleFormat (vk::VkFormat format, deUint32 planeNdx)
    180 {
    181 	DE_ASSERT(planeNdx < 3);
    182 
    183 	switch (format)
    184 	{
    185 		case vk::VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
    186 			return vk::VK_FORMAT_R8_UNORM;
    187 
    188 		case vk::VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
    189 		{
    190 			DE_ASSERT(planeNdx < 2);
    191 
    192 			if (planeNdx == 0)
    193 				return vk::VK_FORMAT_R8_UNORM;
    194 			else
    195 				return vk::VK_FORMAT_R8G8_UNORM;
    196 		}
    197 
    198 		case vk::VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM:
    199 			return vk::VK_FORMAT_R8_UNORM;
    200 
    201 		case vk::VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:
    202 		{
    203 			DE_ASSERT(planeNdx < 2);
    204 
    205 			if (planeNdx == 0)
    206 				return vk::VK_FORMAT_R8_UNORM;
    207 			else
    208 				return vk::VK_FORMAT_R8G8_UNORM;
    209 		}
    210 
    211 		case vk::VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM:
    212 			return vk::VK_FORMAT_R8_UNORM;
    213 
    214 		case vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16:
    215 			return vk::VK_FORMAT_R10X6_UNORM_PACK16;
    216 
    217 		case vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
    218 		{
    219 			DE_ASSERT(planeNdx < 2);
    220 
    221 			if (planeNdx == 0)
    222 				return vk::VK_FORMAT_R10X6_UNORM_PACK16;
    223 			else
    224 				return vk::VK_FORMAT_R10X6G10X6_UNORM_2PACK16;
    225 		}
    226 
    227 		case vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16:
    228 			return vk::VK_FORMAT_R10X6_UNORM_PACK16;
    229 
    230 		case vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
    231 		{
    232 			DE_ASSERT(planeNdx < 2);
    233 
    234 			if (planeNdx == 0)
    235 				return vk::VK_FORMAT_R10X6_UNORM_PACK16;
    236 			else
    237 				return vk::VK_FORMAT_R10X6G10X6_UNORM_2PACK16;
    238 		}
    239 
    240 		case vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16:
    241 			return vk::VK_FORMAT_R10X6_UNORM_PACK16;
    242 
    243 		case vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16:
    244 			return vk::VK_FORMAT_R12X4_UNORM_PACK16;
    245 
    246 		case vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16:
    247 		{
    248 			DE_ASSERT(planeNdx < 2);
    249 
    250 			if (planeNdx == 0)
    251 				return vk::VK_FORMAT_R12X4_UNORM_PACK16;
    252 			else
    253 				return vk::VK_FORMAT_R12X4G12X4_UNORM_2PACK16;
    254 		}
    255 
    256 		case vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16:
    257 			return vk::VK_FORMAT_R12X4_UNORM_PACK16;
    258 
    259 		case vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16:
    260 		{
    261 			DE_ASSERT(planeNdx < 2);
    262 
    263 			if (planeNdx == 0)
    264 				return vk::VK_FORMAT_R12X4_UNORM_PACK16;
    265 			else
    266 				return vk::VK_FORMAT_R12X4G12X4_UNORM_2PACK16;
    267 		}
    268 
    269 		case vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16:
    270 			return vk::VK_FORMAT_R12X4_UNORM_PACK16;
    271 
    272 		case vk::VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM:
    273 			return vk::VK_FORMAT_R16_UNORM;
    274 
    275 		case vk::VK_FORMAT_G16_B16R16_2PLANE_420_UNORM:
    276 		{
    277 			DE_ASSERT(planeNdx < 2);
    278 
    279 			if (planeNdx == 0)
    280 				return vk::VK_FORMAT_R16_UNORM;
    281 			else
    282 				return vk::VK_FORMAT_R16G16_UNORM;
    283 		}
    284 
    285 		case vk::VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM:
    286 			return vk::VK_FORMAT_R16_UNORM;
    287 
    288 		case vk::VK_FORMAT_G16_B16R16_2PLANE_422_UNORM:
    289 		{
    290 			DE_ASSERT(planeNdx < 2);
    291 
    292 			if (planeNdx == 0)
    293 				return vk::VK_FORMAT_R16_UNORM;
    294 			else
    295 				return vk::VK_FORMAT_R16G16_UNORM;
    296 		}
    297 
    298 		case vk::VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM:
    299 			return vk::VK_FORMAT_R16_UNORM;
    300 
    301 		default:
    302 			DE_ASSERT(planeNdx == 0);
    303 			return format;
    304 	}
    305 }
    306 
    307 bool isCompatible (vk::VkFormat	srcFormat,
    308 				   vk::VkFormat	dstFormat)
    309 {
    310 	if (srcFormat == dstFormat)
    311 		return true;
    312 	else
    313 	{
    314 		const vk::VkFormat class8Bit[] =
    315 		{
    316 			vk::VK_FORMAT_R4G4_UNORM_PACK8,
    317 			vk::VK_FORMAT_R8_UNORM,
    318 			vk::VK_FORMAT_R8_SNORM,
    319 			vk::VK_FORMAT_R8_USCALED,
    320 			vk::VK_FORMAT_R8_SSCALED,
    321 			vk::VK_FORMAT_R8_UINT,
    322 			vk::VK_FORMAT_R8_SINT,
    323 			vk::VK_FORMAT_R8_SRGB
    324 		};
    325 		const vk::VkFormat class16Bit[] =
    326 		{
    327 			vk::VK_FORMAT_R4G4B4A4_UNORM_PACK16,
    328 			vk::VK_FORMAT_B4G4R4A4_UNORM_PACK16,
    329 			vk::VK_FORMAT_R5G6B5_UNORM_PACK16,
    330 			vk::VK_FORMAT_B5G6R5_UNORM_PACK16,
    331 			vk::VK_FORMAT_R5G5B5A1_UNORM_PACK16,
    332 			vk::VK_FORMAT_B5G5R5A1_UNORM_PACK16,
    333 			vk::VK_FORMAT_A1R5G5B5_UNORM_PACK16,
    334 			vk::VK_FORMAT_R8G8_UNORM,
    335 			vk::VK_FORMAT_R8G8_SNORM,
    336 			vk::VK_FORMAT_R8G8_USCALED,
    337 			vk::VK_FORMAT_R8G8_SSCALED,
    338 			vk::VK_FORMAT_R8G8_UINT,
    339 			vk::VK_FORMAT_R8G8_SINT,
    340 			vk::VK_FORMAT_R8G8_SRGB,
    341 			vk::VK_FORMAT_R16_UNORM,
    342 			vk::VK_FORMAT_R16_SNORM,
    343 			vk::VK_FORMAT_R16_USCALED,
    344 			vk::VK_FORMAT_R16_SSCALED,
    345 			vk::VK_FORMAT_R16_UINT,
    346 			vk::VK_FORMAT_R16_SINT,
    347 			vk::VK_FORMAT_R16_SFLOAT,
    348 			vk::VK_FORMAT_R10X6_UNORM_PACK16,
    349 			vk::VK_FORMAT_R12X4_UNORM_PACK16
    350 		};
    351 		const vk::VkFormat class24Bit[] =
    352 		{
    353 			vk::VK_FORMAT_R8G8B8_UNORM,
    354 			vk::VK_FORMAT_R8G8B8_SNORM,
    355 			vk::VK_FORMAT_R8G8B8_USCALED,
    356 			vk::VK_FORMAT_R8G8B8_SSCALED,
    357 			vk::VK_FORMAT_R8G8B8_UINT,
    358 			vk::VK_FORMAT_R8G8B8_SINT,
    359 			vk::VK_FORMAT_R8G8B8_SRGB,
    360 			vk::VK_FORMAT_B8G8R8_UNORM,
    361 			vk::VK_FORMAT_B8G8R8_SNORM,
    362 			vk::VK_FORMAT_B8G8R8_USCALED,
    363 			vk::VK_FORMAT_B8G8R8_SSCALED,
    364 			vk::VK_FORMAT_B8G8R8_UINT,
    365 			vk::VK_FORMAT_B8G8R8_SINT,
    366 			vk::VK_FORMAT_B8G8R8_SRGB
    367 		};
    368 		const vk::VkFormat class32Bit[] =
    369 		{
    370 			vk::VK_FORMAT_R8G8B8A8_UNORM,
    371 			vk::VK_FORMAT_R8G8B8A8_SNORM,
    372 			vk::VK_FORMAT_R8G8B8A8_USCALED,
    373 			vk::VK_FORMAT_R8G8B8A8_SSCALED,
    374 			vk::VK_FORMAT_R8G8B8A8_UINT,
    375 			vk::VK_FORMAT_R8G8B8A8_SINT,
    376 			vk::VK_FORMAT_R8G8B8A8_SRGB,
    377 			vk::VK_FORMAT_B8G8R8A8_UNORM,
    378 			vk::VK_FORMAT_B8G8R8A8_SNORM,
    379 			vk::VK_FORMAT_B8G8R8A8_USCALED,
    380 			vk::VK_FORMAT_B8G8R8A8_SSCALED,
    381 			vk::VK_FORMAT_B8G8R8A8_UINT,
    382 			vk::VK_FORMAT_B8G8R8A8_SINT,
    383 			vk::VK_FORMAT_B8G8R8A8_SRGB,
    384 			vk::VK_FORMAT_A8B8G8R8_UNORM_PACK32,
    385 			vk::VK_FORMAT_A8B8G8R8_SNORM_PACK32,
    386 			vk::VK_FORMAT_A8B8G8R8_USCALED_PACK32,
    387 			vk::VK_FORMAT_A8B8G8R8_SSCALED_PACK32,
    388 			vk::VK_FORMAT_A8B8G8R8_UINT_PACK32,
    389 			vk::VK_FORMAT_A8B8G8R8_SINT_PACK32,
    390 			vk::VK_FORMAT_A8B8G8R8_SRGB_PACK32,
    391 			vk::VK_FORMAT_A2R10G10B10_UNORM_PACK32,
    392 			vk::VK_FORMAT_A2R10G10B10_SNORM_PACK32,
    393 			vk::VK_FORMAT_A2R10G10B10_USCALED_PACK32,
    394 			vk::VK_FORMAT_A2R10G10B10_SSCALED_PACK32,
    395 			vk::VK_FORMAT_A2R10G10B10_UINT_PACK32,
    396 			vk::VK_FORMAT_A2R10G10B10_SINT_PACK32,
    397 			vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32,
    398 			vk::VK_FORMAT_A2B10G10R10_SNORM_PACK32,
    399 			vk::VK_FORMAT_A2B10G10R10_USCALED_PACK32,
    400 			vk::VK_FORMAT_A2B10G10R10_SSCALED_PACK32,
    401 			vk::VK_FORMAT_A2B10G10R10_UINT_PACK32,
    402 			vk::VK_FORMAT_A2B10G10R10_SINT_PACK32,
    403 			vk::VK_FORMAT_R16G16_UNORM,
    404 			vk::VK_FORMAT_R16G16_SNORM,
    405 			vk::VK_FORMAT_R16G16_USCALED,
    406 			vk::VK_FORMAT_R16G16_SSCALED,
    407 			vk::VK_FORMAT_R16G16_UINT,
    408 			vk::VK_FORMAT_R16G16_SINT,
    409 			vk::VK_FORMAT_R16G16_SFLOAT,
    410 			vk::VK_FORMAT_R32_UINT,
    411 			vk::VK_FORMAT_R32_SINT,
    412 			vk::VK_FORMAT_R32_SFLOAT,
    413 			vk::VK_FORMAT_B10G11R11_UFLOAT_PACK32,
    414 			vk::VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
    415 			vk::VK_FORMAT_R10X6G10X6_UNORM_2PACK16,
    416 			vk::VK_FORMAT_R12X4G12X4_UNORM_2PACK16
    417 		};
    418 		const vk::VkFormat class48Bit[] =
    419 		{
    420 			vk::VK_FORMAT_R16G16B16_UNORM,
    421 			vk::VK_FORMAT_R16G16B16_SNORM,
    422 			vk::VK_FORMAT_R16G16B16_USCALED,
    423 			vk::VK_FORMAT_R16G16B16_SSCALED,
    424 			vk::VK_FORMAT_R16G16B16_UINT,
    425 			vk::VK_FORMAT_R16G16B16_SINT,
    426 			vk::VK_FORMAT_R16G16B16_SFLOAT
    427 		};
    428 		const vk::VkFormat class64Bit[] =
    429 		{
    430 			vk::VK_FORMAT_R16G16B16A16_UNORM,
    431 			vk::VK_FORMAT_R16G16B16A16_SNORM,
    432 			vk::VK_FORMAT_R16G16B16A16_USCALED,
    433 			vk::VK_FORMAT_R16G16B16A16_SSCALED,
    434 			vk::VK_FORMAT_R16G16B16A16_UINT,
    435 			vk::VK_FORMAT_R16G16B16A16_SINT,
    436 			vk::VK_FORMAT_R16G16B16A16_SFLOAT,
    437 			vk::VK_FORMAT_R32G32_UINT,
    438 			vk::VK_FORMAT_R32G32_SINT,
    439 			vk::VK_FORMAT_R32G32_SFLOAT,
    440 			vk::VK_FORMAT_R64_UINT,
    441 			vk::VK_FORMAT_R64_SINT,
    442 			vk::VK_FORMAT_R64_SFLOAT
    443 		};
    444 		const vk::VkFormat class96Bit[] =
    445 		{
    446 			vk::VK_FORMAT_R32G32B32_UINT,
    447 			vk::VK_FORMAT_R32G32B32_SINT,
    448 			vk::VK_FORMAT_R32G32B32_SFLOAT
    449 		};
    450 		const vk::VkFormat class128Bit[] =
    451 		{
    452 			vk::VK_FORMAT_R32G32B32A32_UINT,
    453 			vk::VK_FORMAT_R32G32B32A32_SINT,
    454 			vk::VK_FORMAT_R32G32B32A32_SFLOAT,
    455 			vk::VK_FORMAT_R64G64_UINT,
    456 			vk::VK_FORMAT_R64G64_SINT,
    457 			vk::VK_FORMAT_R64G64_SFLOAT
    458 		};
    459 		const vk::VkFormat class192Bit[] =
    460 		{
    461 			vk::VK_FORMAT_R64G64B64_UINT,
    462 			vk::VK_FORMAT_R64G64B64_SINT,
    463 			vk::VK_FORMAT_R64G64B64_SFLOAT
    464 		};
    465 		const vk::VkFormat class256Bit[] =
    466 		{
    467 			vk::VK_FORMAT_R64G64B64A64_UINT,
    468 			vk::VK_FORMAT_R64G64B64A64_SINT,
    469 			vk::VK_FORMAT_R64G64B64A64_SFLOAT
    470 		};
    471 
    472 		if (de::contains(DE_ARRAY_BEGIN(class8Bit), DE_ARRAY_END(class8Bit), srcFormat)
    473 			&& de::contains(DE_ARRAY_BEGIN(class8Bit), DE_ARRAY_END(class8Bit), dstFormat))
    474 			return true;
    475 
    476 		if (de::contains(DE_ARRAY_BEGIN(class16Bit), DE_ARRAY_END(class16Bit), srcFormat)
    477 			&& de::contains(DE_ARRAY_BEGIN(class16Bit), DE_ARRAY_END(class16Bit), dstFormat))
    478 			return true;
    479 
    480 		if (de::contains(DE_ARRAY_BEGIN(class24Bit), DE_ARRAY_END(class24Bit), srcFormat)
    481 			&& de::contains(DE_ARRAY_BEGIN(class24Bit), DE_ARRAY_END(class24Bit), dstFormat))
    482 			return true;
    483 
    484 		if (de::contains(DE_ARRAY_BEGIN(class32Bit), DE_ARRAY_END(class32Bit), srcFormat)
    485 			&& de::contains(DE_ARRAY_BEGIN(class32Bit), DE_ARRAY_END(class32Bit), dstFormat))
    486 			return true;
    487 
    488 		if (de::contains(DE_ARRAY_BEGIN(class48Bit), DE_ARRAY_END(class48Bit), srcFormat)
    489 			&& de::contains(DE_ARRAY_BEGIN(class48Bit), DE_ARRAY_END(class48Bit), dstFormat))
    490 			return true;
    491 
    492 		if (de::contains(DE_ARRAY_BEGIN(class64Bit), DE_ARRAY_END(class64Bit), srcFormat)
    493 			&& de::contains(DE_ARRAY_BEGIN(class64Bit), DE_ARRAY_END(class64Bit), dstFormat))
    494 			return true;
    495 
    496 		if (de::contains(DE_ARRAY_BEGIN(class96Bit), DE_ARRAY_END(class96Bit), srcFormat)
    497 			&& de::contains(DE_ARRAY_BEGIN(class96Bit), DE_ARRAY_END(class96Bit), dstFormat))
    498 			return true;
    499 
    500 		if (de::contains(DE_ARRAY_BEGIN(class128Bit), DE_ARRAY_END(class128Bit), srcFormat)
    501 			&& de::contains(DE_ARRAY_BEGIN(class128Bit), DE_ARRAY_END(class128Bit), dstFormat))
    502 			return true;
    503 
    504 		if (de::contains(DE_ARRAY_BEGIN(class192Bit), DE_ARRAY_END(class192Bit), srcFormat)
    505 			&& de::contains(DE_ARRAY_BEGIN(class192Bit), DE_ARRAY_END(class192Bit), dstFormat))
    506 			return true;
    507 
    508 		if (de::contains(DE_ARRAY_BEGIN(class256Bit), DE_ARRAY_END(class256Bit), srcFormat)
    509 			&& de::contains(DE_ARRAY_BEGIN(class256Bit), DE_ARRAY_END(class256Bit), dstFormat))
    510 			return true;
    511 
    512 		return false;
    513 	}
    514 }
    515 
    516 UVec2 getBlockSize (vk::VkFormat format)
    517 {
    518 	switch (format)
    519 	{
    520 		case vk::VK_FORMAT_G8B8G8R8_422_UNORM:
    521 		case vk::VK_FORMAT_B8G8R8G8_422_UNORM:
    522 		case vk::VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16:
    523 		case vk::VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16:
    524 		case vk::VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16:
    525 		case vk::VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16:
    526 		case vk::VK_FORMAT_G16B16G16R16_422_UNORM:
    527 		case vk::VK_FORMAT_B16G16R16G16_422_UNORM:
    528 			return UVec2(2, 1);
    529 
    530 		default:
    531 			return UVec2(1u, 1u);
    532 	}
    533 }
    534 
    535 deUint32 getBlockByteSize (vk::VkFormat format)
    536 {
    537 	switch (format)
    538 	{
    539 		case vk::VK_FORMAT_B8G8R8G8_422_UNORM:
    540 		case vk::VK_FORMAT_G8B8G8R8_422_UNORM:
    541 			return 4u;
    542 
    543 		case vk::VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16:
    544 		case vk::VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16:
    545 		case vk::VK_FORMAT_B16G16R16G16_422_UNORM:
    546 		case vk::VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16:
    547 		case vk::VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16:
    548 		case vk::VK_FORMAT_G16B16G16R16_422_UNORM:
    549 		case vk::VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16:
    550 		case vk::VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16:
    551 		case vk::VK_FORMAT_R16G16B16A16_UNORM:
    552 			return 4u * 2u;
    553 
    554 		case vk::VK_FORMAT_R10X6_UNORM_PACK16:
    555 		case vk::VK_FORMAT_R12X4_UNORM_PACK16:
    556 			return 2u;
    557 
    558 		case vk::VK_FORMAT_R10X6G10X6_UNORM_2PACK16:
    559 		case vk::VK_FORMAT_R12X4G12X4_UNORM_2PACK16:
    560 			return 2u * 2u;
    561 
    562 		case vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16:
    563 		case vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16:
    564 			return 3u * 2u;
    565 
    566 		case vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
    567 		case vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
    568 		case vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16:
    569 		case vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16:
    570 		case vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16:
    571 		case vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16:
    572 		case vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16:
    573 		case vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16:
    574 		case vk::VK_FORMAT_G16_B16R16_2PLANE_420_UNORM:
    575 		case vk::VK_FORMAT_G16_B16R16_2PLANE_422_UNORM:
    576 		case vk::VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM:
    577 		case vk::VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM:
    578 		case vk::VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM:
    579 		case vk::VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
    580 		case vk::VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:
    581 		case vk::VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
    582 		case vk::VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM:
    583 		case vk::VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM:
    584 			DE_FATAL("Plane formats not supported");
    585 			return ~0u;
    586 
    587 		default:
    588 			return (deUint32)vk::mapVkFormat(format).getPixelSize();
    589 	}
    590 }
    591 
    592 UVec2 getPlaneSize (const vk::PlanarFormatDescription&	info,
    593 					deUint32							planeNdx,
    594 					const UVec2&						size)
    595 {
    596 	if (info.numPlanes > 1)
    597 		return UVec2(size.x() / info.planes[planeNdx].widthDivisor, size.y() / info.planes[planeNdx].heightDivisor);
    598 	else
    599 		return size;
    600 }
    601 
    602 UVec2 randomUVec2 (de::Random&	rng,
    603 				   const UVec2&	min,
    604 				   const UVec2&	max)
    605 {
    606 	UVec2 result;
    607 
    608 	result[0] = min[0] + (rng.getUint32() % (1 + max[0] - min[0]));
    609 	result[1] = min[1] + (rng.getUint32() % (1 + max[1] - min[1]));
    610 
    611 	return result;
    612 }
    613 
    614 void genCopies (de::Random&					rng,
    615 				size_t						copyCount,
    616 				vk::VkFormat				srcFormat,
    617 				const UVec2&				srcSize,
    618 				vk::VkFormat				dstFormat,
    619 				const UVec2&				dstSize,
    620 				vector<vk::VkImageCopy>*	copies)
    621 {
    622 	vector<pair<deUint32, deUint32> >	pairs;
    623 	const vk::PlanarFormatDescription	srcPlaneInfo	(vk::getPlanarFormatDescription(srcFormat));
    624 	const vk::PlanarFormatDescription	dstPlaneInfo	(vk::getPlanarFormatDescription(dstFormat));
    625 
    626 	for (deUint32 srcPlaneNdx = 0; srcPlaneNdx < srcPlaneInfo.numPlanes; srcPlaneNdx++)
    627 	{
    628 		for (deUint32 dstPlaneNdx = 0; dstPlaneNdx < dstPlaneInfo.numPlanes; dstPlaneNdx++)
    629 		{
    630 			const vk::VkFormat srcPlaneFormat (getPlaneCompatibleFormat(srcFormat, srcPlaneNdx));
    631 			const vk::VkFormat dstPlaneFormat (getPlaneCompatibleFormat(dstFormat, dstPlaneNdx));
    632 
    633 			if (isCompatible(srcPlaneFormat, dstPlaneFormat))
    634 				pairs.push_back(std::make_pair(srcPlaneNdx, dstPlaneNdx));
    635 		}
    636 	}
    637 
    638 	DE_ASSERT(!pairs.empty());
    639 
    640 	copies->reserve(copyCount);
    641 
    642 	for (size_t copyNdx = 0; copyNdx < copyCount; copyNdx++)
    643 	{
    644 		const pair<deUint32, deUint32>	planes			(rng.choose<pair<deUint32, deUint32> >(pairs.begin(), pairs.end()));
    645 
    646 		const deUint32					srcPlaneNdx			(planes.first);
    647 		const vk::VkFormat				srcPlaneFormat		(getPlaneCompatibleFormat(srcFormat, srcPlaneNdx));
    648 		const UVec2						srcBlockSize		(getBlockSize(srcPlaneFormat));
    649 		const UVec2						srcPlaneSize		(getPlaneSize(srcPlaneInfo, srcPlaneNdx, srcSize));
    650 		const UVec2						srcPlaneBlockSize	(srcPlaneSize / srcBlockSize);
    651 
    652 		const deUint32					dstPlaneNdx			(planes.second);
    653 		const vk::VkFormat				dstPlaneFormat		(getPlaneCompatibleFormat(dstFormat, dstPlaneNdx));
    654 		const UVec2						dstBlockSize		(getBlockSize(dstPlaneFormat));
    655 		const UVec2						dstPlaneSize		(getPlaneSize(dstPlaneInfo, dstPlaneNdx, dstSize));
    656 		const UVec2						dstPlaneBlockSize	(dstPlaneSize / dstBlockSize);
    657 
    658 		const UVec2						copyBlockSize		(randomUVec2(rng, UVec2(1u, 1u), tcu::min(srcPlaneBlockSize, dstPlaneBlockSize)));
    659 		const UVec2						srcOffset			(srcBlockSize * randomUVec2(rng, UVec2(0u, 0u), srcPlaneBlockSize - copyBlockSize));
    660 		const UVec2						dstOffset			(dstBlockSize * randomUVec2(rng, UVec2(0u, 0u), dstPlaneBlockSize - copyBlockSize));
    661 		const UVec2						copySize			(copyBlockSize * srcBlockSize);
    662 		const vk::VkImageCopy			copy				=
    663 		{
    664 			// src
    665 			{
    666 				static_cast<vk::VkImageAspectFlags>(srcPlaneInfo.numPlanes > 1 ?  vk::getPlaneAspect(srcPlaneNdx) : vk::VK_IMAGE_ASPECT_COLOR_BIT),
    667 				0u,
    668 				0u,
    669 				1u
    670 			},
    671 			{
    672 				(deInt32)srcOffset.x(),
    673 				(deInt32)srcOffset.y(),
    674 				0,
    675 			},
    676 			// dst
    677 			{
    678 				static_cast<vk::VkImageAspectFlags>(dstPlaneInfo.numPlanes > 1 ?  vk::getPlaneAspect(dstPlaneNdx) : vk::VK_IMAGE_ASPECT_COLOR_BIT),
    679 				0u,
    680 				0u,
    681 				1u
    682 			},
    683 			{
    684 				(deInt32)dstOffset.x(),
    685 				(deInt32)dstOffset.y(),
    686 				0,
    687 			},
    688 			// size
    689 			{
    690 				copySize.x(),
    691 				copySize.y(),
    692 				1u
    693 			}
    694 		};
    695 
    696 		copies->push_back(copy);
    697 	}
    698 }
    699 
    700 tcu::SeedBuilder& operator<< (tcu::SeedBuilder& builder, const ImageConfig& config)
    701 {
    702 
    703 	builder << (deUint32)config.format << (deUint32)config.tiling << config.disjoint << config.size[0] << config.size[1];
    704 	return builder;
    705 }
    706 
    707 deUint32 buildSeed (const TestConfig& config)
    708 {
    709 	tcu::SeedBuilder builder;
    710 
    711 	builder << 6792903u << config.src << config.dst;
    712 
    713 	return builder.get();
    714 }
    715 
    716 void logImageInfo (TestLog&				log,
    717 				   const ImageConfig&	config)
    718 {
    719 	log << TestLog::Message << "Format: " << config.format << TestLog::EndMessage;
    720 	log << TestLog::Message << "Tiling: " << config.tiling << TestLog::EndMessage;
    721 	log << TestLog::Message << "Size: " << config.size << TestLog::EndMessage;
    722 	log << TestLog::Message << "Disjoint: " << (config.disjoint ? "true" : "false") << TestLog::EndMessage;
    723 }
    724 void logTestCaseInfo (TestLog&							log,
    725 					  const TestConfig&					config,
    726 					  const vector<vk::VkImageCopy>&	copies)
    727 {
    728 	{
    729 		const tcu::ScopedLogSection section (log, "SourceImage", "SourceImage");
    730 		logImageInfo(log, config.src);
    731 	}
    732 
    733 	{
    734 		const tcu::ScopedLogSection section (log, "DestinationImage", "DestinationImage");
    735 		logImageInfo(log, config.dst);
    736 	}
    737 	{
    738 		const tcu::ScopedLogSection section (log, "Copies", "Copies");
    739 
    740 		for (size_t copyNdx = 0; copyNdx < copies.size(); copyNdx++)
    741 			log << TestLog::Message << copies[copyNdx] << TestLog::EndMessage;
    742 	}
    743 }
    744 
    745 tcu::TestStatus imageCopyTest (Context& context, const TestConfig config)
    746 {
    747 	checkSupport(context, config);
    748 
    749 	{
    750 		const size_t			copyCount	= 10;
    751 		TestLog&				log			(context.getTestContext().getLog());
    752 
    753 		MultiPlaneImageData		srcData		(config.src.format, config.src.size);
    754 		MultiPlaneImageData		dstData		(config.dst.format, config.dst.size);
    755 		MultiPlaneImageData		result		(config.dst.format, config.dst.size);
    756 		vector<vk::VkImageCopy>	copies;
    757 
    758 		de::Random				rng			(buildSeed(config));
    759 
    760 		genCopies(rng, copyCount, config.src.format, config.src.size, config.dst.format, config.dst.size, &copies);
    761 
    762 		logTestCaseInfo(log, config, copies);
    763 
    764 		fillRandom(&rng, &srcData);
    765 		fillRandom(&rng, &dstData);
    766 
    767 		{
    768 			const vk::DeviceInterface&		vkd						(context.getDeviceInterface());
    769 			const vk::VkDevice				device					(context.getDevice());
    770 
    771 			const vk::Unique<vk::VkImage>	srcImage				(createImage(vkd, device, config.src.format, config.src.size, config.src.disjoint, config.src.tiling));
    772 			const vk::MemoryRequirement		srcMemoryRequirement	(config.src.tiling == vk::VK_IMAGE_TILING_OPTIMAL
    773 																	? vk::MemoryRequirement::Any
    774 																	: vk::MemoryRequirement::HostVisible);
    775 			const vk::VkImageCreateFlags	srcCreateFlags			(config.src.disjoint ? vk::VK_IMAGE_CREATE_DISJOINT_BIT : (vk::VkImageCreateFlagBits)0u);
    776 			const vector<AllocationSp>		srcImageMemory			(allocateAndBindImageMemory(vkd, device, context.getDefaultAllocator(), *srcImage, config.src.format, srcCreateFlags, srcMemoryRequirement));
    777 
    778 			const vk::Unique<vk::VkImage>	dstImage				(createImage(vkd, device, config.dst.format, config.dst.size, config.dst.disjoint, config.dst.tiling));
    779 			const vk::MemoryRequirement		dstMemoryRequirement	(config.dst.tiling == vk::VK_IMAGE_TILING_OPTIMAL
    780 																	? vk::MemoryRequirement::Any
    781 																	: vk::MemoryRequirement::HostVisible);
    782 			const vk::VkImageCreateFlags	dstCreateFlags			(config.dst.disjoint ? vk::VK_IMAGE_CREATE_DISJOINT_BIT : (vk::VkImageCreateFlagBits)0u);
    783 			const vector<AllocationSp>		dstImageMemory			(allocateAndBindImageMemory(vkd, device, context.getDefaultAllocator(), *dstImage, config.dst.format, dstCreateFlags, dstMemoryRequirement));
    784 
    785 			if (config.src.tiling == vk::VK_IMAGE_TILING_OPTIMAL)
    786 				uploadImage(vkd, device, context.getUniversalQueueFamilyIndex(), context.getDefaultAllocator(), *srcImage, srcData, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
    787 			else
    788 				fillImageMemory(vkd, device, context.getUniversalQueueFamilyIndex(), *srcImage, srcImageMemory, srcData, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
    789 
    790 			if (config.dst.tiling == vk::VK_IMAGE_TILING_OPTIMAL)
    791 				uploadImage(vkd, device, context.getUniversalQueueFamilyIndex(), context.getDefaultAllocator(), *dstImage, dstData, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
    792 			else
    793 				fillImageMemory(vkd, device, context.getUniversalQueueFamilyIndex(), *dstImage, dstImageMemory, dstData, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
    794 
    795 			{
    796 				const deUint32							queueFamilyNdx	(context.getUniversalQueueFamilyIndex());
    797 				const vk::VkQueue						queue			(context.getUniversalQueue());
    798 				const vk::Unique<vk::VkCommandPool>		cmdPool			(createCommandPool(vkd, device, (vk::VkCommandPoolCreateFlags)0, queueFamilyNdx));
    799 				const vk::Unique<vk::VkCommandBuffer>	cmdBuffer		(allocateCommandBuffer(vkd, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
    800 				{
    801 					const vk::VkCommandBufferBeginInfo	beginInfo		=
    802 					{
    803 						vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
    804 						DE_NULL,
    805 						(vk::VkCommandBufferUsageFlags)vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
    806 						(const vk::VkCommandBufferInheritanceInfo*)DE_NULL
    807 					};
    808 
    809 					VK_CHECK(vkd.beginCommandBuffer(*cmdBuffer, &beginInfo));
    810 				}
    811 
    812 				for (size_t i = 0; i < copies.size(); i++)
    813 				{
    814 					vkd.cmdCopyImage(*cmdBuffer, *srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copies[i]);
    815 
    816 					const vk::VkImageMemoryBarrier preCopyBarrier =
    817 					{
    818 						vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
    819 						DE_NULL,
    820 						vk::VK_ACCESS_TRANSFER_WRITE_BIT,
    821 						vk::VK_ACCESS_TRANSFER_WRITE_BIT,
    822 						vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
    823 						vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
    824 						VK_QUEUE_FAMILY_IGNORED,
    825 						VK_QUEUE_FAMILY_IGNORED,
    826 						*dstImage,
    827 						{ vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }
    828 					};
    829 
    830 					vkd.cmdPipelineBarrier(*cmdBuffer,
    831 											(vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
    832 											(vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
    833 											(vk::VkDependencyFlags)0u,
    834 											0u,
    835 											(const vk::VkMemoryBarrier*)DE_NULL,
    836 											0u,
    837 											(const vk::VkBufferMemoryBarrier*)DE_NULL,
    838 											1u,
    839 											&preCopyBarrier);
    840 				}
    841 
    842 				VK_CHECK(vkd.endCommandBuffer(*cmdBuffer));
    843 
    844 				{
    845 					const vk::Unique<vk::VkFence>	fence		(createFence(vkd, device));
    846 					const vk::VkSubmitInfo			submitInfo	=
    847 					{
    848 						vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
    849 						DE_NULL,
    850 						0u,
    851 						(const vk::VkSemaphore*)DE_NULL,
    852 						(const vk::VkPipelineStageFlags*)DE_NULL,
    853 						1u,
    854 						&*cmdBuffer,
    855 						0u,
    856 						(const vk::VkSemaphore*)DE_NULL,
    857 					};
    858 
    859 					VK_CHECK(vkd.queueSubmit(queue, 1u, &submitInfo, *fence));
    860 					VK_CHECK(vkd.waitForFences(device, 1u, &*fence, VK_TRUE, ~0ull));
    861 				}
    862 			}
    863 
    864 			if (config.dst.tiling == vk::VK_IMAGE_TILING_OPTIMAL)
    865 				downloadImage(vkd, device, context.getUniversalQueueFamilyIndex(), context.getDefaultAllocator(), *dstImage, &result, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
    866 			else
    867 				readImageMemory(vkd, device, context.getUniversalQueueFamilyIndex(), *dstImage, dstImageMemory, &result, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
    868 		}
    869 
    870 		{
    871 			MultiPlaneImageData	reference		(dstData);
    872 			const size_t		maxErrorCount	= 30;
    873 			size_t				errorCount		= 0;
    874 
    875 			for (size_t copyNdx = 0; copyNdx < copies.size(); copyNdx++)
    876 			{
    877 				const vk::VkImageCopy&	copy				(copies[copyNdx]);
    878 
    879 				const deUint32			srcPlaneNdx			(copy.srcSubresource.aspectMask != vk::VK_IMAGE_ASPECT_COLOR_BIT
    880 															? vk::getAspectPlaneNdx((vk::VkImageAspectFlagBits)copy.srcSubresource.aspectMask)
    881 															: 0u);
    882 				const UVec2				srcPlaneSize		(getPlaneSize(srcData.getDescription(), srcPlaneNdx, config.src.size));
    883 
    884 				const vk::VkFormat		srcPlaneFormat		(getPlaneCompatibleFormat(config.src.format, srcPlaneNdx));
    885 				const UVec2				srcBlockSize		(getBlockSize(srcPlaneFormat));
    886 
    887 				const deUint32			blockSizeBytes		(getBlockByteSize(srcPlaneFormat));
    888 
    889 				const UVec2				srcPlaneBlockSize	(srcPlaneSize / srcBlockSize);
    890 				const UVec2				srcBlockOffset		(copy.srcOffset.x / srcBlockSize.x(), copy.srcOffset.y / srcBlockSize.y());
    891 				const UVec2				srcBlockPitch		(blockSizeBytes, blockSizeBytes * srcPlaneBlockSize.x());
    892 
    893 				const deUint32			dstPlaneNdx			(copy.dstSubresource.aspectMask != vk::VK_IMAGE_ASPECT_COLOR_BIT
    894 															? vk::getAspectPlaneNdx((vk::VkImageAspectFlagBits)copy.dstSubresource.aspectMask)
    895 															: 0u);
    896 				const UVec2				dstPlaneSize		(getPlaneSize(dstData.getDescription(), dstPlaneNdx, config.dst.size));
    897 
    898 				const vk::VkFormat		dstPlaneFormat		(getPlaneCompatibleFormat(config.dst.format, dstPlaneNdx));
    899 				const UVec2				dstBlockSize		(getBlockSize(dstPlaneFormat));
    900 
    901 				const UVec2				dstPlaneBlockSize	(dstPlaneSize / dstBlockSize);
    902 				const UVec2				dstBlockOffset		(copy.dstOffset.x / dstBlockSize.x(), copy.dstOffset.y / dstBlockSize.y());
    903 				const UVec2				dstBlockPitch		(blockSizeBytes, blockSizeBytes * dstPlaneBlockSize.x());
    904 
    905 				const UVec2				blockSize			(copy.extent.width / srcBlockSize.x(), copy.extent.height / srcBlockSize.y());
    906 
    907 				DE_ASSERT(blockSizeBytes == getBlockByteSize(dstPlaneFormat));
    908 
    909 				for (deUint32 y = 0; y < blockSize.y(); y++)
    910 				{
    911 					const deUint32	size	= blockSize.x() * blockSizeBytes;
    912 					const deUint32	srcPos	= tcu::dot(srcBlockPitch, UVec2(srcBlockOffset.x(), srcBlockOffset.y() + y));
    913 					const deUint32	dstPos	= tcu::dot(dstBlockPitch, UVec2(dstBlockOffset.x(), dstBlockOffset.y() + y));
    914 
    915 					deMemcpy(((deUint8*)reference.getPlanePtr(dstPlaneNdx)) + dstPos,
    916 							 ((const deUint8*)srcData.getPlanePtr(srcPlaneNdx)) + srcPos, size);
    917 				}
    918 			}
    919 
    920 			for (deUint32 planeNdx = 0; planeNdx < result.getDescription().numPlanes; ++planeNdx)
    921 			{
    922 				for (size_t byteNdx = 0; byteNdx < result.getPlaneSize(planeNdx); byteNdx++)
    923 				{
    924 					const deUint8	res	= ((const deUint8*)result.getPlanePtr(planeNdx))[byteNdx];
    925 					const deUint8	ref	= ((const deUint8*)reference.getPlanePtr(planeNdx))[byteNdx];
    926 
    927 					if (res != ref)
    928 					{
    929 						log << TestLog::Message << "Plane: " << planeNdx << ", Offset: " << byteNdx << ", Expected: " << (deUint32)ref << ", Got: " << (deUint32)res << TestLog::EndMessage;
    930 						errorCount++;
    931 
    932 						if (errorCount > maxErrorCount)
    933 							break;
    934 					}
    935 				}
    936 
    937 				if (errorCount > maxErrorCount)
    938 					break;
    939 			}
    940 
    941 			if (errorCount > 0)
    942 				return tcu::TestStatus::fail("Failed, found " + (errorCount > maxErrorCount ?  de::toString(maxErrorCount) + "+" : de::toString(errorCount))  + " incorrect bytes");
    943 			else
    944 				return tcu::TestStatus::pass("Pass");
    945 		}
    946 	}
    947 }
    948 
    949 bool isCopyCompatible (vk::VkFormat srcFormat, vk::VkFormat dstFormat)
    950 {
    951 	if (isYCbCrFormat(srcFormat) && isYCbCrFormat(dstFormat))
    952 	{
    953 		const vk::PlanarFormatDescription	srcPlaneInfo	(vk::getPlanarFormatDescription(srcFormat));
    954 		const vk::PlanarFormatDescription	dstPlaneInfo	(vk::getPlanarFormatDescription(dstFormat));
    955 
    956 		for (deUint32 srcPlaneNdx = 0; srcPlaneNdx < srcPlaneInfo.numPlanes; srcPlaneNdx++)
    957 		{
    958 			for (deUint32 dstPlaneNdx = 0; dstPlaneNdx < dstPlaneInfo.numPlanes; dstPlaneNdx++)
    959 			{
    960 				const vk::VkFormat srcPlaneFormat (getPlaneCompatibleFormat(srcFormat, srcPlaneNdx));
    961 				const vk::VkFormat dstPlaneFormat (getPlaneCompatibleFormat(dstFormat, dstPlaneNdx));
    962 
    963 				if (isCompatible(srcPlaneFormat, dstPlaneFormat))
    964 					return true;
    965 			}
    966 		}
    967 	}
    968 	else if (isYCbCrFormat(srcFormat))
    969 	{
    970 		const vk::PlanarFormatDescription	srcPlaneInfo	(vk::getPlanarFormatDescription(srcFormat));
    971 
    972 		for (deUint32 srcPlaneNdx = 0; srcPlaneNdx < srcPlaneInfo.numPlanes; srcPlaneNdx++)
    973 		{
    974 			const vk::VkFormat srcPlaneFormat (getPlaneCompatibleFormat(srcFormat, srcPlaneNdx));
    975 
    976 			if (isCompatible(srcPlaneFormat, dstFormat))
    977 				return true;
    978 		}
    979 	}
    980 	else if (isYCbCrFormat(dstFormat))
    981 	{
    982 		const vk::PlanarFormatDescription	dstPlaneInfo	(vk::getPlanarFormatDescription(dstFormat));
    983 
    984 		for (deUint32 dstPlaneNdx = 0; dstPlaneNdx < dstPlaneInfo.numPlanes; dstPlaneNdx++)
    985 		{
    986 			const vk::VkFormat dstPlaneFormat (getPlaneCompatibleFormat(dstFormat, dstPlaneNdx));
    987 
    988 			if (isCompatible(dstPlaneFormat, srcFormat))
    989 				return true;
    990 		}
    991 	}
    992 	else
    993 		return isCompatible(srcFormat, dstFormat);
    994 
    995 	return false;
    996 }
    997 
    998 void initTests (tcu::TestCaseGroup* testGroup)
    999 {
   1000 	const vk::VkFormat ycbcrFormats[] =
   1001 	{
   1002 		vk::VK_FORMAT_R4G4_UNORM_PACK8,
   1003 		vk::VK_FORMAT_R4G4B4A4_UNORM_PACK16,
   1004 		vk::VK_FORMAT_B4G4R4A4_UNORM_PACK16,
   1005 		vk::VK_FORMAT_R5G6B5_UNORM_PACK16,
   1006 		vk::VK_FORMAT_B5G6R5_UNORM_PACK16,
   1007 		vk::VK_FORMAT_R5G5B5A1_UNORM_PACK16,
   1008 		vk::VK_FORMAT_B5G5R5A1_UNORM_PACK16,
   1009 		vk::VK_FORMAT_A1R5G5B5_UNORM_PACK16,
   1010 		vk::VK_FORMAT_R8_UNORM,
   1011 		vk::VK_FORMAT_R8G8_UNORM,
   1012 		vk::VK_FORMAT_R8G8B8_UNORM,
   1013 		vk::VK_FORMAT_B8G8R8_UNORM,
   1014 		vk::VK_FORMAT_R8G8B8A8_UNORM,
   1015 		vk::VK_FORMAT_B8G8R8A8_UNORM,
   1016 		vk::VK_FORMAT_A8B8G8R8_UNORM_PACK32,
   1017 		vk::VK_FORMAT_A2R10G10B10_UNORM_PACK32,
   1018 		vk::VK_FORMAT_R16_UNORM,
   1019 		vk::VK_FORMAT_R16G16_UNORM,
   1020 		vk::VK_FORMAT_R16G16B16_UNORM,
   1021 		vk::VK_FORMAT_R16G16B16A16_UNORM,
   1022 		vk::VK_FORMAT_B10G11R11_UFLOAT_PACK32,
   1023 		vk::VK_FORMAT_G8B8G8R8_422_UNORM,
   1024 		vk::VK_FORMAT_B8G8R8G8_422_UNORM,
   1025 		vk::VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,
   1026 		vk::VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
   1027 		vk::VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM,
   1028 		vk::VK_FORMAT_G8_B8R8_2PLANE_422_UNORM,
   1029 		vk::VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM,
   1030 		vk::VK_FORMAT_R10X6_UNORM_PACK16,
   1031 		vk::VK_FORMAT_R10X6G10X6_UNORM_2PACK16,
   1032 		vk::VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
   1033 		vk::VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16,
   1034 		vk::VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16,
   1035 		vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16,
   1036 		vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
   1037 		vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16,
   1038 		vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,
   1039 		vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16,
   1040 		vk::VK_FORMAT_R12X4_UNORM_PACK16,
   1041 		vk::VK_FORMAT_R12X4G12X4_UNORM_2PACK16,
   1042 		vk::VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16,
   1043 		vk::VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16,
   1044 		vk::VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16,
   1045 		vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16,
   1046 		vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16,
   1047 		vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16,
   1048 		vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16,
   1049 		vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16,
   1050 		vk::VK_FORMAT_G16B16G16R16_422_UNORM,
   1051 		vk::VK_FORMAT_B16G16R16G16_422_UNORM,
   1052 		vk::VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM,
   1053 		vk::VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,
   1054 		vk::VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM,
   1055 		vk::VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,
   1056 		vk::VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM
   1057 	};
   1058 	const struct
   1059 	{
   1060 		const char*			name;
   1061 		vk::VkImageTiling	value;
   1062 	} imageTilings[] =
   1063 	{
   1064 		{ "linear",	vk::VK_IMAGE_TILING_LINEAR },
   1065 		{ "optimal",	vk::VK_IMAGE_TILING_OPTIMAL }
   1066 	};
   1067 	tcu::TestContext&	testCtx	= testGroup->getTestContext();
   1068 
   1069 	for (size_t srcFormatNdx = 0; srcFormatNdx < DE_LENGTH_OF_ARRAY(ycbcrFormats); srcFormatNdx++)
   1070 	{
   1071 		const vk::VkFormat				srcFormat		(ycbcrFormats[srcFormatNdx]);
   1072 		const UVec2						srcSize			(isYCbCrFormat(srcFormat) ? UVec2(24u, 16u) : UVec2(23u, 17u));
   1073 		const string					srcFormatName	(de::toLower(std::string(getFormatName(srcFormat)).substr(10)));
   1074 		de::MovePtr<tcu::TestCaseGroup>	srcFormatGroup	(new tcu::TestCaseGroup(testCtx, srcFormatName.c_str(), ("Tests for copies using format " + srcFormatName).c_str()));
   1075 
   1076 		for (size_t dstFormatNdx = 0; dstFormatNdx < DE_LENGTH_OF_ARRAY(ycbcrFormats); dstFormatNdx++)
   1077 		{
   1078 			const vk::VkFormat				dstFormat		(ycbcrFormats[dstFormatNdx]);
   1079 			const UVec2						dstSize			(isYCbCrFormat(dstFormat) ? UVec2(24u, 16u) : UVec2(23u, 17u));
   1080 			const string					dstFormatName	(de::toLower(std::string(getFormatName(dstFormat)).substr(10)));
   1081 
   1082 			if ((!vk::isYCbCrFormat(srcFormat) && !vk::isYCbCrFormat(dstFormat))
   1083 					|| !isCopyCompatible(srcFormat, dstFormat))
   1084 				continue;
   1085 
   1086 			de::MovePtr<tcu::TestCaseGroup>	dstFormatGroup	(new tcu::TestCaseGroup(testCtx, dstFormatName.c_str(), ("Tests for copies using format " + dstFormatName).c_str()));
   1087 
   1088 			for (size_t srcTilingNdx = 0; srcTilingNdx < DE_LENGTH_OF_ARRAY(imageTilings); srcTilingNdx++)
   1089 			{
   1090 				const vk::VkImageTiling	srcTiling		= imageTilings[srcTilingNdx].value;
   1091 				const char* const		srcTilingName	= imageTilings[srcTilingNdx].name;
   1092 
   1093 				for (size_t dstTilingNdx = 0; dstTilingNdx < DE_LENGTH_OF_ARRAY(imageTilings); dstTilingNdx++)
   1094 				{
   1095 					const vk::VkImageTiling	dstTiling		= imageTilings[dstTilingNdx].value;
   1096 					const char* const		dstTilingName	= imageTilings[dstTilingNdx].name;
   1097 
   1098 					for (size_t srcDisjointNdx = 0; srcDisjointNdx < 2; srcDisjointNdx++)
   1099 					for (size_t dstDisjointNdx = 0; dstDisjointNdx < 2; dstDisjointNdx++)
   1100 					{
   1101 						const bool			srcDisjoint	= srcDisjointNdx == 1;
   1102 						const bool			dstDisjoint	= dstDisjointNdx == 1;
   1103 						const TestConfig	config		(ImageConfig(srcFormat, srcTiling, srcDisjoint, srcSize), ImageConfig(dstFormat, dstTiling, dstDisjoint, dstSize));
   1104 
   1105 						addFunctionCase(dstFormatGroup.get(), string(srcTilingName) + (srcDisjoint ? "_disjoint_" : "_") + string(dstTilingName) + (dstDisjoint ? "_disjoint" : ""), "", imageCopyTest, config);
   1106 					}
   1107 				}
   1108 			}
   1109 
   1110 			srcFormatGroup->addChild(dstFormatGroup.release());
   1111 		}
   1112 
   1113 		testGroup->addChild(srcFormatGroup.release());
   1114 	}
   1115 }
   1116 
   1117 } // anonymous
   1118 
   1119 tcu::TestCaseGroup* createCopyTests (tcu::TestContext& testCtx)
   1120 {
   1121 	return createTestGroup(testCtx, "copy", "YCbCr Format Copy Tests", initTests);
   1122 }
   1123 
   1124 } // ycbcr
   1125 } // vkt
   1126