blob: 1b9489fae24597d91636d5beb1d549ae3e33b6bf [file] [log] [blame]
/*-------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
*
* Copyright (c) 2022 Khronos Group
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/ /*!
* \file
* \brief Test for Image Compression control
*/ /*--------------------------------------------------------------------*/
#include <iostream>
#include <typeinfo>
#include "tcuCommandLine.hpp"
#include "tcuDefs.hpp"
#include "tcuFunctionLibrary.hpp"
#include "tcuPlatform.hpp"
#include "tcuResultCollector.hpp"
#include "tcuTestCase.hpp"
#include "tcuTestLog.hpp"
#include "vkApiVersion.hpp"
#include "vkDefs.hpp"
#include "vkPlatform.hpp"
#include "vktApiVersionCheck.hpp"
#include "vktCustomInstancesDevices.hpp"
#include "vktExternalMemoryUtil.hpp"
#include "vktTestCase.hpp"
#include "vktTestCaseUtil.hpp"
#include "vktTestGroupUtil.hpp"
#include "wsi/vktNativeObjectsUtil.hpp"
#include "vkDeviceUtil.hpp"
#include "vkImageUtil.hpp"
#include "vkQueryUtil.hpp"
#include "vkRefUtil.hpp"
#include "vkWsiUtil.hpp"
#include "deString.h"
#include "deStringUtil.hpp"
#include <map>
#include <vector>
using namespace vk;
using namespace vk::wsi;
using namespace std;
typedef vector<VkExtensionProperties> Extensions;
namespace vkt
{
namespace api
{
struct TestParams
{
VkFormat format;
bool useExtension;
VkImageCompressionControlEXT control;
Type wsiType;
};
static void checkImageCompressionControlSupport(Context& context, bool swapchain = false)
{
context.requireDeviceFunctionality("VK_EXT_image_compression_control");
vk::VkPhysicalDeviceImageCompressionControlFeaturesEXT imageCompressionControlFeatures = initVulkanStructure();
vk::VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT imageCompressionSwapchain = initVulkanStructure();
vk::VkPhysicalDeviceFeatures2 features2 = initVulkanStructure(&imageCompressionControlFeatures);
if (swapchain)
{
context.requireDeviceFunctionality("VK_EXT_image_compression_control_swapchain");
imageCompressionControlFeatures.pNext = &imageCompressionSwapchain;
}
context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
if (!imageCompressionControlFeatures.imageCompressionControl)
TCU_THROW(NotSupportedError, "VK_EXT_image_compression_control Image "
"compression control feature not supported.");
if (swapchain && !imageCompressionSwapchain.imageCompressionControlSwapchain)
TCU_THROW(NotSupportedError, "VK_EXT_image_compression_control_swapchain Image "
"compression control feature for swapchains not supported.");
}
static void validate(const InstanceInterface& vki, const DeviceInterface& vkd, tcu::ResultCollector& results,
VkPhysicalDevice physicalDevice, VkDevice device, TestParams& testParams, VkImage image)
{
for (unsigned planeIndex = 0; planeIndex < testParams.control.compressionControlPlaneCount; planeIndex++)
{
VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT;
if (isYCbCrFormat(testParams.format))
{
VkImageAspectFlags planeAspects[]{ VK_IMAGE_ASPECT_PLANE_0_BIT, VK_IMAGE_ASPECT_PLANE_1_BIT,
VK_IMAGE_ASPECT_PLANE_2_BIT };
aspect = planeAspects[planeIndex];
}
VkImageCompressionPropertiesEXT compressionProperties = initVulkanStructure();
VkImageSubresource2EXT subresource = initVulkanStructure();
subresource.imageSubresource.aspectMask = aspect;
VkSubresourceLayout2EXT subresourceLayout = initVulkanStructure(&compressionProperties);
vkd.getImageSubresourceLayout2EXT(device, image, &subresource, &subresourceLayout);
VkImageCompressionControlEXT compressionEnabled = initVulkanStructure();
compressionEnabled.compressionControlPlaneCount = testParams.control.compressionControlPlaneCount;
compressionEnabled.flags = testParams.control.flags;
VkImageCompressionFixedRateFlagsEXT fixedRateFlags[3] = {
VK_IMAGE_COMPRESSION_FIXED_RATE_FLAG_BITS_MAX_ENUM_EXT,
VK_IMAGE_COMPRESSION_FIXED_RATE_FLAG_BITS_MAX_ENUM_EXT,
VK_IMAGE_COMPRESSION_FIXED_RATE_FLAG_BITS_MAX_ENUM_EXT
};
compressionEnabled.pFixedRateFlags = fixedRateFlags;
VkPhysicalDeviceImageFormatInfo2 formatInfo = initVulkanStructure(&compressionEnabled);
formatInfo.format = testParams.format;
formatInfo.type = VK_IMAGE_TYPE_2D;
formatInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
formatInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
VkImageCompressionPropertiesEXT compressionPropertiesSupported = initVulkanStructure();
VkImageFormatProperties2 properties2 = initVulkanStructure(&compressionPropertiesSupported);
vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &formatInfo, &properties2);
if (testParams.useExtension)
{
if ((compressionPropertiesSupported.imageCompressionFixedRateFlags &
compressionProperties.imageCompressionFixedRateFlags) !=
compressionProperties.imageCompressionFixedRateFlags)
{
results.fail("Got image with fixed rate flags that are not supported "
"in image format properties.");
}
if ((compressionPropertiesSupported.imageCompressionFlags & compressionProperties.imageCompressionFlags) !=
compressionProperties.imageCompressionFlags &&
compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DISABLED_EXT)
{
results.fail("Got image with compression flags that are not supported "
"in image format properties.");
}
if (testParams.control.flags == VK_IMAGE_COMPRESSION_DEFAULT_EXT &&
compressionProperties.imageCompressionFixedRateFlags != 0)
{
results.fail("Got lossy compression when DEFAULT compression was requested.");
}
if (testParams.control.flags == VK_IMAGE_COMPRESSION_DISABLED_EXT &&
compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DISABLED_EXT)
{
results.fail("Image compression not disabled.");
}
if (testParams.control.flags == VK_IMAGE_COMPRESSION_DISABLED_EXT &&
compressionProperties.imageCompressionFixedRateFlags != 0)
{
results.fail("Image compression disabled but got fixed rate flags.");
}
if (testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT &&
!(compressionProperties.imageCompressionFlags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT ||
compressionProperties.imageCompressionFlags == VK_IMAGE_COMPRESSION_DISABLED_EXT ||
compressionProperties.imageCompressionFlags == VK_IMAGE_COMPRESSION_DEFAULT_EXT))
{
results.fail("Explicit compression flags not returned for image "
"creation with FIXED RATE DEFAULT.");
}
if (testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT)
{
uint32_t minRequestedRate = 1 << deCtz32(testParams.control.pFixedRateFlags[planeIndex]);
uint32_t actualRate = compressionProperties.imageCompressionFixedRateFlags;
if (compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DISABLED_EXT &&
compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DEFAULT_EXT)
{
if (minRequestedRate > actualRate)
{
results.fail("Image created with less bpc than requested.");
}
}
}
}
else
{
if (compressionProperties.imageCompressionFixedRateFlags != VK_IMAGE_COMPRESSION_FIXED_RATE_NONE_EXT)
{
results.fail("Fixed rate compression should not be enabled.");
}
if (compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DISABLED_EXT &&
compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DEFAULT_EXT)
{
results.fail("Image compression should be default or not be enabled.");
}
}
}
}
static void checkAhbImageSupport (const Context& context, const TestParams testParams, const deUint32 width, const deUint32 height, const VkImageUsageFlagBits vkUsage)
{
using namespace vkt::ExternalMemoryUtil;
// Check android hardware buffer can be allocated for the format with usage.
AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
if (!ahbApi)
{
TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
}
deUint64 ahbUsage = ahbApi->vkUsageToAhbUsage(vkUsage);
{
pt::AndroidHardwareBufferPtr ahb = ahbApi->allocate(width,height, 1, ahbApi->vkFormatToAhbFormat(testParams.format), ahbUsage);
if (ahb.internal == DE_NULL)
{
TCU_THROW(NotSupportedError, "Android hardware buffer format not supported");
}
}
// Check external memory supported.
const VkPhysicalDeviceExternalImageFormatInfoKHR external_image_format_info =
{
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
&testParams.control,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
};
const VkPhysicalDeviceImageFormatInfo2 info =
{
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
&external_image_format_info,
testParams.format,
VK_IMAGE_TYPE_2D,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_SAMPLED_BIT,
0,
};
VkImageCompressionPropertiesEXT compressionPropertiesSupported =
{
VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT,
DE_NULL,
0,
0
};
VkAndroidHardwareBufferUsageANDROID ahbUsageProperties =
{
VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID,
&compressionPropertiesSupported,
0u
};
VkExternalImageFormatProperties externalProperties =
{
VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
&ahbUsageProperties,
{ 0u, 0u, 0u }
};
VkImageFormatProperties2 properties =
{
VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
&externalProperties,
{
{ 0u, 0u, 0u },
0u,
0u,
0u,
0u
}
};
VkResult result = context.getInstanceInterface().getPhysicalDeviceImageFormatProperties2(context.getPhysicalDevice(), &info, &properties);
if(result == VK_ERROR_FORMAT_NOT_SUPPORTED)
TCU_THROW(NotSupportedError, "Format not supported");
if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) == 0)
TCU_THROW(NotSupportedError, "External handle type doesn't support exporting image");
if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0)
TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
if((compressionPropertiesSupported.imageCompressionFlags == VK_IMAGE_COMPRESSION_DISABLED_EXT)
&& (testParams.control.flags != VK_IMAGE_COMPRESSION_DISABLED_EXT))
{
TCU_THROW(NotSupportedError, "Compression is disbaled, and other compression flags are not supported");
}
if((ahbUsageProperties.androidHardwareBufferUsage & ahbUsage) != ahbUsage)
{
TCU_THROW(NotSupportedError, "Android hardware buffer usage is not supported");
}
}
static tcu::TestStatus ahbImageCreateTest(Context& context, TestParams testParams)
{
using namespace vkt::ExternalMemoryUtil;
context.requireDeviceFunctionality("VK_ANDROID_external_memory_android_hardware_buffer");
context.requireDeviceFunctionality("VK_EXT_image_compression_control");
const deUint32 width = 32;
const deUint32 height = 32;
deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
const vk::DeviceInterface& vkd = context.getDeviceInterface();
VkDevice device = context.getDevice();
tcu::TestLog& log = context.getTestContext().getLog();
tcu::ResultCollector results(log);
const VkImageUsageFlagBits vkUsage = VK_IMAGE_USAGE_SAMPLED_BIT;
VkImageCompressionFixedRateFlagsEXT planeFlags[3]{};
for (unsigned i{}; i < (testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT ? 24 : 1); i++)
{
planeFlags[0] ^= 3 << i;
planeFlags[1] ^= 5 << i;
planeFlags[2] ^= 7 << i;
if (testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT)
{
testParams.control.pFixedRateFlags = planeFlags;
}
const vk::VkExternalMemoryImageCreateInfo externalCreateInfo = {
vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, &testParams.control,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
};
const vk::VkImageCreateInfo createInfo = { vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
&externalCreateInfo,
0,
vk::VK_IMAGE_TYPE_2D,
testParams.format,
{
width,
height,
1u,
},
1,
1,
vk::VK_SAMPLE_COUNT_1_BIT,
VK_IMAGE_TILING_OPTIMAL,
vkUsage,
vk::VK_SHARING_MODE_EXCLUSIVE,
1,
&queueFamilyIndex,
vk::VK_IMAGE_LAYOUT_UNDEFINED };
checkAhbImageSupport(context, testParams, width, height, vkUsage);
Move<VkImage> image = vk::createImage(vkd, device, &createInfo);
const VkMemoryRequirements requirements = ExternalMemoryUtil::getImageMemoryRequirements(
vkd, device, image.get(), VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID);
const deUint32 exportedMemoryTypeIndex(ExternalMemoryUtil::chooseMemoryType(requirements.memoryTypeBits));
Move<VkDeviceMemory> memory = ExternalMemoryUtil::allocateExportableMemory(
vkd, device, requirements.size, exportedMemoryTypeIndex,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, image.get());
VK_CHECK(vkd.bindImageMemory(device, image.get(), memory.get(), 0u));
validate(context.getInstanceInterface(), context.getDeviceInterface(), results, context.getPhysicalDevice(),
context.getDevice(), testParams, image.get());
}
return tcu::TestStatus(results.getResult(), results.getMessage());
}
static tcu::TestStatus imageCreateTest(Context& context, TestParams testParams)
{
checkImageCompressionControlSupport(context);
deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
const VkDevice device = context.getDevice();
VkExtent3D extent = { 16, 16, 1 };
tcu::TestLog& log = context.getTestContext().getLog();
tcu::ResultCollector results(log);
VkImageCompressionFixedRateFlagsEXT planeFlags[3]{};
for (unsigned i{}; i < (testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT ? 24 : 1); i++)
{
planeFlags[0] ^= 3 << i;
planeFlags[1] ^= 5 << i;
planeFlags[2] ^= 7 << i;
if (testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT)
{
testParams.control.pFixedRateFlags = planeFlags;
}
VkImageCreateInfo imageCreateInfo = {
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0, // VkImageCreateFlags flags;
VK_IMAGE_TYPE_2D, // VkImageType
testParams.format, // VkFormat format;
extent, // VkExtent3D extent;
1u, // deUint32 mipLevels;
1u, // deUint32 arraySize;
VK_SAMPLE_COUNT_1_BIT, // deUint32 samples;
VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, // VkImageUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // deUint32 queueFamilyCount;
&queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
};
if (testParams.useExtension)
{
imageCreateInfo.pNext = &testParams.control;
}
checkImageSupport(context.getInstanceInterface(), context.getPhysicalDevice(), imageCreateInfo);
Move<VkImage> image = createImage(context.getDeviceInterface(), device, &imageCreateInfo);
validate(context.getInstanceInterface(), context.getDeviceInterface(), results, context.getPhysicalDevice(),
context.getDevice(), testParams, image.get());
}
return tcu::TestStatus(results.getResult(), results.getMessage());
}
void addImageCompressionControlTests(tcu::TestCaseGroup* group, TestParams testParams)
{
static const struct
{
VkFormat begin;
VkFormat end;
} s_formatRanges[] = {
// core formats
{ (VkFormat)(VK_FORMAT_UNDEFINED + 1), VK_CORE_FORMAT_LAST },
// YCbCr formats
{ VK_FORMAT_G8B8G8R8_422_UNORM, (VkFormat)(VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM + 1) },
// YCbCr extended formats
{ VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT, (VkFormat)(VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT + 1) },
};
for (int rangeNdx = 0; rangeNdx < DE_LENGTH_OF_ARRAY(s_formatRanges); ++rangeNdx)
{
const VkFormat rangeBegin = s_formatRanges[rangeNdx].begin;
const VkFormat rangeEnd = s_formatRanges[rangeNdx].end;
for (testParams.format = rangeBegin; testParams.format != rangeEnd;
testParams.format = (VkFormat)(testParams.format + 1))
{
if (isCompressedFormat(testParams.format))
continue;
testParams.control.compressionControlPlaneCount =
isYCbCrFormat(testParams.format) ? getPlaneCount(testParams.format) : 1;
const char* const enumName = getFormatName(testParams.format);
const string caseName = de::toLower(string(enumName).substr(10));
addFunctionCase(group, caseName, enumName, imageCreateTest, testParams);
}
}
}
CustomInstance createInstanceWithWsi(Context& context, Type wsiType, const vector<string> extraExtensions,
const VkAllocationCallbacks* pAllocator = DE_NULL)
{
const deUint32 version = context.getUsedApiVersion();
vector<string> extensions = extraExtensions;
extensions.push_back("VK_KHR_surface");
extensions.push_back(getExtensionName(wsiType));
vector<string> instanceExtensions;
for (const auto& ext : extensions)
{
if (!context.isInstanceFunctionalitySupported(ext))
TCU_THROW(NotSupportedError, (ext + " is not supported").c_str());
if (!isCoreInstanceExtension(version, ext))
instanceExtensions.push_back(ext);
}
return vkt::createCustomInstanceWithExtensions(context, instanceExtensions, pAllocator);
}
struct InstanceHelper
{
const vector<VkExtensionProperties> supportedExtensions;
CustomInstance instance;
const InstanceDriver& vki;
InstanceHelper(Context& context, Type wsiType, const VkAllocationCallbacks* pAllocator = DE_NULL)
: supportedExtensions(enumerateInstanceExtensionProperties(context.getPlatformInterface(), DE_NULL))
, instance(createInstanceWithWsi(context, wsiType, vector<string>(), pAllocator))
, vki(instance.getDriver())
{
}
InstanceHelper(Context& context, Type wsiType, const vector<string>& extensions,
const VkAllocationCallbacks* pAllocator = DE_NULL)
: supportedExtensions(enumerateInstanceExtensionProperties(context.getPlatformInterface(), DE_NULL))
, instance(createInstanceWithWsi(context, wsiType, extensions, pAllocator))
, vki(instance.getDriver())
{
}
};
Move<VkDevice> 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)
{
const float queuePriorities[] = { 1.0f };
const VkDeviceQueueCreateInfo queueInfo = {
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
nullptr,
(VkDeviceQueueCreateFlags)0,
queueFamilyIndex,
DE_LENGTH_OF_ARRAY(queuePriorities),
&queuePriorities[0],
};
vector<string> extensions;
extensions.push_back("VK_KHR_swapchain");
extensions.push_back("VK_EXT_image_compression_control");
extensions.push_back("VK_EXT_image_compression_control_swapchain");
extensions.insert(end(extensions), begin(additionalExtensions), end(additionalExtensions));
for (const auto& extName : extensions)
{
if (!isCoreDeviceExtension(apiVersion, extName) &&
!isExtensionStructSupported(supportedExtensions, RequiredExtension(extName)))
TCU_THROW(NotSupportedError, extName + " is not supported");
}
const void* pNext = nullptr;
const VkPhysicalDeviceFeatures features = {};
// Convert from std::vector<std::string> to std::vector<const char*>.
std::vector<const char*> extensionsChar;
extensionsChar.reserve(extensions.size());
std::transform(begin(extensions), end(extensions), std::back_inserter(extensionsChar),
[](const std::string& s) { return s.c_str(); });
const VkDeviceCreateInfo deviceParams = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
pNext,
(VkDeviceCreateFlags)0,
1u,
&queueInfo,
0u, // enabledLayerCount
nullptr, // ppEnabledLayerNames
static_cast<deUint32>(extensionsChar.size()), // enabledExtensionCount
extensionsChar.data(), // ppEnabledExtensionNames
&features };
return createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &deviceParams, pAllocator);
}
struct DeviceHelper
{
const VkPhysicalDevice physicalDevice;
const deUint32 queueFamilyIndex;
const Unique<VkDevice> device;
const DeviceDriver vkd;
const VkQueue queue;
DeviceHelper(Context& context, const InstanceInterface& vki, VkInstance instance,
const vector<VkSurfaceKHR>& surface, const vector<string>& additionalExtensions = vector<string>(),
const VkAllocationCallbacks* pAllocator = DE_NULL)
: physicalDevice(chooseDevice(vki, instance, context.getTestContext().getCommandLine()))
, queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, surface))
, device(createDeviceWithWsi(context.getPlatformInterface(), context.getUsedApiVersion(), instance, vki,
physicalDevice, enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL),
additionalExtensions, queueFamilyIndex,
context.getTestContext().getCommandLine().isValidationEnabled(), pAllocator))
, vkd(context.getPlatformInterface(), instance, *device)
, queue(getDeviceQueue(vkd, *device, queueFamilyIndex, 0))
{
}
// Single-surface shortcut.
DeviceHelper(Context& context, const InstanceInterface& vki, VkInstance instance, VkSurfaceKHR surface,
const vector<string>& additionalExtensions = vector<string>(),
const VkAllocationCallbacks* pAllocator = DE_NULL)
: DeviceHelper(context, vki, instance, vector<VkSurfaceKHR>(1u, surface), additionalExtensions, pAllocator)
{
}
};
static tcu::TestStatus swapchainCreateTest(Context& context, TestParams testParams)
{
checkImageCompressionControlSupport(context, true);
tcu::TestLog& log = context.getTestContext().getLog();
tcu::ResultCollector results(log);
const InstanceHelper instHelper(context, testParams.wsiType);
const wsi::NativeObjects native(context, instHelper.supportedExtensions, testParams.wsiType);
VkExtent2D extent2d = { 16, 16 };
VkImageCompressionFixedRateFlagsEXT planeFlags[3]{};
for (unsigned i{}; i < (testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT ? 24 : 1); i++)
{
planeFlags[0] ^= 3 << i;
if (testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT)
{
testParams.control.pFixedRateFlags = planeFlags;
}
const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, testParams.wsiType,
native.getDisplay(), native.getWindow()));
const DeviceHelper devHelper(context, instHelper.vki, instHelper.instance, *surface, vector<string>());
VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo = initVulkanStructure();
VkSurfaceCapabilities2KHR caps = initVulkanStructure();
surfaceInfo.surface = surface.get();
instHelper.vki.getPhysicalDeviceSurfaceCapabilities2KHR(devHelper.physicalDevice, &surfaceInfo, &caps);
deUint32 numFormats;
instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(devHelper.physicalDevice, &surfaceInfo, &numFormats,
nullptr);
vector<VkSurfaceFormat2KHR> formats(numFormats);
for (auto& surfaceFormat : formats)
{
surfaceFormat = initVulkanStructure();
}
instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(devHelper.physicalDevice, &surfaceInfo, &numFormats,
formats.data());
deUint32 queueFamilyIndex = devHelper.queueFamilyIndex;
for (auto& format : formats)
{
testParams.format = format.surfaceFormat.format;
VkSwapchainCreateInfoKHR swapchainInfo = initVulkanStructure();
swapchainInfo.surface = surface.get();
swapchainInfo.minImageCount = caps.surfaceCapabilities.minImageCount;
swapchainInfo.imageFormat = format.surfaceFormat.format;
swapchainInfo.imageColorSpace = format.surfaceFormat.colorSpace;
swapchainInfo.imageExtent = extent2d;
swapchainInfo.imageArrayLayers = 1;
swapchainInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
swapchainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
swapchainInfo.queueFamilyIndexCount = 1;
swapchainInfo.pQueueFamilyIndices = &queueFamilyIndex;
swapchainInfo.preTransform = caps.surfaceCapabilities.currentTransform;
swapchainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
swapchainInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR;
swapchainInfo.clipped = VK_TRUE;
swapchainInfo.pNext = &testParams.control;
Move<VkSwapchainKHR> swapchain = createSwapchainKHR(devHelper.vkd, devHelper.device.get(), &swapchainInfo);
deUint32 imageCount = 0;
devHelper.vkd.getSwapchainImagesKHR(devHelper.device.get(), swapchain.get(), &imageCount, nullptr);
vector<VkImage> images(imageCount);
devHelper.vkd.getSwapchainImagesKHR(devHelper.device.get(), swapchain.get(), &imageCount, images.data());
validate(instHelper.vki, devHelper.vkd, results, devHelper.physicalDevice, devHelper.device.get(),
testParams, images[0]);
}
}
return tcu::TestStatus(results.getResult(), results.getMessage());
}
void addAhbCompressionControlTests(tcu::TestCaseGroup *group, TestParams testParams)
{
// Ahb formats
static const vk::VkFormat ahbFormats[] = {
VK_FORMAT_R8G8B8A8_UNORM,
VK_FORMAT_R8G8B8_UNORM,
VK_FORMAT_R5G6B5_UNORM_PACK16,
VK_FORMAT_R16G16B16A16_SFLOAT,
VK_FORMAT_A2B10G10R10_UNORM_PACK32,
VK_FORMAT_D16_UNORM,
VK_FORMAT_X8_D24_UNORM_PACK32,
VK_FORMAT_D24_UNORM_S8_UINT,
VK_FORMAT_D32_SFLOAT,
VK_FORMAT_D32_SFLOAT_S8_UINT,
VK_FORMAT_S8_UINT
};
for (int index = 0; index < DE_LENGTH_OF_ARRAY(ahbFormats); ++index)
{
testParams.format = ahbFormats[index];
const char *const enumName = getFormatName(testParams.format);
const string caseName = de::toLower(string(enumName).substr(10));
addFunctionCase(group, caseName, enumName, ahbImageCreateTest, testParams);
}
}
tcu::TestCaseGroup* createImageCompressionControlTests(tcu::TestContext& testCtx)
{
de::MovePtr<tcu::TestCaseGroup> group(
new tcu::TestCaseGroup(testCtx, "image_compression_control", "Test for image compression control."));
TestParams testParams{};
tcu::TestCaseGroup* subgroup(
new tcu::TestCaseGroup(testCtx, "create_image", "Test creating images with compression control struct"));
subgroup->addChild(createTestGroup(testCtx, "no_compression_control",
"Queries images created without compression control struct.",
addImageCompressionControlTests, testParams));
testParams.useExtension = true;
testParams.control = initVulkanStructure();
testParams.control.flags = VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT;
struct
{
const char* name;
VkImageCompressionFlagsEXT flag;
} compression_flags[] = {
{ "default", VK_IMAGE_COMPRESSION_DEFAULT_EXT },
{ "fixed_rate_default", VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT },
{ "disabled", VK_IMAGE_COMPRESSION_DISABLED_EXT },
{ "explicit", VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT },
};
for (auto& flag : compression_flags)
{
testParams.control.flags = flag.flag;
subgroup->addChild(createTestGroup(testCtx, flag.name,
"Queries images created with compression control struct.",
addImageCompressionControlTests, testParams));
}
group->addChild(subgroup);
testParams.control.compressionControlPlaneCount = 1;
subgroup = new tcu::TestCaseGroup(testCtx, "android_hardware_buffer",
"Test creating Android Hardware buffer with compression control struct");
for (auto& flag : compression_flags)
{
testParams.control.flags = flag.flag;
subgroup->addChild(createTestGroup(testCtx, flag.name,
"Queries images created with compression control struct.",
addAhbCompressionControlTests, testParams));
}
group->addChild(subgroup);
subgroup = new tcu::TestCaseGroup(testCtx, "swapchain", "swapchain");
for (int typeNdx = 0; typeNdx < vk::wsi::TYPE_LAST; ++typeNdx)
{
const vk::wsi::Type wsiType = (vk::wsi::Type)typeNdx;
testParams.wsiType = wsiType;
tcu::TestCaseGroup* wsi_subgroup(new tcu::TestCaseGroup(testCtx, getName(wsiType), "Swapchain tests"));
for (auto& flag : compression_flags)
{
testParams.control.flags = flag.flag;
addFunctionCase(wsi_subgroup, flag.name, flag.name, swapchainCreateTest, testParams);
}
subgroup->addChild(wsi_subgroup);
}
group->addChild(subgroup);
return group.release();
}
} // namespace api
} // namespace vkt