[AGC] Share the interpolant mapping computation of both mapping variants

This commit is contained in:
ParantezTech 2026-10-08 02:52:06 +03:00
parent b61ef8ede6
commit 7fa87a1d9e
1 changed files with 77 additions and 51 deletions

View File

@ -658,47 +658,7 @@ public static partial class AgcExports
{
var source = BinaryPrimitives.ReadUInt32LittleEndian(inputWords[(inputIndex * sizeof(uint))..]);
var hasMask = TryFindOutputSemantic(outputWords, source, out var mask);
var mode = (source >> 20) & 0x3u;
uint flags;
if (mode == 0)
{
flags = (((source >> 24) & 0x1u) | (hasMask ? 0u : 1u)) << 5;
flags = ApplyInterpolantTwoBitField(flags, source >> 28, 8);
}
else
{
flags = ((source << 4) & 0x0300_0000u) + 0x0008_0000u;
if (mode == 2)
{
flags &= 0xFFEF_FFDFu;
flags |= hasMask ? ((~(mask & source) >> 16) & 0x20u) : 0x20u;
flags = ApplyInterpolantTwoBitField(flags, source >> 30, 8);
flags = ApplyInterpolantTwoBitField(flags, source >> 30, 21);
}
else
{
if (hasMask)
{
var masked = mask & source;
flags = (flags & 0xFFFF_FFDFu) | ((masked >> 15) & 0x20u);
flags ^= 0x20u;
flags = (flags & 0xFFEF_FFFFu) | ((~masked >> 1) & 0x0010_0000u);
}
else
{
flags |= 0x0010_0020u;
}
flags = ApplyInterpolantTwoBitField(flags, source >> 28, 8);
flags = ApplyInterpolantTwoBitField(flags, source >> 30, 21);
}
}
flags = hasMask
? ApplyInterpolantFinalMask(flags, source, mask)
: flags & 0xFFFF_FBE0u;
SetInterpolantRegister(registers, inputIndex, flags);
SetInterpolantRegister(registers, inputIndex, InterpolantMapping2Value(source, hasMask, mask));
}
}
finally
@ -778,6 +738,81 @@ public static partial class AgcExports
TryWriteUInt32(ctx, destinationAddress + 8, outputPrimitiveOffset) &&
TryWriteUInt32(ctx, destinationAddress + 12, outputPrimitiveValue);
}
private static uint InterpolantMapping2Value(uint source, bool hasMask, uint mask)
{
var mode = (source >> 20) & 0x3u;
uint flags;
if (mode == 0)
{
flags = (((source >> 24) & 0x1u) | (hasMask ? 0u : 1u)) << 5;
flags = ApplyInterpolantTwoBitField(flags, source >> 28, 8);
}
else
{
flags = ((source << 4) & 0x0300_0000u) + 0x0008_0000u;
if (mode == 2)
{
flags &= 0xFFEF_FFDFu;
flags |= hasMask ? ((~(mask & source) >> 16) & 0x20u) : 0x20u;
flags = ApplyInterpolantTwoBitField(flags, source >> 30, 8);
flags = ApplyInterpolantTwoBitField(flags, source >> 30, 21);
}
else
{
if (hasMask)
{
var masked = mask & source;
flags = (flags & 0xFFFF_FFDFu) | ((masked >> 15) & 0x20u);
flags ^= 0x20u;
flags = (flags & 0xFFEF_FFFFu) | ((~masked >> 1) & 0x0010_0000u);
}
else
{
flags |= 0x0010_0020u;
}
flags = ApplyInterpolantTwoBitField(flags, source >> 28, 8);
flags = ApplyInterpolantTwoBitField(flags, source >> 30, 21);
}
}
return hasMask
? ApplyInterpolantFinalMask(flags, source, mask)
: flags & 0xFFFF_FBE0u;
}
private static uint InterpolantMappingValue(uint psWord, uint? gsWord)
{
var value = (psWord & 0x0030_0000u) != 0
? CreateInterpolantF16Value(psWord, gsWord)
: CreateInterpolantNonF16Value(psWord, gsWord.HasValue);
return gsWord is { } matched
? CreateInterpolantMappingValue(value, psWord, matched)
: CreateInterpolantDefaultParamValue(value, psWord);
}
internal static uint[] ComputeInterpolantMapping(ReadOnlySpan<uint> pixelInputs, ReadOnlySpan<uint> vertexOutputs, bool secondVariant)
{
var registers = new uint[InterpolantRegisterCount];
for (var index = 0; index < registers.Length; index++)
{
registers[index] = (uint)index;
}
var outputBytes = System.Runtime.InteropServices.MemoryMarshal.AsBytes(vertexOutputs);
var count = Math.Min(pixelInputs.Length, InterpolantRegisterCount);
for (var index = 0; index < count; index++)
{
var input = pixelInputs[index];
var matched = TryFindOutputSemantic(outputBytes, input, out var output);
registers[index] = secondVariant
? InterpolantMapping2Value(input, matched, output)
: InterpolantMappingValue(input, matched ? output : null);
}
return registers;
}
private static uint ApplyInterpolantTwoBitField(uint value, uint field, int shift)
{
var mask = 0x3u << shift;
@ -880,16 +915,7 @@ public static partial class AgcExports
{
var psWord = BinaryPrimitives.ReadUInt32LittleEndian(psWords[(psIndex * sizeof(uint))..]);
uint? gsWord = TryFindOutputSemantic(gsWords, psWord, out var candidate) ? candidate : null;
var value = (psWord & 0x0030_0000u) != 0
? CreateInterpolantF16Value(psWord, gsWord)
: CreateInterpolantNonF16Value(psWord, gsWord.HasValue);
SetInterpolantRegister(
registers,
psIndex,
gsWord is { } matched
? CreateInterpolantMappingValue(value, psWord, matched)
: CreateInterpolantDefaultParamValue(value, psWord));
SetInterpolantRegister(registers, psIndex, InterpolantMappingValue(psWord, gsWord));
}
}
finally