Merge vk-gl-cts/vulkan-cts-1.3.4 into vk-gl-cts/vulkan-cts-1.3.5
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / api / vktApiImageCompressionControlTests.cpp
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  *
6  * Copyright (c) 2022 Khronos Group
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */ /*!
21 * \file
22 * \brief Test for Image Compression control
23 */ /*--------------------------------------------------------------------*/
24
25 #include <iostream>
26 #include <typeinfo>
27
28 #include "tcuCommandLine.hpp"
29 #include "tcuDefs.hpp"
30 #include "tcuFunctionLibrary.hpp"
31 #include "tcuPlatform.hpp"
32 #include "tcuResultCollector.hpp"
33 #include "tcuTestCase.hpp"
34 #include "tcuTestLog.hpp"
35
36 #include "vkApiVersion.hpp"
37 #include "vkDefs.hpp"
38 #include "vkPlatform.hpp"
39
40 #include "vktApiVersionCheck.hpp"
41 #include "vktCustomInstancesDevices.hpp"
42 #include "vktExternalMemoryUtil.hpp"
43 #include "vktTestCase.hpp"
44 #include "vktTestCaseUtil.hpp"
45 #include "vktTestGroupUtil.hpp"
46 #include "wsi/vktNativeObjectsUtil.hpp"
47
48 #include "vkDeviceUtil.hpp"
49 #include "vkImageUtil.hpp"
50 #include "vkQueryUtil.hpp"
51 #include "vkRefUtil.hpp"
52 #include "vkWsiUtil.hpp"
53
54 #include "deString.h"
55 #include "deStringUtil.hpp"
56
57 #include <map>
58 #include <vector>
59
60 using namespace vk;
61 using namespace vk::wsi;
62 using namespace std;
63
64 typedef vector<VkExtensionProperties> Extensions;
65
66 namespace vkt
67 {
68
69 namespace api
70 {
71
72 struct TestParams
73 {
74         VkFormat                                         format;
75         bool                                             useExtension;
76         VkImageCompressionControlEXT control;
77         Type                                             wsiType;
78 };
79
80 static void checkImageCompressionControlSupport(Context& context, bool swapchain = false)
81 {
82         context.requireDeviceFunctionality("VK_EXT_image_compression_control");
83         vk::VkPhysicalDeviceImageCompressionControlFeaturesEXT imageCompressionControlFeatures    = initVulkanStructure();
84         vk::VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT imageCompressionSwapchain = initVulkanStructure();
85         vk::VkPhysicalDeviceFeatures2 features2 = initVulkanStructure(&imageCompressionControlFeatures);
86         if (swapchain)
87         {
88                 context.requireDeviceFunctionality("VK_EXT_image_compression_control_swapchain");
89                 imageCompressionControlFeatures.pNext = &imageCompressionSwapchain;
90         }
91
92         context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
93
94         if (!imageCompressionControlFeatures.imageCompressionControl)
95                 TCU_THROW(NotSupportedError, "VK_EXT_image_compression_control Image "
96                                                                          "compression control feature not supported.");
97         if (swapchain && !imageCompressionSwapchain.imageCompressionControlSwapchain)
98                 TCU_THROW(NotSupportedError, "VK_EXT_image_compression_control_swapchain Image "
99                                                                          "compression control feature for swapchains not supported.");
100 }
101
102 static void validate(const InstanceInterface& vki, const DeviceInterface& vkd, tcu::ResultCollector& results,
103                                          VkPhysicalDevice physicalDevice, VkDevice device, TestParams& testParams, VkImage image)
104 {
105         constexpr VkImageAspectFlags planeAspects[]{ VK_IMAGE_ASPECT_PLANE_0_BIT, VK_IMAGE_ASPECT_PLANE_1_BIT,
106                                                                                                  VK_IMAGE_ASPECT_PLANE_2_BIT };
107         const bool isYCbCr   = isYCbCrFormat(testParams.format);
108         const int  numPlanes = isYCbCr ? getPlaneCount(testParams.format) : 1;
109         for (int planeIndex = 0; planeIndex < numPlanes; planeIndex++)
110         {
111                 VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT;
112                 if (isYCbCr)
113                 {
114                         aspect = planeAspects[planeIndex];
115                 }
116
117                 VkImageCompressionPropertiesEXT compressionProperties = initVulkanStructure();
118                 VkImageSubresource2EXT                  subresource                       = initVulkanStructure();
119                 subresource.imageSubresource.aspectMask                           = aspect;
120                 VkSubresourceLayout2EXT subresourceLayout                         = initVulkanStructure(&compressionProperties);
121                 vkd.getImageSubresourceLayout2EXT(device, image, &subresource, &subresourceLayout);
122
123                 VkImageCompressionControlEXT compressionEnabled           = initVulkanStructure();
124                 compressionEnabled.compressionControlPlaneCount           = testParams.control.compressionControlPlaneCount;
125                 compressionEnabled.flags                                                          = testParams.control.flags;
126                 VkImageCompressionFixedRateFlagsEXT fixedRateFlags[3] = {
127                         VK_IMAGE_COMPRESSION_FIXED_RATE_FLAG_BITS_MAX_ENUM_EXT,
128                         VK_IMAGE_COMPRESSION_FIXED_RATE_FLAG_BITS_MAX_ENUM_EXT,
129                         VK_IMAGE_COMPRESSION_FIXED_RATE_FLAG_BITS_MAX_ENUM_EXT
130                 };
131
132                 if (compressionEnabled.compressionControlPlaneCount > 0)
133                 {
134                         compressionEnabled.pFixedRateFlags = fixedRateFlags;
135                 }
136
137                 VkPhysicalDeviceImageFormatInfo2 formatInfo = initVulkanStructure(&compressionEnabled);
138                 formatInfo.format                                                       = testParams.format;
139                 formatInfo.type                                                         = VK_IMAGE_TYPE_2D;
140                 formatInfo.tiling                                                       = VK_IMAGE_TILING_OPTIMAL;
141                 formatInfo.usage                                                        = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
142
143                 VkImageCompressionPropertiesEXT compressionPropertiesSupported = initVulkanStructure();
144                 VkImageFormatProperties2                properties2 = initVulkanStructure(&compressionPropertiesSupported);
145
146                 vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &formatInfo, &properties2);
147
148                 if (testParams.useExtension)
149                 {
150                         if ((compressionPropertiesSupported.imageCompressionFixedRateFlags &
151                                  compressionProperties.imageCompressionFixedRateFlags) !=
152                                 compressionProperties.imageCompressionFixedRateFlags)
153                         {
154                                 results.fail("Got image with fixed rate flags that are not supported "
155                                                          "in image format properties.");
156                         }
157                         if ((compressionPropertiesSupported.imageCompressionFlags & compressionProperties.imageCompressionFlags) !=
158                                         compressionProperties.imageCompressionFlags &&
159                                 compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DISABLED_EXT)
160                         {
161                                 results.fail("Got image with compression flags that are not supported "
162                                                          "in image format properties.");
163                         }
164                         if (testParams.control.flags == VK_IMAGE_COMPRESSION_DEFAULT_EXT &&
165                                 compressionProperties.imageCompressionFixedRateFlags != 0)
166                         {
167                                 results.fail("Got lossy compression when DEFAULT compression was requested.");
168                         }
169                         if (testParams.control.flags == VK_IMAGE_COMPRESSION_DISABLED_EXT &&
170                                 compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DISABLED_EXT)
171                         {
172                                 results.fail("Image compression not disabled.");
173                         }
174                         if (testParams.control.flags == VK_IMAGE_COMPRESSION_DISABLED_EXT &&
175                                 compressionProperties.imageCompressionFixedRateFlags != 0)
176                         {
177                                 results.fail("Image compression disabled but got fixed rate flags.");
178                         }
179                         if (testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT &&
180                                 !(compressionProperties.imageCompressionFlags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT ||
181                                   compressionProperties.imageCompressionFlags == VK_IMAGE_COMPRESSION_DISABLED_EXT ||
182                                   compressionProperties.imageCompressionFlags == VK_IMAGE_COMPRESSION_DEFAULT_EXT))
183                         {
184                                 results.fail("Explicit compression flags not returned for image "
185                                                          "creation with FIXED RATE DEFAULT.");
186                         }
187
188                         if (testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT)
189                         {
190                                 uint32_t minRequestedRate = 1 << deCtz32(testParams.control.pFixedRateFlags[planeIndex]);
191                                 uint32_t actualRate               = compressionProperties.imageCompressionFixedRateFlags;
192                                 if (compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DISABLED_EXT &&
193                                         compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DEFAULT_EXT)
194                                 {
195
196                                         if (minRequestedRate > actualRate)
197                                         {
198                                                 results.fail("Image created with less bpc than requested.");
199                                         }
200                                 }
201                         }
202                 }
203                 else
204                 {
205                         if (compressionProperties.imageCompressionFixedRateFlags != VK_IMAGE_COMPRESSION_FIXED_RATE_NONE_EXT)
206                         {
207                                 results.fail("Fixed rate compression should not be enabled.");
208                         }
209
210                         if (compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DISABLED_EXT &&
211                                 compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DEFAULT_EXT)
212                         {
213                                 results.fail("Image compression should be default or not be enabled.");
214                         }
215                 }
216         }
217 }
218
219 static void checkAhbImageSupport (const Context& context, const TestParams testParams, const deUint32 width, const deUint32     height, const VkImageUsageFlagBits vkUsage)
220 {
221         using namespace vkt::ExternalMemoryUtil;
222
223         // Check android hardware buffer can be allocated for the format with usage.
224         AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
225         if (!ahbApi)
226         {
227                 TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
228         }
229         deUint64 ahbUsage =  ahbApi->vkUsageToAhbUsage(vkUsage);
230         {
231                 pt::AndroidHardwareBufferPtr ahb = ahbApi->allocate(width,height, 1, ahbApi->vkFormatToAhbFormat(testParams.format), ahbUsage);
232                 if (ahb.internal == DE_NULL)
233                 {
234                         TCU_THROW(NotSupportedError, "Android hardware buffer format not supported");
235                 }
236         }
237
238         // Check external memory supported.
239         const VkPhysicalDeviceExternalImageFormatInfoKHR external_image_format_info =
240         {
241                 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
242                 &testParams.control,
243                 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
244         };
245
246         const VkPhysicalDeviceImageFormatInfo2                  info                            =
247         {
248                 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
249                 &external_image_format_info,
250                 testParams.format,
251                 VK_IMAGE_TYPE_2D,
252                 VK_IMAGE_TILING_OPTIMAL,
253                 VK_IMAGE_USAGE_SAMPLED_BIT,
254                 0,
255         };
256
257         VkImageCompressionPropertiesEXT compressionPropertiesSupported =
258         {
259                 VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT,
260                 DE_NULL,
261                 0,
262                 0
263         };
264
265         VkAndroidHardwareBufferUsageANDROID             ahbUsageProperties      =
266         {
267                 VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID,
268                 &compressionPropertiesSupported,
269                 0u
270         };
271
272         VkExternalImageFormatProperties                                 externalProperties      =
273         {
274                 VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
275                 &ahbUsageProperties,
276                 { 0u, 0u, 0u }
277         };
278
279         VkImageFormatProperties2                                                properties                      =
280         {
281                 VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
282                 &externalProperties,
283                 {
284                         { 0u, 0u, 0u },
285                         0u,
286                         0u,
287                         0u,
288                         0u
289                 }
290         };
291
292         VkResult result = context.getInstanceInterface().getPhysicalDeviceImageFormatProperties2(context.getPhysicalDevice(), &info, &properties);
293
294         if(result == VK_ERROR_FORMAT_NOT_SUPPORTED)
295                 TCU_THROW(NotSupportedError, "Format not supported");
296
297         if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) == 0)
298                 TCU_THROW(NotSupportedError, "External handle type doesn't support exporting image");
299
300         if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0)
301                 TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
302
303         if((compressionPropertiesSupported.imageCompressionFlags == VK_IMAGE_COMPRESSION_DISABLED_EXT)
304                 && (testParams.control.flags != VK_IMAGE_COMPRESSION_DISABLED_EXT))
305         {
306                 TCU_THROW(NotSupportedError, "Compression is disbaled, and other compression flags are not supported");
307         }
308
309         if((ahbUsageProperties.androidHardwareBufferUsage & ahbUsage) != ahbUsage)
310         {
311                 TCU_THROW(NotSupportedError, "Android hardware buffer usage is not supported");
312         }
313 }
314
315 static tcu::TestStatus ahbImageCreateTest(Context& context, TestParams testParams)
316 {
317         using namespace vkt::ExternalMemoryUtil;
318
319         context.requireDeviceFunctionality("VK_ANDROID_external_memory_android_hardware_buffer");
320         context.requireDeviceFunctionality("VK_EXT_image_compression_control");
321
322         const deUint32                     width                        = 32;
323         const deUint32                     height                       = 32;
324         deUint32                                   queueFamilyIndex = context.getUniversalQueueFamilyIndex();
325         const vk::DeviceInterface& vkd                          = context.getDeviceInterface();
326         VkDevice                                   device                       = context.getDevice();
327         tcu::TestLog&                      log                          = context.getTestContext().getLog();
328         tcu::ResultCollector       results(log);
329         const VkImageUsageFlagBits vkUsage                      = VK_IMAGE_USAGE_SAMPLED_BIT;
330         const bool                                 is_fixed_rate_ex = testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT;
331         const uint32_t                     numPlanes            = isYCbCrFormat(testParams.format) ? getPlaneCount(testParams.format) : 1;
332
333         testParams.control.compressionControlPlaneCount = is_fixed_rate_ex ? numPlanes : 0;
334
335         VkImageCompressionFixedRateFlagsEXT planeFlags[3]{};
336
337         for (unsigned i{}; i < (is_fixed_rate_ex ? 24 : 1); i++)
338         {
339                 planeFlags[0] ^= 3 << i;
340                 planeFlags[1] ^= 5 << i;
341                 planeFlags[2] ^= 7 << i;
342
343                 if (is_fixed_rate_ex)
344                 {
345                         testParams.control.compressionControlPlaneCount = numPlanes;
346                         testParams.control.pFixedRateFlags = planeFlags;
347                 }
348
349                 const vk::VkExternalMemoryImageCreateInfo externalCreateInfo = {
350                         vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, &testParams.control,
351                         VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
352                 };
353                 const vk::VkImageCreateInfo createInfo = { vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
354                                                                                                    &externalCreateInfo,
355                                                                                                    0,
356                                                                                                    vk::VK_IMAGE_TYPE_2D,
357                                                                                                    testParams.format,
358                                                                                                    {
359                                                                                                            width,
360                                                                                                            height,
361                                                                                                            1u,
362                                                                                                    },
363                                                                                                    1,
364                                                                                                    1,
365                                                                                                    vk::VK_SAMPLE_COUNT_1_BIT,
366                                                                                                    VK_IMAGE_TILING_OPTIMAL,
367                                                                                                    vkUsage,
368                                                                                                    vk::VK_SHARING_MODE_EXCLUSIVE,
369                                                                                                    1,
370                                                                                                    &queueFamilyIndex,
371                                                                                                    vk::VK_IMAGE_LAYOUT_UNDEFINED };
372
373                 checkAhbImageSupport(context, testParams, width, height, vkUsage);
374
375                 Move<VkImage>                      image                = vk::createImage(vkd, device, &createInfo);
376                 const VkMemoryRequirements requirements = ExternalMemoryUtil::getImageMemoryRequirements(
377                         vkd, device, image.get(), VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID);
378                 const deUint32           exportedMemoryTypeIndex(ExternalMemoryUtil::chooseMemoryType(requirements.memoryTypeBits));
379                 Move<VkDeviceMemory> memory = ExternalMemoryUtil::allocateExportableMemory(
380                         vkd, device, requirements.size, exportedMemoryTypeIndex,
381                         VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, image.get());
382
383                 VK_CHECK(vkd.bindImageMemory(device, image.get(), memory.get(), 0u));
384                 validate(context.getInstanceInterface(), context.getDeviceInterface(), results, context.getPhysicalDevice(),
385                                  context.getDevice(), testParams, image.get());
386         }
387         return tcu::TestStatus(results.getResult(), results.getMessage());
388 }
389
390 static tcu::TestStatus imageCreateTest(Context& context, TestParams testParams)
391 {
392         checkImageCompressionControlSupport(context);
393         deUint32                         queueFamilyIndex = context.getUniversalQueueFamilyIndex();
394         const VkDevice           device                   = context.getDevice();
395         VkExtent3D                       extent                   = { 16, 16, 1 };
396         tcu::TestLog&            log                      = context.getTestContext().getLog();
397         tcu::ResultCollector results(log);
398         const bool                       is_fixed_rate_ex = testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT;
399
400         VkImageCompressionFixedRateFlagsEXT planeFlags[3]{};
401
402         for (unsigned i{}; i < (is_fixed_rate_ex ? 24 : 1); i++)
403         {
404                 planeFlags[0] ^= 3 << i;
405                 planeFlags[1] ^= 5 << i;
406                 planeFlags[2] ^= 7 << i;
407
408                 if (is_fixed_rate_ex)
409                 {
410                         testParams.control.pFixedRateFlags = planeFlags;
411                 }
412
413                 VkImageCreateInfo imageCreateInfo = {
414                         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
415                         DE_NULL,                                                         // const void*                  pNext;
416                         0,                                                                       // VkImageCreateFlags   flags;
417                         VK_IMAGE_TYPE_2D,                                        // VkImageType
418                         testParams.format,                                       // VkFormat format;
419                         extent,                                                          // VkExtent3D extent;
420                         1u,                                                                      // deUint32                             mipLevels;
421                         1u,                                                                      // deUint32 arraySize;
422                         VK_SAMPLE_COUNT_1_BIT,                           // deUint32 samples;
423                         VK_IMAGE_TILING_OPTIMAL,                         // VkImageTiling                tiling;
424                         VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, // VkImageUsageFlags    usage;
425                         VK_SHARING_MODE_EXCLUSIVE,                       // VkSharingMode sharingMode;
426                         1u,                                                                      // deUint32                             queueFamilyCount;
427                         &queueFamilyIndex,                                       // const deUint32* pQueueFamilyIndices;
428                         VK_IMAGE_LAYOUT_UNDEFINED,                       // VkImageLayout initialLayout;
429                 };
430
431                 if (testParams.useExtension)
432                 {
433                         imageCreateInfo.pNext = &testParams.control;
434                 }
435
436                 checkImageSupport(context.getInstanceInterface(), context.getPhysicalDevice(), imageCreateInfo);
437
438                 Move<VkImage> image = createImage(context.getDeviceInterface(), device, &imageCreateInfo);
439
440                 validate(context.getInstanceInterface(), context.getDeviceInterface(), results, context.getPhysicalDevice(),
441                                  context.getDevice(), testParams, image.get());
442         }
443         return tcu::TestStatus(results.getResult(), results.getMessage());
444 }
445
446 void addImageCompressionControlTests(tcu::TestCaseGroup* group, TestParams testParams)
447 {
448         const bool is_fixed_rate_ex = testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT;
449
450         static const struct
451         {
452                 VkFormat begin;
453                 VkFormat end;
454         } s_formatRanges[] = {
455                 // core formats
456                 { (VkFormat)(VK_FORMAT_UNDEFINED + 1), VK_CORE_FORMAT_LAST },
457
458                 // YCbCr formats
459                 { VK_FORMAT_G8B8G8R8_422_UNORM, (VkFormat)(VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM + 1) },
460
461                 // YCbCr extended formats
462                 { VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT, (VkFormat)(VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT + 1) },
463         };
464
465         for (int rangeNdx = 0; rangeNdx < DE_LENGTH_OF_ARRAY(s_formatRanges); ++rangeNdx)
466         {
467                 const VkFormat rangeBegin = s_formatRanges[rangeNdx].begin;
468                 const VkFormat rangeEnd   = s_formatRanges[rangeNdx].end;
469
470                 for (testParams.format = rangeBegin; testParams.format != rangeEnd;
471                          testParams.format = (VkFormat)(testParams.format + 1))
472                 {
473                         if (isCompressedFormat(testParams.format))
474                                 continue;
475
476                         const uint32_t numPlanes = isYCbCrFormat(testParams.format) ? getPlaneCount(testParams.format) : 1;
477                         testParams.control.compressionControlPlaneCount = is_fixed_rate_ex ? numPlanes : 0;
478
479                         const char* const enumName = getFormatName(testParams.format);
480                         const string      caseName = de::toLower(string(enumName).substr(10));
481                         addFunctionCase(group, caseName, enumName, imageCreateTest, testParams);
482                 }
483         }
484 }
485
486 CustomInstance createInstanceWithWsi(Context& context, Type wsiType, const vector<string> extraExtensions,
487                                                                          const VkAllocationCallbacks* pAllocator = DE_NULL)
488 {
489         const deUint32 version    = context.getUsedApiVersion();
490         vector<string> extensions = extraExtensions;
491
492         extensions.push_back("VK_KHR_surface");
493         extensions.push_back(getExtensionName(wsiType));
494         extensions.push_back("VK_KHR_get_surface_capabilities2");
495
496         vector<string> instanceExtensions;
497         for (const auto& ext : extensions)
498         {
499                 if (!context.isInstanceFunctionalitySupported(ext))
500                         TCU_THROW(NotSupportedError, (ext + " is not supported").c_str());
501
502                 if (!isCoreInstanceExtension(version, ext))
503                         instanceExtensions.push_back(ext);
504         }
505
506         return vkt::createCustomInstanceWithExtensions(context, instanceExtensions, pAllocator);
507 }
508 struct InstanceHelper
509 {
510         const vector<VkExtensionProperties> supportedExtensions;
511         CustomInstance                                          instance;
512         const InstanceDriver&                           vki;
513
514         InstanceHelper(Context& context, Type wsiType, const VkAllocationCallbacks* pAllocator = DE_NULL)
515                 : supportedExtensions(enumerateInstanceExtensionProperties(context.getPlatformInterface(), DE_NULL))
516                 , instance(createInstanceWithWsi(context, wsiType, vector<string>(), pAllocator))
517                 , vki(instance.getDriver())
518         {
519         }
520
521         InstanceHelper(Context& context, Type wsiType, const vector<string>& extensions,
522                                    const VkAllocationCallbacks* pAllocator = DE_NULL)
523                 : supportedExtensions(enumerateInstanceExtensionProperties(context.getPlatformInterface(), DE_NULL))
524                 , instance(createInstanceWithWsi(context, wsiType, extensions, pAllocator))
525                 , vki(instance.getDriver())
526         {
527         }
528 };
529
530 Move<VkDevice> createDeviceWithWsi(const PlatformInterface& vkp, deUint32 apiVersion, VkInstance instance,
531                                                                    const InstanceInterface& vki, VkPhysicalDevice physicalDevice,
532                                                                    const Extensions& supportedExtensions, const vector<string>& additionalExtensions,
533                                                                    deUint32 queueFamilyIndex, bool validationEnabled,
534                                                                    const VkAllocationCallbacks* pAllocator = DE_NULL)
535 {
536         const float                                       queuePriorities[] = { 1.0f };
537         const VkDeviceQueueCreateInfo queueInfo                 = {
538                 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
539                 nullptr,
540                 (VkDeviceQueueCreateFlags)0,
541                 queueFamilyIndex,
542                 DE_LENGTH_OF_ARRAY(queuePriorities),
543                 &queuePriorities[0],
544         };
545
546         vector<string> extensions;
547         extensions.push_back("VK_KHR_swapchain");
548         extensions.push_back("VK_EXT_image_compression_control");
549         extensions.push_back("VK_EXT_image_compression_control_swapchain");
550         extensions.insert(end(extensions), begin(additionalExtensions), end(additionalExtensions));
551
552         for (const auto& extName : extensions)
553         {
554                 if (!isCoreDeviceExtension(apiVersion, extName) &&
555                         !isExtensionStructSupported(supportedExtensions, RequiredExtension(extName)))
556                         TCU_THROW(NotSupportedError, extName + " is not supported");
557         }
558
559         vk::VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT imageCompressionSwapchain = initVulkanStructure();
560         imageCompressionSwapchain.imageCompressionControlSwapchain = VK_TRUE;
561
562         const VkPhysicalDeviceFeatures features = {};
563
564         // Convert from std::vector<std::string> to std::vector<const char*>.
565         std::vector<const char*> extensionsChar;
566         extensionsChar.reserve(extensions.size());
567         std::transform(begin(extensions), end(extensions), std::back_inserter(extensionsChar),
568                                    [](const std::string& s) { return s.c_str(); });
569
570         const VkDeviceCreateInfo deviceParams = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
571                                                                                           &imageCompressionSwapchain,
572                                                                                           (VkDeviceCreateFlags)0,
573                                                                                           1u,
574                                                                                           &queueInfo,
575                                                                                           0u,                                                                                   // enabledLayerCount
576                                                                                           nullptr,                                                                              // ppEnabledLayerNames
577                                                                                           static_cast<deUint32>(extensionsChar.size()), // enabledExtensionCount
578                                                                                           extensionsChar.data(),                                                // ppEnabledExtensionNames
579                                                                                           &features };
580
581         return createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &deviceParams, pAllocator);
582 }
583
584 struct DeviceHelper
585 {
586         const VkPhysicalDevice physicalDevice;
587         const deUint32             queueFamilyIndex;
588         const Unique<VkDevice> device;
589         const DeviceDriver         vkd;
590         const VkQueue              queue;
591
592         DeviceHelper(Context& context, const InstanceInterface& vki, VkInstance instance,
593                                  const vector<VkSurfaceKHR>& surface, const vector<string>& additionalExtensions = vector<string>(),
594                                  const VkAllocationCallbacks* pAllocator = DE_NULL)
595                 : physicalDevice(chooseDevice(vki, instance, context.getTestContext().getCommandLine()))
596                 , queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, surface))
597                 , device(createDeviceWithWsi(context.getPlatformInterface(), context.getUsedApiVersion(), instance, vki,
598                                                                          physicalDevice, enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL),
599                                                                          additionalExtensions, queueFamilyIndex,
600                                                                          context.getTestContext().getCommandLine().isValidationEnabled(), pAllocator))
601                 , vkd(context.getPlatformInterface(), instance, *device)
602                 , queue(getDeviceQueue(vkd, *device, queueFamilyIndex, 0))
603         {
604         }
605
606         // Single-surface shortcut.
607         DeviceHelper(Context& context, const InstanceInterface& vki, VkInstance instance, VkSurfaceKHR surface,
608                                  const vector<string>&            additionalExtensions = vector<string>(),
609                                  const VkAllocationCallbacks* pAllocator                   = DE_NULL)
610                 : DeviceHelper(context, vki, instance, vector<VkSurfaceKHR>(1u, surface), additionalExtensions, pAllocator)
611         {
612         }
613 };
614 static tcu::TestStatus swapchainCreateTest(Context& context, TestParams testParams)
615 {
616         checkImageCompressionControlSupport(context, true);
617
618         tcu::TestLog&            log = context.getTestContext().getLog();
619         tcu::ResultCollector results(log);
620
621         const InstanceHelper     instHelper(context, testParams.wsiType);
622         const wsi::NativeObjects native(context, instHelper.supportedExtensions, testParams.wsiType);
623         const bool                               is_fixed_rate_ex = testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT;
624
625         VkExtent2D                                                      extent2d = { 16, 16 };
626         VkImageCompressionFixedRateFlagsEXT planeFlags[3]{};
627
628         for (unsigned i{}; i < (is_fixed_rate_ex ? 24 : 1); i++)
629         {
630                 planeFlags[0] ^= 3 << i;
631
632                 if (is_fixed_rate_ex)
633                 {
634                         testParams.control.pFixedRateFlags = planeFlags;
635                 }
636
637                 const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, testParams.wsiType,
638                                                                                                                  native.getDisplay(), native.getWindow(),
639                                                                                                                  context.getTestContext().getCommandLine()));
640
641                 const DeviceHelper devHelper(context, instHelper.vki, instHelper.instance, *surface, vector<string>());
642
643                 VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo = initVulkanStructure();
644                 VkSurfaceCapabilities2KHR               caps            = initVulkanStructure();
645                 surfaceInfo.surface                                                     = surface.get();
646
647                 instHelper.vki.getPhysicalDeviceSurfaceCapabilities2KHR(devHelper.physicalDevice, &surfaceInfo, &caps);
648
649                 deUint32 numFormats;
650                 instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(devHelper.physicalDevice, &surfaceInfo, &numFormats,
651                                                                                                                    nullptr);
652
653                 vector<VkSurfaceFormat2KHR> formats(numFormats);
654                 for (auto& surfaceFormat : formats)
655                 {
656                         surfaceFormat = initVulkanStructure();
657                 }
658
659                 instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(devHelper.physicalDevice, &surfaceInfo, &numFormats,
660                                                                                                                    formats.data());
661
662                 deUint32 queueFamilyIndex = devHelper.queueFamilyIndex;
663
664                 for (auto& format : formats)
665                 {
666                         testParams.format = format.surfaceFormat.format;
667
668                         const uint32_t numPlanes = isYCbCrFormat(testParams.format) ? getPlaneCount(testParams.format) : 1;
669                         testParams.control.compressionControlPlaneCount = is_fixed_rate_ex ? numPlanes : 0;
670
671                         VkSwapchainCreateInfoKHR swapchainInfo = initVulkanStructure();
672                         swapchainInfo.surface                              = surface.get();
673                         swapchainInfo.minImageCount                        = caps.surfaceCapabilities.minImageCount;
674                         swapchainInfo.imageFormat                          = format.surfaceFormat.format;
675                         swapchainInfo.imageColorSpace              = format.surfaceFormat.colorSpace;
676                         swapchainInfo.imageExtent                          = extent2d;
677                         swapchainInfo.imageArrayLayers             = 1;
678                         swapchainInfo.imageUsage                           = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
679                         swapchainInfo.imageSharingMode             = VK_SHARING_MODE_EXCLUSIVE;
680                         swapchainInfo.queueFamilyIndexCount        = 1;
681                         swapchainInfo.pQueueFamilyIndices          = &queueFamilyIndex;
682                         swapchainInfo.preTransform                         = caps.surfaceCapabilities.currentTransform;
683                         swapchainInfo.compositeAlpha               = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
684                         swapchainInfo.presentMode                          = VK_PRESENT_MODE_FIFO_KHR;
685                         swapchainInfo.clipped                              = VK_TRUE;
686
687                         swapchainInfo.pNext = &testParams.control;
688
689                         Move<VkSwapchainKHR> swapchain = createSwapchainKHR(devHelper.vkd, devHelper.device.get(), &swapchainInfo);
690
691                         deUint32 imageCount = 0;
692                         devHelper.vkd.getSwapchainImagesKHR(devHelper.device.get(), swapchain.get(), &imageCount, nullptr);
693                         vector<VkImage> images(imageCount);
694                         devHelper.vkd.getSwapchainImagesKHR(devHelper.device.get(), swapchain.get(), &imageCount, images.data());
695
696                         validate(instHelper.vki, devHelper.vkd, results, devHelper.physicalDevice, devHelper.device.get(),
697                                          testParams, images[0]);
698                 }
699         }
700
701         return tcu::TestStatus(results.getResult(), results.getMessage());
702 }
703
704 void addAhbCompressionControlTests(tcu::TestCaseGroup *group, TestParams testParams)
705 {
706         // Ahb formats
707         static const vk::VkFormat ahbFormats[] = {
708                 VK_FORMAT_R8G8B8A8_UNORM,
709                 VK_FORMAT_R8G8B8_UNORM,
710                 VK_FORMAT_R5G6B5_UNORM_PACK16,
711                 VK_FORMAT_R16G16B16A16_SFLOAT,
712                 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
713                 VK_FORMAT_D16_UNORM,
714                 VK_FORMAT_X8_D24_UNORM_PACK32,
715                 VK_FORMAT_D24_UNORM_S8_UINT,
716                 VK_FORMAT_D32_SFLOAT,
717                 VK_FORMAT_D32_SFLOAT_S8_UINT,
718                 VK_FORMAT_S8_UINT
719         };
720
721         for (int index = 0; index < DE_LENGTH_OF_ARRAY(ahbFormats); ++index)
722         {
723                 testParams.format = ahbFormats[index];
724                 const char *const enumName = getFormatName(testParams.format);
725                 const string caseName = de::toLower(string(enumName).substr(10));
726                 addFunctionCase(group, caseName, enumName, ahbImageCreateTest, testParams);
727         }
728 }
729
730 tcu::TestCaseGroup* createImageCompressionControlTests(tcu::TestContext& testCtx)
731 {
732         de::MovePtr<tcu::TestCaseGroup> group(
733                 new tcu::TestCaseGroup(testCtx, "image_compression_control", "Test for image compression control."));
734
735         TestParams                      testParams{};
736         tcu::TestCaseGroup* subgroup(
737                 new tcu::TestCaseGroup(testCtx, "create_image", "Test creating images with compression control struct"));
738
739         subgroup->addChild(createTestGroup(testCtx, "no_compression_control",
740                                                                            "Queries images created without compression control struct.",
741                                                                            addImageCompressionControlTests, testParams));
742
743         testParams.useExtension  = true;
744         testParams.control               = initVulkanStructure();
745         testParams.control.flags = VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT;
746
747         struct
748         {
749                 const char*                                name;
750                 VkImageCompressionFlagsEXT flag;
751         } constexpr compression_flags[] = {
752                 { "default", VK_IMAGE_COMPRESSION_DEFAULT_EXT },
753                 { "fixed_rate_default", VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT },
754                 { "disabled", VK_IMAGE_COMPRESSION_DISABLED_EXT },
755                 { "explicit", VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT },
756         };
757
758         for (auto& flag : compression_flags)
759         {
760                 testParams.control.flags = flag.flag;
761                 subgroup->addChild(createTestGroup(testCtx, flag.name,
762                                                                                    "Queries images created with compression control struct.",
763                                                                                    addImageCompressionControlTests, testParams));
764         }
765         group->addChild(subgroup);
766
767         subgroup = new tcu::TestCaseGroup(testCtx, "android_hardware_buffer",
768                                                                           "Test creating Android Hardware buffer with compression control struct");
769
770         for (auto& flag : compression_flags)
771         {
772                 testParams.control.flags = flag.flag;
773                 subgroup->addChild(createTestGroup(testCtx, flag.name,
774                                                                                    "Queries images created with compression control struct.",
775                                                                                    addAhbCompressionControlTests, testParams));
776         }
777
778         group->addChild(subgroup);
779
780         subgroup = new tcu::TestCaseGroup(testCtx, "swapchain", "swapchain");
781         for (int typeNdx = 0; typeNdx < vk::wsi::TYPE_LAST; ++typeNdx)
782         {
783                 const vk::wsi::Type wsiType = (vk::wsi::Type)typeNdx;
784                 testParams.wsiType                      = wsiType;
785
786                 tcu::TestCaseGroup* wsi_subgroup(new tcu::TestCaseGroup(testCtx, getName(wsiType), "Swapchain tests"));
787
788                 for (auto& flag : compression_flags)
789                 {
790                         testParams.control.flags = flag.flag;
791                         addFunctionCase(wsi_subgroup, flag.name, flag.name, swapchainCreateTest, testParams);
792                 }
793                 subgroup->addChild(wsi_subgroup);
794         }
795
796         group->addChild(subgroup);
797
798         return group.release();
799 }
800
801 } // namespace api
802
803 } // namespace vkt