From 612f340292129e1c9796a4d1d85fdbf234bb0665 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Thu, 19 Jun 2025 23:36:50 +0200 Subject: [PATCH] Log improper image format uses (#3105) --- src/video_core/renderer_vulkan/vk_instance.h | 6 ++--- .../renderer_vulkan/vk_pipeline_cache.cpp | 9 +++++++- src/video_core/texture_cache/image.cpp | 23 +++++++++++++++---- src/video_core/texture_cache/image_view.cpp | 23 +++++++++++++++++++ 4 files changed, 52 insertions(+), 9 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index c687e6f67..fb13a696a 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -324,6 +324,9 @@ public: return driver_id != vk::DriverId::eMoltenvk; } + /// Determines if a format is supported for a set of feature flags. + [[nodiscard]] bool IsFormatSupported(vk::Format format, vk::FormatFeatureFlags2 flags) const; + private: /// Creates the logical device opportunistically enabling extensions bool CreateDevice(); @@ -338,9 +341,6 @@ private: /// Gets the supported feature flags for a format. [[nodiscard]] vk::FormatFeatureFlags2 GetFormatFeatureFlags(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; vk::PhysicalDevice physical_device; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 2c3f4ba2f..6b1d7e66c 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -346,8 +346,15 @@ bool PipelineCache::RefreshGraphicsKey() { col_buf.GetDataFmt() == AmdGpu::DataFormat::Format8_8 || col_buf.GetDataFmt() == AmdGpu::DataFormat::Format8_8_8_8); - key.color_formats[remapped_cb] = + const auto format = LiverpoolToVK::SurfaceFormat(col_buf.GetDataFmt(), col_buf.GetNumberFmt()); + key.color_formats[remapped_cb] = format; + if (!instance.IsFormatSupported(format, vk::FormatFeatureFlagBits2::eColorAttachment)) { + LOG_WARNING(Render_Vulkan, + "color buffer format {} does not support COLOR_ATTACHMENT_BIT", + vk::to_string(format)); + } + key.color_buffers[remapped_cb] = Shader::PsColorBuffer{ .num_format = col_buf.GetNumberFmt(), .num_conversion = col_buf.GetNumberConversion(), diff --git a/src/video_core/texture_cache/image.cpp b/src/video_core/texture_cache/image.cpp index ab9111e6b..7b8ff4403 100644 --- a/src/video_core/texture_cache/image.cpp +++ b/src/video_core/texture_cache/image.cpp @@ -130,11 +130,24 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_, constexpr auto tiling = vk::ImageTiling::eOptimal; const auto supported_format = instance->GetSupportedFormat(info.pixel_format, format_features); - const auto properties = instance->GetPhysicalDevice().getImageFormatProperties( - supported_format, info.type, tiling, usage_flags, flags); - const auto supported_samples = properties.result == vk::Result::eSuccess - ? properties.value.sampleCounts - : vk::SampleCountFlagBits::e1; + const vk::PhysicalDeviceImageFormatInfo2 format_info{ + .format = supported_format, + .type = info.type, + .tiling = tiling, + .usage = usage_flags, + .flags = flags, + }; + const auto image_format_properties = + instance->GetPhysicalDevice().getImageFormatProperties2(format_info); + if (image_format_properties.result == vk::Result::eErrorFormatNotSupported) { + LOG_ERROR(Render_Vulkan, "image format {} type {} is not supported (flags {}, usage {})", + vk::to_string(supported_format), vk::to_string(info.type), + vk::to_string(format_info.flags), vk::to_string(format_info.usage)); + } + const auto supported_samples = + image_format_properties.result == vk::Result::eSuccess + ? image_format_properties.value.imageFormatProperties.sampleCounts + : vk::SampleCountFlagBits::e1; const vk::ImageCreateInfo image_ci = { .flags = flags, diff --git a/src/video_core/texture_cache/image_view.cpp b/src/video_core/texture_cache/image_view.cpp index 7befb5259..2e162ce83 100644 --- a/src/video_core/texture_cache/image_view.cpp +++ b/src/video_core/texture_cache/image_view.cpp @@ -29,6 +29,24 @@ vk::ImageViewType ConvertImageViewType(AmdGpu::ImageType type) { } } +bool IsViewTypeCompatible(vk::ImageViewType view_type, vk::ImageType image_type) { + switch (view_type) { + case vk::ImageViewType::e1D: + case vk::ImageViewType::e1DArray: + return image_type == vk::ImageType::e1D; + case vk::ImageViewType::e2D: + case vk::ImageViewType::e2DArray: + return image_type == vk::ImageType::e2D || image_type == vk::ImageType::e3D; + case vk::ImageViewType::eCube: + case vk::ImageViewType::eCubeArray: + return image_type == vk::ImageType::e2D; + case vk::ImageViewType::e3D: + return image_type == vk::ImageType::e3D; + default: + UNREACHABLE(); + } +} + ImageViewInfo::ImageViewInfo(const AmdGpu::Image& image, const Shader::ImageResource& desc) noexcept : is_storage{desc.is_written} { const auto dfmt = image.GetDataFmt(); @@ -106,6 +124,11 @@ ImageView::ImageView(const Vulkan::Instance& instance, const ImageViewInfo& info .layerCount = info.range.extent.layers, }, }; + if (!IsViewTypeCompatible(image_view_ci.viewType, image.info.type)) { + LOG_ERROR(Render_Vulkan, "image view type {} is incompatible with image type {}", + vk::to_string(image_view_ci.viewType), vk::to_string(image.info.type)); + } + auto [view_result, view] = instance.GetDevice().createImageViewUnique(image_view_ci); ASSERT_MSG(view_result == vk::Result::eSuccess, "Failed to create image view: {}", vk::to_string(view_result));