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