fix(gpu): support Gen5 flat memory and 3D images (#587)

Vector-mesh UI text samples type-10 volume LUTs; treat MIMG DIM=2 as
Dim3D and transport depth through AGC and Vulkan so Z slices no longer
collapse into a single 2D plane.
This commit is contained in:
MarcelMediaDev
2026-07-24 13:44:58 +01:00
committed by GitHub
parent 21f964a0dc
commit 5228335f15
14 changed files with 1311 additions and 299 deletions
@@ -0,0 +1,106 @@
// Copyright (C) 2026 SharpEmu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
using SharpEmu.Libs.Agc;
using SharpEmu.Libs.Gpu;
using Xunit;
namespace SharpEmu.Libs.Tests.Agc;
public sealed class AgcTextureTransportTests
{
[Theory]
[InlineData(10u, 4u, 4u)]
[InlineData(10u, 0u, 1u)]
[InlineData(9u, 4u, 1u)]
[InlineData(13u, 4u, 1u)]
public void GetTextureVolumeDepth_OnlyUsesDescriptorDepthFor3D(
uint type,
uint descriptorDepth,
uint expectedDepth)
{
Assert.Equal(
expectedDepth,
AgcExports.GetTextureVolumeDepth(type, descriptorDepth));
}
[Fact]
public void GetTextureByteCount_MultipliesUncompressedVolumeDepth()
{
Assert.Equal(
4UL * 8 * 6 * 5,
AgcExports.GetTextureByteCount(
format: 10,
width: 8,
height: 6,
depth: 5));
}
[Fact]
public void GetTextureByteCount_MultipliesBlockCompressedVolumeDepth()
{
// Format 169 uses one eight-byte BC block for each 4x4 texel block.
Assert.Equal(
2UL * 2 * 8 * 3,
AgcExports.GetTextureByteCount(
format: 169,
width: 7,
height: 5,
depth: 3));
}
[Fact]
public void GetTextureByteCount_LeavesTwoDimensionalSizingUnchanged()
{
Assert.Equal(
AgcExports.GetTextureByteCount(10, 8, 6),
AgcExports.GetTextureByteCount(10, 8, 6, depth: 1));
Assert.Equal(
AgcExports.GetTextureByteCount(10, 8, 6),
AgcExports.GetTextureByteCount(10, 8, 6, depth: 0));
}
[Fact]
public void GuestDrawTexture_CarriesRawTypeAndNormalizedDepth()
{
var texture = new GuestDrawTexture(
Address: 0x1234,
Width: 8,
Height: 6,
Format: 10,
NumberType: 0,
RgbaPixels: [],
IsFallback: false,
IsStorage: false,
Type: 10,
Depth: 5);
Assert.Equal(10u, texture.Type);
Assert.Equal(5u, texture.Depth);
}
[Fact]
public void TextureContentIdentity_DistinguishesTypeAndDepth()
{
var twoDimensional = CreateIdentity(type: 9, depth: 1);
var threeDimensional = CreateIdentity(type: 10, depth: 1);
var deeperThreeDimensional = CreateIdentity(type: 10, depth: 5);
Assert.NotEqual(twoDimensional, threeDimensional);
Assert.NotEqual(threeDimensional, deeperThreeDimensional);
}
private static TextureContentIdentity CreateIdentity(uint type, uint depth) =>
new(
Address: 0x1234,
Width: 8,
Height: 6,
Format: 10,
NumberType: 0,
DstSelect: 0xFAC,
TileMode: 0,
Pitch: 8,
Sampler: default,
Type: type,
Depth: depth);
}
@@ -36,4 +36,23 @@ public sealed class VulkanGuestImageByteCountTests
expected,
VulkanVideoPresenter.GetGuestImageByteCount(format, width, height));
}
[Theory]
[InlineData(10u, 8u, 4u, 3u, 384UL)]
[InlineData(169u, 5u, 5u, 7u, 224UL)]
public void MultipliesSurfaceSizeByVolumeDepth(
uint format,
uint width,
uint height,
uint depth,
ulong expected)
{
Assert.Equal(
expected,
VulkanVideoPresenter.GetGuestImageByteCount(
format,
width,
height,
depth));
}
}
@@ -0,0 +1,49 @@
// Copyright (C) 2026 SharpEmu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
using Silk.NET.Vulkan;
using SharpEmu.Libs.VideoOut;
using Xunit;
namespace SharpEmu.Libs.Tests.VideoOut;
public sealed class VulkanGuestImageTypeTests
{
[Fact]
public void ThreeDimensionalDescriptorsMapToVolumeImageAndViewTypes()
{
Assert.Equal(
ImageType.Type3D,
VulkanVideoPresenter.GetGuestTextureImageType(
VulkanVideoPresenter.Gen5TextureType3D));
Assert.Equal(
ImageViewType.Type3D,
VulkanVideoPresenter.GetGuestTextureViewType(
VulkanVideoPresenter.Gen5TextureType3D,
arrayedView: true));
Assert.Equal(
7u,
VulkanVideoPresenter.GetGuestTextureDepth(
VulkanVideoPresenter.Gen5TextureType3D,
7));
}
[Fact]
public void TwoDimensionalArraysKeepLayersSeparateFromImageDepth()
{
Assert.Equal(
ImageType.Type2D,
VulkanVideoPresenter.GetGuestTextureImageType(
VulkanVideoPresenter.Gen5TextureType2D));
Assert.Equal(
ImageViewType.Type2DArray,
VulkanVideoPresenter.GetGuestTextureViewType(
VulkanVideoPresenter.Gen5TextureType2D,
arrayedView: true));
Assert.Equal(
1u,
VulkanVideoPresenter.GetGuestTextureDepth(
VulkanVideoPresenter.Gen5TextureType2D,
7));
}
}