From b02ec385b217486f3e204a5f5858fbc7a3d36ccc Mon Sep 17 00:00:00 2001 From: psucien Date: Sat, 15 Jun 2024 23:16:53 +0200 Subject: [PATCH] video_out: proper sRGB output workflow --- .../renderer_vulkan/liverpool_to_vk.cpp | 39 +++++++++++++------ .../renderer_vulkan/liverpool_to_vk.h | 7 ++-- .../renderer_vulkan/renderer_vulkan.h | 9 +++++ .../renderer_vulkan/vk_pipeline_cache.cpp | 10 ++++- src/video_core/texture_cache/image.cpp | 1 + src/video_core/texture_cache/image.h | 1 + src/video_core/texture_cache/image_view.cpp | 9 +++-- src/video_core/texture_cache/image_view.h | 3 +- .../texture_cache/texture_cache.cpp | 2 +- 9 files changed, 60 insertions(+), 21 deletions(-) diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp index 9a80f9ca..feb39a30 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp @@ -276,12 +276,7 @@ vk::BorderColor BorderColor(AmdGpu::BorderColor color) { } } -vk::Format SurfaceFormat( - AmdGpu::DataFormat data_format, AmdGpu::NumberFormat num_format, - Liverpool::ColorBuffer::SwapMode comp_swap /*= Liverpool::ColorBuffer::SwapMode::Standard*/) { - ASSERT_MSG(comp_swap == Liverpool::ColorBuffer::SwapMode::Standard || - comp_swap == Liverpool::ColorBuffer::SwapMode::Alternate, - "Unsupported component swap mode {}", static_cast(comp_swap)); +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) { @@ -293,14 +288,11 @@ vk::Format SurfaceFormat( } if (data_format == AmdGpu::DataFormat::Format8_8_8_8 && num_format == AmdGpu::NumberFormat::Unorm) { - return comp_swap == Liverpool::ColorBuffer::SwapMode::Alternate - ? vk::Format::eB8G8R8A8Unorm - : vk::Format::eR8G8B8A8Unorm; + return vk::Format::eR8G8B8A8Unorm; } if (data_format == AmdGpu::DataFormat::Format8_8_8_8 && num_format == AmdGpu::NumberFormat::Srgb) { - return comp_swap == Liverpool::ColorBuffer::SwapMode::Alternate ? vk::Format::eB8G8R8A8Srgb - : vk::Format::eR8G8B8A8Srgb; + return vk::Format::eR8G8B8A8Srgb; } if (data_format == AmdGpu::DataFormat::Format32_32_32 && num_format == AmdGpu::NumberFormat::Float) { @@ -362,6 +354,31 @@ vk::Format SurfaceFormat( UNREACHABLE_MSG("Unknown data_format={} and num_format={}", u32(data_format), u32(num_format)); } +vk::Format AdjustColorBufferFormat(vk::Format base_format, + Liverpool::ColorBuffer::SwapMode comp_swap, bool is_vo_surface) { + ASSERT_MSG(comp_swap == Liverpool::ColorBuffer::SwapMode::Standard || + comp_swap == Liverpool::ColorBuffer::SwapMode::Alternate, + "Unsupported component swap mode {}", static_cast(comp_swap)); + + const bool comp_swap_alt = comp_swap == Liverpool::ColorBuffer::SwapMode::Alternate; + + switch (base_format) { + case vk::Format::eR8G8B8A8Unorm: + return comp_swap_alt ? vk::Format::eB8G8R8A8Unorm : base_format; + case vk::Format::eB8G8R8A8Unorm: + return comp_swap_alt ? vk::Format::eR8G8B8A8Unorm : base_format; + case vk::Format::eR8G8B8A8Srgb: + return comp_swap_alt ? vk::Format::eB8G8R8A8Unorm + : is_vo_surface ? vk::Format::eR8G8B8A8Unorm + : base_format; + case vk::Format::eB8G8R8A8Srgb: + return comp_swap_alt ? vk::Format::eR8G8B8A8Unorm + : is_vo_surface ? vk::Format::eB8G8R8A8Unorm + : base_format; + } + UNREACHABLE_MSG("Unsupported base format {}", vk::to_string(base_format)); +} + vk::Format DepthFormat(DepthBuffer::ZFormat z_format, DepthBuffer::StencilFormat stencil_format) { if (z_format == DepthBuffer::ZFormat::Z32Float && stencil_format == DepthBuffer::StencilFormat::Stencil8) { diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.h b/src/video_core/renderer_vulkan/liverpool_to_vk.h index 4146f2e8..59df89b4 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.h +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.h @@ -38,9 +38,10 @@ vk::SamplerMipmapMode MipFilter(AmdGpu::MipFilter filter); vk::BorderColor BorderColor(AmdGpu::BorderColor color); -vk::Format SurfaceFormat( - AmdGpu::DataFormat data_format, AmdGpu::NumberFormat num_format, - Liverpool::ColorBuffer::SwapMode comp_swap = Liverpool::ColorBuffer::SwapMode::Standard); +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); vk::Format DepthFormat(Liverpool::DepthBuffer::ZFormat z_format, Liverpool::DepthBuffer::StencilFormat stencil_format); diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h index 3c1d5f50..a0fb6d4a 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.h +++ b/src/video_core/renderer_vulkan/renderer_vulkan.h @@ -4,6 +4,7 @@ #pragma once #include +#include "video_core/amdgpu/liverpool.h" #include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/renderer_vulkan/vk_swapchain.h" @@ -50,10 +51,17 @@ public: VideoCore::Image& RegisterVideoOutSurface( const Libraries::VideoOut::BufferAttributeGroup& attribute, VAddr cpu_address) { + vo_buffers_addr.emplace_back(cpu_address); const auto info = VideoCore::ImageInfo{attribute}; return texture_cache.FindImage(info, cpu_address); } + bool IsVideoOutSurface(const AmdGpu::Liverpool::ColorBuffer& color_buffer) { + return std::find_if(vo_buffers_addr.cbegin(), vo_buffers_addr.cend(), [&](VAddr vo_buffer) { + return vo_buffer == color_buffer.Address(); + }) != vo_buffers_addr.cend(); + } + bool ShowSplash(Frame* frame = nullptr); void Present(Frame* frame); void RecreateFrame(Frame* frame, u32 width, u32 height); @@ -76,6 +84,7 @@ private: std::condition_variable free_cv; std::condition_variable_any frame_cv; std::optional splash_img; + std::vector vo_buffers_addr; }; } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 425465c0..7d5a839b 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -8,11 +8,14 @@ #include "shader_recompiler/exception.h" #include "shader_recompiler/recompiler.h" #include "shader_recompiler/runtime_info.h" +#include "video_core/renderer_vulkan/renderer_vulkan.h" #include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/renderer_vulkan/vk_pipeline_cache.h" #include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/renderer_vulkan/vk_shader_util.h" +extern std::unique_ptr renderer; + namespace Vulkan { Shader::Info MakeShaderInfo(Shader::Stage stage, std::span user_data, @@ -129,8 +132,11 @@ void PipelineCache::RefreshGraphicsKey() { if (!col_buf) { continue; } - key.color_formats[remapped_cb] = LiverpoolToVK::SurfaceFormat( - col_buf.info.format, col_buf.NumFormat(), col_buf.info.comp_swap.Value()); + const auto base_format = + LiverpoolToVK::SurfaceFormat(col_buf.info.format, col_buf.NumFormat()); + const auto is_vo_surface = renderer->IsVideoOutSurface(col_buf); + key.color_formats[remapped_cb] = LiverpoolToVK::AdjustColorBufferFormat( + base_format, col_buf.info.comp_swap.Value(), is_vo_surface); key.blend_controls[remapped_cb] = regs.blend_control[cb]; key.blend_controls[remapped_cb].enable.Assign(key.blend_controls[remapped_cb].enable && !col_buf.info.blend_bypass); diff --git a/src/video_core/texture_cache/image.cpp b/src/video_core/texture_cache/image.cpp index 308eceec..62ffdd1c 100644 --- a/src/video_core/texture_cache/image.cpp +++ b/src/video_core/texture_cache/image.cpp @@ -132,6 +132,7 @@ ImageInfo::ImageInfo(const Libraries::VideoOut::BufferAttributeGroup& group) noe } else { guest_size_bytes = pitch * 128 * ((size.height + 63) & (~63)) * 4; } + is_vo_surface = true; } ImageInfo::ImageInfo(const AmdGpu::Liverpool::ColorBuffer& buffer, diff --git a/src/video_core/texture_cache/image.h b/src/video_core/texture_cache/image.h index 5ba68726..f54a796f 100644 --- a/src/video_core/texture_cache/image.h +++ b/src/video_core/texture_cache/image.h @@ -48,6 +48,7 @@ struct ImageInfo { bool is_tiled = false; bool is_storage = false; + bool is_vo_surface = false; vk::Format pixel_format = vk::Format::eUndefined; vk::ImageType type = vk::ImageType::e1D; vk::ImageUsageFlags usage; diff --git a/src/video_core/texture_cache/image_view.cpp b/src/video_core/texture_cache/image_view.cpp index dbe93888..72566a88 100644 --- a/src/video_core/texture_cache/image_view.cpp +++ b/src/video_core/texture_cache/image_view.cpp @@ -62,9 +62,12 @@ ImageViewInfo::ImageViewInfo(const AmdGpu::Image& image, bool is_storage) noexce } } -ImageViewInfo::ImageViewInfo(const AmdGpu::Liverpool::ColorBuffer& col_buffer) noexcept { - format = Vulkan::LiverpoolToVK::SurfaceFormat(col_buffer.info.format, col_buffer.NumFormat(), - col_buffer.info.comp_swap.Value()); +ImageViewInfo::ImageViewInfo(const AmdGpu::Liverpool::ColorBuffer& col_buffer, + bool is_vo_surface) noexcept { + const auto base_format = + Vulkan::LiverpoolToVK::SurfaceFormat(col_buffer.info.format, col_buffer.NumFormat()); + format = Vulkan::LiverpoolToVK::AdjustColorBufferFormat( + base_format, col_buffer.info.comp_swap.Value(), is_vo_surface); } ImageView::ImageView(const Vulkan::Instance& instance, const ImageViewInfo& info_, Image& image, diff --git a/src/video_core/texture_cache/image_view.h b/src/video_core/texture_cache/image_view.h index 403e074e..6b567ed1 100644 --- a/src/video_core/texture_cache/image_view.h +++ b/src/video_core/texture_cache/image_view.h @@ -20,7 +20,8 @@ namespace VideoCore { struct ImageViewInfo { explicit ImageViewInfo() = default; explicit ImageViewInfo(const AmdGpu::Image& image, bool is_storage) noexcept; - explicit ImageViewInfo(const AmdGpu::Liverpool::ColorBuffer& col_buffer) noexcept; + explicit ImageViewInfo(const AmdGpu::Liverpool::ColorBuffer& col_buffer, + bool is_vo_surface) noexcept; vk::ImageViewType type = vk::ImageViewType::e2D; vk::Format format = vk::Format::eR8G8B8A8Unorm; diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index 09094c65..526dfa47 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -183,7 +183,7 @@ ImageView& TextureCache::RenderTarget(const AmdGpu::Liverpool::ColorBuffer& buff vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eColorAttachmentRead); - ImageViewInfo view_info{buffer}; + ImageViewInfo view_info{buffer, image.info.is_vo_surface}; return RegisterImageView(image, view_info); }