Support VK_IMAGE_CREATE_EXTENDED_USAGE_BIT The Vulkan spec states that "For images created with VK_IMAGE_CREATE_EXTENDED_USAGE_BIT a usage bit is valid if it is supported for at least one of the formats a VkImageView created from the image can have". Previously this flag was ignored and we failed to create some images for which the usage flag was meant for an image view with a different format. The Format::compatibleFormat() method was renamed to getCompatibilityClassRepresentative(). This method is used in the implementation of the new Format::getCompatibleFormats() method which returns an std::vector with all the formats in the same compatibility class. Bug: b/214957976 Change-Id: I1db61f51744914405825c0471fee014a6b6845af Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/64568 Kokoro-Result: kokoro <noreply+kokoro@google.com> Tested-by: Nicolas Capens <nicolascapens@google.com> Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Vulkan/VkFormat.cpp b/src/Vulkan/VkFormat.cpp index 9cb2061..cdf40ac 100644 --- a/src/Vulkan/VkFormat.cpp +++ b/src/Vulkan/VkFormat.cpp
@@ -682,7 +682,368 @@ } } -VkFormat Format::compatibleFormat() const +std::vector<Format> Format::getCompatibleFormats() const +{ + switch(getCompatibilityClassRepresentative()) + { + // 8 - bit, Block size 1 byte, 1 texel / block + case VK_FORMAT_R8_UNORM: + return { + VK_FORMAT_R4G4_UNORM_PACK8, + VK_FORMAT_R8_UNORM, + VK_FORMAT_R8_SNORM, + VK_FORMAT_R8_USCALED, + VK_FORMAT_R8_SSCALED, + VK_FORMAT_R8_UINT, + VK_FORMAT_R8_SINT, + VK_FORMAT_R8_SRGB, + }; + + // 16 - bit, Block size 2 bytes, 1 texel / block + case VK_FORMAT_R16_UNORM: + return { + VK_FORMAT_R4G4B4A4_UNORM_PACK16, + VK_FORMAT_B4G4R4A4_UNORM_PACK16, + VK_FORMAT_A4R4G4B4_UNORM_PACK16, + VK_FORMAT_A4B4G4R4_UNORM_PACK16, + VK_FORMAT_R5G6B5_UNORM_PACK16, + VK_FORMAT_B5G6R5_UNORM_PACK16, + VK_FORMAT_R5G5B5A1_UNORM_PACK16, + VK_FORMAT_B5G5R5A1_UNORM_PACK16, + VK_FORMAT_A1R5G5B5_UNORM_PACK16, + VK_FORMAT_R8G8_UNORM, + VK_FORMAT_R8G8_SNORM, + VK_FORMAT_R8G8_USCALED, + VK_FORMAT_R8G8_SSCALED, + VK_FORMAT_R8G8_UINT, + VK_FORMAT_R8G8_SINT, + VK_FORMAT_R8G8_SRGB, + VK_FORMAT_R16_UNORM, + VK_FORMAT_R16_SNORM, + VK_FORMAT_R16_USCALED, + VK_FORMAT_R16_SSCALED, + VK_FORMAT_R16_UINT, + VK_FORMAT_R16_SINT, + VK_FORMAT_R16_SFLOAT, + VK_FORMAT_R10X6_UNORM_PACK16, + VK_FORMAT_R12X4_UNORM_PACK16, + }; + + // 32 - bit, Block size 4 bytes, 1 texel / block + case VK_FORMAT_R8G8B8A8_UNORM: + return { + VK_FORMAT_R8G8B8A8_UNORM, + VK_FORMAT_R8G8B8A8_SNORM, + VK_FORMAT_R8G8B8A8_USCALED, + VK_FORMAT_R8G8B8A8_SSCALED, + VK_FORMAT_R8G8B8A8_UINT, + VK_FORMAT_R8G8B8A8_SINT, + VK_FORMAT_R8G8B8A8_SRGB, + VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_B8G8R8A8_SNORM, + VK_FORMAT_B8G8R8A8_USCALED, + VK_FORMAT_B8G8R8A8_SSCALED, + VK_FORMAT_B8G8R8A8_UINT, + VK_FORMAT_B8G8R8A8_SINT, + VK_FORMAT_B8G8R8A8_SRGB, + VK_FORMAT_A8B8G8R8_UNORM_PACK32, + VK_FORMAT_A8B8G8R8_SNORM_PACK32, + VK_FORMAT_A8B8G8R8_USCALED_PACK32, + VK_FORMAT_A8B8G8R8_SSCALED_PACK32, + VK_FORMAT_A8B8G8R8_UINT_PACK32, + VK_FORMAT_A8B8G8R8_SINT_PACK32, + VK_FORMAT_A8B8G8R8_SRGB_PACK32, + VK_FORMAT_A2R10G10B10_UNORM_PACK32, + VK_FORMAT_A2R10G10B10_SNORM_PACK32, + VK_FORMAT_A2R10G10B10_USCALED_PACK32, + VK_FORMAT_A2R10G10B10_SSCALED_PACK32, + VK_FORMAT_A2R10G10B10_UINT_PACK32, + VK_FORMAT_A2R10G10B10_SINT_PACK32, + VK_FORMAT_A2B10G10R10_UNORM_PACK32, + VK_FORMAT_A2B10G10R10_SNORM_PACK32, + VK_FORMAT_A2B10G10R10_USCALED_PACK32, + VK_FORMAT_A2B10G10R10_SSCALED_PACK32, + VK_FORMAT_A2B10G10R10_UINT_PACK32, + VK_FORMAT_A2B10G10R10_SINT_PACK32, + VK_FORMAT_R16G16_UNORM, + VK_FORMAT_R16G16_SNORM, + VK_FORMAT_R16G16_USCALED, + VK_FORMAT_R16G16_SSCALED, + VK_FORMAT_R16G16_UINT, + VK_FORMAT_R16G16_SINT, + VK_FORMAT_R16G16_SFLOAT, + VK_FORMAT_R32_UINT, + VK_FORMAT_R32_SINT, + VK_FORMAT_R32_SFLOAT, + VK_FORMAT_B10G11R11_UFLOAT_PACK32, + VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, + VK_FORMAT_R10X6G10X6_UNORM_2PACK16, + VK_FORMAT_R12X4G12X4_UNORM_2PACK16, + }; + + // 48 - bit, Block size 6 bytes, 1 texel / block + case VK_FORMAT_R16G16B16_UNORM: + return { + VK_FORMAT_R16G16B16_UNORM, + VK_FORMAT_R16G16B16_SNORM, + VK_FORMAT_R16G16B16_USCALED, + VK_FORMAT_R16G16B16_SSCALED, + VK_FORMAT_R16G16B16_UINT, + VK_FORMAT_R16G16B16_SINT, + VK_FORMAT_R16G16B16_SFLOAT, + }; + + // 64 - bit, Block size 8 bytes, 1 texel / block + case VK_FORMAT_R16G16B16A16_UNORM: + return { + VK_FORMAT_R16G16B16A16_UNORM, + VK_FORMAT_R16G16B16A16_SNORM, + VK_FORMAT_R16G16B16A16_USCALED, + VK_FORMAT_R16G16B16A16_SSCALED, + VK_FORMAT_R16G16B16A16_UINT, + VK_FORMAT_R16G16B16A16_SINT, + VK_FORMAT_R16G16B16A16_SFLOAT, + VK_FORMAT_R32G32_UINT, + VK_FORMAT_R32G32_SINT, + VK_FORMAT_R32G32_SFLOAT, + VK_FORMAT_R64_UINT, + VK_FORMAT_R64_SINT, + VK_FORMAT_R64_SFLOAT, + }; + + // 96 - bit, Block size 12 bytes, 1 texel / block + case VK_FORMAT_R32G32B32_UINT: + return { + VK_FORMAT_R32G32B32_UINT, + VK_FORMAT_R32G32B32_SINT, + VK_FORMAT_R32G32B32_SFLOAT, + }; + + // 128 - bit, Block size 16 bytes, 1 texel / block + case VK_FORMAT_R32G32B32A32_UINT: + return { + VK_FORMAT_R32G32B32A32_UINT, + VK_FORMAT_R32G32B32A32_SINT, + VK_FORMAT_R32G32B32A32_SFLOAT, + VK_FORMAT_R64G64_UINT, + VK_FORMAT_R64G64_SINT, + VK_FORMAT_R64G64_SFLOAT, + }; + + // 192 - bit, Block size 24 bytes, 1 texel / block + case VK_FORMAT_R64G64B64_UINT: + return { + VK_FORMAT_R64G64B64_UINT, + VK_FORMAT_R64G64B64_SINT, + VK_FORMAT_R64G64B64_SFLOAT, + }; + + // 256 - bit, Block size 32 bytes, 1 texel / block + case VK_FORMAT_R64G64B64A64_UINT: + return { + VK_FORMAT_R64G64B64A64_UINT, + VK_FORMAT_R64G64B64A64_SINT, + VK_FORMAT_R64G64B64A64_SFLOAT, + }; + + // BC1_RGB(64 bit), Block size 8 bytes, 16 texels / block + case VK_FORMAT_BC1_RGB_UNORM_BLOCK: + return { + VK_FORMAT_BC1_RGB_UNORM_BLOCK, + VK_FORMAT_BC1_RGB_SRGB_BLOCK, + }; + + // BC1_RGBA(64 bit), Block size 8 bytes, 16 texels / block + case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: + return { + VK_FORMAT_BC1_RGBA_UNORM_BLOCK, + VK_FORMAT_BC1_RGBA_SRGB_BLOCK, + }; + + // BC2(128 bit), Block size 16 bytes, 16 texels / block + case VK_FORMAT_BC2_UNORM_BLOCK: + return { + VK_FORMAT_BC2_UNORM_BLOCK, + VK_FORMAT_BC2_SRGB_BLOCK, + }; + + // BC3(128 bit), Block size 16 bytes, 16 texels / block + case VK_FORMAT_BC3_UNORM_BLOCK: + return { + VK_FORMAT_BC3_UNORM_BLOCK, + VK_FORMAT_BC3_SRGB_BLOCK, + }; + + // BC4(64 bit), Block size 8 bytes, 16 texels / block + case VK_FORMAT_BC4_UNORM_BLOCK: + return { + VK_FORMAT_BC4_UNORM_BLOCK, + VK_FORMAT_BC4_SNORM_BLOCK, + }; + + // BC5(128 bit), Block size 16 bytes, 16 texels / block + case VK_FORMAT_BC5_UNORM_BLOCK: + return { + VK_FORMAT_BC5_UNORM_BLOCK, + VK_FORMAT_BC5_SNORM_BLOCK, + }; + + // BC6H(128 bit), Block size 16 bytes, 16 texels / block + case VK_FORMAT_BC6H_UFLOAT_BLOCK: + return { + VK_FORMAT_BC6H_UFLOAT_BLOCK, + VK_FORMAT_BC6H_SFLOAT_BLOCK, + }; + + // BC7(128 bit), Block size 16 bytes, 16 texels / block + case VK_FORMAT_BC7_UNORM_BLOCK: + return { + VK_FORMAT_BC7_UNORM_BLOCK, + VK_FORMAT_BC7_SRGB_BLOCK, + }; + + // ETC2_RGB(64 bit), Block size 8 bytes, 16 texels / block + case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: + return { + VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, + VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK, + }; + + // ETC2_RGBA(64 bit), Block size 8 bytes, 16 texels / block + case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: + return { + VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, + VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK, + }; + + // ETC2_EAC_RGBA(64 bit), Block size 8 bytes, 16 texels / block + case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: + return { + VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, + VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK, + }; + + // EAC_R(64 bit), Block size 8 bytes, 16 texels / block + case VK_FORMAT_EAC_R11_UNORM_BLOCK: + return { + VK_FORMAT_EAC_R11_UNORM_BLOCK, + VK_FORMAT_EAC_R11_SNORM_BLOCK, + }; + + // EAC_RG(128 bit), Block size 16 bytes, 16 texels / block + case VK_FORMAT_EAC_R11G11_UNORM_BLOCK: + return { + VK_FORMAT_EAC_R11G11_UNORM_BLOCK, + VK_FORMAT_EAC_R11G11_SNORM_BLOCK, + }; + + // ASTC_4x4(128 bit), Block size 16 bytes, 16 texels / block + case VK_FORMAT_ASTC_4x4_UNORM_BLOCK: + return { + VK_FORMAT_ASTC_4x4_UNORM_BLOCK, + VK_FORMAT_ASTC_4x4_SRGB_BLOCK, + }; + + // ASTC_5x4(128 bit), Block size 16 bytes, 20 texels / block + case VK_FORMAT_ASTC_5x4_UNORM_BLOCK: + return { + VK_FORMAT_ASTC_5x4_UNORM_BLOCK, + VK_FORMAT_ASTC_5x4_SRGB_BLOCK, + }; + + // ASTC_5x5(128 bit), Block size 16 bytes, 25 texels / block + case VK_FORMAT_ASTC_5x5_UNORM_BLOCK: + return { + VK_FORMAT_ASTC_5x5_UNORM_BLOCK, + VK_FORMAT_ASTC_5x5_SRGB_BLOCK, + }; + + // ASTC_6x5(128 bit), Block size 16 bytes, 30 texels / block + case VK_FORMAT_ASTC_6x5_UNORM_BLOCK: + return { + VK_FORMAT_ASTC_6x5_UNORM_BLOCK, + VK_FORMAT_ASTC_6x5_SRGB_BLOCK, + }; + + // ASTC_6x6(128 bit), Block size 16 bytes, 36 texels / block + case VK_FORMAT_ASTC_6x6_UNORM_BLOCK: + return { + VK_FORMAT_ASTC_6x6_UNORM_BLOCK, + VK_FORMAT_ASTC_6x6_SRGB_BLOCK, + }; + + // ASTC_8x5(128 bit), Block size 16 bytes, 40 texels / block + case VK_FORMAT_ASTC_8x5_UNORM_BLOCK: + return { + VK_FORMAT_ASTC_8x5_UNORM_BLOCK, + VK_FORMAT_ASTC_8x5_SRGB_BLOCK, + }; + + // ASTC_8x6(128 bit), Block size 16 bytes, 48 texels / block + case VK_FORMAT_ASTC_8x6_UNORM_BLOCK: + return { + VK_FORMAT_ASTC_8x6_UNORM_BLOCK, + VK_FORMAT_ASTC_8x6_SRGB_BLOCK, + }; + + // ASTC_8x8(128 bit), Block size 16 bytes, 64 texels / block + case VK_FORMAT_ASTC_8x8_UNORM_BLOCK: + return { + VK_FORMAT_ASTC_8x8_UNORM_BLOCK, + VK_FORMAT_ASTC_8x8_SRGB_BLOCK, + }; + + // ASTC_10x5(128 bit), Block size 16 bytes, 50 texels / block + case VK_FORMAT_ASTC_10x5_UNORM_BLOCK: + return { + VK_FORMAT_ASTC_10x5_UNORM_BLOCK, + VK_FORMAT_ASTC_10x5_SRGB_BLOCK, + }; + + // ASTC_10x6(128 bit), Block size 16 bytes, 60 texels / block + case VK_FORMAT_ASTC_10x6_UNORM_BLOCK: + return { + VK_FORMAT_ASTC_10x6_UNORM_BLOCK, + VK_FORMAT_ASTC_10x6_SRGB_BLOCK, + }; + + // ASTC_10x8(128 bit), Block size 16 bytes, 80 texels / block + case VK_FORMAT_ASTC_10x8_UNORM_BLOCK: + return { + VK_FORMAT_ASTC_10x8_UNORM_BLOCK, + VK_FORMAT_ASTC_10x8_SRGB_BLOCK, + }; + + // ASTC_10x10(128 bit), Block size 16 bytes, 100 texels / block + case VK_FORMAT_ASTC_10x10_UNORM_BLOCK: + return { + VK_FORMAT_ASTC_10x10_UNORM_BLOCK, + VK_FORMAT_ASTC_10x10_SRGB_BLOCK, + }; + + // ASTC_12x10(128 bit), Block size 16 bytes, 120 texels / block + case VK_FORMAT_ASTC_12x10_UNORM_BLOCK: + return { + VK_FORMAT_ASTC_12x10_UNORM_BLOCK, + VK_FORMAT_ASTC_12x10_SRGB_BLOCK, + }; + + // ASTC_12x12(128 bit), Block size 16 bytes, 144 texels / block + case VK_FORMAT_ASTC_12x12_UNORM_BLOCK: + return { + VK_FORMAT_ASTC_12x12_UNORM_BLOCK, + VK_FORMAT_ASTC_12x12_SRGB_BLOCK, + }; + + // All other formats are only compatible with themselves + default: + ASSERT(getCompatibilityClassRepresentative() == format); + return { format }; + } +} + +// Returns a single format per class of compatible formats. +VkFormat Format::getCompatibilityClassRepresentative() const { // According to the Vulkan 1.1 Spec, 37.1.6. Format Compatibility Classes: // "Uncompressed color formats are compatible with each other if they occupy @@ -693,7 +1054,6 @@ // with itself. In the following table, all the formats in the same row are // compatible." - // Return a single format per group of compatible formats, for quick comparison switch(format) { // 8 - bit, Block size 1 byte, 1 texel / block @@ -979,9 +1339,9 @@ } } -bool Format::isCompatible(const Format &other) const +bool Format::isCompatible(Format other) const { - return compatibleFormat() == other.compatibleFormat(); + return getCompatibilityClassRepresentative() == other.getCompatibilityClassRepresentative(); } int Format::blockWidth() const
diff --git a/src/Vulkan/VkFormat.hpp b/src/Vulkan/VkFormat.hpp index dcfe40e..3cff4a0 100644 --- a/src/Vulkan/VkFormat.hpp +++ b/src/Vulkan/VkFormat.hpp
@@ -16,9 +16,10 @@ #define VK_FORMAT_HPP_ #include "System/Types.hpp" - #include "Vulkan/VulkanPlatform.hpp" +#include <vector> + namespace vk { class Format @@ -46,7 +47,9 @@ bool isFloatFormat() const; bool isYcbcrFormat() const; - bool isCompatible(const Format &other) const; + bool isCompatible(Format other) const; + std::vector<Format> getCompatibleFormats() const; + bool isCompressed() const; VkFormat getDecompressedFormat() const; int blockWidth() const; @@ -77,7 +80,7 @@ static VkFormat mapFrom8bit(uint8_t format); private: - VkFormat compatibleFormat() const; + VkFormat getCompatibilityClassRepresentative() const; size_t sliceBUnpadded(int width, int height, int border) const; VkFormat format = VK_FORMAT_UNDEFINED;
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp index 09ba482..198f47b 100644 --- a/src/Vulkan/libVulkan.cpp +++ b/src/Vulkan/libVulkan.cpp
@@ -3831,15 +3831,27 @@ extensionProperties = extensionProperties->pNext; } - VkFormat format = pImageFormatInfo->format; + vk::Format format = pImageFormatInfo->format; VkImageType type = pImageFormatInfo->type; VkImageTiling tiling = pImageFormatInfo->tiling; VkImageUsageFlags usage = pImageFormatInfo->usage; VkImageCreateFlags flags = pImageFormatInfo->flags; - VkFormatProperties properties; + VkFormatProperties properties = {}; vk::PhysicalDevice::GetFormatProperties(format, &properties); + if(flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT) + { + for(vk::Format f : format.getCompatibleFormats()) + { + VkFormatProperties extendedProperties = {}; + vk::PhysicalDevice::GetFormatProperties(f, &extendedProperties); + properties.linearTilingFeatures |= extendedProperties.linearTilingFeatures; + properties.optimalTilingFeatures |= extendedProperties.optimalTilingFeatures; + properties.bufferFeatures |= extendedProperties.bufferFeatures; + } + } + VkFormatFeatureFlags features; switch(tiling) {