sharpemu/tests/SharpEmu.ShaderCompiler.Tests/Resources/DeviceAddressRangePlannerTe...

111 lines
4.3 KiB
C#

// Copyright (C) 2026 SharpEmu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
using SharpEmu.ShaderCompiler;
using SharpEmu.ShaderCompiler.Resources;
using Xunit;
using static SharpEmu.ShaderCompiler.Tests.Resources.ResourceTestProgram;
namespace SharpEmu.ShaderCompiler.Tests.Resources;
public sealed class DeviceAddressRangePlannerTests
{
[Fact]
public void BoundedOffsets_GiveTheLargestExtent()
{
var plan = Extract(Program(
Vop1(0, "VMovB32", 0, Operand(0)),
GlobalAccess(4, "GlobalLoadDword", 0, offset: 8),
GlobalAccess(12, "GlobalLoadDwordx4", 0, offset: 32, dwords: 4),
EndProgram(20)));
var range = Assert.Single(plan.DeviceAddressRanges);
Assert.True(range.Bounded);
Assert.True(range.Plannable);
Assert.False(range.Written);
Assert.Equal(8, range.FirstByte);
Assert.Equal(48, range.EndByte);
Assert.Equal(40ul, range.Extent);
Assert.Equal(2, range.MemoryIndices.Count);
var evaluated = Assert.Single(DeviceAddressRangePlanner.Evaluate(plan, Inputs([0x1000, 0])));
Assert.True(evaluated.Planned);
Assert.Equal(0x1008ul, evaluated.Base);
Assert.Equal(40ul, evaluated.Size);
}
// A store 8 bytes below the handle starts the range there; the range covers the
// lowest byte through the end of the highest access.
[Fact]
public void NegativeOffset_StartsTheRangeAtTheLowestByte()
{
var plan = Extract(Program(
Vop1(0, "VMovB32", 0, Operand(0)),
GlobalAccess(4, "GlobalStoreDword", 0, offset: -8),
GlobalAccess(12, "GlobalLoadDwordx2", 0, offset: 8, dwords: 2),
EndProgram(20)));
var range = Assert.Single(plan.DeviceAddressRanges);
Assert.True(range.Bounded);
Assert.True(range.Written);
Assert.Equal(-8, range.FirstByte);
Assert.Equal(16, range.EndByte);
Assert.Equal(24ul, range.Extent);
var evaluated = Assert.Single(DeviceAddressRangePlanner.Evaluate(plan, Inputs([0x2008, 0])));
Assert.True(evaluated.Planned);
Assert.Equal(0x2000ul, evaluated.Base);
Assert.Equal(24ul, evaluated.Size);
var storeOnly = Extract(Program(
Vop1(0, "VMovB32", 0, Operand(0)),
GlobalAccess(4, "GlobalStoreDword", 0, offset: -8),
EndProgram(12)));
var single = Assert.Single(DeviceAddressRangePlanner.Evaluate(storeOnly, Inputs([0x2008, 0])));
Assert.Equal(0x2000ul, single.Base);
Assert.Equal(4ul, single.Size);
}
[Fact]
public void RuntimeOffset_ExtendsToTheMappedEndUpToTheCap()
{
var plan = Extract(Program(
GlobalAccess(0, "GlobalLoadDword", 0, offset: 8, vectorAddress: 0),
EndProgram(8)));
var range = Assert.Single(plan.DeviceAddressRanges);
Assert.False(range.Bounded);
Assert.True(range.Plannable);
var evaluated = Assert.Single(DeviceAddressRangePlanner.Evaluate(plan, Inputs([0x1000, 0])));
Assert.True(evaluated.Planned);
Assert.Equal(DeviceAddressRangePlanner.MaxRangeBytes, evaluated.Size);
}
[Fact]
public void UnplannableHandle_DoesNotFailThePlan()
{
var plan = Extract(Program(GlobalAccess(0, "FlatLoadDword", 0, vectorAddress: 2), EndProgram(8)));
Assert.True(plan.Info.UsesDeviceAddresses);
var range = Assert.Single(plan.DeviceAddressRanges);
Assert.False(range.Plannable);
var evaluated = Assert.Single(DeviceAddressRangePlanner.Evaluate(plan, Inputs([])));
Assert.False(evaluated.Planned);
Assert.Equal(0ul, evaluated.Size);
}
[Fact]
public void WrittenUnplannableHandle_IsReportedForTheHost()
{
var plan = Extract(Program(GlobalAccess(0, "FlatStoreDword", 0, vectorAddress: 2), EndProgram(8)));
var range = Assert.Single(plan.DeviceAddressRanges);
Assert.True(range.Written);
Assert.False(range.Plannable);
var snapshot = new ResourceSnapshot();
var specialization = new ResourceSpecialization();
Assert.True(ResourceMaterializer.Materialize(plan, Inputs([]), ref snapshot, ref specialization));
var reported = Assert.Single(snapshot.DeviceAddressRanges);
Assert.True(reported.Written);
Assert.False(reported.Planned);
}
}