diff options
| author | ReinUsesLisp <reinuseslisp@airmail.cc> | 2021-01-15 21:37:17 -0300 | 
|---|---|---|
| committer | ReinUsesLisp <reinuseslisp@airmail.cc> | 2021-01-24 18:16:43 -0300 | 
| commit | 6b00443bc1c8379794f82f07636bed05499c2779 (patch) | |
| tree | 17b6306c2449b0e3d6a106d80a8835d476e4c602 | |
| parent | 8be9e5b48b5d8ef1c52fab16668dd479ac799f00 (diff) | |
vk_texture_cache: Support image store on sRGB images with VkImageViewUsageCreateInfo
Vulkan 1.0 didn't support creating sRGB image views on an ABGR8 VkImage
with storage usage bits. VK_KHR_maintenance2 addressed this allowing to
reduce the usage bits on a VkImageView.
To allow image store on non-sRGB image views when the VkImage is created
with sRGB, always create VkImages without sRGB and add the sRGB format
on the view.
| -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_  } // namespace Sampler  namespace { - -enum : u32 { Attachable = 1, Storage = 2 }; +constexpr u32 Attachable = 1 << 0; +constexpr u32 Storage = 1 << 1;  struct FormatTuple {      VkFormat format; ///< Vulkan format @@ -222,22 +222,27 @@ constexpr bool IsZetaFormat(PixelFormat pixel_format) {  } // Anonymous namespace -FormatInfo SurfaceFormat(const Device& device, FormatType format_type, PixelFormat pixel_format) { -    ASSERT(static_cast<std::size_t>(pixel_format) < std::size(tex_format_tuples)); - -    auto tuple = tex_format_tuples[static_cast<std::size_t>(pixel_format)]; +FormatInfo SurfaceFormat(const Device& device, FormatType format_type, bool with_srgb, +                         PixelFormat pixel_format) { +    ASSERT(static_cast<size_t>(pixel_format) < std::size(tex_format_tuples)); +    FormatTuple tuple = tex_format_tuples[static_cast<size_t>(pixel_format)];      if (tuple.format == VK_FORMAT_UNDEFINED) {          UNIMPLEMENTED_MSG("Unimplemented texture format with pixel format={}", pixel_format); -        return {VK_FORMAT_A8B8G8R8_UNORM_PACK32, true, true}; +        return FormatInfo{VK_FORMAT_A8B8G8R8_UNORM_PACK32, true, true};      }      // Use A8B8G8R8_UNORM on hardware that doesn't support ASTC natively      if (!device.IsOptimalAstcSupported() && VideoCore::Surface::IsPixelFormatASTC(pixel_format)) { -        const bool is_srgb = VideoCore::Surface::IsPixelFormatSRGB(pixel_format); -        tuple.format = is_srgb ? VK_FORMAT_A8B8G8R8_SRGB_PACK32 : VK_FORMAT_A8B8G8R8_UNORM_PACK32; +        const bool is_srgb = with_srgb && VideoCore::Surface::IsPixelFormatSRGB(pixel_format); +        if (is_srgb) { +            tuple.format = VK_FORMAT_A8B8G8R8_SRGB_PACK32; +        } else { +            tuple.format = VK_FORMAT_A8B8G8R8_UNORM_PACK32; +            tuple.usage |= Storage; +        }      } -    const bool attachable = tuple.usage & Attachable; -    const bool storage = tuple.usage & Storage; +    const bool attachable = (tuple.usage & Attachable) != 0; +    const bool storage = (tuple.usage & Storage) != 0;      VkFormatFeatureFlags usage{};      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 {      bool storage;  }; -FormatInfo SurfaceFormat(const Device& device, FormatType format_type, PixelFormat pixel_format); +/** + * Returns format properties supported in the host + * @param device       Host device + * @param format_type  Type of image the buffer will use + * @param with_srgb    True when the format can be sRGB when converted to another format (ASTC) + * @param pixel_format Guest pixel format to describe + */ +[[nodiscard]] FormatInfo SurfaceFormat(const Device& device, FormatType format_type, bool with_srgb, +                                       PixelFormat pixel_format);  VkShaderStageFlagBits ShaderStage(Tegra::Engines::ShaderType stage); diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index bd11de012..0f9e93e48 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) {      }  } -[[nodiscard]] VkImageCreateInfo MakeImageCreateInfo(const Device& device, const ImageInfo& info) { -    const auto format_info = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, info.format); -    VkImageCreateFlags flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; -    if (info.type == ImageType::e2D && info.resources.layers >= 6 && -        info.size.width == info.size.height) { -        flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; -    } -    if (info.type == ImageType::e3D) { -        flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT; -    } +[[nodiscard]] VkImageUsageFlags ImageUsageFlags(const MaxwellToVK::FormatInfo& info, +                                                PixelFormat format) {      VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |                                VK_IMAGE_USAGE_SAMPLED_BIT; -    if (format_info.attachable) { -        switch (VideoCore::Surface::GetFormatType(info.format)) { +    if (info.attachable) { +        switch (VideoCore::Surface::GetFormatType(format)) {          case VideoCore::Surface::SurfaceType::ColorTexture:              usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;              break; @@ -120,9 +112,33 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {              UNREACHABLE_MSG("Invalid surface type");          }      } -    if (format_info.storage) { +    if (info.storage) {          usage |= VK_IMAGE_USAGE_STORAGE_BIT;      } +    return usage; +} + +/// Returns the preferred format for a VkImage +[[nodiscard]] PixelFormat StorageFormat(PixelFormat format) { +    switch (format) { +    case PixelFormat::A8B8G8R8_SRGB: +        return PixelFormat::A8B8G8R8_UNORM; +    default: +        return format; +    } +} + +[[nodiscard]] VkImageCreateInfo MakeImageCreateInfo(const Device& device, const ImageInfo& info) { +    const PixelFormat format = StorageFormat(info.format); +    const auto format_info = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, false, format); +    VkImageCreateFlags flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; +    if (info.type == ImageType::e2D && info.resources.layers >= 6 && +        info.size.width == info.size.height) { +        flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; +    } +    if (info.type == ImageType::e3D) { +        flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT; +    }      const auto [samples_x, samples_y] = VideoCommon::SamplesLog2(info.num_samples);      return VkImageCreateInfo{          .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, @@ -130,17 +146,16 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {          .flags = flags,          .imageType = ConvertImageType(info.type),          .format = format_info.format, -        .extent = -            { -                .width = info.size.width >> samples_x, -                .height = info.size.height >> samples_y, -                .depth = info.size.depth, -            }, +        .extent{ +            .width = info.size.width >> samples_x, +            .height = info.size.height >> samples_y, +            .depth = info.size.depth, +        },          .mipLevels = static_cast<u32>(info.resources.levels),          .arrayLayers = static_cast<u32>(info.resources.layers),          .samples = ConvertSampleCount(info.num_samples),          .tiling = VK_IMAGE_TILING_OPTIMAL, -        .usage = usage, +        .usage = ImageUsageFlags(format_info, format),          .sharingMode = VK_SHARING_MODE_EXCLUSIVE,          .queueFamilyIndexCount = 0,          .pQueueFamilyIndices = nullptr, @@ -209,10 +224,11 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {  [[nodiscard]] VkAttachmentDescription AttachmentDescription(const Device& device,                                                              const ImageView* image_view) { -    const auto pixel_format = image_view->format; +    using MaxwellToVK::SurfaceFormat; +    const PixelFormat pixel_format = image_view->format;      return VkAttachmentDescription{          .flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT, -        .format = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, pixel_format).format, +        .format = SurfaceFormat(device, FormatType::Optimal, true, pixel_format).format,          .samples = image_view->Samples(),          .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,          .storeOp = VK_ATTACHMENT_STORE_OP_STORE, @@ -860,11 +876,16 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI              std::ranges::transform(swizzle, swizzle.begin(), ConvertGreenRed);          }      } -    const VkFormat vk_format = -        MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, format).format; +    const auto format_info = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, format); +    const VkFormat vk_format = format_info.format; +    const VkImageViewUsageCreateInfo image_view_usage{ +        .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, +        .pNext = nullptr, +        .usage = ImageUsageFlags(format_info, format), +    };      const VkImageViewCreateInfo create_info{          .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, -        .pNext = nullptr, +        .pNext = &image_view_usage,          .flags = 0,          .image = image.Handle(),          .viewType = VkImageViewType{}, @@ -954,7 +975,7 @@ vk::ImageView ImageView::MakeDepthStencilView(VkImageAspectFlags aspect_mask) {          .flags = 0,          .image = image_handle,          .viewType = ImageViewType(type), -        .format = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, format).format, +        .format = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, format).format,          .components{              .r = VK_COMPONENT_SWIZZLE_IDENTITY,              .g = VK_COMPONENT_SWIZZLE_IDENTITY, | 
