diff --git a/src/video_core/amdgpu/pixel_format.h b/src/video_core/amdgpu/pixel_format.h index 53d30a7fd..88da49632 100644 --- a/src/video_core/amdgpu/pixel_format.h +++ b/src/video_core/amdgpu/pixel_format.h @@ -43,6 +43,23 @@ enum class DataFormat : u32 { FormatBc5 = 39, FormatBc6 = 40, FormatBc7 = 41, + FormatFmask8_1 = 47, + FormatFmask8_2 = 48, + FormatFmask8_4 = 49, + FormatFmask16_1 = 50, + FormatFmask16_2 = 51, + FormatFmask32_2 = 52, + FormatFmask32_4 = 53, + FormatFmask32_8 = 54, + FormatFmask64_4 = 55, + FormatFmask64_8 = 56, + Format4_4 = 57, + Format6_5_5 = 58, + Format1 = 59, + Format1_Reversed = 60, + Format32_As_8 = 61, + Format32_As_8_8 = 62, + Format32_As_32_32_32_32 = 63, }; enum class NumberFormat : u32 { diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp index c4b779fad..cc6302c8f 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp @@ -294,302 +294,336 @@ vk::BorderColor BorderColor(AmdGpu::BorderColor color) { } } -std::span GetAllFormats() { +static constexpr vk::FormatFeatureFlags2 BufferRead = + vk::FormatFeatureFlagBits2::eUniformTexelBuffer | vk::FormatFeatureFlagBits2::eVertexBuffer; +static constexpr vk::FormatFeatureFlags2 BufferWrite = + vk::FormatFeatureFlagBits2::eStorageTexelBuffer | + vk::FormatFeatureFlagBits2::eStorageReadWithoutFormat | + vk::FormatFeatureFlagBits2::eStorageWriteWithoutFormat; +static constexpr vk::FormatFeatureFlags2 ImageRead = vk::FormatFeatureFlagBits2::eTransferSrc | + vk::FormatFeatureFlagBits2::eTransferDst | + vk::FormatFeatureFlagBits2::eSampledImage; +static constexpr vk::FormatFeatureFlags2 ImageWrite = + vk::FormatFeatureFlagBits2::eStorageImage | + vk::FormatFeatureFlagBits2::eStorageReadWithoutFormat | + vk::FormatFeatureFlagBits2::eStorageWriteWithoutFormat; +static constexpr vk::FormatFeatureFlags2 Mrt = vk::FormatFeatureFlagBits2::eColorAttachment; + +// Table 8.13 Data and Image Formats [Sea Islands Series Instruction Set Architecture] +static constexpr vk::FormatFeatureFlags2 GetDataFormatFeatureFlags( + const AmdGpu::DataFormat data_format) { + switch (data_format) { + case AmdGpu::DataFormat::FormatInvalid: + case AmdGpu::DataFormat::Format8: + case AmdGpu::DataFormat::Format16: + case AmdGpu::DataFormat::Format8_8: + case AmdGpu::DataFormat::Format32: + case AmdGpu::DataFormat::Format16_16: + case AmdGpu::DataFormat::Format10_11_11: + case AmdGpu::DataFormat::Format11_11_10: + case AmdGpu::DataFormat::Format10_10_10_2: + case AmdGpu::DataFormat::Format2_10_10_10: + case AmdGpu::DataFormat::Format8_8_8_8: + case AmdGpu::DataFormat::Format32_32: + case AmdGpu::DataFormat::Format16_16_16_16: + case AmdGpu::DataFormat::Format32_32_32_32: + return BufferRead | BufferWrite | ImageRead | ImageWrite | Mrt; + case AmdGpu::DataFormat::Format32_32_32: + return BufferRead | BufferWrite | ImageRead; + case AmdGpu::DataFormat::Format5_6_5: + case AmdGpu::DataFormat::Format1_5_5_5: + case AmdGpu::DataFormat::Format5_5_5_1: + case AmdGpu::DataFormat::Format4_4_4_4: + return ImageRead | ImageWrite | Mrt; + case AmdGpu::DataFormat::Format8_24: + case AmdGpu::DataFormat::Format24_8: + case AmdGpu::DataFormat::FormatX24_8_32: + return ImageRead | Mrt; + case AmdGpu::DataFormat::FormatGB_GR: + case AmdGpu::DataFormat::FormatBG_RG: + case AmdGpu::DataFormat::Format5_9_9_9: + case AmdGpu::DataFormat::FormatBc1: + case AmdGpu::DataFormat::FormatBc2: + case AmdGpu::DataFormat::FormatBc3: + case AmdGpu::DataFormat::FormatBc4: + case AmdGpu::DataFormat::FormatBc5: + case AmdGpu::DataFormat::FormatBc6: + case AmdGpu::DataFormat::FormatBc7: + case AmdGpu::DataFormat::Format4_4: + case AmdGpu::DataFormat::Format6_5_5: + case AmdGpu::DataFormat::Format1: + case AmdGpu::DataFormat::Format1_Reversed: + case AmdGpu::DataFormat::Format32_As_8: + case AmdGpu::DataFormat::Format32_As_8_8: + case AmdGpu::DataFormat::Format32_As_32_32_32_32: + return ImageRead; + case AmdGpu::DataFormat::FormatFmask8_1: + case AmdGpu::DataFormat::FormatFmask8_2: + case AmdGpu::DataFormat::FormatFmask8_4: + case AmdGpu::DataFormat::FormatFmask16_1: + case AmdGpu::DataFormat::FormatFmask16_2: + case AmdGpu::DataFormat::FormatFmask32_2: + case AmdGpu::DataFormat::FormatFmask32_4: + case AmdGpu::DataFormat::FormatFmask32_8: + case AmdGpu::DataFormat::FormatFmask64_4: + case AmdGpu::DataFormat::FormatFmask64_8: + return ImageRead | ImageWrite; + } + UNREACHABLE_MSG("Missing feature flags for data format {}", static_cast(data_format)); +} + +// Table 8.13 Data and Image Formats [Sea Islands Series Instruction Set Architecture] +static constexpr vk::FormatFeatureFlags2 GetNumberFormatFeatureFlags( + const AmdGpu::NumberFormat number_format) { + switch (number_format) { + case AmdGpu::NumberFormat::Unorm: + case AmdGpu::NumberFormat::Snorm: + case AmdGpu::NumberFormat::Uint: + case AmdGpu::NumberFormat::Sint: + case AmdGpu::NumberFormat::Float: + return BufferRead | BufferWrite | ImageRead | ImageWrite; + case AmdGpu::NumberFormat::Uscaled: + case AmdGpu::NumberFormat::Sscaled: + case AmdGpu::NumberFormat::SnormNz: + return BufferRead | ImageRead; + case AmdGpu::NumberFormat::Srgb: + case AmdGpu::NumberFormat::Ubnorm: + case AmdGpu::NumberFormat::UbnromNz: + case AmdGpu::NumberFormat::Ubint: + case AmdGpu::NumberFormat::Ubscaled: + return ImageRead; + } + UNREACHABLE_MSG("Missing feature flags for number format {}", static_cast(number_format)); +} + +static constexpr SurfaceFormatInfo CreateSurfaceFormatInfo(const AmdGpu::DataFormat data_format, + const AmdGpu::NumberFormat number_format, + const vk::Format vk_format) { + return { + .data_format = data_format, + .number_format = number_format, + .vk_format = vk_format, + .flags = + GetDataFormatFeatureFlags(data_format) & GetNumberFormatFeatureFlags(number_format), + }; +} + +std::span SurfaceFormats() { static constexpr std::array formats{ - vk::Format::eA2B10G10R10SnormPack32, - vk::Format::eA2B10G10R10UnormPack32, - vk::Format::eA2R10G10B10UnormPack32, - vk::Format::eB5G6R5UnormPack16, - vk::Format::eB8G8R8A8Srgb, - vk::Format::eB8G8R8A8Unorm, - vk::Format::eB10G11R11UfloatPack32, - vk::Format::eBc1RgbaSrgbBlock, - vk::Format::eBc1RgbaUnormBlock, - vk::Format::eBc2SrgbBlock, - vk::Format::eBc2UnormBlock, - vk::Format::eBc3SrgbBlock, - vk::Format::eBc3UnormBlock, - vk::Format::eBc4UnormBlock, - vk::Format::eBc5UnormBlock, - vk::Format::eBc5SnormBlock, - vk::Format::eBc7SrgbBlock, - vk::Format::eBc7UnormBlock, - vk::Format::eD16Unorm, - vk::Format::eD16UnormS8Uint, - vk::Format::eD24UnormS8Uint, - vk::Format::eD32Sfloat, - vk::Format::eD32SfloatS8Uint, - vk::Format::eR4G4B4A4UnormPack16, - vk::Format::eR5G6B5UnormPack16, - vk::Format::eR5G5B5A1UnormPack16, - vk::Format::eR8G8B8A8Srgb, - vk::Format::eR8G8B8A8Uint, - vk::Format::eR8G8B8A8Unorm, - vk::Format::eR8G8B8A8Snorm, - vk::Format::eR8G8B8A8Uscaled, - vk::Format::eR8G8Snorm, - vk::Format::eR8G8Uint, - vk::Format::eR8G8Unorm, - vk::Format::eR8Sint, - vk::Format::eR8Snorm, - vk::Format::eR8Uint, - vk::Format::eR8Unorm, - vk::Format::eR8Srgb, - vk::Format::eR16G16B16A16Sfloat, - vk::Format::eR16G16B16A16Sint, - vk::Format::eR16G16B16A16Snorm, - vk::Format::eR16G16B16A16Uint, - vk::Format::eR16G16B16A16Unorm, - vk::Format::eR16G16Sfloat, - vk::Format::eR16G16Sint, - vk::Format::eR16G16Snorm, - vk::Format::eR16Sfloat, - vk::Format::eR16Uint, - vk::Format::eR16Unorm, - vk::Format::eR32G32B32A32Sfloat, - vk::Format::eR32G32B32A32Sint, - vk::Format::eR32G32B32A32Uint, - vk::Format::eR32G32B32Sfloat, - vk::Format::eR32G32B32Uint, - vk::Format::eR32G32Sfloat, - vk::Format::eR32G32Uint, - vk::Format::eR32Sfloat, - vk::Format::eR32Sint, - vk::Format::eR32Uint, - vk::Format::eBc6HUfloatBlock, - vk::Format::eBc6HSfloatBlock, - vk::Format::eR16G16Unorm, - vk::Format::eR16G16B16A16Sscaled, - vk::Format::eR16G16Sscaled, - vk::Format::eE5B9G9R9UfloatPack32, + // Invalid + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Unorm, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Snorm, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Uscaled, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Sscaled, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Uint, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Sint, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::SnormNz, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Float, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Srgb, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Ubnorm, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::UbnromNz, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Ubint, + vk::Format::eUndefined), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatInvalid, AmdGpu::NumberFormat::Ubscaled, + vk::Format::eUndefined), + // 8 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8, AmdGpu::NumberFormat::Unorm, + vk::Format::eR8Unorm), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8, AmdGpu::NumberFormat::Snorm, + vk::Format::eR8Snorm), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8, AmdGpu::NumberFormat::Uint, + vk::Format::eR8Uint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8, AmdGpu::NumberFormat::Sint, + vk::Format::eR8Sint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8, AmdGpu::NumberFormat::Srgb, + vk::Format::eR8Srgb), + // 16 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16, AmdGpu::NumberFormat::Unorm, + vk::Format::eR16Unorm), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16, AmdGpu::NumberFormat::Snorm, + vk::Format::eR16Snorm), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16, AmdGpu::NumberFormat::Uint, + vk::Format::eR16Uint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16, AmdGpu::NumberFormat::Sint, + vk::Format::eR16Sint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16, AmdGpu::NumberFormat::Float, + vk::Format::eR16Sfloat), + // 8_8 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8, AmdGpu::NumberFormat::Unorm, + vk::Format::eR8G8Unorm), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8, AmdGpu::NumberFormat::Snorm, + vk::Format::eR8G8Snorm), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8, AmdGpu::NumberFormat::Uint, + vk::Format::eR8G8Uint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8, AmdGpu::NumberFormat::Sint, + vk::Format::eR8G8Sint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8, AmdGpu::NumberFormat::Srgb, + vk::Format::eR8G8Srgb), + // 32 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32, AmdGpu::NumberFormat::Uint, + vk::Format::eR32Uint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32, AmdGpu::NumberFormat::Sint, + vk::Format::eR32Sint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32, AmdGpu::NumberFormat::Float, + vk::Format::eR32Sfloat), + // 16_16 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16, AmdGpu::NumberFormat::Unorm, + vk::Format::eR16G16Unorm), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16, AmdGpu::NumberFormat::Snorm, + vk::Format::eR16G16Snorm), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16, AmdGpu::NumberFormat::Uscaled, + vk::Format::eR16G16Uscaled), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16, AmdGpu::NumberFormat::Sscaled, + vk::Format::eR16G16Sscaled), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16, AmdGpu::NumberFormat::Uint, + vk::Format::eR16G16Uint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16, AmdGpu::NumberFormat::Sint, + vk::Format::eR16G16Sint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16, AmdGpu::NumberFormat::Float, + vk::Format::eR16G16Sfloat), + // 10_11_11 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format10_11_11, AmdGpu::NumberFormat::Float, + vk::Format::eB10G11R11UfloatPack32), + // 11_11_10 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format11_11_10, AmdGpu::NumberFormat::Float, + vk::Format::eB10G11R11UfloatPack32), + // 10_10_10_2 + // 2_10_10_10 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format2_10_10_10, AmdGpu::NumberFormat::Unorm, + vk::Format::eA2B10G10R10UnormPack32), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format2_10_10_10, AmdGpu::NumberFormat::Snorm, + vk::Format::eA2B10G10R10SnormPack32), + // 8_8_8_8 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8_8_8, AmdGpu::NumberFormat::Unorm, + vk::Format::eR8G8B8A8Unorm), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8_8_8, AmdGpu::NumberFormat::Snorm, + vk::Format::eR8G8B8A8Snorm), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8_8_8, AmdGpu::NumberFormat::Uscaled, + vk::Format::eR8G8B8A8Uscaled), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8_8_8, AmdGpu::NumberFormat::Sscaled, + vk::Format::eR8G8B8A8Sscaled), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8_8_8, AmdGpu::NumberFormat::Uint, + vk::Format::eR8G8B8A8Uint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8_8_8, AmdGpu::NumberFormat::Sint, + vk::Format::eR8G8B8A8Sint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format8_8_8_8, AmdGpu::NumberFormat::Srgb, + vk::Format::eR8G8B8A8Srgb), + // 32_32 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32_32, AmdGpu::NumberFormat::Uint, + vk::Format::eR32G32Uint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32_32, AmdGpu::NumberFormat::Sint, + vk::Format::eR32G32Sint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32_32, AmdGpu::NumberFormat::Float, + vk::Format::eR32G32Sfloat), + // 16_16_16_16 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16_16_16, AmdGpu::NumberFormat::Unorm, + vk::Format::eR16G16B16A16Unorm), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16_16_16, AmdGpu::NumberFormat::Snorm, + vk::Format::eR16G16B16A16Snorm), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16_16_16, + AmdGpu::NumberFormat::Uscaled, vk::Format::eR16G16B16A16Uscaled), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16_16_16, + AmdGpu::NumberFormat::Sscaled, vk::Format::eR16G16B16A16Sscaled), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16_16_16, AmdGpu::NumberFormat::Uint, + vk::Format::eR16G16B16A16Uint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16_16_16, AmdGpu::NumberFormat::Sint, + vk::Format::eR16G16B16A16Sint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16_16_16, + AmdGpu::NumberFormat::SnormNz, vk::Format::eR16G16B16A16Snorm), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format16_16_16_16, AmdGpu::NumberFormat::Float, + vk::Format::eR16G16B16A16Sfloat), + // 32_32_32 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32_32_32, AmdGpu::NumberFormat::Uint, + vk::Format::eR32G32B32Uint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32_32_32, AmdGpu::NumberFormat::Sint, + vk::Format::eR32G32B32Sint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32_32_32, AmdGpu::NumberFormat::Float, + vk::Format::eR32G32B32Sfloat), + // 32_32_32_32 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32_32_32_32, AmdGpu::NumberFormat::Uint, + vk::Format::eR32G32B32A32Uint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32_32_32_32, AmdGpu::NumberFormat::Sint, + vk::Format::eR32G32B32A32Sint), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format32_32_32_32, AmdGpu::NumberFormat::Float, + vk::Format::eR32G32B32A32Sfloat), + // 5_6_5 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format5_6_5, AmdGpu::NumberFormat::Unorm, + vk::Format::eB5G6R5UnormPack16), + // 1_5_5_5 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format1_5_5_5, AmdGpu::NumberFormat::Unorm, + vk::Format::eR5G5B5A1UnormPack16), + // 5_5_5_1 + // 4_4_4_4 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format4_4_4_4, AmdGpu::NumberFormat::Unorm, + vk::Format::eR4G4B4A4UnormPack16), + // 8_24 + // 24_8 + // X24_8_32 + // GB_GR + // BG_RG + // 5_9_9_9 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format5_9_9_9, AmdGpu::NumberFormat::Float, + vk::Format::eE5B9G9R9UfloatPack32), + // BC1 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc1, AmdGpu::NumberFormat::Unorm, + vk::Format::eBc1RgbaUnormBlock), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc1, AmdGpu::NumberFormat::Srgb, + vk::Format::eBc1RgbaSrgbBlock), + // BC2 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc2, AmdGpu::NumberFormat::Unorm, + vk::Format::eBc2UnormBlock), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc2, AmdGpu::NumberFormat::Srgb, + vk::Format::eBc2SrgbBlock), + // BC3 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc3, AmdGpu::NumberFormat::Unorm, + vk::Format::eBc3UnormBlock), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc3, AmdGpu::NumberFormat::Srgb, + vk::Format::eBc3SrgbBlock), + // BC4 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc4, AmdGpu::NumberFormat::Unorm, + vk::Format::eBc4UnormBlock), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc4, AmdGpu::NumberFormat::Snorm, + vk::Format::eBc4SnormBlock), + // BC5 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc5, AmdGpu::NumberFormat::Unorm, + vk::Format::eBc5UnormBlock), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc5, AmdGpu::NumberFormat::Snorm, + vk::Format::eBc5SnormBlock), + // BC6 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc6, AmdGpu::NumberFormat::Unorm, + vk::Format::eBc6HUfloatBlock), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc6, AmdGpu::NumberFormat::Snorm, + vk::Format::eBc6HSfloatBlock), + // BC7 + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc7, AmdGpu::NumberFormat::Unorm, + vk::Format::eBc7UnormBlock), + CreateSurfaceFormatInfo(AmdGpu::DataFormat::FormatBc7, AmdGpu::NumberFormat::Srgb, + vk::Format::eBc7SrgbBlock), }; return formats; } vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat num_format) { - - if (data_format == AmdGpu::DataFormat::Format32_32_32_32 && - num_format == AmdGpu::NumberFormat::Float) { - return vk::Format::eR32G32B32A32Sfloat; - } - if (data_format == AmdGpu::DataFormat::Format32_32_32 && - num_format == AmdGpu::NumberFormat::Uint) { - return vk::Format::eR32G32B32Uint; - } - if (data_format == AmdGpu::DataFormat::Format8_8_8_8 && - num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eR8G8B8A8Unorm; - } - if (data_format == AmdGpu::DataFormat::Format8_8_8_8 && - num_format == AmdGpu::NumberFormat::Srgb) { - return vk::Format::eR8G8B8A8Srgb; - } - if (data_format == AmdGpu::DataFormat::Format32_32_32 && - num_format == AmdGpu::NumberFormat::Float) { - return vk::Format::eR32G32B32Sfloat; - } - if (data_format == AmdGpu::DataFormat::Format32_32 && - num_format == AmdGpu::NumberFormat::Float) { - return vk::Format::eR32G32Sfloat; - } - if (data_format == AmdGpu::DataFormat::Format5_6_5 && - num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eB5G6R5UnormPack16; - } - if (data_format == AmdGpu::DataFormat::Format1_5_5_5 && - num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eR5G5B5A1UnormPack16; - } - if (data_format == AmdGpu::DataFormat::Format8 && num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eR8Unorm; - } - if (data_format == AmdGpu::DataFormat::FormatBc3 && num_format == AmdGpu::NumberFormat::Srgb) { - return vk::Format::eBc3SrgbBlock; - } - if (data_format == AmdGpu::DataFormat::FormatBc3 && num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eBc3UnormBlock; - } - if (data_format == AmdGpu::DataFormat::FormatBc4 && num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eBc4UnormBlock; - } - if (data_format == AmdGpu::DataFormat::FormatBc5 && num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eBc5UnormBlock; - } - if (data_format == AmdGpu::DataFormat::FormatBc5 && num_format == AmdGpu::NumberFormat::Snorm) { - return vk::Format::eBc5SnormBlock; - } - if (data_format == AmdGpu::DataFormat::Format16_16_16_16 && - num_format == AmdGpu::NumberFormat::Sint) { - return vk::Format::eR16G16B16A16Sint; - } - if (data_format == AmdGpu::DataFormat::Format16_16_16_16 && - num_format == AmdGpu::NumberFormat::Sscaled) { - return vk::Format::eR16G16B16A16Sscaled; - } - if (data_format == AmdGpu::DataFormat::Format16_16 && - num_format == AmdGpu::NumberFormat::Float) { - return vk::Format::eR16G16Sfloat; - } - if (data_format == AmdGpu::DataFormat::Format16_16 && - num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eR16G16Unorm; - } - if (data_format == AmdGpu::DataFormat::Format2_10_10_10 && - num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eA2B10G10R10UnormPack32; - } - if (data_format == AmdGpu::DataFormat::Format2_10_10_10 && - num_format == AmdGpu::NumberFormat::Snorm) { - return vk::Format::eA2B10G10R10SnormPack32; - } - if (data_format == AmdGpu::DataFormat::FormatBc7 && num_format == AmdGpu::NumberFormat::Srgb) { - return vk::Format::eBc7SrgbBlock; - } - if (data_format == AmdGpu::DataFormat::FormatBc1 && num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eBc1RgbaUnormBlock; - } - if (data_format == AmdGpu::DataFormat::Format8_8_8_8 && - num_format == AmdGpu::NumberFormat::Uint) { - return vk::Format::eR8G8B8A8Uint; - } - if (data_format == AmdGpu::DataFormat::Format16 && num_format == AmdGpu::NumberFormat::Float) { - return vk::Format::eR16Sfloat; - } - if (data_format == AmdGpu::DataFormat::Format32 && num_format == AmdGpu::NumberFormat::Float) { - return vk::Format::eR32Sfloat; - } - if (data_format == AmdGpu::DataFormat::Format16_16_16_16 && - num_format == AmdGpu::NumberFormat::Float) { - return vk::Format::eR16G16B16A16Sfloat; - } - if (data_format == AmdGpu::DataFormat::Format32 && num_format == AmdGpu::NumberFormat::Uint) { - return vk::Format::eR32Uint; - } - if (data_format == AmdGpu::DataFormat::Format32 && num_format == AmdGpu::NumberFormat::Sint) { - return vk::Format::eR32Sint; - } - if (data_format == AmdGpu::DataFormat::Format8_8 && num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eR8G8Unorm; - } - if (data_format == AmdGpu::DataFormat::Format8_8 && num_format == AmdGpu::NumberFormat::Uint) { - return vk::Format::eR8G8Uint; - } - if (data_format == AmdGpu::DataFormat::Format8_8 && num_format == AmdGpu::NumberFormat::Snorm) { - return vk::Format::eR8G8Snorm; - } - if (data_format == AmdGpu::DataFormat::FormatBc7 && num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eBc7UnormBlock; - } - if (data_format == AmdGpu::DataFormat::FormatBc2 && num_format == AmdGpu::NumberFormat::Srgb) { - return vk::Format::eBc2SrgbBlock; - } - if (data_format == AmdGpu::DataFormat::FormatBc2 && num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eBc2UnormBlock; - } - if (data_format == AmdGpu::DataFormat::Format16_16 && - num_format == AmdGpu::NumberFormat::Snorm) { - return vk::Format::eR16G16Snorm; - } - if (data_format == AmdGpu::DataFormat::Format10_11_11 && - num_format == AmdGpu::NumberFormat::Float) { - return vk::Format::eB10G11R11UfloatPack32; - } - if (data_format == AmdGpu::DataFormat::Format16_16 && - num_format == AmdGpu::NumberFormat::Float) { - return vk::Format::eR16G16Sfloat; - } - if (data_format == AmdGpu::DataFormat::Format16_16_16_16 && - num_format == AmdGpu::NumberFormat::Snorm) { - return vk::Format::eR16G16B16A16Snorm; - } - if (data_format == AmdGpu::DataFormat::Format32_32 && - num_format == AmdGpu::NumberFormat::Uint) { - return vk::Format::eR32G32Uint; - } - if (data_format == AmdGpu::DataFormat::Format4_4_4_4 && - num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eR4G4B4A4UnormPack16; - } - if (data_format == AmdGpu::DataFormat::Format16_16_16_16 && - num_format == AmdGpu::NumberFormat::Uint) { - return vk::Format::eR16G16B16A16Uint; - } - if (data_format == AmdGpu::DataFormat::Format32_32_32_32 && - num_format == AmdGpu::NumberFormat::Uint) { - return vk::Format::eR32G32B32A32Uint; - } - if (data_format == AmdGpu::DataFormat::Format32_32_32_32 && - num_format == AmdGpu::NumberFormat::Sint) { - return vk::Format::eR32G32B32A32Sint; - } - if (data_format == AmdGpu::DataFormat::Format8 && num_format == AmdGpu::NumberFormat::Sint) { - return vk::Format::eR8Sint; - } - if (data_format == AmdGpu::DataFormat::FormatBc1 && num_format == AmdGpu::NumberFormat::Srgb) { - return vk::Format::eBc1RgbaSrgbBlock; - } - if (data_format == AmdGpu::DataFormat::Format16_16 && - num_format == AmdGpu::NumberFormat::Sint) { - return vk::Format::eR16G16Sint; - } - if (data_format == AmdGpu::DataFormat::Format16_16 && - num_format == AmdGpu::NumberFormat::Sscaled) { - return vk::Format::eR16G16Sscaled; - } - if (data_format == AmdGpu::DataFormat::Format8_8_8_8 && - num_format == AmdGpu::NumberFormat::Uscaled) { - return vk::Format::eR8G8B8A8Uscaled; - } - if (data_format == AmdGpu::DataFormat::Format16 && num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eR16Unorm; - } - if (data_format == AmdGpu::DataFormat::Format16_16_16_16 && - num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eR16G16B16A16Unorm; - } - if (data_format == AmdGpu::DataFormat::Format16_16 && - num_format == AmdGpu::NumberFormat::Uint) { - return vk::Format::eR16G16Uint; - } - if (data_format == AmdGpu::DataFormat::Format8 && num_format == AmdGpu::NumberFormat::Uint) { - return vk::Format::eR8Uint; - } - if (data_format == AmdGpu::DataFormat::Format16_16_16_16 && - num_format == AmdGpu::NumberFormat::SnormNz) { - return vk::Format::eR16G16B16A16Snorm; - } - if (data_format == AmdGpu::DataFormat::Format8_8_8_8 && - num_format == AmdGpu::NumberFormat::Snorm) { - return vk::Format::eR8G8B8A8Snorm; - } - if (data_format == AmdGpu::DataFormat::FormatBc6 && num_format == AmdGpu::NumberFormat::Unorm) { - return vk::Format::eBc6HUfloatBlock; - } - if (data_format == AmdGpu::DataFormat::FormatBc6 && num_format == AmdGpu::NumberFormat::Snorm) { - return vk::Format::eBc6HSfloatBlock; - } - if (data_format == AmdGpu::DataFormat::Format8_8_8_8 && - num_format == AmdGpu::NumberFormat::Sint) { - return vk::Format::eR8G8B8A8Sint; - } - if (data_format == AmdGpu::DataFormat::Format8 && num_format == AmdGpu::NumberFormat::Srgb) { - return vk::Format::eR8Srgb; - } - if (data_format == AmdGpu::DataFormat::Format11_11_10 && - num_format == AmdGpu::NumberFormat::Float) { - return vk::Format::eB10G11R11UfloatPack32; - } - if (data_format == AmdGpu::DataFormat::Format16 && num_format == AmdGpu::NumberFormat::Uint) { - return vk::Format::eR16Uint; - } - if (data_format == AmdGpu::DataFormat::Format5_9_9_9 && - num_format == AmdGpu::NumberFormat::Float) { - return vk::Format::eE5B9G9R9UfloatPack32; - } - if (data_format == AmdGpu::DataFormat::Format8 && num_format == AmdGpu::NumberFormat::Snorm) { - return vk::Format::eR8Snorm; - } - UNREACHABLE_MSG("Unknown data_format={} and num_format={}", u32(data_format), u32(num_format)); + const auto& formats = SurfaceFormats(); + const auto format = + std::find_if(formats.begin(), formats.end(), [&](const SurfaceFormatInfo& format_info) { + return format_info.data_format == data_format && + format_info.number_format == num_format; + }); + ASSERT_MSG(format != formats.end(), "Unknown data_format={} and num_format={}", + static_cast(data_format), static_cast(num_format)); + return format->vk_format; } vk::Format AdjustColorBufferFormat(vk::Format base_format, @@ -636,30 +670,45 @@ vk::Format AdjustColorBufferFormat(vk::Format base_format, return base_format; } -vk::Format DepthFormat(DepthBuffer::ZFormat z_format, DepthBuffer::StencilFormat stencil_format) { +static constexpr DepthFormatInfo CreateDepthFormatInfo( + const DepthBuffer::ZFormat z_format, const DepthBuffer::StencilFormat stencil_format, + const vk::Format vk_format) { + return { + .z_format = z_format, + .stencil_format = stencil_format, + .vk_format = vk_format, + .flags = vk::FormatFeatureFlagBits2::eDepthStencilAttachment, + }; +} + +std::span DepthFormats() { using ZFormat = DepthBuffer::ZFormat; using StencilFormat = DepthBuffer::StencilFormat; + static constexpr std::array formats{ + // Invalid + CreateDepthFormatInfo(ZFormat::Invalid, StencilFormat::Invalid, vk::Format::eUndefined), + CreateDepthFormatInfo(ZFormat::Invalid, StencilFormat::Stencil8, + vk::Format::eD32SfloatS8Uint), + // 16 + CreateDepthFormatInfo(ZFormat::Z16, StencilFormat::Invalid, vk::Format::eD16Unorm), + CreateDepthFormatInfo(ZFormat::Z16, StencilFormat::Stencil8, vk::Format::eD16UnormS8Uint), + // 32_Float + CreateDepthFormatInfo(ZFormat::Z32Float, StencilFormat::Invalid, vk::Format::eD32Sfloat), + CreateDepthFormatInfo(ZFormat::Z32Float, StencilFormat::Stencil8, + vk::Format::eD32SfloatS8Uint), + }; + return formats; +} - if (z_format == ZFormat::Z32Float && stencil_format == StencilFormat::Stencil8) { - return vk::Format::eD32SfloatS8Uint; - } - if (z_format == ZFormat::Z32Float && stencil_format == StencilFormat::Invalid) { - return vk::Format::eD32Sfloat; - } - if (z_format == ZFormat::Z16 && stencil_format == StencilFormat::Invalid) { - return vk::Format::eD16Unorm; - } - if (z_format == ZFormat::Z16 && stencil_format == StencilFormat::Stencil8) { - return vk::Format::eD16UnormS8Uint; - } - if (z_format == ZFormat::Invalid && stencil_format == StencilFormat::Stencil8) { - return vk::Format::eD32SfloatS8Uint; - } - if (z_format == ZFormat::Invalid && stencil_format == StencilFormat::Invalid) { - return vk::Format::eUndefined; - } - UNREACHABLE_MSG("Unsupported depth/stencil format. depth = {} stencil = {}", - magic_enum::enum_name(z_format), magic_enum::enum_name(stencil_format)); +vk::Format DepthFormat(DepthBuffer::ZFormat z_format, DepthBuffer::StencilFormat stencil_format) { + const auto& formats = DepthFormats(); + const auto format = + std::find_if(formats.begin(), formats.end(), [&](const DepthFormatInfo& format_info) { + return format_info.z_format == z_format && format_info.stencil_format == stencil_format; + }); + ASSERT_MSG(format != formats.end(), "Unknown z_format={} and stencil_format={}", + static_cast(z_format), static_cast(stencil_format)); + return format->vk_format; } void EmitQuadToTriangleListIndices(u8* out_ptr, u32 num_vertices) { diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.h b/src/video_core/renderer_vulkan/liverpool_to_vk.h index f5d10d48f..6a7825ee8 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.h +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.h @@ -40,13 +40,27 @@ vk::SamplerMipmapMode MipFilter(AmdGpu::MipFilter filter); vk::BorderColor BorderColor(AmdGpu::BorderColor color); -std::span GetAllFormats(); +struct SurfaceFormatInfo { + AmdGpu::DataFormat data_format; + AmdGpu::NumberFormat number_format; + vk::Format vk_format; + vk::FormatFeatureFlags2 flags; +}; +std::span SurfaceFormats(); vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat num_format); vk::Format AdjustColorBufferFormat(vk::Format base_format, Liverpool::ColorBuffer::SwapMode comp_swap, bool is_vo_surface); +struct DepthFormatInfo { + Liverpool::DepthBuffer::ZFormat z_format; + Liverpool::DepthBuffer::StencilFormat stencil_format; + vk::Format vk_format; + vk::FormatFeatureFlags2 flags; +}; +std::span DepthFormats(); + vk::Format DepthFormat(Liverpool::DepthBuffer::ZFormat z_format, Liverpool::DepthBuffer::StencilFormat stencil_format); diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index 7d5ff6eda..d919ace2f 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -33,16 +33,41 @@ std::vector GetSupportedExtensions(vk::PhysicalDevice physical) { return supported_extensions; } +vk::FormatProperties3 GetFormatProperties(vk::PhysicalDevice physical, vk::Format format) { + vk::FormatProperties3 properties3{}; + vk::FormatProperties2 properties2 = { + .pNext = &properties3, + }; + physical.getFormatProperties2(format, &properties2); + return properties3; +} + std::unordered_map GetFormatProperties( vk::PhysicalDevice physical) { std::unordered_map format_properties; - for (const auto& format : LiverpoolToVK::GetAllFormats()) { - vk::FormatProperties3 properties3{}; - vk::FormatProperties2 properties2 = { - .pNext = &properties3, - }; - physical.getFormatProperties2(format, &properties2); - format_properties.emplace(format, properties3); + for (const auto& format_info : LiverpoolToVK::SurfaceFormats()) { + const auto format = format_info.vk_format; + if (!format_properties.contains(format)) { + format_properties.emplace(format, GetFormatProperties(physical, format)); + } + } + for (const auto& format_info : LiverpoolToVK::DepthFormats()) { + const auto format = format_info.vk_format; + if (!format_properties.contains(format)) { + format_properties.emplace(format, GetFormatProperties(physical, format)); + } + } + // Other miscellaneous formats, e.g. for color buffers, swizzles, or compatibility + static constexpr std::array misc_formats = { + vk::Format::eA2R10G10B10UnormPack32, vk::Format::eA8B8G8R8UnormPack32, + vk::Format::eA8B8G8R8SrgbPack32, vk::Format::eB8G8R8A8Unorm, + vk::Format::eB8G8R8A8Srgb, vk::Format::eR5G6B5UnormPack16, + vk::Format::eD24UnormS8Uint, + }; + for (const auto& format : misc_formats) { + if (!format_properties.contains(format)) { + format_properties.emplace(format, GetFormatProperties(physical, format)); + } } return format_properties; } @@ -125,22 +150,23 @@ Instance::Instance(Frontend::WindowSDL& window, s32 physical_device_index, CollectToolingInfo(); // Check and log format support details. - for (const auto& key : format_properties | std::views::keys) { - const auto format = key; - if (!IsImageFormatSupported(format)) { - const auto alternative = GetAlternativeFormat(format); - if (IsImageFormatSupported(alternative)) { - LOG_WARNING(Render_Vulkan, - "Format {} is not supported for images, falling back to {}.", - vk::to_string(format), vk::to_string(alternative)); - } else if (IsVertexFormatSupported(format)) { - LOG_WARNING(Render_Vulkan, "Format {} is only supported for vertex buffers.", - vk::to_string(format)); - } else { - LOG_ERROR(Render_Vulkan, - "Format {} is not supported and no suitable alternative is supported.", - vk::to_string(format)); - } + for (const auto& format : LiverpoolToVK::SurfaceFormats()) { + if (!IsFormatSupported(GetSupportedFormat(format.vk_format, format.flags), format.flags)) { + LOG_WARNING(Render_Vulkan, + "Surface format data_format={}, number_format={} is not fully supported " + "(vk_format={}, requested flags={})", + static_cast(format.data_format), + static_cast(format.number_format), vk::to_string(format.vk_format), + vk::to_string(format.flags)); + } + } + for (const auto& format : LiverpoolToVK::DepthFormats()) { + if (!IsFormatSupported(GetSupportedFormat(format.vk_format, format.flags), format.flags)) { + LOG_WARNING(Render_Vulkan, + "Depth format z_format={}, stencil_format={} is not fully supported " + "(vk_format={}, requested flags={})", + static_cast(format.z_format), static_cast(format.stencil_format), + vk::to_string(format.vk_format), vk::to_string(format.flags)); } } } @@ -496,7 +522,8 @@ void Instance::CollectToolingInfo() { } } -bool Instance::IsImageFormatSupported(const vk::Format format) const { +bool Instance::IsFormatSupported(const vk::Format format, + const vk::FormatFeatureFlags2 flags) const { if (format == vk::Format::eUndefined) [[unlikely]] { return true; } @@ -506,49 +533,36 @@ bool Instance::IsImageFormatSupported(const vk::Format format) const { UNIMPLEMENTED_MSG("Properties of format {} have not been queried.", vk::to_string(format)); } - constexpr vk::FormatFeatureFlags2 optimal_flags = vk::FormatFeatureFlagBits2::eTransferSrc | - vk::FormatFeatureFlagBits2::eTransferDst | - vk::FormatFeatureFlagBits2::eSampledImage; - return (it->second.optimalTilingFeatures & optimal_flags) == optimal_flags; + return ((it->second.optimalTilingFeatures | it->second.bufferFeatures) & flags) == flags; } -bool Instance::IsVertexFormatSupported(const vk::Format format) const { - if (format == vk::Format::eUndefined) [[unlikely]] { - return true; - } - - const auto it = format_properties.find(format); - if (it == format_properties.end()) { - UNIMPLEMENTED_MSG("Properties of format {} have not been queried.", vk::to_string(format)); - } - - constexpr vk::FormatFeatureFlags2 optimal_flags = vk::FormatFeatureFlagBits2::eVertexBuffer; - return (it->second.bufferFeatures & optimal_flags) == optimal_flags; -} - -vk::Format Instance::GetAlternativeFormat(const vk::Format format) const { - if (format == vk::Format::eB5G6R5UnormPack16) { +static vk::Format GetAlternativeFormat(const vk::Format format) { + switch (format) { + case vk::Format::eB5G6R5UnormPack16: return vk::Format::eR5G6B5UnormPack16; - } else if (format == vk::Format::eD16UnormS8Uint) { + case vk::Format::eD16UnormS8Uint: return vk::Format::eD24UnormS8Uint; + default: + return format; } - return format; } -vk::Format Instance::GetSupportedFormat(const vk::Format format) const { - if (IsImageFormatSupported(format)) [[likely]] { +vk::Format Instance::GetSupportedFormat(const vk::Format format, + const vk::FormatFeatureFlags2 flags) const { + if (IsFormatSupported(format, flags)) [[likely]] { return format; } const vk::Format alternative = GetAlternativeFormat(format); - if (IsImageFormatSupported(alternative)) [[likely]] { + if (IsFormatSupported(alternative, flags)) [[likely]] { return alternative; } return format; } -vk::ComponentMapping Instance::GetSupportedComponentSwizzle(vk::Format format, - vk::ComponentMapping swizzle) const { - if (IsImageFormatSupported(format)) [[likely]] { +vk::ComponentMapping Instance::GetSupportedComponentSwizzle( + const vk::Format format, const vk::ComponentMapping swizzle, + const vk::FormatFeatureFlags2 flags) const { + if (IsFormatSupported(format, flags)) [[likely]] { return swizzle; } diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index 1c94f586e..e6e39ab1f 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -30,11 +30,12 @@ public: std::string GetDriverVersionName(); /// Gets a compatibility format if the format is not supported. - [[nodiscard]] vk::Format GetSupportedFormat(vk::Format format) const; + [[nodiscard]] vk::Format GetSupportedFormat(vk::Format format, + vk::FormatFeatureFlags2 flags) const; /// Re-orders a component swizzle for format compatibility, if needed. [[nodiscard]] vk::ComponentMapping GetSupportedComponentSwizzle( - vk::Format format, vk::ComponentMapping swizzle) const; + vk::Format format, vk::ComponentMapping swizzle, vk::FormatFeatureFlags2 flags) const; /// Returns the Vulkan instance vk::Instance GetInstance() const { @@ -245,14 +246,8 @@ private: void CollectDeviceParameters(); void CollectToolingInfo(); - /// Determines if a format is supported for images. - [[nodiscard]] bool IsImageFormatSupported(vk::Format format) const; - - /// Determines if a format is supported for vertex buffers. - [[nodiscard]] bool IsVertexFormatSupported(vk::Format format) const; - - /// Gets a commonly available alternative for an unsupported pixel format. - vk::Format GetAlternativeFormat(const vk::Format format) const; + /// Determines if a format is supported for a set of feature flags. + [[nodiscard]] bool IsFormatSupported(vk::Format format, vk::FormatFeatureFlags2 flags) const; private: vk::UniqueInstance instance; diff --git a/src/video_core/texture_cache/image.cpp b/src/video_core/texture_cache/image.cpp index 4ce6e1eea..16a9ce96a 100644 --- a/src/video_core/texture_cache/image.cpp +++ b/src/video_core/texture_cache/image.cpp @@ -86,6 +86,28 @@ static vk::ImageUsageFlags ImageUsageFlags(const ImageInfo& info) { return usage; } +static vk::FormatFeatureFlags2 FormatFeatureFlags(const vk::ImageUsageFlags usage_flags) { + vk::FormatFeatureFlags2 feature_flags{}; + if (usage_flags & vk::ImageUsageFlagBits::eTransferSrc) { + feature_flags |= vk::FormatFeatureFlagBits2::eTransferSrc; + } + if (usage_flags & vk::ImageUsageFlagBits::eTransferDst) { + feature_flags |= vk::FormatFeatureFlagBits2::eTransferDst; + } + if (usage_flags & vk::ImageUsageFlagBits::eSampled) { + feature_flags |= vk::FormatFeatureFlagBits2::eSampledImage; + } + if (usage_flags & vk::ImageUsageFlagBits::eColorAttachment) { + feature_flags |= vk::FormatFeatureFlagBits2::eColorAttachment; + } + if (usage_flags & vk::ImageUsageFlagBits::eDepthStencilAttachment) { + feature_flags |= vk::FormatFeatureFlagBits2::eDepthStencilAttachment; + } + // Note: StorageImage is intentionally ignored for now since it is always set, and can mess up + // compatibility checks. + return feature_flags; +} + UniqueImage::UniqueImage(vk::Device device_, VmaAllocator allocator_) : device{device_}, allocator{allocator_} {} @@ -132,6 +154,7 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_, } usage = ImageUsageFlags(info); + format_features = FormatFeatureFlags(usage); switch (info.pixel_format) { case vk::Format::eD16Unorm: @@ -149,7 +172,7 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_, } constexpr auto tiling = vk::ImageTiling::eOptimal; - const auto supported_format = instance->GetSupportedFormat(info.pixel_format); + const auto supported_format = instance->GetSupportedFormat(info.pixel_format, format_features); const auto properties = instance->GetPhysicalDevice().getImageFormatProperties( supported_format, info.type, tiling, usage, flags); const auto supported_samples = properties.result == vk::Result::eSuccess diff --git a/src/video_core/texture_cache/image.h b/src/video_core/texture_cache/image.h index 01e6fe8f3..312ff97e8 100644 --- a/src/video_core/texture_cache/image.h +++ b/src/video_core/texture_cache/image.h @@ -114,6 +114,7 @@ struct Image { // Resource state tracking vk::ImageUsageFlags usage; + vk::FormatFeatureFlags2 format_features; struct State { vk::Flags pl_stage = vk::PipelineStageFlagBits2::eAllCommands; vk::Flags access_mask = vk::AccessFlagBits2::eNone; diff --git a/src/video_core/texture_cache/image_view.cpp b/src/video_core/texture_cache/image_view.cpp index 2aad1afb6..a77798e1b 100644 --- a/src/video_core/texture_cache/image_view.cpp +++ b/src/video_core/texture_cache/image_view.cpp @@ -164,8 +164,9 @@ ImageView::ImageView(const Vulkan::Instance& instance, const ImageViewInfo& info .pNext = &usage_ci, .image = image.image, .viewType = info.type, - .format = instance.GetSupportedFormat(format), - .components = instance.GetSupportedComponentSwizzle(format, info.mapping), + .format = instance.GetSupportedFormat(format, image.format_features), + .components = + instance.GetSupportedComponentSwizzle(format, info.mapping, image.format_features), .subresourceRange{ .aspectMask = aspect, .baseMipLevel = info.range.base.level,