[Tests] Cover Gen5 tiling, DCC clears and offline authentication
Co-authored-by: Sekai <140012992+SekaixX@users.noreply.github.com>
This commit is contained in:
parent
c0028d304b
commit
dd6a936a12
|
|
@ -78,7 +78,7 @@ internal static class TilerCases
|
|||
transfer.Tail = true;
|
||||
break;
|
||||
case Shape.Layered:
|
||||
if (kind is not (TileBlockKind.RenderTarget64KB or TileBlockKind.Depth64KB))
|
||||
if (kind is not (TileBlockKind.RenderTarget64KB or TileBlockKind.Depth64KB or TileBlockKind.RenderTarget64KBGen5))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
|
@ -203,7 +203,7 @@ public sealed class GpuTilerTests : IClassFixture<HeadlessVulkanFixture>
|
|||
public void CpuTwinCases_CoverEveryKindAndElementSize()
|
||||
{
|
||||
var cases = TilerCases.All().ToList();
|
||||
Assert.Equal(44 + 39 + 9, cases.Count);
|
||||
Assert.Equal((44 + 39 + 9) + 15, cases.Count);
|
||||
Assert.All(cases, tilerCase => Assert.True(tilerCase.Transfer.SurfaceZ != 0 || tilerCase.Tiled.Length == (int)tilerCase.Transfer.TiledSize));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -100,31 +100,31 @@ public sealed partial class GuestImageCacheTests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void DccFills_AreAbsorbedOnlyByRegisteredDcc()
|
||||
public void DccFills_RemainGuestProducersUntilDescriptorDiscovery()
|
||||
{
|
||||
if (!GatePrerequisites.Ready(_vulkan)) return;
|
||||
using var fatal = new FatalScope();
|
||||
using var harness = new CacheHarness(_vulkan);
|
||||
var address = harness.MapBacked(0x20000, ReadWrite);
|
||||
var metadata = address + 0x10000;
|
||||
Assert.False(harness.Images.TryAbsorbDccFill(metadata, 0x100, 0x20202020u));
|
||||
harness.Write(metadata, Bytes(0x11223344u));
|
||||
Assert.False(harness.Images.TryAbsorbDccFill(metadata, 0x1000, 0x20202020u));
|
||||
Assert.False(harness.Images.IsMetadata(metadata));
|
||||
Assert.False(harness.Images.TryAbsorbDccFill(metadata, 0x100, 0x40404040u));
|
||||
Assert.False(harness.Images.TryAbsorbDccFill(metadata, 0x1000, 0x40404040u));
|
||||
|
||||
harness.Write(address + 0xc000, Bytes(0x55667788u));
|
||||
var target = LinearRequest(address + 0xc000, 4, Format.R8G8B8A8Srgb, GuestPixelFormat.Bits8_8_8_8Srgb, GuestImageType.Color2D, new Extent3D(1, 1, 1), 1, 4, 1);
|
||||
target = AsColorTarget(target);
|
||||
target.Description.Metadata.Kind = MetadataKind.Dcc;
|
||||
target.Description.Metadata.Range = new GuestSpan(metadata, 0x100);
|
||||
target.Description.Metadata.Range = new GuestSpan(metadata, 0x1000);
|
||||
target.Description.Metadata.Compression = DisplayCompression.Dcc256_256_0;
|
||||
var targetId = harness.Acquire(ref target);
|
||||
Assert.True(harness.Images.IsMetadata(metadata));
|
||||
Assert.True(harness.Images.IsMetadataCleared(metadata, 0, out var fill));
|
||||
Assert.Equal(0x40404040u, fill);
|
||||
Assert.True(harness.Images.TryAbsorbDccFill(metadata, 0x100, 0x01010101u));
|
||||
Assert.False(harness.Images.IsMetadata(metadata));
|
||||
Assert.False(harness.Images.IsMetadataCleared(metadata, 0));
|
||||
Assert.True(harness.Images.TryAbsorbDccFill(metadata, 0x100, 0xc0c0c0c0u));
|
||||
Assert.True(harness.Images.IsMetadataCleared(metadata, 5));
|
||||
Assert.Equal(0x11223344u, harness.ReadUInt32(metadata));
|
||||
Assert.False(harness.Images.TryAbsorbDccFill(metadata, 0x1000, 0x01010101u));
|
||||
Assert.False(harness.Images.TryAbsorbDccFill(metadata, 0x1000, 0xc0c0c0c0u));
|
||||
Assert.False(harness.Images.IsMetadataCleared(metadata, 5));
|
||||
Assert.Equal(0x11223344u, harness.ReadUInt32(metadata));
|
||||
Assert.False(harness.Images.ClearMetadata(metadata));
|
||||
|
||||
// A compressed target rejects readback and read claims but keeps GPU ownership.
|
||||
|
|
@ -144,15 +144,169 @@ public sealed partial class GuestImageCacheTests
|
|||
Assert.False(videoImage.Binding.NeedsRebind);
|
||||
Assert.False(videoImage.Uses.VideoOut);
|
||||
|
||||
// A depth target must not reuse DCC metadata.
|
||||
var depth = LinearRequest(address + 0xe000, 4, Format.D32Sfloat, GuestPixelFormat.Bits32Float, GuestImageType.Color2D, new Extent3D(1, 1, 1), 1, 4, 1);
|
||||
depth = AsDepthTarget(depth, Format.D32Sfloat);
|
||||
depth.Description.Metadata.Kind = MetadataKind.Htile;
|
||||
depth.Description.Metadata.Range = new GuestSpan(metadata, 0x100);
|
||||
var depthId = harness.Find(ref depth);
|
||||
var depthLocal = depth;
|
||||
harness.Worker.Run(() => Assert.Throws<SchedulerFatalException>(() => harness.Images.AcquireDepthTargetView(depthId, depthLocal)));
|
||||
Assert.Contains(fatal.Messages, message => message.Contains("depth target reuses metadata that is not HTile"));
|
||||
harness.Worker.Run(() => Assert.NotEqual(
|
||||
0UL,
|
||||
harness.Images.AcquireDepthTargetView(depthId, depthLocal).Handle));
|
||||
Assert.True(harness.Images.IsMetadata(metadata));
|
||||
harness.Shutdown();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DccVolumeOverThirtyTwoSlices_MaterializesAndConsumesEveryUniformSlice()
|
||||
{
|
||||
if (!GatePrerequisites.Ready(_vulkan)) return;
|
||||
using var harness = new CacheHarness(_vulkan);
|
||||
var address = harness.MapBacked(0x80000, ReadWrite);
|
||||
var imageAddress = address + 0x1000;
|
||||
var metadataAddress = address + 0x10000;
|
||||
const uint depth = 64;
|
||||
const ulong metadataSliceSize = 0x1000;
|
||||
var metadataBytes = new byte[checked((int)(depth * metadataSliceSize))];
|
||||
Array.Fill(metadataBytes, (byte)0xc0);
|
||||
harness.Write(metadataAddress, metadataBytes);
|
||||
|
||||
const uint width = 4;
|
||||
const uint height = 4;
|
||||
var imageSize = (ulong)width * height * depth * 4;
|
||||
var target = LinearRequest(
|
||||
imageAddress,
|
||||
imageSize,
|
||||
Format.R8G8B8A8Unorm,
|
||||
GuestPixelFormat.Bits8_8_8_8UNorm,
|
||||
GuestImageType.Color3D,
|
||||
new Extent3D(width, height, depth),
|
||||
1,
|
||||
4,
|
||||
1);
|
||||
target = AsColorTarget(target);
|
||||
target.View = target.View with
|
||||
{
|
||||
Type = ImageViewType.Type2DArray,
|
||||
BaseLayer = 0,
|
||||
LayerCount = depth,
|
||||
};
|
||||
target.Description.Metadata.Kind = MetadataKind.Dcc;
|
||||
target.Description.Metadata.Range = new GuestSpan(metadataAddress, depth * metadataSliceSize);
|
||||
target.Description.Metadata.DccAlphaMsb = true;
|
||||
|
||||
Assert.False(harness.Images.TryAbsorbDccFill(
|
||||
metadataAddress,
|
||||
depth * metadataSliceSize,
|
||||
0xc0c0c0c0u));
|
||||
var targetId = harness.Find(ref target);
|
||||
harness.Finish();
|
||||
|
||||
Assert.True(targetId.IsValid);
|
||||
Assert.Equal(uint.MaxValue, harness.ReadUInt32(metadataAddress));
|
||||
Assert.Equal(uint.MaxValue, harness.ReadUInt32(metadataAddress + 31 * metadataSliceSize));
|
||||
Assert.Equal(uint.MaxValue, harness.ReadUInt32(metadataAddress + 32 * metadataSliceSize));
|
||||
Assert.Equal(uint.MaxValue, harness.ReadUInt32(metadataAddress + (depth - 1) * metadataSliceSize));
|
||||
Assert.False(harness.Images.IsMetadataCleared(metadataAddress, 0));
|
||||
Assert.False(harness.Images.IsMetadataCleared(metadataAddress, 31));
|
||||
Assert.False(harness.Images.IsMetadataCleared(metadataAddress, 32));
|
||||
harness.Shutdown();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SelflossShapeDccVolume_HandlesOneHundredTwentyEightSlicesIndependently()
|
||||
{
|
||||
if (!GatePrerequisites.Ready(_vulkan)) return;
|
||||
using var harness = new CacheHarness(_vulkan);
|
||||
var address = harness.MapBacked(0x140000, ReadWrite);
|
||||
var imageAddress = address + 0x1000;
|
||||
var metadataAddress = address + 0x20000;
|
||||
const uint depth = 128;
|
||||
const ulong metadataSliceSize = 0x2000;
|
||||
var metadataBytes = new byte[checked((int)(depth * metadataSliceSize))];
|
||||
Array.Fill(metadataBytes, (byte)0xc0);
|
||||
const uint mixedSlice = 73;
|
||||
Array.Fill(
|
||||
metadataBytes,
|
||||
(byte)0x55,
|
||||
checked((int)(mixedSlice * metadataSliceSize + 1)),
|
||||
checked((int)metadataSliceSize - 1));
|
||||
harness.Write(metadataAddress, metadataBytes);
|
||||
|
||||
const uint width = 4;
|
||||
const uint height = 4;
|
||||
var imageSize = (ulong)width * height * depth * 8;
|
||||
var texture = LinearRequest(
|
||||
imageAddress,
|
||||
imageSize,
|
||||
Format.R16G16B16A16Sfloat,
|
||||
GuestPixelFormat.Bits16_16_16_16Float,
|
||||
GuestImageType.Color3D,
|
||||
new Extent3D(width, height, depth),
|
||||
1,
|
||||
8,
|
||||
1);
|
||||
texture.Description.Metadata.Kind = MetadataKind.Dcc;
|
||||
texture.Description.Metadata.Range = new GuestSpan(
|
||||
metadataAddress,
|
||||
depth * metadataSliceSize);
|
||||
texture.Description.Metadata.DccAlphaMsb = true;
|
||||
|
||||
var textureId = harness.Find(ref texture);
|
||||
harness.Finish();
|
||||
|
||||
Assert.True(textureId.IsValid);
|
||||
Assert.Equal(uint.MaxValue, harness.ReadUInt32(metadataAddress));
|
||||
Assert.Equal(
|
||||
0x555555c0u,
|
||||
harness.ReadUInt32(metadataAddress + mixedSlice * metadataSliceSize));
|
||||
Assert.Equal(
|
||||
uint.MaxValue,
|
||||
harness.ReadUInt32(metadataAddress + (depth - 1) * metadataSliceSize));
|
||||
Assert.False(harness.Images.IsMetadata(metadataAddress));
|
||||
harness.Shutdown();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DccMetadataScan_RejectsAMismatchBeyondTheFirstPooledChunk()
|
||||
{
|
||||
if (!GatePrerequisites.Ready(_vulkan)) return;
|
||||
using var harness = new CacheHarness(_vulkan);
|
||||
var address = harness.MapBacked(0x50000, ReadWrite);
|
||||
var imageAddress = address + 0x1000;
|
||||
var metadataAddress = address + 0x10000;
|
||||
const uint layers = 2;
|
||||
const ulong metadataSliceSize = 0x11000;
|
||||
var metadataBytes = new byte[checked((int)(layers * metadataSliceSize))];
|
||||
Array.Fill(metadataBytes, (byte)0xc0);
|
||||
metadataBytes[^1] = 0x55;
|
||||
harness.Write(metadataAddress, metadataBytes);
|
||||
|
||||
const uint width = 4;
|
||||
const uint height = 4;
|
||||
var texture = LinearRequest(
|
||||
imageAddress,
|
||||
(ulong)width * height * layers * 4,
|
||||
Format.R8G8B8A8Unorm,
|
||||
GuestPixelFormat.Bits8_8_8_8UNorm,
|
||||
GuestImageType.Color2D,
|
||||
new Extent3D(width, height, 1),
|
||||
layers,
|
||||
4,
|
||||
1);
|
||||
texture.Description.Metadata.Kind = MetadataKind.Dcc;
|
||||
texture.Description.Metadata.Range = new GuestSpan(
|
||||
metadataAddress,
|
||||
layers * metadataSliceSize);
|
||||
texture.Description.Metadata.DccAlphaMsb = true;
|
||||
|
||||
var textureId = harness.Find(ref texture);
|
||||
harness.Finish();
|
||||
|
||||
Assert.True(textureId.IsValid);
|
||||
Assert.Equal(uint.MaxValue, harness.ReadUInt32(metadataAddress));
|
||||
Assert.Equal(0xc0c0c0c0u, harness.ReadUInt32(metadataAddress + metadataSliceSize));
|
||||
Assert.Equal(0x55, harness.Read(metadataAddress + 2 * metadataSliceSize - 1, 1)[0]);
|
||||
harness.Shutdown();
|
||||
}
|
||||
|
||||
|
|
@ -196,8 +350,10 @@ public sealed partial class GuestImageCacheTests
|
|||
harness.Shutdown();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ATextureRequestWithDcc_GivesAnImageFoundWithoutMetadataItsDccMetadata()
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
public void DccDescriptor_SynchronizesMetadataOnAnImageFoundWithoutIt(bool native)
|
||||
{
|
||||
if (!GatePrerequisites.Ready(_vulkan)) return;
|
||||
using var harness = new CacheHarness(_vulkan);
|
||||
|
|
@ -220,14 +376,15 @@ public sealed partial class GuestImageCacheTests
|
|||
var compressed = plain;
|
||||
compressed.Description.TileMode = GuestTileMode.RenderTarget;
|
||||
compressed.Description.Metadata.Kind = MetadataKind.Dcc;
|
||||
compressed.Description.Metadata.Range = new GuestSpan(metadata, 0);
|
||||
compressed.Description.Metadata.Range = new GuestSpan(metadata, native ? SliceSize : 0);
|
||||
Assert.Equal(imageId, harness.Find(ref compressed));
|
||||
Assert.Equal(MetadataKind.Dcc, image.Description.Metadata.Kind);
|
||||
Assert.Equal(metadata, image.Description.Metadata.Range.Address);
|
||||
Assert.Equal(SliceSize, image.Description.DccSliceSize);
|
||||
Assert.False(harness.Cache.HasGpuDirtyBytes(metadata, SliceSize));
|
||||
Assert.True(harness.Images.TryReadGuestDccClear(metadata, SliceSize, 0, out _, out var code));
|
||||
Assert.Equal(0x00, code);
|
||||
harness.Finish();
|
||||
Assert.Equal(native ? uint.MaxValue : 0u, harness.ReadUInt32(metadata));
|
||||
Assert.Equal(!native, harness.Images.TryReadGuestDccClear(metadata, SliceSize, 0, out _, out _));
|
||||
harness.Shutdown();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -154,6 +154,21 @@ public sealed class ImageDescriptionTests
|
|||
Assert.False(ImageDescription.CanUseDisplayNativeWithoutUpload(DisplayCompression.Unsupported, renderTarget: true, gpuModified: true, guestModified: false));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, 0.0f, 1.0f)]
|
||||
[InlineData(false, 1.0f, 0.0f)]
|
||||
public void DccFixedClear_RespectsTheAlphaPosition(bool alphaMsb, float red, float alpha)
|
||||
{
|
||||
var metadata = new MetadataDescription { DccAlphaMsb = alphaMsb };
|
||||
Assert.True(PackedClearValue.TryDecodeDccColor(
|
||||
Format.A2B10G10R10UnormPack32, 0x40404040, metadata, false, out var clear));
|
||||
Assert.Equal((red, 0.0f, 0.0f, alpha), (clear.Float32_0, clear.Float32_1, clear.Float32_2, clear.Float32_3));
|
||||
Assert.False(PackedClearValue.TryDecodeDccColor(
|
||||
Format.A2B10G10R10UnormPack32, 0x40400040, metadata, false, out _));
|
||||
Assert.False(PackedClearValue.TryDecodeDccColor(
|
||||
Format.A2B10G10R10UnormPack32, 0xffffffff, metadata, false, out _));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PackedClears_DecodePerFormat()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -74,21 +74,40 @@ public sealed class ImageRequestBuildersTests : IClassFixture<HeadlessVulkanFixt
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(GuestImageType.Color2D, 1u, false)]
|
||||
[InlineData(GuestImageType.Color2D, 1u, true)]
|
||||
[InlineData(GuestImageType.Color3D, 32u, false)]
|
||||
[InlineData(GuestImageType.Color3D, 32u, true)]
|
||||
[InlineData(GuestImageType.Color2DArray, 4u, false)]
|
||||
public void CompressedTexture_CarriesDccMetadataOnlyForSingleLayer2D(GuestImageType type, uint layers, bool expected)
|
||||
[InlineData(GuestImageType.Color2DArray, 4u, true)]
|
||||
public void CompressedTexture_CarriesDccMetadataForEverySlice(GuestImageType type, uint layers, bool storage)
|
||||
{
|
||||
const ulong metadata = 0x1_2000_0000;
|
||||
var words = RegisterWords.Texture(Base, GuestPixelFormat.Bits8_8_8_8UNorm, 32, 32, type, GuestTileMode.RenderTarget, layers: layers);
|
||||
words[6] |= (1u << 21) | (uint)(((metadata >> 8) & 0xFF) << 24);
|
||||
words[7] = (uint)(metadata >> 16);
|
||||
var shape = Sampled2D with { Volume = type == GuestImageType.Color3D, Arrayed = type == GuestImageType.Color2DArray };
|
||||
var shape = Sampled2D with { Volume = type == GuestImageType.Color3D, Arrayed = type == GuestImageType.Color2DArray, Storage = storage };
|
||||
|
||||
var description = ImageRequestBuilders.Texture(words, shape).Request.Description;
|
||||
|
||||
Assert.Equal(expected ? MetadataKind.Dcc : MetadataKind.None, description.Metadata.Kind);
|
||||
Assert.Equal(expected ? metadata : 0UL, description.Metadata.Range.Address);
|
||||
Assert.Equal(MetadataKind.Dcc, description.Metadata.Kind);
|
||||
Assert.Equal(metadata, description.Metadata.Range.Address);
|
||||
Assert.Equal((ulong)layers * 0x1000, description.Metadata.Range.Size);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DemonSlayerColorLut_CarriesItsVolumeDccFootprintAndAlphaPosition()
|
||||
{
|
||||
uint[] words = [0x606D4E00, 0xC3200000, 0x0007C007, 0xA1B00FAC, 0x0000001F, 0x00700000, 0x006B0000, 0x00606D6E];
|
||||
var description = ImageRequestBuilders.Texture(words, Sampled2D with { Volume = true }).Request.Description;
|
||||
|
||||
Assert.Equal(GuestImageType.Color3D, description.Type);
|
||||
Assert.Equal(new Extent3D(32, 32, 32), description.Extent);
|
||||
Assert.Equal(Format.A2B10G10R10UnormPack32, description.PixelFormat);
|
||||
Assert.Equal(MetadataKind.Dcc, description.Metadata.Kind);
|
||||
Assert.Equal(0x606D6E0000UL, description.Metadata.Range.Address);
|
||||
Assert.Equal(0x20000UL, description.Metadata.Range.Size);
|
||||
Assert.True(description.Metadata.DccAlphaMsb);
|
||||
}
|
||||
|
||||
private readonly HeadlessVulkan? _vulkan;
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ public sealed class TextureTransferLayoutTests
|
|||
var target = TextureTransferLayout.Compute(GuestPixelFormat.Bits8_8_8_8UNorm, 128, 128, 1, 2, GuestTileMode.RenderTarget, 0, false, false, "test");
|
||||
Assert.True(target.TryBuildTileTransfers(2 * 65536, target.BuildCopies(), 1, out var targetTransfers));
|
||||
Assert.Equal(1u, targetTransfers[1].SurfaceZ);
|
||||
Assert.Equal(TileBlockKind.RenderTarget64KB, targetTransfers[1].Kind);
|
||||
Assert.Equal(TileBlockKind.RenderTarget64KBGen5, targetTransfers[1].Kind);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
using SharpEmu.Libs.Gpu.Images;
|
||||
using SharpEmu.ShaderCompiler.Vulkan;
|
||||
using Xunit;
|
||||
|
||||
namespace SharpEmu.Libs.Tests.Gpu.Images;
|
||||
|
|
@ -39,6 +40,7 @@ public sealed class TileGeometryTests
|
|||
[InlineData(TileBlockKind.Prt64KB3D, 65536u, 16u)]
|
||||
[InlineData(TileBlockKind.RenderTarget64KB, 65536u, 16u)]
|
||||
[InlineData(TileBlockKind.Depth64KB, 65536u, 8u)]
|
||||
[InlineData(TileBlockKind.RenderTarget64KBGen5, 65536u, 16u)]
|
||||
public void BlockLayouts_CoverEveryElementSize(TileBlockKind kind, uint blockSize, uint maxBytes)
|
||||
{
|
||||
for (uint bytes = 1; bytes <= 16; bytes *= 2)
|
||||
|
|
@ -107,6 +109,83 @@ public sealed class TileGeometryTests
|
|||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(1u, 0x0B75u, 0x8000u, 0x4000u)]
|
||||
[InlineData(2u, 0x0B7Au, 0x8000u, 0x4100u)]
|
||||
[InlineData(4u, 0x0BF4u, 0x8100u, 0x4100u)]
|
||||
[InlineData(8u, 0x1BD8u, 0x4100u, 0x8800u)]
|
||||
[InlineData(16u, 0x3BB0u, 0x4400u, 0x8800u)]
|
||||
public void RenderTargetBlockOffsets_MatchRbPlusReferenceSpotValues(
|
||||
uint bytes,
|
||||
uint elementOffset,
|
||||
uint xBlockXor,
|
||||
uint yBlockXor)
|
||||
{
|
||||
Assert.True(TileGeometry.TryGetBlockLayout(TileBlockKind.RenderTarget64KB, bytes, out var layout));
|
||||
Assert.True(TileGeometry.TryGetBlockOffset(layout, 37, 23, 0, out var offset));
|
||||
Assert.Equal(elementOffset, offset);
|
||||
|
||||
Assert.True(TileGeometry.TryGetBlockXor(layout, 1, 0, out var blockX));
|
||||
Assert.Equal(xBlockXor, blockX);
|
||||
Assert.True(TileGeometry.TryGetBlockXor(layout, 0, 1, out var blockY));
|
||||
Assert.Equal(yBlockXor, blockY);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(1u, 0x0b75u, 0x0abdu)]
|
||||
[InlineData(2u, 0x0b7au, 0x1a7au)]
|
||||
[InlineData(4u, 0x0bf4u, 0x0af4u)]
|
||||
[InlineData(8u, 0x1bd8u, 0x5ad8u)]
|
||||
[InlineData(16u, 0x3bb0u, 0x3ab0u)]
|
||||
public void Gen5RenderTargetBlockOffsets_MatchReferenceAndDifferFromRbPlus(
|
||||
uint bytes,
|
||||
uint expectedRbPlus,
|
||||
uint expectedGen5)
|
||||
{
|
||||
Assert.True(TileGeometry.TryGetBlockLayout(TileBlockKind.RenderTarget64KB, bytes, out var rbPlus));
|
||||
Assert.True(TileGeometry.TryGetBlockLayout(TileBlockKind.RenderTarget64KBGen5, bytes, out var gen5));
|
||||
|
||||
Assert.True(TileGeometry.TryGetBlockOffset(rbPlus, 37, 23, 0, out var rbPlusOffset));
|
||||
Assert.True(TileGeometry.TryGetBlockOffset(gen5, 37, 23, 0, out var gen5Offset));
|
||||
Assert.Equal(expectedRbPlus, rbPlusOffset);
|
||||
Assert.Equal(expectedGen5, gen5Offset);
|
||||
Assert.NotEqual(rbPlusOffset, gen5Offset);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gen5RenderTargetGeometry_MatchesTheReferenceVolumeAllocation()
|
||||
{
|
||||
const uint width = 480;
|
||||
const uint height = 270;
|
||||
const uint depth = 128;
|
||||
Assert.True(TileGeometry.TryGetBlockLayout(TileBlockKind.RenderTarget64KBGen5, 8, out var block));
|
||||
Assert.Equal((128u, 64u, 1u), (block.BlockWidth, block.BlockHeight, block.BlockDepth));
|
||||
|
||||
var paddedWidth = (width + block.BlockWidth - 1) / block.BlockWidth * block.BlockWidth;
|
||||
var paddedHeight = (height + block.BlockHeight - 1) / block.BlockHeight * block.BlockHeight;
|
||||
var blocksPerSlice = (ulong)(paddedWidth / block.BlockWidth) * (paddedHeight / block.BlockHeight);
|
||||
var sliceSize = blocksPerSlice * block.BlockSize;
|
||||
var totalSize = sliceSize * depth;
|
||||
|
||||
Assert.Equal((512u, 320u), (paddedWidth, paddedHeight));
|
||||
Assert.Equal(0x140000UL, sliceSize);
|
||||
Assert.Equal(0xA000000UL, totalSize);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CpuAndShaderBlockKindOrdinals_StayAligned()
|
||||
{
|
||||
var cpuKinds = Enum.GetValues<TileBlockKind>();
|
||||
var shaderKinds = Enum.GetValues<TilerBlockShape>();
|
||||
Assert.Equal(cpuKinds.Length, shaderKinds.Length);
|
||||
|
||||
for (var index = 0; index < cpuKinds.Length; index++)
|
||||
{
|
||||
Assert.Equal(cpuKinds[index].ToString(), shaderKinds[index].ToString());
|
||||
Assert.Equal((uint)cpuKinds[index], (uint)shaderKinds[index]);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MipTail_StartsWhereTheLevelFitsAndOffsetsRunBackwards()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -59,6 +59,11 @@ public sealed class TilerParityTests : IClassFixture<HeadlessVulkanFixture>
|
|||
foreach (var tilerCase in TilerCases.All())
|
||||
{
|
||||
var transfer = tilerCase.Transfer;
|
||||
if (transfer.Kind == TileBlockKind.RenderTarget64KBGen5)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var reference = blobs[(int)transfer.Kind]!;
|
||||
foreach (var toTiled in new[] { false, true })
|
||||
{
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ public sealed class ShaderPrewarmListTests : IDisposable
|
|||
Assert.True(
|
||||
ShaderProgramCache.TryCompilePrewarm(
|
||||
record, code, new FakeShaderCompiler(Compile), host.SharedInt64AtomicsEnabled, host.ExecGuardElisionEnabled,
|
||||
out var compiled, out var layout, out var error),
|
||||
host.ShaderSignedZeroInfNanPreserveFloat32Supported, out var compiled, out var layout, out var error),
|
||||
error);
|
||||
Assert.NotNull(layout);
|
||||
Assert.Equal(runtime, Assert.IsType<FakeCompiledShader>(compiled).Spirv);
|
||||
|
|
|
|||
|
|
@ -46,14 +46,48 @@ public sealed class NpAuthExportsTests
|
|||
Assert.Equal(unchecked((int)0x80550304), BinaryPrimitives.ReadInt32LittleEndian(resultBytes));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OnlineOperation_ReturnsServiceDownWithoutProducingCredentials()
|
||||
[Theory]
|
||||
[InlineData(false, false)]
|
||||
[InlineData(false, true)]
|
||||
[InlineData(true, false)]
|
||||
[InlineData(true, true)]
|
||||
public void OnlineOperation_CompletesSignedOutWithoutProducingCredentials(bool async, bool idToken)
|
||||
{
|
||||
NpAuthExports.ResetRuntimeState();
|
||||
var ctx = new CpuContext(new FakeCpuMemory(MemoryBase, 0x1000), Generation.Gen5);
|
||||
var requestId = NpAuthExports.NpAuthCreateRequest(ctx);
|
||||
ctx[CpuRegister.Rdi] = unchecked((uint)requestId);
|
||||
var memory = new FakeCpuMemory(MemoryBase, 0x2000);
|
||||
var ctx = new CpuContext(memory, Generation.Gen5);
|
||||
ctx[CpuRegister.Rdi] = MemoryBase;
|
||||
Assert.True(ctx.TryWriteUInt64(MemoryBase, 24));
|
||||
var requestId = async
|
||||
? NpAuthExports.NpAuthCreateAsyncRequest(ctx)
|
||||
: NpAuthExports.NpAuthCreateRequest(ctx);
|
||||
Assert.True(requestId > 0);
|
||||
|
||||
Assert.Equal(unchecked((int)0x80550401), NpAuthExports.NpAuthGetAuthorizationCodeV3(ctx));
|
||||
var outputAddress = MemoryBase + 0x100;
|
||||
var issuerAddress = MemoryBase + 0x1800;
|
||||
var credentials = new byte[idToken ? 4104 : 136];
|
||||
Array.Fill(credentials, (byte)0xAA);
|
||||
Assert.True(memory.TryWrite(outputAddress, credentials));
|
||||
Assert.True(ctx.TryWriteUInt32(issuerAddress, uint.MaxValue));
|
||||
ctx[CpuRegister.Rdi] = unchecked((uint)requestId);
|
||||
ctx[CpuRegister.Rdx] = outputAddress;
|
||||
ctx[CpuRegister.Rcx] = issuerAddress;
|
||||
|
||||
var result = idToken
|
||||
? NpAuthExports.NpAuthGetIdTokenV3(ctx)
|
||||
: NpAuthExports.NpAuthGetAuthorizationCodeV3(ctx);
|
||||
Assert.Equal(async ? 0 : unchecked((int)0x80550006), result);
|
||||
Assert.True(memory.TryRead(outputAddress, credentials));
|
||||
Assert.All(credentials, value => Assert.Equal((byte)0, value));
|
||||
Assert.True(ctx.TryReadUInt32(issuerAddress, out var issuer));
|
||||
Assert.Equal(idToken ? uint.MaxValue : 0u, issuer);
|
||||
|
||||
var resultAddress = MemoryBase + 0x1880;
|
||||
ctx[CpuRegister.Rsi] = resultAddress;
|
||||
Assert.Equal(0, NpAuthExports.NpAuthPollAsync(ctx));
|
||||
Assert.True(ctx.TryReadUInt32(resultAddress, out var completionResult));
|
||||
Assert.Equal(0x80550006u, completionResult);
|
||||
|
||||
Assert.Equal(unchecked((int)0x80550301), NpAuthExports.NpAuthGetAuthorizationCodeV3(ctx));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue