69 lines
2.5 KiB
C#
69 lines
2.5 KiB
C#
// Copyright (C) 2026 SharpEmu Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
using System.Runtime.InteropServices;
|
|
using SharpEmu.ShaderCompiler.Tests.Resources;
|
|
using SharpEmu.ShaderCompiler.Vulkan;
|
|
using Xunit;
|
|
using static SharpEmu.ShaderCompiler.Tests.Resources.ResourceTestProgram;
|
|
|
|
namespace SharpEmu.ShaderCompiler.Tests;
|
|
|
|
public sealed class Gen5MultiplyHighTests
|
|
{
|
|
[Theory]
|
|
[InlineData("VMulHiU32", false)]
|
|
[InlineData("VMulHiU32U24", false)]
|
|
[InlineData("VMulHiI32", true)]
|
|
[InlineData("VMadU64U32", false)]
|
|
public void VectorProducts_UseExtendedMultiplies(string opcode, bool signed)
|
|
{
|
|
var program = Program(
|
|
Vop3(0, opcode, 2, Gen5Operand.Vector(4), Gen5Operand.Scalar(8), Gen5Operand.Scalar(10)),
|
|
EndProgram(8));
|
|
AssertExtendedMultiply(program, signed);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("SMulHiU32", false)]
|
|
[InlineData("SMulHiI32", true)]
|
|
public void ScalarProducts_UseExtendedMultiplies(string opcode, bool signed)
|
|
{
|
|
var program = Program(
|
|
Sop2(0, opcode, 12, Gen5Operand.Scalar(8), Gen5Operand.Scalar(9)),
|
|
EndProgram(4));
|
|
AssertExtendedMultiply(program, signed);
|
|
}
|
|
|
|
private static void AssertExtendedMultiply(Gen5ShaderProgram program, bool signed)
|
|
{
|
|
var (plan, resources, layout) = Prepare(program);
|
|
var request = new ShaderCompileRequest(plan, resources, layout) { LocalSizeX = 1, ThreadCountX = 1 };
|
|
Assert.True(Gen5SpirvTranslator.TryCompileProgram(request, out var shader, out var error), error);
|
|
var inspector = new SpirvModuleInspector(shader.Spirv);
|
|
Assert.Contains((ushort)(signed ? SpirvOp.SMulExtended : SpirvOp.UMulExtended), inspector.Opcodes);
|
|
Assert.Empty(WideMultiplies(shader.Spirv));
|
|
}
|
|
|
|
private static List<uint> WideMultiplies(byte[] spirv)
|
|
{
|
|
var words = MemoryMarshal.Cast<byte, uint>(spirv);
|
|
var wideTypes = new HashSet<uint>();
|
|
var multiplies = new List<uint>();
|
|
for (var index = 5; index < words.Length; index += (int)(words[index] >> 16))
|
|
{
|
|
var opcode = (ushort)(words[index] & 0xFFFF);
|
|
if (opcode == (ushort)SpirvOp.TypeInt && words[index + 2] == 64)
|
|
{
|
|
wideTypes.Add(words[index + 1]);
|
|
}
|
|
else if (opcode == (ushort)SpirvOp.IMul && wideTypes.Contains(words[index + 1]))
|
|
{
|
|
multiplies.Add(words[index + 2]);
|
|
}
|
|
}
|
|
|
|
return multiplies;
|
|
}
|
|
}
|