Add fallback system for unsupported pixel formats.
This commit is contained in:
parent
35d629a730
commit
175ffe8ce3
|
@ -281,6 +281,63 @@ vk::BorderColor BorderColor(AmdGpu::BorderColor color) {
|
|||
}
|
||||
}
|
||||
|
||||
const std::vector<vk::Format>& GetAllFormats() {
|
||||
static const std::vector formats{
|
||||
vk::Format::eR32G32B32A32Sfloat,
|
||||
vk::Format::eR32G32B32Uint,
|
||||
vk::Format::eR8G8B8A8Unorm,
|
||||
vk::Format::eB8G8R8A8Unorm,
|
||||
vk::Format::eR8G8B8A8Srgb,
|
||||
vk::Format::eB8G8R8A8Srgb,
|
||||
vk::Format::eR32G32B32Sfloat,
|
||||
vk::Format::eR32G32Sfloat,
|
||||
vk::Format::eB5G6R5UnormPack16,
|
||||
vk::Format::eR5G6B5UnormPack16,
|
||||
vk::Format::eR8Unorm,
|
||||
vk::Format::eBc3SrgbBlock,
|
||||
vk::Format::eBc3UnormBlock,
|
||||
vk::Format::eBc4UnormBlock,
|
||||
vk::Format::eBc5UnormBlock,
|
||||
vk::Format::eR16G16B16A16Sint,
|
||||
vk::Format::eR16G16Sfloat,
|
||||
vk::Format::eB10G11R11UfloatPack32,
|
||||
vk::Format::eA2B10G10R10UnormPack32,
|
||||
vk::Format::eBc7SrgbBlock,
|
||||
vk::Format::eBc1RgbaUnormBlock,
|
||||
vk::Format::eR8G8B8A8Uint,
|
||||
vk::Format::eR16Sfloat,
|
||||
vk::Format::eR32Sfloat,
|
||||
vk::Format::eR16G16B16A16Sfloat,
|
||||
vk::Format::eR32Uint,
|
||||
vk::Format::eR32Sint,
|
||||
vk::Format::eR8G8Unorm,
|
||||
vk::Format::eR8G8Snorm,
|
||||
vk::Format::eBc7UnormBlock,
|
||||
vk::Format::eBc2UnormBlock,
|
||||
vk::Format::eR16G16Snorm,
|
||||
vk::Format::eA2R10G10B10UnormPack32,
|
||||
vk::Format::eA2R10G10B10SnormPack32,
|
||||
vk::Format::eB10G11R11UfloatPack32,
|
||||
vk::Format::eR16G16Sfloat,
|
||||
vk::Format::eR16G16B16A16Snorm,
|
||||
vk::Format::eR32G32Uint,
|
||||
vk::Format::eR4G4B4A4UnormPack16,
|
||||
vk::Format::eR16G16B16A16Uint,
|
||||
vk::Format::eR32G32B32A32Uint,
|
||||
vk::Format::eR8Sint,
|
||||
vk::Format::eBc1RgbaSrgbBlock,
|
||||
vk::Format::eR16G16Sint,
|
||||
vk::Format::eR8G8B8A8Uscaled,
|
||||
vk::Format::eR16Unorm,
|
||||
vk::Format::eR16G16B16A16Unorm,
|
||||
vk::Format::eD32SfloatS8Uint,
|
||||
vk::Format::eD32Sfloat,
|
||||
vk::Format::eD16Unorm,
|
||||
vk::Format::eD16UnormS8Uint,
|
||||
};
|
||||
return formats;
|
||||
}
|
||||
|
||||
vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat num_format) {
|
||||
|
||||
if (data_format == AmdGpu::DataFormat::Format32_32_32_32 &&
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "video_core/amdgpu/liverpool.h"
|
||||
#include "video_core/amdgpu/pixel_format.h"
|
||||
#include "video_core/amdgpu/resource.h"
|
||||
|
@ -38,6 +39,8 @@ vk::SamplerMipmapMode MipFilter(AmdGpu::MipFilter filter);
|
|||
|
||||
vk::BorderColor BorderColor(AmdGpu::BorderColor color);
|
||||
|
||||
const std::vector<vk::Format>& GetAllFormats();
|
||||
|
||||
vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat num_format);
|
||||
|
||||
vk::Format AdjustColorBufferFormat(vk::Format base_format,
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "common/assert.h"
|
||||
#include "sdl_window.h"
|
||||
#include "video_core/renderer_vulkan/liverpool_to_vk.h"
|
||||
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||
#include "video_core/renderer_vulkan/vk_platform.h"
|
||||
|
||||
|
@ -28,6 +29,15 @@ std::vector<std::string> GetSupportedExtensions(vk::PhysicalDevice physical) {
|
|||
return supported_extensions;
|
||||
}
|
||||
|
||||
std::unordered_map<vk::Format, vk::FormatProperties> GetFormatProperties(
|
||||
vk::PhysicalDevice physical) {
|
||||
std::unordered_map<vk::Format, vk::FormatProperties> format_properties;
|
||||
for (const auto& format : LiverpoolToVK::GetAllFormats()) {
|
||||
format_properties.emplace(format, physical.getFormatProperties(format));
|
||||
}
|
||||
return format_properties;
|
||||
}
|
||||
|
||||
std::string GetReadableVersion(u32 version) {
|
||||
return fmt::format("{}.{}.{}", VK_VERSION_MAJOR(version), VK_VERSION_MINOR(version),
|
||||
VK_VERSION_PATCH(version));
|
||||
|
@ -93,6 +103,7 @@ Instance::Instance(Frontend::WindowSDL& window, s32 physical_device_index,
|
|||
}
|
||||
|
||||
available_extensions = GetSupportedExtensions(physical_device);
|
||||
format_properties = GetFormatProperties(physical_device);
|
||||
properties = physical_device.getProperties();
|
||||
CollectDeviceParameters();
|
||||
ASSERT_MSG(properties.apiVersion >= TargetVulkanApiVersion,
|
||||
|
@ -102,6 +113,22 @@ Instance::Instance(Frontend::WindowSDL& window, s32 physical_device_index,
|
|||
|
||||
CreateDevice();
|
||||
CollectToolingInfo();
|
||||
|
||||
// Check and log format support details.
|
||||
for (const auto& key : format_properties | std::views::keys) {
|
||||
const auto format = key;
|
||||
if (!IsFormatSupported(format)) {
|
||||
const auto alternative = GetAlternativeFormat(format);
|
||||
if (IsFormatSupported(alternative)) {
|
||||
LOG_WARNING(Render_Vulkan, "Format {} is not supported, falling back to {}",
|
||||
vk::to_string(format), vk::to_string(alternative));
|
||||
} else {
|
||||
LOG_ERROR(Render_Vulkan,
|
||||
"Format {} is not supported and no suitable alternative is supported.",
|
||||
vk::to_string(format));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Instance::~Instance() {
|
||||
|
@ -303,7 +330,7 @@ bool Instance::CreateDevice() {
|
|||
vk::TimeDomainEXT::eClockMonotonicRaw) != time_domains.cend();
|
||||
#else
|
||||
// Tracy limitation means only Windows and Linux can use host time domain.
|
||||
// See https://github.com/shadps4-emu/tracy/blob/c6d779d78508514102fbe1b8eb28bda10d95bb2a/public/tracy/TracyVulkan.hpp#L384-L389
|
||||
// https://github.com/shadps4-emu/tracy/blob/c6d779d78508514102fbe1b8eb28bda10d95bb2a/public/tracy/TracyVulkan.hpp#L384-L389
|
||||
const bool has_host_time_domain = false;
|
||||
#endif
|
||||
if (has_host_time_domain) {
|
||||
|
@ -377,4 +404,52 @@ void Instance::CollectToolingInfo() {
|
|||
}
|
||||
}
|
||||
|
||||
bool Instance::IsFormatSupported(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::FormatFeatureFlags optimal_flags = vk::FormatFeatureFlagBits::eTransferSrc |
|
||||
vk::FormatFeatureFlagBits::eTransferDst |
|
||||
vk::FormatFeatureFlagBits::eSampledImage;
|
||||
return (it->second.optimalTilingFeatures & optimal_flags) == optimal_flags;
|
||||
}
|
||||
|
||||
vk::Format Instance::GetAlternativeFormat(const vk::Format format) const {
|
||||
if (format == vk::Format::eB5G6R5UnormPack16) {
|
||||
return vk::Format::eR5G6B5UnormPack16;
|
||||
}
|
||||
return format;
|
||||
}
|
||||
|
||||
vk::Format Instance::GetSupportedFormat(const vk::Format format) const {
|
||||
if (IsFormatSupported(format)) [[likely]] {
|
||||
return format;
|
||||
}
|
||||
const vk::Format alternative = GetAlternativeFormat(format);
|
||||
if (IsFormatSupported(alternative)) [[likely]] {
|
||||
return alternative;
|
||||
}
|
||||
return format;
|
||||
}
|
||||
|
||||
vk::ComponentMapping Instance::GetSupportedComponentSwizzle(vk::Format format,
|
||||
vk::ComponentMapping swizzle) const {
|
||||
if (IsFormatSupported(format)) [[likely]] {
|
||||
return swizzle;
|
||||
}
|
||||
|
||||
vk::ComponentMapping supported_swizzle = swizzle;
|
||||
if (format == vk::Format::eB5G6R5UnormPack16) {
|
||||
// B5G6R5 -> R5G6B5
|
||||
std::swap(supported_swizzle.r, supported_swizzle.b);
|
||||
}
|
||||
return supported_swizzle;
|
||||
}
|
||||
|
||||
} // namespace Vulkan
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <span>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "video_core/renderer_vulkan/vk_platform.h"
|
||||
|
||||
|
@ -34,6 +35,13 @@ public:
|
|||
/// Returns a formatted string for the driver version
|
||||
std::string GetDriverVersionName();
|
||||
|
||||
/// Gets a compatibility format if the format is not supported.
|
||||
[[nodiscard]] vk::Format GetSupportedFormat(vk::Format format) const;
|
||||
|
||||
/// Re-orders a component swizzle for format compatibility, if needed.
|
||||
[[nodiscard]] vk::ComponentMapping GetSupportedComponentSwizzle(
|
||||
vk::Format format, vk::ComponentMapping swizzle) const;
|
||||
|
||||
/// Returns the Vulkan instance
|
||||
vk::Instance GetInstance() const {
|
||||
return *instance;
|
||||
|
@ -211,6 +219,12 @@ private:
|
|||
void CollectDeviceParameters();
|
||||
void CollectToolingInfo();
|
||||
|
||||
/// Determines if a format is supported.
|
||||
[[nodiscard]] bool IsFormatSupported(vk::Format format) const;
|
||||
|
||||
/// Gets a commonly available alternative for an unsupported pixel format.
|
||||
vk::Format GetAlternativeFormat(const vk::Format format) const;
|
||||
|
||||
private:
|
||||
vk::DynamicLoader dl{VULKAN_LIBRARY_NAME};
|
||||
vk::UniqueInstance instance;
|
||||
|
@ -226,6 +240,7 @@ private:
|
|||
vk::Queue graphics_queue;
|
||||
std::vector<vk::PhysicalDevice> physical_devices;
|
||||
std::vector<std::string> available_extensions;
|
||||
std::unordered_map<vk::Format, vk::FormatProperties> format_properties;
|
||||
TracyVkCtx profiler_context{};
|
||||
u32 queue_family_index{0};
|
||||
bool image_view_reinterpretation{true};
|
||||
|
|
|
@ -142,7 +142,7 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_,
|
|||
const vk::ImageCreateInfo image_ci = {
|
||||
.flags = flags,
|
||||
.imageType = info.type,
|
||||
.format = info.pixel_format,
|
||||
.format = instance->GetSupportedFormat(info.pixel_format),
|
||||
.extent{
|
||||
.width = info.size.width,
|
||||
.height = info.size.height,
|
||||
|
|
|
@ -89,8 +89,8 @@ ImageView::ImageView(const Vulkan::Instance& instance, const ImageViewInfo& info
|
|||
.pNext = usage_override ? &usage_ci : nullptr,
|
||||
.image = image.image,
|
||||
.viewType = info.type,
|
||||
.format = format,
|
||||
.components = info.mapping,
|
||||
.format = instance.GetSupportedFormat(format),
|
||||
.components = instance.GetSupportedComponentSwizzle(format, info.mapping),
|
||||
.subresourceRange{
|
||||
.aspectMask = aspect,
|
||||
.baseMipLevel = 0U,
|
||||
|
|
Loading…
Reference in New Issue