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