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