mirror of
https://github.com/par274/sharpemu.git
synced 2026-08-01 15:39:47 +08:00
Share one guest image across sRGB/UNORM aliases (#717)
Ported from origin/fix/view-compatible-guest-images 7fb8fdf. Rendering as sRGB and ImageLoad/Store-ing as UNORM at the same guest address are the same surface accessed through different number formats. Recreating the guest image per number format ping-pongs content between two VkImages and loses the rendered pixels on every transition; the mutable-format image now accepts the counterpart identity and serves it through alias views. The commit names AvPlayer movie copies as the pattern that needs this. Adapted for this base: GetOrCreateGuestImage has since grown resolution scaling and 3D/array support, so the alias accept is folded into the current predicate (LogicalWidth/LogicalHeight/LogicalDepth/Type) rather than the old Width/Height pair, and the storage-counterpart widening is placed before the physical-dimension computation. The helper functions it relies on (GetStorageImageFormat, IsCompatibleViewFormat) already existed.
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
// 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 VulkanGuestImageAliasTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(Format.R8G8B8A8Srgb, Format.R8G8B8A8Unorm)]
|
||||
[InlineData(Format.R8G8B8A8Unorm, Format.R8G8B8A8Srgb)]
|
||||
public void SrgbAndUnormCounterpartsShareOneGuestImage(
|
||||
Format existing,
|
||||
Format requested)
|
||||
{
|
||||
Assert.True(
|
||||
VulkanVideoPresenter.IsAliasableGuestImageFormat(existing, requested));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(Format.R8G8B8A8Unorm)]
|
||||
[InlineData(Format.R8G8B8A8Srgb)]
|
||||
[InlineData(Format.R16G16B16A16Sfloat)]
|
||||
public void IdenticalFormatsUseTheExactMatchPath(Format format)
|
||||
{
|
||||
// Equal formats are accepted by the exact-match condition; the alias
|
||||
// helper only reports genuinely different identities.
|
||||
Assert.False(
|
||||
VulkanVideoPresenter.IsAliasableGuestImageFormat(format, format));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(Format.R32Uint, Format.R8G8B8A8Unorm)]
|
||||
[InlineData(Format.R32Sint, Format.R8G8B8A8Unorm)]
|
||||
[InlineData(Format.R32Sfloat, Format.R8G8B8A8Unorm)]
|
||||
[InlineData(Format.R16G16Sfloat, Format.R8G8B8A8Unorm)]
|
||||
[InlineData(Format.A2B10G10R10UnormPack32, Format.R8G8B8A8Unorm)]
|
||||
[InlineData(Format.B10G11R11UfloatPack32, Format.R8G8B8A8Srgb)]
|
||||
public void SameClassNumericReinterpretationKeepsRecreatePath(
|
||||
Format existing,
|
||||
Format requested)
|
||||
{
|
||||
// These pairs are legal Vulkan view aliases (same 32-bit class), but
|
||||
// accepting them would attach fragment shaders translated for the
|
||||
// other numeric encoding to the existing attachment format.
|
||||
Assert.True(
|
||||
VulkanVideoPresenter.IsCompatibleGuestImageViewFormat(existing, requested));
|
||||
Assert.False(
|
||||
VulkanVideoPresenter.IsAliasableGuestImageFormat(existing, requested));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(Format.R8Srgb, Format.R8Unorm)]
|
||||
[InlineData(Format.BC3SrgbBlock, Format.BC3UnormBlock)]
|
||||
public void CounterpartsOutsideTheViewClassTableAreNotAliased(
|
||||
Format existing,
|
||||
Format requested)
|
||||
{
|
||||
// sRGB/UNORM counterparts that the view-compatibility table cannot
|
||||
// alias must keep the recreate path: the shared image could never
|
||||
// legally serve the second identity through an alias view.
|
||||
Assert.False(
|
||||
VulkanVideoPresenter.IsCompatibleGuestImageViewFormat(existing, requested));
|
||||
Assert.False(
|
||||
VulkanVideoPresenter.IsAliasableGuestImageFormat(existing, requested));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AliasedPairStaysWithinOneCompatibilityClass()
|
||||
{
|
||||
// The alias accept creates identity views of both formats on one
|
||||
// mutable-format image; this guards the compatibility table entries
|
||||
// the accept relies on.
|
||||
Assert.True(
|
||||
VulkanVideoPresenter.IsCompatibleGuestImageViewFormat(
|
||||
Format.R8G8B8A8Srgb,
|
||||
Format.R8G8B8A8Unorm));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user