sharpemu/tests/SharpEmu.Libs.Tests/Agc/AgcEventWriteTests.cs

78 lines
3.0 KiB
C#

// Copyright (C) 2026 SharpEmu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
using System.Buffers.Binary;
using SharpEmu.HLE;
using SharpEmu.Libs.Agc;
using SharpEmu.Libs.Gpu.GpuCommands;
using SharpEmu.Libs.Tests.Gpu.GpuCommands;
using Xunit;
namespace SharpEmu.Libs.Tests.Agc;
public sealed class AgcEventWriteTests
{
[Fact]
public void DrawCounterDumpsPublishBothHalvesOfQueryResults()
{
var runner = new StreamRunner();
var begin = Build(0x39, StreamRunner.LabelAddress);
var end = Build(0x39, StreamRunner.LabelAddress + 8);
Assert.Equal(0x139u, begin[1]);
Assert.Equal(SubmissionProgress.Complete, runner.Run(begin, end));
for (var block = 0u; block < 16; block++)
{
var address = StreamRunner.LabelAddress + block * 16;
var first = runner.Host.ReadQword(address);
var last = runner.Host.ReadQword(address + 8);
Assert.NotEqual(0UL, first & last & (1UL << 63));
Assert.True(last > first);
}
}
[Theory]
[InlineData(0x38u, 0x1234567800UL, 4)]
[InlineData(0x39u, 0x1234567800UL, 4)]
[InlineData(0x3Au, 0UL, 2)]
[InlineData(0x10u, 0UL, 2)]
public void DrawEventsPreservePayloadAndAdvanceCursor(uint eventType, ulong payload, int words)
{
var packet = Build(eventType, payload);
Assert.Equal(words, packet.Length);
Assert.Equal(eventType | (words == 4 ? 0x100u : 0), packet[1]);
if (words == 4)
{
Assert.Equal((uint)payload, packet[2]);
Assert.Equal((uint)(payload >> 32), packet[3]);
}
}
private static uint[] Build(uint eventType, ulong payload)
{
const ulong memoryAddress = 0x2_1000_0000;
const ulong commandBuffer = memoryAddress + 0x80;
const ulong packetAddress = memoryAddress + 0x200;
var memory = new FakeCpuMemory(memoryAddress, 0x1000);
var context = new CpuContext(memory, Generation.Gen5);
Span<byte> bytes = stackalloc byte[16];
BinaryPrimitives.WriteUInt64LittleEndian(bytes, packetAddress);
BinaryPrimitives.WriteUInt64LittleEndian(bytes[8..], packetAddress + 0x100);
Assert.True(memory.TryWrite(commandBuffer + 0x10, bytes));
context[CpuRegister.Rdi] = commandBuffer;
context[CpuRegister.Rsi] = eventType;
context[CpuRegister.Rdx] = payload;
AgcExports.DcbEventWrite(context);
Assert.Equal(packetAddress, context[CpuRegister.Rax]);
Assert.True(memory.TryRead(commandBuffer + 0x10, bytes[..8]));
var length = checked((int)(BinaryPrimitives.ReadUInt64LittleEndian(bytes) - packetAddress));
Assert.InRange(length, 8, 16);
Assert.True(memory.TryRead(packetAddress, bytes[..length]));
var packet = new uint[length / 4];
for (var i = 0; i < packet.Length; i++)
packet[i] = BinaryPrimitives.ReadUInt32LittleEndian(bytes[(i * 4)..]);
return packet;
}
}