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