diff options
author | gdkchan <gab.dark.100@gmail.com> | 2023-08-16 21:31:07 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-16 21:31:07 -0300 |
commit | 6ed613a6e6a66d57d2fdb045d926e42dfcdd3206 (patch) | |
tree | 3dbd8e34edf12925f49a0a6c1229e3565b5cfd4f /src/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs | |
parent | 64079c034c1c3a18133542d6ac745490149d8043 (diff) |
Fix vote and shuffle shader instructions on AMD GPUs (#5540)1.1.995
* Move shuffle handling out of the backend to a transform pass
* Handle subgroup sizes higher than 32
* Stop using the subgroup size control extension
* Make GenerateShuffleFunction static
* Shader cache version bump
Diffstat (limited to 'src/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs')
-rw-r--r-- | src/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs | 58 |
1 files changed, 52 insertions, 6 deletions
diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs index 9d1c7d08..944039d6 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs @@ -76,7 +76,7 @@ namespace Ryujinx.Graphics.Shader.Instructions switch (op.SReg) { case SReg.LaneId: - src = context.Load(StorageKind.Input, IoVariable.SubgroupLaneId); + src = EmitLoadSubgroupLaneId(context); break; case SReg.InvocationId: @@ -146,19 +146,19 @@ namespace Ryujinx.Graphics.Shader.Instructions break; case SReg.EqMask: - src = context.Load(StorageKind.Input, IoVariable.SubgroupEqMask, null, Const(0)); + src = EmitLoadSubgroupMask(context, IoVariable.SubgroupEqMask); break; case SReg.LtMask: - src = context.Load(StorageKind.Input, IoVariable.SubgroupLtMask, null, Const(0)); + src = EmitLoadSubgroupMask(context, IoVariable.SubgroupLtMask); break; case SReg.LeMask: - src = context.Load(StorageKind.Input, IoVariable.SubgroupLeMask, null, Const(0)); + src = EmitLoadSubgroupMask(context, IoVariable.SubgroupLeMask); break; case SReg.GtMask: - src = context.Load(StorageKind.Input, IoVariable.SubgroupGtMask, null, Const(0)); + src = EmitLoadSubgroupMask(context, IoVariable.SubgroupGtMask); break; case SReg.GeMask: - src = context.Load(StorageKind.Input, IoVariable.SubgroupGeMask, null, Const(0)); + src = EmitLoadSubgroupMask(context, IoVariable.SubgroupGeMask); break; default: @@ -169,6 +169,52 @@ namespace Ryujinx.Graphics.Shader.Instructions context.Copy(GetDest(op.Dest), src); } + private static Operand EmitLoadSubgroupLaneId(EmitterContext context) + { + if (context.TranslatorContext.GpuAccessor.QueryHostSubgroupSize() <= 32) + { + return context.Load(StorageKind.Input, IoVariable.SubgroupLaneId); + } + + return context.BitwiseAnd(context.Load(StorageKind.Input, IoVariable.SubgroupLaneId), Const(0x1f)); + } + + private static Operand EmitLoadSubgroupMask(EmitterContext context, IoVariable ioVariable) + { + int subgroupSize = context.TranslatorContext.GpuAccessor.QueryHostSubgroupSize(); + + if (subgroupSize <= 32) + { + return context.Load(StorageKind.Input, ioVariable, null, Const(0)); + } + else if (subgroupSize == 64) + { + Operand laneId = context.Load(StorageKind.Input, IoVariable.SubgroupLaneId); + Operand low = context.Load(StorageKind.Input, ioVariable, null, Const(0)); + Operand high = context.Load(StorageKind.Input, ioVariable, null, Const(1)); + + return context.ConditionalSelect(context.BitwiseAnd(laneId, Const(32)), high, low); + } + else + { + Operand laneId = context.Load(StorageKind.Input, IoVariable.SubgroupLaneId); + Operand element = context.ShiftRightU32(laneId, Const(5)); + + Operand res = context.Load(StorageKind.Input, ioVariable, null, Const(0)); + res = context.ConditionalSelect( + context.ICompareEqual(element, Const(1)), + context.Load(StorageKind.Input, ioVariable, null, Const(1)), res); + res = context.ConditionalSelect( + context.ICompareEqual(element, Const(2)), + context.Load(StorageKind.Input, ioVariable, null, Const(2)), res); + res = context.ConditionalSelect( + context.ICompareEqual(element, Const(3)), + context.Load(StorageKind.Input, ioVariable, null, Const(3)), res); + + return res; + } + } + public static void SelR(EmitterContext context) { InstSelR op = context.GetOp<InstSelR>(); |