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.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
checkAhbImageSupport(const Context & context,const TestParams testParams,const deUint32 width,const deUint32 height,const VkImageUsageFlagBits vkUsage)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
ahbImageCreateTest(Context & context,TestParams testParams)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
imageCreateTest(Context & context,TestParams testParams)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
addImageCompressionControlTests(tcu::TestCaseGroup * group,TestParams testParams)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
createInstanceWithWsi(Context & context,Type wsiType,const vector<string> extraExtensions,const VkAllocationCallbacks * pAllocator=DE_NULL)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
InstanceHelpervkt::api::InstanceHelper514 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
InstanceHelpervkt::api::InstanceHelper521 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
createDeviceWithWsi(const PlatformInterface & vkp,deUint32 apiVersion,VkInstance instance,const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const Extensions & supportedExtensions,const vector<string> & additionalExtensions,deUint32 queueFamilyIndex,bool validationEnabled,const VkAllocationCallbacks * pAllocator=DE_NULL)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
DeviceHelpervkt::api::DeviceHelper592 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.
DeviceHelpervkt::api::DeviceHelper607 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 };
swapchainCreateTest(Context & context,TestParams testParams)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
addAhbCompressionControlTests(tcu::TestCaseGroup * group,TestParams testParams)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
createImageCompressionControlTests(tcu::TestContext & testCtx)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
804