diff options
| author | 2021-01-24 18:44:51 -0300 | |
|---|---|---|
| committer | 2021-01-24 18:44:51 -0300 | |
| commit | b769b1be26958eb89b2de938b95c48d390bd1fd8 (patch) | |
| tree | 900612a33a52d0ee49294547503b873c9862f7fe | |
| parent | Merge pull request #5151 from comex/xx-vfs (diff) | |
| parent | vk_texture_cache: Support image store on sRGB images with VkImageViewUsageCre... (diff) | |
| download | yuzu-b769b1be26958eb89b2de938b95c48d390bd1fd8.tar.gz yuzu-b769b1be26958eb89b2de938b95c48d390bd1fd8.tar.xz yuzu-b769b1be26958eb89b2de938b95c48d390bd1fd8.zip | |
Merge pull request #5363 from ReinUsesLisp/vk-image-usage
vk_texture_cache: Support image store on sRGB images with VkImageViewUsageCreateInfo
| -rw-r--r-- | src/video_core/renderer_vulkan/maxwell_to_vk.cpp | 27 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/maxwell_to_vk.h | 10 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.cpp | 73 |
3 files changed, 72 insertions, 38 deletions
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp index ca7c2c579..b4473f194 100644 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp | |||
| @@ -110,8 +110,8 @@ VkCompareOp DepthCompareFunction(Tegra::Texture::DepthCompareFunc depth_compare_ | |||
| 110 | } // namespace Sampler | 110 | } // namespace Sampler |
| 111 | 111 | ||
| 112 | namespace { | 112 | namespace { |
| 113 | 113 | constexpr u32 Attachable = 1 << 0; | |
| 114 | enum : u32 { Attachable = 1, Storage = 2 }; | 114 | constexpr u32 Storage = 1 << 1; |
| 115 | 115 | ||
| 116 | struct FormatTuple { | 116 | struct FormatTuple { |
| 117 | VkFormat format; ///< Vulkan format | 117 | VkFormat format; ///< Vulkan format |
| @@ -222,22 +222,27 @@ constexpr bool IsZetaFormat(PixelFormat pixel_format) { | |||
| 222 | 222 | ||
| 223 | } // Anonymous namespace | 223 | } // Anonymous namespace |
| 224 | 224 | ||
| 225 | FormatInfo SurfaceFormat(const Device& device, FormatType format_type, PixelFormat pixel_format) { | 225 | FormatInfo SurfaceFormat(const Device& device, FormatType format_type, bool with_srgb, |
| 226 | ASSERT(static_cast<std::size_t>(pixel_format) < std::size(tex_format_tuples)); | 226 | PixelFormat pixel_format) { |
| 227 | 227 | ASSERT(static_cast<size_t>(pixel_format) < std::size(tex_format_tuples)); | |
| 228 | auto tuple = tex_format_tuples[static_cast<std::size_t>(pixel_format)]; | 228 | FormatTuple tuple = tex_format_tuples[static_cast<size_t>(pixel_format)]; |
| 229 | if (tuple.format == VK_FORMAT_UNDEFINED) { | 229 | if (tuple.format == VK_FORMAT_UNDEFINED) { |
| 230 | UNIMPLEMENTED_MSG("Unimplemented texture format with pixel format={}", pixel_format); | 230 | UNIMPLEMENTED_MSG("Unimplemented texture format with pixel format={}", pixel_format); |
| 231 | return {VK_FORMAT_A8B8G8R8_UNORM_PACK32, true, true}; | 231 | return FormatInfo{VK_FORMAT_A8B8G8R8_UNORM_PACK32, true, true}; |
| 232 | } | 232 | } |
| 233 | 233 | ||
| 234 | // Use A8B8G8R8_UNORM on hardware that doesn't support ASTC natively | 234 | // Use A8B8G8R8_UNORM on hardware that doesn't support ASTC natively |
| 235 | if (!device.IsOptimalAstcSupported() && VideoCore::Surface::IsPixelFormatASTC(pixel_format)) { | 235 | if (!device.IsOptimalAstcSupported() && VideoCore::Surface::IsPixelFormatASTC(pixel_format)) { |
| 236 | const bool is_srgb = VideoCore::Surface::IsPixelFormatSRGB(pixel_format); | 236 | const bool is_srgb = with_srgb && VideoCore::Surface::IsPixelFormatSRGB(pixel_format); |
| 237 | tuple.format = is_srgb ? VK_FORMAT_A8B8G8R8_SRGB_PACK32 : VK_FORMAT_A8B8G8R8_UNORM_PACK32; | 237 | if (is_srgb) { |
| 238 | tuple.format = VK_FORMAT_A8B8G8R8_SRGB_PACK32; | ||
| 239 | } else { | ||
| 240 | tuple.format = VK_FORMAT_A8B8G8R8_UNORM_PACK32; | ||
| 241 | tuple.usage |= Storage; | ||
| 242 | } | ||
| 238 | } | 243 | } |
| 239 | const bool attachable = tuple.usage & Attachable; | 244 | const bool attachable = (tuple.usage & Attachable) != 0; |
| 240 | const bool storage = tuple.usage & Storage; | 245 | const bool storage = (tuple.usage & Storage) != 0; |
| 241 | 246 | ||
| 242 | VkFormatFeatureFlags usage{}; | 247 | VkFormatFeatureFlags usage{}; |
| 243 | switch (format_type) { | 248 | switch (format_type) { |
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.h b/src/video_core/renderer_vulkan/maxwell_to_vk.h index 537969840..e59e6b6e2 100644 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.h +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.h | |||
| @@ -35,7 +35,15 @@ struct FormatInfo { | |||
| 35 | bool storage; | 35 | bool storage; |
| 36 | }; | 36 | }; |
| 37 | 37 | ||
| 38 | FormatInfo SurfaceFormat(const Device& device, FormatType format_type, PixelFormat pixel_format); | 38 | /** |
| 39 | * Returns format properties supported in the host | ||
| 40 | * @param device Host device | ||
| 41 | * @param format_type Type of image the buffer will use | ||
| 42 | * @param with_srgb True when the format can be sRGB when converted to another format (ASTC) | ||
| 43 | * @param pixel_format Guest pixel format to describe | ||
| 44 | */ | ||
| 45 | [[nodiscard]] FormatInfo SurfaceFormat(const Device& device, FormatType format_type, bool with_srgb, | ||
| 46 | PixelFormat pixel_format); | ||
| 39 | 47 | ||
| 40 | VkShaderStageFlagBits ShaderStage(Tegra::Engines::ShaderType stage); | 48 | VkShaderStageFlagBits ShaderStage(Tegra::Engines::ShaderType stage); |
| 41 | 49 | ||
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index ab14922d7..aa7c5d7c6 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -95,20 +95,12 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { | |||
| 95 | } | 95 | } |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | [[nodiscard]] VkImageCreateInfo MakeImageCreateInfo(const Device& device, const ImageInfo& info) { | 98 | [[nodiscard]] VkImageUsageFlags ImageUsageFlags(const MaxwellToVK::FormatInfo& info, |
| 99 | const auto format_info = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, info.format); | 99 | PixelFormat format) { |
| 100 | VkImageCreateFlags flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; | ||
| 101 | if (info.type == ImageType::e2D && info.resources.layers >= 6 && | ||
| 102 | info.size.width == info.size.height) { | ||
| 103 | flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; | ||
| 104 | } | ||
| 105 | if (info.type == ImageType::e3D) { | ||
| 106 | flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT; | ||
| 107 | } | ||
| 108 | VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | | 100 | VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | |
| 109 | VK_IMAGE_USAGE_SAMPLED_BIT; | 101 | VK_IMAGE_USAGE_SAMPLED_BIT; |
| 110 | if (format_info.attachable) { | 102 | if (info.attachable) { |
| 111 | switch (VideoCore::Surface::GetFormatType(info.format)) { | 103 | switch (VideoCore::Surface::GetFormatType(format)) { |
| 112 | case VideoCore::Surface::SurfaceType::ColorTexture: | 104 | case VideoCore::Surface::SurfaceType::ColorTexture: |
| 113 | usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; | 105 | usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; |
| 114 | break; | 106 | break; |
| @@ -120,9 +112,33 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { | |||
| 120 | UNREACHABLE_MSG("Invalid surface type"); | 112 | UNREACHABLE_MSG("Invalid surface type"); |
| 121 | } | 113 | } |
| 122 | } | 114 | } |
| 123 | if (format_info.storage) { | 115 | if (info.storage) { |
| 124 | usage |= VK_IMAGE_USAGE_STORAGE_BIT; | 116 | usage |= VK_IMAGE_USAGE_STORAGE_BIT; |
| 125 | } | 117 | } |
| 118 | return usage; | ||
| 119 | } | ||
| 120 | |||
| 121 | /// Returns the preferred format for a VkImage | ||
| 122 | [[nodiscard]] PixelFormat StorageFormat(PixelFormat format) { | ||
| 123 | switch (format) { | ||
| 124 | case PixelFormat::A8B8G8R8_SRGB: | ||
| 125 | return PixelFormat::A8B8G8R8_UNORM; | ||
| 126 | default: | ||
| 127 | return format; | ||
| 128 | } | ||
| 129 | } | ||
| 130 | |||
| 131 | [[nodiscard]] VkImageCreateInfo MakeImageCreateInfo(const Device& device, const ImageInfo& info) { | ||
| 132 | const PixelFormat format = StorageFormat(info.format); | ||
| 133 | const auto format_info = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, false, format); | ||
| 134 | VkImageCreateFlags flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; | ||
| 135 | if (info.type == ImageType::e2D && info.resources.layers >= 6 && | ||
| 136 | info.size.width == info.size.height) { | ||
| 137 | flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; | ||
| 138 | } | ||
| 139 | if (info.type == ImageType::e3D) { | ||
| 140 | flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT; | ||
| 141 | } | ||
| 126 | const auto [samples_x, samples_y] = VideoCommon::SamplesLog2(info.num_samples); | 142 | const auto [samples_x, samples_y] = VideoCommon::SamplesLog2(info.num_samples); |
| 127 | return VkImageCreateInfo{ | 143 | return VkImageCreateInfo{ |
| 128 | .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, | 144 | .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, |
| @@ -130,17 +146,16 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { | |||
| 130 | .flags = flags, | 146 | .flags = flags, |
| 131 | .imageType = ConvertImageType(info.type), | 147 | .imageType = ConvertImageType(info.type), |
| 132 | .format = format_info.format, | 148 | .format = format_info.format, |
| 133 | .extent = | 149 | .extent{ |
| 134 | { | 150 | .width = info.size.width >> samples_x, |
| 135 | .width = info.size.width >> samples_x, | 151 | .height = info.size.height >> samples_y, |
| 136 | .height = info.size.height >> samples_y, | 152 | .depth = info.size.depth, |
| 137 | .depth = info.size.depth, | 153 | }, |
| 138 | }, | ||
| 139 | .mipLevels = static_cast<u32>(info.resources.levels), | 154 | .mipLevels = static_cast<u32>(info.resources.levels), |
| 140 | .arrayLayers = static_cast<u32>(info.resources.layers), | 155 | .arrayLayers = static_cast<u32>(info.resources.layers), |
| 141 | .samples = ConvertSampleCount(info.num_samples), | 156 | .samples = ConvertSampleCount(info.num_samples), |
| 142 | .tiling = VK_IMAGE_TILING_OPTIMAL, | 157 | .tiling = VK_IMAGE_TILING_OPTIMAL, |
| 143 | .usage = usage, | 158 | .usage = ImageUsageFlags(format_info, format), |
| 144 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | 159 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, |
| 145 | .queueFamilyIndexCount = 0, | 160 | .queueFamilyIndexCount = 0, |
| 146 | .pQueueFamilyIndices = nullptr, | 161 | .pQueueFamilyIndices = nullptr, |
| @@ -209,10 +224,11 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { | |||
| 209 | 224 | ||
| 210 | [[nodiscard]] VkAttachmentDescription AttachmentDescription(const Device& device, | 225 | [[nodiscard]] VkAttachmentDescription AttachmentDescription(const Device& device, |
| 211 | const ImageView* image_view) { | 226 | const ImageView* image_view) { |
| 212 | const auto pixel_format = image_view->format; | 227 | using MaxwellToVK::SurfaceFormat; |
| 228 | const PixelFormat pixel_format = image_view->format; | ||
| 213 | return VkAttachmentDescription{ | 229 | return VkAttachmentDescription{ |
| 214 | .flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT, | 230 | .flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT, |
| 215 | .format = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, pixel_format).format, | 231 | .format = SurfaceFormat(device, FormatType::Optimal, true, pixel_format).format, |
| 216 | .samples = image_view->Samples(), | 232 | .samples = image_view->Samples(), |
| 217 | .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, | 233 | .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, |
| 218 | .storeOp = VK_ATTACHMENT_STORE_OP_STORE, | 234 | .storeOp = VK_ATTACHMENT_STORE_OP_STORE, |
| @@ -868,11 +884,16 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI | |||
| 868 | std::ranges::transform(swizzle, swizzle.begin(), ConvertGreenRed); | 884 | std::ranges::transform(swizzle, swizzle.begin(), ConvertGreenRed); |
| 869 | } | 885 | } |
| 870 | } | 886 | } |
| 871 | const VkFormat vk_format = | 887 | const auto format_info = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, format); |
| 872 | MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, format).format; | 888 | const VkFormat vk_format = format_info.format; |
| 889 | const VkImageViewUsageCreateInfo image_view_usage{ | ||
| 890 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, | ||
| 891 | .pNext = nullptr, | ||
| 892 | .usage = ImageUsageFlags(format_info, format), | ||
| 893 | }; | ||
| 873 | const VkImageViewCreateInfo create_info{ | 894 | const VkImageViewCreateInfo create_info{ |
| 874 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, | 895 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, |
| 875 | .pNext = nullptr, | 896 | .pNext = &image_view_usage, |
| 876 | .flags = 0, | 897 | .flags = 0, |
| 877 | .image = image.Handle(), | 898 | .image = image.Handle(), |
| 878 | .viewType = VkImageViewType{}, | 899 | .viewType = VkImageViewType{}, |
| @@ -962,7 +983,7 @@ vk::ImageView ImageView::MakeDepthStencilView(VkImageAspectFlags aspect_mask) { | |||
| 962 | .flags = 0, | 983 | .flags = 0, |
| 963 | .image = image_handle, | 984 | .image = image_handle, |
| 964 | .viewType = ImageViewType(type), | 985 | .viewType = ImageViewType(type), |
| 965 | .format = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, format).format, | 986 | .format = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, format).format, |
| 966 | .components{ | 987 | .components{ |
| 967 | .r = VK_COMPONENT_SWIZZLE_IDENTITY, | 988 | .r = VK_COMPONENT_SWIZZLE_IDENTITY, |
| 968 | .g = VK_COMPONENT_SWIZZLE_IDENTITY, | 989 | .g = VK_COMPONENT_SWIZZLE_IDENTITY, |