video_out: proper sRGB output workflow
This commit is contained in:
parent
b2b45bf480
commit
b02ec385b2
|
@ -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<u32>(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<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) {
|
||||
if (z_format == DepthBuffer::ZFormat::Z32Float &&
|
||||
stencil_format == DepthBuffer::StencilFormat::Stencil8) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <condition_variable>
|
||||
#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<VideoCore::Image> splash_img;
|
||||
std::vector<VAddr> vo_buffers_addr;
|
||||
};
|
||||
|
||||
} // namespace Vulkan
|
||||
|
|
|
@ -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<Vulkan::RendererVulkan> renderer;
|
||||
|
||||
namespace Vulkan {
|
||||
|
||||
Shader::Info MakeShaderInfo(Shader::Stage stage, std::span<const u32, 16> 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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue