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 ©(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