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
checkImageCompressionControlSupport(Context & context,bool swapchain=false)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
validate(const InstanceInterface & vki,const DeviceInterface & vkd,tcu::ResultCollector & results,VkPhysicalDevice physicalDevice,VkDevice device,TestParams & testParams,VkImage image)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.getImageSubresourceLayout2KHR(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 if (compressionEnabled.compressionControlPlaneCount > 0)
132 {
133 compressionEnabled.pFixedRateFlags = fixedRateFlags;
134 }
135
136 VkPhysicalDeviceImageFormatInfo2 formatInfo = initVulkanStructure(&compressionEnabled);
137 formatInfo.format = testParams.format;
138 formatInfo.type = VK_IMAGE_TYPE_2D;
139 formatInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
140 formatInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
141
142 VkImageCompressionPropertiesEXT compressionPropertiesSupported = initVulkanStructure();
143 VkImageFormatProperties2 properties2 = initVulkanStructure(&compressionPropertiesSupported);
144
145 vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &formatInfo, &properties2);
146
147 if (testParams.useExtension)
148 {
149 if ((compressionPropertiesSupported.imageCompressionFixedRateFlags &
150 compressionProperties.imageCompressionFixedRateFlags) !=
151 compressionProperties.imageCompressionFixedRateFlags)
152 {
153 results.fail("Got image with fixed rate flags that are not supported "
154 "in image format properties.");
155 }
156 if ((compressionPropertiesSupported.imageCompressionFlags & compressionProperties.imageCompressionFlags) !=
157 compressionProperties.imageCompressionFlags &&
158 compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DISABLED_EXT)
159 {
160 results.fail("Got image with compression flags that are not supported "
161 "in image format properties.");
162 }
163 if (testParams.control.flags == VK_IMAGE_COMPRESSION_DEFAULT_EXT &&
164 compressionProperties.imageCompressionFixedRateFlags != 0)
165 {
166 results.fail("Got lossy compression when DEFAULT compression was requested.");
167 }
168 if (testParams.control.flags == VK_IMAGE_COMPRESSION_DISABLED_EXT &&
169 compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DISABLED_EXT)
170 {
171 results.fail("Image compression not disabled.");
172 }
173 if (testParams.control.flags == VK_IMAGE_COMPRESSION_DISABLED_EXT &&
174 compressionProperties.imageCompressionFixedRateFlags != 0)
175 {
176 results.fail("Image compression disabled but got fixed rate flags.");
177 }
178 if (testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT &&
179 !(compressionProperties.imageCompressionFlags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT ||
180 compressionProperties.imageCompressionFlags == VK_IMAGE_COMPRESSION_DISABLED_EXT ||
181 compressionProperties.imageCompressionFlags == VK_IMAGE_COMPRESSION_DEFAULT_EXT))
182 {
183 results.fail("Explicit compression flags not returned for image "
184 "creation with FIXED RATE DEFAULT.");
185 }
186
187 if (testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT)
188 {
189 uint32_t minRequestedRate = 1 << deCtz32(testParams.control.pFixedRateFlags[planeIndex]);
190 uint32_t actualRate = compressionProperties.imageCompressionFixedRateFlags;
191 if (compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DISABLED_EXT &&
192 compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DEFAULT_EXT)
193 {
194
195 if (minRequestedRate > actualRate)
196 {
197 results.fail("Image created with less bpc than requested.");
198 }
199 }
200 }
201 }
202 else
203 {
204 if (compressionProperties.imageCompressionFixedRateFlags != VK_IMAGE_COMPRESSION_FIXED_RATE_NONE_EXT)
205 {
206 results.fail("Fixed rate compression should not be enabled.");
207 }
208
209 if (compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DISABLED_EXT &&
210 compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DEFAULT_EXT)
211 {
212 results.fail("Image compression should be default or not be enabled.");
213 }
214 }
215 }
216 }
217
checkAhbImageSupport(const Context & context,const TestParams testParams,const uint32_t width,const uint32_t height,const VkImageUsageFlagBits vkUsage)218 static void checkAhbImageSupport(const Context &context, const TestParams testParams, const uint32_t width,
219 const uint32_t 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 uint64_t ahbUsage = ahbApi->vkUsageToAhbUsage(vkUsage);
230 {
231 pt::AndroidHardwareBufferPtr ahb =
232 ahbApi->allocate(width, height, 1, ahbApi->vkFormatToAhbFormat(testParams.format), ahbUsage);
233 if (ahb.internal == DE_NULL)
234 {
235 TCU_THROW(NotSupportedError, "Android hardware buffer format not supported");
236 }
237 }
238
239 // Check external memory supported.
240 const VkPhysicalDeviceExternalImageFormatInfoKHR external_image_format_info = {
241 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, &testParams.control,
242 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID};
243
244 const VkPhysicalDeviceImageFormatInfo2 info = {
245 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
246 &external_image_format_info,
247 testParams.format,
248 VK_IMAGE_TYPE_2D,
249 VK_IMAGE_TILING_OPTIMAL,
250 VK_IMAGE_USAGE_SAMPLED_BIT,
251 0,
252 };
253
254 VkImageCompressionPropertiesEXT compressionPropertiesSupported = {
255 VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT, DE_NULL, 0, 0};
256
257 VkAndroidHardwareBufferUsageANDROID ahbUsageProperties = {VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID,
258 &compressionPropertiesSupported, 0u};
259
260 VkExternalImageFormatProperties externalProperties = {
261 VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES, &ahbUsageProperties, {0u, 0u, 0u}};
262
263 VkImageFormatProperties2 properties = {
264 VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, &externalProperties, {{0u, 0u, 0u}, 0u, 0u, 0u, 0u}};
265
266 VkResult result = context.getInstanceInterface().getPhysicalDeviceImageFormatProperties2(
267 context.getPhysicalDevice(), &info, &properties);
268
269 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
270 TCU_THROW(NotSupportedError, "Format not supported");
271
272 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures &
273 VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) == 0)
274 TCU_THROW(NotSupportedError, "External handle type doesn't support exporting image");
275
276 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures &
277 VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0)
278 TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
279
280 if ((compressionPropertiesSupported.imageCompressionFlags == VK_IMAGE_COMPRESSION_DISABLED_EXT) &&
281 (testParams.control.flags != VK_IMAGE_COMPRESSION_DISABLED_EXT))
282 {
283 TCU_THROW(NotSupportedError, "Compression is disbaled, and other compression flags are not supported");
284 }
285
286 if ((ahbUsageProperties.androidHardwareBufferUsage & ahbUsage) != ahbUsage)
287 {
288 TCU_THROW(NotSupportedError, "Android hardware buffer usage is not supported");
289 }
290 }
291
ahbImageCreateTest(Context & context,TestParams testParams)292 static tcu::TestStatus ahbImageCreateTest(Context &context, TestParams testParams)
293 {
294 using namespace vkt::ExternalMemoryUtil;
295
296 context.requireDeviceFunctionality("VK_ANDROID_external_memory_android_hardware_buffer");
297 context.requireDeviceFunctionality("VK_EXT_image_compression_control");
298
299 const uint32_t width = 32;
300 const uint32_t height = 32;
301 uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
302 const vk::DeviceInterface &vkd = context.getDeviceInterface();
303 VkDevice device = context.getDevice();
304 tcu::TestLog &log = context.getTestContext().getLog();
305 tcu::ResultCollector results(log);
306 const VkImageUsageFlagBits vkUsage = VK_IMAGE_USAGE_SAMPLED_BIT;
307 const bool is_fixed_rate_ex = testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT;
308 const uint32_t numPlanes = isYCbCrFormat(testParams.format) ? getPlaneCount(testParams.format) : 1;
309
310 testParams.control.compressionControlPlaneCount = is_fixed_rate_ex ? numPlanes : 0;
311
312 VkImageCompressionFixedRateFlagsEXT planeFlags[3]{};
313
314 for (unsigned i{}; i < (is_fixed_rate_ex ? 24u : 1u); i++)
315 {
316 planeFlags[0] ^= 3 << i;
317 planeFlags[1] ^= 5 << i;
318 planeFlags[2] ^= 7 << i;
319
320 if (is_fixed_rate_ex)
321 {
322 testParams.control.compressionControlPlaneCount = numPlanes;
323 testParams.control.pFixedRateFlags = planeFlags;
324 }
325
326 const vk::VkExternalMemoryImageCreateInfo externalCreateInfo = {
327 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, &testParams.control,
328 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID};
329 const vk::VkImageCreateInfo createInfo = {vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
330 &externalCreateInfo,
331 0,
332 vk::VK_IMAGE_TYPE_2D,
333 testParams.format,
334 {
335 width,
336 height,
337 1u,
338 },
339 1,
340 1,
341 vk::VK_SAMPLE_COUNT_1_BIT,
342 VK_IMAGE_TILING_OPTIMAL,
343 vkUsage,
344 vk::VK_SHARING_MODE_EXCLUSIVE,
345 1,
346 &queueFamilyIndex,
347 vk::VK_IMAGE_LAYOUT_UNDEFINED};
348
349 checkAhbImageSupport(context, testParams, width, height, vkUsage);
350
351 Move<VkImage> image = vk::createImage(vkd, device, &createInfo);
352 const VkMemoryRequirements requirements = ExternalMemoryUtil::getImageMemoryRequirements(
353 vkd, device, image.get(), VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID);
354 const uint32_t exportedMemoryTypeIndex(ExternalMemoryUtil::chooseMemoryType(requirements.memoryTypeBits));
355 Move<VkDeviceMemory> memory = ExternalMemoryUtil::allocateExportableMemory(
356 vkd, device, requirements.size, exportedMemoryTypeIndex,
357 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, image.get());
358
359 VK_CHECK(vkd.bindImageMemory(device, image.get(), memory.get(), 0u));
360 validate(context.getInstanceInterface(), context.getDeviceInterface(), results, context.getPhysicalDevice(),
361 context.getDevice(), testParams, image.get());
362 }
363 return tcu::TestStatus(results.getResult(), results.getMessage());
364 }
365
imageCreateTest(Context & context,TestParams testParams)366 static tcu::TestStatus imageCreateTest(Context &context, TestParams testParams)
367 {
368 checkImageCompressionControlSupport(context);
369 uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
370 const VkDevice device = context.getDevice();
371 VkExtent3D extent = {16, 16, 1};
372 tcu::TestLog &log = context.getTestContext().getLog();
373 tcu::ResultCollector results(log);
374 const bool is_fixed_rate_ex = testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT;
375
376 VkImageCompressionFixedRateFlagsEXT planeFlags[3]{};
377
378 for (unsigned i{}; i < (is_fixed_rate_ex ? 24u : 1u); i++)
379 {
380 planeFlags[0] ^= 3 << i;
381 planeFlags[1] ^= 5 << i;
382 planeFlags[2] ^= 7 << i;
383
384 if (is_fixed_rate_ex)
385 {
386 testParams.control.pFixedRateFlags = planeFlags;
387 }
388
389 VkImageCreateInfo imageCreateInfo = {
390 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
391 DE_NULL, // const void* pNext;
392 0, // VkImageCreateFlags flags;
393 VK_IMAGE_TYPE_2D, // VkImageType
394 testParams.format, // VkFormat format;
395 extent, // VkExtent3D extent;
396 1u, // uint32_t mipLevels;
397 1u, // uint32_t arraySize;
398 VK_SAMPLE_COUNT_1_BIT, // uint32_t samples;
399 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
400 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, // VkImageUsageFlags usage;
401 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
402 1u, // uint32_t queueFamilyCount;
403 &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices;
404 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
405 };
406
407 if (testParams.useExtension)
408 {
409 imageCreateInfo.pNext = &testParams.control;
410 }
411
412 checkImageSupport(context.getInstanceInterface(), context.getPhysicalDevice(), imageCreateInfo);
413
414 Move<VkImage> image = createImage(context.getDeviceInterface(), device, &imageCreateInfo);
415
416 validate(context.getInstanceInterface(), context.getDeviceInterface(), results, context.getPhysicalDevice(),
417 context.getDevice(), testParams, image.get());
418 }
419 return tcu::TestStatus(results.getResult(), results.getMessage());
420 }
421
addImageCompressionControlTests(tcu::TestCaseGroup * group,TestParams testParams)422 void addImageCompressionControlTests(tcu::TestCaseGroup *group, TestParams testParams)
423 {
424 const bool is_fixed_rate_ex = testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT;
425
426 static const struct
427 {
428 VkFormat begin;
429 VkFormat end;
430 } s_formatRanges[] = {
431 // core formats
432 {(VkFormat)(VK_FORMAT_UNDEFINED + 1), VK_CORE_FORMAT_LAST},
433
434 // YCbCr formats
435 {VK_FORMAT_G8B8G8R8_422_UNORM, (VkFormat)(VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM + 1)},
436
437 // YCbCr extended formats
438 {VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT, (VkFormat)(VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT + 1)},
439 };
440
441 for (int rangeNdx = 0; rangeNdx < DE_LENGTH_OF_ARRAY(s_formatRanges); ++rangeNdx)
442 {
443 const VkFormat rangeBegin = s_formatRanges[rangeNdx].begin;
444 const VkFormat rangeEnd = s_formatRanges[rangeNdx].end;
445
446 for (testParams.format = rangeBegin; testParams.format != rangeEnd;
447 testParams.format = (VkFormat)(testParams.format + 1))
448 {
449 if (isCompressedFormat(testParams.format))
450 continue;
451
452 const uint32_t numPlanes = isYCbCrFormat(testParams.format) ? getPlaneCount(testParams.format) : 1;
453 testParams.control.compressionControlPlaneCount = is_fixed_rate_ex ? numPlanes : 0;
454
455 const char *const enumName = getFormatName(testParams.format);
456 const string caseName = de::toLower(string(enumName).substr(10));
457 addFunctionCase(group, caseName, imageCreateTest, testParams);
458 }
459 }
460 }
461
createInstanceWithWsi(Context & context,Type wsiType,const vector<string> extraExtensions,const VkAllocationCallbacks * pAllocator=DE_NULL)462 CustomInstance createInstanceWithWsi(Context &context, Type wsiType, const vector<string> extraExtensions,
463 const VkAllocationCallbacks *pAllocator = DE_NULL)
464 {
465 const uint32_t version = context.getUsedApiVersion();
466 vector<string> extensions = extraExtensions;
467
468 extensions.push_back("VK_KHR_surface");
469 extensions.push_back(getExtensionName(wsiType));
470 extensions.push_back("VK_KHR_get_surface_capabilities2");
471
472 vector<string> instanceExtensions;
473 for (const auto &ext : extensions)
474 {
475 if (!context.isInstanceFunctionalitySupported(ext))
476 TCU_THROW(NotSupportedError, (ext + " is not supported").c_str());
477
478 if (!isCoreInstanceExtension(version, ext))
479 instanceExtensions.push_back(ext);
480 }
481
482 return vkt::createCustomInstanceWithExtensions(context, instanceExtensions, pAllocator);
483 }
484 struct InstanceHelper
485 {
486 const vector<VkExtensionProperties> supportedExtensions;
487 CustomInstance instance;
488 const InstanceDriver &vki;
489
InstanceHelpervkt::api::InstanceHelper490 InstanceHelper(Context &context, Type wsiType, const VkAllocationCallbacks *pAllocator = DE_NULL)
491 : supportedExtensions(enumerateInstanceExtensionProperties(context.getPlatformInterface(), DE_NULL))
492 , instance(createInstanceWithWsi(context, wsiType, vector<string>(), pAllocator))
493 , vki(instance.getDriver())
494 {
495 }
496
InstanceHelpervkt::api::InstanceHelper497 InstanceHelper(Context &context, Type wsiType, const vector<string> &extensions,
498 const VkAllocationCallbacks *pAllocator = DE_NULL)
499 : supportedExtensions(enumerateInstanceExtensionProperties(context.getPlatformInterface(), DE_NULL))
500 , instance(createInstanceWithWsi(context, wsiType, extensions, pAllocator))
501 , vki(instance.getDriver())
502 {
503 }
504 };
505
createDeviceWithWsi(const PlatformInterface & vkp,uint32_t apiVersion,VkInstance instance,const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const Extensions & supportedExtensions,const vector<string> & additionalExtensions,uint32_t queueFamilyIndex,bool validationEnabled,const VkAllocationCallbacks * pAllocator=DE_NULL)506 Move<VkDevice> createDeviceWithWsi(const PlatformInterface &vkp, uint32_t apiVersion, VkInstance instance,
507 const InstanceInterface &vki, VkPhysicalDevice physicalDevice,
508 const Extensions &supportedExtensions, const vector<string> &additionalExtensions,
509 uint32_t queueFamilyIndex, bool validationEnabled,
510 const VkAllocationCallbacks *pAllocator = DE_NULL)
511 {
512 const float queuePriorities[] = {1.0f};
513 const VkDeviceQueueCreateInfo queueInfo = {
514 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
515 nullptr,
516 (VkDeviceQueueCreateFlags)0,
517 queueFamilyIndex,
518 DE_LENGTH_OF_ARRAY(queuePriorities),
519 &queuePriorities[0],
520 };
521
522 vector<string> extensions;
523 extensions.push_back("VK_KHR_swapchain");
524 extensions.push_back("VK_EXT_image_compression_control");
525 extensions.push_back("VK_EXT_image_compression_control_swapchain");
526 extensions.insert(end(extensions), begin(additionalExtensions), end(additionalExtensions));
527
528 for (const auto &extName : extensions)
529 {
530 if (!isCoreDeviceExtension(apiVersion, extName) &&
531 !isExtensionStructSupported(supportedExtensions, RequiredExtension(extName)))
532 TCU_THROW(NotSupportedError, extName + " is not supported");
533 }
534
535 vk::VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT imageCompressionSwapchain = initVulkanStructure();
536 imageCompressionSwapchain.imageCompressionControlSwapchain = VK_TRUE;
537
538 const VkPhysicalDeviceFeatures features = {};
539
540 // Convert from std::vector<std::string> to std::vector<const char*>.
541 std::vector<const char *> extensionsChar;
542 extensionsChar.reserve(extensions.size());
543 std::transform(begin(extensions), end(extensions), std::back_inserter(extensionsChar),
544 [](const std::string &s) { return s.c_str(); });
545
546 const VkDeviceCreateInfo deviceParams = {VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
547 &imageCompressionSwapchain,
548 (VkDeviceCreateFlags)0,
549 1u,
550 &queueInfo,
551 0u, // enabledLayerCount
552 nullptr, // ppEnabledLayerNames
553 static_cast<uint32_t>(extensionsChar.size()), // enabledExtensionCount
554 extensionsChar.data(), // ppEnabledExtensionNames
555 &features};
556
557 return createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &deviceParams, pAllocator);
558 }
559
560 struct DeviceHelper
561 {
562 const VkPhysicalDevice physicalDevice;
563 const uint32_t queueFamilyIndex;
564 const Unique<VkDevice> device;
565 const DeviceDriver vkd;
566 const VkQueue queue;
567
DeviceHelpervkt::api::DeviceHelper568 DeviceHelper(Context &context, const InstanceInterface &vki, VkInstance instance,
569 const vector<VkSurfaceKHR> &surface, const vector<string> &additionalExtensions = vector<string>(),
570 const VkAllocationCallbacks *pAllocator = DE_NULL)
571 : physicalDevice(chooseDevice(vki, instance, context.getTestContext().getCommandLine()))
572 , queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, surface))
573 , device(createDeviceWithWsi(context.getPlatformInterface(), context.getUsedApiVersion(), instance, vki,
574 physicalDevice, enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL),
575 additionalExtensions, queueFamilyIndex,
576 context.getTestContext().getCommandLine().isValidationEnabled(), pAllocator))
577 , vkd(context.getPlatformInterface(), instance, *device, context.getUsedApiVersion(),
578 context.getTestContext().getCommandLine())
579 , queue(getDeviceQueue(vkd, *device, queueFamilyIndex, 0))
580 {
581 }
582
583 // Single-surface shortcut.
DeviceHelpervkt::api::DeviceHelper584 DeviceHelper(Context &context, const InstanceInterface &vki, VkInstance instance, VkSurfaceKHR surface,
585 const vector<string> &additionalExtensions = vector<string>(),
586 const VkAllocationCallbacks *pAllocator = DE_NULL)
587 : DeviceHelper(context, vki, instance, vector<VkSurfaceKHR>(1u, surface), additionalExtensions, pAllocator)
588 {
589 }
590 };
swapchainCreateTest(Context & context,TestParams testParams)591 static tcu::TestStatus swapchainCreateTest(Context &context, TestParams testParams)
592 {
593 checkImageCompressionControlSupport(context, true);
594
595 tcu::TestLog &log = context.getTestContext().getLog();
596 tcu::ResultCollector results(log);
597
598 const InstanceHelper instHelper(context, testParams.wsiType);
599 const wsi::NativeObjects native(context, instHelper.supportedExtensions, testParams.wsiType);
600 const bool is_fixed_rate_ex = testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT;
601
602 VkExtent2D extent2d = {16, 16};
603 VkImageCompressionFixedRateFlagsEXT planeFlags[3]{};
604
605 for (unsigned i{}; i < (is_fixed_rate_ex ? 24u : 1u); i++)
606 {
607 planeFlags[0] ^= 3 << i;
608
609 if (is_fixed_rate_ex)
610 {
611 testParams.control.pFixedRateFlags = planeFlags;
612 }
613
614 const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, testParams.wsiType,
615 native.getDisplay(), native.getWindow(),
616 context.getTestContext().getCommandLine()));
617
618 const DeviceHelper devHelper(context, instHelper.vki, instHelper.instance, *surface, vector<string>());
619
620 VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo = initVulkanStructure();
621 VkSurfaceCapabilities2KHR caps = initVulkanStructure();
622 surfaceInfo.surface = surface.get();
623
624 instHelper.vki.getPhysicalDeviceSurfaceCapabilities2KHR(devHelper.physicalDevice, &surfaceInfo, &caps);
625
626 uint32_t numFormats;
627 instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(devHelper.physicalDevice, &surfaceInfo, &numFormats,
628 nullptr);
629
630 vector<VkSurfaceFormat2KHR> formats(numFormats);
631 VkImageCompressionPropertiesEXT *compressionProps = new VkImageCompressionPropertiesEXT[numFormats];
632 for (uint32_t j = 0; j < numFormats; ++j)
633 {
634 VkImageCompressionPropertiesEXT formatCompressionProps = initVulkanStructure();
635 VkSurfaceFormat2KHR surfaceFormat = initVulkanStructure();
636
637 compressionProps[j] = formatCompressionProps;
638 formats[j] = surfaceFormat;
639 formats[j].pNext = &compressionProps[j];
640 }
641
642 instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(devHelper.physicalDevice, &surfaceInfo, &numFormats,
643 formats.data());
644
645 uint32_t queueFamilyIndex = devHelper.queueFamilyIndex;
646
647 for (uint32_t j = 0; j < numFormats; ++j)
648 {
649 VkSurfaceFormat2KHR format = formats[j];
650 testParams.format = format.surfaceFormat.format;
651 VkImageCompressionFlagsEXT supportedCompressionMode = compressionProps[j].imageCompressionFlags;
652 VkImageCompressionFixedRateFlagsEXT supportedCompressionRate =
653 compressionProps[j].imageCompressionFixedRateFlags;
654
655 const uint32_t numPlanes = isYCbCrFormat(testParams.format) ? getPlaneCount(testParams.format) : 1;
656 testParams.control.compressionControlPlaneCount = is_fixed_rate_ex ? numPlanes : 0;
657
658 // check that is format is compatible with selected compression mode/rate
659 if (((testParams.control.flags & supportedCompressionMode) == 0) ||
660 (is_fixed_rate_ex && ((testParams.control.pFixedRateFlags[0] & supportedCompressionRate) == 0)))
661 {
662
663 // When testing fixed rate default, query returns fixed rate explicit flag - don't skip it unless compression rate
664 // is also zero
665 if (!((testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT) &&
666 (supportedCompressionRate != 0)))
667 TCU_THROW(NotSupportedError, "Swapchain compression control and format not compatible");
668 }
669
670 if (is_fixed_rate_ex && (numPlanes >= 1))
671 {
672 // only use compression rate that is supported
673 testParams.control.pFixedRateFlags[0] =
674 testParams.control.pFixedRateFlags[0] & supportedCompressionRate;
675 }
676
677 VkSwapchainCreateInfoKHR swapchainInfo = initVulkanStructure();
678 swapchainInfo.surface = surface.get();
679 swapchainInfo.minImageCount = caps.surfaceCapabilities.minImageCount;
680 swapchainInfo.imageFormat = format.surfaceFormat.format;
681 swapchainInfo.imageColorSpace = format.surfaceFormat.colorSpace;
682 swapchainInfo.imageExtent = extent2d;
683 swapchainInfo.imageArrayLayers = 1;
684 swapchainInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
685 swapchainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
686 swapchainInfo.queueFamilyIndexCount = 1;
687 swapchainInfo.pQueueFamilyIndices = &queueFamilyIndex;
688 swapchainInfo.preTransform = caps.surfaceCapabilities.currentTransform;
689 swapchainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
690 swapchainInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR;
691 swapchainInfo.clipped = VK_TRUE;
692
693 swapchainInfo.pNext = &testParams.control;
694
695 Move<VkSwapchainKHR> swapchain = createSwapchainKHR(devHelper.vkd, devHelper.device.get(), &swapchainInfo);
696
697 uint32_t imageCount = 0;
698 devHelper.vkd.getSwapchainImagesKHR(devHelper.device.get(), swapchain.get(), &imageCount, nullptr);
699 vector<VkImage> images(imageCount);
700 devHelper.vkd.getSwapchainImagesKHR(devHelper.device.get(), swapchain.get(), &imageCount, images.data());
701
702 validate(instHelper.vki, devHelper.vkd, results, devHelper.physicalDevice, devHelper.device.get(),
703 testParams, images[0]);
704 }
705
706 delete[] compressionProps;
707 }
708
709 return tcu::TestStatus(results.getResult(), results.getMessage());
710 }
711
addAhbCompressionControlTests(tcu::TestCaseGroup * group,TestParams testParams)712 void addAhbCompressionControlTests(tcu::TestCaseGroup *group, TestParams testParams)
713 {
714 // Ahb formats
715 static const vk::VkFormat ahbFormats[] = {VK_FORMAT_R8G8B8A8_UNORM,
716 VK_FORMAT_R8G8B8_UNORM,
717 VK_FORMAT_R5G6B5_UNORM_PACK16,
718 VK_FORMAT_R16G16B16A16_SFLOAT,
719 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
720 VK_FORMAT_D16_UNORM,
721 VK_FORMAT_X8_D24_UNORM_PACK32,
722 VK_FORMAT_D24_UNORM_S8_UINT,
723 VK_FORMAT_D32_SFLOAT,
724 VK_FORMAT_D32_SFLOAT_S8_UINT,
725 VK_FORMAT_S8_UINT};
726
727 for (int index = 0; index < DE_LENGTH_OF_ARRAY(ahbFormats); ++index)
728 {
729 testParams.format = ahbFormats[index];
730 const char *const enumName = getFormatName(testParams.format);
731 const string caseName = de::toLower(string(enumName).substr(10));
732 addFunctionCase(group, caseName, ahbImageCreateTest, testParams);
733 }
734 }
735
createImageCompressionControlTests(tcu::TestContext & testCtx)736 tcu::TestCaseGroup *createImageCompressionControlTests(tcu::TestContext &testCtx)
737 {
738 // Test for image compression control.
739 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "image_compression_control"));
740
741 TestParams testParams{};
742 // Test creating images with compression control struct
743 tcu::TestCaseGroup *subgroup(new tcu::TestCaseGroup(testCtx, "create_image"));
744
745 // Queries images created without compression control struct.
746 subgroup->addChild(createTestGroup(testCtx, "no_compression_control", addImageCompressionControlTests, testParams));
747
748 testParams.useExtension = true;
749 testParams.control = initVulkanStructure();
750 testParams.control.flags = VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT;
751
752 struct
753 {
754 const char *name;
755 VkImageCompressionFlagsEXT flag;
756 } constexpr compression_flags[] = {
757 {"default", VK_IMAGE_COMPRESSION_DEFAULT_EXT},
758 {"fixed_rate_default", VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT},
759 {"disabled", VK_IMAGE_COMPRESSION_DISABLED_EXT},
760 {"explicit", VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT},
761 };
762
763 for (auto &flag : compression_flags)
764 {
765 testParams.control.flags = flag.flag;
766 // Queries images created with compression control struct.
767 subgroup->addChild(createTestGroup(testCtx, flag.name, addImageCompressionControlTests, testParams));
768 }
769 group->addChild(subgroup);
770
771 // Test creating Android Hardware buffer with compression control struct
772 subgroup = new tcu::TestCaseGroup(testCtx, "android_hardware_buffer");
773
774 for (auto &flag : compression_flags)
775 {
776 testParams.control.flags = flag.flag;
777 // Queries images created with compression control struct.
778 subgroup->addChild(createTestGroup(testCtx, flag.name, addAhbCompressionControlTests, testParams));
779 }
780
781 group->addChild(subgroup);
782
783 subgroup = new tcu::TestCaseGroup(testCtx, "swapchain");
784 for (int typeNdx = 0; typeNdx < vk::wsi::TYPE_LAST; ++typeNdx)
785 {
786 const vk::wsi::Type wsiType = (vk::wsi::Type)typeNdx;
787 testParams.wsiType = wsiType;
788
789 tcu::TestCaseGroup *wsi_subgroup(new tcu::TestCaseGroup(testCtx, getName(wsiType)));
790
791 for (auto &flag : compression_flags)
792 {
793 testParams.control.flags = flag.flag;
794 addFunctionCase(wsi_subgroup, flag.name, swapchainCreateTest, testParams);
795 }
796 subgroup->addChild(wsi_subgroup);
797 }
798
799 group->addChild(subgroup);
800
801 return group.release();
802 }
803
804 } // namespace api
805
806 } // namespace vkt
807