renderer_vulkan: Refactor surface and depth format mapping. (#1067)

* renderer_vulkan: Refactor surface and depth format mapping.

* image: Convert usage to feature flags for format support checks.
This commit is contained in:
squidbus 2024-09-25 02:10:44 -07:00 committed by GitHub
parent cc99f52606
commit 36ef61908d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 491 additions and 377 deletions

View file

@ -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 {

View file

@ -294,302 +294,336 @@ vk::BorderColor BorderColor(AmdGpu::BorderColor color) {
}
}
std::span<const vk::Format> 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<u32>(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<u32>(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<const SurfaceFormatInfo> 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<u32>(data_format), static_cast<u32>(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<const DepthFormatInfo> 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<u32>(z_format), static_cast<u32>(stencil_format));
return format->vk_format;
}
void EmitQuadToTriangleListIndices(u8* out_ptr, u32 num_vertices) {

View file

@ -40,13 +40,27 @@ vk::SamplerMipmapMode MipFilter(AmdGpu::MipFilter filter);
vk::BorderColor BorderColor(AmdGpu::BorderColor color);
std::span<const vk::Format> GetAllFormats();
struct SurfaceFormatInfo {
AmdGpu::DataFormat data_format;
AmdGpu::NumberFormat number_format;
vk::Format vk_format;
vk::FormatFeatureFlags2 flags;
};
std::span<const SurfaceFormatInfo> 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<const DepthFormatInfo> DepthFormats();
vk::Format DepthFormat(Liverpool::DepthBuffer::ZFormat z_format,
Liverpool::DepthBuffer::StencilFormat stencil_format);

View file

@ -33,16 +33,41 @@ std::vector<std::string> 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<vk::Format, vk::FormatProperties3> GetFormatProperties(
vk::PhysicalDevice physical) {
std::unordered_map<vk::Format, vk::FormatProperties3> 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<u32>(format.data_format),
static_cast<u32>(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<u32>(format.z_format), static_cast<u32>(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;
}

View file

@ -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;

View file

@ -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

View file

@ -114,6 +114,7 @@ struct Image {
// Resource state tracking
vk::ImageUsageFlags usage;
vk::FormatFeatureFlags2 format_features;
struct State {
vk::Flags<vk::PipelineStageFlagBits2> pl_stage = vk::PipelineStageFlagBits2::eAllCommands;
vk::Flags<vk::AccessFlagBits2> access_mask = vk::AccessFlagBits2::eNone;

View file

@ -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,