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