• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "vkCmdUtil.hpp"
34 
35 #include "tcuSeedBuilder.hpp"
36 #include "tcuTestLog.hpp"
37 #include "tcuVector.hpp"
38 #include "tcuVectorUtil.hpp"
39 
40 #include "deRandom.hpp"
41 #include "deSTLUtil.hpp"
42 #include "deStringUtil.hpp"
43 
44 #include <string>
45 #include <utility>
46 #include <vector>
47 
48 using tcu::UVec2;
49 using tcu::Vec4;
50 using tcu::TestLog;
51 
52 
53 using std::string;
54 using std::vector;
55 using std::pair;
56 
57 namespace vkt
58 {
59 namespace ycbcr
60 {
61 namespace
62 {
63 
64 struct ImageConfig
65 {
ImageConfigvkt::ycbcr::__anon037541f80111::ImageConfig66 						ImageConfig	(vk::VkFormat		format_,
67 									 vk::VkImageTiling	tiling_,
68 									 bool				disjoint_,
69 									 const UVec2&		size_)
70 		: format	(format_)
71 		, tiling	(tiling_)
72 		, disjoint	(disjoint_)
73 		, size		(size_)
74 	{
75 	}
76 
77 	vk::VkFormat		format;
78 	vk::VkImageTiling	tiling;
79 	bool				disjoint;
80 	UVec2				size;
81 };
82 
83 struct TestConfig
84 {
TestConfigvkt::ycbcr::__anon037541f80111::TestConfig85 				TestConfig		(const ImageConfig&	src_,
86 								 const ImageConfig&	dst_,
87 								 const bool intermediateBuffer_)
88 		: src					(src_)
89 		, dst					(dst_)
90 		, intermediateBuffer	(intermediateBuffer_)
91 	{
92 	}
93 
94 	ImageConfig	src;
95 	ImageConfig	dst;
96 	bool intermediateBuffer;
97 };
98 
checkFormatSupport(Context & context,const ImageConfig & config)99 void checkFormatSupport(Context& context, const ImageConfig& config)
100 {
101 	const auto&							instInt	(context.getInstanceInterface());
102 
103 	{
104 		const vk::VkPhysicalDeviceImageFormatInfo2			imageFormatInfo				=
105 		{
106 			vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,	// sType;
107 			DE_NULL,													// pNext;
108 			config.format,												// format;
109 			vk::VK_IMAGE_TYPE_2D,										// type;
110 			vk::VK_IMAGE_TILING_OPTIMAL,								// tiling;
111 			vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT |
112 			vk::VK_IMAGE_USAGE_SAMPLED_BIT,									// usage;
113 			(vk::VkImageCreateFlags)0u										// flags
114 		};
115 
116 		vk::VkSamplerYcbcrConversionImageFormatProperties	samplerYcbcrConversionImage = {};
117 		samplerYcbcrConversionImage.sType = vk::VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES;
118 		samplerYcbcrConversionImage.pNext = DE_NULL;
119 
120 		vk::VkImageFormatProperties2						imageFormatProperties		= {};
121 		imageFormatProperties.sType = vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
122 		imageFormatProperties.pNext = &samplerYcbcrConversionImage;
123 
124 		vk::VkResult result = instInt.getPhysicalDeviceImageFormatProperties2(context.getPhysicalDevice(), &imageFormatInfo, &imageFormatProperties);
125 		if (result == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
126 			TCU_THROW(NotSupportedError, "Format not supported.");
127 		VK_CHECK(result);
128 
129 		// Check for plane compatible format support when the disjoint flag is being used
130 		if (config.disjoint)
131 		{
132 			const vk::PlanarFormatDescription				formatDescription		= vk::getPlanarFormatDescription(config.format);
133 
134 			for (deUint32 channelNdx = 0; channelNdx < 4; ++channelNdx)
135 			{
136 				if (!formatDescription.hasChannelNdx(channelNdx))
137 					continue;
138 				deUint32					planeNdx					= formatDescription.channels[channelNdx].planeNdx;
139 				vk::VkFormat				planeCompatibleFormat		= getPlaneCompatibleFormat(formatDescription, planeNdx);
140 
141 				const vk::VkPhysicalDeviceImageFormatInfo2			planeImageFormatInfo				=
142 				{
143 					vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,	// sType;
144 					DE_NULL,												// pNext;
145 					planeCompatibleFormat,									// format;
146 					vk::VK_IMAGE_TYPE_2D,										// type;
147 					vk::VK_IMAGE_TILING_OPTIMAL,								// tiling;
148 					vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT |
149 					vk::VK_IMAGE_USAGE_SAMPLED_BIT,								// usage;
150 					(vk::VkImageCreateFlags)0u									// flags
151 				};
152 
153 				vk::VkResult planesResult = instInt.getPhysicalDeviceImageFormatProperties2(context.getPhysicalDevice(), &planeImageFormatInfo, &imageFormatProperties);
154 				if (planesResult == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
155 					TCU_THROW(NotSupportedError, "Plane compatibile format not supported.");
156 				VK_CHECK(planesResult);
157 			}
158 		}
159 	}
160 
161 	{
162 		const vk::VkFormatProperties	properties	(vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), config.format));
163 		const vk::VkFormatFeatureFlags	features	(config.tiling == vk::VK_IMAGE_TILING_OPTIMAL
164 													? properties.optimalTilingFeatures
165 													: properties.linearTilingFeatures);
166 
167 		if ((features & vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0
168 			&& (features & vk::VK_FORMAT_FEATURE_TRANSFER_DST_BIT) == 0)
169 		{
170 			TCU_THROW(NotSupportedError, "Format doesn't support copies");
171 		}
172 
173 		if (config.disjoint && ((features & vk::VK_FORMAT_FEATURE_DISJOINT_BIT) == 0))
174 			TCU_THROW(NotSupportedError, "Format doesn't support disjoint planes");
175 	}
176 }
177 
checkSupport(Context & context,const TestConfig config)178 void checkSupport (Context& context, const TestConfig config)
179 {
180 	const vk::VkPhysicalDeviceLimits limits = context.getDeviceProperties().limits;
181 
182 	if (config.src.size.x() > limits.maxImageDimension2D || config.src.size.y() > limits.maxImageDimension2D
183 		|| config.dst.size.x() > limits.maxImageDimension2D || config.dst.size.y() > limits.maxImageDimension2D)
184 	{
185 		TCU_THROW(NotSupportedError, "Requested image dimensions not supported");
186 	}
187 
188 	if (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), string("VK_KHR_sampler_ycbcr_conversion")))
189 		TCU_THROW(NotSupportedError, "Extension VK_KHR_sampler_ycbcr_conversion not supported");
190 
191 	const vk::VkPhysicalDeviceSamplerYcbcrConversionFeatures	features = context.getSamplerYcbcrConversionFeatures();
192 	if (features.samplerYcbcrConversion == VK_FALSE)
193 		TCU_THROW(NotSupportedError, "samplerYcbcrConversion feature is not supported");
194 
195 	checkFormatSupport(context, config.src);
196 	checkFormatSupport(context, config.dst);
197 }
198 
createImage(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkFormat format,const UVec2 & size,bool disjoint,vk::VkImageTiling tiling)199 vk::Move<vk::VkImage> createImage (const vk::DeviceInterface&	vkd,
200 								   vk::VkDevice					device,
201 								   vk::VkFormat					format,
202 								   const UVec2&					size,
203 								   bool							disjoint,
204 								   vk::VkImageTiling			tiling)
205 {
206 	const vk::VkImageCreateInfo createInfo =
207 	{
208 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
209 		DE_NULL,
210 		disjoint ? (vk::VkImageCreateFlags)vk::VK_IMAGE_CREATE_DISJOINT_BIT : (vk::VkImageCreateFlags)0u,
211 
212 		vk::VK_IMAGE_TYPE_2D,
213 		format,
214 		vk::makeExtent3D(size.x(), size.y(), 1u),
215 		1u,
216 		1u,
217 		vk::VK_SAMPLE_COUNT_1_BIT,
218 		tiling,
219 		vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
220 		vk::VK_SHARING_MODE_EXCLUSIVE,
221 		0u,
222 		(const deUint32*)DE_NULL,
223 		tiling == vk::VK_IMAGE_TILING_LINEAR ? vk::VK_IMAGE_LAYOUT_PREINITIALIZED : vk::VK_IMAGE_LAYOUT_UNDEFINED,
224 	};
225 
226 	return vk::createImage(vkd, device, &createInfo);
227 }
228 
isCompatible(vk::VkFormat srcFormat,vk::VkFormat dstFormat)229 bool isCompatible (vk::VkFormat	srcFormat,
230 				   vk::VkFormat	dstFormat)
231 {
232 	if (srcFormat == dstFormat)
233 		return true;
234 	else
235 	{
236 		const vk::VkFormat class8Bit[] =
237 		{
238 			vk::VK_FORMAT_R4G4_UNORM_PACK8,
239 			vk::VK_FORMAT_R8_UNORM,
240 			vk::VK_FORMAT_R8_SNORM,
241 			vk::VK_FORMAT_R8_USCALED,
242 			vk::VK_FORMAT_R8_SSCALED,
243 			vk::VK_FORMAT_R8_UINT,
244 			vk::VK_FORMAT_R8_SINT,
245 			vk::VK_FORMAT_R8_SRGB
246 		};
247 		const vk::VkFormat class16Bit[] =
248 		{
249 			vk::VK_FORMAT_R4G4B4A4_UNORM_PACK16,
250 			vk::VK_FORMAT_B4G4R4A4_UNORM_PACK16,
251 			vk::VK_FORMAT_R5G6B5_UNORM_PACK16,
252 			vk::VK_FORMAT_B5G6R5_UNORM_PACK16,
253 			vk::VK_FORMAT_R5G5B5A1_UNORM_PACK16,
254 			vk::VK_FORMAT_B5G5R5A1_UNORM_PACK16,
255 			vk::VK_FORMAT_A1R5G5B5_UNORM_PACK16,
256 			vk::VK_FORMAT_R8G8_UNORM,
257 			vk::VK_FORMAT_R8G8_SNORM,
258 			vk::VK_FORMAT_R8G8_USCALED,
259 			vk::VK_FORMAT_R8G8_SSCALED,
260 			vk::VK_FORMAT_R8G8_UINT,
261 			vk::VK_FORMAT_R8G8_SINT,
262 			vk::VK_FORMAT_R8G8_SRGB,
263 			vk::VK_FORMAT_R16_UNORM,
264 			vk::VK_FORMAT_R16_SNORM,
265 			vk::VK_FORMAT_R16_USCALED,
266 			vk::VK_FORMAT_R16_SSCALED,
267 			vk::VK_FORMAT_R16_UINT,
268 			vk::VK_FORMAT_R16_SINT,
269 			vk::VK_FORMAT_R16_SFLOAT,
270 			vk::VK_FORMAT_R10X6_UNORM_PACK16,
271 			vk::VK_FORMAT_R12X4_UNORM_PACK16
272 		};
273 		const vk::VkFormat class24Bit[] =
274 		{
275 			vk::VK_FORMAT_R8G8B8_UNORM,
276 			vk::VK_FORMAT_R8G8B8_SNORM,
277 			vk::VK_FORMAT_R8G8B8_USCALED,
278 			vk::VK_FORMAT_R8G8B8_SSCALED,
279 			vk::VK_FORMAT_R8G8B8_UINT,
280 			vk::VK_FORMAT_R8G8B8_SINT,
281 			vk::VK_FORMAT_R8G8B8_SRGB,
282 			vk::VK_FORMAT_B8G8R8_UNORM,
283 			vk::VK_FORMAT_B8G8R8_SNORM,
284 			vk::VK_FORMAT_B8G8R8_USCALED,
285 			vk::VK_FORMAT_B8G8R8_SSCALED,
286 			vk::VK_FORMAT_B8G8R8_UINT,
287 			vk::VK_FORMAT_B8G8R8_SINT,
288 			vk::VK_FORMAT_B8G8R8_SRGB
289 		};
290 		const vk::VkFormat class32Bit[] =
291 		{
292 			vk::VK_FORMAT_R8G8B8A8_UNORM,
293 			vk::VK_FORMAT_R8G8B8A8_SNORM,
294 			vk::VK_FORMAT_R8G8B8A8_USCALED,
295 			vk::VK_FORMAT_R8G8B8A8_SSCALED,
296 			vk::VK_FORMAT_R8G8B8A8_UINT,
297 			vk::VK_FORMAT_R8G8B8A8_SINT,
298 			vk::VK_FORMAT_R8G8B8A8_SRGB,
299 			vk::VK_FORMAT_B8G8R8A8_UNORM,
300 			vk::VK_FORMAT_B8G8R8A8_SNORM,
301 			vk::VK_FORMAT_B8G8R8A8_USCALED,
302 			vk::VK_FORMAT_B8G8R8A8_SSCALED,
303 			vk::VK_FORMAT_B8G8R8A8_UINT,
304 			vk::VK_FORMAT_B8G8R8A8_SINT,
305 			vk::VK_FORMAT_B8G8R8A8_SRGB,
306 			vk::VK_FORMAT_A8B8G8R8_UNORM_PACK32,
307 			vk::VK_FORMAT_A8B8G8R8_SNORM_PACK32,
308 			vk::VK_FORMAT_A8B8G8R8_USCALED_PACK32,
309 			vk::VK_FORMAT_A8B8G8R8_SSCALED_PACK32,
310 			vk::VK_FORMAT_A8B8G8R8_UINT_PACK32,
311 			vk::VK_FORMAT_A8B8G8R8_SINT_PACK32,
312 			vk::VK_FORMAT_A8B8G8R8_SRGB_PACK32,
313 			vk::VK_FORMAT_A2R10G10B10_UNORM_PACK32,
314 			vk::VK_FORMAT_A2R10G10B10_SNORM_PACK32,
315 			vk::VK_FORMAT_A2R10G10B10_USCALED_PACK32,
316 			vk::VK_FORMAT_A2R10G10B10_SSCALED_PACK32,
317 			vk::VK_FORMAT_A2R10G10B10_UINT_PACK32,
318 			vk::VK_FORMAT_A2R10G10B10_SINT_PACK32,
319 			vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32,
320 			vk::VK_FORMAT_A2B10G10R10_SNORM_PACK32,
321 			vk::VK_FORMAT_A2B10G10R10_USCALED_PACK32,
322 			vk::VK_FORMAT_A2B10G10R10_SSCALED_PACK32,
323 			vk::VK_FORMAT_A2B10G10R10_UINT_PACK32,
324 			vk::VK_FORMAT_A2B10G10R10_SINT_PACK32,
325 			vk::VK_FORMAT_R16G16_UNORM,
326 			vk::VK_FORMAT_R16G16_SNORM,
327 			vk::VK_FORMAT_R16G16_USCALED,
328 			vk::VK_FORMAT_R16G16_SSCALED,
329 			vk::VK_FORMAT_R16G16_UINT,
330 			vk::VK_FORMAT_R16G16_SINT,
331 			vk::VK_FORMAT_R16G16_SFLOAT,
332 			vk::VK_FORMAT_R32_UINT,
333 			vk::VK_FORMAT_R32_SINT,
334 			vk::VK_FORMAT_R32_SFLOAT,
335 			vk::VK_FORMAT_B10G11R11_UFLOAT_PACK32,
336 			vk::VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
337 			vk::VK_FORMAT_R10X6G10X6_UNORM_2PACK16,
338 			vk::VK_FORMAT_R12X4G12X4_UNORM_2PACK16
339 		};
340 		const vk::VkFormat class48Bit[] =
341 		{
342 			vk::VK_FORMAT_R16G16B16_UNORM,
343 			vk::VK_FORMAT_R16G16B16_SNORM,
344 			vk::VK_FORMAT_R16G16B16_USCALED,
345 			vk::VK_FORMAT_R16G16B16_SSCALED,
346 			vk::VK_FORMAT_R16G16B16_UINT,
347 			vk::VK_FORMAT_R16G16B16_SINT,
348 			vk::VK_FORMAT_R16G16B16_SFLOAT
349 		};
350 		const vk::VkFormat class64Bit[] =
351 		{
352 			vk::VK_FORMAT_R16G16B16A16_UNORM,
353 			vk::VK_FORMAT_R16G16B16A16_SNORM,
354 			vk::VK_FORMAT_R16G16B16A16_USCALED,
355 			vk::VK_FORMAT_R16G16B16A16_SSCALED,
356 			vk::VK_FORMAT_R16G16B16A16_UINT,
357 			vk::VK_FORMAT_R16G16B16A16_SINT,
358 			vk::VK_FORMAT_R16G16B16A16_SFLOAT,
359 			vk::VK_FORMAT_R32G32_UINT,
360 			vk::VK_FORMAT_R32G32_SINT,
361 			vk::VK_FORMAT_R32G32_SFLOAT,
362 			vk::VK_FORMAT_R64_UINT,
363 			vk::VK_FORMAT_R64_SINT,
364 			vk::VK_FORMAT_R64_SFLOAT
365 		};
366 		const vk::VkFormat class96Bit[] =
367 		{
368 			vk::VK_FORMAT_R32G32B32_UINT,
369 			vk::VK_FORMAT_R32G32B32_SINT,
370 			vk::VK_FORMAT_R32G32B32_SFLOAT
371 		};
372 		const vk::VkFormat class128Bit[] =
373 		{
374 			vk::VK_FORMAT_R32G32B32A32_UINT,
375 			vk::VK_FORMAT_R32G32B32A32_SINT,
376 			vk::VK_FORMAT_R32G32B32A32_SFLOAT,
377 			vk::VK_FORMAT_R64G64_UINT,
378 			vk::VK_FORMAT_R64G64_SINT,
379 			vk::VK_FORMAT_R64G64_SFLOAT
380 		};
381 		const vk::VkFormat class192Bit[] =
382 		{
383 			vk::VK_FORMAT_R64G64B64_UINT,
384 			vk::VK_FORMAT_R64G64B64_SINT,
385 			vk::VK_FORMAT_R64G64B64_SFLOAT
386 		};
387 		const vk::VkFormat class256Bit[] =
388 		{
389 			vk::VK_FORMAT_R64G64B64A64_UINT,
390 			vk::VK_FORMAT_R64G64B64A64_SINT,
391 			vk::VK_FORMAT_R64G64B64A64_SFLOAT
392 		};
393 
394 		if (de::contains(DE_ARRAY_BEGIN(class8Bit), DE_ARRAY_END(class8Bit), srcFormat)
395 			&& de::contains(DE_ARRAY_BEGIN(class8Bit), DE_ARRAY_END(class8Bit), dstFormat))
396 			return true;
397 
398 		if (de::contains(DE_ARRAY_BEGIN(class16Bit), DE_ARRAY_END(class16Bit), srcFormat)
399 			&& de::contains(DE_ARRAY_BEGIN(class16Bit), DE_ARRAY_END(class16Bit), dstFormat))
400 			return true;
401 
402 		if (de::contains(DE_ARRAY_BEGIN(class24Bit), DE_ARRAY_END(class24Bit), srcFormat)
403 			&& de::contains(DE_ARRAY_BEGIN(class24Bit), DE_ARRAY_END(class24Bit), dstFormat))
404 			return true;
405 
406 		if (de::contains(DE_ARRAY_BEGIN(class32Bit), DE_ARRAY_END(class32Bit), srcFormat)
407 			&& de::contains(DE_ARRAY_BEGIN(class32Bit), DE_ARRAY_END(class32Bit), dstFormat))
408 			return true;
409 
410 		if (de::contains(DE_ARRAY_BEGIN(class48Bit), DE_ARRAY_END(class48Bit), srcFormat)
411 			&& de::contains(DE_ARRAY_BEGIN(class48Bit), DE_ARRAY_END(class48Bit), dstFormat))
412 			return true;
413 
414 		if (de::contains(DE_ARRAY_BEGIN(class64Bit), DE_ARRAY_END(class64Bit), srcFormat)
415 			&& de::contains(DE_ARRAY_BEGIN(class64Bit), DE_ARRAY_END(class64Bit), dstFormat))
416 			return true;
417 
418 		if (de::contains(DE_ARRAY_BEGIN(class96Bit), DE_ARRAY_END(class96Bit), srcFormat)
419 			&& de::contains(DE_ARRAY_BEGIN(class96Bit), DE_ARRAY_END(class96Bit), dstFormat))
420 			return true;
421 
422 		if (de::contains(DE_ARRAY_BEGIN(class128Bit), DE_ARRAY_END(class128Bit), srcFormat)
423 			&& de::contains(DE_ARRAY_BEGIN(class128Bit), DE_ARRAY_END(class128Bit), dstFormat))
424 			return true;
425 
426 		if (de::contains(DE_ARRAY_BEGIN(class192Bit), DE_ARRAY_END(class192Bit), srcFormat)
427 			&& de::contains(DE_ARRAY_BEGIN(class192Bit), DE_ARRAY_END(class192Bit), dstFormat))
428 			return true;
429 
430 		if (de::contains(DE_ARRAY_BEGIN(class256Bit), DE_ARRAY_END(class256Bit), srcFormat)
431 			&& de::contains(DE_ARRAY_BEGIN(class256Bit), DE_ARRAY_END(class256Bit), dstFormat))
432 			return true;
433 
434 		return false;
435 	}
436 }
437 
getBlockByteSize(vk::VkFormat format)438 deUint32 getBlockByteSize (vk::VkFormat format)
439 {
440 	switch (format)
441 	{
442 		case vk::VK_FORMAT_B8G8R8G8_422_UNORM:
443 		case vk::VK_FORMAT_G8B8G8R8_422_UNORM:
444 			return 4u;
445 
446 		case vk::VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16:
447 		case vk::VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16:
448 		case vk::VK_FORMAT_B16G16R16G16_422_UNORM:
449 		case vk::VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16:
450 		case vk::VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16:
451 		case vk::VK_FORMAT_G16B16G16R16_422_UNORM:
452 		case vk::VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16:
453 		case vk::VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16:
454 		case vk::VK_FORMAT_R16G16B16A16_UNORM:
455 			return 4u * 2u;
456 
457 		case vk::VK_FORMAT_R10X6_UNORM_PACK16:
458 		case vk::VK_FORMAT_R12X4_UNORM_PACK16:
459 			return 2u;
460 
461 		case vk::VK_FORMAT_R10X6G10X6_UNORM_2PACK16:
462 		case vk::VK_FORMAT_R12X4G12X4_UNORM_2PACK16:
463 			return 2u * 2u;
464 
465 		case vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16:
466 		case vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16:
467 			return 3u * 2u;
468 
469 		case vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
470 		case vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
471 		case vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16:
472 		case vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16:
473 		case vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16:
474 		case vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16:
475 		case vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16:
476 		case vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16:
477 		case vk::VK_FORMAT_G16_B16R16_2PLANE_420_UNORM:
478 		case vk::VK_FORMAT_G16_B16R16_2PLANE_422_UNORM:
479 		case vk::VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM:
480 		case vk::VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM:
481 		case vk::VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM:
482 		case vk::VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
483 		case vk::VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:
484 		case vk::VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
485 		case vk::VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM:
486 		case vk::VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM:
487 		case vk::VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT:
488 		case vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT:
489 		case vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT:
490 		case vk::VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT:
491 			DE_FATAL("Plane formats not supported");
492 			return ~0u;
493 
494 		default:
495 			return (deUint32)vk::mapVkFormat(format).getPixelSize();
496 	}
497 }
498 
randomUVec2(de::Random & rng,const UVec2 & min,const UVec2 & max)499 UVec2 randomUVec2 (de::Random&	rng,
500 				   const UVec2&	min,
501 				   const UVec2&	max)
502 {
503 	UVec2 result;
504 
505 	result[0] = min[0] + (rng.getUint32() % (1 + max[0] - min[0]));
506 	result[1] = min[1] + (rng.getUint32() % (1 + max[1] - min[1]));
507 
508 	return result;
509 }
510 
genCopies(de::Random & rng,size_t copyCount,vk::VkFormat srcFormat,const UVec2 & srcSize,vk::VkFormat dstFormat,const UVec2 & dstSize,vector<vk::VkImageCopy> * copies)511 void genCopies (de::Random&					rng,
512 				size_t						copyCount,
513 				vk::VkFormat				srcFormat,
514 				const UVec2&				srcSize,
515 				vk::VkFormat				dstFormat,
516 				const UVec2&				dstSize,
517 				vector<vk::VkImageCopy>*	copies)
518 {
519 	vector<pair<deUint32, deUint32> >	pairs;
520 	const vk::PlanarFormatDescription	srcPlaneInfo	(vk::getPlanarFormatDescription(srcFormat));
521 	const vk::PlanarFormatDescription	dstPlaneInfo	(vk::getPlanarFormatDescription(dstFormat));
522 
523 	for (deUint32 srcPlaneNdx = 0; srcPlaneNdx < srcPlaneInfo.numPlanes; srcPlaneNdx++)
524 	{
525 		for (deUint32 dstPlaneNdx = 0; dstPlaneNdx < dstPlaneInfo.numPlanes; dstPlaneNdx++)
526 		{
527 			const vk::VkFormat srcPlaneFormat (getPlaneCompatibleFormat(srcPlaneInfo, srcPlaneNdx));
528 			const vk::VkFormat dstPlaneFormat (getPlaneCompatibleFormat(dstPlaneInfo, dstPlaneNdx));
529 
530 			if (isCompatible(srcPlaneFormat, dstPlaneFormat))
531 				pairs.push_back(std::make_pair(srcPlaneNdx, dstPlaneNdx));
532 		}
533 	}
534 
535 	DE_ASSERT(!pairs.empty());
536 
537 	copies->reserve(copyCount);
538 
539 	for (size_t copyNdx = 0; copyNdx < copyCount; copyNdx++)
540 	{
541 		const pair<deUint32, deUint32>	planes			(rng.choose<pair<deUint32, deUint32> >(pairs.begin(), pairs.end()));
542 
543 		const deUint32					srcPlaneNdx			(planes.first);
544 		const vk::VkFormat				srcPlaneFormat		(getPlaneCompatibleFormat(srcPlaneInfo, srcPlaneNdx));
545 		const UVec2						srcBlockExtent		(getBlockExtent(srcPlaneFormat));
546 		const UVec2						srcPlaneExtent		(getPlaneExtent(srcPlaneInfo, srcSize, srcPlaneNdx, 0));
547 		const UVec2						srcPlaneBlockExtent	(srcPlaneExtent / srcBlockExtent);
548 
549 		const deUint32					dstPlaneNdx			(planes.second);
550 		const vk::VkFormat				dstPlaneFormat		(getPlaneCompatibleFormat(dstPlaneInfo, dstPlaneNdx));
551 		const UVec2						dstBlockExtent		(getBlockExtent(dstPlaneFormat));
552 		const UVec2						dstPlaneExtent		(getPlaneExtent(dstPlaneInfo, dstSize, dstPlaneNdx, 0));
553 		const UVec2						dstPlaneBlockExtent	(dstPlaneExtent / dstBlockExtent);
554 
555 		const UVec2						copyBlockExtent		(randomUVec2(rng, UVec2(1u, 1u), tcu::min(srcPlaneBlockExtent, dstPlaneBlockExtent)));
556 		const UVec2						srcOffset			(srcBlockExtent * randomUVec2(rng, UVec2(0u, 0u), srcPlaneBlockExtent - copyBlockExtent));
557 		const UVec2						dstOffset			(dstBlockExtent * randomUVec2(rng, UVec2(0u, 0u), dstPlaneBlockExtent - copyBlockExtent));
558 		const UVec2						copyExtent			(copyBlockExtent * srcBlockExtent);
559 		const vk::VkImageCopy			copy				=
560 		{
561 			// src
562 			{
563 				static_cast<vk::VkImageAspectFlags>(srcPlaneInfo.numPlanes > 1 ?  vk::getPlaneAspect(srcPlaneNdx) : vk::VK_IMAGE_ASPECT_COLOR_BIT),
564 				0u,
565 				0u,
566 				1u
567 			},
568 			{
569 				(deInt32)srcOffset.x(),
570 				(deInt32)srcOffset.y(),
571 				0,
572 			},
573 			// dst
574 			{
575 				static_cast<vk::VkImageAspectFlags>(dstPlaneInfo.numPlanes > 1 ?  vk::getPlaneAspect(dstPlaneNdx) : vk::VK_IMAGE_ASPECT_COLOR_BIT),
576 				0u,
577 				0u,
578 				1u
579 			},
580 			{
581 				(deInt32)dstOffset.x(),
582 				(deInt32)dstOffset.y(),
583 				0,
584 			},
585 			// size
586 			{
587 				copyExtent.x(),
588 				copyExtent.y(),
589 				1u
590 			}
591 		};
592 
593 		copies->push_back(copy);
594 	}
595 }
596 
operator <<(tcu::SeedBuilder & builder,const ImageConfig & config)597 tcu::SeedBuilder& operator<< (tcu::SeedBuilder& builder, const ImageConfig& config)
598 {
599 
600 	builder << (deUint32)config.format << (deUint32)config.tiling << config.disjoint << config.size[0] << config.size[1];
601 	return builder;
602 }
603 
buildSeed(const TestConfig & config)604 deUint32 buildSeed (const TestConfig& config)
605 {
606 	tcu::SeedBuilder builder;
607 
608 	builder << 6792903u << config.src << config.dst;
609 
610 	return builder.get();
611 }
612 
logImageInfo(TestLog & log,const ImageConfig & config)613 void logImageInfo (TestLog&				log,
614 				   const ImageConfig&	config)
615 {
616 	log << TestLog::Message << "Format: " << config.format << TestLog::EndMessage;
617 	log << TestLog::Message << "Tiling: " << config.tiling << TestLog::EndMessage;
618 	log << TestLog::Message << "Size: " << config.size << TestLog::EndMessage;
619 	log << TestLog::Message << "Disjoint: " << (config.disjoint ? "true" : "false") << TestLog::EndMessage;
620 }
logTestCaseInfo(TestLog & log,const TestConfig & config,const vector<vk::VkImageCopy> & copies)621 void logTestCaseInfo (TestLog&							log,
622 					  const TestConfig&					config,
623 					  const vector<vk::VkImageCopy>&	copies)
624 {
625 	{
626 		const tcu::ScopedLogSection section (log, "SourceImage", "SourceImage");
627 		logImageInfo(log, config.src);
628 	}
629 
630 	{
631 		const tcu::ScopedLogSection section (log, "DestinationImage", "DestinationImage");
632 		logImageInfo(log, config.dst);
633 	}
634 	{
635 		const tcu::ScopedLogSection section (log, "Copies", "Copies");
636 
637 		for (size_t copyNdx = 0; copyNdx < copies.size(); copyNdx++)
638 			log << TestLog::Message << copies[copyNdx] << TestLog::EndMessage;
639 	}
640 }
641 
chooseFloatFormat(vk::VkFormat srcFormat,vk::VkFormat dstFormat)642 vk::VkFormat chooseFloatFormat(vk::VkFormat srcFormat, vk::VkFormat dstFormat) {
643 	const std::vector<vk::VkFormat> floatFormats =
644 	{
645 		vk::VK_FORMAT_B10G11R11_UFLOAT_PACK32,
646 		vk::VK_FORMAT_R16_SFLOAT,
647 		vk::VK_FORMAT_R16G16_SFLOAT,
648 		vk::VK_FORMAT_R16G16B16_SFLOAT,
649 		vk::VK_FORMAT_R16G16B16A16_SFLOAT,
650 		vk::VK_FORMAT_R32_SFLOAT,
651 		vk::VK_FORMAT_R32G32_SFLOAT,
652 		vk::VK_FORMAT_R32G32B32_SFLOAT,
653 		vk::VK_FORMAT_R32G32B32A32_SFLOAT,
654 		vk::VK_FORMAT_R64_SFLOAT,
655 		vk::VK_FORMAT_R64G64_SFLOAT,
656 		vk::VK_FORMAT_R64G64B64_SFLOAT,
657 		vk::VK_FORMAT_R64G64B64A64_SFLOAT,
658 	};
659 
660 	if (std::find(floatFormats.begin(), floatFormats.end(), srcFormat) != floatFormats.end())
661 		return srcFormat;
662 
663 	return dstFormat;
664 }
665 
imageCopyTest(Context & context,const TestConfig config)666 tcu::TestStatus imageCopyTest (Context& context, const TestConfig config)
667 {
668 	{
669 		const size_t			copyCount	= 10;
670 		TestLog&				log			(context.getTestContext().getLog());
671 
672 		MultiPlaneImageData		srcData		(config.src.format, config.src.size);
673 		MultiPlaneImageData		dstData		(config.dst.format, config.dst.size);
674 		MultiPlaneImageData		result		(config.dst.format, config.dst.size);
675 		vector<vk::VkImageCopy>	copies;
676 
677 		de::Random				rng			(buildSeed(config));
678 		const bool				noNan		= true;
679 
680 		genCopies(rng, copyCount, config.src.format, config.src.size, config.dst.format, config.dst.size, &copies);
681 
682 		logTestCaseInfo(log, config, copies);
683 
684 		// To avoid putting NaNs in dst in the image copy
685 		fillRandom(&rng, &srcData, chooseFloatFormat(config.src.format, config.dst.format), noNan);
686 		fillRandom(&rng, &dstData, config.dst.format, noNan);
687 
688 		{
689 			const vk::DeviceInterface&		vkd						(context.getDeviceInterface());
690 			const vk::VkDevice				device					(context.getDevice());
691 
692 			const vk::Unique<vk::VkImage>	srcImage				(createImage(vkd, device, config.src.format, config.src.size, config.src.disjoint, config.src.tiling));
693 			const vk::MemoryRequirement		srcMemoryRequirement	(config.src.tiling == vk::VK_IMAGE_TILING_OPTIMAL
694 																	? vk::MemoryRequirement::Any
695 																	: vk::MemoryRequirement::HostVisible);
696 			const vk::VkImageCreateFlags	srcCreateFlags			(config.src.disjoint ? vk::VK_IMAGE_CREATE_DISJOINT_BIT : (vk::VkImageCreateFlagBits)0u);
697 			const vector<AllocationSp>		srcImageMemory			(allocateAndBindImageMemory(vkd, device, context.getDefaultAllocator(), *srcImage, config.src.format, srcCreateFlags, srcMemoryRequirement));
698 
699 			const vk::Unique<vk::VkImage>	dstImage				(createImage(vkd, device, config.dst.format, config.dst.size, config.dst.disjoint, config.dst.tiling));
700 			const vk::MemoryRequirement		dstMemoryRequirement	(config.dst.tiling == vk::VK_IMAGE_TILING_OPTIMAL
701 																	? vk::MemoryRequirement::Any
702 																	: vk::MemoryRequirement::HostVisible);
703 			const vk::VkImageCreateFlags	dstCreateFlags			(config.dst.disjoint ? vk::VK_IMAGE_CREATE_DISJOINT_BIT : (vk::VkImageCreateFlagBits)0u);
704 			const vector<AllocationSp>		dstImageMemory			(allocateAndBindImageMemory(vkd, device, context.getDefaultAllocator(), *dstImage, config.dst.format, dstCreateFlags, dstMemoryRequirement));
705 
706 			if (config.src.tiling == vk::VK_IMAGE_TILING_OPTIMAL)
707 				uploadImage(vkd, device, context.getUniversalQueueFamilyIndex(), context.getDefaultAllocator(), *srcImage, srcData, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
708 			else
709 				fillImageMemory(vkd, device, context.getUniversalQueueFamilyIndex(), *srcImage, srcImageMemory, srcData, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
710 
711 			if (config.dst.tiling == vk::VK_IMAGE_TILING_OPTIMAL)
712 				uploadImage(vkd, device, context.getUniversalQueueFamilyIndex(), context.getDefaultAllocator(), *dstImage, dstData, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
713 			else
714 				fillImageMemory(vkd, device, context.getUniversalQueueFamilyIndex(), *dstImage, dstImageMemory, dstData, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
715 
716 			{
717 				const deUint32							queueFamilyNdx		(context.getUniversalQueueFamilyIndex());
718 				const vk::VkQueue						queue				(context.getUniversalQueue());
719 				const vk::Unique<vk::VkCommandPool>		cmdPool				(createCommandPool(vkd, device, (vk::VkCommandPoolCreateFlags)0, queueFamilyNdx));
720 				const vk::Unique<vk::VkCommandBuffer>	cmdBuffer			(allocateCommandBuffer(vkd, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
721 
722 				beginCommandBuffer(vkd, *cmdBuffer);
723 
724 				std::vector<de::MovePtr<vk::BufferWithMemory>> buffers(copies.size());
725 
726 				for (size_t i = 0; i < copies.size(); i++)
727 				{
728 					const deUint32							srcPlaneNdx			(copies[i].srcSubresource.aspectMask != vk::VK_IMAGE_ASPECT_COLOR_BIT
729 																				? vk::getAspectPlaneNdx((vk::VkImageAspectFlagBits)copies[i].srcSubresource.aspectMask)
730 																				: 0u);
731 
732 					const vk::VkFormat						srcPlaneFormat		(getPlaneCompatibleFormat(config.src.format, srcPlaneNdx));
733 
734 					const deUint32							blockSizeBytes		(getBlockByteSize(srcPlaneFormat));
735 					const vk::VkDeviceSize					bufferSize			= config.src.size.x() * config.src.size.y() * blockSizeBytes;
736 					const vk::VkBufferCreateInfo			bufferCreateInfo	=
737 					{
738 						vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,									// VkStructureType		sType;
739 						DE_NULL,																	// const void*			pNext;
740 						0u,																			// VkBufferCreateFlags	flags;
741 						bufferSize,																	// VkDeviceSize			size;
742 						vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,// VkBufferUsageFlags	usage;
743 						vk::VK_SHARING_MODE_EXCLUSIVE,												// VkSharingMode		sharingMode;
744 						0u,																			// deUint32				queueFamilyIndexCount;
745 						(const deUint32*)DE_NULL,													// const deUint32*		pQueueFamilyIndices;
746 					};
747 					buffers[i] = de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(vkd, device, context.getDefaultAllocator(), bufferCreateInfo, vk::MemoryRequirement::Any));
748 
749 					if (config.intermediateBuffer)
750 					{
751 						const vk::VkBufferImageCopy imageToBufferCopy = {
752 							0u,							//	VkDeviceSize				bufferOffset;
753 							0u,							//	uint32_t					bufferRowLength;
754 							0u,							//	uint32_t					bufferImageHeight;
755 							copies[i].srcSubresource,	//	VkImageSubresourceLayers	imageSubresource;
756 							copies[i].srcOffset,		//	VkOffset3D					imageOffset;
757 							copies[i].extent,			//	VkExtent3D					imageExtent;
758 						};
759 						vkd.cmdCopyImageToBuffer(*cmdBuffer, *srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **buffers[i], 1, &imageToBufferCopy);
760 
761 						const vk::VkBufferMemoryBarrier bufferBarrier =
762 						{
763 							vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,// VkStructureType	sType;
764 							DE_NULL,									// const void*		pNext;
765 							vk::VK_ACCESS_TRANSFER_WRITE_BIT,			// VkAccessFlags	srcAccessMask;
766 							vk::VK_ACCESS_TRANSFER_READ_BIT,			// VkAccessFlags	dstAccessMask;
767 							VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
768 							VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
769 							**buffers[i],								// VkBuffer			buffer;
770 							0u,											// VkDeviceSize		offset;
771 							VK_WHOLE_SIZE,								// VkDeviceSize		size;
772 						};
773 
774 						vkd.cmdPipelineBarrier(*cmdBuffer,
775 												(vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
776 												(vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
777 												(vk::VkDependencyFlags)0u,
778 												0u,
779 												(const vk::VkMemoryBarrier*)DE_NULL,
780 												1u,
781 												&bufferBarrier,
782 												0u,
783 												(const vk::VkImageMemoryBarrier*)DE_NULL);
784 
785 						const vk::VkBufferImageCopy bufferToImageCopy = {
786 							0u,							//	VkDeviceSize				bufferOffset;
787 							0u,							//	uint32_t					bufferRowLength;
788 							0u,							//	uint32_t					bufferImageHeight;
789 							copies[i].dstSubresource,	//	VkImageSubresourceLayers	imageSubresource;
790 							copies[i].dstOffset,		//	VkOffset3D					imageOffset;
791 							copies[i].extent,			//	VkExtent3D					imageExtent;
792 						};
793 						vkd.cmdCopyBufferToImage(*cmdBuffer, **buffers[i], *dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferToImageCopy);
794 					}
795 					else
796 					{
797 						vkd.cmdCopyImage(*cmdBuffer, *srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copies[i]);
798 					}
799 
800 					const vk::VkImageMemoryBarrier preCopyBarrier =
801 					{
802 						vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
803 						DE_NULL,
804 						vk::VK_ACCESS_TRANSFER_WRITE_BIT,
805 						vk::VK_ACCESS_TRANSFER_READ_BIT | vk::VK_ACCESS_TRANSFER_WRITE_BIT,
806 						vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
807 						vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
808 						VK_QUEUE_FAMILY_IGNORED,
809 						VK_QUEUE_FAMILY_IGNORED,
810 						*dstImage,
811 						{ vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }
812 					};
813 
814 					vkd.cmdPipelineBarrier(*cmdBuffer,
815 											(vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
816 											(vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
817 											(vk::VkDependencyFlags)0u,
818 											0u,
819 											(const vk::VkMemoryBarrier*)DE_NULL,
820 											0u,
821 											(const vk::VkBufferMemoryBarrier*)DE_NULL,
822 											1u,
823 											&preCopyBarrier);
824 				}
825 
826 				endCommandBuffer(vkd, *cmdBuffer);
827 
828 				submitCommandsAndWait(vkd, device, queue, *cmdBuffer);
829 			}
830 
831 			if (config.dst.tiling == vk::VK_IMAGE_TILING_OPTIMAL)
832 				downloadImage(vkd, device, context.getUniversalQueueFamilyIndex(), context.getDefaultAllocator(), *dstImage, &result, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
833 			else
834 				readImageMemory(vkd, device, context.getUniversalQueueFamilyIndex(), *dstImage, dstImageMemory, &result, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
835 		}
836 
837 		{
838 			MultiPlaneImageData	reference		(dstData);
839 			const size_t		maxErrorCount	= 30;
840 			size_t				errorCount		= 0;
841 
842 			for (size_t copyNdx = 0; copyNdx < copies.size(); copyNdx++)
843 			{
844 				const vk::VkImageCopy&	copy				(copies[copyNdx]);
845 
846 				const deUint32			srcPlaneNdx			(copy.srcSubresource.aspectMask != vk::VK_IMAGE_ASPECT_COLOR_BIT
847 															? vk::getAspectPlaneNdx((vk::VkImageAspectFlagBits)copy.srcSubresource.aspectMask)
848 															: 0u);
849 				const UVec2				srcPlaneExtent		(getPlaneExtent(srcData.getDescription(), config.src.size, srcPlaneNdx, 0));
850 
851 				const vk::VkFormat		srcPlaneFormat		(getPlaneCompatibleFormat(config.src.format, srcPlaneNdx));
852 				const UVec2				srcBlockExtent		(getBlockExtent(srcPlaneFormat));
853 
854 				const deUint32			blockSizeBytes		(getBlockByteSize(srcPlaneFormat));
855 
856 				const UVec2				srcPlaneBlockExtent	(srcPlaneExtent / srcBlockExtent);
857 				const UVec2				srcBlockOffset		(copy.srcOffset.x / srcBlockExtent.x(), copy.srcOffset.y / srcBlockExtent.y());
858 				const UVec2				srcBlockPitch		(blockSizeBytes, blockSizeBytes * srcPlaneBlockExtent.x());
859 
860 				const deUint32			dstPlaneNdx			(copy.dstSubresource.aspectMask != vk::VK_IMAGE_ASPECT_COLOR_BIT
861 															? vk::getAspectPlaneNdx((vk::VkImageAspectFlagBits)copy.dstSubresource.aspectMask)
862 															: 0u);
863 				const UVec2				dstPlaneExtent		(getPlaneExtent(dstData.getDescription(), config.dst.size, dstPlaneNdx, 0));
864 
865 				const vk::VkFormat		dstPlaneFormat		(getPlaneCompatibleFormat(config.dst.format, dstPlaneNdx));
866 				const UVec2				dstBlockExtent		(getBlockExtent(dstPlaneFormat));
867 
868 				const UVec2				dstPlaneBlockExtent	(dstPlaneExtent / dstBlockExtent);
869 				const UVec2				dstBlockOffset		(copy.dstOffset.x / dstBlockExtent.x(), copy.dstOffset.y / dstBlockExtent.y());
870 				const UVec2				dstBlockPitch		(blockSizeBytes, blockSizeBytes * dstPlaneBlockExtent.x());
871 
872 				const UVec2				blockExtent			(copy.extent.width / srcBlockExtent.x(), copy.extent.height / srcBlockExtent.y());
873 
874 				DE_ASSERT(blockSizeBytes == getBlockByteSize(dstPlaneFormat));
875 
876 				for (deUint32 y = 0; y < blockExtent.y(); y++)
877 				{
878 					const deUint32	size	= blockExtent.x() * blockSizeBytes;
879 					const deUint32	srcPos	= tcu::dot(srcBlockPitch, UVec2(srcBlockOffset.x(), srcBlockOffset.y() + y));
880 					const deUint32	dstPos	= tcu::dot(dstBlockPitch, UVec2(dstBlockOffset.x(), dstBlockOffset.y() + y));
881 
882 					deMemcpy(((deUint8*)reference.getPlanePtr(dstPlaneNdx)) + dstPos,
883 							 ((const deUint8*)srcData.getPlanePtr(srcPlaneNdx)) + srcPos, size);
884 				}
885 			}
886 
887 			bool ignoreLsb6Bits = areLsb6BitsDontCare(srcData.getFormat(), dstData.getFormat());
888 			bool ignoreLsb4Bits = areLsb4BitsDontCare(srcData.getFormat(), dstData.getFormat());
889 
890 			for (deUint32 planeNdx = 0; planeNdx < result.getDescription().numPlanes; ++planeNdx)
891 			{
892 				deUint32 planeSize = vk::getPlaneSizeInBytes(result.getDescription(), result.getSize(), planeNdx, 0u, 1u);
893 				for (size_t byteNdx = 0; byteNdx < planeSize; byteNdx++)
894 				{
895 					const deUint8	res	= ((const deUint8*)result.getPlanePtr(planeNdx))[byteNdx];
896 					const deUint8	ref	= ((const deUint8*)reference.getPlanePtr(planeNdx))[byteNdx];
897 
898 					deUint8 mask = 0xFF;
899 					if (!(byteNdx & 0x01) && (ignoreLsb6Bits))
900 						mask = 0xC0;
901 					else if (!(byteNdx & 0x01) && (ignoreLsb4Bits))
902 						mask = 0xF0;
903 
904 					if ((res & mask) != (ref & mask))
905 					{
906 						log << TestLog::Message << "Plane: " << planeNdx << ", Offset: " << byteNdx << ", Expected: " << (deUint32)(ref & mask) << ", Got: " << (deUint32)(res & mask) << TestLog::EndMessage;
907 						errorCount++;
908 
909 						if (errorCount > maxErrorCount)
910 							break;
911 					}
912 				}
913 
914 				if (errorCount > maxErrorCount)
915 					break;
916 			}
917 
918 			if (errorCount > 0)
919 				return tcu::TestStatus::fail("Failed, found " + (errorCount > maxErrorCount ?  de::toString(maxErrorCount) + "+" : de::toString(errorCount))  + " incorrect bytes");
920 			else
921 				return tcu::TestStatus::pass("Pass");
922 		}
923 	}
924 }
925 
isCopyCompatible(vk::VkFormat srcFormat,vk::VkFormat dstFormat)926 bool isCopyCompatible (vk::VkFormat srcFormat, vk::VkFormat dstFormat)
927 {
928 	if (isYCbCrFormat(srcFormat) && isYCbCrFormat(dstFormat))
929 	{
930 		const vk::PlanarFormatDescription	srcPlaneInfo	(vk::getPlanarFormatDescription(srcFormat));
931 		const vk::PlanarFormatDescription	dstPlaneInfo	(vk::getPlanarFormatDescription(dstFormat));
932 
933 		for (deUint32 srcPlaneNdx = 0; srcPlaneNdx < srcPlaneInfo.numPlanes; srcPlaneNdx++)
934 		{
935 			for (deUint32 dstPlaneNdx = 0; dstPlaneNdx < dstPlaneInfo.numPlanes; dstPlaneNdx++)
936 			{
937 				const vk::VkFormat srcPlaneFormat (getPlaneCompatibleFormat(srcFormat, srcPlaneNdx));
938 				const vk::VkFormat dstPlaneFormat (getPlaneCompatibleFormat(dstFormat, dstPlaneNdx));
939 
940 				if (isCompatible(srcPlaneFormat, dstPlaneFormat))
941 					return true;
942 			}
943 		}
944 	}
945 	else if (isYCbCrFormat(srcFormat))
946 	{
947 		const vk::PlanarFormatDescription	srcPlaneInfo	(vk::getPlanarFormatDescription(srcFormat));
948 
949 		for (deUint32 srcPlaneNdx = 0; srcPlaneNdx < srcPlaneInfo.numPlanes; srcPlaneNdx++)
950 		{
951 			const vk::VkFormat srcPlaneFormat (getPlaneCompatibleFormat(srcFormat, srcPlaneNdx));
952 
953 			if (isCompatible(srcPlaneFormat, dstFormat))
954 				return true;
955 		}
956 	}
957 	else if (isYCbCrFormat(dstFormat))
958 	{
959 		const vk::PlanarFormatDescription	dstPlaneInfo	(vk::getPlanarFormatDescription(dstFormat));
960 
961 		for (deUint32 dstPlaneNdx = 0; dstPlaneNdx < dstPlaneInfo.numPlanes; dstPlaneNdx++)
962 		{
963 			const vk::VkFormat dstPlaneFormat (getPlaneCompatibleFormat(dstFormat, dstPlaneNdx));
964 
965 			if (isCompatible(dstPlaneFormat, srcFormat))
966 				return true;
967 		}
968 	}
969 	else
970 		return isCompatible(srcFormat, dstFormat);
971 
972 	return false;
973 }
974 
initYcbcrDefaultCopyTests(tcu::TestCaseGroup * testGroup)975 void initYcbcrDefaultCopyTests (tcu::TestCaseGroup* testGroup)
976 {
977 	const vk::VkFormat ycbcrFormats[] =
978 	{
979 		vk::VK_FORMAT_R4G4_UNORM_PACK8,
980 		vk::VK_FORMAT_R4G4B4A4_UNORM_PACK16,
981 		vk::VK_FORMAT_B4G4R4A4_UNORM_PACK16,
982 		vk::VK_FORMAT_R5G6B5_UNORM_PACK16,
983 		vk::VK_FORMAT_B5G6R5_UNORM_PACK16,
984 		vk::VK_FORMAT_R5G5B5A1_UNORM_PACK16,
985 		vk::VK_FORMAT_B5G5R5A1_UNORM_PACK16,
986 		vk::VK_FORMAT_A1R5G5B5_UNORM_PACK16,
987 		vk::VK_FORMAT_R8_UNORM,
988 		vk::VK_FORMAT_R8G8_UNORM,
989 		vk::VK_FORMAT_R8G8B8_UNORM,
990 		vk::VK_FORMAT_B8G8R8_UNORM,
991 		vk::VK_FORMAT_R8G8B8A8_UNORM,
992 		vk::VK_FORMAT_B8G8R8A8_UNORM,
993 		vk::VK_FORMAT_A8B8G8R8_UNORM_PACK32,
994 		vk::VK_FORMAT_A2R10G10B10_UNORM_PACK32,
995 		vk::VK_FORMAT_R16_UNORM,
996 		vk::VK_FORMAT_R16G16_UNORM,
997 		vk::VK_FORMAT_R16G16B16_UNORM,
998 		vk::VK_FORMAT_R16G16B16A16_UNORM,
999 		vk::VK_FORMAT_B10G11R11_UFLOAT_PACK32,
1000 		vk::VK_FORMAT_G8B8G8R8_422_UNORM,
1001 		vk::VK_FORMAT_B8G8R8G8_422_UNORM,
1002 		vk::VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,
1003 		vk::VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
1004 		vk::VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM,
1005 		vk::VK_FORMAT_G8_B8R8_2PLANE_422_UNORM,
1006 		vk::VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM,
1007 		vk::VK_FORMAT_R10X6_UNORM_PACK16,
1008 		vk::VK_FORMAT_R10X6G10X6_UNORM_2PACK16,
1009 		vk::VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
1010 		vk::VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16,
1011 		vk::VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16,
1012 		vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16,
1013 		vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
1014 		vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16,
1015 		vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,
1016 		vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16,
1017 		vk::VK_FORMAT_R12X4_UNORM_PACK16,
1018 		vk::VK_FORMAT_R12X4G12X4_UNORM_2PACK16,
1019 		vk::VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16,
1020 		vk::VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16,
1021 		vk::VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16,
1022 		vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16,
1023 		vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16,
1024 		vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16,
1025 		vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16,
1026 		vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16,
1027 		vk::VK_FORMAT_G16B16G16R16_422_UNORM,
1028 		vk::VK_FORMAT_B16G16R16G16_422_UNORM,
1029 		vk::VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM,
1030 		vk::VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,
1031 		vk::VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM,
1032 		vk::VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,
1033 		vk::VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM,
1034 		vk::VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT,
1035 		vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT,
1036 		vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT,
1037 		vk::VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT,
1038 	};
1039 	const struct
1040 	{
1041 		const char*			name;
1042 		vk::VkImageTiling	value;
1043 	} imageTilings[] =
1044 	{
1045 		{ "linear",	vk::VK_IMAGE_TILING_LINEAR },
1046 		{ "optimal",	vk::VK_IMAGE_TILING_OPTIMAL }
1047 	};
1048 	tcu::TestContext&	testCtx	= testGroup->getTestContext();
1049 
1050 	for (size_t srcFormatNdx = 0; srcFormatNdx < DE_LENGTH_OF_ARRAY(ycbcrFormats); srcFormatNdx++)
1051 	{
1052 		const vk::VkFormat				srcFormat		(ycbcrFormats[srcFormatNdx]);
1053 		const UVec2						srcSize			(isYCbCrFormat(srcFormat) ? UVec2(24u, 16u) : UVec2(23u, 17u));
1054 		const string					srcFormatName	(de::toLower(std::string(getFormatName(srcFormat)).substr(10)));
1055 		de::MovePtr<tcu::TestCaseGroup>	srcFormatGroup	(new tcu::TestCaseGroup(testCtx, srcFormatName.c_str()));
1056 
1057 		for (size_t dstFormatNdx = 0; dstFormatNdx < DE_LENGTH_OF_ARRAY(ycbcrFormats); dstFormatNdx++)
1058 		{
1059 			const vk::VkFormat				dstFormat		(ycbcrFormats[dstFormatNdx]);
1060 			const UVec2						dstSize			(isYCbCrFormat(dstFormat) ? UVec2(24u, 16u) : UVec2(23u, 17u));
1061 			const string					dstFormatName	(de::toLower(std::string(getFormatName(dstFormat)).substr(10)));
1062 
1063 			if ((!vk::isYCbCrFormat(srcFormat) && !vk::isYCbCrFormat(dstFormat))
1064 					|| !isCopyCompatible(srcFormat, dstFormat))
1065 				continue;
1066 
1067 			de::MovePtr<tcu::TestCaseGroup>	dstFormatGroup	(new tcu::TestCaseGroup(testCtx, dstFormatName.c_str()));
1068 
1069 			for (size_t srcTilingNdx = 0; srcTilingNdx < DE_LENGTH_OF_ARRAY(imageTilings); srcTilingNdx++)
1070 			{
1071 				const vk::VkImageTiling	srcTiling		= imageTilings[srcTilingNdx].value;
1072 				const char* const		srcTilingName	= imageTilings[srcTilingNdx].name;
1073 
1074 				for (size_t dstTilingNdx = 0; dstTilingNdx < DE_LENGTH_OF_ARRAY(imageTilings); dstTilingNdx++)
1075 				{
1076 					const vk::VkImageTiling	dstTiling		= imageTilings[dstTilingNdx].value;
1077 					const char* const		dstTilingName	= imageTilings[dstTilingNdx].name;
1078 
1079 					for (size_t srcDisjointNdx = 0; srcDisjointNdx < 2; srcDisjointNdx++)
1080 					for (size_t dstDisjointNdx = 0; dstDisjointNdx < 2; dstDisjointNdx++)
1081 					for (size_t useBufferNdx = 0; useBufferNdx < 2; useBufferNdx++)
1082 					{
1083 						const bool			srcDisjoint			= srcDisjointNdx == 1;
1084 						const bool			dstDisjoint			= dstDisjointNdx == 1;
1085 						const bool			useBuffer			= useBufferNdx == 1;
1086 						const TestConfig	config		(ImageConfig(srcFormat, srcTiling, srcDisjoint, srcSize), ImageConfig(dstFormat, dstTiling, dstDisjoint, dstSize), useBuffer);
1087 
1088 						addFunctionCase(dstFormatGroup.get(), string(srcTilingName) + (srcDisjoint ? "_disjoint_" : "_") + (useBuffer ? "buffer_" : "") + string(dstTilingName) + (dstDisjoint ? "_disjoint" : ""), checkSupport, imageCopyTest, config);
1089 					}
1090 				}
1091 			}
1092 
1093 			srcFormatGroup->addChild(dstFormatGroup.release());
1094 		}
1095 
1096 		testGroup->addChild(srcFormatGroup.release());
1097 	}
1098 }
1099 
initYcbcrDimensionsCopyTests(tcu::TestCaseGroup * testGroup)1100 void initYcbcrDimensionsCopyTests (tcu::TestCaseGroup* testGroup)
1101 {
1102 	tcu::TestContext&	testCtx				= testGroup->getTestContext();
1103 
1104 	const vk::VkFormat	testFormats[]		=
1105 	{
1106 		// 8-bit
1107 		vk::VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,
1108 		// 10-bit
1109 		vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16,
1110 		// 12-bit
1111 		vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16,
1112 		// 16-bit
1113 		vk::VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM,
1114 		// Non-ycbcr
1115 		vk::VK_FORMAT_R8G8B8A8_UNORM,
1116 	};
1117 
1118 	const tcu::UVec2	imageDimensions[]	=
1119 	{
1120 		// Wide: large pot x small pot
1121 		tcu::UVec2(4096,	4u),
1122 		tcu::UVec2(8192,	4u),
1123 		tcu::UVec2(16384,	4u),
1124 		tcu::UVec2(32768,	4u),
1125 
1126 		// Wide: large pot x small npot
1127 		tcu::UVec2(4096,	6u),
1128 		tcu::UVec2(8192,	6u),
1129 		tcu::UVec2(16384,	6u),
1130 		tcu::UVec2(32768,	6u),
1131 
1132 		// Tall: small pot x large pot
1133 		tcu::UVec2(4u, 4096),
1134 		tcu::UVec2(4u, 8192),
1135 		tcu::UVec2(4u, 16384),
1136 		tcu::UVec2(4u, 32768),
1137 
1138 		// Tall: small npot x large pot
1139 		tcu::UVec2(6u, 4096),
1140 		tcu::UVec2(6u, 8192),
1141 		tcu::UVec2(6u, 16384),
1142 		tcu::UVec2(6u, 32768)
1143 	};
1144 
1145 	const struct
1146 	{
1147 		const char*			name;
1148 		vk::VkImageTiling	value;
1149 	} imageTilings[] =
1150 	{
1151 		{ "linear",		vk::VK_IMAGE_TILING_LINEAR	},
1152 		{ "optimal",	vk::VK_IMAGE_TILING_OPTIMAL	}
1153 	};
1154 
1155 	for (size_t imageDimensionNdx = 0; imageDimensionNdx < DE_LENGTH_OF_ARRAY(imageDimensions); imageDimensionNdx++)
1156 	{
1157 		const UVec2						srcSize			(imageDimensions[imageDimensionNdx]);
1158 		const UVec2						dstSize			(imageDimensions[imageDimensionNdx]);
1159 		const string					dimensionsName	("src" + de::toString(srcSize.x()) + "x" + de::toString(srcSize.y()) + "_dst" + de::toString(dstSize.x()) + "x" + de::toString(dstSize.y()));
1160 
1161 		de::MovePtr<tcu::TestCaseGroup>	dimensionGroup	(new tcu::TestCaseGroup(testCtx, dimensionsName.c_str()));
1162 
1163 		for (size_t srcFormatNdx = 0; srcFormatNdx < DE_LENGTH_OF_ARRAY(testFormats); srcFormatNdx++)
1164 		{
1165 			const vk::VkFormat				srcFormat		(testFormats[srcFormatNdx]);
1166 			const string					srcFormatName	(de::toLower(std::string(getFormatName(srcFormat)).substr(10)));
1167 			de::MovePtr<tcu::TestCaseGroup>	srcFormatGroup	(new tcu::TestCaseGroup(testCtx, srcFormatName.c_str()));
1168 
1169 			for (size_t dstFormatNdx = 0; dstFormatNdx < DE_LENGTH_OF_ARRAY(testFormats); dstFormatNdx++)
1170 			{
1171 				const vk::VkFormat	dstFormat		(testFormats[dstFormatNdx]);
1172 				const string		dstFormatName	(de::toLower(std::string(getFormatName(dstFormat)).substr(10)));
1173 
1174 				if ((!vk::isYCbCrFormat(srcFormat) && !vk::isYCbCrFormat(dstFormat))
1175 						|| !isCopyCompatible(srcFormat, dstFormat))
1176 					continue;
1177 
1178 				de::MovePtr<tcu::TestCaseGroup>	dstFormatGroup	(new tcu::TestCaseGroup(testCtx, dstFormatName.c_str()));
1179 
1180 				for (size_t srcTilingNdx = 0; srcTilingNdx < DE_LENGTH_OF_ARRAY(imageTilings); srcTilingNdx++)
1181 				{
1182 					const vk::VkImageTiling	srcTiling		= imageTilings[srcTilingNdx].value;
1183 					const char* const		srcTilingName	= imageTilings[srcTilingNdx].name;
1184 
1185 					for (size_t dstTilingNdx = 0; dstTilingNdx < DE_LENGTH_OF_ARRAY(imageTilings); dstTilingNdx++)
1186 					{
1187 						const vk::VkImageTiling	dstTiling		= imageTilings[dstTilingNdx].value;
1188 						const char* const		dstTilingName	= imageTilings[dstTilingNdx].name;
1189 
1190 						for (size_t srcDisjointNdx = 0; srcDisjointNdx < 2; srcDisjointNdx++)
1191 						for (size_t dstDisjointNdx = 0; dstDisjointNdx < 2; dstDisjointNdx++)
1192 						{
1193 							const bool			srcDisjoint	= srcDisjointNdx == 1;
1194 							const bool			dstDisjoint	= dstDisjointNdx == 1;
1195 							const TestConfig	config		(ImageConfig(srcFormat, srcTiling, srcDisjoint, srcSize), ImageConfig(dstFormat, dstTiling, dstDisjoint, dstSize), false);
1196 
1197 							addFunctionCase(dstFormatGroup.get(), string(srcTilingName) + (srcDisjoint ? "_disjoint_" : "_") + string(dstTilingName) + (dstDisjoint ? "_disjoint" : ""), checkSupport, imageCopyTest, config);
1198 						}
1199 					}
1200 				}
1201 
1202 				srcFormatGroup->addChild(dstFormatGroup.release());
1203 			}
1204 
1205 			dimensionGroup->addChild(srcFormatGroup.release());
1206 		}
1207 
1208 		testGroup->addChild(dimensionGroup.release());
1209 	}
1210 }
1211 
1212 } // anonymous
1213 
createCopyTests(tcu::TestContext & testCtx)1214 tcu::TestCaseGroup* createCopyTests (tcu::TestContext& testCtx)
1215 {
1216 	return createTestGroup(testCtx, "copy", initYcbcrDefaultCopyTests);
1217 }
1218 
createDimensionsCopyTests(tcu::TestContext & testCtx)1219 tcu::TestCaseGroup* createDimensionsCopyTests (tcu::TestContext& testCtx)
1220 {
1221 	return createTestGroup(testCtx, "copy_dimensions", initYcbcrDimensionsCopyTests);
1222 }
1223 
1224 } // ycbcr
1225 } // vkt
1226