blob: 8304d8970dbcba13ae9d9d98debb490d685f223d [file] [log] [blame]
// Copyright 2023 The Khronos Group Inc.
// Copyright 2023 Valve Corporation
// Copyright 2023 LunarG, Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
#include <gtest/gtest.h>
#define MAGIC_ENUM_RANGE_MIN 0
#define MAGIC_ENUM_RANGE_MAX 512
#include <magic_enum.hpp>
#include <magic_enum_flags.hpp>
#include <vulkan/utility/vk_format_utils.h>
#include <string_view>
// Given the string_view of a VkFormat, find the location of the letter that corresponds with a component
// EG. find_component("R8G8B8", 'G') would return 2
// returns std::string::npos if it is not found.
size_t find_component(std::string_view str, char letter) {
size_t loc = str.find(letter, 10);
while (loc != std::string_view::npos) {
if (loc < str.length() - 1 && str[loc] == letter && (std::isdigit(str[loc - 1]) || str[loc - 1] == '_') &&
std::isdigit(str[loc + 1])) {
break;
}
loc = str.find(letter, loc + 1);
}
return loc;
}
// Given the string_view of a VkFormat, find the size of the letter that corresponds with a component
// EG. find_component_size("R16G16B16", 3) would return 16
// Returns 0 if the component can't be found
size_t find_component_size(std::string_view str, char letter) {
size_t loc = find_component(str, letter);
if (loc == std::string_view::npos) return 0;
if (loc + 1 >= str.length()) return 0;
return static_cast<size_t>(std::stoi(std::string(str.substr(loc + 1)), nullptr));
}
size_t find_component_count(std::string_view str) {
size_t comp_count = 0;
if (find_component(str, 'R') != std::string_view::npos) comp_count++;
if (find_component(str, 'G') != std::string_view::npos) comp_count++;
if (find_component(str, 'B') != std::string_view::npos) comp_count++;
if (find_component(str, 'A') != std::string_view::npos) comp_count++;
if (find_component(str, 'D') != std::string_view::npos) comp_count++;
if (find_component(str, 'S') != std::string_view::npos) comp_count++;
return comp_count;
}
TEST(format_utils, vkuFormatIsSFLOAT) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
// special case depth + stencil formats
if (format == VK_FORMAT_D32_SFLOAT_S8_UINT) {
EXPECT_FALSE(vkuFormatIsSFLOAT(format));
continue;
}
if (std::string::npos != format_str.find("_SFLOAT")) {
EXPECT_TRUE(vkuFormatIsSFLOAT(format));
} else {
EXPECT_FALSE(vkuFormatIsSFLOAT(format));
}
}
}
TEST(format_utils, vkuFormatIsSINT) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (std::string::npos != format_str.find("_SINT")) {
EXPECT_TRUE(vkuFormatIsSINT(format));
} else {
EXPECT_FALSE(vkuFormatIsSINT(format));
}
}
}
TEST(format_utils, vkuFormatIsSNORM) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (std::string::npos != format_str.find("_SNORM")) {
EXPECT_TRUE(vkuFormatIsSNORM(format));
} else {
EXPECT_FALSE(vkuFormatIsSNORM(format));
}
}
}
TEST(format_utils, vkuFormatIsSRGB) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (std::string::npos != format_str.find("_SRGB")) {
EXPECT_TRUE(vkuFormatIsSRGB(format));
} else {
EXPECT_FALSE(vkuFormatIsSRGB(format));
}
}
}
TEST(format_utils, vkuFormatIsUFLOAT) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (std::string::npos != format_str.find("_UFLOAT")) {
EXPECT_TRUE(vkuFormatIsUFLOAT(format));
} else {
EXPECT_FALSE(vkuFormatIsUFLOAT(format));
}
}
}
TEST(format_utils, vkuFormatIsUINT) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
// special case depth + stencil formats
if (format == VK_FORMAT_D16_UNORM_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT ||
format == VK_FORMAT_D32_SFLOAT_S8_UINT) {
EXPECT_FALSE(vkuFormatIsUINT(format));
continue;
}
if (std::string::npos != format_str.find("_UINT")) {
EXPECT_TRUE(vkuFormatIsUINT(format));
} else {
EXPECT_FALSE(vkuFormatIsUINT(format));
}
}
}
TEST(format_utils, vkuFormatIsUNORM) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (format == VK_FORMAT_D16_UNORM_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT) {
EXPECT_FALSE(vkuFormatIsUNORM(format));
continue;
}
if (std::string::npos != format_str.find("_UNORM")) {
EXPECT_TRUE(vkuFormatIsUNORM(format));
} else {
EXPECT_FALSE(vkuFormatIsUNORM(format));
}
}
}
TEST(format_utils, vkuFormatIsUSCALED) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (std::string::npos != format_str.find("_USCALED")) {
EXPECT_TRUE(vkuFormatIsUSCALED(format));
} else {
EXPECT_FALSE(vkuFormatIsUSCALED(format));
}
}
}
TEST(format_utils, vkuFormatIsCompressed_ASTC_HDR) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
// contains ASTC and SFLOAT in the enum
if (std::string::npos != format_str.find("_ASTC_") && std::string::npos != format_str.find("_SFLOAT_BLOCK")) {
EXPECT_TRUE(vkuFormatIsCompressed_ASTC_HDR(format));
} else {
EXPECT_FALSE(vkuFormatIsCompressed_ASTC_HDR(format));
}
}
}
TEST(format_utils, vkuFormatIsCompressed_ASTC_LDR) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
// contains ASTC and does not contain SFLOAT in the enum
if (std::string::npos != format_str.find("_ASTC_") && std::string::npos == format_str.find("_SFLOAT_BLOCK")) {
EXPECT_TRUE(vkuFormatIsCompressed_ASTC_LDR(format));
} else {
EXPECT_FALSE(vkuFormatIsCompressed_ASTC_LDR(format));
}
}
}
TEST(format_utils, vkuFormatIsCompressed_BC) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (std::string::npos != format_str.find("_BC1") || std::string::npos != format_str.find("_BC2") ||
std::string::npos != format_str.find("_BC3") || std::string::npos != format_str.find("_BC4") ||
std::string::npos != format_str.find("_BC5") || std::string::npos != format_str.find("_BC6") ||
std::string::npos != format_str.find("_BC7")) {
EXPECT_TRUE(vkuFormatIsCompressed_BC(format));
} else {
EXPECT_FALSE(vkuFormatIsCompressed_BC(format));
}
}
}
TEST(format_utils, vkuFormatIsCompressed_EAC) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (std::string::npos != format_str.find("_EAC_")) {
EXPECT_TRUE(vkuFormatIsCompressed_EAC(format));
} else {
EXPECT_FALSE(vkuFormatIsCompressed_EAC(format));
}
}
}
TEST(format_utils, vkuFormatIsCompressed_ETC2) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (std::string::npos != format_str.find("_ETC2_")) {
EXPECT_TRUE(vkuFormatIsCompressed_ETC2(format));
} else {
EXPECT_FALSE(vkuFormatIsCompressed_ETC2(format));
}
}
}
TEST(format_utils, vkuFormatIsCompressed_PVRTC) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (std::string::npos != format_str.find("_PVRTC_")) {
EXPECT_TRUE(vkuFormatIsCompressed_PVRTC(format));
} else {
EXPECT_FALSE(vkuFormatIsCompressed_PVRTC(format));
}
}
}
TEST(format_utils, vkuFormatIsCompressed) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
// Since the contents of FormatIsCompressed is generated, there is no easy way to check a format based on the string.
// Instead, this function will have to be
if (std::string::npos != format_str.find("_BLOCK")) {
EXPECT_TRUE(vkuFormatIsCompressed(format));
} else {
EXPECT_FALSE(vkuFormatIsCompressed(format));
}
}
}
TEST(format_utils, vkuFormatIsDepthOrStencil) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (std::string::npos != format_str.find("_D16") || std::string::npos != format_str.find("_D24") ||
std::string::npos != format_str.find("_D32") || std::string::npos != format_str.find("_S8")) {
EXPECT_TRUE(vkuFormatIsDepthOrStencil(format));
} else {
EXPECT_FALSE(vkuFormatIsDepthOrStencil(format));
}
}
}
TEST(format_utils, vkuFormatIsDepthAndStencil) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if ((std::string::npos != format_str.find("_D16") || std::string::npos != format_str.find("_D24") ||
std::string::npos != format_str.find("_D32")) &&
std::string::npos != format_str.find("_S8")) {
EXPECT_TRUE(vkuFormatIsDepthAndStencil(format));
} else {
EXPECT_FALSE(vkuFormatIsDepthAndStencil(format));
}
}
}
TEST(format_utils, vkuFormatIsDepthOnly) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
// enum contains D16, D24, or D32 but does not contain _S8
if ((std::string::npos != format_str.find("_D16") || std::string::npos != format_str.find("_D24") ||
std::string::npos != format_str.find("_D32")) &&
std::string::npos == format_str.find("_S8")) {
EXPECT_TRUE(vkuFormatIsDepthOnly(format));
} else {
EXPECT_FALSE(vkuFormatIsDepthOnly(format));
}
}
}
TEST(format_utils, vkuFormatIsStencilOnly) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
// enum contains _S8 but does not contain D16, D24, or D32
if (std::string::npos == format_str.find("_D16") && std::string::npos == format_str.find("_D24") &&
std::string::npos == format_str.find("_D32") && std::string::npos != format_str.find("_S8")) {
EXPECT_TRUE(vkuFormatIsStencilOnly(format));
} else {
EXPECT_FALSE(vkuFormatIsStencilOnly(format));
}
}
}
TEST(format_utils, vkuFormatDepthSize) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (std::string::npos != format_str.find("_D16")) {
EXPECT_EQ(vkuFormatDepthSize(format), 16);
} else if (std::string::npos != format_str.find("_D24")) {
EXPECT_EQ(vkuFormatDepthSize(format), 24);
} else if (std::string::npos != format_str.find("_D32")) {
EXPECT_EQ(vkuFormatDepthSize(format), 32);
} else {
EXPECT_EQ(vkuFormatDepthSize(format), 0);
}
}
}
TEST(format_utils, vkuFormatStencilSize) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (std::string::npos != format_str.find("_S8")) {
EXPECT_EQ(vkuFormatStencilSize(format), 8);
} else {
EXPECT_EQ(vkuFormatStencilSize(format), 0);
}
}
}
TEST(format_utils, vkuFormatDepthNumericalType) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (std::string::npos != format_str.find("D16_UNORM") || std::string::npos != format_str.find("D24_UNORM") ||
std::string::npos != format_str.find("D32_UNORM")) {
EXPECT_EQ(vkuFormatDepthNumericalType(format), VKU_FORMAT_NUMERICAL_TYPE_UNORM);
} else if (std::string::npos != format_str.find("D32_SFLOAT")) {
EXPECT_EQ(vkuFormatDepthNumericalType(format), VKU_FORMAT_NUMERICAL_TYPE_SFLOAT);
} else {
EXPECT_EQ(vkuFormatDepthNumericalType(format), VKU_FORMAT_NUMERICAL_TYPE_NONE);
}
}
}
TEST(format_utils, vkuFormatStencilNumericalType) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (std::string::npos != format_str.find("S8_UINT")) {
EXPECT_EQ(vkuFormatStencilNumericalType(format), VKU_FORMAT_NUMERICAL_TYPE_UINT);
} else {
EXPECT_EQ(vkuFormatStencilNumericalType(format), VKU_FORMAT_NUMERICAL_TYPE_NONE);
}
}
}
TEST(format_utils, vkuFormatIsPacked) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (std::string::npos != format_str.find("_PACK8") || std::string::npos != format_str.find("_PACK16") ||
std::string::npos != format_str.find("_PACK32")) {
EXPECT_TRUE(vkuFormatIsPacked(format));
} else {
EXPECT_FALSE(vkuFormatIsPacked(format));
}
}
}
TEST(format_utils, vkuFormatRequiresYcbcrConversion) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (std::string::npos != format_str.find("_444_") || std::string::npos != format_str.find("_422_") ||
std::string::npos != format_str.find("_420_")) {
EXPECT_TRUE(vkuFormatRequiresYcbcrConversion(format));
} else {
EXPECT_FALSE(vkuFormatRequiresYcbcrConversion(format));
}
}
}
TEST(format_utils, vkuFormatIsXChromaSubsampled) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (std::string::npos == format_str.find("_444_") &&
(std::string::npos != format_str.find("_422_") || std::string::npos != format_str.find("_420_"))) {
EXPECT_TRUE(vkuFormatIsXChromaSubsampled(format));
} else {
EXPECT_FALSE(vkuFormatIsXChromaSubsampled(format));
}
}
}
TEST(format_utils, vkuFormatIsYChromaSubsampled) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (std::string::npos != format_str.find("_420_")) {
EXPECT_TRUE(vkuFormatIsYChromaSubsampled(format));
} else {
EXPECT_FALSE(vkuFormatIsYChromaSubsampled(format));
}
}
}
TEST(format_utils, vkuFormatIsSinglePlane_422) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (std::string::npos != format_str.find("_422_")) {
EXPECT_TRUE(vkuFormatIsSinglePlane_422(format));
} else {
EXPECT_FALSE(vkuFormatIsSinglePlane_422(format));
}
}
}
TEST(format_utils, vkuFormatPlaneCount) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (std::string::npos != format_str.find("2PLANE")) {
EXPECT_EQ(vkuFormatPlaneCount(format), 2);
} else if (std::string::npos != format_str.find("3PLANE")) {
EXPECT_EQ(vkuFormatPlaneCount(format), 3);
} else {
EXPECT_EQ(vkuFormatPlaneCount(format), 1);
}
}
}
TEST(format_utils, vkuFormatIsMultiplane) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (std::string::npos != format_str.find("2PLANE") || std::string::npos != format_str.find("3PLANE")) {
EXPECT_TRUE(vkuFormatIsMultiplane(format));
} else {
EXPECT_FALSE(vkuFormatIsMultiplane(format));
}
}
}
TEST(format_utils, vkuFindMultiplaneCompatibleFormat) {
EXPECT_EQ(vkuFindMultiplaneCompatibleFormat(VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, VK_IMAGE_ASPECT_PLANE_0_BIT),
VK_FORMAT_R10X6_UNORM_PACK16);
EXPECT_EQ(vkuFindMultiplaneCompatibleFormat(VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, VK_IMAGE_ASPECT_PLANE_1_BIT),
VK_FORMAT_R10X6_UNORM_PACK16);
EXPECT_EQ(vkuFindMultiplaneCompatibleFormat(VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, VK_IMAGE_ASPECT_PLANE_2_BIT),
VK_FORMAT_R10X6_UNORM_PACK16);
EXPECT_EQ(vkuFindMultiplaneCompatibleFormat(VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, VK_IMAGE_ASPECT_PLANE_0_BIT),
VK_FORMAT_R16_UNORM);
EXPECT_EQ(vkuFindMultiplaneCompatibleFormat(VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, VK_IMAGE_ASPECT_PLANE_1_BIT),
VK_FORMAT_R16G16_UNORM);
EXPECT_EQ(vkuFindMultiplaneCompatibleFormat(VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, VK_IMAGE_ASPECT_PLANE_2_BIT),
VK_FORMAT_UNDEFINED);
}
TEST(format_utils, vkuFindMultiplaneExtentDivisors) {
EXPECT_EQ(
vkuFindMultiplaneExtentDivisors(VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, VK_IMAGE_ASPECT_PLANE_0_BIT).width,
1);
EXPECT_EQ(
vkuFindMultiplaneExtentDivisors(VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, VK_IMAGE_ASPECT_PLANE_1_BIT).width,
2);
EXPECT_EQ(
vkuFindMultiplaneExtentDivisors(VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, VK_IMAGE_ASPECT_PLANE_2_BIT).width,
2);
EXPECT_EQ(
vkuFindMultiplaneExtentDivisors(VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, VK_IMAGE_ASPECT_PLANE_0_BIT).height,
1);
EXPECT_EQ(
vkuFindMultiplaneExtentDivisors(VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, VK_IMAGE_ASPECT_PLANE_1_BIT).height,
2);
EXPECT_EQ(
vkuFindMultiplaneExtentDivisors(VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, VK_IMAGE_ASPECT_PLANE_2_BIT).height,
2);
EXPECT_EQ(vkuFindMultiplaneExtentDivisors(VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, VK_IMAGE_ASPECT_PLANE_0_BIT).width, 1);
EXPECT_EQ(vkuFindMultiplaneExtentDivisors(VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, VK_IMAGE_ASPECT_PLANE_1_BIT).width, 2);
EXPECT_EQ(vkuFindMultiplaneExtentDivisors(VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, VK_IMAGE_ASPECT_PLANE_2_BIT).width, 1);
EXPECT_EQ(vkuFindMultiplaneExtentDivisors(VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, VK_IMAGE_ASPECT_PLANE_0_BIT).height, 1);
EXPECT_EQ(vkuFindMultiplaneExtentDivisors(VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, VK_IMAGE_ASPECT_PLANE_1_BIT).height, 1);
EXPECT_EQ(vkuFindMultiplaneExtentDivisors(VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, VK_IMAGE_ASPECT_PLANE_2_BIT).height, 1);
}
TEST(format_utils, vkuFormatComponentCount) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (vkuFormatIsCompressed(format)) {
// special case compressed formats because they don't typically list their components in the enum itself
continue;
}
EXPECT_EQ(vkuFormatComponentCount(format), find_component_count(format_str));
if (vkuFormatComponentCount(format) != find_component_count(format_str)) {
std::cout << "";
}
}
}
TEST(format_utils, vkuFormatTexelBlockExtent) {
constexpr auto formats = magic_enum::enum_values<VkFormat>();
for (auto format : formats) {
auto extent = vkuFormatTexelBlockExtent(format);
if (vkuFormatIsCompressed(format)) {
EXPECT_GT(extent.width, 1);
EXPECT_GT(extent.height, 1);
EXPECT_EQ(extent.depth, 1);
} else if (format == VK_FORMAT_UNDEFINED) {
EXPECT_EQ(extent.width, 0);
EXPECT_EQ(extent.height, 0);
EXPECT_EQ(extent.depth, 0);
continue;
} else {
EXPECT_EQ(extent.width, 1);
EXPECT_EQ(extent.height, 1);
EXPECT_EQ(extent.depth, 1);
}
}
auto extent = vkuFormatTexelBlockExtent(static_cast<VkFormat>(10001));
EXPECT_EQ(extent.width, 0);
EXPECT_EQ(extent.height, 0);
EXPECT_EQ(extent.depth, 0);
}
TEST(format_utils, vkuFormatCompatibilityClass) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (format == VK_FORMAT_UNDEFINED) {
EXPECT_EQ(vkuFormatCompatibilityClass(format), VKU_FORMAT_COMPATIBILITY_CLASS_NONE);
continue;
}
if (std::string::npos != format_str.find("D16") && std::string::npos != format_str.find("S8")) {
EXPECT_EQ(vkuFormatCompatibilityClass(format), VKU_FORMAT_COMPATIBILITY_CLASS_D16S8);
} else if (std::string::npos != format_str.find("D16") && std::string::npos == format_str.find("S8")) {
EXPECT_EQ(vkuFormatCompatibilityClass(format), VKU_FORMAT_COMPATIBILITY_CLASS_D16);
} else if (std::string::npos != format_str.find("D24") && std::string::npos != format_str.find("S8")) {
EXPECT_EQ(vkuFormatCompatibilityClass(format), VKU_FORMAT_COMPATIBILITY_CLASS_D24S8);
} else if (std::string::npos != format_str.find("D24") && std::string::npos == format_str.find("S8")) {
EXPECT_EQ(vkuFormatCompatibilityClass(format), VKU_FORMAT_COMPATIBILITY_CLASS_D24);
} else if (std::string::npos != format_str.find("D32") && std::string::npos != format_str.find("S8")) {
EXPECT_EQ(vkuFormatCompatibilityClass(format), VKU_FORMAT_COMPATIBILITY_CLASS_D32S8);
} else if (std::string::npos != format_str.find("D32") && std::string::npos == format_str.find("S8")) {
EXPECT_EQ(vkuFormatCompatibilityClass(format), VKU_FORMAT_COMPATIBILITY_CLASS_D32);
} else if (std::string::npos != format_str.find("S8")) {
EXPECT_EQ(vkuFormatCompatibilityClass(format), VKU_FORMAT_COMPATIBILITY_CLASS_S8);
} else if (std::string::npos != format_str.find("_PACK8")) {
EXPECT_EQ(vkuFormatCompatibilityClass(format), VKU_FORMAT_COMPATIBILITY_CLASS_8BIT);
} else if (std::string::npos != format_str.find("_PACK16")) {
EXPECT_EQ(vkuFormatCompatibilityClass(format), VKU_FORMAT_COMPATIBILITY_CLASS_16BIT);
} else if (std::string::npos != format_str.find("_PACK32")) {
EXPECT_EQ(vkuFormatCompatibilityClass(format), VKU_FORMAT_COMPATIBILITY_CLASS_32BIT);
} else if (vkuFormatIsCompressed(format)) {
// special case compressed formats because they don't typically list their components in the enum itself
continue;
} else {
size_t component_size_combined = find_component_size(format_str, 'R') + find_component_size(format_str, 'G') +
find_component_size(format_str, 'B') + find_component_size(format_str, 'A');
VKU_FORMAT_COMPATIBILITY_CLASS comp_class = VKU_FORMAT_COMPATIBILITY_CLASS_NONE;
if (component_size_combined == 8) comp_class = VKU_FORMAT_COMPATIBILITY_CLASS_8BIT;
if (component_size_combined == 16) comp_class = VKU_FORMAT_COMPATIBILITY_CLASS_16BIT;
if (component_size_combined == 24) comp_class = VKU_FORMAT_COMPATIBILITY_CLASS_24BIT;
if (component_size_combined == 32) comp_class = VKU_FORMAT_COMPATIBILITY_CLASS_32BIT;
if (component_size_combined == 48) comp_class = VKU_FORMAT_COMPATIBILITY_CLASS_48BIT;
if (component_size_combined == 64) comp_class = VKU_FORMAT_COMPATIBILITY_CLASS_64BIT;
if (component_size_combined == 96) comp_class = VKU_FORMAT_COMPATIBILITY_CLASS_96BIT;
if (component_size_combined == 128) comp_class = VKU_FORMAT_COMPATIBILITY_CLASS_128BIT;
if (component_size_combined == 192) comp_class = VKU_FORMAT_COMPATIBILITY_CLASS_192BIT;
if (component_size_combined == 256) comp_class = VKU_FORMAT_COMPATIBILITY_CLASS_256BIT;
if (comp_class == VKU_FORMAT_COMPATIBILITY_CLASS_8BIT && find_component(format_str, 'A') != std::string_view::npos)
comp_class = VKU_FORMAT_COMPATIBILITY_CLASS_8BIT_ALPHA;
EXPECT_EQ(vkuFormatCompatibilityClass(format), comp_class);
if (vkuFormatCompatibilityClass(format) != comp_class) {
std::cout << "";
}
}
}
}
TEST(format_utils, vkuFormatElementIsTexel) {
constexpr auto formats = magic_enum::enum_values<VkFormat>();
for (auto format : formats) {
if (!(vkuFormatIsPacked(format) || vkuFormatIsCompressed(format) || vkuFormatIsSinglePlane_422(format) ||
vkuFormatIsMultiplane(format))) {
EXPECT_TRUE(vkuFormatElementIsTexel(format));
} else {
EXPECT_FALSE(vkuFormatElementIsTexel(format));
}
}
}
TEST(format_utils, vkuFormatElementSizeWithAspect) {
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_R64G64_SFLOAT, VK_IMAGE_ASPECT_NONE), 16);
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_R64G64_SFLOAT, VK_IMAGE_ASPECT_STENCIL_BIT), 0);
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_R64G64_SFLOAT, VK_IMAGE_ASPECT_DEPTH_BIT), 0);
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_ASTC_5x4_SRGB_BLOCK, VK_IMAGE_ASPECT_NONE), 16);
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_ASTC_5x4_SRGB_BLOCK, VK_IMAGE_ASPECT_PLANE_0_BIT), 16);
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_ASTC_5x4_SRGB_BLOCK, VK_IMAGE_ASPECT_PLANE_1_BIT), 16);
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_ASTC_5x4_SRGB_BLOCK, VK_IMAGE_ASPECT_PLANE_2_BIT), 16);
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_ASTC_5x4_SRGB_BLOCK, VK_IMAGE_ASPECT_STENCIL_BIT), 0);
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_ASTC_5x4_SRGB_BLOCK, VK_IMAGE_ASPECT_DEPTH_BIT), 0);
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, VK_IMAGE_ASPECT_NONE), 0);
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, VK_IMAGE_ASPECT_PLANE_0_BIT), 2);
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, VK_IMAGE_ASPECT_PLANE_1_BIT), 2);
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, VK_IMAGE_ASPECT_PLANE_2_BIT), 2);
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, VK_IMAGE_ASPECT_STENCIL_BIT), 0);
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, VK_IMAGE_ASPECT_DEPTH_BIT), 0);
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_D32_SFLOAT, VK_IMAGE_ASPECT_NONE), 4);
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_D32_SFLOAT, VK_IMAGE_ASPECT_STENCIL_BIT), 0);
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_D32_SFLOAT, VK_IMAGE_ASPECT_DEPTH_BIT), 4);
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_D32_SFLOAT_S8_UINT, VK_IMAGE_ASPECT_NONE), 5);
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_D32_SFLOAT_S8_UINT, VK_IMAGE_ASPECT_STENCIL_BIT), 1);
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_D32_SFLOAT_S8_UINT, VK_IMAGE_ASPECT_DEPTH_BIT), 4);
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_S8_UINT, VK_IMAGE_ASPECT_NONE), 1);
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_S8_UINT, VK_IMAGE_ASPECT_STENCIL_BIT), 1);
EXPECT_EQ(vkuFormatElementSizeWithAspect(VK_FORMAT_S8_UINT, VK_IMAGE_ASPECT_DEPTH_BIT), 0);
}
TEST(format_utils, vkuFormatTexelSizeWithAspect) {
EXPECT_EQ(vkuFormatTexelSizeWithAspect(VK_FORMAT_R64G64_SFLOAT, VK_IMAGE_ASPECT_NONE), 16);
EXPECT_EQ(vkuFormatTexelSizeWithAspect(VK_FORMAT_R64G64_SFLOAT, VK_IMAGE_ASPECT_STENCIL_BIT), 0);
EXPECT_EQ(vkuFormatTexelSizeWithAspect(VK_FORMAT_R64G64_SFLOAT, VK_IMAGE_ASPECT_DEPTH_BIT), 0);
EXPECT_EQ(vkuFormatTexelSizeWithAspect(VK_FORMAT_ASTC_5x4_SRGB_BLOCK, VK_IMAGE_ASPECT_NONE), 16. / 20.);
EXPECT_EQ(vkuFormatTexelSizeWithAspect(VK_FORMAT_ASTC_5x4_SRGB_BLOCK, VK_IMAGE_ASPECT_STENCIL_BIT), 0);
EXPECT_EQ(vkuFormatTexelSizeWithAspect(VK_FORMAT_ASTC_5x4_SRGB_BLOCK, VK_IMAGE_ASPECT_DEPTH_BIT), 0);
EXPECT_EQ(vkuFormatTexelSizeWithAspect(VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, VK_IMAGE_ASPECT_NONE), 0);
EXPECT_EQ(vkuFormatTexelSizeWithAspect(VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, VK_IMAGE_ASPECT_PLANE_0_BIT), 2);
EXPECT_EQ(vkuFormatTexelSizeWithAspect(VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, VK_IMAGE_ASPECT_PLANE_1_BIT), 2);
EXPECT_EQ(vkuFormatTexelSizeWithAspect(VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, VK_IMAGE_ASPECT_PLANE_2_BIT), 2);
EXPECT_EQ(vkuFormatTexelSizeWithAspect(VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, VK_IMAGE_ASPECT_STENCIL_BIT), 0);
EXPECT_EQ(vkuFormatTexelSizeWithAspect(VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, VK_IMAGE_ASPECT_STENCIL_BIT), 0);
EXPECT_EQ(vkuFormatTexelSizeWithAspect(VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, VK_IMAGE_ASPECT_DEPTH_BIT), 0);
EXPECT_EQ(vkuFormatTexelSizeWithAspect(VK_FORMAT_D32_SFLOAT, VK_IMAGE_ASPECT_NONE), 4);
EXPECT_EQ(vkuFormatTexelSizeWithAspect(VK_FORMAT_D32_SFLOAT, VK_IMAGE_ASPECT_STENCIL_BIT), 0);
EXPECT_EQ(vkuFormatTexelSizeWithAspect(VK_FORMAT_D32_SFLOAT, VK_IMAGE_ASPECT_DEPTH_BIT), 4);
EXPECT_EQ(vkuFormatTexelSizeWithAspect(VK_FORMAT_D32_SFLOAT_S8_UINT, VK_IMAGE_ASPECT_NONE), 5);
EXPECT_EQ(vkuFormatTexelSizeWithAspect(VK_FORMAT_D32_SFLOAT_S8_UINT, VK_IMAGE_ASPECT_STENCIL_BIT), 1);
EXPECT_EQ(vkuFormatTexelSizeWithAspect(VK_FORMAT_D32_SFLOAT_S8_UINT, VK_IMAGE_ASPECT_DEPTH_BIT), 4);
EXPECT_EQ(vkuFormatTexelSizeWithAspect(VK_FORMAT_S8_UINT, VK_IMAGE_ASPECT_NONE), 1);
EXPECT_EQ(vkuFormatTexelSizeWithAspect(VK_FORMAT_S8_UINT, VK_IMAGE_ASPECT_STENCIL_BIT), 1);
EXPECT_EQ(vkuFormatTexelSizeWithAspect(VK_FORMAT_S8_UINT, VK_IMAGE_ASPECT_DEPTH_BIT), 0);
}
TEST(format_utils, vkuFormatIs64bit) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (std::string::npos != format_str.find("R64")) {
EXPECT_TRUE(vkuFormatIs64bit(format));
} else {
EXPECT_FALSE(vkuFormatIs64bit(format));
}
}
}
TEST(format_utils, vkuFormatHasComponentSize) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (vkuFormatIsCompressed(format)) {
// special case compressed formats because they don't typically list their components in the enum itself
continue;
}
for (uint32_t i = 1; i < 64; i++) {
bool has_component_size = false;
has_component_size |= find_component_size(format_str, 'R') == i;
has_component_size |= find_component_size(format_str, 'G') == i;
has_component_size |= find_component_size(format_str, 'B') == i;
has_component_size |= find_component_size(format_str, 'A') == i;
has_component_size |= find_component_size(format_str, 'D') == i;
has_component_size |= find_component_size(format_str, 'S') == i;
EXPECT_EQ(vkuFormatHasComponentSize(format, i), has_component_size);
}
}
}
void check_for_letter(char letter, bool (*func)(VkFormat)) {
for (auto [format, format_str] : magic_enum::enum_entries<VkFormat>()) {
if (vkuFormatIsCompressed(format)) {
// special case compressed formats because they don't typically list their components in the enum itself
continue;
}
auto loc = find_component(format_str, letter);
if (std::string::npos != loc) {
EXPECT_TRUE(func(format));
} else {
EXPECT_FALSE(func(format));
}
}
}
TEST(format_utils, vkuFormatHasRed) { check_for_letter('R', vkuFormatHasRed); }
TEST(format_utils, vkuFormatHasGreen) { check_for_letter('G', vkuFormatHasGreen); }
TEST(format_utils, vkuFormatHasBlue) { check_for_letter('B', vkuFormatHasBlue); }
TEST(format_utils, vkuFormatHasAlpha) { check_for_letter('A', vkuFormatHasAlpha); }
TEST(format_utils, vkuFormatIsUndefined) {
constexpr auto formats = magic_enum::enum_values<VkFormat>();
for (auto format : formats) {
if (format == VK_FORMAT_UNDEFINED) {
EXPECT_TRUE(vkuFormatIsUndefined(format));
} else {
EXPECT_FALSE(vkuFormatIsUndefined(format));
}
}
}
TEST(format_utils, vkuFormatIsBlockedImage) {
constexpr auto formats = magic_enum::enum_values<VkFormat>();
for (auto format : formats) {
if (vkuFormatIsCompressed(format) || vkuFormatIsSinglePlane_422(format)) {
EXPECT_TRUE(vkuFormatIsBlockedImage(format));
} else {
EXPECT_FALSE(vkuFormatIsBlockedImage(format));
}
}
}
TEST(format_utils, vkuFormatIsColor) {
constexpr auto formats = magic_enum::enum_values<VkFormat>();
for (auto format : formats) {
if (!(vkuFormatIsUndefined(format) || vkuFormatIsDepthOrStencil(format) || vkuFormatIsMultiplane(format))) {
EXPECT_TRUE(vkuFormatIsColor(format));
} else {
EXPECT_FALSE(vkuFormatIsColor(format));
}
}
}
template <>
struct magic_enum::customize::enum_range<VkImageAspectFlagBits> {
static constexpr bool is_flags = true;
};
TEST(format_utils, vkuGetPlaneIndex) {
for (auto [aspect_flag, aspect_flag_str] : magic_enum::enum_entries<VkImageAspectFlagBits>()) {
if (std::string::npos != aspect_flag_str.find("_ASPECT_PLANE_0")) {
EXPECT_EQ(vkuGetPlaneIndex(aspect_flag), 0);
} else if (std::string::npos != aspect_flag_str.find("_ASPECT_PLANE_1")) {
EXPECT_EQ(vkuGetPlaneIndex(aspect_flag), 1);
} else if (std::string::npos != aspect_flag_str.find("_ASPECT_PLANE_2")) {
EXPECT_EQ(vkuGetPlaneIndex(aspect_flag), 2);
} else {
EXPECT_EQ(vkuGetPlaneIndex(aspect_flag), VKU_FORMAT_INVALID_INDEX);
}
}
}