video_out: proper sRGB output workflow

This commit is contained in:
psucien 2024-06-15 23:16:53 +02:00
parent b2b45bf480
commit b02ec385b2
9 changed files with 60 additions and 21 deletions

View File

@ -276,12 +276,7 @@ vk::BorderColor BorderColor(AmdGpu::BorderColor color) {
} }
} }
vk::Format SurfaceFormat( vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat num_format) {
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<u32>(comp_swap));
if (data_format == AmdGpu::DataFormat::Format32_32_32_32 && if (data_format == AmdGpu::DataFormat::Format32_32_32_32 &&
num_format == AmdGpu::NumberFormat::Float) { num_format == AmdGpu::NumberFormat::Float) {
@ -293,14 +288,11 @@ vk::Format SurfaceFormat(
} }
if (data_format == AmdGpu::DataFormat::Format8_8_8_8 && if (data_format == AmdGpu::DataFormat::Format8_8_8_8 &&
num_format == AmdGpu::NumberFormat::Unorm) { num_format == AmdGpu::NumberFormat::Unorm) {
return comp_swap == Liverpool::ColorBuffer::SwapMode::Alternate return vk::Format::eR8G8B8A8Unorm;
? vk::Format::eB8G8R8A8Unorm
: vk::Format::eR8G8B8A8Unorm;
} }
if (data_format == AmdGpu::DataFormat::Format8_8_8_8 && if (data_format == AmdGpu::DataFormat::Format8_8_8_8 &&
num_format == AmdGpu::NumberFormat::Srgb) { num_format == AmdGpu::NumberFormat::Srgb) {
return comp_swap == Liverpool::ColorBuffer::SwapMode::Alternate ? vk::Format::eB8G8R8A8Srgb return vk::Format::eR8G8B8A8Srgb;
: vk::Format::eR8G8B8A8Srgb;
} }
if (data_format == AmdGpu::DataFormat::Format32_32_32 && if (data_format == AmdGpu::DataFormat::Format32_32_32 &&
num_format == AmdGpu::NumberFormat::Float) { 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)); 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<u32>(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) { vk::Format DepthFormat(DepthBuffer::ZFormat z_format, DepthBuffer::StencilFormat stencil_format) {
if (z_format == DepthBuffer::ZFormat::Z32Float && if (z_format == DepthBuffer::ZFormat::Z32Float &&
stencil_format == DepthBuffer::StencilFormat::Stencil8) { stencil_format == DepthBuffer::StencilFormat::Stencil8) {

View File

@ -38,9 +38,10 @@ vk::SamplerMipmapMode MipFilter(AmdGpu::MipFilter filter);
vk::BorderColor BorderColor(AmdGpu::BorderColor color); vk::BorderColor BorderColor(AmdGpu::BorderColor color);
vk::Format SurfaceFormat( vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat num_format);
AmdGpu::DataFormat data_format, AmdGpu::NumberFormat num_format,
Liverpool::ColorBuffer::SwapMode comp_swap = Liverpool::ColorBuffer::SwapMode::Standard); vk::Format AdjustColorBufferFormat(vk::Format base_format,
Liverpool::ColorBuffer::SwapMode comp_swap, bool is_vo_surface);
vk::Format DepthFormat(Liverpool::DepthBuffer::ZFormat z_format, vk::Format DepthFormat(Liverpool::DepthBuffer::ZFormat z_format,
Liverpool::DepthBuffer::StencilFormat stencil_format); Liverpool::DepthBuffer::StencilFormat stencil_format);

View File

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <condition_variable> #include <condition_variable>
#include "video_core/amdgpu/liverpool.h"
#include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/renderer_vulkan/vk_instance.h"
#include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/renderer_vulkan/vk_scheduler.h"
#include "video_core/renderer_vulkan/vk_swapchain.h" #include "video_core/renderer_vulkan/vk_swapchain.h"
@ -50,10 +51,17 @@ public:
VideoCore::Image& RegisterVideoOutSurface( VideoCore::Image& RegisterVideoOutSurface(
const Libraries::VideoOut::BufferAttributeGroup& attribute, VAddr cpu_address) { const Libraries::VideoOut::BufferAttributeGroup& attribute, VAddr cpu_address) {
vo_buffers_addr.emplace_back(cpu_address);
const auto info = VideoCore::ImageInfo{attribute}; const auto info = VideoCore::ImageInfo{attribute};
return texture_cache.FindImage(info, cpu_address); 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); bool ShowSplash(Frame* frame = nullptr);
void Present(Frame* frame); void Present(Frame* frame);
void RecreateFrame(Frame* frame, u32 width, u32 height); void RecreateFrame(Frame* frame, u32 width, u32 height);
@ -76,6 +84,7 @@ private:
std::condition_variable free_cv; std::condition_variable free_cv;
std::condition_variable_any frame_cv; std::condition_variable_any frame_cv;
std::optional<VideoCore::Image> splash_img; std::optional<VideoCore::Image> splash_img;
std::vector<VAddr> vo_buffers_addr;
}; };
} // namespace Vulkan } // namespace Vulkan

View File

@ -8,11 +8,14 @@
#include "shader_recompiler/exception.h" #include "shader_recompiler/exception.h"
#include "shader_recompiler/recompiler.h" #include "shader_recompiler/recompiler.h"
#include "shader_recompiler/runtime_info.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_instance.h"
#include "video_core/renderer_vulkan/vk_pipeline_cache.h" #include "video_core/renderer_vulkan/vk_pipeline_cache.h"
#include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/renderer_vulkan/vk_scheduler.h"
#include "video_core/renderer_vulkan/vk_shader_util.h" #include "video_core/renderer_vulkan/vk_shader_util.h"
extern std::unique_ptr<Vulkan::RendererVulkan> renderer;
namespace Vulkan { namespace Vulkan {
Shader::Info MakeShaderInfo(Shader::Stage stage, std::span<const u32, 16> user_data, Shader::Info MakeShaderInfo(Shader::Stage stage, std::span<const u32, 16> user_data,
@ -129,8 +132,11 @@ void PipelineCache::RefreshGraphicsKey() {
if (!col_buf) { if (!col_buf) {
continue; continue;
} }
key.color_formats[remapped_cb] = LiverpoolToVK::SurfaceFormat( const auto base_format =
col_buf.info.format, col_buf.NumFormat(), col_buf.info.comp_swap.Value()); 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] = regs.blend_control[cb];
key.blend_controls[remapped_cb].enable.Assign(key.blend_controls[remapped_cb].enable && key.blend_controls[remapped_cb].enable.Assign(key.blend_controls[remapped_cb].enable &&
!col_buf.info.blend_bypass); !col_buf.info.blend_bypass);

View File

@ -132,6 +132,7 @@ ImageInfo::ImageInfo(const Libraries::VideoOut::BufferAttributeGroup& group) noe
} else { } else {
guest_size_bytes = pitch * 128 * ((size.height + 63) & (~63)) * 4; guest_size_bytes = pitch * 128 * ((size.height + 63) & (~63)) * 4;
} }
is_vo_surface = true;
} }
ImageInfo::ImageInfo(const AmdGpu::Liverpool::ColorBuffer& buffer, ImageInfo::ImageInfo(const AmdGpu::Liverpool::ColorBuffer& buffer,

View File

@ -48,6 +48,7 @@ struct ImageInfo {
bool is_tiled = false; bool is_tiled = false;
bool is_storage = false; bool is_storage = false;
bool is_vo_surface = false;
vk::Format pixel_format = vk::Format::eUndefined; vk::Format pixel_format = vk::Format::eUndefined;
vk::ImageType type = vk::ImageType::e1D; vk::ImageType type = vk::ImageType::e1D;
vk::ImageUsageFlags usage; vk::ImageUsageFlags usage;

View File

@ -62,9 +62,12 @@ ImageViewInfo::ImageViewInfo(const AmdGpu::Image& image, bool is_storage) noexce
} }
} }
ImageViewInfo::ImageViewInfo(const AmdGpu::Liverpool::ColorBuffer& col_buffer) noexcept { ImageViewInfo::ImageViewInfo(const AmdGpu::Liverpool::ColorBuffer& col_buffer,
format = Vulkan::LiverpoolToVK::SurfaceFormat(col_buffer.info.format, col_buffer.NumFormat(), bool is_vo_surface) noexcept {
col_buffer.info.comp_swap.Value()); 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, ImageView::ImageView(const Vulkan::Instance& instance, const ImageViewInfo& info_, Image& image,

View File

@ -20,7 +20,8 @@ namespace VideoCore {
struct ImageViewInfo { struct ImageViewInfo {
explicit ImageViewInfo() = default; explicit ImageViewInfo() = default;
explicit ImageViewInfo(const AmdGpu::Image& image, bool is_storage) noexcept; 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::ImageViewType type = vk::ImageViewType::e2D;
vk::Format format = vk::Format::eR8G8B8A8Unorm; vk::Format format = vk::Format::eR8G8B8A8Unorm;

View File

@ -183,7 +183,7 @@ ImageView& TextureCache::RenderTarget(const AmdGpu::Liverpool::ColorBuffer& buff
vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eColorAttachmentWrite |
vk::AccessFlagBits::eColorAttachmentRead); vk::AccessFlagBits::eColorAttachmentRead);
ImageViewInfo view_info{buffer}; ImageViewInfo view_info{buffer, image.info.is_vo_surface};
return RegisterImageView(image, view_info); return RegisterImageView(image, view_info);
} }