From ce42eccc9d9b629b2e25296d42f7d686d53cfb25 Mon Sep 17 00:00:00 2001 From: TheTurtle Date: Sun, 8 Jun 2025 23:09:08 +0300 Subject: [PATCH] texture_cache: Handle compressed views of uncompressed images (#3056) * pixel_format: Remove unused tables, refactor * host_compatibilty: Cleanup and support uncompressed views of compressed formats * texture_cache: Handle compressed views of uncompressed images * tile_manager: Bump max supported mips to 16 Fixes a crash during start * oops * texture_cache: Fix order of format compat check --- CMakeLists.txt | 1 + .../ir/passes/lower_buffer_format_to_raw.cpp | 2 +- src/video_core/amdgpu/liverpool.h | 2 +- src/video_core/amdgpu/pixel_format.cpp | 214 +++++----- src/video_core/amdgpu/pixel_format.h | 6 +- .../host_shaders/detilers/micro_128bpp.comp | 2 +- .../host_shaders/detilers/micro_16bpp.comp | 2 +- .../host_shaders/detilers/micro_32bpp.comp | 2 +- .../host_shaders/detilers/micro_64bpp.comp | 2 +- .../host_shaders/detilers/micro_8bpp.comp | 2 +- .../texture_cache/host_compatibility.cpp | 220 ++++++++++ .../texture_cache/host_compatibility.h | 380 +----------------- src/video_core/texture_cache/image.cpp | 65 +-- src/video_core/texture_cache/image_info.cpp | 79 +++- src/video_core/texture_cache/image_info.h | 25 +- .../texture_cache/texture_cache.cpp | 25 +- src/video_core/texture_cache/tile_manager.cpp | 14 +- 17 files changed, 434 insertions(+), 609 deletions(-) create mode 100644 src/video_core/texture_cache/host_compatibility.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 20d33ac95..6dfe9348a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -964,6 +964,7 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp src/video_core/texture_cache/tile_manager.cpp src/video_core/texture_cache/tile_manager.h src/video_core/texture_cache/types.h + src/video_core/texture_cache/host_compatibility.cpp src/video_core/texture_cache/host_compatibility.h src/video_core/page_manager.cpp src/video_core/page_manager.h diff --git a/src/shader_recompiler/ir/passes/lower_buffer_format_to_raw.cpp b/src/shader_recompiler/ir/passes/lower_buffer_format_to_raw.cpp index 65be02541..fcb86e3fb 100644 --- a/src/shader_recompiler/ir/passes/lower_buffer_format_to_raw.cpp +++ b/src/shader_recompiler/ir/passes/lower_buffer_format_to_raw.cpp @@ -15,7 +15,7 @@ struct FormatInfo { AmdGpu::NumberFormat num_format; AmdGpu::CompMapping swizzle; AmdGpu::NumberConversion num_conversion; - int num_components; + u32 num_components; }; static bool IsBufferFormatLoad(const IR::Inst& inst) { diff --git a/src/video_core/amdgpu/liverpool.h b/src/video_core/amdgpu/liverpool.h index 245e34d35..2f33c7302 100644 --- a/src/video_core/amdgpu/liverpool.h +++ b/src/video_core/amdgpu/liverpool.h @@ -914,7 +914,7 @@ struct Liverpool { } size_t GetColorSliceSize() const { - const auto num_bytes_per_element = NumBits(info.format) / 8u; + const auto num_bytes_per_element = NumBitsPerBlock(info.format) / 8u; const auto slice_size = num_bytes_per_element * (slice.tile_max + 1) * 64u * NumSamples(); return slice_size; diff --git a/src/video_core/amdgpu/pixel_format.cpp b/src/video_core/amdgpu/pixel_format.cpp index 881c33e44..682cdf357 100644 --- a/src/video_core/amdgpu/pixel_format.cpp +++ b/src/video_core/amdgpu/pixel_format.cpp @@ -111,136 +111,106 @@ std::string_view NameOf(NumberFormat fmt) { } } -int NumComponents(DataFormat format) { - constexpr std::array num_components_per_element = { - 0, 1, 1, 2, 1, 2, 3, 3, 4, 4, 4, 2, 4, 3, 4, -1, 3, 4, 4, 4, 2, - 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 3, 3, 4, 4, 4, 1, 2, 3, 4, - -1, -1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 1, 1}; - - const u32 index = static_cast(format); - if (index >= num_components_per_element.size()) { - return 0; - } - return num_components_per_element[index]; -} - -int NumBits(DataFormat format) { - const std::array num_bits_per_element = { - 0, 8, 16, 16, 32, 32, 32, 32, 32, 32, 32, 64, 64, 96, 128, -1, 16, 16, 16, 16, 32, - 32, 64, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, 16, 32, 4, 8, 8, 4, 8, 8, 8, - -1, -1, 8, 8, 8, 8, 8, 8, 16, 16, 32, 32, 32, 64, 64, 8, 16, 1, 1}; - - const u32 index = static_cast(format); - if (index >= num_bits_per_element.size()) { - return 0; - } - return num_bits_per_element[index]; -} - -static constexpr std::array component_bits = { - std::array{0, 0, 0, 0}, // 0 FormatInvalid - std::array{8, 0, 0, 0}, // 1 Format8 - std::array{16, 0, 0, 0}, // 2 Format16 - std::array{8, 8, 0, 0}, // 3 Format8_8 - std::array{32, 0, 0, 0}, // 4 Format32 - std::array{16, 16, 0, 0}, // 5 Format16_16 - std::array{11, 11, 10, 0}, // 6 Format10_11_11 - std::array{10, 11, 11, 0}, // 7 Format11_11_10 - std::array{2, 10, 10, 10}, // 8 Format10_10_10_2 - std::array{10, 10, 10, 2}, // 9 Format2_10_10_10 - std::array{8, 8, 8, 8}, // 10 Format8_8_8_8 - std::array{32, 32, 0, 0}, // 11 Format32_32 - std::array{16, 16, 16, 16}, // 12 Format16_16_16_16 - std::array{32, 32, 32, 0}, // 13 Format32_32_32 - std::array{32, 32, 32, 32}, // 14 Format32_32_32_32 - std::array{0, 0, 0, 0}, // 15 - std::array{5, 6, 5, 0}, // 16 Format5_6_5 - std::array{5, 5, 5, 1}, // 17 Format1_5_5_5 - std::array{1, 5, 5, 5}, // 18 Format5_5_5_1 - std::array{4, 4, 4, 4}, // 19 Format4_4_4_4 - std::array{24, 8, 0, 0}, // 20 Format8_24 - std::array{8, 24, 0, 0}, // 21 Format24_8 - std::array{8, 24, 0, 0}, // 22 FormatX24_8_32 - std::array{0, 0, 0, 0}, // 23 - std::array{0, 0, 0, 0}, // 24 - std::array{0, 0, 0, 0}, // 25 - std::array{0, 0, 0, 0}, // 26 - std::array{0, 0, 0, 0}, // 27 - std::array{0, 0, 0, 0}, // 28 - std::array{0, 0, 0, 0}, // 29 - std::array{0, 0, 0, 0}, // 30 - std::array{0, 0, 0, 0}, // 31 - std::array{0, 0, 0, 0}, // 32 FormatGB_GR - std::array{0, 0, 0, 0}, // 33 FormatBG_RG - std::array{0, 0, 0, 0}, // 34 Format5_9_9_9 - std::array{0, 0, 0, 0}, // 35 FormatBc1 - std::array{0, 0, 0, 0}, // 36 FormatBc2 - std::array{0, 0, 0, 0}, // 37 FormatBc3 - std::array{0, 0, 0, 0}, // 38 FormatBc4 - std::array{0, 0, 0, 0}, // 39 FormatBc5 - std::array{0, 0, 0, 0}, // 40 FormatBc6 - std::array{0, 0, 0, 0}, // 41 FormatBc7 +static constexpr std::array NUM_COMPONENTS = { + 0, // 0 FormatInvalid + 1, // 1 Format8 + 1, // 2 Format16 + 2, // 3 Format8_8 + 1, // 4 Format32 + 2, // 5 Format16_16 + 3, // 6 Format10_11_11 + 3, // 7 Format11_11_10 + 4, // 8 Format10_10_10_2 + 4, // 9 Format2_10_10_10 + 4, // 10 Format8_8_8_8 + 2, // 11 Format32_32 + 4, // 12 Format16_16_16_16 + 3, // 13 Format32_32_32 + 4, // 14 Format32_32_32_32 + 0, // 15 + 3, // 16 Format5_6_5 + 4, // 17 Format1_5_5_5 + 4, // 18 Format5_5_5_1 + 4, // 19 Format4_4_4_4 + 2, // 20 Format8_24 + 2, // 21 Format24_8 + 2, // 22 FormatX24_8_32 + 0, // 23 + 0, // 24 + 0, // 25 + 0, // 26 + 0, // 27 + 0, // 28 + 0, // 29 + 0, // 30 + 0, // 31 + 3, // 32 FormatGB_GR + 3, // 33 FormatBG_RG + 4, // 34 Format5_9_9_9 + 4, // 35 FormatBc1 + 4, // 36 FormatBc2 + 4, // 37 FormatBc3 + 1, // 38 FormatBc4 + 2, // 39 FormatBc5 + 3, // 40 FormatBc6 + 4, // 41 FormatBc7 }; -u32 ComponentBits(DataFormat format, u32 comp) { +u32 NumComponents(DataFormat format) { const u32 index = static_cast(format); - if (index >= component_bits.size() || comp >= 4) { - return 0; - } - return component_bits[index][comp]; + ASSERT_MSG(index < NUM_COMPONENTS.size(), "Invalid data format = {}", format); + return NUM_COMPONENTS[index]; } -static constexpr std::array component_offset = { - std::array{-1, -1, -1, -1}, // 0 FormatInvalid - std::array{0, -1, -1, -1}, // 1 Format8 - std::array{0, -1, -1, -1}, // 2 Format16 - std::array{0, 8, -1, -1}, // 3 Format8_8 - std::array{0, -1, -1, -1}, // 4 Format32 - std::array{0, 16, -1, -1}, // 5 Format16_16 - std::array{0, 11, 22, -1}, // 6 Format10_11_11 - std::array{0, 10, 21, -1}, // 7 Format11_11_10 - std::array{0, 2, 12, 22}, // 8 Format10_10_10_2 - std::array{0, 10, 20, 30}, // 9 Format2_10_10_10 - std::array{0, 8, 16, 24}, // 10 Format8_8_8_8 - std::array{0, 32, -1, -1}, // 11 Format32_32 - std::array{0, 16, 32, 48}, // 12 Format16_16_16_16 - std::array{0, 32, 64, -1}, // 13 Format32_32_32 - std::array{0, 32, 64, 96}, // 14 Format32_32_32_32 - std::array{-1, -1, -1, -1}, // 15 - std::array{0, 5, 11, -1}, // 16 Format5_6_5 - std::array{0, 5, 10, 15}, // 17 Format1_5_5_5 - std::array{0, 1, 6, 11}, // 18 Format5_5_5_1 - std::array{0, 4, 8, 12}, // 19 Format4_4_4_4 - std::array{0, 24, -1, -1}, // 20 Format8_24 - std::array{0, 8, -1, -1}, // 21 Format24_8 - std::array{0, 8, -1, -1}, // 22 FormatX24_8_32 - std::array{-1, -1, -1, -1}, // 23 - std::array{-1, -1, -1, -1}, // 24 - std::array{-1, -1, -1, -1}, // 25 - std::array{-1, -1, -1, -1}, // 26 - std::array{-1, -1, -1, -1}, // 27 - std::array{-1, -1, -1, -1}, // 28 - std::array{-1, -1, -1, -1}, // 29 - std::array{-1, -1, -1, -1}, // 30 - std::array{-1, -1, -1, -1}, // 31 - std::array{-1, -1, -1, -1}, // 32 FormatGB_GR - std::array{-1, -1, -1, -1}, // 33 FormatBG_RG - std::array{-1, -1, -1, -1}, // 34 Format5_9_9_9 - std::array{-1, -1, -1, -1}, // 35 FormatBc1 - std::array{-1, -1, -1, -1}, // 36 FormatBc2 - std::array{-1, -1, -1, -1}, // 37 FormatBc3 - std::array{-1, -1, -1, -1}, // 38 FormatBc4 - std::array{-1, -1, -1, -1}, // 39 FormatBc5 - std::array{-1, -1, -1, -1}, // 40 FormatBc6 - std::array{-1, -1, -1, -1}, // 41 FormatBc7 +static constexpr std::array BITS_PER_BLOCK = { + 0, // 0 FormatInvalid + 8, // 1 Format8 + 16, // 2 Format16 + 16, // 3 Format8_8 + 32, // 4 Format32 + 32, // 5 Format16_16 + 32, // 6 Format10_11_11 + 32, // 7 Format11_11_10 + 32, // 8 Format10_10_10_2 + 32, // 9 Format2_10_10_10 + 32, // 10 Format8_8_8_8 + 64, // 11 Format32_32 + 64, // 12 Format16_16_16_16 + 96, // 13 Format32_32_32 + 128, // 14 Format32_32_32_32 + 0, // 15 + 16, // 16 Format5_6_5 + 16, // 17 Format1_5_5_5 + 16, // 18 Format5_5_5_1 + 16, // 19 Format4_4_4_4 + 32, // 20 Format8_24 + 32, // 21 Format24_8 + 64, // 22 FormatX24_8_32 + 0, // 23 + 0, // 24 + 0, // 25 + 0, // 26 + 0, // 27 + 0, // 28 + 0, // 29 + 0, // 30 + 0, // 31 + 16, // 32 FormatGB_GR + 16, // 33 FormatBG_RG + 32, // 34 Format5_9_9_9 + 64, // 35 FormatBc1 + 128, // 36 FormatBc2 + 128, // 37 FormatBc3 + 64, // 38 FormatBc4 + 128, // 39 FormatBc5 + 128, // 40 FormatBc6 + 128, // 41 FormatBc7 }; -s32 ComponentOffset(DataFormat format, u32 comp) { +u32 NumBitsPerBlock(DataFormat format) { const u32 index = static_cast(format); - if (index >= component_offset.size() || comp >= 4) { - return -1; - } - return component_offset[index][comp]; + ASSERT_MSG(index < BITS_PER_BLOCK.size(), "Invalid data format = {}", format); + return BITS_PER_BLOCK[index]; } } // namespace AmdGpu diff --git a/src/video_core/amdgpu/pixel_format.h b/src/video_core/amdgpu/pixel_format.h index faba8e285..bd0f778f4 100644 --- a/src/video_core/amdgpu/pixel_format.h +++ b/src/video_core/amdgpu/pixel_format.h @@ -310,10 +310,8 @@ constexpr bool IsInteger(const NumberFormat nfmt) { std::string_view NameOf(DataFormat fmt); std::string_view NameOf(NumberFormat fmt); -int NumComponents(DataFormat format); -int NumBits(DataFormat format); -u32 ComponentBits(DataFormat format, u32 comp); -s32 ComponentOffset(DataFormat format, u32 comp); +u32 NumComponents(DataFormat format); +u32 NumBitsPerBlock(DataFormat format); } // namespace AmdGpu diff --git a/src/video_core/host_shaders/detilers/micro_128bpp.comp b/src/video_core/host_shaders/detilers/micro_128bpp.comp index a09a0b4c4..a43073a8b 100644 --- a/src/video_core/host_shaders/detilers/micro_128bpp.comp +++ b/src/video_core/host_shaders/detilers/micro_128bpp.comp @@ -16,7 +16,7 @@ layout(push_constant) uniform image_info { uint num_levels; uint pitch; uint height; - uint sizes[14]; + uint sizes[16]; } info; // Inverse morton LUT, small enough to fit into K$ diff --git a/src/video_core/host_shaders/detilers/micro_16bpp.comp b/src/video_core/host_shaders/detilers/micro_16bpp.comp index 909a14acc..5f1240d64 100644 --- a/src/video_core/host_shaders/detilers/micro_16bpp.comp +++ b/src/video_core/host_shaders/detilers/micro_16bpp.comp @@ -18,7 +18,7 @@ layout(push_constant) uniform image_info { uint num_levels; uint pitch; uint height; - uint sizes[14]; + uint sizes[16]; } info; #define MICRO_TILE_DIM 8 diff --git a/src/video_core/host_shaders/detilers/micro_32bpp.comp b/src/video_core/host_shaders/detilers/micro_32bpp.comp index cdc8d0018..605523e4d 100644 --- a/src/video_core/host_shaders/detilers/micro_32bpp.comp +++ b/src/video_core/host_shaders/detilers/micro_32bpp.comp @@ -16,7 +16,7 @@ layout(push_constant) uniform image_info { uint num_levels; uint pitch; uint height; - uint sizes[14]; + uint sizes[16]; } info; // Inverse morton LUT, small enough to fit into K$ diff --git a/src/video_core/host_shaders/detilers/micro_64bpp.comp b/src/video_core/host_shaders/detilers/micro_64bpp.comp index c128ba5a1..1bca44067 100644 --- a/src/video_core/host_shaders/detilers/micro_64bpp.comp +++ b/src/video_core/host_shaders/detilers/micro_64bpp.comp @@ -16,7 +16,7 @@ layout(push_constant) uniform image_info { uint num_levels; uint pitch; uint height; - uint sizes[14]; + uint sizes[16]; } info; // Inverse morton LUT, small enough to fit into K$ diff --git a/src/video_core/host_shaders/detilers/micro_8bpp.comp b/src/video_core/host_shaders/detilers/micro_8bpp.comp index ecf706450..1d9b48daa 100644 --- a/src/video_core/host_shaders/detilers/micro_8bpp.comp +++ b/src/video_core/host_shaders/detilers/micro_8bpp.comp @@ -19,7 +19,7 @@ layout(push_constant) uniform image_info { uint num_levels; uint pitch; uint height; - uint sizes[14]; + uint sizes[16]; } info; #define MICRO_TILE_DIM 8 diff --git a/src/video_core/texture_cache/host_compatibility.cpp b/src/video_core/texture_cache/host_compatibility.cpp new file mode 100644 index 000000000..327709e64 --- /dev/null +++ b/src/video_core/texture_cache/host_compatibility.cpp @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright © 2023 Skyline Team and Contributors (https://github.com/skyline-emu/) +// Copyright © 2015-2023 The Khronos Group Inc. +// Copyright © 2015-2023 Valve Corporation +// Copyright © 2015-2023 LunarG, Inc. + +#include +#include "common/enum.h" +#include "video_core/texture_cache/host_compatibility.h" + +namespace VideoCore { + +/** + * @brief All classes of format compatibility according to the Vulkan specification + * @url + * https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/d37c676f/layers/generated/vk_format_utils.h#L47-L131 + */ +enum class CompatibilityClass { + NONE = 0, + _128BIT = 1 << 0, + _16BIT = 1 << 1, + _192BIT = 1 << 2, + _24BIT = 1 << 3, + _256BIT = 1 << 4, + _32BIT = 1 << 5, + _48BIT = 1 << 6, + _64BIT = 1 << 7, + _8BIT = 1 << 8, + _96BIT = 1 << 9, + BC1_RGB = 1 << 10, + BC1_RGBA = 1 << 11, + BC2 = 1 << 12, + BC3 = 1 << 13, + BC4 = 1 << 14, + BC5 = 1 << 15, + BC6H = 1 << 16, + BC7 = 1 << 17, + D16 = 1 << 18, + D16S8 = 1 << 19, + D24 = 1 << 20, + D24S8 = 1 << 21, + D32 = 1 << 22, + D32S8 = 1 << 23, + S8 = 1 << 24, +}; +DECLARE_ENUM_FLAG_OPERATORS(CompatibilityClass) + +/** + * @brief The format compatibility class according to the Vulkan specification + * @url + * https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#formats-compatibility-classes + * @url + * https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/d37c676f/layers/generated/vk_format_utils.cpp#L70-L812 + */ +static const std::unordered_map FORMAT_TABLE = { + {vk::Format::eA1R5G5B5UnormPack16, CompatibilityClass::_16BIT}, + {vk::Format::eA2B10G10R10SintPack32, CompatibilityClass::_32BIT}, + {vk::Format::eA2B10G10R10SnormPack32, CompatibilityClass::_32BIT}, + {vk::Format::eA2B10G10R10SscaledPack32, CompatibilityClass::_32BIT}, + {vk::Format::eA2B10G10R10UintPack32, CompatibilityClass::_32BIT}, + {vk::Format::eA2B10G10R10UnormPack32, CompatibilityClass::_32BIT}, + {vk::Format::eA2B10G10R10UscaledPack32, CompatibilityClass::_32BIT}, + {vk::Format::eA2R10G10B10SintPack32, CompatibilityClass::_32BIT}, + {vk::Format::eA2R10G10B10SnormPack32, CompatibilityClass::_32BIT}, + {vk::Format::eA2R10G10B10SscaledPack32, CompatibilityClass::_32BIT}, + {vk::Format::eA2R10G10B10UintPack32, CompatibilityClass::_32BIT}, + {vk::Format::eA2R10G10B10UnormPack32, CompatibilityClass::_32BIT}, + {vk::Format::eA2R10G10B10UscaledPack32, CompatibilityClass::_32BIT}, + {vk::Format::eA4B4G4R4UnormPack16, CompatibilityClass::_16BIT}, + {vk::Format::eA4R4G4B4UnormPack16, CompatibilityClass::_16BIT}, + {vk::Format::eA8B8G8R8SintPack32, CompatibilityClass::_32BIT}, + {vk::Format::eA8B8G8R8SnormPack32, CompatibilityClass::_32BIT}, + {vk::Format::eA8B8G8R8SrgbPack32, CompatibilityClass::_32BIT}, + {vk::Format::eA8B8G8R8SscaledPack32, CompatibilityClass::_32BIT}, + {vk::Format::eA8B8G8R8UintPack32, CompatibilityClass::_32BIT}, + {vk::Format::eA8B8G8R8UnormPack32, CompatibilityClass::_32BIT}, + {vk::Format::eA8B8G8R8UscaledPack32, CompatibilityClass::_32BIT}, + {vk::Format::eB10G11R11UfloatPack32, CompatibilityClass::_32BIT}, + {vk::Format::eB4G4R4A4UnormPack16, CompatibilityClass::_16BIT}, + {vk::Format::eB5G5R5A1UnormPack16, CompatibilityClass::_16BIT}, + {vk::Format::eB5G6R5UnormPack16, CompatibilityClass::_16BIT}, + {vk::Format::eB8G8R8A8Sint, CompatibilityClass::_32BIT}, + {vk::Format::eB8G8R8A8Snorm, CompatibilityClass::_32BIT}, + {vk::Format::eB8G8R8A8Srgb, CompatibilityClass::_32BIT}, + {vk::Format::eB8G8R8A8Sscaled, CompatibilityClass::_32BIT}, + {vk::Format::eB8G8R8A8Uint, CompatibilityClass::_32BIT}, + {vk::Format::eB8G8R8A8Unorm, CompatibilityClass::_32BIT}, + {vk::Format::eB8G8R8A8Uscaled, CompatibilityClass::_32BIT}, + {vk::Format::eB8G8R8Sint, CompatibilityClass::_24BIT}, + {vk::Format::eB8G8R8Snorm, CompatibilityClass::_24BIT}, + {vk::Format::eB8G8R8Srgb, CompatibilityClass::_24BIT}, + {vk::Format::eB8G8R8Sscaled, CompatibilityClass::_24BIT}, + {vk::Format::eB8G8R8Uint, CompatibilityClass::_24BIT}, + {vk::Format::eB8G8R8Unorm, CompatibilityClass::_24BIT}, + {vk::Format::eB8G8R8Uscaled, CompatibilityClass::_24BIT}, + {vk::Format::eBc1RgbaSrgbBlock, CompatibilityClass::BC1_RGBA | CompatibilityClass::_64BIT}, + {vk::Format::eBc1RgbaUnormBlock, CompatibilityClass::BC1_RGBA | CompatibilityClass::_64BIT}, + {vk::Format::eBc1RgbSrgbBlock, CompatibilityClass::BC1_RGB | CompatibilityClass::_64BIT}, + {vk::Format::eBc1RgbUnormBlock, CompatibilityClass::BC1_RGB | CompatibilityClass::_64BIT}, + {vk::Format::eBc2SrgbBlock, CompatibilityClass::BC2 | CompatibilityClass::_128BIT}, + {vk::Format::eBc2UnormBlock, CompatibilityClass::BC2 | CompatibilityClass::_128BIT}, + {vk::Format::eBc3SrgbBlock, CompatibilityClass::BC3 | CompatibilityClass::_128BIT}, + {vk::Format::eBc3UnormBlock, CompatibilityClass::BC3 | CompatibilityClass::_128BIT}, + {vk::Format::eBc4SnormBlock, CompatibilityClass::BC4 | CompatibilityClass::_64BIT}, + {vk::Format::eBc4UnormBlock, CompatibilityClass::BC4 | CompatibilityClass::_64BIT}, + {vk::Format::eBc5SnormBlock, CompatibilityClass::BC5 | CompatibilityClass::_128BIT}, + {vk::Format::eBc5UnormBlock, CompatibilityClass::BC5 | CompatibilityClass::_128BIT}, + {vk::Format::eBc6HSfloatBlock, CompatibilityClass::BC6H | CompatibilityClass::_128BIT}, + {vk::Format::eBc6HUfloatBlock, CompatibilityClass::BC6H | CompatibilityClass::_128BIT}, + {vk::Format::eBc7SrgbBlock, CompatibilityClass::BC7 | CompatibilityClass::_128BIT}, + {vk::Format::eBc7UnormBlock, CompatibilityClass::BC7 | CompatibilityClass::_128BIT}, + {vk::Format::eD16Unorm, CompatibilityClass::D16}, + {vk::Format::eD16UnormS8Uint, CompatibilityClass::D16S8}, + {vk::Format::eD24UnormS8Uint, CompatibilityClass::D24S8}, + {vk::Format::eD32Sfloat, CompatibilityClass::D32}, + {vk::Format::eD32SfloatS8Uint, CompatibilityClass::D32S8}, + {vk::Format::eE5B9G9R9UfloatPack32, CompatibilityClass::_32BIT}, + {vk::Format::eR10X6G10X6Unorm2Pack16, CompatibilityClass::_32BIT}, + {vk::Format::eR10X6UnormPack16, CompatibilityClass::_16BIT}, + {vk::Format::eR12X4G12X4Unorm2Pack16, CompatibilityClass::_32BIT}, + {vk::Format::eR12X4UnormPack16, CompatibilityClass::_16BIT}, + {vk::Format::eR16G16B16A16Sfloat, CompatibilityClass::_64BIT}, + {vk::Format::eR16G16B16A16Sint, CompatibilityClass::_64BIT}, + {vk::Format::eR16G16B16A16Snorm, CompatibilityClass::_64BIT}, + {vk::Format::eR16G16B16A16Sscaled, CompatibilityClass::_64BIT}, + {vk::Format::eR16G16B16A16Uint, CompatibilityClass::_64BIT}, + {vk::Format::eR16G16B16A16Unorm, CompatibilityClass::_64BIT}, + {vk::Format::eR16G16B16A16Uscaled, CompatibilityClass::_64BIT}, + {vk::Format::eR16G16B16Sfloat, CompatibilityClass::_48BIT}, + {vk::Format::eR16G16B16Sint, CompatibilityClass::_48BIT}, + {vk::Format::eR16G16B16Snorm, CompatibilityClass::_48BIT}, + {vk::Format::eR16G16B16Sscaled, CompatibilityClass::_48BIT}, + {vk::Format::eR16G16B16Uint, CompatibilityClass::_48BIT}, + {vk::Format::eR16G16B16Unorm, CompatibilityClass::_48BIT}, + {vk::Format::eR16G16B16Uscaled, CompatibilityClass::_48BIT}, + {vk::Format::eR16G16Sfloat, CompatibilityClass::_32BIT}, + {vk::Format::eR16G16Sint, CompatibilityClass::_32BIT}, + {vk::Format::eR16G16Snorm, CompatibilityClass::_32BIT}, + {vk::Format::eR16G16Sscaled, CompatibilityClass::_32BIT}, + {vk::Format::eR16G16Uint, CompatibilityClass::_32BIT}, + {vk::Format::eR16G16Unorm, CompatibilityClass::_32BIT}, + {vk::Format::eR16G16Uscaled, CompatibilityClass::_32BIT}, + {vk::Format::eR16Sfloat, CompatibilityClass::_16BIT}, + {vk::Format::eR16Sint, CompatibilityClass::_16BIT}, + {vk::Format::eR16Snorm, CompatibilityClass::_16BIT}, + {vk::Format::eR16Sscaled, CompatibilityClass::_16BIT}, + {vk::Format::eR16Uint, CompatibilityClass::_16BIT}, + {vk::Format::eR16Unorm, CompatibilityClass::_16BIT}, + {vk::Format::eR16Uscaled, CompatibilityClass::_16BIT}, + {vk::Format::eR32G32B32A32Sfloat, CompatibilityClass::_128BIT}, + {vk::Format::eR32G32B32A32Sint, CompatibilityClass::_128BIT}, + {vk::Format::eR32G32B32A32Uint, CompatibilityClass::_128BIT}, + {vk::Format::eR32G32B32Sfloat, CompatibilityClass::_96BIT}, + {vk::Format::eR32G32B32Sint, CompatibilityClass::_96BIT}, + {vk::Format::eR32G32B32Uint, CompatibilityClass::_96BIT}, + {vk::Format::eR32G32Sfloat, CompatibilityClass::_64BIT}, + {vk::Format::eR32G32Sint, CompatibilityClass::_64BIT}, + {vk::Format::eR32G32Uint, CompatibilityClass::_64BIT}, + {vk::Format::eR32Sfloat, CompatibilityClass::_32BIT}, + {vk::Format::eR32Sint, CompatibilityClass::_32BIT}, + {vk::Format::eR32Uint, CompatibilityClass::_32BIT}, + {vk::Format::eR4G4B4A4UnormPack16, CompatibilityClass::_16BIT}, + {vk::Format::eR4G4UnormPack8, CompatibilityClass::_8BIT}, + {vk::Format::eR5G5B5A1UnormPack16, CompatibilityClass::_16BIT}, + {vk::Format::eR5G6B5UnormPack16, CompatibilityClass::_16BIT}, + {vk::Format::eR64G64B64A64Sfloat, CompatibilityClass::_256BIT}, + {vk::Format::eR64G64B64A64Sint, CompatibilityClass::_256BIT}, + {vk::Format::eR64G64B64A64Uint, CompatibilityClass::_256BIT}, + {vk::Format::eR64G64B64Sfloat, CompatibilityClass::_192BIT}, + {vk::Format::eR64G64B64Sint, CompatibilityClass::_192BIT}, + {vk::Format::eR64G64B64Uint, CompatibilityClass::_192BIT}, + {vk::Format::eR64G64Sfloat, CompatibilityClass::_128BIT}, + {vk::Format::eR64G64Sint, CompatibilityClass::_128BIT}, + {vk::Format::eR64G64Uint, CompatibilityClass::_128BIT}, + {vk::Format::eR64Sfloat, CompatibilityClass::_64BIT}, + {vk::Format::eR64Sint, CompatibilityClass::_64BIT}, + {vk::Format::eR64Uint, CompatibilityClass::_64BIT}, + {vk::Format::eR8G8B8A8Sint, CompatibilityClass::_32BIT}, + {vk::Format::eR8G8B8A8Snorm, CompatibilityClass::_32BIT}, + {vk::Format::eR8G8B8A8Srgb, CompatibilityClass::_32BIT}, + {vk::Format::eR8G8B8A8Sscaled, CompatibilityClass::_32BIT}, + {vk::Format::eR8G8B8A8Uint, CompatibilityClass::_32BIT}, + {vk::Format::eR8G8B8A8Unorm, CompatibilityClass::_32BIT}, + {vk::Format::eR8G8B8A8Uscaled, CompatibilityClass::_32BIT}, + {vk::Format::eR8G8B8Sint, CompatibilityClass::_24BIT}, + {vk::Format::eR8G8B8Snorm, CompatibilityClass::_24BIT}, + {vk::Format::eR8G8B8Srgb, CompatibilityClass::_24BIT}, + {vk::Format::eR8G8B8Sscaled, CompatibilityClass::_24BIT}, + {vk::Format::eR8G8B8Uint, CompatibilityClass::_24BIT}, + {vk::Format::eR8G8B8Unorm, CompatibilityClass::_24BIT}, + {vk::Format::eR8G8B8Uscaled, CompatibilityClass::_24BIT}, + {vk::Format::eR8G8Sint, CompatibilityClass::_16BIT}, + {vk::Format::eR8G8Snorm, CompatibilityClass::_16BIT}, + {vk::Format::eR8G8Srgb, CompatibilityClass::_16BIT}, + {vk::Format::eR8G8Sscaled, CompatibilityClass::_16BIT}, + {vk::Format::eR8G8Uint, CompatibilityClass::_16BIT}, + {vk::Format::eR8G8Unorm, CompatibilityClass::_16BIT}, + {vk::Format::eR8G8Uscaled, CompatibilityClass::_16BIT}, + {vk::Format::eR8Sint, CompatibilityClass::_8BIT}, + {vk::Format::eR8Snorm, CompatibilityClass::_8BIT}, + {vk::Format::eR8Srgb, CompatibilityClass::_8BIT}, + {vk::Format::eR8Sscaled, CompatibilityClass::_8BIT}, + {vk::Format::eR8Uint, CompatibilityClass::_8BIT}, + {vk::Format::eR8Unorm, CompatibilityClass::_8BIT}, + {vk::Format::eR8Uscaled, CompatibilityClass::_8BIT}, + {vk::Format::eS8Uint, CompatibilityClass::S8}, + {vk::Format::eX8D24UnormPack32, CompatibilityClass::D24}, + {vk::Format::eUndefined, CompatibilityClass::NONE}, +}; + +bool IsVulkanFormatCompatible(vk::Format base, vk::Format view) { + if (base == view) { + return true; + } + const auto base_comp = FORMAT_TABLE.at(base); + const auto view_comp = FORMAT_TABLE.at(view); + return (base_comp & view_comp) == view_comp; +} + +} // namespace VideoCore diff --git a/src/video_core/texture_cache/host_compatibility.h b/src/video_core/texture_cache/host_compatibility.h index a73f7e6be..b0579137b 100644 --- a/src/video_core/texture_cache/host_compatibility.h +++ b/src/video_core/texture_cache/host_compatibility.h @@ -6,387 +6,11 @@ #pragma once -#include #include "video_core/renderer_vulkan/vk_common.h" namespace VideoCore { -/** - * @brief All classes of format compatibility according to the Vulkan specification - * @url - * https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/d37c676f75f545a3e5a98d7dfb89864391a1db1e/layers/generated/vk_format_utils.h#L47-L131 - * @note This is copied directly from Vulkan Validation Layers and doesn't follow the Skyline naming - * conventions - */ -enum class FORMAT_COMPATIBILITY_CLASS { - NONE = 0, - _10BIT_2PLANE_420, - _10BIT_2PLANE_422, - _10BIT_2PLANE_444, - _10BIT_3PLANE_420, - _10BIT_3PLANE_422, - _10BIT_3PLANE_444, - _12BIT_2PLANE_420, - _12BIT_2PLANE_422, - _12BIT_2PLANE_444, - _12BIT_3PLANE_420, - _12BIT_3PLANE_422, - _12BIT_3PLANE_444, - _128BIT, - _16BIT, - _16BIT_2PLANE_420, - _16BIT_2PLANE_422, - _16BIT_2PLANE_444, - _16BIT_3PLANE_420, - _16BIT_3PLANE_422, - _16BIT_3PLANE_444, - _192BIT, - _24BIT, - _256BIT, - _32BIT, - _32BIT_B8G8R8G8, - _32BIT_G8B8G8R8, - _48BIT, - _64BIT, - _64BIT_B10G10R10G10, - _64BIT_B12G12R12G12, - _64BIT_B16G16R16G16, - _64BIT_G10B10G10R10, - _64BIT_G12B12G12R12, - _64BIT_G16B16G16R16, - _64BIT_R10G10B10A10, - _64BIT_R12G12B12A12, - _8BIT, - _8BIT_2PLANE_420, - _8BIT_2PLANE_422, - _8BIT_2PLANE_444, - _8BIT_3PLANE_420, - _8BIT_3PLANE_422, - _8BIT_3PLANE_444, - _96BIT, - ASTC_10X10, - ASTC_10X5, - ASTC_10X6, - ASTC_10X8, - ASTC_12X10, - ASTC_12X12, - ASTC_4X4, - ASTC_5X4, - ASTC_5X5, - ASTC_6X5, - ASTC_6X6, - ASTC_8X5, - ASTC_8X6, - ASTC_8X8, - BC1_RGB, - BC1_RGBA, - BC2, - BC3, - BC4, - BC5, - BC6H, - BC7, - D16, - D16S8, - D24, - D24S8, - D32, - D32S8, - EAC_R, - EAC_RG, - ETC2_EAC_RGBA, - ETC2_RGB, - ETC2_RGBA, - PVRTC1_2BPP, - PVRTC1_4BPP, - PVRTC2_2BPP, - PVRTC2_4BPP, - S8 -}; -/** - * @brief The format compatibility class according to the Vulkan specification - * @url - * https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#formats-compatibility-classes - * @url - * https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/d37c676f75f545a3e5a98d7dfb89864391a1db1e/layers/generated/vk_format_utils.cpp#L70-L812 - * @note This is copied directly from Vulkan Validation Layers and doesn't follow the Skyline naming - * conventions - */ -static const std::unordered_map vkFormatClassTable{ - {VK_FORMAT_A1R5G5B5_UNORM_PACK16, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_A2B10G10R10_SINT_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_A2B10G10R10_SNORM_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_A2B10G10R10_SSCALED_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_A2B10G10R10_UINT_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_A2B10G10R10_UNORM_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_A2B10G10R10_USCALED_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_A2R10G10B10_SINT_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_A2R10G10B10_SNORM_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_A2R10G10B10_SSCALED_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_A2R10G10B10_UINT_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_A2R10G10B10_UNORM_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_A2R10G10B10_USCALED_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_A8B8G8R8_SINT_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_A8B8G8R8_SNORM_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_A8B8G8R8_SRGB_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_A8B8G8R8_SSCALED_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_A8B8G8R8_UINT_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_A8B8G8R8_UNORM_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_A8B8G8R8_USCALED_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_10X10}, - {VK_FORMAT_ASTC_10x10_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_10X10}, - {VK_FORMAT_ASTC_10x10_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_10X10}, - {VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_10X5}, - {VK_FORMAT_ASTC_10x5_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_10X5}, - {VK_FORMAT_ASTC_10x5_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_10X5}, - {VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_10X6}, - {VK_FORMAT_ASTC_10x6_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_10X6}, - {VK_FORMAT_ASTC_10x6_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_10X6}, - {VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_10X8}, - {VK_FORMAT_ASTC_10x8_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_10X8}, - {VK_FORMAT_ASTC_10x8_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_10X8}, - {VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_12X10}, - {VK_FORMAT_ASTC_12x10_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_12X10}, - {VK_FORMAT_ASTC_12x10_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_12X10}, - {VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_12X12}, - {VK_FORMAT_ASTC_12x12_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_12X12}, - {VK_FORMAT_ASTC_12x12_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_12X12}, - {VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_4X4}, - {VK_FORMAT_ASTC_4x4_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_4X4}, - {VK_FORMAT_ASTC_4x4_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_4X4}, - {VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_5X4}, - {VK_FORMAT_ASTC_5x4_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_5X4}, - {VK_FORMAT_ASTC_5x4_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_5X4}, - {VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_5X5}, - {VK_FORMAT_ASTC_5x5_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_5X5}, - {VK_FORMAT_ASTC_5x5_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_5X5}, - {VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_6X5}, - {VK_FORMAT_ASTC_6x5_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_6X5}, - {VK_FORMAT_ASTC_6x5_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_6X5}, - {VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_6X6}, - {VK_FORMAT_ASTC_6x6_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_6X6}, - {VK_FORMAT_ASTC_6x6_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_6X6}, - {VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_8X5}, - {VK_FORMAT_ASTC_8x5_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_8X5}, - {VK_FORMAT_ASTC_8x5_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_8X5}, - {VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_8X6}, - {VK_FORMAT_ASTC_8x6_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_8X6}, - {VK_FORMAT_ASTC_8x6_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_8X6}, - {VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT, FORMAT_COMPATIBILITY_CLASS::ASTC_8X8}, - {VK_FORMAT_ASTC_8x8_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_8X8}, - {VK_FORMAT_ASTC_8x8_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ASTC_8X8}, - {VK_FORMAT_B10G11R11_UFLOAT_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16, - FORMAT_COMPATIBILITY_CLASS::_64BIT_B10G10R10G10}, - {VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16, - FORMAT_COMPATIBILITY_CLASS::_64BIT_B12G12R12G12}, - {VK_FORMAT_B16G16R16G16_422_UNORM, FORMAT_COMPATIBILITY_CLASS::_64BIT_B16G16R16G16}, - {VK_FORMAT_B4G4R4A4_UNORM_PACK16, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_B5G5R5A1_UNORM_PACK16, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_B5G6R5_UNORM_PACK16, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_B8G8R8A8_SINT, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_B8G8R8A8_SNORM, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_B8G8R8A8_SRGB, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_B8G8R8A8_SSCALED, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_B8G8R8A8_UINT, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_B8G8R8A8_UNORM, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_B8G8R8A8_USCALED, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_B8G8R8G8_422_UNORM, FORMAT_COMPATIBILITY_CLASS::_32BIT_B8G8R8G8}, - {VK_FORMAT_B8G8R8_SINT, FORMAT_COMPATIBILITY_CLASS::_24BIT}, - {VK_FORMAT_B8G8R8_SNORM, FORMAT_COMPATIBILITY_CLASS::_24BIT}, - {VK_FORMAT_B8G8R8_SRGB, FORMAT_COMPATIBILITY_CLASS::_24BIT}, - {VK_FORMAT_B8G8R8_SSCALED, FORMAT_COMPATIBILITY_CLASS::_24BIT}, - {VK_FORMAT_B8G8R8_UINT, FORMAT_COMPATIBILITY_CLASS::_24BIT}, - {VK_FORMAT_B8G8R8_UNORM, FORMAT_COMPATIBILITY_CLASS::_24BIT}, - {VK_FORMAT_B8G8R8_USCALED, FORMAT_COMPATIBILITY_CLASS::_24BIT}, - {VK_FORMAT_BC1_RGBA_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC1_RGBA}, - {VK_FORMAT_BC1_RGBA_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC1_RGBA}, - {VK_FORMAT_BC1_RGB_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC1_RGB}, - {VK_FORMAT_BC1_RGB_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC1_RGB}, - {VK_FORMAT_BC2_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC2}, - {VK_FORMAT_BC2_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC2}, - {VK_FORMAT_BC3_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC3}, - {VK_FORMAT_BC3_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC3}, - {VK_FORMAT_BC4_SNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC4}, - {VK_FORMAT_BC4_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC4}, - {VK_FORMAT_BC5_SNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC5}, - {VK_FORMAT_BC5_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC5}, - {VK_FORMAT_BC6H_SFLOAT_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC6H}, - {VK_FORMAT_BC6H_UFLOAT_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC6H}, - {VK_FORMAT_BC7_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC7}, - {VK_FORMAT_BC7_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::BC7}, - {VK_FORMAT_D16_UNORM, FORMAT_COMPATIBILITY_CLASS::D16}, - {VK_FORMAT_D16_UNORM_S8_UINT, FORMAT_COMPATIBILITY_CLASS::D16S8}, - {VK_FORMAT_D24_UNORM_S8_UINT, FORMAT_COMPATIBILITY_CLASS::D24S8}, - {VK_FORMAT_D32_SFLOAT, FORMAT_COMPATIBILITY_CLASS::D32}, - {VK_FORMAT_D32_SFLOAT_S8_UINT, FORMAT_COMPATIBILITY_CLASS::D32S8}, - {VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_EAC_R11G11_SNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::EAC_RG}, - {VK_FORMAT_EAC_R11G11_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::EAC_RG}, - {VK_FORMAT_EAC_R11_SNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::EAC_R}, - {VK_FORMAT_EAC_R11_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::EAC_R}, - {VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ETC2_RGBA}, - {VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ETC2_RGBA}, - {VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ETC2_EAC_RGBA}, - {VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ETC2_EAC_RGBA}, - {VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK, FORMAT_COMPATIBILITY_CLASS::ETC2_RGB}, - {VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, FORMAT_COMPATIBILITY_CLASS::ETC2_RGB}, - {VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16, - FORMAT_COMPATIBILITY_CLASS::_64BIT_G10B10G10R10}, - {VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, - FORMAT_COMPATIBILITY_CLASS::_10BIT_2PLANE_420}, - {VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, - FORMAT_COMPATIBILITY_CLASS::_10BIT_2PLANE_422}, - {VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT, - FORMAT_COMPATIBILITY_CLASS::_10BIT_2PLANE_444}, - {VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, - FORMAT_COMPATIBILITY_CLASS::_10BIT_3PLANE_420}, - {VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16, - FORMAT_COMPATIBILITY_CLASS::_10BIT_3PLANE_422}, - {VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16, - FORMAT_COMPATIBILITY_CLASS::_10BIT_3PLANE_444}, - {VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16, - FORMAT_COMPATIBILITY_CLASS::_64BIT_G12B12G12R12}, - {VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, - FORMAT_COMPATIBILITY_CLASS::_12BIT_2PLANE_420}, - {VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16, - FORMAT_COMPATIBILITY_CLASS::_12BIT_2PLANE_422}, - {VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT, - FORMAT_COMPATIBILITY_CLASS::_12BIT_2PLANE_444}, - {VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16, - FORMAT_COMPATIBILITY_CLASS::_12BIT_3PLANE_420}, - {VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16, - FORMAT_COMPATIBILITY_CLASS::_12BIT_3PLANE_422}, - {VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16, - FORMAT_COMPATIBILITY_CLASS::_12BIT_3PLANE_444}, - {VK_FORMAT_G16B16G16R16_422_UNORM, FORMAT_COMPATIBILITY_CLASS::_64BIT_G16B16G16R16}, - {VK_FORMAT_G16_B16R16_2PLANE_420_UNORM, FORMAT_COMPATIBILITY_CLASS::_16BIT_2PLANE_420}, - {VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, FORMAT_COMPATIBILITY_CLASS::_16BIT_2PLANE_422}, - {VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT, FORMAT_COMPATIBILITY_CLASS::_16BIT_2PLANE_444}, - {VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, FORMAT_COMPATIBILITY_CLASS::_16BIT_3PLANE_420}, - {VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, FORMAT_COMPATIBILITY_CLASS::_16BIT_3PLANE_422}, - {VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, FORMAT_COMPATIBILITY_CLASS::_16BIT_3PLANE_444}, - {VK_FORMAT_G8B8G8R8_422_UNORM, FORMAT_COMPATIBILITY_CLASS::_32BIT_G8B8G8R8}, - {VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, FORMAT_COMPATIBILITY_CLASS::_8BIT_2PLANE_420}, - {VK_FORMAT_G8_B8R8_2PLANE_422_UNORM, FORMAT_COMPATIBILITY_CLASS::_8BIT_2PLANE_422}, - {VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT, FORMAT_COMPATIBILITY_CLASS::_8BIT_2PLANE_444}, - {VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, FORMAT_COMPATIBILITY_CLASS::_8BIT_3PLANE_420}, - {VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM, FORMAT_COMPATIBILITY_CLASS::_8BIT_3PLANE_422}, - {VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM, FORMAT_COMPATIBILITY_CLASS::_8BIT_3PLANE_444}, - {VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG, FORMAT_COMPATIBILITY_CLASS::PVRTC1_2BPP}, - {VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, FORMAT_COMPATIBILITY_CLASS::PVRTC1_2BPP}, - {VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG, FORMAT_COMPATIBILITY_CLASS::PVRTC1_4BPP}, - {VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG, FORMAT_COMPATIBILITY_CLASS::PVRTC1_4BPP}, - {VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG, FORMAT_COMPATIBILITY_CLASS::PVRTC2_2BPP}, - {VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG, FORMAT_COMPATIBILITY_CLASS::PVRTC2_2BPP}, - {VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG, FORMAT_COMPATIBILITY_CLASS::PVRTC2_4BPP}, - {VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG, FORMAT_COMPATIBILITY_CLASS::PVRTC2_4BPP}, - {VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16, FORMAT_COMPATIBILITY_CLASS::_64BIT_R10G10B10A10}, - {VK_FORMAT_R10X6G10X6_UNORM_2PACK16, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_R10X6_UNORM_PACK16, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16, FORMAT_COMPATIBILITY_CLASS::_64BIT_R12G12B12A12}, - {VK_FORMAT_R12X4G12X4_UNORM_2PACK16, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_R12X4_UNORM_PACK16, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_R16G16B16A16_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_64BIT}, - {VK_FORMAT_R16G16B16A16_SINT, FORMAT_COMPATIBILITY_CLASS::_64BIT}, - {VK_FORMAT_R16G16B16A16_SNORM, FORMAT_COMPATIBILITY_CLASS::_64BIT}, - {VK_FORMAT_R16G16B16A16_SSCALED, FORMAT_COMPATIBILITY_CLASS::_64BIT}, - {VK_FORMAT_R16G16B16A16_UINT, FORMAT_COMPATIBILITY_CLASS::_64BIT}, - {VK_FORMAT_R16G16B16A16_UNORM, FORMAT_COMPATIBILITY_CLASS::_64BIT}, - {VK_FORMAT_R16G16B16A16_USCALED, FORMAT_COMPATIBILITY_CLASS::_64BIT}, - {VK_FORMAT_R16G16B16_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_48BIT}, - {VK_FORMAT_R16G16B16_SINT, FORMAT_COMPATIBILITY_CLASS::_48BIT}, - {VK_FORMAT_R16G16B16_SNORM, FORMAT_COMPATIBILITY_CLASS::_48BIT}, - {VK_FORMAT_R16G16B16_SSCALED, FORMAT_COMPATIBILITY_CLASS::_48BIT}, - {VK_FORMAT_R16G16B16_UINT, FORMAT_COMPATIBILITY_CLASS::_48BIT}, - {VK_FORMAT_R16G16B16_UNORM, FORMAT_COMPATIBILITY_CLASS::_48BIT}, - {VK_FORMAT_R16G16B16_USCALED, FORMAT_COMPATIBILITY_CLASS::_48BIT}, - {VK_FORMAT_R16G16_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_R16G16_SINT, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_R16G16_SNORM, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_R16G16_SSCALED, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_R16G16_UINT, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_R16G16_UNORM, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_R16G16_USCALED, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_R16_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_R16_SINT, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_R16_SNORM, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_R16_SSCALED, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_R16_UINT, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_R16_UNORM, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_R16_USCALED, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_R32G32B32A32_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_128BIT}, - {VK_FORMAT_R32G32B32A32_SINT, FORMAT_COMPATIBILITY_CLASS::_128BIT}, - {VK_FORMAT_R32G32B32A32_UINT, FORMAT_COMPATIBILITY_CLASS::_128BIT}, - {VK_FORMAT_R32G32B32_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_96BIT}, - {VK_FORMAT_R32G32B32_SINT, FORMAT_COMPATIBILITY_CLASS::_96BIT}, - {VK_FORMAT_R32G32B32_UINT, FORMAT_COMPATIBILITY_CLASS::_96BIT}, - {VK_FORMAT_R32G32_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_64BIT}, - {VK_FORMAT_R32G32_SINT, FORMAT_COMPATIBILITY_CLASS::_64BIT}, - {VK_FORMAT_R32G32_UINT, FORMAT_COMPATIBILITY_CLASS::_64BIT}, - {VK_FORMAT_R32_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_R32_SINT, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_R32_UINT, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_R4G4B4A4_UNORM_PACK16, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_R4G4_UNORM_PACK8, FORMAT_COMPATIBILITY_CLASS::_8BIT}, - {VK_FORMAT_R5G5B5A1_UNORM_PACK16, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_R5G6B5_UNORM_PACK16, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_R64G64B64A64_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_256BIT}, - {VK_FORMAT_R64G64B64A64_SINT, FORMAT_COMPATIBILITY_CLASS::_256BIT}, - {VK_FORMAT_R64G64B64A64_UINT, FORMAT_COMPATIBILITY_CLASS::_256BIT}, - {VK_FORMAT_R64G64B64_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_192BIT}, - {VK_FORMAT_R64G64B64_SINT, FORMAT_COMPATIBILITY_CLASS::_192BIT}, - {VK_FORMAT_R64G64B64_UINT, FORMAT_COMPATIBILITY_CLASS::_192BIT}, - {VK_FORMAT_R64G64_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_128BIT}, - {VK_FORMAT_R64G64_SINT, FORMAT_COMPATIBILITY_CLASS::_128BIT}, - {VK_FORMAT_R64G64_UINT, FORMAT_COMPATIBILITY_CLASS::_128BIT}, - {VK_FORMAT_R64_SFLOAT, FORMAT_COMPATIBILITY_CLASS::_64BIT}, - {VK_FORMAT_R64_SINT, FORMAT_COMPATIBILITY_CLASS::_64BIT}, - {VK_FORMAT_R64_UINT, FORMAT_COMPATIBILITY_CLASS::_64BIT}, - {VK_FORMAT_R8G8B8A8_SINT, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_R8G8B8A8_SNORM, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_R8G8B8A8_SRGB, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_R8G8B8A8_SSCALED, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_R8G8B8A8_UINT, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_R8G8B8A8_UNORM, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_R8G8B8A8_USCALED, FORMAT_COMPATIBILITY_CLASS::_32BIT}, - {VK_FORMAT_R8G8B8_SINT, FORMAT_COMPATIBILITY_CLASS::_24BIT}, - {VK_FORMAT_R8G8B8_SNORM, FORMAT_COMPATIBILITY_CLASS::_24BIT}, - {VK_FORMAT_R8G8B8_SRGB, FORMAT_COMPATIBILITY_CLASS::_24BIT}, - {VK_FORMAT_R8G8B8_SSCALED, FORMAT_COMPATIBILITY_CLASS::_24BIT}, - {VK_FORMAT_R8G8B8_UINT, FORMAT_COMPATIBILITY_CLASS::_24BIT}, - {VK_FORMAT_R8G8B8_UNORM, FORMAT_COMPATIBILITY_CLASS::_24BIT}, - {VK_FORMAT_R8G8B8_USCALED, FORMAT_COMPATIBILITY_CLASS::_24BIT}, - {VK_FORMAT_R8G8_SINT, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_R8G8_SNORM, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_R8G8_SRGB, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_R8G8_SSCALED, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_R8G8_UINT, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_R8G8_UNORM, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_R8G8_USCALED, FORMAT_COMPATIBILITY_CLASS::_16BIT}, - {VK_FORMAT_R8_SINT, FORMAT_COMPATIBILITY_CLASS::_8BIT}, - {VK_FORMAT_R8_SNORM, FORMAT_COMPATIBILITY_CLASS::_8BIT}, - {VK_FORMAT_R8_SRGB, FORMAT_COMPATIBILITY_CLASS::_8BIT}, - {VK_FORMAT_R8_SSCALED, FORMAT_COMPATIBILITY_CLASS::_8BIT}, - {VK_FORMAT_R8_UINT, FORMAT_COMPATIBILITY_CLASS::_8BIT}, - {VK_FORMAT_R8_UNORM, FORMAT_COMPATIBILITY_CLASS::_8BIT}, - {VK_FORMAT_R8_USCALED, FORMAT_COMPATIBILITY_CLASS::_8BIT}, - {VK_FORMAT_S8_UINT, FORMAT_COMPATIBILITY_CLASS::S8}, - {VK_FORMAT_X8_D24_UNORM_PACK32, FORMAT_COMPATIBILITY_CLASS::D24}, - {VK_FORMAT_UNDEFINED, FORMAT_COMPATIBILITY_CLASS::NONE}, -}; +/// Returns true if the two formats are compatible according to Vulkan's format compatibility rules +bool IsVulkanFormatCompatible(vk::Format base, vk::Format view); -/** - * @return If the two formats are compatible according to Vulkan's format compatibility rules - * @url - * https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#formats-compatibility - */ -static bool IsVulkanFormatCompatible(vk::Format lhs, vk::Format rhs) { - if (lhs == rhs) { - return true; - } - return vkFormatClassTable.at(VkFormat(lhs)) == vkFormatClassTable.at(VkFormat(rhs)); -} } // namespace VideoCore diff --git a/src/video_core/texture_cache/image.cpp b/src/video_core/texture_cache/image.cpp index 522e6fd5b..8522f1307 100644 --- a/src/video_core/texture_cache/image.cpp +++ b/src/video_core/texture_cache/image.cpp @@ -14,62 +14,6 @@ namespace VideoCore { using namespace Vulkan; -bool ImageInfo::IsBlockCoded() const { - switch (pixel_format) { - case vk::Format::eBc1RgbaSrgbBlock: - case vk::Format::eBc1RgbaUnormBlock: - case vk::Format::eBc1RgbSrgbBlock: - case vk::Format::eBc1RgbUnormBlock: - case vk::Format::eBc2SrgbBlock: - case vk::Format::eBc2UnormBlock: - case vk::Format::eBc3SrgbBlock: - case vk::Format::eBc3UnormBlock: - case vk::Format::eBc4SnormBlock: - case vk::Format::eBc4UnormBlock: - case vk::Format::eBc5SnormBlock: - case vk::Format::eBc5UnormBlock: - case vk::Format::eBc6HSfloatBlock: - case vk::Format::eBc6HUfloatBlock: - case vk::Format::eBc7SrgbBlock: - case vk::Format::eBc7UnormBlock: - return true; - default: - return false; - } -} - -bool ImageInfo::IsPacked() const { - switch (pixel_format) { - case vk::Format::eB5G5R5A1UnormPack16: - [[fallthrough]]; - case vk::Format::eB5G6R5UnormPack16: - return true; - default: - return false; - } -} - -bool ImageInfo::IsDepthStencil() const { - switch (pixel_format) { - case vk::Format::eD16Unorm: - case vk::Format::eD16UnormS8Uint: - case vk::Format::eD32Sfloat: - case vk::Format::eD32SfloatS8Uint: - return true; - default: - return false; - } -} - -bool ImageInfo::HasStencil() const { - if (pixel_format == vk::Format::eD32SfloatS8Uint || - pixel_format == vk::Format::eD24UnormS8Uint || - pixel_format == vk::Format::eD16UnormS8Uint) { - return true; - } - return false; -} - static vk::ImageUsageFlags ImageUsageFlags(const ImageInfo& info) { vk::ImageUsageFlags usage = vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eTransferDst | @@ -161,6 +105,9 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_, if (info.props.is_volume) { flags |= vk::ImageCreateFlagBits::e2DArrayCompatible; } + if (info.props.is_block) { + flags |= vk::ImageCreateFlagBits::eBlockTexelViewCompatible; + } usage_flags = ImageUsageFlags(info); format_features = FormatFeatureFlags(usage_flags); @@ -372,9 +319,9 @@ void Image::CopyImage(const Image& image) { boost::container::small_vector image_copy{}; for (u32 m = 0; m < image.info.resources.levels; ++m) { - const auto mip_w = std::max(info.size.width >> m, 1u); - const auto mip_h = std::max(info.size.height >> m, 1u); - const auto mip_d = std::max(info.size.depth >> m, 1u); + const auto mip_w = std::max(image.info.size.width >> m, 1u); + const auto mip_h = std::max(image.info.size.height >> m, 1u); + const auto mip_d = std::max(image.info.size.depth >> m, 1u); image_copy.emplace_back(vk::ImageCopy{ .srcSubresource{ diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp index 39322f449..769c4211f 100644 --- a/src/video_core/texture_cache/image_info.cpp +++ b/src/video_core/texture_cache/image_info.cpp @@ -81,7 +81,7 @@ ImageInfo::ImageInfo(const AmdGpu::Liverpool::ColorBuffer& buffer, tiling_mode = buffer.GetTilingMode(); pixel_format = LiverpoolToVK::SurfaceFormat(buffer.GetDataFmt(), buffer.GetNumberFmt()); num_samples = buffer.NumSamples(); - num_bits = NumBits(buffer.GetDataFmt()); + num_bits = NumBitsPerBlock(buffer.GetDataFmt()); type = vk::ImageType::e2D; size.width = hint.Valid() ? hint.width : buffer.Pitch(); size.height = hint.Valid() ? hint.height : buffer.Height(); @@ -142,7 +142,7 @@ ImageInfo::ImageInfo(const AmdGpu::Image& image, const Shader::ImageResource& de resources.levels = image.NumLevels(); resources.layers = image.NumLayers(); num_samples = image.NumSamples(); - num_bits = NumBits(image.GetDataFmt()); + num_bits = NumBitsPerBlock(image.GetDataFmt()); guest_address = image.Address(); @@ -152,6 +152,80 @@ ImageInfo::ImageInfo(const AmdGpu::Image& image, const Shader::ImageResource& de UpdateSize(); } +bool ImageInfo::IsBlockCoded() const { + switch (pixel_format) { + case vk::Format::eBc1RgbaSrgbBlock: + case vk::Format::eBc1RgbaUnormBlock: + case vk::Format::eBc1RgbSrgbBlock: + case vk::Format::eBc1RgbUnormBlock: + case vk::Format::eBc2SrgbBlock: + case vk::Format::eBc2UnormBlock: + case vk::Format::eBc3SrgbBlock: + case vk::Format::eBc3UnormBlock: + case vk::Format::eBc4SnormBlock: + case vk::Format::eBc4UnormBlock: + case vk::Format::eBc5SnormBlock: + case vk::Format::eBc5UnormBlock: + case vk::Format::eBc6HSfloatBlock: + case vk::Format::eBc6HUfloatBlock: + case vk::Format::eBc7SrgbBlock: + case vk::Format::eBc7UnormBlock: + return true; + default: + return false; + } +} + +bool ImageInfo::IsPacked() const { + switch (pixel_format) { + case vk::Format::eB5G5R5A1UnormPack16: + [[fallthrough]]; + case vk::Format::eB5G6R5UnormPack16: + return true; + default: + return false; + } +} + +bool ImageInfo::IsDepthStencil() const { + switch (pixel_format) { + case vk::Format::eD16Unorm: + case vk::Format::eD16UnormS8Uint: + case vk::Format::eD32Sfloat: + case vk::Format::eD32SfloatS8Uint: + return true; + default: + return false; + } +} + +bool ImageInfo::HasStencil() const { + if (pixel_format == vk::Format::eD32SfloatS8Uint || + pixel_format == vk::Format::eD24UnormS8Uint || + pixel_format == vk::Format::eD16UnormS8Uint) { + return true; + } + return false; +} + +bool ImageInfo::IsCompatible(const ImageInfo& info) const { + return (pixel_format == info.pixel_format && num_samples == info.num_samples && + num_bits == info.num_bits); +} + +bool ImageInfo::IsTilingCompatible(u32 lhs, u32 rhs) const { + if (lhs == rhs) { + return true; + } + if (lhs == 0x0e && rhs == 0x0d) { + return true; + } + if (lhs == 0x0d && rhs == 0x0e) { + return true; + } + return false; +} + void ImageInfo::UpdateSize() { mips_layout.clear(); MipInfo mip_info{}; @@ -163,7 +237,6 @@ void ImageInfo::UpdateSize() { if (props.is_block) { mip_w = (mip_w + 3) / 4; mip_h = (mip_h + 3) / 4; - bpp *= 16; } mip_w = std::max(mip_w, 1u); mip_h = std::max(mip_h, 1u); diff --git a/src/video_core/texture_cache/image_info.h b/src/video_core/texture_cache/image_info.h index ca4d9f5e9..47718a095 100644 --- a/src/video_core/texture_cache/image_info.h +++ b/src/video_core/texture_cache/image_info.h @@ -25,6 +25,11 @@ struct ImageInfo { bool IsTiled() const { return tiling_mode != AmdGpu::TilingMode::Display_Linear; } + Extent3D BlockDim() const { + const u32 shift = props.is_block ? 2 : 0; + return Extent3D{size.width >> shift, size.height >> shift, size.depth}; + } + bool IsBlockCoded() const; bool IsPacked() const; bool IsDepthStencil() const; @@ -33,24 +38,8 @@ struct ImageInfo { s32 MipOf(const ImageInfo& info) const; s32 SliceOf(const ImageInfo& info, s32 mip) const; - /// Verifies if images are compatible for subresource merging. - bool IsCompatible(const ImageInfo& info) const { - return (pixel_format == info.pixel_format && num_samples == info.num_samples && - num_bits == info.num_bits); - } - - bool IsTilingCompatible(u32 lhs, u32 rhs) const { - if (lhs == rhs) { - return true; - } - if (lhs == 0x0e && rhs == 0x0d) { - return true; - } - if (lhs == 0x0d && rhs == 0x0e) { - return true; - } - return false; - } + bool IsCompatible(const ImageInfo& info) const; + bool IsTilingCompatible(u32 lhs, u32 rhs) const; void UpdateSize(); diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index 4b173c313..f070b9132 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -199,7 +199,8 @@ std::tuple TextureCache::ResolveOverlap(const ImageInfo& imag scheduler.CurrentTick() - tex_cache_image.tick_accessed_last > NumFramesBeforeRemoval; if (image_info.guest_address == tex_cache_image.info.guest_address) { // Equal address - if (image_info.size != tex_cache_image.info.size) { + if (image_info.BlockDim() != tex_cache_image.info.BlockDim() || + image_info.num_bits != tex_cache_image.info.num_bits) { // Very likely this kind of overlap is caused by allocation from a pool. if (safe_to_delete) { FreeImage(cache_image_id); @@ -211,15 +212,19 @@ std::tuple TextureCache::ResolveOverlap(const ImageInfo& imag return {depth_image_id, -1, -1}; } + if (image_info.IsBlockCoded() && !tex_cache_image.info.IsBlockCoded()) { + // Compressed view of uncompressed image with same block size. + // We need to recreate the image with compressed format and copy. + return {ExpandImage(image_info, cache_image_id), -1, -1}; + } + if (image_info.pixel_format != tex_cache_image.info.pixel_format || image_info.guest_size <= tex_cache_image.info.guest_size) { auto result_id = merged_image_id ? merged_image_id : cache_image_id; const auto& result_image = slot_images[result_id]; - return { - IsVulkanFormatCompatible(image_info.pixel_format, result_image.info.pixel_format) - ? result_id - : ImageId{}, - -1, -1}; + const bool is_compatible = + IsVulkanFormatCompatible(result_image.info.pixel_format, image_info.pixel_format); + return {is_compatible ? result_id : ImageId{}, -1, -1}; } if (image_info.type == tex_cache_image.info.type && @@ -340,7 +345,7 @@ ImageId TextureCache::FindImage(BaseDesc& desc, FindFlags flags) { continue; } if (False(flags & FindFlags::RelaxFmt) && - (!IsVulkanFormatCompatible(info.pixel_format, cache_image.info.pixel_format) || + (!IsVulkanFormatCompatible(cache_image.info.pixel_format, info.pixel_format) || (cache_image.info.type != info.type && info.size != Extent3D{1, 1, 1}))) { continue; } @@ -512,9 +517,9 @@ void TextureCache::RefreshImage(Image& image, Vulkan::Scheduler* custom_schedule // So this calculation should be very uncommon and reasonably fast // For now we'll just check up to 64 first pixels const auto addr = std::bit_cast(image.info.guest_address); - const auto w = std::min(image.info.size.width, u32(8)); - const auto h = std::min(image.info.size.height, u32(8)); - const auto size = w * h * image.info.num_bits / 8; + const u32 w = std::min(image.info.size.width, u32(8)); + const u32 h = std::min(image.info.size.height, u32(8)); + const u32 size = w * h * image.info.num_bits >> (3 + image.info.props.is_block ? 4 : 0); const u64 hash = XXH3_64bits(addr, size); if (image.hash == hash) { image.flags &= ~ImageFlagBits::MaybeCpuDirty; diff --git a/src/video_core/texture_cache/tile_manager.cpp b/src/video_core/texture_cache/tile_manager.cpp index d7fc54338..683ac08db 100644 --- a/src/video_core/texture_cache/tile_manager.cpp +++ b/src/video_core/texture_cache/tile_manager.cpp @@ -25,10 +25,9 @@ namespace VideoCore { const DetilerContext* TileManager::GetDetiler(const ImageInfo& info) const { - const auto bpp = info.num_bits * (info.props.is_block ? 16 : 1); switch (info.tiling_mode) { case AmdGpu::TilingMode::Texture_MicroTiled: - switch (bpp) { + switch (info.num_bits) { case 8: return &detilers[DetilerType::Micro8]; case 16: @@ -43,7 +42,7 @@ const DetilerContext* TileManager::GetDetiler(const ImageInfo& info) const { return nullptr; } case AmdGpu::TilingMode::Texture_Volume: - switch (bpp) { + switch (info.num_bits) { case 8: return &detilers[DetilerType::Macro8]; case 32: @@ -55,7 +54,7 @@ const DetilerContext* TileManager::GetDetiler(const ImageInfo& info) const { } break; case AmdGpu::TilingMode::Display_MicroTiled: - switch (bpp) { + switch (info.num_bits) { case 64: return &detilers[DetilerType::Display_Micro64]; default: @@ -71,7 +70,7 @@ struct DetilerParams { u32 num_levels; u32 pitch0; u32 height; - u32 sizes[14]; + std::array sizes; }; TileManager::TileManager(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler) @@ -276,7 +275,7 @@ std::pair TileManager::TryDetile(vk::Buffer in_buffer, u32 in_o params.sizes[0] = tiles_per_row; params.sizes[1] = tiles_per_slice; } else { - ASSERT(info.resources.levels <= 14); + ASSERT(info.resources.levels <= params.sizes.size()); std::memset(¶ms.sizes, 0, sizeof(params.sizes)); for (int m = 0; m < info.resources.levels; ++m) { params.sizes[m] = info.mips_layout[m].size + (m > 0 ? params.sizes[m - 1] : 0); @@ -287,8 +286,7 @@ std::pair TileManager::TryDetile(vk::Buffer in_buffer, u32 in_o ¶ms); ASSERT((image_size % 64) == 0); - const auto bpp = info.num_bits * (info.props.is_block ? 16u : 1u); - const auto num_tiles = image_size / (64 * (bpp / 8)); + const auto num_tiles = image_size / (64 * (info.num_bits / 8)); cmdbuf.dispatch(num_tiles, 1, 1); return {out_buffer.first, 0}; }