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