mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-22 19:06:15 +08:00
Encode linear-float flips to sRGB at present (#448)
PS5 float VideoOut buffers (A16B16G16R16F flips) hold linear scRGB light where 1.0 is SDR white; hardware scan-out applies the display transfer function. vkCmdBlitImage converts numerically only, so raw-blitting a linear-float guest frame into a UNORM swapchain crushes dim scenes to near-black. Blit float flip sources through a cached swapchain-sized sRGB intermediate (the sRGB store performs the linear->sRGB encode), then raw vkCmdCopyImage the encoded bytes into the same-compatibility-class UNORM swapchain image. Swapchains that are already sRGB keep the direct blit (their store encodes), and swapchain formats without an sRGB counterpart keep today's raw blit unchanged.
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
// Copyright (C) 2026 SharpEmu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
using SharpEmu.Libs.VideoOut;
|
||||
using Silk.NET.Vulkan;
|
||||
using Xunit;
|
||||
|
||||
namespace SharpEmu.Libs.Tests.VideoOut;
|
||||
|
||||
public sealed class VulkanPresentEncodeFormatTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(Format.B8G8R8A8Unorm, Format.B8G8R8A8Srgb)]
|
||||
[InlineData(Format.R8G8B8A8Unorm, Format.R8G8B8A8Srgb)]
|
||||
public void UnormSwapchainFormatsHaveSrgbCounterparts(
|
||||
Format swapchainFormat,
|
||||
Format expected)
|
||||
{
|
||||
Assert.Equal(
|
||||
expected,
|
||||
VulkanVideoPresenter.GetSrgbCounterpart(swapchainFormat));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
// Already-sRGB swapchains encode on store; the direct blit stays.
|
||||
[InlineData(Format.B8G8R8A8Srgb)]
|
||||
[InlineData(Format.R8G8B8A8Srgb)]
|
||||
// No same-class sRGB counterpart exists; the raw blit must remain.
|
||||
[InlineData(Format.A2B10G10R10UnormPack32)]
|
||||
[InlineData(Format.R16G16B16A16Sfloat)]
|
||||
[InlineData(Format.R5G6B5UnormPack16)]
|
||||
[InlineData(Format.Undefined)]
|
||||
public void OtherSwapchainFormatsKeepTheDirectBlit(Format swapchainFormat)
|
||||
{
|
||||
Assert.Equal(
|
||||
Format.Undefined,
|
||||
VulkanVideoPresenter.GetSrgbCounterpart(swapchainFormat));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(Format.R16G16B16A16Sfloat)]
|
||||
[InlineData(Format.R32G32B32A32Sfloat)]
|
||||
public void FloatFlipSourcesNeedLinearToSrgbEncode(Format sourceFormat)
|
||||
{
|
||||
Assert.True(VulkanVideoPresenter.IsLinearFloatPresentSource(sourceFormat));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(Format.B8G8R8A8Unorm)]
|
||||
[InlineData(Format.R8G8B8A8Unorm)]
|
||||
[InlineData(Format.B8G8R8A8Srgb)]
|
||||
[InlineData(Format.A2B10G10R10UnormPack32)]
|
||||
[InlineData(Format.B10G11R11UfloatPack32)]
|
||||
[InlineData(Format.Undefined)]
|
||||
public void NonFloatFlipSourcesKeepTheDirectBlit(Format sourceFormat)
|
||||
{
|
||||
Assert.False(VulkanVideoPresenter.IsLinearFloatPresentSource(sourceFormat));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user